2

假设我有这张桌子:

name        varchar(255),
quantity    integer,
value       float

当我使用此代码时:

select left(name, 99), quantity, value from table;

但是dbgrid除非我使用滚动条而且我的目标是制作滚动条没有必要。

我如何正确地实现这个目标?我使用火鸟和 MySQL。

我不能通过 pascal 代码执行此操作,也不能在表组件的 Fields 对象上定义它,因为此代码来自许多表,因为这是一个报告生成器,第一个字段并不总是相同,对于每个报告我必须使用不同的 SQL 代码。

在此处输入图像描述

请大家在回答之前阅读所有问题。前 3 个答案哪里错了,因为他们没有考虑最后一段中写的内容!

4

4 回答 4

4

由于您已经说过您不能在TField级别或 Delphi 代码中执行此操作,因此您可以使用Trim()or Left(),具体取决于您使用的数据库,在列上删除您不想显示的空格:

例如,在许多 SQL 方言中,您可以使用如下内容:

SELECT Col1, Col2, Trim(Col3) as Col3 FROM yourtable 
WHERE somecondition

有些人允许这样做:

SELECT Col1, Col2, Left(Col3, MaxCharWidthAllowed) as Col3 FROM yourtable 
WHERE somecondition

或者

SELECT Col1, Col2, Substring(Col3, 1, MaxCharWidth) as Col3 FROM yourtable

作为快速测试(我没有FB,但是有SQL Server 2008,所以我用了),我在SQL Server Management Studio中创建了如下测试数据:

SSMS 中的测试数据

然后我创建了一个新的 D2007 VCL Forms 应用程序,并执行了以下步骤:

  • TADOConnection在表单 ( ) 上删除了一个ADOConnection1,并将连接字符串设置为上面的测试数据
  • 将两个TADOQuery组件放在表单 (ADOQuery1ADOQuery2) 上,并将它们的Connection属性设置为ADOConnection1
  • TDataSource在表单 (DataSource1DataSource2)上删除了两个组件并将它们的DataSet属性连接到匹配的ADOQuery1ADOQuery2
  • 删除了两个TDBGrid组件 ( DBGrid1and DBGrid2) 并将它们的DataSource属性设置为匹配的DataSource1and DataSource2
  • 添加SELECT * FROM test到 SQL 中ADOQuery1
  • 添加SELECT Substring(itemname, 1, 30) as itemname, quantity, value FROM testSQLADOQuery2。的长度30被任意选择为足够小的值,以证明列宽相当小。
  • 设置ADOConnection1.ConnectedTrue,并将两个TADOQuery.Active属性都设置为True

上面产生了这个输出(在设计时,没有编译或运行应用程序),顶部网格是DBGrid1

上述步骤的设计时输出

如您所见,in与SQL 中的DBGrid2相连,第一列的大小正确设置为 30 个字符宽度。ADOQuery2Substring

于 2013-01-24T12:16:33.923 回答
3

如果列类型是真的varchar(255)而不是char(255),那么值的末尾不应该有任何空格,除非你自己保存了空格。IOW 这些varchar(255)值将完全按照您将它们保存到表中的方式返回给您,无论char(255)值是否正确填充空格,以便您始终获得 255 个字符的字符串。

因此,我会说,如果您使用varchartype 并且在将值保存到 DB 时没有用空格填充值,那么问题实际上出在网格中,您无法trim()在 SQL 中使用 simg 或等效项来解决它。网格很可能会读取字段的定义,看到该值的最大长度为 255 个字符,并相应地设置列宽。所以解决方案实际上是手动设置列宽或使用列的ApplyBestFit方法(如果有的话)。

于 2013-01-24T13:44:24.180 回答
1

有两种方法可以限制在 DBGrid 中显示的字段的长度,它们不会改变数据库中的数据。一种是设置字段的 DisplayWidth,另一种是设置网格列的 Width。

您可以在查询的 After open 事件中设置 DisplayWidth。该示例适用于 ZeosLib,并假定第一个字段是要限制的字段。这需要添加到每个查询中。

procedure TForm1.ZQuery1AfterOpen(DataSet: TDataSet);
begin
  DataSet.Fields[0].DisplayWidth := 99;
end;

或在打开查询后使用过程设置 DBGrid 列宽。此示例允许您指定列和宽度。

procedure TForm1.SetColWidth(c,w: integer);
begin
  if DBGrid1.Columns.Count > c then
    DBGrid1.Columns[c].Width := w;
end;
于 2013-01-25T07:00:30.357 回答
1

更新:

Delphi 将varchar 字段的长度作为 Displaylength 的默认varchar(255) = 显示长度 = 255。

我可以用“SQL”改变这种行为吗?NO 如果结果只有 99 个字符长,则长度 varchar (255) = 255 和 Displaylength = 255 。

