控制语句
第十篇、VBA核心控制语句(一):条件判断和循环
接上一篇:操控顶级对象Application(Excel应用程序本身)。①通过改变获取到的Excel属性和状态值,达到控制Excel显示和行为的目的;②和用户的交互;③调用内置函数、高效执行特定的计算;④Application级别的事件所能完成工作,是我们通篇介绍的概括。
至此,对Excel_VBA的核心对象(第6至9篇)这些个枯燥知识的学习,已经完成了100%。
对于VBA知识的学习过程,每个人的学习路径多多少少会有不同,有的从宏录制开始、有的从认识变量和对象开始、有从基础语法开始、还有的“有基础编程知识”、了解VBA这种语言类型后就立刻能上手的,毕竟编程的底层逻辑和通用概念是相通的。但完整的知识点,都逃不脱对VBA特有的对象模型(Excel的Range、Sheet、Workbook)特点的熟练掌握,认识对象枯燥但不可或缺!
对Excel_VBA可操控的关键对象学习后,能不能用代码操控它们完成对数据的自动化整理工作呢?答案是:可以!这时你可以自动化操作的内容包括但不限于:选取工作簿、打开工作簿、从工作表取值、单元格计算、数据汇总等等。
但是想想觉得现在能做的,觉得又缺少点什么?是程序没有思考、不会判断、没有逻辑!如果遇到有选择性获取分析结果时该怎么办?或者说是遇到了情况A就想让它这样执行、遇到了情况B就让它那样执行,这样该如何处理?
好比微信支付输入了支付密码,如果密码错误了就提醒并清空密码重新输入,如果输入正确但余额不足会提醒是否更改银行卡,如果6位数密码只输入5位一直停留在当前页面啥也不做!
这就相当于给了程序一个控制,运行时按照某项条件,指引它应该往某个方向去执行!
任何的编程语言也都离不开控制语句(流程控制),基础编程概念如变量、循环、条件语句这些,在编程语言中几乎是相通用的。VBA作为一种程序语言也不例外,它核心控制语句包括:条件判断、循环执行、错误处理、程序跳转。循环执行我们在第三篇🔗3、了解基础编程知识:循环和第四篇🔗4、其他循环结构>已经做了详细的阐述和示例,也就不再重复。
接下来的两个篇幅认识条件判断和错误处理及程序跳转,它们相对于“对象类型”就显得不那么繁杂,但是应用更加的灵活,各种嵌套应用组合在一起能产生巨大的能量。
对于编程知识零基础的人,接下来的内容建议阅读和练习同步,手敲代码的同时也思考有无其它方法完成同样的结果!通过VBA学习到的编程基础、逻辑思维和调试经验,如果以后有机会接触其他编程语言,也会有帮助。
本篇视频:
|01 条件判断语句
条件控制语句主要用于根据不同的条件执行不同的代码分支,核心结构包括If...Then...Else和Select Case,它们理解起来并不复杂。
1-1 If...Then...Else: 用于单条件或多条件判断,支持嵌套和分支扩展
它理解起来较为简单,if如果满足条件Then就执行代码块1Else否则执行代码块2,
语句有三种使用方式,适用不同的场景。
示例:
背景:
- 小学五年级的期末考试,依据语文、数学、英语的成绩和课堂纪律来选择“单科优秀奖”“和“学习小状元奖”;
- 依据三科的平均分值对每个学生做综合评价“优秀、良好、需要加油、努力赶上”。
条件:
- “单科优秀奖”评价条件:“语文成绩≥90、数学成绩≥95、英语成≥93”;
- “学习小状元“评价条件:课堂纪律是“好”且平均分高于80分,其他的需要平均分高于85分;
- 综合评价:平均分≥90“优秀”,≥75“良好”,≥60“需要加油”,不及格“努力赶上”。
需求:
- 将“单科优秀奖”的人员名单和单科成绩,复到一个新的工作表中;
- 将“学习小状元“的人员名单和各课成绩,复制到一个新工作表中内,增加平均值列;
- 在原本中,增加一列”综合评价“,把评价结果填写到对应的行。
样式:
代码:
Sub 期末成绩分析()
'评价期末成绩,列出“单科优秀奖”和“学习小状元”人员名单,按照平均分对学生评价
'声明五个变量
Dim name_max As Long '存储原表行数
Dim name_i As Long '存储循环值
Dim yw_index As Long '存储符合条件的语文成绩数
Dim sx_index As Long
Dim yy_index As Long
Dim pj_index As Long
name_max = ThisWorkbook.Worksheets("五一班期末成绩").UsedRange.Rows.Count() '成绩表末行的行数
'先增加一个新表,重命名为“单科优秀奖”
Dim new_sheet As Worksheet
Set new_sheet = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
new_sheet.Name = "单科优秀奖"
'重复执行一次,新表命名为“”
Set new_sheet = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
new_sheet.Name = "学习小状元"
'新表中增加标题字段
Worksheets("单科优秀奖").Range("A1").Value = "姓名" '单个单元格赋值
Worksheets("单科优秀奖").Range("B1").Value = "语文优秀"
Worksheets("单科优秀奖").Range("D1:E1") = Array("姓名", "数学优秀") '数组方法赋值
Worksheets("单科优秀奖").Range("G1:H1") = Array("姓名", "英语优秀")
Worksheets("学习小状元").Range("A1:F1") = Array("姓名", "语文", "数学", "英语", "课堂表现", "平均分")
yw_index = 2 '目标表都是从第二行开始填写内容
sx_index = 2
yy_index = 2
pj_index = 2
'循环学生成绩
For name_i = 2 To name_max
'单科优秀奖-----------------------------------------------------------------------------------------------------
'简单条件的用法
If Worksheets("五一班期末成绩").Cells(name_i, 2).Value >= 90 Then '如果满足条件,即成绩大于等于90分时,执行语句
Worksheets("单科优秀奖").Cells(yw_index, 1).Value = Worksheets("五一班期末成绩").Cells(name_i, 1).Value '原表的“姓名”,赋值到目标表的目标单元格,和copy功能相仿
Worksheets("单科优秀奖").Cells(yw_index, 2).Value = Worksheets("五一班期末成绩").Cells(name_i, 2).Value '接着是成绩
yw_index = yw_index + 1 '每符合一次,存储的变量值增加1
Else '不满足条件时执行的语句, 注意Else有无均可,没有就表示“如果没有符合条件的值,则什么也不做”
Worksheets("五一班期末成绩").Cells(name_i, 2).Interior.Color = RGB(155, 155, 155)
End If 'end if结束判断
'第二个是数学成绩,换一个用copy的方法
If Worksheets("五一班期末成绩").Cells(name_i, 3).Value >= 95 Then
Worksheets("五一班期末成绩").Cells(name_i, 1).Copy Destination:=Worksheets("单科优秀奖").Cells(sx_index, 4)
Worksheets("五一班期末成绩").Cells(name_i, 3).Copy Destination:=Worksheets("单科优秀奖").Cells(sx_index, 5)
sx_index = sx_index + 1 '每符合一次,存储的变量值增加1
End If
'第三个是英语成绩
If Worksheets("五一班期末成绩").Cells(name_i, 4).Value >= 93 Then
Worksheets("五一班期末成绩").Cells(name_i, 1).Copy Destination:=Worksheets("单科优秀奖").Cells(yy_index, 7)
Worksheets("五一班期末成绩").Cells(name_i, 4).Copy Destination:=Worksheets("单科优秀奖").Cells(yy_index, 8)
yy_index = yy_index + 1 '每符合一次,存储的变量值增加1
End If
'学习小状元-----------------------------------------------------------------------------------------------------
'嵌套条件的用法
If Worksheets("五一班期末成绩").Cells(name_i, 5).Value = "好" Then '满足条件1
If Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i)) >= 80 Then '满足条件2
Worksheets("五一班期末成绩").Range("A" & name_i & ":E" & name_i).Copy Destination:=Worksheets("学习小状元").Cells(pj_index, 1) '区域单元格的复制和粘贴,只需选择目标单元格区域的首个单元格位置就可以
Worksheets("学习小状元").Cells(pj_index, 6) = Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i))
pj_index = pj_index + 1
End If
Else
If Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i)) >= 85 Then
Worksheets("五一班期末成绩").Range("A" & name_i & ":E" & name_i).Copy Destination:=Worksheets("学习小状元").Cells(pj_index, 1)
Worksheets("学习小状元").Cells(pj_index, 6) = Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i))
pj_index = pj_index + 1
End If
End If
'综合评价-----------------------------------------------------------------------------------------------------
'多个分支(ElseIf)
If Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i)) >= 90 Then '分支1
Worksheets("五一班期末成绩").Cells(name_i, 6).Value = "优秀"
ElseIf Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i)) >= 75 Then '分支2
Worksheets("五一班期末成绩").Cells(name_i, 6).Value = "良好"
ElseIf Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i)) >= 60 Then '分支2
Worksheets("五一班期末成绩").Cells(name_i, 6).Value = "需要加油"
Else '最后一个分支
Worksheets("五一班期末成绩").Cells(name_i, 6).Value = "努力赶上"
End If
Next name_i
Worksheets("五一班期末成绩").Cells(1, 6).Value = "综合评价" '增加一个表头
End Sub
- ※:核心的条件判断代码存for...next循环中,三个条件判断语句适用的场景有差异,相互之间却也可以按照需求任意嵌套使用,你用有无、我中也可以有你,一切都为了满足逻辑实现!
- ※:其他的代码行:定义变量、控制工作表对象新增、单元格对象复制和赋值等等我们都已了解过。其实有些用代码实现时繁琐的地方,手动操作也是可以的,比如新建工作表、重命名和标题行赋值的部分,不用代码而用手动操作会更快捷!
1-2 Select Case: 多分支选择结构,简化多重条件判断
和If Then...ElseIf Then...ElseIf Then*...适用于多分支类似,Select Case也同样适用于多分支选择,它常用来替代复杂的if...Elseif链,代码更简洁易读。
基本语法
Select Case 测试表达式
Case 值1
' 匹配值1时执行
Case 值2, 值3
' 匹配值2或值3时执行
Case 值4 To 值5
' 值在值4到值5范围内时执行
Case Is > 值6
' 值大于值6时执行
Case Else
' 默认情况
End Select
示例:
- 仍以小学五年级的期末考试的综合评价为例,看Select Case的使用
Sub 综合评价_Select_case()
Dim name_max As Long '存储原表行数
Dim name_i As Long '存储循环值
Dim pj_index As Long
name_max = ThisWorkbook.Worksheets("五一班期末成绩").UsedRange.Rows.Count() '成绩表末行的行数
For name_i = 2 To name_max
'select case 替代 if...elseif,更简洁易读
Select Case Application.WorksheetFunction.Average(Worksheets("五一班期末成绩").Range("B" & name_i & ":D" & name_i))
Case Is >= 90
Worksheets("五一班期末成绩").Cells(name_i, 7).Value = "优秀"
Case 75 To 90
Worksheets("五一班期末成绩").Cells(name_i, 7).Value = "良好"
Case Is >= 60
Worksheets("五一班期末成绩").Cells(name_i, 7).Value = "需要加油"
Case Else
Worksheets("五一班期末成绩").Cells(name_i, 7).Value = "努力赶上"
End Select
'select case 多值匹配
Select Case Worksheets("五一班期末成绩").Cells(name_i, 1).Value
Case "张雅婷", "杨文嘉"
Worksheets("五一班期末成绩").Cells(name_i, 1).Interior.Color = RGB(155, 155, 155)
End Select
Next name_i
Worksheets("五一班期末成绩").Cells(1, 7).Value = "综合评价_select方法" '增加一个表头
End Sub
既然If...ElseIf和Select Case的使用场景类型,可以相互替代,但是要知道,同一个程序语言中不会创造出来两个不同的语句实现共一个功能,它俩之间肯定是有差别的。
- ※:If...ElseIf和Select Case,条件都会按顺序判断,一旦满足某个条件,后续条件不再执行
- ※:Select Case 的局限性,它只能针对单个表达式进行判断,如Case x>10,不能支持多个组合的条件,如x>10 and y>20,这时就不能用它了,需要用if语句。
- ※:Select Case的优势在于它的简洁性,让代码变得更易读。一般如果是超过3层的if嵌套(深层嵌套),可以改用Select Case或拆分逻辑!
- ※:Select Case的优势还在于它的更灵活的条件匹配:范围匹配(case 10 to 20),比较运算符(case is >90)、多值匹配(case “张”,“王”)
下一篇:VBA核心控制语句二:错误处理和程序跳转
条件判断和循环的套用,让程序执行变得不在是从第一句一行行执行到最后一句,而是随着条件的不同有取舍的执行,代码显得高效和富有逻辑些!
想想日常工作,是每件事情一旦开始了就都必须要从头做到尾吗?无论过程怎样都要把预先设定的工作流程完整执行一遍吗?
接到任务去A地参加会议,如果发现重要文件没带上是不是就得立刻终止前进?导航到A结果走到半路接到通知地点变更到B,是不是得立刻结束当前导航重新将目的地切换到B。
这就和程序执行的问题一样,当发现某个问题(错误或者缺失等)时如何处理。也就是我们下一篇所要了解的:错误处理和跳转。
下一篇了解控制语句(二):错误处理和程序跳转。
请开发者喝杯咖啡!