Author Topic: Mtext Letter Bullets Query  (Read 4561 times)

0 Members and 1 Guest are viewing this topic.

Ambo

  • Mosquito
  • Posts: 20
Mtext Letter Bullets Query
« on: October 24, 2015, 10:37:35 AM »
Hi Guys,

Is there anyone out there who can write/share a code on extracting the last letter bullet in an Mtext and then save it as a value of a certain variable.

For example:

A.  Room Description
B.  Room Description
C.  Room Description

The list above is from a single Mtext and I need to automatically get the value of the last letter bullet which is C (dot not needed).  The list may be longer than the example and may contain double letters, say AA, AB, AC, etc. Any help would be highly appreciated.  Thank you.


Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Mtext Letter Bullets Query
« Reply #1 on: October 24, 2015, 11:00:12 AM »
Maybe something along these lines?

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / ent enx pos str )
  2.     (if
  3.         (and
  4.             (setq ent  (car (entsel "\nSelect MText: ")))
  5.             (= "MTEXT" (cdr (assoc 0 (setq enx (entget ent)))))
  6.         )
  7.         (progn
  8.             (setq str (cdr (assoc 1 enx)))
  9.             (while (setq pos (vl-string-search "\\P" str))
  10.                 (setq str (substr str (+ 3 pos)))
  11.             )
  12.             (substr str 1 (vl-string-position 9 str))
  13.         )
  14.     )
  15. )

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #2 on: October 24, 2015, 11:50:07 AM »
Thanks Lee Mac! Wow! That's absolutely brilliant!

Can I just make two follow-up request on this if you don't mind. Is it possible to remove the prompt and just select the mtext automatically?  I'm planning to run this on multiple drawings that's why.  There's only one of this mtext on every drawing and it's on the layer Room_Description.  And lastly, could you please remove the "." after the letter as well?  Many thanks!  You're the best!


CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Mtext Letter Bullets Query
« Reply #3 on: October 24, 2015, 11:51:31 AM »
Careful, the Mtext may be larger than 256 characters.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Mtext Letter Bullets Query
« Reply #4 on: October 24, 2015, 12:33:46 PM »
Thanks Lee Mac! Wow! That's absolutely brilliant!

Can I just make two follow-up request on this if you don't mind. Is it possible to remove the prompt and just select the mtext automatically?  I'm planning to run this on multiple drawings that's why.  There's only one of this mtext on every drawing and it's on the layer Room_Description.  And lastly, could you please remove the "." after the letter as well?  Many thanks!  You're the best!

