Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Tabelle aus PG Datenbank in StringGrid füllen? (https://www.delphipraxis.net/194830-tabelle-aus-pg-datenbank-stringgrid-fuellen.html)

W4lt3r 11. Jan 2018 12:54

Tabelle aus PG Datenbank in StringGrid füllen?
 
Hallo an alle,

ich habe gerade eine große Wissenslücke. Wie es schon im Titel steht muss ich einen StringGrid befühlen mit Inhalten aus einer Datenbank. Ich hab mich jetzt zu StringGrid belesen. Aber nichts gefunden was mir wirklich helfen würde. Meine erster Ansatz wäre eine Schleife die die Inhalte befüllt und das StringGrid automatisch erweitert. Allerdings bin ich mir nicht mal im klaren, ob das über Haupt ein guter Ansatz, geschweige den der richtige ist.

Wenn ihr eine Idee zu dem Thema hättet oder wenigstens ein Hinweis in welche Richtung ich suchen muss, würde das mir schon sehr viel bringen.

Schon mal Danke für alle Beiträge.

W4lt3r

DeddyH 11. Jan 2018 12:59

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Muss es denn unbedingt ein StringGrid sein? Wenn man keine datensensitiven Controls (z.B. DBGrid) verwenden darf/soll/möchte, würde ich eher in Richtung ListView mit ViewStyle vsReport tendieren. Mit der Schleife hast Du schon recht, und für das dynamische Einfügen von Zeilen finde ich ganz persönlich die ListView etwas eleganter.

W4lt3r 11. Jan 2018 13:05

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Ich will kein DBGrid verwenden weil es um Tabellen geht die über 5 mio. Datensätze enthalten und dabei reicht der Arbeitsspeicher nicht. Und nun ja mir wurde gesagt das ich StringGrid benutzen soll.

himitsu 11. Jan 2018 13:06

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Zitat:

Muss es denn unbedingt ein StringGrid sein? Wenn man keine datensensitiven Controls (z.B. DBGrid) verwenden darf/soll/möchte
Aber wenn es nicht "verboten" ist, dann wäre natülich eine Datensensitive Komponente bestimmt besser einfacher.

[edit]
Beim TStringGrid muß auch alles in den Speicher.
Zwar nicht "dauernd" doppelt (außer eventuell beim Befüllen), also Daten im DataSet und als Kopie im DataController des Grids

Wenn der Speicher das Problem ist, dann würde ich eher in Richtung VirtuelStringTree (nur 1. Ebene, also als Grid) tendieren.



Oder einen passenden Filter+Limit auf die Daten und weniger anzeigen. (siehe nachfolgend DeddyH)

Oder die Anwendung als 64 Bit. :stupid:

DeddyH 11. Jan 2018 13:07

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Das hat aber doch weniger mit der Darstellungskomponente zu tun als damit, wie man das zugrundeliegende Dataset konfiguriert. Welcher Mensch will denn auf einen Schlag 5.000.000 Datensätze angezeigt bekommen?

Delphi.Narium 11. Jan 2018 13:40

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Die Menge der Daten ist bei 'nem StringGrid sicherlich ausschlaggebend für den Speicherverbrauch.

Bei 'nem DBGrid wird nur das geladen, was auch angezeigt wird, es sei denn, dass man die Datenbankkomponenten (DataSet und Nachfolger) drum "bittet", alle Datensätze in den Arbeitstspeicher zu laden. Oder z. B. den Datencursor auf den Client legt, der muss dann zwangsweise alle Daten vorhalten, auch ohne Anzeige.

Aber wenn's denn ein StringGrid sein muss:
Delphi-Quellcode:
StringGrid.Cols := DataSet.Fields.Count;
StringGrid.Rows := DataSet.RecordCount;
DataSet.First;
while not DataSet.EoF do begin
  for i := 0 to StringGrid.Cols - 1 do StringGrid.Cells[i, DataSet.RecNo] := DataSet.Fields[i].AsString;
  DataSet.Next;
end;
Die Sinnhaftigkeit dieses Vorgehens bei genannter Datenmenge, zweifle ich allerdings an.

Ein DBGrid zeigt übrigens "nur" die bereits im DataSet befindlichen Daten an, bei einem StringGrid muss man von den Daten noch 'ne Kopie anlegen (Cells[x,y] := Feldinhalt).
Was mag letztlich dann mehr Speicher verbrauchen? Nur die Daten, die sowieso schon den Speicher sprengen oder diese Daten plus die Kopie im Stringgrid?

Und beim Stringgrid muss man die Formatierungen (rechts- / linksbündig, je nachdem ob Text oder Zahlen, Nachkommastellen ...) gefälligst selber machen.

Um sowas zu machen, müsste ich schon sehr verzweifelt sein.
Oder eine objektorientierte Applikation schreiben, bei der Anzeige und Datenhaltung streng getrennt sind. Aber das dann sicherlich nicht mit der gleichzeitigen Anzeige von 5.000.000 und mehr Objekten.

jobo 11. Jan 2018 13:47

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Ich schätze/hoffe mal, dass die 5 mio hier nur ein Missverständnis in der Nutzung der Komponenten ist. Also auch die Stringgridvariante nur ein "Workaroung" ist, um einen Teil der Daten anzuzeigen.
Geht es dann letztlich um die Anzeige eines Teils der Datenmenge, so können sehr wohl datensensitive Komponenten genutzt werden. Die bekommen dann eben nur eine definierte Menge an Daten geliefert.
Das wäre vielleicht das Gewollte, wenn man davon ausgeht, dass die standard Verwendungsmöglichkeiten dieser Komponenten (noch) nicht bekannt sind.

W4lt3r 12. Jan 2018 13:33

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Danke für alle die mir geholfen haben ich stelle einfach meine Komplette Lösung zum beurteilen zu verfügung.
Delphi-Quellcode:
nit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error,
  FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
  FireDAC.Phys.PG, FireDAC.Phys.PGDef, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
  FireDAC.DApt, FireDAC.Comp.DataSet, FireDAC.Comp.Client, Vcl.ExtCtrls, Vcl.DBCtrls, Vcl.Grids, Vcl.DBGrids,
  FireDAC.Comp.UI, Vcl.StdCtrls, Vcl.Mask;

type
  TForm1 = class(TForm)
    DataSource1: TDataSource;
    FDQuery1: TFDQuery;
    FDPhysPgDriverLink1: TFDPhysPgDriverLink;
    FDConnection1: TFDConnection;
    Button1: TButton;
    Memo1: TMemo;
    StringGrid1: TStringGrid;
    Label1: TLabel;
    RadioGroup1: TRadioGroup;
    procedure Button1Click(Sender: TObject);
  private
    function GetWidthText(const Text:String; Font:TFont) : Integer;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i,Zähler,OldW,NewW: Integer;

begin
 OldW:= 64;
 for i := 0 to StringGrid1.RowCount do
  StringGrid1.Rows[i].Clear;
 StringGrid1.RowCount:= 0;
 StringGrid1.ColCount:= 0;
 Zähler:= 1;
 if FDQuery1.Active then FDQuery1.Close;
 FDQuery1.SQL.Text:= Memo1.Text;
 FDQuery1.Open;
 StringGrid1.ColCount:= FDQuery1.Fields.Count;
 for i := 0 to FDQuery1.Fields.Count - 1  do begin
  StringGrid1.Cells[i, 0]:= FDQuery1.Fields[i].FieldName;                                             {List[i];}
 end;
 while not FDQuery1.Eof do begin
  StringGrid1.RowCount:= StringGrid1.RowCount +1;
  for i := 0 to FDQuery1.Fields.Count - 1 do begin
   StringGrid1.Cells[i, Zähler] := FDQuery1.Fields[i].AsString;
  end;
  Inc(Zähler);
  FDQuery1.Next;
 end;
 Zähler:= 0;
 i:= 0;
 while i <= StringGrid1.ColCount do begin
  while Zähler <= StringGrid1.RowCount do begin
   NewW:=GetWidthText(StringGrid1.Cells[i, Zähler], StringGrid1.Font);
   if NewW > OldW then begin
    OldW:= NewW;
   end;
   Inc(Zähler);
  end;
  Zähler:= 0;
  if OldW > 64 then Stringgrid1.ColWidths[i] := OldW+10;
  OldW:= 64;
  Inc(i)
 end;
 StringGrid1.Refresh;
end;

function TForm1.GetWidthText(const Text:String; Font:TFont) : Integer;
var LBmp: TBitmap;
begin
 LBmp := TBitmap.Create;
 try
  LBmp.Canvas.Font := Font;
  Result := LBmp.Canvas.TextWidth(Text);
 finally
  LBmp.Free;
 end;
end;

end.
Ich setze ein Limit im Memo mit einem SQL Statement. Ihr hattet recht mit der sinn haftigkeit, habe die Person falsch verstanden. Es sollte am Ende nur eine Herausforderung sein.

Tut mir Leid :?

Aviator 12. Jan 2018 13:56

AW: Tabelle aus PG Datenbank in StringGrid füllen?
 
Das Laden von 5.000.000 Datensätzen wurde ja schon angesprochen und du hast es ja auch entsprechend umgesetzt.

Trotzdem will ich hier einmal die VirtualTreeView Komponente in den Raum werfen, die für solch große Datenmengen ebenfalls gemacht ist.

Die Einarbeitung in die Komponenten mag zwar etwas schwierig sein, aber dafür profitiert man später von den Vorzügen umso mehr.

Einfach mal ausprobieren. Bei Fragen einfach hier (also in einem neuen Thread) posten. :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:48 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