Author Topic: manipulating layers in a block  (Read 4092 times)

0 Members and 1 Guest are viewing this topic.

psuchewinner

  • Guest
manipulating layers in a block
« on: January 06, 2011, 09:20:02 AM »
Is it possible to edit the layers of entities in a block through Vlisp?
Suppose I have entities in a block that are on a layer that I dont want them to be on.  Can I put all of those entities on a layer of my choosing?

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: manipulating layers in a block
« Reply #1 on: January 06, 2011, 09:23:34 AM »
I can't tell you how; although I know that you can.
Be your Best


Michael Farrell
http://primeservicesglobal.com/

kpblc

  • Bull Frog
  • Posts: 396
Re: manipulating layers in a block
« Reply #2 on: January 06, 2011, 09:30:11 AM »
Try this:
Code: [Select]
(vl-load-com)

(defun change-layer-subent-in-block (block layer-name)
                                    ;|
block -> pointer to block reference
layer-name -> name of layer to place subentities

layer-name have to been created in file. All layers have to bu unlocked and thaw
|;
  (cond
    ((not block)
     (if (= (type (setq block (vl-catch-all-apply
                                (function
                                  (lambda ()
                                    (ssname (ssget "_+.:S:E" '((0 . "INSERT"))) 0)
                                    ) ;_ end of lambda
                                  ) ;_ end of function
                                ) ;_ end of vl-catch-all-apply
                        ) ;_ end of setq
                  ) ;_ end of type
            'ename
            ) ;_ end of =
       (change-layer-subent-in-block
         (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
                   (cdr (assoc 2 (entget block)))
                   ) ;_ end of vla-item
         layer-name
         ) ;_ end of change-layer-subent-in-block
       ) ;_ end of if
     )
    ((and (= (type block) 'ename)
          (= (cdr (assoc 0 (entget block))) "INSERT")
          ) ;_ end of and
     (change-layer-subent-in-block (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
                                             (cdr (assoc 2 (entget block)))
                                             ) ;_ end of vla-item
                                   layer-name
                                   ) ;_ end of change-layer-subent-in-block
     )
    ((and (= (type block)
             'vla-object
             (wcmatch (strcase (vla-get-objectname block)) "*BLOCKREF*")
             ) ;_ end of =
          ) ;_ end of and
     (change-layer-subent-in-block (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
                                             (vla-get-name block)
                                             ) ;_ end of vla-item
                                   layer-name
                                   ) ;_ end of change-layer-subent-in-block
     )
    ((and (= (type block)
             'vla-object
             (wcmatch (strcase (vla-get-objectname block)) "*BLOCKDEF*")
             ) ;_ end of =
          ) ;_ end of and
     (vlax-for sub block
       (vl-catch-all-apply
         (function
           (lambda ()
             (vla-put-layer sub layer-name)
             ) ;_ end of lambda
           ) ;_ end of function
         ) ;_ end of vl-catch-all-apply
       ) ;_ end of vlax-for
     )
    ) ;_ end of cond
  ) ;_ end of defun
Sorry for my English.

Lee Mac

  • Seagull
  • Posts: 12924
  • London, England
Re: manipulating layers in a block
« Reply #3 on: January 06, 2011, 09:30:51 AM »
Consider this code perhaps:

Code: [Select]
;;---------------=={ Apply to Block Objects }==---------------;;
;;                                                            ;;
;;  Applies a supplied function to all objects in a block     ;;
;;  definition.                                               ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  _blockname - name of block to apply function              ;;
;;  _function  - function to apply to all objects in block    ;;
;;------------------------------------------------------------;;
;;  Returns:  T if block is found, else nil                   ;;
;;------------------------------------------------------------;;

(defun LM:ApplytoBlockObjects ( _blockname _function )
  (vl-load-com)
  ;; © Lee Mac 2010
  (
    (lambda ( _function / def ) 
      (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))
                  )
                  _blockname
                )
              )
            )
          )
        )
        (vlax-for obj def (_function obj))
      )
    )
    (eval _function)
  )
)