Thanks - perhaps try the following:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / sel )
  2.     (if (setq sel (ssget "_X" '((0 . "MTEXT") (8 . "Room_Description"))))
  3.         (getlastbullet (ssname sel 0))
  4.     )
  5. )
  6.  
  7. (defun getlastbullet ( ent / enx itm pos str )
  8.     (setq enx (entget ent)
  9.           str (cdr (assoc 1 enx))
  10.     )
  11.     (while (setq itm (assoc 3 enx))
  12.         (setq str (strcat (cdr itm) str)
  13.               enx (cdr (member itm enx))
  14.         )
  15.     )
  16.     (while (setq pos (vl-string-search "\\P" str))
  17.         (setq str (substr str (+ 3 pos)))
  18.     )
  19.     (if (setq pos (vl-string-position 9 str))
  20.         (substr str 1 (1- pos))
  21.         str
  22.     )
  23. )

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #5 on: October 24, 2015, 12:57:29 PM »
Thanks Lee Mac,  You're absolutely genius!  Thanks to CAB as well for his comment.

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #6 on: October 24, 2015, 04:06:45 PM »
Hi Lee Mac,

Sorry to be a pain but I'm getting some weird values whenever the mtext contains only one bulleted entry.  I'm getting this value: "\\pxi-3,l3,t3;A" on a single entry instead of just "A".

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Mtext Letter Bullets Query
« Reply #7 on: October 24, 2015, 06:11:48 PM »
Thanks - and good catch!

Try the following instead:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / sel )
  2.     (if (setq sel (ssget "_X" '((0 . "MTEXT") (8 . "Room_Description"))))
  3.         (getlastbullet (ssname sel 0))
  4.     )
  5. )
  6.  
  7. (defun getlastbullet ( ent / enx itm pos str )
  8.     (setq enx (entget ent)
  9.           str (cdr (assoc 1 enx))
  10.     )
  11.     (while (setq itm (assoc 3 enx))
  12.         (setq str (strcat (cdr itm) str)
  13.               enx (cdr (member itm enx))
  14.         )
  15.     )
  16.     (cond
  17.         (   (wcmatch str "*\\P*")
  18.             (while (setq pos (vl-string-search "\\P" str))
  19.                 (setq str (substr str (+ 3 pos)))
  20.             )
  21.         )
  22.         (   (wcmatch str "\\pxi*;*")
  23.             (setq str (substr str (+ 2 (vl-string-position 59 str))))
  24.         )
  25.     )
  26.     (if (setq pos (vl-string-position 9 str))
  27.         (substr str 1 (1- pos))
  28.         str
  29.     )
  30. )

Though, the above still does not account for general formatting overrides applied to the content through the MText Editor (such as changes to font, text height etc.) - in order to account for the presence of other MText formatting codes, you may want to consider the following:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / sel )
  2.     (if (setq sel (ssget "_X" '((0 . "MTEXT") (8 . "Room_Description"))))
  3.         (getlastbullet (ssname sel 0))
  4.     )
  5. )
  6.  
  7. (defun getlastbullet ( ent / enx itm pos rgx str )
  8.     (setq enx (entget ent)
  9.           str (cdr (assoc 1 enx))
  10.     )
  11.     (while (setq itm (assoc 3 enx))
  12.         (setq str (strcat (cdr itm) str)
  13.               enx (cdr (member itm enx))
  14.         )
  15.     )
  16.     (while (setq pos (vl-string-search "\\P" str))
  17.         (setq str (substr str (+ 3 pos)))
  18.     )
  19.     (if (setq pos (vl-string-position 9 str))
  20.         (setq str (substr str 1 (1- pos)))
  21.     )
  22.     (if (setq rgx (vlax-get-or-create-object "vbscript.regexp"))
  23.         (progn
  24.             (setq str (LM:quickunformat rgx str))
  25.             (vlax-release-object rgx)
  26.         )
  27.     )
  28.     str
  29. )
  30.  
  31. ;; Quick Unformat  -  Lee Mac
  32. ;; Returns a string with all MText formatting codes removed.
  33. ;; rgx - [vla] Regular Expressions (RegExp) Object
  34. ;; str - [str] String to process
  35.  
  36. (defun LM:quickunformat ( rgx str )
  37.     (if
  38.         (null
  39.             (vl-catch-all-error-p
  40.                 (setq str
  41.                     (vl-catch-all-apply
  42.                        '(lambda nil
  43.                             (vlax-put-property rgx 'global     actrue)
  44.                             (vlax-put-property rgx 'multiline  actrue)
  45.                             (vlax-put-property rgx 'ignorecase acfalse)
  46.                             (foreach pair
  47.                                '(
  48.                                     ("\032"     . "\\\\\\\\")
  49.                                     (" "        . "\\\\P|\\n|\\t")
  50.                                     ("$1"       . "\\\\(\\\\[ACcFfHKkLlOopQTW])|\\\\[ACcFfHKkLlOopQTW][^\\\\;]*;|\\\\[ACcFfKkHLlOopQTW]")
  51.                                     ("$1$2/$3"  . "([^\\\\])\\\\S([^;]*)[/#\\^]([^;]*);")
  52.                                     ("$1$2"     . "\\\\(\\\\S)|[\\\\](})|}")
  53.                                     ("$1"       . "[\\\\]({)|{")
  54.                                     ("\\$1$2$3" . "(\\\\[ACcFfHKkLlOoPpQSTW])|({)|(})")
  55.                                     ("\\\\"     . "\032")
  56.                                 )
  57.                                 (vlax-put-property rgx 'pattern (cdr pair))
  58.                                 (setq str (vlax-invoke rgx 'replace str (car pair)))
  59.                             )
  60.                         )
  61.                     )
  62.                 )
  63.             )
  64.         )
  65.         str
  66.     )
  67. )

However, the above is likely overkill for most situations.

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #8 on: October 24, 2015, 07:36:51 PM »
Hi Lee Mac,

I never thought that it's going to complicate the code that much!!! Wow!  And thank you very much by the way for your quick response.  You never ceases to amaze me with your brilliant codes. Many, many thanks! *Thumbs up*

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Mtext Letter Bullets Query
« Reply #9 on: October 25, 2015, 07:58:00 AM »
I never thought that it's going to complicate the code that much!!! Wow!  And thank you very much by the way for your quick response.  You never ceases to amaze me with your brilliant codes. Many, many thanks! *Thumbs up*

You're most welcome Ambo, I'm happy to help  :-)

As noted, the first code snippet in my last post is probably sufficient for 95% of the MText that you are likely to process with the function (and will be much faster to evaluate than the second function); the second example uses the Regular Expressions object to ensure all remaining MText formatting codes are removed from the resulting string - the increased complexity of this second example may give some indication as to how much of a headache MText formatting codes are to work with...

Lee

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #10 on: October 25, 2015, 03:05:10 PM »
Can I just pick your brain some more Lee Mac.  I'm just thinking that if some stubborn individual opted to type the letters manually instead of using the bullets then we will be getting the whole last line (e.g C.  Room Description) instead of just the letter C .  Is there a way to cover for this in the code in case it happens just to avoid any errors? But please don't bother if it's going to take a lot of time. Thanks.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Mtext Letter Bullets Query
« Reply #11 on: October 25, 2015, 06:42:14 PM »
I'm just thinking that if some stubborn individual opted to type the letters manually instead of using the bullets then we will be getting the whole last line (e.g C.  Room Description) instead of just the letter C .  Is there a way to cover for this in the code in case it happens just to avoid any errors?

Sure - please try the following:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / sel )
  2.     (if (setq sel (ssget "_X" '((0 . "MTEXT") (8 . "Room_Description"))))
  3.         (getlastbullet (ssname sel 0))
  4.     )
  5. )
  6.  
  7. (defun getlastbullet ( ent / enx itm pos str )
  8.     (setq enx (entget ent)
  9.           str (cdr (assoc 1 enx))
  10.     )
  11.     (while (setq itm (assoc 3 enx))
  12.         (setq str (strcat (cdr itm) str)
  13.               enx (cdr (member itm enx))
  14.         )
  15.     )
  16.     (cond
  17.         (   (wcmatch str "*\\P*")
  18.             (while (setq pos (vl-string-search "\\P" str))
  19.                 (setq str (substr str (+ 3 pos)))
  20.             )
  21.         )
  22.         (   (wcmatch str "\\pxi*;*")
  23.             (setq str (substr str (+ 2 (vl-string-position 59 str))))
  24.         )
  25.     )
  26.     (if (setq pos (vl-some '(lambda ( c ) (vl-string-position c str)) '(46 9 32)))
  27.         (substr str 1 pos)
  28.         str
  29.     )
  30. )

Or perhaps the following is a better approach:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / sel )
  2.     (if (setq sel (ssget "_X" '((0 . "MTEXT") (8 . "Room_Description"))))
  3.         (getlastbullet (ssname sel 0))
  4.     )
  5. )
  6.  
  7. (defun getlastbullet ( ent / enx itm pos str )
  8.     (setq enx (entget ent)
  9.           str (cdr (assoc 1 enx))
  10.     )
  11.     (while (setq itm (assoc 3 enx))
  12.         (setq str (strcat (cdr itm) str)
  13.               enx (cdr (member itm enx))
  14.         )
  15.     )
  16.     (cond
  17.         (   (wcmatch str "*\\P*")
  18.             (while (setq pos (vl-string-search "\\P" str))
  19.                 (setq str (substr str (+ 3 pos)))
  20.             )
  21.         )
  22.         (   (wcmatch str "\\pxi*;*")
  23.             (setq str (substr str (+ 2 (vl-string-position 59 str))))
  24.         )
  25.     )
  26.     (if (setq pos (vl-remove nil (mapcar '(lambda ( c ) (vl-string-position c str)) '(46 9 32))))
  27.         (substr str 1 (apply 'min pos))
  28.         str
  29.     )
  30. )

The above will return all characters on the last line until either a period, tab or space character is found - of course, this will be tripped up if such characters are not used following the bullet letter, but are subsequently used elsewhere on the last line.
« Last Edit: October 25, 2015, 06:47:25 PM by Lee Mac »

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #12 on: October 25, 2015, 07:04:25 PM »
Hi Lee Mac,

Thanks very much.  If I'll use the second one, does it mean there's no need for your Quick Unformat routine anymore?

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Mtext Letter Bullets Query
« Reply #13 on: October 25, 2015, 07:08:01 PM »
Thanks very much.  If I'll use the second one, does it mean there's no need for your Quick Unformat routine anymore?

You're welcome Ambo  :-)

I could incorporate the Quick Unformat function, but unless you are working with heavily formatted MText I think it may be overkill for this task - if you find yourself receiving unexpected results which include fragments of MText formatting, I can post a version of the function which incorporates it.

Lee

Ambo

  • Mosquito
  • Posts: 20
Re: Mtext Letter Bullets Query
« Reply #14 on: October 25, 2015, 07:52:09 PM »
Hi Lee Mac,

You're such a great help. I can't thank you enough.