如何使用 C# 处理极大的 .xlsx 文件

AVA*_*AVT 2 c# excel memory-management

我需要解决的情况

我的客户有一些非常大的 .xlsx 文件,类似于数据库表(每行是一条记录,列是字段)

我需要帮助他们处理这些文件(搜索、过滤等)。

我的意思是其中最小的有 100 万条记录。


我尝试过的:

  • SheetJS 和 NPOI:两个库都只回复一个简单的“文件太大”。
  • EPPlus:可以读取多达数百 K 条记录的文件,但是当面对实际文件时,它只会给我一个 . System.OverflowException,我的猜测是它基本上内存不足,因为一个 200MB 的 xlsx 文件已经占用了我 4GB 的内存来读取。
  • 我没有尝试 Microsoft OleDB,但我宁愿避免它,因为我不想为了工作而购买 Microsoft Office。

由于保密,我无法共享实际文件,但您可以轻松创建一个类似的结构,其中包含 60 个列(名字、姓氏、dob 等)和大约 100 万条记录。

只要您可以读取具有该条件的 .xlsx 文件,删除一半的记录,然后写入另一个地方而不会遇到内存问题,这个问题就会解决

  • 时间不是太大的问题。如果需要,用户愿意等待一两个小时的结果。
  • 内存似乎是当前的问题。这是个人要求,客户的机器是一台内存上限为 8GB 的​​笔记本电脑。
  • csv不是这里的选项。我的客户有 .xlsx 输入并且需要 .xlsx 输出。
  • 语言选择最好是 JS,C# for Python,因为我已经知道如何用它们创建可执行文件(不能告诉会计师学习终端,我们可以吗?)。

如果有一种方法可以逐行缓慢地从文件中读取小块数据,那就太好了,但我发现的解决方案只能同时读取整个文件。

Rom*_*lko 5

对于读取Excel文件,我会推荐ExcelDataReader。它在读取大文件方面做得非常好。我个人尝试过500k-1M

using (var stream = File.Open("C:\\temp\\input.xlsx", FileMode.Open, FileAccess.Read))
{
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        while (reader.Read())
        {
            for (var i = 0; i < reader.FieldCount; i++)
            {
                var value = reader.GetValue(i)?.ToString();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以同样有效的方式写回数据更加棘手。我完成了创建自己的SwiftExcel库,该库非常快速和高效(有一个性能图表与其他Nuget库包括EPPlus),因为它不使用任何 XML 序列化并将数据直接写入文件:

using (var ew = new ExcelWriter("C:\\temp\\test.xlsx"))
{
    for (var row = 1; row <= 100; row++)
    {
        for (var col = 1; col <= 10; col++)
        {
            ew.Write($"row:{row}-col:{col}", col, row);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)