Подтвердить что ты не робот

Microsoft.Office.Interop.Excel действительно медленный

Я экспортирую матрицу 1200 X 800 (indexMatrix) в файл excel, используя стандартный Microsoft.Office.Interop.Excel. Приложение работает, просто, что это действительно действительно очень медленно (даже для матрицы 100 х 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");
4b9b3361

Ответ 1

Вы обновляете отдельные ячейки. Это будет очень медленно. Если вы думаете об этом, каждый раз, когда вы обновляете ячейку, вызов RPC будет перенаправлен на процесс Excel.

Это будет намного быстрее, если вы присвоите свой двумерный массив значений диапазону Excel одинаковых размеров в одном выражении (один межпроцессный вызов) вместо текущего 1200 x 800 = 960 000 межпроцессных вызовов.

Что-то вроде:

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

На самом деле, чтобы быть педантичным, в приведенном выше коде есть три вызова по перекрестному процессу (.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.Resize и range.Value, как указано в комментарии @The1nk.

Ответ 2

Интеллект Excel никогда не будет быстрым. Вы в основном дистанционно управляете экземпляром приложения Excel. У вас может быть больше успеха, создав файл CSV, а затем с помощью Excel interop, чтобы преобразовать его в файл .xls или .xlsx.

Ответ 3

У меня были схожие проблемы при чтении чрезвычайно большого файла excel, и он занял более 2 часов, используя interop.

Я попытался использовать ClosedXml, и процесс занял менее 10 секунд. ClosedXml

// To loop 
Sheet.Row(y).Cell(x).Value

Также имейте в виду, что interop не будет работать на вашем сервере, если вы не используете excel. ClosedXml не требует установки excel.

Ответ 4

Используйте значение2, чтобы сделать его быстрым; Показывать excel перед заполнением данных

Ответ 5

Отключите ScreenUpdating перед записью любых данных Application.ScreenUpdating = FALSE, затем включите в конце кода = TRUE

Ответ 6

ClosedXML - это чудо, это намного быстрее и проще в использовании.

var workbook = new XLWorkbook();//create the new book

var worksheet = workbook.Worksheets.Add("Computer Install");// Add a sheet
worksheet.Cell(1,1).Value = "PC Name";// (Row, column) write to a cell

workbook.SaveAs(@"LIC documents.xlsx");// Save the book

Вы устанавливаете с помощью пакета nu Get. https://www.nuget.org/packages/ClosedXML

Ответ 7

Есть три способа сделать это, 2 из которых упоминаются в разных ответах другими:

  • Непосредственно задайте значение диапазона в excel для 2D-массива.
  • Запишите данные в файл CSV, затем используйте interop для сохранения CSV файла в виде файла xls или xlsx.
  • Запишите данные в файл CSV, затем используйте функцию подключения данных, чтобы использовать CSV в качестве источника данных и импортировать данные.

Все три метода выше очень быстры. Я мог бы написать данные размером 90000 строк и 100 столбцов примерно за 6 секунд.

P.S. Однако они не решили мою проблему с форматированием данных для границ, стилей шрифтов, цветов, слияния ячеек и т.д.