运行时错误处理的元素

expandtri全部显示

错误和错误处理

编写应用程序时,必须考虑出现错误时应该怎么办。有两个原因会导致应用程序中出错。第一,在运行应用程序时某些条件可能会使原本正确的代码产生错误。例如,如果代码尝试打开一个已被用户删除的,就会出错。第二,代码可能包含不正确的逻辑,导致不能运行所需的操作。例如,如果在代码中试图将数值被 0 除,就会出现错误。

如果没有做任何错误处理,则在代码出错时 Visual Basic 将停止运行并显示一条出错消息。当发生这种情况时,用户很可能对此感到迷惑和沮丧。通过把完整的错误处理例程包含在代码中来处理可能产生的所有错误,可以预防许多问题。

当将错误处理代码添加到过程中时,应当考虑在出现错误时过程将如何控制执行顺序。在将执行交给错误处理程序的步骤中,第一步是通过将某些形式的 On Error 语句包含在过程中而启用错误处理程序。On Error 语句在错误事件中对执行进行定向。如果没有 On Error 语句,在出现错误时 Visual Basic 只是简单地中止程序执行并显示一条出错消息。

如果已启用了错误处理程序的过程发生了错误,Visual Basic 将并不显示普通的出错消息,而是将它路由给错误处理程序(如果存在)。当执行传递到一个已启用的错误处理程序时,该错误处理程序就被激活。在活动的错误处理程序中,可以确定出现的错误类型,并按所选的方式处理它。Microsoft Access 提供了三类对象,它们包含关于已发生错误的信息。这三类对象分别是:ADO Error 对象、Visual Basic Err 对象和 DAO Error 对象。

出现错误时路由执行

错误处理程序指定发生错误时过程如何响应。例如,在出现特定的错误时您可能需要终止过程的运行,或者需要改正导致错误的条件并恢复过程执行。On ErrorResume 语句决定了如何在错误事件中继续执行。

On Error 语句

On Error 语句启用或禁用错误处理例程。如果启用了错误处理例程,则当出现错误时执行会传递给错误处理例程。

On Error 语句有三种形式:On Error GoTo label、On Error GoTo 0On Error Resume NextOn Error GoTo label 语句启用错误处理例程,该例程从这个语句出现的代码行开始执行。应当在可能出现错误的第一行代码前启用错误处理例程。在错误处理程序被激活并出现错误时,执行就会传到由 label 参数指定的代码行上。

由 label 参数指定的行应是错误处理例程的开头。例如,下面的过程指定:如果发生错误,执行会传给标签为 Error_MayCauseAnError 的行:

Function MayCauseAnError()

    ' Enable error handler.

    On Error GoTo Error_MayCauseAnError

    .            ' Include code here that may generate error.

    .

    .

Error_MayCauseAnError:

    .            ' Include code here to handle error.

    .

    .

End Function

On Error GoTo 0 语句在过程中禁用错误处理。即使过程中包含有标号为 0 的代码行,该语句也不把 0 行指定为错误处理代码的起始。如果代码中没有 On Error GoTo 0 语句,则在过程运行完成时将自动禁用错误处理程序。On Error GoTo 0 语句会重置 Err 对象的属性,这与使用 Err 对象的 Clear 方法效果一样。

On Error Resume Next 语句会忽略导致错误的代码行并将执行路由到错误代码行的下一行。此时过程执行并没有中止。如果要检查紧挨可能导致错误的代码行之后的 Err 对象的属性,并且要在过程中(而不是错误处理程序中)处理错误,则可使用 On Error Resume Next 语句。

Resume 语句

Resume 语句将执行从错误处理例程中重定向回到过程的主体。如果要从过程某一特定点上继续执行程序,则可以在错误处理例程中包含 Resume 语句。不过 Resume 语句并不是必需的;也可以在运行完错误处理例程之后就结束过程。

Resume 语句有三种形式。其中 ResumeResume 0 语句将执行返回到发生错误的代码行。而 Resume Next 语句将执行返回到错误代码行的下一行。Resume label 语句则将执行返回到由 label 参数指定的代码行。label 参数必须指定一个行标签或一个行号。

通常如果要求用户必须更正错误,则可以使用 ResumeResume 0 语句。例如,如果提示用户输入一个表的名称以便打开该表,而用户输入了一个并不存在的表名,则可以再次提示用户并在导致错误的语句上继续程序的执行。

