Lỗi Là Gì
Bạn chạy một macro và lập tức thấy hộp thoại này:
Run-time error '13': Type Mismatch
VBA tô vàng một dòng code. Macro dừng lại. Bạn ngồi nhìn chằm chằm vào code tự hỏi biến nào vừa gây ra vấn đề.
Chuyện gì thực sự xảy ra: VBA đang cố gán hoặc so sánh một giá trị không khớp với kiểu dữ liệu đã khai báo. Ví dụ điển hình — nhét một chuỗi văn bản vào biến Integer, hoặc thực hiện phép tính trên một ô chứa "N/A" thay vì số.
Các Tình Huống Thường Gặp
- Ô mà macro đọc chứa giá trị lỗi (
#VALUE!,#N/A,#REF!) thay vì số. - Ô chứa văn bản trông có vẻ là số (
"123"), nhưng biến được khai báo làIntegerhoặcLongmà không có hàm chuyển đổi. - Bạn đang thực hiện thao tác mảng trên một biến thông thường không phải mảng.
- Một hàm trả về
NullhoặcEmptyvà bạn đưa thẳng vào biến có kiểu dữ liệu cụ thể. - Ô chứa chuỗi ngày tháng theo định dạng vùng miền mà VBA không thể tự chuyển đổi — ví dụ:
"12.05.2026"trên máy dùng locale Đức.
Cách Chẩn Đoán Nhanh
Khi hộp thoại lỗi xuất hiện, nhấn Debug — đừng nhấn End. VBA sẽ tô vàng dòng gây lỗi. Rê chuột qua từng biến trên dòng đó để xem giá trị hiện tại trong tooltip.
Cần kiểm tra một ô trước khi xảy ra lỗi? Gõ lệnh này vào Immediate Window (Ctrl+G):
' Trong Immediate Window, gõ:
? TypeName(ActiveSheet.Range("B2").Value)
? ActiveSheet.Range("B2").Value
Nếu in ra Error 2042 (tức là #N/A trong VBA) hoặc String khi bạn mong đợi Double, thì bạn đã tìm ra thủ phạm rồi.
Cách Sửa 1 — Kiểm Tra Lỗi Trong Ô
Ô chứa lỗi công thức là nguyên nhân phổ biến nhất. Macro đọc phải #VALUE! hoặc #N/A và lập tức bị lỗi. Hãy dùng IsError() để kiểm tra trước khi làm bất cứ điều gì:
Dim cellVal As Variant
cellVal = ActiveSheet.Range("B2").Value
If IsError(cellVal) Then
MsgBox "Cell B2 has an error: " & CStr(cellVal)
Exit Sub
End If
' Dùng an toàn ở đây
Dim total As Double
total = CDbl(cellVal)
Lưu ý biến được khai báo là Variant trước. Luôn đọc các ô có thể có lỗi vào Variant trước khi kiểm tra — đừng bao giờ đọc thẳng vào biến có kiểu cụ thể.
Cách Sửa 2 — Chuyển Đổi Kiểu Dữ Liệu Rõ Ràng
Việc chuyển đổi ngầm của VBA rất dễ xảy ra lỗi. Một ô hiển thị 123 thực chất có thể lưu dạng text — và VBA không báo cho bạn biết cho đến khi bị crash. Hãy dùng hàm chuyển đổi tường minh:
' Rủi ro — crash nếu ô chứa text
Dim qty As Integer
qty = Range("C5").Value
' An toàn
Dim qty As Integer
If IsNumeric(Range("C5").Value) Then
qty = CInt(Range("C5").Value)
Else
MsgBox "Expected a number in C5, got: " & Range("C5").Value
Exit Sub
End If
Bộ công cụ đầy đủ: CInt(), CLng(), CDbl(), CStr(), CDate(), CBool(). Mỗi hàm sẽ báo lỗi rõ ràng nếu việc chuyển đổi thực sự thất bại — dễ debug hơn nhiều so với lỗi Type Mismatch mơ hồ.
Cách Sửa 3 — Dùng Variant Cho Dữ Liệu Không Xác Định
Đang duyệt qua một vùng ô mà một số ô có thể rỗng, là text, hoặc công thức bị lỗi? Khai báo biến lặp là Variant và lọc trong quá trình chạy:
Dim cell As Range
Dim total As Double
total = 0
For Each cell In ActiveSheet.Range("B2:B100")
If Not IsError(cell.Value) And IsNumeric(cell.Value) Then
total = total + CDbl(cell.Value)
End If
Next cell
MsgBox "Total: " & total
Các ô lỗi sẽ bị bỏ qua. Không crash. Vòng lặp chạy trơn tru dù 30 trong 99 ô chứa #N/A.
Cách Sửa 4 — Vấn Đề Với Kiểu Ngày Tháng
Ngày tháng là bẫy ngầm. Ô được định dạng text chứa "05/12/2026" sẽ gây crash trên hệ thống không phải tiếng Anh nếu bạn gán trực tiếp vào biến Date — VBA không biết đó là ngày 12 tháng 5 hay ngày 5 tháng 12.
' Có vấn đề
Dim d As Date
d = Range("A1").Value ' Crash nếu ô được định dạng text
' An toàn
Dim rawVal As Variant
rawVal = Range("A1").Value
If IsDate(rawVal) Then
Dim d As Date
d = CDate(rawVal)
Else
MsgBox "A1 is not a valid date: " & rawVal
End If
Cách Sửa 5 — Gán Object So Với Gán Giá Trị
Quên từ khóa Set và bạn sẽ gặp Type Mismatch trông hoàn toàn không liên quan đến kiểu dữ liệu:
' Type Mismatch — thiếu Set
Dim ws As Worksheet
ws = ThisWorkbook.Sheets("Data") ' SAI
' Đúng
Set ws = ThisWorkbook.Sheets("Data")
Khi không có Set, VBA lấy thuộc tính mặc định của object — chuỗi tên sheet — và cố nhét vào biến kiểu Worksheet. Lỗi xảy ra ngay. Luôn dùng Set cho các object.
Giải Pháp Lâu Dài — Mẫu Đọc Dữ Liệu An Toàn
Với bất kỳ macro nào đọc dữ liệu do người dùng nhập, hãy tập trung việc kiểm tra vào một hàm helper. Viết một lần, dùng ở khắp nơi:
Function SafeReadNumeric(ws As Worksheet, cellAddr As String) As Variant
Dim v As Variant
v = ws.Range(cellAddr).Value
If IsError(v) Then
SafeReadNumeric = CVErr(xlErrValue) ' Truyền lỗi lên trên
ElseIf Not IsNumeric(v) Or IsEmpty(v) Then
SafeReadNumeric = CVErr(xlErrValue)
Else
SafeReadNumeric = CDbl(v)
End If
End Function
' Cách dùng:
Dim price As Variant
price = SafeReadNumeric(ActiveSheet, "D5")
If IsError(price) Then
MsgBox "D5 doesn't have a valid number."
Exit Sub
End If
Kiểm Tra Sau Khi Sửa
- Đóng hộp thoại lỗi, áp dụng bản sửa, nhấn F5 để chạy lại.
- Cố tình nhập dữ liệu sai — gõ
abcvào ô mà macro đọc — và xác nhận rằng phần kiểm tra bắt được lỗi một cách nhẹ nhàng thay vì crash. - Thử nghiệm với ô chứa
#N/Ahoặc#VALUE!. Kiểm traIsError()của bạn phải xử lý được mà không báo lỗi. - Nếu macro chạy xong không có hộp thoại đỏ và cho kết quả đúng, là bạn đã xong.
Tóm Tắt
Lỗi Run-time error '13' hầu như luôn xuất phát từ việc đọc dữ liệu từ worksheet mà không kiểm tra trước. Các ô có thể chứa giá trị lỗi, text bất ngờ, hoặc chuỗi rỗng — và hệ thống kiểu dữ liệu của VBA không tha thứ cho bất kỳ sự không khớp nào.
Mẫu xử lý cho 90% trường hợp: đọc vào Variant, kiểm tra bằng IsError() / IsNumeric() / IsDate(), rồi chuyển đổi tường minh bằng CInt(), CDbl(), hoặc CDate(). Chỉ vậy thôi. Nắm vững thói quen này và lỗi Type Mismatch sẽ trở thành khách hiếm chứ không phải kẻ quấy rầy thường xuyên nữa.

