Lisp modification request

Lisp modification request

brendon_butler2
Explorer Explorer
444 Views
7 Replies
Message 1 of 8

Lisp modification request

brendon_butler2
Explorer
Explorer

I would love some assistance with a Lisp routine that I used AI to create for me that is not working 100% and don't seem to be getting anywhere with AI now after many revisions.

Summary of what i'm trying to achieve.

A Lisp routine that prompts to select multiple single-line text objects and replaces the period symbols (.) with | (vertical bar). But only those that appear as decimals in numeric values.

 

e.g. Int. Walls 0.15, 0.35
to 
Int. Walls 0|15, 0|35

 

Unfortunately, the below code will only result in processing 1 line of text and won't process the other lines of text when selecting multiple. It otherwise works fine.

Can this be modified for this to work?

 

Thanks in advance! 

 

(defun is-digit (ch)
"Return T if character CH is a numeric digit (0-9)."
(if (and (>= (ascii ch) (ascii "0"))
(<= (ascii ch) (ascii "9")))
T
nil
)
)

(defun replace-decimal-period (str)
"Return a new string built from STR where a period that is both preceded and followed
by a digit (i.e. a decimal point) is replaced with a '|'."
(setq newStr "") ; accumulator for new string
(setq len (strlen str)) ; note: in AutoLISP, string indexes are 1-based.
(setq i 1)
(while (<= i len)
(setq char (substr str i 1))
(if (and (equal char ".")
(> i 1) ; make sure we have a previous character
(< i len) ; and a character following the period
(is-digit (substr str (- i 1) 1)) ; previous char is a digit
(is-digit (substr str (+ i 1) 1)) ; next char is a digit
)
(setq newStr (strcat newStr "|")) ; Add the pipe symbol
;; Skip adding the period by not adding `char`
)
(if (not (and (equal char ".")
(> i 1)
(< i len)
(is-digit (substr str (- i 1) 1))
(is-digit (substr str (+ i 1) 1)))
)
(setq newStr (strcat newStr char)) ; Add the character if it's not a period to replace
)
(setq i (1+ i))
)
newStr
)

