EPPlus 将 200 万行、200 多列的数据表保存到多个 Excel 文件

2023-12-11

我有使用 EPPlus 将所有记录从 SQL 表保存到 Excel 工作表的功能。 如果我导出少量数据,一切正常,但如果导出 200 多列和 500 000 多行,则会出现 OutOfMemory 异常。

我想修改我的代码,以便每个文件能够保存 50 000 条记录。

这是我的适用于小数据的代码:

private Task SaveAsync(string tableName)
{

    return Task.Run(() =>
    {
        try
        {
            using (var conn = new SqlConnection(_connectionString))
            {
                using (var cmd = new SqlCommand(string.Format(DataQuery, tableName), conn))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandTimeout = 360;
                    conn.Open();
                    using (SqlDataReader sdr = cmd.ExecuteReader())
                    {
                        var fileName = string.Format(TargetFile, tableName);
                        if (File.Exists(fileName))
                        {
                            File.Delete(fileName);
                        }

                        sdr.Read();
                        var numberOfRecordsInTable = sdr.GetInt32(0);

                        sdr.NextResult();

                        using (ExcelPackage pck = new ExcelPackage(new FileInfo(fileName)))
                        {
                            ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Results");

                            int count = sdr.FieldCount;
                            int col = 1, row = 1;

                            for (int i = 0; i < count; i++)
                            {
                                ws.SetValue(row, col++, sdr.GetName(i));
                            }
                            row++;
                            col = 1;
                            while (sdr.Read())
                            {
                                for (int i = 0; i < count; i++)
                                {
                                    var val = sdr.GetValue(i);
                                    ws.SetValue(row, col++, val);
                                }
                                row++;
                                col = 1;
                            }
                            //autosize
                            ws.Cells[ws.Dimension.Address].AutoFitColumns();
                            //autofiltr
                            ws.Cells[1, 1, 1, count].AutoFilter = true;
                        }
                    }
                    conn.Close();
                }
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine("Error at: " + Thread.CurrentThread.ManagedThreadId);
            Debug.WriteLine(e);
        }
    });
}

我修改后的代码将每个文件分割 50 000 条记录:

private Task SaveAsync2(string tableName)
{
    return Task.Run(() =>
    {
        try
        {
            using (var conn = new SqlConnection(_connectionString))
            {
                using (var cmd = new SqlCommand(string.Format(DataQuery, tableName), conn))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandTimeout = 360;
                    conn.Open();
                    using (SqlDataReader sdr = cmd.ExecuteReader())
                    {

                        var fileName = string.Format(TargetFile, tableName,"");
                        if (File.Exists(fileName))
                        {
                            File.Delete(fileName);
                        }

                        sdr.Read();
                        var max = sdr.GetInt32(0);
                        int filesCount = 1;
                        if (max > 50000)
                        {
                            fileName = string.Format(TargetFile, tableName, filesCount);
                        }

                        sdr.NextResult();

                        ExcelPackage pck = new ExcelPackage(new FileInfo(fileName));
                        ExcelWorksheet ws = pck.Workbook.Worksheets.Add("RESULTS");

                        int count = sdr.FieldCount;

                        int col = 1, row = 1;

                        for (int i = 0; i < count; i++)
                        {
                            ws.SetValue(row, col++, sdr.GetName(i));
                        }
                        row++;
                        col = 1;
                        while (sdr.Read())
                        {
                            for (int i = 0; i < count; i++)
                            {
                                var val = sdr.GetValue(i);
                                ws.SetValue(row, col++, val);
                            }
                            row++;
                            col = 1;

                            if (row > 50000)
                            {
                                pck.Save();
                                filesCount++;
                                fileName = string.Format(TargetFile, tableName, filesCount);

                                pck = new ExcelPackage(new FileInfo(fileName));
                                ws = pck.Workbook.Worksheets.Add("RESULTS");

                                count = sdr.FieldCount;

                                col = 1;
                                row = 1;

                                for (int i = 0; i < count; i++)
                                {
                                    ws.SetValue(row, col++, sdr.GetName(i));
                                }
                                row++;
                                col = 1;
                            }
                        }

                        //autosize
                        ws.Cells[ws.Dimension.Address].AutoFitColumns();
                        //autofiltr
                        ws.Cells[1, 1, 1, count].AutoFilter = true;

                        pck.Save();
                    }
                }
                conn.Close();

            }
        }
        catch (Exception e)
        {
            Debug.WriteLine("Error at: " + Thread.CurrentThread.ManagedThreadId);
            Debug.WriteLine(e);
        }
    });
}