;; Test Function to Move all Objects in a Block to Layer "0"

(defun c:test ( / ss l )

  (if (setq ss (ssget "_+.:E:S" '((0 . "INSERT"))))
    (progn   
      (LM:ApplytoBlockObjects (cdr (assoc 2 (setq l (entget (ssname ss 0)))))
        (function
          (lambda ( obj ) (vla-put-Layer obj "0"))
        )
      )
      (if (= 1 (cdr (assoc 66 l)))
        (vl-cmdf "_.attsync" "_N" (cdr (assoc 2 l)))
      )
    )
  )

  (princ)
)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: manipulating layers in a block
« Reply #4 on: January 06, 2011, 09:31:47 AM »
Just so you get what you ask for.

Do you want only one instance of the block to change .. or all and future inserts. ?

Do you want the color and linetyle retained or to match the layer you're nominating. ?

How are you proposing identifying the entities you want to change .. is it simply a matter of " if they're on layer X move them to layer Y " ??
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

psuchewinner

  • Guest
Re: manipulating layers in a block
« Reply #5 on: January 06, 2011, 10:31:04 AM »
Probably something to fix it as needed.  Sometimes blocks from old drawings are layered differently.  When we go to purge the bad layer and we find that it is in an instance of an old block, it is kind of a pain to fix it, especially if the block is used in more than one place.  I know that we could just update the block but that would not be a "cool" enough way to do it.  Plus I am kinda bored and want to learn something new.

kpblc

  • Bull Frog
  • Posts: 396
Re: manipulating layers in a block
« Reply #6 on: January 06, 2011, 11:50:56 AM »
Sorry for my English.

psuchewinner

  • Guest
Re: manipulating layers in a block
« Reply #7 on: January 06, 2011, 02:03:45 PM »
Thanks all for the replies and thanks Lee for the code, it does kinda what i want.
Let me ask this......
I can access the block from the block collection but how do I access the layers of the individual elements of the block?

Lee Mac

  • Seagull
  • Posts: 12924
  • London, England
Re: manipulating layers in a block
« Reply #8 on: January 06, 2011, 02:16:36 PM »
I can access the block from the block collection but how do I access the layers of the individual elements of the block?

In reference to my code, the function you supply to the ApplytoBlockObjects function takes one argument, namely an object within the block defintion. With this in mind, we could call it with the following example test function to print the layers of each object to the command line.

Code: [Select]
;; Test function to print the layer of all objects in the definition of a selected block

(defun c:test ( / ss )

  (if (setq ss (ssget "_+.:E:S" '((0 . "INSERT"))))   
    (LM:ApplytoBlockObjects (cdr (assoc 2 (entget (ssname ss 0))))
      (function
        (lambda ( obj ) (print (vla-get-Layer obj)))
      )
    )
  )
  (princ)
)

As to the HOW the code works: the Block Definition within the Block Collection is a Collection itself composed of all the objects making up the block - hence upon retrieving the definition from the block collection, one can iterate through it using vlax-for to access each object in the definition.
« Last Edit: January 06, 2011, 02:20:42 PM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12924
  • London, England
Re: manipulating layers in a block
« Reply #9 on: January 06, 2011, 02:34:14 PM »
Reading through my last post, I realise how confusing my wording is...

Perhaps this is a better example to learn from:

Code: [Select]
[color=green];; This is a VLA Collection of all
;; Block definitions in the Active Drawing[/color]

(setq BlockCollection
  (vla-get-Blocks
    (vla-get-ActiveDocument
      (vlax-get-acad-object)
    )
  )
)
[color=green]
;; Note that the ModelSpace and PaperSpace
;; objects are also block definitions  containing
;; all the objects appearing in Model/Paper Space and
;; will hence appear in this collection.

;; Luckily we can identify these from other blocks
;; using the isLayout property.
[/color]

[color=green];; Now let's retrieve a specific block
;; definition from this collection

;; Prompt the user to Select a Block[/color]

(setq Entity (car (entsel "\nSelect Block: ")))

[color=green];; Convert it to a VLA-Object:[/color]

(setq VLAObject (vlax-ename->vla-object Entity))

[color=green];; Retrieve the EffectiveName, if possible

;; We use the EffectiveName, as, if the block
;; is dynamic and the visibility state of the
;; Insert (Block Reference) has changed, it will
;; appear as an Anonymous Block with name *U##[/color]

(setq BlockName
  (if (vlax-property-available-p VLAObject 'EffectiveName)
    (vla-get-EffectiveName VLAObject)
    (vla-get-Name VLAObject)
  )
)

[color=green];; Now to locate the Block Definition of the
;; selected Block Reference.

;; Note the wording: the Inserted block is a
;; Reference of the Definition.

;; Think about it this way: the Definition is the Block Blueprints
;; and the Reference or Insert is the construction
;; from these Blueprints - hence if we change the
;; block Defintion all the existing and future
;; References will reflect the change.
[/color]
(setq BlockDefintion (vla-Item BlockCollection BlockName))

[color=green];; This Block Definition is a collection in itself
;; containing all the objects making up the definition

;; With this knowledge, we can iterate through it
;; as we would with any other VLA Collection:[/color]

(vlax-for Object BlockDefinition

  (print (vla-get-ObjectName object))
 
)


psuchewinner

  • Guest
Re: manipulating layers in a block
« Reply #10 on: January 06, 2011, 04:13:48 PM »
Very good explanation.  Thank you for taking the time to teach me.  It is starting to sink in!

Lee Mac

  • Seagull
  • Posts: 12924
  • London, England
Re: manipulating layers in a block
« Reply #11 on: January 06, 2011, 04:35:38 PM »
Very good explanation.  Thank you for taking the time to teach me.  It is starting to sink in!

You're very welcome  :-)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: manipulating layers in a block
« Reply #12 on: January 06, 2011, 05:07:06 PM »
Just so you get what you ask for.

Do you want only one instance of the block to change .. or all and future inserts. ?

Do you want the color and linetyle retained or to match the layer you're nominating. ?

How are you proposing identifying the entities you want to change .. is it simply a matter of " if they're on layer X move them to layer Y " ??

psuchewinner, thanks for taking the time to answer my questions.   :|
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

psuchewinner

  • Guest
Re: manipulating layers in a block
« Reply #13 on: January 07, 2011, 08:03:31 AM »
The block with the messed up layer is rarely inserted and this is the first time that I have come accross it.  Basically, I want to now is select the block and move the items on layer "x" to layer "y".  I havent really thought to much about any future instances but for the most case any block that has the wrong layer came from an older drawing, which is not supposed to happen.  Maybe when I get my head wrapped around this part of it, I can run a query for the bad layer and find any blocks that have it in it and attack it that way.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: manipulating layers in a block
« Reply #14 on: January 08, 2011, 10:07:28 PM »
Just so everyone knows ACAD2000 will create a block with the CURRENT layer embedded in the (0 . "ENDBLK") entity.
This will stop it from purging that layer.
See a copy of FixBlock.lsp
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: manipulating layers in a block
« Reply #15 on: January 08, 2011, 11:23:16 PM »
Just so everyone knows ACAD2000 will create a block with the CURRENT layer embedded in the (0 . "ENDBLK") entity.
This will stop it from purging that layer.
See a copy of FixBlock.lsp


Can't recall the AC2000 version Alan, but I have 2 versions by Owen Wengerd ( http://www.manusoft.com ) dated 1996 and 1998 ... from CompuServe era :)

added:
In fact, Owen still has a version on his site
http://www.manusoft.com/software/freebies/lisp.html

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: manipulating layers in a block
« Reply #16 on: January 09, 2011, 08:31:20 AM »
That's the one Kerry. Thanks for the link.
I modified my copy to remove '(71 . 1)   It was in 2004 I think but I could not find the thread.

Not sure when that ACAD bug went away, maybe version 2002?
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.