一、LISP导出数据到新建Excel工作表

如果当前 Windows 系统已经打开了 Excel 程序,则导出数据较快,否则将自动创建 Excel 对象进程,处于隐藏模式。为简便起见,本函数未检测当前系统是否安装 Excel 程序。如果已经打开了包含若干工作表的工作簿文件,则本函数将会在激活的工作表后插入一个空白工作表,用来导出 lisp 数据,而不会覆盖已有工作表,导致原数据丢失。操作 Excel 对象时必须清楚对象模型结构,工作簿与工作表的区别,对象集合与对象的区别:

  • 工作簿对象集合: WorkBooks,一个 Excel 进程可以有 0 到多个工作簿,就是同时打开了多个 excel 文件(同一进程)。点两次 Excel 软件图标,将会打开两个 Excel 进程
  • 工作表对象集合: Sheets,一个 Excel 文件(工作簿)可以包含1 到多个工作表,一个工作表对象是工作表对象集合的子集
  • 对象是对象集合的子集,对象集合名称以对象加 s 后缀,集合可以为空,具有 cont 属性和 item 属性;对象集合可以用 vlax-for 来遍历,而不必关心集合的
    1. ;;函数: (List_Save_Excel List)
    2. ;;功能: 将表数据输出到Excel (新建工作表)
    3. ;;参数: List 表,可以是一维或者二维表,或任意 list 表数据
    4. ;;返回: 0
    5. ;;示例: (List_Save_Excel '(1 2 3))
    6. (defun List_Save_Excel( Lit / GetPy PutPy wbs wb sht xcells d c r)
    7. (setq *appxls* (vlax-get-or-create-object "excel.application"))
    8. (setq GetPy vlax-get-property PutPy vlax-put-property)
    9. (setq wbs (GetPy *appxls* 'Workbooks))
    10. ;;判断工作薄(集合)是否为空,若空则新建工作簿,并返回工作薄指针
    11. (setq wb (if (= 0 (GetPy wbs 'count))
    12. (vlax-invoke-method wbs 'add)
    13. (GetPy wbs 'item 1)) ;;如果不为空则返回第一个工作薄
    14. )
    15. ;;新建工作表,用于导出数据。 (GetPy wb 'sheets) 是工作表集合对象
    16. (setq sht (vlax-invoke-method (GetPy wb 'sheets) 'add))
    17. ;;得到工作表的 cells 对象,该对象与 range 对象的区别就是可以用行列定位
    18. (setq xcells (GetPy sht 'cells) r 0 c 0)
    19. (if (= (type Lit) 'LIST)
    20. (repeat (length Lit)
    21. (setq d (nth r Lit) r (1+ r))
    22. (if (= (type d) 'LIST)
    23. (repeat (length d) (PutPy xcells 'item r (1+ c)(vl-princ-to-string(nth c d))) (setq c (1+ c)) )
    24. (PutPy xcells 'item 1 r (vl-princ-to-string d))
    25. )
    26. (setq c 0)
    27. )(PutPy xcells 'item 1 1 (vl-princ-to-string Lit))
    28. )
    29. (vla-put-visible *appxls* 1) ;;显示工作表
    30. (vlax-release-object xcells) ;;用完销毁
    31. (vlax-release-object sht)
    32. (vlax-release-object *appxls*)
    33. )

    二、载入工作表区域为 VisualLisp 数组

    有 lisp 数据输出到 excel 的函数,反过来,也少不了 excel 数据的输入函数。总有种感觉,VisualLisp 的变体数组就是为了 Excel 量身打造的,因为其他地方几乎用不上 ``` ;;功能:载入工作表指定区域数据为 VisualLisp 数组 ;;参数:ss 路径及文件名; n 工作表的下标或名称; usg 指定的数据区域 ;;返回:VL数组 ;;示例:(Get_Sheet_arry “d:\cpp\data.xlsx” 1 “a2:e2000”) ;;VisualLisp 数组用法,查找第 2 行,第 3 列数据,转 lisp 表用 mapcar ;;(vlax-variant-value(vlax-safearray-get-element arr 2 3))

(defun Get_Sheet_arry(ss n usg / vg ws sht) (setq excel (vlax-get-or-create-object “excel.application”) vg vlax-get-property ws (vg excel ‘Workbooks) sht(vg (vg (vlax-invoke ws ‘Open ss) ‘Worksheets) ‘item n) arr (vlax-variant-value (vg (vg sht ‘Range usg) ‘Formula))) (vlax-invoke ws ‘close) arr )

  1. <a name="13874bb7"></a>
  2. # 三、按名称获取工作表对象句柄
  3. 值得一提的是,Excel 对象集合的 Item 属性有一个十分贴心的功能,都可以用数字 ID 或字符串 string 来作为参数。当用 ID 作为 Item 的参数时,ID 表示当前工作簿打开的顺序,例如 (vlax-get-property sheets ‘item 1) 返回当前工作簿集合的第一个打开的工作簿对象;当用字符串 string 作为参数时,(vlax-get-property sheets ‘item “abc”) 可以获取当前工作簿集合中名称为 “abc” 工作簿的对象,如果不存在则返回一个自动化错误。<br />一般获取地址的函数,都可以通过 ID 和 string 作为参数,例如 GetProcAddress。而用 ID 的调用速度比 string 快,因此推荐使用 ID 来获取工作薄(表)的对象句柄。

;;获取 Excel 进程对象及工作簿对象集合的句柄 (setq Excel (vlax-get-or-create-object “excel.application”)) (setq Wbks (vlax-get-property Excel ‘Workbooks))

;;获取第一个打开的文件的句柄以及文件名 (setq wbs1 (vlax-get-property Wbks ‘item 1)) (setq wbname (vlax-get-property wbs1 ‘name))

;;返回当前已经打开的文件 abc.xlsx 的对象句柄,如果该文件未打开,则提示: ;; 错误: Automation 错误。未提供说明。 ;;此时可以用 vl-catch-all-apply 捕获错误,并用 vl-catch-all-error-p 判断 (setq wbnName (vlax-get-property Wbks ‘item “abc.xlsx”))

  1. 用同样的办法,可以按名称得到一个工作表对象的句柄(指针),如果工作表在多个文件中重复存在,则返回最后一个打开的工作簿(文件)的工作表对象,通用函数如下:

;;函数: (Get_Sheet_obj ss) ;;功能: 根据工作表名称,从当前打开的所有excel文件中获取某个工作表对象 ;;参数: ss 工作表名称,不分大小写 ;;返回: 如果 ss 工作表已打开,则返回对象句柄,否则返回 nil ;;示例: (Get_Sheet_obj “abc”)

(defun Get_Sheet_obj(ss / sheets sheet retrun) (setq excel (vlax-get-or-create-object “excel.application”)) (vlax-for x (vlax-get-property excel ‘Workbooks) (setq sheets (vlax-get-property x ‘Sheets) sheet (vl-catch-all-apply ‘vlax-get-property (list sheets ‘item ss))) (if (not (vl-catch-all-error-p sheet))(setq retrun sheet)) )retrun )

  1. **例如:**将名为 abc 的工作表 C3:C5 单元格背景色设置为黑色

(setq C35 (vlax-get-property (Get_Sheet_obj “abc”) “Range” “C3:C5”)) (vlax-put-property (vlax-get-property C35 “Interior”) ‘Color 1) ```