Fabio Vitale
Fabio Vitale

Reputation: 2287

How can I access a TDBGrid column by name instead of by Index?

How can I access a TDBGrid column by name instead of Index?

For example, now I use:

 grdInvoiceItems.Columns[2].Visible := False;

but it would be much better to write something like:

 grdInvoiceItems.Columns['UnitPrice'].Visible := False;

In the mean time I use a for cycle like in:

  for idx := 0 to grdInvoiceItems.Columns.Count - 1 do
    begin
    if (
         (grdInvoiceItems.Columns[idx].FieldName = 'UnitPrice') or
         (grdInvoiceItems.Columns[idx].FieldName = 'Discount') or
         (grdInvoiceItems.Columns[idx].FieldName = 'SecretCode')
       ) then
      grdInvoiceItems.Columns[idx].Visible := False;
    end;

Using colum name is IMO much better tham column index since index is subject to change more often than name.

Any idea on how to encapsulate it better?

Upvotes: 8

Views: 14932

Answers (3)

Chillispike
Chillispike

Reputation: 1

I wanted to to the similar thing, but i was thinking if the dbgrid doesn't know the colmuns by name (for this case), maybe one else (speaking of components) does know it allready.

In my case i use a fdquery -> Datasource -> DBgrid connection. The FDQuery knows the fields by name and by id.

So considering you use similar components you can do

dbgrid1.Columns[fdquery1.FieldByName('UnitPrice').Index].visible:=false;

Upvotes: 0

MartynA
MartynA

Reputation: 30745

You could try something like this:

function ColumnByName(Grid : TDBGrid; const AName : String) : TColumn;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to Grid.Columns.Count - 1 do begin
  if (Grid.Columns[i].Field <> Nil) and (CompareText(Grid.Columns[i].FieldName, AName) = 0) then begin
       Result := Grid.Columns[i];
       exit;
     end;
  end;
end;

Of course, if you are using a version of Delphi which is recent enough to support Class Helpers, you could wrap this function into a Class Helper for TDBGrid, like this

type
  TGridHelper = class helper for TDBGrid
    function ColumnByName(const AName : String) : TColumn;
  end;
[...]

function TGridHelper.ColumnByName(const AName: String): TColumn;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to Columns.Count - 1 do begin
     if (Columns[i].Field <> Nil) and (CompareText(Columns[i].FieldName, AName) = 0) then begin
       Result := Columns[i];
       exit;
     end;
  end;
end;

Then, you could do this

Col := DBGrid1.ColumnByName('SomeName');

Obviously, you could write a similar function which searches by the column's title, rather than the associated Field's FieldName.

Upvotes: 14

dummzeuch
dummzeuch

Reputation: 11252

You could create a mapping between column name and grid index e.g. as a dictionary and use that. Note that not every column in a dataset is necessarily visible in a dbgrid. In addition there might be calculated fields in the dataset, so don't forget these. The safest way to create the mapping would be to iterate trough the columns of the dbgrid and store their field names together with the column index. This way you won't get any invalid entries and any field that's not in the mapping does not have a dbgrid column.

Upvotes: 1

Related Questions