Skip to main content
 首页 » 编程设计

.net之使用 OpenXML 替换 word 文档中的图像

2024年11月01日19emanlee

继我上一个问题 here

OpenXML 看起来可能正是我想要的,但文档很糟糕。一个小时的谷歌搜索并没有让我更接近于弄清楚我需要做什么。

我有一个word文档。我想以这样一种方式将图像添加到该 word 文档(使用 word),然后我可以在 OpenXML 中打开该文档并替换该图像。应该很简单吧?

我假设我应该能够为我的图像“占位符”提供某种 id,然后使用 GetPartById找到图像并替换它。这会是正确的方法吗?这个 ID 是什么?你如何使用Word添加它?

我能找到的每个示例都可以从头开始在 ML 中构建整个 word 文档,这实际上并没有太多用处。

编辑:我突然想到,将媒体文件夹中的图像替换为新图像会更容易,但又找不到任何有关如何执行此操作的指示。

请您参考如下方法:

尽管 OpenXML 的文档不是很好,但是有一个出色的工具可以用来查看现有 Word 文档是如何构建的。如果您安装 OpenXml SDK,它会附带 DocumentReflector.exe Open XML Format SDK\V2.0\tools 目录下的工具。

Word 文档中的图像由图像数据和分配给它的 ID 组成,该 ID 在文档正文中引用。您的问题似乎可以分为两部分:查找图像的 ID 在文档中,然后 重写图像数据为了它。

要查找图像的 ID,您需要解析 MainDocumentPart。图像作为绘图元素存储在 Runs 中

<w:p> 
  <w:r> 
    <w:drawing> 
      <wp:inline> 
        <wp:extent cx="3200400" cy="704850" /> <!-- describes the size of the image --> 
        <wp:docPr id="2" name="Picture 1" descr="filename.JPG" /> 
        <a:graphic> 
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"> 
            <pic:pic> 
              <pic:nvPicPr> 
                <pic:cNvPr id="0" name="filename.JPG" /> 
                <pic:cNvPicPr /> 
              </pic:nvPicPr> 
              <pic:blipFill> 
                <a:blip r:embed="rId5" /> <!-- this is the ID you need to find --> 
                <a:stretch> 
                  <a:fillRect /> 
                </a:stretch> 
              </pic:blipFill> 
              <pic:spPr> 
                <a:xfrm> 
                  <a:ext cx="3200400" cy="704850" /> 
                </a:xfrm> 
                <a:prstGeom prst="rect" /> 
              </pic:spPr> 
            </pic:pic> 
          </a:graphicData> 
        </a:graphic> 
      </wp:inline> 
    </w:drawing> 
  </w:r> 
</w:p> 

在上面的示例中,您需要找到存储在 blip 元素中的图像的 ID。如何查找取决于您的问题,但如果您知道原始图像的文件名,则可以查看 docPr 元素:
using (WordprocessingDocument document = WordprocessingDocument.Open("docfilename.docx", true)) { 
 
  // go through the document and pull out the inline image elements 
  IEnumerable<Inline> imageElements = from run in Document.MainDocumentPart.Document.Descendants<Run>() 
      where run.Descendants<Inline>().First() != null 
      select run.Descendants<Inline>().First(); 
 
  // select the image that has the correct filename (chooses the first if there are many) 
  Inline selectedImage = (from image in imageElements 
      where (image.DocProperties != null && 
          image.DocProperties.Equals("image filename")) 
      select image).First(); 
 
  // get the ID from the inline element 
  string imageId = "default value"; 
  Blip blipElement = selectedImage.Descendants<Blip>().First(); 
  if (blipElement != null) { 
      imageId = blipElement.Embed.Value; 
  } 
} 

然后,当您拥有图像 ID 时,您可以使用它来重写图像数据。我认为这就是你的做法:
ImagePart imagePart = (ImagePart)document.MainDocumentPart.GetPartById(imageId); 
byte[] imageBytes = File.ReadAllBytes("new_image.jpg"); 
BinaryWriter writer = new BinaryWriter(imagePart.GetStream()); 
writer.Write(imageBytes); 
writer.Close();