Pregunta

I have a TDBGrid. It works, but the columns shown are very large.

How can I set an "auto-fix column width"?

¿Fue útil?

Solución

The needed Columnwidth is depended of the settings of the Grids canvas and the mamimum length of the displaytext of each field.

procedure FitGrid(Grid: TDBGrid);
const
  C_Add=3;
var
  ds: TDataSet;
  bm: TBookmark;
  i: Integer;
  w: Integer;
  a: Array of Integer;
begin
  ds := Grid.DataSource.DataSet;
  if Assigned(ds) then
  begin
    ds.DisableControls;
    bm := ds.GetBookmark;
    try
      ds.First;
      SetLength(a, Grid.Columns.Count);
      while not ds.Eof do
      begin
        for I := 0 to Grid.Columns.Count - 1 do
        begin
          if Assigned(Grid.Columns[i].Field) then
          begin
            w :=  Grid.Canvas.TextWidth(ds.FieldByName(Grid.Columns[i].Field.FieldName).DisplayText);
            if a[i] < w  then
               a[i] := w ;
          end;
        end;
        ds.Next;
      end;
      for I := 0 to Grid.Columns.Count - 1 do
        Grid.Columns[i].Width := a[i] + C_Add;
        ds.GotoBookmark(bm);
    finally
      ds.FreeBookmark(bm);
      ds.EnableControls;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FitGrid(DBgrid1)
end;

Otros consejos

Minor modification of bummi's answer to insure that Title Row (Row 0) is not truncated, and excess space will be allocated on each column

procedure FitGrid(Grid: TDBGrid);
const
  C_Add = 3;
var
  ds: TDataSet;
  bm: TBookmark;
  i: Integer;
  w: Integer;
  a: array of Integer;
begin
  ds := Grid.DataSource.DataSet;

  if not Assigned(ds) then
    exit;

  if Grid.Columns.Count = 0 then
    exit;

  ds.DisableControls;
  bm := ds.GetBookmark;
  try
    ds.First;
    SetLength(a, Grid.Columns.Count);
    for i := 0 to Grid.Columns.Count - 1 do
      if Assigned(Grid.Columns[i].Field) then
        a[i] := Grid.Canvas.TextWidth(Grid.Columns[i].FieldName);

    while not ds.Eof do
    begin

      for i := 0 to Grid.Columns.Count - 1 do
      begin
        if not Assigned(Grid.Columns[i].Field) then
          continue;

        w := Grid.Canvas.TextWidth(ds.FieldByName(Grid.Columns[i].Field.FieldName).DisplayText);

        if a[i] < w then
          a[i] := w;
      end;
      ds.Next;
    end;

    w := 0;
    for i := 0 to Grid.Columns.Count - 1 do
    begin
      Grid.Columns[i].Width := a[i] + C_Add;
      inc(w, a[i] + C_Add);
    end;

    w := (Grid.ClientWidth - w - 20) div (Grid.Columns.Count);

    if w > 0 then
      for i := 0 to Grid.Columns.Count - 1 do
        Grid.Columns[i].Width := Grid.Columns[i].Width + w;


    ds.GotoBookmark(bm);
  finally
    ds.FreeBookmark(bm);
    ds.EnableControls;
  end;
end;

Minor modification of bummi's answer to insure that Title Row (Row 0) is not truncated

procedure FitGrid(Grid: TDBGrid);
const
  C_Add=3;
var
  ds: TDataSet;
  bm: TBookmark;
  i: Integer;
  w: Integer;
  a: Array of Integer;
