­

Please feel free to be inspired, cut&paste or if you have any feedback, questions or looking for an AutoLISP programmer for small or large projects go here. If you want some customization or anything else that you can come up with that we might help you with you're welcome to contact us

If you look for an app that can load AutoLISP files from your library take a look at our app JTB Lisp.

AutoLISP / Visual LISP

AutoLISP is based on the LISP programming language.  Because AutoCAD has a built-in LISP interpreter, you can enter AutoLISP code at the command prompt or load AutoLISP code from external files. Visual LISP (VLISP) is a software tool designed to expedite AutoLISP program development. AutoLISP and Visual LISP is often used mutually but AutoLISP is only a subset of Visual LISP. Visual LISP was incorporated into AutoCAD 2000 released in March 1999, as a replacement for AutoLISP.

Visual LISP technology is a tool for code creation in the AutoCAD software application. It is a full-featured, interpretive programming language that you can use to call AutoCAD commands, system variables, and dialog boxes. Visual LISP offers a complete development environment, including

  • Reduced development time using the integrated development environment (IDE), which makes it easier and faster for users and developers alike to create, debug, and deliver AutoLISP-based applications
  • Access to Microsoft ActiveX objects and event reactors
  • Source code protection against theft and alteration
  • Operating system file-operation functions
  • LISP function extensions for list processing

In February 2018, BricsCAD V18.2 came with BLADE, the BricsCAD LISP Advanced Development Environment. See this blog post.

LISP is used by CAD applications like AutoCAD, BricsCAD, DraftSight, GstarCAD, CADopia, IntelliCAD, progeCAD and ZWCAD.

With AutoCAD 2021 improvements have been made to AutoLISP and DCL. These improvements include:

Miscellaneous tips and trix for AutoCAD AutoLISP

; AutoLISP function to convert degrees to radians
(defun dtr (a)
  (* pi (/ a 180.0))
)

; AutoLISP function to convert radians to degrees
(defun rtd (r)
  (* 180.0 (/ r pi))
)

