creating lisp routine to setup new drawing

creating lisp routine to setup new drawing

faisalWJ8Y9
Enthusiast Enthusiast
2,539 Views
18 Replies
Message 1 of 19

creating lisp routine to setup new drawing

faisalWJ8Y9
Enthusiast
Enthusiast

hi all,

 

seeking some help regarding a lisp routine. Basically, I have created a template file for creating our drawing sheets. In this template are several layout tabs that houses the titleblock attributes associated with the layout style eg a1 horizontal, a1 vertical etc. I want this routine when ran to open a dialog box that prompts to select the template file, when selected a list of the layouts appears below, when the layout is selected a new drawing is created with that layout and the other unneeded layouts are deleted. IE I click the a1 horizontal, it uses the template to create a new drawing with the horizontal layout and attributes and deletes the other tabs.

I have created a lisp routine below that works in conjunction with a dcl file, but the lisp fails after selecting the template, it does not bring up a list of the layouts.

 

See below: 

 

Lisp: 

 

(defun c:CreateNewSheet ()
(setq templatePath (getfiled "Select Template" "" "dwt" 1)) ; Prompt user to select template file
(if (null templatePath)
(exit)
)

(setq dialog (load_dialog "CreateNewSheet.dcl")) ; Load the dialog box
(if (not dialog)
(progn
(alert "Failed to load dialog box.")
(exit)
)
)

(if (not (new_dialog "CreateNewSheet" dialog)) ; Display the dialog box
(progn
(alert "Failed to display dialog box.")
(unload_dialog "CreateNewSheet" dialog) ; Unload the dialog box if failed to display
(exit)
)
)

(set_tile "template" templatePath) ; Set default template path in the dialog

(setq layoutTabsList (list "A1 Horizontal" "A1 Vertical")) ; Example list of layout tabs, replace with actual list

(foreach tab layoutTabsList
(start_list "layoutTabs")
(add_list tab)
)

(start_dialog) ; Start the dialog loop

(unload_dialog "CreateNewSheet" dialog) ; Unload the dialog box
)

(defun c:CreateSheetOK () ; Function to be called when OK button is pressed
(setq selectedTemplate (get_tile "template")) ; Get selected template path

; Get selected layout tab
(setq selectedLayout (get_tile "layoutTabs"))

; Perform necessary actions with selectedTemplate and selectedLayout
(princ (strcat "Selected Template: " selectedTemplate "\n"))
(princ (strcat "Selected Layout: " selectedLayout "\n"))

; Close dialog
(done_dialog 1)
)

(defun c:CreateSheetCancel () ; Function to be called when Cancel button is pressed
(done_dialog 0) ; Close the dialog box
)

 

 

DCL:

 

// CreateNewSheet.dcl

createNewSheet : dialog {
label = "Create New Sheet";
: row {
: static_text { label = "Select Template:"; }
: edit_box { key = "template"; width = 30; }
: browse_button { label = "Browse..."; }
}
: row {
: list_box { key = "layoutTabs"; width = 30; }
}
: row {
: button { key = "ok"; label = "OK"; is_default = true; action = "(c:CreateSheetOK)"; }
: button { key = "cancel"; label = "Cancel"; is_cancel = true; action = "(c:CreateSheetCancel)"; }
}
}

 

 

Note that essentially I want it to work similiar to the sheetset in when you create a new sheet it brings up the prompts like seen in screenshot. However we are updating attributes using an excel sheet, so I don't need it to prompt for the name of file and so on if that makes sense

 

any help is appreciated.

0 Likes
2,540 Views
18 Replies
Replies (18)
Message 2 of 19

rl_jackson
Mentor
Mentor

You might try having this posted to Civil 3D Customization Forum - Autodesk Community 

 

Maybe @lim.wendy could make other suggestions.


Rick Jackson
Survey CAD Technician VI

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature

Message 3 of 19

jroot
Advisor
Advisor

We do a similar thing but with the Action Recorder. We have a template DWG with layout tabs. Instead of picking the tab name from a menu, each one has its own Action Recorder Macro.  We type in "FULL" in the command line and a certain 24x36 tab gets created.

0 Likes
Message 4 of 19

lim.wendy
Alumni
Alumni

Hi Faisal, 

 

