Microsoft.Office.Interop.Excel真的很慢

Ale*_*lex 41 c# excel interop

我使用标准的Microsoft.Office.Interop.Excel将1200 X 800矩阵(indexMatrix)导出到excel文件.该应用程序工作,只是它真的非常慢(即使对于100 x 100矩阵).我还通过TextWriter导出文本文件,它几乎可以立即工作.有没有办法更快地导出到excel文件?

这是我的代码:

        Excel.Application xlApp=new Excel.Application();
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        object misValue = System.Reflection.Missing.Value;

        //xlApp = new Excel.ApplicationClass();
        xlWorkBook = xlApp.Workbooks.Add(misValue);

        xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
        for (int i = 0; i < 800; i++)   //h
            for (int j = 0; j < 1200; j++)
                xlWorkSheet.Cells[i+1,j+1] =indexMatrix[i][j];


        xlWorkBook.SaveAs("C:\\a.xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
        xlWorkBook.Close(true, misValue, misValue);
        xlApp.Quit();

        releaseObject(xlWorkSheet);
        releaseObject(xlWorkBook);
        releaseObject(xlApp);

        MessageBox.Show("Excel file created , you can find the file c:\\csharp-Excel.xls");
Run Code Online (Sandbox Code Playgroud)

Joe*_*Joe 66

您正在更新单个单元格.那将是非常缓慢的.如果您考虑一下,每次更新单元格时,RPC调用都将被编组到Excel进程.

这将是很大,如果你在一条语句(一个跨进程调用),代替目前的1200*800 = 960000跨进程调用指定您的值二维数组相同尺寸的Excel范围更快.

就像是:

// Get dimensions of the 2-d array
int rowCount = indexMatrix.GetLength(0);
int columnCount = indexMatrix.GetLength(1);
// Get an Excel Range of the same dimensions
Excel.Range range = (Excel.Range) xlWorkSheet.Cells[1,1];
range = range.get_Resize(rowCount, columnCount);
// Assign the 2-d array to the Excel Range
range.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, indexMatrix);
Run Code Online (Sandbox Code Playgroud)

实际上,要迂腐,上面的代码中有三个跨进程调用(.Cells,.get_Resize和.set_Value),并且在代码中每次迭代有两次调用(.Cells get和一个隐式.set_Value)总计1200 x 800 x 2 = 1,920,000.

注意 range.get_Resize并且range.set_Value是我在第一次创作此帖子时使用的旧版Excel互操作库所需的.这些天你可以使用range.Resizerange.Value@The1nk评论中所述.

  • "如果你考虑一下,每次更新单元格时,RPC调用都会被编组到Excel进程中." 即使你没有考虑它,这可能仍会发生. (4认同)
  • 美丽的解决方案,为我的43,479细胞工作.从5分钟到3秒.未来访客的一个注意事项 - 您不需要使用`get_Resize`或`set_Value`.你只需正常使用`cell.Resize`和`cell.Value`. (3认同)
  • 谢谢,但给出了“HRESULT:0x800A03EC”异常。 (2认同)

Yul*_*liy 16

Excel互操作永远不会快.您基本上是远程控制Excel应用程序的实例.您可以通过创建CSV文件然后使用Excel interop将其转换为.xls或.xlsx文件来获得更多成功


MIK*_*IKE 10

我在阅读一个非常大的ex​​cel文件时遇到了类似的问题,并且使用interop花了2个多小时.

我尝试使用ClosedXml,这个过程不到10秒. ClosedXml

// To loop 
Sheet.Row(y).Cell(x).Value
Run Code Online (Sandbox Code Playgroud)

另外请记住,除非安装了excel,否则interop将无法在您的服务器上运行.ClosedXml不需要安装excel.


小智 7

ScreenUpdating在写入任何数据之前关闭,Application.ScreenUpdating = FALSE然后在代码结束时打开= TRUE