語句
語法On Error GoTo line 、On Error Resume Next、On Error GoTo 0
On Error 語句的語法可以具有以下任何一種形式的語句描述:
On Error GoTo line
啟動錯誤處理程式,且該例程從必要的 line 參數中指定的 line 開始。line 參數可以是任何行標籤或
行號。如果發生一個運行時錯誤,則控制項會跳到 line,激活錯誤處理程式。指定的 line 必須在一個過程中,這個過程與 On Error 語句相同; 否則會發生
編譯時間錯誤。
On Error Resume Next
說明當一個運行時錯誤發生時,控制項轉到緊接著發生錯誤的語句之後的語句,並在此繼續運行。訪問對象時要使用這種形式而不使用 On Error GoTo。
On Error GoTo 0
禁止當前過程中任何已啟動的錯誤處理程式。
說明:如果不使用 On Error 語句,則任何運行時錯誤都是致命的;也就是說,結果會導致顯示錯誤信息並中止運行。一個“允許的”錯誤處理程式是由 On Error 語句打開的一個處理程式;一個“活動的”錯誤處理程式是處理錯誤的過程中允許的錯誤處理程式。如果在錯誤處理程式處於活動狀態時(在發生錯誤和執行 Resume、Exit Sub、Exit Function 或 Exit Property 語句之間這段時間)又發生錯誤,則當前過程的錯誤處理程式將無法處理這個錯誤。控制項返回調用的過程。如果調用過程有一個已啟動的錯誤處理程式,則激活錯誤處理程式來處理該錯誤。如果調用過程的錯誤處理程式也是活動的,則控制項將再往回傳到前面的調用過程,這樣一直進行下去,直到找到一個被允許的但不是活動的錯誤處理程式為止。如果沒有找到被允許而且不活動的錯誤處理程式,那么在錯誤實際發生的地方,錯誤本身是嚴重的。錯誤處理程式每次將控制項返回調用過程時,該過程就成為當前過程。在任何過程中,一旦錯誤處理程式處理了錯誤,在當前過程中就會從 Resume 語句指定的位置恢復運行。注意 一個錯誤處理程式不是 Sub 過程或 Function 過程。它是一段用行標籤或行號標記的代碼。錯誤處理程式依靠 Err 對象的 Number 屬性中的值來確定錯誤發生的原因。在其它任何錯誤發生之前,或在調用一個可能會導致錯誤發生的過程之前,錯誤處理程式應該先測試或存儲 Err 對象中相關的屬性值。Err 對象中的屬性值只反映最近發生的錯誤。Err.Description 中包含有與 Err.Number 相關聯的錯誤信息。On Error Resume Next 會使程式從緊隨產生錯誤的語句之後的語句繼續執行,或是從緊隨最近一次調用含有 On Error Resume Next 語句的過程的語句繼續運行。這個語句可以置運行時錯誤於不顧,使程式得以繼續執行。可以將錯誤處理程式放置在錯誤發生的地方,而不必將控制項傳輸到過程中的其它位置。在調用另一個過程時,On Error Resume Next 語句成為非活動的,所以,如果希望在例程中進行嵌入錯誤處理,則應在每一個調用的例程中執行 On Error Resume Next 語句。注意 當處理在訪問其它對象期間產生的錯誤時,與其使用 On Error GoTo 指令,不如使用 On Error Resume Next。每次和對象打交道,在不知道用代碼訪問哪個對象時,檢查一下 Err 都會打消這種疑慮。可以確定是哪個對象產生錯誤(Err.Source 中指定的對象),也可以確定是哪個對象將錯誤代碼放在 Err.Number 中。On Error GoTo 0 停止在當前過程中處理錯誤。即使過程中包含編號為 0 的行,它也不把行 0 指定為處理錯誤的代碼的起點。如果沒有 On Error GoTo 0 語句,在退出過程時,錯誤處理程式會自動關閉。在錯誤未發生的時候,為了防止錯誤處理程式代碼運行,請像在下段程式中那樣,在緊靠著錯誤處理程式的前面寫入 Exit Sub、Exit Function 或 Exit Property 語句。Sub InitializeMatrix(Var1, Var2, Var3, Var4) On Error GoTo ErrorHandler . . . Exit SubErrorHandler: . . . Resume NextEnd Sub此處,錯誤處理程式代碼在 Exit Sub 語句之後,而在 End Sub 語句之前,從而與過程中的流程分開。錯誤處理程式代碼可以在程式中的任何地方寫入。當對象作為檔案運行時,對象中未捕獲的錯誤都被返回控制應用程式。在開發環境中,如果設定了正確選項,未捕獲的錯誤只返回控制應用程式。請參考主應用程式的文檔的有關描述,從而得知,在調試時應該設定哪些選項、如何設定這些選項以及主機能否建立類。如果建立一個訪問其它對象的對象,則應該著手處理從那些對象返回的未處理錯誤。如果無法處理這種錯誤,請將 Err.Number 中的錯誤代碼當作自己的一個錯誤,然後將錯誤回傳給對象的調用者。應該將錯誤代碼添加到 vbObjectError 常數上來指定這個錯誤。舉例來說,如果錯誤代碼為 1052,則使用如下方法指定錯誤:Err.Number = vbObjectError + 1052注意 調用動態程式庫 (DLL) 期間產生的系統錯誤不會產生例外情況,也不會被 Visual Basic 的錯誤捕獲操作所捕獲。當調用 DLL 函式時,應該(根據 API 的詳細說明)檢查每一個返回值以確定是成功還是失敗,如果失敗,則檢查 Err 對象的 LastDLLError 屬性中的值。
忽略錯誤
對錯誤進行處理的最簡單(和最危險)的方法是使用On Error Resume Next語句。On Error Resume Next語句規定,代碼中的錯誤將完全被忽略,存在錯誤的代碼行被跳過,然後繼續執行下一個語句。例如,下面這個過程存在一個運行期錯誤(即一個被0除的錯誤),它由On Error Resume Next錯誤處理程式來處理:
Private Sub cmdGenerateError_Click()
'* Purpose: Test On Error Resume Next
On Error Resume Next
Debug.Print 10 / 0
End Sub
Debug.print語句產生了一個被0除的錯誤。但是,由於存在一個已經激活的錯誤處理程式(由On Error Resume Next指定),因此該錯誤被忽略,並在下一個語句(即End Sub語句)上恢復執行。錯誤被忽略並不意味著我們無法知道錯誤已經發生。當一個語句產生了一個錯誤之後,儘管沒有顯示出錯訊息,Err對象仍然包含關於該錯誤的信息。
代碼流
除非我們捕獲了一個意料之外的錯誤,比如上面代碼中的那種錯誤,否則忽略代碼中的錯誤是非常危險的,並且是一種不得已時採用的辦法。當一個過程中出現了意料之外的錯誤時,該過程就會產生許多問題。如果忽略該錯誤,就會對用戶產生嚴重的影響,比如數據沒有保存,或者保存不正確。許多情況下,當出現代碼錯誤時,必須執行某些操作,將代碼的執行轉移到On Error
GoTo語句中指定的錯誤處理程式。該語句的句法如下:
On Error GoTo line
請注意,line必須是指與On Error GoTo語句相同的過程中的一個語句。
在這個句法中, line有兩個意思。首先它是指出現錯誤時要轉移到的這個代碼行號。不過這個行號並不是過程中的代碼行的物理位置。請看下面這個代碼例子:
Private Sub TestErrorHandler()
'* Purpose : Test the On Error GoTo statement by deliberately
'* generating a run-timeerror.
On Error GoTo 4
Debug.Print "Line 2"
Debug.Print 10 / 0
Debug.Print "Line 4"
Debug.Print "Line 5"
End Sub
我們可能認為,被0除的錯誤會導致代碼在輸出文本line 4這個語句上繼續執行,因為這是代碼的第四個語句(不是計數注釋)。不僅這種情況不會發生,而且該代碼實際上會導致產生一個編譯錯誤,並且代碼根本不會執行。
激活狀態
雖然我們不希望已
編譯程式中的錯誤不被捕獲,但是,當程式在IDE中運行時如果出現錯誤,讓VB中止代碼的執行,這樣做常常是非常不利的。當代碼的執行中止時,會看到一條相關的出錯訊息,並告訴我們出現錯誤的代碼行,這對於代碼的調試來說是大有幫助的。VB為處理代碼設計時遇到的錯誤而使用的方法取決於VB IDE的Error Trapping(捕獲錯誤)屬性。Error Trapping屬性是VB環境的一個屬性,不是某個項目的屬性。我們操作的每個項目,即使在關閉和重新啟動VB之後,均使用該設定值。若要為VB的當前會話設定Error Trapping選項,而不必為將來的會話修改默認值,請使用代碼視窗的
快捷選單上的Toggle命令。
可以將Error Trapping屬性設定為下列值中的一個:
Break On All Errors(在所有錯誤上中止)。
Break In Class Module(在
類模組中中止)。
Break On Unhandled Errors(在未處理的錯誤上中止)。
Break On All Errors實際上可使所有錯誤處理程式均取消激活狀態。當出現一個錯誤時,無論是否激活了處理程式,代碼均在出錯的語句上進入中止方式,同時VB顯示一條出錯訊息。這使我們能夠在IDE進行測試時處理意料不到的錯誤。