Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Export eines Suchergebnisses nach Excel zu langsam (https://www.delphipraxis.net/80857-export-eines-suchergebnisses-nach-excel-zu-langsam.html)

GoTo0815 16. Nov 2006 13:05

Datenbank: Paradox • Version: 7 • Zugriff über: Query

Export eines Suchergebnisses nach Excel zu langsam
 
Hallo @ all,


ich habe auf meinem Formular eine Query, ein DBGrid, ein StringGrid & ein Button.

Nun lasse ich mir über das DBGrid das Suchergebnis der Query anzeigen.

Beispiel SQL: Select * from retouren WHERE ....

Die Datenbank liegt im Netzwerk auf einem Server.

Das Suchergebnis der Quersy erscheint sehr schnell, daher gehe ich davon aus, dass bis dahin alles in Ordnung ist.

Nun soll per Knopfdruck ein Export der Daten nach Excel stattfinden. Das funktioniert auch. Aber der Kopiervorgang ist sowas von langsam, dass ich nicht nur ne Kanne Kaffe kochen, sondern auch noch austrinken kann.
Kann man das DBGrid nicht mit einem Schlag in ein StrinGrid kopieren? Muss man da immer über die einzelnen Datensätze der Query gehen? Das DBGrid muss doch auch so ein Art Array bzw. StringList haben, oder?


Delphi-Quellcode:
procedure TForm1.BitBtn7Click(Sender: TObject);
var RowC, ColC,rowCount,k,i :integer;
    Str: string;
    StrList: TStringList;
begin
    rowCount := 1; StringGrid2.ColCount := 11;
    StringGrid2.RowCount := rowcount;
    //Übernehmen der Daten aus der DBGrid in ein StringGrid
    StringGrid2.Cells[0,0]:= 'Auftragsnr.';
    StringGrid2.Cells[1,0]:= 'Artikelnr.';
    StringGrid2.Cells[2,0]:= 'Artikel';
    StringGrid2.Cells[3,0]:= 'Seriennummer';
    StringGrid2.Cells[4,0]:= 'Kunde';
    StringGrid2.Cells[5,0]:= 'RMA-Nr.';
    StringGrid2.Cells[6,0]:= 'Fehler';
    StringGrid2.Cells[7,0]:= 'Getauscht';
    StringGrid2.Cells[8,0]:= 'Status';
    StringGrid2.Cells[9,0]:= 'Datum';
    StringGrid2.Cells[10,0]:= 'Lieferdatum';


    Query_Suchen.First;
    for i:= 1 to Query_Suchen.RecordCount do
    begin
      for k := 0 to DBGrid11.Columns.Count - 1 do
      begin
        StringGrid2.Cells[k, rowCount] := DBGrid11.Fields[k].AsString;
      end;
      Query_Suchen.Next;
      rowCount := rowCount + 1;
      StringGrid2.RowCount := rowCount;
    end;

  //zunächst wird hier eine csv-Datei erstellt:

  StrList := TStringList.Create();
  for RowC := 0 to StringGrid2.RowCount - 1 do
  begin
    Str := '';
    for ColC := 0 to StringGrid2.ColCount - 1 do
      Str := Str + StringGrid2.Cells[ColC, RowC] + ';';
    Delete(Str, length(Str), 1); // löscht den überfluessigen String
    StrList.Add(Str);
  end;

  StrList.SaveToFile('tmpExcel.csv');

  //dann wird die Datei mit Excel geöffnet:
  ShellExecute(Application.Handle, 'OPEN', pchar(ExtractFilePath
     (Application.ExeName) + 'tmpExcel.csv'), NIL, NIL, SW_NORMAL);

  // und schließlich die csv-Datei wieder gelöscht
  DeleteFile(ExtractFilePath(Application.ExeName) + 'tmpExcel.csv');



end;

Pumba 16. Nov 2006 14:31

Re: Export eines Suchergebnisses nach Excel zu langsam
 
Hallo schau dir mal auf Max's component page (Freeware)
TmxNativeExcel und TmxExports an

www.maxcomponents.net/download.html

Ich benutze sie regelmäßig und bin damit recht zufrieden :dancer:

Andidreas 16. Nov 2006 15:01

Re: Export eines Suchergebnisses nach Excel zu langsam
 
nur mal um auf deine frage einzugehen ob das normal ist,

ich würde sagen ja...

ich hab für meinen kollegen ein tool geschrieben das eine txt datei als xls ausgibt...

die größe der txt datei liegt bei 3 MB ca. 75.000 datensätze...
dauer des exports zu excel liegt bei ca. 10 min.

wenn mans über ole objects macht

GoTo0815 16. Nov 2006 15:48

Re: Export eines Suchergebnisses nach Excel zu langsam
 
Hallo,

@Pumpa / sehr ungern installiere ich Dinge über die ich nichts weiß oder nutze ich Komponenten von anderen aufgrund von Copyrights.

Mein Tool schreibe ich für den Einsatz in meiner Firma, somit möchte ich ungern die Rechte Dritter verletzen.

Ich danke Dir dennoch, wäre aber an einer Klärung hier im Forum eher interessiert.

Es muss doch irgendwie funktionieren, die Daten, welche im DBGrid angezeigt werden lokal auszulesen ohne erneut auf die Datenbank zuzugreifen. Die DBGrid speichert die Daten doch bestimmt auch irgendwo zwischen, oder?

hoika 16. Nov 2006 15:56

Re: Export eines Suchergebnisses nach Excel zu langsam
 
Hallo,

for i:= 1 to Query_Suchen.RecordCount do

das ist nicht notwendig.

Delphi-Quellcode:
while not Query_Suchen.EOF do
begin
  Query_Suchen.Next;
end;
Schnapp dir das mal,
um zu prüfen, ob es wirklich das Netz ist.

http://delphi.about.com/od/fullcodep.../aa112903a.htm

Ausserdem wird bei deinem Durchlaufen der Query
auch das DBGrid ständig aktualisert.
Mit DataSource.Enabled (EnableControls?) oder so ähnlich kannst du das ausschalten.


Heiko

alzaimar 16. Nov 2006 20:48

Re: Export eines Suchergebnisses nach Excel zu langsam
 
hoika, das dürfte des Pudels Kern sein.
Delphi-Quellcode:
MyDataset.DisableControls;
Try
  MyDataSet.First;
  While not MyDataSet.Eof do begin
    ExportRecord (MyDataset);
    MyDataSet.Next;
  End;
Finally
  MyDataSet.EnableControls;
End;
Hendrik, Du verletzt keinerlei Copyrights, wenn Du Freeware installierst. Ein Blick in den Sourcecode hilft und schafft Klarheit. Ungeachtet dessen ist es aber sicherlich eine gesunde Einstellung, keine Freeware innerhalb von kommerziellen Anwendungen zu verwenden. Die von Pumpa vorgeschlagenen Komponenten sind aber ausnahmsweise zu empfehlen.

Wenn ein Export in Excel zum Tagesgeschäft gehört, solltest Du überlegen, kommerzielle Komponenten zu verwenden. Ich verwende XLSReadWriteII sowie die Grid-Komponenten von Developer Express, die auch einen Export in natives XLS-Format ohne OLE unterstützen, inklusive aller Formatanweisungen, Farben etc.

Weiterhin gibt es eine freie BIFF-Library, irgendwo hier im Forum.

raiguen 16. Nov 2006 22:35

Re: Export eines Suchergebnisses nach Excel zu langsam
 
Moin :-)
ich werfe mal ne Procedure aus einem meiner Kundenprojekte rein; die Proc habe ich von den Schweizern etwas umgebaut:
Delphi-Quellcode:
{Original-Code von [url]http://www.swissdelphicenter.ch/de/showcode.php?id=725[/url] }
{siehe auch [url]http://www.swissdelphicenter.ch/de/showcode.php?id=379[/url] }
procedure TFrmBewertZiff.p_InExcel(const TabellenName: String);
const
  CXlsBof: array[0..5] of Word = ($809, 8, 00, $10, 0, 0);
  CXlsEof: array[0..1] of Word = ($0A, 00);
  CXlsLabel: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
  CXlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0);
  CXlsRk: array[0..4] of Word = ($27E, 10, 0, 0, 0);

  //---inbound Procs ----------------//
  procedure XlsBeginStream(XlsStream: TStream; const BuildNumber: Word);
  begin
    CXlsBof[4] := BuildNumber;
    XlsStream.WriteBuffer(CXlsBof, SizeOf(CXlsBof));
  end;

  procedure XlsEndStream(XlsStream: TStream);
  begin
    XlsStream.WriteBuffer(CXlsEof, SizeOf(CXlsEof));
  end;

  procedure XlsWriteCellRk(XlsStream: TStream; const ACol, ARow: Word;
    const AValue: Integer);
  var
    V: Integer;
  begin
    CXlsRk[2] := ARow;
    CXlsRk[3] := ACol;
    XlsStream.WriteBuffer(CXlsRk, SizeOf(CXlsRk));
    V := (AValue shl 2) or 2;
    XlsStream.WriteBuffer(V, 4);
  end;

  procedure XlsWriteCellNumber(XlsStream: TStream; const ACol, ARow: Word;
    const AValue: Double);
  begin
    CXlsNumber[2] := ARow;
    CXlsNumber[3] := ACol;
    XlsStream.WriteBuffer(CXlsNumber, SizeOf(CXlsNumber));
    XlsStream.WriteBuffer(AValue, 8);
  end;

  procedure XlsWriteCellLabel(XlsStream: TStream; const ACol, ARow: Word;
    const AValue: string);
  var
    L: Word;
  begin
    L := Length(AValue);
    CXlsLabel[1] := 8 + L;
    CXlsLabel[2] := ARow;
    CXlsLabel[3] := ACol;
    CXlsLabel[5] := L;
    XlsStream.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel));
    XlsStream.WriteBuffer(Pointer(AValue)^, L);
  end;

  //---ENDE inbound Procs----------------------//

