TJvCsvDataSet 和过滤器
TJvCsvDataSet and filter
我在过滤上传到 TJvCsvDataSet 中的 .csv 文件时遇到问题。
下面是MCVE的解释
program Project3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
JvCsvData,
data.DB;
var
FJvCsvDataSet: TJvCsvDataSet;
I:Integer;
begin
;
FJvCsvDataSet := TJvCsvDataSet.Create(nil);
FJvCsvDataSet.CsvFieldDef :=
'VTHB:%,VTHS:%,VTHBBP:&,VTBBSP:&,VTHBLP:&,VTHBLS:&,VTHTS:@';
FJvCsvDataSet.FieldDefs.Add('VTHB', ftInteger, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHS', ftInteger, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHBBP', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTBBSP', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHBLP', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHBLS', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHTS', ftDateTime, 0, False);
FJvCsvDataSet.FileName :=
'E:\...\abc.csv';
FJvCsvDataSet.Open;
FJvCsvDataSet.First;
// FJvCsvDataSet.Sort('VTHB,VTHBBP', True);
FJvCsvDataSet.Filtered := False;
FJvCsvDataSet.Filter := '';
for I := 1 to 1093 do
begin
FJvCsvDataSet.Filter:='VTHB=' + IntToStr(I);
FJvCsvDataSet.Filtered := True;
end;
FJvCsvDataSet.Free;
end.
下面是FJvCsvDataSet
上传的abc.csv样本
VTHB,VTHS,VTHBBP,VTBBSP,VTHBLP,VTHBLS,VTHTS
1,1,3.05,279.86,3.1,115.98,2019-08-10 14:28:47.505
1,2,3.9,259.65,3.95,237.73,2019-08-10 14:28:47.52
1,3,3.9,136.48,3.95,31.97,2019-08-10 14:28:47.52
1,5,10.5,68.83,11,52.03,2019-08-10 14:28:47.52
1,4,12.5,41.4,13,47.75,2019-08-10 14:28:47.52
2,1,3.05,279.86,3.1,115.98,2019-08-10 14:28:47.863
2,2,3.9,259.65,3.95,237.73,2019-08-10 14:28:47.863
2,3,3.9,136.48,3.95,31.97,2019-08-10 14:28:47.863
2,5,10.5,68.83,11,52.03,2019-08-10 14:28:47.863
2,4,12.5,41.4,13,47.75,2019-08-10 14:28:47.863
当执行语句FJvCsvDataSet.Filter:='VTHB=' + IntToStr(I);
时FJvCsvDataSet.RecordCount
没有改变因此不执行过滤
我做错了什么?
我不认为你在做什么"wrong",似乎 TJvCsvDataSet 以一种相当奇怪的方式实现过滤。
使用您的代码设置和打开数据集,以下代码工作正常并生成预期的记录(在您代码的 VCL 版本的 DBGrid 中观察到):
FJvCsvDataSet.SetFilterNum('VTHB', jfIntEqual, 1);
FJvCsvDataSet.Filtered := True;
这会导致 FJvCsvDataSet.RecordCount 为 5,这是应该的。这种过滤方式使用以下枚举作为 SetFilterNum 的第二个参数:
TJvCsvFilterNumCompare = (jfIntEqual, jfIntNotEqual, jfLessThan, jfGreaterThan);
但是,改为这样做
FJvCsvDataSet.Filter:= 'VTHB=1';
产生不正确的结果,即没有记录被过滤掉并且 RecordCount 为 10。显然出了问题,我稍后会回来告诉我是否找到它是什么。
更新 我进一步研究了一下,确实有些东西
奇怪的事情发生了。
正在做
FJvCsvDataSet.Filter:= 'VTHB = 1';
FJvCsvDataSet.Filtered := True;
没有任何影响,数据集甚至不扫描记录以查看它们是否
匹配过滤器。 OTOH 这样做
FJvCsvDataSet.SetFilter('VTHB', '1');
FJvCsvDataSet.Filtered := True;
会导致行开始扫描,通过 SetFilter 方法
// string Filtering: Make Rows Visible Only if they match filterString
procedure TJvCustomCsvDataSet.SetFilter(const FieldName: string; Pattern: string);
并且这些行是否正确标记为已过滤取决于它们是否与过滤器匹配。
然而,至少有两件奇怪的事:
所有的记录,无论匹配与否,仍然以网格显示。我认为这
意味着问题出在其他地方,可能与 InternalSkipFiltered 方法有关,
但是 FJvCsvDataSet.SetFilterNum('VTHB', jfIntEqual, 1)
怎么会起作用呢?
需要进一步探索。
应用过滤器后在数据集上调用关闭和打开不会导致
正在重新扫描的行,从逻辑上讲应该如此,但是我们不调用 SetFilter
第二次,所以这大概是 WAD。但这是一个奇怪的设计,因为
SeFilter
首先不应该公开访问,它应该由 setter 为 Filter
属性 调用,imo.
更新 #2 好吧,我们不能说我们没有收到警告
https://wiki.delphi-jedi.org/wiki/JVCL_Help:TJvCustomCsvDataSet.SetFilter
说
Note that this feature is NOT API-compatible with or similar to the filtering feature that is normally found in VCL TTable component.
前面的描述是根据将字段过滤为字符数据来表达的,所以我想知道它是否曾经打算处理 ftInteger 字段....
我在过滤上传到 TJvCsvDataSet 中的 .csv 文件时遇到问题。 下面是MCVE的解释
program Project3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
JvCsvData,
data.DB;
var
FJvCsvDataSet: TJvCsvDataSet;
I:Integer;
begin
;
FJvCsvDataSet := TJvCsvDataSet.Create(nil);
FJvCsvDataSet.CsvFieldDef :=
'VTHB:%,VTHS:%,VTHBBP:&,VTBBSP:&,VTHBLP:&,VTHBLS:&,VTHTS:@';
FJvCsvDataSet.FieldDefs.Add('VTHB', ftInteger, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHS', ftInteger, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHBBP', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTBBSP', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHBLP', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHBLS', ftFloat, 0, False);
FJvCsvDataSet.FieldDefs.Add('VTHTS', ftDateTime, 0, False);
FJvCsvDataSet.FileName :=
'E:\...\abc.csv';
FJvCsvDataSet.Open;
FJvCsvDataSet.First;
// FJvCsvDataSet.Sort('VTHB,VTHBBP', True);
FJvCsvDataSet.Filtered := False;
FJvCsvDataSet.Filter := '';
for I := 1 to 1093 do
begin
FJvCsvDataSet.Filter:='VTHB=' + IntToStr(I);
FJvCsvDataSet.Filtered := True;
end;
FJvCsvDataSet.Free;
end.
下面是FJvCsvDataSet
上传的abc.csv样本VTHB,VTHS,VTHBBP,VTBBSP,VTHBLP,VTHBLS,VTHTS
1,1,3.05,279.86,3.1,115.98,2019-08-10 14:28:47.505
1,2,3.9,259.65,3.95,237.73,2019-08-10 14:28:47.52
1,3,3.9,136.48,3.95,31.97,2019-08-10 14:28:47.52
1,5,10.5,68.83,11,52.03,2019-08-10 14:28:47.52
1,4,12.5,41.4,13,47.75,2019-08-10 14:28:47.52
2,1,3.05,279.86,3.1,115.98,2019-08-10 14:28:47.863
2,2,3.9,259.65,3.95,237.73,2019-08-10 14:28:47.863
2,3,3.9,136.48,3.95,31.97,2019-08-10 14:28:47.863
2,5,10.5,68.83,11,52.03,2019-08-10 14:28:47.863
2,4,12.5,41.4,13,47.75,2019-08-10 14:28:47.863
当执行语句FJvCsvDataSet.Filter:='VTHB=' + IntToStr(I);
时FJvCsvDataSet.RecordCount
没有改变因此不执行过滤
我做错了什么?
我不认为你在做什么"wrong",似乎 TJvCsvDataSet 以一种相当奇怪的方式实现过滤。
使用您的代码设置和打开数据集,以下代码工作正常并生成预期的记录(在您代码的 VCL 版本的 DBGrid 中观察到):
FJvCsvDataSet.SetFilterNum('VTHB', jfIntEqual, 1);
FJvCsvDataSet.Filtered := True;
这会导致 FJvCsvDataSet.RecordCount 为 5,这是应该的。这种过滤方式使用以下枚举作为 SetFilterNum 的第二个参数:
TJvCsvFilterNumCompare = (jfIntEqual, jfIntNotEqual, jfLessThan, jfGreaterThan);
但是,改为这样做
FJvCsvDataSet.Filter:= 'VTHB=1';
产生不正确的结果,即没有记录被过滤掉并且 RecordCount 为 10。显然出了问题,我稍后会回来告诉我是否找到它是什么。
更新 我进一步研究了一下,确实有些东西 奇怪的事情发生了。
正在做
FJvCsvDataSet.Filter:= 'VTHB = 1';
FJvCsvDataSet.Filtered := True;
没有任何影响,数据集甚至不扫描记录以查看它们是否 匹配过滤器。 OTOH 这样做
FJvCsvDataSet.SetFilter('VTHB', '1');
FJvCsvDataSet.Filtered := True;
会导致行开始扫描,通过 SetFilter 方法
// string Filtering: Make Rows Visible Only if they match filterString
procedure TJvCustomCsvDataSet.SetFilter(const FieldName: string; Pattern: string);
并且这些行是否正确标记为已过滤取决于它们是否与过滤器匹配。 然而,至少有两件奇怪的事:
所有的记录,无论匹配与否,仍然以网格显示。我认为这 意味着问题出在其他地方,可能与 InternalSkipFiltered 方法有关, 但是
FJvCsvDataSet.SetFilterNum('VTHB', jfIntEqual, 1)
怎么会起作用呢? 需要进一步探索。应用过滤器后在数据集上调用关闭和打开不会导致 正在重新扫描的行,从逻辑上讲应该如此,但是我们不调用 SetFilter 第二次,所以这大概是 WAD。但这是一个奇怪的设计,因为
SeFilter
首先不应该公开访问,它应该由 setter 为Filter
属性 调用,imo.
更新 #2 好吧,我们不能说我们没有收到警告
https://wiki.delphi-jedi.org/wiki/JVCL_Help:TJvCustomCsvDataSet.SetFilter
说
Note that this feature is NOT API-compatible with or similar to the filtering feature that is normally found in VCL TTable component.
前面的描述是根据将字段过滤为字符数据来表达的,所以我想知道它是否曾经打算处理 ftInteger 字段....