明经CAD社区

 找回密码
 注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

查看: 430|回复: 12

[函数] 两个简单的读取excel表格函数

[复制链接]
发表于 2019-9-7 16:22 | 显示全部楼层 |阅读模式
本帖最后由 ljxkm 于 2019-9-10 12:32 编辑

在CAD二次开发中,常需要读取excel表格数据,根据lisp语言的特点,有时一个一个单元格读取反而方便,以下是在实际中常用的两个读取excel表格数据小程序,个人觉得还是比较实用啊:
;;;;;读取excel据函数
(defun Ljx-read-excel-data (vv hor sh / hor ru) ;;;vv为列数直接输入字母、hor为行数,直接输入数字,sh为工作表对象sheet
  (setq hor (itoa hor))
  (setq ru (vlax-variant-value (msxl-get-value (msxl-get-range sh (strcat vv hor)))))
  ru
)

;;;;;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;;;;;读取excel数据函数输出text格式
(defun Ljx-read-excel-text (vv hor sh / hor ru) ;;;vv为列数直接输入字母、hor为行数,直接输入数字,sh为工作表对象sheet
  (setq hor (itoa hor))
  (setq ru (vlax-variant-value (msxl-get-text (msxl-get-range sh (strcat vv hor)))))
  ru
)

本帖被以下淘专辑推荐:

 楼主| 发表于 2019-9-7 19:47 | 显示全部楼层
