Hi all,
I've been looking for this answer for a very long time. Switching between layouts programatically is a slow process for many pages and I have for along time now thought about "What if I could do things to a page without actually having to make it current first". How can I add an MTEXT entity to a page without the need for the page to be current first. Can't I simply use the page's name in a function to add the entity to that specific page? As many times as I've come to this conclusion it would seem that others have also.
One such program I worked with a long time ago had to adjust block attributes on seveeral pages but with a hundred or so attributes on more that 10 pages had taken about 10 minutes to complete. Now, in favor of MTEXT with fields for speed and acuracy I find a simular conundrum. Although much faster, I still have the need to add and edit those MTEXT entities on multiple pages and prefer to takle this issue now before the improved functionality rolls out.
Thank you for any suggestion.
Solved! Go to Solution.
Solved by Lee_Mac. Go to Solution.
Solved by Lee_Mac. Go to Solution.
Here is a quick & simple example to add an MText object to the origin in layout 'Layout1':
(vla-addmtext (vla-get-block (vla-item (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object) ) ) "Layout1" ) ) (vlax-3D-point 0 0) 0.0 "My Text" )
However, please note that the above example assumes that the drawing layout exists and, for simplicity of the example, makes no provision if it doesn't (the vla-item method will return an error).
Alternatively, you could use Vanilla AutoLISP to entmake the MText entity:
(entmake (list '(000 . "MTEXT") '(100 . "AcDbEntity") '(100 . "AcDbMText") '(010 0.0 0.0 0.0) '(001 . "My Text") '(410 . "Layout1") ) )
This has the advantage that the code will not error if the layout does not exist, but will simply create the MText entity in the active layout.
You can use vl-catch-all-error-p function
to avoid problem with not existing layout,
just a hint:
(vl-load-com) (setq olayouts(vla-get-layouts (vla-get-activedocument (vlax-get-acad-object))) layoutname "Layout1"); change layout name here (if (vl-catch-all-error-p (setq olayout (vl-catch-all-apply 'vla-item (list olayouts layoutname)))) (alert (strcat layoutname " does not exists.")) (vla-addmtext (vla-get-block olayout ) (vlax-3D-point 0 0) 0.0 "\\fComic Sans MS|c0|b0|i1|p34;\\C163;AHHA" ) )
@Hallex wrote:You can use vl-catch-all-error-p function
to avoid problem with not existing layout,
Thank you Oleg -
I was aware of how to avoid this exception, however, I did not wish to overcomplicate the example for the OP.
@mid-awe wrote:
Thank you Lee,
If you will, why the reference to "vla-get-block"?
Because the MText object needs to be added to the block definition (AcDbBlockTableRecord) associated with the layout in question, not the Layout object (AcDbLayout) which stores the plot configuration data.
The functions vla-get-modelspace & vla-get-paperspace are 'convenience functions' which retrieve the block definition associated with the Model layout & active paperspace layout respectively; if the required paperspace layout is not active, the paperspace property of the document object cannot be used and the relevant block definition must instead be accessed from the Layout object as shown in my above example.
Thank you. That explains why all of my efforts have been in vain. I did not understand the difference between (AcDbBlockTableRecord) (AcDbLayout) for this application until your clear explanation. 🙂
No problem - I'm glad my explanation was clear!
Is it possible to AddMtext to multiple layouts at the same time? I tried supplying more that one layout name by separating them with a comma like "POOL B 8,POOL C 8,POOL D 8" It's not a problem if I have to wrap it in a foreach statement. I would just like to know if a foreach is necessary.
In case it matters, the error I recieved is: ; error: Automation Error. Key not found
Thank you.
In this case easily to use VLAX_FOR instead of foreach:
(vlax-for olayout olayouts (if (member (vla-get-name olayout) (list "Layout1" "Layout3" "LayoutN");|<-- layouts to be processed|;) (vla-addmtext (vla-get-block olayout) (vlax-3D-point 0 0) 0.0 "My text\\Pnext line" ) ) )
Given the consistency of your layout names, you could also use wcmatch, e.g.:
(defun c:mymtext ( ) (vlax-for lay (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object))) (if (wcmatch (strcase (vla-get-name lay)) "POOL [BCD] 8") (vla-addmtext (vla-get-block lay) (vlax-3D-point 0 0) 0.0 "My MText" ) ) ) (princ) ) (vl-load-com) (princ)
@mid-awe wrote:
Thank you Lee. Could I also utilize a strcat for the names? I have included as an argument to the function the specific set of plans to work with. We have the POOL set but, for instance, we also have the LANDSCAPE set, etc...
Using a wcmatch test you can separate multiple wildcard patterns using commas, these patterns are then tested using a logical OR behaviour.
Does this answer your query, or have I possibly misunderstood?
Can't find what you're looking for? Ask the community or share your knowledge.