在 AutoCAD 二次开发中,经常需要与 Excel 交互:读取数据表、导入参数、生成报表……而这一切的基础是 获取单元格的值。
通过 ActiveX 操作 Excel 时,获取单元格有两种常见方式:
每次都要写一堆嵌套的 vlax-get-property,还要处理 Variant 转换。代码又长又难记。
sheetCell< 正是为此而生 —— 用一个函数统一两种访问方式,自动返回单元格的值(已经转换好类型)。
一、效果预览
;; 假设已打开 Excel 并获取了工作表对象 sheet;; 方式一:使用列字母+行号(像 Range("A1"))(sheetCell< sheet "A" 1) ;; → 返回 A1 单元格的值;; 方式二:使用行列数字(像 Cells(1,1))(sheetCell< sheet 1 1) ;; → 同样返回 A1 单元格的值;; 可以是任意行列(sheetCell< sheet "C" 5) ;; → C5 单元格(sheetCell< sheet 3 5) ;; → 第3行第5列,即 E3
无论你习惯哪种引用方式,都能直接拿到值,无需手动转换 Variant。
二、完整代码
;; 获取 Excel 工作表单元格的值;; 参数 sht : Excel 工作表对象 (VLA 对象);; 参数 A : 列标识(字符串如 "A",或数字行号);; 参数 n : 行号(若 A 为字符串)或列号(若 A 为数字);; 返回 : 单元格的值(已自动从 Variant 转换)(defun sheetCell< (sht A n) (if (= 'STR (type A)) ;; A 是字符串 → 使用 Range 方式,如 "A1" (vlax-variant-value (vlax-get-property (vlax-get-property sht 'RANGE (strcat A (itoa n))) 'value ) ) ;; A 是数字 → 使用 Cells 方式,如 Cells(行, 列) (vlax-variant-value (vlax-get-property (vlax-variant-value (vlax-get-property (vlax-get-property sht 'CELLS) 'ITEM A n ) ) 'value ) ) ))
三、设计思路解析
1️⃣ 自动识别参数类型
函数通过 (type A) 判断第一个参数是字符串还是数字:
2️⃣ 统一处理 Variant 转换
vlax-get-property 返回的值通常是 Variant 类型,直接使用可能出错。vlax-variant-value 将其转换为 AutoLISP 能直接使用的数据类型(字符串、数字等)。
四、典型使用场景
| 场景 | 示例 |
|---|
| 读取参数表中的配置 | (setq val (sheetCell< sheet "B" 2)) |
| 遍历多行数据 | (repeat 10 (setq val (sheetCell< sheet row 1)) (setq row (1+ row))) |
| 根据用户输入的行列号读取 | (sheetCell< sheet row col) |
与 vlax-for 配合批量导出 | 逐单元格读取并写入 CAD 文字 |
完整示例:从 Excel 读取数据并创建文字
(defun c:ImportExcel (/ excel wb sht row val) (setq excel (vlax-get-or-create-object "Excel.Application")) (vlax-put-property excel 'Visible :vlax-true) (setq wb (vlax-invoke-method excel 'Workbooks 'Open "C:\\data.xlsx")) (setq sht (vlax-get-property wb 'Sheets 'Item 1)) (setq row 1) (while (setq val (sheetCell< sht "A" row)) (princ (strcat "\n第" (itoa row) "行数据: " (vl-princ-to-string val))) (setq row (1+ row)) ) (vlax-invoke-method wb 'Close) (vlax-invoke-method excel 'Quit) (princ))
五、与传统写法对比
传统写法(Cells 方式):
(setq cells (vlax-get-property sht 'Cells))(setq cell (vlax-get-property cells 'Item 3 5))(setq val (vlax-variant-value (vlax-get-property cell 'Value)))
使用 sheetCell<:
(setq val (sheetCell< sht 35))
代码量减少约 80%,而且不需要记住 Cells → Item → Value 的调用链。
六、注意事项
⚠️ 需要预先打开 Excel 并获取工作表对象
函数本身不创建 Excel 连接,调用前请确保 sht 是有效的 VLA 对象。示例:
(setq excel (vlax-get-or-create-object "Excel.Application"))(setq wb (vlax-invoke-method excel 'Workbooks 'Open "C:\\test.xlsx"))(setq sht (vlax-get-property wb 'Sheets 'Item 1))
⚠️ 行列索引从 1 开始
与 Excel 的习惯一致,行号和列号(数字方式)从 1 开始。字符串方式如 "A" 对应列 1,"B" 对应列 2,以此类推。
⚠️ 返回值的类型多样
单元格可能是字符串、数字、日期、空值等。vlax-variant-value 会尽量转换为 AutoLISP 兼容类型:
数值 → 整数或实数
字符串 → 字符串
空单元格 → nil
日期 → 浮点数(需自行转换)
⚠️ 对合并单元格的处理
函数仍然能读取合并单元格的值(返回左上角单元格的值),与 Excel 行为一致。
七、进阶扩展
1️⃣ 写入单元格的值
(defun sheetCell> (sht A n val) (if (= 'STR (type A)) (vlax-put-property (vlax-get-property sht 'RANGE (strcat A (itoa n))) 'Value val ) (vlax-put-property (vlax-get-property (vlax-get-property sht 'Cells) 'Item A n ) 'Value val ) ))
2️⃣ 获取单元格的显示文本(而非公式值)
将 'Value 改为 'Text 即可。可在函数中增加一个可选参数。
3️⃣安全版本(错误捕获)
(defun sheetCell<-safe (sht A n) (vl-catch-all-apply '(lambda () (sheetCell< sht A n) ) ))
八、写在最后
sheetCell< 是对 Excel ActiveX 操作中重复代码的一次优雅封装。它让你不必关心 Range 与 Cells 的区别,也不必手动处理 Variant 转换。只需记住一个函数名,就能读取任意单元格。
如果你经常需要从 Excel 导入数据到 AutoCAD,这个小函数会让你的代码干净很多。你也可以基于它扩展出写入、整行读取等功能。
开源分享
代码完全开放,你可以随意使用、修改。如果需要支持更复杂的 Excel 操作(如命名区域、公式读写),可以在其基础上继续封装。
觉得这个函数实用?点个「在看」或分享给需要与 Excel 打交道的朋友,让表格读取更轻松。 📊
关注我,每天一个让 AutoLISP 开发更高效的小工具。