Dot-Net

使用 OpenXML 替換 word 文件中的圖像

  • May 11, 2010

繼我的最後一個問題之後

OpenXML 看起來可能正是我想要的,但是文件很糟糕。一個小時的Google搜尋並沒有讓我更接近於弄清楚我需要做什麼。

我有一個word文件。我想以這樣一種方式將圖像添加到該 word 文件(使用 word),然後我可以在 OpenXML 中打開該文件並替換該圖像。應該很簡單吧?

我假設我應該能夠為我的圖像“佔位符”提供某種 id,然後使用GetPartById它來定點陣圖像並替換它。這會是正確的方法嗎?這個 ID 是什麼?你如何使用Word添加它?

我能找到的每個範例都可以從頭開始在 ML 中建構整個 word 文件,這實際上並沒有太多用處。

**編輯:**在我看來,將媒體文件夾中的圖像替換為新圖像會更容易,但再次找不到任何有關如何執行此操作的指示。

儘管 OpenXML 的文件不是很好,但有一個出色的工具可以用來查看現有 Word 文件是如何建構的。如果您安裝 OpenXml SDK,它會附帶Open XML 格式 SDK\V2.0\tools目錄下的DocumentReflector.exe工具。

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();

引用自:https://stackoverflow.com/questions/2810138