var
  FStream: TFileStream;
  Spalte, Zeile: Integer;
begin
  //--Grid etc 'einfrieren'
  DBGrid2.DataSource.DataSet.DisableControls;

  FStream := TFileStream.Create(PChar(TabellenName), fmCreate);
  try
    XlsBeginStream(FStream, 0);
      Zeile := 0;
      //--Spaltenbezeichnung eintragen
      XlsWriteCellLabel(FStream, 0, Zeile, 'Leitung/Station-Nr');
      XlsWriteCellLabel(FStream, 1, Zeile, 'Bezeichnung');
      XlsWriteCellLabel(FStream, 2, Zeile, 'Bewertungsziffer');

      Zeile := 1;
      while not Query2.Eof do begin
        for Spalte := 0 to Query2.Fields.Count -1 do
          case Spalte of
            0,1 : XlsWriteCellLabel(FStream, Spalte, Zeile, Query2.Fields[Spalte].Text);
            2:   XlsWriteCellNumber(FStream, Spalte, Zeile, Query2.Fields[Spalte].Value);
        end;
        INC(Zeile);
        Query2.Next;
      end;
    XlsEndStream(FStream);
  finally
    FStream.Free;
  end;

  //--Grid 'freigeben'
  DBGrid2.DataSource.DataSet.EnableControls;

end;
Funktioniert so bei einem Kunden relativ passabel von der Geschwindigkeit her.
Denke mal, eine Anpassung an deine Gegebenheiten dürfte nicht allzuschwer sein...

GoTo0815 17. Nov 2006 08:52

Re: Export eines Suchergebnisses nach Excel zu langsam
 
Vielen, vielen Dank an alle.

Die Lösung lag 'NATÜRLICH' :-) in den Controls.

Nach Query_Suchen.DisableControls läuft alles wie ein geölter Blitz.

9000 Datensätze in 4 Sekunden.

Gruß

Hendrik


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:26 Uhr.

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