基本上这工作正常,但在我的代码的第一个版本中,我使用了里面的所有内容using声明,在第二个版本中我调用相同的代码两次。

  1. 我怎样才能修复我的代码以删除重复的代码并将所有内容放入使用中。
  2. 我可以添加下一组(50 000 条记录)作为新工作表而不是创建新文件吗?
  3. 将数据保存到文件时 EPPlus 的限制是多少?rows x columns?我发现 EPPlus 应该处理超过一百万行的信息,但没有我拥有的那么多列。我认为我可以用单列导出百万行,但对于 200 多列,对我来说 50 000 行是限制。我想知道是否存在限制我的导出正常工作的数字(行x列)。我希望该导出函数是通用的,因此当我传递具有 50 列的数据表时,它将导出每个文件 100 000 行,对于 2 列,它将导出每个文件 50 万行。

我过去曾遇到 EPPlus 的内存限制,最终生成了多个 .xlsx 文件作为解决方法(类似于您的方法)。另一种选择是将编译器设置更改为仅针对 64 位(如果您可以不支持 32 位平台)。我记得,EPPlus 是针对“任何 CPU”编译的,因此如果您可以将代码更改为目标“x64”,则可能会放宽内存限制并允许您生成单个 .xlsx 文件。以 x64 为目标可能对我的情况有效,但我直到事后才想到这一点,所以我从来没有机会进行测试。

UPDATE:我刚刚使用 EPPlus 3.1.3 运行了一个快速测试,创建了 500,000 行,每行 70 列。我的 32 位应用程序在生成内存不足异常之前能够生成大约 119,000 行。将目标切换到 x64 后,它成功生成了所有 500,000 行,尽管花了很长时间。创建实际工作表只花了几分钟,但 ExcelPackage.SaveAs() 花了近 20 分钟。 RAM 消耗也相当高(大约 11GB RAM)。生成的 .xlsx 大小为 220MB,32 位 Excel 无法打开(内存不足)。底线:以 x64 为目标可能不是一个可行的解决方案;您最好将输出拆分为多个 .xlsx 文件。

我很想删除这个答案,因为它被证明是一个死胡同,但决定保留它,以防它帮助其他人将来避免这条路。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EPPlus 将 200 万行、200 多列的数据表保存到多个 Excel 文件 的相关文章

