Sửa lỗi VBA Runtime Error 1004: Application-defined or Object-defined Error trong Excel Macro

intermediate📊 Microsoft Excel2026-03-18| Microsoft Excel 2016, 2019, 2021, Microsoft 365 — Windows 10/11, macOS

Error Message

Run-time error '1004': Application-defined or object-defined error
#excel#vba#macro#runtime-error

Lỗi

Bạn đang chạy một macro Excel và hộp thoại bất ngờ xuất hiện:

Run-time error '1004':
Application-defined or object-defined error

Macro dừng hoàn toàn. Nhấn Debug và VBA tô vàng dòng lệnh gây lỗi — thường là những đoạn liên quan đến Range, Cells, ActiveSheet hoặc lệnh .Select.

Error 1004 là lỗi runtime tổng quát của Excel. Nó có thể mang hàng chục ý nghĩa khác nhau, đó là lý do tại sao nó rất khó chẩn đoán. Tuy nhiên, hầu hết các trường hợp đều rơi vào năm nhóm nguyên nhân. Nhận ra nhóm nào, áp dụng cách sửa tương ứng là xong.

Nguyên nhân

  • Tham chiếu đến range trên sheet không phải sheet đang active khi dùng .Select hoặc .Activate
  • Gọi .Select trên range thuộc workbook hoặc sheet khác với sheet đang active
  • Ghi vào sheet đang được bảo vệ
  • Dùng địa chỉ range không hợp lệ — chuỗi rỗng, số hàng vượt quá 1.048.576 hoặc số cột vượt quá 16.384
  • Truy cập named range không tồn tại trong workbook
  • Dán vào vùng ô được merge khi kích thước dán không khớp
  • Gọi AutoFill, Sort hoặc PasteSpecial trên range rỗng hoặc không khớp

Cách sửa 1 — Ngừng dùng .Select và .Activate (Cách sửa phổ biến nhất)

Kết quả từ macro recorder là thủ phạm số 1. Khi bạn record một macro, Excel tạo ra code như thế này:

Sheets("Data").Select
Range("A1").Select
Selection.Value = "Hello"

Đoạn code này chỉ hoạt động nếu "Data" đang là sheet active lúc chạy. Ngay khi có thứ khác đang active — sheet khác, workbook khác — nó sẽ ném ra lỗi 1004. Hãy viết lại để tham chiếu trực tiếp đến sheet:

' TRƯỚC (dễ bị lỗi)
Sheets("Data").Select
Range("A1").Select
Selection.Value = "Hello"

' SAU (đáng tin cậy)
Sheets("Data").Range("A1").Value = "Hello"

Đây là mẫu đầy đủ để ghi vào sheet mà không cần active chúng:

Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Data")

ws.Range("A1").Value = "Hello"
ws.Range("B2:B10").ClearContents
ws.Cells(3, 1).Value = 42

Cách sửa 2 — Kiểm tra bảo vệ sheet

Một sheet được bảo vệ sẽ ném ra Error 1004 ngay lập tức khi bạn cố ghi vào — không có ngoại lệ. Hãy bỏ bảo vệ trước khi ghi, rồi bảo vệ lại sau khi xong:

Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Report")

' Bỏ bảo vệ trước khi ghi (dùng mật khẩu nếu có)
ws.Unprotect Password:="yourpassword"

ws.Range("C5").Value = "Updated"

' Bảo vệ lại sau khi xong
ws.Protect Password:="yourpassword"

Nếu bạn không biết mật khẩu và muốn bỏ qua thay vì gặp lỗi:

If Not ws.ProtectContents Then
    ws.Range("C5").Value = "Updated"
Else
    MsgBox "Sheet đang được bảo vệ. Không thể ghi."
End If

Cách sửa 3 — Kiểm tra tham chiếu range trước khi dùng

Một chuỗi rỗng hoặc số hàng ngoài phạm vi sẽ kích hoạt lỗi 1004 ngay lập tức. Giới hạn hàng tối đa của Excel là 1.048.576 — vượt quá con số này là crash. Hãy kiểm tra đầu vào trước:

' Sai: rowNum có thể là 0 hoặc âm
ws.Cells(rowNum, 1).Value = "data"

' Đúng: kiểm tra trước khi dùng
If rowNum >= 1 And rowNum <= ws.Rows.Count Then
    ws.Cells(rowNum, 1).Value = "data"
Else
    MsgBox "Số hàng ngoài phạm vi: " & rowNum
End If

