TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: like_citrus on October 08, 2020, 02:28:56 AM

Title: Relative paths
Post by: like_citrus on October 08, 2020, 02:28:56 AM
I found this code which batch converts DGN to DWG. It works (apart from not converting the first drawing, but that's another issue).
I'm trying to use relative folder paths for reasons of moving computer.
The critical parameters are "tx1", "tx2" and "tx3".
The LISP file which is set to autoload is on the same path as "tx1" which contains a list of the drawings to be converted.

Code: [Select]
(defun C:MicroStationToAutoCAD (/ fil tx1 tx2 tx3 tx4 tx5)
(setq tx1 "C:\\Drawing Conversion\\List.txt" ; File holding a list of MicroStation drawings to be imported
  tx2 "C:\\Drawing Conversion\\In\\" ; Input folder
  tx3 "C:\\Drawing Conversion\\Out\\" ; Output folder
  tx4 "Default" ; Drawing model name
)
(setvar "DGNIMPORTMODE" 1)
(setq fil (open tx1 "r")
  tx5 (read-line fil))
(while tx5
(if (wcmatch tx5 "*`.???")
(setq tx5 (substr tx5 1 (- (strlen tx5) 4)))
)
(command "_UNDO" "_MARK"
     "_-DGNIMPORT" (strcat tx2 tx5) tx4 "" ""
     "_ZOOM" "_E"
     "._DELAY" 1000
     "_SAVEAS" "2007(LT2007)" (strcat tx3 tx5)
     "_UNDO" "_BACK"
)
(setq tx5 (read-line fil))
)
(close fil)
(command "_QUIT" "_Y")
(princ)
)

Attempt at relative path:
Code: [Select]
(setq tx1 (load (findfile ".\\List.txt") nil)
  tx2 ((load (findfile ".\\In\\") nil)
  tx3 (load (findfile ".\\Out\\") nil)

Title: Re: Relative paths
Post by: kpblc on October 08, 2020, 06:00:11 AM
I didn't check the code:
Code - Auto/Visual Lisp: [Select]
  1. (defun t1 (/ acad_obj adoc content folder handle input_subfolder item lst output_subfolder str sysvars file)
  2.   (setq folder "C:\\Drawing Conversion"
  3.         content "list.txt"
  4.         input_subfolder "In\\"
  5.         output_subfolder "Out\\"
  6.   ) ;_ end of setq
  7.   (if (and (findfile (setq folder (strcat (vl-string-right-trim folder "\\") "\\")))
  8.            (setq content (findfile (strcat folder content)))
  9.            (findfile (setq input_subfolder (strcat folder (vl-string-left-trim input_subfolder "\\.") "\\")))
  10.            (findfile (setq output_subfolder (strcat folder (vl-string-left-trim output_subfolder "\\.") "\\")))
  11.       ) ;_ end of and
  12.     (progn (setq handle (open content "r"))
  13.            (while (setq str (read-line handle)) (setq lst (cons lst str)))
  14.            (close handle)
  15.            (vla-startundomark
  16.              (vla-startundomark (setq adoc (vla-get-activedocument (setq acad_obj (vlax-get-acad-object)))))
  17.            ) ;_ end of vla-startundomark
  18.            (setq sysvars (mapcar (function (lambda (var / temp)
  19.                                              (if (setq temp (getvar (car var)))
  20.                                                (progn (if (cdr var)
  21.                                                         (setvar (car var) (cdr var))
  22.                                                       ) ;_ end of if
  23.                                                       (cons (car var) temp)
  24.                                                ) ;_ end of progn
  25.                                              ) ;_ end of if
  26.                                            ) ;_ end of lambda
  27.                                  ) ;_ end of function
  28.                                  '(("sysmon" . 0) ("cmdecho" . 0) ("menuecho" . 0) ("nomutt" . 1))
  29.                          ) ;_ end of mapcar
  30.            ) ;_ end of setq
  31.            (foreach item (reverse lst)
  32.              (if (wcmatch item "*`.???")
  33.                (setq item (substr item 1 (- (strlen item) 4)))
  34.              ) ;_ end of if
  35.              (if (findfile (setq file (strcat input_subfolder item)))
  36.                (progn (vl-cmdf "_.-dgnimport" file "Default")
  37.                       (vla-zoomall acad_obj)
  38.                       (vla-saveas adoc (strcat output_subfolder (vl-filename-base item) ".dwg") ac2007_dwg)
  39.                       ;; I think you have to erase all modelspace entities:
  40.                       ;; (vlax-for ent (vla-get-modelspace adoc) (vla-erase ent))
  41.                ) ;_ end of progn
  42.              ) ;_ end of if
  43.            ) ;_ end of foreach
  44.            (foreach item (vl-remove nil sysvars) (setvar (car item) (cdr item)))
  45.            (vla-endundomark adoc)
  46.     ) ;_ end of progn
  47.   ) ;_ end of if
  48.   (princ)
  49. ) ;_ end of defun
  50.  
Title: Re: Relative paths
Post by: like_citrus on October 08, 2020, 06:16:18 AM
Thanks for responding kpblc.
I didn't frame my question properly.
So there would be no changes to the LISP file when moving computers. At the moment, in your code, you would have to input the path "C:\\Drawing Conversion".
This is because paths are relative to the LISP file and are in the same directory. The automatic load of the LISP file takes care of the path. Is this possible?
Not that I don't want to do it but will forget at the time and may or may not be able to decipher what has to be done.
I'll try your code at some stage, thanks for that.
Title: Re: Relative paths
Post by: ribarm on October 08, 2020, 08:49:50 AM
Man, I can't figure this syntax :

Code - Auto/Visual Lisp: [Select]
  1.            (vla-startundomark
  2.              (vla-startundomark (setq adoc (vla-get-activedocument (setq acad_obj (vlax-get-acad-object)))))
  3.            ) ;_ end of vla-startundomark
  4.  

Why 2 (vla-startundomark)?
Title: Re: Relative paths
Post by: kpblc on October 08, 2020, 04:00:22 PM
Ah, my mistake, sorry.
P.S. I wrote - I didn't check to code $;)
Thanks for responding kpblc.
I didn't frame my question properly.
So there would be no changes to the LISP file when moving computers. At the moment, in your code, you would have to input the path "C:\\Drawing Conversion".
This is because paths are relative to the LISP file and are in the same directory. The automatic load of the LISP file takes care of the path. Is this possible?
Not that I don't want to do it but will forget at the time and may or may not be able to decipher what has to be done.
I'll try your code at some stage, thanks for that.
Hmmm... As fas as I know LISP can't define his loading path. You can automatically load lisp through at least 3 ways. How do you loading lisp? By Startup suite? By MNL? By acaddoc.lsp?
Title: Re: Relative paths
Post by: BIGAL on October 08, 2020, 07:12:21 PM
4 is drag drop
Title: Re: Relative paths
Post by: kpblc on October 09, 2020, 01:00:13 AM
D&D is autoload? :)
Title: Re: Relative paths
Post by: like_citrus on October 14, 2020, 09:25:02 PM
Sorry for the late reply as I didn't get a notification for the messages.
To answer your question, my LISP is loaded through the Startup Suite.
Should I abandon this then? If there is no way to have relative paths?
Title: Re: Relative paths
Post by: PKENEWELL on October 15, 2020, 12:38:42 PM
Like_Citrus:

when you call (findfile), it can only check the paths that are included in the "Support Paths" in options and in the currently opened drawing folder. In order to use the path you want - add it to the support paths in options, then when you call (findfile), just search for the file i.e. (findfile "list.txt").

From that - you can use (vl-filename-directory) to remove the file name from the full path returned from (findfile), then use (strcat) to combine it with the relative sub-directories.

Try this (untested):
Code - Auto/Visual Lisp: [Select]
  1. (defun C:MicroStationToAutoCAD (/ fil fn pth tx1 tx2 tx3 tx4 tx5)
  2.    (setq fn "list.txt"
  3.         ;; the path that the file is in must be in the support paths!
  4.          tx1 (findfile fn)
  5.          tx4 "Default"
  6.    )
  7.    (if (not tx1)
  8.       (princ "\nList file not found! Check the support paths. ")
  9.       (setq pth (vl-filename-directory tx1)
  10.             tx2 (strcat pth "\\in\\")
  11.             tx3 (strcat pth "\\out\\")
  12.       )
  13.    )
  14.    (setvar "DGNIMPORTMODE" 1)
  15.    (setq fil (open tx1 "r")
  16.            tx5 (read-line fil))
  17.    (while tx5
  18.       (if (wcmatch tx5 "*`.???")
  19.          (setq tx5 (substr tx5 1 (- (strlen tx5) 4)))
  20.       )
  21.       (command "._UNDO" "_MARK"
  22.                       "._-DGNIMPORT" (strcat tx2 tx5) tx4 "" ""
  23.       )
  24.       (while (= (logand (getvar "cmdactive") 1) 1) (command ""))
  25.       (command "._ZOOM" "_E"
  26.                       "._DELAY" 1000
  27.                      "._SAVEAS" "2013(LT2013)" (strcat tx3 tx5)
  28.                      "._UNDO" "_BACK"
  29.       )
  30.       (setq tx5 (read-line fil))
  31.    )
  32.    (close fil)
  33.    (command "_QUIT" "_Y")
  34.    (princ)
  35. )

Note: Sorry - had to make some edits as I was using the wrong function - corrected.
Title: Re: Relative paths
Post by: like_citrus on October 15, 2020, 08:35:25 PM
Thanks for providing the code.
I tried to run it after adding the path. The program was stuck though, whatever it was processing required a lot of memory. There was no error message in the command line.
The way I added the support path was: Tools, Options, Support File Search Path, Add. Added "C:\Drawing Conversion". Tried moving to the top, restarting, etc, no luck.
The only thing I could think of was adding "\\" after the "list.txt" using "strcat" ... but got an error message.

Code: [Select]
(setq pth (vl-filename-directory strcat tx1 "\\")
Title: Re: Relative paths
Post by: PKENEWELL on October 16, 2020, 10:55:23 AM
Thanks for providing the code.
I tried to run it after adding the path. The program was stuck though, whatever it was processing required a lot of memory. There was no error message in the command line.
The way I added the support path was: Tools, Options, Support File Search Path, Add. Added "C:\Drawing Conversion". Tried moving to the top, restarting, etc, no luck.
The only thing I could think of was adding "\\" after the "list.txt" using "strcat" ... but got an error message.

Code: [Select]
(setq pth (vl-filename-directory strcat tx1 "\\")

Like_citrus: Yes - the code you tried to add would not work - both the syntax is incorrect and you were trying to add a folder slash to the end of a full path and filename.


Otherwise I cannot explain what it happening. Perhaps also add the "C:\Drawing Conversion\" folder to the "Trusted Locations"?
Also - did you re-start AutoCAD after adding the support path? EDIT - OK i see you did restart AutoCAD.
Sorry - I cannot test this program because I have no DGN files to import.
Title: Re: Relative paths
Post by: like_citrus on October 16, 2020, 09:24:22 PM
That's OK, your understanding was quite good and well explained.
I did also try the C drive as a trusted path as well as other things, but no luck.
Title: Re: Relative paths
Post by: PKENEWELL on October 19, 2020, 12:40:05 PM
Like_Citrus:

Could you send a few sample DGN files for me to test? Then I might be able to figure out what is going on.
Title: Re: Relative paths
Post by: like_citrus on October 19, 2020, 09:42:03 PM
PKENEWELL, I tried to send a sample via PM but there was no option to attach.
Given I don't have ownership of the drawings, I can't post them online.
I did find a site which has sample DGN drawings available, please see link:
https://www.q-cad.com/samples/microstation-2d/microstation-2d-samples/ (https://www.q-cad.com/samples/microstation-2d/microstation-2d-samples/)
 
Title: Re: Relative paths
Post by: PKENEWELL on October 20, 2020, 09:35:07 AM
PKENEWELL, I tried to send a sample via PM but there was no option to attach.
Given I don't have ownership of the drawings, I can't post them online.
I did find a site which has sample DGN drawings available, please see link:
https://www.q-cad.com/samples/microstation-2d/microstation-2d-samples/ (https://www.q-cad.com/samples/microstation-2d/microstation-2d-samples/)

Like Citrus:

Thanks for the link. I tried out the program with a list of all the sample files and it worked for me. NOTE - I think you need to add the sub-folders to the support paths as well as the main folder. EDIT: I tried it without adding the sub-paths and it worked still. Sorry - I still can't explain why it doesn't work for you.

Try this: I did some more clean up on the program and re-posted here. I added some error handling, some conditional to prevent error, removed the command scrolling and replaced with a status message.

Code - Auto/Visual Lisp: [Select]
  1. (defun C:MicroStationToAutoCAD (/ *error* fil fn pth oecho odgn resp tx1 tx2 tx3 tx4 tx5)
  2.    
  3.    (defun *error* (msg)
  4.       (if (not (wcmatch (strcase msg T) "*break*,*cancel*,*quit*,*exit*"))
  5.               (princ (strcat "\nError: " msg "\n"))
  6.          (princ "\nProgram Aborted.\n")
  7.       )
  8.       (setvar "cmdecho" oecho)
  9.       (setvar "dgnimportmode" odgn)
  10.    )
  11.    
  12.    (setq fn "list.txt"
  13.          tx1 (findfile fn)
  14.          tx4 "Default"
  15.          oecho (getvar "cmdecho")
  16.          odgn (getvar "dgnimportmode")
  17.    )
  18.    (setvar "cmdecho" 0)
  19.    (setvar "dgnimportmode" 1)
  20.    (if (not tx1)
  21.       (princ "\nList file not found! Check the support paths. ")
  22.       (setq pth (vl-filename-directory tx1)
  23.             tx2 (strcat pth "\\in\\")
  24.             tx3 (strcat pth "\\out\\")
  25.       )
  26.    )
  27.    (if pth
  28.       (progn
  29.         (setq fil (open tx1 "r")
  30.                    tx5 (read-line fil)
  31.          )
  32.          (princ "\nConverting Files =")
  33.         (while tx5
  34.                 (if (wcmatch tx5 "*`.???")
  35.                         (setq tx5 (substr tx5 1 (- (strlen tx5) 4)))
  36.                 )
  37.                 (command "._UNDO" "_MARK"
  38.                      "._-DGNIMPORT" (strcat tx2 tx5) tx4 "" ""
  39.             )
  40.             (while (= (logand (getvar "cmdactive") 1) 1) (command ""))
  41.             (command "._ZOOM" "_E"
  42.                      "._DELAY" 1000
  43.                      "._SAVEAS" "2013(LT2013)" (strcat tx3 tx5)
  44.                      "._UNDO" "_BACK"
  45.             )
  46.             (if (= (logand (getvar "cmdactive") 1) 1)(Alert "Something Did not process correctly in this drawing.\nVerify the command sequence."))
  47.             (princ "=")
  48.                 (setq tx5 (read-line fil))
  49.         )
  50.         (close fil)
  51.          (princ " Conversion Completed! ")
  52.          (initget "Yes No")
  53.          (if (or (= (setq resp (getkword "\nDo you want to quit AutoCAD? [Yes/No] <Yes>: ")) "Yes")(= resp ""))
  54.           (command "_QUIT" "_Y")
  55.          )
  56.       )
  57.    )
  58.    (setvar "cmdecho" oecho)
  59.    (setvar "dgnimportmode" odgn)
  60.         (princ)
  61. )
  62.  
Title: Re: Relative paths
Post by: PKENEWELL on October 20, 2020, 03:41:12 PM
Here is a new version of the batch import routine, using some ideas from kpblc and adding my own.

I added in a check at the beginning to make sure the user is in a new, blank drawing. I also made a choice at the end to close AutoCAD completely, or just close the open drawing.

Code - Auto/Visual Lisp: [Select]
  1. (defun C:MicroStationToAutoCAD (/ acd doc *error* fil fn pth oecho odgn resp tx1 tx2 tx3 tx4 tx5)
  2.    
  3.    (defun *error* (msg)
  4.       (if (not (wcmatch (strcase msg T) "*break*,*cancel*,*quit*,*exit*"))
  5.          (princ (strcat "\nError: " msg "\n"))
  6.          (princ "\nProgram Aborted.\n")
  7.       )
  8.       (setvar "cmdecho" oecho)
  9.       (setvar "dgnimportmode" odgn)
  10.       (setvar "nomutt" omut)
  11.    )
  12.    
  13.    (setq fn "list.txt"
  14.          tx1 (findfile fn)
  15.          tx4 "Default"
  16.          oecho (getvar "cmdecho")
  17.          odgn (getvar "dgnimportmode")
  18.          omut (getvar "nomutt")
  19.          acd (vlax-get-acad-object)
  20.          doc (vla-get-activedocument acd)
  21.    )
  22.    (setvar "cmdecho" 0)
  23.    (setvar "dgnimportmode" 1)
  24.    
  25.    (if (not tx1)
  26.       (princ "\nList file not found! Check the support paths. ")
  27.       (progn
  28.          (setq pth (vl-filename-directory tx1)
  29.                tx2 (strcat pth "\\in\\")
  30.                tx3 (strcat pth "\\out\\")
  31.          )
  32.          (initget "Yes No")
  33.          (if (= (setq resp (getkword (strcat "\nFile List \"" fn "\" found. You should be in a new drawing to begin conversion. Proceed [Yes/No] <Yes>: "))) "No")
  34.             (setq pth nil)
  35.          )
  36.       )
  37.    )
  38.    (if pth
  39.       (progn
  40.          (setq fil (open tx1 "r")
  41.                tx5 (read-line fil)
  42.          )
  43.          (princ (strcat "\nConverting Files in " fn "> ="))
  44.          (setvar "nomutt" 1)
  45.          (while tx5
  46.             (if (and (wcmatch (strcase tx5) "*`.DGN")
  47.                      (findfile (strcat tx2 tx5))
  48.                 )
  49.                (progn
  50.                   (setq tx5 (vl-filename-base tx5))
  51.                   (command "._UNDO" "_MARK"
  52.                            "._-DGNIMPORT" (strcat tx2 tx5) tx4
  53.                   )
  54.                   (while (= (logand (getvar "cmdactive") 1) 1) (command ""))
  55.                   (vla-zoomall acd)
  56.                   (vla-saveas doc (strcat tx3 tx5 ".dwg") ac2013_dwg)
  57.                   (command "._UNDO" "_BACK")
  58.                   (if (= (logand (getvar "cmdactive") 1) 1)(Alert "Something Did not process correctly in this drawing.\nVerify the command sequence."))
  59.                   (princ "=")
  60.                )
  61.                (princ (strcat "\n file \"" tx5 "\" not found. File does not exist or filename is incorrect in \"" fn "\". Skipping file."))
  62.             )
  63.             (setq tx5 (read-line fil))
  64.          )
  65.          (close fil)
  66.          (princ " Conversion Completed! ")
  67.          (setvar "nomutt" omut)
  68.          (initget "Yes No")
  69.          (if (or (= (setq resp (getkword "\nDo you want to quit AutoCAD? [Yes/No] <Yes>: ")) "Yes")(= resp nil))
  70.            (command "._QUIT" "_Y")
  71.            (command "._CLOSE" "_y")
  72.          )
  73.       )
  74.    )
  75.    (setvar "cmdecho" oecho)
  76.    (setvar "dgnimportmode" odgn)
  77.    (princ)
  78. )
  79.  

EDIT: Added even more checks in the program, including testing if the file exists and is in fact a DGN file.
EDIT2: Changed response test to getkword from incorrect "" to correct nil.
Title: Re: Relative paths
Post by: like_citrus on October 21, 2020, 12:03:36 AM
Thanks very much PKENEWELL, this works now.
I think your previous shorter version works as well.

Long story, but the issue was with the text file, as I discovered having issues with the initial code, once working, then not. It took me a while to figure it out. I was using Excel to dump the drawing list data into the text file and AutoCAD didn't seem to accept it.
Initially I tried the latest code, that did not work, then after working out the issue, your code did work and the previous shorter version seems to work as well.

Sorry if this wasted your time, but it may be useful for someone else.
Title: Re: Relative paths
Post by: PKENEWELL on October 21, 2020, 09:22:36 AM
Thanks very much PKENEWELL, this works now.
I think your previous shorter version works as well.

Long story, but the issue was with the text file, as I discovered having issues with the initial code, once working, then not. It took me a while to figure it out. I was using Excel to dump the drawing list data into the text file and AutoCAD didn't seem to accept it.
Initially I tried the latest code, that did not work, then after working out the issue, your code did work and the previous shorter version seems to work as well.

Sorry if this wasted your time, but it may be useful for someone else.

No Problem Like_Citrus.  :-D I enjoyed playing with the program and trying to make it better! There is still more that could be done, but I like how this works.

Examples of improvements:

I might look back on these and add features if I have time.
Title: Re: Relative paths
Post by: PKENEWELL on October 28, 2020, 11:28:49 AM
Here is an alternative I just wrote that does not rely on a text file to list the files. It just searches the import path for DGN files and processes them.

Upon the first time starting, the program will ask for the Import and Output folders using a "Browse for Folder" dialog (thanks to Lee Mac's function). Then it saves them to the registry for future use. You can afterward use the "Configure" option at the "...Proceed? " prompt to change them if needed.

Before proceeding with the conversion, Make sure the Import folder you selected has the DGN files in it that you want to convert, and that you are currently in a NEW BLANK drawing. Then select "Yes" to proceed with the conversion. This uses all the default options of the DGNIMPORT comment so just update the command string if you need different options.

Any other Guru's out there - feel free to critique and note any improvements or issues with the code. There are still improvements that could be made, such as a DCL interface for the "Configure" option and the first start up. Note: I don't normally deal with Microstation files at all, so someone with a better understanding of the DGNIMPORT options could chime in and give some advisement.
Title: Re: Relative paths
Post by: like_citrus on October 28, 2020, 09:33:16 PM
Thanks for your efforts again. The code seems quite sophisticated. It does work as described and seems to have been thought through.
Title: Re: Relative paths
Post by: PKENEWELL on October 29, 2020, 02:09:06 PM
Thanks Like_Citrus. It's better than the old method used before we had the benefit of Visual LISP added to AutoLISP. The original AutoLISP language did not have any methods for querying and manipulating files outside of the (findfile) and text file functions, nor had any ActiveX / COM access like it does now. There were some creative ways around those problems, but now it's much easier.