Block Attribute Text Extraction.

Block Attribute Text Extraction.

Mr_J
Contributor Contributor
4,900 Views
15 Replies
Message 1 of 16

Block Attribute Text Extraction.

Mr_J
Contributor
Contributor

So what I'm looking for is way above my skill level with macros and LISP routines. I would like to know if there is a way to extract data from multiple block attributes and merge them into one line of text. I have created a macro to burst the blocks and separate all the text individually from the rest of the drawing but it is still not very efficient. If anyone with can help create a macro to preform this task or point me in a direction to research this, I would appreciate it. If there is any confusion about what I'm looking for please feel free to ask.

 

I have added a screen shot of the blocks I'm talking about with the extracted info desired below them. Also I have attached a DWG file with the samples and info explaining what I'm trying to do. Thanks!

 

Extract Example.jpg

0 Likes
Accepted solutions (2)
4,901 Views
15 Replies
Replies (15)
Message 2 of 16

pbejse
Mentor
Mentor
Accepted solution

@Anonymous wrote:

...I would like to know if there is a way to extract data from multiple block attributes and merge them into one line of text....

 

 


 

(defun c:attempt ( / ss i e attValue com_str)
(if (setq ss (ssget '((0 . "INSERT")(66 . 1)(2 . "`*U*,FIELD MOUNTED INSTRUMENT"))))
	(repeat (setq i (sslength ss))
	      (and	(setq e (vlax-ename->vla-object (ssname ss (setq i (1- i)))))
	              	(eq "FIELD MOUNTED INSTRUMENT" (strcase (vla-get-EffectiveName e)))
	            	(setq ipt (Vlax-get e 'InsertionPoint))
	              	(setq attValue (mapcar '(lambda (v)
	                                (vla-get-textstring v))
					(vlax-invoke e 'Getattributes)))
	            	(setq com_str (apply 'strcat attValue))
	            	(snvalid com_str)
	            	(entmakex (list (cons 0 "TEXT")
	          		(cons 10  (Setq ipt (polar IPT (* pi 1.5) 0.5500 )))
	          		(cons 11 ipt) '(40 . 0.1250)'(8 . "Extracted Text")
		  		'(72 . 1)'(73 . 0) (cons 1  com_str)))
			)
	              )
    		)
    (princ)
    )

HTH

 

Message 3 of 16

3wood
Advisor
Advisor

2 solutions:

 

1. Use ALTEXT.vlx

a) Edit the block, switch to "Face mounted" visibility and add a new attribute at bottom of the block to receive input of combined texts.

b) Save the codes below as a lisp file.

c) Load and run ALTEXT.vlx, select all blocks, enter "4" when it prompts "Which attribute to be changed (Enter 0 to search attribute tag name): Attribute No.<1>:"

d) In the pop-up setting box, Select "Use formula", then select the lisp file saved in Step b)

 

2 Use field. This solution is for future use, not to update existing blocks.

a) Same as Step a) in the solution above

b) Edit the new attribute and right-click, insert fields.

I have updated the block so it already has the 4th attribute and fields. You can use it in the new project. The 4th attribute can be updated automatically after REGEN.

 

There might be some routines which can write fields in the 4th attribute. In that case, you can use this routine to updated existing blocks with fields written into the 4th attribute. It is even better.

 

;;; This is an example formula for ALTEXT.vlx
(defun ALTEXT_FORMULA ()
  (strcat ALTEXT_ATT_1 ALTEXT_ATT_2 ALTEXT_ATT_3)
  )
Message 4 of 16

Mr_J
Contributor
Contributor

Pbejse! Thank you so much!!! You nailed it! However I have a follow up question. The blocks I posted are just one of many (different titled blocks with similar structure) can I alter the code to select from a list of preexisting blocks or should I just duplicate the command and create a command for each block type?

 

Example 2.gif

I’ve attached another file to explain a little better.

0 Likes
Message 5 of 16

pbejse
Mentor
Mentor

@Anonymous wrote:

Pbejse! Thank you so much!!! You nailed it! However I have a follow up question. The blocks I posted are just one of many (different titled blocks with similar structure) can I alter the code to select from a list of preexisting blocks or should I just duplicate the command and create a command for each block type?

 


You have 3 options here (maybe more)

