duplicate AcDbText and turn it to AcDbAttributeDefinition

duplicate AcDbText and turn it to AcDbAttributeDefinition

Moshe-A
Mentor Mentor
1,359 Views
17 Replies
Message 1 of 18

duplicate AcDbText and turn it to AcDbAttributeDefinition

Moshe-A
Mentor
Mentor

Guys hi,

 

Attached  a dwg contain A1.dwg block that contain a text object and i would like to duplicate the text and turn it's copy to attdef. the text\attdef is not on WCS should stay that.  i tried to get the text database with (entget) and replace (0 . "text") to (0. "attdef") add tagname (2 . "tag") add prompt (3 . "prompt") add flag (70 . 0) and call (entmake elist) and it does not work, to me it look like the 210 field is interrupting?

 

p.s: the attribute value flag would be set to preset and the user is not suppose to insert this block manually. 

 

thanks in advance

moshe

 

0 Likes
Accepted solutions (1)
1,360 Views
17 Replies
Replies (17)
Message 2 of 18

dlanorh
Advisor
Advisor

Any chance of a 2010 dwg Moshe?

I am not one of the robots you're looking for

0 Likes
Message 3 of 18

Moshe-A
Mentor
Mentor

here it is

0 Likes
Message 4 of 18

Kent1Cooper
Consultant
Consultant

@Moshe-A wrote:

....  i tried to get the text database with (entget) and replace (0 . "text") to (0. "attdef") add tagname (2 . "tag") add prompt (3 . "prompt") add flag (70 . 0) and call (entmake elist) and it does not work, to me it look like the 210 field is interrupting?

....


 

