TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: cmwade77 on October 22, 2010, 06:40:56 PM

Title: Help joining text together into one piece of mtext
Post by: cmwade77 on October 22, 2010, 06:40:56 PM
I am working on combining a few routines that I have that work with text and in the process I want to fix one of them. I have a routine that joins text together into one piece of mtext. The routine works fine as long as the first piece of text is already mtext, but I don't want my users to have to think about it. I know I could call the express tools command txt2mtxt, but I am trying to avoid that for a variety of reasons.

I have the command most of the way there, but for some reason the text moves a bit when it is converted, which I do not want, I would like for it to stay at the correct insertion point. I know that there are many on here with far better skills than I at LISP, so I thought I would ask for a little help.

Also on another note, I want it to be able to remove tabs from regular text and mtext, if you can look at the tabs portion as well and tell me what's wrong with it. (For now, I have remarked out what I need to in order to make this mode not selectable).

I appreciate any help that you can provide.


[edit:kdub. Modify Thread Title.]
Title: Re: Help joining text together into one piece of mtext
Post by: CAB on October 23, 2010, 12:11:20 AM
Haven't looked at your code but,
This won't do it for you?
http://www.theswamp.org/index.php?topic=35382.msg406001#msg406001
Title: Re: Help joining text together into one piece of mtext
Post by: CAB on October 23, 2010, 12:18:59 AM
Oh, sorry Chris I see you have some other things going on there.
Maybe more time tomorrow. 

ZZZZZZZZZZZZZZZZZz
Title: Re: Help joining text together into one piece of mtext
Post by: hermanm on October 23, 2010, 02:59:03 AM
vl-string-subst replaces only the first instance it finds:
Code: [Select]
Command: !astring
"abc\tdef\t\tqrst\t"
Command: (vl-string-subst "" "\t" astring)
"abcdef\t\tqrst\t"
Command: !bstring
"abcdefabc"
Command: (vl-string-subst "qrs" "abc" bstring)
"qrsdefabc"

So, you can test after each pass, and call the function again on the modified string if any tabs remain.

Code: [Select]
(defun detab (astring / )
  (if (vl-string-position 9
      (setq astring (vl-string-subst "" "\t" astring)))
      (setq astring(detab astring)))
  astring
)
Command: (detab astring)
"abcdefqrst"
Title: Re: Help joining text together into one piece of mtext
Post by: cmwade77 on October 25, 2010, 11:09:56 AM
I do repeat the tab test; however, it seems that in 2011 \t is not the code for tabs for some reason.

If I list a piece of text with tabs in it, I get the following result:

Quote
This is a        test with    tabs in           it.

