变量

范围

可以声明变量(增加可见性级别):

  • 在程序级别,在任何程序中使用 Dim 关键字; 一个局部变量
  • 在模块级别,在任何类型的模块中使用 Private 关键字; 一个私人领域
  • 在实例级别,在任何类型的类模块中使用 Friend 关键字; 一个朋友的领域
  • 在实例级别,在任何类型的类模块中使用 Public 关键字; 一个公共领域
  • 在全局范围内,在标准模块中使用 Public 关键字 ; 一个全局变量

应始终使用尽可能小的范围声明变量:首选将参数传递给过程,而不是声明全局变量。

有关更多信息,请参阅访问修饰符

局部变量

使用 Dim 关键字声明一个局部变量

Dim identifierName [As Type][, identifierName [As Type], ...]

声明语法的 [As Type] 部分是可选的。指定时,它设置变量的数据类型,该类型确定将为该变量分配多少内存。这声明了一个 String 变量:

Dim identifierName As String

如果未指定类型,则类型隐式为 Variant

Dim identifierName 'As Variant is implicit

VBA 语法还支持在单个语句中声明多个变量:

Dim someString As String, someVariant, someValue As Long

请注意,必须为每个变量指定 [As Type](除了’Variant’之外)。这是一个相对常见的陷阱:

Dim integer1, integer2, integer3 As Integer 'Only integer3 is an Integer. 
                                            'The rest are Variant.

静态变量

局部变量也可以是 Static。在 VBA 中,Static 关键字用于使变量记住它具有的值,上次调用过程时:

Private Sub DoSomething()
    Static values As Collection
    If values Is Nothing Then
        Set values = New Collection
        values.Add "foo"
        values.Add "bar"
    End If
    DoSomethingElse values
End Sub

这里的 values 系列被声明为 Static local; 因为它是一个对象变量,它被初始化为 Nothing。声明后面的条件验证对象引用之前是否为 Set - 如果它是第一次运行该过程,则集合将被初始化。DoSomethingElse 可能正在添加或删除项目,并且下次调用 DoSomething 时它们仍然会在集合中。

替代

VBA 的 Static 关键字很容易被误解 - 特别是经常使用其他语言的经验丰富的程序员。在许多语言中,static 用于使类成员(字段,属性,方法,…)属于类型而不是实例static 上下文中的代码不能引用实例上下文中的代码。VBA Static 关键字意味着完全不同的东西。

通常,Static 本地也可以作为 Private,模块级变量(字段)实现 - 但是这挑战了应该以尽可能小的范围声明变量的原则; 相信你的直觉,使用你喜欢的任何一个 - 两者都会起作用……但是使用 Static 而不了解它的作用可能会导致有趣的错误。

昏暗与私人

Dim 关键字在程序和模块级别是合法的; 它在模块级别的使用等同于使用 Private 关键字:

Option Explicit
Dim privateField1 As Long 'same as Private privateField2 as Long
Private privateField2 As Long 'same as Dim privateField2 as Long

Private 关键字仅在模块级别合法; 这邀请保留 Dim 用于局部变量并使用 Private 声明模块变量,特别是使用对比的 Public 关键字,无论如何必须使用它来声明公共成员。或者在任何地方使用 Dim - 重要的是一致性

私人领域

  • 使用 Private 声明模块级变量。
  • 使用 Dim 声明一个局部变量。
  • 请勿使用 Dim 声明模块级变量。

无处不在

  • 使用 Dim 声明任何私人/本地。
  • 请勿使用 Private 声明模块级变量。
  • 避免声明 Public 字段。*

*一般来说,无论如何都应该避免宣称 PublicGlobal 字段。

字段

在模块级别的声明部分中,在模块级别声明的变量是一个字段。在标准模块中声明的 Public 字段是全局变量

Public PublicField As Long

可以从任何地方访问具有全局范围的变量,包括将引用其声明的项目的其他 VBA 项目。

要创建变量 global / public,但仅在项目中可见,请使用 Friend 修饰符:

Friend FriendField As Long

这在加载项中尤其有用,其中的意图是其他 VBA 项目引用加载项项目并且可以使用公共 API。

Friend FriendField As Long 'public within the project, aka for "friend" code
Public PublicField As Long 'public within and beyond the project

朋友字段在标准模块中不可用。

实例字段

在模块级声明的变量,在声明部分在一个类模块的主体的顶部(包括 ThisWorkbookThisDocumentWorksheetUserForm类模块 ),是一个实例字段 :只要有一个它只存在实例的上课。

'> Class1
Option Explicit
Public PublicField As Long
'> Module1
Option Explicit
Public Sub DoSomething()
    'Class1.PublicField means nothing here
    With New Class1
        .PublicField = 42
    End With
    'Class1.PublicField means nothing here
End Sub

封装字段

实例数据通常保留为 Private,并且被称为封装。可以使用 Property 程序公开私有字段。要公开公开私有变量而不给调用者提供写访问权,类模块(或标准模块)实现了 Property Get 成员:

Option Explicit
Private encapsulated As Long

Public Property Get SomeValue() As Long
    SomeValue = encapsulated
End Property

Public Sub DoSomething()
    encapsulated = 42
End Sub

类本身可以修改封装的值,但调用代码只能访问 Public 成员(如果调用者在同一个项目中,则访问 Friend 成员)。

允许调用者修改:

  • 一个封装的,一个模块暴露了 Property Let 成员。
  • 封装对象引用,模块公开 Property Set 成员。