1

我有一个 Access 2007 数据库,其中包含一系列函数调用。我在所有子程序和函数中使用 On Error Goto Error_Handler 调用错误处理子程序,该子程序使用错误信息更新表并发送错误通知电子邮件。我以这种方式进行设置,因此我只能拥有一个可由任何子或函数调用的错误处理模块。

当“非主”子例程或函数之一出现错误时发生的情况是错误处理函数被调用(如预期并正常工作)但随后代码执行在主过程中继续执行子程序之后的任何内容导致错误(在我的情况下,发送虚假的“成功”电子邮件)。需要明确的是,我所有的子程序和函数都有“On Error Goto Error_Handler”,所以这不是 On Error Resume Next 问题。

有没有办法让 sub 调用单独的错误处理函数并让“main”过程停止执行?(在这种情况下,我们在计时器上有一个表单,它每秒循环一次记录集,并且不会尝试重新执行任何记录了错误的事件,因此希望退出该过程以防止错误的成功指示。)

4

1 回答 1

4

如果我正在阅读您正确执行的操作,那么这与我第一次开始做类似事情时陷入的陷阱相同。问题在于,因为错误是在非主程序中“处理”的,所以就错误处理系统而言,它已经完成并除尘了;当程序控制流返回到主程序时,不再有错误情况。让我看看我是否可以用伪代码说明:

MainFunction()

   On Error Goto ErrorHandler

   Call MySubFunction

   CodeToSendSuccessEmail    

ExitPoint:
'Here we do any necessary cleanup.

Exit Function

ErrorHandler:

   Call MyErrorRoutine
   Resume ExitPoint

End Function


Function MySubFunction()

   On Error Goto ErrorHandler

   DoStuffThatCauseAnError

ExitPoint:
Exit Function

ErrorHandler:

   Call MyErrorRoutine
   Resume ExitPoint

End Function

好的,那么当 MySubFunction 发生错误时会发生什么?它将跳转到该函数中的 ErrorHandler: 标签。完成此操作后,就错误处理系统而言,错误已得到处理,因此它将离开该函数(在我的例子中,通过 ExitPoint: label 和 Exit Function 语句)并返回到 MainFunction。当它这样做时,将不再有错误,因为它已被处理,因此将发送“成功”电子邮件。

处理此类情况的最快和最肮脏的方法是根本不在子过程中放置​​任何错误处理。这样,当发生错误时,它将立即被抛出调用堆栈,直到遇到错误处理程序,在这种情况下,该处理程序将在您的 MainFunction 中。当它这样做时,它会直接跳到 MainFunction 的 ErrorHandler: 标签。

这样做的缺点是您无法准确跟踪错误发生在哪个函数中。我在实践中所做的是让我的子例程错误处理程序执行此操作: (a) 调用我的跟踪程序来编写错误(及其位置)到我的应用程序的日志文件;(b) 注意变量中的 Err.Number 和 Err.Description;然后 (c) 在我返回 ExitPoint: 标签后,使用这些变量中的值重新引发错误,以便它会流回堆栈。

这样可以确保我知道错误的来源,但是向用户显示错误消息的主要显示(在您的情况下,通过写入表格并发送电子邮件)将发生一次,并且仅发生一次;也就是说,仅通过我的顶级函数调用我的主要错误例程。

顺便说一句,当我第一次遇到它时,我对 VB.Net 和 T-SQL 中使用的 Try/Catch 语法持怀疑态度,但实际上它在错误处理方面确实提供了很多优势,包括不需要捏造发生错误时跟踪堆栈。并不是说您在 Access 中使用 VBA 有一点好处;正如我所说,这只是一个旁白。

于 2013-03-29T05:54:19.940 回答