hosannabizarre Posted July 16, 2010 Posted July 16, 2010 Is there a method for changing the layer of objects (lines and circles) within a block, without using BEDIT? i.e. I'd like to be able to force all the elements within selected blocks onto a certain layer, but don't want to use BEDIT to change blocks individually. Quote
Lee Mac Posted July 16, 2010 Posted July 16, 2010 Look through the Block definition within the block table and change the element layers in there. Quote
hosannabizarre Posted July 19, 2010 Author Posted July 19, 2010 How can I access the table to which you refer? Searched the AutoCAD help for 'block tables' but found nothing on how to invoke it. I am keenly interested, and would appreciate some advice on how to access it. Kind regards Quote
Lee Mac Posted July 19, 2010 Posted July 19, 2010 Not a problem, There are two ways to access the Block Definition within the Block Table/Collection: Vanilla: (tblobjname "BLOCK" <BlockName>) Visual: (vla-item (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object) ) ) <BlockName> ) You can then proceed to iterate through the items in the Block Definition using either entnext (for the first example) or vlax-for (for the second example), and modify the properties of the objects that make up the definition. If you need more advice, just shout. Lee Quote
hosannabizarre Posted July 28, 2010 Author Posted July 28, 2010 Lee, please pardon my ignorance; I am unsure how to use the above code to access a block definition table. I've tried entering both examples at the command prompt, but this does not seem to bring up anything. I have tried loading them as .scr files, but again, this isn't working. I would love to edit multiple block definitions using a table - it sounds easier than using bedit, so I'm still just as keen. Kean Walmsley's C# code for selecting objects nested in blocks and then changing the layer (on the "Through the Interface" blog) is the closest thing I've found for what I'm after, as you can create a big selection set across multiple blocks and then change the layer of everything selected (bypassing bedit). Quote
Lee Mac Posted July 28, 2010 Posted July 28, 2010 Not a problem, here is an example function (using the VL method I posted above): (defun LM:BlockObjectstoLayer ( block layer ) (vl-load-com) ;; © Lee Mac 2010 (if (not (vl-catch-all-error-p (setq def (vl-catch-all-apply 'vla-item (list (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object) ) ) block ) ) ) ) ) (vlax-for obj def (vl-catch-all-apply 'vla-put-layer (list obj layer)) ) ) ) (defun c:test ( / e ) (if (and (setq e (car (entsel))) (eq "INSERT" (cdr (assoc 0 (entget e))))) (LM:BlockObjectstoLayer (cdr (assoc 2 (entget e))) "0") ) (command "_.regenall") (princ) ) I have included a test function that will set all objects in a selected block to layer "0". Note that there isn't too much error trapping, and it doesn't allow for the layer existing, or for dynamic blocks. But it should give an idea. Lee Quote
hosannabizarre Posted July 29, 2010 Author Posted July 29, 2010 Lee Mac you are officially an AutoCAD hero. Thanks so much for this - a very nifty bit of code. I still have traces of AutoCAD adrenaline in my blood from watching this work!!! I have a couple of requests, not sure if they're possible. 1) Right now, after entering "test", and selecting my nested object, I just keep pressing enter to repeat the command, and clicking though all the objects I need to change. Is it possible to build a 'repeat' into the code, so the user doesn't need to keep pressing enter to repeat the last command. i.e. you keeping selecting nested objects and changing the layer to 0 until you're done and then press escape?? 2) Could you get this to work such that you can change the colour, rather than layer, of the nested objects in a similar fashion (also with a repeat)? Thanks again, a million blessings upon you for your generous spirit!! Quote
Lee Mac Posted July 29, 2010 Posted July 29, 2010 Many thanks for your kind words hosannabizarre - they are appreciated and I am happy to help out. I think perhaps there is a slight misunderstanding - the test function in the above code will allow the user to select the block object and will change ALL sub objects within the block to layer "0". Were you after something different? I shall post a few options so you can see the method/pattern. Quote
Lee Mac Posted July 29, 2010 Posted July 29, 2010 Quick example for single elements: (defun c:test ( / ent ) ;; © Lee Mac 2010 (while (setq ent (car (nentselp))) (Update (SubstDXF 8 "0" (entget ent))) ) (command "_.regenall") (princ) ) (defun SubstDXF ( code value elist ) ;; © Lee Mac 2010 (entmod (subst (cons code value) (assoc code elist) elist ) ) ) (defun Update ( elist ) ;; © Lee Mac 2010 (entupd (cdr (assoc -1 elist))) ) Quote
hosannabizarre Posted July 30, 2010 Author Posted July 30, 2010 (edited) Thanks again - the single elements version works great. I would go as far as to say I love it. Coupled with the SETBYLAYER command, I am finding this tool you've made extremely useful. I can set my level colours up, and then, once I've performed the layer change, using the tool, the colours are sorted too. I think this is a valuable post, as I have seen many instances of people grumbling about not being able to modify blocks efficiently enough. I was interested to know if it's possible to get a version designed to change the colour of a nested block object, rather than the layer. So in instances where the desired colour for the block object differs from the layer colour, you can change it to what you want. Or indeed a version where you apply two changes to each selected object: i.e. change the layer of the selected object to "0" and the colour to "Red", or whatever. I am just thinking of what else is possible, as I can imagine the usefulness. If a 'change block object colour' version is easy to create, or a layer and colour version, I would sure be interested. I understand that you use your own precious time to help with these lisp concoctions, so know that I really appreciate it. Again, I am convinced this is a highly useful capability you've developed here. I will sure be using the heck out of it. I have already created a custom toolbar, with icons for all the main layers I need to impose on block objects! hbizarre Edited July 30, 2010 by hosannabizarre Quote
hunszab Posted July 30, 2010 Posted July 30, 2010 Hi all! How can I select every object that is in a specific point? To be more specific... I have blocks, so they have just one point. And I want to select a block that point is i.e. (x,y). So how can I do that? Thanks any help Quote
Lee Mac Posted July 30, 2010 Posted July 30, 2010 Hi all! How can I select every object that is in a specific point? To be more specific... I have blocks, so they have just one point. And I want to select a block that point is i.e. (x,y). So how can I do that? Thanks any help Don't double post it won't get your question answered any quicker. Quote
Lee Mac Posted July 30, 2010 Posted July 30, 2010 Thanks again - the single elements version works great. I would go as far as to say I love it. Coupled with the SETBYLAYER command, I am finding this tool you've made extremely useful. I can set my level colours up, and then, once I've performed the layer change, using the tool, the colours are sorted too. I think this is a valuable post, as I have seen many instances of people grumbling about not being able to modify blocks efficiently enough. I was interested to know if it's possible to get a version designed to change the colour of a nested block object, rather than the layer. So in instances where the desired colour for the block object differs from the layer colour, you can change it to what you want. Or indeed a version where you apply two changes to each selected object: i.e. change the layer of the selected object to "0" and the colour to "Red", or whatever. I am just thinking of what else is possible, as I can imagine the usefulness. If a 'change block object colour' version is easy to create, or a layer and colour version, I would sure be interested. I understand that you use your own precious time to help with these lisp concoctions, so know that I really appreciate it. Again, I am convinced this is a highly useful capability you've developed here. I will sure be using the heck out of it. I have already created a custom toolbar, with icons for all the main layers I need to impose on block objects! hbizarre Hi hbizarre, I'm glad you like the functions that I have demonstrated - once you have understood the concept, additional modification will be a piece of cake. I have provided a selection of functions that perform various modifications in the same vein as the above function. Please take a moment to study the code I have provided so you may better understand the process involved and if you have any questions just ask. ;; DXF for Colour = 62 ;; Code changes selected objects in a block def ;; to colour 1 (red) ;; Note: only one instance of a block need be selected ;; and all instances of the block are changed. (defun c:test1 ( / ent ) ;; © Lee Mac 2010 (while (setq ent (car (nentselp))) (Update (SubstDXF 62 1 (entget ent))) ) (command "_.regenall") (princ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DXF for Layer = 8 ;; Code changes selected objects in a block def to ;; layer "0". (defun c:test2 ( / ent ) ;; © Lee Mac 2010 (while (setq ent (car (nentselp))) (Update (SubstDXF 8 "0" (entget ent))) ) (command "_.regenall") (princ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Changing both colour to 2 and layer to "0" (defun c:test3 ( / ent ) ;; © Lee Mac 2010 (while (setq ent (car (nentselp))) (Update (SubstDXF 62 2 (SubstDXF 8 "0" (entget ent)) ) ) ) (command "_.regenall") (princ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Code changes: ;; - DXF 8 (Layer) to "0" ;; - DXF 62 (Colour) to 4 (cyan) ;; - DXF 48 (LinetypeScale) to 3.0 ;; - DXF 370 (Lineweight) to 0.30mm (defun c:test4 ( / ent ) ;; © Lee Mac 2010 (while (setq ent (car (nentselp))) (Update (SubstDXF 370 30 (SubstDXF 48 3.0 (SubstDXF 62 4 (SubstDXF 8 "0" (entget ent)) ) ) ) ) ) (command "_.regenall") (princ) ) ;; Alternatively by using mapcar: (defun c:test5 ( / ent elist ) ;; © Lee Mac 2010 (while (setq ent (car (nentselp))) (setq elist (entget ent)) (Update (last (mapcar (function (lambda ( code value ) (setq elist (SubstDXF code value elist)) ) ) '(8 62 48 370) '("0" 4 3.0 30) ) ) ) ) (command "_.regenall") (princ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Library Functions: (defun SubstDXF ( code value elist ) ;; © Lee Mac 2010 (entmod (if (assoc code elist) (subst (cons code value) (assoc code elist) elist ) (append elist (list (cons code value))) ) ) ) (defun Update ( elist ) ;; © Lee Mac 2010 (entupd (cdr (assoc -1 elist))) ) Also note that all of the above could be also achieved through the use of Visual LISP, using the various properties/methods exposed in the ActiveX COM Model. Lee Quote
saunambon654 Posted July 18, 2013 Posted July 18, 2013 It's very good for simple case. But if there are some blocks inside the block, the sub-block will be skiped. So could you upgrade to support including sub-block? > Quote
daveyboyd Posted July 24, 2013 Posted July 24, 2013 Hi Lee, I am trying to use the command for changing the block attributes but I don't know how to invoke the command. Usually I just copy everything into a txt file and change the file extension to .lsp then load through appload. The command can then be started by typing whatever its called tlen tabcord etc etc I may be missing something really obvious but I can make it work?? I have a lot of blocks with different names and different nested layers which I need to change to the same layer without editing them all individually of poss?? Can you give me a little advice please (go easy on me I don't claim to be a programmer by any means!) Quote
srinak47 Posted January 15, 2014 Posted January 15, 2014 Hi Lee,. I like this lisp but i required a small modification, since i have try correcting and i failed can you please change as i required. this lisp allows me to change all layers in the blocks to zero layer but i can able to select each block every time to changes.. insted of that i want to select all blocks at once and change it. is that possible? Not a problem, here is an example function (using the VL method I posted above): (defun LM:BlockObjectstoLayer ( block layer ) (vl-load-com) ;; © Lee Mac 2010 (if (not (vl-catch-all-error-p (setq def (vl-catch-all-apply 'vla-item (list (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object) ) ) block ) ) ) ) ) (vlax-for obj def (vl-catch-all-apply 'vla-put-layer (list obj layer)) ) ) ) (defun c:test ( / e ) (if (and (setq e (car (entsel))) (eq "INSERT" (cdr (assoc 0 (entget e))))) (LM:BlockObjectstoLayer (cdr (assoc 2 (entget e))) "0") ) (command "_.regenall") (princ) ) I have included a test function that will set all objects in a selected block to layer "0". Note that there isn't too much error trapping, and it doesn't allow for the layer existing, or for dynamic blocks. But it should give an idea. Lee Quote
Lee Mac Posted January 19, 2014 Posted January 19, 2014 Please try the following code: (defun c:b20 ( / e i l n s x ) (if (setq s (ssget '((0 . "INSERT")))) (repeat (setq i (sslength s)) (if (not (member (setq n (cdr (assoc 2 (entget (ssname s (setq i (1- i))))))) l)) (progn (setq e (tblobjname "block" n) l (cons n l) ) (while (setq e (entnext e)) (setq x (entget e)) (entmod (subst '(8 . "0") (assoc 8 x) x)) ) ) ) ) ) (command "_.regen") (princ) ) Quote
srinak47 Posted January 22, 2014 Posted January 22, 2014 (edited) Hey check out this.. i did but i cant change few things i mentioned.... Block entities are perfectly changing to "0" layer, but Block remain in same layer i wanted block also to change in "Desired Layer" or "0" Layer... And if possible Nested block and Nested Entities to "0" Layer or to "Desired Layer" thanks (defun c:norm (/ *error* adoc lst_layer func_restore-layers) (defun *error* (msg) (func_restore-layers) (vla-endundomark adoc) (princ msg) (princ) ) ;_ end of defun (defun func_restore-layers () (foreach item lst_layer (vla-put-lock (car item) (cdr (assoc "lock" (cdr item)))) (vl-catch-all-apply '(lambda () (vla-put-freeze (car item) (cdr (assoc "freeze" (cdr item))) ) ;_ end of vla-put-freeze ) ;_ end of lambda ) ;_ end of vl-catch-all-apply ) ;_ end of foreach ) ;_ end of defun (vl-load-com) (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))) ) ;_ end of vla-startundomark (if (and (not (vl-catch-all-error-p (setq selset (vl-catch-all-apply (function (lambda () (ssget '((0 . "INSERT"))) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of vl-catch-all-error-p ) ;_ end of not selset ) ;_ end of and (progn (vlax-for item (vla-get-layers adoc) (setq lst_layer (cons (list item (cons "lock" (vla-get-lock item)) (cons "freeze" (vla-get-freeze item)) ) ;_ end of list lst_layer ) ;_ end of cons ) ;_ end of setq (vla-put-lock item :vlax-false) (vl-catch-all-apply '(lambda () (vla-put-freeze item :vlax-false)) ) ;_ end of vl-catch-all-apply ) ;_ end of vlax-for (foreach blk_def (mapcar (function (lambda (x) (vla-item (vla-get-blocks adoc) x) ) ;_ end of lambda ) ;_ end of function ((lambda (/ res) (foreach item (mapcar (function (lambda (x) (vla-get-name (vlax-ename->vla-object x) ) ;_ end of vla-get-name ) ;_ end of lambda ) ;_ end of function ((lambda (/ tab item) (repeat (setq tab nil item (sslength selset) ) ;_ end setq (setq tab (cons (ssname selset (setq item (1- item)) ) ;_ end of ssname tab ) ;_ end of cons ) ;_ end of setq ) ;_ end of repeat tab ) ;_ end of lambda ) ) ;_ end of mapcar (if (not (member item res)) (setq res (cons item res)) ) ;_ end of if ) ;_ end of foreach (reverse res) ) ;_ end of lambda ) ) ;_ end of mapcar (vlax-for ent blk_def (vla-put-layer ent "0") (vla-put-color ent 0) (vla-put-lineweight ent aclnwtbyblock) (vla-put-linetype ent "byblock") ) ;_ end of vlax-for ) ;_ end of foreach (func_restore-layers) (vla-regen adoc acallviewports) ) ;_ end of progn ) ;_ end of if (vla-endundomark adoc) (princ) ) ;_ end of defun Edited January 31, 2014 by srinak47 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.