[英]Delphi: how to find and format DBGrid field
我將DBGrid與Delphi XE2一起使用以顯示一些查詢結果。 結果中,某些(整數)字段表示以秒為單位的持續時間,我想以“ hh:mm:ss”之類的格式顯示該字段,由於查詢可能有所不同,所以我事先不知道字段順序,但我知道這些字段我要格式化的名稱。 最有效的方法是什么?
雖然@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個臨時字符串變量和老式的Str
過程(如http://docwiki.embarcadero.com/Libraries/XE4所述)來替換過於靈活的Format函數。 /en/System.SysUtils.IntToStr :-)
這應該設置為http://docwiki.embarcadero.com/Libraries/XE2/en/Data.DB.TField.OnGetText
這比復制粘貼相同的操作兩次或更多次好,這樣既增加了CPU時間,又增加了犯錯字的機會。
然后是問題的下一部分: 不知道字段順序...但是我知道我要格式化的字段名稱 。 這意味着您應該在查詢打開后調整此字段:
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
事件中,您可以類似地刪除(設置為nil
)此事件處理程序。 僅出於罕見的檢查,以后將同一TField對象重新用於不同目的。 除了一些非常特殊的情況外,它不應該發生,而只是“自己清潔”。
(從CPU的角度來看)效果較差,但在精神方法上也有更多的VCL。
對於其AfterOpen
事件中的查詢:查找與上面類似的給定字段名稱,如果找到,則:
FieldByName
內部的線性字符串搜索本身並不是最有效的操作,因此不應在顯示的每個值上都重復此操作)
TTimeField
屬性。 Int32
屬性TDataSet.Tag
,通過類型轉換將指針存儲在那里。 那是脆弱,不安全且不可移植的代碼,但是將Integer
, pointer
和TObject
值存儲在任何這些變量中都是“舊的Delphi風格” (例如TStringList.Objects),並且如果您小心翼翼並且只對Win32感興趣,那么它就可以工作。 'hh:nn:ss'
設置為該新字段的格式: http : //docwiki.embarcadero.com/Libraries/XE2/en/Data.DB.TDateTimeField.DisplayFormat 然后在查詢上設置OnCalcFields
,如下所示:
// 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;
然后,您將能夠在Delphi例程期望TDateTime
值的每個位置使用新的虛擬字段。
您可以為請求使用字段的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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.