簡談VBA的錯誤處理
在 Word 、 Excel 乃至其他支援 VBA 的 Office 元件中,在程式碼中處理錯誤的方式通常都是使用“ On Error Goto 錯誤標籤”語句,然後在程式碼的後面新增錯誤標籤及其中包含的錯誤處理程式碼。下面總結了建立錯誤處理程式的步驟:
( 1 )在過程中可能導致錯誤的程式碼行的前面新增錯誤處理語句 On Error Goto ErrHandler ,其中的“ ErrHandler ”為自定義的錯誤標籤名稱。
( 2 )在有可能導致錯誤的程式碼行後面新增取消錯誤處理的語句 On Error Goto 0 ,這樣當遇到錯誤時,就不會跳轉到指定的錯誤標籤處,而是直接顯示錯誤提示視窗,其中包括【除錯】、【結束】等按鈕。
( 3 )在巨集的末尾(正常程式的末尾)新增程式碼行 Exit Sub ,這樣可以避免程式未發生錯誤時執行錯誤處理程式。
( 4 )在程式碼行 Exit Sub 的下一行新增一個錯誤標籤,該標籤由名稱和冒號組成,例如“ MyErr: ”。
( 5 )在錯誤標籤的下一行編寫錯誤處理程式碼。如果要返回導致錯誤的程式碼行後面的程式碼行,可以使用 Resume Next 語句。
注意:可以在過程的末尾新增多個錯誤處理程式,但必須確保每個錯誤處理程式都以 Resume Next 或 Exit Sub 語句結束,這樣可以避免從當前錯誤程式之後繼續執行其後的錯誤處理程式。
舉一個簡單的例子可能會更直觀地反映出上面所說的內容。在下面的程式碼中,當檢測到工作簿中沒有指定的工作表時,將出現錯誤,並執行錯誤程式碼,顯示一個包含錯誤號與錯誤描述的對話方塊。
Sub 檢測工作表是否存在 ()
Dim wksname As String, msg As String
On Error GoTo MyErr
wksName = Worksheets("sx").Name
MyErr:
msg = " 錯誤 " & Err.Number & " : " & Err.Description
MsgBox msg
End Sub
注意:無論在導致問題的程式碼行前面使用
On
Error Resume Next
語句還是“
On Error Goto
標籤”語句,要想讓程式重新獲取其他錯誤資訊,則都必須在導致問題的程式碼行後面使用
Sub ErrTest()
Dim x As Integer, y As Integer, z As Single
x = 1
y = 0
On Error GoTo MyErr
MsgBox x / y
MsgBox x / y
MsgBox " 繼續執行錯誤程式碼行的下一行程式碼 "
Exit Sub
MyErr:
MsgBox " 第 1 次:除數不能為 0"
Resume Next
End Sub
而下面的程式碼由於及時使用了 On Error Goto 0 語句,因此,在第 2 次錯誤發生時(即第 2 個 x/y ),系統將顯示內建錯誤訊息,而不是執行 MyErr 標籤處的程式碼。
Sub ErrTest()
Dim x As Integer, y As Integer, z As Single
x = 1
y = 0
On Error GoTo MyErr
MsgBox x / y
On Error GoTo 0
MsgBox x / y
MsgBox " 繼續執行錯誤程式碼行的下一行程式碼 "
Exit Sub
MyErr:
MsgBox " 第 1 次:除數不能為 0"
Resume Next
End Sub
下面的程式碼雖然未使用 On Error Goto 0 語句,但是在第 2 個錯誤發生前,添加了第 2 個錯誤標籤,因此,兩個錯誤處理程式分別處理各自的錯誤。
Sub ErrTest()
Dim x As Integer, y As Integer, z As Single
x = 1
y = 0
On Error GoTo MyErr1
MsgBox x / y
On Error GoTo MyErr2
MsgBox x / y
MsgBox " 繼續執行錯誤程式碼行的下一行程式碼 "
Exit Sub
MyErr1:
MsgBox " 第 1 次:除數不能為 0"
Resume Next
MyErr2:
MsgBox " 第 2 次:除數不能為 0"
Resume Next
End Sub
以上 3 段程式碼在執行完錯誤處理程式後,都會返回發生錯誤的程式碼之後繼續執行。對於本例來說,在執行完錯誤處理程式後,都會繼續執行“ MsgBox " 繼續執行錯誤程式碼行的下一行程式碼 " ”程式碼行。
雖然我們不希望在程式執行時出現錯誤,但是有些時候我們可以利用錯誤來提高程式碼的效率。例如,當用戶由於某些原因將工作簿中的某個工作表刪除,如果 VBA 程式中中包括操作該工作表的程式碼,那麼當用戶執行該程式時,將導致錯誤發生。此時,可以利用錯誤來檢測要操作的工作表是否存在於工作簿中。程式碼如下:
Sub 檢測工作表是否存在 ()
Dim WksName As String
On Error Resume Next
WksName = Worksheets("sx").Name
If Err.Number <> 0 Then
MsgBox prompt:=" 此工作簿中未找到工作表 sx", Title:=" 錯誤 "
End If
On Error GoTo 0
End Sub
注意:當使用 On Error Resume Next 語句後,應該及時在可能導致錯誤的程式碼行之後使用 On Error Goto 0 語句恢復錯誤的捕獲,即恢復到錯誤檢查的正常狀態,以便可以獲悉其他任何可能發生的錯誤。另外,如果使用 On Error Resume Next 語句忽略了無法忽略的錯誤,將會立刻結束當前執行的過程。而更糟糕的是,如果巨集 1 呼叫巨集 2 ,但巨集 2 發生了無法忽略的錯誤,那麼將立刻結束巨集 2 的執行,而繼續執行巨集 1 中的下一行程式碼,這種情況可能會使整個程式碼包含了不可預知的錯誤,因此務必要小心。