Alaskachick Posted April 6, 2012 Posted April 6, 2012 I thought I was writing a simple lisp routine and then it all went wrong... Beginning premise: Build a selection set with one click that will select all the blocks (these are dynamic blocks with anonymous names, hence the layer selection for simplicity) on any layer containing the word TRANS, but ignore any frozen layers. The lisp needs to leave the items selected so common properties can be changed in the properties window by the drafter. This is simple in quickselect, but the operators want it done in a single click or typed word. Below is the working line of code. It selects all the right stuff, but it doesn't leave the selection set selected. The user then has to type SELECT, P to get the set back into action. (command "._select" (ssget "A" '((8 . "*TRANS*")))) I then put this line into program format (or whatever the technical name for it is) and now it freezes Civil when I test it. I am pretty sure I have not closed a loop somewhere. (defun c:TRANS (/ sstrans) (setq sstrans (command "._select" (ssget "A" '((8 . "*TRANS*"))))) (princ) ) I can't believe this simple line of code is giving me so much grief. I am sure I am missing something really simple. In the end I have 5-6 different blocks on their respective layers that I will need to build selection sets for. I have attached my test drawing. I plan is to have one lisp file from which I can run all the different sel sets with the single click of a button on a toolbar. I would really appreciate someone pointing out whatever obvious thing I am missing. Details: Running on Civil 2011, all blocks are dynamic w/ *U names trans_pole_test.dwg Quote
MSasu Posted April 6, 2012 Posted April 6, 2012 The SELECT command is repetitive, so it expects to close the selection process; you may also add an extra filter for entity type since you are looking only for blocks: (defun c:TRANS ( / sstrans) (setq sstrans (command "._select" (ssget "[color=red]_[/color]A" '([color=red](0 . "INSERT")[/color] (8 . "*TRANS*")))[color=red] ""[/color])) (princ) ) Quote
MSasu Posted April 6, 2012 Posted April 6, 2012 Reading again your post I'm wondering what do you want to achieve by creating that selection set? You are going to call it for an editing command? In this case, wouldn't be better to create a new button and add only the selection function in the Macro field of that button? (ssget "_A" '((0 . "INSERT") (8 . "*TRANS*"))) Make sure that you remove the default "^C^C" from Macro field since this will cancel your command. To use it just call desired command (i.e. MOVE) and press that button. Quote
Alaskachick Posted April 6, 2012 Author Posted April 6, 2012 Thank you, Thank you! The macro idea worked great and the Task Master is very happy with his new toy...I mean, tool. Quote
BlackBox Posted April 6, 2012 Posted April 6, 2012 There's no need for the Select command; instead look into Sssetfirst function. Pseudo code: (defun c:FOO ( / ss) (if (setq ss (ssget "_x" ;|your filter|) (sssetfirst nil ss) (prompt "\n** Nothing selected ** ")) (princ)) Quote
MSasu Posted April 7, 2012 Posted April 7, 2012 A combined solution, taking into consideration RenderMan's suggestion; this will create a default selection set if no command is active or feed the section prompt of an editing command. (defun SelectBlocks( / ssetBlocks ) (setq ssetBlocks (ssget "_A" '((0 . "INSERT") (8 . "*TRANS*")))) (if ssetBlocks (if (= (getvar "CMDACTIVE") 0) (sssetfirst nil ssetBlocks) ;return on command prompt ssetBlocks ;return on select prompt ) (princ) ;return silent if no items to match filter ) ) May place this into your startup list and add the following line to the Macro field of a dedicated button: (SelectBlocks) Quote
Alaskachick Posted April 10, 2012 Author Posted April 10, 2012 Wow, the tool works even better when your two minds are combined. I'm afraid success has only made the Task Master greedy. Now that the button works, I am trying to error proof it against human error. (translated--rewrite it all) The Situation: The dynamic blocks are selected correctly if they were originally placed on the correct layer. But there are rare occurrences when the users placing the blocks get 1 on the wrong layer. The button then doesn't select the block because it is hard wired to the layer name. So, I am trying to make the selection set work by selecting via the effective block name. I have scoured the web and know I have to use the vba "effective name" tool, but I can't figure out the best place to put it in my lisp or how to connect the routines together. Yes, all this can be done with a few clicks via quickselect, but these selections sets are getting done hundreds of times a day so a single click is the goal. Down the road the Task Master wants me to build more lisps that use this same tool in them and build on it. (success on the small scale has given him the idea I can do great things. I keep telling him I have very little idea what I am doing, but it does not seem to deter the requests.) (Yes, he reads this forum. lol) Here’s the 4 steps I need to achieve in my lisp: 1. Select all blocks named “elect_transformr_bank_point” or “ *u*”. Use the “selectblock” from MSau. It works really good. 2. Get the effective name of all *u* blocks selected by selectblock lisp. Use the EFname lisp from pBe, it works well on one block at a time. 3. Filter out of the selection set any effective names that don’t match “elect_transformr_bank_point”. 4. Create an active selection set of the remaining blocks with the block name or effective name “elect_transformr_bank_point”. Use the last few lines of MSau’s “selectblock” lisp So here's what I've tried: Started with this from pBe : defun c:test (/ ss en) ;;Written by pBe in this [url="http://www.cadtutor.net/forum/showthread.php?64785-How-to-get-the-original-block-name-of-a-dynamic-block&highlight=EFFECTIVE+BLOCK"]thread[/url]. (defun _EFName (ent) (vl-load-com) (vla-get-effectivename (vlax-ename->vla-object ent))) (if (setq ss (ssget '((0 . "INSERT")(2 . "ELECT_TRANSFORMR_BANK_POINT,`*U*")))) (repeat (sslength ss) (setq en (ssname ss 0)) (setq blockname (_EFName en)) (princ "\nThe rest of your code") (print blockname) (ssdel (ssname ss 0) ss) ) )(princ) ) 1. “SelectBlock” lisp from MSasu (tweaked a little) (defun SelectBlocks( / ssetBlocks ) ;;by MSasu, see earlier post in this thread. (setq ssetBlocks (ssget "_A" '((0 . "INSERT") (2 . "ELECT_TRANSFORMR_BANK_POINT,`*U*")))) (if ssetBlocks (if (= (getvar "CMDACTIVE") 0) (sssetfirst nil ssetBlocks) ;return on command prompt ssetBlocks ;return on select prompt ) ;end if (princ) ;return silent if no items to match filter ) ;end if ) ;end defun 2. Get effective name of blocks, From pBe defun c:test (/ssetBlocks en) ;;I think this will only get the effective name one at a time, so I added some ideas to make the lisp go through the entire list and get the effective name of each block selected. (defun _EFName (ent) (vl-load-com) (vla-get-effectivename (vlax-ename->vla-object ent)));; I think I need to add something like this (setq cntr 0) (ssname ssetBlocks 0) so that the effective name lisp looks at each entity individually, but I am not sure if ssname is the correct command to use. (if (ssetBlocks)) ;; I put the selection set variable from “selectblocks” where the selection filter used to be. (repeat (sslength ssetBlocks) 3. Filter out of the selection set any effective names that don’t match “elect_transformr_bank_point” progn if (setq en (ssname ssetBlocks 0)) ;;If the name of the first entity is “ELECT_TRANSFORMR_BANK_POINT” I want to keep it, otherwise I want to delete it from the selection set. Then (ssdel (en /= “ELECT_TRANSFORMR_BANK_POINT”)) (setq cntr (+ cntr 1)) ;; at some point I need to add this so the lisp increments through the list created in ssetBlocks. (setq blockname (_EFName en)) );; this line was in the original code, but I’m not sure what it does. (princ "\nThe rest of your code"));; this line was in the original code, but I’m not sure what it does. (ssdel (ssname ss 0) ss);; this line was in the original code, but I’m not sure what it does. ) )(princ) ) 4. Create an active selection set of the remaining blocks with the block name or effective name “elect_transformr_bank_point”. This part is repeated from above and I think I need only one instance of it in the routine. (if (= (getvar "CMDACTIVE") 0) (sssetfirst nil ssetBlocks) ;return on command prompt ssetBlocks ;return on select prompt ) ;end if (princ) ;return silent if no items to match filter As you can see, the ideas start out with some promise (I hope) and then fizzle into crazy ideas tied together with wishes. Any guidance for this struggling code writer? One day, I dream of spitting out code in my sleep, waking up and finding I automated the coffee maker, but I will start with figuring out the task at hand. 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.