[英]How to use checkboxes inside TDBGrid to select multiple records?
[英]How to internally process filtered tDataSet records not to be shown on tDBGrid the result
在下面的tFDMemTable中,我嘗試對ID字段以字母A開頭的記錄的值進行求和.A1,A2和結果應為4。
type
TForm1 = class(TForm)
FDMemTable1: TFDMemTable;
DBGrid1: TDBGrid;
DataSource1: TDataSource;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
_FieldDef: TFieldDef;
begin
_FieldDef := FDMemTable1.FieldDefs.AddFieldDef;
_FieldDef.Name := 'ID';
_FieldDef.DataType := ftString;
_FieldDef.Size := 5;
_FieldDef := FDMemTable1.FieldDefs.AddFieldDef;
_FieldDef.Name :='value';
_FieldDef.DataType := ftInteger;
FDMemTable1.CreateDataSet;
FDMemTable1.Append;
FDMemTable1.FieldValues['ID'] := 'A1';
FDMemTable1.FieldValues['value'] := 1;
FDMemTable1.Append;
FDMemTable1.FieldValues['ID'] := 'B1';
FDMemTable1.FieldValues['value'] := 2;
FDMemTable1.Append;
FDMemTable1.FieldValues['ID'] := 'A2';
FDMemTable1.FieldValues['value'] := 3;
FDMemTable1.Append;
FDMemTable1.FieldValues['ID'] := 'B2';
FDMemTable1.FieldValues['value'] := 4;
end;
我編寫了以下代碼,但它將tDBGrid更改為已過濾。 我想要的只是一個內部過程,tDBGrid應該保持不變。
procedure TForm1.Button1Click(Sender: TObject);
var
_ValueSum: Integer;
i: Integer;
begin
FDMemTable1.Filter := 'ID like ' + QuotedStr('A%');
FDMemTable1.Filtered := True;
_ValueSum := 0;
FDMemTable1.FindFirst;
for i := 0 to FDMemTable1.RecordCount - 1 do
begin
_ValueSum := _ValueSum + FDMemTable1.FieldValues['value'];
FDMemTable1.FindNext;
end;
Button1.Caption := IntToStr(_ValueSum);
end;
我知道tDataSet.Locate不允許NEXT SEARCH,我嘗試了這樣的原始方式。 它工作正常,但似乎有點愚蠢。
procedure TForm1.Button2Click(Sender: TObject);
var
_ValueSum: Integer;
i: Integer;
begin
_ValueSum := 0;
FDMemTable1.First;
for i := 0 to FDMemTable1.RecordCount do
begin
if Copy(FDMemTable1.FieldValues['ID'], 1, 1) = 'A' then
begin
_ValueSum := _ValueSum + FDMemTable1.FieldValues['value'];
end;
FDMemTable1.FindNext;
end;
Button2.Caption := IntToStr(_ValueSum);
end;
當我在過濾之前斷開tFDMemTable和tDBGrid或設置非活動以保持最后一個網格狀態時,網格將變為空白狀態。 最后一個代碼是最好的解決方案還是有更好的方法,在過濾工作時顯示未過濾的結果?
有幾件事,如果不是“錯誤的”,對你的代碼來說是不對的。
您應該使用Next
而不是FindNext
移動到數據集中的下一行。 Next
移動到數據集中的下一行,而FindNext
移動到下一行,該行匹配您已經設置的搜索條件,例如使用DataSet.SetKey; ...
DataSet.SetKey; ...
- 閱讀FindKey
用法的在線幫助。
您不應該嘗試使用For
循環遍歷數據集; 使用While not FDMemData.Eof do
循環。 Eof
代表“文件結束”,一旦數據集位於其最后一行,則返回true。
你應該調用FDMemTable1.DisableControls
循環之前和FDMemTable1.EnableControls
之后。 這可以防止像DBGrid這樣的db-aware控件在循環內更新,否則會在網格更新時減慢循環速度。
除非你有充分的理由不這樣做,否則總是按照你設置的方法清除數據集過濾器,否則如果忘記過濾器處於活動狀態,你可能會遇到一些非常令人困惑的錯誤。
當你不是絕對需要時盡量避免使用RecordCount
。 根據您使用的RDMS,它可能會在服務器和網絡上產生大量可避免的處理開銷(因為某些服務器類型會導致整個數據集被檢索到客戶端)。
將您的第一個循環更改為
procedure TForm1.Button1Click(Sender: TObject);
var
_ValueSum : Integer;
begin
_ValueSum := 0;
FDMemTable1.Filter := 'ID like ' + QuotedStr('A%');
try
FDMemTable1.DisableControls;
FDMemTable1.First;
while not FDMemTable1.Eof do begin
_ValueSum:= _ValueSum + FDMemTable1.FieldByName('Value').AsInteger;
FDMemTable1.Next;
end
finally
FDMemTable1.Filter := '';
FDMemTable1.Filtered := False;
FDMemTable1.EnableControls;
end;
Button1.Caption := IntToStr(_ValueSum);
end;
如果你這樣做,根本不需要你的Button2Click方法。
如評論中所述,您可以使用TBookMark在循環之前在數據集中記錄您的位置,然后返回到它,如
var
_ValueSum : Integer;
BM : TBookMark;
begin
_ValueSum := 0;
BM := FDMemTable.GetBookMark;
FDMemTable1.Filter := 'ID like ' + QuotedStr('A%');
try
[etc]
finally
FDMemTable1.Filter := '';
FDMemTable1.Filtered := False;
FDMemTable1.GotoBookMark(BM);
FDMemTable1.FeeBookMark(BM);
FDMemTable1.EnableControls;
end;
順便說一句,您可以使用InsertRecord
方法保存自己的一些輸入並獲得更簡潔的代碼
FDMemTable1.InsertRecord(['A1', 1]);
FDMemTable1.InsertRecord(['B1', 2]);
FDMemTable1.InsertRecord(['A2', 3]);
FDMemTable1.InsertRecord(['B2', 4]);
順便說一下#2:使用FindKey
的時間是在你設置了一個要查找的密鑰之后,通過調用SetKey
不是設置密鑰值。
對於數據集的普通導航,請使用標准導航方法,例如Next
, Prior
, First
, Last
, MoveBy
等。
FireDAC還有另一個有趣的選擇 - 聚合:
procedure TForm1.Button1Click(Sender: TObject);
begin
FDMemTable1.Aggregates.Clear;
with FDMemTable1.Aggregates.Add do
begin
Name := 'SUM';
Expression := 'sum(iif(ID like ''A%'', value, 0))';
Active := True;
end;
FDMemTable1.AggregatesActive := True;
FDMemTable1.Refresh;
Button1.Caption := VarToStr(FDMemTable1.Aggregates[0].Value));
end;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.