Excel自动化 - 设置单元格字体

时间:2015-06-08 12:51:12

标签: excel vba delphi excel-vba c++builder-xe4

这是我设置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行×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;

现在我正在尝试对细胞字体使用相同的机制。是否可以准备字体颜色数组(每个单元格可以使用不同的颜色)并在一次调用中将其设置为工作表?

P.S。答案应该最好用C ++,但也可以用Delphi。

0 个答案:

没有答案