Vba 如何限制标准模块中的功能范围

Vba 如何限制标准模块中的功能范围,vba,scope,Vba,Scope,我准备了一个标准模块,MyPath,其中包含一些有用的函数。在这种情况下,标准模块比类模块更适合我 写起来舒服多了: Dim ext作为字符串 ext=MyPath.getFileExtension(“test.docx”)返回“docx” 而不是: 将Pth变暗为MyPath 设置Pth=newmypath Dim ext作为字符串 ext=Pth.getFileExtension(“test.docx”) 或者类似的 Dim ext作为字符串 使用新的MyPath ext=.getFil

我准备了一个标准模块,
MyPath
,其中包含一些有用的函数。在这种情况下,标准模块比类模块更适合我

写起来舒服多了:

Dim ext作为字符串
ext=MyPath.getFileExtension(“test.docx”)返回“docx”
而不是:

将Pth变暗为MyPath
设置Pth=newmypath
Dim ext作为字符串
ext=Pth.getFileExtension(“test.docx”)
或者类似的

Dim ext作为字符串
使用新的MyPath
ext=.getFileExtension(“test.docx”)
以
我的“伪静态类”模块的唯一问题是它的作用域(以及IntelliSense的使用)

Dim ext作为字符串
ext=getFileExtension(“test.docx”)'这是可行的,但我不希望这样
我希望达到的目标是:

  • 如果调用函数时未指定
    MyPath
    ,则IntelliSense不会建议模块中的方法,因此无法使用这些方法
  • 为了使用
    MyPath
    模块中的任何方法,需要键入
    MyPath.
    ,并且在dot IntelliSense之后,应建议模块中的方法
我尝试了一些与
选项专用模块
专用
功能的组合,但没有人能像我描述的那样工作。
我正在准备很多课程和类似的模块,我会让一切井然有序

编辑
简而言之,如果我没有为函数或子函数指定“父”模块,我想强制编译器抛出一个错误。同时,如果我键入模块的名称,我将能够使用IntelliSense(没有运行/调用解决方案,只需键入模块名、点并选择成员)


您描述的行为实际上可以通过预先声明的课程实现,但需要做一些准备工作

要创建一个预先声明的类,您可以编写一个包含您想要的任何函数的类。然后将其导出为文本(.cls)并对其进行编辑,将
属性VB\u PredeclaredId
设置为True。然后重新导入它。我的类称为
PredeclaredClass
,在.cls文件中如下所示:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "PredeclaredClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "Rubberduck" ,"Predeclared Class Module"

Option Explicit

Public Sub ThisIsVisible()

End Sub
导入此类后,现在只能通过引用类模块(不需要新实例)来使用其方法

如果没有模块引用,您将无法在intellisense中看到它,也无法使用其功能。如果您使用的是
选项Explicit


顺便说一句,这样做非常容易,无需导出/导入模块。

另一个解决方案,受VBA的Err对象启发,是实现一个函数,返回对“静态对象”的引用

公共静态函数MyPath()作为PathObject
暗淡的结果作为病理对象
如果结果为Nothing,则将结果设置为New PathObject
设置MyPath=result
端函数
其中
PathObject
是包含所有伪静态方法的类

这种方法还有一个额外的好处,即调用者不能将MyPath引用设置为Nothing(无),以防您决定静态模块应该是有状态的(可能是为了一些昂贵的初始化例程)

PS我认为
静态函数
语法很可爱,但您也可以使用Static关键字声明结果


事实上,你可以通过使用

Public Static Function MyPath() As PathObject
    Dim result As New PathObject
    Set MyPath = result
End Function

未经测试,但应具有这样的行为:
MyPath
仅在第一次使用时才会实例化,但此后会无限期地挂起

您是在同一工作簿中谈论Excel模块吗?如果函数确实位于标准模块中,而不是类模块中,并且如果它们是公共的,默认情况下,其他代码可以访问它们,而无需键入模块名称。如果您试图从另一个文档中使用这些函数,则显然需要先添加对包含该文档的引用。同一工作簿。所以不幸的是,似乎不可能隐藏模块的函数、子函数,并且仅在使用名称时才显示它们:(我会避免事情变得一团糟,我不确定我能帮到你…你喜欢使用intellisense,还是想隐藏它们以防被访问?或者两者都是…?你想不访问某些模块(函数)吗,来自同一工作簿中的其他模块?您需要它吗,还是只播放以查看发生了什么?@FaneDuru当然不是在键入时,它应该会在编译时阻止我。不过,ArcherBird给出了解决方案,感谢大家的帮助。请注意,这会创建一个隐式的“缓存”类的实例。因为所有的方法现在实际上都是实例方法,它们都将接收隐式
this
参数,因此如果您需要它,它们将不符合
AddressOf
操作符的资格。太棒了,我一直在寻找这样的方法!非常感谢!我们最喜欢的VBE addin帮助Eprocess@GSerg你仍然可以使用类似的方法来获取类方法的地址。你能看看链接的问题吗?如果你能提供帮助,那就太好了。我甚至不知道
static
是一个可以应用于函数的关键字vba@ArcherBird这没什么特别的-通常静态函数是g是一个类,但不需要调用类实例。然而,在VBA中,它只意味着所有局部变量都声明为静态(因此基本上与在函数体中将Dim替换为静态相同)