Lisp for Attribute to text within a block

Lisp for Attribute to text within a block

Anonymous
Not applicable
5,522 Views
27 Replies
Message 1 of 28

Lisp for Attribute to text within a block

Anonymous
Not applicable

Hallo everybody

 

 

I found this great lisp on internet converting attributes into text

This routine will get all the attributes in a dwg ans make them into text except for attributes inside a block.

what do i need to do for this routine to make it work with block attributes as well?

 

 

(defun c:AttDef2Text (/ ActDoc LayoutCol tmpLayoutBlk)
 ; Changes attdef entities (attributes that haven't been put into a block) into dtext

 (vl-load-com)
 (setq ActDoc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
 (vla-StartUndoMark ActDoc)
 (setq LayoutCol (vla-get-Layouts ActDoc))
 (vlax-for LayoutObj LayoutCol
 (setq tmpLayoutBlk (vla-get-Block LayoutObj))
 (vlax-for Obj tmpLayoutBlk
 (if (= (vla-get-ObjectName Obj) "AcDbAttributeDefinition")
 (progn
 (setq TextObj (vla-AddText tmpLayoutBlk (vla-get-textString Obj) (vla-get-InsertionPoint Obj) (vla-get-Height Obj)))
 (vla-put-Alignment TextObj (vla-get-Alignment Obj))
 (if (/= (vla-get-Alignment TextObj) 0)
 (vla-put-TextAlignmentPoint TextObj (vla-get-TextAlignmentPoint Obj))
 )
 (vla-put-Backward TextObj (vla-get-Backward Obj))
 (vla-put-Layer TextObj (vla-get-Layer Obj))
 (vla-put-Normal TextObj (vla-get-Normal Obj))
 (vla-put-ObliqueAngle TextObj (vla-get-ObliqueAngle Obj))
 (vla-put-Rotation TextObj (vla-get-Rotation Obj))
 (vla-put-ScaleFactor TextObj (vla-get-ScaleFactor Obj))
 (vla-put-StyleName TextObj (vla-get-StyleName Obj))
 (vla-put-UpsideDown TextObj (vla-get-UpsideDown Obj))
 (vla-Delete Obj)
 )
 )
 )
 )
 (vla-EndUndoMark ActDoc)
 (princ)
 )

Kind regards

 

0 Likes
5,523 Views
27 Replies
Replies (27)
Message 2 of 28

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

I found this great lisp on internet converting attributes into text

This routine will get all the attributes in a dwg ans make them into text except for attributes inside a block.

what do i need to do for this routine to make it work with block attributes as well?

.... 


Before considering how that might be done, a major question arises:

 

Suppose you have a Block inserted more than once, with different values  assigned to the same Attribute in the different insertions [the main purpose  of Attributes, after all].  For example, an Attribute whose tag is "Name" is set to "Bob" in one Block insertion, "Carol" in another, "Ted" in another, and "Alice" in another.

 

After your desired routine has run, what should those Text elements in the Block say?  Should it be the tag, i.e. "Name"?  Or do you want the different ones to remain different?  That can't be done while retaining one  Block definition, because Text in a Block must be the same in every insertion.  So presumably they would all say which name that Attribute was set to in the last Block processed -- they would all  be [for example] "Alice."

 

If you want them to remain different, each Block would have to become its own lone insertion of a different Block name  [which can be done].  But if they're ultimately Blocks with only one insertion each, there's no point in their being Blocks, one of the main benefit of which is the memory savings in repetitive  use.  Given that, look into using the BURST Express Tool, which will turn Attributes into Text with the value that was assigned to the Attribute [but the Blocks will Exploded].

Kent Cooper, AIA
0 Likes
Message 3 of 28

Anonymous
Not applicable

Hi @Kent1Cooper

 

 

The answer to your questions is simple

 

There is only 1 block ( 100% for sure )

The attribute VALUE is the text we want to see back in the text object
The attribute needs to be deleted

It can be either TEXT or MTEXT


Can this be done?

0 Likes
Message 4 of 28

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

There is only 1 block ( 100% for sure )

The attribute VALUE is the text we want to see back in the text object
The attribute needs to be deleted

It can be either TEXT or MTEXT


Can this be done?


Certainly [though I can't start into it immediately].  If the code in Post 1 is for all  "loose" Attribute Definitions in a drawing, are you talking about doing this to all  Blocks in a drawing, or would the User select  one [or maybe more than one], or is it a Block of a specific known name that could be built into the routine?

Kent Cooper, AIA
0 Likes
Message 5 of 28

Anonymous
Not applicable

There is a specific name for the block so something like this can be coded

The code in pos 1 will apply to ALL "loose" attributes but i need it to apply to attibutes within a named block.

 

Please make auto select based on hard coded name

 

 

0 Likes
Message 6 of 28

Anonymous
Not applicable
Maybe BURST command (Express Tools)
0 Likes
Message 7 of 28

DGRL
Advisor
Advisor

@Anonymous

 

Burst does not work for what he wants

Or do you know how to burst entities within a block?

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 8 of 28

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Maybe BURST command (Express Tools)

@DGRL wrote:

 

Burst does not work for what he wants

Or do you know how to burst entities within a block?


As I already suggested in Post 2, BURST does  do what they want [as I read the request] -- it converts Attribute definition objects into Text whose content is the values that the Attributes had assigned to them -- except  that the pieces would no longer be a Block.  But it's just occurred to me to check this, and it turns out to be true, that as with EXPLODE, the pieces of what was the Block become the Previous selection set.  @Anonymous, would a routine that BURSTs that Block, and then redefines  it using the previous Block's insertion point and the Previous selection for the contents, work for you?  In order for the new Block definition to be truly the same as the old [if that's important] except for  the former value-assigned Attribute becoming Text, it would need the original Block to always be Inserted at scales of 1 and rotation of 0, and all the Layers of the pieces would need to be thawed and turned on and unlocked.  BURST is an Express Tool, not a command, so it can't be applied with a (command) function as EXPLODE can, but I think there's a way to apply it [it's not something I've done, but I think I recall it coming up in this Forum somewhere].

Kent Cooper, AIA
0 Likes
Message 9 of 28

DGRL
Advisor
Advisor

@Kent1Cooper wrote:

@Anonymous wrote:

Maybe BURST command (Express Tools)

@DGRL wrote:

 

Burst does not work for what he wants

Or do you know how to burst entities within a block?


As I already suggested in Post 2, BURST does  do what they want [as I read the request] -- it converts Attribute definition objects into Text whose content is the values that the Attributes had assigned to them -- except  that the pieces would no longer be a Block.  But it's just occurred to me to check this, and it turns out to be true, that as with EXPLODE, the pieces of what was the Block become the Previous selection set.  @Anonymous, would a routine that BURSTs that Block, and then redefines  it using the previous Block's insertion point and the Previous selection for the contents, work for you?  In order for the new Block definition to be truly the same as the old [if that's important] except for  the former value-assigned Attribute becoming Text, it would need the original Block to always be Inserted at scales of 1 and rotation of 0, and all the Layers of the pieces would need to be thawed and turned on and unlocked.  BURST is an Express Tool, not a command, so it can't be applied with a (command) function as EXPLODE can, but I think there's a way to apply it [it's not something I've done, but I think I recall it coming up in this Forum somewhere].


@Kent1Cooper Please dont get me wrong i dont want to be rude to you But 276040 Clearly says WITHIN a block right and not "bursting" the block?

thats why i said that burst does not works for what he wants and that is to "burst" the ATT inside the block and not the whole block itself.

Or am i wrong?

Again i just want it to be clear and not insult you in any way 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 10 of 28

Anonymous
Not applicable

Hi 

 

Yes that would work!!
What I want is this 

 

1. block contains attributes and a value

2. the attributes needs to be "converted" into text or mtext
    Does not really matters but if possible the routine should be able to convert to TEXT or MTEXT

3. if needed to explode block please redefine it as you proposed i.e block with attributes is block with text ( everything else will remain the same ) 

 

if needed any more information please let me know 

0 Likes
Message 11 of 28

Kent1Cooper
Consultant
Consultant

@DGRL wrote:

....

@Kent1Cooper Please dont get me wrong i dont want to be rude to you But 276040 Clearly says WITHIN a block right and not "bursting" the block?

thats why i said that burst does not works for what he wants and that is to "burst" the ATT inside the block and not the whole block itself.

Or am i wrong? ....


I was after the desired end result, which is, agreed, ultimately that the Attribute is converted to Text within the Block, but through the temporary intermediate  step of BURSTing.  The Block would not remain disassembled.

 

Before posting that, I had tried some things to convert an Attribute inside  a Block insertion to Text and assign the value on the Attribute as the Text content.  I went through things like (subst)/(entmod) methods, manipulating the Attribute data to suit Text data entries, and/or (entmake)ing the Text and deleting the Attribute, but an Attribute object within a Block insertion seems to be quite a different animal from an Attribute Definition object outside one.  I didn't try going through REFEDIT or BEDIT, not being as sure how to move through the Block's contents that way with AutoLisp functions, but maybe that can work.  It would still require a conversion or replacement of some kind -- you can't EXPLODE or  BURST an Attribute Definition into Text, the way you can Mtext.

 

I hadn't found the right way [yet], and if there is one, it would have to be applied to each Attribute in turn when there are several.  It just seemed to me that the BURST-and-redefine approach was going to be a lot easier -- BURST simply because it does the Attribute-to-Text conversion, and all at once if there are more than one [let it serve as a "sub-routine"], then redefine so that the replacement Text gets put back within the Block again.  Even though it passes through a condition they don't want as the end result, on the way to getting there, it should get to what they want to achieve in the end.

 

But as with so many other things in AutoCAD, there are bound to be other ways to go about it.

Kent Cooper, AIA
0 Likes
Message 12 of 28

Anonymous
Not applicable

hi

 

if the burst-redefine approach is the cheapest way to get what I need then why not going that way?

in then end the block name needs to remain the same so a purge would be needed before redefining I guess

except the change of attributes into text everything else remains the same.


@DGRL
In the end burst might do indeed what I need 
It just depends on how you approach the way of coding 

 

 

 

0 Likes
Message 13 of 28

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

in then end the block name needs to remain the same so a purge would be needed before redefining I guess

.... 


No Purge should be necessary.  The same Block name can be used [answering Yes to the question of whether to redefine it].  I may play with that in the next few days, but not immediately.

Kent Cooper, AIA
0 Likes
Message 14 of 28

DGRL
Advisor
Advisor

@Anonymous and @Kent1Cooper


I gave it a try and made this quick and expensive routine to start with as basis ( NOT READY YET )
This routine does the following

 

 

It selects a block based on name

Explodes it

Get all entities as selection set

Undo the explode ;; THIS NEEDS TO BE FIXED COZ AFTER UNDO SELECTION SET IS NIL
Select block again and burst

make new selection set (ONLY CONTAINS ATTRIBUTES AS BURTS ONLY GIVES THIS BACK AS SELECTION SET)

Deletes all the bursted attributes

Entmakes block with all entities

 

 

Things that needs to be fixed in this LISP

 

1. delete all entities from first selection set after bursting

2. insertion point is now at 0,0,0 and not original insertion
3. block name is now anonymous and not the same

4. Text does not contain field that is linked to DWGPROP


Sorry I am a noob if it comes to coding in lisp but I gave it a shot since I wanna learn

@ all skilled coders like @Kent1Cooper Please don't be to hard on me I know this lisp is very expensive atm

 

(defun c:ATT2TEXT ()

;(setq insertp (cdr (assoc 10 (entget (ssname (ssget "_X" '((2 . "Titelblok AFS11"))) 0)))))
;
(setq ss1 (ssget "_X" (list (cons 2 blk))))
  (setq i -1)
  (setq ename (ssname ss1 (setq i (1+ i))))
    (setq elist (entget ename))
    (command "explode" ss1)
 (setq ss1 (ssget "_P"))
   ; (setq elist (append elist (list (entget (entlast)))))
   
  (setq index 0);<----- indexed at 0 
(repeat (sslength ss1)
(setq Data (ssname ss1 index));<-- wherein 0 is the first element on the selectionset
(setq EntityData (entget DATA));<---- Entity properties data
(setq EntityData1 DATA);<---- Entity properties data
(print EntityData)
(setq fexp (append (list EntityData)fexp))
(setq fexp1 (append (list EntityData1)fexp1))
(setq index (1+ index)));<--- increment index number for next loop 
 ; 
;(foreach a fexp (entmake a))
(command "undo" 1)

(if (setq ss (ssget "_X" (list (cons 2 blk))))
    (progn
      (sssetfirst nil ss)
      (c:burst)
    )
 )
(setq ssa (ssget "_P"))
(if ss1 (command "_.Erase" ss1 ""))

(setq index 0);<----- indexed at 0 
(repeat (sslength ssa)
(setq Data (ssname ssa index));<-- wherein 0 is the first element on the selectionset
(setq EntityData (entget DATA));<---- Entity properties data
(setq EntityData2 DATA);<---- Entity properties data
(print EntityData)
(setq fexpp (append (list EntityData)fexpp))
(setq fexpp1 (append (list EntityData2)fexpp1))
(setq index (1+ index)));<--- increment index number for next loop
;
(if ssa (command "_.Erase" ssa ""))
;(foreach a fexpp (entmake a))

(entmake '((0 . "Block")
 (100 . "AcDbEntity")
 (8 . "0")
 (100 . "AcDbBlockBegin")
 (2 . "*U")
 (70 . 1)
 (10 0.0 0.0 0.0)
 )
 )
 (foreach a fexp (entmake a))
 (foreach a fexpp (entmake a))
 
 (setq BlockName (entmake '((0 . "ENDBLK"))))
(entmake (list '(0 . "INSERT")
 '(100 . "AcDbEntity")
 '(100 . "AcDbBlockReference")
 (cons 2 BLockName)
 ;(cons 10 insertp)
 '(10 0.0 0.0 0.0)
 )
 )

 );end defun ATT2TEXT
(c:ATT2TEXT)

 

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 15 of 28

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

if the burst-redefine approach is the cheapest way to get what I need then why not going that way?

.... 


Give this a try [lightly tested]:

 

;; To convert the Attributes in a Block insertion into Text with the Attributes' values,
;; in a drawing with ONE Insertion of the subject Block [which must be defined to
;; allow Exploding], in the current space, at scales of 1 and rotation of 0.

(defun C:A2T (/ blkss blk blkref ins)
  (setq osm (getvar 'osmode))
  (setvar 'osmode 0)
  (if (setq blkss (ssget "_X" '((0 . "INSERT") (2 . "YourBlockName"))))
    (progn ; then
      (setq blk (ssname blkss 0))
      (command "_.copy" blk "" "0,0" "0,0"); for MATCHPROP later [original will be gone]
      (setq blkref (entlast) ins (cdr (assoc 10 (entget blk))))
      (sssetfirst nil blkss); pre-selection for use by BURST
      (C:BURST)
      (command
        "_.block" "YourBlockName" "_yes" ins "_previous" ""
        "_.insert" "YourBlockName" "_scale" 1 "_rotate" 0 ins
        "_.matchprop" blkref (entlast) "" ; for Layer, any other properties
        "_.erase" blkref ""
      ); command
    ); progn
  ); if
  (setvar 'osmode osm)
  (princ)
); defun

 

Oddly, I originally didn't save and reset OSMODE, but had a couple of "_none" Osnap calls associated with that 'ins' insertion-point variable, but for some reason those threw it off.  But this way worked.  Also oddly, in one test there ended up being two pieces of Text in the redefined Block, but that was coming somehow from the result of the BURST command.  That test Block had one Attribute; the same didn't happen in another with two Attributes, but I couldn't say whether that difference is what mattered.

 

It could use some of the other enhancements [*error* handling, command-echo suppression, etc.].

Kent Cooper, AIA
Message 16 of 28

DGRL
Advisor
Advisor

Dear @Kent1Cooper

 

Very nice routine

I tried it on 1 of my blocks and the result is like this,

 

All the Bursted text became a block and all the lines and other entities are not in block

The text is also moved out of the block
And my block has its insertion in the lower right corner
I also uploaded the dwg with block that contains the attributes I work with

Maybe for @Anonymous the routine works Idk.

 

first try.PNG

 

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 17 of 28

Kent1Cooper
Consultant
Consultant

@DGRL wrote:

.... 

All the Bursted text became a block and all the lines and other entities are not in block

.... 


I had the same thing happen when a test Block was defined to not  allow Exploding [that's why the comment at the top of the routine specifies it needs to be defined to Allow Exploding].

Kent Cooper, AIA
0 Likes
Message 18 of 28

DGRL
Advisor
Advisor

As far as i know the block is allowed to explode

Is there a way to "lock" blocks for exploding other the locking the layer?

 

If this was of any help please kudo and/or Accept as Solution
Kind Regards
0 Likes
Message 19 of 28

Anonymous
Not applicable

HI

 

 

Thanks for the reply
I tried it and had the same result as @DGRL
Even when a block is defined as allowed explode it still gives this result

0 Likes
Message 20 of 28

Kent1Cooper
Consultant
Consultant

@DGRL wrote:

.... 

All the Bursted text became a block and all the lines and other entities are not in block

The text is also moved out of the block
And my block has its insertion in the lower right corner
....

@Anonymous wrote:

I tried it and had the same result as @DGRL ....


Might either of you have it in a non-World UCS?  Any locked Layer(s)?  I just tried it again, including with a multi-line Attribute, and it worked for me.

Kent Cooper, AIA
0 Likes