0

这是我设置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。

4

0 回答 0