How to auto fit/scale DBGrid's (or other similar) columns widths according to its contents?
What you have to do is to use the grid's canvas to measure the contents of each column and set the column's width accordingly. You can either iterate through the dataset or use the OnColumnDraw-Event to adjust the width on the fly.
Here's a sample (I had to use an offset of 5 pixels)
procedure TForm7.DBGridDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
Var
w : Integer;
begin
w := 5+DBGrid.Canvas.TextExtent(Column.Field.DisplayText).cx;
if w>column.Width then Column.Width := w;
end;
procedure TForm7.FormActivate(Sender: TObject);
Var
i : Integer;
begin
// Initialize width
for I := 0 to DBGrid.Columns.Count - 1 do
DBGrid.Columns[i].Width := 5 + DBGrid.Canvas.TextWidth(DBGrid.Columns[i].title.caption)
end;
EDITED:
My first code was about fit the columns inside the grid with, with this new code, AutoSizeColumns reads the records to calc the width of each column until MaxRows or Dataset.Eof:
class function TDBGridHelper.AutoSizeColumns(DBGrid: TDBGrid; const MaxRows: Integer = 25): Integer;
var
DataSet: TDataSet;
Bookmark: TBookmark;
Count, I: Integer;
ColumnsWidth: array of Integer;
begin
SetLength(ColumnsWidth, DBGrid.Columns.Count);
for I := 0 to DBGrid.Columns.Count - 1 do
if DBGrid.Columns[I].Visible then
ColumnsWidth[I] := DBGrid.Canvas.TextWidth(DBGrid.Columns[I].Title.Caption + ' ')
else
ColumnsWidth[I] := 0;
if DBGrid.DataSource <> nil then
DataSet := DBGrid.DataSource.DataSet
else
DataSet := nil;
if (DataSet <> nil) and DataSet.Active then
begin
Bookmark := DataSet.GetBookmark;
DataSet.DisableControls;
try
Count := 0;
DataSet.First;
while not DataSet.Eof and (Count < MaxRows) do
begin
for I := 0 to DBGrid.Columns.Count - 1 do
if DBGrid.Columns[I].Visible then
ColumnsWidth[I] := Max(ColumnsWidth[I], DBGrid.Canvas.TextWidth(
DBGrid.Columns[I].Field.Text));
Inc(Count);
DataSet.Next;
end;
finally
DataSet.GotoBookmark(Bookmark);
DataSet.FreeBookmark(Bookmark);
DataSet.EnableControls;
end;
end;
Count := 0;
for I := 0 to DBGrid.Columns.Count - 1 do
if DBGrid.Columns[I].Visible then
begin
DBGrid.Columns[I].Width := ColumnsWidth[I];
Inc(Count, ColumnsWidth[I]);
end;
Result := Count - DBGrid.ClientWidth;
end;
I call it in the DataSet.AfterOpen event:
TGridHelper.AutoSizeColumns(MyDBGrid);
Why to use so complicated code? :D Just use this. Its also have 5 px offset.
procedure TForm1.FormActivate(Sender: TObject);
var
i:integer;
begin
for i :=0 to DbGrid1.Columns.Count - 1 do
DbGrid1.Columns[i].width :=5+dbgrid1.Canvas.TextWidth(DbGrid1.Columns[i].Title.Caption);
end;