System.IO.FileFormatException 打开使用 OpenXml SDK 嵌入到 PowerPoint 2016 中的 excel 工作表

System.IO.FileFormatException on opening excel worksheet embedded in PowerPoint 2016 with OpenXml SDK

我有用户使用 PowerPoint 2016 生成的 PPTX 文件。幻灯片中嵌入了 excel 工作表,我需要访问这些工作表以进行进一步处理。我在我的项目中使用 Open Xml SDK v2.6.1。

在将嵌入对象流传递到 SpreadsheetDocument 时,使用以下代码:

using (PresentationDocument pd = PresentationDocument.Open(pptxFile, true))
{
  foreach (SlidePart slide in pd.PresentationPart.GetPartsOfType<SlidePart>())
  {
    foreach (EmbeddedObjectPart eoPart in slide.EmbeddedObjectParts)
    {
      using (SpreadsheetDocument sd = SpreadsheetDocument.Open(eoPart.GetStream(), true))
      {
        // do some work with worksheets                                
        var count = sd.WorkbookPart.WorksheetParts.Count();
      }
    }
  }
}

我得到以下异常:

System.IO.FileFormatException: File contains corrupted data.
at System.IO.Packaging.ZipPackage..ctor(Stream s, FileMode packageFileMode, FileAccess packageFileAccess)
at System.IO.Packaging.Package.Open(Stream stream, FileMode packageMode, FileAccess packageAccess)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.OpenCore(Stream stream, Boolean readWriteMode)
at DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Open(Stream stream, Boolean isEditable, OpenSettings openSettings)
at...

当我打开pptx包,在embeddings文件夹中将oleObject1.bin重命名为oleObject1.zip,然后在WinRar中查看文件信息,我看到它是SFX Zip卷,而不是ZipArchive。

让 SpreadsheetDocument 打开嵌入对象流的唯一方法是使用 DotNetZip 库将流转换为 System.IO.Compression.ZipArchive。

所以我有以下问题:

  1. 有没有办法让 Open XML SDK 打开嵌入式 excel 工作表流,而无需显式转码(从 SFX Zip 卷到 Zip Archive)?
  2. 将修改后的流写回演示文稿的最佳方法是什么?这很重要,因为工作表数据将被更新并且必须写回主机文档。
  3. 有没有其他更优雅的方法来解决这个问题?

注意:在演示文稿中使用 OpenXml SDK 以编程方式嵌入工作表时,不会出现此问题。

我终于想通了,虽然像WinRar这样的工具显示嵌入对象是SFX zip卷,但它实际上是一个MS-CFB(复合文件二进制)文件。

您可以通过以下方式处理 CFB 文件:

  1. Windows API: ole32.dll提供读写CFB文件的方法。我发现这个关于这个主题的文章非常好 article
  2. this page 上有一些有用的资源参考了一些开源选项。

最重要的是,为了处理作为嵌入对象嵌入到其他办公文档中的办公文档,以 MS-CFB 格式保存。读取和写入这些文件需要在 Open XML SDK 之外完成,可以使用 Win API 或任何其他替代方法。