Как ускорить вставку данных в Excel

Многие сталкиваются с необходимостью передачи (экспорта) данных из своих программы в Excel.
Ниже мы рассмотрим два варианта для записи данных в Excel файл.
Первый вставка значений в каждую ячейку из кода программы, путем простого перебора (и да… оказывается так многие делают и сейчас)
Второй вариант это заполнение двумерного массива необходимыми значениями и последующая вставка этого массива целиком, так сказать разом.
Ниже представлен маленький тест демонстрирующий разницу в скорости работы двух методов вставки:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;</code>

namespace ExcelTestNet
{
class Program
{
static void Main(string[] args)
{
Excel.Application xlApp;
//Рабочая книга
Excel.Workbook xlWorkbook;
//Лист
Excel._Worksheet xlWorksheet;
//Диапазон
Excel.Range xlRange;

//Создаем Excel
xlApp = new Excel.Application();
//Создали книгу
xlWorkbook = xlApp.Workbooks.Add();
//Добавили новый лист
xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];

//Создали и запустили таймер
Stopwatch watch = new Stopwatch();
watch.Start();

for (int row = 1; row &lt; 100; row++)
for (int col = 1; col &lt; 100; col++)
((Excel.Range)xlWorksheet.Cells[row, col]).Value2 = "row:" + Convert.ToString(row) + ", col:" + Convert.ToString(col);

//Остановили таймер
watch.Stop();
Console.WriteLine("Потрачено времени {0}", watch.Elapsed);

//Создали новый лист
xlWorkbook.Sheets.Add();
xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];

//Перезапустили таймер
watch.Restart();

//Создаем двумерный массив типа string[,] и заполняем его
string[,] data = new string[99, 99];
for (int row = 1; row &lt; 100; row++)
for (int col = 1; col &lt; 100; col++)
data[row-1,col-1]= "row:" + Convert.ToString(row) + ", col:" + Convert.ToString(col);

//Определяем верхнюю левую ячейку для вставки нашего массива
Excel.Range c1 = xlWorksheet.Cells[1, 1];
//Определяем нижнюю правую ячейку для вставки
Excel.Range c2 = xlWorksheet.Cells[data.GetLength(0), data.GetLength(1)]; //Получаем размеры наешго массива

//Создаем диапазон с верхней левой ячейки до нижней правой
xlRange = xlWorksheet.get_Range(c1, c2);
//Записываем в диапазон xlRange содержимое массива data
xlRange.Value = data;

watch.Stop();

Console.WriteLine("Потрачено времени {0}", watch.Elapsed);
Console.ReadLine();

//СОхраняем файл Exel
xlWorkbook.SaveAs("g:\\test.xlsx");

//Прибираемся
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
xlWorkbook.Close();
Marshal.ReleaseComObject(xlWorkbook);
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);

}
}

}

Результаты теста:
1. Простая вставка в каждую ячейку 99 строк, 99 столбцов — Потрачено времени 00:00:54.324226
2. Вставка массива 99 строк, 99 столбцов — Потрачено времени 00:00:00.0787437

Вполне ожидаемые результаты.

Но есть одно но, всё это достаточно быстро до того момента, пока не потребуется менять стили (шрифт, цвет шрифта, цвет фона и т.д.), тут уже тормозов не избежать. Пример из практики: выгрузка из 30К записей, вставка массивом по способу выше заняла несколько секунд, возникла необходимость стилизации выгружаемых данных, строки групп одним цветом, вложенные подстроки другим шрифтом, после решения в лоб, выгрузка длилась около 8 часов (там множество условий подсветки).

Естественно, что такой способ выгрузки уже не подходит. Лучшее решение для ускорения выгрузки это писать напрямую в экселевский файл. В моём случае я использовал библиотеку EPPlus. С тем же самым решением в лоб, выгрузка занимает 1 минуту

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *