Excel VBA 编程基础 — VBA 简介(六)
前文我们说过,VBA 代码中的变量既可以声明,也能够不声明就可以用。譬如下图中的代码:
这似乎不是我们的 MyFirstCode 代码所期望的结果,为什么会这样?
上图红框中的内容,本来应该是 name 和 age,因为输入时发生打字错误(typo),name 打成了 namw,age 打成了 ahe。因为 namw 没有声明,因此默认为变体类型,又因为没有经过初始化,因此其值为空(Empty),又因为 & 操作符要求操作数是字符串类型,因此 namw 也是以字符串类型(其值为空)参与 & 操作。再看子表达式 (ahe + 1),因为 ahe 没有经过声明,所以默认为变体类型,又因为 + 是算术运算符,要求两边的操作数必须是数值型,因此 ahe 以数值型参与 + 运算,但 ahe 没有经过初始化,未初始化的数值型变量其值为 0,因此子表达式 (ahe + 1) 的结果是 1。
VBA 中的变量不经过声明即可以使用,初看似乎很方便,但从上面的例子可以看出,这种不强制变量类型声明的做法,造成的麻烦比提供的方便更多!
这行代码告诉 VBA,代码中使用到的所有变量都必须要有类型声明。在图1 的代码中加入这行代码,然后再运行,则会报告错误,如图4:
因为前面有了 Option Explicit,因此 VBA 编译器捕捉到 namw 这个变量没有声明,因此报告错误:在编译期间,发现 namw 变量没有定义。对于后面的 ahe,也会报告同样的错误信息。
这里你有没有发现一个问题:我们没有声明 namw 变量,但 VBA 给出的错误信息是“变量未定义”!
一般来说,在编程语言中,变量的声明(declaration)和定义(definition)是不同的:
-
-
变量定义:编译器为变量分配存储空间,或许会对该存储空间进行初始化。
声明用来告知编译器:我叫什么,属于什么类型。编译器据此登记该变量的信息。此时,该变量并不存在。
定义用来告知编译器:在内存中给我分配一块空间,或许还会对这块存储空间进行初始化。此时,该变量已经存在。
编译器在编译这个语句时,知道这个变量名为 x,属于 16 位整数类型,在内存中占有 2 个字节的空间,并初始化为 0。
为了验证以上结论,让我们改正图4 代码中的两处错误,然后点击“视图” => “本地窗口”打开本地窗口,如图5:
现在,点击代码窗口,使光标位于 Sub MyFirstCode() 过程之内。然后按下 F8,如图6:
此时,当前的执行位置(箭头所指)位于 Sub MyFirstCode(),这说明代码完成了编译,即将执行。此时的本地窗口中所显示的 name、age、info 都是经过编译后的状态:这三个变量都有名字、类型、值,说明这三个变量都已有定义。
这样一条类型声明语句,不仅使得 name 这个变量有了名字和类型,而且被初始化为空字符串(长度为零的字符串)。其他两个变量以此类推。
这说明 Dim 语句将变量的类型声明和定义合二为一了。
因此,在有 Option Explicit 的情况下,对于未经声明的变量,VBA 编译器会报告“变量未定义”的错误信息:变量 namw 未经 Dim 声明,不仅没有类型信息,也没有定义(没有内存空间),不存在。
在上面的例子中,我们是在代码窗口的最顶端手动添加了一行 Option Explicit。每次手动添加毕竟很麻烦,VBE 提供了一个一劳永逸的解决方案:设置配置项。点击 VBE 的“工具” => “选项……”,弹出“选项”对话框,如图7:
选中这个配置项之后,每次我们插入新的模块,VBE 都会自动在顶端添加 Option Explicit 语句。
有了 Option Explicit 语句,VBA 就会强制我们要对变量进行类型声明。如果忘了声明某个变量或者如上面的代码那样,在写代码的时候发生了打字错误,把 name 变量写成了 namw,VBA 在编译时就会发现这种错误。这样一来,VBA 编译器就帮我们减少了很多发生错误的机会。