begin
  ds := Grid.DataSource.DataSet;
  if Assigned(ds) then
  begin
    ds.DisableControls;
    bm := ds.GetBookmark;
    try
      ds.First;
      SetLength(a, Grid.Columns.Count);
      while not ds.Eof do
      begin
        for I := 0 to Grid.Columns.Count - 1 do
        begin
          if Assigned(Grid.Columns[i].Field) then
          begin
            w :=  Grid.Canvas.TextWidth(ds.FieldByName(Grid.Columns[i].Field.FieldName.).DisplayText);
            if a[i] < w  then
               a[i] := w ;
          end;
        end;
        ds.Next;
      end;
      //if fieldwidth is smaller than Row 0 (field names) fix
      for I := 0 to Grid.Columns.Count - 1 do
      begin
        w :=  Grid.Canvas.TextWidth(Grid.Columns[i].Field.FieldName);
        if a[i] < w  then
           a[i] := w ;
      end;

      for I := 0 to Grid.Columns.Count - 1 do
        Grid.Columns[i].Width := a[i] + C_Add;
        ds.GotoBookmark(bm);
    finally
      ds.FreeBookmark(bm);
      ds.EnableControls;
    end;
  end;
end;

Minor modification of bummi's, TheSteven's and Jens' answers to insure that Title Row (Row 0) is not truncated, and excess space will be allocated on each column, and take visibility of columns into account.

procedure FitGrid(const Grid: TDBGrid; const CoverWhiteSpace: Boolean = True);
const
  C_Add=3;
var
  DS: TDataSet;
  BM: TBookmark;
  I, W, VisibleColumnsCount: Integer;
  A: array of Integer;
  VisibleColumns: array of TColumn;
begin
  DS := Grid.DataSource.DataSet;
  if Assigned(DS) then
  begin
    VisibleColumnsCount := 0;
    SetLength(VisibleColumns, Grid.Columns.Count);
    for I := 0 to Grid.Columns.Count - 1 do
      if Assigned(Grid.Columns[I].Field) and (Grid.Columns[I].Visible) then
      begin
        VisibleColumns[VisibleColumnsCount] := Grid.Columns[I];
        Inc(VisibleColumnsCount);
      end;
    SetLength(VisibleColumns, VisibleColumnsCount);

    DS.DisableControls;
    BM := DS.GetBookmark;
    try
      DS.First;
      SetLength(A, VisibleColumnsCount);
      while not DS.Eof do
      begin
        for I := 0 to VisibleColumnsCount - 1 do
        begin
            W :=  Grid.Canvas.TextWidth(DS.FieldByName(VisibleColumns[I].Field.FieldName).DisplayText);
            if A[I] < W then
               A[I] := W;
        end;
        DS.Next;
      end;
      //if fieldwidth is smaller than Row 0 (field names) fix
      for I := 0 to VisibleColumnsCount - 1 do
      begin
        W := Grid.Canvas.TextWidth(VisibleColumns[I].Field.FieldName);
        if A[I] < W then
           A[I] := W;
      end;

      W := 0;
      if CoverWhiteSpace then
      begin
        for I := 0 to VisibleColumnsCount - 1 do
          Inc(W, A[I] + C_Add);
        W := (Grid.ClientWidth - W - 20) div VisibleColumnsCount;
        if W < 0 then
          W := 0;
      end;

      for I := 0 to VisibleColumnsCount - 1 do
        VisibleColumns[I].Width := A[I] + C_Add + W;
      DS.GotoBookmark(BM);
    finally
      DS.FreeBookmark(BM);
      DS.EnableControls;
    end;
  end;
end;

I found 'Columns' in the properties of my TDBGrid and new window is opened. In that window I add new FieldNames - you can choose columnNames only from the result of your SQL string of your TADOQuery and then when you click to the exact column you can find 'Width' in the properties of selected column so change it whatever you like. It works for me.

I'm afraid the last adaptation of the code is no correct.

I would rather write something like :

 const
  C_Add=20;

//.....

Sup := 0;
      if CoverWhiteSpace then
        sup :=C_Add;

      for I := 0 to VisibleColumnsCount - 1 do
          VisibleColumns[I].Width := A[I] + sup;
      DS.GotoBookmark(BM);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top