error handling help

error handling help

Anonymous
Not applicable
1,414 Views
14 Replies
Message 1 of 15

error handling help

Anonymous
Not applicable

I am fairly new at writing LISP and only have a basic knowledge of it.

 

I have writen a macro/lisp to draw multilines of certain styles.

 

I have 2 problems with it currently.

 

1. I cant get it to revert back to the current layer when an error occurs.   and unless there is a better way of doing this in order to complete the function you have to escape (so an error will always occur)

 

It is more of a macro than a LISP as all it is designed to do is load a certain multiline style and use it.

I dont want it to be overly complicated in that I want it to draw just like any other line or polyline.

 

2. Setting a location to find the muliline style from, as at the moment it opens a dialog box and you have to go and find it manually.

 

Here is the code for the LISP:

 

;Draw multiline using LBW MLStyle
(DEFUN C:MLLBW ( / *error* )

;error trap
(defun *error* ( msg )
(if oldl (setvar "clayer" oldl))
(if (not (member msg '("Function cancelled" "quit / exit abort")))
(princ (strcat "\nError: " msg))
)
(princ)
);end error trap function

;store current layer
(setq oldl (getvar "CLAYER"))

;function
(setq mlst "LBW") ;multiline style used
(command "layer" "m" "ARCHITECT" "") ;change layer to architect layer
(command "mline" "st" mlst "s" "1" "j" "z" ) ;draw multiline with LBW style
)

 

I have also attached atached the .mln file used for the styles (In order to attach I had to change the extension to .bmp to be valid it will need to be changed back to .mln to work correctly)

 

Thanks for your help

0 Likes
Accepted solutions (1)
1,415 Views
14 Replies
Replies (14)
Message 2 of 15

Satoews
Advocate
Advocate
;Draw multiline using LBW MLStyle
(DEFUN C:MLLBW ( / *error* )
;error trap
(defun *error* ( msg )
(if (not (eq (getvar 'clayer) oldl))
  (setvar 'clayer oldl))
(if (not (member msg '("Function cancelled" "quit / exit abort")))
(princ (strcat "\nError: " msg))
)
(princ)
);end error trap function
;store current layer
(setq oldl (getvar "CLAYER"))

;function
(setq mlst "LBW") ;multiline style used
(command "layer" "m" "ARCHITECT" "") ;change layer to architect layer
(command "mline" "st" mlst "s" "1" "j" "z" ) ;draw multiline with LBW style
)

the 1st one is easy enough.

 

 

Shawn T
0 Likes
Message 3 of 15

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

.... 

1. I cant get it to revert back to the current layer when an error occurs. and unless there is a better way of doing this in order to complete the function....

 

It is more of a macro than a LISP as all it is designed to do is load a certain multiline style and use it.

I dont want it to be overly complicated in that I want it to draw just like any other line or polyline.

 

2. Setting a location to find the muliline style from, as at the moment it opens a dialog box and you have to go and find it manually.

 

Here is the code for the LISP:

 

;Draw multiline using LBW MLStyle
(DEFUN C:MLLBW ( / *error* )

;error trap
(defun *error* ( msg )
(if oldl (setvar "clayer" oldl))
(if (not (member msg '("Function cancelled" "quit / exit abort")))
(princ (strcat "\nError: " msg))
)
(princ)
);end error trap function

;store current layer
(setq oldl (getvar "CLAYER"))

;function
(setq mlst "LBW") ;multiline style used
(command "layer" "m" "ARCHITECT" "") ;change layer to architect layer
(command "mline" "st" mlst "s" "1" "j" "z" ) ;draw multiline with LBW style
)

....

1.  [EDITED]  I don't see any reason for the Layer-resetting not to work from the *error* function.  But on that particular operation within *error*, since there is no opportunity for User input before the setting of the 'oldl' variable, and that's the very first thing that happens in the actual operation, it will always exist, so it shouldn't be necessary even to check whether it's there -- you should just be able to just set the CLAYER System Variable back, regardless.

 

1a.  The way to handle that is to have it wait while the User completes the command, and then go on to reset the Layer.

 

2.  I don't know about that....  I was hoping that setting the FILEDIA System Variable to 0 would take care of it, but it doesn't.  At least it only seems to do it on the first use.  But unrelated to your question, there doesn't seem to be any reason for the 'mlst' variable -- you can just use the Style name directly in the command.  [But if you do use the variable, it also ought to be added to the localized variables list at the top.]

 

Try something like this [untested]:

 

 

;Draw multiline using LBW MLStyle
(DEFUN C:MLLBW (/ *error* oldl)

;error trap
  (defun *error* (msg)
    (setvar "clayer" oldl)
    (if (not (member msg '("Function cancelled" "quit / exit abort")))
      (princ (strcat "\nError: " msg))
    )
    (princ)
  );end error trap function

;store current layer
  (setq oldl (getvar "CLAYER"))

;function
;  (setq mlst "LBW") ;multiline style used
  (command "layer" "m" "ARCHITECT" "") ;change layer to architect layer
  (command "mline" "st" "LBW" "s" "1" "j" "z") ;draw multiline with LBW style

  (while (> (getvar 'cmdactive) 0) (command pause)); take User input until command is completed, and then:

  (setvar 'clayer oldl)

  (princ)

)

 

[By the way, on the file-type acceptability issue, if you put it into a .zip file and attach that, you don't need to change the filetype ending.]

Kent Cooper, AIA
Message 4 of 15

hmsilva
Mentor
Mentor

Hi Braydenlang,

in addition to other advices, does not exist a 'full' commandline version to load a '*.mln' file.

One way is to set a block wiith your lintypes, insert the block in the current dwg, cancel the insert command before finalizing, and the mline definitions will be in the current dwg.

Another way is using 'LoadMln' function by Augusto Goncalves. to load the mline definitions into the current dwg.

 

Your code, with some mods...

 ;Draw multiline using LBW MLStyle
(defun C:MLLBW (/ *error* LoadMln ReadObject mlst mlnfile oldl)

    ;; http://adndevblog.typepad.com/autocad/2012/12/how-to-load-a-mln-file-using-lisp.html
    ;; by Augusto Goncalves
    (defun LoadMln (mlnFile / f mlineDict same newStyle xName)
        (setq mlnFile (findfile mlnFile))
        (setq f (open mlnFile "r"))
        ;;(setq f (open mlnFile "r")) 
        (if (= NIL f)
            (princ "\nInvalid MLN file.\n")
            (progn
                ;; Get the MLINESTLYE dictionary. 
                (setq mlineDict (dictsearch
                                    (namedobjdict)
                                    "ACAD_MLINESTYLE"
                                )
                )
                ;; Create the beginning of an MLINESTYLE object. 
                (setq same (list (cons 0 "MLINESTYLE")
                                 ;;(cons 102 "{ACAD_REACTORS") 
                                 ;;(cons 330 (cdr (assoc -1 mlineDict))) 
                                 ;;(cons 102 "}") 
                                 ;;(cons 330 (cdr (assoc -1 mlineDict))) 
                                 (cons 100 "AcDbMlineStyle")
                           )
                )
                ;; 
                ;; Read the data of the MLINESTYLE 
                ;; 
                (while (/= nil (setq mlStyle (ReadObject f)))
                    ;; Create the complete MLINESTYLE object. 
                    (setq newStyle (append same mlStyle)
                          xName    (entmakex newStyle)
                    )
                    ;; Append it to the MLINESTYLE dictionary. 
                    (dictadd (cdr (assoc -1 mlineDict))
                             (cdr (assoc 2 newStyle))
                             xName
                    )
                )
            )
        )
        (close f)
        (princ)
    )

    ;; http://adndevblog.typepad.com/autocad/2012/12/how-to-load-a-mln-file-using-lisp.html
    ;; by Augusto Goncalves
    (defun ReadObject (f / ObjectList firstLine code value)
        (setq ObjectList nil)
        ;; Skip the 'MLSTYLE'. 
        (setq firstLine (read-line f))
        (if (/= nil firstLine)
            (progn
                (while (/= 0 (setq code (atoi (read-line f))))
                    (setq value (vl-string-trim " " (read-line f)))
                    (if (or (= code 2)
                            (= code 3)
                            (= code 6)
                        )
                        (setq ObjectList
                                 (append ObjectList
                                         (list (cons code value))
                                 )
                        )
                    )
                    (if (or (= code 70)
                            (= code 62)
                            (= code 71)
                        )
                        (setq ObjectList
                                 (append ObjectList
                                         (list (cons code (atoi value)))
                                 )
                        )
                    )
                    (if (or (= code 51)
                            (= code 52)
                        )
                        ;; Code 51 and 52 must be converted into degrees. 
                        (setq ObjectList
                                 (append ObjectList
                                         (list (cons code
                                                     (angtof value 0)
                                               )
                                         )
                                 )
                        )
                    )
                    (if (= code 49)
                        (setq ObjectList
                                 (append ObjectList
                                         (list (cons code (atof value)))
                                 )
                        )
                    )
                )
            )
        )
        ObjectList
    )

    ;; error trap
    (defun *error* (msg)
        (if oldl
            (setvar 'CLAYER oldl)
        )
        (if (not (member msg '("Function cancelled" "quit / exit abort")))
            (princ (strcat "\nError: " msg))
        )
        (princ)
    ) ;end error trap function


    (if (setq mlnfile (findfile "C:\\Your\\Path\\BL-MLStyles.mln"))
        (progn
            (LoadMln mlnfile)
            (setq oldl (getvar 'CLAYER)) ;store current layer
            (command "_.layer" "_U" "ARCHITECT" "_T" "ARCHITECT" "_M" "ARCHITECT" "") ;change layer to architect layer
            (setq mlst "LBW") ;multiline style used
            (command "_.mline" "st" mlst "s" "1" "j" "z") ;draw multiline with LBW style
            (while (> (getvar 'cmdactive) 0) (command "\\"))
            (*error* nil) ; call the *error* function to restore oldl
        )
        (prompt "\n 'BL-MLStyles.mln' was not found... ")
    )
    (princ)
)

 

Hope this helps,
Henrique

EESignature

Message 5 of 15

Kent1Cooper
Consultant
Consultant

Wow.... I wouldn't have thought it would take that much to get a MLStyle loaded!

 

On another note -- a small thing, perhaps --

 

It always "feels wrong" to me [just psychologically -- I know it "works"] to force the *error* handler to run when there hasn't actually been an error, as a way of resetting things at the end of a routine, by using

 

(*error* nil)

 

But if you're going to do it that way, don't you need adjust the definition of the *error* function?  I haven't loaded anything like this and tried it, since I don't like that construction, but it seems to me that since you have:

  (defun *error* (msg)

    ....

    (if (not (member msg '("Function cancelled" "quit / exit abort")))

      (princ (strcat "\nError: " msg))

    )

    ....

 

and since nil [the 'msg' argument] is not a member of that list of error messages you don't want printed [such as from hitting the Escape key], won't that (if) function's test be satisifed, and won't it print

 

"Error: nil"

 

to the Command line?  Shouldn't it check both that there is a non-nil message [coming from some actual error] and that it isn't in that list?  Something like:

    ....

    (if

      (and

        msg

        (not (member msg '("Function cancelled" "quit / exit abort"))

      )

      (princ (strcat "\nError: " msg))

    )

    ....

 

 

 

Kent Cooper, AIA
0 Likes
Message 6 of 15

hmsilva
Mentor
Mentor

@Kent1Cooper wrote:

Wow.... I wouldn't have thought it would take that much to get a MLStyle loaded!

 

...


To read/load a mln file, It's the only method I know, probably exists a simpler one...

 

To get the a MLStyle loaded, we can always 'insert' a dwg with the MLStyle or use the copy-from method to copy from a dwg to the current one...

 


@Kent1Cooper wrote:

...

On another note -- a small thing, perhaps --

 

It always "feels wrong" to me [just psychologically -- I know it "works"] to force the *error* handler to run when there hasn't actually been an error, as a way of resetting things at the end of a routine, by using

 

(*error* nil)

 

But if you're going to do it that way, don't you need adjust the definition of the *error* function?  I haven't loaded anything like this and tried it, since I don't like that construction, but it seems to me that since you have:

  (defun *error* (msg)

    ....

    (if (not (member msg '("Function cancelled" "quit / exit abort")))

      (princ (strcat "\nError: " msg))

    )

    ....

 

and since nil [the 'msg' argument] is not a member of that list of error messages you don't want printed [such as from hitting the Escape key], won't that (if) function's test be satisifed, and won't it print

 

"Error: nil"

 

to the Command line?  Shouldn't it check both that there is a non-nil message [coming from some actual error] and that it isn't in that list?  Something like:

    ....

    (if

      (and

        msg

        (not (member msg '("Function cancelled" "quit / exit abort"))

      )

      (princ (strcat "\nError: " msg))

    )

    ....


My bad, you are correct, we need to check a nil or a non nil msg...

I would suggest something like this:

 

(cond ((not msg))
              ((member msg '("Function cancelled" "quit / exit abort")))
              ((princ (strcat "\n** Error: " msg " ** ")))
        )

 

Henrique

EESignature

0 Likes
Message 7 of 15

Anonymous
Not applicable

I was unable to get that load lisp to find the location on the server, I also tried putting the file locally (which is not prefered) and it came up with "** Error: bad argument type: lentityp nil **"

 

as I said this level of LISP is well beyound my understanding and dont fully know how to use visual lisp to determine and correct errors.

 

I understand why the error check was changed and that all works well.

 

Thanks for your help so far.

 

Brayden

0 Likes
Message 8 of 15

Anonymous
Not applicable
This one does not appear to work Kent1Coopers solution works for me.

Thanks for your time and help
0 Likes
Message 9 of 15

hmsilva
Mentor
Mentor

@Anonymous wrote:

I was unable to get that load lisp to find the location on the server, I also tried putting the file locally (which is not prefered) and it came up with "** Error: bad argument type: lentityp nil **"

 

as I said this level of LISP is well beyound my understanding and dont fully know how to use visual lisp to determine and correct errors.

 

I understand why the error check was changed and that all works well.

 

Thanks for your help so far.

 

Brayden


Hi Brayden,

to find the location on the server:

"\\\\yourservername\\Your\\Path\\BL-MLStyles.mln"

or

"//yourservername/your/pat/BL-MLStyles.mln"

 

the "** Error: bad argument type: lentityp nil **" I don't know where it is coming, I did test the 'demo' with the 'BL-MLStyles.mln' file, and everything worked as expected.

Don't forget to change the mln path.

 

 ;Draw multiline using LBW MLStyle
(defun C:MLLBW (/ *error* LoadMln ReadObject mlst mlnfile oldl)

   ;; http://adndevblog.typepad.com/autocad/2012/12/how-to-load-a-mln-file-using-lisp.html
   ;; by Augusto Goncalves
   (defun LoadMln (mlnFile / f mlineDict same newStyle xName)
      (setq mlnFile (findfile mlnFile))
      (setq f (open mlnFile "r"))
      ;;(setq f (open mlnFile "r")) 
      (if (= NIL f)
         (princ "\nInvalid MLN file.\n")
         (progn
            ;; Get the MLINESTLYE dictionary. 
            (setq mlineDict (dictsearch
                               (namedobjdict)
                               "ACAD_MLINESTYLE"
                            )
            )
            ;; Create the beginning of an MLINESTYLE object. 
            (setq same (list (cons 0 "MLINESTYLE")
                             ;;(cons 102 "{ACAD_REACTORS") 
                             ;;(cons 330 (cdr (assoc -1 mlineDict))) 
                             ;;(cons 102 "}") 
                             ;;(cons 330 (cdr (assoc -1 mlineDict))) 
                             (cons 100 "AcDbMlineStyle")
                       )
            )
            ;; 
            ;; Read the data of the MLINESTYLE 
            ;; 
            (while (/= nil (setq mlStyle (ReadObject f)))
               ;; Create the complete MLINESTYLE object. 
               (setq newStyle (append same mlStyle)
                     xName    (entmakex newStyle)
               )
               ;; Append it to the MLINESTYLE dictionary. 
               (dictadd (cdr (assoc -1 mlineDict))
                        (cdr (assoc 2 newStyle))
                        xName
               )
            )
         )
      )
      (close f)
      (princ)
   )

   ;; http://adndevblog.typepad.com/autocad/2012/12/how-to-load-a-mln-file-using-lisp.html
   ;; by Augusto Goncalves
   (defun ReadObject (f / ObjectList firstLine code value)
      (setq ObjectList nil)
      ;; Skip the 'MLSTYLE'. 
      (setq firstLine (read-line f))
      (if (/= nil firstLine)
         (progn
            (while (/= 0 (setq code (atoi (read-line f))))
               (setq value (vl-string-trim " " (read-line f)))
               (if (or (= code 2)
                       (= code 3)
                       (= code 6)
                   )
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code value))
                          )
                  )
               )
               (if (or (= code 70)
                       (= code 62)
                       (= code 71)
                   )
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code (atoi value)))
                          )
                  )
               )
               (if (or (= code 51)
                       (= code 52)
                   )
                  ;; Code 51 and 52 must be converted into degrees. 
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code
                                              (angtof value 0)
                                        )
                                  )
                          )
                  )
               )
               (if (= code 49)
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code (atof value)))
                          )
                  )
               )
            )
         )
      )
      ObjectList
   )

   ;; error trap
   (defun *error* (msg)
      (if oldl
         (setvar 'CLAYER oldl)
      )
      (cond ((not msg))
            ((member msg '("Function cancelled" "quit / exit abort")))
            ((princ (strcat "\n** Error: " msg " ** ")))
      )
      (princ)
   ) ;end error trap function


   (if (setq mlnfile (findfile "C:\\Your\\Path\\BL-MLStyles.mln"))
      (progn
         (LoadMln mlnfile)
         (setq oldl (getvar 'CLAYER)) ;store current layer
         (command "_.layer" "_U" "ARCHITECT" "_T" "ARCHITECT" "_M" "ARCHITECT" "") ;change layer to architect layer
         (setq mlst "LBW") ;multiline style used
         (command "_.mline" "st" mlst "s" "1" "j" "z") ;draw multiline with LBW style
         (while (> (getvar 'cmdactive) 0) (command "\\"))
         (*error* nil) ; call the *error* function to restore oldl
      )
      (prompt "\n 'BL-MLStyles.mln' was not found... ")
   )
   (princ)
)

 

Hope this helps,
Henrique

EESignature

Message 10 of 15

Anonymous
Not applicable

This is what I changed it to, it no longer comes up with the cannot find the .mln file

but still comes up with the "** error: bad argument type:lentityp nill **"

 

;Draw multiline using LBW MLStyle
(defun C:MLLBW (/ *error* LoadMln ReadObject mlst mlnfile oldl)

   ;; http://adndevblog.typepad.com/autocad/2012/12/how-to-load-a-mln-file-using-lisp.html
   ;; by Augusto Goncalves
   (defun LoadMln (mlnFile / f mlineDict same newStyle xName)
      (setq mlnFile (findfile mlnFile))
      (setq f (open mlnFile "r"))
      ;;(setq f (open mlnFile "r")) 
      (if (= NIL f)
         (princ "\nInvalid MLN file.\n")
         (progn
            ;; Get the MLINESTLYE dictionary. 
            (setq mlineDict (dictsearch
                               (namedobjdict)
                               "ACAD_MLINESTYLE"
                            )
            )
            ;; Create the beginning of an MLINESTYLE object. 
            (setq same (list (cons 0 "MLINESTYLE")
                             ;;(cons 102 "{ACAD_REACTORS") 
                             ;;(cons 330 (cdr (assoc -1 mlineDict))) 
                             ;;(cons 102 "}") 
                             ;;(cons 330 (cdr (assoc -1 mlineDict))) 
                             (cons 100 "AcDbMlineStyle")
                       )
            )
            ;; 
            ;; Read the data of the MLINESTYLE 
            ;; 
            (while (/= nil (setq mlStyle (ReadObject f)))
               ;; Create the complete MLINESTYLE object. 
               (setq newStyle (append same mlStyle)
                     xName    (entmakex newStyle)
               )
               ;; Append it to the MLINESTYLE dictionary. 
               (dictadd (cdr (assoc -1 mlineDict))
                        (cdr (assoc 2 newStyle))
                        xName
               )
            )
         )
      )
      (close f)
      (princ)
   )

   ;; http://adndevblog.typepad.com/autocad/2012/12/how-to-load-a-mln-file-using-lisp.html
   ;; by Augusto Goncalves
   (defun ReadObject (f / ObjectList firstLine code value)
      (setq ObjectList nil)
      ;; Skip the 'MLSTYLE'. 
      (setq firstLine (read-line f))
      (if (/= nil firstLine)
         (progn
            (while (/= 0 (setq code (atoi (read-line f))))
               (setq value (vl-string-trim " " (read-line f)))
               (if (or (= code 2)
                       (= code 3)
                       (= code 6)
                   )
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code value))
                          )
                  )
               )
               (if (or (= code 70)
                       (= code 62)
                       (= code 71)
                   )
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code (atoi value)))
                          )
                  )
               )
               (if (or (= code 51)
                       (= code 52)
                   )
                  ;; Code 51 and 52 must be converted into degrees. 
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code
                                              (angtof value 0)
                                        )
                                  )
                          )
                  )
               )
               (if (= code 49)
                  (setq ObjectList
                          (append ObjectList
                                  (list (cons code (atof value)))
                          )
                  )
               )
            )
         )
      )
      ObjectList
   )

   ;; error trap
   (defun *error* (msg)
      (if oldl
         (setvar 'CLAYER oldl)
      )
      (cond ((not msg))
            ((member msg '("Function cancelled" "quit / exit abort")))
            ((princ (strcat "\n** Error: " msg " ** ")))
      )
      (princ)
   ) ;end error trap function


   (if (setq mlnfile (findfile "\\\\Server\\acad\\Acad\\MLSTYLES\\BL-MLStyles.mln"))
      (progn
         (LoadMln mlnfile)
         (setq oldl (getvar 'CLAYER)) ;store current layer
         (command "_.layer" "_U" "ARCHITECT" "_T" "ARCHITECT" "_M" "ARCHITECT" "") ;change layer to architect layer
         (setq mlst "LBW") ;multiline style used
         (command "_.mline" "st" mlst "s" "1" "j" "z") ;draw multiline with LBW style
         (while (> (getvar 'cmdactive) 0) (command "\\"))
         (*error* nil) ; call the *error* function to restore oldl
      )
      (prompt "\n 'BL-MLStyles.mln' was not found... ")
   )
   (princ)
)
0 Likes
Message 11 of 15

hmsilva
Mentor
Mentor

Unfortunately, I don't have an error when I test it.

Try to load the code in VLIDE, and Debug, Break on error.

Run the code, on error, Debug and Last Break Source, and the error wil be highlited.

 

Henrique

EESignature

0 Likes
Message 12 of 15

Anonymous
Not applicable

@hmsilva wrote:

Unfortunately, I don't have an error when I test it.

Try to load the code in VLIDE, and Debug, Break on error.

Run the code, on error, Debug and Last Break Source, and the error wil be highlited.

 

Henrique


This is what was highlighted:

(dictadd (cdr (assoc -1 mlineDict))
                        (cdr (assoc 2 newStyle))
                        xName
               )

 

0 Likes
Message 13 of 15

hmsilva
Mentor
Mentor

@Anonymous wrote:
...

This is what was highlighted:

(dictadd (cdr (assoc -1 mlineDict))
                        (cdr (assoc 2 newStyle))
                        xName
               )

I can not reproduce that error, tested in AC2012/14/16...

 

Henrique

EESignature

0 Likes
Message 14 of 15

Anonymous
Not applicable
Thanks for your help with this,

once I get more knowledge in LISP I will revisit this, for know I have taken the simple solution of loading up a block with the ml styles in it.

Thanks again for the time you spent trying to sort it out.
0 Likes
Message 15 of 15

hmsilva
Mentor
Mentor

@Anonymous wrote:
Thanks for your help with this,

once I get more knowledge in LISP I will revisit this, for know I have taken the simple solution of loading up a block with the ml styles in it.

Thanks again for the time you spent trying to sort it out.

You're welcome, Braydenlang

Henrique

EESignature

0 Likes