Delphi数据展示进阶:用DBGridEh+FDQuery实现智能分组统计(含Footer定制技巧)
Delphi数据展示进阶用DBGridEhFDQuery实现智能分组统计含Footer定制技巧在数据处理与展示领域动态分组统计一直是开发者面临的挑战之一。对于使用Delphi进行数据库应用开发的工程师而言如何优雅地实现数据分组统计并展示在界面上直接影响着用户体验和系统专业性。本文将深入探讨如何利用DBGridEh组件结合FDQuery构建一个支持动态分组统计的解决方案并重点解决分组状态下Footer栏的定制难题。1. 基础环境搭建与组件配置在开始之前确保你已经安装了EhLib组件包这是使用DBGridEh的前提。我们将使用FireDAC的FDQuery作为数据访问层结合DBGridEh实现数据展示。首先配置基础数据连接// 创建FDConnection连接数据库 FDConnection1.Params.DriverID : MySQL; FDConnection1.Params.Database : your_database; FDConnection1.Params.UserName : user; FDConnection1.Params.Password : password; FDConnection1.Connected : True; // 设置FDQuery FDQuery1.Connection : FDConnection1; FDQuery1.SQL.Text : SELECT * FROM sales_data; FDQuery1.Open;接下来配置数据源和DBGridEh的基础属性DataSource1.DataSet : FDQuery1; DBGridEh1.DataSource : DataSource1; DBGridEh1.Options : [dgEditing, dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit];2. 实现基础合计功能DBGridEh提供了简单的合计功能可以通过以下配置实现// 启用合计功能 DBGridEh1.SumList.Active : True; // 为需要合计的列设置Footer属性 DBGridEh1.Columns[2].Footer.ValueType : fvtSum; DBGridEh1.Columns[2].Footer.DisplayFormat : 0.00;这种基础合计功能虽然简单易用但存在明显局限只能在表格底部显示全局合计不支持分组状态下的子组合计数据刷新时合计值可能丢失3. 进阶分组统计实现要实现真正的智能分组统计我们需要引入MemTableEh和DataSetDriverEh组件构建更灵活的数据处理管道。3.1 组件链配置// 配置组件链 FDQuery1 - DataSetDriverEh1 - MemTableEh1 - DataSource1 - DBGridEh1 // 属性设置 DataSetDriverEh1.ProviderDataSet : FDQuery1; MemTableEh1.DataDriver : DataSetDriverEh1; DataSource1.DataSet : MemTableEh1;3.2 分组功能激活在DBGridEh中启用分组功能// 启用分组功能 DBGridEh1.DataGrouping.Active : True; DBGridEh1.DataGrouping.GroupPanelVisible : True; // 设置分组列 DBGridEh1.DataGrouping.GroupLevels.Clear; with DBGridEh1.DataGrouping.GroupLevels.Add do begin Column : DBGridEh1.Columns[0]; // 按第一列分组 Color : clSkyBlue; end;3.3 分组Footer定制这是实现分组统计的核心部分// 配置分组Footer DBGridEh1.DataGrouping.FooterInAllGroups : True; DBGridEh1.DataGrouping.FooterInGroupFooter : True; // 为分组Footer添加统计列 var Footer : DBGridEh1.DataGrouping.Footers.Add; Footer.ColumnItems.Add(DBGridEh1.Columns[2]); // 选择需要统计的列 Footer.ColumnItems[0].ValueType : gfvSumEh; // 设置统计类型为求和 Footer.ColumnItems[0].DisplayFormat : 0.00; Footer.Visible : True;4. 动态计算与刷新处理数据动态变化时需要确保统计值正确更新4.1 数据刷新处理procedure TForm1.RefreshData; begin FDQuery1.DisableControls; try FDQuery1.Close; FDQuery1.Open; MemTableEh1.Close; MemTableEh1.Open; DBGridEh1.DataGrouping.RefreshGrouping; finally FDQuery1.EnableControls; end; end;4.2 自定义统计逻辑对于复杂的统计需求可以使用OnGetFooterText事件procedure TForm1.DBGridEh1GetFooterText(Sender: TObject; DataCol, Row: Integer; Column: TColumnEh; var FooterText: String); begin if (Column.FieldName Amount) and (Row 0) then begin // 计算自定义统计值 var CustomSum : CalculateCustomSum(Column.Field); FooterText : Format(%.2f (Custom), [CustomSum]); end; end;5. 高级定制技巧5.1 多级分组统计// 添加第二级分组 with DBGridEh1.DataGrouping.GroupLevels.Add do begin Column : DBGridEh1.Columns[1]; // 第二分组列 Color : clMoneyGreen; end; // 为第二级分组添加Footer var SecondFooter : DBGridEh1.DataGrouping.Footers.Add; SecondFooter.ColumnItems.Add(DBGridEh1.Columns[2]); SecondFooter.ColumnItems[0].ValueType : gfvAvgEh; // 平均值 SecondFooter.ColumnItems[0].DisplayFormat : 0.00; SecondFooter.Visible : True;5.2 条件格式化procedure TForm1.DBGridEh1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumnEh; State: TGridDrawState); begin if Column.FieldName Amount then begin if Column.Field.AsFloat 1000 then DBGridEh1.Canvas.Font.Color : clRed else DBGridEh1.Canvas.Font.Color : clGreen; DBGridEh1.DefaultDrawColumnCell(Rect, DataCol, Column, State); end; end;5.3 性能优化处理大数据量时的性能考虑// 批量操作前 DBGridEh1.BeginUpdate; try // 大量数据操作 for var I : 1 to 1000 do MemTableEh1.AppendRecord([...]); finally DBGridEh1.EndUpdate; end; // 禁用不必要的功能 DBGridEh1.DataGrouping.GroupRowDefValues.NodeExpanded : False; DBGridEh1.DataGrouping.GroupRowDefValues.RowHeight : 22;6. 常见问题解决方案6.1 统计值不更新确保在数据变化后调用MemTableEh1.RecalcFooterValues; DBGridEh1.DataGrouping.RefreshGrouping;6.2 分组后排序问题// 设置分组排序 DBGridEh1.DataGrouping.GroupLevels[0].SortOrder : soAscEh; DBGridEh1.DataGrouping.GroupLevels[0].GroupInterval : giKeyValueEh;6.3 自定义分组标题procedure TForm1.DBGridEh1GetGroupRowText(Sender: TCustomDBGridEh; GroupLevel: TGridDataGroupLevelEh; var GroupRowText: String); begin if GroupLevel.Column.FieldName Category then GroupRowText : 分类: GroupRowText; end;在实际项目中我发现最实用的技巧是为每个分组级别设置不同的背景色这样用户能直观地区分不同层级的数据。另外对于经常需要刷新的数据建议将MemTableEh的CachedUpdates属性设为True可以显著提升性能。