DBGrid Reihenfolge der Spalten sichern

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

Hallo,

ich möchte ein DBGrid konfektionieren d.h. die Reihenfolge der Spalten ermitteln und dann abspeichern - wie greife ich auf die Spalten indexe zu ?
Ändert sich der Index beim umsortiern oder gibt es eine Feste Zuordnung Inex zu Spaltenname ?

Gruß Frank

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

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von Michl »

Ist ein bischen tricky, da sich bei der Zuweisung eines Indexes, die restlichen Columns automatisch anpassen. Daher der Umweg mittels einer Liste (schnell mal zusammengeschustert):

Code: Alles auswählen

  TForm1 = class(TForm)
...
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure SQLQuery1AfterOpen(DataSet: TDataSet);
  private
    ProjectIniFile: String;
    procedure LoadIni;
    procedure SaveIni;
  end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  ProjectIniFile := Application.Location + PathDelim + 'project.ini';
...
end;
 
procedure TForm1.SQLQuery1AfterOpen(DataSet: TDataSet);
begin
...
  LoadIni;
end;
 
procedure TForm1.LoadIni;
var
  Ini: TIniFile;
  List: TList;
  i, i2: Integer;
  AFieldName: String;
begin
  if not SQLQuery1.Active then Exit;
 
  List := TList.Create;
  Ini := TIniFile.Create(ProjectIniFile);
  try
    for i := 0 to DBGrid1.Columns.Count - 1 do
      List.Add(DBGrid1.Columns.Items[i]);
 
    for i := 0 to DBGrid1.Columns.Count - 1 do
    begin
      AFieldName := Ini.ReadString('Grid', 'Column' + IntToStr(i), DBGrid1.Columns.Items[i].FieldName);
      for i2 := 0 to List.Count - 1 do
        if AFieldName = TColumn(List[i2]).FieldName then
        begin
          TColumn(List[i2]).Index := i;
          Break;
        end;
    end;
  except
    on e: Exception do
      ShowMessage('TForm1.LoadIni: ' + e.Message);
  end;
  Ini.Free;
  List.Free;
end;
 
procedure TForm1.SaveIni;
var
  Ini: TIniFile;
  i: Integer;
begin
  if not SQLQuery1.Active then Exit;
 
  Ini := TIniFile.Create(ProjectIniFile);
  try
    for i := 0 to DBGrid1.Columns.Count - 1 do
      Ini.WriteString('Grid', 'Column' + IntToStr(i), DBGrid1.Columns.Items[i].FieldName);
  except
    on e: Exception do
      ShowMessage('TForm1.SaveIni: ' + e.Message);
  end;
  Ini.Free;
end;
 
procedure TForm1.FormClose(Sender: TObject;
  var CloseAction: TCloseAction);
begin
  SaveIni;
...
end;

Code: Alles auswählen

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

DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

Hallo Michl,

Danke!
du sagst es - es ist mir zu tricky.

Ich möchte die einzelnen Eigenschaften verstehen - gibt da auch keine vernünftige Hilfe

Wie greife ich auf die Spalten indexe zu ?
Ändert sich der Index beim umsortiern oder gibt es eine Feste Zuordnung Inex zu Spaltenname ?
Was ist die Eigenschaft Tag?
Was ist SortColumn?
Was ist TSortorder?

Zur Laufzeit kann man die Reihenfolge ja beliebig Ändern d.h. es gehen die Zuordnungen zu den Feldnamen nicht verloren

Gruß Frank

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von wp_xyz »

Ich verstehe nicht... Der Spalten"index" ist wie der Index in einem Array, das erste Array-Element hat den Index 0, das zweite den Index 1 usw. Welches Feld der Spalte zugeordnet ist, ist eine andere Sache - das erhältst du über die Eigenschaft FieldName der Spalte, also DBGrid.Columns[0].FieldName ist der Name des Feldes, das in der 1.Spalte dargestellt ist.

Wenn du die Spalten umsortierst, bleibt der Index der 1. Spalte immer 0 - sonst wär's ja nicht die 1.Spalte!, nur steht dann dort ein anderes Feld.

Falls dies dir nicht weiterhilft, versuche die Frage klarer zu formulieren.

