3.1 案例06:不使用相对引用标记2020年所有周日
在第2章的案例中,相对引用起到了至关重要的作用,但相对引用的概念并不好理解,使用起来也不够直观,频繁使用还可能导致意料之外的错误。因此,在制作VBA的宏时,往往使用Range对象来代替相对引用。
本案例要求,在图3-1所示的工作表中,不使用相对引用标记出2020年的所有周日。

图3-1 2020年全年日期的一部分
3.1.1 案例解析
下面简单介绍一下VBA中的Range对象。Range对象可用于指定某个单元格或某个单元格区域,如Range("a1")表示工作表的A1单元格,Range("a1:f100")表示工作表中A1至F100的单元格区域。
使用Range对象还可以向单元格或者单元格区域赋值,如代码清单3-1中的两行代码分别表示在A1单元格中写入数值1,以及在A1至F100区域内的所有单元格中写入数值1。
代码清单3-1
Range("a1") = 1
Range("a1:f100") = 1
小贴士: 在VBA代码中表示单元格时,可不区分大小写,如Range("a1")和Range("A1")都表示A1单元格。
如果在Range对象中使用变量,则可表示不确定的单元格和区域,如代码清单3-2所示。
代码清单3-2
Sub test()
a = "a"
b = 1
Range(a & b) = 1
End Sub
代码清单3-2中变量a的值为字符“A”,变量b的值为数字1,表达式“a & b”等价于字符串“A1”,因此,执行代码清单3-2可在A1单元格中写入数字1。注意,当变量a和b的值发生变化时,Range(a & b)指定的单元格也会发生改变。
在Range对象中直接使用单元格地址时,单元格地址作为常量,必须以文本类型显示,因此需要使用英文双引号,如Range("a1");在Range对象中使用变量时,变量不需要使用双引号,如Range(a & b),但变量之间必须使用连接符号“&”,并且连接符号“&”两边必须留有空格,Range(ab)和Range(a&b)都是错误写法。
VBA中的常量和变量还能混合使用,常量和变量之间同样需要使用连接符号“&”。例如表达式Range("a" & i),当i等于1时,表示A1单元格;当i等于2时,表示A2单元格。如果要在A1至A100单元格中依次写入1至100,则可通过代码清单3-3实现。
代码清单3-3
For i = 1 To 100
Range("a" & i) = i
Next
在代码清单3-3中,For循环的计数变量i依次等于1至100:当i = 1时,表示在A1单元格中写入数值1;当i = 2时,则会在A2单元格中写入数值2……
我们还可以在Range对象中插入计算式,如对代码清单3-3进行改动,将表达式Range("a" & i) = i改为Range("a" & i * 7) = i,即可实现每隔7个单元格赋值一次;若将表达式改为Range("a" & i) = i * 7,则表示在工作表的A列中依次写入7的倍数。
综合以上内容,则可尝试编写代码实现不使用相对引用标记出2020年的所有周日。在不使用相对引用的情况下,开始录制宏,选中图3-1中的A5单元格(2020年的第一个周日),并改变其填充色,停止录制,代码见代码清单3-4。
代码清单3-4
Sub 宏1()
Range("A5").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
代码清单3-4中的其他语句暂时不用理解,读者只需要理解代码“Range("A5").Select”表示选中A5单元格。我们将表达式Range("A5")替换为Range("a" & i),然后将代码清单3-4的主体部分嵌入For循环。因为代表2020年第一个周日的单元格为A5单元格,代表2020年最后一天的单元格为A366单元格,所以计数变量i的取值范围应设为5到366。For循环的步长(Step)应设为7,表示计数变量i在5和366之间每7个数取一次值。For循环代码见代码清单3-5。
代码清单3-5
For i = 5 To 366 Step 7
……
Next
3.1.2 案例代码
合并代码清单3-4和代码清单3-5,得到不使用相对引用的“标记”过程的代码,见代码清单3-6。
代码清单3-6
Sub 标记()
Dim i As Integer
For i = 5 To 366 Step 7
Range("a" & i).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Next
End Sub
执行代码清单3-6,所得结果如图3-2所示。

图3-2 不使用相对引用标记2020年所有周日(部分展示)
代码清单3-6中的For循环步长也可设置为1,此时需要将Range("a" & i)改为Range("a" & i * 7 − 2),将计数变量i的取值范围改为1到52(2020年共有52个周日),获得的代码执行效果一样。
3.1.3 案例小结
本案例介绍了Range对象,以及如何在Range对象中使用常量、变量和计算式等。
因为Range对象可用于指定单元格和单元格区域,所以在VBA中的使用频率相当高。在本书前半部分的案例中,大多数操作对象都是Range对象。本节仅简单介绍如何使用Range对象指定单元格,后续章节会详细介绍Range对象的其他内容。