简体   繁体   English

在Delphi中从SQLite导出到Excel

[英]Exporting from SQLite to Excel in Delphi

I'm exporting data from SqlLite using TSQLConnection with the following procedure: 我使用TSQLConnection通过以下过程从SqlLite导出数据:

  Campos := TStringList.Create;
  SQLiteConnection.Execute('SELECT * FROM tabela', nil, results);
  if not results.IsEmpty then
  begin
    results.GetFieldNames(Campos);

    XLApp1 := createoleobject('excel.application');
    XLApp1.Workbooks.Add(xlWBatWorkSheet);
    Sheet := XLApp1.Workbooks[1].WorkSheets[1];
    linha := 1;
    begin
       pBar.Max := results.RecordCount;
       for coluna := 0 to results.FieldCount - 1 do
           Sheet.Cells[1, coluna + 1]  :=  Campos[coluna];

       while ( not results.Eof ) do
       begin
          linha := linha + 1;
          for coluna := 0 to results.FieldCount - 1 do
              Sheet.Cells[linha, coluna + 1]  :=  results.FieldByName(campos[coluna]).AsString;
          results.next;
          pBar.Position := pBar.Position + 1;
          Application.ProcessMessages;
       end;
   end;

);

It works ok. 它工作正常。 But it takes too much time to finish. 但这需要太多时间才能完成。 35 minutes to export a table with 40,000 records and 45 fields on i7 note with SSD. 使用SSD导出带有40,000条记录和45个字段的i7笔记表的35分钟。

So my question: is there a chance I could do a little faster? 所以我的问题是:我有可能做得更快一点吗?

The easiest way to do it is to collect all of the data into a single variant array, and then pass that over to Excel in a single pass. 最简单的方法是将所有数据收集到一个变量数组中,然后一次性传递给Excel。 The vast portion of the time is in writing to Excel, and reducing it to one write operation is much faster. 很大一部分时间是写入Excel,将其减少到一次写入操作要快得多。

The code below is adapted from code to transfer data from a TStringGrid to an Excel worksheet. 下面的代码改编自代码,以将数据从TStringGrid传输到Excel工作表。 Results is from your original code, so consider that it's been set up exactly as you've done it above where indicated. Results来自您的原始代码,因此请考虑它的设置与您在上面所指示的完全相同。 (The below code is untested as modified, because clearly I don't have your data to test against. It works with the stringgrid, as I've mentioned - I just couldn't test the adaptations. If you run into issues, leave a comment and I'll try to address them.) (以下代码未经测试修改,因为很明显我没有你的数据要测试。它与stringgrid一起工作,正如我所提到的 - 我无法测试适应性。如果你遇到问题,请离开评论,我会尝试解决它们。)

With 40K rows of 35 fields, you may need to break it up into blocks (even doing a few hundred rows at a time would be a major performance improvement over doing it one at a time). 使用40个行的35个字段,您可能需要将其分解为块(即使一次执行几百行也是一次性执行一次的主要性能改进)。

var
  xls, wb, Range: OLEVariant;
  arrData: Variant;
  RowCount, ColCount, i, j: Integer;
begin
  // Set up your dataset as Result here, just as in your own code
  // ....

  //create variant array where we'll copy our data
  RowCount := Results.RecordCount;
  ColCount := StringGrid1.FieldCount;
  arrData := VarArrayCreate([1, RowCount, 1, ColCount], varVariant);

  //fill array
  j := 1;
  while not Results.Eof do
  begin
    for i := 1 to ColCount do
      arrData[i, j] := Results.Fields[i].AsString;
    Inc(j);
    Results.Next;
  end;

  //initialize an instance of Excel
  xls := CreateOLEObject('Excel.Application');

  //create workbook
  wb := xls.Workbooks.Add;

  //retrieve a range where data must be placed
  Range := wb.WorkSheets[1].Range[wb.WorkSheets[1].Cells[1, 1],
                                  wb.WorkSheets[1].Cells[RowCount, ColCount]];

  //copy data from allocated variant array
  Range.Value := arrData;

  //show Excel with our data
  xls.Visible := True;
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM