这是我设置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 接口的每个函数调用都有一些开销(cca 1 - 3 ms)。要生成由 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。