TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: V-Man on January 20, 2006, 08:55:14 PM
-
Ok,
I have many blocks, so I need a automated routine to search the drawing for a particular block, once found I need to get all of the attributes in the block layer to change to a different layer. How do I go around doing this?
-
Still stuck. I have tried this code but it does not seem to work..
(defun c:alcc ()
(setq attl(getstring "\nEnter new attribute layer: "))
(command "attedit" "y" "*" "*" "*" "c" pause pause)
(while
(= 1 (logand (getvar "cmdactive") 1))
(command "l" attl "n")
);;; end while
)
-
Hi Don,
Give this a whirl......
(defun c:att2layr (/ layr ss atts idx)
(vl-load-com)
(if (and (setq layr (getstring "\nLayer for attributes: "))
(setq ss (ssget '((0 . "INSERT")(66 . 1))))
)
(progn
(setq idx -1)
(while (setq ent (ssname ss (setq idx (1+ idx))))
(setq atts (vlax-invoke (vlax-ename->vla-object ent) 'getattributes))
(foreach att atts
(vla-put-layer att layr)
)
)
)
)
;;Note that there is no error trapping included in this example!
;;At the bare minimum, a check should be made for the existence of the destination layer.
(princ)
)
-
Great, Question, after running your code I explode the block and manually select on an attribute and when I do that it still says it's the old layer. Basically, I am trying to put all of the attributes of my block on a specific layer so that I may PURGE out the unwanted layers.
-
That's because the block defenition hasn't changed.
If you want to get rid of a layer without losing objects you can better use the LAYTRANS command, or use LYDELMRG.LSP from the express tools.
-
If you want to get rid of a layer without losing objects you can better use the LAYTRANS command, or use LYDELMRG.LSP from the express tools.
Neither of these options will work. I have tried them with no success. LayTrans will not work because the target layer that I want the attributes to be on already exist in the block itself. As for LayDel, it will not work at all. I guess I need the block Definition to change so that I may purge out the unwanted layers.
-
It doesn't matter if the layer already exists.
If you want to use lisp, try this (http://www.theswamp.org/lilly_pond/crank/LayMerge.lsp) LayMerge routine.
It is a modified version of the LYDELMRG.LSP that came with Acad2004.
(laymerge "merge" "SourceLayer" DestLayer")
-
Thanks Crank, that did work. Much appreciated...
TY
-
Ooops too late. :?
I just threw this together, but try it.
The block selection code needs work.
Exclude all but one or add code to step through the ss.
My code changes the block definition & jeff's changes all the Inserts.
(defun c:att2layr (/ layr ss atts idx bname blk)
(vl-load-com)
(cond
((or (not (setq layr (getstring t "\nLayer for attributes: ")))
(not (tblsearch "LAYER" layr))
)
(prompt "\nERROR in layer name.")
)
((not (and
(not (prompt "\nSelect the block to change."))
(setq ss (ssget '((0 . "INSERT") (66 . 1))))
(setq ent (ssname ss 0))
(< (sslength ss) 2) ; only one pick allowed
)
)
(prompt "\nERROR in block selection.")
)
(t
(setq ent (ssname ss 0))
(setq ent (tblobjname "BLOCK" (setq bname (cdr (assoc 2 (entget ent)))))
blk ent
)
(setq entl (entget ent))
(while (and ent
(/= "SEQEND" (cdr (assoc 0 (setq entl (entget ent)))))
)
(if (= (cdr (assoc 0 entl)) "ATTDEF")
(entmod (subst (cons 8 layr) (assoc 8 entl) entl))
)
(setq ent (entnext ent))
)
(entupd blk)
;; Change the Inserts, by Jeff
(vl-load-com)
(setq ss (ssget "x" (list '(0 . "INSERT") '(66 . 1) (cons 2 bname))))
(setq idx -1)
(while (setq ent (ssname ss (setq idx (1+ idx))))
(setq atts (vlax-invoke (vlax-ename->vla-object ent) 'getattributes))
(foreach att atts
(vla-put-layer att layr)
)
)
)
)
(princ)
)
-
ummm... refedit the block then attsync ??
-
In ACAD 2000 the refedit won't let you at the attributes to change the layer.
Or did I miss something?
Good to see ya Randy. :-)
-
R2002 you get a dialog box that you check the "Display attributes definitions for editting" box and attributes become refeditable. once complete use attsync to force all block instances to the new block definition.
-
Well that's just too easy. :-)
-
It is pretty easy with lisp too
The syntax is (blockattlay "MyblockName" "NewAttributeLayer")
Peter
(defun BlockAttLay (strBlockName strLayerName / intCount entSelection objSelection ssSelections )
(setq ssSelections (ssget "X" (list (cons 2 strBlockName))))
(repeat (setq intCount (sslength ssSelections))
(setq intCount (1- intCount)
entSelection (ssname ssSelections intCount)
objSelection (vlax-ename->vla-object entSelection)
)
(compoundObject objSelection strLayerName)
)
(setq objBlock (vla-item
(vla-get-blocks
(vla-get-activedocument
(vlax-get-acad-object)
)
)
strBlockName
)
)
(vlax-for objItem objBlock
(if (= (vla-get-objectname objItem) "AcDbAttributeDefinition")
(vla-put-layer objItem strLayerName)
)
)
(princ)
)
(defun CompoundObject (objItem strLayerName / entItem2)
(if (wcmatch (setq strObjectName (vla-get-objectname objItem))
"AcDbBlockReference,AcDbMInsertBlock"
)
(if (= (vla-get-hasattributes objItem) :vlax-true)
(progn
(setq entItem2 (vlax-vla-object->ename objItem))
(while (/= (cdr (assoc 0 (entget entItem2))) "SEQEND")
(setq objItem2 (vlax-ename->vla-object entItem2))
(vla-put-layer objItem2 strLayerName)
(setq entItem2 (entnext entItem2))
)
(setq objItem2 (vlax-ename->vla-object entItem2))
(vla-put-layer objItem2 strLayerName)
)
)
)
)
-
uh, wont battman do the same thing? not the winged character...
i thought battman had a global editor in it.
-
Peter
Looks like you changed the attribute def in the BLOCK but changed all objects within all the INSERTS
including the SEQEND to the new layer.
-
Well that's just too easy. :-)
those of us with no discernible lisp skills have to resort to using the commands available :-)
-
Peter
Looks like you changed the attribute def in the BLOCK but changed all objects within all the INSERTS
including the SEQEND to the new layer.
The routine does change the block definition and it change the attribute entities, but not all of the objects in the block.
Using the (entnext (car (entsel))) selecting a block with attributes will return the first attribute in a block.
The routine I shared switches the attribute defintions in the blocks collection and it changes the existing block instances in a drawing. It changes the seqend (nasty little problem in drawings) to the desired layer. If you don't there are drawings that when you change the layer of the block, the seqend used to not change. If you use activex to change the attributes it can also not change. The only way to get at it was through the entnext procedure. hence the code above.
Peter :-o
-
Peter
Looks like you changed the attribute def in the BLOCK but changed all objects within all the INSERTS
including the SEQEND to the new layer.
Hi Alan, glad to meet you again
I agree with you about "SEQEND"...
I wrote similar routine but I have feeling that I missed
something here (include locked layers)
Are you can to explain to me where I mistaken seriously?
(defun chatlay (bname lname / a adoc atts axss b
blkcol blkdef lname ss)
(or (vl-load-com))
(or adoc
(setq adoc (vla-get-activedocument
(vlax-get-acad-object)
)
)
)
(setq blkcol (vla-get-blocks adoc))
(if (setq ss (ssget "X" (list (cons 2 bname))))
(progn
(setq axss (vla-get-activeselectionset adoc))
(vlax-for a axss
(if (eq :vlax-true (vla-get-hasattributes a))
(progn
(setq atts (vlax-invoke a 'Getattributes))
(foreach at atts
(vl-catch-all-apply
(function (lambda ()
(progn
(vla-put-layer at lname)
(vla-update at)
)
)
)
)
)
(vla-update a)
(setq blkdef (vla-item blkcol bname))
(vlax-for b blkdef
(if (eq "AcDbAttributeDefinition" (vla-get-objectname b))
(vl-catch-all-apply
(function (lambda ()
(vla-put-layer b lname)
)
)
)
)
)
)
)
)
)
(prompt
"\nHere aren't block insertions with the same block name ...\n"
)
)
(princ)
)
;CaLL : (chatlay "MYBLOCK" "NEWLAYER")
My apologies to Peter for an offtopic
~'J'~
-
OK Peter, I found my mistake. :-(
When I read through you code it looked to me as though you were changing all
objects in the Insert to the new layer. Which is what you were doing.
My mistake was not remembering that the actual objects except the attributes
are not in the INSERT but in the BLOCK definition. This BLOCK/INSERT thing has
always caused my grief. After stepping through the code I see that as you
process each object in the INSERT definition none of the objects show up except
the attributes. But when you step through the BLOCK definition the all the objects
show up but you filter for the attribute definition so only it get changed.
Sorry for the confusion, it was all mine. 8-) I know most of this stuff is automatic
to you with your depth of knowledge but I'm not there yet.
Here is you code commented by me as I worked through it.
;; By Peter J
;; ** comments by CAB
(defun BlockAttLay (strBlockName strLayerName / intCount entSelection objSelection ssSelections )
;;========================
;; change all Inserts
;;========================
(setq ssSelections (ssget "X" (list (cons 2 strBlockName))))
(repeat (setq intCount (sslength ssSelections))
(setq intCount (1- intCount)
entSelection (ssname ssSelections intCount)
objSelection (vlax-ename->vla-object entSelection)
)
;; go change the INSERT entities
(compoundObject objSelection strLayerName)
)
;; Now get the block
(setq objBlock (vla-item
(vla-get-blocks
(vla-get-activedocument
(vlax-get-acad-object)
)
)
strBlockName
)
)
;;==========================================
;; change the block attributes entities
;;==========================================
(vlax-for objItem objBlock ; step through the block objects
;; only if it is an attribute
(if (= (vla-get-objectname objItem) "AcDbAttributeDefinition")
(vla-put-layer objItem strLayerName) ; change the layer
)
)
(princ)
)
;;==============================================
;; sub to change sub entities in the Insert
;;==============================================
(defun CompoundObject (objItem strLayerName / entItem2)
;; make sure it's a block
(if (wcmatch (setq strObjectName (vla-get-objectname objItem))
"AcDbBlockReference,AcDbMInsertBlock"
)
;; make sure it has attibutes
(if (= (vla-get-hasattributes objItem) :vlax-true)
(progn
(setq entItem2 (vlax-vla-object->ename objItem))
;; step through the objects within the Insert definition
;; but stop at seqend
(while (/= (cdr (assoc 0 (entget entItem2))) "SEQEND")
(setq objItem2 (vlax-ename->vla-object entItem2))
(vla-put-layer objItem2 strLayerName) ; change the layer
(setq entItem2 (entnext entItem2)) ; next item in the database
)
;; next two lines change the seqend layer
(setq objItem2 (vlax-ename->vla-object entItem2))
(vla-put-layer objItem2 strLayerName)
)
)
)
)
-
Fatty,
Glad to see you here.
I think you should be asking Peter. :)
The only way to get at it was through the entnext procedure.
I think that answered your question.
-
Fatty,
Glad to see you here.
I think you should be asking Peter. :)
The only way to get at it was through the entnext procedure.
I think that answered your question.
Yes you are right, I think also,
thank you for an explanation
Fatty