控制语句
第十一篇、VBA核心控制语句(二):错误处理和跳转
接上一篇:VBA控制语句“条件判断和循环”的套用,让程序变得更灵活、也带来了效率的提升。
- ①“条件判断”使得程序有了动态决策的能力;
- ②“循环”能自动化重复任务。
它们的相互套用,让代码更符合业务逻辑,节省时间和资源,也可以通过修改条件或循环范围,轻松适配需求变化,让程序有了可扩展性。
本篇视频:
|03 错误处理语句
错误处理(Error Handling)是,通过捕获运行时错误(Runtime Errors)并优雅处理,避免程序意外崩溃。
注意:这里的“错误处理”可是和程序员常说的Bug不同,Bug通常指的是程序中存在的代码缺陷,导致程序行为与预期不符(如逻辑错误、计算错误、死循环等)。而这里说的“错误处理”,是程序员主动编写的代码逻辑,用于捕获、管理程序运行时可能发生的错误(如文件找不到、除以零等),帮助程序更优雅地处理运行时的问题。
可以把它想象成“另一种条件判断”来帮助理解,即:“当发生错误时,应该怎么办?”。
比如:”程序让我找某个文件,但是找不到时该怎么办?程序让我计算变量A除以变量B的结果,但是B是0时没办法得到结果该怎么办?引用了一个不存在的工作表而出现错误,这时该怎么办?....”,
从这个角度再去理解"错误处理"就会变得容易。预先判断程序运行可能发生的错误,如果发生了某种错误就做出不同的应对,目的是让程序能稳定执行不中断!
错误处理的核心语句和适用错误处理模式(方法):
以上关于错误的处理中,有关于(特定)错误的捕获,通常是过Err(错误)对象的Number属性返回的错误编号得到的。Err.Description则获取错误的具体描述。
Err 对象的关键属性:
通过几个关于错误处理的示例,看有无“错误处理”的程序会有什么不同?用不同的错误处理方式后程序的执行过程有什么不同?
示例:
Sub 不使用错误处理打开文件()
Dim FilePath As String
FilePath = "C:\Users\MagicBook\Desktop\kk\工作薄对象\工作簿5.xlsx" '文件路径
Workbooks.Open FilePath '打开文件
MsgBox "文件已打开"
End Sub
'-----------------------------------------
Sub 使用错误处理打开文件1()
Dim FilePath As String
On Error GoTo Err_处理 '遇到错误时执行
FilePath = "C:\Users\MagicBook\Desktop\kk\工作薄对象\工作簿5.xlsx" '文件路径
Workbooks.Open FilePath '打开文件
MsgBox "文件已打开"
Exit Sub
Err_处理:
MsgBox "错误描述:" & Err.Description & vbCrLf & "请检查文件路径。", vbCritical
FilePath = "C:\Users\MagicBook\Desktop\kk\工作薄对象\工作簿4.xlsx" '文件路径
Workbooks.Open FilePath '打开文件
MsgBox Right(FilePath, 9) & "文件已打开"
End Sub
'以上如果用if尝试呢?if 找不到需要打开的文件 then 打开其他文件,可以尝试下。结果就是行不通,发生尝试打开时,就已经是错误终止了
'-------------------------------------------------------------------------------
Sub 合并工作簿时遇到的错误示例()
'选取工作工作簿合并,只合并每个工作表内的名称为“Sheet1”的工作表,如果某个工作簿内缺少该工作表就直接关闭,最后msgbox弹出未汇总的工作簿
Dim end_row As Long, step_row As Long
Dim FileToOpen As Variant
Dim i As Long
Dim Err_name As String
FileToOpen = Application.GetOpenFilename("Excel文件,*.xl*", , "请选择要合并的多个工作簿/表", , True)
On Error Resume Next '次行开始发生的错误都会被忽略,结合On Error GoTo 0的位置,就是For循环内的错误,都会被忽略
For i = 1 To UBound(FileToOpen)
Workbooks.Open Filename:=FileToOpen(i)
'For Each sht In Worksheets 取消遍历工作表,只复制Sheet1
'Next
end_row = ThisWorkbook.Sheets("汇总").UsedRange.Rows.Count + 1
Worksheets("Sheet1").UsedRange.Copy Destination:=ThisWorkbook.Sheets("汇总").Range("B" & end_row)
step_row = Worksheets("Sheet1").UsedRange.Rows.Count
ThisWorkbook.Sheets("汇总").Range("A" & end_row & ":A" & end_row + step_row).Value = ActiveWorkbook.Name & "-" & "Sheet1"
If Err.Number = 9 Then '如果发现找不到工作表的“下标越界”错误,错误代码是9
'If Err.Number > 0,也是可以的,只要发生错误,错误代码就大于0,这时在汇总的就不是“找不到工作表”的错误了,而是所有发生的错误都会被记录下来
Err_name = Err_name & FileToOpen(i) & vbCrLf '把找不到工作表的工作簿串起来,注意换行符
End If
Err.Clear '清除错误,保证在下次循环时,以往的错误值不被记录下来,试下取消看看?
ActiveWorkbook.Close
Next i
On Error GoTo 0 '次行开始发生的错误不在被忽略,即如果有错误就会终止
MsgBox Err_name & vbCrLf & "以上工作簿中不存在“Sheet1”的工作表", vbCritical
End Sub
- ※:不使用错误处理打开不存在的文件,程序运用时中止,不在往下进行;
- ※:使用错误处理遇到错误,GoTo语句导向指定位置,继续执行需要处理的语句;
- ※:On Error Resume Next,在此之后发生的任何任务都会被忽略,直到程序结束或OnErrorGoTo0之后
- ※:捕获到的错误也可以为开发者所用,写出不同错误的应对措施,让程序更健壮!
|04 跳转语句
跳转:顾名思义就是跳过和转向,即跳过某段代码不执行,转到指定的位置继续执行!
需要说明的是,虽然跳转语句在某些场景下非常有用,但它也有可能导致代码逻辑混乱,所以一定要避免过度使用跳转,滥用的结果就是代码可读性变差。
比如,正常的代码执行过程是自上而下、从左到右,和阅读文章一样,跳转却是隔段执行,从第一页到第三页,不合理的滥用的话在第三页使用一个跳转又跳回到第二页,阅读起来就不容易理解,逻辑混乱执行也容易发生问题。
VBA常用的跳转语句:
几个关于程序跳转的示例
示例:
Sub 跳转_GoTo()
'找到第一个语文成绩及格的学生
Dim name_max As Long '存储原表行数
name_max = ThisWorkbook.Worksheets("五一班期末成绩").UsedRange.Rows.Count() '成绩表末行的行数
Dim j As Long
For j = 1 To name_max
If Cells(j, 2) <= 60 Then
GoTo Skip_end '跳转到Skip_end:
End If
Next j
Skip_end:
MsgBox "第一个不及格的学生名单和成绩:" & vbCrLf & Cells(j, 1) & ":" & Cells(j, 2)
End Sub
'------------------------------
Sub 跳转_Exit_For()
'找到三个语文成绩高于90的同学即结束循环
Dim name_max As Long '存储原表行数
name_max = ThisWorkbook.Worksheets("五一班期末成绩").UsedRange.Rows.Count() '成绩表末行的行数
Dim i_num As Byte
Dim j As Long
Dim name_A As String
For j = 2 To name_max
If Cells(j, 2) >= 90 Then
name_A = name_A & Cells(j, 1) & ":" & Cells(j, 2) & vbCrLf
i_num = i_num + 1
End If
If i_num = 3 Then
MsgBox "循环遍历至第:" & j & "行" & vbCrLf & name_A
Exit For
End If
Next j
Debug.Print "是否执行1"
End Sub
'------------------------------------
Sub 跳转_Exit_Do()
'找到高于90的同学,至多查找10个
Dim name_max As Long '存储原表行数
name_max = ThisWorkbook.Worksheets("五一班期末成绩").UsedRange.Rows.Count() '成绩表末行的行数
Dim i_num As Byte
Dim j As Long
Dim name_A As String
j = 2
Do While j <= name_max
If Cells(j, 2) >= 90 Then
name_A = name_A & Cells(j, 1) & ":" & Cells(j, 2) & vbCrLf
MsgBox "第一个语文成绩高于90分的学生:" & vbCrLf & name_A
Exit Do
End If
j = j + 1
Loop
Debug.Print "是否执行2"
End Sub
'------------------------------------
Sub 跳转_Exit_sub()
'找到三个语文成绩高于90的同学即结束循环
Dim name_max As Long '存储原表行数
name_max = ThisWorkbook.Worksheets("五一班期末成绩").UsedRange.Rows.Count() '成绩表末行的行数
Dim i_num As Byte
Dim j As Long
Dim name_A As String
For j = 2 To name_max
If Cells(j, 2) >= 90 Then
name_A = name_A & Cells(j, 1) & ":" & Cells(j, 2) & vbCrLf
i_num = i_num + 1
End If
If i_num = 3 Then
MsgBox "循环遍历至第:" & j & "行" & vbCrLf & name_A
Exit Sub
End If
Next j
Debug.Print "是否执行3"
End Sub
下一篇:VBA基础语句(一):注释和操作符
关于VBA程序语言的学习,到本篇为止,如果你只是用来通过编程自动化处理Excel中相对复杂的任务,知识点已经足够了!认识了对象也能控制它、还能控制程序的执行流程,就完全可以让程序自己去处理Excel中的数据任务。
下一节要介绍“基础语句”,会不会觉得:“基础知识不是刚开始接触VBA就需要介绍吗?为什么要先去了解“宏”的录制、繁杂的“对象”、核心的“控制语句”,然后在了解基础知识呢?”
是因为这样才不会感觉枯燥和无从开始!
零基础的情况下,如果先去了解注释和操作符这些“实现各种计算和逻辑判断”的非常基础的编程知识,可能的结果就是:每一个字都认识,就是不知道说的是啥?
太基础的知识就必须要把它们放到程序代码中去了解,先知道它发挥的作用是什么,最后再归纳总结,才会对它们有全新的认知,最终让自己的VBA知识逐渐丰富起来,写出更有逻辑的优秀代码。
方法论:
「从应用场景切入,构建认知框架;再通过逆向拆解,夯实底层基础。」
- 从实际案例出发建立整体认知,再通过分解过程补充细节知识
请开发者喝杯咖啡!