扫码关注 |
---|
![]() |
1. 写在前面
在往期文章 不怕一亿,就怕一分:让我们从小数位数说起 里,我们提到了在适当的时候要主要保留小数位数。在往期文章
如何在 Excel 功能区增加自定义的功能 里,我们创建了一个快捷使用 Round
公式的方法。其中有一段 VBA 代码,今天我们就来讲一讲这段代码,算是我们后续 VBA 之路的一个起点。
2. 原始代码
Sub cmdRound() Dim Rng As Range For Each Rng In Application.Selection If (IsNumeric(Rng)) And (Rng <> "") Then If Left(Rng.Formula, 1) = "=" Then Rng.Value = "=Round(" & Mid(Rng.Formula, 2) & ",2)" Else Rng.Value = Round(Rng.Value, 2) End If End If NextEnd Sub
3. 代码讲解
其实这段代码并不适合作为初学者的示例。按照编程界的惯例,都是先输出一个“Hello World!”作为开始的。而且里面没有具体单元格的引用,还用到了一大堆内置函数...
不过,这丝毫不影响我们开启学习之路!
3.1 子过程
第1行 Sub cmdRound()
定义了一个子过程,其中 cmdRound
是过程名称,自己怎么开心怎么定义(呃。。。其实也不是,是有命名规则的,不过现在可以不管,之后会专门留一篇来说名称的事)
VBA 程序包含子过程、函数过程和属性过程,其中子过程最常见。
上面的例子,是形式上最简单的子过程定义,这条语句,就叫过程声明语句。
整个代码的最后一行 End Sub
与过程声明语句对应,用来结束这个子过程。这个过程的全部代码都放在这两条语句之间。
VBA 中有很多语句都是这种有头有尾的形式。
3.2 定义变量
第2行 Dim Rng As Range
是变量定义语句。
变量代表了未知数,可以在代码运行过程中任意修改所代表的值。
在 VBA 中,变量包括数据变量、对象变量、数组变量。三种变量都是经常使用的。
例子中,我们定义的是一个对象变量。
Dim
是变量声明语句。Rng
是我们定义的变量名称。as
用来定义这个变量的数据类型。Range
用来指定这个变量的数据类型是Range
,实际上是个对象类型,代表单元格。
类似的,我们可以这样定义变量:
Dim i as Inteer ' 定义一个整型变量 iDim str as String ' 定义一个字符串变量 strDim x ' 定义一个没有指定数据类型的变量 x
3.3 循环语句
语句
For Each ... In ...
...Next
构成了一组循环语句。
在例子中的 For
语句是 For Each Rng In Application.Selection
,翻译成人话就是“对于选中的单元格中的每一个单元格”。
For Each a In b
就是说在b
中的每一个a
。Application.Selection
就是选中的单元格。其中Application
代表应用程序,也就是 Excel 软件;Selection
是Application
的一个属性,代表活动工作表上当前选定的对象(不一定是单元格)。.
这个符号代表一种从属关系,说明后者是前者的属性。Rng
就是我们自己定义的变量,前面说过变量类型是单元格。在这个语句中,就是把选中的单元格的每一个循环赋值给Rng
。
刚提到的什么“属性”什么的,大可不必纠结,之后会详谈。
For
语句的作用,实际上就是从一个集合中(这里是一堆选中的单元格)一个一个的拿出来,赋值给一个变量(这里是Rng
),然后让后面的语句去使用这个变量。
使用完之后,就到了 Next
语句。作用是告诉 For
语句,刚才的变量用完了,该给下一个了。于是乎,又开始从 For
语句开始。这就是一个循环。
在 VBA 中,循环语句还有其他几种,之后需要的时候我们再谈。
大家可能都听过高斯十岁的时候就快速计算出了从 1 加到 100的值。如果使用 VBA 该怎么计算呢?就是这样:
Sub 累加()Dim result as IntegerDim i as IntegerFor i = 1 To 100
result = result + iNext i
MsgBox resultEnd Sub
上面这段代码注意点主要包括:
过程名定义成“累加”,也就是说,过程名可以是中文。不过这只是举例,实际不建议使用中文。
For
语句不再是For Each
,这一句的意思就是说,从 1 到 100,逐渐让i
等于每一个值;定义的变量
result
等于自己加上i
,下次再循环的时候又把自己加上i
,通过这个循环,实现把 1 到 100 逐渐都加到result
中。语句
MsgBos
是个弹窗,把结果在弹窗中显示出来。
3.4 条件判断语句
我们经常在程序中需要判断,某个情况(如变量)是不是满足某个条件,如果满足,做什么,如果不满足,做什么。
条件判断语句主要是 IF
语句和 Select Case
语句。今天我们说 IF
语句。
IF
语句也有两种使用方式,一种是单行代码,一种是多行代码。显然我们更多用到的是多行代码。大概结构是:
IF Condition Then
[statements]
[Else
[elsestatements]]End IF
上面的 Condition
代表条件。在我们的例子中,第一次使用 IF
语句的条件是 (IsNumeric(Rng)) And (Rng <> "")
,意思是 Rng
是一个数字并且不是空值;第二次的条件是 Left(Rng.Formula, 1) = "="
,意思是 Rng
的属性 Formula
(代表单元格的公式内容)的第一个字符是 =
。如果条件成立,也就是说结果为真,就执行 statements
语句,否则如果 IF
语句中有 Else
则执行 elsestatements
语句,否则语句执行完毕。
例子中第一次使用 IF
语句的条件,是判断单元格的结果是不是一个数值,如果是数值,结果为真,才能做小数保留的计算。结果为真的语句是一个完整的 IF
语句,也就是第二次条件判断。后面就是 End IF
语句,也就是说,如果判断结果为假,不做处理,语句结束。
第二次使用 IF
语句的条件判断的内容是单元格的内容的第一个字符是不是等号。如果是等号,说明是公式,结果为真,否则说明单元格是一个数值,结果为假。
条件为真的语句是:Rng.Value = "=Round(" & Mid(Rng.Formula, 2) & ",2)"
我们从里往外说。
Rng.Formula
,前面说过,代表单元格的公式的内容,比如说可能是=SUM(A1:A6)
;Mid(Rng.Formula, 2)
,就是把这个公式内容从第二个字符开始截取到最后,就成了SUM(A1:A6)
;&
用来连接两个字符串,比如a
&b
就是ab
;现在上面的语句就相当于
Rng.Value = "=Round(SUM(A1:A6),2)"
;=
后面的部分"=Round(SUM(A1:A6),2)"
,双引号说明这是一个字符串,里面的部分,就是大家都熟悉的Round
公式了。也就是说,到现在为止,我们把单元格里原来的公式外面嵌套了一个Round
公式,保留了两位小数。=
前面的部分,是Rng.Value
,就是说单元格的值。我们把单元格的值改成了我们处理后的嵌套了Round
的公式,这样单元格还是使用公式计算,但结果已经是保留的两位小数的了。
条件为假的语句是:Rng.Value = Round(Rng.Value, 2)
条件为假,对比面前的分析,这个就很容易了,注意点是:
这次等号后面部分没有双引号,也就是说,结果不再是字符串,而是直接计算数值。
这里的
Round
和前面的Round
实际不是一个东西。前面的代表了 Excel 公式里的Round
公式。这里的Round
是 VBA 中的一个函数。
4. 总结
好了,整段代码讲解完毕。现在才发现确实不适合作为初学者的示例,因为写了这么长......不过,如果你能看到这里,恭喜你,你已经可以面对后续的学习了,因为这个起步就不是太简单。
往期
不怕一亿,就怕一分:让我们从小数位数说起
如何在 Excel 功能区增加自定义的功能
规划 Excel 表结构,让数据处理更方便
扫码关注 |
---|
![]() |