随机推荐

  • 对空数组使用 $push

    我有一个 mongo 文档 其中包含名为 events 的数组字段 该字段有时可能为空 我在用着 push将元素添加到 事件 数组中 问题是 当 events 字段为空时它无法工作 例如 如果在数据库中它看起来像这样 id ObjectId
  • 如何修剪字符串中的空格? [复制]

    这个问题在这里已经有答案了 我正在为 J2ME 应用程序编写此函数 因此我没有一些可用的更高级 现代的 Java 类 我正进入 状态java lang ArrayIndexOutOfBoundsException关于这一点 所以 显然它不喜
  • ASP javascript radiobutton启用禁用不包含在回发ajax中

    问题就在这里 我有一个单选按钮组 两个单选按钮 这些人最初都是残疾的 当用户单击复选框时 我通过设置动态启用 JavaScript 中的单选按钮rbtn disabled false 并对其父级 span 元素 执行相同操作 以便它在 IE
  • div 内的 JQuery .load()

    这让我抓狂 我搜索并尝试了一堆看起来应该有效的建议 所以我一定是做了一些愚蠢的事情 document ready function trigger click function var link this attr href target
  • R数据框字符串包含:第1列是否包含第2列?

    我有一个包含两列的数据框 Surname Email 1 house email protected 2 wilson email protected 我想创建一个逻辑向量来检查是否Surname包含在Email 因此结果应该是 Surna
  • 如何在 Flexbox 内获取具有外部高度和内部宽度的 div

    Problem 假设我们有一个具有给定宽度和高度的垂直 即 flex direction column Flexbox 容器 Flexbox 包含 div 每个 div 包含一个图像 所有 div 和图像都应该以相同的百分比收缩 增长以填充
  • Android Studio 模拟器找不到 wglgetextensionsstringarb

    When I try to start the emulator suddenly I started getting this error 几天前一切正常 如果我禁用 GPU 加速 那么它可以工作 但速度非常慢 我尝试在 BIOS 中重新
  • 如何打破条形图中的轴(也许使用plotrix gap.barplot)?

    我发现了很多解决轴中断和间隙的问题和答案 但大多数都是低质量的 SO 意义上的 因为没有示例代码 没有图片或复杂的代码 这就是我问的原因 我尝试使用library plotrix 如果有一个没有它和 或另一个库的解决方案 那对我来说也可以
  • 在 ui:repeat 或 p:dataTable 中使用 p:graphicImage

    我有一个 Bean 它有一个对象列表 其中包含代表数据库中图像的 StreamedContent 对象 Primefaces 类型 现在我想在 JSF 2 0 页面 使用 Primefaces 中迭代此列表 并显示图像 以这种方式仅显示一张
  • 如何防止 PrimeFaces 向导的下一步按钮激活客户端验证?

    我的 JSF 2 2 PrimeFaces 应用程序中有一个带有三个选项卡的向导 在每个选项卡中 我都有一个表单来捕获用户的数据 每个表单都有一些验证 现在 当我单击 下一步 进入下一个选项卡时 它正在验证表单中的数据 我不希望这种事发生
  • Google Api 获取用户电子邮件地址

    我正在使用 Google Api PHP 客户端登录用户 我想获取用户的电子邮件地址 我有以下代码 Scope client gt setScopes https www googleapis com auth userinfo profi
  • @function 处的 Mingw32 汇编器错误

    我正在使用 mingw32 将一个项目移植到 Windows 该项目依赖于一个名为 libfec 的库 Libfec 有大量汇编代码来优化内部工作 在 Linux 使用 GCC 5 4 中 该库编译得很好 今天我尝试使用 mingw32 以
  • 从 PHP 写入图像文件时出错

    我正在尝试从 blob 写入图像文件 if POST logoFilename undefined logoFile fopen POST logoFilename w or die Cannot create POST logoFilen
  • Appcelerator 5.2GA 中的 Facebook 模块不再是 64 位

    Facebook 模块已停止工作 我正在 appcelerator 中开发钛金应用程序 当我尝试构建我的应用程序时 出现以下错误 INFO Invoking xcodebuild ERROR BUILD FAILED ERROR The f
  • 使用 Perl 提取特定行

    我正在编写一个 perl 程序来提取我匹配的两个模式之间的行 例如下面的文本文件有 6 行 我正在匹配负载均衡器和终端 我想要得到中间的 4 条线 load balancer new old good bad end 我的问题是如何将负载均
  • 对如何构建 GUI (wxpython) 感到困惑

    我从一本书转到另一本书 从谷歌搜索到另一本书 我注意到每一本书都以完全不同的方式启动主窗口 我不想养成坏习惯 所以有人可以给我最好的这些选择以及为什么这是更好的方法 以下是我见过的所有方法 A 类 iFrame wx Frame 定义ini
  • 发送有关受监控目录中文件更改的电子邮件

    如果服务器上的员工文件夹中的文件发生更改 我想向我们公司的人员发送电子邮件通知 我有一个脚本 可以很好地使用 inotifywait 在每次文件更改时发送电子邮件 我想做的是在多个文件上传 假设 10 个 jpg 正在上传到某人的员工文件夹
  • 使用 set_value 以 codeigniter 形式填充下拉列表

    我有一个使用下拉菜单的表单 我使用 codeigniter 表单助手和表单验证 因此 当我在表单中收到验证错误时 所有正确输入的字段都会使用 codeigniter 的 set value 进行填充 但这不适用于下拉列表 我正在做 当表单出
  • 如何使用 Windows 身份验证连接字符串使用 OLEDB 连接到 SQL Server

    我的 SQL Server 2010 在 Windows 身份验证模式下运行 并且已分配了正确的组 我可以使用 Windows 身份验证通过 SQL Server Client Studio 进行连接 这样可行 但是当使用 NET OLED
  • EPPlus 将 200 万行、200 多列的数据表保存到多个 Excel 文件

    我有使用 EPPlus 将所有记录从 SQL 表保存到 Excel 工作表的功能 如果我导出少量数据 一切正常 但如果导出 200 多列和 500 000 多行 则会出现 OutOfMemory 异常 我想修改我的代码 以便每个文件能够保存