Cách xử lý lỗi VBA bằng các lệnh On Error

Lỗi khi bạn lập trình bằng VBA trong Excel là điều không tránh khỏi. Cái chính là khi bạn phát hiện ra lỗi thì cần phải biết nguyên nhân gây ra lỗi thì bạn mới xử lý triệt để vấn đề lỗi. Có một cách khá hay là bạn có thể sử dụng một số câu lệnh On Error xử lý lỗi VBA.

Người lập trình có thể xử lý lỗi VBA bằng lệnh On Error

Hướng dẫn xử lý lỗi VBA bằng các lệnh On Error

Nếu quá trình thực thi mã xảy ra lỗi, chúng ta có 2 tùy chọn:

- Thứ nhất: Bỏ qua lỗi và để mã tiếp tục chạy.
- Thứ hai: Sử dụng mã xử lý lỗi tại chỗ và chạy khi lỗi xảy ra.

Cả 2 phương pháp xử lý lỗi này đều đảm bảo người dùng cuối không gặp phải lỗi nữa.

Ngoài ra, chúng ta có thể sử dụng một số lệnh On Error để khắc phục lỗi.

1. Lệnh On Error Resume Next

Khi sử dụng lệnh On Error Resume Next trong đoạn mã, các lỗi xảy ra sẽ bị bỏ qua và mã sẽ tiếp tục chạy.

Phương pháp xử lý lỗi này được sử dụng khá thường xuyên, tuy nhiên chúng ta cần thận trọng vì phương pháp này bỏ qua các lỗi có thể xảy ra nên không thể xác định được các lỗi cần sửa.

Cho ví dụ, nếu chạy đoạn mã dưới đây nó sẽ trả về lỗi:

Sub AssignValues()
x = 20 / 4
y = 30 / 0
End Sub

Lỗi xảy ra vì chúng ta không thể chia một số cho số 0.

Nhưng nếu sử dụng lệnh On Error Resume Next trong đoạn mã trên, nó sẽ bỏ qua lỗi và chúng ta không thể biết được lỗi nào cần sửa:

Sub AssignValues()
On Error Resume Next
x = 20 / 4
y = 30 / 0
End Sub

Lưu ý: Chỉ nên sử dụng lệnh On Error Resume Next khi chúng ta biết rõ loại lỗi mà mã VBA sẽ bỏ qua và có thể bỏ qua lỗi đó.

Cho ví dụ, dưới đây là mã sự kiện VBA thêm các giá trị ngày và giờ trong ô A1 của sheet mới được chèn (mã này được thêm vào bảng tính chứ không phải module):

Private Sub Workbook_NewSheet(ByVal Sh As Object)
Sh.Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss")
End Sub

Mặc dù đoạn mã trên hoạt động tốt trong hầu hết các trường hợp, nhưng nếu chúng ta thêm một biểu đồ chứ không phải một sheet, nó sẽ trả về lỗi. Điều này là bởi vì biểu đồ không có các ô.

Nếu sử dụng lệnh On Error Resume Next trong đoạn mã trên, nó sẽ chạy bình thường mà không có bất kỳ lỗi nào xảy ra.

Private Sub Workbook_NewSheet(ByVal Sh As Object)
On Error Resume Next
Sh.Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss")
End Sub

Nếu muốn chúng ta có thể phân tích lỗi (nếu có) và hiển thị thông báo lỗi có liên quan.

Sử dụng đoạn mã dưới đây để hiển thị hộp thoại thông báo lỗi để thông báo cho người bảng tính chưa được chèn:

Private Sub Workbook_NewSheet(ByVal Sh As Object)
On Error Resume Next
Sh.Range("A1") = Format(Now, "dd-mmm-yyyy hh:mm:ss")
If Err.Number <> 0 Then
MsgBox "bạn đã chèn một biểu đồ" & vbCrLf & "Error - " & Err.Description
End If
End Sub

Trong đó Err.Number được sử dụng để lấy mã lỗi và Err.Description được sử dụng để lấy mô tả lỗi.

2. Lệnh On Error GoTo 0

Lệnh On Error GoTo 0 sẽ dừng mã tại dòng gây ra lỗi và hiển thị hộp thoại thông báo mô tả lỗi.

Nói một cách đơn giản, lệnh này cho phép kiểm tra hành vi lỗi và hiển thị thông báo lỗi mặc định.

Thường thì chúng ta không cần sử dụng lệnh On Error Goto 0, nhưng có thể sử dụng lệnh này kết hợp với lệnh On Error Resume Next để cho kết quả tốt hơn.

Để dễ hình dung, bạn đọc cùng tham khảo ví dụ dưới đây. Đoạn mã dưới đây sẽ chọn tất cả các ô trống trong phạm vi:

Sub SelectFormulaCells()
Selection.SpecialCells(xlCellTypeBlanks).Select
End Sub

