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

Find & Replace

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
Anonymous
1347 Views, 11 Replies

Find & Replace

I have a template that is used for multiple markets. Within this template are many instances of text similar to:

 

?MARKET ONE/MARKET TWO?

 

I'd like to run a lisp at the begining of each project that will find this text string and modify per the desired market.

 

For example:

 

C: ONE (All instances of ?MARKET ONE/MARKET TWO? change to MARKET ONE)

 

C: TWO (All instances of ?MARKET ONE/MARKET TWO? change to MARKET TWO)

 

Any help would be greatly appreciated.

11 REPLIES 11
Message 2 of 12
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:
.... 

C: ONE (All instances of ?MARKET ONE/MARKET TWO? change to MARKET ONE)

 

C: TWO (All instances of ?MARKET ONE/MARKET TWO? change to MARKET TWO)

....


Something like this ought to do it [lightly tested]:

 

(vl-load-com); if needed

(defun marketchoice (num)
  (foreach txt (mapcar 'cadr (ssnamex (ssget "_X" '((1 . "?MARKET ONE/MARKET TWO?"))))); list of entity names
    (vla-put-TextString (vlax-ename->vla-object txt) (strcat "MARKET " num))
  ); foreach
); defun
(defun C:ONE ()
  (marketchoice "ONE")
); defun
(defun C:TWO ()
  (marketchoice "TWO")
); defun

 

There are various other approaches one could take, such as using (substr) with different starting positions to extract the desired content instead of constructing it, using (subst) & (entmod) on the entity data list to make the substitution, using other ways of stepping through the Text/Mtext entities it found, using largely duplicated but fully independent commands without a subroutine, etc.

 

Those find both Text and Mtext of which that is the entire content [and for that matter, Attribute definitions not yet incorporated into Blocks, Dimensions with override Text, etc., however unlikely those might be to have that content].  If you want only [for instance] Text entities, you can restrict it in the (ssget) filter:

 

,,,,  (ssget "_X" '((0 . "TEXT") (1 . "?MARKET ONE/MARKET TWO?"))),,,,

 

or similarly with "MTEXT" instead.

 

It's case-sensitive, so if that ?both-options? text string might not always be in all capitals, that would need to be accounted for.

Kent Cooper, AIA
Message 3 of 12
Anonymous
in reply to: Kent1Cooper

Kent,

 

Thanks for the quick reply!!

 

I modified as follows:

 

(vl-load-com); if needed

(defun marketchoice (num)
  (foreach txt (mapcar 'cadr (ssnamex (ssget "_X" '((1 . "?OWNER/RENTER?"))))); list of entity names
    (vla-put-TextString (vlax-ename->vla-object txt) (strcat num))
  ); foreach
); defun
(defun C:OWN ()
  (marketchoice "OWNER")
); defun
(defun C:RENT ()
  (marketchoice "RENTER")
); defun

The problem I am having now is that the text has additional text on either side (i.e., THE ?OWNER/RENTER? AGREES TO THE FOLLOWING)

 

The routine doesn't seem to work if additional text is in the string. Also,
 will this work with Multileaders?

 

Thanks!

 

Message 4 of 12
marko_ribar
in reply to: Anonymous

Try this :

 

(vl-load-com); needed

(defun personchoice ( str )
  (foreach txt (mapcar 'cadr (ssnamex (ssget "_X" '((1 . "*?OWNER/RENTER?*"))))); list of entity names
    (vla-put-TextString (vlax-ename->vla-object txt) (vl-string-subst str "?OWNER/RENTER?" (vla-get-TextString (vlax-ename->vla-object txt))))
  ); foreach
); defun
(defun C:OWN ()
  (personchoice "OWNER")
); defun
(defun C:RENT ()
  (personchoice "RENTER")
); defun

 And don't know ab multileaders...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 5 of 12
alanjt_
in reply to: marko_ribar

(defun personchoice (str / ss i d c)
  (if (and (eq (type str) 'STR)
           (setq ss (ssget "_X"
                           '((0 . "MTEXT,MULTILEADER,TEXT")
                             (-4 . "<OR")
                             (1 . "*`?OWNER/RENTER`?*")
                             (304 . "*`?OWNER/RENTER`?*")
                             (-4 . "OR>")
                            )
                    )
           )
      )
    (repeat (setq i (sslength ss))
      (setq c (if (eq (cdr (assoc 0 (setq d (entget (ssname ss (setq i (1- i)))))))
                      "MULTILEADER"
                  )
                304
                1
              )
      )
      (entmod (subst (cons c (vl-string-subst str "?OWNER/RENTER?" (cdr (setq a (assoc c d))))) a d)
      )
    )
  )
  (princ)
)

(defun c:Own (/) (personchoice "OWNER") (princ))
(defun c:Rent (/) (personchoice "RENTER") (princ))

 

FYI: converting the PICKSET to a list and stepping through it multiple times is horrible innefficent. 

Message 6 of 12
BlackBox_
in reply to: alanjt_

FWIW - 

 

Batch Find & Replace Text



"How we think determines what we do, and what we do determines what we get."

Message 7 of 12
Anonymous
in reply to: alanjt_

Thanks to everyone for their help! The lisp provided by alanjt_ did the trick. Any chance this will also work on text with tables? If not, what I have will certainly work and save me tons of time. Thanks again!

Message 8 of 12
scot-65
in reply to: Anonymous

Another method to consider is to add extended data to the text object.

That way, if the text string does not match (possibly due to syntax error or misspelling),

the text object can still be found.

 

