Help with error catching - Modifying Lee Mac Txtinc.lsp

Help with error catching - Modifying Lee Mac Txtinc.lsp

JGranata_GdB
Enthusiast Enthusiast
1,573 Views
7 Replies
Message 1 of 8

Help with error catching - Modifying Lee Mac Txtinc.lsp

JGranata_GdB
Enthusiast
Enthusiast

Good day all, 

 

I am still learning lisp, and how to modify code. Lee Mac has provided a txtinc.lsp from his website and another post (can not recall which forum) that will add/subtract numbers within text. I have already modified the code slightly, and used it. However, recently I found an issue with it and receive an error when a quotation mark (") is included in the selected text.

I.e. Selecting a text with 12" or  "13.4 will produce an error message of "Error: malformed string on input" and halt the code where it is, without continuing, and no indication of which items were adjusted. 

 

Ideally I would love to fix the code to work around this, while still having the functionality of working with negative numbers (using the - within text). However I assume that this would be difficult to change/adjust and I would love to take this opportunity to learn how to use error catching to disregard these instances. The code I am working with is below: 

 

;; Text Increment  -  Lee Mac
;; Increments numerical data found in a selection of Text or MText
;; objects by a value specified by the user.
;;***************************************************************************************************************
;; Added in repeat for multiple selection, worked with Lee Mac with rounding issue. 
;; J.Granata - January 2017 
;;***************************************************************************************************************

(defun c:TEST ( / e i l s x )
(prompt "\n***Select Text To Adjust Elevations****")
    (if (null *inc*)
        (setq *inc* -1.1)
    );;If -set default value to -1.1 if no previous data
    (if (setq i (getreal (strcat "\nEnter value to change Elevation by: <" (rtos *inc* 2) ">: ")))
        (setq *inc* i)
    );;If - get value
    (if (equal 0.0 (rem *inc* 1) 1e-8)
        (setq *inc* (fix *inc*))
    );;If
    (if (setq s (ssget "_:L" '((0 . "TEXT,MTEXT") (1 . "*#*"))))
        (repeat (setq i (sslength s))
            (setq e (entget (ssname s (setq i (1- i))))
                  x (assoc 1 e)
            )
            (entmod
                (subst
                    (cons 1
                        (apply 'strcat
                            (mapcar
                                (function
                                    (lambda ( x )
                                        (if (numberp x)
                                            (LM:num->str (+ x *inc*))
                                            x
                                        )
                                    );;Lambda
                                );;Function
                                (LM:splitstring (cdr x))
                            )
                        );;Apply
                    );;Cons
                    x e
                );;Subst
            );;EntMod
        );;Repeate
    );;If
    (princ);;Exit Cleanly
);;End Function         

;; Split String  -  Lee Mac
;; Splits a string into a list of text and numbers

(defun LM:splitstring ( s )
    (
        (lambda ( l )
            (read
                (strcat "("
                    (vl-list->string
                        (apply 'append
                            (mapcar
                                (function
                                    (lambda ( a b c )
                                        (cond
                                            (   (= 92 b)
                                                (list 32 34 92 b 34 32)
                                            )
                                            (   (or (< 47 b 58)
                                                    (and (= 45 b) (< 47 c 58) (not (< 47 a 58)))
                                                    (and (= 46 b) (< 47 a 58) (< 47 c 58))
                                                )
                                                (list b)
                                            )
                                            (   (list 32 34 b 34 32))
                                        )
                                    )
                                )
                                (cons nil l) l (append (cdr l) (list nil))
                            )
                        )
                    )
                    ")"
                )
            )
        )
        (vl-string->list s)
    )
)
;; Number to String  -  Lee Mac
;; Converts a supplied numerical argument to a string

(defun LM:num->str ( num / dim rtn )
    (if (equal num (atoi (rtos num 2 0)) 1e-8)
        (rtos num 2 0)
        (progn
            (setq dim (getvar 'dimzin))
            (setvar 'dimzin 8)
            (setq rtn (rtos num 2 8))
            (setvar 'dimzin dim)
            rtn
        )
    )
)

(princ)

 

I was thinking of adding in an if statement within the repeat similar to what is below using a combination of Vl-catch-all-apply and vl-catch-all-error-p and then using a princ line at the end of the code with a statement telling how many instances were not included. There is potent in the loop to changing the color to 'highlight' these error instances where the code would not adjust the numbers.

 

However, I do not know where to add the (setq catchit (vl-catch-all-apply... )) to catch the "Error: malformed string on input".  In the below code, I have set up the structure that I though could be used.  I have commented out the AutoDesk example for vl-catch-all-apply to test my loop and output. 

 

......
(setq T2a (Cdr T2)) ;;Extracts text item
(setq catchit nil) ;;defaults the Catchit back to nil for current loop
;;TEST for Catchit
;(setq catchit (vl-catch-all-apply '/ '(50 0))) ;;Example line to test. need format of (vl-catch-all-apply 'function list)
(if (vl-catch-all-error-p catchit) ;;if error catch is not nil
	(setq ErrorCnt (1+ ErrorCnt)) ;;Adds 1 to error counter, else continue with program. Potentially add code here to change the color to find these instances easier
	(progn
		(if (vl-some 'numberp (setq l (LM:SplitString T2a)))
		......
)) ;; These right parenthesis are to close the new If and Progn statements at their correct locations
.....
(princ "\n")(princ ErrorCnt)(princ " Items have been skipped")
(princ);;Exit cleanly
);;End Function

Thank you for the help and guidance. 

 

 

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

ВeekeeCZ
Consultant
Consultant

Better post a dwg example...

 

BTW... Not sure... try THIS routine... 

0 Likes
Message 3 of 8

JGranata_GdB
Enthusiast
Enthusiast

Thanks BeeKee, however I am only looking to adjust the current code with either an error catching mechanic or a way to fix. I would prefer to learn how to use the error catching in this case so that i can apply it to other code that I write or modify in the future. 

 

As per your request, I attached a sample drawing. Not much in there, as I am only displaying the case where the "malformed string on input :error#0 " is shown. To see the working code, just edit the text to remove the ". 

0 Likes
Message 4 of 8

Anonymous
Not applicable
Accepted solution

in the LM:splitstring function replace line 12

 

 

(  (= 92 b)

to

(  (or(= 92 b)(= 34 b))

Message 5 of 8

ВeekeeCZ
Consultant
Consultant

Erased by the user.

0 Likes
Message 6 of 8

hencoop
Advisor
Advisor
Accepted solution

I acquired this error function from either here or The Swamp or CAD Tutor.  I just cannot remember and I did not note it at the time.

 

;;; Usage:
;;; (errortrap '(function))
;;; For example:
;;; (errortrap (quote (setq objDict (vla-item (vla-get-dictionaries (vla-get-activedocument (vlax-get-acad-object) )) "ACAD_IMAGE_DICT" )))

;;;It will return the result if successful; returns T if it is successful and the result of the wrapped expression is nil; returns nil if Not successful.
;;;By putting it inside an if statement allows the program to continue if successful or stop if not.


;;; Standardized Error Trap
(DEFUN errortrap (symfunction / objerror result)
  (IF (VL-CATCH-ALL-ERROR-P
        (SETQ objerror (VL-CATCH-ALL-APPLY
                         '(LAMBDA (x) (SET x (EVAL symfunction)))
                         (LIST 'result)
                       ) ;_ end of vl-catch-all-apply
        ) ;_ end of setq
      ) ;_ end of vl-catch-all-error-p
    (PROGN
      (IF debug
        (STRCAT "\n"
                (VL-CATCH-ALL-ERROR-MESSAGE objerror)
                "\nWhile evaluating the expression: "
                (IF (EQ (TYPE symfunction) 'STR) symfunction "")
                "\n"
        ) ;_ end of strcat
      ) ;_ end of if
      nil
    ) ;_ end of progn
    (IF result
      result
      'T
    ) ;_ end of if
  ) ;_ end of if
) ;_ end of defun

 I use it mostly with (VL-...); VLA-...); and (VLAX-...) functions to help debug as well as continue through errors but it works for any lisp function.

AutoCAD User since 1989. Civil Engineering Professional since 1983
Product Version: 13.6.1963.0 Civil 3D 2024.4.1 Update Built on: U.202.0.0 AutoCAD 2024.1.6
                        27.0.37.14 Autodesk AutoCAD Map 3D 2024.0.1
                        8.6.52.0 AutoCAD Architecture 2024
Message 7 of 8

hencoop
Advisor
Advisor

Hello @JGranata_GdB,

 

Thanks for your kind acknowledgements.  I have used the attached routine for increasing, decreasing, incrementing, and blanking out integers and reals in strings since 1995.

 

It has seen a few revisions over the years.  I've been putting up with a minor issue it has had for quite some time but your post encouraged me to solve the problem so I could offer it to everyone here.

 

I also revised it so that external subroutines for GETKWORD, GETREAL, and GETSTRING are no longer used.

 

I have never directly coded for any GET... functions before! Smiley Surprised

 

When I first learned AutoLISP it was through the book: "INSIDE AUTOLISP - Using AutoLISP to Customize AutoCAD" for rel. 10; published by New Riders Publications, 1989; Authored by Joseph Smith and Rusty Gesner.  Early in their book they offered subroutines for all of the GET... functions and encouraged readers to make full and free use of them in their own customizations.  Recoding the attached lisp routine to replace those subroutines confirms for me that using Joseph's and Rusty's subroutines was a great choice which has saved days of coding time over the decades!  It wasn't very difficult to write the replacement code but it was tedious in comparison.

 

For those who are interested, the GET... subroutines are here: uangleudistuintukwordupointurealustr
I
n 2004 I had an error caused by a keyword being fed to one of these functions (the keyword list was programmatically constructed from the LINETYPE table).  I revised the subroutines that use them to check the keywords first using CHKKWDS and remove the offending keyword if possible.

AutoCAD User since 1989. Civil Engineering Professional since 1983
Product Version: 13.6.1963.0 Civil 3D 2024.4.1 Update Built on: U.202.0.0 AutoCAD 2024.1.6
                        27.0.37.14 Autodesk AutoCAD Map 3D 2024.0.1
                        8.6.52.0 AutoCAD Architecture 2024
Message 8 of 8

hencoop
Advisor
Advisor

I should have mentioned that NINT.LSP defines these commands: NINT (for a single object) and NINTS (for a selection of objects)

And, it has a core function which can be used in other functions: (NINT <units of precision> <change by amount> <ename>).

AutoCAD User since 1989. Civil Engineering Professional since 1983
Product Version: 13.6.1963.0 Civil 3D 2024.4.1 Update Built on: U.202.0.0 AutoCAD 2024.1.6
                        27.0.37.14 Autodesk AutoCAD Map 3D 2024.0.1
                        8.6.52.0 AutoCAD Architecture 2024
0 Likes