How to insert image into header of OpenXML Word document?
Asked Answered
P

3

9

My OpenXML Word document generation project requires text, tables, and images. But first, I need a document header with a logo (image) in it.

I've used the Microsoft example for creating headers and footers at Generating Documents with Headers and Footers in Word 2007 by Using the Open XML SDK 2.0 for Microsoft Office, and text headers work just fine, but the images show up in the header with the broken image icon, a correctly sized border, and the message "This image cannot currently be displayed." Also, I can load the selected image into the document body just fine. Here's how I create the ImagePart:

// Create AG logo part.
_agLogoPart = mainDocumentPart.AddImagePart(ImagePartType.Jpeg);
using (FileStream stream = new FileStream(_agLogoFilename, FileMode.Open))
{
    _agLogoPart.FeedData(stream);
}
_agLogoRel = mainDocumentPart.GetIdOfPart(_agLogoPart);

The images are loaded with a LoadImage method, derived from the Microsoft example, but adding parameters for width and height, and returning a Drawing object:

private static Drawing LoadImage(string relationshipId,
                             string filename,
                             string picturename,
                             double inWidth,
                             double inHeight)
{
double emuWidth = Konsts.EmusPerInch * inWidth;
double emuHeight = Konsts.EmusPerInch * inHeight;

var element = new Drawing(
    new DW.Inline(
    new DW.Extent { Cx = (Int64Value)emuWidth, Cy = (Int64Value)emuHeight },
    new DW.EffectExtent { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
    new DW.DocProperties { Id = (UInt32Value)1U, Name = picturename },
    new DW.NonVisualGraphicFrameDrawingProperties(
    new A.GraphicFrameLocks { NoChangeAspect = true }),
    new A.Graphic(
    new A.GraphicData(
    new PIC.Picture(
    new PIC.NonVisualPictureProperties(
    new PIC.NonVisualDrawingProperties { Id = (UInt32Value)0U, Name = filename },
    new PIC.NonVisualPictureDrawingProperties()),
    new PIC.BlipFill(
    new A.Blip(
    new A.BlipExtensionList(
    new A.BlipExtension { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" }))
    {
    Embed = relationshipId,
    CompressionState = A.BlipCompressionValues.Print },
    new A.Stretch(
    new A.FillRectangle())),
    new PIC.ShapeProperties(
    new A.Transform2D(
    new A.Offset { X = 0L, Y = 0L },
    new A.Extents { Cx = (Int64Value)emuWidth, Cy = (Int64Value)emuHeight }),
    new A.PresetGeometry(
    new A.AdjustValueList()) { Preset = A.ShapeTypeValues.Rectangle })))
    {
        Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture"
    }))
    {
        DistanceFromTop = (UInt32Value)0U,
        DistanceFromBottom = (UInt32Value)0U,
        DistanceFromLeft = (UInt32Value)0U,
        DistanceFromRight = (UInt32Value)0U,
        EditId = "50D07946"
    });
return element;
}

Using this, the following code works, loading an image anywhere into the body I want:

Paragraph paraImage = new Paragraph(new Run(LoadImage(_genomeImageRel, _genomeImageFilename, "name" + _genomeImageRel, 7.5, 2.925)));
body.AppendChild(paraImage);

And the following code does not work to put a logo image in the header:

private static Header GeneratePageHeaderPart(string headerText)
{
    Header hdr = new Header(new Paragraph(new Run(LoadImage(_agLogoRel, _agLogoFilename, "name" + _agLogoRel, 2.57, 0.73))));
    return hdr;
}

I suspect I'm doing something very subtle incorrectly, because I can load the image anywhere but in the header. Can anyone advise?

Palmate answered 18/7, 2013 at 14:23 Comment(1)
Hi, can you please show the full code to insert image into Word document header? Thank youHelminthology
D
12

I suspect I'm doing something very subtle incorrectly, because I can load the image anywhere but in the header.

If you are able to insert an image into main document, you can also insert an image in header or footer with this code (private static Drawing LoadImage).

The only one difference is where you add the ImagePart:

  • to insert an image in the body of the document, you add an ImagePart to the MainDocumentPart:

    _agLogoPart = mainDocumentPart.AddImagePart(ImagePartType.Jpeg);
    ...
     _agLogoRel = mainDocumentPart.GetIdOfPart(_agLogoPart);
    
  • to insert an image in a header, you need add an ImagePart to the HeaderPart that you use to create the header

    _agLogoPart = headerPart.AddImagePart(ImagePartType.Jpeg);
    ...
    _agLogoRel = headerPart.GetIdOfPart(_agLogoPart);
    
  • to insert an image in a footer, you need add an ImagePart to the FooterPart that you use to create the footer:

    _agLogoPart = footerPart.AddImagePart(ImagePartType.Jpeg);
    ...
    _agLogoRel = footerPart.GetIdOfPart(_agLogoPart);
    

Related:

Diondione answered 2/8, 2013 at 15:28 Comment(1)
Hi there, do you have full source code for inserting a picture into docx header ? If yes, can you please share it. Really struggling with it. Thank you!Helminthology
I
0

Please try the following code:

Bitmap image = new Bitmap(imagePath);
SdtElement controlBlock = doc.MainDocumentPart.HeaderParts.First().Header.Descendants<SdtElement>().Where
                                (r => r.SdtProperties.GetFirstChild<Tag>().Val == tagName).SingleOrDefault();
 //find the Blip element of the content control
 Blip blip = controlBlock.Descendants<Blip>().FirstOrDefault();

 //add image and change embeded id
 ImagePart imagePart = doc.MainDocumentPart.AddImagePart(ImagePartType.Jpeg);
 using (MemoryStream stream = new MemoryStream())
 {
      image.Save(stream, ImageFormat.Jpeg);
      stream.Position = 0;
      imagePart.FeedData(stream);
 }
 blip.Embed = doc.MainDocumentPart.GetIdOfPart(imagePart);
Intermolecular answered 19/7, 2013 at 15:4 Comment(0)
W
0
private static MainDocumentPart AddHeader(MainDocumentPart mainDocPart)
        {
            string LogoFilename = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/Images/TemplateLogo.png");     
            mainDocPart.DeleteParts(mainDocPart.HeaderParts);
            var FirstHeaderPart = mainDocPart.AddNewPart<HeaderPart>();
            var DefaultHeaderPart = mainDocPart.AddNewPart<HeaderPart>();
            var imgPartFirst = FirstHeaderPart.AddImagePart(ImagePartType.Jpeg);           
            var imagePartFirstID = FirstHeaderPart.GetIdOfPart(imgPartFirst);
            var imgPartDefault = FirstHeaderPart.AddImagePart(ImagePartType.Jpeg);
            var imagePartDefaultID = FirstHeaderPart.GetIdOfPart(imgPartDefault);
            using (FileStream fs = new FileStream(LogoFilename, FileMode.Open))
            {
                imgPartFirst.FeedData(fs);                
            }
            using (FileStream fsD = new FileStream(LogoFilename, FileMode.Open))
            {
                imgPartDefault.FeedData(fsD);
            }
            var rIdFirst = mainDocPart.GetIdOfPart(FirstHeaderPart);
            var FirstHeaderRef = new HeaderReference { Id = rIdFirst, Type = HeaderFooterValues.First };
            var rIdDefault = mainDocPart.GetIdOfPart(DefaultHeaderPart);
            var DefaultHeaderRef = new HeaderReference { Id = rIdDefault };

            var sectionProps = mainDocPart.Document.Body.Elements<SectionProperties>().LastOrDefault();
            if (sectionProps == null)
            {
                sectionProps = new SectionProperties();
                mainDocPart.Document.Body.Append(sectionProps);
            }
            sectionProps.RemoveAllChildren<HeaderReference>();        
            FirstHeaderPart.Header = GenerateFirstPicHeader(imagePartFirstID);
            DefaultHeaderPart.Header = GeneratePicHeader(imagePartDefaultID);
            FirstHeaderPart.Header.Save();
            DefaultHeaderPart.Header.Save();
            sectionProps.PrependChild(new TitlePage());

            sectionProps.AppendChild(DefaultHeaderRef);
            sectionProps.AppendChild(FirstHeaderRef);

            return mainDocPart;
        }
Wurst answered 16/9, 2018 at 16:40 Comment(1)
Add some description to the answerDispermous

© 2022 - 2024 — McMap. All rights reserved.