Loading VBA Files
There are two AutoCAD
functions that can you would use to Load and Run VBA Applications namely, VBALOAD
and VBARUN. In a menu file you would use them like this :
[Test]^C^C^C^P-vbaload
test.dvb -vbarun Module1.MyTest
Or, in an AutoLisp routine,
you would write something like this :
(command "vbaload"
"test.dvb")
(command "-vbarun" "Module1.MyTest")
The VBALOAD function has
one serious flaw though!
If a VBA application is already loaded, and you run VBALOAD again,
you get an error message. Try it out :
Command: -vbaload
Initializing VBA System...
Open VBA Project: test.dvb
Now try and load it
again.
Command: -vbaload
Open VBA Project: test.dvb
You should get an error
message :
"File
already loaded d:/drawings/test.dvb"
This is where Visual Lisp
come into play.
The function (VL-VBALOAD)
behaves much like the command VBALOAD. You need to supply the file name of
a project or DVB file. The complete file name should be provided along
with the path and DVB extension. For example, if you want to load a
project named MyProject.dvb in the C:\MyWork\ folder, the (VL-VBALOAD)
function call would appear as follows.
(VL-VBALOAD "C:/MyWork/MyProject.DVB")
You should note a couple of things right away. Visual LISP makes use of
forward slashes when separating folder or directory names. Also, the
parentheses are required and the extension DVB is needed for the project
to be properly located.
Unlike the VBALOAD command, this function will not generate an error if
the project has already been loaded into the current drawing environment.
Thus, programs can proceed smoothly by just calling the load function and
then calling the run function without concern about the project already
being loaded. Another interesting feature is that the Enable Macros/Virus
Warning message does not appear when you use the Visual LISP approach.
Therefore, your menu macro
:
[Test]^C^C^C^P-vbaload
test.dvb -vbarun MyTest
can be replaced with the following one:
[Test]^C^C^C^P(vl-vbaload "test.dvb")(vl-vbarun "MyTest")
And of course, your
AutoLisp coding should be replaced with this :
(vl-vbaload "test.dvb")
(vl-vbarun "MyTest")
Here's a little function
that you could load at startup to help you locate, load and run VBA files:
;CODING START
HERE
(defun VBA-LOADIT (ProjName Macro)
(if (findfile ProjName)
(progn
(vl-vbaload ProjName)
(vl-vbarun Macro)
);progn
);if
(princ)
);defun
(princ)
;CODING ENDS HERE
Syntax : (vbaloadit "dvb-file"
"macro")
Example : (vbaloadit "test.dvb"
"MyTest")
You must keep some other considerations
in mind when using (VL-VBALOAD) and (VL-VBARUN). For example, after you
invoke the (VL-VBARUN) function, the Visual LISP function will continue to
run and can (will) interfere with the VBA interface if you try to do too
much. On the other hand, there are some distinct advantages to using the
Visual LISP approach to loading and launching VBA macros instead of the
command-line versions when programming a menu- or toolbar-based interface.
One thing to note is that the VBARUN is not a subroutine. That is, program
execution will not be handed to the VBA macro and the Visual LISP routine
suspended as if it were running a function. Instead, the Visual LISP
function will continue to run as the VBA macro starts. The best thing to
do is simply finish the Visual LISP function as quickly as possible and
let the VBA macro run the command interface from that point forward. If
you want to return to a Visual LISP function after running the VBA code,
then use the SendCommand method attached to the Document object in VBA.
When you are ready to hand control back to Visual LISP, call the function
directly (remember to wrap parentheses around the command start up for
direct launches of Visual LISP functions). When you use this approach, the
VBA program should end and allow the Visual LISP function to proceed
without interference. Similar to starting the VBA macro in the first
place, when you send commands to the AutoCAD document from VBA, they will
be run along with the VBA and sometimes this can result in confusion at
the user level as the two try to take turns. Note that you can pass
parameters from VBA to the Visual LISP function by sending them as part of
the command stream. They will need to be converted to strings first, then
sent to the Visual LISP function as part of the function start up from the
Send Command method.
NOTE : Sorry, but due
to additions to the Object Model, this next section will only work in
AutoCAD 2002 :-(
Want to know what Projects are loaded in
your drawing?
Type this at the console prompt :
_$ (vl-load-com)
_$ (setq oApp (vlax-get-acad-object))
#<VLA-OBJECT IAcadApplication 00ac8928>
_$ (setq oVbe (vlax-get oapp "VBE"))
#<VLA-OBJECT VBE 020b9c18>
_$ (vlax-dump-object oVBE T)
; VBE: nil
; Property values:
; ActiveCodePane = nil
; ActiveVBProject = #<VLA-OBJECT _VBProject 020ba620>
; ActiveWindow (RO) = nil
; CodePanes (RO) = #<VLA-OBJECT _CodePanes 00b1c2e0>
; CommandBars (RO) = #<VLA-OBJECT _CommandBars 030b2a24>
; Events (RO) = #<VLA-OBJECT Events 020b9c94>
; MainWindow (RO) = #<VLA-OBJECT Window 020b8ce8>
; SelectedVBComponent (RO) = #<VLA-OBJECT _VBComponent 020ba748>
; VBProjects (RO) = #<VLA-OBJECT _VBProjects
020b9c4c>
; Version (RO) = "5.00"
; Windows (RO) = #<VLA-OBJECT _Windows 020b9d18>
; No methods
T
I presume you can see what I see? A
"VBProjects" property.
Now that's interesting! But how do we extract the loaded Projects?
Load and run this small routine.
;CODING STARTS
HERE
(defun Gvba ( /oApp oVBE oProjs N Nams oProj)
(vl-load-com) ;requires automation links
(if (and
;Drill down to the Projects object
(setq oApp (vlax-get-acad-object))
(setq oVBE (vla-get-vbe oApp))
(setq oProjs (vlax-get oVBE "VBProjects"))
)
;Loop through Projects object
(repeat (setq N (vla-get-count oProjs))
;get the item at position N
(setq oProj (vla-item oProjs N)
;get the name property,
;add it to the list.
Nams (cons
(list
(vlax-get oProj "Name")
(vlax-get oProj "FileName")
) Nams) N (1- N)))
)
; return list of names
Nams
);defun
;CODING ENDS HERE
You should have a list of Projects in
the variable "Nams".
And, would you like to Unload all
Projects within your drawing? Try this :
;CODING STARTS
HERE
(defun C:UNLOADALLVBA ( / VBAProjs
VBAProj)
(setq VBAProjs (Gvba))
(foreach VBAProj VBAProjs
(command "_VBAUNLOAD" (cadr VBAProj)))
)
;CODING ENDS HERE
|