Trường hợp nếu không có ô trống nào trong các ô đã chọn, nó sẽ trả về lỗi. Để tránh lỗi xảy ra, chúng ta có thể sử dụng lệnh On Error Resume Next:

Sub SelectFormulaCells()
On Error Resume Next
Selection.SpecialCells(xlCellTypeBlanks).Select
End Sub

Vấn đề phát sinh nếu một phần của mã xảy ra lỗi, vì vậy chúng ta sử dụng lệnh On Error Resume Next để bỏ qua lỗi và chuyển qua dòng tiếp theo.

Cho ví dụ khác, đoạn mã dưới đây không trả về lỗi nào:

Sub SelectFormulaCells()
On Error Resume Next
Selection.SpecialCells(xlCellTypeBlanks).Select
' .. more code that can contain error
End Sub

Về cơ bản trong đoạn mã trên có 2 lỗi. Lỗi đầu tiên nằm trong lệnh chọn tất cả các ô trống (sử dụng Selection.SpecialCells) và lỗi thứ 2 nằm trong mã còn lại.

Trong đó lỗi đầu tiên có thể bị bỏ qua nhưng lỗi sau thì không. Trong trường hợp này chúng ta sẽ sử dụng lệnh On Error Goto 0.

Khi sử dụng lệnh này chúng ta sẽ reset lại cài đặt lỗi về trạng thái mặc định ban đầu, tức là lỗi sẽ hiển thị (nếu có).

Ví dụ, đoạn mã bên dưới đây sẽ không có lỗi trong trường hợp nếu không có ô trống nhưng sẽ có thông báo lỗi hiển thị vì "10/0".

Sub SelectFormulaCells()
On Error Resume Next
Selection.SpecialCells(xlCellTypeBlanks).Select
On Error GoTo 0
' .. more code that can contain error
End Sub

3. Lệnh On Error Goto Label

Bản chất các lệnh On Error Resume Next và On Error Goto 0 không phải là sửa lỗi mà là cho phép bỏ qua lỗi và tiếp tục kiểm tra lỗi.

Bằng cách sử dụng lệnh On Error Go [Label] để chỉ định những gì mà bạn muốn làm trong trường hợp nếu mã xảy ra lỗi.

Cấu trúc mã sử dụng lệnh này để xử lý lỗi có dạng như dưới đây:

Sub Test()
On Error GoTo Label:
X = 10 / 0 'dòng này gây ra lỗi
' .... mã còn lại
Exit Sub
Label:
' mã để xử lý lỗi
End Sub

Lưu ý: Trước mã Label là Exit Sub. Điều này để đảm bảo trong trường hợp nếu không có lỗi xảy ra, chúng ta sẽ thoát Sub và mã Label không được thực thi. Trong trường hợp nếu không sử dụng Exit Sub, nó sẽ luôn luôn thực thi mã Label.

Trong đoạn mã ví dụ bên dưới đây khi có lỗi xảy ra, mã sẽ nhảy và thực thi mã trong phần xử lý lỗi:

Sub Errorhandler()
On Error GoTo ErrMsg
X = 12
Y = 20 / 0
Z = 30
Exit Sub
ErrMsg:
MsgBox "có lỗi xảy ra" & vbCrLf & Err.Description
End Sub

Lưu ý: Khi xảy ra lỗi, mã đã chạy và thực thi các dòng trước dòng gây ra lỗi. Trong ví dụ trên, mã thiết lập giá tri của X là 12, nhưng do lỗi xảy ra ở dòng tiếp theo nên nó không thiết lập giá trị cho Y và Z.

Khi nảy đến mã xử lý lỗi (trong ví dụ trên là ErrMsg), nó sẽ tiếp tục thực thi tất cả các dòng trong và bên dưới mã xử lý lỗi và thoát khỏi Sub.

4. Lệnh On Error Goto -1

Lệnh này hơi phức tạp một chút, và trong hầu hết các trường hợp người dùng ít khi sử dụng đến lệnh này. Dưới đây Taimienphi.vn sẽ giải thích qua cho bạn về cách sử dụng lệnh On Error Goto -1 để sửa lỗi VBA trong Excel.

Giả sử nếu đoạn mã của bạn đang xảy ra lỗi nhưng đã được khắc phục bằng cách sử dụng trình xử lý mã lỗi tại chỗ. Nhưng nếu có một lỗi khác xảy ra trong trình xử lý mã lỗi tại chỗ.

Trong trường hợp này bạn không thể sử dụng trình xử lý lỗi thứ 2 vì lỗi đầu tiên chưa được sửa. Vì vậy trong khi xử lý lỗi đầu tiên, lỗi này vẫn tồn tại trong bộ nhớ VBA. Và bộ nhớ VBA chỉ có thể chứa một lỗi duy nhất.

Giải pháp trong trường hợp này là sử dụng lệnh On Error Goto -1. Lệnh này sẽ xóa lỗi và giải phóng bộ nhớ VBA để xử lý lỗi tiếp theo.

