Lisp to take an attribute out of block and convert it to text

Lisp to take an attribute out of block and convert it to text

Anonymous
Not applicable
5,252 Views
18 Replies
Message 1 of 19

Lisp to take an attribute out of block and convert it to text

Anonymous
Not applicable

Hey everyone, 

 

I am wandering is there it a way for lisp to pull an attribute out from inside of a block and put it in the same place but on the out side of the block and as text. If you look here at the attached drawing, I want to be able to select a group of blocks and put that attribute value outside of the block. 

0 Likes
Accepted solutions (1)
5,253 Views
18 Replies
Replies (18)
Message 2 of 19

dlanorh
Advisor
Advisor
I can't open your drawing as it is a later version than mine (2012), but yes and there is probably more than one way.
Do you need to delete the original attribute from the block reference, or is this just a copy of the attribute?

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

0 Likes
Message 3 of 19

Anonymous
Not applicable

Yes, I would like to delete it out of the block. 

Here is the drawing in 2010 version, try that...

0 Likes
Message 4 of 19

dlanorh
Advisor
Advisor
Is this for every "P64" block in the drawing or only those selected?

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

0 Likes
Message 5 of 19

Anonymous
Not applicable

It is just for every block that I select no mater what drawing I am in or the name of the block. They could even have the same definition name due the the dynamics.  

0 Likes
Message 6 of 19

dlanorh
Advisor
Advisor

OK, then i would suggest that instead of deleting the attribute from the block, that it's "text string" is set to "" (blank) , otherwise any attsync will make it reappear with the default prompt. If it is still in the block and blank, this won't happen.

To make it work for any attribute in any block it would have to be by single (nentsel) selection of the attribute for each block (i.e. one block at a time). It could be expanded to allow multiple block selections after the initial selection, but it would only then work on blocks with the same effective block name and the same tag name until another block/attribute combination is selected.

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

0 Likes
Message 7 of 19

3wood
Advisor
Advisor

You can get it done with command BURST.

Step 1: Copy all blocks.

Step 2: Command: BURST -> Select objects: P

Step 3: Delete all polylines (You can use QSELECT, SELECTSIMILAR, FILTER etc.)

Step 4: Command: PROPERTIES -> Change all block attributes value to a space " ". 

Capture.JPG

 

 

0 Likes
Message 8 of 19

dlanorh
Advisor
Advisor

Not as elegant as I would have liked, but try this :

(vl-load-com)

