Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to VLA-ADDMTEXT to specified Layout tab?

24 REPLIES 24
SOLVED
Reply
Message 1 of 25
mid-awe
1812 Views, 24 Replies

How to VLA-ADDMTEXT to specified Layout tab?

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.

24 REPLIES 24
Message 2 of 25
Lee_Mac
in reply to: mid-awe

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.

Message 3 of 25
Hallex
in reply to: Lee_Mac

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" )
  )

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 4 of 25
mid-awe
in reply to: Lee_Mac

Thank you Lee,
If you will, why the reference to "vla-get-block"?
Message 5 of 25
mid-awe
in reply to: Hallex

Hallex, thank you. vl-catch-all-error-p happens to be one of my new friends among the VL functions. It such a headache eliminator. For me, the ability to easily assign an alternative to reporting an error is a real relief.
Message 6 of 25
Hallex
in reply to: mid-awe

You welcome, friend

Cheers 🙂

Oleg

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 7 of 25
Lee_Mac
in reply to: Hallex


@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. Smiley Wink

Message 8 of 25
Lee_Mac
in reply to: mid-awe


@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.

Message 9 of 25
mid-awe
in reply to: Lee_Mac

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. 🙂

Message 10 of 25
Lee_Mac
in reply to: mid-awe

No problem - I'm glad my explanation was clear! Smiley Happy

Message 11 of 25
mid-awe
in reply to: Lee_Mac

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.

Message 12 of 25
Hallex
in reply to: mid-awe

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" )
  )
  )

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 13 of 25
Lee_Mac
in reply to: mid-awe

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)
Message 14 of 25
mid-awe
in reply to: Hallex

Thank you Hallex.
Message 15 of 25
mid-awe
in reply to: Lee_Mac

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...
Message 16 of 25
Lee_Mac
in reply to: mid-awe


@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?

 

 

Message 17 of 25
mid-awe
in reply to: Lee_Mac

Yeah, that answers it for me. Thank you.

I believe I may have to go about the project differently because after several lines everything breaks. The next line of MTEXT overwrites the existing MTEXT and I loose the first chunk.

I thought I had it working with (VLAX-PUT (VLAX-ENAME->VLA-OBJECT (HANDENT HNDL)) 'TextString NEWSTR)
NEWSTR is a concatenation of the existing MTEXT with the next line to add to it. But, somewhere it is going haywire.

I looked it up and it should work fine up to about 280,000,000 characters, but maybe that does not include fields. Either way I'm no where near 1,000 characters yet. If it is failing now then it will never work with the next 50 or so lines I still have to add.

BTW- I utilizing your "LM:gettextstring" function.
Message 18 of 25
mid-awe
in reply to: Lee_Mac

This method with wcmatch is working well now that I discovered my mistake. (I was adding a newline with the \P, I should've been using \n).

But, I need help with one more concern. I need to grab the handle of the individual MTEXT objects. It would be nice to have all three with the page name they were inserted to. The goal is to not stack a new MTEXT object on top of the old one. (just in case they need to be recreated at a later point). So in order to delete them before creating the new MTEXT object, I need to have some way to reference them.

I already tried to use the lay variable but that only returns "T"; no help.

Do you have a suggestion? (I get the handle just fine but without a KEY the handle will just get overwritten).

Thank you.
Message 19 of 25
mid-awe
in reply to: mid-awe

Smiley Embarassed Never mind I found it. (VLA-GET-NAME LAY)

 

Thanks again for all your help: Lee & Oleg.

Message 20 of 25
mid-awe
in reply to: Lee_Mac

I've been working with this, but for some reason I don't actually get anything like a foreach. All 3 pages receive the MTEXT object added but as it adds the MTEXT I am also trying to store the handles. Unfortunately, it only gets the first one and stores one handle for all three MTEXT objects.

I don't mean to annoy, but I really need to know if this approach can be used for my needs.

Thank you for any advice.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost