和尚777 发表于 2022-9-6 22:05:29

vlisp以数组读写excel 超快

本帖最后由 和尚777 于 2022-12-16 16:56 编辑


[*]论坛里有很多读写Excel数据的代码,大多是循环逐个读写,速度很慢
[*]Excel vba操作数组是非常方便快速的
[*]vlisp操作数组或许可以做到像Excel vba那样快速操作数据
[*]附件有我写的几个函数以数组读写Excel数据,百万数据3秒左右

    下面是源码
       不缺函数! ket是WPS的app名,改成Excel就行!
;vlisp读写excel 超快
;类库函数我注释了,不需要加载,兼容WPS
; 2022-9-6 hs777
(defun c:tt (/ lst time)

      (setq time(hs-jsq))
      (princ "\n数据构建时间")
      (setq lst(tt-t1 10 50));
      (hs-jsq-end time)

      (setq e(vlax-get-object "Excel.Application")) ;ket.Application
      ;(setq sht(E-Get-ActiveSheet e))
      (setq sht(vlax-get-property e "ActiveSheet"))
      (princ "\n数据写入excel时间")
      (setq time(hs-jsq))
      (E-Lst-2-Range sht "a1" lst)
      (hs-jsq-end time)

      (setq time(hs-jsq))
      (princ "\n读取excel数据时间")
      (setq newlst(E-Get-Range-Value (vlax-get-propertysht "UsedRange")))
      (hs-jsq-end time)
      (princ)
);读取
(vl-load-com)
(defun c:tt2()
      (setq time(hs-jsq))
      (princ "\n读取excel数据时间")
      (setq e(vlax-get-object "Excel.Application")) ;ket.Application
      (setq sht(vlax-get-property e "ActiveSheet"))
      (setq newlst(E-Get-Range-Value (vlax-get-property sht "UsedRange")))
      (hs-jsq-end time)
);写入函数
;(E-Lst-2-Range sht "a1" (tt-t1 1 1))
;(E-Lst-2-Range sht "c2" (tt-t1 10 10000));百万数据
;(E-Lst2Range 工作表对象 "c2" lst)
;二维lst表数据写入Excel单元格,写入成功返回T
(defun E-Lst-2-Range(sht a1 lst / arr c r range)
      ;可以不加载Excel类库函数,
      ;注释部分get,put,invoke 3个函数 完全代替类库
      (if(and sht a1 lst
                         (setq arr(hs-lst2arr2 lst))
                         ;(setq a1(E-Get-Range sht a1))
                         (setq a1(vlax-get-property sht "range" a1))
                         (setq r(length lst))
                         (setq c(length (car lst)))
                         ;(setq range (E-Get-Resize a1 r c))
                         (setq range(vlax-get-property a1 "resize" r c))
               )
                (progn
                        ;(E-Put-Value2 range arr)
                        (vlax-put-property range "value2" arr)
                        t
                )
      )
);转换函数
;(setq lst '((1 5 6)(1 2 3)))
;二维lst表转二维变体数组
;返回数组
(defun hs-Lst2Arr2(lst / a c r)
      (if (and lst (car(setq a(car lst)))
                              (listp a)(setq c(length a))
                              (vl-every '(lambda(x)(= c x))(mapcar 'length lst))
                        )
                (vlax-safearray-fill
                        (vlax-make-safearray
                              vlax-vbVariant
                              (cons 0 (1- (length lst)))(cons 1 c)
                        ) lst)
      )
);读取函数
;获取Excel单元格区域的值
;一个单元格返回一个值,一片区域返回二维lst表
(defun E-Get-Range-Value(range / a arr)
      (if(and range
                         ;(setq arr(e-get-value range))
                         (setq arr(vlax-get-property range "value" nil))
               )
                (progn
                        (if (< 8000(vlax-variant-type arr))
                              (progn
                                        (setq a(vlax-safearray->list(vlax-variant-value arr)))
                                        (mapcar '(lambda(x)(mapcar 'vlax-variant-value x))a)
                              )
                              (progn
                                        (vlax-variant-value arr)
                              )
                        )
                )
      )
)
;测试函数
;构建二维lst表
(defun tt-t1(r c / a i s)
      (setq i 0 s nil)
      (repeat c
                (setq a nil)
                (repeat r
                        (setq a(cons (setq i(1+ i)) a))
                )
                (setq s(cons (reverse a) s))
      )(setq s(reverse s))
)

(defun hs-jsq ()(setq $timebe(getvar "millisecs")))
(defun hs-jsq-end (time / tt) ;计时器结束
      (or time (setq time $timebe))
      (setq tt(- (getvar "millisecs") time))
      (print(strcat"程序运行时间为:"(rtos(* 0.00000001(* tt 86400))2 4)"秒"))
      tt
)
[*]

nyistjz 发表于 2022-9-7 00:22:58

本帖最后由 nyistjz 于 2022-9-7 00:24 编辑

e-xl24HourClock
e-xl24HourClock
e-AccrInt
E-Get-ActiveSheet
E-Get-Range
E-Get-Resize
E-Put-Value2
e-get-value


缺少一些关键函数的定义!

vip-happy 发表于 2023-1-9 12:57:54

本帖最后由 vip-happy 于 2023-1-10 11:44 编辑

现学没学会,写入不成功,麻烦看一下怎么回事

(defun Lst2Range (fn lst / e rg sh tp ws)
(setq e(vlax-get-object "excel.Application")
      ws(vlax-invoke-method (vlax-get-property e "workbooks") "open"(findfile fn))
      sh(vlax-get-property (vlax-get-property ws "sheets") "item" 1)
      tp(vlax-get-property sh "range" "a1")
      rg(vlax-get-property tp "resize" (length lst) (length(car lst)))
)(vlax-put-property rg "value2" (hs-Lst2Arr2 lst))
(vlax-invoke-method ws "close" :vlax-true)
)

cchessbd 发表于 2022-10-9 20:44:11

cchessbd 发表于 2022-10-9 20:36
老大太牛了。但是我看不懂额。。。我测了一下,可以读取,也可以写入。
能不能提供一个调用列子,比方说读 ...
哦,我明白了,这个已经全部读取到newlst表了,现在只需要对newlst表处理就行了。
感谢大大!感谢大大!感谢大大!感谢大大!感谢大大!

hhh454 发表于 2022-9-6 22:16:10

很厉害,感谢楼主分享,学习了

AndyWang 发表于 2022-9-6 23:35:42

支持一下,看着速度确实很快,是用多维度数组做的吗?

烟盒迷唇 发表于 2022-9-7 06:18:43

能够支持WPS嘛

liuhe 发表于 2022-9-7 08:25:23

收藏成功66666

czb203 发表于 2022-9-7 08:27:27

很厉害,感谢楼主分享,学习了

guosheyang 发表于 2022-9-7 10:19:19

感谢共享资料!

dlfjdy 发表于 2022-9-7 10:46:41

感谢分享!

和尚777 发表于 2022-9-7 11:16:41

烟盒迷唇 发表于 2022-9-7 06:18
能够支持WPS嘛

"ket.Application" 应该支持,有些属性方法参数可能不一样
页: [1] 2 3 4 5
查看完整版本: vlisp以数组读写excel 超快