The 210 entry is just the extrusion direction -- I wouldn't think that would interfere.  But did you remove  the entity name [e.g. (-1 . <Entity name: 34156060>)] entry and the handle [e.g. (5 . "8E3AE")] entry from the entity data list?  You can't make a second entity with the same entity name or handle as another.  If those were still in the list, try taking those out and see whether (entmake) works [I'm not guaranteeing... untested].

[Never mind -- I just opened up the AutoLisp Reference about (entmake), and it says that if the entity name and/or handle are present, they are ignored.]

 

EDIT AGAIN:  But I thought the idea sounded familiar!  Check >this< out, with its T2A command.  I haven't analyzed to see what I may have done differently than what you've tried, but it works in minimal testing.

Kent Cooper, AIA
0 Likes
Message 5 of 18

dlanorh
Advisor
Advisor

1. Is this by any means or must I use "entmod"?

 

2. Where do you want the attdef in relation to the text?

 

 

I am not one of the robots you're looking for

0 Likes
Message 6 of 18

Kent1Cooper
Consultant
Consultant

@dlanorh wrote:

1. Is this by any means or must I use "entmod"?

2. Where do you want the attdef in relation to the text?


 

T2A in the link in Message 4 does it with (entmake) rather than (entmod), which is also the way @Moshe-A  described having trouble doing it in Message 1, so I assume that's okay.  It leaves it in the same location, justification, rotation, size, style, etc., as the source Text, with the one difference that if it isn't already, it becomes ALL-UPPERCASE, because [for whatever unknown reason] Attribute Tags always are, no matter how you type them in.

Kent Cooper, AIA
0 Likes
Message 7 of 18

Moshe-A
Mentor
Mentor

thanks @Kent1Cooper and @dlanorh 

 

As i said my situation is text is inside a block and the text it is not in WCS

can you run your code on that text?

 

what i want to do is a command to 'convert' any texts inside a block so when the block is mirrored the text value remain readable. the origin text is not removed but goes invisible so the user have the option to restore it.

 

Moshe

0 Likes
Message 8 of 18

Kent1Cooper
Consultant
Consultant

@Moshe-A wrote:

....

As i said my situation is text is inside a block and the text it is not in WCS

can you run your code on that text?

....


 

I would think [without trying it] that it ought to work inside the Block Editor, as other commands do.

Kent Cooper, AIA
0 Likes
Message 9 of 18

Moshe-A
Mentor
Mentor

tried it, doesn't work.

do you have an idea how can i transform it to wcs?

 

0 Likes
Message 10 of 18

Kent1Cooper
Consultant
Consultant

@Moshe-A wrote:

tried it, doesn't work.  do you have an idea how can i transform it to wcs?


 

What does "doesn't work" mean?  Does it not turn the Text into an Attdef  while you are in the Block Editor?  Does it succeed in doing that, but it's in the wrong place [a (trans) function should get around that]?  Or does it succeed in doing that, but you don't see it in existing Insertions of the Block  afterward?  If it's the latter, ATTSYNC may be needed, and/or you may only need to double-click on an Insertion for the Attribute Editor to come up so you can give it a value, which T2A doesn't do for you [it uses the original text content for the Tag and the Prompt, but that's all].

Kent Cooper, AIA
0 Likes
Message 11 of 18

dlanorh
Advisor
Advisor

OK. After a bit of faffing about, I got this to work. I have tested it on your drawing in AutoCAD 2012.

 

I couldn't set the textalignmentpoint as it refused it, probably because the alignment is bottom left (zero), but found that re-inserting the "insertionpoint" property after having set the "normal" property made it happen. I haven't put the required "attsync" into the code.

 

(defun c:add_att2blk ( / c_doc c_blks blk blk_n prop_c_lst prop_m_lst prop_c_vals prop_m_vals n_att )

  (setq c_doc (vla-get-activedocument (vlax-get-acad-object))
        c_blks (vla-get-blocks c_doc)
        blk (vlax-ename->vla-object (car (entsel "\nSelect Block Reference of Block Definition : ")))
        blk_n (vlax-get-property blk (if (vlax-property-available-p blk 'effectivename) 'effectivename 'name))
        blk (vla-item c_blks blk_n)
        prop_c_lst (list 'height 'insertionpoint 'textstring)
        prop_m_lst (list 'layer 'alignment 'stylename 'normal 'rotation 'linetype)
  );end_setq
  (vlax-for obj blk
    (cond ( (= (vlax-get-property obj 'objectname) "AcDbText");See above
            (mapcar '(lambda (x) (setq prop_c_vals (cons (vlax-get-property obj x) prop_c_vals))) prop_c_lst)
            (mapcar '(lambda (x) (setq prop_m_vals (cons (vlax-get-property obj x) prop_m_vals))) prop_m_lst)
            (setq prop_c_vals (reverse prop_c_vals)
                  prop_m_vals (reverse prop_m_vals)
                  n_att (vla-addattribute blk (nth 0 prop_c_vals) acAttributeModePreset "Prompt" (nth 1 prop_c_vals) "TAG" (nth 2 prop_c_vals))
            );end_setq
            (mapcar '(lambda (x y) (vlax-put-property n_att x y)) prop_m_lst prop_m_vals)
            (vlax-put-property n_att 'insertionpoint (nth 1 prop_c_vals))
          )
    );end_cond
  );end_for    
);end_defun

I am not one of the robots you're looking for

Message 12 of 18

Moshe-A
Mentor
Mentor

@Kent1Cooper 

 

it means (entmake) return nil and the attdef is not created

and again i think the problem is in the text object that it is not in wcs

 

 

0 Likes
Message 13 of 18

Moshe-A
Mentor
Mentor

@dlanorh 

 

thanks i will give this a try tonight

 

0 Likes
Message 14 of 18

Moshe-A
Mentor
Mentor

@dlanorh 

 

thanks you very much for your code.

 

As a matter of fact my code i very similar to yours (e.g using activex) but to achieve a readable text in mirrored block i set attdef justification to acAlignmentMiddleCenter and this is calculated from (vla-getBoundingBox) of the text but this some how produce a wrong point and together with normal property transforms the attdef about the ucs origin (of the block). the problem only arise when the text is not in wcs.

 

and may i remark about your code?!

 

take a look at this code snippet:

 

(mapcar '(lambda (x) (setq prop_c_vals (cons (vlax-get-property obj x) prop_c_vals))) prop_c_lst)
(setq prop_c_vals (reverse prop_c_vals))

 

although the result of 'prop_c_vals'  value is good but it's intermediate value is overridden each iteration.

instead you could get that same result with only this line:

 

(setq prop_c_vals (mapcar '(lambda (x) (vlax-get-property obj x)) prop_c_lst))

 

thanks,

moshe

 

 

 

 

 

 

 

0 Likes
Message 15 of 18

_gile
Consultant
Consultant

This seems to work:

 

(vl-load-com)
(or *acad* (setq *acad* (vlax-get-acad-object)))
(or *acdoc* (setq *acdoc* (vla-get-ActiveDocument *acad*)))
(or *blocks* (setq *blocks* (vla-get-Blocks *acdoc*)))

(defun c:test (/ blk props attdef)
  (setq blk (vla-item *blocks* "a1"))
  (vlax-for obj blk
    (if (= (vla-get-ObjectName obj) "AcDbText")
      (progn
        (foreach prop '(Alignment
                        Backward
                        Layer
                        Linetype
                        LinetypeScale
                        Lineweight
                        Material
                        Normal
                        ObliqueAngle
                        Rotation
                        ScaleFactor
                        StyleName
                        Thickness
                        TrueColor
                        UpsideDown
                        Visible
                       )
          (setq props (cons (cons prop (vlax-get-Property obj prop)) props))
        )
        (setq attdef (vla-AddAttribute blk
                                       (vla-get-Height obj)
                                       acAttributeModeConstant
                                       ""
                                       (vlax-3d-point '(0. 0. 0.))
                                       "CONST"
                                       "this is now an attdef"
                     )
        )
        (foreach prop props
          (vlax-put-Property attdef (car prop) (cdr prop))
        )
        (if (/= (vla-get-Alignment obj) 0)
          (vla-put-TextAlignmentPoint attdef (vla-get-TextAlignmentPoint obj))
          (vla-put-InsertionPoint attdef (vla-get-InsertionPoint obj))
        )
        (vla-Delete obj)
      )
    )
  )
  (vla-Regen *acdoc* acAllViewports)
  (princ)
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 16 of 18

Moshe-A
Mentor
Mentor

@_gile  hi,

 

cause it looks like you did not had the time to read all the thread (it's ok) i'll shorten it for you

i want to 'replace' each AcDbText to attribute in a selected block so the block can be mirrored and leave the texts readable. why 'replace'? cause i do not really delete it i only make it invisible.

we know that a start point justify attribute when mirrored it is shifted a bit, i want to change the justification

to middle point, but there my catch  in the sample dwg i attached (most up in thread) the text is not in wcs so after mirror the attribute it's rotate about the 0,0,0 of the block and i want to prevent it.

 

thanks

moshe

 

 

0 Likes
Message 17 of 18

_gile
Consultant
Consultant
Accepted solution

Still not sure to understand but you can try this new version, it seems to work with the drawing you posted.

 

(vl-load-com)
(or *acad* (setq *acad* (vlax-get-acad-object)))
(or *acdoc* (setq *acdoc* (vla-get-ActiveDocument *acad*)))
(or *blocks* (setq *blocks* (vla-get-Blocks *acdoc*)))

(defun c:test (/ blk props attdef ll ur pt)
  (setq blk (vla-item *blocks* "a1"))
  (vlax-for obj blk
    (if (= (vla-get-ObjectName obj) "AcDbText")
      (progn
        (vla-GetBoundingBox obj 'll 'ur)
        (setq ll (vlax-safearray->list ll)
              ur (vlax-safearray->list ur)
              pt (list (/ (+ (car ll) (car ur)) 2.) (/ (+ (cadr ll) (cadr ur)) 2.) 0.)
              )
        (foreach prop '(Alignment
                        Backward
                        Layer
                        Linetype
                        LinetypeScale
                        Lineweight
                        Material
                        Normal
                        ObliqueAngle
                        Rotation
                        ScaleFactor
                        StyleName
                        Thickness
                        TrueColor
                        UpsideDown
                        Visible
                       )
          (setq props (cons (cons prop (vlax-get-Property obj prop)) props))
        )
        (setq attdef (vla-AddAttribute blk
                                       (vla-get-Height obj)
                                       0
                                       ""
                                       (vlax-3d-point '(0. 0. 0.))
                                       "TAG"
                                       (vla-get-Textstring obj)
                     )
        )
        (foreach prop props
          (vlax-put-Property attdef (car prop) (cdr prop))
        )
        (vla-put-Alignment attdef acAlignmentMiddlecenter)
        (vla-put-TextAlignmentPoint attdef (vlax-3d-point pt))
        (vla-put-Visible obj :vlax-false)
      )
    )
  )
  (command-s "_.attsync" "_name" "a1")
  (princ)
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 18 of 18

Moshe-A
Mentor
Mentor

Gills,

 

As always you are right - it works - thank you very much.

the only different of what i did\has is that i set the alignment first then copied all other properties. turns out 'timing' is the most 'important thing' Smiley LOL  

another issue with this kind of blocks (as "a1") is after mirror the return text angle is the block ucs and that still in some cases leave the text unreadable. sure you will say that need matrix transformation? but i for now decide to leave this problem to the users. they now have attributes and they can handle this on their own.

 

thanks

Moshe

 

 

  

 

0 Likes