简介XLSReadWriteII v6.0.0.47 是一款面向 Delphi 开发者的 Excel 文件读写组件支持 D7 至 D10.3 Rio 等版本适合需要在程序中直接操作 xls/xlsx 而无需安装 Excel 或其它办公软件的项目场景。组件自带针对单元格值优化的内存管理器可处理较大文件并提供 Direct Read 与 Direct Write 模式在内存不足时直接对磁盘文件进行流式处理其 XLSX 引擎依据文件格式规范自动生成力求最大兼容性且不损坏、不篡改原有数据同时不收取运行时费用并附完整源码。资源包为 rar 格式共 596 个文件约 2.59MB包含 248 个 pas 源码单元、53 个 dfm 窗体、32 个 dpr 工程、16 个 dproj 项目文件以及 html 文档、obj 编译单元、png/gif 图示与 cfg 示例配置等覆盖源码、示例与说明文档。目前已有 299 人学习下载适合希望深入掌握 Delphi 下 Excel 读写、参考示例工程与源码实现的中高级开发者。1. 老 Delphi 项目里读写 Excel为什么我最后留了这套 v6.0.0.47接手一个维护了七八年的 Delphi 老系统时最头疼的不是业务逻辑而是导出报表。客户要 Excel还得是带格式、带公式、能直接打印的那种。一开始用 OLE 自动化调 Excel 进程服务器上没装 Office 直接崩换成 CSV客户嫌没有表头样式、数字变科学计数法。折腾几轮之后我把目光放回了 XLSReadWriteII 这个老牌组件库最终在项目里锁定了 v6.0.0.47 这个版本同时兼容 D7 和 D10.3 Rio 两套编译环境。这套东西解决的核心问题很明确不依赖本机安装 Excel直接在 Delphi 代码里生成和解析 xls/xlsx 文件单元格样式、公式、多工作表都能控制。适合谁还在维护 Delphi 老项目、需要程序化产出 Excel 报表、又不想被 Office 环境绑架的从业者。下面把我拆包、编译、踩坑的全过程摊开讲新手能照着跑熟手能直接看参数边界。2. 拆包看结构D7 与 D10.3 Rio 两套源码怎么摆拿到压缩包先别急着装先看清楚目录结构这决定了你后面是走「编译源码」还是「装设计期包」。XLSReadWriteII 这类组件库通常分运行期包和设计期包D7 和 D10.3 Rio 的包文件格式不一样混用必翻车。2.1 目录里到底有什么解压后一般能看到这么几类东西我按实际拆包经验列一下目录/文件作用对应版本Source 目录核心单元源码如 XLSReadWriteII2.pas 等通用Packages 目录.dpk 包工程分 D7 与高版本按编译器区分Demo 目录示例工程含读写、样式、公式通用Help/文档接口说明与属性列表通用Lib 目录预编译的 .dcu按版本分关键点在于D7 用的是老式 .dpk 加 .dof 配置D10.3 Rio 用的是 .dpk 加 .dproj两者不能互相打开。我一般先确认自己主力的 IDE 是哪个再决定编哪套包不要想着一个包通吃。2.2 先编运行期包再编设计期包顺序错了会报「找不到单元」或者「组件面板不出现」。正确流程是这样# 以 D10.3 Rio 为例先打开运行期包工程 # 1. 用 IDE 打开 Packages 下对应版本的运行期 .dpk # 2. Build不是 Compile确保生成 .bpl # 3. 再打开设计期 .dpkInstall # 4. 检查组件面板是否出现 XLSReadWriteII 页签逻辑说明运行期包Runtime Package提供实际功能代码设计期包Design Package只负责把组件注册到 IDE 面板它依赖运行期包。先 Build 运行期包是为了让设计期包能找到它引用的单元。参数上注意 Output 路径别指向系统目录我习惯统一输出到项目下的 bin 目录避免权限问题。提示D7 下没有 .dproj改的是 .dof 里的搜索路径把 Source 目录加进 Library Path否则编译时报找不到 XLSReadWriteII2。2.3 把 Source 路径加进搜索路径不管哪个版本Source 目录都要进搜索路径。D10.3 Rio 在 Tools → Options → Language → Delphi → Library 里加D7 在 Project → Options → Directories/Conditionals 里加。加完之后新建一个空工程uses 里写 XLSReadWriteII2能编译过就说明环境通了。这一步是后面所有操作的地基别跳过。3. 写第一个导出单元格、样式、公式三件套环境通了之后先跑一个最小可用的导出把「新建工作簿 → 写单元格 → 设样式 → 存盘」这条链路走通。很多人一上来就搞复杂报表结果卡在某个属性上不知道哪步错了。3.1 最小导出代码uses XLSReadWriteII2; // 核心单元不同版本单元名可能略有差异 procedure TForm1.ExportDemo; var XLS: TXLSReadWriteII2; begin XLS : TXLSReadWriteII2.Create(nil); try XLS.Sheets.Add; // 新增一个工作表 XLS.Sheets[0].Name : 报表; // 工作表命名 // 写表头 XLS.Sheets[0].AsString[0, 0] : 姓名; XLS.Sheets[0].AsString[0, 1] : 金额; // 写数据行 XLS.Sheets[0].AsString[1, 0] : A同学; XLS.Sheets[0].AsFloat[1, 1] : 1234.56; // 写公式对金额列求和 XLS.Sheets[0].AsString[2, 1] : SUM(B2:B2); XLS.Filename : D:\out\demo.xls; XLS.Write; // 落盘 finally XLS.Free; end; end;逻辑说明AsString、AsFloat 是按行列索引写值索引从 0 开始这点和 Excel 的 A1 表示法不一样容易搞混。公式直接以字符串形式写入前面带等号组件会把它当公式处理而不是文本。Write 负责把内存中的工作簿写到 Filename 指定的路径。参数说明Sheets.Add 增加工作表Sheets[0] 取第一个AsFloat 写入的是浮点避免金额被当文本Filename 建议用绝对路径相对路径在服务端跑的时候工作目录不确定容易写到意想不到的地方。3.2 样式设置别用错对象样式是新手最容易翻车的地方。字体、边框、背景色分别挂在不同的对象上// 设置第一行表头加粗、居中、灰底 with XLS.Sheets[0] do begin CellFormat[0, 0].Font.Style : [fsBold]; CellFormat[0, 0].Alignment.Horz : ahlCenter; CellFormat[0, 0].Brush.BackgroundColor : clGray; CellFormat[0, 1].Font.Style : [fsBold]; end;逻辑说明CellFormat 是按单元格取格式对象Font 管字体Alignment 管对齐Brush 管填充。注意这些是「格式」不是「值」写值和写格式是两条独立的线互不覆盖。参数说明fsBold 是字体样式集合可以叠加 fsItalicahlCenter 是水平对齐枚举垂直对齐是 Alignment.Vert。颜色用 Delphi 的 TColor别直接填 RGB 整数。3.3 多工作表与命名冲突一个工作簿里加多个 Sheet 时名字不能重复否则写盘时可能报错或者后一个覆盖前一个。我一般加完就立刻设 Name并在代码里维护一个已用名字的集合做校验。另外 Sheet 数量多了之后注意内存占用几万行级别建议分批写或者用流式接口别一次性全塞内存。4. 读旧文件与兼容性xls 和 xlsx 的边界在哪导出跑通只是第一步实际项目里更多是「读客户给的老 Excel改完再存回去」。这一步的坑比写新文件多得多。4.1 打开文件与读取单元格procedure TForm1.ReadDemo(const AFile: string); var XLS: TXLSReadWriteII2; Row: Integer; begin XLS : TXLSReadWriteII2.Create(nil); try XLS.Filename : AFile; XLS.Read; // 读入文件 for Row : 0 to XLS.Sheets[0].LastRow do begin Memo1.Lines.Add( XLS.Sheets[0].AsString[Row, 0] | FloatToStr(XLS.Sheets[0].AsFloat[Row, 1])); end; finally XLS.Free; end; end;逻辑说明Read 把文件加载进内存之后就能按行列访问。LastRow 返回最后一个有数据的行号用它做循环上界比写死行数安全。AsFloat 读数值单元格如果单元格里其实是文本读出来会是 0这点要特别注意。参数说明AFile 传绝对路径LastRow 是动态的空表时可能是 0 或 -1循环前最好判断一下。4.2 xls 与 xlsx 的差异v6 这个版本对两种格式的支持程度不一样。xls 是老二进制格式读写都稳xlsx 是压缩包结构某些复杂样式或者图表读进来会丢。我实测下来纯数据加基础样式的 xlsx 没问题带数据透视表或者条件格式的读进来大概率残缺。所以如果你的场景是「读客户模板」先确认模板格式xlsx 复杂模板建议让客户另存为 xls 再处理。4.3 编码与中文乱码中文乱码通常出在两个地方一是文件本身编码二是字符串转换。Delphi 老版本默认 AnsiStringD10.3 Rio 默认 UnicodeString跨版本传字符串时如果不注意中文就成问号。我的做法是统一在读写前后做一次显式转换别依赖隐式转换。另外工作表名、单元格内容都建议用 UTF-8 思维去检查一遍。注意D7 下编译的代码拿到 D10.3 Rio 下重编字符串类型变化可能导致原本正常的中文变乱码迁移时这块要单独测。5. 避坑与排查那些让我加班到半夜的问题这一章全是血泪经验每条都按「现象 → 原因 → 解决」写遇到对应症状直接对号入座。5.1 编译报找不到单元现象uses 里写了核心单元编译报「Unit not found」。 原因Source 目录没进搜索路径或者进的是错的版本目录。 解决确认 Library Path 指向当前 IDE 对应的 SourceD7 和 D10.3 Rio 的路径分开配别共用一份配置。5.2 组件面板不出现现象设计期包 Install 了但面板上找不到。 原因设计期包没 Build 成功或者运行期包没先 Build。 解决先 Build 运行期包生成 .bpl再 Build 并 Install 设计期包顺序不能反。装完重启 IDE 再看。5.3 写盘报文件被占用现象Write 时抛异常提示文件无法访问。 原因目标文件正被 Excel 打开或者上一次的流没释放。 解决写之前判断文件是否存在且被占用必要时先改名备份确保每次 Create 都有对应 Free用 try...finally 包住。5.4 公式不计算现象写进去的公式在 Excel 里打开显示为文本不计算。 原因公式字符串格式不对或者单元格格式被设成了文本。 解决公式必须以等号开头且写入前别把该单元格格式设成文本格式。函数名用英文参数分隔符用逗号。5.5 大数据量导出卡死现象几万行导出时界面卡住甚至内存溢出。 原因一次性全写内存再落盘内存扛不住。 解决分批写或者用组件的流式接口导出放后台线程主线程只更新进度。别在主线程里干重活。6. 进阶技巧用模板 批量填充把报表做稳前面都是单文件操作实际项目里更常见的是「固定模板 动态数据」。我的习惯是先用 Excel 做好一个带样式的空模板代码只负责往指定单元格填数这样样式维护交给设计代码只管数据分工清楚改版也方便。具体做法把模板文件放资源目录运行时先 Read 模板再按坐标写值最后另存为新文件。坐标建议用常量或者配置表管理别散落在代码里。下面是一个批量填充的骨架procedure TForm1.FillFromTemplate(const Tmpl, OutFile: string; const Data: array of array of Variant); var XLS: TXLSReadWriteII2; R, C: Integer; begin XLS : TXLSReadWriteII2.Create(nil); try XLS.Filename : Tmpl; XLS.Read; // 读模板保留原有样式 for R : 0 to High(Data) do for C : 0 to High(Data[R]) do XLS.Sheets[0].AsString[R 1, C] : VarToStr(Data[R][C]); XLS.Filename : OutFile; XLS.Write; // 另存不动模板 finally XLS.Free; end; end;逻辑说明先 Read 模板把样式带进来再只覆盖数据区域最后 Write 到新路径模板文件本身不被修改。Data 用二维 Variant 数组传兼容字符串和数字。参数说明R 1 是假设第一行是表头数据从第二行开始这个偏移量按你模板实际结构调整VarToStr 做统一转换避免类型不匹配。验证方法导出后别只看代码跑没跑通一定用 Excel 打开检查三件事——样式有没有丢、公式算没算、中文有没有乱码。我一般还会用另一个工具比如开源的表格查看器交叉验证一遍文件结构确认不是只有 Excel 能打开。从那以后我每次换 IDE 版本或者迁移项目都强制先把这套组件的编译和最小导出跑一遍再动业务代码省得后面分不清是环境问题还是逻辑问题。希望帮到你。本文还有配套的精品资源点击获取