如果代码在错误处理程序中改正了错误,并且无需再次运行引起错误的代码行而想继续执行,可以使用 Resume Next 语句。如果想在过程中由 label 参数指定的其他代码行上继续执行,则可以使用 Resume label 语句。例如,可以在退出例程上恢复程序的运行,如以下章节所述。

退出过程

在过程中包含一个错误处理例程的同时,还应该包括一个退出例程,以便只有在发生错误时才运行错误处理例程。可以像指定错误处理例程一样用行标签指定退出例程。

例如,可以将退出例程添加到前面章节的示例中。如果没有出现错误,退出例程在过程主体之后运行。而如果出现错误,则在运行完错误处理例程之后执行将传到退出例程。退出例程包含一个 Exit 语句。

Function MayCauseAnError()

    ' Enable error handler.

    On Error GoTo Error_MayCauseAnError

    .            ' Include code here that may generate error.

    .

    .

Exit_MayCauseAnError:

    Exit Function

Error_MayCauseAnError:

    .            ' Include code to handle error.

    .

    .

    ' Resume execution with exit routine to exit function.

    Resume Exit_MayCauseAnError

End Function

处理嵌套过程中的错误

当一个没有已启用的错误处理程序的嵌套过程中出现错误时,Visual Basic 将通过向后搜索调用列表查找其他过程中已启用的错误处理程序,而不是简单地中止执行程序。这就使得代码有机会在其他过程中纠正错误。例如,假设过程 A 调用过程 B,过程 B 调用过程 C。如果过程 C 出现错误而其中没有已启用的错误处理程序,则 Visual Basic 会先检查过程 B 再检查过程 A,以找出已启用的错误处理程序。如果找到了,执行就会传到该错误处理程序。否则会中止程序执行并显示出错消息。

当活动的错误处理程序中出现错误时,Visual Basic 也会通过向后搜索调用列表查找已启用的错误处理程序。通过用 Err 对象的 Raise 方法在活动的错误处理程序中产生错误,可以强制 Visual Basic 向后搜索调用列表。这在处理错误处理程序中出现预料外的错误时很有用。如果出现预料之外的错误,而在错误处理程序中又重新生成了该错误,则执行将按照调用列表的逆序传递以查找其他可能被设置来处理该错误的错误处理程序。

例如,假设过程 C 有一个已启用的错误处理程序,但并未纠正已经出现的错误。当该错误处理程序检查了所有预料之中的错误之后,它可以重新产生原有的错误。此时执行将按照调用列表的逆序传给过程 B 中的错误处理程序(如果存在该程序的话),给该错误处理程序纠正错误的机会。如果过程 B 没有错误处理程序或者如果不能纠正错误并重新生成了错误,则执行将传给过程 A 中的错误处理程序(假设该误处理程序存在)。

为了换一个角度来阐明这个概念,假设有一个嵌套过程,其中包含的错误处理程序用于处理预料中类型可能不匹配的错误。过程 C 的某个代码行上出现了一个预料之外的错误:值被 0 除。如果包含了一个重新生成原有错误的语句,则执行将按照调用列表的逆序传给其他已启用的错误处理程序(如果存在该程序的话)。如果已在调用列表中的另一个过程中纠正了“值被 0 除”的错误,那么该错误就可被纠正。但如果代码不重新生成该错误,则过程将继续运行但不纠正“值被 0 除”的错误。按照这种次序有可能会在嵌套过程集内产生其他错误。

总之,在以下情况下 Visual Basic 会按照调用列表的逆序搜索已启用的错误处理程序:

?过程中出现错误,而该过程又不包含已启用的错误处理程序。
?在活动的错误处理程序中出现错误。如果使用 Err 对象的 Raise 方法来产生一个错误,就可强制 Visual Basic 向后搜索调用列表以查找已启用的错误处理程序。

获得有关错误的信息

一旦执行传至错误处理例程,代码就必须确定发生了何种错误并处理它。Visual Basic 和 Microsoft Access 提供了几种可用来获取特定错误信息的语言元素。每种语言元素都适用于不同类型的错误。因为错误将发生在应用程序的不同部分,所有需要根据所预期的错误在代码中选择使用不同的语言元素。

可用于错误处理的语言元素有:

?Err 对象。
?ADO Error 对象和 Errors 集合。
?DAO Error 对象和 Errors 集合。

?AccessError 方法。

