Gói gọn xử lý lỗi
Để bạn nắm rõ cách thức xử lý lỗi, tôi làm một bản tóm tắt ngắn gọn và … khó nhớ. một thủ tục xử lý lỗi có các đặc điểm sau:
• Được thực hiện ngay sau nhãn được xác định trong câu lệnh On Error
• Chỉ nên được kích hoạt khi macro của bạn phát sinh lỗi. điều này có nghĩa là bạn phải sử dụng một câu lệnh như Exit Sub hoặc Exit Function ngay lập tức trước khi đến nhãn xử lý lỗi.
• Có thể bạn cần câu lệnh Resume. Nếu bạn không muốn chấm dứt thủ tục khi phát sinh lỗi, bạn phải kích hoạt câu lệnh Resume trước khi quay về thủ tục chính.
Biết khi nào thì nên bỏ qua lỗi
Trong một vài trường hợp, chúng ta hoàn toàn có thể bỏ qua lỗi. khi đó ta sử dụng câu lệnh Resume Next.
Ví dụ sau chạy qua tất cả các ô trong một vùng được chọn và khai căn bậc hai tất cả các giá trị. Thủ tục này sẽ báo lỗi nếu gặp bất kỳ một ô nào chứa số âm.
Sub SelelectionSqrt()
Dim cell As Range
If TypeName(Selection) <> "Range" Then Exit Sub
For Each cell In Selection
cell.Value = Sqr(cell.Value)
Next cell
End Sub
Trong trường hợp này, bạn có thể muốn đơn giản là bỏ qua tất cả những ô chứa giá trị mà bạn không thể khai căn. Bạn có thể liệt kê tất cả những lỗi phát sinh bằng cách sử dụng If-Then, nhưng bạn có thể đưa ra một phương pháp tốt hơn bằng cách đơn giản là bỏ qua những lỗi này.
Đoạn mã sau thể hiện điều này thông qua việc sử dụng On Error Resume Next:
Sub SelelectionSqrt()
Dim cell As Range
If TypeName(Selection) <> "Range" Then Exit Sub
On Error Resume Next
For Each cell In Selection
cell.Value = Sqr(cell.Value)
Next cell
End Sub
Một cách tổng quát, bạn có thể sử dụng On Error Resume Next nếu bạn thấy rằng lỗi không ảnh hưởng đến mục tiêu của bạn.
Xác định lỗi cụ thể
Không phải mọi lỗi đều như nhau. Có những loại lỗi nghiêm trọng, có những loại ít nghiêm trọng hơn. Mặc dù bạn có thể bỏ qua lỗi mà bạn cho là không quan trọng, bạn vẫn phải xử lý những lỗi còn lại (nếu thằng lỗi nghiêm trọng ấy). trong một vài trường hợp bạn cần xác định những lỗi cụ thế phát sinh.
Khi một lỗi phát sinh, Excel lưu mã số lỗi vào một Object lỗi gọi là Err. Thuộc tính Number của Object này chứa mã số lỗi. bạn có thể tìm được diễn giải của lỗi này thông qua hàm VBA Error. Ví dụ, câu lệnh sau hiển thị mã lỗi và diễn giải:
MsgBox Err.Number & ": " & Error(Err.Number)
Hình 12-6 thể hiện ví dụ trên. Nên nhớ rằng thông báo lỗi của Excel không hữu ích gì cho lắm.
Thủ tục sau minh họa làm thế nào để xác định lỗi nào phát sinh. Trong trường hợp này, bạn có thể yên tâm bỏ qua những lỗi do gặp phải khi cố khai căn số âm (error 5), hoặc những lỗi gặp phải do khai căn các ký tự (error 13). Nói cách khác, bạn cần phải thông báo cho người dùng biết nếu Worksheet bị protect và vùng được lựa chọn có những ô bị khóa. (Nếu không người dùng có thể nghĩ là macro đã làm xong việc trong khi thực tế nó không làm). Sự kiện này gây ra lỗi 1004
Sub SelelectionSqrt()
Dim cell As Range
Dim ErrMsg As String
If TypeName(Selection) <> "Range" Then Exit Sub
On Error GoTo ErrorHandler
For Each cell In Selection
cell.Value = Sqr(cell.Value)
Next cell
Exit Sub
ErrorHandler:
Select Case Err
Case 5 'So Am
Resume Next
Case 13 'Sai loai. Vi du nhu ky tu chu
Resume Next
case1004 'O bi khoa, sheet bi protect
MsgBox "O bi khoa roi ban oi. Thu lai lan nua di"
Exit Sub
Case Else
ErrMsg = Error(Err.Number)
MsgBox "ERROR: " & ErrMsg
Exit Sub
End Select
End Sub
Khi lỗi run-time error phát sinh, thủ tục sẽ nhảy đến nhãn ErrorHandler. Cấu trúc Select Case duyệt qua 3 lỗi thông dụng. nếu lỗi là 5 hoặc 13, thủ tục sẽ quay lại xử lý ô kế tiếp (nói cách khác, lỗi được bỏ qua). Nếu lỗi là 1004, thủ tục sẽ thông báo cho người dùng và ngưng lại. trường hợp cuối cùng, xử lý mọi trường hợp lỗi còn lại, thủ tục sẽ bẫy mọi lỗi và hiển thị thông báo lỗi cụ thể.
Lỗi cố ý
Đôi khi bạn sử dụng lỗi để làm những việc mình muốn. ví dụ bạn có một macro chỉ chạy được khi có một Workbook nào đó đang mở. làm sao bạn biết được Workbook đó đã được mở chưa? Có lẽ giải pháp tốt nhất là viết một hàm tổng quát nhận một tham số (là tên Workbook) và trả lại giá trị True nếu Workbook ấy đang mở, false nếu Workbook ấy đang đóng.
Đây là hàm nói trên :
Function WorkBookOpen(book As String) As Boolean
Dim WBName As String
On Error GoTo notopen
WBName = Workbooks(book).Name
WorkBookOpen = True
Exit Function
notopen:
WorkBookOpen = False
End Function
Hàm này lợi dùng đặc điểm là Excel sẽ báo lỗi nếu bạn tham chiếu đến một Workbook chưa được mở. ví dụ câu lệnh dưới đây sẽ báo lỗi nếu Workbook tên là “MyWorkbook.xls” không được mở:
WBName = Workbooks(MyWorkbook.xls).Name
Trong hàm WorkBookOpen, câu lệnh On Error yêu cầu VBA nhảy đến notopen nếu có lỗi phát sinh. Do đó, cứ có lỗi thì có nghĩa là Workbook chưa được mở, và hàm sẽ trả lại giá trị False. Nếu Workbook đang mở, không có lỗi và hàm này sẽ trả lại giá trị True.
Đây lại là một biến thể khác của hàm WorkBookOpen. PHiên bản này sử dụng On Error Resume Next để bỏ qua những lỗi phát sinh. Nhưng đoạn mã lại kiểm tra thuộc tính của mã Err. Nếu thuộc tính Err.Number là 0 tức là không có lỗi và Workbook đang được mở. nếu Err.Number là bất cứ số nào khác, có nghĩa là lỗi đã phát sinh (và Workbook hiện không ở trạng thái mở)
Function WorkBookOpen(book As String) As Boolean
Dim WBName As String
On Error Resume Next
WBName = Workbooks(book).Name
If Err.Number = 0 Then WorkBookOpen = True_
Else: WorkBookOpen = False
End Function
Ví dụ dưới đây minh họa cách sử dụng hàm này trong một thủ tục:
Sub macro1()
If not workbookopen(“Prices.xls”) then
Msgbox “Hay mo Workbook Price”
Exit sub
End if
‘ Các đoạn mã khác ….
End sub
Macro1 (phải nằm trong cùng một project với WorkbookOpen) gọi hàm WorkbookOpen và lấy tên của Workbook (Price.xls) chuyển làm tham số cho hàm. Hàm WorkbookOpen sẽ trả lại hai giá trị True hoặc False. Do đó, nếu Workbook chưa được mở, thủ tục sẽ báo lại người dùng biết. nếu Workbook đang mở, macro sẽ tiếp tục chạy.
Xử lý lỗi là một vấn đề hắc búa, có rất nhiều lỗi phát sinh mà bạn không thể lường trước. nhìn chung, bạn nên bẫy lỗi và xử lý các tình huống trước khi Excel xen vào (nếu có thể được). viết những đoạn mã bẫy lỗi yêu cầu cần phải có một nội công thâm hậu về Excel và một vốn hiểu biết rõ ràng về việc VBA xử lý lỗi như thế nào. Chương kế tiếp sẽ bao gồm những ví dụ về việc xử lý lỗi.