Как включить параметры "Общий доступ" в книгах Excel?

Можно ли включить "Совместное использование" в документах Excel через OpenXML или ClosedXML? Или любая другая библиотека, если она может помочь... Я считаю, что это обычно выполняется при сохранении документа (по крайней мере, так оно работает в VBA), но я не могу найти, как указать аргументы сохранения в C#.

Я хотел бы избежать использования InterOp, так как я мог бы пакетировать этот процесс для нескольких файлов по сети.

РЕДАКТИРОВАТЬ: Согласно некоторым старым страницам с 2009 года, существуют ограничения, когда OpenXML не может работать с защищенными файлами. Однако будет ли это относится и к совместному использованию?

1 ответ

Решение

Совместное использование документов Excel с использованием OpenXML SDK плохо документировано. Я провел несколько тестов и обнаружил, что можно включить общий доступ к документам Excel с помощью OpenXML SDK. Для включения общего доступа необходимо выполнить следующие шаги:

  1. Добавить WorkbookUserDataPart в ваш документ Excel. Добавить пустой Users Коллекция на части. В этой коллекции Excel хранятся все пользователи, у которых в данный момент открыта эта общая книга.

  2. Добавить WorkbookRevisionHeaderPart в ваш документ Excel. Добавить Headers Коллекция на части. В этой коллекции Excel будет хранить ссылки на историю, версию и ревизию информации. Добавить первый элемент (Header) в коллекцию, которая содержит SheetIdMap (используется для отслеживания записей ревизий). В приведенном ниже примере кода я добавил все рабочие листы, включенные в документ. Кроме того, добавить WorkbookRevisionLogPart в части заголовка ревизии книги. В части журнала хранится список изменений, внесенных в документ.

Пример кода ниже показывает, как включить общий доступ к документу Excel. Код также проверяет, включено ли совместное использование документа.

Прежде чем включить общий доступ, вы должны создать резервную копию ваших оригинальных документов.

using (SpreadsheetDocument sd = SpreadsheetDocument.Open("c:\\temp\\enable_sharing.xlsx", true))
{
  WorkbookPart workbookPart = sd.WorkbookPart;

  if (workbookPart.GetPartsCountOfType<WorkbookRevisionHeaderPart>() != 0)
  {
    Console.Out.WriteLine("Excel document already shared!");
    return;
  }

  // Create user data part if it does not exist.
  if (workbookPart.GetPartsCountOfType<WorkbookUserDataPart>() == 0)
  {
    Console.Out.WriteLine("Adding user data part");
    WorkbookUserDataPart workbookUserDataPart = workbookPart.AddNewPart<WorkbookUserDataPart>();

    Users users = new Users() { Count = (UInt32Value)0U };
    users.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");

    workbookUserDataPart.Users = users;
  }

  // Create revision header part and revision log part.
  WorkbookRevisionHeaderPart workbookRevisonHeaderPart = workbookPart.AddNewPart<WorkbookRevisionHeaderPart>();

  WorkbookRevisionLogPart workbookRevisionLogPart = workbookRevisonHeaderPart.AddNewPart<WorkbookRevisionLogPart>();

  // Create empty collection of revisions.
  Revisions revisions = new Revisions();
  revisions.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");

  workbookRevisionLogPart.Revisions = revisions;

  string lastSetOfRevisionsGuid = Guid.NewGuid().ToString("B");

  // Create headers collection (references to history, revisions)
  Headers headers = new Headers() { Guid = lastSetOfRevisionsGuid };
  headers.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");

  int worksheetPartsCount = workbookPart.GetPartsCountOfType<WorksheetPart>();                        

  // Create first element in headers collection
  // which contains the SheetIdMap.
  Header header = new Header() { Guid = lastSetOfRevisionsGuid, DateTime = DateTime.Now, 
                                 MaxSheetId = (UInt32Value)(uint)worksheetPartsCount+1, UserName = "hans", Id = "rId1" };

  // Create the list of sheet IDs that are used for tracking
  // revision records. For every worksheet in the document
  // create one SheetId.
  SheetIdMap sheetIdMap = new SheetIdMap() { Count = (UInt32Value)(uint)worksheetPartsCount };

  for (uint i = 1; i <= worksheetPartsCount; i++)
  {
    SheetId sheetId = new SheetId() { Val = (UInt32Value)i };

    sheetIdMap.Append(sheetId);
  }        

  header.Append(sheetIdMap);
  headers.Append(header);

  workbookRevisonHeaderPart.Headers = headers;
}
Другие вопросы по тегам