TDataset.Locate 在所有领域
TDataset.Locate in all field
假设我们有一个包含 5 个字段的数据集,显示在 DBGrid 中。
用户想要在网格中的任意位置定位文本。
如果我想搜索所有字段或者我必须实现自定义代码来实现此目的,有什么方法可以使用 TDataset.Locate() 方法吗?
简短的回答是您需要一些自定义代码,因为当您使用多个字段调用 Locate 时,您必须传递一个变体数组,其中包含您要在相应字段中匹配的值。虽然您可以指定匹配可以基于部分键(字段)值,但要匹配的模式不能跨越多个字段。
幸运的是,有一个简单的方法可以达到你想要的结果,如下所示:
将FieldKind fkInternalCalc的计算字符串字段添加到数据集,我们称之为AllFields。
在数据集的 OnCalcFields 中,将 AllField 的值设置为数据集所有其他字段的 AsString 值的串联;
针对 AllFields 字段调用 Locate,代码如下
if MyDataSet.Locate('AllFields', AValue, [loPartialKey]) then;
这就是你所需要的。
例子
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
MyDataSet: TClientDataSet;
DataSource1: TDataSource;
Button1: TButton;
DBNavigator1: TDBNavigator;
edSearch: TEdit;
procedure FormCreate(Sender: TObject);
procedure MyDataSetCalcFields(DataSet: TDataSet);
procedure edSearchChange(Sender: TObject);
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
var
AField : TField;
i : Integer;
begin
AField := TIntegerField.Create(Self);
AField.FieldName := 'ID';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldA';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldB';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldC';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldD';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'AllFields';
AField.Size := 255; // increase if necessary
AField.FieldKind := fkInternalCalc; // not fkCalculated
AField.DataSet := MyDataSet;
MyDataSet.CreateDataSet;
for i := 1 to 100 do begin
MyDataSet.InsertRecord([i, 'value'+ IntToStr(i), 'value'+ IntToStr(i), 'value'+ IntToStr(i), 'value'+ IntToStr(i)]);
end;
end;
procedure TForm1.MyDataSetCalcFields(DataSet: TDataSet);
var
S : String;
i : Integer;
begin
S := '';
for i := 0 to DataSet.FieldCount - 2 do // the 2 is to stop the loop before the AllFields filed
S := S + DataSet.Fields[i].AsString;
DataSet.Fields[5].AsString := S; // AllField is field 5
end;
procedure TForm1.edSearchChange(Sender: TObject);
begin
if edSearch.Text <>'' then
MyDataSet.Locate('AllFields', edSearch.Text, [loPartialKey, loCaseInsensitive])
else
MyDataSet.First;
end;
注意:要使上述代码正常工作,MyDataSet 的数据集类型必须是
支持 fkInternalCalc 字段类型,例如 TClientDataSet。
假设我们有一个包含 5 个字段的数据集,显示在 DBGrid 中。
用户想要在网格中的任意位置定位文本。
如果我想搜索所有字段或者我必须实现自定义代码来实现此目的,有什么方法可以使用 TDataset.Locate() 方法吗?
简短的回答是您需要一些自定义代码,因为当您使用多个字段调用 Locate 时,您必须传递一个变体数组,其中包含您要在相应字段中匹配的值。虽然您可以指定匹配可以基于部分键(字段)值,但要匹配的模式不能跨越多个字段。
幸运的是,有一个简单的方法可以达到你想要的结果,如下所示:
将FieldKind fkInternalCalc的计算字符串字段添加到数据集,我们称之为AllFields。
在数据集的 OnCalcFields 中,将 AllField 的值设置为数据集所有其他字段的 AsString 值的串联;
针对 AllFields 字段调用 Locate,代码如下
if MyDataSet.Locate('AllFields', AValue, [loPartialKey]) then;
这就是你所需要的。
例子
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
MyDataSet: TClientDataSet;
DataSource1: TDataSource;
Button1: TButton;
DBNavigator1: TDBNavigator;
edSearch: TEdit;
procedure FormCreate(Sender: TObject);
procedure MyDataSetCalcFields(DataSet: TDataSet);
procedure edSearchChange(Sender: TObject);
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
var
AField : TField;
i : Integer;
begin
AField := TIntegerField.Create(Self);
AField.FieldName := 'ID';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldA';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldB';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldC';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'FieldD';
AField.DataSet := MyDataSet;
AField := TStringField.Create(Self);
AField.FieldName := 'AllFields';
AField.Size := 255; // increase if necessary
AField.FieldKind := fkInternalCalc; // not fkCalculated
AField.DataSet := MyDataSet;
MyDataSet.CreateDataSet;
for i := 1 to 100 do begin
MyDataSet.InsertRecord([i, 'value'+ IntToStr(i), 'value'+ IntToStr(i), 'value'+ IntToStr(i), 'value'+ IntToStr(i)]);
end;
end;
procedure TForm1.MyDataSetCalcFields(DataSet: TDataSet);
var
S : String;
i : Integer;
begin
S := '';
for i := 0 to DataSet.FieldCount - 2 do // the 2 is to stop the loop before the AllFields filed
S := S + DataSet.Fields[i].AsString;
DataSet.Fields[5].AsString := S; // AllField is field 5
end;
procedure TForm1.edSearchChange(Sender: TObject);
begin
if edSearch.Text <>'' then
MyDataSet.Locate('AllFields', edSearch.Text, [loPartialKey, loCaseInsensitive])
else
MyDataSet.First;
end;
注意:要使上述代码正常工作,MyDataSet 的数据集类型必须是 支持 fkInternalCalc 字段类型,例如 TClientDataSet。