Sửa lỗi 'Automation error: The object invoked has disconnected from its clients' trong VBA Excel

intermediate📊 Microsoft Excel2026-06-01| Microsoft Excel 2016/2019/2021/365, Windows 10/11, VBA macro sử dụng COM automation hoặc tham chiếu workbook chéo

Error Message

Run-time error '-2147417848 (80010108)': Automation error The object invoked has disconnected from its clients
#vba#automation#excel-error#runtime-error

TL;DR — Sửa Nhanh

Nói ngắn gọn: code của bạn đang giữ tham chiếu đến một đối tượng Excel — Workbook, Worksheet, Range — không còn tồn tại nữa. Workbook đã đóng, COM server bị crash, hoặc Excel bị tắt trong khi macro vẫn đang chạy. Hãy lấy lại tham chiếu mới trước mỗi lần sử dụng và thêm kiểm tra để xác nhận đối tượng vẫn còn sống.

Mẫu code nhanh giải quyết hầu hết các trường hợp:

Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")  ' Lấy lại mỗi lần dùng

' Kiểm tra trước khi dùng
If Not ws Is Nothing Then
    ws.Range("A1").Value = "Hello"
End If

Nguyên Nhân Gây Ra Lỗi Này

Về bản chất, 0x80010108 là lỗi COM/DCOM — cụ thể là RPC_E_DISCONNECTED. Windows ném ra lỗi này ngay khi VBA cố gọi một phương thức hoặc đọc thuộc tính trên một đối tượng mà COM server đã tắt.

Chín trong mười trường hợp, một trong các tình huống sau đã gây ra lỗi:

  • Một workbook bị đóng trong khi code vẫn còn biến Workbook hoặc Worksheet trỏ đến nó.
  • Bạn mở Excel qua CreateObject("Excel.Application") hoặc GetObject() từ một ứng dụng Office khác (Access, Word, Outlook), và instance Excel đó tắt giữa chừng.
  • Một vòng lặp chạy lâu để lại tham chiếu đối tượng cũ sau khi người dùng đóng workbook thủ công.
  • Một biến cấp module hoặc biến toàn cục giữ tham chiếu đến đối tượng đã bị đóng trước lần chạy macro tiếp theo.
  • COM server của Excel bị crash hoặc bị tắt cưỡng bức — kill bằng Task Manager, hết bộ nhớ, hoặc crash hoàn toàn — trong khi đang tự động hóa.

Cách Sửa 1 — Lấy Lại Tham Chiếu Đối Tượng (Phổ Biến Nhất)

Dừng việc lưu cache tham chiếu đối tượng qua các lần gọi thủ tục. Tra cứu workbook và worksheet mới mỗi lần cần dùng — chỉ tốn thêm một dòng và ngăn hoàn toàn lỗi này.

Mẫu lỗi (tham chiếu cũ):

' Biến cấp module — nguy hiểm
Dim gSheet As Worksheet

Sub Init()
    Set gSheet = Workbooks("Data.xlsx").Worksheets("Report")
End Sub

Sub ProcessData()
    ' Nếu Data.xlsx đã đóng từ lúc Init() chạy, dòng này sẽ crash
    gSheet.Range("A1").Value = "Done"  ' Lỗi -2147417848 ở đây
End Sub

Mẫu đã sửa (lấy tham chiếu mới mỗi lần):

Sub ProcessData()
    Dim wb As Workbook
    Dim ws As Worksheet

    ' Kiểm tra workbook có đang mở không trước khi truy cập
    On Error Resume Next
    Set wb = Workbooks("Data.xlsx")
    On Error GoTo 0

    If wb Is Nothing Then
        MsgBox "Data.xlsx chưa được mở. Vui lòng mở file và thử lại."
        Exit Sub
    End If

    Set ws = wb.Worksheets("Report")
    ws.Range("A1").Value = "Done"
End Sub

Cách Sửa 2 — Kiểm Tra Đối Tượng Trong Vòng Lặp Dài

Vòng lặp chạy lâu là một cái bẫy. Xử lý được mười nghìn dòng rồi người dùng đóng Data.xlsx, macro của bạn sẽ vui vẻ crash ở lần gọi ws.Cells() tiếp theo. Kiểm tra xem workbook có còn sống không sau mỗi trăm vòng lặp.

Function IsWorkbookOpen(wbName As String) As Boolean
    Dim wb As Workbook
    On Error Resume Next
    Set wb = Workbooks(wbName)
    On Error GoTo 0
    IsWorkbookOpen = Not (wb Is Nothing)
End Function

Sub ProcessRows()
    Dim i As Long
    Dim ws As Worksheet

    For i = 1 To 10000
        ' Kiểm tra lại mỗi 100 dòng
        If i Mod 100 = 0 Then
            If Not IsWorkbookOpen("Data.xlsx") Then
                MsgBox "Workbook đã bị đóng. Dừng tại dòng " & i
                Exit For
            End If
            ' Lấy lại tham chiếu sau khi kiểm tra
            Set ws = Workbooks("Data.xlsx").Worksheets("Sheet1")
        End If

        ws.Cells(i, 1).Value = i
    Next i
End Sub

Cách Sửa 3 — Tự Động Hóa Giữa Các Ứng Dụng (Access/Word → Excel)

Điều khiển Excel từ Access hoặc Word tạo thêm một kiểu lỗi hoàn toàn mới. Excel có thể crash, bị hệ điều hành kill, hoặc đơn giản là timeout — để lại biến xlApp của bạn trỏ vào bóng ma. Một trình xử lý lỗi GoTo thực sự, không phải On Error Resume Next dạng inline, là cách duy nhất để dọn dẹp đáng tin cậy.