First, register an application:

     (if (not (tblsearch "appid" "My_App")) (regapp "My_App") );if

 

Next is to add extended data to the object:
     (entmod (append (entget (car d)) '( (-3 ("My_App" (1000 . "My_Comment"))))))

 

To find these objects:

 (if (setq s (ssget "x" '( (-3 ("My_App"))) ))...

 

???


Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.


Message 9 of 12
pbejse
in reply to: Anonymous


@Anonymous wrote:

Thanks to everyone for their help! The lisp provided by alanjt_ did the trick. Any chance this will also work on text with tables? If not, what I have will certainly work and save me tons of time. Thanks again!


Quick addition on Alanjts' code

 

(defun personchoice (str / ss func i d c e f ones)
  (if (and (eq (type str) 'STR)
           (setq ss (ssget ;"_X"
                           '((0 . "MTEXT,MULTILEADER,TEXT,ACAD_TABLE")
                             (-4 . "<OR")
                             (1 . "*`?OWNER/RENTER`?*")
                             (304 . "*`?OWNER/RENTER`?*")
                             (-4 . "OR>")
                            )
                    )
           )
          (setq func (lambda (dx st)
                       (cons dx (vl-string-subst str "?OWNER/RENTER?" st))))
      )
    (repeat (setq i (sslength ss))
           (if (eq (setq e (cdr (assoc 0
                            (setq d  (entget (ssname ss  (setq i (1- i))))))))
                  		 "ACAD_TABLE")
                 (progn (setq ones (vl-remove-if-not
                                         '(lambda (o)
                                                (and  (= (car o) 1)
                                                      (wcmatch (cdr o)
                                                            "*`?OWNER/RENTER`?*")))  d))
                        (foreach itm  ones
                              (setq d (entmod (subst (func 1 (cdr itm)) itm  d))
                                    d (entmod (subst (func 302 (cdr itm))
                                                     (cons 302  (cdr itm)) d))))
                        )
                 (entmod (subst (func (Setq f    (if (Eq e
                                                         "MULTILEADER")
                                                       304
                                                       1))
                                      (cdr (setq a (assoc f d))))
                                a
                                d))
                 )
           )
      )
(princ)
)

 

HTH

Message 10 of 12
alanjt_
in reply to: Anonymous

(defun personchoice (str / ss i d n)
  (if (and (eq (type str) 'STR)
           (setq str (strcase str)
                 ss  (ssget "_A"
                            '((0 . "ACAD_TABLE,MTEXT,MULTILEADER,TEXT")
                              (-4 . "<OR")
                              (1 . "*`?OWNER/RENTER`?*")
                              (302 . "*`?OWNER/RENTER`?*")
                              (304 . "*`?OWNER/RENTER`?*")
                              (-4 . "OR>")
                             )
                     )
           )
      )
    (repeat (setq i (sslength ss))
      (setq d (entget (ssname ss (setq i (1- i))))
            n (cdr (assoc 0 d))
      )

      (cond ((eq n "ACAD_TABLE")
             (entmod
               (mapcar
                 (function
                   (lambda (x)
                     (if (member (car x) '(1 302))
                       (cons (car x) (vl-string-subst str "?OWNER/RENTER?" (cdr x)))
                       x
                     )
                   )
                 )
                 d
               )
             )
            )
            ((member n '("MTEXT" "TEXT"))
             (entmod (subst (cons 1 (vl-string-subst str "?OWNER/RENTER?" (cdr (assoc 1 d))))
                            (assoc 1 d)
                            d
                     )
             )
            )
            ((eq n "MULTILEADER")
             (entmod (subst (cons 304 (vl-string-subst str "?OWNER/RENTER?" (cdr (assoc 304 d))))
                            (assoc 304 d)
                            d
                     )
             )
            )
      )
    )
  )
  (princ)
)

 

Message 11 of 12
pbejse
in reply to: alanjt_


@alanjt_ wrote:
(defun personchoice (str / ss i d n)
........
                   (lambda (x)
                     (if (member (car x) '(1 302))
                       (cons (car x) (vl-string-subst str "?OWNER/RENTER?" (cdr x)))
                       x
                     )
                   )
  

 


Should have thought of that and do away with wcmatch as  vl-string-subst wont do any harm if string is not found. my thinking was reduced the number of items to replace, but i ended up using entmod multiple times.

 

Clever approach Alanjt

 

Message 12 of 12
alanjt_
in reply to: pbejse


@pbejse wrote:

@alanjt_ wrote:
(defun personchoice (str / ss i d n)
........
                   (lambda (x)
                     (if (member (car x) '(1 302))
                       (cons (car x) (vl-string-subst str "?OWNER/RENTER?" (cdr x)))
                       x
                     )
                   )
  

 


Should have thought of that and do away with wcmatch as  vl-string-subst wont do any harm if string is not found. my thinking was reduced the number of items to replace, but i ended up using entmod multiple times.

 

Clever approach Alanjt

 


Well, I figured, since you have to step through the entire list to find the codes you want, why not just wrap the entire thing into one entmod, rather than checking it, then only entmoding what you want. If you look at yours, you actually step through the entity data twice. Once to remove what you don't want, then to step through what you've isolated. Also, while wcmatch is great, it can be sloooooow.

 

I doubt it made much of a difference in editing time. Also, I didn't realize one could edit a table as you did. Since civil 3d has dynamic tables, I never use regular tables, so I have little to no experience with them.

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

Post to forums  

Forma Design Contest


Autodesk Design & Make Report