【问题标题】:OutOfMemoryException while saving/creating/exporting excel sheet保存/创建/导出 Excel 工作表时出现 OutOfMemoryException
【发布时间】:2022-04-27 14:47:33
【问题描述】:

开发环境:

  • 操作系统 - Windows 7 64bit
  • CPU - i5 460M
  • 内存 - 8GB
  • .NET 框架 - 4.0
  • Excel 互操作 - Microsoft Excel 14.0 对象库

我正在使用 Excel-InteropDataGridView (dgv) 导出 excel 文件。

当我保存超过 150,000 行时

OutOfMemoryException

被抛出。

{
    object[,] valueObjArray = new object[rowCnt, colCnt];
    int rowCnt = dgv.Rows.Count;
    int colCnt = dgv.Columns.Count;

    for (int rowIndex = 0; rowIndex < rowCnt; rowIndex++)
    {
        for (int colIndex = 0; colIndex < colCnt; colIndex++)
        {
            valueObjArray[rowIndex, colIndex] = dgv[colIndex, rowIndex].Value;
        }
    }

    _workSheet.get_Range("A1", Convert.ToChar(colCnt + 64).ToString() + "1").Value2 = headerObjArray;                
    _workSheet.get_Range("A2", Convert.ToChar(colCnt + 64).ToString() + (rowCnt + 1).ToString()).Value2 = valueObjArray;
    _workSheet.get_Range("B2", "B" + (rowCnt+1).ToString()).NumberFormat = "yyyy-mm-dd hh:mm";

    _workBook.SaveAs(path);
}

这是我所知道的加快速度的最佳方式。

但是,在监控 RAM 之后,我认为它会导致内存增加。当内存使用量达到大约 900Mb 时抛出异常。

如何捕捉这个异常?

【问题讨论】:

  • @Trix 感谢您的编辑:D
  • 我最后保存了 258927 行 15 列。导出的文件大小为 24.2MB,内存使用量约为 600Mb。
  • 在你写的问题中,你有 150,00 行的问题。它小于 258,927。
  • 您在哪一行收到了 OutOfMemoryException?在创建 valueObjArray 或调用 SaveAs 方法的行中...
  • @MichałKomorowski _workSheet.get_Range("A2", Convert.ToChar(colCnt + 64).ToString() + (rowCnt + 1).ToString()).Value2 = valueObjArray;这条线收到了。 258,927 行成功,但 270,000 行失败

标签: c# excel out-of-memory export-to-excel excel-interop


【解决方案1】:

尝试分批进行:

//We will call SaveAs method many times and we don't want to be asked
//if a file should be overwritten every time.
xlApp.DisplayAlerts = false

int rowCnt = dgv.Rows.Count;
int colCnt = dgv.Columns.Count;

int batchSize = 100000; //Try to experiment with other values
int currentRow = 0;

object[,] valueObjArray = new object[batchSize, colCnt];

_workSheet.get_Range("A1", Convert.ToChar(colCnt + 64).ToString() + "1").Value2 = headerObjArray;     

while (currentRow < rowCnt)
{
    for (int rowIndex = 0; rowIndex < batchSize && currentRow + rowIndex < rowCnt; rowIndex++)
    {
        for (int colIndex = 0; colIndex < colCnt; colIndex++)
        {
            valueObjArray[rowIndex, colIndex] =             
            dgv[colIndex, currentRow + rowIndex].Value;
        }
    }

    ws.get_Range("A2", Convert.ToChar(colCnt + 64).ToString() + (currentRow + batchSize + 1).ToString()).Value2 = valueObjArray;
    ws.get_Range("B2", "B" + (currentRow + batchSize + 1).ToString()).NumberFormat = "yyyy-mm-dd hh:mm";

    wb.SaveAs("a.xlsx");

    currentRow += batchSize;
}

我能够以这种方式保存 100 万行。我使用虚假数据对其进行了测试,因此可能需要进行一些小的更改/修复。

【讨论】:

  • 感谢您的回答!它工作正常。但是,我必须使用批处理意味着容量有限。我知道极限在哪里吗?
  • 嗯,很难给出一个精确的限制,这取决于列数、每个单元格中的数据大小、机器规格......
  • 这个解决方案看起来很有希望 :) 只有一个问题。切换到下一批时,我认为您需要更改以下行:ws.get_Range("A2", Convert.ToChar(colCnt + 64).ToString() + (currentRow + batchSize + 1).ToString()).Value2 = valueObjArray; 特别是“A2”,其动态值考虑了批次值。
【解决方案2】:

试试这个....

我有 20 万及以上的大量数据。首先我使用 excel 包和 Microsoft.Office.Interop.Excel 本地系统工作正常, 但 iis(静态 IP 地址)托管后(worksheet.cells/worksheet.range)OutOfMemoryeException 错误thorw。所以我正在使用 StreamWriter 并写入 .xls 文件。 .xls 转换为 .xlsx 文件并删除 .xls 文件后。它为我工作。我的英语不是很好 。请理解。

  private void ExportxlFile(DataTable dt)
    {
        try
        {
            //open file
            //non english not support(ex: Bangla Language)"সালাউদ্দিন স্টোর";
            // StreamWriter wr = new StreamWriter(@"D:\TestBook.xls");

            //non english support(ex: Bangla Language)
            StreamWriter wr = new StreamWriter(@"D:\TestBook.xls", true, Encoding.Unicode); // Encoding.Unicode or Encoding.UTF32

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                wr.Write(dt.Columns[i].ToString().ToUpper() + "\t");
            }

            wr.WriteLine();

            //write rows to excel file
            for (int i = 0; i < (dt.Rows.Count); i++)
            {
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    if (dt.Rows[i][j] != null)
                    {
                        wr.Write(Convert.ToString(dt.Rows[i][j]) + "\t");
                    }
                    else
                    {
                        wr.Write("\t");
                    }
                }
                //go to next line
                wr.WriteLine();
            }
            //close file
            wr.Close();

            //xls to xlsx convertion
            Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
            Microsoft.Office.Interop.Excel.Workbook wb = app.Workbooks.Open(@"D:\TestBook.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            wb.SaveAs(@"D:\TestBook.xlsx", Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            wb.Close();
            app.Quit();

            //delete xls file
            System.IO.File.Delete(@"D:\TestBook.xls");
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

【讨论】:

    猜你喜欢
    • 2012-08-11
    • 2020-12-13
    • 2014-09-30
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多