Jump to content

Lisp inserted Mtext (w/fields) not automatically updating


lfe011969

Recommended Posts

I have a program that inserts an Mtext string containing two fields that works great other than the fact the text within the string displays as the field code instead of the results obtained by the field. However, if I double click the Mtext after inserting it, the text changes to what it is supposed to. See below for a screenshot. I didn't double-click the text on the right so it shows the code.

 

Is there a way to make the text display as it should other than to double click it?

 

Lonnie

 

test.jpg

 

insertSV.lsp

Link to comment
Share on other sites

Hi Lonnie,

 

Entmake'ing Fields is pretty difficult, as you have to also entmake the extension dictionary of the text, mtext or attribute and then the ACAD_FIELD dictionary stored within that and the TEXT dictionary stored within that...

 

Hence the workaround is to use vla-AddMText to create the MText Field.

Link to comment
Share on other sites

As a very rough mod to your code;

 

(defun c:isv (/ pt1 pt1x pt1y zoneNUM zoneLTR mtstr) (vl-load-com)
 (and
   (progn
    (setq pt1 (getpoint "\nSpecify insertion point: "))
    (setq pt1x (car pt1))
    (setq pt1y (cadr pt1))
    (cond
      ((<= pt1x 5)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone8>%")))
      ((and (<= pt1x 10)(> pt1x 5)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone7>%"))))
      ((and (<= pt1x 15)(> pt1x 10)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone6>%"))))
      ((and (<= pt1x 20)(> pt1x 15)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone5>%"))))
      ((and (<= pt1x 25)(> pt1x 20)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone4>%"))))
      ((and (<= pt1x 30)(> pt1x 25)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone3>%"))))
      ((and (<= pt1x 35)(> pt1x 30)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone2>%"))))
      ((> pt1x 35)(setq zoneNUM (strcat "%<\\AcVar CustomDP.zone1>%")))
      )
    (cond
      ((<= pt1y 4.68)(setq zoneLTR "%<\\AcVar CustomDP.zonea>%"))
      ((and (<= pt1y  9.34)(> pt1y  4.68)(setq zoneLTR "%<\\AcVar CustomDP.zoneb>%")))
      ((and (<= pt1y 14.00)(> pt1y  9.34)(setq zoneLTR "%<\\AcVar CustomDP.zonec>%")))
      ((and (<= pt1y 18.66)(> pt1y 14.00)(setq zoneLTR "%<\\AcVar CustomDP.zoned>%")))
      ((and (<= pt1y 23.32)(> pt1y 18.66)(setq zoneLTR "%<\\AcVar CustomDP.zonee>%")))
      ((> pt1y 23.32)(setq zoneLTR "%<\\AcVar CustomDP.zonef>%"))
      )
    (setq mtstr (strcat zoneNUM "-" zoneLTR))
   )
   (progn
     (setq mobj
       (vla-AddMText
         (vlax-get
           (vla-get-ActiveDocument
             (vlax-get-acad-object)
           )
           (if (= 1 (getvar 'CVPORT)) 'Paperspace 'Modelspace)
         )
         (vlax-3D-point (trans pt1 1 0)) 0 mtstr
       )
     )
     (vla-put-layer mobj "TEXT")
     (vla-put-height mobj 0.188)
     (vla-put-stylename mobj "romans")
     (vla-put-attachmentpoint mobj acAttachmentpointmiddlecenter)
   )
 )
)

Link to comment
Share on other sites

Hi Lonnie,

 

Entmake'ing Fields is pretty difficult, as you have to also entmake the extension dictionary of the text, mtext or attribute and then the ACAD_FIELD dictionary stored within that and the TEXT dictionary stored within that...

 

Hence the workaround is to use vla-AddMText to create the MText Field.

 

Oh I see. Though I've been using more and more VL commands in my programs, I'm still figuring out new ones so thanks for the suggestion. I will try out your code and post the results later. Thanks again.

 

Lonnie

Link to comment
Share on other sites

Ok so I've completely changed gears Lee and I'm hoping your lisp super powers can fix my lisp :).

 

While working on my Mtext insertion routine I was also putting together a very similar routine that inserts a Block with Attributes. There had been a lot of talk on the board recently about Block Attribute Editing/Extraction/Replacing so I thought I'd try my hand at putting something together that way.

 

The routine I came up with works as it should. The block gets inserted at a user defined point and based on the location of the block on the drawing, the 1 and only attribute of the block gets populated with the appropriate fields. However if that block gets moved to another location then the fields don't update so I've had to come up with another routine that will update all blocks. That's where I'm stuck. Here's my code:

 

(defun c:bu(/ Att1Tag ss_blocks NumBlocks Count Ename Attname
      Att_Data Att_txt  pt1  pt1x pt1y mtstr
      NewStr New_Attdata)
 (setq Att1Tag "SV")
 (setq ss_blocks (ssget "_X" '((0 . "INSERT")(2 . "SECT_VIEW"))))
 (setq NumBlocks (sslength ss_blocks))
 (setq Count 0)
 (repeat NumBlocks
   (setq Ename (ssname ss_blocks Count))
   (setq Attname Ename)
   (while (= "ATTRIB" (dxf 0 (setq Attname (entnext Attname))))
     (if (= Att1Tag (dxf 2 Attname))
    (progn
  (setq Att_Data (entget Attname))
  (setq Att_txt (cdr (assoc 1 Att_Data)))
  (setq pt1 (assoc 10 Att_Data))
  (setq pt1x (cadr pt))
  (setq pt1y (caddr pt))
  (cond
    ((<= pt1x 5)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone8>%")))
    ((and (<= pt1x 10)(> pt1x 5)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone7>%"))))
    ((and (<= pt1x 15)(> pt1x 10)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone6>%"))))
    ((and (<= pt1x 20)(> pt1x 15)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone5>%"))))
    ((and (<= pt1x 25)(> pt1x 20)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone4>%"))))
    ((and (<= pt1x 30)(> pt1x 25)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone3>%"))))
    ((and (<= pt1x 35)(> pt1x 30)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone2>%"))))
    ((> pt1x 35)(setq zoneNUM (strcat "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zone1>%")))
    )
  (cond
    ((<= pt1y 4.68)(setq zoneLTR "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zonea>%"))
    ((and (<= pt1y  9.34)(> pt1y  4.68)(setq zoneLTR "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zoneb>%")))
    ((and (<= pt1y 14.00)(> pt1y  9.34)(setq zoneLTR "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zonec>%")))
    ((and (<= pt1y 18.66)(> pt1y 14.00)(setq zoneLTR "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zoned>%")))
    ((and (<= pt1y 23.32)(> pt1y 18.66)(setq zoneLTR "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zonee>%")))
    ((> pt1y 23.32)(setq zoneLTR "%<[url="file://\\AcVar"]\\AcVar[/url] CustomDP.zonef>%"))
    )
  (setq mtstr (strcat zoneNUM "-" zoneLTR))
  (setq NewStr mtstr)
  (setq New_Attdata (subst (cons 1 NewStr)(assoc 1 Att_data) Att_Data))
  (entmod New_Attdata)
  (entupd (cdr (assoc 330 Att_Data)))
  ); progn
); if
     ); while
   (setq Count (1+ Count))
   ); repeat
 (redraw att1 1)
 (princ)
 )
(defun dxf (code e)
 (cdr (assoc code (entget e)))
 )

 

 

All blocks called "SECT_VIEW" have the tag "SV" and they all get updated by this routine but only to the value calculated by the last block evaulated. I mean each block should have a different value based on where they are located on the drawing but instead they all have the value that is tied to the last block of the selection set (I believe).

 

Where am I going wrong?

 

Lonnie

Link to comment
Share on other sites

Hi Lonnie,

 

Again, you will have to approach the problem using VL, unless you create the dictionary objects for the Field.

 

Perhaps something like this?

 

(defun c:bu ( / *error* _StartUndo _EndUndo _2D _FieldString doc ss Att Block )
 (vl-load-com)
 ;; © Lee Mac 2010

 (setq Att "SV" Block "SECT_VIEW")

 (defun *error* ( msg )
   (and doc (_EndUndo doc))
   (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
       (princ (strcat "\n** Error: " msg " **")))
   (princ)
 )

 (defun _StartUndo ( doc ) (_EndUndo doc)
   (vla-StartUndoMark doc)
 )

 (defun _EndUndo ( doc )
   (if (= 8 (logand 8 (getvar 'UNDOCTL)))
     (vla-EndUndoMark doc)
   )
 )

 (defun _2D ( p ) (list (car p) (cadr p)))

 (defun _GetInsertion ( o )
   (if (eq AcAlignmentLeft (vla-get-Alignment o))
     (vlax-get o 'InsertionPoint)
     (vlax-get o 'TextAlignmentPoint)
   )
 )

 (defun _FieldString ( x y )
   (strcat "%<\\AcVar CustomDP.zone"
     (cond
       ( (<= x 5.0) "8")
       ( (and (<  5.0 x) (<= x 10.0)) "7" )
       ( (and (< 10.0 x) (<= x 15.0)) "6" )
       ( (and (< 15.0 x) (<= x 20.0)) "5" )
       ( (and (< 20.0 x) (<= x 25.0)) "4" )
       ( (and (< 25.0 x) (<= x 30.0)) "3" )
       ( (and (< 30.0 x) (<= x 35.0)) "2" )
       ( "1" )
     )
     ">%-%<\\AcVar CustomDP.zone"
     (cond
       ( (<= y 4.68) "a" )
       ( (and (<= y  9.34)(> y  4.68)) "b" )
       ( (and (<= y 14.00)(> y  9.34)) "c" )
       ( (and (<= y 18.66)(> y 14.00)) "d" )
       ( (and (<= y 23.32)(> y 18.66)) "e" )
       ( "f" )
     )
     ">%"
   )
 )

 (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))

 (if (ssget "_X" (list (cons 0 "INSERT") (cons 2 Block) (cons 66 1)))
   (progn
     (_StartUndo doc)
     
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))

       (mapcar
         (function
           (lambda ( attrib )
             (if (eq Att (vla-get-TagString attrib))
               (vla-put-TextString attrib
                 (apply '_FieldString
                   (_2D
                     (_GetInsertion attrib)
                   )
                 )
               )
             )
           )
         )
         (vlax-invoke obj 'GetAttributes)
       )
     )
     (vla-delete ss)

     (_EndUndo doc)
   )
 )

 (princ)
)

Completely Untested of course.

Edited by Lee Mac
Link to comment
Share on other sites

Lee,

 

I'm getting the following error:

 

** Error: bad argument type: VLA-OBJECT "SV" **

 

I tried looking at your code to figure out what's going on but I'm like a tourist in a foreign country having only a High School class as the basis for my understanding of the language :?

Link to comment
Share on other sites

What did you change? I've been looking at it and I'm trying to figure out the ins and outs of it but I'm getting nowhere....

 

BTW, thanks a heap. It works great!

 

Lonnie

Link to comment
Share on other sites

Oh I changed one line of your code to better reflect just how awesome you are:

 

;; © Lee "The Superman of LISP" Mac 2010

 

 

 

Lonnie

Link to comment
Share on other sites

Ahh sorry, I changed:

 

(vla-put-TextString Att .. 

to

 

(vla-put-TextString attrib ... 

 

Att was the attribute string, attrib was the attribute object :)

 

Thanks for your compliments, I'm glad the code works :D If you have any questions about the code, just shout.

 

Lee

Link to comment
Share on other sites

So as I'm looking at your code, because you format your code so well, I had a revelation. I was using fields in the Mtext that's created but I really don't need fields do I since the whole value for the "SV" tag is being replaced? I just tried it out without using the fields and it still works.

 

Again thanks for all the help you give out both consciously and otherwise. There is no one (other than Alan, David and maybe a couple of others) who can't learn from the code you post here.

 

Lonnie

Link to comment
Share on other sites

Lee,

 

One more thing, how would I make the text underlined? Before when I was making Mtext with ENTMAKEX, all I had to do was put a "\L" in front of the string but that doesn't work this way.

 

Lonnie

Link to comment
Share on other sites

Nevermind Lee I figured it out myself. Putting the %%U in front of the string did the trick.

 

I was confusing my routines. That's what I get for changing directions in the middle of this thread :oops:.

 

Lonnie

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...