我使用DBGrid和Delphi XE2来显示一些查询结果。 在结果中,一些(整数)字段表示我想以某种格式显示的持续时间(以秒为单位),例如“hh:mm:ss” 我事先并不知道字段顺序,因为查询可能不同但我知道要格式化的字段名称。 最有效的方法是什么?
答案 0 :(得分:3)
虽然@AndreaBoc的答案是正确的(但只回答了你的一个问题),但它有些重复:复制粘贴相同的计算看起来对我来说是一种反模式。
使用http://docwiki.embarcadero.com/Libraries/XE4/en/System.Math.DivMod
可能会删除重复性procedure TForm1.PrettyPrintSeconds(Sender: TField;
var Text: string; DisplayText: Boolean);
var
hh,mm,ss: Word;
begin
DivMod( Sender.AsInteger, 3600, hh, mm );
DivMod( mm, 60, mm, ss );
Text := Format('%.2d:%.2d:%.2d',[hh,mm,ss]);
end;
此外,如果你真的想要高效(但为什么要使用TDataset
?)你可以用3个临时字符串变量和旧式{替换太灵活的格式函数{1}} http://docwiki.embarcadero.com/Libraries/XE4/en/System.SysUtils.IntToStr概述的程序: - )
应为http://docwiki.embarcadero.com/Libraries/XE2/en/Data.DB.TField.OnGetText
设置这比复制粘贴相同的操作要好两倍甚至更多,增加了CPU时间和制造愚蠢错字的机会。
然后还有下一部分问题:不知道字段顺序...但我知道要格式化的字段名称。这意味着您应该在查询打开后调整此字段:
Str
从procedure TDataModule1.Query1AfterOpen(DataSet: TDataSet);
var F: TField;
begin
F := DataSet.FindField('MY-Name-For-Time');
if F = nil
then (* .... no such field - do something about it .... *)
else F.OnGetText := TForm1.PrettyPrintSeconds;
end;
事件中,您可以类似地删除(设置为BeforeClose
)此事件处理程序。只是为了那个罕见的检查,以后相同的TField对象被重新用于不同的目的。除了一些非常奇特的情况,它不应该发生,而只是为了“自我清理”。
效果较差(从CPU的角度来看),但精神方法中的VCL也更多。
对于nil
事件中的查询:查找上面给定的字段名称,如果找到则:
AfterOpen
内的线性字符串搜索本身并不是最有效的操作,所以不应该为每个显示的值重复它)
FieldByName
属性。TTimeField
属性Int32
,通过type-cast存储指针。这是脆弱,不安全和不可移植的代码,但在任何这些变量中存储TDataSet.Tag
,Integer
和pointer
值都是“旧的Delphi样式”(就像在TStringList.Objects中一样) )如果你小心并且只对Win32感兴趣,它就可以工作。TObject
设置为该新字段的格式:http://docwiki.embarcadero.com/Libraries/XE2/en/Data.DB.TDateTimeField.DisplayFormat 然后在查询上设置'hh:nn:ss'
,如:
OnCalcFields
然后,您就可以在Delphi例程期望// 1. Delphi TDateTime is double and 1 day equals to 1.0
// 2. Multiplication is more efficient than division - do it by pen and paper and see
procedure TDataModule1.Query1AfterOpen(DataSet: TDataSet);
const coeff = 1.0 / ( 24 * 60 * 60 );
begin
MyCalcField.AsTime := MySourceField.AsInteger * coeff;
end;
值的每个地方使用新的虚拟字段。
答案 1 :(得分:1)
您可以使用该字段的OnGetText事件请求:
procedure TForm1.Table1secondsGetText(Sender: TField;
var Text: string; DisplayText: Boolean);
var
seconds,hh,mm,ss:Integer;
begin
seconds := Sender.AsInteger;
hh := seconds div 3600;
mm := (seconds - (hh * 3600)) div 60;
ss := (seconds - (hh * 3600) - (mm * 60));
Text := Format('%.2d:%.2d:%.2d',[hh,mm,ss]);
end;
例如185秒将以这种方式显示:00:03:05