[EDIT]
Michl hat recht: es gibt noch eine zweite Art von Index. Nachdem TColumn ein Element einer Collection ist, hat es auch die Eigenschaft Index, also der Index, mit dem sie ursprünglich erzeugt wurde. Allerdings wird dieser Index verändert, wenn sich die Reihenfolge durch Umsortieren ändert. Baue in Michl Projekt des folgenden Beitrags einen Button ein, der auf folgenden Code im OnClick reagiert, und du siehst, dass die Spalten-Eigenschaft Index beim Verändern der Spaltenreihenfolge mit der Maus mit dem Array-Index identisch bleibt. Zur Identification einer Spalte ist Index also nicht geeignet, sondern nur FieldName.

Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
var
  L: TStrings;
  F: TForm;
  LB: TListbox;
  i: Integer;
  col: TColumn;
begin
  F := TForm.Create(nil);
  try
    F.Position := poMainFormCenter;
    LB := TListbox.Create(F);
    LB.Parent := F;
    LB.Align := alClient;
    L := TStringList.Create;
    try
      for i:=0 to DBGrid1.Columns.Count-1 do begin
        col := DBGrid1.Columns[i];
        L.Add('%d - Index: %d, FieldName: %s', [i, col.Index, col.FieldName]);
      end;
        LB.Items.Assign(L);
    finally
      L.Free;
    end;
    F.ShowModal;
  finally
    F.Free;
  end;
end;
Zuletzt geändert von wp_xyz am So 23. Jul 2017, 17:01, insgesamt 1-mal geändert.

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

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von Michl »

DL3AD hat geschrieben:Wie greife ich auf die Spalten indexe zu ?
Mittels DBGrid1.Columns.Items[...].Index

DL3AD hat geschrieben:Ändert sich der Index beim umsortiern
Ja

DL3AD hat geschrieben:gibt es eine Feste Zuordnung Inex zu Spaltenname ?
Nein, daher oben der Umweg über TList.

DL3AD hat geschrieben:Was ist die Eigenschaft Tag?
http://www.delphipraxis.net/71648-ist-tag.html

DL3AD hat geschrieben:Was ist SortColumn? Was ist TSortorder?
Das sind beides Eigenschaften vom CustomGrid, die für Nachfahren vom CustomGrid verwendet werden, nicht jedoch vom DBGrid. Diese kannst du dort ignorieren.

Ich hänge mal ein kleines Bsp. an mit 32bit SQLite für Windows an (wenn du ein anderes OS oder 64bit verwendest, müsstest du die SQLite-Bibliothek austauschen), mit einem Button, der das Grid von vorn nach hinten sortiert. Vielleicht hilft es ja zum besseren Verständnis?
Dateianhänge
SQLDB-SQLite-Einfach.zip
(325.74 KiB) 89-mal heruntergeladen

Code: Alles auswählen

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

DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

... d.h. mit DBGrid1.Columns.Items[...].Index wird die Reihenfolge 0...n von links nach rechts gekennzeichnet.
Wenn ich z.B. eine Spalte Datum habe und verschiebe diese so erhält sie je nach position einen anderen Index.
An jede Spalte sind ja verschiedene Eigenschaften geknüpft welche alle erhalten bleiben bist auf den Index wenn ich verschiebe.
Gibt es außer dem Feldnamen einen Marker mit dem ich arbeiten könnte um die Spalte zu identifizieren ?

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

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von Michl »

Der Fieldname ist eindeutig. D.h. wenn das Query aktiv ist und das entsprechende Field liefert, kann das Column eindeutig zugeordnet werden. Daher würde ich immer dieses verwenden. Ansonsten könnte man die Columns auch nach Column.Tag, Column.Title.Caption bzw Column.Displayname unterscheiden, wenn diese unverwechselbar zugewiesen wurden.

Code: Alles auswählen

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

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von wp_xyz »

DL3AD hat geschrieben:Gibt es außer dem Feldnamen einen Marker mit dem ich arbeiten könnte um die Spalte zu identifizieren ?

Eigentlich nicht. Es sei denn, du verwendest die Allzweck-Eigenschaft "Tag" dafür (übersetzt etwa wie "Aufkleber"). Diese Eigenschaft wird für sonst nichts verwendet und steht zur freien (einmaligen) Verfügung. Du könntest nach dem Öffnen der Datenbank, wenn die ursprüngliche Reihenfolge der Spalten feststeht, die Columns des Grid durchlaufen und DBGrid.Columns[i].Tag den Laufindex i zuweisen.

