【问题标题】:Late Binding Global Variables?后期绑定全局变量?
【发布时间】:2020-07-13 18:08:25
【问题描述】:

我正在为 Excel 使用 VBA。据我了解,全局变量需要在任何 subs 之外声明。这是所有潜艇都可以访问它们的唯一方式。

同时,我想进行后期绑定以引用“Microsoft Scripting Runtime”库(以使用字典对象类型),这样最终用户就不必自己动手了。

我的代码如下:

On Error Resume Next
strGUID = "{420B2830-E718-11CF-893D-00A0C9054228}"
ThisWorkbook.VBProject.References.AddFromGuid GUID:=strGUID, Major:=1, Minor:=0

Dim Dic1 As Object
Set Dic1 = CreateObject("Scripting.Dictionary")
Dim Dic2 As Object
Set Dic2 = CreateObject("Scripting.Dictionary")

如果我想用后期绑定声明全局字典对象怎么办?看起来 VBA 不允许我将任何代码放在 subs 之外(除了声明)。

如何在不需要最终用户自己配置库引用的情况下声明全局字典对象?我应该执行以下操作吗?

Dim Dic1 As Object
Dim Dic2 As Object

Sub Prog1()
    On Error Resume Next
    strGUID = "{420B2830-E718-11CF-893D-00A0C9054228}"
    ThisWorkbook.VBProject.References.AddFromGuid GUID:=strGUID, Major:=1, Minor:=0

    Set Dic1 = CreateObject("Scripting.Dictionary")
    Set Dic2 = CreateObject("Scripting.Dictionary")
End Sub

【问题讨论】:

  • 只能声明对象,不能设置。所以只是Dim Dic1 As Object 在子之外。也许在 Workbook_Open() 子/事件中你可以做 Set?
  • 旁注:在扫描您的代码时,我看到On Error Resume Next 没有On Error GoTo 任何地方都可以将其关闭。这是非常危险的——你永远不知道你的代码什么时候抛出错误,也不知道是什么原因造成的。
  • FWIW 你很少需要一个全局变量。你知道如何将参数传递给过程/函数吗?
  • 此外,脚本运行时库是每个 Windows 机器上的标准问题,本世纪还没有看到更新,在可预见的未来也不太可能看到更新 - 除非您的代码需要在其上运行Mac,无需后期绑定该库。项目引用与 VBA 项目一起保存在宿主文档中,用户无需自行添加。
  • 是的,(开发者)需要添加它。 一次。一旦它在那里,它就在那里。

标签: ms-access vba


【解决方案1】:

与 VBA 代码本身一样,项目引用不会在用户打开主机工作簿时神奇地消失。它们与宿主文档中的代码一起保存。

所以,你的问题的前提是错误的:用户永远不需要调整项目引用。

此外,Scripting Runtime 类型库是标准问题,并且在本世纪(甚至在此之前)构建的每台 Windows 机器上都提供了完全相同的版本,这意味着除非您的代码需要在 Mac 上运行,否则无需永远后期绑定脚本运行时库。

如果您的代码需要在 Mac 上运行,该库无论如何都不会后期绑定,因为它不会在主机上找到,因此后期绑定脚本运行时只会产生愚蠢的错别字并引入IntelliSense 有助于防止的其他容易避免的错误。


ThisWorkbook.VBProject.References.AddFromGuid GUID:=strGUID, Major:=1, Minor:=0

这违背了后期绑定的全部目的:它使用 VBIDE 可扩展库(需要降低宏安全设置)以编程方式添加一个引用,您可以在设计时通过 VBE 的 工具 菜单。

后期绑定的代码根本不需要引用。不在编译时,不在运行时。

添加引用,保存,然后声明您的对象As Scripting.Dictionary 并享受早期绑定代码的好处。

Set Dic1 = New Scripting.Dictionary

这就是你所需要的。


如果我想用后期绑定声明全局字典对象怎么办?看起来 VBA 不允许我将任何代码放在 subs 之外(除了声明)。

在这方面,后期绑定与早期绑定没有任何不同。迟绑定代码和早绑定代码之间的唯一区别在于声明的As 子句:

Private foo As Object ' no compile-time type knowledge: late-bound
Private bar As Dictionary ' compile-time type knowledge: early-bound

您如何初始化该对象引用对声明的后期/早期绑定性质没有影响。

这会在注册表中查找 ProgID 以查找库和类型:

Set foo = CreateObject("Scripting.Dictionary")

这使用了项目引用:

Set foo = New Scripting.Dictionary

两者都是正确的,并且都适用于早期或晚期绑定声明。除非,如果您已经拥有对类型库的引用,则无需访问注册表即可找到该库 - 只需 New 即可!

【讨论】:

    【解决方案2】:

    全局变量确实不需要,应该避免。但是,如果您出于自己的原因决定使用它们,则可以将它们放入 Workbook_Open 事件中:

    Option Explicit
    
    Dim Dic1 As Object
    Dim Dic2 As Object
    
    Private Sub Workbook_Open()
    
        Set Dic1 = CreateObject("Scripting.Dictionary")
        Set Dic2 = CreateObject("Scripting.Dictionary")
    
    End Sub
    

    因此,每次打开工作簿时都会创建对象。

    【讨论】:

    • 呸,我在早期/晚期绑定的事情上跑偏了,忘了解决变量的实际初始化问题 - 赞成。
    猜你喜欢
    • 2021-03-29
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    相关资源
    最近更新 更多