问题
I have a VBA script for Excel that adds a small procedure in the active workbook. The final version will add a procedure that auto-saves backup copies of the workbook.
The code requires the Microsoft Visual Basic for Applications Extensibility 5.3 library which I can add manually, but I'm interested in having a single script that can add that library into Excel and then use it.
Here's the code that adds the library reference to Excel. It works.
On Error Resume Next ' If library already referenced, ignore the error
ThisWorkbook.VBProject.References.AddFromGuid _
GUID:="{0002E157-0000-0000-C000-000000000046}", _
Major:=5, Minor:=3
On Error GoTo 0 ' Resume normal error handling
Below is the code that uses this library to add a VBA procedure into the active workbook. It works, but only if the required library reference has first been added to Excel:
Sub AddProcedureToModule()
' This script adds a sample VBA procedure to the active workbook
' Add Library Reference: Microsoft Visual Basic for Applications
' Extensibility 5.3
On Error Resume Next ' If library already referenced, ignore the error
ThisWorkbook.VBProject.References.AddFromGuid _
GUID:="{0002E157-0000-0000-C000-000000000046}", _
Major:=5, Minor:=3
On Error GoTo 0 ' Resume normal error handling
Dim VBProj As VBIDE.VBProject ' requires Ref: MS VB for Apps Extensibility 5.3
Dim VBComp As VBIDE.VBComponent ' requires Ref: MS...5.3
Dim CodeMod As VBIDE.CodeModule ' requires Ref: MS...5.3
Dim LineNum As Long
Const DQUOTE = """" ' one " character
Set VBProj = ActiveWorkbook.VBProject ' requires Ref: MS...5.3
Set VBComp = VBProj.VBComponents("Module1") ' requires Ref: MS...5.3
Set CodeMod = VBComp.CodeModule ' requires Ref: MS...5.3
' Insert code into workbook
With CodeMod
LineNum = .CountOfLines + 1
.InsertLines LineNum, "Public Sub SayHello()"
LineNum = LineNum + 1
.InsertLines LineNum, " MsgBox " & DQUOTE & "Hello World" & DQUOTE
LineNum = LineNum + 1
.InsertLines LineNum, "End Sub"
End With
End Sub
The problem arises when I try to combine the two in a single procedure. Excel throws compile error "User defined type not defined". If I understand correctly, my code uses something called early binding. Excel looks for the library before any code is executed and can't find it.
The answer may be to adapt my code to use late binding so that Excel won't look for that library until after part of the script has executed and the library is available.
Using this post as a guide I modified part of the code to look like this:
Dim VBProj As Object
Dim VBComp As Object
Dim CodeMod As Object
Dim LineNum As Long
Const DQUOTE = """" ' one " character
Set VBProj = CreateObject("ActiveWorkbook.VBProject")
Set VBProj = ActiveWorkbook.VBProject
Set VBComp = CreateObject("VBProj.VBComponents(""Module1"")")
Set CodeMod = CreateObject("VBComp.CodeModule")
Excel threw error "Run-time error '429': ActiveX component can't create object".
Any idea how I can either modify this code to utilize late binding, or otherwise load the library reference and run the rest of the code in the same procedure/module?
回答1:
There is a false premise in your original code:
Set VBProj = ActiveWorkbook.VBProject ' requires Ref: MS...5.3 Set VBComp = VBProj.VBComponents("Module1") ' requires Ref: MS...5.3 Set CodeMod = VBComp.CodeModule ' requires Ref: MS...5.3
This code does not require any references per se. What does require a reference is the variable declaration above:
Dim VBProj As VBIDE.VBProject Dim VBComp As VBIDE.VBComponent Dim CodeMod As VBIDE.CodeModule
As soon as you have replaced them with As Object
you can run the rest of the code as is without adding a reference. Make sure you have Option Explicit
at the top to catch any now-undeclared constants you might be using.
However I would advise you consider a different approach, such as moving the code you want to putting into files into an adding that the files can refer to. Automatically adding VBA code to files is a security concern because it is a common way of spreading malware, it might set antiviruses off, and it requires the Trust access to the VBA project object model setting to be set in the user interface (which I would personally never set).
来源:https://stackoverflow.com/questions/39519805/how-can-i-load-a-vba-library-reference-and-use-it-in-the-same-procedure