我正在加载一个数据集,然后从中过滤并提取一些聚合。我最初使用 CDS.Filter 属性来过滤数据集,并使用以下代码创建运行时聚合字段:
lAgg := TAggregateField.Create(cdDataOrRecord);
lAgg.FieldKind := TFieldKind.fkAggregate;
lAgg.Expression := IfThen(lColumns[loop].Values['total'] = 'T', 'SUM', 'AVG') + '(' + lColumns[loop].Values['data'] + ')';
lAgg.FieldName := lColumns[loop].Values['data'] + IfThen(lColumns[loop].Values['total'] = 'T', 'Total', 'Average');
lAgg.Active := True;
lAgg.DisplayFormat := '########0' + IfThen(lColumns[loop].Values['total'] = 'A', '.##');
lAgg.GroupingLevel := 0;
lAgg.DataSet := cdDataOrRecord;
这工作得很好。但是,最近我不得不停止使用 CDS.Filter 并改用 .OnFilterRecords,因为对于更简单的版本,过滤器变得太复杂了。不久之后,我们注意到我们的总数和平均值现在是错误的,最终发现它聚合了 CDS 的前 X 行,其中 X 是过滤结果的数量。因此,如果我从数据库中提取 50 并且过滤器产生 5 条记录,那么即使实际结果集中没有出现前 5 行,也会在聚合中使用前 5 行。
我尝试使用以下代码交换聚合值而不是聚合字段:
with cdDataOrRecord.Aggregates.Add do
begin
DisplayName := lColumns[loop].Values['data'] + IfThen(lColumns[loop].Values['total'] = 'T', 'Total', 'Average');
Expression := IfThen(lColumns[loop].Values['total'] = 'T', 'SUM', 'AVG') + '(' + lColumns[loop].Values['data'] + ')';
Active := True;
end;
lColumns[loop].Values['AggregateIndex'] := IntToStr(cdDataOrRecord.Aggregates.Count - 1);
这会导致得到正确的总和和平均值,但也存在其自身的问题。聚合值似乎不支持 DisplayFormat 属性,所以我需要格式化我得到的值而不是依赖 .DisplayText,而且您似乎只能通过索引来引用聚合值,这也很令人沮丧?我注意到 CDS.Aggregates 有一个 .Find 函数,它似乎需要一个 DisplayName: String 参数,但是当我尝试使用它来通过我添加的 DisplayName 引用聚合时,我只是遇到了访问冲突。
这是聚合字段的已知问题吗?还是我的实现有问题?
谢谢你的帮助。