EhLib 10.0.031 For Delphi 11:TDBGridEh排序、过滤、合计功能实战

📅 发布时间:2026/10/18 8:29:25
EhLib 10.0.031 For Delphi 11:TDBGridEh排序、过滤、合计功能实战
简介EhLib 10.0.031 是专为 Delphi 11 开发者打造的组件库覆盖图形处理、数据库操作、报表设计、图表分析和界面增强等常见开发场景帮助程序员在 RAD 环境下快速构建功能丰富的桌面应用。这版压缩包共 890 个文件以 dfm 表单、pas 源码、dpr 工程文件为主另有 dcu 编译单元、res 资源、ico 图标、chm 帮助文档及示例程序整体约 24.63MB目录结构清晰便于按需查阅。目前已有 885 人学习下载受到 Delphi 开发者的关注。资源内置完整源代码和安装工具兼容 Delphi 11.1.5其中数据库组件支持 MySQL、Oracle、SQL Server 等多种系统报表设计器可导出 PDF、HTML、Excel 等格式图表组件支持实时刷新适合开发进销存、财务分析等数据密集型应用。此外其数据网格与分页控件在交互体验上做了专门优化能有效提升后台管理系统的开发效率。通过研读源码开发者还可进一步定制界面与功能满足项目差异化需求。1. 从控件冗余到起效EhLib 10.0.031 是 Delphi 11 项目里早就该换的那套表格组件做 Delphi 11 的 VCL 项目做久了很多人会碰上一类需求界面表格要能按标题栏点一下排序、能弹过滤条件、能显示合计行还得在编辑时有像样的下拉选择框。自带的 TDBGrid 这些东西一个都不给要么自己攒事件要么在第三方控件里反复横跳。EhLib 10.0.031 For Delphi 11 就是干这个的它是一整套 VCL 界面控件库核心是增强版的 TDBGridEh 网格连带一批配套编辑框、下拉框、内存表、进度框安装完直接出现在 IDE 组件面板里拖出来就能用。我这篇主要讲我实际拆这个版本时的安装顺序、TDBGridEh 的排序过滤合计三个高频功能怎么配、常见翻车点在哪以及 TMemTableEh 和导出 Excel 的进阶玩法。适合正在做进销存、MIS、报表类桌面程序的人也适合老项目从低版本 EhLib 往 Delphi 11 迁移时照着校验一遍坑位。2. 安装与接入10.0.031 在 Delphi 11 里的落地顺序2.1 安装前的版本匹配10.0.031 与 Delphi 11 的对应关系EhLib 的发布节奏跟 Delphi 版本绑定得很死。10.0.031 这个版本号对应的就是 Delphi 11 那一代 IDE 的编译环境。你如果机器里同时装了 Delphi 10.4 和 11装包的时候不要图省事全选不同版本 VCL 结构有细微差别全选之后容易出现 BPL 互相覆盖。我在某公司一台旧机器上装过一次当时机器里 Delphi 10.4 和 11 并存安装向导里默认勾选所有检测到的 IDE我也没改结果 Delphi 11 里组件面板出现重复项Delphi 10.4 里反而加载不完整。后来卸载干净只勾选当前要用的 IDE 版本才正常。所以第一步先确认 IDE 版本再决定装哪个目标。2.2 从源码安装到 IDE 的完整步骤这个版次提供的是源码安装包。拿到压缩包之后完整解压到一个无空格路径比如D:\Components\EhLib路径里不能有中文否则编译生成的 dcu 引用会出问题。安装步骤如下解压后进入Delphi11\目录运行安装程序Install.exe。安装向导里勾选 Delphi 11 对应的编译目标直接下一步。编译过程会生成一系列 .bpl 和 .dcp 文件安装结束后打开 Delphi 11。在 IDE 里打开Component Install Packages确认EhLib Runtime和EhLib Design两个包已勾选。编译输出的默认目录一般在Delphi11\Lib\下。如果你的 IDE 报了找不到 .dcu 的错误需要手动把库路径加进去。# Delphi 11 菜单路径Tools Options Language Delphi Library # 在 Library path 里追加两行注意用分号分隔 D:\Components\EhLib\Delphi11\Lib D:\Components\EhLib\Common这里解释一下为什么两行都要加第一行是编译产物目录第二行是跨版本公共源码目录。EhLib 把很多公共单元放在 Common 下Delphi 11 的源码包只负责把平台相关部分编译链接上来少了 Common 路径会出现 hover 提示时找不到源文件、编译偶尔蹦出未知标识符的问题。加完后新建一个 VCL 项目看组件面板是否多出EhLib页签。正常的页签里至少有 TDBGridEh、TDBEditEh、TDBLookupComboboxEh、TMemTableEh 这几个常用控件。如果面板里没有多半是设计期包没装上回第 4 步检查。2.3 用一个小表单验证组件是否真的可用组件面板看得见不代表能用。我的习惯是立刻往空表单上扔一个 TDBGridEh、一个 TButton再连一个测试用的 ClientDataSet直接走一遍编译、运行、断点。// 最小可用表单Form1 上放置 DBGridEh1, Button1 // 双击 Button1 写入以下代码然后 F9 运行 procedure TForm1.Button1Click(Sender: TObject); begin // 用内存表做一个假数据源避免连数据库环境依赖 CDS1.Close; CDS1.CreateDataSet; CDS1.AppendRecord([A001, 测试物料, 12.5]); CDS1.AppendRecord([A002, 包装箱, 8.0]); CDS1.Open; end;这段代码的逻辑很简单ClientDataSet 作为内存数据集不依赖外部数据库用来验证 DBGridEh 能不能正常取数、显示、滚动。如果组件安装有问题通常在这一步就会暴露要么编译期报找不到DBGridEh单元要么运行期一拖动列宽就崩溃。这两类都说明设计时包没注册好回到 2.2 重新过一遍库路径。参数说明CDS1.CreateDataSet会自动按字段定义生成结构AppendRecord的参数顺序必须与字段顺序一致。实际项目里你连接的是数据库查询结果集这一步本质上是验证“给定的 DataSource 有数据时DBGridEh 能不能正确接收并展示”跟底层是 ADO 还是 FireDAC 无关。3. 把 TDBGridEh 用起来排序、过滤、合计和分组3.1 绑定数据集TDataSource TDBGridEh 的最小配置TDBGridEh 跟 TDBGrid 一样走的是 DataSource 路由不直接接查询组件。所以一个可用的绑定链是数据集 - TDataSource - TDBGridEh.DataSource。这一步做错的常见情况是把 DataSource 直接接到 Grid 的某个奇怪属性上其实就一个入口。在 DFM 里看起来是这个样子object DBGridEh1: TDBGridEh Left 24 Top 24 Width 640 Height 240 DataSource DataSource1 Options [dgEditing, dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit] OptionsEh [dghFixed3D, dghResizeWholeRightPart, dghAutoSortMarking, dghClearSelection, dghEnterAsTab] TabOrder 0 end逻辑说明DataSource DataSource1是数据绑定的核心其余全是显示层控制。Options是 VCL 原生网格选项控制是否可编辑、是否显示标题栏OptionsEh是 EhLib 扩展项其中dghAutoSortMarking决定点击标题栏时是否显示三角箭头排序标记dghEnterAsTab控制回车键移动到右一格而不是跳下一行。参数说明如果你只想要“显示数据”Options里去掉dgEditing即可变成只读网格。dghResizeWholeRightPart是调整列宽时右边所有列一起动的开关喜欢一格格拖的就别开否则拖起来很“跟手”但容易误伤别的列。3.2 本地排序与过滤SortLocal 是默认行为还是黑匣子很多人误以为 EhLib 的排序是自动的其实不完全是。它分两层标题点击触发排序标记真正的排序行为要落在数据集层面。如果你用的是 ADO 查询点击标题后 EhLib 会尝试往 SQL 里拼 ORDER BY如果你不想改 SQL就要开SortLocal。SortLocal是 DBGridEh 的一个布尔属性设为 True 后EhLib 会对当前数据集里的记录做本地排序不修改查询语句。这个功能非常实用尤其是查询结果集已经拉回本地、只想快速看顺序的时候。对应的 DFM 片段object DBGridEh1: TDBGridEh SortLocal True ColumnDefValues.Title.TitleButton True Columns item FieldName MaterialID Title.Caption 物料编码 Width 100 end item FieldName MaterialName Title.Caption 物料名称 Width 160 end item FieldName Price Title.Caption 单价 Width 80 end end逻辑说明SortLocal True是本地排序总开关ColumnDefValues.Title.TitleButton True让所有列默认显示可点击的标题按钮Columns里列出来的字段才显示。三个字段的显示顺序和标题文字也在这里定。参数说明关闭TitleButton的列会显示标题但不可点击排序。如果你的业务要求某些列比如备注列不允许排序单独在该列的Title.TitleButton设为 False 即可不必全局关闭。过滤类似。想要在列头下方出现过滤框需要设置列的STFilter相关属性object DBGridEh1: TDBGridEh STFilter.Local True STFilter.Visible True endSTFilter.Visible True让每列标题下方多出一个过滤输入框STFilter.Local True则过滤也在本地完成。与SortLocal一样开启本地过滤后EhLib 会在内存中对当前结果集做条件筛选不碰底层 SQL。这种设计的好处和代价都很明显好处是响应快、实现简单坏处是如果你过滤完还想看筛选前的总数得自己在状态栏里记录本地过滤不会帮你保留“全集”。3.3 合计行与状态栏FooterRowCount 和面板信息合计行是 TDBGridEh 比较有代表性的功能。默认情况下 Grid 不显示合计行需要在数据网格底部打开FooterRowCount。object DBGridEh1: TDBGridEh FooterRowCount 1 FooterParams.RowHeight 18 Columns item FieldName Price Title.Caption 单价 Footer.ValueType gfSum Footer.ValueFormat #,##0.00 Width 80 end end逻辑说明FooterRowCount 1表示底部保留一行合计区域FooterParams.RowHeight控制该行高度避免文字挤压。Footer.ValueType gfSum表示该列底部单元格显示数值汇总Footer.ValueFormat控制汇总值的显示格式这是 VCL 的 FormatFloat 语法。参数说明gfSum、gfCount、gfAvg是三种最常用的统计类型。字段是字符串类型时不要用gfSum否则 Excel 那种求和得到 0 的闹剧会重演gfCount更适合文本列。实际项目里常有用户问为什么合计行没有数据多半是FooterRowCount忘了设或者合计的列不是数值字段。3.4 分组视图拖拽表头分组的数据塌缩TDBGridEh 还支持在界面上直接拖拽列标题到网格上方形成分组栏。这项功能在设计期不需要写代码运行期用户自己就能拖但前提是属性要配合上。object DBGridEh1: TDBGridEh Grouping True OptionsEh [dghAutoSortMarking, dghGrouping] end逻辑说明Grouping True先打开分组模式OptionsEh里的dghGrouping则允许用户把列标题拖到顶部区域形成分组。分组出现后用户可以点击分组栏左侧箭头把该组数据折叠成一行适合在明细表里快速看大类汇总。参数说明注意分组模式下数据集会自动按分组字段排序这跟SortLocal会互相干扰。如果你既开了SortLocal又开了Grouping可能出现分组栏显示正常但点击某个列排序后分组顺序错乱的情况。我的做法是有分组需求的网格排序交给分组逻辑去维护SortLocal保持 False。4. 编辑场景里的细节Lookup 列、下拉框和运行时调整4.1 用 DBGridEhColumns 配置下拉列表格里需要在编辑时选值这是最常见的需求。TDBGridEh 可以直接指定某列为下拉选择不需要额外放编辑框。// 在设计期选择 DBGridEh1.Columns新增一列属性面板中做如下配置 // 运行时也可以动态赋值 DBGridEh1.Columns[3].EditButtons : [tebPickListEh]; DBGridEh1.Columns[3].PickList.Add(待入库); DBGridEh1.Columns[3].PickList.Add(已入库); DBGridEh1.Columns[3].PickList.Add(已出库);逻辑说明EditButtons设置为tebPickListEh后该列在编辑状态会出现下拉箭头展开后是PickList里预置的选项列表。这个方案适合状态字段等固定字典值。参数说明PickList是普通字符串集合运行时可以像代码里那样动态填充。如果选项来自数据库字典表别用PickList改用 Lookup 字段或者下拉组件硬塞 PickList 会带来维护上的重复劳动。4.2 下拉框组件的选择使用 TDBLookupComboboxEh 还是列内 Lookup当选项来源是一张字典表时两个方案都成立一种是在字段层定义 Lookup 字段网格列绑定到 lookup 字段另一种是放置独立的 TDBLookupComboboxEh 组件在表格外部做选择。实际项目中我偏好前者。Lookup 字段方案把数据关系收敛在数据集内部查询的时候一次带出显示文本网格列直接绑定显示文本字段。TDBLookupComboboxEh 更适合表单编辑界面里某个联系人字段旁边放一个下拉而不是网格内部。TDBLookupComboboxEh 设计期要配置的属性一共四个属性作用典型值DataSource当前表单的主数据源DataSource1DataField需要写入值的字段CustomerIDLookupDataSource字典表的数据源DataSource2LookupKeyField字典表的键字段CustomerID这里要记住的是DataSource和LookupDataSource千万别搞混前者指向业务表单的数据集后者指向字典表。我在模拟项目X里第一次用这个组件就把两个数据源都指向了同一个结果下拉列表永远只显示一行排查半天才发现是数据源接错了。4.3 运行时调整列宽、移动列、保存布局桌面程序里用户调整列宽后下次打开往往希望布局还在。TDBGridEh 提供了列布局存取接口用起来也很直接// 保存当前网格列布局列宽、顺序、隐藏状态 DBGridEh1.SaveGridLayout(CompanyModule, GridMainLayout); // 窗体创建时恢复布局第二个参数区分不同页面用同一控件的场景 DBGridEh1.RestoreGridLayout(CompanyModule, GridMainLayout);逻辑说明SaveGridLayout会在当前项目目录下生成布局配置文件保存的信息包括每列的宽度、显示顺序、是否隐藏以及排序方向。RestoreGridLayout在窗体OnShow或OnCreate时调用按上次保存的状态恢复。参数说明两个参数的组合是“模块名 布局名”。模块名可以按业务子模块分布局名则对应具体网格。如果你一个窗体上放了多个 DBGridEh保证第二个参数不同即可。注意运行时新增列后恢复布局新增列不在配置里会显示在末尾这是正常行为。4.4 用自带 Demo 当手册用安装包里带着几十个 Demo 工程有些人装完就把它们忘在那里了其实这是最有价值的文档。目录D:\Components\EhLib\Demos\下按功能分好类我遇到不确定的属性第一反应是去 Demos 里搜而不是翻帮助文档。5. 避坑指南常见安装与运行问题的排查笔记5.1 安装后 IDE 崩溃或组件面板不显示现象安装完成后重启 Delphi 11打开一个带老版本 DBGridEh 的项目直接报Class TDBGridEh not found或者 IDE 启动时弹“Package 加载错误”的框。原因大部分情况是设计期包没有正确注册到当前 IDE。Delphi 11 对 RTL/VCL 版本要求严格安装包编译出来的是给 Delphi 11 的但如果你的包文件被 10.4 的安装覆盖了两边版本不一致IDE 启动时加载就会失败。解决打开Component Install Packages把列出的 EhLib 包全部移除关闭 IDE重新删除Delphi11\Lib下的所有 .bpl 和 .dcu再按 2.2 的顺序重装一次。重装后先新建一个空项目验证不要直接打开旧项目避免旧项目的旧组件残留干扰判断。5.2 中文排序错乱本地排序不是拼音排序现象开启SortLocal后点击“物料名称”列中文字段没有按拼音排而是按汉字码位或数据库排序规则排看起来毫无规律。原因SortLocal默认按数据集底层字符集的排序规则来比较对于汉字来说如果数据集连接使用旧版驱动可能返回的是 Unicode 码位顺序。解决这种情况没办法只靠 Grid 层解决我一般把排序放回数据库端。具体做法是关闭SortLocal由后台 SQL 按ORDER BY Name COLLATE Chinese_PRC_CI_AS处理网格层只负责显示排序标记。注意关掉SortLocal后dghAutoSortMarking仍然会显示箭头但实际排序动作由你在TitleBtnClick事件里触发 SQL 重查来控制。5.3 合计行不显示检查 FooterRowCount 与 Footer 属性是否配对现象给某个列设置了Footer.ValueType gfSum运行后底部没有任何合计行。原因最常见的是FooterRowCount保持默认的 0。这个属性是合计行的总开关不设 1列上的 Footer 配置全部不生效。解决把网格FooterRowCount改为 1。如果已经是 1 但还是不显示检查该列的Footer.FieldName是否等于绑定字段个别版本在列字段名变化后会失去 Footer 关联重新选择字段名即可。5.4 导出 Excel 乱码编码格式与后缀名的匹配问题现象用SaveToExcel导出的 xls 文件用 Excel 打开后中文全部变成乱码英文正常。原因EhLib 导出的其实是 HTML 表格格式但是用了 xls 后缀Excel 打开时按 HTML 解析如果源数据集是 ANSI 编码且没有声明字符集中文就会乱。解决导出前先确认网格关联的数据集 ClientDataSet或其他数据集的编码设置。FireDAC 连接时把Encoding设为utUTF8导出的文件里模块会带上对应字符集声明。如果数据集编码无法调整导出后用脚本把内容转一遍 UTF-8 再覆盖也不复杂。6. 进阶用 TMemTableEh 做内存数据集和导出 Excel6.1 什么时候适合用 TMemTableEhTMemTableEh 不是网格控件它是一个内存数据集继承自 TDataSet支持排序、过滤、查找、聚合。适合两种场景一是让 Grid 完全离线工作先取数到内存再关闭数据库连接二是报表模块里做二次加工把查询结果放到内存表里做分组统计。我一般用它做“临时明细”比如导出 Excel 前先对查询结果做一轮排序过滤再把内存表接到 DBGridEh 上让用户预览。// 假设 ADOQuery1 已经查询出数据 // 创建内存表拷贝结构载入数据 MemTableEh1.DataSet : ADOQuery1; MemTableEh1.Open; // 现在可以把 DBGridEh1.DataSource 指向 MemTableEh1 对应的 DataSource // 后续所有操作都在内存中进行数据库连接可以断开 ADOQuery1.Connection.Close;逻辑说明MemTableEh1.DataSet : ADOQuery1是让内存表从源数据集拉取结构和数据的关键Open之后内存表即为可用状态。断开连接之后网格的排序、过滤、浏览都不会再触发数据库请求这在做报表导出时能明显减少数据库压力。参数说明DataSet属性需要注意的是源数据集必须处于打开状态否则拷贝不到数据。拷贝完成后内存表是独立副本你修改内存表数据不会反向写回源数据集这点和主从表联动不同适合做临时数据处理。6.2 导出 Excel 的格式边界TDBGridEh 自带 SaveToExcel 方法但命名上容易让人误解。它导出的不是真正的 xlsx 二进制格式而是带表格结构的文件Excel 能打开但严格来说不是 Excel 原生格式。// 导出当前网格显示的数据到 xls DBGridEh1.SaveToExcel(D:\Report\material_list.xls);逻辑说明SaveToExcel会按当前网格的列顺序、列宽、标题文字导出数据区域包含当前筛选后的结果不是全量数据。如果你希望导出前做筛选先用 STFilter 或 SQL 把数据集过滤到目标范围。参数说明使用该方法要注意三点文件路径目录必须存在不存在不会自动创建导出的是网格所见列隐藏列不会导出每次导出直接覆盖同名文件没有弹窗确认。所以我在代码里通常会先做一次文件存在检查给用户留一个覆盖确认框避免误操作。6.3 配合 TMemTableEh 的导出流程实际项目里我最常用的一套组合是查询结果先进 TMemTableEh然后在内存表上做筛选和排序最后把 DBGridEh 的数据源切到内存表再调用 SaveToExcel。这样数据库只查询一次后续操作全部脱离连接报表导出不会出现“连接已关闭”之类的异常。procedure TForm1.ExportReport(Sender: TObject); begin // 1. 把查询结果拉入内存表断开数据库连接 MemTableEh1.DataSet : ADOQuery1; MemTableEh1.Open; ADOQuery1.Connection.Close; // 2. 内存表筛选只导指定状态的数据 MemTableEh1.Filter : Status 已入库; MemTableEh1.Filtered : True; // 3. 绑定到网格并导出 DBGridEh1.DataSource : DataSourceMem; DBGridEh1.SaveToExcel(D:\Report\stock_in.xls); end;逻辑说明步骤 1 先把数据完全拿到本地步骤 2 用内存表自带过滤缩小范围步骤 3 网格展示过滤后的结果并导出。这一步对报表模块特别有用用户可以在导出前先预览一遍筛选效果所见即所得。参数说明Filter语法与数据集的标准过滤一致字符串值必须用两个引号包裹。Filtered True才会启用过滤条件。整个过程中数据库只有一次查询开销其余都在内存完成导出大明细表时能明显感觉到比直接连库导出平稳。用 TMemTableEh 这个习惯是早年在做某跨平台系统被坑出来的。那时候我直接拿着一个绑定的 ADOQuery 去导 Excel用户一边在界面上录入一边点导出结果每次导出都闪一下查询状态有时候还会碰上表锁。后来就强制自己走“查询进内存、断开连接、再导出”这条路从那以后导出报表模块再没出过连接相关的幺蛾子。希望这些细节能帮你在自己的项目里少撞几次墙。本文还有配套的精品资源点击获取