Delphi TJVCSV数据集和过滤器
在筛选TJvCsvDataSet中上载的.csv文件时,我遇到了一个问题。 以下是要解释的MCVEDelphi TJVCSV数据集和过滤器,delphi,jedi,Delphi,Jedi,在筛选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
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
不会更改,因此不会执行筛选
我做错了什么?我不认为您做错了什么,只是TJvCsvDataSet以一种非常奇怪的方式实现了过滤
使用您的代码设置和打开数据集,以下代码工作正常,并生成预期的记录(在VCL版本代码的DBGrid中观察到):
这将导致FJvCsvDataSet.RecordCount按其应有的值为5。这种过滤方式使用以下枚举作为SetFilterNum的第二个参数:
TJvCsvFilterNumCompare = (jfIntEqual, jfIntNotEqual, jfLessThan, jfGreaterThan);
但是,这样做,
FJvCsvDataSet.Filter:= 'VTHB=1';
产生不正确的结果,即未筛选出任何记录,且记录计数为10。显然出了点问题,如果我发现了问题所在,我稍后会回来说
更新我对它进行了更深入的研究,确实有些东西
奇怪的事情正在发生
正在做
FJvCsvDataSet.Filter:= 'VTHB = 1';
FJvCsvDataSet.Filtered := True;
没有任何影响,数据集甚至不扫描记录以查看它们是否正确
匹配过滤器。奥托这样做
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);
行是否正确标记为已过滤取决于它们是否匹配过滤器。
然而,至少有两件奇怪的事情:
- 所有记录,无论是否匹配,仍由网格显示。我觉得这个
意味着问题可能存在于其他地方,可能是内部SkipFiltered方法,
但是,为什么要使用
FJvCsvDataSet.SetFilterNum('VTHB',jfIntEqual,1)
呢?
需要进一步探索
- 应用筛选器后对数据集调用Close和Open不会导致
按逻辑应该重新扫描的行,但是我们不调用SetFilter
第二次,所以这大概是瓦德。但这是一个stange设计,因为
SeFilter
首先不应该公开访问,它应该由Filter
属性的setter调用,imo
更新#2好吧,我们不能说没有得到警告
说
请注意,此功能与通常在VCL TTable组件中找到的过滤功能不兼容或类似
前面的描述是用过滤字段作为字符数据来表达的,所以我想知道它是否打算处理ftInteger字段……在我看来,TJvCsvDataSet
应该扩展TClientDataSet
。实施起来会简单得多。相反,他们选择重新发明轮子,他们的过滤功能不是标准的。@Olivier:是的,我完全同意。从资料来源来看,作者显然有一些特定的想法,他们正试图做,从过滤的角度来看,但对我来说,这仍然是一个谜。
// string Filtering: Make Rows Visible Only if they match filterString
procedure TJvCustomCsvDataSet.SetFilter(const FieldName: string; Pattern: string);