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