【问题标题】:Fast way to retrieve data from Tstringgrid and to populate the retrieved data in chart containing in word从 Tstringgrid 检索数据并在包含 word 的图表中填充检索到的数据的快速方法
【发布时间】:2016-09-20 21:14:46
【问题描述】:

我已将包含 TStringgrid 表的记录存储在数据库中的表中的长 blob 字段中。我正在使用下面的代码检索存储在数据库中的表中的长 blob。但是,它非常缓慢。有人可以建议使用delphi将存储为数据库中的longblob的tstringgrid数据打印到word中的图表的快速方法。

Field := mySQLQuery1.FieldByName('Table');  //Accessing the table field in DB
blob := mySQLQuery1.CreateBlobStream(Field, bmRead); 
F := TStringList.Create;
try
  F.LoadFromStream(blob); //To load blob into string list
  try
    rowCount:= StrToInt(F[0])-1; //To get the total count of rows in string grid
    colCount:= StrToInt(F[1]); //To get the total count of columns in string grid

    aShape := WordApplication1.ActiveDocument.InlineShapes.Item(1); //To access the excel embedded chart in word
    ashape.OLEFormat.Activate;
    control2 := aShape.OLEFormat.Object_ as ExcelWorkBook;
    AWorkSheet := control2.sheets['Table1'] as ExcelWorkSheet; //To access the sheet in word
  except
    on E: Exception do
      MessageDlg(E.Message, mtInformation, [mbOk], 0);
  end; { try }

  i:= 2;           
  while i <= rowCount do
  begin
    str:=F[i + 2];  
    //The values of each row stored in Tstringgrid for example are of the followingorder 
    //',,,,,,"0,00011","13,6714","0,00023","13,5994"'

    for j := 1 to colCount do
    begin
      a:=pos('"',str);
      b:=pos(',',str);
      if (b<a) OR (a=0) then //To get and remove all null values by using searching for , delimiter
      begin
        if b=0 then substring:=str
        else
        begin
          substring:=copy(str,0,pos(',',str)-1);
          str:=copy(str,pos(',',str)+1,length(str));
        end; {if}
      end {if}
      else
      begin   //To get all values by using searching for " delimiter
        str:=copy(str,pos('"',str)+1, length(str));
        substring:=copy(str,0,pos('"',str)-1);
        str:=copy(str,pos('"',str)+2,length(str));
      end; {else}
      if substring<> '' then
      begin
        AWorkSheet.Cells.Item[i, (j-6)].value := StrToFloat(substring);
      end;
    end; {for j}
    i := i + 1;
  end;{ while i}
finally
  F.Free;
  freeandnil(blob);
end; {try}

【问题讨论】:

  • 做一些分析。找出哪个部分慢。
  • 我存储了超过 10000 条记录。当我使用较少的记录时速度很快
  • 猜测,瓶颈可能是对AWorkSheet.Cells.Item[i, (j-6)].value := StrToFloat(substring); 的调用,但您确实需要分析以找出哪个部分慢。您可以在上面的代码中重写或重新设计六项内容,以提高不同地方的性能,但除非您修复缓慢的部分,否则您只是在黑暗中盲目地刺,可能不会成功。
  • @J... 你是绝对正确的。我刚刚注释掉了您提到的行,代码运行得非常快。那么您能否建议我一种更好的方法来快速填写工作表中的项目以生成图表?
  • @DavidHeffernan 在他的回答中发布了一个很好的起点 - 通常使用 Excel,您希望将数组数据传输到此类操作的范围。有很多关于如何做到这一点的例子。

标签: delphi delphi-2007


【解决方案1】:

根据 cmets,瓶颈是分配给

AWorkSheet.Cells.Item[i, (j-6)].value

在一个循环中。这是自动化 Excel 时常犯的错误。每次调用自动化 Excel 都会产生大量成本,因为您正在对不同的进程执行 COM 调用。这样做有很大的开销。

不是使用 N 个不同的调用来设置数据,每个单元格一个调用,而是使用一个分配给所有 N 个单元格的调用来设置数据。通过选择一个代表工作表整个目标区域的范围来实现这一点,并在一次调用中分配一个包含所有 N 项的变量数组。

可以在这里找到一些类似的示例代码:c++ Excel OLE automation. Setting the values of an entire cell-range 'at once'

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
相关资源
最近更新 更多