OpenXml从大型Excel文档中的单元格读取值优化

时间:2014-10-07 18:47:25

标签: c# openxml large-files

简介

首先,让我解释一下,这不是一个问题,因为在我使用OpenXml的短暂时间里它是一个有用的提示。但是,欢迎所有评论。此外,这是一个问题,因为我无法弄清楚如何发布"建议"或者"最佳实践"交。

以下代码直接来自MSDN自己动手文档。 MSDN Do-it-yourself

...

// If the cell does not exist, return an empty string:
if (theCell != null)
{
  value = theCell.InnerText;

  // If the cell represents a numeric value, you are done. 
  // For dates, this code returns the serialized value that 
  // represents the date. The code handles strings and Booleans
  // individually. For shared strings, the code looks up the 
  // corresponding value in the shared string table. For Booleans, 
  // the code converts the value into the words TRUE or FALSE.
  if (theCell.DataType != null)
  {
    switch (theCell.DataType.Value)
    {
      case CellValues.SharedString:
        // For shared strings, look up the value in the shared 
        // strings table.
        var stringTable = wbPart.
          GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
        // If the shared string table is missing, something is 
        // wrong. Return the index that you found in the cell.
        // Otherwise, look up the correct text in the table.
        if (stringTable != null)
        {
          value = stringTable.SharedStringTable.
            ElementAt(int.Parse(value)).InnerText;
        }
        break;

      case CellValues.Boolean:
        switch (value)
        {
          case "0":
            value = "FALSE";
            break;
          default:
            value = "TRUE";
            break;
        }
        break;
    }
  }

...

瓶颈

现在,让我们特别看一下这一行。如果您只是读取一个非常大的Excel文档并从文档中的单元格中提取数据,那么这一行将导致性能瓶颈,因为每次尝试从单元格中获取字符串值时它将迭代整个SharedStringTable。

value = stringTable.SharedStringTable.
            ElementAt(int.Parse(value)).InnerText;

优化解决方案

在您的课程中插入以下字段。

private OpenXmlElement[] sharedStringArray;

打开XmlSpreadSheet后,初始化一次数组。当然,这种方法会占用更多内存,但我发现使用的内存量远远低于MSDN方法的执行时间。

var stringTable = wbPart.
          GetPartsOfType<SharedStringTablePart>().FirstOrDefault();

this.sharedStringArray = stringTable.SharedStringTable.ToArray();

现在我们可以直接引用数组,而不是迭代枚举中的所有对象。

value = this.sharedStringArray[int.Parse(value)].InnerText;

从这种方法来看,我假设不会修改共享字符串表。我也假设你可能获得了数百万个细胞的价值。这是一个简单的修改,可帮助您通过放弃少量内存来实现所需的执行时间。

我希望你喜欢!

0 个答案:

没有答案