Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Stringgrid "schnell" beladen (https://www.delphipraxis.net/136354-stringgrid-schnell-beladen.html)

QuickAndDirty 29. Jun 2009 08:01


Stringgrid "schnell" beladen
 
Hallo liebe Mitdelphianer, *g*

heute geht es mir darum eine TStringgrid Instanz möglichst Effizient zu beladen...

JA ich weiß das ein TStringgrid für größere Datenmengen nicht wirklich gut
geeignet ist. Und Ich weiß das es Ideal wäre nur wenig mehr als den
angezeigten Bereich an Daten zu laden. Das ist jetzt nicht das Thema.

Wie also bekomme ich möglichst schnell ein Gitter mit 3 * ca. 16000
Zellen gefüllt?

Die 3 Datenfelder werden aus einer Datenbank gelesen und es können unterschiedlich
viele Zeilen/Datensätze sein.

-Ich dachte erst ich könnte mir zeitsparen wenn ich z.B. Das Gitter nicht immer
Zeile für Zeile vergrößere sondern einmal die nötige Größer ermittele und setzte...
leider dauert Dataset.recordcount auch lange und wird nicht überall unterstützt :(
-> Also könnte es Sinn machen einfach in großen Schritten den Rowcount zu erhöhen ? Kostet das überhaupt Zeit?

-Z.z. Wird Schreibend auf CELLS[c,r] zugegriffen. Ich habe es auch schon mal mit ROWS[r].commatext versucht, scheint
keinen Gewinn zu bringen(vielleicht weil das zusammen bauen und auseinander bauen der Feld Inhalte die Zeit wieder auffrisst).

-Rows[r].append würde ja nur sinn machen wenn das gitter dynamisch erweitert wird. Und ich weiß nicht ob es schneller ist.


habt ihr ne Idee?

mirage228 29. Jun 2009 08:09

Re: Stringgrid "schnell" beladen
 
Hat das StringGrid eventuell einen virtuellen Modus? Der arbeitet meistens schneller als ein normales Befüllen... Sonst könnte ich natürlich noch das VirtualTreeView empfehlen, mit dem sich auch ganz einfach ein Stringgrid "bauen" lässt...

Viele Grüße

QuickAndDirty 29. Jun 2009 08:27

Re: Stringgrid "schnell" beladen
 
Virtueller Modus ? Hört sich vielversprechend an, aber ich glaube das hat es nicht.

so befülle ich es aktuell:
Delphi-Quellcode:
    oldvisible := visible;
    visible := false;
    j := 1; // Zeile Zahler initialisieren
    RowCount := 2; // Zeilen Anzahl ist 2 ,weniger geht nicht
    Protokoll := Protokoll + 'RowCount := ...init'#13#10;
    DataSet.first;
    While not DataSet.EOF do //bis das ende der datenmenge erreicht ist...
    begin
      try
        For i := 0 to FNames.Count - 1 do // für alle Spalten...
          try
            Cells[Anfang + i, j] := DataSet.Fields[i].asString; //..werte eintragen, Anfang = erste spalte( ?0 / 1?)
          except
            on E:Exception do
              raise EXception.create(e.Message + #13#10
              + 'ThisRow: CELL=' + inttostr(Anfang+i) + ',' + inttostr(j) + #13#10
              + 'Anfang bei=' + inttostr(Anfang) + #13#10
              + 'Recordcount=' + inttostr(Dataset.RecordCount) + #13#10
              + 'Zeilenanzahl=' + inttostr(Rowcount));
          end;
        DataSet.Next;


        if not DataSet.eof then// Wenn noch mehr daten vorhanden..
        begin //..dann schaffe platz
          Inc(j); //erhöhe Zeilen zähler (spalte 0 enthält die Überschriften)
          RowCount := succ(j); // dann Zeilen anzahl mit erhöhen;
        end;


      except
        on E:Exception do
          raise EXception.create(e.Message + 'DS-Loop position='+inttostr(j)+'Zeilenanzahl= '+inttostr(Rowcount));
      end;
    end;
    Visible := oldvisible;  
  except
    on e:Exception do
      raise exception.Create(Self.Name + '.LoadFromDataSet' + #13#10 + Protokoll + #13#10 + e.Message);
  end;
Nachteil ist, dass ein Dialog auf dem das drauf liegt tooootal lange lädt wenn extrem viele Datensätze in das Gitter kommen.
Ich habe mir schon überlegt ob ich das befüllen des Gitters in einem Hintergrund Thread ausführe...aber leider geht das mit Datenbanken multithreaded ja nicht sooo toll...
...ab einer gewissen Anzahl macht so ein Ladebalken schon fast wieder Sinn....

jfheins 29. Jun 2009 08:36

Re: Stringgrid "schnell" beladen
 
Schonmal .BeginUpdate + .EndUpdate ausprobiert?

also vor dem ganzen Zeug .beginupdate aufrufen und danach .endupdate ;)

QuickAndDirty 29. Jun 2009 08:58

Re: Stringgrid "schnell" beladen
 
Ich probiers mal aus

QuickAndDirty 29. Jun 2009 09:02

Re: Stringgrid "schnell" beladen
 
Diese Funktionalität (BeginUpdate, EndUpdate) bietet das Stringgrid nicht.
Aber da ich eh einen Nachfahren habe könnte ich mal sehen ob es möglich ist das dahinterliegende Persistenz Object
vom Typ TStringgridStrings direkt anzusprechen...

DeddyH 29. Jun 2009 09:19

Re: Stringgrid "schnell" beladen
 
Zitat:

Zitat von QuickAndDirty
Diese Funktionalität (BeginUpdate, EndUpdate) bietet das Stringgrid nicht.

Das StringGrid als solches nicht, aber Cols und Rows. Inwiefern Dir das etwas nützt, sei dahingestellt.

Satty67 29. Jun 2009 09:20

Re: Stringgrid "schnell" beladen
 
StringGrid.RowCount für jede einzelne Zeile erhöhen ist sehr langsam. Sieht so aus, als ob Du die Datenmenge nicht weiter filterst, also könntest Du RowCount gleich am Anfang auf den maximalen Wert setzen.

Dann wenn DataSet wärend der Anzeige des Grid die Datenmenge behält, könntest Du selber das Grid nur mit den sichtbaren Zellen "zeichnen". StringGrid.RowCount := 2.000.000 dauert nur ein paar ms und wenn du das Grid nicht wirklich füllst, gibt es keine weitere Verzögerung.

Lannes 29. Jun 2009 09:31

Re: Stringgrid "schnell" beladen
 
Hallo,

man kann RowCount auch erst nach dem Füllen der Zellen auf den endgültigen Wert setzen.

Abgesehen davon ist der Ansatz von Satty67 das schnellste, keine Daten ins Grid setzen, nur die Werte über onDrawCell ausgeben lassen.

hoika 29. Jun 2009 10:07

Re: Stringgrid "schnell" beladen
 
Hallo,

Zitat:

leider dauert Dataset.recordcount auch lange und wird nicht überall unterstützt
Das stimmt schon
select count(*) kennt aber jede (anständige) Datenbank.

Von welcher DB reden wir denn ?

Ich mache das immer so,
alle benötigten Datensätze in eine TList (oder ähnliches) laden
Grid.RowCount:= List.Count+1 (dada ;) ).

Ausserdem weder der alte Spruch:
Wozu 16.000 Records anzeigen ?


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:13 Uhr.
Seite 1 von 2  1 2      

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