Einzelnen Beitrag anzeigen

hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#1

Excel-Daten lesen sehr langsam

  Alt 17. Okt 2008, 07:57
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

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
Heiko
  Mit Zitat antworten Zitat