簡體   English   中英

Delphi:如何查找和格式化DBGrid字段

[英]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事件中的查詢:查找與上面類似的給定字段名稱,如果找到,則:

  1. 保存結果以備后用(由於FieldByName內部的線性字符串搜索本身並不是最有效的操作,因此不應在顯示的每個值上都重復此操作)
    • 正確但有些乏味的方法是為查詢所有者創建新的TTimeField屬性。
    • 在Win32下,您可以(ab)使用Int32屬性TDataSet.Tag ,通過類型轉換將指針存儲在那里。 那是脆弱,不安全且不可移植的代碼,但是將IntegerpointerTObject值存儲在任何這些變量中都是“舊的Delphi風格” (例如TStringList.Objects),並且如果您小心翼翼並且只對Win32感興趣,那么它就可以工作。
  2. 添加日期時間類型的計算字段
  3. 'hh:nn:ss'設置為該新字段的格式: http//docwiki.embarcadero.com/Libraries/XE2/en/Data.DB.TDateTimeField.DisplayFormat
  4. 使新字段對DBGrid和其他數據庫感知控件友好
  5. 使原始字段不可見或從網格中刪除其列-您將擁有新字段。

然后在查詢上設置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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM