aloy Posted May 5, 2017 Posted May 5, 2017 Hello Everyone, I have prepared a table from a list. After editing it by inserting additional information I want to return it to a list. How can I do it?. Thanking in advance, Aloy Quote
BIGAL Posted May 6, 2017 Posted May 6, 2017 Just look at this example you can get columns and rows so just do a double repeat as you build the list. ; pick your table (setq obj (vlax-ename->vla-object (car (entsel "\nPick object")))) (setq col (vla-get-columns obj)) (setq row (vla-get-rows obj)) ;(setq celltxt (vla-gettext obj row column)) (setq celltxt (vla-gettext obj 0 0)) Quote
aloy Posted May 6, 2017 Author Posted May 6, 2017 This is what I have been looking for. Thanks very much BIGAL. Aloy Quote
aloy Posted May 7, 2017 Author Posted May 7, 2017 (edited) Full code tested on a Table of 24 rows and 18 columns is as follows: ;;By BIGAL & Aloy (defun C:TableToList( / row cell rws clns lstx) (setq obj (vlax-ename->vla-object (car (entsel "\nPick object")))) (setq lst nil lstx nil row 2 cell 0) (setq rws(vla-get-rows obj)) (setq clns(vla-get-columns obj)) (while (and (<= row (- rws 1)) (< cell clns)) (setq celltxt(vla-gettext obj row cell)) (setq lstx(cons celltxt lstx)) (setq cell(+ cell 1)) (if (>= cell clns) (progn (setq lst (cons (reverse lstx) lst)) (setq row (+ row 1) cell 0 lstx nil) ) ) ) (setq lst(reverse lst)) (princ) ) Aloy Edited May 7, 2017 by aloy Quote
Lee Mac Posted May 7, 2017 Posted May 7, 2017 Here's another way to write it: (defun c:tab2lst ( / sel ) (if (setq sel (ssget "_+.:E:S" '((0 . "ACAD_TABLE")))) (tab2lst (vlax-ename->vla-object (ssname sel 0))) ) ) (defun tab2lst ( obj / col lst row tmp ) (repeat (setq row (vla-get-rows obj)) (repeat (setq row (1- row) col (vla-get-columns obj)) (setq tmp (cons (vla-gettext obj row (setq col (1- col))) tmp)) ) (setq lst (cons tmp lst) tmp nil) ) lst ) Quote
Grrr Posted May 7, 2017 Posted May 7, 2017 This was version of mine: ; (GetTableContent (vlax-ename->vla-object (car (entsel "\nPick a table: ")))) (defun GetTableContent ( o / IntegerToLst Lst1 Lst2 ) (defun IntegerToLst ( n / L ) ; returns zero-based lst ; (IntegerToLst 5) -> (0 1 2 3 4) (if (and (eq 'INT (type n)) (< 0 n) ) (repeat n (setq L (cons (setq n (1- n)) L)) ) ) ) (if (and (eq 'VLA-OBJECT (type o)) (eq "AcDbTable" (vla-get-ObjectName o))) (foreach r (IntegerToLst (vla-get-Rows o)) (foreach c (IntegerToLst (vla-get-Columns o)) (setq Lst1 (cons (vla-GetText o r c) Lst1)) ) (if Lst1 (setq Lst2 (cons (reverse Lst1) Lst2))) (setq Lst1 nil) ) ) (reverse Lst2) ); defun GetTableContent But Lee's suggestion is most effective. (remember mapcartablecells? ) Quote
aloy Posted May 8, 2017 Author Posted May 8, 2017 Yes, this works well giving me a list including the title and headings of the table. It took some time to get a clue of the method of selection of table object. Thanks Lee. Quote
Lee Mac Posted May 8, 2017 Posted May 8, 2017 Yes, this works well giving me a list including the title and headings of the table. It took some time to get a clue of the method of selection of table object.Thanks Lee. You're most welcome - you may find this reference helpful to understanding the selection mode string. Quote
aloy Posted May 8, 2017 Author Posted May 8, 2017 Grrr, I cannot figure out what the parameter to be used for the function call. The other thing is the outcome from all these method is lists of texts which we cannot use for any processing. Before these data were put into table they were integers, point coordinate values, strings and so on. But after extraction they are all text strings. Therefore I tend to believe that it is much better to export them to excel, then format besides putting in additional info and then import to a'cad with all data types intact. What do you think the best way?. Regards, Aloy Quote
Grrr Posted May 8, 2017 Posted May 8, 2017 Grrr,I cannot figure out what the parameter to be used for the function call. Like this (the example is commented above the function) : Command: (GetTableContent (vlax-ename->vla-object (car (entsel "\nPick a table: ")))) Pick a table: (("A1" "" "") ("B1" "B2" "B3") ("C1" "C2" "C3") ("D1" "D2" "D3")) The other thing is the outcome from all these method is lists of texts which we cannot use for any processing. Before these data were put into table they were integers, point coordinate values, strings and so on. But after extraction they are all text strings. Therefore I tend to believe that it is much better to export them to excel, then format besides putting in additional info and then import to a'cad with all data types intact. What do you think the best way?. To apply some value (other than block definition) into a cell it must be in string format, check vla-SetText method. - Atleast I think so. Thats why when "reading" the table, outputs are lists that contain text strings. I'd rely on string-checking functions to determine whats the string content, like: ; _$ (f "1. 2. 0.") -> 3DPOINT ; _$ (f "0. -3.") -> 2DPOINT ; _$ (f "ABC DEF GHI") -> LIST ; _$ (f "123") -> INT ; _$ (f "123.") -> REAL ; _$ (f "ABC") -> STR (defun f ( x ) ( (lambda (x / tmp len) (cond ( (and (setq tmp (read (strcat "(" x ")"))) (< 1 (setq len (length tmp)))) (if (vl-every 'numberp tmp) (cond ( (= 2 len) '2dpoint ) ( (= 3 len) '3dpoint )) 'list ) ) ( (numberp (read x)) (if (eq 'INT (type (read x))) 'int 'real) ) (T 'str) ) ) x ) ); defun Quote
Lee Mac Posted May 8, 2017 Posted May 8, 2017 The other thing is the outcome from all these method is lists of texts which we cannot use for any processing. Before these data were put into table they were integers, point coordinate values, strings and so on. But after extraction they are all text strings. To apply some value (other than block definition) into a cell it must be in string format, check vla-SetText method. - Atleast I think so. Not quite true - to retrieve the value of a table cell whilst honouring the cell data format, use the getcellvalue method, which will return a variant of type dependent on the cell data format. Quote
Grrr Posted May 8, 2017 Posted May 8, 2017 Not quite true - to retrieve the value of a table cell whilst honouring the cell data format, use the getcellvalue method, which will return a variant of type dependent on the cell data format. Ah I see, so my string-checking function could become variant checking, by using a little modification: (setq L (tab2lst o)) ; where vla-getcellvalue is used instead of vla-gettext (mapcar 'vlax-variant-type L) (mapcar 'vlax-variant-value L) Thanks again, Lee! Quote
Lee Mac Posted May 8, 2017 Posted May 8, 2017 You're welcome. Since the returned variant can be of Safearray type (e.g. 8192+5=8197 for the 'Point' cell data format), you may want to use a function similar to the following: (defun variant->value ( var ) (cond ( (= 'variant (type var)) (variant->value (vlax-variant-value var)) ) ( (= 'safearray (type var)) (mapcar 'variant->value (vlax-safearray->list var)) ) ( var ) ) ) I believe this form of function was originally demonstrated by Vladimir Nesterovsky several years back - another version here. Quote
aloy Posted May 8, 2017 Author Posted May 8, 2017 "Originally posted by Aloy" Before these data were put into table they were integers, point coordinate values, strings and so on. I need to modify my above statement a bit as follows: "Before these data were put into original table from a list they were integers, point coordinate values, strings and so on. And that was prepared with following code: (vla-settext myTable row cell (car lst1)) Is there a way to retain the data type in the original table ?. Quote
Lee Mac Posted May 8, 2017 Posted May 8, 2017 that was prepared with following code: (vla-settext myTable row cell (car lst1)) Is there a way to retain the data type in the original table ?. Use vla-setcellvalue in place of vla-settext, and supply the data as a variant of the desired data type. Quote
aloy Posted May 9, 2017 Author Posted May 9, 2017 (edited) Many thanks Lee, it is so simple as I do not deal with Safearrays. I have made changes to my codes in creation of table and it comes right. However, retrieval after editing appears to be still a problem. I tried the method 'GetcelValue' and I ended up with a list where each value is preceded with a '' statement. I am still trying to get it right. Edited May 9, 2017 by aloy Quote
Lee Mac Posted May 9, 2017 Posted May 9, 2017 You're welcome aloy. I tried the method 'GetcelValue' and I ended up with a list where each value is preceded with a '' statement. Refer to this post. Quote
aloy Posted May 10, 2017 Author Posted May 10, 2017 (edited) Lee, here is how I tried. Still no luck as I get entire list as text. My original list that made the table and the list I got at the end are also given: (defun C:TabToLst( / row cell rws clns lstx) (setq obj (vlax-ename->vla-object (car (entsel "\nPick object")))) (setq lst nil lstx nil row 2 cell 0) (setq rws(vla-get-rows obj)) (setq clns(vla-get-columns obj)) (while (and (<= row (- rws 1)) (< cell clns)) (setq cellcont(vla-getcellvalue obj row cell)) (setq cellcont(variant->value cellcont)) (setq lstx(cons cellcont lstx)) (setq cell(+ cell 1)) (if (>= cell clns) (progn (setq lst (cons (reverse lstx) lst)) (setq row (+ row 1) cell 0 lstx nil) ) ) ) (setq lst(reverse lst)) (princ) ) (defun variant->value ( var ) (cond ( (= 'variant (type var)) (variant->value (vlax-variant-value var)) ) ( (= 'safearray (type var)) (mapcar 'variant->value (vlax-safearray->list var)) ) ( var ) ) ) Command: !l ((4 "MH- 4" 1097.01 88.8977 0.0 6.49583 29.8119 0.0 0.0 "p200" 0.0 0.0 "p250" 0.0 0.0 0.0 0.0 0.0) (3 "MH- 3" 1091.32 92.0437 0.0 13.693 23.316 0.0 0.0 "p200" 0.0 0.0 "p250" 0.0 0.0 0.0 0.0 0.0) (2 "MH- 2" 1079.4 98.7786 0.0 9.62301 9.62301 0.0 0.0 "p200" 0.0 0.0 "p250" 0.0 0.0 0.0 0.0 0.0) (1 "MH-1" 1083.56 107.455 0.0 0.0 0.0 0.0 0.0 "p200" 0.0 0.0 "p250" 0.0 0.0 0.0 0.0 0.0)) Command: !lst (("1" "MH-1" "1083.56462823596" "107.455006691549" "0" "0" "0" "0" "0" "p200" "0" "0" "p250" "0" "0" "0" "0" "0") ("2" "MH- 2" "1079.4026719087" "98.7785814962926" "0" "9.62300548887428" "9.62300548887428" "0" "0" "p200" "0" "0" "p250" "0" "0" "0" "0" "0") ("3" "MH- 3" "1091.32495061517" "92.043721670568" "0" "13.6930298483224" "23.3160353371967" "0" "0" "p200" "0" "0" "p250" "0" "0" "0" "0" "0") ("4" "MH- 4" "1097.00813495964" "88.8977432136699" "0" "6.49582671755135" "29.8118620547481" "0" "0" "p200" "0" "0" "p250" "0" "0" "0" "0" "0")) Edited May 10, 2017 by aloy Quote
aloy Posted May 11, 2017 Author Posted May 11, 2017 I have used vla-setcellvalue in creating the table from the list given above. However, it appears the autocad doesn't understand the context and applied variant type 8 (ie. vlax-vbString) to all. Perhaps I need to force the data type at the time of creation of the table and I have to find a way. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.