在VBA中使用预先声明的类作为名称空间

Jon*_*aen 6 excel vba

我在VBA中进行编码的最大问题之一是完全缺乏名称空间,这使得在同一个名称的每个函数都位于全局命名空间中时,很难确保诸如范围界定和选择正确的函数之类的事情。我知道您可以在函数调用之前添加模块名称,但在我看来,也可以通过将所有模块替换为预先声明的类来实现。名称空间看起来像这样:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "MyNamespace"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'@Folder("Project.Namespace")
Option Explicit

Public Function Foo() As String
    Foo = "bar"
End Function

' Opionally make sure users do not use this as a class
Private Sub Class_Initialize()
    If Not Me Is MyNamespace Then
        Err.Raise 512, _
            Source:="MyNamespace.Initialize", _
            Description:="Cannot create an instance of a namespace."
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

因此,如果您想Foo在此命名空间中调用,则必须编写

MyNamespace.Foo()
Run Code Online (Sandbox Code Playgroud)

虽然简单地打电话是Foo()行不通的。

我的问题是这样的:

有什么理由不想这样做吗?据我所知,仅在打开项目后第一次调用类的构造函数时才调用该类的构造函数,因此我看不到那里的任何开销,但可能有一些我不知道的偷偷摸摸的事情。当然,这绝不是解决这种功能缺失的理想方法,但这并不是好像VBA程序员尚未以round回的方式使用该语言来提供功能缺失。

另外,我看到这基本上与问题相同,但是我还想知道在代码中拥有大量预先声明的“空”类是否存在任何特定问题。假设您用100个预声明的类替换了100个模块,这会对性能/稳定性/等产生重大影响吗?

Mat*_*don 5

它花费了你一个对象指针,仅此而已。但我不会将其称为命名空间

UserForm您使用过的每个模块都有一个VB_PredeclaredId属性设置为True。正如您所注意到的,这个实例是自动创建的,虽然您可以显式地销毁它,但下次引用它时,它将再次自动(默默地)重新创建......无论原始状态是/曾经是......漂亮很像自动实例化的对象,也称为As New声明。

因此,您所拥有的更像是对象层次结构,而不是命名空间结构 - 非常非常类似于如何从 开始深入了解 Excel 对象模型Application,然后执行以下操作:

Set someCell = Excel.Application.Workbooks(1).Worksheets(1).Range("A1")
Run Code Online (Sandbox Code Playgroud)

这里的“命名空间”是Excel库,Application是根对象,该表达式的其余部分是所有成员访问 - 属性获取器,以类命名。

但这些类不在“命名空间”中...Worksheets集合类型(类)独立存在于库下Excel:类Worksheets上的属性Application不会以任何方式、形状或形式屏蔽该类“名称冲突”:如果您的用户代码有一个名为的类模块Worksheets(而且它很好可以),那么根据 VBA 解析标识符引用的方式,Dim foo As Worksheet将是自定义类的一个实例:唯一有效的限定符是库名称(Excel、 或MyVBAProject)。

因此,您拥有的是构建相对复杂的对象模型结构的合理方法 - 但它不会(不能)替换或模拟名称空间。如果您发现自己在创建“空”类,请重新考虑您的设计。

至于最后一个问题,我不明白拥有 100 个预先声明的自定义对象与具有 100 个用户表单的项目有什么不同:在这两种情况下,我想知道是否有一种方法可以减少并概括/重用组件,无论它们是表单还是类。

您想要避免的是一个保存状态的预先声明的对象 - 因为该状态现在实际上是全局的,并且您无法控制什么会改变该状态,何时何地:Application.Calculation就是一个很好的例子。

  • @JonasGlesaaen我不认为我们对“空”有相同的定义=)...如果你的类有属性和方法,那么它是合法的(经验法则) (2认同)