Named range cũng cần xử lý tương tự. Đừng giả sử chúng tồn tại — hãy kiểm tra trước:

Function NamedRangeExists(wb As Workbook, nameStr As String) As Boolean
    Dim nm As Name
    On Error Resume Next
    Set nm = wb.Names(nameStr)
    NamedRangeExists = (Not nm Is Nothing)
    On Error GoTo 0
End Function

' Cách dùng
If NamedRangeExists(ThisWorkbook, "SalesData") Then
    ThisWorkbook.Names("SalesData").RefersToRange.Value = 0
End If

Cách sửa 4 — Sửa lỗi PasteSpecial và AutoFill

PasteSpecial thất bại khi clipboard trống hoặc bạn đang dán vào vùng không tương thích — ô merge là bẫy phổ biến. Luôn copy trước, sau đó chỉ dán giá trị để tránh xung đột định dạng:

' Sao chép nguồn
wsSource.Range("A1:A10").Copy

' Chỉ dán giá trị vào đích (tránh xung đột định dạng)
wsDest.Range("B1").PasteSpecial Paste:=xlPasteValues

' Xóa clipboard sau khi dán
Application.CutCopyMode = False

AutoFill có yêu cầu nghiêm ngặt hơn: range đích phải bắt đầu từ cùng ô với range nguồn. Lệch dù chỉ một chút là bạn sẽ gặp lỗi 1004:

Dim srcRange As Range
Dim fillRange As Range

Set srcRange = ws.Range("A1:A2")
' Range đích phải BẮT ĐẦU từ cùng ô với nguồn
Set fillRange = ws.Range("A1:A10")

srcRange.AutoFill Destination:=fillRange, Type:=xlFillDefault

Cách sửa 5 — Workbook chưa mở hoặc tham chiếu workbook sai

Tham chiếu đến workbook theo tên khi nó chưa mở sẽ khiến Excel ném ra lỗi 1004. Dùng ThisWorkbook khi bạn muốn tham chiếu đến file chứa macro — nó luôn sẵn sàng bất kể những gì khác đang mở:

' Rủi ro: giả sử workbook đã mở và tên chính xác
Workbooks("Report_2024.xlsx").Sheets("Data").Range("A1").Value = 1

' An toàn: tham chiếu workbook chứa macro này
ThisWorkbook.Sheets("Data").Range("A1").Value = 1

' Hoặc dùng vòng lặp để tìm workbook đang mở cụ thể
Dim wb As Workbook
For Each wb In Application.Workbooks
    If wb.Name = "Report_2024.xlsx" Then
        wb.Sheets("Data").Range("A1").Value = 1
        Exit For
    End If
Next wb

Debug: Tìm dòng lỗi chính xác

Khi hộp thoại lỗi xuất hiện, nhấn Debug. VBA sẽ tô vàng dòng gây lỗi. Từ đó:

  • Di chuột qua các biến để xem giá trị hiện tại trong tooltip
  • Mở Immediate Window (Ctrl+G) và gõ ? variableName để kiểm tra giá trị
  • Thêm lệnh Stop ngay trước dòng lỗi để tạm dừng thực thi và kiểm tra trạng thái
' Debug tạm thời — xóa trước khi triển khai
Stop  ' Thực thi dừng lại tại đây
ws.Range(rangeAddress).Value = newValue

Phòng ngừa

  • Tái cấu trúc toàn bộ code macro được record — loại bỏ mọi .Select.Activate trước khi triển khai
  • Luôn khai báo đầy đủ tham chiếu range với biến sheet: ws.Range(...) thay vì chỉ Range(...)
  • Thêm xử lý On Error GoTo trong macro sản xuất để hiển thị thông báo lỗi có nghĩa
  • Bỏ bảo vệ sheet ở đầu mọi macro ghi dữ liệu, bảo vệ lại ở cuối
  • Kiểm tra các giá trị động (số hàng, chuỗi range) trước khi truyền vào lệnh range

Kiểm tra kết quả

Nhấn F5 trong VBA editor để chạy từ đầu. Không có hộp thoại lỗi nghĩa là đã thành công. Sau đó kiểm tra các trường hợp biên:

  • Chạy trên sheet trống
  • Chạy khi sheet được bảo vệ đang active
  • Truyền đầu vào không hợp lệ — số hàng bằng 0, chuỗi range rỗng
  • Xóa mọi lệnh Stop hoặc debug trước khi phát hành phiên bản cuối

Related Error Notes