You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

导出Excel时触发System.OutOfMemory异常,求解决方案

解决ClosedXML导出Excel时的OutOfMemory异常

嘿,我之前在处理大数据量导出Excel时也踩过这个坑,XLWorkbook(ClosedXML库)是在内存中构建整个工作表的,当你的dt(DataTable)数据量过大时,很容易触发内存溢出异常。给你几个实用的解决思路:

1. 分批写入数据,避免一次性加载全量数据

不要直接把整个DataTable丢给Worksheets.Add,而是先创建空工作表,然后分批将数据写入,比如每次处理1000行,能大幅降低内存占用:

using (XLWorkbook wb = new XLWorkbook())
{
    string db = Request.QueryString["DB"].ToString().Replace("-", "_");
    // 注意你代码里db和de变量重复定义了,这里可以修正下
    var ws = wb.Worksheets.Add("Relatorio");
    
    // 先写入表头
    for (int col = 0; col < dt.Columns.Count; col++)
    {
        ws.Cell(1, col + 1).Value = dt.Columns[col].ColumnName;
    }
    
    // 分批写入数据,每次处理1000行
    int batchSize = 1000;
    int rowIndex = 2;
    for (int i = 0; i < dt.Rows.Count; i += batchSize)
    {
        int endRow = Math.Min(i + batchSize, dt.Rows.Count);
        for (int row = i; row < endRow; row++)
        {
            for (int col = 0; col < dt.Columns.Count; col++)
            {
                ws.Cell(rowIndex, col + 1).Value = dt.Rows[row][col];
            }
            rowIndex++;
        }
        // 手动触发垃圾回收(可选,视内存压力情况使用)
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
    
    // 设置表头样式
    ws.Range("A1:O1").Style.Fill.BackgroundColor = XLColor.Gainsboro;
    ws.Range("A1:O1").Style.Font.Bold = true;
    
    // 导出到响应流
    Response.Clear();
    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    Response.AddHeader("content-disposition", "attachment;filename=Relatorio.xlsx");
    using (MemoryStream ms = new MemoryStream())
    {
        wb.SaveAs(ms);
        ms.WriteTo(Response.OutputStream);
        Response.Flush();
        Response.End();
    }
}

2. 改用支持流式导出的库(推荐大数据量场景)

ClosedXML本身不支持流式导出,如果你数据量特别大(比如10万行以上),建议换成EPPlus库,它从5.x版本开始支持流式导出,可以直接将数据写入输出流,不需要在内存中存储整个工作表,内存占用极低:

using (var package = new ExcelPackage())
{
    var ws = package.Workbook.Worksheets.Add("Relatorio");
    
    // 启用流式模式加载DataTable
    ws.Cells["A1"].LoadFromDataTable(dt, true, TableStyles.None);
    package.Compatibility.IsWorksheets1Based = true;
    
    // 设置表头样式
    ws.Cells["A1:O1"].Style.Fill.PatternType = ExcelFillStyle.Solid;
    ws.Cells["A1:O1"].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.Gainsboro);
    ws.Cells["A1:O1"].Style.Font.Bold = true;
    
    // 直接导出到响应流
    Response.Clear();
    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    Response.AddHeader("content-disposition", "attachment;filename=Relatorio.xlsx");
    package.SaveAs(Response.OutputStream);
    Response.Flush();
    Response.End();
}

注意:使用EPPlus需要安装对应的NuGet包,商业用途需遵守其许可协议。

3. 检查并优化DataTable的数据量

先确认你的dt里到底有多少行数据,如果是几十万甚至上百万行,先考虑是否真的需要导出全量数据——比如给用户增加分页导出选项,让用户选择导出某一部分数据,从源头上减少数据量。

另外,检查DataTable中是否有不必要的大字段(比如超长字符串、二进制数据),如果有的话,尽量在导出前过滤掉或者压缩这些字段。

内容的提问来源于stack exchange,提问作者Pat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:30:05