【问题标题】:How can I load a VBA library reference and use it in the same procedure?如何加载 VBA 库引用并在同一过程中使用它?
【发布时间】:2016-09-15 20:28:03
【问题描述】:

我有一个 Excel 的 VBA 脚本,它在活动工作簿中添加了一个小过程。最终版本将添加一个自动保存工作簿备份副本的过程。

代码需要 Microsoft Visual Basic for Applications Extensibility 5.3 库,我可以手动添加该库,但我有兴趣拥有一个可以将该库添加到 Excel 中然后使用它的单个脚本。

以下是将库引用添加到 Excel 的代码。它有效。

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

以下是使用此库将 VBA 过程添加到活动工作簿的代码。它有效,但前提是首先将所需的库引用添加到 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

当我尝试将两者结合在一个程序中时,就会出现问题。 Excel 抛出编译错误“未定义用户定义类型”。如果我理解正确,我的代码使用了一种叫做早期绑定的东西。 Excel 在执行任何代码之前查找库,但找不到。

答案可能是调整我的代码以使用后期绑定,以便 Excel 在执行部分脚本并且该库可用之前不会查找该库。

使用this post 作为指导,我将部分代码修改为如下所示:

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 抛出错误“运行时错误 '429': ActiveX 组件无法创建对象”。

知道如何修改此代码以利用后期绑定,或者加载库引用并在同一过程/模块中运行其余代码吗?

【问题讨论】:

  • AFAIK,它无法完成。您不能后期绑定,因为CreateObject 仅适用于已注册的类型。您不能提前绑定,因为这需要重新编译。
  • 您没有使用任何CreateObjects。您将所有声明为Object,然后保留原始分配(Set VBProj = ActiveWorkbook.VBProject 等)。然而,整个事情是一个很大的安全问题,需要设置“信任对 VBA 项目对象模型的访问”勾选。
  • @GSerg 在“对象”处声明并保持原始分配有效,但您能解释一下安全问题吗?
  • 顺便说一句,为了清楚起见,在这种情况下,声明对象工作没有引用 CreateObject。它起作用的唯一原因是您可以使用ActiveWorkbook.VBProject 请求一个对象,而不是创建一个。

标签: excel vba class late-binding vbide


【解决方案1】:

您的原始代码中有一个错误的前提:

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

此代码本身不需要任何引用。需要引用的是上面的变量声明:

Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent 
Dim CodeMod As VBIDE.CodeModule 

一旦您将它们替换为As Object,您就可以按原样运行其余代码,而无需添加引用。确保您在顶部有 Option Explicit 以捕获您可能正在使用的任何现在未声明的常量。

但是,我建议您考虑一种不同的方法,例如将要放入文件的代码移动到文件可以引用的添加中。自动将 VBA 代码添加到文件是一个安全问题,因为它是传播恶意软件的常见方式,它可能会关闭防病毒软件,并且需要在用户界面中设置 Trust access to the VBA project object model 设置(我个人永远不会设置)。

【讨论】:

  • 在“对象”处声明并保持原始分配有效,但您能解释一下安全问题吗?
  • 来自链接“此安全选项使未经授权的程序更难构建可能损害最终用户系统的“自我复制”代码。”
猜你喜欢
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 2020-01-11
  • 2016-11-15
  • 2018-11-27
相关资源
最近更新 更多