Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Excel-Daten lesen sehr langsam (https://www.delphipraxis.net/122504-excel-daten-lesen-sehr-langsam.html)

hoika 17. Okt 2008 06:57


Excel-Daten lesen sehr langsam
 
Hallo #,

mit folgendem Code werden etwa 10 Spalten und 500 Zeilen,
also 5000 Zellen gelesen.
Das dauert ~ 10 sec.
zu viel denke ich.



Delphi-Quellcode:
procedure TForm.DoLoad;
var
  sValue           : String;
  filename         : String;
  ExcelApplication0 : TExcelApplication;
  ExcelWorkbook0    : TExcelWorkbook;
  ExcelWorksheet0   : TExcelWorksheet;
  iCurRow_Excel    : Integer;
  iCurRow_Grid     : Integer;
  iMaxRow_Excel    : Integer;
  iCol             : Integer;
  sCol             : String;
  sColRange        : String;
begin
  Button_Load.Enabled:= False;
  try
    OpenDialog1.InitialDir:= ExtractFilePath(ParamStr(0));
    if not OpenDialog1.Execute then Exit;

    Label_SourceFile.Caption:= OpenDialog1.FileName;

    Panel_Buttons.Visible:= False;
    ProgressBar.Max    := ColList_Source.Count;
    ProgressBar.Visible := True;
    Panel_Buttons.Visible:= True;
    Application.ProcessMessages;

    flcid:=GetUserDefaultLCID;

    ExcelApplication0 := TExcelApplication.Create(NIL);
    ExcelWorkbook0    := TExcelWorkbook.Create(NIL);
    ExcelWorksheet0   := TExcelWorksheet.Create(NIL);
    try
      ExcelApplication0.Connect;
      ExcelApplication0.Visible[flcid]:=False;
      ExcelApplication0.UserControl:=true;

      filename:= OpenDialog1.FileName;
      ExcelWorkbook0.ConnectTo(ExcelApplication0.Workbooks.Open(filename,
           emptyParam, emptyParam, emptyParam, emptyParam, emptyParam,
           emptyParam, emptyParam, emptyParam, emptyParam, emptyParam,
           emptyParam, emptyParam, flcid));
      ExcelWorksheet0.ConnectTo(ExcelWorkbook0.Sheets.Item[1] as ExcelWorkSheet);

      iCurRow_Excel:= iStartRow_Source;
      sValue:= ExcelWorksheet0.Range['A'+IntToStr(iCurRow_Excel),'A'+IntToStr(iCurRow_Excel)].Value;
      while sValue<>'' do
      begin
        Inc(iCurRow_Excel);

        sValue:= ExcelWorksheet0.Range['A'+IntToStr(iCurRow_Excel),'A'+IntToStr(iCurRow_Excel)].Value;
      end;
      iMaxRow_Excel:= iCurRow_Excel-1;

      Grid.ColCount:= ColList_Source.Count+1;
      Grid.RowCount:= iMaxRow_Excel-iStartRow_Source+2;
      Grid.Visible:= True;
      if Grid.ColCount>1 then Grid.FixedCols:= 1;

      iCurRow_Grid:= 0;
      for iCurRow_Excel:= iStartRow_Source to iMaxRow_Excel do
      begin
        Inc(iCurRow_Grid);
        Grid.Cells[0,iCurRow_Grid]:= IntToStr(iCurRow_Excel);
      end;

      for iCol:= 0 to ColList_Source.Count-1 do
      begin
        ProgressBar.StepIt;

        sCol:= ColList_Source[iCol];
        Grid.Cells[iCol+1,0]:= sCol;

        iCurRow_Grid:= 0;
        for iCurRow_Excel:= iStartRow_Source to iMaxRow_Excel do
        begin
          sColRange:= sCol+IntToStr(iCurRow_Excel);
          sValue:= ExcelWorksheet0.Range[sColRange,sColRange].Value;

          Inc(iCurRow_Grid);
          Grid.Cells[iCol+1,iCurRow_Grid]:= sValue;
        end;
      end;
    finally
      ExcelWorksheet0.Disconnect;
      FreeAndNIL(ExcelWorksheet0);

      // Workbook ohne Speichern schliessen
      ExcelWorkbook0.Close(False);
      ExcelWorkbook0.Disconnect;
      FreeAndNil(ExcelWorkbook0);

      // Excel beenden
      ExcelApplication0.Quit;
      ExcelApplication0.Disconnect;
      FreeAndNil(ExcelApplication0);
    end;

    Grid.SetFocus;
  finally
    ProgressBar.Visible := False;
    Button_Load.Enabled := True;

    Button_Save.Enabled := True;
    Button_Load.Enabled := False;
  end;
end;

Die Spalten stehen nicht nebeneinander,
dafür ist ColList_Source (TStringList) zuständig.

Der langsame Befehl ist

Delphi-Quellcode:
sValue:= ExcelWorksheet0.Range[sColRange,sColRange].Value;
Da die Zeilenzahl verschieden ist,
ermittle ich sie zuerst,
dann gehe ich durch die anderen Spalten.

Wie man sieht, alde ich jede Zelle einzeln das ExcelWorksheet0.Range
könnte mir doch aber die komplette Spalte zurückgeben,
was hat Value aber dann für einen Typ (ValueList ?),
und wie greife ich darauf zu ?


Danke im voraus


Heiko

Chemiker 17. Okt 2008 20:31

Re: Excel-Daten lesen sehr langsam
 
Hallo hoika,

Du musst versuchen die Procedure dahin zu überarbeiten das nur einmal die Zelle in Excel gelesen wird, weil das die meiste Zeit verbraucht. Am besten einmal auslesen und dann den Wert in StringGrid reinsetzen (oder auch nicht). So wie es jetzt ist, liest Du den Wert 2-mal aus. Als weiteres ist der Range-Befehl beim Auslesen einzelner Zelle langsamer als der Cells- Befehl.

Zitat:

Wie man sieht, alde ich jede Zelle einzeln das ExcelWorksheet0.Range
könnte mir doch aber die komplette Spalte zurückgeben,
was hat Value aber dann für einen Typ (ValueList ?),
und wie greife ich darauf zu ?
Value ist OleVariant.
Du muss Dir dann einen Array aus Variant mit Create erstellen.

Delphi-Quellcode:
Var
   oArray: OleVariant;
begin
   oArray:= VarArrayCreate([Zeile,Spalte]),varVariant);

  oArray := Range [‘A1’,’A10’].Value;
ich habe das jetzt nicht getestet, aber so in etwa müsste das Aussehen.

Bis bald Chemiker

hoika 18. Okt 2008 09:47

Re: Excel-Daten lesen sehr langsam
 
Hallo,

danke,

ich probiere es aus.


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:36 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz