控制语句

第十一篇、VBA核心控制语句(二):错误处理和跳转

  接上一篇:VBA控制语句“条件判断和循环”的套用,让程序变得更灵活、也带来了效率的提升。

  • ①“条件判断”使得程序有了动态决策的能力;
  • ②“循环”能自动化重复任务。

  它们的相互套用,让代码更符合业务逻辑,节省时间和资源,也可以通过修改条件或循环范围,轻松适配需求变化,让程序有了可扩展性。

  本篇接着了解其他两个核心控制语句:错误处理跳转

  • 错误处理让程序更健壮,预判它的预判,捕获运行时的错误并优雅处理,避免程序崩溃;
  • 跳转语句则是控制代码执行流程,使得程序跳过某些代码块、跳到指定位置。
本篇视频:

|03 错误处理语句

  错误处理(Error Handling)是,通过捕获运行时错误(Runtime Errors)并优雅处理,避免程序意外崩溃。

注意:这里的“错误处理”可是和程序员常说的Bug不同,Bug通常指的是程序中存在的代码缺陷,导致程序行为与预期不符(如逻辑错误、计算错误、死循环等)。而这里说的“错误处理”,是程序员主动编写的代码逻辑,用于捕获、管理程序运行时可能发生的错误(如文件找不到、除以零等),帮助程序更优雅地处理运行时的问题。

  可以把它想象成“另一种条件判断”来帮助理解,即:“当发生错误时,应该怎么办?”。

  比如:”程序让我找某个文件,但是找不到时该怎么办?程序让我计算变量A除以变量B的结果,但是B是0时没办法得到结果该怎么办?引用了一个不存在的工作表而出现错误,这时该怎么办?....”,

  从这个角度再去理解"错误处理"就会变得容易。预先判断程序运行可能发生的错误,如果发生了某种错误就做出不同的应对,目的是让程序能稳定执行不中断!

错误处理的核心语句和适用错误处理模式(方法):
点击放大的图片

  以上关于错误的处理中,有关于(特定)错误的捕获,通常是过Err(错误)对象的Number属性返回的错误编号得到的。Err.Description则获取错误的具体描述。

Err 对象的关键属性:
点击放大的图片

  通过几个关于错误处理的示例,看有无“错误处理”的程序会有什么不同?用不同的错误处理方式后程序的执行过程有什么不同?

示例:
复制成功!
1

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

|04 跳转语句

  跳转:顾名思义就是跳过和转向,即跳过某段代码不执行,转到指定的位置继续执行!

需要说明的是,虽然跳转语句在某些场景下非常有用,但它也有可能导致代码逻辑混乱,所以一定要避免过度使用跳转,滥用的结果就是代码可读性变差。

  比如,正常的代码执行过程是自上而下、从左到右,和阅读文章一样,跳转却是隔段执行,从第一页到第三页,不合理的滥用的话在第三页使用一个跳转又跳回到第二页,阅读起来就不容易理解,逻辑混乱执行也容易发生问题。

VBA常用的跳转语句:
点击放大的图片
几个关于程序跳转的示例
示例:
复制成功!
1

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知识逐渐丰富起来,写出更有逻辑的优秀代码。

方法论:
「从应用场景切入,构建认知框架;再通过逆向拆解,夯实底层基础。」
  • 从实际案例出发建立整体认知,再通过分解过程补充细节知识
请开发者喝杯咖啡 请开发者喝杯咖啡!