?Error 事件。

Err 对象

Err 对象是由 Visual Basic 提供的。当出现 Visual Basic 错误时,有关该错误的信息将存储在 Err 对象中。Err 对象每次只维护一个错误的信息。当出现新的错误时,Err 对象将更新为新的错误信息。

若要获取某个特定错误的信息,可以使用 Err 对象的属性和方法。Number 属性是 Err 对象的默认属性。它将返回所出现的错误的标识号。Err 对象的 Description 属性则返回与 Visual Basic 错误有关的描述性字符串。Clear 方法将清除 Err 对象的当前错误信息。Raise 方法可生成一个特定的错误并用关于该错误的信息填充 Err 对象的属性。

下面的示例说明了如何在可能导致类型不匹配错误的过程中使用 Err 对象:

Function MayCauseAnError()

    ' Declare constant to represent likely error.

    Const conTypeMismatch As Integer = 13

    On Error GoTo Error_MayCauseAnError

        .            ' Include code here that may generate error.

        .

        .

Exit_MayCauseAnError:

    Exit Function

Error_MayCauseAnError:

    ' Check Err object properties.

    If Err = conTypeMismatch Then

        .            ' Include code to handle error.

        .

        .

    Else

        ' Regenerate original error.

        Dim intErrNum As Integer

        intErrNum = Err

        Err.Clear

        Err.Raise intErrNum

    End If

    ' Resume execution with exit routine to exit function.

    Resume Exit_MayCauseAnError

End Function

请注意在上面的示例中,Raise 方法用来重新产生原有的错误。如果出现除了类型不匹配以外的错误,执行将按照调用列表的逆序传递给其他的错误处理程序(如果存在该程序的话)。

Err 对象提供了所需有关 Visual Basic 错误的所有信息。然而,它并没有给出有关 Microsoft Access 错误或 Microsoft Jet 数据库引擎错误的完整信息。Microsoft Access 和数据访问对象 (DAO) 提供了附加的语言元素来帮助处理这些错误。

Error 对象和 Errors 集合

Error 对象和 Errors 集合是由 ADO 和 DAO 提供的。Error 对象代表一个 ADO 或 DAO 错误。单个 ADO 或 DAO 操作可能引起几个错误,特别是执行 DAO ODBC 操作时。在特定数据访问操作过程中发生的每个错误都有一个相关 Error 对象。与特定的 ADO 或 DAO 对象有关的所有 Error 对象都存储在 Errors 集合中,其中最低级别的错误为集合中的第一个对象,最高级别的错误为集合中的最后一个对象。

出现 ADO 或 DAO 错误时,Visual Basic 的 Err 对象包含 Errors 集合中第一个对象的错误编号。若要确定是否出现了其他的 ADO 或 DAO 错误,可检查 Errors 集合。Errors 集合中第一个 Error 对象的 ADO Number 或 DAO Number 属性和 ADO Description 或 DAO Description 属性应该与 Visual Basic Err 对象的 NumberDescription 属性值相匹配。

AccessError 方法

使用 Err 对象的 Raise 方法可产生一个实际上并未出现的 Visual Basic 错误并确定与该错误相关的描述性字符串。然而,不能使用 Raise 方法产生 Microsoft Access 错误、ADO 错误或 DAO 错误。若要确定与实际上并未发生的 Microsoft Access 错误、ADO 错误或 DAO 错误相关的描述性字符串,可使用 AccessError 方法。

Error 事件

使用 Error 事件可捕获发生在 Microsoft Access 窗体报表上的错误。例如,当用户试图在数据类型为“日期/时间”的字段中输入文本就会发生 Error 事件。如果把 Error 事件过程添加到“雇员”窗体上,然后试图在“雇佣日期”字段中输入一个文本值,Error 事件过程就会运行。

Error 事件过程有一个整型参数 DataErr。在运行 Error 事件过程时,DataErr 参数将包含出现的 Microsoft Access 错误的编号。确定发生错误的编号的唯一方法就是在事件过程中检查 DataErr 参数。在发生 Error 事件之后,Err 对象并不为错误信息所填充。可将 DataErr 参数值与 AccessError 方法一起使用来确定错误编号及其描述性字符串。

注释  提供 Error 语句和 Error 函数的目的只是为了向后兼容。在编写新代码时,请使用 ErrError 对象、AccessError 函数和 Error 事件来获取错误信息。