; Example on how to remove the last element or item in a list
(setq lst '(1 2 3 4))
(setq lst (reverse (cdr (reverse lst))))
; result is (1 2 3)

; Example on how to right rotate a list 1 step
(setq lst '(1 2 3 4))
(setq lst (append (list (last lst)) (reverse (cdr (reverse lst)))))
; result is (4 1 2 3)

; Example on how to left rotate a list 1 step
(setq lst '(1 2 3 4))
(setq lst (append (cdr lst) (list (car lst))))
; result is (2 3 4 1)


Problem

Any idea why any AutoLISP command call is not working with attached bundle placed in any of the ApplicationPlugins folders. 

Bundle code:

<Components>
<ComponentEntry AppName="test" Version="1.0.0" ModuleName="./Contents/test.lsp"
PerDocument="True">
</ComponentEntry>
</Components>

All enough to trigger this is (command "erase" "").
(command-s is not working either.

 test.lsp as follow:

(princ "\nBefore")
(command "erase" "")
(princ "\nAfter")
(princ)

Result on the command line:

Regenerating model.
Before; error: AutoCAD command rejected: "erase"
Before; error: AutoCAD command rejected: "erase"
Before; error: AutoCAD command rejected: "erase"
Before; error: AutoCAD command rejected: "erase"
Before; error: AutoCAD command rejected: "erase"
AutoCAD menu utilities loaded.*Cancel*
Command:

Solution

Synchronous commands are not supported. Therefore AutoCAD will cancel any inward command until the AutoCAD application becomes stable and active.

Workaround is vl-cmdf as an alternative to command.

Another way that worked is using s::startup

(defun mystartup ()
(princ "\nloaded")
(command "menubar" "1")
(princ "\nended")
)
(if s::startup
(setq s::startup (append s::startup (quote ((mystartup)))))
(defun s::startup () (mystartup))
)
(princ)

SendStringToExecute used in a DLL will also work. 


Q. Compiling a VLX might give this error:  Start packing VLX-application...
; error: bad argument type: output-streamp: nil

A. The VLX might exist and be read-only. For example after digitally signing it. Delete it and compile again.


Visual LISP example how to delete all empty layouts (tabs). If the layout has been activated it will contain a viewport object and will not be deleted by this function.

In previous version (= nil (ssget "x" (list (cons 410 (vla-get-name layout))))) was used but did not catch layouts where the viewport object has been deleted. vla-get-count will return 0 for non activated layouts and 1 for a layout with no objects.

(defun c:DeleteEmptyLayouts (/ layouts layout i)
  (vl-load-com)
  (setq i 0 layouts (vla-get-Layouts (vla-get-activedocument (vlax-get-acad-object))))
  (if (> (vla-get-count layouts) 2)
    (vlax-for layout layouts
      (if (= (vla-get-ModelType layout) :vlax-false)
        (if (< (vla-get-count (vla-get-block layout)) 2)
          (progn
            (princ (strcat "\n" (vla-get-name layout) " deleted"))
            (setq i (1+ i))
            (vla-delete layout)
          )
        )
      )
    )
  )
  (cond
    ((> i 1) (princ (strcat "\n" (itoa i) " layouts deleted")))
    ((= i 0) (princ "\nNo layouts deleted"))
  )
  (princ)
)

Show if each layout and model space is empty or not. 

(defun c:emptyornot (/ empty) 
(vl-load-com)
(vlax-for layout (vla-get-Layouts (vla-get-activedocument (vlax-get-acad-object)))
(if (= (vla-get-ModelType layout) :vlax-false)
(setq empty (< (vla-get-count (vla-get-block layout)) 2))
(setq empty (not (ssget "_x" '((410 . "Model")))))
)
(princ (strcat "\n" (vla-get-name layout) (if empty " " " not ") "empty"))
)
(princ)
)

Purge layer filters / delete layer filters in AutoCAD. You get it here at my blog or here.

; To set the a custom scale, first set the StandardScale property to acVpCustomScale,
; then use the property CustomScale to define the custom scale value.
; Code examples to play with follow

(setq al (vla-get-ActiveLayout (vla-get-activedocument (vlax-get-acad-object)))
(vla-get-CustomScale al)
(vla-put-StandardScale al acVpCustomScale)
(vla-put-StandardScale al acVpScaleToFit)
(vla-put-StandardScale al ac1_10)
(setq numerator 1)
(setq denominator 25)
(vla-setCustomScale al numerator denominator)
(vla-getCustomScale al 'numerator 'denominator)
(princ numerator)
(princ denominator)

 

; The is how you can do a PGP file reinitialization (reload)awing template file used by QNEW
;;; (ax:GetQnewPath)
(defun ax:GetQnewPath (/ prof key)
  (setq prof (vla-get-ActiveProfile (vla-get-profiles (vla-get-preferences (vlax-get-Acad-Object)))))
  (setq key (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\Profiles\\" prof "\\General"))
  (vl-registry-read key "QnewTemplate")
)
;;; Set the drawing template file used by QNEW
;;; This writes it to the registry but is later dismissed and overwritten by AutoCAD
;;; (ax:SetQnewPath "M:\\CAD\\ACADISO.DWT")
(defun ax:SetQnewPath (QnewPath / prof key)
  (setq prof (vla-get-ActiveProfile (vla-get-profiles (vla-get-preferences (vlax-get-Acad-Object)))))
  (setq key (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\Profiles\\" prof "\\General"))
  (vl-registry-write key "QnewTemplate" QnewPath)
)
;; Gets current template
(getenv "QnewTemplate")
"c:\\my files\\templates\\qnew.dwt"
and
;; Sets a different template
(setenv "QnewTemplate" "")

or another approach because the above one is not working in newer versions of AutoCAD:

Using VBA where QnewPath is the Template File Name: ThisDrawing.Application.Preferences.Files.QNewTemplateFile = QnewPath

Using LISP: (vla-put-QNewTemplateFile (vla-Get-Files (vla-Get-Preferences (vlax-get-acad-object))) QnewPath)

This is how you can preset the Path type in the xref attach dialog box
;;; Sets the Xref Path type used in the xref attach dialog box
;;; Absolute Path: (SetPathType 0)
;;; Relative Path: (SetPathType 1)
;;; No Path: (SetPathType 2)
(defun SetPathType (v)
  (vl-load-com)
  (vl-registry-write
    (strcat
      "HKEY_CURRENT_USER\\"
      (vlax-product-key)
      "\\Profiles\\"
      (vla-get-activeprofile
	(vla-get-profiles
	  (vla-get-preferences (vlax-get-acad-object))
	)
      )
      "\\Dialogs\\XattachDialog"
    )
    "PathType"
    v
  )
)
;;; Gets the Xref Path type used in the xref attach dialog box
;;; 0 = Absolute Path
;;; 1 = Relative Path
;;; 2 = No Path
(defun GetPathType ()
  (vl-load-com)
  (vl-registry-read
    (strcat
      "HKEY_CURRENT_USER\\"
      (vlax-product-key)
      "\\Profiles\\"
      (vla-get-activeprofile
	(vla-get-profiles
	  (vla-get-preferences (vlax-get-acad-object))
	)
      )
      "\\Dialogs\\XattachDialog"
    )
    "PathType"
  )
)

This is how you can preset the folder in the PDF attach dialog box

;;; Open PDFATTACH to a specific folder
;;; Example: (PDFAttach "c:\\temp")
(defun PDFAttach (path)
  (vl-load-com)
  (vl-registry-write
    (strcat
      "HKEY_CURRENT_USER\\"
      (vlax-product-key)
      "\\Profiles\\"
      (vla-get-activeprofile
	(vla-get-profiles
	  (vla-get-preferences (vlax-get-acad-object))
	)
      )
      "\\Dialogs\\BrowseropenDialog"
    )
    "InitialDirectory"
    path
  )
  (initdia)
  (command "._PDFATTACH")
  (princ)
)
­