Jump to content

Format MTEXT with Numbered List


Bill Tillman

Recommended Posts

I'm adding some text in the notes section of a drawing using LISP and would like to use numbered list. In searching for how to format the string to add numbers I'm only finding limited information. I need the list to look like this when it's on the page

  1. Note #1
  2. Note #2
  3. Note #3 and this paragraph shows how the text will be formatted correctly and wrap the desired way with an indent on the left side to align with the other text using a numbered list.
  4. Note #4

 

So far I've found that \pxi does something like this but I haven't found the correct way to turn it on and off when needed.

Link to comment
Share on other sites

hi bill,

Mtext does have numbering but can't be compressed like your #3 paragraph.

i'm not sure whether system variable to control?

i would also need to know :)

 

[This is alternative]

i would create acad table with 2 columns x few rows which

left column for numbering text , the right column for longer text.

After filling texts in required cells,

explode the table, remove the exploded lines by simple routine.

 

my 0.02

Link to comment
Share on other sites

Thanks. I have found how AutoCAD formats a numbered MTEXT list by creating one and then looking at it's properties. See attached screenshot. If I follow this correctly, I will need to first know the number of items in the list. This is for my infamous automated process so there are no users around to click a mouse or enter text. And the number of items in the list will always vary depending on the type of drawing being created. So I think I can make a first pass through the optional features and for each one to be included increment a counter so I can then format the string....but I still think there has to be an easier way.

 

BTW - The list above will show up differently depending on the screen resolution you're using. And I may be splitting hairs with this but MTEXT does compress, that is it indents the text like I've shown if one of the paragraphs needs to wrap around to the next line. This is exactly what I want to happen, I just need to figure out how to format the string before I use MTEXT to print it.

MtextNumberedList.jpg

Link to comment
Share on other sites

Bill,

 

Just setup an MText the way you want, and then dig through the MText Object's TextString Property.

 

Example:

 

\pxi-3,l3,t3;1.[color="red"]Note #1[/color]\P2.[color="red"]Note #2[/color]\P3.[color="red"]Note #3 and this paragraph shows how the text will be formatted correctly and wrap the desired way with an indent on the left side to align with the other text using a numbered list.[/color]\P4.[color="red"]Note #4[/color]

Link to comment
Share on other sites

Or maybe not....WOW Black Box that looks like you have something there. Now, is the pxi-3, l3 is a little confusing in the example I use because it has three items in it. I just added some more items to the list and noticed that pxi-3 remained the same. So, it looks like all I have to do is reinstall the counter I was using earlier....darn I really was hoping MTEXT would handle the auto increment for me. Won't be easy but I think I see to do this now. Thanks.

Link to comment
Share on other sites

Give this a try... Working here:

 

(vl-load-com)

(defun _AddNumberedListToMText (oMText lst / i)
 (setq i 0)
 (vla-put-textstring
   oMText
   (strcat
     "\\pxi-3,l3,t3;"
     (vl-string-right-trim
       "\\P"
       (apply
         'strcat
         (mapcar
           (function
             (lambda (x)
               (strcat (itoa (setq i (1+ i))) ".\t" x "\\P")
             )
           )
           lst
         )
       )
     )
   )
 )
)

 

 

Quick demonstration, undo not supported; I know you're doing this automagically, hence the sub-function above:

 

