【问题标题】:OpenXML does not help to read large Excel files contrary to documentation与文档相反,OpenXML 无助于读取大型 Excel 文件
【发布时间】:2015-03-06 11:09:54
【问题描述】:

documentation 说:

The following code segment is used to read a very large Excel 
file using the DOM approach.

然后举个例子。我用它来实现读取具有 700K 行的相对较大的文件。我现在有这个代码:

using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(path, false)) 
{
    WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
    WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
    SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
    // no other code
}

当我启动我的程序时,我发现它以多快的速度耗尽内存 (>1G) - 只需 5 秒。并且调试器指向这行代码:

SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

所以,我需要知道OpenXML 是否真的有助于读取大文件。如果没有,还有什么替代方案(互操作没有帮助 - 我已经检查过了)。

编辑

一个额外的神秘事物。我现在得到的这段代码:

OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
while (reader.Read())
{
    if (reader.ElementType == typeof(Row))
    {
        count++;
    }                                
}

count 变量中为我提供超过一百万行。但是,我在第一张纸上有 14K,在第二张纸上有 700K。这很奇怪。所以,我的额外问题是如何使用SAX 方法仅解析带有数据的行。在 OpenXML 上读取大型 Excel 文件的最后一个谜团。 thread 中的一个人说:“事实证明,由于某种原因,工作表被向后枚举(所以我的三张表中的第一张实际上是索引 3”。所以,我最后一个额外的问题是如何获得你想要的表.此刻我使用这个代码:

WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart =     workbookPart.WorksheetParts.First();

但考虑到所说的内容,我不确定在我的情况下我是否真的会得到第一个工作表。

【问题讨论】:

    标签: c# excel openxml


    【解决方案1】:

    您似乎有几个问题,我会尝试一一解决。

    所以,我需要知道 OpenXML 是否真的有助于读取大文件。如果没有,还有什么替代方案(互操作没有帮助 - 我已经检查过了)。

    是的,OpenXml SDK 非常适合读取大文件,但您可能需要使用 SAX 方法而不是 DOM 方法。从您引用的同一文档中:

    但是,DOM 方法需要将整个 Open XML 部分加载到内存中,当您处理非常大的文件时,这可能会导致内存不足异常...。当您需要处理非常大的文件时,请考虑使用 SAX。

    DOM 方法将整个工作表加载到内存中,对于大工作表可能会导致内存不足异常。使用 SAX 方法,您可以依次读取每个元素,这大大减少了内存消耗。

    所以,我的额外问题是如何使用 SAX 方法仅解析包含数据的行

    正在使用 SDK 仅获取具有数据的行(或至少是 XML 中存在的行)。您似乎已将此作为一个单独的问题提出,我已经更详细地回答了该问题,但基本上您使用问题中的代码看到了每个行元素的开始和结束。有关更多详细信息,请参阅我对您的 Why does OpenXML read rows twice 问题的回答。

    所以,我最后一个额外的问题是如何获得你想要的表格。

    您需要按名称找到Sheet,它是Workbook 的后代。一旦你有了它,你就可以使用它的Id 来获取WorksheetPart

    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, false))
    {
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
    
        Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).First();
        if (sheet != null)
        {
            WorksheetPart worksheetPart = workbookPart.GetPartById(sheet.Id) as WorksheetPart;
    
            //read worksheetPart...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2020-06-29
      相关资源
      最近更新 更多