4

我正在尝试使用实体框架数据创建 Excel 2010 工作簿(EF 不是问题)。我或多或少在以下代码中: CodeProject 链接

在上面的链接中创建文本单元格的代码将所有文本创建为内联字符串。为了遵循最佳实践(至少就我对 OpenXML 的理解而言),我想将其更改为使用共享字符串表,因此我将遵循此处找到的代码以提供帮助。

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

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(); 线

我试图通过将 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.

在这一点上,我对 mystringtable是否与 OpenXmlPart 相关联感到困惑。

有人可以看到我做错了什么,或者指出更好的方法吗?

4

2 回答 2

4

添加 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 对象。如果它为空,那么......好吧,同时创建两者。

于 2013-04-16T03:00:51.227 回答
2

Probably not useful for the original poster, but in case anyone else stumbles across this. Microsoft's example has a template excel file they use to modify. This answer is for creating an excel document from scratch. Hope this helps someone.

Try adding the SharedStringTablePart and SharedStringTable when creating and first saving the document. I'm creating a file and place it in the temp folder, then reopen the file to modify.

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;
    }
于 2014-09-13T01:48:17.400 回答