(defun c:ReplaceDecimal ( / ss count i obj txt newTxt)
"Prompt to select TEXT objects. Then, for each, replace a decimal point ('.')
that is between two digits with a '|'. Works on both AcDbText and AcDbMText."
(setq ss (ssget '((0 . "TEXT,MTEXT"))))
(if ss
(progn
(setq count (sslength ss))
(setq i 0)
(while (< i count)
(setq obj (vlax-ename->vla-object (ssname ss i)))
(cond
((= (vla-get-objectname obj) "AcDbText")
(setq txt (vla-get-TextString obj))
(setq newTxt (replace-decimal-period txt))
(if (/= txt newTxt)
(vla-put-TextString obj newTxt)
)
)
((= (vla-get-objectname obj) "AcDbMText")
(setq txt (vla-get-contents obj))
(setq newTxt (replace-decimal-period txt))
(if (/= txt newTxt)
(vla-put-contents obj newTxt)
)
)
)
(setq i (1+ i))
)
(princ "\nFinished processing: decimal points replaced where applicable.")
)
(princ "\nNo text objects selected.")
)
(princ) ; exit quietly
)

0 Likes
Accepted solutions (1)
445 Views
7 Replies
Replies (7)
Message 2 of 8

Sea-Haven
Mentor
Mentor

One way may be to split the sentence into words, Int. Walls 0.15, 0.35 becomes ("Int." "Walls" 0.15 0.35) then change the numbers only and join back into a string.

 

Added to my to do list have some thing urgent at moment.

 

Another thought just wcmatch 0. 1. 2. -> 9. then use string subst.

0 Likes
Message 3 of 8

paullimapa
Mentor
Mentor

There are a number of minor issues but first of all I would move both sub functions is-digitreplace-decimal-period inside the main function c:ReplaceDecimal

Also place semi-colons in front of the lines describing what the function is going to do so it becomes a comment and lisp won't process those lines.
;"Return T if character CH is a numeric digit (0-9)."
(defun is-digit (ch)
(if (and (>= (ascii ch) (ascii "0"))
(<= (ascii ch) (ascii "9")))
T
nil
)
)
As for the reason why it only works on one line of TEXT is because there are variables re-used inside the replace-decimal-period function as in the main function c:ReplaceDecimal. So it's important to localize variables & functions so they won't be confused ie:
(defun replace-decimal-period (str / i newStr len char ) ; localize variables

Since the variable i is used inside this function it is equated to a different value so when returning to the main function the i variable there is now greater than the while loop so it ends. 

Also there's no such function as vla-get-contentsvla-put-contents when it comes to MTEXT.

So whether it's TEXT or MTEXT just use the same vla-get-TextStringvla-put-TextString

So I commented out the need to have separate conditions for TEXT vs MTEXT:

(setq i 0)
(while (< i count)
(setq obj (vlax-ename->vla-object (ssname ss i)))
;(cond
;((= (vla-get-objectname obj) "AcDbText")
(setq txt (vla-get-TextString obj))
(setq newTxt (replace-decimal-period txt))
(if (/= txt newTxt)
(vla-put-TextString obj newTxt)
)
;)
;((= (vla-get-objectname obj) "AcDbMText")
;(setq txt (vla-get-contents obj))
;(setq newTxt (replace-decimal-period txt))
;(if (/= txt newTxt)
;(vla-put-contents obj newTxt)
;)
;)
;)
(setq i (1+ i))
)

So give the revised version a try.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 4 of 8

brendon_butler2
Explorer
Explorer

Thank you very much for your quick response and explanations, Paul.

I have just run your revised version. However, I'm getting the same result as my previous version. I wonder if there's something else going on?
I've attached a sample DWG with my text objects. Maybe see how it works for you. Basically I want to be able to isolate all text objects in that layer to apply the command to in one go. But, it only worked if I select text strings individually.

0 Likes
Message 5 of 8

paullimapa
Mentor
Mentor
Accepted solution

looks like it works when I run my revised version:

 

paullimapa_2-1743571388458.pngpaullimapa_0-1743571321058.png

Make sure you close out of the dwg also save & load my version and not yours.

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 6 of 8

brendon_butler2
Explorer
Explorer

Yes my apologies Paul. I didn't overwrite the file. I have just retried and got it to work.
Thank you very much for your time today. I really appreciate it

0 Likes
Message 7 of 8

paullimapa
Mentor
Mentor

You are welcome…cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 8 of 8

Sea-Haven
Mentor
Mentor

Just thought would post this anyway a different method, I am sure the string-subst could be done in a loop also using (chr x)

 

; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/lisp-modification-request/td-p/13403368
; "Int. Walls 0.15, 0.35" change to "Int. Walls 0|15, 0|35"


defun c:convpipe ( / ss obj str)

(setq ss (ssget '((0 . "*text"))))
(if (= ss nil)
(progn (alert "You have not picked any text \nWill now exit")(exit))
)

(repeat (setq x (sslength ss))
  (setq obj (vlax-ename->vla-object (ssname ss (setq x (- x 1)))))
  (setq str (vlax-get obj 'textstring))
  (repeat 2
  (cond 
    ((vl-string-search "0." str)(setq str (vl-string-subst "0|" "0." str)))
    ((vl-string-search "1." str)(setq str (vl-string-subst "1|" "1." str)))
    ((vl-string-search "2." str)(setq str (vl-string-subst "2|" "2." str)))
    ((vl-string-search "3." str)(setq str (vl-string-subst "3|" "3." str)))
    ((vl-string-search "4." str)(setq str (vl-string-subst "4|" "4." str)))
    ((vl-string-search "5." str)(setq str (vl-string-subst "5|" "5." str)))
    ((vl-string-search "6." str)(setq str (vl-string-subst "6|" "6." str)))
    ((vl-string-search "7." str)(setq str (vl-string-subst "7|" "7." str)))
    ((vl-string-search "8." str)(setq str (vl-string-subst "8|" "8." str)))
    ((vl-string-search "9." str)(setq str (vl-string-subst "9|" "9." str)))
  )
  )
  (vlax-put obj 'textstring str)
)

(princ)
)
0 Likes