2013-07-07 99 views
5

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

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

+4

每列的宽度默认调整为相应字段的声明大小。如果这与现实不符,则应重新考虑数据库设计。 –

+0

@Uwe,对于字段的'0'字符的DisplayWidth计数是正确的,它的宽度为6px,每个字符都是Tahoma大小为8的字体(默认缩放)。如果您正在显示,我们假设有100个“W”字符(每个宽度为10px),默认列宽将比实际需要的窄400px(当DisplayWidth为100时)。所以也可能有相反的原因来自动调整宽度。 – TLama

回答

10

所需的Columnwidth取决于Grids画布的设置和每个字段的displaytext的最大长度。

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; 
+5

ZeroMemory不是必需的。 SetLength用零初始化所有新成员。 –

+0

好的解决方案。只是一个nit pick:在内部'if a [i] lurker

+0

对于大型数据集和大量数据集,当您的内容很长时,会出现杂散记录,这会花费很长时间。顺便说一句,“TDBGrid”首先没有这种功能,而且Windows Explorer在某些情况下也没有正确调整大小。 –

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; 
+0

嗨,我对delphi很新,我想问你,解释这是如何工作的细节。什么是像我这样的变量,w和一个好的等等。我会非常感激。 – user2886091

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

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;