zhang007 发表于 2004-4-12 11:13:00

用EXCEL数据做图的小问题

以下是论坛现成的读取EXCEL数据的LSP程序,只是稍稍改了一下,测试时读取1万个单元格只用1分钟多一点,我听版主说用REPEAT读取数据很慢,可以说详细一点吗?另外我在处理数据时发现,用(command "text" "j" "c"        '(10 20 0) 2 "" "我爱CAD")添加对中样式的文字很容易,用(vla-AddText mspace (vlax-3d-point '(10 20 0)) "我爱CAD")))只能添加左对齐样式的文字,怎样才能方便地用 ActiveX方式添加对中样式的文字呢。由于只能看书或查看论坛上现成的代码,一个看似简单的问题也要有劳各位了。

meflying 发表于 2004-4-12 11:38:00

把你的测试程序和数据也给一份吧

meflying 发表于 2004-4-12 12:19:00

你不能一个一个地循环去读,要一次读一块或一条,我用了读取列的方式,读同样的数据,你的程序用了0.017136335秒,你的程序用了11.15724444秒

zhang007 发表于 2004-4-12 14:58:00

本帖最后由 作者 于 2004-4-12 15:42:49 编辑

我看了你的评论,我认为还不够详细,至少我还看不懂,能不能说多一些?把压箱货拿出来有点舍不得吧。以下是我的数据、程序和图件,这只是最简单的,数据多时,要反复调用Cammand 达上千次,据说调用Cammand 过多容易使CAD崩溃,所以我想用ActiveX方式添加对中样式的文字。谢了。


传错了一个文件,应该是这个

meflying 发表于 2004-4-12 21:55:00

本来我写了上面的回答后,就在写一个读取EXCEL的通用函数,现在也写好了,不过我不喜欢被激将。。。你可以看看我的帖子,我什么时候有舍不得过。。。等你自己根据我3楼说的要求你自己先琢磨一下,等差不多了,我在把通用函数给你吧


你也可以用entmake来创建文字,根据你自己需要进行修改。。。


