保存OpenXML文档时操作共享字符串表

时间:2013-04-04 05:29:47

标签: c# excel excel-vba openxml vba

我正在尝试使用Entity Framework数据创建Excel 2010工作簿(EF不是问题)。我或多或少地遵循以下代码:CodeProject link

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

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

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;
}

我突出显示(并且明显分开)问题区域)

不幸的是我在stringTable.Save()上得到了InvalidOperationException: Cannot save DOM tree since this element is not associated with an 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.

此时,我对我的stringtable是否与OpenXmlPart相关联感到困惑。

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

2 个答案:

答案 0 :(得分: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对象。如果它为null,那么......好吧,同时创建两个。

答案 1 :(得分:2)

可能对原始海报没用,但万一其他人偶然发现了这个。 Microsoft的示例有一个用于修改的模板excel文件。这个答案是从头开始创建一个excel文档。希望这有助于某人。

创建并首次保存文档时,请尝试添加SharedStringTablePartSharedStringTable。我正在创建一个文件并将其放在temp文件夹中,然后重新打开要修改的文件。

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;
    }