Board logo

標題: [原創] Excel VBA 錯誤處理流程(全圖解) [打印本頁]

作者: iamaraymond    時間: 2018-5-22 20:48     標題: Excel VBA 錯誤處理流程(全圖解)

本帖最後由 iamaraymond 於 2018-5-22 20:49 編輯

一般來說,當我們的程式執行起來沒有錯誤時,可以直接執行到底
[attach]28751[/attach]

但如果不小心有個錯誤時,就會啟動「錯誤處理機制」
[attach]28752[/attach]

那這時候,我們有3個方式來處理錯誤
1.on error resume next
2.on error goto [line]
3.on error goto 0

1.on error resume next
[attach]28753[/attach]

若使用on error resume next的話,當出現錯誤時,雖然錯誤處理機制會啟動,但會馬上關閉
就像甚麼事都沒發生一樣繼續執行下一行,完全不會跳出錯誤訊息框

2.on error goto [line]
[attach]28754[/attach]

當使用這個語法時,若遇到錯誤就會跳到指定的位置,但要注意的是,此時錯誤機制並未關閉!!
也就是說,雖然程式可以繼續執行,但錯誤機制仍然是啟動中,所以萬一不小心又出錯。。。

[attach]28755[/attach]

這個時候,他就會直接跳出錯誤訊息框,並暫停程式,這也是許多人會很困惑的地方
比如很多人常把on error goto [line] 的語法寫進迴圈中:
  1. Sub test11()

  2. For I = 1 To 3
  3. continue:
  4.     On Error GoTo myErr
  5.     k = 0 / 0
  6. Next
  7. myErr:
  8. k = 1
  9. GoTo continue
  10. End Sub
複製代碼
第一次執行時,可以成功跳轉到myErr,但第二次就不行了
原因就是此時錯誤機制已經啟動,在錯誤機制已經啟動時
即使你加了on error resume next 也一樣會跳出錯誤訊息框
  1. Sub test12()

  2. For I = 1 To 3
  3.     On Error GoTo myErr
  4.     k = 0 / 0
  5. Next

  6. myErr:
  7. On Error Resume Next
  8. I = 0 / 0

  9. End Sub
複製代碼
那要如何把錯誤機制關閉呢?
這時有3個方法
(1)resume:關閉錯誤機制並回到出錯的那一行

[attach]28756[/attach]

(2)resume next:關閉錯誤機制並回到出錯的下一行

[attach]28757[/attach]

(3)on error goto -1:關閉錯誤機制並繼續執行下一行

[attach]28758[/attach]

所以當錯誤機制被關掉時,若再次遇到錯誤就可以繼續用前面所說的3個方式來處理錯誤

3.on error goto 0

[attach]28761[/attach]

on error goto 0會關閉錯誤機制,但跳出錯誤訊息框

那這時大家可能就會很疑惑:
Q:既然on error goto 0會直接跳出錯誤訊息框,為什麼還要使用這個語法呢?
A:因為有時候必須用這個語法來取消on error resume next 的功能

EX:曾有人問過如果我想要前十行可以跳過錯誤,但過了這十行要能跳出錯誤訊息框,要怎麼做呢?

Sub Test()

On error resume next
.
.
.
On error goto 0

End Sub

因此這時候就需要這個語法來取消on error resume next


補充篇:如何處理錯誤?

[attach]28759[/attach]
[attach]28760[/attach]

文章來源:
https://raymondchiendtrt.blogspot.tw/2018/05/vba_14.html#more

參考資料:
http://club.excelhome.net/thread-503926-1-1.html
http://club.excelhome.net/forum.php?mod=redirect&goto=findpost&ptid=99895&pid=4506304
http://club.excelhome.net/thread-255631-1-1.html
http://yes.nctu.edu.tw/vb/9_Misc/%E5%8F%AF%E8%99%95%E7%90%86%E7%9A%84%E9%8C%AF%E8%AA%A4.htm
作者: nolookyou    時間: 2018-5-23 09:11

本帖最後由 nolookyou 於 2018-5-23 09:14 編輯

回復 1# iamaraymond


    感謝版大用心發文,實屬難能可貴~
    看到on error goto語法 想到我還是中二屁孩時寫Basic美好時光...XD

    長大後接觸的程式專案漸多且功能需求日益龐大,
    會發現當初Basic支援的on error goto其實沒有很好用,用了還會增加程式維護困擾QQ

    看國外一些高手寫VBA,會發現他們用on error或Err系列錯誤處理語法,
    多用在可能無法預期的1-1000號系統錯誤做處理,
   
    程式需求設計的可預期邏輯錯誤,在盡量設想好各種可預期問題後,
    把較完整處理方法都在If...Then...Else 或 Select Case做掉,
    而比較少依賴on error goto做錯誤處理,
    是小弟覺得比較好的程式內錯誤處理方式^^

作者: iamaraymond    時間: 2018-5-24 00:12

回復 2# nolookyou

感謝nolookyou大提供的經驗
其實小弟原本很擔心PO這種錯誤處理的文會不會太枯燥乏味XD
所以您的意思是說比較好的方式是
直接用on error resume next
接著下面就直接用if或select case語句
搭配err.number直接把錯誤處理掉嗎?
作者: quickfixer    時間: 2018-5-24 00:44

本帖最後由 quickfixer 於 2018-5-24 00:52 編輯

補充:不好意思,發文後才發現,你的教學裡面就有Err.Description,多發了一篇廢文

這樣就可以用err.number  錯誤代碼
也可以用err.description 錯誤訊息

看是要用什麼msgbox 提示,還是重跑程式
  1. Sub test()

  2.     On Error GoTo checkid
  3.    
  4.         ' 程式碼
  5.    
  6.    
  7.    
  8.     Exit Sub
  9.    



  10. checkid:

  11.     If Err.Number <> 0 Then
  12.         Debug.Print Err.Description
  13.         Debug.Print Err.Number
  14.     End If

  15. End Sub
複製代碼

作者: nolookyou    時間: 2018-5-24 08:40

回復 3# iamaraymond


    版大早安
    其實我建議能不用on error resume next的話也盡量找其他方法處理掉

    單純用if或select case語句 + err.number是我比較常用的作法,
    這種方法就像VB.net或 C#內的 try...catch語法,
    讓程式結構比較不那麼鬆散,後面也比較好維護^^




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)