比较一下!
允许:

select left(name,99), quantity, value from table;
  • Sql 应该快速交付数据集(而不是报表的设计)。
  • 对于每个 varchar 字段的每个表,您必须设置一个额外的 SQL 语句(xname,99)
  • 我可以看到截断的(也许很重要的)信息吗?绝不。

不允许:

Columns[index].Width = 99;
  • 更容易设计报告。
  • 更简单的选择 SQL 语句:select name, quantity, value from table
  • 用鼠标简单展开列以查看隐藏信息。
  • 良好的设计:DBGrid 的列大小应该是您一次可以看到至少 2 列。

程序应该接管设计。

我不能通过 pascal 代码执行此操作,也不能在表组件的 Fields 对象上定义它,因为此代码来自许多表,因为这是一个报告生成器。

对于每个报告,我必须使用不同的 SQL 代码。

谁生成了这个“不同的 SQL 代码”?
我认为类似的行用于生成代码(Pascal 代码)。

允许:帕斯卡码

   Query1.Close;
   Query1.SQL.Clear;
   Query1.SQL.Add ('select name, quantity, value from table');
   Query1.Active: = true;

为什么不允许:帕斯卡代码

   Columns[index].Width := 99;

您可以通过自动调整列来做到这一点。所有宽一定尺寸的列都将适应它们的实际宽度。这仍然比固定大小 = 99 好。

以下程序已使用 Rad Studio 2007 和 Zeos Components 进行了测试。
Firebird 2.5,在 Windows 2000 计算机上。

  • A) Zeos 组件。
  • B) DBGrid1 没有活动的数据连接。
  • C) Firebird 自动为 varchar (255) 分配大小。
  • D) 正在运行的程序。“使用我”用于自动调整列的大小。

由于时间不够,我只创建了 2 个数据字段。

在此处输入图像描述

如果需要下载整个源代码,请告诉我。

unit FBAuto;
{
~Zarko Gajic
About Delphi Programing
http://delphi.about.com
customized 2013
moskito-x software
}

interface

uses
  Math,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, DBTables, Grids, DBGrids, ExtCtrls, StdCtrls, ZAbstractRODataset,
  ZAbstractDataset, ZDataset, ZConnection;

type
  TAutoColumnWidth = record
    Index : integer;
    Width : integer;
  end;

  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    DataSource1: TDataSource;
    CBuseMe: TCheckBox;
    DBGrid2: TDBGrid;
    ZQuery2: TZQuery;
    DataSource2: TDataSource;
    IntegerField1: TIntegerField;
    StringField1: TStringField;
    procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure CBuseMeClick(Sender: TObject);
  private
    { Private declarations }
    procedure SetFit;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  AutoColumnWidth : TAutoColumnWidth;
  useMe :Boolean;

procedure TForm1.SetFit;
var
  i:integer;
begin
  if NOT CBuseMe.Checked then begin
  for i := 0 to DBGrid1.Columns.Count - 1 do begin
     if DBGrid1.Columns[i].Field.Size > 300 then
        DBGrid1.Columns[i].Width := DBGrid1.Columns[i].Field.Size;
  end;
  end else begin
  useMe:=true;
  for i := 0 to DBGrid1.Columns.Count - 1 do begin
  AutoColumnWidth.Index:=-1;
  if DBGrid1.Columns[i].Field.DisplayWidth > 200 then  AutoColumnWidth.Index:=i;
     if AutoColumnWidth.Index > -1 then begin
        AutoColumnWidth.Width := -1;
        DBGrid1.Repaint;
        DBGrid1.Columns[AutoColumnWidth.Index].Width := AutoColumnWidth.Width+ 5;
     end;
  end;
  useMe:=false;
  end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
ZQuery1.Active:=true;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  AutoColumnWidth.Index := -1;
  AutoColumnWidth.Width := -1;
  useMe:=false;
end;

procedure TForm1.CBuseMeClick(Sender: TObject);
begin
  setFit;
end;

procedure TForm1.DBGrid1DrawColumnCell(
  Sender: TObject;
  const Rect: TRect;
  DataCol: Integer;
  Column: TColumn;
  State: TGridDrawState);
begin
  if useMe then begin
   if DataCol = AutoColumnWidth.Index then
   begin
    if Assigned(Column.Field) then
    begin
      AutoColumnWidth.Width := Max(AutoColumnWidth.Width, DBGrid1.Canvas.TextWidth(Column.Field.DisplayText));
    end;
   end;
  end;
end;

end.

> 200可以设置以适应您的需要。

if DBGrid1.Columns[i].Field.DisplayWidth > 200 then  AutoColumnWidth.Index:=i;

我希望这会有所帮助,或者可能会导致正确的方向。

于 2013-01-29T05:16:08.243 回答