我有一个用于存储 UDF 的 Excel 插件以及一个用于存储子程序的个人工作簿。
在插件内部,我有一个常数模块,其中有一个理想气体常数的条目:
Global Const r = 8.314 'Same result using Global or Public
可以从 Excel 插件和个人工作簿中的所有模块访问这个“全局”常量。
我的问题是,我希望能够将此变量的范围限制为仅插件的模块,而不限制其他打开的项目。否则,我需要在所有打开的项目中跟踪我声明为全局的变量。最终,我会像 NASA 一样,弄混我的单位……
提前感谢大家的帮助。
答案1
Global
是已过时的关键字;Global
和之间的唯一区别Public
在于您不能Global
在类模块中使用。Public
为了保持一致性,建议使用。
使用鲜为人知的Friend
访问修饰符使成员可在其声明的项目内的任何地方访问,但仅限于该项目内。
需要注意的是,它只能在类模块中使用,并且只能用于过程 - 您不能制作Friend Const
。
一种解决方法是利用隐藏的VB_PredeclaredId
类属性并将其设置为True
- 在记事本中创建一个新的文本文件,内容如下:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "StaticClass1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
使用扩展名保存文件.cls
,然后将其导入到您的项目中。
然后,您可以将其重命名为更有意义的名称,并公开一个Friend Property Get
成员:
Friend Property Get R() As Single
R = 8.314
End Property
现在您可以使用该值,但只能在包含此类的项目中使用。由于该PredeclaredId
属性,您不需要创建New
实例:
Debug.Print StaticClass1.R ' 8.314
遗憾的是(?)该VB_GlobalNamespace
属性在 VBA 用户类中不起作用,因此UserForm1.Show
需要合格对象(预声明的类实例与类模块本身具有相同的名称 - 这正是可以工作的方式)。
警告:在默认实例(尤其是在表单中)上存储实例状态(例如私有模块级变量)可能很诱人,但应尽可能避免。如果需要存储状态,请考虑使用
New
类的实例。有状态的默认实例更容易出现错误,特别是因为对象的生存期由 VBA 运行时管理,而不是由用户代码管理。如果回收/重新创建默认实例,则之前保存的任何状态都将重置为设计时默认值。
请注意,类模块私人的默认情况下,这已经使它们对其他引用项目不可见。您可以更改实例化类的属性来使其成为,这将改变 it属性PublicNotCreatable
的值以:VB_Exposed
True
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
公共类可以从项目外部访问,但不能直接用关键字创建New
(在 VBA 中更改属性的值VB_Creatable
无效)。使用公共/公开类,引用项目将能够调用Public
成员,但不能调用以下Friend
成员:
Public Property Get UseMeAnywhere() As Long
UseMeAnywhere = 42
End Property
Friend Property Get YouOnlySeeMeInThisProject() As Long
YouOnlySeeMeInThisProject = 42
End Property
答案2
解决方法是将 Option Private 语句添加到模块的声明部分。这将限制范围仅限于模块所在的项目,而不是任何打开的项目。下面包含来自 Microsoft Docs 的链接,具体说明如何执行此操作。
有关范围和可见性的更多信息,请参阅以下来自 Microsoft Docs 的链接:
编辑于 2019 年 4 月 22 日:删除了公共到全局变量标识符周围的部分,因为这并不能解决问题。