调整列宽 DBGrid

Posted

技术标签:

【中文标题】调整列宽 DBGrid【英文标题】:Adjust Column width DBGrid 【发布时间】:2013-07-07 06:49:21 【问题描述】:

我有一个 TDBGrid。它可以工作,但显示的列非常大。

如何设置“自动修复列宽”?

【问题讨论】:

每列的宽度默认调整为相应字段的声明大小。如果这与现实不符,您应该重新考虑您的数据库设计。 @Uwe,对于字段的 DisplayWidth 计数 0 字符来说是这样,每个字符宽 6 像素,Tahoma 大小为 8 字体(默认缩放)。如果您正在显示,假设有 100 个 W 字符(每个 10 像素宽),默认列宽将比实际需要的窄 400 像素(当 DisplayWidth 为 100 时)。因此,自动调整宽度可能还有一个相反的原因。 【参考方案1】:

所需的列宽取决于网格画布的设置和每个字段的显示文本的最小长度。

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;

【讨论】:

不需要零内存。 SetLength 用零初始化所有新成员。 很好的解决方案。挑剔:在内部 if a[i] &lt; w then 中设置 a[i] := w; 然后在最后一个 for 循环中设置 Grid.Columns[i].Width := a[i] + C_Add 这在大型数据集上可能需要很长时间,并且当您有一条内容很长的杂散记录时会失败。顺便说一句,TDBGrid 首先没有这种功能,而且 Windows 资源管理器在某些情况下也不会“正确”调整大小。【参考方案2】:

对 bummi 的回答稍作修改,以确保标题行(第 0 行)不被截断,并且将在每一列上分配多余的空间

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;

【讨论】:

【参考方案3】:

对 bummi 的回答稍作修改,以确保标题行(第 0 行)不被截断

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;

【讨论】:

您好,我是 delphi 的新手,想请教您,详细解释一下它是如何工作的。什么是变量,如 i、w 和 a good for 等。我会很感激的。【参考方案4】:

对 bummi、TheSteven 和 Jens 的回答进行了细微修改,以确保标题行(第 0 行)不会被截断,并且将在每列上分配多余的空间,并考虑列的可见性 .

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;

【讨论】:

【参考方案5】:

我在 TDBGrid 的属性中找到了“列”,并打开了新窗口。在该窗口中,我添加了新的 FieldNames - 您只能从 TADOQuery 的 SQL 字符串的结果中选择 columnNames,然后当您单击确切的列时,您可以在所选列的属性中找到“宽度”,因此可以随意更改它.它对我有用。

【讨论】:

【参考方案6】:

恐怕最后的代码改编不正确。

我宁愿写这样的东西:

 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);

【讨论】:

以上是关于调整列宽 DBGrid的主要内容,如果未能解决你的问题,请参考以下文章

excel小技巧之快速调整行高列宽 如何快速调整行高列宽

怎样根据内容自动调整excel表格的行高列宽?

qt中QTableWidget怎么根据内容自动调整列宽行高?

C# iTextSharp 自动调整列宽

C# ListView 列宽自动调整

PHPExcel自动调整列宽