再贴一个我用的函数,一般读取excel数据基本够用了啊:
取得exce表指定单元格数据:
;;;;;;Ljx-vlxls-get-range-value
;;;;;;取得单元格数据,支持区域输入
;;;;;;参数:sheet当前工作表,rangeid:区域id,如"A1","A1:F10", "A1:A100","A1:EE1"
;;;;;;示例:(Ljx-vlxls-get-range-value *sheet* "E5")输出:-25.10,
;;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:F5"")输出:((-25.10 "张三"))
;;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:E6"")输出:((-25.10)(26.85))
;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:F6"")输出:((-25.10 "张三")(26.85 "李四")
(defun Ljx-vlxls-get-range-value (sheet rangeid / range value value1 valuelist index_i)
  (setq range (msxl-get-range sheet rangeid))
  (setq value (MSXL-GET-VALUE2 range ))
  (cond
    ((=(vlax-variant-type value)  8204);;;为数组时,即为区域
     (progn
       (setq value (vlax-safearray->list(vlax-variant-value value)))
       (setq valuelist '()
             index_i 0
       )
       (repeat (length value)
(setq value1 (nth index_i value))
(setq valuelist (cons (mapcar
     '(lambda (x)(vlax-variant-value x))
     value1
       )
       valuelist
)
)
(setq index_i (1+ index_i))
       );;;;repeat
       (setq valuelist (reverse valuelist))
     )
    )
    (T;;;;为单个单元格
     (setq valuelist (vlax-variant-value value))
    )
  );;;;cond
  valuelist
);;;;defun
发表于 2019-9-8 09:13 | 显示全部楼层
留个脚印,先
发表于 2019-9-8 15:13 | 显示全部楼层
(Ljx-vlxls-get-range-value *sheet* "E5:F5"")
*sheet*具体些,或具体实例,好让新手明白

(defun Ljx-read-excel-data (vv hor sh / hor ru)
(defun Ljx-read-excel-text (vv hor sh / hor ru)
;;;sh;具体些,或具体实例,好让新手明白
 楼主| 发表于 2019-9-8 18:21 | 显示全部楼层
本帖最后由 ljxkm 于 2019-9-10 12:30 编辑

crtrccrt说的很对,*SHeet*、sh均为工作表对象,就是你要读取数据的工作表,VV和hor分开主要便于循环读取,Ljx-vlxls-get-range-value函数功能强一些,当为单个单元格时如(Ljx-vlxls-get-range-value *sheet* "E5")直接读得该单元格的数据,输出:-25.10,为区域时按((第一行) (第二行)...(第n行))的格式读取输出,
;;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:F5")输出:((-25.10 "张三")),第5行:“E5”数据为-25.10、“F5”数据为“张三”
;;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:E6")输出:((-25.10)(26.85)) ,第5行“E5”数据为-25.10、第六行“E6”数据为26.85
;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:F6")输出:((-25.10 "张三")(26.85 "李四")),第五行:“E5”数据为-25.10、“F5”数据为“张三”;第六行:“E6”数据为26.85、 “F6”数据为"李四"。
简单点,几个单元格数据分别为:
"E5"=-25.10
"F5"=“张三”
"E6"=26.85
"F6"=“李四”。
(Ljx-read-excel-data  "E"  5 *sheet*)-->-25.10
(Ljx-read-excel-text  "E"  5  *sheet* )-->"-25.10"
(Ljx-read-excel-data  "E"  6 *sheet* )-->26.85
(Ljx-read-excel-text "E"  6 *sheet*)-->"26.85"

(Ljx-read-excel-data "F"  5 *sheet*)-->“张三”
(Ljx-read-excel-text "F"  5 *sheet*)-->“张三”
(Ljx-read-excel-data  "F"  6 *sheet* )-->"李四"
(Ljx-read-excel-text  "F"  6 *sheet* )-->"李四"

;;;;两个函数再精简一下:
;;;;;读取excel数据函数
(defun Ljx-read-excel-data (vv hor sh /  ru) ;;;vv为列数直接输入字母、hor为 第几行,直接输入数字,sh为工作表对象sheet
  (setq ru (vlax-variant-value (msxl-get-value (msxl-get-range sh (strcat vv (itoa hor))))))
)

;;;;;读取excel数据函数输出text格式
(defun Ljx-read-excel-text (vv hor sh /  ru) ;;;vv为列数直接输入字母、hor为 第几行,直接输入数字,sh为工作表对象sheet
  (setq ru (vlax-variant-value (msxl-get-text (msxl-get-range sh (strcat vv (itoa hor))))))
)

;;;;这样好像差不多了,这几个函数都是在初始化excel应用程序,打开excel表格,取得要读取的sheet后才能用啊,有关的步骤论坛上都有,大家可以去搜索一下




发表于 2019-9-9 21:04 | 显示全部楼层
举例:
d:/ABC.xls中有DEF工作簿
如何形成Ljx-vlxls-get-range-value子程序需要的*sheet*参数.
新手一时半会也搞不明白.
直接给新手实例,举手之劳,新手会节省很多时间.
 楼主| 发表于 2019-9-10 10:28 | 显示全部楼层
本帖最后由 ljxkm 于 2019-9-10 20:37 编辑
crtrccrt 发表于 2019-9-9 21:04
举例:
d:/ABC.xls中有DEF工作簿
如何形成Ljx-vlxls-get-range-value子程序需要的*sheet*参数.

这有点超出贴两个函数源码的初衷了啊,真要函数动起来,还需要不少步骤,用到不少函数哈,不过既然提出来,就啰嗦一下,用到的函数都是网路搜索的集体成果啊:
定义以下函数:
(defun test ()
  (vl-load-com)
  (setq exname "d:\\ABC.xls")
  (vlxls-app-init1 exname)
  (setq *xlapp* (vlxls-app-open exname T))
  (vlxls-sheet-put-active *xlapp* "DEF");;;;设为活动工作表
  (setq *sheet* (msxl-get-ActiveSheet *Xlapp*))
  (setq dat0 (Ljx-vlxls-get-range-value *sheet* "E5")
        dat1 (Ljx-vlxls-get-range-value *sheet* "E5:F5");;;;输出:((-25.10 "张三"))
        dat2 (Ljx-vlxls-get-range-value *sheet* "E5:E6");;;;输出:((-25.10)(26.85))
        dat3 (Ljx-vlxls-get-range-value *sheet* "E5:F6");;;;输出:((-25.10 "张三")(26.85 "李四"))
        dat4 (Ljx-read-excel-data  "E" 5 *sheet*);;;;-->-25.10
        dat5 (Ljx-read-excel-text  "E"  5  *sheet* );;;;-->"-25.10"
        dat6 (Ljx-read-excel-data  "E"  6 *sheet* );;;;-->26.85
        dat7 (Ljx-read-excel-text "E"  6 *sheet*);;;;-->"26.85"
        dat8 (Ljx-read-excel-data "F"  5 *sheet*);;;;-->“张三”
        dat9 (Ljx-read-excel-text "F"  5 *sheet*);;;;-->“张三”
        dat10 (Ljx-read-excel-data  "F"  6 *sheet* );;;;-->"李四"
        dat11 (Ljx-read-excel-text  "F"  6 *sheet* );;;;-->"李四"
  )  
  (vlxls-app-quit *xlapp* nil);;;;退出excel应用程序  
  (vlax-Release-Object *sheet*)
)
;;;;具体使用时先将ABC.xls(解压ABC.zip)拷贝至d盘根目录下,加载test.lsp文件,在CAD命令行输入 (test)即可运行,好了,两个函数扯出这么多来,lisp操控excel有点复杂,是集体智慧,实际工作中,要收集前辈编的较为全面的函数拷在一个lsp文件下成为模块,这样就方便了,excel版本不断更新,以前在网络上找的vlxls-app-init函数不能用了,那个vlxls-app-init1是我自己改来用的,一并贴出了,有点啰嗦,不是很好,但确实是可用的,祝大家进步,提高





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1明经币 +1 收起 理由
USER2128 + 1 赞一个!

查看全部评分

发表于 2019-9-11 11:31 | 显示全部楼层
;=========楼主细心,认真,值得表扬。;
;=========优化后Ljx-vlxls-get-range-value;
;;;;;;Ljx-vlxls-get-range-value
;;;;;;取得单元格数据,支持区域输入
;;;;;;参数:sheet当前工作表,rangeid:区域id,如"A1","A1:F10", "A1:A100","A1:EE1"
;;;;;;示例:(Ljx-vlxls-get-range-value *sheet* "E5");;;;;输出:-25.10,
;;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:F5");输出:((-25.10 "张三"))
;;;;;;      (Ljx-vlxls-get-range-value *sheet* "E5:E6");输出:((-25.10)(26.85))
;;;;;       (Ljx-vlxls-get-range-value *sheet* "E5:F6");输出:((-25.10 "张三")(26.85 "李四")
(defun ljx-vlxls-get-range-value ( sheet rangeid / range value valuelist )
  (setq range (msxl-get-range sheet rangeid))
  (setq value (MSXL-GET-VALUE2 range ))
  (cond
    ( (= (vlax-variant-type value)  8204);;;为数组时,即为区域;
        (progn
          (setq value (vlax-safearray->list(vlax-variant-value value)))
          (setq valuelist (mapcar (function (lambda (x)  (mapcar 'vlax-variant-value x)  )) value))
        )
    )
    ( T;;;;为单个单元格;
      (setq valuelist (vlax-variant-value value))
    )
  );;;;cond
  valuelist
)
 楼主| 发表于 2019-9-11 13:02 | 显示全部楼层
crtrccrt 发表于 2019-9-11 11:31
;=========楼主细心,认真,值得表扬。;
;=========优化后Ljx-vlxls-get-range-value;
;;;;;;Ljx-vlxls ...

这样确实简洁,mapcar这个函数确实好,
发表于 2019-9-11 15:54 | 显示全部楼层
本帖最后由 crtrccrt 于 2019-9-11 15:56 编辑

;;;ljx-vlxls-app-Init;子程序局部优化;

      (cond
        ( (wcmatch excelname "*.xls");;;为2003-xls文件时;
            (cond
              ( (setq out2003 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2003))    (setq out (car out2003))    )
              ( (setq out2007 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2007))    (setq out (car out2007))    )
              ( (setq out2010 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2010))    (setq out (car out2010))    )
              ( (setq out2013 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2013))    (setq out (car out2013))    )
              ( (setq out2016 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2016))    (setq out (car out2016))    )
              ( t    (princ "\\n  计算机上未安装excel2003、excel2007、excel2010、excel2013、excel2016,不能打开xls文件!")  )
            );;;cond;
        )
        ( (wcmatch excelname "*.xlsx");;;为2007-xlsx文件时;
            (cond
              ( (setq out2007 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2007))    (setq out (car out2007))    )
              ( (setq out2010 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2010))    (setq out (car out2010))    )
              ( (setq out2013 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2013))    (setq out (car out2013))    )
              ( (setq out2016 (vl-member-if (function (lambda (x) (findfile x)  )) hm-2016))    (setq out (car out2016))    )
              ( t    (princ "\\n  计算机上未安装excel2007、excel2010、excel2013、excel2016,不能打开xls文件!")  )
            );;;cond;
        )
        ( T  (setq out nil)  )
      );;;cond;
;;;先加载低版本,低版本不存在再加载高版本;;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号  
©2000-2017 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2019-9-20 05:45 , Processed in 0.411966 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表