我有一个Access 2007数据库,它有一系列函数调用。我在所有调用错误处理子的子函数和函数中使用On Error Goto Error_Handler,它使用错误信息更新表并发送错误通知电子邮件。我这样设置,所以我只能有一个可由任何子或函数调用的错误处理模块。
当其中一个“非主要”子程序或函数出现错误时,会发生错误,即调用错误处理函数(正如预期的那样正常工作),然后代码执行在主程序中继续执行导致错误的子(在我的情况下,发送错误的“成功”电子邮件)。要清楚,我的所有子函数和函数都有“On Error Goto Error_Handler”,因此它不是On Error Resume Next问题。
是否有办法让子调用的单独的错误处理函数让“主”程序停止执行? (在这种情况下,我们在计时器上有一个表单,它每秒循环一次记录集,并且不会尝试重新执行任何记录错误的事件,因此需要退出该过程以防止错误的成功指示。)
答案 0 :(得分: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:label。
这样做的缺点是你无法确切地追踪错误发生在哪个函数。我在实践中做的是让我的子例程错误处理程序执行此操作: (a)调用我的跟踪程序将错误(及其位置)写入我的应用程序的日志文件; (b)注意变量中的Err.Number和Err.Description;然后 (c)在我返回到我的ExitPoint:标签后,使用这些变量中的值重新引发错误,以便它返回堆栈。
以这种方式,它将确保我知道错误源自何处,但是向用户显示错误消息(在您的情况下通过写入表并发送电子邮件)将发生一次,并且只有一次;也就是说,只能通过我的顶级函数调用我的主错误例程。
另外,我对VB.Net和T-SQL中使用的Try / Catch语法非常谨慎,当我第一次遇到它时,但实际上它确实在错误处理方面提供了很多优势,包括不需要在发生错误时跟踪堆栈。这并不是说你在Access中使用VBA是一件好事吗?正如我所说,它只是一个旁边。