从XLSX导出大量数据 - OutOfMemoryException

时间:2015-09-21 08:45:12

标签: .net openxml xlsx closedxml

我正在接近以Excel OpenXML格式(xlsx)导出大量数据(115.000行x 30列)。 我正在使用一些库,如DocumentFormat.OpenXML,ClosedXML,NPOI。

每次抛出OutOfMemoryException都会抛出,因为内存中表单的表示会导致指数内存增加。

每1000个关闭文档文件(并释放内存),下一次加载会导致内存增加。

有没有更高效的方法在xlsx中导出数据而不占用大量内存?

3 个答案:

答案 0 :(得分:19)

OpenXML SDK是适合此工作的正确工具,但您需要小心使用SAX(Simple API for XML)方法而不是DOM方法。来自SAX的链接维基百科文章:

  

在DOM作为整体对文档进行操作的地方,SAX解析器按顺序对每个XML文档进行操作

这个极大地减少了处理大型Excel文件时消耗的内存量。

这里有一篇很好的文章 - http://polymathprogrammer.com/2012/08/06/how-to-properly-use-openxmlwriter-to-write-large-excel-files/

改编自该文章,这是一个输出115k行,包含30列的例子:

[for (x of _.range(192, 256)) for (y of _.range(0, 256)) `10.${x}.${y}.1`];

答案 1 :(得分:1)

只要您的计算机有足够的内存,Excel就能打开相当大的文件。这大部分时间都是限制因素......

99%的库尚未构建用于处理大型数据集,如果您尝试向它们投入太多数据,最终会出现内存不足错误。

我创建了一些像我创建的Spout来解决这个问题。诀窍是流式传输数据并避免将内容存储在内存中。我不确定你使用的是哪种语言(不是PHP似乎),但是你的语言可能有类似的库。如果没有,你仍然可以看看Spout - 它是开源的 - 并用你的语言转换它。

答案 2 :(得分:-1)

看起来您正在使用必须使用数据库的电子表格。它有其局限性,这很容易就是其中之一。如果您绝对需要坚持使用现有解决方案,请进一步阅读。但是,我不推荐它。因为还有一个问题:如果Excel无法保存这么大的文件,是否可以打开这样的文件?

因此,如果您无法切换到上面提到的数据库平台和标准库,那么内部无法处理这么多数据,那么在创建大型XLSX时可能就是您自己。我的意思是这种方法:

  1. 批量导出数据(1,000或10,000或其他任何工作)以分离每批文件
  2. 创建工具((最接近),,无论具有可靠的XML库)将单独的文件合并为一个。它涉及:

    1. 从XLSX中提取XML(通常为file.xlsx\xl\worksheets\sheet1.xmlfile.xlsx\xl\worksheets\sharedStrings.xml
    2. 通过XML操作库将这些部分粘合在一起(这不应该在OutOfMemoryException上崩溃,因为您不再使用复杂的电子表格对象)
    3. 将结果文件重新打包回主XLSX(您可以将第一批输出文件作为主XLSX)
  3. 我已经向您展示了完成结果的可能方法,但我会避免这种情况。 Excel从来就不是存储大量数据的平台。与上述任务相比,可以更容易说服管理层是时候改变这一领域的工具/流程了。