1. 程式人生 > >簡談VBA的錯誤處理

簡談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 標籤”語句,要想讓程式重新獲取其他錯誤資訊,則都必須在導致問題的程式碼行後面使用

On Error Goto 0 語句恢復正常的錯誤捕獲狀態。否則當前的錯誤處理程式將對後面的所有錯誤都起作用。例如,下面的程式碼由於沒有使用 On Error Goto 0 語句,因此,在後面遇到錯誤時(兩次 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

    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 中的下一行程式碼,這種情況可能會使整個程式碼包含了不可預知的錯誤,因此務必要小心。