itacad Posted April 19, 2022 Posted April 19, 2022 Hello, i have to problem to read the value of an attribute in a group of same block. I don't want to use extraction data, I simple need to read (and possibly to copy) in a window which in my case often correspond to a numerical succession. you know a "lisp that list"? In my example i need to read: 1 2 4 5 6 7 9 11 12 Thank you in advance example for list attributes value.dwg Quote
mhupp Posted April 20, 2022 Posted April 20, 2022 (edited) This will display to the command prompt like this. (1 2 4 5 6 7 9 11 12) You can then simply highlight and copy it from there. ;;----------------------------------------------------------------------------;; ;; LIST ATTRIBUTE OF BLOCK (defun C:foo (/ ss ent blk atts x lst) (if (setq ss (ssget "X" '((0 . "INSERT") (66 . 1) (2 . "TAG_BUS_QTA") (410 . "Model")))) (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS))) (setq blk (vlax-ename->vla-object ent) atts (vlax-safearray->list (vlax-variant-value (vla-getattributes blk))) ) (foreach x atts (if (= (vla-get-tagstring x) "QTA") (setq lst (cons (atoi (vla-get-textstring x)) lst)) ) ) ) ) (setq lst (vl-sort lst '<)) ) Edited April 20, 2022 by mhupp Quote
Steven P Posted April 20, 2022 Posted April 20, 2022 8 hours ago, mhupp said: You can then simply highlight and copy it from there. and there was a thread recently copying text to clipboard if you want to copy straight to clipboard as well (my first comment here, 3rd line in the code with a couple of easy changes. https://www.cadtutor.net/forum/topic/74896-get-blockname-and-copy-in-memory/ ) 1 Quote
itacad Posted April 23, 2022 Author Posted April 23, 2022 Thank you mhupp, you understood the example perfectly! I don't know how to program in lisp, but I can try, I ask you for help to transform the lisp so that I can use it in a more general way. 1) I would like to select a block and an attribute with different name and tag...I would like it to work on any block with an attribute. 2) I would like to list the result one result per row instead of all the results in succession on a single row I try to modify your lisp but there are too many subjects unknown to me... Thanks in advance for any help LAOB prove.lsp Quote
mhupp Posted April 24, 2022 Posted April 24, 2022 (edited) 1. Select a block and it will pop up a list of all attribute values that aren't blank. 2. it will then select all blocks with that name and return the vaules of that tag if they aren't blank it will automatically open your command prompt so its easier to read the lines. if you don't like that just remove (textscr) at the end. Their might be a better way to retrieve the tag but meshed part of @ronjonp code here with mine ;;----------------------------------------------------------------------------;; ;; DISPLAY ATTRIBUTE OF BLOCK (defun C:foo (/ blk blkname attlst attvalue att tag ss ent atts lst) (while (setq blk (car (entsel "\nSelect Block"))) (if (and (= "INSERT" (cdr (assoc 0 (setq x (entget blk))))) (setq blkname (cdr (assoc 2 x)))) (progn (setq attlst (mapcar '(lambda (at) (list (vla-get-tagstring at) (vla-get-textstring at))) (vlax-invoke (vlax-ename->vla-object blk) 'getattributes) ) ) (setq attvalue (mapcar '(lambda (at) (cadr at)) attlst)) (setq attvalue (vl-remove "" attvalue)) (setq att (AT:ListSelect (strcat "Attribues in " blkname) "Pick A Attribue" 30 60 "false" attvalue)) (setq tag (car (nth (vl-position (car att) (mapcar 'cadr attlst)) attlst))) (if (setq ss (ssget "X" (list '(0 . "INSERT") (cons 2 blkname) '(410 . "Model")))) (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS))) (setq blk (vlax-ename->vla-object ent) atts (vlax-safearray->list (vlax-variant-value (vla-getattributes blk))) ) (foreach x atts (if (= (vla-get-tagstring x) tag) (setq lst (cons (vla-get-textstring x) lst)) ) ) ) ) (setq lst (vl-remove "" lst)) (setq lst (vl-sort lst '<)) (prompt (strcat "\n" (itoa (length lst)) " Attribues Found")) (foreach x lst (print x) ) (textscr) ) (prompt "\nNot a Block") ) (setq lst nil) ) (princ) ) ;;----------------------------------------------------------------------------;; ;; List Select Dialog (Temp DCL list box selection, based on provided list) ;; (AT:ListSelect "Title" "Lable" ## ## "ture/false" lst) ;; title - list box title ;; label - label for list box ;; height - height of box ;; width - width of box ;; multi - selection method ["true": multiple, "false": single] ;; lst - list of strings to place in list box ;; Alan J. Thompson, 09.23.08 / 05.17.10 (rewrite) (defun AT:ListSelect (title label height width multi lst / fn fo d f) (setq fo (open (setq fn (vl-filename-mktemp "" "" ".dcl")) "w")) (write-line (strcat "list_select : dialog { label = \"" title "\"; spacer;") fo) (write-line (strcat ": list_box { label = \"" label "\";" "key = \"lst\";") fo) (write-line (strcat "allow_accept = true; height = " (vl-princ-to-string height) ";") fo) (write-line (strcat "width = " (vl-princ-to-string width) ";") fo) (write-line (strcat "multiple_select = " multi "; } spacer; ok_cancel; }") fo) (close fo) (new_dialog "list_select" (setq d (load_dialog fn))) (start_list "lst") (mapcar (function add_list) lst) (end_list) (setq item (set_tile "lst" "0")) (action_tile "lst" "(setq item $value)") (setq f (start_dialog)) (unload_dialog d) (vl-file-delete fn) (if (= f 1) ((lambda (s / i s l) (while (setq i (vl-string-search " " s)) (setq l (cons (nth (atoi (substr s 1 i)) lst) l)) (setq s (substr s (+ 2 i))) ) (reverse (cons (nth (atoi s) lst) l)) ) item ) ) ) --Edit-- Just realized this might not give the correct results if the block has multiple tags with the same value. see below. Select Block 9 Attribues Found "6" "BUS" "BUS" "BUS" "BUS" "BUS" "BUS" "BUS" "BUS" Edited April 30, 2022 by mhupp Error Handling / repeat command with while Quote
itacad Posted April 30, 2022 Author Posted April 30, 2022 hello mhupp, and in the meantime, thanks for your help. in the meantime I have discovered the useful command of the "utout "express tools which helps me a lot. I have prepared a more complex file to make you understand what I was looking for. Simulating having a single lisp with which: - I select the block that interests me - I select the attribute that interests me in the chosen block I have created three examples of results that I would need in the "white" example I select the block "TAG_BUS_QTA" and the attribute "QTA", the result that should be displayed is: 1 2 4 7 11 in the "yellow" example I select the block "DB_SCH_V4_INT_MT" and the attribute "SIGLA", the result that should be displayed is: Q1 Q2 Q3 Q5 in the "red" example I select the block "DB_TARGHETTA_ITEM_RI" and the attribute "PROG", the result that should be displayed is: 001 004 009 201 I hope I explained myself better than in previous posts regards example for list attributes value 2.dwg Quote
mhupp Posted April 30, 2022 Posted April 30, 2022 (edited) 1 hour ago, itacad said: Simulating having a single lisp with which: - I select the block that interests me - I select the attribute that interests me in the chosen block I have created three examples of results that I would need That's what it currently does. : FOO Select Block 5 Attribues Found "01" "02" "04" "07" "11" Select Block 4 Attribues Found "001" "004" "009" "201" Select Block 4 Attribues Found "Q1" "Q2" "Q3" "Q5" Select Block If you want things to show up in order they have to be the same length. This is what happens when it sorts a list of items that aren't the same length. its only looking at the first character and I don't know how to fix this. 1 11 2 4 7 Edited April 30, 2022 by mhupp Quote
itacad Posted May 5, 2022 Author Posted May 5, 2022 Sorry! I was not using it properly! It's perfect! Thank you very much! Quote
BIGAL Posted May 6, 2022 Posted May 6, 2022 - I select the block that interests me - I select the attribute that interests me in the chosen block You only need 1 pick using nentselect you can pick the attribute this returns its properties, ie tag name or attribute value, you then use the selection point with a ssget and auto select the block again get its properties in particular block name. Quote
itacad Posted July 18, 2022 Author Posted July 18, 2022 Hello! This bruise is very powerful! I use it daily with a lot of time savings! I hope it will be useful to others too! I ask this: would it be possible to make it work with the pickfirst method? In many situations it would be more convenient for me to use it on a defined group of objects. Thank you in advance Quote
mhupp Posted July 18, 2022 Posted July 18, 2022 Glad to hear your liking it. updated to do what you want. ;;----------------------------------------------------------------------------;; ;; DISPLAY ATTRIBUTE OF BLOCK (defun C:foo (/ blk blkname attlst attvalue att tag ss ent atts lst) (while (setq blk (ssget "_+.:E:S" '((0 . "INSERT") (66 . 1)))) (setq blkname (cdr (assoc 2 (entget (ssname blk 0))))) (setq attlst (mapcar '(lambda (at) (list (vla-get-tagstring at) (vla-get-textstring at))) (vlax-invoke (vlax-ename->vla-object (ssname blk 0)) 'getattributes) ) ) (setq attvalue (mapcar '(lambda (at) (cadr at)) attlst)) (setq attvalue (vl-remove "" attvalue)) (setq att (AT:ListSelect (strcat "Attribues in " blkname) "Pick A Attribue" 10 10 "false" attvalue)) (setq tag (car (nth (vl-position (car att) (mapcar 'cadr attlst)) attlst))) (if (setq ss (ssget "X" (list '(0 . "INSERT") (cons 2 blkname) '(410 . "Model")))) (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS))) (setq blk (vlax-ename->vla-object ent) atts (vlax-safearray->list (vlax-variant-value (vla-getattributes blk))) ) (foreach x atts (if (= (vla-get-tagstring x) tag) (setq lst (cons (vla-get-textstring x) lst)) ) ) ) ) (setq lst (vl-remove "" lst)) (setq lst (vl-sort lst '<)) (prompt (strcat "\n" (itoa (length lst)) " Attribues Found")) (foreach x lst (print x) ) (setq lst nil) ) (textscr) (princ) ) ;;----------------------------------------------------------------------------;; ;; List Select Dialog (Temp DCL list box selection, based on provided list) ;; (AT:ListSelect "Title" "Lable" ## ## "ture/false" lst) ;; title - list box title ;; label - label for list box ;; height - height of box ;; width - width of box ;; multi - selection method ["true": multiple, "false": single] ;; lst - list of strings to place in list box ;; Alan J. Thompson, 09.23.08 / 05.17.10 (rewrite) (defun AT:ListSelect (title label height width multi lst / fn fo d f) (setq fo (open (setq fn (vl-filename-mktemp "" "" ".dcl")) "w")) (write-line (strcat "list_select : dialog { label = \"" title "\"; spacer;") fo) (write-line (strcat ": list_box { label = \"" label "\";" "key = \"lst\";") fo) (write-line (strcat "allow_accept = true; height = " (vl-princ-to-string height) ";") fo) (write-line (strcat "width = " (vl-princ-to-string width) ";") fo) (write-line (strcat "multiple_select = " multi "; } spacer; ok_cancel; }") fo) (close fo) (new_dialog "list_select" (setq d (load_dialog fn))) (start_list "lst") (mapcar (function add_list) lst) (end_list) (setq item (set_tile "lst" "0")) (action_tile "lst" "(setq item $value)") (setq f (start_dialog)) (unload_dialog d) (vl-file-delete fn) (if (= f 1) ((lambda (s / i s l) (while (setq i (vl-string-search " " s)) (setq l (cons (nth (atoi (substr s 1 i)) lst) l)) (setq s (substr s (+ 2 i))) ) (reverse (cons (nth (atoi s) lst) l)) ) item ) ) ) Quote
itacad Posted July 25, 2022 Author Posted July 25, 2022 Thank you very much! works perfectly with this version too! Satisfy my curiosity...What does foo mean? Hello! 1 1 Quote
mhupp Posted July 25, 2022 Posted July 25, 2022 Far as I know its just a place holder for the function name. feel free to change it to whatever you think is best. https://en.wikipedia.org/wiki/Metasyntactic_variable Quote
itacad Posted April 12, 2023 Author Posted April 12, 2023 Hi mhupp, I'm bothering you again about this useful lisp. Perhaps the use I made today was not foreseen in the tests I had made and I ask you if what I am about to describe to you can be considered an anomaly. In the example that I attach there are a series of blocks with attributes, they are compiled in the same way except for one attribute. One group has the attribute labeled "bus" filled with "DALI 10" and the other group with "DALI 11". To get to perform a "pickfirst" selection to which to apply your lisp (which in the meantime I've renamed to LAOB) I do the following: 1) I use the powerful lisp SelBlksByAttTag (found on this forum) and I select the blocks with "DALI 10". 2) I run the lisp LAOB 3) select the fourth proposed item from the drop-down menu (which corresponds to the attribute labeled "ID") 4) lisp returns the list of ID values, but also including the blocks that have the "BUS" label compiled with "DALI 11", in this way I can't have the sequence of ID I want to check available Is it possible to change the lisp to actually apply only to the group of selected objects before launching? I also ask you if it is possible to modify the lisp drop-down menu so that it proposes the attribute label and not the content it proposes (this aspect would be useful but not important) Thank you in advance LAOB test pickfirst selection.dwg LAOB.lsp SelBlksByAttTag.lsp Quote
mhupp Posted April 12, 2023 Posted April 12, 2023 (edited) Updated the lisp to streamline the process. You no longer have to select a text from a list just select it with your mouse and it will spit out how many block it found and the value. and error checking to see if it was a attribute you selected. Example LAOB-2.0.lsp Edited April 15, 2023 by mhupp 1 Quote
itacad Posted April 13, 2023 Author Posted April 13, 2023 Sorry but I probably didn't explain myself well, maybe due to my poor English. The lisp was fine as it was before because it allowed me to read all the values of the selected attribute (ID) thus being able to check the sequence, with this update this functionality is gone. Basically I want: - Select a group of blocks (operation independent of LOAB) - Proceed to launch the lisp LOAB (pickfirst) which must perform the check only on the selected group of blocks (in my example I preselected all blocks with the "BUS" attribute filled in with "DALI 10") - select from the LOAB lisp dialog the attribute to check (in my example the ID attribute) - read the sequence that lisp displays in the command line: "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30" "31" "32" "33" "34" "35" "36" "36" "37" "38" "39" "40" "41" "42" "43" "44" "45" "46" "47" "48" "49" "50" "51" "52" "53" "54" "55" (in my example id 36 is duplicate and i need to fix it) The problem I encountered is that the lisp of the previous revision does not only control the pre-selected group (DALI 10) but also integrates the other non-pre-selected blocks into the control, this means that I can't check only the IDs of the DALI 10. Thank you for your patience and for your work Quote
mhupp Posted April 14, 2023 Posted April 14, 2023 A few things. it does what the old lisp did but better/faster. using getpropertyvalue and setpropertyvalue so you don't have to test each attribute of each block. these commands are used in autocad but they don't work with my BricsCAD. So I can't really test the lisp. But what it should do is the following. :LAOB Select Block Attribute: *pick ID *list all attributes ----------------------------- 37 Attributes found Process Results? Yes/<No>: Yes Select Block by value: *input 36 2 Blocks Found Change Values? Yes/<No>: Yes *Zoom to first one Input [36]: *input 56 Attribute updated to "56" *Zoom to Next Input [36]: *enter *zoom back out. Select Block Attribute: check last post for updated lisp. Quote
itacad Posted April 14, 2023 Author Posted April 14, 2023 Thanks, I tried but it gives me an error Comando: LAOB Select Block Attribute: ; errore: tipo di argomento errato: (or stringp symbolp): nil But re-reading your last post. the logic you are applying is not what I need, if the lisp works as you describe, it no longer allows me to control the numerical sequence of the IDs because I should manually enter "36" even though I don't know in advance that it is a repeated value as I don't have the sequence that was shown in the command line with the first version. lisp was fine as it was, the only drawback it had was that it couldn't actually be applied to just the actually selected blocks before being executed. However, I don't want to waste your time, I will use the previous version and copy only the blocks to be checked onto an empty drawing and from there I will use the lisp, making sure that the check takes place only on those blocks Quote
mhupp Posted April 15, 2023 Posted April 15, 2023 14 hours ago, itacad said: if the lisp works as you describe, it no longer allows me to control the numerical sequence of the IDs Where i posted "*list all attributes" it still outputs the id's the the command line 20 21 22 23 24 ... Just didn't want to type them all out. and i didn't really like what it was doing (too much spam) so I went back and made the code the old way so I could test things. and made a few updates. Now when you select an attribute it will check for duplicates. if it finds any it will list them out and then ask you if you want to process the results if you do it will ask for a search string this is case sensitive. so if i typed gr.8 it wouldn't find anything. : LAOB Select Block Attribute: "GR.10" Found 2 Time(s) "GR.11" Found 16 Time(s) "GR.12" Found 2 Time(s) ... Process Results? Yes/<No>: y Value to Search: GR.8 it will then zoom to each block that matches GR.8 and ask for an input. if you don't want to change anything just hit enter and it will go to the next block. if you do typing it in there will update the your looking at. Change [GR.8]:test Attribute updated to "test" After all blocks are cycled thought it will zoom back out and ask for another selection to start the process over again. two things. you will only see duplicated items now or a unique list (I could change this back if you want) No Duplicate Values Found list Results? Yes/<No>:y "20" "21" "22" ... if something is mistyped it won't be found as a duplicate. like "GR.8" "gR.8" "G R.8" are all seen as different. When it ask yes or no "<no>" is default so you can hit enter or right click to skip. See updated code above. Quote
itacad Posted April 16, 2023 Author Posted April 16, 2023 Thanks but it still gives me an error LAOB Select Block Attribute: ; errore: funzione errata: #<SUBR @0000019e286eaa70 -lambda-> I specify one thing: the block I used is an example, I may have to check others with different attributes Greetings 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.