(defun c:FOO (/ ss)
 (if (setq ss (ssget ":S:E:L" '((0 . "MTEXT"))))
   (_AddNumberedListToMText
     (vlax-ename->vla-object (ssname ss 0))
     '("Note #1"
       "Note #2"
       "Note #3 and this paragraph shows how the text will be formatted correctly and wrap the desired way with an indent on the left side to align with the other text using a numbered list."
       "Note #4"
      )
   )
 )
 (princ)
)

 

 

 

[Edit] - Technically, it replaces the existing TextString, and doesn't 'add' to it, so as always, take from this what you like. Just wanted to clarify.

Link to comment
Share on other sites

Thanks again Black Box. I guess I need a little more hand holding with this. Here is the code I'm using to build the string:

(setq Features "\\LSELECTED FEATURES\\l\\P\\pxi-3,l3,t3;"
       fcount 1)
(if (= field1 "Y")
   (setq Features  (strcat Features (itoa fcount) ".Feature Field1\\P"
           fcount (1+ fcount)    
         )
   )

 (if (= field2 "Y")
   (setq Features  (strcat Features (itoa fcount) ".Feature Field2\\P")
           fcount (1+ fcount)
         )
   )

   (if (= field3 "Y")
     (setq Features  (strcat Features (itoa fcount) ".Feature Field3\P")
             fcount (1+ fcount)
           )
     )

 (if (= field4 "Y")
   (setq Features  (strcat Features (itoa fcount) ".Feature Field4\\P")
           fcount (1+ fcount)
         )
   )
.
  and so on, and so on.....
.

(command "._MTEXT" '(8.6875 7.6875) '(10.40625 3.5) Features "")

Notice I build a string, not a list. When it's all done the string will have anywhere from 1 to 16 line items in it. This kinda works, but I don't end up with a real numbered list. And your example works with a selection set....I'm not sure how to convert that to a totally unmanned operation. I'm starting to lean towards an ENTMAKE method to do this...!

Edited by Bill Tillman
Link to comment
Share on other sites

Thanks again Black Box. I guess I need a little more hand holding with this. Here is the code I'm using to build the string:

(setq Features "\\LSELECTED FEATURES\\l\\P\\pxi-3,l3,t3;"
       fcount 1)
(if (= field1 "Y")
   (setq Features  (strcat Features (itoa fcount) ".Feature Field1\\P"
           fcount (1+ fcount)    
         )
   )

 (if (= field2 "Y")
   (setq Features  (strcat Features (itoa fcount) ".Feature Field2\\P")
           fcount (1+ fcount)
         )
   )

   (if (= field3 "Y")
     (setq Features  (strcat Features (itoa fcount) ".Feature Field3\P")
             fcount (1+ fcount)
           )
     )

 (if (= field4 "Y")
   (setq Features  (strcat Features (itoa fcount) ".Feature Field4\\P")
           fcount (1+ fcount)
         )
   )
.
  and so on, and so on.....
.

(command "._MTEXT" '(8.6875 7.6875) '(10.40625 3.5) Features "")

Notice I build a string, not a list. When it's all done the string will have anywhere from 1 to 16 line items in it. This kinda works, but I don't end up with a real numbered list. And your example works with a selection set....I'm not sure how to convert that to a totally unmanned operation. I'm starting to lean towards an ENTMAKE method to do this...!

 

Firstly, the second offering was just to offer a manual demonstration of the sub-function's concept, and not for your production use.

 

Second, I really wish you'd have supplied your code from the outset, as it would have saved me time, etc. in being able to help. Please do that when possible moving forward. As to your code, there seems to be a misplaced paren in the field1 IF statement's 'then' expression, and a back-slash in field3 IF statement's 'then' expression, as this slight mod works here:

 

(setq Features "\\LSELECTED FEATURES\\l\\P\\pxi-3,l3,t3;"
     fcount   1
)
(if (= field1 "Y")
 (setq Features (strcat Features (itoa fcount) ".Feature Field1\\P"[color="red"])[/color]
       fcount (1+ fcount)
 )
)
(if (= field2 "Y")
 (setq Features (strcat Features (itoa fcount) ".Feature Field2\\P")
       fcount   (1+ fcount)
 )
)
(if (= field3 "Y")
 (setq Features (strcat Features (itoa fcount) ".Feature Field3\[color="red"]\[/color]P")
       fcount   (1+ fcount)
 )
)
(if (= field4 "Y")
 (setq Features (strcat Features (itoa fcount) ".Feature Field4\\P")
       fcount   (1+ fcount)
 )
)
;|
 and so on, and so on.....
|;
(command "._MTEXT" '(8.6875 7.6875) '(10.40625 3.5) Features "")

 

 

 

Cheers

Link to comment
Share on other sites

Thanks and sorry about the confusion. I think that ENTMAKE might do this...

 

(defun C:TEST (/ str)
 (doit "SELECTED FEATURES:\\P\\pxi-3,l3,t3;1.\tTHIS IS LINE ITEM #1\\P2.\tTHIS IS LINE ITEM #2\\P3.\tTHIS IS LINE ITEM #3 AND IT'S A LOT LONGER STRING OF TEXT THAN THE OTHER ITEMS\\P4.\tTHIS IS THE LAST LINE ITEM")

(defun doit (str)
 
 (entmake
   (list
     (cons 0 "MTEXT")
     (cons 100 "AcDbEntity")
     (cons 67 0)
     (cons 410 "Model")
     (cons 8 "Text2")
     (cons 100 "AcDbMText")
     (cons 10 '(8.32062 8.01356 0.0))
     (cons 40 0.08)
     (cons 41 4.16978)
     (cons 46 0.0)
     (cons 71 1)
     (cons 72 5)
     (cons 1 str)
     (cons 7 "DIM")
     (cons 210 '(0.0 0.0 1.0))
     (cons 11 '(1.0 0.0 0.0))
     (cons 42 3.8781)
     (cons 43 0.792381)
     (cons 50 0.0)
     (cons 73 1)
     (cons 44 1.0)
   )
 )
 (princ)
)

This is working and it's actually building the numbered list I'm looking for. I just gotta work on the location (x,y,z) to place it and get some more work done on properly building the string to pass to it. And I guess I'll still have to use a counter to build the string correctly. I'm going to keep at this after lunch.

Link to comment
Share on other sites

Give this a try... Working here:

 

(defun _AddNumberedListToMText (oMText lst / i)
 ...
     [color="red"]"\\pxi-3,l3,t3;"[/color]
     (vl-string-right-trim
       "\\P"
 ...
 ...

 

yeah! good tips :thumbsup: !

you guys know everything. thank you for the right direction!

thanks bill too

Link to comment
Share on other sites

Thanks and sorry about the confusion. I think that ENTMAKE might do this...

 

 

This is working and it's actually building the numbered list I'm looking for. I just gotta work on the location (x,y,z) to place it and get some more work done on properly building the string to pass to it. And I guess I'll still have to use a counter to build the string correctly. I'm going to keep at this after lunch.

 

No worries; yes, entmake and vla-AddMText will both work.

 

The advantage of using a list in lieu of concatenating strings (before you've identified all of the necessary sub-strings), is that you can easily calculate the padded width of the resultant MText, without having to then subsequently break the string you just concatenated, or evaluate the distance between vl-Position for each-and-every-single ".\t" sub-string instance... Simply build your list of strings conditionally, using the same logic above, and then perform the vl-String-Right-Trim + Apply + Mapcar sequence on said list. Lemon squeezy.

 

Cheers

Link to comment
Share on other sites

yeah! good tips :thumbsup: !

you guys know everything. thank you for the right direction!

thanks bill too

 

That is kind of you to say, hanhphuc; inaccurate of me, but appreciated nonetheless. :beer:

 

Cheers

Link to comment
Share on other sites

Yes, many thanks for the input. I have it working nicely now. The \t (tab) character was important in the string. And this handles whatever I throw at it. I just typed in what I wanted and then did a quick (entget) on the object to see how the text was being formatted. If I build the sting like that, even using a counter as well as a split with non-numbered lines and then it picks up a new numbered list in the second section. Works great but I'll probably tweak it some more once the users start asking questions about it.

(defun doit (str pt width textSize _LayoutTab)
 
 (entmake
   (list
     (cons 0 "MTEXT")
     (cons 100 "AcDbEntity")
     (cons 67 0)
     (cons 410 _LayoutTab)
     (cons 8 "Text2")
     (cons 100 "AcDbMText")
     (cons 10 pt)
     (cons 40 textSize)
     (cons 41 width)
     (cons 46 0.0)
     (cons 71 1)
     (cons 72 5)
     (cons 1 str)
     (cons 7 "DIM")
     (cons 210 '(0.0 0.0 1.0))
     (cons 11 '(1.0 0.0 0.0))
     (cons 42 3.8781)
     (cons 43 0.792381)
     (cons 50 0.0)
     (cons 73 1)
     (cons 44 1.0)
   )
 )
 (princ)
)

Link to comment
Share on other sites

No worries; yes, entmake and vla-AddMText will both work.

 

The advantage of using a list in lieu of concatenating strings (before you've identified all of the necessary sub-strings), is that you can easily calculate the padded width of the resultant MText, without having to then subsequently break the string you just concatenated, or evaluate the distance between vl-Position for each-and-every-single ".\t" sub-string instance... Simply build your list of strings conditionally, using the same logic above, and then perform the vl-String-Right-Trim + Apply + Mapcar sequence on said list. Lemon squeezy.

 

Cheers

Thanx for the idea sir, i also prefer list method :beer:

my attempt a bit different

 

sub-function

http://www.cadtutor.net/forum/showthread.php?89739-Format-MTEXT-with-Numbered-List
(defun [color="blue"]mtxno[/color] (p $ lst / i doc wid num str)
 ;hanhphuc 2014
 (setq	i   0
doc (vlax-get-acad-object)
wd (*(apply '+(mapcar ''((x) (apply x (mapcar 'strlen (cons $ lst)) ) )'(min max))) (getvar "textsize") 0.5)
) ;_ end of setq
 (repeat (length lst) (setq num (cons (itoa (setq i (1+ i))) num)))
 (vla-AddMText
   (foreach x '(ActiveDocument ActiveLayout Block) (setq doc (vlax-get doc x))) ;_ end of foreach
   (vlax-3d-point p)
   wd
   (foreach x '((mapcar ''((a b) (strcat a ".\t" b "\\P")) (reverse num) lst)
	 (cons
	  (strcat $ "\\P\\pxi-"
	   (rtos wd 2 1) ",l"
	   (rtos (/ wd 8.) 2 1) ",t"
	   (rtos wd 2 1) ";")
	  str
	  )
	 ([color="blue"]vl-string-right-trim[/color] "\\P" (apply 'strcat str)) 
	 )
     (setq str (eval x))
     ) ;_ end of foreach
   ) ;_ end of vla-AddMText
 ) ;_ end of defun

 

Bill's example

([color="blue"]mtxno[/color] '(0. 0. 0.) 			;  <-- Insertion point
      "SELECTED FEATURES:" 		;  <-- 'STR, 1st paragraph
      '("THIS IS LINE ITEM #1"	;  <-- 'LST, string list
 "THIS IS LINE ITEM #2"
 "THIS IS LINE ITEM #3 AND IT'S A LOT LONGER STRING OF TEXT THAN THE OTHER ITEMS"
 "THIS IS THE LAST LINE ITEM"
 )
      ) ;_ end of mtxno

 

example in commandline, incremental numbering is automated

invoke: test -> click point -> input 1st paragraph -> repeating 1. 2. 3... getstring -> [Enter]

(defun c:test (/ l n pt hd str lst)
 (setq	l t
n 0
) ;_ end of setq
 (if (and (setq pt (getpoint "\nPoint.. ")) (not(textpage)) (setq hd (getstring "\nHeader : " t)))
   (progn (while l
     (if (= (setq str (getstring (strcat (itoa (setq n (1+ n)))" : ") t)) "")
       (setq l nil)
       (setq lst (cons str lst))
       ) ;_ end of if
     ) ;_ end of while
   ([color="blue"]mtxno[/color] pt hd (reverse lst))
   ) ;_ end of progn
(princ "\nsorry..")
   ) ;_ end of if
 ([color="blue"]graphscr[/color])
 (princ)
 ) ;_ end of defun

Edited by hanhphuc
graphscr
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...