Thanks for sharing your question about creating a Lisp routine to set up a new drawing. I agree with Rick that you might receive more helpful replies on the Civil 3D customization forum. With that in mind, I've moved your post to that board. They tend to have a wealth of knowledge and experience in this area. Best of luck with your project, and I hope you find the solution you're looking for!



Wendy Lim

Data Nerd | Community Advocate | AEC Industry


facebook twitter twitter blogs pm


Join the new online Rail Community


Rails Summit




0 Likes
Message 5 of 19

Joe-Bouza
Mentor
Mentor

Use SSM

that's what it does 

Joe Bouza
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature

0 Likes
Message 6 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

The whole point of this process is that we don't want to use SSM.

0 Likes
Message 7 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

thanks lim

0 Likes
Message 8 of 19

hippe013
Advisor
Advisor

It appears to me that you are missing the end_list statement and that your start_list is being fired for each item in the list. It has been a while since I worked with dcl, but it should be something like this. 

 

(start_list "layoutTabs")
(foreach tab layoutTabsList
   (add_list tab)
)
(end_list)

 

AutoCAD 2023 Developer and ObjectARX Help | About List Operations for List Boxes and Pop-Up Lists (D...

 

I hope that this helps. 

 

 

 

0 Likes
Message 9 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

hello,

 

thank you for your response I appreciate it. Unfortunately adding this line of code didn't work either. The dialog box will appear, and you can select your template though for some reason it asks you to save over it, rather than select to use it.. (werid). Anyway, upon doing so it will say "failed to display dialog box". It also gives me the error that there are too many arguments? Sorry I'm not paticuarly versed in lisp writing lol.

 

Hopefully the link you provided will give some more insight.

0 Likes
Message 10 of 19

hippe013
Advisor
Advisor

Your dcl has a couple errors for the defined tiles.

 

It is text not static_text

 

and 

 

It is button not browse_button

0 Likes
Message 11 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

hmm I have fixed these issues, thank you for spotting them. The problem however still persists 

0 Likes
Message 12 of 19

hippe013
Advisor
Advisor

Welcome to the joys of programming!

 

At least at this point you should be able to get a DCL ID from the load_dialog function. 

So, the errors within the DCL have been addressed and is now able to be loaded.

 

The next error appears at this line. 

(if (not (new_dialog "CreateNewSheet" dialog)) ; Display the dialog box

The dialog name is case sensitive, so it should be this: 

(if (not (new_dialog "createNewSheet" dialog)) ; Display the dialog box

 

 

The getFiled function should have a zero for the flag

(setq templatePath (getfiled "Select Template" "" "dwt" 0))

AutoCAD 2022 Developer and ObjectARX Help | getfiled (AutoLISP) | Autodesk

 

 

Here is a cleaned-up version. 

 

(defun c:CreateNewSheet ( / templatePath dcl)
  ;Select Template Path
  ; Prompt user to select template file
  (setq templatePath (getfiled "Select Template" "" "dwt" 0)) 
  (if (not templatePath)
    (progn
      (princ "\nUser must select a path. ")
      (exit)
      )
    )

  ;Search for DCL File
  (setq dcl (findFile "CreateNewSheet.dcl"))
  (if (not dcl)
    (progn
      (princ "\nCould not find CreateNewSheet.dcl")
      (exit)
      )
    )

  ;Load the DCL File
  (setq dclId (load_dialog dcl))
  (if (not dclId)
    (progn
      (alert "Failed to load dialog box.")
      (exit)
      )
    )

  ;Attempt to Display Dialog
  (if (not (new_dialog  "createNewSheet" dclId))
    (progn
      (alert "Failed to display dialog box.")
      (unload_dialog dclId)
      (exit)
      )
    )
  ; Set default template path in the dialog
  (set_tile "template" templatePath)

  ; Example list of layout tabs, replace with actual list
  (setq layoutTabsList (list "A1 Horizontal" "A1 Vertical")) 
  (start_list "layoutTabs")
  (foreach tab layoutTabsList
    (add_list tab)
    )
  (end_list )

  (start_dialog)
  (unload_dialog  dclId) 
)


 ; Function to be called when OK button is pressed
(defun c:CreateSheetOK ()
  ; Get selected template path
  (setq selectedTemplate (get_tile "template"))

  ; Get selected layout tab
  (setq selectedLayout (get_tile "layoutTabs"))

  ; Perform necessary actions with selectedTemplate and selectedLayout
  (princ (strcat "Selected Template: " selectedTemplate "\n"))
  (princ (strcat "Selected Layout: " selectedLayout "\n"))

  ; Close dialog
  (done_dialog 1)
  )


; Function to be called when Cancel button is pressed
(defun c:CreateSheetCancel ()
  ; Close the dialog box
  (done_dialog 0)
  )

 

The functions createSheetOk and createSheetCancel should not have a "c:" prefix as you don't want them run from the command line. If you remove the "c:" prefix you will need to make that change in your dcl file as well.

 

I hope that this helps in getting you going in the right direction. 

 

0 Likes
Message 13 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

Hello,

 

I really appreciate the time you have taken to help me clean this lisp routine up thank you very much.

It seems I still have a fair bit to learn in regard to working with DCL. I updated the prefix issue in both locations as per what you mentioned. 

 

it now prompts me for the layout! YAY! However, upon selecting the layout it feeds me this error: Command: CREATENEWSHEET
Selected Template: U:\My Lisps and Scripts\testing\SAP_TBK.dwt
Selected Layout: 0
nil

 

I thought maybe it was because the layout names were different, so I updated them to match exactly what is in the template, but it's not creating the sheet with the template using the paper layout specified. I tried prompting for it to do the _new command after selecting the template to use and then it uses that template, but that seems to fail as well.

 

Do you have any ideas? I've attached the template file for your information on what it's pulling

0 Likes
Message 14 of 19

hippe013
Advisor
Advisor

I hope that you weren’t thinking that your code was complete. You have a ways to go to get to what you describe what your code is supposed to do. It currently just prompts a user for a file path. Displays a DCL with that file path and has the user prompt from a list of hard-coded strings (layout tabs). The exiting function then prints to the command line the selected path and the chosen “Layout Tab” from the DCL. What you are seeing is not an error, but is what your code currently does. You need to do some research on your end to figure out how to open the DWT, get its list of layout tabs, display that in the DCL and then copy the selected layout contents to your current drawing. That’s what you want it to do, correct? 

 

0 Likes
Message 15 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

oh sorry I forgot to provide the updated lisp lol. But yes you are correct. Essentially I want it to use the template to create a drawing with the layout chosen and remove the other layout.

 

so I'm working in conjunction with what I have found, but its telling me that this function (setq acad (vlax-get-interface-object (vlax-get-acad-object))) isn't a valid function. I googled it and it seems to be correct. I also added the vl-load-com so that the visual com library is loaded first, but it still seems to not be working, It's unfortunate I'm not having much luck finding a forum where someone is trying or has tried to do something similar.

 

this is the revised code:

(defun c:CreateNewSheet ( / templatePath dcl)
; Select Template Path
(setq templatePath (getfiled "Select Template" "" "dwt" 0))
(if (not templatePath)
(progn
(princ "\nUser must select a path. ")
(exit)
)
)

; Search for DCL File
(setq dcl (findFile "CreateNewSheet.dcl"))
(if (not dcl)
(progn
(princ "\nCould not find CreateNewSheet.dcl")
(exit)
)
)

; Load the DCL File
(setq dclId (load_dialog dcl))
(if (not dclId)
(progn
(alert "Failed to load dialog box.")
(exit)
)
)

; Attempt to Display Dialog
(if (not (new_dialog "createNewSheet" dclId))
(progn
(alert "Failed to display dialog box.")
(unload_dialog dclId)
(exit)
)
)

; Set default template path in the dialog
(set_tile "template" templatePath)

; Example list of layout tabs, replace with actual list
(setq layoutTabsList (list "SAP_A1_H" "SAP_A1_VER"))
(start_list "layoutTabs")
(foreach tab layoutTabsList
(add_list tab)
)
(end_list )

(start_dialog)
(unload_dialog dclId)
)


; Function to be called when OK button is pressed
(defun CreateSheetOK ()
; Get selected template path
(setq selectedTemplate (get_tile "template"))

; Get selected layout tab
(setq selectedLayout (get_tile "layoutTabs"))

; Create new drawing with selected layout
(create_drawing selectedTemplate selectedLayout)

; Close dialog
(done_dialog 1)
)


; Function to be called when Cancel button is pressed
(defun CreateSheetCancel ()
; Close the dialog box
(done_dialog 0)
)

(defun create_drawing (templatePath layoutName)
(vl-load-com) ; Load Visual Lisp COM Automation library
(setq acad (vlax-get-interface-object (vlax-get-acad-object)))
(setq activedoc (vla-open acad templatePath))
(vla-get-layout doc layoutName)
(vla-delete layout)
)

0 Likes
Message 16 of 19

hippe013
Advisor
Advisor

(defun create_drawing (templatePath layoutName)
(vl-load-com) ; Load Visual Lisp COM Automation library
(setq acad (vlax-get-interface-object (vlax-get-acad-object)))
(setq activedoc (vla-open acad templatePath))
(vla-get-layout doc layoutName)
(vla-delete layout)
)


Where are you getting your example code from? Are you understanding what each line of your code does? 

 


It's unfortunate I'm not having much luck finding a forum where someone is trying or has tried to do something similar.

You are not looking very hard. There are a multitude of examples of lisp doing different operations far more complex than the project that you are working on. I am doing my best to help guide you to find your answers, but I need to know that you understand your code as it stands. It seems to me that you are grasping at straws at getting something working without taking the time to understand what it does or how to figure out what it does.

 

The function is not vlax-get-interface-object, it is vla-getInterfaceObject, but what interface object are you trying to get? 

 

AutoCAD 2023 Developer and ObjectARX Help | GetInterfaceObject Method (ActiveX) | Autodesk

 

Look into what this function does and how to use it.

(vlax-get-acad-object)

 

AutoCAD 2022 Developer and ObjectARX Help | vlax-get-acad-object (AutoLISP/ActiveX) | Autodesk

 

 

 

 

0 Likes
Message 17 of 19

Jeff_M
Consultant
Consultant

@faisalWJ8Y9 I believe @lim.wendy moved this post to the wrong forum as it is not Civil 3D specific. So I am moving it over to the Visual LISP, AutoLISP and General Customization forum where there are far more lispers who might jump in.

@hippe013 

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 18 of 19

faisalWJ8Y9
Enthusiast
Enthusiast

I have been wrking with a combination of chatgpt and another forum that I had found at CAD Tutor (can't recall the exact name) as mentioned earlier my knowledge in lisping is limited. But basically, from my understanding (defun createsheetok) is the function im assigning and is what's called after clicking OK in the DCL.  (setq selectedtemplate (get_title "template") should inherently retrieve the value selected by the user for the template and store it as a variable, then the next line (setq selectedlayout (get_title "layouttabs)) should retrieve the value selected for the layout tab and store that as variable.

 

after the dcl prompts I have the create_drawing function within that I have 2 arguments templatepath (ie the template file path) and layout name (the layout tab names) within the function (setq acad vla-get-interface-object) not vlax that's a typo thanks for pointing out, from my understanding should retrieve the active x automation object for CAD and then stores it in the variable acad.  The next line (setq doc (vla-open acad templatePath)) I've specified opens the chosen template file and returns a document object, stored in the variable 'doc'.  The (vla-get-layout doc layoutName) I imagine would retrieve the layout specified by the layout name from the document object and then the last line (vla-delete layout) should delete the layouts that are unused.

 

So essentially after the DCL prompts are run through by the user the lisp should retrieve the selected template path and layout name, call the create_drawing function to create the new drawing with selected layout from the specified template and then delete the other layouts unused.

 

To answer your question with my understanding the (vla-get-acad-object) is being used to create a new instance of CAD because according to the forum, I read it mitigates the issue between attempting to interact with an existing instance of CAD where there may be compatibility issues with the lisp code and version of cad being used. so by creating a new instance of CAD the lisp code should have a fresh isolated instance to work in

0 Likes
Message 19 of 19

Sea-Haven
Mentor
Mentor

The dcl

SeaHaven_0-1710717646328.png

 

Then next step is to take advantage of where you want the layouts to be linked to in model space nad make the required layouts.

 

Happy to discuss but it has a small cost as must be customised to suit your title blocks. Walk along pline/s or grids are available.

SeaHaven_1-1710717801990.png

 

 

 

0 Likes