Move Attribute after insert.

Move Attribute after insert.

Strydaris2492
Advocate Advocate
1,747 Views
24 Replies
Message 1 of 25

Move Attribute after insert.

Strydaris2492
Advocate
Advocate

Afternoon everyone,

 

Hopefully someone can help me out with this.

 

I have a snippet of code that I found somewhere. Props to whomever made it and I wish I kept the location and person that posted it. What it does, is it allows me to move the attribute after the block is inserted into the drawing. 

This is the part that is in my main LISP to insert the block then invoke the function.

     (cond
	(
	 (setq blk (vlax-invoke
		      (vlax-get
			 (vla-get-ActiveLayout
			    (vla-get-activedocument
			       (vlax-get-acad-object)))
			 'Block)
		      'InsertBlock  ptcrv
		      blk2 1 1 1 ang))
	 (setq atb  (Car (vlax-invoke blk 'Getattributes)))
	 (vla-put-textstring atb (strcat hgtnew " HP"))
	 (princ "\n<< Pick point for text location >>")
	 (_NextTrick (trans (vlax-get atb 'TextAlignmentPoint) 0 1) atb)
	 (setq inserted (cons blk2 inserted)
	       )
	 )
	(
	 (and (setq str (eq (type ptcrv) 'STR))(eq ptcrv "U") inserted)
	 (vla-delete (car inserted))
	 (setq inserted (Cdr inserted)
	       counter (1- counter))
	 )
	(str (princ "\nNothing to UNDO"))
	)

 

Below is the subfunction that allows me to move the object.

  (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

 

What I am looking to do is modify this so that instead of using the text alignment to grab the text, I would like to use a dynamic block point to move parameter.

I know the area to edit is probably the 'TextAlignmentPoint to something else, but I dont understand where the 'TextAlignmentPoint comes from.

Also I cant seem to find much info on  the VLAX-GET/VLAX-PUT function and how to use it/them.

Can anyone help out?

0 Likes
Accepted solutions (1)
1,748 Views
24 Replies
Replies (24)
Message 2 of 25

paullimapa
Mentor
Mentor

Since blk is the block object then to use that insertion point instead of the Attributes:

(_NextTrick (trans (vlax-get blk 'InsertionPoint) 0 1) atb)

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 3 of 25

Strydaris2492
Advocate
Advocate

Hi paullimapa,

 

I'm not looking to use the insertion point.

I would like to use the dynamic block move parameter point.

0 Likes
Message 4 of 25

paullimapa
Mentor
Mentor

***update: forgot to add x, y of blocks insert point to point parameter**

then we'll have to rely on Lee Mac's getdynprops function:

 

(defun LM:getdynprops ( blk )
    (mapcar '(lambda ( x ) (cons (vla-get-propertyname x) (vlax-get x 'value)))
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)
(setq par (LM:getdynprops blk)) ; blk is the vl obj of the inserted dynamic block
;; now assuming the Point Parameter with Move Action uses the default name of Position1
(setq parx (cdr(assoc "Position1 X" par)) 
      pary (cdr(assoc "Position1 Y" par))
)
;; now get dynamic block's insertion point
(setq ipt (vlax-get blk 'InsertionPoint)
      iptx (car ipt)
      ipty (cadr ipt)
)
;; finally add the two coordinates together
(_NextTrick (trans (list (+ iptx parx) (+ ipty pary)) 0 1) atb)

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 5 of 25

Strydaris2492
Advocate
Advocate

Hi Paullimapa,

 

I think I see what you are doing with this code.

 

For the most part this works, but what it doesnt solve is how to edit the _NextTrick subfunction.

I changed the subfunction from this ....

 

(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

 

 

To this.....

 

  (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
			      (list (+ iptx parx) (+ ipty pary))
                              (setq pt2 (trans (cadr p) 1 0)))
                        (setq pt pt2)
                        )
                       ((or (= 2 code) (= code 3))
                        (setq end T)))
                 )
      );defun      

 

 

The thought was that you replaced the 'TextAlignmentPoint with the (list (+ iptx parx) (+ ipty pary)) point.

When doing this I get the Error "error: bad argument type: (or stringp symbolp): (-97.6956 -57.8739)"

Where the (-97.6956 -57.8739) looks to be the X,Y coordinates of the list.

Any thoughts?

 

0 Likes
Message 6 of 25

paullimapa
Mentor
Mentor

If you want _NextTrick function to place the coordinates into the “Position1” parameter of the dynamic block then use Lee Macs

LM:setdynpropvalue function as shown here:

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/dynamic-block-insert-and-use-lisp-to...

 

;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
    (setq prp (strcase prp))
    (vl-some
       '(lambda ( x )
            (if (= prp (strcase (vla-get-propertyname x)))
                (progn
                    (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                    (cond (val) (t))
                )
            )
        )
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)

 

So try changing that _NextTrick section of the code with this:

 

(LM:setdynpropvalue obj "Position1" (setq pt2 (trans (cadr p) 1 0)))

 

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 7 of 25

komondormrex
Mentor
Mentor

why do not you move target attribute usung its insertion point? that is changing 'textalignmentpoint in line 10 of _nexttrick to 'insertionpoint

 

0 Likes
Message 8 of 25

Strydaris2492
Advocate
Advocate

This doesnt seem to be working.

I keep getting the error "error: ActiveX Server returned the error: unknown name: "GETDYNAMICBLOCKPROPERTIES" "

I think I know what is going on with that though.

_NextTrick requires (pt obj) to work.

LM:setdynpropvalue requires ( blk prp val ) to work.

Because (LM:setdynpropvalue obj "Position1" (setq pt2 (trans (cadr p) 1 0))) is inside of the _NextTrick subfunction, the obj (block object) isnt getting passed onto the LM:setdynpropvalue subfunction.

So I changed the line 

(LM:setdynpropvalue obj "Position1" (setq pt2 (trans (cadr p) 1 0)))

to

(LM:setdynpropvalue blk "Position1" (setq pt2 (trans (cadr p) 1 0)))

And that seemed  to work in terms of inserting the block , but it doesnt allow the grread to show the block moving like it used to. Even after clicking on an new MOVE point, the block remains the same.

It doesnt seem to be passing the new Position1 value to the dynamic block for some reason.

Here is the updated code with your suggestions. Dont mind  the extra comments I added, helps me think it through.

 (defun _NextTrick  (pt obj / end code pt2)
      (while
            (and (null end)
                 (setq p    (grread t 15 0); T=track 15=allkeys added up 0=curser type to display crosshairs
                       code (car p)));This gets the code for the tracking for the while loop
                 (cond
                       ((= 5 code);While the code for tracking is still 5, do below

			(LM:setdynpropvalue obj "Position1" (setq pt2 (trans (cadr p) 1 0)))

                        (setq pt pt2)
                        )
                       ((or (= 2 code) (= code 3));checks if the mouse is still tracking and hasnt clicked or keyboard entry yet
                        (setq end T)));If above happened, end the while loop
                 )
      );defun      

 

 And here is the conditional statement that inserts the block in the main lisp

   (cond
      ((setq blk (vlax-invoke
		    (vlax-get
		       (vla-get-ActiveLayout
			  (vla-get-activedocument
			     (vlax-get-acad-object)))
		       'Block)
		    'InsertBlock  (trans pt3 1 0)
		    blk2 1 1 1 ang1)
	     );_ setq
          (setq par (LM:getdynprops blk)) ; blk is the vl obj of the inserted dynamic block
;; now assuming the Point Parameter with Move Action uses the default name of Position1
(setq parx (cdr(assoc "Position1 X" par)) 
      pary (cdr(assoc "Position1 Y" par))
)
;; now get dynamic block's insertion point
(setq ipt (vlax-get blk 'InsertionPoint)
      iptx (car ipt)
      ipty (cadr ipt)
      pospt (list (+ iptx parx) (+ ipty pary) 0.0)
)

       (setq atb  (Car (vlax-invoke blk 'Getattributes)))
       (vla-put-textstring atb grdtxt)
       (princ "\n<< Pick point for text location >>")
       ;(setq leemactemp (LM:setdynpropvalue blk prp val )
	(_NextTrick (trans pospt 0 1) atb)
       (setq inserted (cons blk inserted)
	     );_setq
       );_ cond 1
      ((and (setq str (eq (type pt3) 'STR))(eq pt3 "U") inserted)
       (vla-delete (car inserted))
       (setq inserted (Cdr inserted)
	     counter (1- counter))
       );_cond 2
      (str (princ "\nNothing to UNDO")
       )
      );_ end cond

 

I am still a little new to this. I am getting used to standard autolisp stuff, but Visual Lisp I havent used much so I am still getting used to the functions.

BTW I appreciate the help on this.

0 Likes
Message 9 of 25

paullimapa
Mentor
Mentor

Perhaps you can share your dynamic block here so others can jump in to troubleshoot 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 10 of 25

Strydaris2492
Advocate
Advocate

Hi paullimapa,

 

Yes I think that might be the better way to handle it.

Might give more understanding to what I am trying to do as well.

 

I've attached a temp CAD file and the LISP file before any of the changes we discussed.

If you open the CAD file and run the LISP with the command "ITRP".

Once in the command select one of the 115.## values, then select the other value on the red line.

Then select between them somewhere along the red line. There is suppose to be a temp line drawn to show you where to select, but I think the colour might be too light and might need to change it.

Once you select an insertion point for the new block along the red line, _NextTrick kicks in and allows you to PLACE the value where you want. This is a feature I want to use due to sometimes over crowding of information where the default value location is.

I was asked to add in the rotation for "After the fact" adjustments in the text values.

If you look at the block after insert, you can see that in using the "TextAlignmentPoint, adjusts the text placement in the block, but leaves the dynamic block parameters where the original insertion point is.

This is why I am trying to use the point parameter as the point at which _NextTrick allows me to move the text.

Thanks.

0 Likes
Message 11 of 25

Strydaris2492
Advocate
Advocate

Hey Paul,

So I have been playing around with this for most of the day and it seems you were sort of correct.

The part of the code you mentioned  to put into the _NextTrick Subfunction was a little bit off.

This code....

(LM:setdynpropvalue obj "Position1" (setq pt2 (trans (cadr p) 1 0)))

needed to be this....

(LM:setdynpropvalue blk "Position1 X" (setq pnt2 (car (cadr p))))
(LM:setdynpropvalue blk "Position1 Y" (setq pnt3 (cadr (cadr p))))

Apparently you need to use Lee's Code to push both the Position1 X and the Position1 Y back separately.

This works, but it also created a whole new set of issues.

Now for some reason, the attributed text flies off to no where and not at the cursor.

It moves to allow me to place it, but it seems the distance from the insertion point of the block is based on the distance from 0,0,0. So if my insertion point is at 50,50,0 the text is 50,50,0 from my crosshairs. Therefore if my crosshairs are at the insertion point the attributed text is at 100,100,0. 

It also seems as though rotation is a factor when using Position1 X & Y. From my testing it seems as though if the block is inserted at a rotated angle, then the Positions rotate with them. Meaning if I rotate the block 90 degrees, my Position1 Y now acts like a Position1 X moving in the negative direction.

This update to the code is more trouble than its worth. lol

 

0 Likes
Message 12 of 25

paullimapa
Mentor
Mentor

looks like you've now discovered most of the issues...and adding in a rotation definitely complicates things...let's see if others can chime in to provide more insights...


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 13 of 25

paullimapa
Mentor
Mentor

***Modified to include drawing with changed dynamic block***

Not sure if this meets with your intent but I made the following modifications to the Dynamic Block Grad_Point:

Changed justification of the Attribute Definition Tag ELEV to Middle Center 

Moved Attribute Definition Tag ELEV alignment point to match with Block's 0,0,0

Moved Rotation action center also to 0,0,0

paullimapa_0-1695021546450.png

So now when you place the Block using your original ITRP function, after picking the two 115.## values & the location of the third value:

paullimapa_1-1695021917390.png

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 14 of 25

fbyfatih
Contributor
Contributor

Why can't I find any function reference for vlax-get function?

0 Likes
Message 15 of 25

Sea-Haven
Mentor
Mentor

Start with (Vla-get-apropertyyouwant obj) eg (vla-get-length obj) if object is pline etc. (vlax-get obj 'Length)

 

Use Dumpit.lsp to look at properties of objects.

 

Big list of VL functions. List of AutoCAD VisualLISP functions (cadforum.cz)

0 Likes
Message 16 of 25

fbyfatih
Contributor
Contributor

(vlax-get (vla-get-ActiveLayout (vla-get-activedocument (vlax-get-acad-object))) 'Block)

 

What does this block of code do?

0 Likes
Message 17 of 25

Strydaris2492
Advocate
Advocate
Don't quote me on this, but to my understanding its this....
vlax-get = Gets properties of object
vla-get-activeLayout = In the active Layout (Model Space or Paperspace)
vla-get-activedocument = in the current dwg file
vlax-get-acad-object = an object in Autocad
I'm not too familiar with the vl, vla, vlax functions and how they work yet.
You can learn more about what these do here..
https://help.autodesk.com/view/OARX/2022/ENU/?guid=GUID-53DB599B-641D-45DD-A201-604942A4596C
0 Likes
Message 18 of 25

Strydaris2492
Advocate
Advocate

Hi Paul,

 

I modified the code slightly yesterday after posting it.

I removed unnecessary coding and also added in an if statement for my ang variable.

My desired rotation is placing the block at somewhere between 0 and 180 degrees to the relative UCS.

So I added this section of code to adjust for that rotation if you select the values in a different order.

(if (and (> ang1 (DtR 180))(< ang1 (DtR 360)))
       (setq ang1 (+ (angle pt2 pt1)(angle '(0 0 0) (trans '(1 0 0) 1 0 t))))
)

 

The alignment and the location of the attribute is important where it was. The industry standard is to have the values to the right of the X wherever possible.  The image below shows a bit of the work and that Grade_point block being used. The rotation of the text here is incorrect, but as you can see it can get a little crowded with numbers.

Strydaris2492_0-1695041835965.png

If I can't find a solution to using the _NextTrick subfunction to move the text during the insert in the Lisp Routine, Then I may just remove it altogether.

 

0 Likes
Message 19 of 25

paullimapa
Mentor
Mentor

Since you prefer not to moody the dynamic block which still includes the move and rotation actions then you might as well remove the NextTrick function call. The Attribute can easily be moved and rotated after block placement. Though there’s an industry standard when push comes to shove in tight spaces as shown in your screen capture example the attribute will end up placed at wherever there’s space available whether right or left regardless of rotation. But this sure is a good code learning experience. I just love how we can get immediate feedback on things we try…cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 20 of 25

Strydaris2492
Advocate
Advocate
I have posted this over on CadTutor forums as well.
Hoping that maybe I can get some help over there.
Maybe I can get some thoughts directly from Lee Mac on what is going on with how the block is behaving in the NextTrick subfunction when I use his code.
I will post here if I get any reply.
0 Likes