Join multiple Dtext contents

Join multiple Dtext contents

Anonymous
Not applicable
5,386 Views
25 Replies
Message 1 of 26

Join multiple Dtext contents

Anonymous
Not applicable

Hi all.

Is there a lisp to join two "dtext" text contents in one single text line? Maybe all the text on the same Text Alignment Y value?

0 Likes
5,387 Views
25 Replies
Replies (25)
Message 2 of 26

dlanorh
Advisor
Advisor

The following should do what you ask. It doesn't delete the second text object.

(vl-load-com)

(defun c:jointext (/ *error* c_doc c_lyrs)

; localised error function
	(defun *error* ( msg ) 
		(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
		(if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nOops an Error : " msg " occurred.")))
		(princ)
	);_end_*error*_defun

;initial setups go here	
	(setq c_doc (vla-get-ActiveDocument (vlax-get-acad-object))
        t_obj (vlax-ename->vla-object (car (entsel "\nSelect text Entity to add TO : ")))
        x_obj (vlax-ename->vla-object (car (entsel "\nSelect text Entity to add FROM : ")))
  )
;start of altering drawing  
	(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
	(vla-startundomark c_doc)
  (vla-put-textstring t_obj (strcat (vla-get-textstring t_obj) " " (vla-get-textstring x_obj)))
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
  (princ) 
);end_defun

I am not one of the robots you're looking for

0 Likes
Message 3 of 26

Anonymous
Not applicable

Try this:  Text2MText Upgraded

 

 

 

 

 

Júnior Nogueira.

Por favor,  Aceitar como Solução se meu post te ajudar.

Please Accept as Solution if my post helps you.

0 Likes
Message 4 of 26

Anonymous
Not applicable

I have it. Thank you. What I want is something different. I need to join all the texts with only one selection. I need to put the texts together, but I have a file with lots of texts to put together. I needed to do this with a single selection. If I have to join one by one, maybe by the year 2050 I will finish it. I know that AutoCAD has TXT2MTXT and there is a lisp from Lee that do that, but I have to do one by one.

0 Likes
Message 5 of 26

dlanorh
Advisor
Advisor
Multiple selection into a selection set will join the text together in their database order or selection set pick order depending on how the selection is done. You will have NO control over whether the final string makes sense unless they are all in a line and you can use x or y to determine the string order.

I am not one of the robots you're looking for

Message 6 of 26

Anonymous
Not applicable

Hi  dlanorh

 

Thank you. I have a solution like that, but I need something to join all the text in a dwg file. See image attached.

In this example I need to join 2P6Ø6.3 with C=3.3. All of them.

Capturar.PNG

0 Likes
Message 7 of 26

dlanorh
Advisor
Advisor
OK, that makes more sense.
Are there the same number of each?
Are they on the same layer?
Do you want the redundant text deleted?

I am not one of the robots you're looking for

0 Likes
Message 8 of 26

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... I need to join all the texts with only one selection. I need to put the texts together, but I have a file with lots of texts to put together. I needed to do this with a single selection. ... AutoCAD has TXT2MTXT ... , but I have to do one by one.


TXT2MTXT doesn't require you to select them one by one, if that's what you're saying.  What should be the effect of the drawing order of the selected Text objects, if you select them all at once?  Does the result need to be in positional order as TXT2MTXT does it, whether or not that's the same as the drawing order?  It wouldn't be hard to make a routine if it can use drawing order, but that won't do if it's not going to give you the desired result.

 

I have a routine that requires you to select them one by one, because it uses the selection order for combining the contents, but you can pick as many as you want all in one command.  It's OneMtext.lsp, available >here<.  You would use the 1MT0 command in it, which puts a space [i.e. zero Enters] between the contents of each selected Text object in the overall combined result.  [The other commands in it put 1 or 2 Enters to start a new line, without or with a blank line between, for each one's contents.]  Unlike TXT2MTXT, it accepts selection of both plain-Text and Mtext objects.  After using it, if you want it all strung out as one Text object as your description implies [I'm not sure that's what you meant], you could pick the result and in the Properties Palette, set its Defined width to zero and then Explode it.

 

EDIT:  Your image came in while I was writing the above.  That's a little different than what I understood from your initial description, though I now see I mis-read part of it.  You just want to combine pairs  of Text objects, separately from other pairs [i.e. not all together into one overall combined one], but with mass selection?  The difficulty would seem to be in getting a routine to decide which pairs go together, but if the paired ones are always adjacent in drawing order, or if their Y coordinates always match and never match those of any other pair, it could probably be done.

Kent Cooper, AIA
0 Likes
Message 9 of 26

Anonymous
Not applicable

They are only on same layer and can have different charactrs number.

0 Likes
Message 10 of 26

Anonymous
Not applicable

As I said in my first post:

[…] All the text are on the same Text Alignment Y value […] Only those pairs.

0 Likes
Message 11 of 26

ВeekeeCZ
Consultant
Consultant

This one is working well on my example. Not sure if on yours since it's kind of hard to test that on a picture. 

 

(vl-load-com)

(defun c:PairText ( / ssp ssc lst i a ent)

  (if (and (setq ssp (ssget "_X" '((0 . "TEXT") (1 . "*P*") (410 . "Model"))))
	   (setq ssc (ssget "_X" '((0 . "TEXT") (1 . "*C*") (410 . "Model"))))
	   )
    (progn
      (setq lst (mapcar '(lambda (x) (cons (rtos (caddr (assoc 11 (entget x))) 2 8)
					   (cdr (assoc 1 (entget x)))))
			(vl-remove-if 'listp (mapcar 'cadr (ssnamex ssc)))))
      (repeat (setq i (sslength ssp))
	(setq ent (entget (ssname ssp (setq i (1- i)))))
	(if (setq a (assoc (rtos (caddr (assoc 11 ent)) 2 8) lst))
	  (entmod (subst (cons 1 (strcat (cdr (assoc 1 ent)) (cdr a)))
			 (assoc 1 ent)
			 ent))))
      (command "_.erase" ssc "")))
  (princ)
)

 

Message 12 of 26

dlanorh
Advisor
Advisor

Try this

(vl-load-com)

(defun c:jtxt ( / *error* c_doc t_obj x_obj ss1 ss2 i a_ents b_ents y_pt y1_pt j t1 t2 new_txt d_ent)

; localised error function
	(defun *error* ( msg ) 
		(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
		(if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nOops an Error : " msg " occurred.")))
		(princ)
	);_end_*error*_defun

;initial setups go here	
	(setq c_doc (vla-get-ActiveDocument (vlax-get-acad-object))
        t_obj (vlax-ename->vla-object (car (entsel "\nSelect Entity with text to add TO : ")))
        x_obj (vlax-ename->vla-object (car (entsel "\nSelect Entity with text to add FROM : ")))
        ss1 (ssget "X" (list (cons 0 "TEXT") (cons 1 (vla-get-textstring t_obj)) (cons 8 (vla-get-layer t_obj)) (cons 410 "Model")))
        ss2 (ssget "X" (list (cons 0 "TEXT") (cons 1 (vla-get-textstring x_obj)) (cons 8 (vla-get-layer x_obj)) (cons 410 "Model")))
        i 0
  );end_setq

  ;start of altering drawing  
	(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
	(vla-startundomark c_doc)
  
  (repeat (sslength ss1)
    (setq a_ents (entget (ssname ss1 i))
          y_pt (cadr (cdr (assoc 10 a_ents)))
          j 0
          i (1+ i)
    );end_setq       
    (repeat (sslength ss2)
      (setq d_ent (ssname ss2 j)
            b_ents (entget d_ent)
            y1_pt (cadr (cdr (assoc 10 b_ents)))
            j (1+ j)
      );end_setq
      (if (= y_pt y1_pt)
        (progn
          (setq t1 (cdr (assoc 1 a_ents))
                t2 (cdr (assoc 1 b_ents))
                new_txt (strcat t1 " " t2)
                a_ents (subst (cons 1 new_txt) (assoc 1 a_ents) a_ents)
          );end_setq      
          (entmod a_ents)
          (entdel d_ent)
        );end_progn
      );end_if
    );end_repeat_ss2  
  );end_repeat_ss1
  (setq ss1 nil
        ss2 nil
  );end_setq	
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
  (princ) 
);end_defun

type jtxt to start. There are two text entity selections required. The first should be one of the dtext entities the text will be added to; and the second, one of the dtext entities of the text you want to add

1st select a "2P6.." text  2nd select a "C = 3.3" text, it will then search modelspace for all other similar text strings and join those with the same y value

 

I am not one of the robots you're looking for

0 Likes
Message 13 of 26

Moshe-A
Mentor
Mentor
Accepted solution

Paulo,

 

Check this one called TxtConcat (it's simple and works Smiley LOL)

concatenatination (join) texts is base on alignment [(start,align, center,middle, fit, end) they must share the same aligment] and of cours same Y Coords. the join will be from left to right.

the text value is not restricted (e.g they must not have P or C inside) in could be anything.

 

enjoy

Moshe

 

(defun C:TxtConcat (/ isAlreadyExist formatX  formatY Y&Align X&Object ; local functions
		      ss i data^ ename0 elist0 elist1 c72 item0 item1 text1 lst0 lst1)
  
 (defun isAlreadyExist (item1)
  (vl-some
    '(lambda (item0)
      (if (and
	    (equal (car  item0) (car  item1) 0.01)
	    (=     (cadr item0) (cadr item1))
	  )
       item0
      )
     )
   data^
  )
 ); isAlreadyExist

  
 ; return formated X coords
 (defun formatX ()
  (atof (rtos (car p0) 2 2))
 )
  
 ; return formated Y coords
 (defun formatY ()
  (atof (rtos (cadr p0) 2 2))
 )

 ; return formated X coords + text entity name
 (defun X&Object ()
  (list (formatX) ename)
 )
  
 ; return formated Y coords + text alignment
 (defun Y&Align ()
  (list (formatY) c72)
 )

  
 ; here starts C:TxtConcat
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")
  
 (if (setq ss (ssget ":L" '((0 . "text"))))
  (progn
  (setq i -1 data^ '())
   (repeat (sslength ss)
    (setq i (1+ i) elist0 (entget (setq ename (ssname ss i))))

    (setq c72 (cdr (assoc '72 elist0)))
    (if (or (= c72 0) (= c72 3))
     (setq p0 (cdr (assoc '10 elist0)))
     (setq p0 (cdr (assoc '11 elist0)))
    ) 
      
    ; Build database
    (if (setq item0 (isAlreadyExist (Y&Align)))
     (setq data^ (cons (append item0 (list (X&Object))) (vl-remove item0 data^)))
     (setq data^ (cons (list (formatY) c72 (X&Object)) data^))
    )       
   ); repeat

   
   ; Concatenate texts from left to right
   ; base on text Alignment and Y coords
   (foreach item0 data^
    (if (> (vl-list-length (setq lst0 (cddr item0))) 1)
     (progn
; sort list base on X coords, from left to right (setq lst1 (vl-sort lst0 (function (lambda (x0 x1) (< (car x0) (car x1)))))) (setq elist1 (entget (cadr (car lst1)))); get first text (setq text1 (cdr (assoc '1 elist1))) (foreach item1 (cdr lst1) (setq text1 (strcat text1 " " (cdr (assoc '1 (entget (cadr item1)))))) ; concatenate texts (entdel (cadr item1)) ) (entmod (subst (cons '1 text1) (assoc '1 elist1) elist1)); update database ); progn ); if ); foreach ); progn ); if (command "._undo" "_end") (setvar "cmdecho" 1) (princ) )
0 Likes
Message 14 of 26

DannyNL
Advisor
Advisor

And here are my 2 cents....

Just a small routine that will let you select your main text and a second text to be concatenated to the main text separated by a space.

 

(defun c:Test (/ T_MainText T_SearchText T_YValue T_SearchSelection)
   (if
      (and
         (princ "\nSelect target text:")
         (setq T_MainText   (ssget ":S+." '((0 . "TEXT"))))
         (princ "\nSelect search text:")
         (setq T_SearchText (ssget ":S+." '((0 . "TEXT"))))         
      )
      (progn
         (setq T_MainText   (cdr (assoc 1 (entget (ssname T_MainText   0)))))
         (setq T_SearchText (cdr (assoc 1 (entget (ssname T_SearchText 0)))))
         (if
            (/= T_MainText T_SearchText)
            (progn
               (foreach T_Text (ssnamex (ssget "_X" (list '(0 . "TEXT") (cons 1 T_MainText))))
                  (setq T_YValue (caddr (assoc 10 (setq T_TextEntget (entget (cadr T_Text))))))
                  (if
                     (setq T_SearchSelection (ssget "_X" (list '(0 . "TEXT") (cons 1 T_SearchText) '(-4 . "*,=,*") (list 10 0.0 T_YValue 0.0))))
                     (progn
                        (entmod (subst (cons 1 (strcat T_MainText " " T_SearchText))(assoc 1 T_TextEntget) T_TextEntget))
                        (entdel (ssname T_SearchSelection 0))
                     )
                  )
               )
            )
            (princ "\n ** Error; main & search text cannot be the same string!")
         )
      )
      (princ "\n ** Error: both main & search text need to be selected!")
   )
   (princ)
)
0 Likes
Message 15 of 26

dlanorh
Advisor
Advisor
Accepted solution

The following routine will concatenated two text items with the same y value together. It is independent of the text string. You are asked to make one text entity selection to establish the text layer. The routine will then sort all text entities on that layer and the join the right of the two texts to the left with a space, before deleting the right text. Any un paired text will be left as is.

(vl-load-com)

(defun rh:sortset2_lst ( s_set / i lst ent rtn)
  (if (eq (type s_set) 'PICKSET)
    (progn
      (repeat (setq i (sslength s_set))
        (setq lst (cons (cons (vlax-ename->vla-object (setq ent (ssname s_set (setq i (1- i))))) (caddr (assoc 10 (entget ent)))) lst))
      );end_repeat
      (setq lst (vl-sort lst (function (lambda (x y) (< (cdr x) (cdr y))))))
      (setq s_set nil)
    );end_progn        
  );end_if
  (if lst (setq rtn lst) (setq rtn nil))
);end_defun

(defun c:jtxt ( / *error* c_doc t_obj x_obj ss_lst i t_x x_x)

; localised error function
	(defun *error* ( msg ) 
		(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
		(if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nOops an Error : " msg " occurred.")))
		(princ)
	);_end_*error*_defun

;initial setups go here	
	(setq c_doc (vla-get-ActiveDocument (vlax-get-acad-object))
        t_obj (vlax-ename->vla-object (car (entsel "\nSelect Text Entity on Layer to Process : ")))
        ss_lst (rh:sortset2_lst (ssget "X" (list (cons 0 "TEXT") (cons 8 (vla-get-layer t_obj)) (cons 410 "Model"))))
  );end_setq
  (if (not ss_lst) (progn (alert "Empty Selection Set") (exit)))
  
  ;start of altering drawing  
	(if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
	(vla-startundomark c_doc)
  (setq i 0)
  (while (<= i (length ss_lst))
    (if (= (cdr (nth i ss_lst)) (cdr (nth (+ i 1) ss_lst)))
      (progn
        (setq t_obj (car (nth i ss_lst))
              x_obj (car (nth (+ i 1) ss_lst))
              t_x (car (vlax-get t_obj 'insertionpoint))
              x_x (car (vlax-get x_obj 'insertionpoint))
        )
        (if (< t_x x_x)
          (progn
            (vla-put-textstring t_obj (strcat (vla-get-textstring t_obj) " " (vla-get-textstring x_obj)))
            (vla-delete x_obj)
          )
          (progn
            (vla-put-textstring x_obj (strcat (vla-get-textstring x_obj) ":" (vla-get-textstring t_obj)))
            (vla-delete t_obj)
          )
        )
        (setq i (+ i 2))
      )  
      (setq i (1+ i))
    )
  )  
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
  (princ) 
);end_defun

I am not one of the robots you're looking for

0 Likes
Message 16 of 26

Anonymous
Not applicable

Hi Moshe

That is it!

Thank you. Can it remove the space, because my text before "C" has a space, and when lisp is applied it adds two spaces between text. 

0 Likes
Message 17 of 26

Anonymous
Not applicable

Hi dlanorh

Nice!

 

Can it not add another space because my text before "C" has a space?

Maybe this?

           

            (vla-put-textstring t_obj (strcat (vla-get-textstring t_obj) "" (vla-get-textstring x_obj)))

Thank you.

0 Likes
Message 18 of 26

dlanorh
Advisor
Advisor
Accepted solution
(if (< t_x x_x)
          (progn
            (vla-put-textstring t_obj (strcat (vla-get-textstring t_obj) " " (vla-get-textstring x_obj)))
            (vla-delete x_obj)
          )
          (progn
            (vla-put-textstring x_obj (strcat (vla-get-textstring x_obj) ":" (vla-get-textstring t_obj)))
            (vla-delete t_obj)
          )
        )

To remove the extra space, remove the two red coloured strings (see above), one from each strcat statement. The bottom one is wrong anyway and still contains the  ":"  from testing.

I am not one of the robots you're looking for

0 Likes
Message 19 of 26

Moshe-A
Mentor
Mentor
Accepted solution

find this line in the code and remove  " "  that's it !

save the file and you officialy declared as co-shared coder Smiley LOL

 

 

 

(setq text1 (strcat text1 " " (cdr (assoc '1 (entget (cadr item1))))))
0 Likes
Message 20 of 26

Anonymous
Not applicable

Moshe,

Thank you.

I have some notions of lisp, but in this case the solution was obvious.

0 Likes