In the properties palette it displays the same way. In 2010 it would have had the \t in place of tabs in both locations. So, I am not sure what the problem is.
Title: Re: Help joining text together into one piece of mtext
Post by: hermanm on October 25, 2010, 05:10:48 PM
I see what you mean :(
Attached image from a 3rd party text editor in 2011 shows the tabs as non-printing chars (which they are, obviously)

but:

Command: (chr 9)
"\t"

Stumped. for the moment.
Title: Re: Help joining text together into one piece of mtext
Post by: CAB on October 25, 2010, 05:19:07 PM
I do repeat the tab test; however, it seems that in 2011 \t is not the code for tabs for some reason.

If I list a piece of text with tabs in it, I get the following result:

Quote
This is a        test with    tabs in           it.

In the properties palette it displays the same way. In 2010 it would have had the \t in place of tabs in both locations. So, I am not sure what the problem is.


What do you get when you use this to select the mtext you are testing?
Code: [Select]
(assoc 1 (entget(car(entsel))))and this
Code: [Select]
(vl-string->list (cdr (assoc 1 (entget(car(entsel))))))
Title: Re: Help joining text together into one piece of mtext
Post by: cmwade77 on October 25, 2010, 05:22:17 PM
I do get the \t that way....but it will require some reworking of my code. I was hoping to keep only the vla stuff, but if it won't work that way, then I may have to opt for the old way of working it.
Title: Re: Help joining text together into one piece of mtext
Post by: CAB on October 25, 2010, 05:38:36 PM
How about this?
Code: [Select]
(vl-list->string (vl-remove 9 (vl-string->list (cdr (assoc 1 (entget(car(entsel))))))))
Title: Re: Help joining text together into one piece of mtext
Post by: cmwade77 on October 25, 2010, 06:51:52 PM
Thanks CAB, the link to the code above worked for combining into mtext. The code for tabs works some of the time, but I have attached an example of what occasionally happens. The first picture is what it starts with, the second is what I end up with. Any ideas? I have also attached the latestcode.
Title: Re: Help joining text together into one piece of mtext
Post by: Sam on October 26, 2010, 02:37:05 AM
dear sir
i thing help for u
very useful tool
from lee mac
http://www.cadtutor.net/forum/showthread.php?43115-Text-2-MText-Upgraded
Title: Re: Help joining text together into one piece of mtext
Post by: Joe Burke on October 26, 2010, 06:52:09 AM
For what it's worth...

In general the string returned by (cdr (assoc 1 (entget <mtext ename>))) is more reliable than what (vlax-get <mtext object> 'TextString) returns.

Example: the mtext string on screen is "this <delta symbol> that". The vlisp function returns "this ? that". Entget returns "this Δ that".

Stuff I learned while working on StripMtext with Steve Doman.
Title: Re: Help joining text together into one piece of mtext
Post by: cmwade77 on October 26, 2010, 06:06:34 PM
The problem with that method is if the text is too long, it only returns a small portion of the text. For my needs, I generally will not have the symbols, but I will have long (sometimes extremely long) pieces of text to work with.
Title: Re: Help joining text together into one piece of mtext
Post by: alanjt on October 27, 2010, 12:54:14 AM
For what it's worth...

In general the string returned by (cdr (assoc 1 (entget <mtext ename>))) is more reliable than what (vlax-get <mtext object> 'TextString) returns.
Agreed.

The problem with that method is if the text is too long, it only returns a small portion of the text. For my needs, I generally will not have the symbols, but I will have long (sometimes extremely long) pieces of text to work with.
Just step through the entity data, strcat all 1 and 3 dxf codes and you'll have your string.
Title: Re: Help joining text together into one piece of mtext
Post by: CAB on October 27, 2010, 08:20:24 AM
Maybe this?
Code: [Select]
;;  CAB 01.08.2010    
;;  If 2 dxf 1's ignore the first occurrence
(defun Get-String (ent / str dxf1)
  (if (= (type ent) 'VLA-OBJECT)
     (setq ent (vlax-vla-object->ename ent))
  )
  (setq str "" dxf1 "")
  (mapcar (function (lambda (x)
     (cond
       ((= (car x) 3)(setq str (strcat str (cdr x))))
       ((= (car x) 1)(setq dxf1 (cdr x)))
     )))
    (entget ent)
  )
  (setq str (strcat str dxf1))
)
Title: Re: Help joining text together into one piece of mtext
Post by: alanjt on October 27, 2010, 09:31:10 AM
mine...

Code: [Select]
(defun AT:TextString (Obj)
  ;; Extract textstring (with symbols) from text object
  ;; Works on: Attrib, Attdef, MText, Multileader, Text
  ;; Obj - Object to extract textstring from
  ;; Alan J. Thompson, 11.24.09 / 04.13.10
  (if Obj
    ((lambda (e)
       (cond ((eq (cdr (assoc 0 e)) "MULTILEADER") (cdr (assoc 304 e)))
             ((vl-position (cdr (assoc 0 e)) '("ATTDEF" "ATTRIB" "TEXT")) (cdr (assoc 1 e)))
             ((eq (cdr (assoc 0 e)) "MTEXT")
              (apply (function strcat)
                     (mapcar (function (lambda (x)
                                         (if (vl-position (car x) '(1 3))
                                           (cdr x)
                                           ""
                                         )
                                       )
                             )
                             e
                     )
              )
             )
       )
     )
      (entget (cond ((vl-consp Obj) (car Obj))
                    ((eq (type Obj) 'ENAME) Obj)
                    ((eq (type Obj) 'VLA-ObjECT) (vlax-vla-object->ename Obj))
              )
      )
    )
  )
)
Title: Re: Help joining text together into one piece of mtext
Post by: Joe Burke on October 27, 2010, 11:11:03 AM
Agreed, getting the full text string from an mtext ename which contains both DXF 1 and 3 codes is fairly well known operation.
Title: Re: Help joining text together into one piece of mtext
Post by: cmwade77 on October 27, 2010, 05:30:25 PM
Agreed, getting the full text string from an mtext ename which contains both DXF 1 and 3 codes is fairly well known operation.
This may very well be, but to be honest, I have taught myself all I know about LISP, with the help of those on this board and others. As a result, I definitely do not know everything and I do know that there are others that are far more skilled than I on this board.

I would like to know more about what the following portion does:
Code: [Select]
(mapcar (function (lambda (x)
     (cond
       ((= (car x) 3)(setq str (strcat str (cdr x)))); I understand strcat and setq, I just don't get the mapcar and such
       ((= (car x) 1)(setq dxf1 (cdr x)))
     )))
    (entget ent)
  )

At any rate, attached is what I have so far....I still need to add some code to allow for selecting multiple pieces of text, I know of one way to accomplish this, I just haven't had the time to implement it yet.
Title: Re: Help joining text together into one piece of mtext
Post by: alanjt on October 27, 2010, 05:32:27 PM
Mapcar is just there to step through the entity's data. (entget ENAME)
Title: Re: Help joining text together into one piece of mtext
Post by: CAB on October 27, 2010, 11:38:17 PM
mapcar is like a foreach except the the foreach has a variable that is set with each item in a list, like
Code: [Select]
(foreach pair (entget ent)
  ;;  do something with the variable pair
) ; end foreach

mapcar is set up with the list at the end and here the variable is x, you often see it like this:
Code: [Select]
(mapcar '(lambda(x) <do something with x> ) (entget ent))The form using (function ) executes faster but may be confusing to some.
Code: [Select]
(mapcar (function (lambda(x) <do something with x> )) (entget ent))
So this code can be setup with a foreach
Code: [Select]
(mapcar
  (function
    (lambda (x)
     (cond
       ((= (car x) 3)(setq str (strcat str (cdr x))))
       ((= (car x) 1)(setq dxf1 (cdr x)))
     )))
    (entget ent)
  )

Code: [Select]
(foreach x (entget ent)
     (cond
       ((= (car x) 3)(setq str (strcat str (cdr x))))
       ((= (car x) 1)(setq dxf1 (cdr x)))
     )
)

This code steps through each DXF pair looking for (1 . "some text") and  (3 . "some more text")

We expect the mtext to contain at least one (1 . "some text") and if the text exceeds 255 characters (not sure of the exact number)
then there will be a (3 . "some more text") the order is DXF 3 holds the first 255 characters & then the next 255 but the
remainder is placed in DXF 1. There is a bug in ACAD that sometimes there is more than one DXF 1 and the first one in
the list is not to be used. So my code collects all the DXF 3 in one variable with starcat. The DXF 1 is stored in another variable
but is overwritten each time a DXF 1 is found therefore the last or valid DXF 1 is found and added to the DXF 3 data to
complete the text string.
Title: Re: Help joining text together into one piece of mtext
Post by: CHulse on October 28, 2010, 10:00:08 AM
Thanks for that explanation CAB, I have never really understood Mapcar and Lambda...
Title: Re: Help joining text together into one piece of mtext
Post by: cmwade77 on October 28, 2010, 10:49:21 AM
Yes thank you CAB, that helps a lot. I can see how I could use it to speed up some of my other routines.