我在尝试替换 Word 文档中的图像占位符时遇到一些奇怪的问题。如果我尝试用下面的代码替换占位符,它将替换所有这些代码。不仅仅是与 docproperties 中的名称匹配的那个。
经过进一步检查,我发现使用 OpenXML SDK Productivity Tool 查看 Word 文档时,我的占位符图片共享相同的嵌入 id。这是为什么?这似乎就是为什么我的所有占位符都被新图像替换的原因。
使用 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>
我的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);
}
}
}
}
}
重点是 EmbedID 将绘图链接到图像部分,图像部分又链接到图像文件。您将从要替换的绘图中获取图像部分 ID,并使用它用新图像填充图像部分。这样,链接到该图像部分的所有形状都将获得新图像。要仅替换具有指定名称的形状,您必须使用新文件创建一个新的图像部分,并将 id 放入您正在更新的绘图元素中。
这样您将只更新单个元素。
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;
}
}
}
}