VBA 变量作用域

变量的作用域:指能够访问变量的位置范围,离开该位置范围则不能访问。

变量根据作用域分为:局部变量、模块变量、全局变量。

变量根据作用域分 说明
局部变量 只能在过程中访问
模块变量 只能在当前模块中访问
全局变量 允许在任意位置访问

1 局部变量

过程内部声明的变量为局部变量。只能在过程中访问。

Sub sub1()
  'i1在过程内部声明,为局部变量。只允许在sub1过程中访问。
  Dim i1 As Integer
  i1 = 2023
  Debug.Print "i1:" & i1
End Sub

Sub sub2()
  'sub2过程中无法访问sub1过程中声明的局部变量
  Debug.Print "i1:" & i1
End Sub

运行sub1输出结果:

i1:2023

运行sub2输出结果:

i1:

过程sub2会把变量i1当作未声明直接使用的新的变量处理,所有输出空内容,也没有报错。


2 模块变量

在模块的最上方直接声明的变量为模块变量。模块变量在过程的外面。

模块变量声明:

Dim 变量名 As 数据类型

或者

Private 变量名 As 数据类型

两者作用相同。

示例如下。

'i2声明在模块代码的最上方,为模块级变量
Dim i2 As Integer

Sub sub3()
  i2 = 200
  Debug.Print "i2:" & i2
  i2 = i2 + 100
End Sub

Sub sub4()
  Debug.Print "i2:" & i2
End Sub

首先运行sub3过程,输出结果如下:

i2:200

然后运行sub4过程,输出结果如下:

i2:300

sub3中将i2加了100,sub4中访问到此结果,说明两个过程中访问的是同一个变量。


3 Excel的模块类型

Excel的模块类型:Excel对象模块、标准模块。还有其它类型,后续介绍。

VBA 模块类型

Excel对象模块:针对每个工作表默认会有一个对象。

标准模块:由用户自己新建,如图中[模块]文件夹。


我们前面的编码都是在Excel对象模块中。接下来我们新建标准模块。

菜单右键,选中[插入]—[模块]。

VBA 模块类型

下方的属性窗口修改模块名称为[ModuleA]。

VBA 模块类型

模块ModuleA添加如下代码。

Sub sub5()
  '输出结果为空,说明无法访问Excel对象中的模块变量。
  Debug.Print "i2类型:" & TypeName(i2)
  Debug.Print "i2:" & i2
End Sub

TypeName(变量):返回变量数据类型,如果认为变量不存在,则返回Empty。

输出结果为:

i2类型:Empty
i2:

4 全部变量

在标准模块声明的public变量为全局变量。

全局变量声明语法

public 变量名 As 数据类型

新建标准模块ModuleB与ModuleC。

ModuleB中编码如下:

'通过public声明全局变量
Public GlobalI1 As Integer

Sub sub6()
  GlobalI1 = 2023
  Debug.Print "GlobalI1:" & GlobalI1
  GlobalI1 = GlobalI1 + 1
End Sub

ModuleC中编码如下:

Sub sub7()
  Debug.Print "GlobalI1:" & GlobalI1
  Debug.Print "TypName(GlobalI1):" & TypeName(GlobalI1)
End Sub

运行ModuleB中的sub6过程,输出结果如下:

GlobalI1:2023

继续运行ModuleC中的sub7过程,输出结果如下:

GlobalI1:2024
TypName(GlobalI1):Integer

输出结果表示:不同模块都能够访问全局变量。


注意事项

当过程sub6执行完毕后,其值依然存在,sub7还能够继续访问。这属于static型变量的特性。