Автоматизация 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.