1. Redefine your blocks to include a TAG for the combined text and run a program to update the values (as suggested by 

2. Hard code the block names & the size of the circle ("FIELD MOUNTED INSTRUMENT LARGE" 0.50) and add more data to it as you go along OR

3. We write a smart program to work on any block which meet a set of condtion.

 

Tell me, are there blocks where the scale & rotation is other than 1?

 

 

Message 6 of 16

Mr_J
Contributor
Contributor

In the second attachment I provided, the blocks are exactly how the appear when pulled from my tool palette. And should not be altered in any way other than different numbers. So no, they should not be rotated or scaled any different than they appear in the second sample. As for the options I am open to any or all of the suggestions provided, however I have thousands of preexisting documents that would be incredibly difficult to update when the data extraction would be needed, so a smart program may work best. Or would it be possible to create each individual routine and have them run simultaneously with one command? Only wondering because your first LISP worked so perfectly that it doesn’t stop running even if one of the fields is empty or scale is altered.

0 Likes
Message 7 of 16

pbejse
Mentor
Mentor
Accepted solution

@Anonymous wrote:

...... So no, they should not be rotated or scaled any different than they appear in the second sample. n if one of the fields is empty or scale is altered.As for the options I am open to any or all of the suggestions provided, however I have thousands of preexisting documents that would be incredibly difficult to update when the data extraction would be needed....


The code is based on your posted blocks, The only condition is the block has to have a "circle" as basis for the TEXT insertion point.
One thing you will notice on the code, the text height will match the attribute text height, and YES scale does matter on this routine.

 

Try the attached lisp 

 

command: Joker

 

HTH

 

 

Message 8 of 16

Mr_J
Contributor
Contributor

Holy crap!!! You are the Man! I don’t know how you did it but I am truly impressed. The LSP you gave me worked perfectly. Thank you! Is there a particular source to where you learned how to create this stuff? Everything I know has just been self-taught but I’d like to learn more, just wondering?

 

P.S. I love that the command was “Joker”!

0 Likes
Message 9 of 16

pbejse
Mentor
Mentor

@Anonymous wrote:
... Thank you! Is there a particular source to where you learned how to create this stuff? Everything I know has just been self-taught but I’d like to learn more, just wondering?

 

P.S. I love that the command was “Joker”!


You are welcome,  There is this place high up on a mountain, they led me into a room and gave me the wi-fi password and said "google" everything you need to know about lisp and start reading" (sounds very familiar eh....) [ the doctor ]

 

I am self taught as well, just practice, practice, practice some more, and do ask questions <this forum>, you will get there faster if you do. 

 

That is what the "J" on Mr_J stands for right? cmon tell it is... 😄

 

Cheers

 

Message 10 of 16

Mr_J
Contributor
Contributor

I too am not a savage, and do in fact have access to wifi. And I agree, this forum has improved my skills 10 fold but you are definitely on another level. I try understand the coding and not just copy and paste what I find online, which is why I asked if there was a better way. However it seems I'm still in the montage stage of my life so I'll just continue on this path till I can one day surpass even you (but don't be surprised if I come to you with more questions in the future). Thanks again!

 

Also my name starts with the letter "J" but you are correct about the "J" in Mr_J!

0 Likes
Message 11 of 16

burniksapwet
Enthusiast
Enthusiast

Amazing amazing work. This lsp will help us tremendously.  If I may I would like to request another .lsp that uses the same concept of what you did for Mr_J.

 

- First step is to zoom extent.

- We need to just select the instrumentation blocks the Joker .lsp works for. (So basically I think it will be for blocks with attributes that have a circle.) We have other blocks that has attributes and dont want them included in the selection.

- Select all text or mtext that are under the "Text-Legend" and "Text-Legend 2"

- Move all those selected from coordinates X = 33.415669 Y = 21.226325 Z to X = 1.134419 Y = 21.226325

**Note: No zoom extent at the end.**

 

Thank you so much.

 

Before

Before.gif

 

After

After.gif

 

After (Zoomed Out which is only for your viewing reference)

After (Zoomed Out Only For Reference).gif

0 Likes
Message 12 of 16

pbejse
Mentor
Mentor

@burniksapwet wrote:

Amazing amazing work. This lsp will help us tremendously.  If I may I would like to request another .lsp that uses the same concept of what you did for Mr_J.

 

 

 

 


You are both welcome, I have a feeling you guys are working for the same company.

 


@burniksapwet wrote:

 

 

- First step is to zoom extent....

 

Thank you so much.

 


Easy, but he question is WHY write a program that will work for a specific set of conditions <too specific> ? I'm guessing there's more to it than just "moving' stuff around, what is the ultimate goal?  Perhaps we can write something more generic.

 

 EDIT: Mr_J did say, "... however I have thousands of preexisting documents.." He may have something there, is this for thousands of sheet relating to one huge project?

 

 

0 Likes
Message 13 of 16

pbejse
Mentor
Mentor

burniksapwet wrote:

 

- We need to just select the instrumentation blocks the Joker .lsp works for. (So basically I think it will be for blocks with attributes that have a circle.) We have other blocks that has attributes and dont want them included in the selection.

- Select all text or mtext that are under the "Text-Legend" and "Text-Legend 2"

- Move all those selected.....

 

 

 


Strange as this request may be (limited testing)

 

(defun c:bsp ( / ss i e ot bn lst MoveToNowhere_T MoveToNowhere_o str pts)
	(setq blocks (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object))))     
	(And (setq MoveToNowhere_o (ssadd)
                           ss (ssget  '((-4 . "<OR")
				(-4 . "<AND")
				(0 . "MTEXT,TEXT")(8 . "Text-Legend 2,Text-Legend")(-4 . "AND>")
				(-4 . "<AND")
				(0 . "INSERT")(66 . 1)(-4 . "AND>")
				(-4 . "OR>")))
	      		)
	   (repeat (setq i (sslength ss))
		    (setq e (vlax-ename->vla-object  (ssname ss (setq i (1- i)))))
	                 
	 ;;;	Why COND because there'll probably more objects type to come			;;;
	            (if      
	                 (setq str (cond
	                       	(	(And
		                                (eq (setq ot (vla-get-objectname e)) "AcDbBlockReference")
		                         	(Setq inf nil bn  (vla-get-EffectiveName e)
		                              		atv (mapcar '(lambda (v) (vla-get-textstring  v))
		                                       			(vlax-invoke e 'Getattributes)))
						(or (member bn lst)
							(and 	
								(vlax-for itm (vla-item blocks bn)
								(setq inf (cons (list (vla-get-ObjectName itm) itm ) inf )))
								(assoc "AcDbCircle" inf)
								(Setq lst (cons  bn lst)))
								)
	                                		)
	                                    (ssadd (ssname ss i) MoveToNowhere_o )(apply 'strcat atv)
	                                    	)
	                         (	(member ot '("AcDbText" "AcDbMText")) (ssadd (ssname ss i) MoveToNowhere_o )
                                  		(Vla-get-textstring e)
	                          		)
	                        	)
	                 	)
                   			(setq MoveToNowhere_T (cons str MoveToNowhere_T))
                         	)
                   	MoveToNowhere_T
                   )
                   (Setq str (substr (apply 'strcat (mapcar '(lambda (s)
                                            		(strcat  "\\P" s))  MoveToNowhere_T)) 3))
                   (Setq pts (mapcar 'cadr (cdr (Assoc -1 (ssnamex ss)))))
		   (entmakex (list (cons 0 "MTEXT")         
			          	(cons 100 "AcDbEntity")
		          		(cons 100 "AcDbMText")
		          		(cons 10 (Cadr pts))
		          		(cons 1 str)
                                        '(71 . 1) 
					'(72 . 5)))
                   
                   (command "_move" MoveToNowhere_o "" "_non" (Car pts) "_non" (Cadr pts))
                   )
      (princ)
		)

HTH

 

Message 14 of 16

smallƑish
Advocate
Advocate

How to modify the code to get the text data from A block or Mleader , or a leader  or  A MTEXT

 

(setq raw (car (entsel "\nSelect it: ")))
(setq txt (strcase (cdr (assoc 1 (entget raw)))))

 

0 Likes
Message 15 of 16

Sea-Haven
Mentor
Mentor

Do you mean the block has attributes or it contains text as part of the block objects. 2 very different things.

0 Likes
Message 16 of 16

Mr_J
Contributor
Contributor

It was a block with text attributes but fortunately I was able to get a good solution from Pbejse. Thanks!

0 Likes