VBA 模块中的可选依赖项

问题描述 投票:0回答:1

背景

我正在为 UDF 的 VBA 开发人员开发一个 VBA 模块(称之为“

Greg
”),这增强了他们现有的模块。他们只需将一个片段复制到自己的模块中(称之为
Dev
):如果
Greg
被加载,该片段会增强行为;否则没有什么区别。

方法

这是

Greg.bas
...

的简化草图
Attribute VB_Name = "Greg"

' Keep these functions invisible to Excel users.
Option Private Module


' Enhancement Function.
Public Function Enhancer(Optional x)
   ' ...
End Function


' Assert the 'Greg' module is loaded.
Public Function IsLoaded() As Boolean
    IsLoaded = True
End Function

...以及

Dev.bas
:

Attribute VB_Name = "Dev"

' Some UDF by the dev.
Public Function DevRegular()
   ' ...
End Function


' #############
' ## Snippet ##
' #############

' Use the enhancer, if available via the 'Greg' module.
Public Function DevEnhanced(Optional x)
    If Enhance_IsSupported() Then
        DevEnhanced = Greg.Enhancer(x)
    Else
        DevEnhanced = DevRegular()
        
        ' Prompt the user to import the enhancer.
        MsgBox "Import the 'Greg' module to enhance your experience."
    End If
End Function


' Check if enhancement is supported via the 'Greg' module.
Private Function Enhance_IsSupported() As Boolean
    On Error GoTo Fail
    Enhance_IsSupported = Greg.IsLoaded()
    Exit Function
Fail:
    Enhance_IsSupported = False
End Function

问题

虽然这在 Windows 上偶尔有效,但在 Mac 上却经常失败。关键似乎是

Enhance_IsSupported()
Dev
:

Private Function Enhance_IsSupported() As Boolean
    On Error GoTo Fail
    Enhance_IsSupported = Greg.IsLoaded()
    Exit Function
Fail:
    Enhance_IsSupported = False
End Function

我假设

Greg.IsLoaded()
行会编译,即使没有
Greg
模块存在......而且确实如此!仅当
Greg
模块 不存在 名为
IsLoaded()
的成员时才会失败。

不幸的是,VBA 似乎无法可靠地刷新其对具有 Greg

 函数的 
IsLoaded()
 模块的“感知”。

当我导入

Greg.bas
Dev.bas
一起时,一切都会按预期工作:
Enhance_IsSupported()
返回
True
,如果删除
False
,它会更新为 
Greg

但是当我第一次导入

Dev.bas
run
DevEnhanced()
,并且只有 afterwards 导入
Greg.bas
时,然后
Enhance_IsSupported()
显然会返回
False
尽管 存在
Greg

注意

后一个工作流程绝对重要:Excel 用户必须首先运行

DevEnhanced()
并查看提示,以便首先了解
Greg.bas

失败的解决方案

不幸的是,没有任何实验有效。在

Greg
本身,我尝试使用常量...

Public Const IS_LOADED As Boolean = True

...还有一个程序:

Public Function IsLoaded() As Boolean
   IsLoaded = True
End Function

Dev
的片段中,我已经隐式尝试了
Application.Evaluate()
...

Private Function Enhance_IsSupported() As Boolean
    On Error GoTo Fail
    Enhance_IsSupported = [Greg.IsLoaded()]
    '                     ^^^^^^^^^^^^^^^^^
    '                     Application.Evaluate("Greg.IsLoaded()")
    Exit Function
Fail:
    Enhance_IsSupported = False
End Function

...但是虽然这适用于

Enhance_IsSupported()
本身,同样的错误只会在其他地方出现 - 就像在
Greg.*
的其他实例上打地鼠一样 - 并且 只有手动编辑才能“刷新”这些程序。我还希望避免对任何
.Evaluate()
方法的不稳定调用,即使是在
Worksheet
范围内。

问题

  • “刷新”
    Dev
    模块的最简单方法是什么,以便其程序现在识别对
    Greg.*
    的调用?
  • 这是否可以在不重置
    Static
     中的缓存或 
    Dev
    变量的情况下实现?
  • 这可以通过
    IS_LOADED
    常量而不是
    IsLoaded()
    过程来完成吗?

奖金

  • 这个茶点可以由像
    Sub
    这样在
    Dev.Refresh()
    开始时自动调用的
    Enhance_IsSupported()
    来完成吗?
  • 此茶点可以由某些
    Sub
    (如
    Greg.Refresh()
    )来完成吗?由用户在 VBA 编辑器中手动运行?

这个项目代表了我大量的时间和精力的投入,并且它在其他方面是可操作的,因此非常感谢您的帮助来克服这最后的障碍!

vba module compilation dependencies dependency-management
1个回答
0
投票

你已经提到了一个常数,为什么不呢:

在格雷格模块中:

Public Const GREG_IS_LOADED = True

在模块开发中:

' Use the enhancer, if available via the 'Greg' module.
Public Function DevEnhanced(Optional x)
#If GREG_IS_LOADED Then
    'If Enhance_IsSupported() Then
       DevEnhanced = Greg.Enhancer(x)
#Else
    'Else
       DevEnhanced = DevRegular()
        
       ' Prompt the user to import the enhancer.
       MsgBox "Import the 'Greg' module to enhance your experience."
    'End If
#End If
End Function
© www.soinside.com 2019 - 2024. All rights reserved.