Aber, eigentlich würde ich das nicht machen. Vielleicht brauchst du Tag später für noch etwas anderes? Und FieldName ist von der Datenbank her garantiert eindeutig. Z.B. könntest du so nach der Spalte mit einem bestimmten Feld suchen:

Code: Alles auswählen

function FindColumnOfField(AGrid: TDBGrid; AFieldName: String): TColumn;
var
  i: Integer;
begin
  for i:=0 to AGrid.Columns.Count-1 do
    if AGrid.Columns[i].FieldName = AFieldName then begin
      Result := AGrid.Columns[i];
      exit;
    end;
  Result := nil;
end;

DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

... Danke - das mit FindColumnOfField ist ein sehr guter Ansatz - da werde ich darauf aufbauen.

Gruß Frank

DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

Hallo,

es funktioniert soweit alle prima - Spaltenbreite, Titel, Feldnamen und Sichtbakeit der Spalten sichern sowie die Reihenfolge sicher geht auch (über Testbutton)
Ein kleines Problem habe ich noch - wenn ich die Reihenfolge der Spalten durch verschieben ändere dann habe ich mit OnColumnMoved ein Event erzeugt und
wollte dann die neue Reihenfolge speichern.
Nun habe ich festgestellt dass das Event kommt befor die neue Reihenfolge der Spalten "fertig" ist - das sieht man schön wenn eine SchowMessage macht.
Es wird nachdem man die Maustaste losgelassen hat die Message ausgegeben und der Rote Marker zwischen den Spalten wird noch angezeigt.
Erst wenn die Message bestätigt wird sortiert sich die Spalte um.
Gibt es da ein anderes Event welchen man verwenden kann wenn das Umsortieren komplett fertig ist ?

Gruß Frank

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

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von Michl »

Hast du mal probiert eine Methode mit Application.QueueAsyncall im OnColumnMoved aufzurufen und in dieser Methode zu speichern?

Wenn das Grid auf einem Formular (und nicht z.B. auf einem Frame) liegt, warum speicherst du nicht im OnClose vom Formular?

Code: Alles auswählen

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

DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

Michl hat geschrieben:Hast du mal probiert eine Methode mit Application.QueueAsyncall im OnColumnMoved aufzurufen und in dieser Methode zu speichern?

Wie macht man das ?

Michl hat geschrieben:Wenn das Grid auf einem Formular (und nicht z.B. auf einem Frame) liegt, warum speicherst du nicht im OnClose vom Formular?

Wird auch gemacht - aber wen ich Spalten verschoben habe dann will ich vieleicht noch welche ein und ausblenden - dann muss ich vorher noch
meine CheckListBox mit der neuen Reihenfolge befüllen - und dafür benötige ich das Event OnColumnMoved

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von wp_xyz »

DL3AD hat geschrieben:aber wen ich Spalten verschoben habe dann will ich vieleicht noch welche ein und ausblenden - dann muss ich vorher noch
meine CheckListBox mit der neuen Reihenfolge befüllen - und dafür benötige ich das Event OnColumnMoved

Aber das machst du doch nicht gleichzeitig. Ich würde die Checklistbox erst zu Beginn der Routine, die den Dialog zum An/Abwählen von Spalten erzeugt, füllen. Oder ist diese Checklistbox permanent sichtbar?

DL3AD
Beiträge: 478
Registriert: Fr 13. Sep 2013, 12:07
OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
CPU-Target: 64Bit
Wohnort: Rügen

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von DL3AD »

... ist in einem DBGrid Configurations Form - da wird alles zum Tabellendesign eingestellt und somit gleichzeitig sichtbar.

EDIT:

Problem gelößt:
Habe einen TTimer in der OnColumnMoved gesetzt (1ms) und in der Timer procedure den rest erledigt - nun is wie muss :mrgreen:

Gruß Frank

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: DBGrid Reihenfolge der Spalten sichern

Beitrag von braunbär »

Diese Vorgangsweise ist eine "quick and dirty" Notlösung, wenn es gar nicht anders geht, und beinhaltet m.E. immer das Risiko von instabilem Programmverhalten.
Du kannst nie 100% sicher sein, ob die Zeit, die du dem Timer lässt, auch wirklich ausreicht. Wenn ein anderer Task mit hoher Priorität dein Programm kurzzeitig blockiert, passiert nicht mehr das, was du wilst. Mag sein, dass die Wahrscheinlichkeit gering ist, aber man sollte immer eine bessere Lösung suchen.

Antworten