Jump to content

Change layer of Block Elements


hosannabizarre

Recommended Posts

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

  • 2 weeks later...

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).

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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!!

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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)))
)

Link to comment
Share on other sites

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 by hosannabizarre
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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. :glare:

Link to comment
Share on other sites

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

Link to comment
Share on other sites

  • 2 years later...

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?

>

Link to comment
Share on other sites

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!)

Link to comment
Share on other sites

  • 5 months later...

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

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

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 by srinak47
Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...