j2lstaples Posted February 20, 2023 Posted February 20, 2023 I'm trying to get a custom association list with the format: ((("TAG1" . "VAL1A") ("TAG2" . "VAL2A")("TAG3" . "VAL3A") ...) (("TAG1" . "VAL1B")("TAG5" . "VAL5B) ("TAG7". "VAL7B") ...) (("TAG1" . "VAL1C)("TAG3" . "VAL3C")("TAG4" . "VAL4C") ...)) So far, I can generate this list. So, in essence, the keys of each sublist (tags) in the list can differ slightly, meaning some tags can be missing in the other sub list. Where this happens is when attributes of blocks differ by a bit, with some values missing from another. When we use "ATTOUT", AutoCAD bypasses this by inserting empty values when you read the file as a csv file. When I'm trying to create a CSV file, I'd like to have these tags be at the first row and fill up values per item in the list. What I want is basically an ATTOUT but with my own association list. I'm trying to use Write CSV by Lee-Mac for this. So far, the only way I can do this is brute force the first row with the tags, and then extract each Value such that (("TAG1" "TAG2" "TAG3" "TAG4" ...) ("VAL1A" "VAL2A" "VAL3A" "VAL4A" ...) ("VAL1B" "VAL2B" "VAL3B" "VAL4B" ...)) Any ideas about how I should go forward with these. Quote
BIGAL Posted February 20, 2023 Posted February 20, 2023 Trying to understand this is 3 blocks only or more ? One of the simple functions with attributes is you can retrieve attribute values by their creation order so don't need even "TAG1" just ( 1 2 3 4), if the order is wrong can still use creation order number. Quote
j2lstaples Posted February 21, 2023 Author Posted February 21, 2023 13 hours ago, BIGAL said: Trying to understand this is 3 blocks only or more ? One of the simple functions with attributes is you can retrieve attribute values by their creation order so don't need even "TAG1" just ( 1 2 3 4), if the order is wrong can still use creation order number. The tag names are just for simplification of what the actual tag was and there are a lot of blocks with these tags, some missing from others. There are about 16-20 tags. The tag names are unique and can't be simplified by numeric ordering. It's just to signify that some blocks have the same tag name. It's like when you retrieve data from a selection set of blocks with attributes using ATTOUT, when you open it in Excel, there are missing data from some blocks and these get inserted with <>. I'm trying to achieve something similar as a final output. Quote
j2lstaples Posted February 21, 2023 Author Posted February 21, 2023 Here is what I've ended up doing. (setq rail_list (getraillist)) ;; Generates my initial list (setq attlist nil) (setq dynproptags (list "Distance" "Distance1" "Distance2")) (setq attproptags (list "ITEM_NO" "LENGTH-A" "LENGTH-B" "PART_NUMBER" "TOTAL_LENGTH" "ARC_LENGTH" "BEND_ANGLE" "CAT_CODE" "BLOCK_NAME" "SCALE_X" "GRADIENT")) (repeat (setq idx (sslength rail_list)) (setq data (ssname rail_list (setq idx (1- idx)))) (setq ent (entget data)) (setq list1 nil) (setq list2 nil) (setq attlist (append (list (append (list (cons "X" (rtos (car (cdr (assoc 10 ent))))) (cons "Y" (rtos (cadr (cdr (assoc 10 ent))))) (cons "Z" (rtos (caddr (cdr (assoc 10 ent))))) (cons "Rotation" (rtos (cdr (assoc 50 ent)))) ;(cons "BLOCK_NAME" (vla-get-effectivename (vlax-ename->vla-object data))) (cons "Unit Factor" (rtos (vlax-get (vlax-ename->vla-object data) 'InsUnitsFactor))) ) (reverse (foreach tag1 dynproptags (setq list1 (append (list (cons-add-dyn data tag1)) list1)) )) (reverse (foreach tag2 attproptags (setq list2 (append (list (cons-add-att data tag2)) list2)) )) ;(LM:getdynprops (vlax-ename->vla-object data)) ;(LM:vl-getattributevalues (vlax-ename->vla-object data)) )) attlist)) ) (setq outlist (list (append (list "X" "Y" "Z" "Rotation" "Unit Factor") dynproptags attproptags))) (repeat (setq idx (length attlist)) (setq data1 (nth (setq idx (1- idx)) attlist)) (repeat (setq idx1 (length data1)) (setq test1 (append (list (cdr (nth (setq idx1 (1- idx1)) data1))) test1)) ) (setq outlist (append (list test1) outlist)) (setq test1 nil) ) This basically creates an even list for each block/object where it'll hold a value in each tag regardless of whether the block has it or not. It'll input the string "<>" if it sees it empty. It uses two functions: cons-add-dyn and cons-add-att which gets dynamic property values and attribute values. Here it is: ;; Add to cons from attributes (defun cons-add-att (data tag / output) (if (LM:vl-getattributevalue (vlax-ename->vla-object data) tag) (setq output (cons tag (LM:vl-getattributevalue (vlax-ename->vla-object data) tag))) (setq output (cons tag "<>")) ) output ) ;; Add to cons from dynamic properties (defun cons-add-dyn ( data tag / output) (if (LM:getdynpropvalue (vlax-ename->vla-object data) tag) (setq output (cons tag (rtos (LM:getdynpropvalue (vlax-ename->vla-object data) tag)))) (setq output (cons tag "<>")) ) output ) It also uses Lee-Mac's LM:getdynpropvalue and LM:vl-getattributevalue functions. The output of the first code can then be used for Lee-Mac's writecsv function. I use the code: (defun c:testrail ( / fn in lst ss ) (if (and (setq ss (C:getrailinfo)) (setq fn (getfiled "Create Output File" "" "csv" 1)) ) (progn (if (LM:WriteCSV ss fn) (startapp "explorer" fn) ) ) ) (princ) ) C:getrailinfo is the output of the first code which is (reverse outlist). This basically recreates a similar functionality as ATTOUT from the ExpressTools but also gets other values such as the coordinates (X, Y, Z), rotation, unit factor and dynamic properties. I hope someone can use a similar function to this. Quote
BIGAL Posted February 21, 2023 Posted February 21, 2023 Just a suggestion, if the output is to be used in Excel why not do just that and write direct to Excel, lots of examples out there. Quote
j2lstaples Posted February 21, 2023 Author Posted February 21, 2023 2 minutes ago, BIGAL said: Just a suggestion, if the output is to be used in Excel why not do just that and write direct to Excel, lots of examples out there. I've found a solution by just tinkering with it for a bit. It's still not what I need but it's getting there. I need to modify the XYZ values such that it isn't the insertion point of the block but instead a function that takes into account the block or current object and finds the corresponding starting point. I have a function from a previous project that already calculates these values so it should be an easy implementation. 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.