Microsoft.Office.Interop.Excel really slow

前端 未结 8 1527
执笔经年
执笔经年 2020-11-27 13:43

I am exporting a 1200 X 800 matrix (indexMatrix) to a excel file using the standard Microsoft.Office.Interop.Excel. The app works, just that it is really really really slow(

相关标签:
8条回答
  • 2020-11-27 14:34

    There are three ways to do this, 2 of which are mentioned in different answers by others:

    1. Directly set the value of a range in excel to the 2D array.
    2. Write data to a CSV file, then use interop to save the CSV file as an xls or xlsx file.
    3. Write data to a CSV file, then use the data connections feature to use the CSV as a data source and import the data.

    All the three methods above are very fast. I could write data with a size of 90000 rows and 100 columns in around 6 seconds.

    P.S. They didn't however solve my problem with formatting the data for borders, font styles, colors, cell merging etc.

    0 讨论(0)
  • 2020-11-27 14:40

    You are updating individual cells. That's going to be very slow. If you think about it, each time you update a cell, an RPC call will be marshalled to the Excel process.

    It will be much faster if you assign your two dimensional array of values to an Excel Range of the same dimensions in a single statement (one cross-process call) instead of your current 1200 x 800 = 960,000 cross-process calls.

    Something like:

    // 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);
    

    Actually, to be pedantic, there are three cross-process calls in the above code (.Cells, .get_Resize and .set_Value), and there are two calls per iteration in your code (.Cells get and an implicit .set_Value) for a total of 1200 x 800 x 2 = 1,920,000.

    Note range.get_Resize and range.set_Value were needed for an old version of the Excel interop library I was using when this post was first authored. These days you can use range.Resize and range.Value as noted in the comment by @The1nk.

    0 讨论(0)
提交回复
热议问题