View Full Version : Edit Mtext via LISP
jmerch
24th Feb 2011, 04:44 am
I've searched high and low for a LISP to edit Mtext via LISP and have only found one (thanks Mike Weaver) that is almost what I want. It is posted below but I want it to autoselect a piece of MTEXT that I designate (via ssget). I have modified this code but don't understand Visual LISP enough to know why it's erroring...any help?
Original:
(defun c:mtval( / ent objmtext stroldval
strnewval)
(setq
ent (car (entsel))
objMText
(vlax-ename->vla-object ent)
strOldval (vlax-get-property objMText
"TEXTSTRING")
strnewval (getstring T (strcat "\nNew text value<"
stroldval ">: "))
)
(if
strnewval
(vlax-put-property objmtext "TEXTSTRING"
strnewval)
)
(vlax-release-object objmtext)
)
My modified code:
(defun c:mtval( / getmtext objMText strnewval)
(setq getmtext (ssget "_X" '((0 . "MTEXT")(1 . "TEST")))
objMText (vlax-ename->vla-object (entlast))
strnewval (getstring T "Enter New Text: ")
)
(if strnewval (vlax-put-property objmtext "TEXTSTRING" strnewval)
)
(vlax-release-object objmtext)
)
Tharwat
24th Feb 2011, 05:24 am
Be careful that the text string is case sensitive .
So here it goes buddy.:)
(defun c:test (/ new ss)
; Tharwat 24.02. 2010
(if (and (setq new (getstring T "Enter New Text: "))
(setq ss (ssget "_X" '((0 . "MTEXT") (1 . "test"))))
)
((lambda (i / ss1 e)
(while
(setq ss1 (ssname ss (setq i (1+ i))))
(entupd
(cdr
(assoc
-1
(entmod
(subst (cons 1 new) (assoc 1 (setq e (entget ss1))) e)
)
)
)
)
)
)
-1
)
(Alert
"\n Your replaced text is not found in the drawing....."
)
)
(princ)
)
Tharwat
jmerch
24th Feb 2011, 03:19 pm
that doesn't work...:( it asks me to select an object then just isolates it....
alanjt
24th Feb 2011, 03:49 pm
(setq getmtext (ssget "_X" '((0 . "MTEXT")(1 . "TEST"))) <-Select all MText with "TEST" value
objMText (vlax-ename->vla-object (entlast)) <- converts the last created object to a vla-object (not what you want to do here)
jmerch
24th Feb 2011, 03:56 pm
(setq getmtext (ssget "_X" '((0 . "MTEXT")(1 . "TEST"))) <-Select all MText with "TEST" value
objMText (vlax-ename->vla-object (entlast)) <- converts the last created object to a vla-object (not what you want to do here)
I know I'm selecting all Mtext with "Test" value, I understand the ssget function. But on the entlast, i thought that just grabbed the entity data from the last object, I didn't realize it converts the last created object.
In order to edit the Mtext, from what I can tell it has to be a vla-object which is why it's getting converted, right?
alanjt
24th Feb 2011, 04:00 pm
I know I'm selecting all Mtext with "Test" value, I understand the ssget function. But on the entlast, i thought that just grabbed the entity data from the last object, I didn't realize it converts the last created object.
In order to edit the Mtext, from what I can tell it has to be a vla-object which is why it's getting converted, right?
Your selection with ssget has no bearing on (entlast). You need to step through the selectionset with repeat/while or vla-get-activeselectinset.
Tharwat
24th Feb 2011, 04:21 pm
Check this out in VL .
(defun c:test (/ new ss)(vl-load-com)
; Tharwat 24.02. 2010
(if (and (setq new (getstring T "Enter New Text: "))
(setq ss (ssget "_X" '((0 . "MTEXT") (1 . "test"))))
)
((lambda (i / ss1)
(while
(setq ss1 (ssname ss (setq i (1+ i))))
(vla-put-textstring (vlax-ename->vla-object ss1) new)
)
)
-1
)
(Alert
"\n Your replaced text is not found in the drawing....."
)
)
(princ)
)
Tharwat
jmerch
24th Feb 2011, 04:46 pm
@alan: Maybe I'm not understanding you. I was doing the ssget to "grab" the mtext on my drawing, and thought I needed to convert this to vla-obect. What contains the properties (text string) of mtext? vla-get-activeselectionset isn't a function.
@Tharwat: Same result, it asks 'Select Objects in Current Drawing or Xref'...then isolates it. Why is it doing that? it's not asking me to enter any text or anything...
I appreciate the help from both of you.
Tharwat
24th Feb 2011, 04:52 pm
The two routines that I already posted for you are working normally in Arch. Autocad , but I do not have MEP cad to check these codes for it .
Anyway , can you please copy your command line after fails of the routine with your version ?
Tharwat
jmerch
24th Feb 2011, 04:54 pm
it's not really "failing", just not doing what I want...I wonder what in your code has dependency on the ACAD version...
Command: test
Select Objects in Current Drawing or Xref:
Select Objects in Current Drawing or Xref:
Regenerating model.
alanjt
24th Feb 2011, 04:57 pm
it's not really "failing", just not doing what I want...I wonder what in your code has dependency on the ACAD version...
Command: test
Select Objects in Current Drawing or Xref:
Select Objects in Current Drawing or Xref:
Regenerating model.
LoL, that's a different program all together. Make sure you are actually loading the routine.
jmerch
24th Feb 2011, 05:01 pm
LMAO....WTF...I've been loading it correctly and am pretty sure I don't have any commands called TEST....but I changed this command to something else and it seems to be working now....so thank you very much Tharwat!!!
And I'm still curious about my questions to you alan, just so I can understand it better.
Tharwat
24th Feb 2011, 05:04 pm
....but I changed this command to something else and it seems to be working now....so thank you very much Tharwat!!!
Could you please post what you have changed to let routines working with your MEP cad ?
Just curious about other cad versions.
alanjt
24th Feb 2011, 05:05 pm
LMAO....WTF...I've been loading it correctly and am pretty sure I don't have any commands called TEST....but I changed this command to something else and it seems to be working now....so thank you very much Tharwat!!!
And I'm still curious about my questions to you alan, just so I can understand it better.
(defun c:Test (/ ss str)
(if (and (setq ss (ssget "_X" '((0 . "MTEXT") (1 . "TEST")))) ; select mtext
(/= "" (setq str (getstring T "\nSpecify string: "))) ; specify string & /= ""
)
(progn
;; below steps through active selectionset
(vlax-for obj (setq ss (vla-get-activeselectionset ; active selectionset
(vla-get-activedocument (vlax-get-acad-object))
)
)
(vla-put-textstring obj str)
)
(vla-delete ss) ; delete selection set (not acutal objects, just the selection set)
)
)
(princ)
)
jmerch
24th Feb 2011, 05:15 pm
Could you please post what you have changed to let routines working with your MEP cad ?
Just curious about other cad versions.
I was just saying I changed your C:test to something like C:test1 and it worked....so somewhere I must have a routine loaded that uses TEST for the command...other than that the last code you posted works as is.
Tharwat
24th Feb 2011, 05:24 pm
I was just saying I changed your C:test to something like C:test1 and it worked....so somewhere I must have a routine loaded that uses TEST for the command...other than that the last code you posted works as is.
Yeah.... that's it .... .
Tharwat
Tharwat
24th Feb 2011, 05:36 pm
Please note jmerch that if your intended to use any of my routines that I have already posted for you, you should modify the first line of
routines to ...... which is .
(/= (setq new (getstring T "Enter New Text: ")) "")
Because if a user used the routines and pressed enter instead of supporting a string , the routine would replace the found Mtexts to nil string (invisible).
Tharwat
alanjt
24th Feb 2011, 05:37 pm
Please note jmerch that if your intended to use any of my routines that I have already posted for you, you should modify the first line of
routines to ...... which is .
(/= (setq new (getstring T "Enter New Text: ")) "")
Because if a user used the routines and pressed enter instead of supporting a string , the routine would replace the found Mtexts to nil string (invisible).
TharwatLook who's learning.
Tharwat
24th Feb 2011, 05:40 pm
Look who's learning.
Everyday I am getting odd things with Lisp. :lol:
Regards
alanjt
24th Feb 2011, 06:05 pm
To add:
In these situations, I would stay clear of using the 1 dxf code for finding text. It's case sensitive and only searches the first 250 characters.
I would avoid the use of vla-get-textstring since there is a huge bug in that it will not return a symbol properly, and instead give you a "?".
jmerch
24th Feb 2011, 09:58 pm
Please note jmerch that if your intended to use any of my routines that I have already posted for you, you should modify the first line of
routines to ...... which is .
(/= (setq new (getstring T "Enter New Text: ")) "")
Because if a user used the routines and pressed enter instead of supporting a string , the routine would replace the found Mtexts to nil string (invisible).
Tharwat
so the /= forces the user to enter something?
alanjt
24th Feb 2011, 10:01 pm
so the /= forces the user to enter something?No. /= means not equal to. If you look at my example, I have it comparing the getstring return to make sure it isn't equal to "" (what's returned if nothing is typed).
(/= "" (getstring T "\nEnter something: "))
Try it for yourself.
Tharwat
24th Feb 2011, 10:02 pm
so the /= forces the user to enter something?
No. but if the user hit enter instead of adding a string the routine won't change any of selection set to avoid the changes to nil texts.
Lee Mac
24th Feb 2011, 10:06 pm
Look who's learning.
lol.......
jmerch
24th Feb 2011, 10:42 pm
OK, I see what the /= is doing now. I haven't seen it used like that...only mainly in conditional statements...my mind doesn't think outside the box on that right now :)
Now I'm thinking of changing directions based on your guys' warnings. My MTEXT was theoretically going to always say the same thing until the user changed it which should only be once. The MTEXT is on the border for the sheet title. But I think I want to make it flexible if they have to change it in the future (I'm doing it this way b/c I'm using the setq value to enter the same data elsewhere). So, I probably shouldn't do the selection set based on MTEXT and the text value. So then I started thinking about ssget "_W" and give it points but I want this to be used on all my border sizes so the window area would never be the same...trying to think of what else I can use to filter it. I don't want it to be an attribute b/c I'd rather have it be MTEXT in case the user has to modify the layout of it or something.
alanjt
24th Feb 2011, 10:43 pm
Why not just use FIND?
jmerch
24th Feb 2011, 10:47 pm
1. b/c the data stored from the user entering the text string will be used in naming my layout tab as well as other items on the drawing.
2. I was trying to cut out the extra step of the user having to type in the initial text to replace. So if I can have a LISP find this MTEXT that will always be in the same place, and ask the user to enter the new text, it'd be done.
alanjt
24th Feb 2011, 10:50 pm
1. b/c the data stored from the user entering the text string will be used in naming my layout tab as well as other items on the drawing.
2. I was trying to cut out the extra step of the user having to type in the initial text to replace. So if I can have a LISP find this MTEXT that will always be in the same place, and ask the user to enter the new text, it'd be done.Right on. Just like to suggest core commands, even if I'm a little late at suggesting them.
jmerch
24th Feb 2011, 10:53 pm
Not a problem, I'm very open to suggestions even if they're the basic commands...sometimes I get zoned in on my ideas and try to over-think it when simple commands do the same thing.
The only other thing I can think of is to put it on it's own layer which I'd rather not do, but it could be easily filtered.
Lee Mac
24th Feb 2011, 11:15 pm
If having it on its own layer is undesirable, how about adding some xData to it on creation, then it could be filtered just by filtering for the xData App name.
Something simple like:
(-3
(
"LMAC_MTEXT"
(1002 . "{")
(1000 . "Titleblock-Text")
(1002 . "}")
)
)With a unique App Name (don't use anything prefixed with ACAD)
Then selection would be:
(ssget "_X" '((0 . "MTEXT")(-3 ("LMAC_MTEXT"))))/idea
Lee Mac
24th Feb 2011, 11:36 pm
If you decide to go down this route, you could use a function like this to add the xData:
(defun c:AddMTextXData ( / ss i )
(if (setq ss (ssget "_:L" '((0 . "MTEXT") (-4 . "<NOT") (-3 ("LMAC_MTEXT")) (-4 . "NOT>"))))
(repeat (setq i (sslength ss))
(entmod
(list
(cons -1 (ssname ss (setq i (1- i))))
'(-3 ("LMAC_MTEXT" (1002 . "{") (1000 . "Titleblock-Text") (1002 . "}")))
)
)
)
)
(princ)
)And this will edit the MText with the above xData:
(defun c:EditXDataMText ( / ss str ) (vl-load-com)
(if
(and
(ssget "_X" '((0 . "MTEXT") (-3 ("LMAC_MTEXT"))))
(not (eq "" (setq str (getstring t "\nSpecify Text Value: "))))
)
(progn
(vlax-for obj
(setq ss
(vla-get-ActiveSelectionSet
(vla-get-ActiveDocument (vlax-get-acad-object))
)
)
(vla-put-TextString obj str)
)
(vla-delete ss)
)
)
(princ)
)
And to remove the XData:
(defun c:RemoveMTextXData ( / ss i )
(if (setq ss (ssget "_:L" '((0 . "MTEXT") (-3 ("LMAC_MTEXT")))))
(repeat (setq i (sslength ss))
(entmod (list (cons -1 (ssname ss (setq i (1- i)))) '(-3 ("LMAC_MTEXT"))))
)
)
(princ)
)
jmerch
24th Feb 2011, 11:42 pm
I will have to play around with Xdata and your samples...I've never used Xdata before (let alone heard of it) :D....learn something new every day...I mean hour... :shock:
Thanks you guys!
Lee Mac
24th Feb 2011, 11:49 pm
I will have to play around with Xdata and your samples...I've never used Xdata before (let alone heard of it) :D....learn something new every day...I mean hour... :shock:
I've added a complementary function to my above post to demonstrate how to edit only those MText objects with the xData as assigned by my first function.
To view the structure of the assigned xData, use the above function to assign some xData, then query the object with this (http://lee-mac.com/entitylist.html). Try it also with a Dimension object created with Dimension Style overrides.
Lee
Lee Mac
24th Feb 2011, 11:57 pm
Updated my post to include a function to Remove the specific XData.
alanjt
25th Feb 2011, 12:26 am
Why don't you post an example drawing/titleblock. I'm not saying XData isn't a viable option, but this might can be accomplished with a little less legwork.
jmerch
25th Feb 2011, 05:01 am
When you add the vla-delete ss, shouldn't that only be deleting that selection set? Is it deleting my "str" value also? b/c this is the data I would like to keep and use elsewhere.
Lee Mac
25th Feb 2011, 12:13 pm
When you add the vla-delete ss, shouldn't that only be deleting that selection set? Is it deleting my "str" value also? b/c this is the data I would like to keep and use elsewhere.
(vla-delete ss)
Deletes the SelectionSet object from the Document SelectionSets Collection since we are finished with it at that point. When iterating through SelectionSets with Vanilla as opposed to Visual, AutoCAD takes care of the SelectionSet handling when the variable pointing to the SelectionSet is localised in the routine, so we don't have to worry.
By 'deleting' your 'str' value, I'm guessing you mean that the 'str' value is nil after the routine has completed - this is a result of the 'str' variable being localised in the routine. Have a read of this (http://lee-mac.com/localising.html) to understand why this is.
Regards,
Lee
jmerch
25th Feb 2011, 01:50 pm
local/global...I knew that :) didn't pick up on it.
jmerch
25th Feb 2011, 02:59 pm
when the user enters the sheet name, it may contain a slash "/" in it. is there a way in the lisp to convert that to a different symbol (&) to be used elsewhere? What I mean is in the stored data, not actually on the sheet. I still want the "/" to display, but want to be able to change the "/" to a "&" just within LISP not to be displayed anywhere yet.
Lee Mac
25th Feb 2011, 05:25 pm
Look into the vl-string-translate function
jmerch
25th Feb 2011, 06:21 pm
Look into the vl-string-translate function
:thumbsup: can't say it enough, you are AWESOME! Same to you alanjt!
Lee Mac
25th Feb 2011, 06:24 pm
Thanks JMerch :)
Tharwat
25th Feb 2011, 06:26 pm
:whistle: :whistle:
jmerch
25th Feb 2011, 06:30 pm
I thanked you very much yesterday :lol:...today is Lee's day....and I probably thanked Alan twice but you can't just take a thank you back, ya know?
But seriously, thanks to all of you guys! Too bad there's not a Beer icon on here or I would hand them out.
Tharwat
25th Feb 2011, 06:32 pm
I thanked you very much yesterday :lol:...today is Lee's day....and I probably thanked Alan twice but you can't just take a thank you back, ya know?
But seriously, thanks to all of you guys! Too bad there's not a Beer icon on here or I would hand them out.
Yeah........ :)
It's very kind of you to say that.
Tharwat
Powered by vBulletin™ Version 4.1.2 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.