Search code examples
delphidatagridlazarus

How can I find the order of grid columns?


I have a grid on a form connected to a database table with 10 fields. The first field (hidden) is the ID. The second field is First_Name, the third Last_Name, etc. These columns are indexed 1 through 10. Now, if the user wants the Last_Name before the First_Name, he can grab that column and slide it over. First_Name now holds index 3 and Last_Name is at index 2.

I need to be able to read the order of the column indices so I can write them to an INI file. Then the next time the user opens the app, I can set the grid back to the preferred state.

I'm doing this with Lazarus 2.0.6 using a TRxDBGrid. I've tried several of its properties, but none of them show the grid column order.


Solution

  • I usually use Delphi rather than Lazarus and have been trying to install the RXDbGrid package into Lazarus 2.0.6 to check my suggested answer to this without any luck so far. However ...

    TRxColumn descends from TColumn in the DBGrids source file.

    TColumnhas a public property Index which is an integer, which is the index of the column into the GridColumns collection.

    Because I can't get the RXDBGrid to install atm, the example below uses a normal TDBGrid, but should work fine with obvious detail changes.

    The example has 3 fields, ID integer, Name String[20] and Value integer.

    For simplicity, instead of saving and loading an IniFile, the Column order is saved to a TMemo, and to test the LoadColumnInfo you need to change the column order in the memo.

    As you'll see, to reload the grid column order, it's easiest to save the column tit;es in left->right order and use a function ColumnByName to find the correct column when reloading the saved info.

    uses
      Classes, SysUtils, memds, db, Forms, Controls, Graphics, Dialogs, DBGrids,
      StdCtrls;
    
    type
      TForm1 = class(TForm)
        btnSaveColumns: TButton;
        btnLoadColumns: TButton;
        DataSource1: TDataSource;
        DBGrid1: TDBGrid;
        MemDataset1: TMemDataset;
        Memo1: TMemo;
        procedure btnLoadColumnsClick(Sender: TObject);
        procedure btnSaveColumnsClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        function ColumnByName(const AName: String): TColumn;
        procedure LoadColumnInfo;
        procedure SaveColumnInfo;
      public
      end;
     [...]
    
    { TForm1 }
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      i : integer;
    begin
      MemDataSet1.Open;
      for i := 0 to 5 do
        MemDataSet1.InsertRecord([i, 'Name' + IntToStr(i), i]);
    end;
    
    procedure TForm1.btnSaveColumnsClick(Sender: TObject);
    begin
      SaveColumnInfo;
    end;
    
    procedure TForm1.btnLoadColumnsClick(Sender: TObject);
    begin
      LoadColumnInfo;
    end;
    
    procedure TForm1.SaveColumnInfo;
    var
      i : Integer;
      S : String;
    begin
      Memo1.Lines.Clear;
      for i := 0 to DBGrid1.Columns.Count - 1 do begin
         S := DBGrid1.Columns[i].Title.Caption;
         Memo1.Lines.Add(S);
      end;
     end;
    
    function TForm1.ColumnByName(const AName : String) : TColumn;
    var
      i : integer;
    begin
      for i := 0 to DBGrid1.Columns.Count - 1 do begin
        Result := DBGrid1.Columns[i];
        if CompareText(AName, Result.Title.Caption) = 0 then
          exit;
      end;
      Result := Nil;
    end;
    
    procedure TForm1.LoadColumnInfo;
    var
      i : Integer;
      Index : Integer;
      Column : TColumn;
      S : String;
    begin
    
      for i := 0 to Memo1.Lines.Count - 1 do begin
        S := Memo1.Lines[i];
         Column := ColumnByName(S);
         Assert(Column <> Nil);
         Column.Index := i;
      end;
    end;
    
    end.