Để dễ hình dung, bạn đọc cùng tham khảo một số ví dụ bên dưới đây:

Đoạn mã dưới đây sẽ trả về thông báo lỗi vì không thể chia cho số 0:

Sub Errorhandler()
X = 12
Y = 20 / 0
Z = 30
End Sub

Vì vậy, để xử lý nó, tôi sử dụng mã xử lý lỗi (với tên ErrMsg) như hình dưới đây:

Sub Errorhandler()
On Error GoTo ErrMsg
X = 12
Y = 20 / 0
Z = 30
Exit Sub
ErrMsg:
MsgBox "có lỗi xảy ra" & vbCrLf & Err.Description
End Sub

Ngay sau khi lỗi xảy ra, trình xử lý lỗi được sử dụng và hiển thị thông báo lỗi như hình dưới đây:

Tiếp theo chúng ta mở rộng mã để thêm mã trong hoặc sau trình xử lý lỗi:

Sub Errorhandler()
On Error GoTo ErrMsg
X = 12
Y = 20 / 0
Z = 30
Exit Sub
ErrMsg:
MsgBox "Có lỗi xảy ra" & vbCrLf & Err.Description
A = 10 / 2
B = 35 / 0
End Sub

Vì lỗi đầu tiên đã được xử lý nhưng lỗi thứ 2 thì chưa, trên màn hình tiếp tục hiển thị thông báo lỗi như hình dưới đây:

Tuy nhiên mã vẫn đang hoạt động theo cách mà chúng ta mong muốn. Để xử lý lỗi thứ 2, chúng ta sử dụng trình xử lý lỗi khác (ErrMsg2).

Sub Errorhandler()
On Error GoTo ErrMsg
X = 12
Y = 20 / 0
Z = 30
Exit Sub
ErrMsg:
MsgBox "Có lỗi xảy ra" & vbCrLf & Err.Description
On Error GoTo ErrMsg2
A = 10 / 2
B = 35 / 0
Exit Sub
ErrMsg2:
MsgBox "Có lỗi xảy ra" & vbCrLf & Err.Description
End Sub

Nếu chạy đoạn mã trên, nó vẫn sẽ trả về lỗi run-time ngay cả khi chúng ta đã có trình xử lý lỗi thứ 2.

Lỗi này xảy ra khi chúng ta xóa lỗi đầu tiên từ bộ nhớ VBA.

Khi VBA gặp phải lỗi khác, nó vẫn bị lỗi với lỗi đầu tiên, vì vậy trình xử lý lỗi thứu 2 không được sử dụng. Mã dừng chạy ở dòng gây ra lỗi và hiển thị thông báo lỗi.

Để xóa bộ nhớ VBA và xóa lỗi trước đó, chúng ta sẽ sử dụng lệnh On Error Goto -1.

Khi thêm lệnh này vào đoạn mã dưới đây và chạy, mã sẽ hoạt động như mong đợi:

Sub Errorhandler()
On Error GoTo ErrMsg
X = 12
Y = 20 / 0
Z = 30
Exit Sub
ErrMsg:
MsgBox "Có lỗi xảy ra" & vbCrLf & Err.Description
On Error GoTo -1
On Error GoTo ErrMsg2
A = 10 / 2
B = 35 / 0
Exit Sub
ErrMsg2:
MsgBox "Có lỗi xảy ra" & vbCrLf & Err.Description
End Sub

Lưu ý: Lỗi sẽ tự động được xóa khi chương trình con (subroutine) kết thúc. Vì vậy lệnh On Error Goto -1 có thể hữu ích trong trường hợp nếu chúng ta đang gặp phải một hoặc nhiều lỗi trong cùng một chương trình con.

Qua bài viết này, Taimienphi.vn hy vọng bạn sẽ nắm rõ và biết cách xử lý lỗi VBA bằng các lệnh On Error. Ngoài ra, còn rất nhiều lỗi VBA khác mà chúng tôi đã chia sẻ trong bài viết Tất tần tật cách sửa lỗi VBA trong Excel, bạn nên tìm hiểu và không nên bỏ qua nhé.

Nếu bạn hay làm việc với VBA thì việc gặp lỗi khi sử dụng là điều khó tránh khỏi. Do vậy, bạn cần phải biết cách để bẫy lỗi khi viết code cũng như biết cách xử lý một số lỗi hay gặp phải... Hãy tham khảo nội dung dưới đây để biết cách xử lý lỗi VBA bằng các lệnh On Error.
Tìm hiểu các thuộc tính và phương thức đối tượng Err
Virtual DJ Pro - Xử lý lỗi "Protection error 8"
Xóa dòng trống trắng trong Excel bằng VBA Marco 2007 2010 2013
Sửa lỗi Network Connection Error Free Fire, lỗi kết nối mạng
iTunes - Xử lý lỗi "Unknown error occurred (0xE8000012)"
HJSplit - Khắc phục, fix lỗi "I/O error 123"

ĐỌC NHIỀU