Vba 在通过早期绑定使用库之前,我可以使用后期绑定检查库的存在吗?

Vba 在通过早期绑定使用库之前,我可以使用后期绑定检查库的存在吗?,vba,late-binding,early-binding,Vba,Late Binding,Early Binding,我喜欢在VBA项目中使用早期绑定,因为我喜欢在开发过程中自动完成方法名等。我还喜欢自信地知道,如果我拼写错误了方法名,编译器会警告我 但是,要使用早期绑定,我需要添加对相关库的引用(例如,“Microsoft脚本运行时”)。对于这样的“标准”库来说,这很好,但有时我想使用用户机器上可能存在或不存在的库 理想情况下,如果库不存在,我希望显示一条有用的消息(例如“此计算机上未安装xyz,因此无法使用此功能”)。如果我只使用后期绑定,那么我可以这样做: Dim o As Object Set o =

我喜欢在VBA项目中使用早期绑定,因为我喜欢在开发过程中自动完成方法名等。我还喜欢自信地知道,如果我拼写错误了方法名,编译器会警告我

但是,要使用早期绑定,我需要添加对相关库的引用(例如,“Microsoft脚本运行时”)。对于这样的“标准”库来说,这很好,但有时我想使用用户机器上可能存在或不存在的库

理想情况下,如果库不存在,我希望显示一条有用的消息(例如“此计算机上未安装xyz,因此无法使用此功能”)。如果我只使用后期绑定,那么我可以这样做:

Dim o As Object
Set o = CreateObject("foo", "bar")

If o Is Nothing Then
    MsgBox "nope"
End If
但是,如果为了使用早期绑定而添加了对库的引用,那么如果库不存在,则在加载VBA项目时会出现编译错误。因此,没有任何代码运行(包括检测库不存在的代码)

有什么办法可以解决这一难题吗?

不太可能

然而,我在开发中处理这个问题的一种方法是使用两个单独的声明行。我会根据我是在做开发工作还是发布到生产环境来评论其中一个。您可以将所有其他内容(包括
CreateObject
行)都放在一边,然后只需记住切换注释行并添加/删除引用本身

例如:

Dim o As foo.bar   'Comment out for production'
'Dim o As Object    ''Comment out for dev work'
Set o = CreateObject("foo", "bar")

If o Is Nothing Then
    MsgBox "nope"
End If

您可以创建一个类模块作为对象库的代理——包装其他过程所需的所有方法、属性和常量

所有这些过程都将以相同的方式使用代理类,因此不需要修改这些过程来在早期绑定和后期绑定之间切换。Intellisense将向您展示使用代理类公开的所有内容

该类将是在早期绑定和后期绑定之间切换的单个控制点。您提到的Excel就是一个例子:

#Const DevStatus = "PROD"
#If DevStatus = "DEV" Then
    Private objApp As Excel.Application
    Private objBook As Excel.Workbook
    Private objSheet As Excel.Worksheet
#Else 'assume PROD
    Private objApp As Object
    Private objBook As Object
    Private objSheet As Object
#End If
如果任何用户的计算机上都可能未安装Excel,则可以在类初始化期间检查其可用性

Dim blnExcelAvailable As Boolean

Private Sub Class_Initialize()
    blnExcelAvailable = IsExcelAvailable()
End Sub

Private Function IsExcelAvailable() As Boolean
    Dim blnReturn As Boolean
    Dim objTest As Object

On Error GoTo ErrorHandler

    Set objTest = CreateObject("Excel.Application")
    blnReturn = True

ExitHere:
    On Error GoTo 0
    Set objTest = Nothing
    IsExcelAvailable = blnReturn
    Exit Function

ErrorHandler:
    blnReturn = False
    GoTo ExitHere
End Function
然后,使用代理类的过程可以检查属性以查看Excel是否可用

Public Property Get ExcelAvailable() As Boolean
    ExcelAvailable = blnExcelAvailable
End Property
我认为这种方法是可行的,它满足了您的AFAICT要求。然而,我不确定这是否合理。回到Excel示例,您可以对其对象模型的可管理子集执行类似的操作。但是,如果您需要它的全部或大部分方法、属性和常量,那么代理类将是一项巨大的任务


就我个人而言,我不会使用这种方法。对于我来说,像Mwolfe2和JP一样管理早/晚绑定的工作更少。描述。然而,我的印象是,在您的情况下,这是一个更沉重的负担,因此,也许您愿意在类似的事情上投入比我更多的精力。

我使用早期绑定来利用Intellisense,然后转换为后期绑定以避免特定于版本的代码。@JP:请参阅我对mwolfe02答案的回复-我认为这对我来说不是一个可行的解决方案,除非您有其他方法来实现它。我将所有声明放在每个过程的顶部,并使用CreateObject来处理后期或早期绑定。因此,简单地将所有早期绑定的声明更改为后期绑定的“As-Object”。但条件编译也可以工作,这没什么,只是我的项目太大了,所以会有成百上千的声明。每个Excel.Range、每个单词、段落等都必须有这个双重声明。我想我可以使用一个编译器常量,并用#If LATE _boundthe。。。这将使两种模式之间的切换更容易。但是它会把代码弄得乱七八糟,因为现在每个声明都需要5行。。。。这也意味着对我所有的方法和函数都有一个不同的声明。哎呀!好主意。对于Excel之类的东西来说,重复所有对象、方法和(特别是)常量将是一项艰巨的任务,这一点您是100%正确的。然而,我以Excel为例是愚蠢的,因为我可以假设Office的存在——毕竟,这是VBA,如果代码正在运行,那么宿主应用程序必须存在。对于我真正关心的那种小型库,您的技术将更加可行。谢谢+1我非常喜欢这个想法,但它似乎只适用于预定义的“Office”apps@mehow我的意思是用一个VBA类包装一个COM应用程序,因此应用程序将在该类中定义。(这就是您所说的预定义吗?)。但这一概念并不局限于办公应用程序。其他启用COM的应用程序也应该可以工作。@HansUp是的,这是正确的。(对不起,可能是我的英语)。我现在已经重读了你的答案,是的,我收回了我关于限制的最后陈述。