System.IO.FileFormatException при открытии рабочего листа Excel, встроенного в PowerPoint 2016 с помощью OpenXml SDK

У меня есть файлы PPTX, созданные пользователями с PowerPoint 2016. На слайдах есть встроенные рабочие листы 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 для открытия потока встроенных объектов - это преобразовать поток в System.IO.Compression.ZipArchive с использованием библиотеки DotNetZip.

Итак, у меня есть следующие вопросы:

  1. Есть ли способ получить Open XML SDK для открытия встроенного потока листов Excel без явного транскодирования (из тома SFX Zip в Zip Archive)?
  2. Каков наилучший способ записать измененный поток обратно в документ презентации? Это важно, потому что данные рабочего листа будут обновлены и должны быть записаны обратно в основной документ.
  3. Есть еще один более элегантный способ решить эту проблему?

Примечание: эта проблема не возникает, когда лист внедряется программно с использованием OpenXml SDK в презентации.

1 ответ

Решение

Я наконец-то понял, что хотя такой инструмент, как WinRar, показывает, что внедренный объект - это zip-том SFX, на самом деле это файл MS-CFB (двоичный файл составного файла).

Вы можете работать с файлами CFB следующими способами:

  1. Windows API: ole32.dll предоставляет методы для чтения и записи файлов CFB. Я нашел эту отличную статью на эту тему.
  2. На этой странице есть несколько полезных ресурсов, которые ссылаются на некоторые опции с открытым исходным кодом.

В итоге, для работы с офисными документами, встроенными в другие офисные документы, как внедренными объектами, они сохраняются в формате MS-CFB. Чтение и запись в эти файлы должны выполняться вне Open XML SDK, используя Win API или любую другую альтернативу.

Другие вопросы по тегам