Dynamische Spalten in TDBGrid?

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Dynamische Spalten in TDBGrid?

Beitrag von MmVisual »

Hallo,

In einer TZQuery sind einige Spalten die eingeblendet werden sollen deklariert (rechtsklick auf dem TZQuery auf dem Formular und "Felder bearbeiten...").
Wenn ich die TZQuery öffne werden alle Spalten angezeigt die da in der Liste drin stehen und die Spalten die da nicht drin stehen werden nicht in TDBGrid gezeigt. Soweit ist das auch OK.

Nun ist es so dass der ein oder andere noch extra Spalten haben möchte, die in meinem Programm so nicht existieren, dazu legt er dann einfach in z.B. MySQL in der Tabelle noch zusätzliche neue Spalten an.
Mein Programm stört das soweit nicht, es werden einfach diese Spalten nicht in TDBGrid gezeigt.

Wie kann ich es hin bekommen dass diese Spalten dennoch in TDBGrid eingeblendet werden?
Ich habe ein Schleife durchlaufen und erkenne welche Spalten "Fremd" sind und versucht diese hinzu zu fügen. Doch leider zeigt mir das TDBGrid die immer noch nicht.

Code: Alles auswählen

fi := TIntegerField.Create(Self); // Erzeuge ein neues TField
fi.FieldName := slQ_bauteilExtra[i2]; // Feldname zuweisen
fi.DisplayLabel := slQ_bauteilExtra[i2]; // Bezeichner dem Feldname gleich setzen
qBauteil.Fields.Add(fi); // Felddeklaration erweitern
Das geht nicht:

Code: Alles auswählen

qBauteil.FieldDefs.Add(slQ_bauteilExtra[i2], q.FieldByName(slQ_bauteilExtra[i2]).DataType); 
Muss in TDBGrid noch extra was gemacht werden?

Vielen Dank für die Hilfe, Markus
EleLa - Elektronik Lagerverwaltung - www.elela.de

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Dynamische Spalten in TDBGrid?

Beitrag von MmVisual »

Hat jemand eine Idee dazu was ich noch testen könnte, oder woran es liegt?
Vielen Dank, Markus
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Dynamische Spalten in TDBGrid?

Beitrag von six1 »

Doppelklick auf das Grid und alle Spalten mit deren Feldnamen einzeln anlegen.
Gruß, Michael

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Dynamische Spalten in TDBGrid?

Beitrag von MmVisual »

Das geht ja nicht zur Laufzeit.

Mit Query.Field.Visible kann man das Feld für das TDBGrid Sichtbar/Unsichtbar machen, jedoch nur dann wenn es in der Query Deklaration definiert wurde. Jedoch zusätzliche Spalten die erst zur Laufzeit erkannt werden (weil derjenige eine erweiterte Datenbank hat) werden nicht in TDBGrid gezeigt, egal ob Visible auf True gesetzt wird.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Dynamische Spalten in TDBGrid?

Beitrag von Michl »

Habe mal ein altes SQLite Testprojekt modifiziert. Ich weiß nicht, ob ich die eigentliche Frage richtig verstanden habe, aber hier geht das einfach, in dem man die DataSource vom DBGrid aushängt und nach dem Einfügen wieder einhängt:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
  LField: TStringField;
begin
  s := InputBox('Neue Spalte anlegen', 'Name neue Spalte', '');
  if not s.IsEmpty then
  begin
    DBGrid1.DataSource := nil;
    LField := TStringField.Create(Self);
    LField.FieldName := s;
    LField.DisplayLabel := s;
    Query.Fields.Add(LField);
    DBGrid1.DataSource := Datasource;
    QueryAfterOpen(nil);
  end;
end;  
Beispielprojekt anbei (mit 32bit dll - für 64bit müsste einfach die sqlite.dll mit einer 64bit - Version ersetzt werden).
Dateianhänge
SQLDB_SQLite_Test.zip
(324.32 KiB) 67-mal heruntergeladen

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Dynamische Spalten in TDBGrid?

Beitrag von MmVisual »

Vielen Dank für den Demo Code.
Ja, mit der Zuweisung von "DBGrid1.DataSource := Datasource;" wird im Hintergrund vom TDBGrid noch etwas mehr berechnet.

Ich habe deinen Code etwas angepasst so dass die Spalte nicht nur im Query sondern auch in der DB angelegt wird, dann noch in der Query die Felddeklarationen (rechtsklick auf der Query) hinzugefügt.
Wenn ich jetzt "Button1" drücke kann die Query nicht mehr geöffnet werden.

Anbei das Demo zurück, ohne die DLL.
SQLDB.zip
(5.12 KiB) 66-mal heruntergeladen
Im zweiten Button kann man das Feld einblenden das man mal zuvor in der DB angelegt hatte, das geht.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
  LField: TStringField;
begin
  s := InputBox('Neue Spalte anlegen', 'Name neue Spalte', '');
  if not s.IsEmpty then
  begin
    DBGrid1.DataSource := nil;
    Query.Close;
    Query.SQL.Text := 'ALTER TABLE persons ADD ' + s + ' VARCHAR(15)';
    Query.ExecSQL;
    Query.SQL.Text := 'SELECT * FROM persons;';
    Query.Open; // <<<<<<<<<<<<<<<<
    If Assigned(Query.FindField(s)) Then
      Query.FindField(s).Visible := True
    Else Begin
      LField := TStringField.Create(Self);
      LField.FieldName := s;
      LField.DisplayLabel := s;
      Query.Fields.Add(LField);
    End;
    DBGrid1.DataSource := Datasource;
    QueryAfterOpen(nil);
  end;
end;
EleLa - Elektronik Lagerverwaltung - www.elela.de

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Dynamische Spalten in TDBGrid?

Beitrag von Michl »

Habs mir jetzt angeschaut. Jetzt weiß ich, was du erreichen willst. Ich selber arbeite überhaupt nicht Fields, daher funktioniert hier ein Zufügen einer Tabellenspalte auch out of the box.

Wenn du die Fields zur Designzeit erstellst, kannst du auch das selbst erzeugte zufügen. Die Fields müssen vor dem Öffnen der Query bekannt sein. Allerdings muss ein selbst erzeugtes Field auch wieder selbst zerstört werden. So läuft das jetzt hier:

Code: Alles auswählen

  TForm1 = class(TForm)
  ...
  private
    FField: TStringField;
  end; 
  
...  

procedure TForm1.FormClose(Sender: TObject;
  var CloseAction: TCloseAction);
begin
  if Assigned(FField) then
    Query.Fields.Remove(FField);
  Query.ApplyUpdates;
  Transaction.Commit;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
begin
  s := InputBox('Neue Spalte anlegen', 'Name neue Spalte', '');
  if not s.IsEmpty then
  begin
    Query.Close;
    Query.SQL.Text := 'ALTER TABLE persons ADD ' + s + ' VARCHAR(15)';
    Query.ExecSQL;
    FField := TStringField.Create(Self);
    FField.FieldName := s;
    FField.DisplayLabel := s;
    Query.Fields.Add(FField);
    Query.SQL.Text := 'SELECT * FROM persons;';
    Query.Open;
  end;
end; 

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Antworten