Help fixing my LISP - Inserting .dwg from directory as a block

Help fixing my LISP - Inserting .dwg from directory as a block

SirRS
Explorer Explorer
723 Views
7 Replies
Message 1 of 8

Help fixing my LISP - Inserting .dwg from directory as a block

SirRS
Explorer
Explorer

Hello,

 

I am trying to fix this LISP routine which pulls a list of .dwg files from a directory and displays them in a dropdown menu organized by subfolder. Currently, using the insert detail button returns a stringp nil error.

(defun c:DetailsBrowser (/ dcl_id dialog_return folderPath folderList fileDict doc selectedFolder selectedFile fullFilePath)

;; Initialize variables
(setq folderPath "I:\\CADLIB\\Standard Details")
(setq fileDict '())

;; Function to populate the folder list and file dictionary
(defun populate-folder-and-file-list ()
(setq folderList (vl-directory-files folderPath nil -1))
(foreach folder folderList
(if (and (not (wcmatch folder "."))
(not (wcmatch folder ".."))
(eq (vl-file-directory-p (strcat folderPath "\\" folder)) T))
(progn
(setq fileList (vl-sort (vl-directory-files (strcat folderPath "\\" folder) "*.dwg" 1) '<))
(setq fileDict (cons (cons folder fileList) fileDict))
)
)
)
)

;; Function to populate the folder dropdown list
(defun populate-folder-dropdown ()
(start_list "folder_dropdown")
(foreach entry fileDict
(add_list (car entry))
)
(end_list)
)

;; Function to populate the file list for a folder
(defun populate-file-list (folder)
(setq fileList (cdr (assoc folder fileDict)))
(start_list "file_list")
(foreach file fileList
(add_list file)
)
(end_list)
)

;; Load the DCL file
(setq dcl_file "details_browser.dcl")
(setq dcl_path (findfile dcl_file))
(if (not dcl_path)
(progn
(princ (strcat "\nDCL file not found: " dcl_file))
(exit)
)
)
(setq dcl_id (load_dialog dcl_path))
(if (not (new_dialog "details_browser" dcl_id))
(progn
(princ "\nFailed to load dialog.")
(exit)
)
)

;; Get the document object
(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))

;; Populate the initial folder and file lists
(populate-folder-and-file-list)
(populate-folder-dropdown)

;; Set up the action for the folder dropdown selection
(action_tile "folder_dropdown"
"(progn
(setq selectedFolder (nth (atoi (get_tile \"folder_dropdown\")) (mapcar 'car fileDict)))
(populate-file-list selectedFolder)
(princ (strcat \"\\nSelected folder: \" selectedFolder))
)")

;; Set up the action for the "Insert Detail" button
(action_tile "insert_detail" "(done_dialog 1)")

;; Set up the action for the "Cancel" button
(action_tile "cancel" "(done_dialog 0)")

;; Display the dialog and get the user's input
(setq dialog_return (start_dialog))

;; Handle the user's input
(cond
((= dialog_return 1)
;; Insert the selected detail
(setq selectedFile (nth (atoi (get_tile "file_list")) fileList))
(princ (strcat "\nSelected file: " (get_tile "file_list") "\n"))
(princ (strcat "\nSelected file (variable): " selectedFile "\n"))
(if selectedFile
(progn
(setq fullFilePath (strcat folderPath "\\" selectedFolder "\\" selectedFile))
(princ (strcat "\nFull file path: " fullFilePath "\n"))
(if (findfile fullFilePath)
(insert-block fullFilePath)
(princ (strcat "\nFile not found: " fullFilePath "\n")))
(princ (strcat "\nInserted detail: " fullFilePath "\n"))
)
)
)
(t (princ "\nDialog canceled."))
)

;; Cleanup
(unload_dialog dcl_id)
(princ)
)

(defun insert-block (fullFilePath)
(vl-load-com)
(setq acadObj (vlax-get-acad-object))
(setq doc (vla-get-ActiveDocument acadObj))
(setq db (vla-get-Database doc))
(setq blockName (vl-filename-base fullFilePath))

;; Create a temporary database
(setq tempDb (vlax-create-object "AutoCAD.AcadDatabase"))
(vla-ReadDwgFile tempDb fullFilePath)

;; Insert the block into the current database
(vla-Insert db blockName tempDb :vlax-false)

;; Clean up
(vlax-release-object tempDb)
(princ "\nBlock inserted successfully.\n")
)

(princ "\nDetailsBrowser loaded. Type DetailsBrowser to start.")
(princ)


Let me know if you have any suggestions!

0 Likes
724 Views
7 Replies
Replies (7)
Message 2 of 8

Moshe-A
Mentor
Mentor

@SirRS  hi,

 

Without the dcl file i can not run the your lisp but what i found is when you click on "insert_detail" button you close the dialog [(done_dialog 1) which is bad to do cause this is should be reserved for OK button, which you do not have?] than you trying to call (get_tile "file_list") but the dialog is closed - you cannot 😀

 

Moshe

 

 

;; Handle the user's input
(cond
((= dialog_return 1)
;; Insert the selected detail
(setq selectedFile (nth (atoi (get_tile "file_list")) fileList))
(princ (strcat "\nSelected file: " (get_tile "file_list") "\n"))
(princ (strcat "\nSelected file (variable): " selectedFile "\n"))

 

0 Likes
Message 3 of 8

pbejse
Mentor
Mentor

@SirRS wrote:
...
(vla-ReadDwgFile tempDb fullFilePath)
...

I'm more interested on this one, only time I get to use ReadDwg is with .NET.  How were you able to pull this off?

 

0 Likes
Message 4 of 8

SirRS
Explorer
Explorer

I am using ChatGPT to assist with this code (I am unsure how to code myself). I am posting here to see if I can get some assistance modifying the code or suggestions on how to revise for what I'm looking for.

I've gone through some iterations and landed on this, but get an unhandled exception error:

 

LISP:

(defun c:DetailsBrowser (/ dcl_id dialog_return folderPath folderList fileDict doc selectedFolder selectedFile fullFilePath selectedFiles)

  ;; Initialize variables
  (setq folderPath "I:\\CADLIB\\Standard Details")
  (setq fileDict '())
  (setq selectedFiles '())

  ;; Function to populate the folder list and file dictionary
  (defun populate-folder-and-file-list ()
    (setq folderList (vl-directory-files folderPath nil -1))
    (foreach folder folderList
      (if (and (not (wcmatch folder "."))
               (not (wcmatch folder ".."))
               (eq (vl-file-directory-p (strcat folderPath "\\" folder)) T))
        (progn
          (setq fileList (vl-sort (vl-directory-files (strcat folderPath "\\" folder) "*.dwg" 1) '<))
          (setq fileDict (cons (cons folder fileList) fileDict))
        )
      )
    )
  )

  ;; Function to populate the folder dropdown list
  (defun populate-folder-dropdown ()
    (start_list "folder_dropdown")
    (foreach entry fileDict
      (add_list (car entry))
    )
    (end_list)
  )

  ;; Function to populate the file list for a folder
  (defun populate-file-list (folder)
    (setq fileList (cdr (assoc folder fileDict)))
    (start_list "file_list")
    (foreach file fileList
      (add_list file)
    )
    (end_list)
  )

  ;; Load the DCL file
  (setq dcl_file "details_browser.dcl")
  (setq dcl_path (findfile dcl_file))
  (if (not dcl_path)
    (progn
      (princ (strcat "\nDCL file not found: " dcl_file))
      (exit)
    )
  )
  (setq dcl_id (load_dialog dcl_path))
  (if (not (new_dialog "details_browser" dcl_id))
    (progn
      (princ "\nFailed to load dialog.")
      (exit)
    )
  )

  ;; Get the document object
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))

  ;; Populate the initial folder and file lists
  (populate-folder-and-file-list)
  (populate-folder-dropdown)

  ;; Set up the action for the folder dropdown selection
  (action_tile "folder_dropdown" 
               "(progn
                  (setq selectedFolder (nth (atoi (get_tile \"folder_dropdown\")) (mapcar 'car fileDict)))
                  (populate-file-list selectedFolder)
                  (princ (strcat \"\\nSelected folder: \" selectedFolder))
                )")

  ;; Set up the action for the "Add to Cart" button
  (action_tile "add_to_cart"
               "(progn
                  (setq selectedFile (nth (atoi (get_tile \"file_list\")) (cdr (assoc selectedFolder fileDict))))
                  (setq selectedFiles (cons (strcat folderPath \"\\\\\" selectedFolder \"\\\\\" selectedFile) selectedFiles))
                  (princ (strcat \"\\nAdded to cart: \" selectedFile))
                )")

  ;; Function to insert block using command method
  (defun insert-block (filepath)
    (setq insertionPoint (getpoint "\nSpecify insertion point: "))
    (if (findfile filepath)
      (progn
        (command "_-insert" (strcat filepath "=") insertionPoint "1" "1" "0")
      )
      (princ (strcat "\nFile not found: " filepath))
    )
  )

  ;; Set up the action for the "Insert Cart" button
  (action_tile "insert_cart"
               "(progn
                  (if selectedFiles
                    (foreach file selectedFiles
                      (princ (strcat \"\\nInserting file: \" file))
                      (insert-block file)
                    )
                  )
                  (setq selectedFiles '())
                  (done_dialog 1)
                )")

  ;; Set up the action for the "Cancel" button
  (action_tile "cancel" "(done_dialog 0)")

  ;; Display the dialog and get the user's input
  (setq dialog_return (start_dialog))

  ;; Cleanup
  (unload_dialog dcl_id)
  (princ)
)

(princ "\nDetailsBrowser loaded. Type DetailsBrowser to start.")
(princ)

 

dcl:

details_browser : dialog {
    label = "Details Browser";
    : row {
        : list_box {
            key = "folder_dropdown";
            label = "Folders";
            width = 20;
            height = 15;
        }
        : list_box {
            key = "file_list";
            label = "DWG Files";
            width = 30;
            height = 15;
        }
    }
    : row {
        : button {
            key = "add_to_cart";
            label = "Add to Cart";
            fixed_width = true;
        }
        : button {
            key = "insert_cart";
            label = "Insert Cart";
            fixed_width = true;
        }
        : button {
            key = "cancel";
            label = "Cancel";
            is_cancel = true;
            fixed_width = true;
        }
    }
}
0 Likes
Message 5 of 8

SirRS
Explorer
Explorer

Please see the recent comment with revised code & the dcl code as well! Thanks 🙂

0 Likes
Message 6 of 8

Moshe-A
Mentor
Mentor

@SirRS ,

 

Your lisp is noting more then having a list of library folders and blocks (dwg).

 

AutoCAD has number of build-in methods to do exactly this:

explore the new Blocks Palette, Tool Palettes and AutoCAD Design Center

each of them and all of them together will satisfy you 😀

 

Moshe

 

0 Likes
Message 7 of 8

Kent1Cooper
Consultant
Consultant

A small thing, not really important for your request, but an illustration of the fact that ChatGPT doesn't know AutoLisp all that well yet:

 

These lines do nothing at all for you, and could be simply removed:

  (setq fileDict '())
  (setq selectedFiles '())

They look like they're creating lists with nothing in them yet.  But a list with nothing in it is not a list -- it's just nothing.  Note that what is returned by doing that is not a list, but nil, and checking for the value of the intended variable returns likewise nothingness:

Command: (setq test '())
nil

Command: !test
nil

Those variables will be nil anyway at the beginning, since they are listed as localized variables.

The code later goes to add things to those lists.  But it is not necessary for a list to exist yet to add something to it -- it will come into existence in the process of adding the first thing, returning a list with that in it:

(setq test (cons 123 test))

(123)

Farther down, at line 102, it wipes out one of those lists [I wonder whether there's really any need to]:

(setq selectedFiles '())

But if that's really needed, it would get the same result with nil itself used explicitly:

(setq selectedFiles nil)

 

Kent Cooper, AIA
0 Likes
Message 8 of 8

Sea-Haven
Mentor
Mentor

Are you select dwg's that are say a single item dwg, a detail of some sort ? As suggested use tool palettes or for me old fashioned pop menu's. Behind the image is the dwg name and an insert command.

 

SeaHaven_0-1721181857314.png

 

 

0 Likes