保存OpenXML文档时操作共享string表

我正在尝试使用Entity Framework数据创buildExcel 2010工作簿(EF不是问题)。 我或多或less地跟随代码: CodeProject链接

在上面的链接中创build文本单元格的代码将所有文本创build为内联string。 为了遵循最佳实践(至less据我了解OpenXML)我想改变这个使用共享string表,所以我在这里find的代码来帮助。

为此,我从工作簿中获取共享string表,添加我的字符​​串,然后保存表。 我的代码:

private static int InsertSharedStringItem(WorkbookPart wbPart, string value) { int index = 0; bool found = false; var stringTablePart = wbPart.GetPartsOfType<SharedStringTablePart>() .FirstOrDefault(); if (stringTablePart == null) { // Create it. stringTablePart = wbPart.AddNewPart<SharedStringTablePart>(); } var stringTable = stringTablePart.SharedStringTable; if (stringTable == null) { stringTable = new SharedStringTable(); } foreach (SharedStringItem item in stringTable.Elements<SharedStringItem>()) { if (item.InnerText == value) { found = true; break; } index += 1; } 

  if (!found) { stringTable.AppendChild(new SharedStringItem(new Text(value))); stringTable.Save(); } 

  return index; } 

我已经突出(显然分离)的问题领域)

不幸的是我得到一个InvalidOperationException: Cannot save DOM tree since this element is not associated with an OpenXmlPart到stringTable.Save()上的OpenXmlPart。 线

我试图通过将if(!found)块更改为:

 if (!found) { stringTable.AppendChild(new SharedStringItem(new Text(value))); wbPart.SharedStringTablePart.SharedStringTable = stringTable; stringtable.Save(); } 

当代码碰到新行时,它将返回一个UnhandledArgument Exception: Cannot set the given root element to this part. The given part root element has already been associated with another OpenXmlPart. UnhandledArgument Exception: Cannot set the given root element to this part. The given part root element has already been associated with another OpenXmlPart.

在这一点上,我很困惑我的stringtable是否与OpenXmlPart相关联。

有人可以看到我做错了什么,或者指出一个更好的方法来做到这一点?

添加SharedStringTablePart时,立即初始化与该部件关联的SharedStringTable。 然后你不检查SharedStringTable对象的无效性。 尝试这个:

 if (stringTablePart == null) { // Create it. stringTablePart = wbPart.AddNewPart<SharedStringTablePart>(); stringTablePart.SharedStringTable = new SharedStringTable(); } var stringTable = stringTablePart.SharedStringTable; //if (stringTable == null) //{ // stringTable = new SharedStringTable(); //} 

我希望这个片段足以让你识别你的函数中的部分。 如果SharedStringTablePart不为null,则已经有一个SharedStringTable对象。 如果它是空的,那么…好吧,同时创build两个。

可能对原始海报没有用处,但是如果其他人绊倒了这一点。 微软的例子有一个模板excel文件,他们用来修改。 这个答案是从头创build一个Excel文档。 希望这有助于某人。

在创build和首次保存文档时,请尝试添加SharedStringTablePartSharedStringTable 。 我正在创build一个文件,并将其放置在临时文件夹中,然后重新打开文件进行修改。

 public string CreateSpreadsheet() { string filepath = Path.GetTempFileName(); filepath = filepath.Replace(".tmp", ".xlsx"); // Create a spreadsheet document by supplying the filepath. // By default, AutoSave = true, Editable = true, and Type = xlsx. SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument. Create(filepath, SpreadsheetDocumentType.Workbook); // Add a WorkbookPart to the document. WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); workbookpart.Workbook = new Workbook(); workbookpart.Workbook.Save(); **WorkbookPart wbPart = spreadsheetDocument.WorkbookPart; var stringTablePart = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault(); if (stringTablePart == null) { // Create it. stringTablePart = wbPart.AddNewPart<SharedStringTablePart>(); } stringTablePart.SharedStringTable = new SharedStringTable();** // Close the document. spreadsheetDocument.Close(); return filepath; }