I've got a working batch-file that runs a script on a bunch of drawings.
The script is supposed to run a lisp-function but that function appears to only run after the main function has ran.
since I don't know much about lisps, I'll try to give the information I have.
the lsp :
(princ "\nLoading AREAS...")
(defun c:areas(); Start the program.
(setvar "cmdecho" 0)
(if (= (getvar "tilemode") 1)
(progn
(command "_.ucs" "_world")
(setq osnp (getvar "osmode"))
(setq laag (getvar "clayer"))
(setvar "osmode" 0)
(setq dimz (getvar "dimzin"))
(setvar "dimzin" 0)
(ge_dellay ladeptmp)
(if (>= (substr (getvar "acadver") 1 2) "15")
(ge_convert)
)
(setq allsel (list (cons 0 "POLYLINE")'(-4 . "<OR")(cons 8 ladeppoly)(cons 8 ladeptraf)'(-4 . "OR>")'(-3 ("COSBI"))))
(setq depsel (list (cons 0 "POLYLINE")(cons 8 ladeppoly)'(-3 ("COSBI"))))
(setq areasel (list (cons 0 "POLYLINE")(cons 8 ladeptraf)'(-3 ("COSBI"))))
(setq textsel (list (cons 0 "TEXT")(cons 8 ladeptext)'(-3 ("COSBI"))))
(setq dcl_area (load_dialog "areas"))
(setq dcl_gen (load_dialog "general"))
(setq intp nil dparea nil seltot nil)
(ar_setdep)
(ar_dia)
(if (= what_next 1)(ar_setlay))
(if (= what_next 2)(ar_check))
(if (= what_next 3)(ar_startcheck))
(unload_dialog dcl_area)
(unload_dialog dcl_gen)
(setvar "osmode" osnp)
(setvar "clayer" laag)
(setvar "dimzin" dimz)
(ge_dellay ladeptmp)
)
(alert "Only allowed in original drawing...")
)
(princ)
)
is followed by a few other (not sure) less important functions, like the ar_dia - which opens a dialog box with buttons to call other functions.
One of the other functions is AR_LIST, which is the one I need to run on each file the batch-file opens, in a script.
the ar_list is a few blocks down and looks like this
(defun ar_list(); Make department/areas list.
(setq sel (ssget "x" allsel))
(if sel
(progn
(setq temp (findfile "template.sqm"))
(if temp
(progn
(command "_.zoom" "_all")
(setq rowlist nil deplist nil)
(setq bestand (open temp "r"))
(setq row (read-line bestand))
(while row
(setq row (read-line bestand))
(if row
(progn
(setq rowlist (cons (strcase (strcat (spatie (substr row 23 14)) "_-")) rowlist))
(setq deplist (cons (strcase (spatie (substr row 23 14))) deplist))
)
)
)
(setq country (ge_dir 3 "Country"))
(ge_dwg)
(if (= (strlen dwgnaam) 9); 3to4storenr
(progn
(setq store (substr dwgnaam (- (strlen dwgnaam) 3))); 3to4storenr
(setq floor (substr dwgnaam (- (strlen dwgnaam) 5) 2)); 3to4storenr
(setq num 0)
(repeat (sslength sel)
(setq depname (cdr (cadadr (assoc -3 (entget (ssname sel num)'("COSBI"))))))
(if (not (wcmatch depname "*`island*"))
(progn
(setq ename (ssname sel num))
(command "_.area" "_a" "_o" ename "")
(ge_puntlist ename)
(setq numpol 0)
(setq selpol (ssget "_wp" puntlist allsel))
(if selpol
(repeat (sslength selpol)
(setq islname (cdr (cadadr (assoc -3 (entget (ssname selpol numpol)'("COSBI"))))))
(if (= islname (strcat depname "-island"))
(command "_s" "_o" (ssname selpol numpol) "")
)
(setq numpol (1+ numpol))
)
)
(command "")
(setq deparea (/ (getvar "area") 1000000))
(if (not (member (strcase depname) deplist))
(progn
(setq deplist (cons (strcase depname) deplist))
(setq rowlist (cons (strcase (strcat depname "_-")) rowlist))
)
)
(setq nummem (- (length deplist)(length (member (strcase depname) deplist))))
(setq deptot (nth nummem rowlist))
(vindpos "_" deptot)
(setq depareaold (substr deptot (+ pos 1)))
(if (/= depareaold "-")
(setq deparea (+ (atof depareaold) deparea))
)
(setq rowlist (subst (strcase (strcat depname "_" (rtos deparea 2 1))) (nth nummem rowlist) rowlist))
)
)
(setq num (1+ num))
)
(command "_.zoom" "_previous")
(setq rowlist (acad_strlsort rowlist)); 13-10-2014
(setq deplist (acad_strlsort deplist)); 13-10-2014
;(setq rowlist (reverse rowlist))
;(setq deplist (reverse deplist))
(ar_write)
)
(alert (strcat "Drawing name " dwgnaam " not correct, must be 9 characters.")); 3to4storenr
)
)
(alert "File TEMPLATE.SQM not found...")
)
)
(alert "No department or traffic found...")
)
)
the script only needs to run this command, close the drawing, and don't save.
so I tried (test.scr)
(ar_list)
quit
n
but that gives me the error:
Command: (ar_list)
bad argument type: stringp nil
I think the ar_list needs something from the defun c:areas , but I don't know what. The ar_list works after entering areas in the command bar.
So I also tried
areas
(ar_list)
quit
n
, but that opened the areas dialog box, does not close it, blocking the loop.
Also, when I cancel the dialog box, the ar_list works, but it again opens the areas dialog box. I think the code repeats itself in the script.
Any help would be very welcome. I received related help on here
stringp nil give us sugestion that some variable which should be text string in fact is nil. Probably because it reads value from dialog control (which is unavaliable while dialog is not active).
there is few places which may cause such problem:
we don't know what happes in ge_dir ge_dwg ge_puntlist vindpos ar_write
ar_write Maybe want to write something to dialog?
variable dwgnaam is used as string but never initialized in this function, (maybe somewhere else it is?)
(setq depname (cdr (cadadr (assoc -3 (entget (ssname sel num)'("COSBI")))))) (if (not (wcmatch depname "*island*")) if selected entity not contains XData "cosbi", it can be problem, but if I'm not wrong, there is other error message.
Related
I have a lisp written that involves setting a variable, then selecting points inside of a loop. Once I decide that I am done selecting points, I would like to be able to revert that variable back to what it was originally when I press the escape key.
eg.
(defun c:df ()
(setq oom (getvar "osmode")) ;store current state
(setq type(getint "\nEnter Type: 1 For Horizontal, 2 For Vertical : "))
(setq startpt (getpoint "\nChoose Start Point : "))
(setq ptx (+ (nth 0 startpt)10))
(setq pty (+ (nth 1 startpt)10))
(setvar "osmode" 2); change state state
(while
(setq nextpt (getpoint "'Pick Mid: ")) ;make selection
(if (null nextpt) ((princ "\nNull Value Error.") return))
(if (= type 1) (command "dimlinear" startpt nextpt "H" (list 0 pty) ))
(if (= type 2) (command "dimlinear" startpt nextpt "V" ptx ))
(setq ptx (+ 5 ptx))
(setq pty (+ 5 pty))
)
;do after escape key is pressed.
(setvar "osmode" oom) ;revert state back to original.
)
I have found possible leads to do with "User Input Errors" but couldn't really get anything to work. To my understating, when escape is pressed lisp just exits and doesn't finish executing.
Thanks in advance.
AutoLISP considers a cancellation an error.
You can therefore manage the cancellations with an error handling. AutoLISP provides the *error* function that can be locally redefined.
In addition, I would like to make a few recommendations:
do not use the type symbol for a variable, it is the name of a built-in AutoLISP function
declare the variables locally (imperatively the *error* function)
use getkword and initget to let the user choose an option.
(defun c:df (/ *error* oom option startpt ptx pty nextpt) ; local variables
;; *error* local redefinition
(defun *error* (msg)
(if (/= msg "Function cancelled")
(princ (strcat "\nError: " msg))
)
(if oom
(setvar "osmode" oom)
)
(princ)
)
(setq oom (getvar "osmode")) ;store current state
(initget 1 "Horizontal Vertical")
(setq option (getkword "\nChoose an option [Horizontal/Vertical]: "))
(if (setq startpt (getpoint "\nChoose Start Point : "))
(progn
(setq ptx (+ (car startpt) 10))
(setq pty (+ (cadr startpt) 10))
(setvar "osmode" 2) ; change state state
(while (setq nextpt (getpoint "'Pick Mid: ")) ;make selection
(if (= option "Horizontal")
(command "_dimlinear" startpt nextpt "H" (list 0 pty))
(command "_dimlinear" startpt nextpt "V" (list ptx 0))
)
(setq ptx (+ 5 ptx))
(setq pty (+ 5 pty))
)
(setvar "osmode" oom) ;revert state back to original.
)
)
(princ)
)
I have below code to call elisp function "myfun" when user click the link:
#+BEGIN_SRC elisp :results output raw
(defun myfun(filepath lineno)
(if (not (get-buffer bufname))
(get-buffer-create bufname)
)
(switch-to-buffer-other-window bufname)
(global-linum-mode)
(erase-buffer)
(insert-file-contents (format "%s" filepath))
(goto-char (point-min))
(forward-line lineno)
(setq start (point))
(forward-line -1)
(setq end (point))
(let ((x (make-overlay start end)))
(overlay-put x 'face '(:background "#fef0f1")))
)
(defun createSampleFile(file-name count)
(let ((c 0))
(with-temp-buffer
(while (< c (* 2 count))
(setq c (1+ c))
(insert (format "line %d\n" c))
(write-file filename)
))))
(let ((c 0)(filename nil))
(while (< c 4)
(setq c (1+ c))
(setq filename (format "./test%d.txt" c))
(createSampleFile filename c)
(princ (format "[[elisp:(myfun '%s' %d)][%s]]\n" filename c filename))
))
#+END_SRC
#+RESULTS:
[[elisp:(myfun './test1.txt' 1)][./test1.txt]]
[[elisp:(myfun './test2.txt' 2)][./test2.txt]]
[[elisp:(myfun './test3.txt' 3)][./test3.txt]]
[[elisp:(myfun './test4.txt' 4)][./test4.txt]]
But when click the link, I got below prompt warning dialog always:
Can we disable that dialog?
Add below line to init.el:
(setq org-confirm-elisp-link-function nil)
Here is the Code;
(setq Tobjs (vla-Explode Tvlaobj))
(setq ObjectsAsList (vlax-safearray->list (vlax-variant-value Tobjs ) ) )
(foreach % ObjectsAsList
(setq TSublayerNew (vla-get-layer %))
(cond ((eq TSublayerNew TLaynemeShort)
(command "_.AREA" "_O" %)
(setq Teee (getvar 'area))
(setq Ttvm (+ Ttvm Teee))
(princ (strcat (rtos Teee 2 0) " | "))
(setq Tcntr (+ Tcntr 1))
)
)
)
(setq TNumF Ttvm)
(princ (strcat (rtos TNumF 2 2)))
I want to get the Total area for all Region and Solids in Block (Tobjs) into variable TNumF, if it matches the condition,
it give an error: bad argument value: AutoCAD command: #
please help
Thanks in advance
It's because % is entity as vla-object, but command needs entity, so try this code:
(command "_.AREA" "_O" (vlax-vla-object->ename % ))
I have a working lisp which creates spline from 3d polylines. My problem is I cant make it work to select multiple 3d polylines or entire layer, and also a lisp changes the result layer to the default layer. It should kept on the original one.
Here is my working lisp:
(defun c:3p2spl ( / *error* line2spl loop pl e s ss sss )
(vl-load-com)
(defun *error* ( msg )
(vla-endundomark (vla-get-activedocument (vlax-get-acad-object)))
)
(defun line2spl ( e / sp ep d )
(setq sp (cdr (assoc 10 (entget e)))
ep (cdr (assoc 11 (entget e)))
d (distance sp ep)
)
(entdel e)
(entmakex
(list
'(0 . "SPLINE") '(100 . "AcDbEntity") '(100 . "AcDbSpline") '(210 0.0 0.0 1.0) '(71 . 1) '(73 . 2)
'(42 . 1.0e-010) '(43 . 1.0e-010) '(40 . 0.0) '(40 . 0.0) (cons 40 d) (cons 40 d) (cons 10 sp) (cons 10 ep)
)
)
)
(vla-startundomark (vla-get-activedocument (vlax-get-acad-object)))
(setq loop T)
(setq sss (ssget "_I"))
(if (and sss (eq (cdr (assoc 0 (entget (setq pl (ssname sss 0))))) "POLYLINE") (< 7 (cdr (assoc 70 (entget pl))) 14)) (setq loop nil))
(while loop
(setq pl (car (entsel "\nPick 3DPOLYLINE to convert it to SPLINE")))
(if (and (eq (cdr (assoc 0 (entget pl))) "POLYLINE") (< 7 (cdr (assoc 70 (entget pl))) 14)) (setq loop nil))
)
(setq e (entlast))
(command "_.explode" pl "")
(setq ss (ssadd))
(while (setq e (entnext e))
(if (eq (cdr (assoc 0 (entget e))) "LINE")
(progn
(setq s (line2spl e))
(ssadd s ss)
)
)
)
(command "_.join" (ssname ss 0) ss "")
(*error* nil)
(princ)
)
if I change the ssget "_I" to ssget "_:E" I can select multiple lines however it will change to spline only the first one.
I didn't test this code, only read, so maybe I'm wrong, but I thing the problem is because:
...
(setq pl (ssname sss 0))
...
(command "_.explode" pl "")
You explode only first entity.
I think
(command "_.explode" pl "")
should be used inside loop by all sss items.
I'm new to LISP in autocad. The code shown below draws circles (with radius of 1) in a sloped line. What I don't understand is the value of "a" does not increase in increments of 1. The center of the circle drawn in autocad is (1,1) , (1.7071,1.7071) , (3,3) , (3.7071,3.7071) , (5,5) ... Can someone pls. explain why?
(defun c:wwq ()
(setq a 0)
(while (< a 10)
(setq a (+ 1 a))
(setq pt1 (list a a ) )
(command "circle" pt1 1 )
)
)
While using the AutoLISP command function, you have to care about active object snaps.
One way is to force object snaps to "none" within the (command ...) expression:
(defun c:wwq (/ a pt1)
(setq a 0)
(while (< a 10)
(setq a (+ 1 a))
(setq pt1 (list a a))
(command "_circle" "_none" pt1 1)
)
(princ)
)
Or, you can deactivate every osnap by setting the OSMODE system variable to 0 at the begining of the code and retore the previous value at the end (to be really safe, this method should need and error handler to insure the the previous value is reset in case an error occur during the code execution).
(defun c:wwq (/ a pt1 os)
(setq a 0
os (getvar 'osmode)
)
(setvar 'osmode 0)
(while (< a 10)
(setq a (+ 1 a))
(setq pt1 (list a a))
(command "_circle" pt1 1)
)
(setvar 'osmode os)
(princ)
)
Another way is to use the entmake function which is faster and do not care about osnaps.
(defun c:wwq (/ a)
(setq a 0.0)
(while (< a 10.0)
(setq a (+ 1.0 a))
(entmake
(list
(cons 0 "CIRCLE")
(list 10 a a 0.0)
(cons 40 1.0)
)
)
)
(princ)
)