主要内容一览
本期主要包括以下几个方面的内容:
VBA中的数据类型
数据的储存
数据的运算
数据类型
Visual Basic有以下6种数据类型:
数值型(Numeric)、字符串型(String)、布尔型(Boolean)、日期型(Date)、对象型(Object)、变体型(Variant)
数值型(Numeric)
在VB中,用于保存数值的数据类型有Byte(字节型)、Integer(整型)、Long(长整型)、Single(单精度浮点型)、Double(双精度浮点型)和Currency(货币型)。如果变量总是存放整数,那么应将其声明为Byte型、Integer型或Long型,Byte用一个字节存储,不能表示负数,Integer型变量用2个字节(16位)存储,Long型变量用4个字节(32位存储)。如果变量包含小数,应声明为Single、Double或Currency型。Single变量用4个字节存储,Double和Currency型变量用8个字节存储,Currency型变量用于货币计算。
字符串型(String)
字符串型数据就是文本数据,当然文本数据不仅仅包括文字、字母,也包括文本型的数字。而文本型的数字与数值型的数字肯定是不一样的。
布尔型(Boolean)
Boolean型变量主要用来进行逻辑判断,其值只能为True(真)或False(假)。
Boolean型变量用两个字节存储,其默认值是False。如:
Dim blnRunning As Boolean
blnRunning = True
日期型(Date)
Date型变量表示日期和时间值,用8个字节存储,标准格式有三种:
– #月/日/年#,表示日期,如#3/6/1999#;
– #时:分:秒AM或PM#,表示时间,如#8:06:06AM#
– #月/日/年 时:分:秒AM或PM#,表示日期和时间,如#3/6/1999 8:06:06AM#
对象型(Object)
对象型(Object)数据就是对象变量,用来引用对象。对象型其实仅仅是一个全称,并不是dim i as object,而是dim i as range 或者 dim i as sheet等。
变体型(Variant)
Variant类型是一种特殊的数据类型,如果事先没有指定数据类型,那么变量的数据类型是Variant型。Variant型变量可在不同场合代表不同类型的数据。当指定变量为Variant型时,不必在数据类型之间进行转换,VBA会自动完成各种必要的转换。
作为初学者,我们一开始用得比较多的就是以下几种类型。
合理的声明变量的数据类型,有利于节省空间,提高代码的运行速度。
数据储存
在VBA中,主要使用常量和变量来储存数据。顾名思义,“变量”是会变的,即它的值是可以改变的;而常量,则它的值通常是固定不变的。变量和常量在任意一段代码中都可能被用到,他们作为应用程序最为基本的组成要素,必不可少。合理使用变量和常量有助于增加程序的可读性和可维护性。
1.常量
VBA中常量的类型有3种,分别是直接常量、符号常量和系统常量。
1) 直接常量。在VBA程序代码种直接书写的量,为直接常量,例如:
K=3.1415926
程序种的3.1415926就是直接常量。直接常量也有数据类型的区别,其数据类型有它本身所表示的数据形式决定。根据数据类型的不同,直接常量分为数值常量、字符串常量、日期/时间常量和布尔常量。
数值常量是由数字、小数点和正负号所构成的量。如3.1415926
字符串常量是由数字、英文字母和汉字等可见字符构成的,在使用时必须使用双引号作为定界符。例如:“这就是街舞!”
时间常量用来表示某一天或者某一具体时间,书写时使用“#”作为定界符。
布尔常量也就逻辑常量,只有两个值:true/false
2) 符号常量。如果在程序总需要反复地使用某一个常量,则可以为该常量命名,在需要使用该常量的地方引用其常量名即可。
使用符号常量由许多优点。
A. 快速修改程序。如果需要在程序种修改常量的具体值,只需要在定义符号常量的地方修改即可。
B. 减少出错率。如果反复在程序种输入同一数据,有可能在某处输入错误,导致计算结果不同,不好查错。使用符号常量则只需要定义一次就可以引用。
通常采用const语句来声明,声明时不仅要指定常量的名称及数据类型,还要在声明的同时给常量赋值,并且赋值后的常量不能在重新赋值。常量通常用来储存一些固定的、不会被修改的值,比如圆周率、税率等。
Const语句的基本结构是这样的:Const 常量名称 As 数据类型 = 数值
如:Const pi As Single = 3.14,Const语句了声明一个名称为pi的单精度浮点型的常量,值为3.14.
3) 系统常量。VBA系统内部提供了一系列各种不同用途的符号常量,称为系统常量。这些常量可与应用程序的对象、方法和属性一起使用,如vbYES,vbNO等等。
在VBA中,系统常量名采用大小写混合的格式,其前缀表示定义常数的对象库名。在excel中的系统常量名通常都是以小写的xl为前缀,如xlcelltype的成员包括xlcelltypeblanks等几个。
2.变量
在VBA执行应用程序的过程中,用变量临时存储数值,其内容随程序的执行而变化。可以把变量看作存放未知值的内存单元。
1) 变量的命名。变量的引用是通过变量名来进行的,因此在程序设计过程中,应该给相应的变量命名。VBA中的变量名不区分大小写,Mygod和mygod是指同一个变量。变量命名时最好采用一种易读、易理解的命名方式。通常用小写字母的前缀表示变量的类型,后面是首字母大写的代表变量含义的名称。例如:strNAME,表示字符串型变量用intAge等等。
2) 声明变量。声明变量就是实现将变量名数据类型通知VBA,由VBA为变量分配存储空间。常用Dim语句声明变量,
Dim语句的基本结构是这样的:Dim 变量名 As 数据类型
其中变量名必须以字母(或汉字)开头,不能包括空格、句号、感叹号、@、&、$和#,最长不超过255字符。尽管这样定义变量名称是完全可以的,但是建议大家在实际操作的过程中只用英文和数字来表示变量,这样看起来比较好一些。dim和as为声明关键字;数据类型是我们前面讲的类型关键字,如integer,string等等;中括号部分表示可以省略,即声明变量时也可以不指定变量的类型。
在声明多个变量时,可以写在同一个Dim后面,变量名之间用逗号隔开即可;当然,也可以写好几句Dim。
A. 隐式声明,在使用一个变量之前不声明变量,而是让VBA自动去识别赋值变量的类型。这种方法很容易出错,不好调试,不要用这种方法。建议还是在使用每个变量之前先声明。
B. 显式声明。为了避免隐式声明引起的麻烦,可以规定,只要遇到一个未声明的变量名,vba就发出警告。要显示声明,可以在模块、类模块的声明段加入如下语句。
Option Explicit
或者在工具-选项种勾选要求声明变量。这样如果你没有声明变量就会由提示,这样就出错了也比较好找。
3) 变量的作用范围。变量的作用范围就是指变量起作用的区域。在VBA中,每个工程项目都包含多个模块,模块又包含多个过程。变量作用范围主要可以分为3个等级。
A. 局部变量。在过程内声明的变量为局部变量,只有在声明它们的过程中才能被识别。用Dim或者Static关键字来声明它们,例如:
Dim sa as integer
Static ssa AS single
对任何临时计算来说,局部变量是最佳选择。例如,建立十几个不同的过程,每个过程都包含称作sa的变量,只要每个sa都声明为局部变量,那么每个过程只识别自己的sa版本,改变自己局部sa变量的值,将不会影响别的过程中的sa变量。
B. 模块变量。在模块顶部的声明段中用Dim或Prevate关键字声明模块级变量,建议private,这样比较好区分,模块级变量在该模块所有过程中都可用,但在其他模块中不可以引用。例如:
Previte sa as integer
C. 全局变量。为了使模块变量在其他模块中也有效,可用Public关键字声明变量,该变量可用于应用程序的所有过程。和所有模块变量一样,也在模块顶部的声明段中来声明全局变量(也称为公用变量)。例如:
Public sa as integer
在程序设计中,一般情况下尽量使用局部变量。如果要在同一模块的多个过程中共享某一值时,才能使用模块变量。对全局变量更应控制使用数量,除非需要在多个模块中共享变量值,否则尽量不要使用全局变量,以减少程序出错的概率。
4) 静态变量
变量除了具有作用范围之外,还有生存期,在生存期变量能够保持它的值。但对于局部变量,当一个过程执行完毕,其局部变量的值就已经不存在,变量所占据的内存也就被释放,当下一次执行该过程时,其局部变量将重新分配内存单元并进行初始化。
但将局部变量定义成静态的,就可以在退出过程时保留变量的值。在过程内部用Static关键字声明一个或多个变量,其用法和dim语句完全一样。
Static sa as integer
当过程执行结束时,静态变量的值将保留,在罅隙调用该过程时,该静态变量的初始值就是上次过程执行结束时被保留的值。当然,无论什么类型的变量,关闭相关工作簿后,其生存期都将结束。
5)给变量赋值
给变量赋值的意思是把数据储存到变量里,给变量赋值之后,当需要使用这个数据时,就可以直接使用变量名称来代替对应的数据,从而起到简化程序的效果。
在给字符串、数值、日期等数据类型的变量赋值时,可以直接使用 [Let] 变量名称 = 数据 的方法来进行赋值,其中Let可以省略,所以一般就直接采用 变量名称 = 数据的方法来赋值。此时,等于号也可以称之为赋值符号,其实在各种编程语言中,一般都采用等号来进行赋值。
i = 10 / 3
j = 10 / 3
s = 10 / 3
除了上面这样的直接赋值某一个数字的方法之外,还可以将一个变量的值赋值给另外一个变量,如 语句 i = j,就是将 j 变量的值赋值给 i 变量。
然而给对象变量(Object型,如单元格)赋值时,需要使用的语句为:
Set 变量名称 = 对象
其中,Set不可省略,这是需要特别注意的一点。关于对象变量的赋值,将在后续讲解到对象时进行举例。
3.数组
(1)数组的概念
数组这个词,在之前的更新中其实也提到过,但是和这里不太一样。在VBA中,数组其实也是一种变量,是同种类型的多个变量的集合,数组中的每个变量称为一个元素。
举例来说,一个单元格是一个类型为Range的变量,一张工作表就是一个包含多个单元格的数组变量,这张工作表中的每个单元格就是一个元素。其实集合和元素的概念是高中数学的内容,我相信大家还是能够理解的。
(2)声明数组
由于数组是一种特殊的变量,其实可以直接使用Dim语句来声明数组,只不过与声明单个变量还是略有差别。
在声明数组的时候,除了要指定数组的名称及数据类型,还要指定数组的大小。
声明数组采用的代码基本结构是这样的:
Dim 数组名(a to b)As 数据类型
其中,数组名的命名规则与变量名是一致的;a和b表示的是数组的起始和终止索引号,确定的数组中的元素的个数为(b-a+1)个。
如果省略a,而直接使用Dim 数组名(b)As 数据类型来定义一个数据变量,那么起始索引号就默认为0,数组中元素的个数为b+1个。
但是如果在代码的最前面写上“Option Base 1”的语句,那么起始的默认索引号就为1了,数组中元素的个数就是b个。
除了这种方法之外,还可以使用Array函数或者Range对象来创建数组。
在使用Array函数定义数组时,需要先定义一个Variant型的变量,其实就直接 Dim 变量名,就行了,然后将Array函数赋值给这个变量。如Array(1, 2, 3, 4, 5),这样定义出来的数组就有5个元素。
通过Range对象创造数组的方法可以将一个单元格区域内的值直接储存到数组中,只需要使用Range对象的Value属性将单元格区域的值直接赋值给变量名就可以了。这也会在介绍Range对象时,进行说明,敬请期待。
(3)给数组赋值
由于数组是一个集合,给一个集合赋值的方法,就是单独给集合中的每一个元素进行赋值。
那么就需要知道怎么去表示数组里的某一个元素,由于数组中的元素是按照次序储存在数组中的,通过索引号进行区分,因此在VBA中就可以使用 数组名(索引号)的方式来表示数组中的某个元素。
又由于每一个元素都是一个变量,知道怎么表示元素之后,就懂得了给元素赋值的方法(等号赋值),给每一个元素全部都赋值了之后,就完成了对数组的赋值。
(4)数组的维度
一般来说,我们经常接触到的是一维数组和二维数组。
一维数组的含义就是排成一行或者一列的多个同类型变量,比如引用了工作表中的一行或者一列,那么就构成了一个一维数组。
而二维数组就像是一个平面,一维数组是工作表中的一行或者一列,那么二维数组就是工作表中的多行多列所构成的一个数组。
前面提到了一维数组的声明方法,那么二维数组是怎么声明的呢?其实只需要多加个逗号,就行了。
Dim 数组名(a to b, c to d)As 数据类型
(5)与数组相关的函数
与数组相关的函数有很多,常用的主要有UBound函数和LBound函数,其中UBound函数计算的是数组某个维度上最大的索引号,LBound计算的是数组某个维度上最小的索引号。
这两个函数一般用于Range对象直接创建了数组之后,具体去数到底有多少行和多少列的时候来使用。
代码为:
UBound(数组名,1)、UBound(数组名,2)
LBound(数组名,1)、LBound(数组名,2)
其中1和2表示的是数组的第一个维度和第二个维度,如果仅对一维数组使用的话,可以省略后面的维度参数,而直接使用UBound(数组名)和LBound(数组名)。
(6)一个综合的举例
这个例子在附件的模块二中可以查看。
Option Explicit
Sub test2()
Dim arr(1 To 5) As String
arr(1) = "a"
arr(2) = "b"
arr(3) = "c"
arr(4) = "d"
arr(5) = "e"
'以上为一般的数组声明以及给数组赋值的方法
Debug.Print "arr(5)=" & arr(5)
Dim arr1, arr2
arr1 = Array(1, 2, 3, 4, 5)
arr2 = Sheet1.Range("A1:B8").Value
Debug.Print "arr1(1)=" & arr1(1), "arr2(2,4)=" & arr2(4, 2), "arr2是一个" & UBound(arr2, 1) & "行和"; UBound(arr2, 2) & "列的二维数组"
'此处定位了数组中的元素,同时计算了Range对象所直接创建的二维数组两个维度的上标,由于是单元格区域,第一个维度的上标就是行数,第二个维度的上标就是列数。
End Sub
运行结果是这样的:
数据运算
最后一部分的内容,让我们来聊一聊运算符。程序执行的过程就是对数据进行运算的过程,不同的数据类型可以进行不同的运算,按照数据运算类型的不同,VBA里的运算符主要分为算术运算符、比较运算符、连接运算符和逻辑运算符。
(1)算术运算符
算术运算符就是普通的数学中的那些运算,算术运算符用于算术运算,返回值的类型为数值型。
算术运算符包括+、-、*、/、\、^、Mod。
其中 \ 是整除运算符,返回的结果是两数相除取商的整数,如 5 \ 2 = 2;
Mod是求余数(求模)运算符,返回的结果是两数相除后的余数,如12Mod5 = 2。
(2)比较运算符
比较运算符用于比较运算,如比较两个数的大小,返回值的类型为布尔型,也就是True或者False。
常见的比较运算符有大于(>)、小于(=)、小于等于(<=)、不等于(<>)。
这几个运算符置于两个表达式之间,比如表达式1 = 表达式2,以此来判断比较运算符两边的表达式是否相等,如果相等,则返回True,如果不相等,则返回False。这部分是高中数学的知识。
除了这几个常见的之外,还有两个特殊的比较运算符:Is 和 Like。
Is 比较两个对象的引用变量是不是相同的对象,如果相同则返回True,语法为:对象1 Is 对象2。
Like 比较两个字符串是否匹配,如果匹配则返回True,语法为:字符串1 Like 字符串2。在Like运算中可以采用通配符,以此来判断某些字符串中是否包含某些关键字。
(3)连接运算符
连接运算符用来连接前后两部分的内容,有+和&两种。
由于+还可以用作算术运算符,在面临运算符一侧有数值的情况下,发挥的并不是连接的作用,因此建议要使用连接运算时,就用&符号来进行连接。
比如前面提到的数组部分的那个例子中,在debug.print语句中就使用了连接运算符&,将不同的部分连接在一起。
(4)逻辑运算符
逻辑运算符用于判断逻辑运算式的真假,返回的结果为布尔型数据,也就是True或False。
在VBA中,常见的逻辑运算符包括 与(And)、或(Or)、非(Not)三个,其他的逻辑运算符一般也用不到,如果有兴趣可以参考《别怕,Excel VBA其实很简单》一书77页的相关内容。
在VBA中,这三个逻辑运算符的基础语法为:表达式1 逻辑运算符 表达式2,如表达式1 And 表达式2。
与或非这三个词最早出现在高中数学书中,大家应该都有了解,这些表达式在什么情况下,会输出什么样的结果,大家也应该是心知肚明的。
此外,这三个关键字也是Excel中可以使用的函数,只不过使用方法与VBA中有所不同。在函数中,And、Or和Not是在最外层,而VBA中,是在中间使用,大家需要注意,别搞混了。
(5)运算的优先级
在数学中,我们会提及运算的优先级,在VBA中也是如此。
在VBA中,先处理算术运算符,再处理连接运算符,然后处理比较运算符,最后处理逻辑运算符。当然,括号是万能的,可以使用括号来改变运算顺序。
运算符按照优先级由高到低的次序排列为:括号 → 指数运算 → 求相反数 → 乘除 → 整除 → 求模 → 加减 → 连接运算 → 比较运算 → 逻辑运算。
最后给大家提一个运算符相关的问题,请大家计算下面这个表达式的结果:
200 > (3 * 50) + 60 Mod 3 ^ 2 And 10 ^ 2 \ 6 > 15