Reputation: 91
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?
Upvotes: 9
Views: 13976
Reputation: 1
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;
}
Upvotes: 0
Reputation: 8647
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:
Upvotes: 12
Reputation: 1223
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);
Upvotes: 0