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

发布于 2024-12-28 01:22:43 字数 528 浏览 3 评论 0原文

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

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

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

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

If o Is Nothing Then
    MsgBox "nope"
End If

但是,如果我添加了对库的引用以便使用早期绑定,那么如果该库不存在,我会得到一个加载我的 VBA 项目时出现编译错误。因此,没有代码运行(包括检测库不存在的代码)。

有什么办法可以解决这个第 22 条军规吗?

I like to use early binding in my VBA projects, since I like the auto-complete of method names, etc. during development. I also like the confidence of knowing that the compiler will warn me if I've mis-spelled a method name.

However, to use early binding I need to add a reference to the relevant library (for example, the "Microsoft Scripting Runtime"). That's fine for "standard" libraries like that, but sometimes I want to use a library that may or may not be present on the user's machine.

Ideally, I'd like to display a useful message if the library is not present (such as "xyz is not installed on this computer, and so this feature cannot be used"). If I was using only late binding, then I could do this:

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

If o Is Nothing Then
    MsgBox "nope"
End If

But, if I've added a reference to the library in order to use early binding, then if the library is not present I get a compile error when my VBA project is loaded. Thus, none of the code runs (including the code to detect the non-existence of the library).

Is there any way around this catch-22?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不顾 2025-01-04 01:22:43

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

所有这些过程都将以相同的方式使用代理类,因此您不需要修改这些过程来在早期绑定和后期绑定之间切换。 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 的示例,您可以对其对象模型的可管理子集执行类似的操作。但如果您需要它的全部或大部分方法、属性和常量,代理类将是一项艰巨的任务。

我个人不会使用这种方法。对于我来说,像 mwolfe02 和 JP 一样管理早期/后期绑定的工作量更少。描述的。然而,我的印象是,这对你的情况来说是更沉重的负担,所以也许你愿意在这样的事情上投入比我更多的努力。

You could create a class module as a proxy for an object library --- wrap all the methods, properties, and constants needed by your other procedures.

All those procedures would use the proxy class the same way, so you wouldn't need to revise those procedures to switch between early and late binding. And Intellisense would show you everything you expose with the proxy class.

The class would be a single point of control to switch between early and late binding. You mentioned Excel as one example:

#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

If there is a possibility Excel may not be installed on any users' machines, you can check its availability during class initialize.

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

Then your procedures which use the proxy class could check a property to see whether Excel is available.

Public Property Get ExcelAvailable() As Boolean
    ExcelAvailable = blnExcelAvailable
End Property

I think this approach is possible, and it satisfies your requirements AFAICT. However, I'm unsure whether it's reasonable. Back to the example of Excel, you could do something like this for a manageable subset of its object model. But if you need all or most of its methods, properties, and constants, the proxy class would be a huge undertaking.

Personally I wouldn't use this approach. It's less work for me to manage early/late binding as mwolfe02 and JP. described. However my impression is this is more burdensome in your situation, so perhaps you're willing to invest more effort than I am in something like this.

画骨成沙 2025-01-04 01:22:43

并不真地。

然而,我在开发中处理这个问题的一种方法是有两个单独的声明行。我根据我是在进行开发工作还是发布到生产环境来评论其中之一。您可以保留其他所有内容(包括 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

Not really.

However, one way I've dealt with this in development is to have two separate declaration lines. I comment one or the other depending on whether I am doing dev work or releasing to production. You can leave everything else alone (including the CreateObject line) and then you just need to remember to switch the commented line and add/remove the reference itself.

For example:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文