Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Spalten während Laufzeit ausblenden/verschieben (https://www.delphipraxis.net/217025-spalten-waehrend-laufzeit-ausblenden-verschieben.html)

thomas.h 9. Apr 2025 15:58

Datenbank: MySQL • Version: Delphi 11 • Zugriff über: FireDAC

Spalten während Laufzeit ausblenden/verschieben
 
Ich lese eine SQL-Tabelle mit FDQuery aus lasse es mir in einem DBGrid anzeigen. Das Funktioniert auch soweit.

Die Tabelle hat am Anfang 8 Spalten, die ich aber wegen anderen Anwendungen welche die Tabelle auch nutzen nicht in der Reihenfolge ändern kann. Da ich sie aber bei mir in einer anderen Reihenfolge benötige habe ich sie im DBGrid von der Reihenfolge geändert.
Da aber nicht jeder Benutzer alle Spalten sehen darf blende ich im Nachgang je nach Berechtigung die Spalten aus und ändere in diesem Moment gleichzeitig die Spaltenüberschriften dies mache ich wie folgt:

FDQuerryAfterOpen
for i := 0 to DataSet.Fields.Count-1 do begin
DataSet.Fields[i].DisplayLabel := DataSet.Fields[i].DisplayLabel + '_TXT'; // Umbenennen geht
if NOT(Access[i]) then begin
// DataSet.Fields[i].Visible := FALSE; // -> Erzeugt eine Fehlermeldung daher geändert in:
DBGGrid.Columns[i].Visible := FALSE // Blendet falsche Spalten aus, da Reihenfolge geändert
end;
end;

Durch das Umsortieren bekomme ich jetzt die Falschen Spalten ausgeblendet da "DataSet.Fields[i]" auf eine andere Spalte verweist als "DBGGrid.Columns[i]"

Hat jemand ein Tipp wie ich das zusammen bekomme?
Oder wie ich das VISIBLE der Spalte unter "DataSet" erreiche?
Alternative wäre noch dass ich die Reihenfolge der Spalten im original lasse und sie dann nach dem Auslesen in der Reihenfolge verändere, was ich aber auch noch nicht herausgefunden habe, wie es geht.

Zu alten Zeiten als es noch kein FireDAC gab und man es mit etwas mehr und aufwändigerem Code auslesen musste und in einen normalen GRID geschrieben hat hat es in der Auslese-Schleife ganz gut Funktioniert. Jetzt wo das alte Programm ein Update braucht und ich es in meine Aktuelle Version übernehme soße ich gerade an die grenzen meines wissens mit FireDAC.

himitsu 9. Apr 2025 17:48

AW: Spalten während Laufzeit ausblenden/verschieben
 
Natürlich hat der Index/Liste im DataSet.Fields nichts mit der Liste der Grid.Columns gemeinsam und per se darf nicht davon ausgegangen werden, dass diese Listen irgendeine Übereinstimmung haben. :roll:

Ja, wenn die Columns automatisch generiert werden, anhand der Fields des verknüpften DataSets, dann passt es zufällig (anfangs),
aber sobald man selbst an diese Liste Hand angelegt hat, halt nicht mehr unbedingt.

Da es auch keine ColumnByFieldName-Methode gibt (echt peinlich, denn sowas fehlt an vielen hauseigenen Komponenten von Embarcadero), mußt du eben selbst suchen,
und alle DBGrid.Columns[idx].FieldName durchgehen.

DeddyH 9. Apr 2025 18:18

AW: Spalten während Laufzeit ausblenden/verschieben
 
Ich würde vermutlich ganz pragmatisch die SQL-Abfrage passend zusammenklöppeln, dann muss ich nicht im Nachhinein an den Darstellungs-Komponenten herumfummeln. Ob das in Deinem Fall jetzt so einfach machbar ist, kann ich natürlich nicht beurteilen.

Sinspin 9. Apr 2025 19:33

AW: Spalten während Laufzeit ausblenden/verschieben
 
Zitat:

Zitat von DeddyH (Beitrag 1547965)
Ich würde vermutlich ganz pragmatisch die SQL-Abfrage passend zusammenklöppeln, dann muss ich nicht im Nachhinein an den Darstellungs-Komponenten herumfummeln. Ob das in Deinem Fall jetzt so einfach machbar ist, kann ich natürlich nicht beurteilen.

Genau. Und dann noch beim öffnen alle Spalten aus den Grid hauen und neu erstellen. Jedenfalls wenn sich was ändert.
Man kann dann ja noch die Einstellungen für die aktuelle Liste irgendwo speichern, so dass man das beim erstellen wieder herstellen kann.

Andere Option ist, pro möglicher Spaltenkombination einen eigenen Grid erstellen und jeweils den passenden sichtbar machen.

thomas.h 10. Apr 2025 08:15

AW: Spalten während Laufzeit ausblenden/verschieben
 
Danke soweit mal für die Rückmeldungen.

Das mit der SQL-Abfrage umstellen funktioniert in meinem Fall leider nicht, da es mit den Spalten 9 und folgend etwas komplexer ist.

Demnach werde ich es dann mal mit dem anderen Ansatz mit "DBGrid.Columns[idx].FieldName" probieren, wobei ich da noch prüfen muss ob ich die Spaltenüberschriften auch mit ändern kann oder ob ich dafür eine extra schleife machen muss. Bisher verwende ich unter DataSet.Fields[i]. "DisplayLabel", aber das gibt es unter DBGrid.Columns[idx]. nicht. Eventuell geht es aber mit "DisplayName".
Werde ich jetzt testen.

Für andere Vorschläge bin ich aber weiterhin offen.

Delphi.Narium 10. Apr 2025 08:41

AW: Spalten während Laufzeit ausblenden/verschieben
 
Das TDBGrid kann die Spaltenkonfiguration aus einer Datei lesen und in eine Datei speichern.
Delphi-Quellcode:
  DBGrid1.Columns.LoadFromFile();
  DBGRid1.Columns.SaveToFile();
Es ginge auch mit einem Stream.

Mach' Dir einmal ein DBGrid nach den genauene Vorstellungen. Wenn Du mehrere bestimmte, aber feste Spaltenkombinationen benötigst, halt entsprechend viele. Die speicherst Du in Konfigurationsdateien und lädst sie dann jeweils situationsbedingt.

Für das DBGrid hab' ich mit mal (für Delphi 7) folgende Funktionen geschrieben:
Delphi-Quellcode:
type
  TColumnsWrapper = class(TComponentWrapper)
  private
    FColumns    : TDBGridColumns;
  public
  published
    property Columns    : TDBGridColumns read fColumns    write fColumns;
  end;

...

    function   LoadColumnsFromText : boolean;
    function   SaveColumnsToText(dbg: TDBGrid; sFilename : String): boolean;

...

function TfrmDGB.LoadColumnsFromText(dbg: TDBGrid; sFilename : String): boolean;
var
  Wrapper : TColumnsWrapper;
  st     : TMemoryStream;
  stFile : TMemoryStream;
begin
  Result := false;
  if not Assigned(dbg.DataSource) then exit;
  if not Assigned(dbg.DataSource.DataSet) then exit;
  if not Assigned(dbg.Columns) then exit;
  if dbg.DataSource.DataSet.Active then begin
    if dbg.DataSource.DataSet.Fields.Count = 0 then exit;
  end;
  if dbg.Columns.Count = 0 then exit;
  Result := FileExists(sFilename);
  if not Result then exit;
  if dbg.Columns.Count > 0 then dbg.Columns.Clear;
  Wrapper := TColumnsWrapper.Create(dbg);
  try
    Wrapper.Columns := TDBGridColumns.Create(nil, TColumn);
    try
      stFile := TMemoryStream.Create;
      try
        st := TMemoryStream.Create;
        try
          stFile.LoadFromFile(sFilename);
          stFile.Position := 0;
          ObjectTextToBinary(stFile,st);
          st.Position    := 0;
          st.ReadComponent(Wrapper);
          dbg.Columns.Assign(Wrapper.Columns);
        finally
          st.Free;
        end;
      finally
        stFile.Free;
      end;
    finally
      Wrapper.Columns.Free;
    end;
  finally
    Wrapper.Free;
  end;
  Result := dbg.Columns.Count > 0;
end;

function TfrmDGB.SaveColumnsToText(dbg: TDBGrid; sFilename : String): boolean;
var
  Wrapper : TColumnsWrapper;
  st     : TMemoryStream;
  stFile : TMemoryStream;
  s      : String;
begin
  Result := false;
  if not Assigned(dbg.DataSource) then exit;
  if not Assigned(dbg.DataSource.DataSet) then exit;
  if not Assigned(dbg.Columns) then exit;
  if dbg.DataSource.DataSet.Active then begin
    if dbg.DataSource.DataSet.Fields.Count = 0 then exit;
  end;
  if dbg.Columns.Count = 0 then exit;
  Wrapper            := TColumnsWrapper.Create(nil);
  Wrapper.Name       := Format('DBGrid_%s',[dbg.Name]);
  Wrapper.Filename   := sFilename;
  Wrapper.Application := Application.ExeName;
  try
    st := TMemoryStream.Create;
    try
      stFile := TMemoryStream.Create;
      try
        Wrapper.Columns := dbg.Columns;
        st.WriteComponent(Wrapper);
        st.Position    := 0;
        ObjectBinaryToText(st, stFile);
        stFile.Position := 0;
        s := ExtractFilePath(sFilename);
        if s <> '' then ForceDirectories(s);
        stFile.SaveToFile(sFilename);
      finally
        stFile.Free;
      end;
    finally
      st.Free;
    end;
  finally
    Wrapper.Free;
  end;
  Result := FileExists(sFileName);
end;
Damit bekommst Du dann Textdateien, die Du auch in einem Editor nach Deinen Wünschen gestalten kannst. Es handelt sich um delphitypische DFM-Dateien.

Ein Beispiel:
Delphi-Quellcode:
object DBGrid_dbg: TColumnsWrapper
  Filename = 'C:\Delphi\Config\Konfigurationsname.dfm'
  Application = 'C:\Delphi\Programmname.exe'
  Columns = <
    item
      // Hier stehen alle Attribute von TDBGrid.Columns.Items[x] zur Verfügung
      // Der Title ist auch darunter.
      Expanded = False
      FieldName = 'DatabaseFile'
      Width = 443
      Visible = True
    end
    item
      Expanded = False
      FieldName = 'UserID'
      Width = 64
      Visible = True
    end
    item
      Expanded = False
      FieldName = 'Password'
      Width = 64
      Visible = True
    end
    item
      Expanded = False
      FieldName = 'CharSet'
      Width = 65
      Visible = True
    end>
end
Eventuell könnte das ja ein Ansatz für dich sein.

thomas.h 15. Apr 2025 11:52

AW: Spalten während Laufzeit ausblenden/verschieben
 
Danke noch mal an Alle,

auch das Speichern in eine Datei at mir weiter geholfen, auch wenn ich es inzwischen insgesamt noch etwas anders gelöst habe.

Ich mache es zwar weiterhin in FDQuerryAfterOpen, aber eben in 2 getrennten Schleife.
Die Überschriften der Spalten mit dem Beinhaltentenden "DataSet" und dann noch eine fürs Spalten ausblenden anhand des DB-Grid´s.

Mein Programm macht auf jeden Fall was es soll :)


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