如果我正在閱讀你正在做的事情,那麼當我第一次開始做類似事情時,我陷入了同樣的陷阱。問題是,因爲錯誤正在非主程序中「處理」,所以就錯誤處理系統而言,它已經完成並被丟棄;當程序控制流程返回到主程序時,則不再有錯誤情況。讓我看看,如果我能在僞代碼說明:
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:標籤和Exit Function語句)並返回到MainFunction。當它這樣做時,將不再有效果的錯誤,因爲它已經被處理,因此「成功」電子郵件將被髮送。
處理這種情況的最快和最骯髒的方法是不要在子程序中放置任何錯誤處理。在這種情況下,當發生錯誤時,它會立即拋出調用堆棧,直到它遇到一個錯誤處理程序,在這種情況下,它將在您的MainFunction中。當它這樣做時,它會直接跳到MainFunction的ErrorHandler:標籤。
這樣做的缺點是,您不能確切地跟蹤錯誤發生在哪個函數。我在練習中做的是讓我的子例程錯誤處理程序執行此操作: (a)Call my跟蹤程序將錯誤(及其位置)寫入我的應用程序的日誌文件; (b)注意變量中的Err.Number和Err.Description;然後 (c)使用這些變量中的值在我返回到ExitPoint:標籤後重新提升錯誤,以便它返回堆棧。
這樣可以確保我知道錯誤來自哪裏,但錯誤消息主要顯示給用戶(在您的情況下,通過寫入表格併發送電子郵件)會發生一次,只有一次;也就是說,只通過我的頂級函數調用我的主要錯誤例程。
另一方面,我對VB中使用的Try/Catch語法非常感興趣。Net和T-SQL,但實際上它在錯誤處理方面提供了很多優勢,包括在出現錯誤時不需要追蹤堆棧。這並不是說你在Access中使用VBA的時候一點都不好;正如我所說,它只是一個旁觀。