(defun MakeText(pt1 str / ptInsert TextDxf)<BR>       (setq TextDxf '(<BR>                                       (0 . "MTEXT")<BR>                                       (100 . "AcDbEntity")                                       ; 需要所有 R12 之后版本的图元<BR>                                       (100 . "AcDbMText")                ; 将图元标记为 MTEXT<BR>                                       )<BR>       )<BR>       (setq TextDxf (append TextDxf (list<BR>                                       (cons 10 pt1)<BR>                                       (cons 1 str)<BR>                                       (cons 40 14)<BR>                                       ;(cons 7       "HZ")<BR>                                )<BR>                )<BR>       )<BR>       (entmake TextDxf)<BR>       (princ)<BR>)

meflying 发表于 2004-4-12 22:29:00

给你个编译过的,你先用用:函数(GetRange sheet sCELL nRow),读取范围,用法:;参数说明:sheet——excel的sheet对象
;sCELL——起始单元
;eCELL——结束单元
;如:(GetRang sheet "A1" "C10");表示从"A1"到"C10"之间所有范围函数(GetCol sheet sCELL nRow),读取列,用法:;参数说明:sheet——excel的sheet对象
;sCELL——起始单元
;nRow——行数
;如:(GetCol sheet "A1" 10);表示读取"A"列1到11行之间所有范围函数(GetRow sheet sCELL nCol),读取行,用法:;参数说明:sheet——excel的sheet对象
;sCELL——起始单元
;eCol——列数;如:(GetRow sheet "A1" 10);表示读取1行A开始读11个单元以下是测试程序,你可以跟你原来的比较一下时间,我想,读1万个数据应该在1秒以内完成(只是读取数据的时间,不包括建立EXCEL对象时间)(defun Exl-Open (dmode / )
   (princ "\n创建一个新的 Excel 电子表格文件...")
   (cond
       ((setq appsession (vlax-create-object "Excel.Application"))
         (vlax-invoke-method (vlax-get-property appsession 'WorkBooks) 'open (getfiled "打开存放数据的Excel电子表格文档" "" "XLS" 8))
         (if (= (strcase dmode) "SHOW")
             (vla-put-visible appsession 1)
             (vla-put-visible appsession 0)
         );IF
       );COND1
   );COND
)
(defun Exl-quit ()
   (cond
       ((not (vlax-object-released-p appsession))
         (vlax-invoke-method appsession 'QUIT)
         (vlax-release-object appsession)
       )
   )
)
(defun main( / points)
   (Exl-Open "SHOW")
   (setq sheet (vlax-get-property appsession 'ActiveSheet))
   (setq time (getvar "cdate"))
   (GetRange sheet "E24" "F323")
   (princ "\n")
   (princ (rtos (- (getvar "cdate") time) 2 14))
   (setvar "cmdecho" 0)
   (Exl-quit)
   (princ)
)

zhang007 发表于 2004-4-13 09:59:00

这么简明,还加上了测试时间的小程序,非常感谢!我试试看。本来我认为用entmake写文字太麻烦,在看了版主用子程序写文字的方法后,我觉得还是比较方便。再次感谢!!

zhang007 发表于 2004-4-13 11:52:00

版主,我在测试时发现速度的确快得惊人,但加载程序时要有先后顺序,ExcelLib.VLX文件必须先加载,再加载后面主程序来刷新它,大概是        ExcelLib.VLX中有一些东西没删完罢,我只是猜测。

meflying 发表于 2004-4-13 12:04:00

哈哈,被你猜到了...确实这样的,不过发现时已经传上来了,就算了...其实很简单的,主要是对EXCEL对象模型要熟悉,我也不是很熟悉,不知道哪儿能有这方面资料...把代码给你吧,或许能让你对EXCEL对象模型又多了解一点:;根据起始单元和水平垂直移动单元数目,算出下一单元
(defun CalCell(Cell nRow nCol / i n h str sRow sCol sum pos)
   (setq sRow nil sCol "" sum 0 h nil pos nil)
   (setq i 1)   
   (repeat (strlen Cell)
       (setq str (substr Cell i 1))
       (if (/= (type (read str)) 'INT)
         (setq sRow (append sRow (list str)))
         (setq sCol (strcat sCol str))
       )
       (setq i (1+ i))
   )
   (setq sRow (mapcar '(lambda(e) (- (ascii (strcase e)) 64)) sRow))
   (setq n (length sRow) i n sum 0)
   (repeat n
       (setq sum (+ sum (* (nth (1- i) sRow) (expt 26 (- n i)))))
       (setq i (1- i))
   )
   (setq sum (+ sum nCol))
   (setq pos nil)
   (while (> (setq n (/ sum 26)) 0)
       (setq h n)
       (setq sum (- sum (* 26 (/ sum 26))))
       (setq pos (cons sum pos ))
   )
   (if h
       (setq pos (cons h pos))
       (setq pos (cons sum pos ))
   )
   (strcat (apply 'strcat (mapcar '(lambda(e) (chr (+ e 64))) pos))
   (itoa (+ (atoi sCol) nRow)))
);函数(GetRange sheet sCELL nRow),读取范围,用法:
;参数说明:
;sheet—— excel的sheet对象
;sCELL——起始单元
;eCELL——结束单元
;如:(GetRang sheet "A1" "C10");表示从"A1"到"C10"之间所有范围
(defun GetRange(sheet sCELL eCELL / val items )
   (setq val (vlax-get-property sheet 'range sCELL eCELL))
   (setq val (vlax-variant-value (vlax-get-property val 'value)))
   (if (/= (type val) 'REAL)
       (progn
         (setq items (vlax-safearray->list val))
         (setq items (mapcar '(lambda(e) (mapcar 'vlax-variant-value e)) items))
       )
       (setq items val)
   )
)
;函数(GetCol sheet sCELL nRow),读取列,用法:
;参数说明:
;sheet—— excel的sheet对象
;sCELL——起始单元
;nRow——行数
;如:(GetCol sheet "A1" 10);表示读取"A"列1到11行之间所有范围
(defun GetCol(sheet sCELL nRow / Rows)
   (setq Rows (GetRange sheet sCELL (CalCell sCell nRow 0)))
   (if (/= (type Rows) 'REAL)
       (apply 'append Rows)
       Rows
   )
)
;函数(GetRow sheet sCELL nCol),读取行,用法:
;参数说明:
;sheet—— excel的sheet对象
;sCELL——起始单元
;nCol——列数
;如:(GetRow sheet "A1" 10);表示读取1行A开始读11个单元
(defun GetRow(sheet sCELL nCol / Cols)
   (setq Cols (GetRange sheet sCELL (CalCell sCell 0 nCol)))
   (if (/= (type Cols) 'REAL)
       (car Cols)
       Cols
   )
)

zhang007 发表于 2004-4-13 13:13:00

和VBA上读EXCEL表的方法有些类似,再次感谢!


版主真是一个热心人。。。。。。。。
页: [1] 2
查看完整版本: 用EXCEL数据做图的小问题