(defun rh:put_properties ( obj1 obj2 p_lst / f_lst txt)
  (cond ( (> (length p_lst) 0)
          (foreach prop p_lst
            (cond ( (and  (vlax-property-available-p obj2 prop T)
                          (vlax-property-available-p obj1 prop)
                    )      
                    (vlax-put-property obj2 prop (vlax-get-property obj1 prop))
                  )
                  ( (vlax-property-available-p obj2 prop)
                    (setq ro_lst (cons prop ro_lst))
                  )
                  ( (setq f_lst (cons prop f_lst)))
                  
            );end_cond  
          );end_foreach
        );end property list exists  
        ( (= (length p_lst) 0)
          (alert "Passed Property List is Empty")
        );end property list doesn't exists
  );end_cond
  (cond ( (or (> (length f_lst) 0) (> (length ro_lst) 0))
          (setq txt 
            (strcat "Not "(vlax-get-property obj2 'objectname) " Properties.\n"
              (foreach prop f_lst (setq txt (strcat txt prop " ")))
              "\n(RO) Properties\n"
              (foreach prop ro_lst (setq txt (strcat txt prop " ")))
            );end_strcat
          );end_setq
          (alert txt)
        );end problem properties
  );end_cond      
);end_defun

(defun rh:convert2txt ( obj txt / ms i_pt n_obj rtn)
  (setq ms (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))))
  (if (= (vlax-get-property obj 'alignment) 0)
      (setq i_pt (vlax-get-property obj 'insertionpoint))
      (setq i_pt (vlax-get-property obj 'textalignmentpoint))
  );end_if    
  (setq n_obj (vla-addtext ms txt i_pt (vlax-get-property obj 'height))
  );end_setq
  (rh:put_properties obj n_obj (list 'stylename 'alignment 'scalefactor 'color))
  (vla-delete obj)
  (setq rtn n_obj)     
);end_defun

(defun c:att2txt (/ *error* c_doc a_ent ent_lst tag blk_ent tmp_obj b_name ss blk_name atts a_tag a_val a_att c_obj c_lyr c_col x_objs e_obj)

	(defun *error* ( msg ) 
		(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
		(if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nAn Error : " msg " occured.")))
		(princ)
	);_end_*error*_defun
  
	(setq c_doc (vla-get-activedocument (vlax-get-acad-object))
        a_ent (nentsel "\Select Attribute to convert to text : ")
        ent_lst (entget (car a_ent))
        tag (strcase (cdr (assoc 2 ent_lst)))
        blk_ent (cdr (assoc 330 ent_lst))
        tmp_obj (vlax-ename->vla-object blk_ent)
        cnt 0
	);end_setq
	(setq b_name  (strcase  (if (vlax-property-available-p tmp_obj 'effectivename)
                            (vlax-get-property tmp_obj 'effectivename)
                            (vlax-get-property tmp_obj 'name)                        
                          )
                )          
  )
  (initget "Yes No")
  (setq ans "Yes"
        ans (getkword (strcat "\nSelect More Blocks [Yes / No] < " ans " > : "))
  )
  (if (= ans "Yes")
    (progn 
      (prompt "\nSelect Blocks : ")
      (while (not ss)
        (setq ss (ssget '((0 . "INSERT") (66 . 1))))
        (if (not ss) (alert "You must Select at least One other Entity"))
      );end_while
    );end_progn  
    (setq ss (ssadd blk_ent))
  )
  
  (if (not (ssmemb blk_ent ss)) (ssadd blk_ent ss))
  
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
	(vla-startundomark c_doc)

  (repeat (sslength ss)
    (setq b_obj (vlax-ename->vla-object (ssname ss cnt))
          cnt (1+ cnt)
          blk_name  (if (vlax-property-available-p b_obj 'effectivename)
                        (vlax-get-property b_obj 'effectivename)
                        (vlax-get-property b_obj 'name)                        
                    )
    );end_setq                
    (cond ( (= (strcase blk_name) b_name)
            (setq atts (vlax-invoke b_obj 'getattributes))
            (foreach att atts
              (if (= (strcase (vlax-get-property att 'tagstring)) tag)
                (setq a_att att
                      a_val (vlax-get-property att 'textstring)
                )
              );end_if    
            );end_foreach
          )
    );end_cond
    (setq c_obj (vla-copy b_obj)
          c_lyr (vlax-get-property c_obj 'layer)
          c_col (vlax-get-property c_obj 'color)
          x_objs (vlax-invoke c_obj 'explode)
    )
    (vla-delete c_obj)
    
    (foreach obj x_objs
      (cond ( (and  (= (vlax-get-property obj 'objectname) "AcDbAttributeDefinition")
                    (= (strcase (vlax-get-property obj 'tagstring)) tag)
              );end_and 
              (setq e_obj (rh:convert2txt obj a_val))
              (if (= (vlax-get-property e_obj 'layer) "0") (vlax-put-property e_obj 'layer c_lyr))
              (if (= (vlax-get-property e_obj 'color) 0) (vlax-put-property e_obj 'color c_col))
            );end_cond attribute
            (
              (vla-delete obj)
            )
      );end_cond
    );end_foreach  
    (vlax-put-property a_att 'textstring "")
  );end_repeat  
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
);end_defun

The initial selection requires you to select the attribute within the block you wish to extract. It finds the block name and attribute tag itself.

 

The prompt to select more blocks is to enable you to select several other similar blocks with the same effective name. If you answer "Yes" (the default) you will be prompted to select. If you select "No" then the block initially selected block only is added to the selection set. The routine will also check if the intially selected block is in the selecton set and if not it adds it.

There is no check at present that the initial selection is an attribute. I will sort this sometime this evening.

 

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

Message 9 of 19

Anonymous
Not applicable

This is phenomenal!

0 Likes
Message 10 of 19

dlanorh
Advisor
Advisor
Accepted solution

Attached is the updated lisp.

 

While I was updating it I noticed a logic error if a non similar block was selected. This has been rectified.

 

I have also added an information popup alert to the end of the lisp. If you don't want this just remove the code between the ;REPORT and ;END REPORT comments.

 

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

0 Likes
Message 11 of 19

Anonymous
Not applicable

Thank you so much, this is golden!

0 Likes
Message 12 of 19

Anonymous
Not applicable

Sorry to bring up an old thread.

 

I am trying to use this lisp (att2txt.lsp by dlaorth), but the problem I am having is that the resultant text is not staying in the same position as the source attribute. In fact the text places itself at 0,0,0.

 

I am wondering if I have some variable setting that is affecting the result.

 

If anybody can help I would be grateful.

For reference I post the drawing "TRY.dwg". The attribute I am trying to convert to text is "DWG_N0"

 

0 Likes
Message 13 of 19

dlanorh
Advisor
Advisor

I will get a chance to look at this later, but i suspect that the attribute is justified and the code is trying to use the insertion point.

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

Message 14 of 19

Anonymous
Not applicable

Thank you dlanorh for your reply.

 

I did just check the justification of the attribute that I was interested in.

It was justified as "middle centre". I amended the attribute to be justified "left" and the code worked as it should.

 

I appreciate your prompt reply and valued help. Thank you again. 

 

0 Likes
Message 15 of 19

dlanorh
Advisor
Advisor

I've looked at the code and it should work for justified attributes, so there is a bug. I will try to sort it later.

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

0 Likes
Message 16 of 19

dlanorh
Advisor
Advisor

Attached is updated lisp that should now handle justified attributes correctly.

 

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

0 Likes
Message 17 of 19

Anonymous
Not applicable

Sincere thanks for your time and expertise dlanorh.

 

I tested the revised code on numerous blocks and numerous attributes.

All working very well indeed.

 

Cheers.

 

0 Likes
Message 18 of 19

john.uhden
Mentor
Mentor

@dlanorh 

Nice work, Ron.  But I want to keep the block without an attribute.

The ATT-TEXT function in BURST.lsp looks like it works just fine.  I'll work on MATTS later if I must.

The whole purpose is to make the attributes annotative at the same height, no matter the scale of the insert.

Hmm, maybe you know what codes to add to entmake a text annotative.

John F. Uhden

0 Likes
Message 19 of 19

Sea-Haven
Mentor
Mentor

If you change a text to Annotative looks like adds Extensiondictionary do a dumpit and can see 0 or -1. Sorry no idea past this point. Other than did a follow down the rabbit hole looking at (entget (cdr (assoc 360 & 330 etc.

 

(102 . "{ACAD_XDICTIONARY") 
(360 . <Entity name: 6973cd20>) 
(102 . "}") 

 

Did find though

: CHPROP
Select entities to change: 
Entities in set: 1
Select entities to change: 
Property to change [Color/LAyer/LineType/linetype Scale/Line Weight/Thickness/TRansparency/Material/Annotative]:A
Make Annotative?[Yes/No] <No>:y
Property to change [Color/LAyer/LineType/linetype Scale/Line Weight/Thickness/TRansparency/Material/Annotative]:
0 Likes