Stepping through block to get Text value.

Stepping through block to get Text value.

Strydaris2492
Advocate Advocate
955 Views
11 Replies
Message 1 of 12

Stepping through block to get Text value.

Strydaris2492
Advocate
Advocate

Hi everyone,

 

Looking for some help here with something.

What I am looking to do is to get a text or mtext value inside a block.

Issue may be that that text value could be another block nested in another block nest in another one.

All depends on how the consultants we work with decide to send them.

The other issue may be that there my be 2 text values inside the nested block, but what I want is the one that will be selected by the LISP.

 

I have moderate knowledge of LISP, but have never looked into stepping through a block to get to a nested block. Not sure where to begin with this.

 

Thanks in advance for the knowledge and help.

0 Likes
Accepted solutions (3)
956 Views
11 Replies
Replies (11)
Message 2 of 12

ronjonp
Mentor
Mentor
Accepted solution

@Strydaris2492 If you can pick the item then NENTSEL should work:

(defun c:foo (/ e)
  (if (and (setq e (car (nentsel "\nPick your text: "))) (cdr (assoc 1 (entget e))))
    (alert (cdr (assoc 1 (entget e))))
  )
  (princ)
)
0 Likes
Message 3 of 12

Strydaris2492
Advocate
Advocate
Ahhh ok I see. That works.
I always thought it was a lot harder than it seems.
Basically I can change the
(alert (cdr (assoc 1 (entget e)))
to
(setq attv (cdr (assoc 1 (entget e)))
to use that obtained value later on in the lisp.
One other thing, nentsel and entsel always confuse me a bit.
How do I go about using entdel to delete the selected object at the end of the code?
For some reason I can never wrap my head around where the initial Entity Name is using Nentsel.
0 Likes
Message 4 of 12

ronjonp
Mentor
Mentor

@Strydaris2492 wrote:
Ahhh ok I see. That works.
I always thought it was a lot harder than it seems.
Basically I can change the
(alert (cdr (assoc 1 (entget e)))
to
(setq attv (cdr (assoc 1 (entget e)))
to use that obtained value later on in the lisp. YES
One other thing, nentsel and entsel always confuse me a bit.
How do I go about using entdel to delete the selected object at the end of the code? TO DELETE THE TEXT OR THE BLOCK?
For some reason I can never wrap my head around where the initial Entity Name is using Nentsel.

@Strydaris2492 

See above.

0 Likes
Message 5 of 12

Strydaris2492
Advocate
Advocate
To delete the initial block that the text is nested in.
What I am looking to do is select the block with the nested text, store it in a variable, delete the block and insert my own block with the text I retrieved to fill out an attribute.
To my understanding entsel only grabs the list of the first level of block with the entity name at the begining as assoc 0?
Whereas nentsel grabs the list and puts all the entities at the end?
0 Likes
Message 6 of 12

ronjonp
Mentor
Mentor

Here's a quick example:

(defun c:foo (/ e)
  (if (and (setq e (nentsel "\nPick your text: ")) (cdr (assoc 1 (entget (car e)))))
    (progn (alert (cdr (assoc 1 (entget (car e))))) (entdel (car (last e))))
  )
  (princ)
)

This is a typical output for NENTSEL where the top item (0) is the deepest and the first item of the last (3) is the topmost host for the text.

ronjonp_0-1686167760204.png

 

If you do have crazy nesting this will delete all the 'host' blocks:

(defun c:foo (/ e)
  (if (and (setq e (nentsel "\nPick your text: ")) (cdr (assoc 1 (entget (car e)))))
    (progn (alert (cdr (assoc 1 (entget (car e))))) (mapcar 'entdel (last e)))
  )
  (princ)
)
0 Likes
Message 7 of 12

Strydaris2492
Advocate
Advocate

Hmmm that doesnt seem to be working.

 

I played around a bit because I think I understand what you are saying.

This is what worked to del the initial block.

(defun c:foo (/ e)
  (if (and (setq e (nentsel "\nPick your text: ")) (cdr (assoc 1 (entget (car e)))))
    (progn (alert (cdr (assoc 1 (entget (car e))))) (entdel (last (last e))))
  )
  (princ)
)

To my understanding, the entdel needs to look in the last part of the list, to the last entity in that list.

0 Likes
Message 8 of 12

Kent1Cooper
Consultant
Consultant
Accepted solution

@Strydaris2492 wrote:
.... select the block with the nested text, store it in a variable, delete the block ....

For that, I would use plain (entsel) to select the Block, but be sure to select it on the Text piece:

 

(setq esel (entsel "\nSelect Text element in Block: "))

 

Then pull the point you picked it by to use in an (nentselp) function to get the Text piece, and you can pull its content at the same time:

 

(setq attv (cdr (assoc 1 (entget (car (nentselp (cadr esel)))))))

 

Then use the entity name from the original (entsel) function to delete the Block:

 

(entdel (car esel))

Kent Cooper, AIA
0 Likes
Message 9 of 12

ronjonp
Mentor
Mentor

@Strydaris2492 wrote:

Hmmm that doesnt seem to be working.

 

I played around a bit because I think I understand what you are saying.

This is what worked to del the initial block.

(defun c:foo (/ e)
  (if (and (setq e (nentsel "\nPick your text: ")) (cdr (assoc 1 (entget (car e)))))
    (progn (alert (cdr (assoc 1 (entget (car e))))) (entdel (last (last e))))
  )
  (princ)
)

To my understanding, the entdel needs to look in the last part of the list, to the last entity in that list.


@Strydaris2492 

Use my second example above: 

(mapcar 'entdel (last e))

Your:

(entdel (last (last e)))

Should work as well. My previous example was for a simple non-nested block.

 

0 Likes
Message 10 of 12

Strydaris2492
Advocate
Advocate

Hey Kent,

 

I'm not sure I 100% understand what you are saying here.

Let me see if I understand this correctly

Using Entsel will only pull the Parent block info (Pardon the terminology, but this is how I understand it better)

I can then use nentselp to pull the nested block info.

The idea being that I can easily get the parent block info I need without going to deep into the info returned by nentselp?

0 Likes
Message 11 of 12

Strydaris2492
Advocate
Advocate

Thanks for the help today.

I was able to get the code working as I had hoped and added a couple extras.

(defun _NextTrick  (pt obj / end code pt2)
      (while
            (and (null end)
                 (setq p    (grread t 15 0)
                       code (car p)))
                 (cond
                       ((= 5 code)
                        (vlax-put
                              obj
                              'TextAlignmentPoint
                              (setq pt2 (trans (cadr p) 1 0)))
                        (setq pt pt2)
                        )
                       ((or (= 2 code) (= code 3))
                        (setq end T)))
                 )
      );defun      
  ;radians to degrees & degrees to radian
(defun rtd (r) (* 180.0 (/ r pi)))
(defun DtR (D) (/ (* D pi) 180))

(defun c:foo2 (/ ent)
    ;Set Layers and block names
  (setq lay1 "S-Slope-Frozen"
	lay2 "PROP-GRADE"
	lay3 "SLOPE-PH1"
	blk1 "DRAR"
	blk2 "Grade_Point"
	blk3 "PSEX"
	);End setq for varible layers and blocks
(setvar 'clayer lay2)
  (setq ent (entsel "\nSelect Grade Elevation Text: ")
  	attv (cdr (assoc 1 (entget (car (nentselp (cadr ent))))))
  	ang (cdr (assoc 50 (entget (car (nentselp (cadr ent))))))
	ins (cdr (assoc 10 (entget (car ent))))
	ins (list(car ins)(cadr ins) 0 )
	)
  		(cond	
                      (	
			(setq blk (vlax-invoke
			                (vlax-get
			                      (vla-get-ActiveLayout
			                            (vla-get-activedocument
			                                  (vlax-get-acad-object)))
			                      'Block)
			                'InsertBlock  (trans ins 1 0)
			                blk2 1 1 1 ang))

                       
		            (setq atb  (Car (vlax-invoke blk 'Getattributes)))
                            (vla-put-textstring atb attv)
                       	    (princ "\n<< Pick point for text location >>")	
                       		(_NextTrick (trans (vlax-get atb 'TextAlignmentPoint) 0 1) atb)
		            (setq inserted (cons blk inserted)
                                  )
                       						)
                      (	(and  (setq str (eq (type ins) 'STR))(eq ins "U") inserted)
                       		(vla-delete (car inserted))
                       		(setq inserted (Cdr inserted)
                                      counter (1- counter) )
		                      				)
                      (	str (princ "\nNothing to UNDO")	)
                      )
(entdel (car ent))
    (princ)
)

It was a lot easier than I thought.

Only thing I need to add is maybe some conditions just in case the text is not within a block.

0 Likes
Message 12 of 12

Kent1Cooper
Consultant
Consultant
Accepted solution

@Strydaris2492 wrote:

....

Using Entsel will only pull the Parent block info ....

KC:  Not quite -- (entsel) doesn't pull any information, but just returns the object's [in this case the Block's] entity name and the point at which you picked it, both of which you can use without pulling any information..  

I can then use nentselp to pull the nested block info.

KC:  Use (nentselp), with the p part being the selection point that's part of what (entsel) returned, to get the entity name of the Text object nested inside the Block.  My suggestion expands around that to extract the text content from it and put it into your 'attv' variable, all in that one line of code.

The idea being that I can easily get the parent block info I need without going to deep into the info returned by nentselp?

KC:  You don't need any parent Block information except its entity name, which is the first thing in the list that (entsel) returns.  The (entdel) function will use that to delete the Block after the Text's content has been extracted/saved.


Putting my earlier suggested lines together:

 

(defun C:TRYIT (/ esel)
  (setq esel (entsel "\nSelect Text element in Block: "))
  (setq attv (cdr (assoc 1 (entget (car (nentselp (cadr esel)))))))
  (entdel (car esel))
  (prin1)
)

 

That should [I don't have AutoCAD up to try it] leave the Text content in the 'attv' variable, to do with what you will.

Kent Cooper, AIA
0 Likes