' Chạy từ Access VBA hoặc Word VBA
Sub ExportToExcel()
    Dim xlApp As Object
    Dim xlWb As Object
    Dim xlWs As Object

    On Error GoTo Cleanup

    ' Tạo một instance Excel mới
    Set xlApp = CreateObject("Excel.Application")
    xlApp.Visible = True

    Set xlWb = xlApp.Workbooks.Add
    Set xlWs = xlWb.Worksheets(1)

    xlWs.Range("A1").Value = "Exported Data"

    xlWb.SaveAs "C:\Reports\output.xlsx"
    xlWb.Close False
    xlApp.Quit

    Set xlWs = Nothing
    Set xlWb = Nothing
    Set xlApp = Nothing
    Exit Sub

Cleanup:
    MsgBox "Tự động hóa Excel thất bại: " & Err.Description
    ' Luôn dọn dẹp ngay cả khi có lỗi
    If Not xlApp Is Nothing Then
        On Error Resume Next
        xlApp.Quit
        Set xlApp = Nothing
    End If
End Sub

Ba quy tắc cần ghi nhớ:

  • Luôn gọi xlApp.Quit trong phần dọn dẹp — các instance Excel bị rò rỉ sẽ tích tụ trong Task Manager và khiến mọi lần tự động hóa tiếp theo đều thất bại.
  • Đặt biến đối tượng về Nothing theo thứ tự ngược lại: Worksheet → Workbook → Application.
  • Dùng trình xử lý lỗi GoTo cho phần thân chính, không dùng On Error Resume Next — lỗi im lặng che giấu chính xác nơi xảy ra sự cố.

Cách Sửa 4 — Xử Lý Lỗi Và Thử Lại

Script chạy không giám sát không thể hiện hộp thông báo lúc 3 giờ sáng. Bắt lỗi -2147417848 cụ thể, dừng hai giây, rồi thử lại trước khi bỏ cuộc:

Sub RobustWrite(targetCell As String, value As Variant)
    Const MAX_RETRIES As Integer = 3
    Dim attempt As Integer
    Dim ws As Worksheet

    For attempt = 1 To MAX_RETRIES
        On Error GoTo RetryHandler
        Set ws = ThisWorkbook.Worksheets("Output")
        ws.Range(targetCell).Value = value
        On Error GoTo 0
        Exit For  ' Thành công — thoát vòng lặp

RetryHandler:
        If Err.Number = -2147417848 Then
            ' COM bị ngắt kết nối — chờ và thử lại
            Application.Wait Now + TimeValue("00:00:02")
            Err.Clear
            Resume Next
        Else
            ' Lỗi khác — không bỏ qua
            Err.Raise Err.Number, Err.Source, Err.Description
        End If
    Next attempt
End Sub

Cách Sửa 5 — Sự Kiện Cấp Workbook Gây Ra Lỗi

Các sự kiện workbook và worksheet có thể khiến bạn bị bất ngờ. Vào lúc Workbook_BeforeClose hoặc Worksheet_Deactivate kích hoạt, Excel đã bắt đầu đóng đối tượng. Tham chiếu range của bạn về mặt kỹ thuật vẫn còn đó — nhưng không đáng tin cậy. Chuyển mọi cập nhật hiển thị sang sự kiện sớm hơn, an toàn hơn.

' SAI — sheet đang hủy kích hoạt, tham chiếu range có thể bị ngắt
Private Sub Worksheet_Deactivate()
    Me.Range("A1").Interior.Color = RGB(255, 0, 0)  ' Có thể ném lỗi 80010108
End Sub

' ĐÚNG — dùng cờ và xử lý trong sự kiện an toàn hơn
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    ' Thực hiện cập nhật hiển thị khi sheet vẫn còn hoạt động đầy đủ
    Me.Range("A1").Interior.Color = RGB(255, 0, 0)
End Sub

Xác Nhận — Kiểm Tra Bản Sửa Đã Hoạt Động

  • Mở VBA Editor (Alt+F11) và đặt breakpoint tại dòng trước đây bị crash.
  • Chạy macro bằng F5. Khi dừng tại breakpoint, mở Immediate Window (Ctrl+G) và gõ ? ws Is Nothing (thay bằng tên biến thực của bạn). Kết quả phải in ra False.
  • Xóa breakpoint và chạy toàn bộ macro. Không có hộp thoại lỗi nghĩa là bản sửa đã hoạt động.
  • Đối với tự động hóa giữa các ứng dụng: mở Task Manager → tab Details sau khi macro chạy xong. Không có tiến trình EXCEL.EXE mồ côi nào nghĩa là code dọn dẹp của bạn đang làm tốt việc của mình.

Tóm Tắt

  • Lỗi -2147417848 (80010108) = code của bạn đang gọi một đối tượng COM đã ngắt kết nối.
  • Hầu hết các bản sửa: lấy lại tham chiếu đối tượng thay vì cache nó, và kiểm tra bằng Is Nothing trước khi sử dụng.
  • Đối với tự động hóa giữa ứng dụng: luôn Quit + Set Nothing trong trình xử lý dọn dẹp.
  • Đối với trình xử lý sự kiện: tránh truy cập đối tượng sheet trong các sự kiện Deactivate hoặc BeforeClose.

Related Error Notes