Автоматизация Excel - установить шрифт ячейки

Это мой оригинальный код для настройки содержимого листа Excel. Короче говоря, код перебирает все строки и столбцы и устанавливает три вещи: содержимое ячейки, цвет шрифта ячейки и цвет фона ячейки:

Excel_xp::ExcelApplicationPtr app = excel->Application;
app->set_ScreenUpdating(LOCALE_USER_DEFAULT, TVariant(false));

Excel_xp::ExcelRangePtr cells = worksheet->Cells;
cells->Clear();

for (int i = 0; i < line_count; i++)
{
   CsvLine *line = lines[i];
   int col_count = line->GetColCount();
   for (int j = 0; j < col_count; j++)
   {
      CsvLine::Data data;
      line->GetData(j, data);
      TVariant _cell = cells->get_Item(TVariant(i+1), TVariant(j+1));
      IDispatch *__cell = (IDispatch*)_cell;
      Excel_xp::ExcelRange *cell = NULL;
      if (__cell->QueryInterface(DIID_ExcelRange, (void**)&cell) != S_OK)
      {
         __cell->Release();
         __cell->Release();
         __cell = NULL;
         continue;
      }

      cell->set_Item(TVariant(1), TVariant(1), TVariant(data.str));

      TColor font_color, back_color;
      if (data.good || ((!data.good) && (!highlight_bad_values)))
      {
         font_color = (TColor)0;
         back_color = (TColor)-4142;
      }
      else
      {
         font_color = (TColor)0x06009C;
         back_color = (TColor)0xCEC7FF;
      }
      Excel_xp::FontPtr font = cell->Font;
      font->set_Color(TVariant(font_color));
      font->Release();
      font = (IUnknown*)NULL;
      Excel_xp::InteriorPtr back = cell->Interior;
      back->set_Color(TVariant(back_color));
      back->Release();
      back = (IUnknown*)NULL;

      cell->Release();
      cell->Release();
      cell->Release();
      cell = NULL;
   }
}

Предыдущий код, даже когда функционально в порядке, имел один недостаток, а именно скорость. Каждый вызов функции из интерфейса COM имеет некоторые накладные расходы (около 1 - 3 мс). Для создания листа, состоящего из 900 строк x 6 столбцов, мне потребовалось около 38 секунд, что было неприемлемо по сравнению с производительностью современных вычислений. Поэтому я оптимизировал код. Вместо того, чтобы устанавливать ячейку за ячейкой, я сначала подготовил все данные в памяти в одном большом массиве и установил содержимое всего листа за один шаг. Позже я могу оптимизировать его, чтобы минимизировать требования к памяти моего приложения. Я могу ограничить максимальное количество строк, записанных за один шаг, например, до 100. Но это не имеет отношения к моей проблеме. Это мой оптимизированный код:

Excel_xp::ExcelApplicationPtr app = excel->Application;
app->set_ScreenUpdating(LOCALE_USER_DEFAULT, TVariant(false));

Excel_xp::ExcelRangePtr cells = worksheet->Cells;
cells->Clear();

int bounds[] = {1, lines.size(), 1, GetMaxColCount()};
Variant arr_text = VarArrayCreate(bounds, 3, varVariant);
int line_count = lines.size();
int arr_idx[2];
for (int i = 0; i < line_count; i++)
{
   arr_idx[0] = i + 1;
   CsvLine *line = lines[i];
   int col_count = line->GetColCount();
   for (int j = 0; j < col_count; j++)
   {
      arr_idx[1] = j + 1;
      CsvLine::Data data;
      line->GetData(j, data);
      VarArrayPut(arr_text, TVariant(data.str), arr_idx, 1);      
   }
}
TVariant _cell1 = cells->get_Item(TVariant(1), TVariant(1));   // ref_count = 1
TVariant _cell2 = cells->get_Item(TVariant(bounds[1]), TVariant(bounds[3]));   // ref_count = 1
Excel_xp::ExcelRangePtr rng = cells->get_Range(_cell1, _cell2);
_cell1 = NULL;
_cell2 = NULL;

rng->set_Value2(arr_text);
arr_text.Clear();
rng->Release();
rng = (IUnknown*)NULL;

Сейчас я пытаюсь использовать тот же механизм для шрифта ячейки. Можно ли подготовить массив цветов шрифта (где каждая ячейка может использовать разные цвета) и установить его для рабочего листа за один вызов?

PS Ответ должен быть предпочтительно на C++, но может быть и на Delphi.

0 ответов

Другие вопросы по тегам