乐于分享
好东西不私藏

Excel VBA 编程基础 — 结构化数据类型(一)

Excel VBA 编程基础 — 结构化数据类型(一)

我们已经见识过 VBA 的基本数据类型,譬如数值类型、字符串类型、Boolean 类型等。虽然这些基本类型是必要的,还需要一些更高阶的类型来完成更复杂的任务。从今天开始我们来讨论 VBA 中的结构化数据类型。
结构化数据类型(structured data type),也称为复合数据类型(composite data type),是指由多个基本数据类型组成的类型。VBA 的结构化数据类型包括以下几种:
  • 用户自定义类型(UDT)
  • 数组(Array)
  • 集合(Collection)
  • 字典(Dictionary)
我们今天主要讨论用户自定义类型(User-Defined Type, UDT)。
VBA 提供了定义我们自己的类型的手段:Type … End Type 结构。
还是来看例子。
例1. 定义 Employee 类型
Type Employee  Id As Long  Name As String  Department As String  Title As String  Salary As Currency    ' 薪水用 Currency 表示  IsActive As BooleanEnd Type
这样,我们就用 Type … End Type 结构定义了一个雇员(Employee)类型。在这个类型中,表示雇员编号的 Id 是 Long 数值类型,姓名(Name)是字符串类型,部门(Department)也是字符串类型,为了保证精度,薪水用 Currency 类型表示(Currency 类型多用于财务方面),目前是否在职(IsActive)用 Boolean 类型表示。
由上可知,我们定义的 Employee 类型是由一些基本数据类型组成的复合类型。这样定义了 Employee 之后,Employee 就可以作为一个类型用于声明该类型的变量:
Dim ZhangSan As EmployeeDim LiSi As EmployeeWith ZhangSan  .Id =1001  .Name = "张三"  .Department = "采购部"  .Title = "采购员"  .Salary =8000  .IsActive =TrueEndWithWith LiSi  .Id =1010  .Name = "李四"  .Department = "技术部"  .Title = "研发工程师"  .Salary =12000  .IsActive =TrueEndWith
以上代码声明了两个变量,ZhangSan 和 LiSi,然后对这两个变量赋值。对这两个结构化数据类型变量的赋值中,我们使用了 With … End With 结构,这样就省去了每次都要写变量名的麻烦。
现在,可以对这两个变量进行各种操作。譬如,ZhangSan 调岗,从采购部调到市场部,头衔也从“采购员”变为“市场专员”,就可以用如下代码反映现实中的员工调动:
ZhangSan.Department = "市场部"ZhangSan.Title = "市场专员"
又譬如,LiSi 升职了,从研发工程师升职为技术部副经理,相应地,薪水也跟着上调,就可以用如下代码修改 LiSi 的相关属性:
With LiSi  .Title = "技术部副经理'  .Salary = 15000End With
我们可以用下面的代码来显示 LiSi 的情况:
With LiSi  Debug.Print .Name & ",职位:" & .Title & ",薪水:" & .SalaryEndWith
如果 LiSi 离职了,可以通过以下代码来表示:
LiSi.IsActive = False
用户自定义类型的变量可以进行整体赋值,如下面代码所示:
Dim Wang As EmployeeWang = LiSi  ' UDT 变量可以进行整体赋值' 修改 Wang 的属性With Wang  .Id = LiSi.Id +1  .Name = "王老五"  .Title = "技术部经理"  .Salary =22000EndWith
如果 UDT 是一个有着很多项目的复杂数据类型,整体赋值可以减少很多重复性的赋值操作。
例2. 用 UDT 表示工作表记录
对于下面的工作表数据集(假设是一个学生数学成绩单):
图1 学生数学成绩单
我们可以定义一个 UDT 来表示每一行的记录:
Type MathScoreid As Long  name As String  email As String  age As Integer  score As DoubleEnd Type
获取成绩单数据:
Dim mscore As MathScoreDim rowAsIntegerrow=2数据从第二行开始With mscore  .id = CLng(Cells(row, 1).Value)  .name = Cells(row, 2).Value  .email = Cells(row, 3).Value  .age = CInt(Cells(row, 4).Value)  .score = CDbl(Cells(row, 5).Value)End WithDebug.Print mscore.name & ", " & mscore.score
在获取成绩单数据的过程中,我们使用了显式类型转换(CLng,CInt,CDbl)将单元格的值转换为对应属性的类型。依靠 VBA 的隐式类型转换也可以完成赋值,但显式类型转换可以明确表达我们的意图,所以应该尽量使用显式类型转换。
我们这里只是获取了第一行数据,构造了第一个 UDT 变量。获取整个数据集需要数组的概念,这是下一篇文章的内容。