如何使用 Open XML SDK 删除 Word 和 PowerPoint 中的所有嵌入对象?

How to delete all embedded objects in Word and PowerPoint using Open XML SDK?

我正在尝试使用 openxml SDK 从 Word 和 PowerPoint 文件中删除所有嵌入对象。我是 Open XML 的新手,不确定我这样做是否正确。下面是我的代码。我的意图是删除嵌入的任何对象并删除嵌入的图像。执行时这两个代码都给出错误。

我试图删除文档中所有嵌入项目的代码。

using (var wdDoc = WordprocessingDocument.Open(wordFilePath, true))
{
    var docPart = wdDoc.MainDocumentPart;
    var document = docPart.Document;
    var embeddedObjectsCount = docPart.EmbeddedObjectParts.Count();
    while (embeddedObjectsCount > 0)
    {
        docPart.DeletePart(docPart.EmbeddedObjectParts.FirstOrDefault());
        embeddedObjectsCount = docPart.EmbeddedObjectParts.Count();
    }
}

我试图删除文档中所有图像的代码。 (如果我没有在文档中嵌入任何对象,这会部分起作用。)

using (var wdDoc = WordprocessingDocument.Open(wordFilePath, true))
{
    var docPart = wdDoc.MainDocumentPart;
    var document = docPart.Document;
    var imageObjectsCount = docPart.ImageParts.Count();
    while (imageObjectsCount > 0)
    {
        docPart.DeletePart(docPart.ImageParts.FirstOrDefault());
        imageObjectsCount = docPart.ImageParts.Count();
    }
}

当我 运行 上述代码时,我使用的文件已损坏。我想知道如何在不损坏文件的情况下从 Word 中删除所有嵌入的对象。

我还没有在 PowerPoint 上做过任何事情,但我希望它类似于 Word 文档。

根据我的经验,"corrupt" OpenXML 文档的最快方法是使用错误的关系指针。处理这些神秘错误消息背后的内容的最快方法是直接转到原始 OpenXML 标记。

了解正在发生的事情:

  1. 在 运行 你的代码之前复制你的文件,称之为 A.docx
  2. 运行 你的代码并复制你的结果,调用这个 B.docx
  3. A.docxB.docx 重命名为 A.zipB.zip

调查源文件

首先,在 A.zip 中,打开名为 [Content_Types].xml 的文件。记下您要删除的部分。将此文件视为对字处理器的声明,说明它将在子目录中遇到的文件类型。

文档内容(word/document.xml)或脚注部分(word/footnotes.xml)等部分有自己的关系部分,命名为[part path here].rels

例如,document.xml.rels 将保存 document.xml 中图表、超链接和图像等内容的关系信息;同样,footnotes.xml.rels 包含有关 footnotes.xml.

中的超链接之类的信息

调查结果文件

现在打开 B.zip 并比较 [Content_Types].xml 文件。您是否看到您打算删除的部分?是否缺少您不打算删除的部分?

B.zipword 子目录中,您是否看到 未在 [Content_Types].xml 中列出的任何嵌入文件?文件?

如果您查看原始标记,并且您没有发现错误,请随时发表评论,提供有关您的文件结构的更多详细信息,我们可以从那里进行故障排除。

我设法找到了解决问题的方法。我必须深入研究 Open XML SDK 的概念才能得到它。但是,我不太确定这是否是最佳解决方案。

目标

  1. 删除 PowerPoint 和 Word 中的所有嵌入对象。

  2. 删除 PowerPoint 和 Word 中的所有图像。

对于单词

//using Ovml = DocumentFormat.OpenXml.Vml.Office;
//Determine whether there are any Embedded Objects in the document
using (var wdDoc = WordprocessingDocument.Open(wordFilePath, true))
{
    var docPart = wdDoc.MainDocumentPart;
    var docHasEmbeddedOleObjects = document.Body.Descendants<Ovml.OleObject>().Any();
    if (docHasEmbeddedOleObjects)
    {
        foreach (var oleObj in document.Body.Descendants<Ovml.OleObject>())
        {
            oleObj.Remove(); //Remove each ole object in the document. This will remove the object from view in word.
        }
        //Delete the embedded objects. This will remove the actual attached files from the document.
        docPart.DeleteParts(docPart.EmbeddedObjectParts);
        //Delete all picture in the document
        docPart.DeleteParts(docPart.ImageParts);
    }
}

PowerPoint

using (var ppt = PresentationDocument.Open(powerPointFilePath, true))
{
    foreach (var slide in slides)
    {
        //Remove Ole Objects
        var oleObjectCount = slide.Slide.Descendants<OleObject>().Count();
        while (oleObjectCount > 0)
        {
            var oleObj = slide.Slide.Descendants<OleObject>().FirstOrDefault();
            var oleObjGraphicFrame = oleObj?.Ancestors<GraphicFrame>().FirstOrDefault();
            if (oleObjGraphicFrame != null)
            {
                oleObjGraphicFrame.RemoveAllChildren();
                oleObjGraphicFrame.Remove();
            }
            oleObjectCount = slide.Slide.Descendants<OleObject>().Count();
        }
        //Delete embedded objects
        slide.DeleteParts(slide.EmbeddedObjectParts);
        //Delete all pictures
        slide.DeleteParts(slide.ImageParts);
    }
}