Reputation: 185
I have some weird problem trying to replace image placeholders in a Word document. If I try to replace the placeholder with the code below it replaces all of them. Not only the one who matches the name in docproperties.
With some further inspection I've discovered that viewing the word document with OpenXML SDK Productivity Tool that my placeholder pictures share the same embed id.. Why is that? That seems to be why all my placeholders get replaced by the new image.
Part of Document using OpenXML Productivity Tool:
<pic:blipFill>
<a:blip r:embed="rId6">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0" />
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect />
</a:stretch>
</pic:blipFill>
My code in C#
public static void ReplacePlaceHolderWithPicture(this WordprocessingDocument doc, string nameOfImage, string imgFilePath)
{
var drawings = doc.MainDocumentPart.Document.Descendants<Drawing>().ToList();
var newImageBytes = File.ReadAllBytes(imgFilePath);
foreach (var drawing in drawings)
{
var dpr = drawing.Descendants<DocProperties>().FirstOrDefault();
if (dpr != null && dpr.Name == nameOfImage)
{
foreach (var b in drawing.Descendants<A.Blip>())
{
OpenXmlPart imagePart = doc.MainDocumentPart.GetPartById(b.Embed);
using (var writer = new BinaryWriter(imagePart.GetStream()))
{
writer.Write(newImageBytes);
}
}
}
}
}
Upvotes: 1
Views: 672
Reputation: 11
The point is that the EmbedID links the Drawing to an image part, wich links to a image file. You are getting the imagepart ID from the Drawing you want to replace, and using it to fill the imagepart with a new image. This way, all the shapes linked to that imagepart will get the new image. To replace only the shape with the specified name, you will have to create a new imagepart with the new file and place the id into the Drawing element you are updating.
This way you will only update a single element.
public static void ReplacePlaceHolderWithPicture(this WordprocessingDocument doc, string nameOfImage, string imgFilePath)
{
var drawings = doc.MainDocumentPart.Document.Descendants<Drawing>().ToList();
var newImageBytes = File.ReadAllBytes(imgFilePath);
foreach (var drawing in drawings)
{
var dpr = drawing.Descendants<DocProperties>().FirstOrDefault();
if (dpr != null && dpr.Name == nameOfImage)
{
//Instead of replacing the imagePart Data (and replacing all the images with the same embed id) add a new imagepart
var imagePart = doc.MainDocumentPart.AddImagePart(ImagePartType.Jpeg); //Check if the image extensions specified is correct
using (var stream = new MemoryStream(newImageBytes))
{
imagePart.FeedData(stream);
}
//Get the embed id of the image just added
var relationshipId = doc.MainDocumentPart.GetIdOfPart(imagePart);
foreach (var b in drawing.Descendants<Blip>())
{
//Set the ID of the new image into the blip of the aimed Drawing element
b.Embed = relationshipId;
}
}
}
}
Upvotes: 0