엑셀 VBA 매크로를 실행할 때 다음과 같은 메시지가 나타날 수 있습니다.
런타임 오류 '438':
개체가 이 속성 또는 메서드를 지원하지 않습니다.
오류 438은 객체 변수가 비어 있다는 뜻이 아닙니다. VBA가 객체를 찾기는 했지만, 해당 객체에서 사용할 수 없는 속성이나 메서드를 점 뒤에 작성했다는 뜻입니다.
따라서 오류가 발생하면 코드를 전부 바꾸기보다 디버그로 멈춘 줄에서 점 왼쪽에 있는 객체와 점 오른쪽에 있는 멤버를 나누어 확인해야 합니다.
|
| 오류 438은 점 왼쪽의 객체와 점 오른쪽의 속성 또는 메서드가 맞지 않을 때 발생합니다. 위 이미지는 오류 구조를 설명하기 위한 대표 개념 이미지입니다. |
이 글은 Microsoft의 VBA 오류 438, 개체 찾아보기, TypeName과 Excel 객체 모델 공식 문서를 기준으로 작성했습니다. 예제의 파일명, 시트명과 범위는 실제 통합 문서에 맞게 변경해야 합니다.
오류 창에서 디버그를 눌러 노란색 줄 확인
오류 438 메시지가 나타났을 때 종료를 누르면 실행이 완전히 중단되어 문제가 된 위치를 다시 찾아야 합니다. 먼저 디버그를 누르세요.
Visual Basic Editor가 열리면서 오류가 발생한 코드가 노란색으로 표시됩니다.
예를 들어 다음 줄에서 멈췄다고 가정하겠습니다.
target.Range("A1").Value = "완료"
이 줄은 점을 기준으로 다음과 같이 나누어 봅니다.
target이 현재 어떤 종류의 객체인지 확인합니다.점 오른쪽
해당 객체가
Range 속성을 지원하는지 확인합니다.
target이 Worksheet라면 Range를 사용할 수
있습니다. 하지만 Workbook이나 다른 종류의 객체라면 같은 코드가 오류
438을 발생시킬 수 있습니다.
오류 91과 438을 먼저 구분하세요
VBA 객체 오류는 메시지가 비슷해 보여도 수정해야 할 위치가 다릅니다.
| 오류 | 의미 | 우선 확인할 내용 |
|---|---|---|
| 오류 91 | 객체 변수가 설정되지 않음 |
Set 누락, Nothing, 실패한 Find 결과
|
| 오류 424 | 객체가 필요한 위치에 올바른 객체가 없음 | 객체 한정자와 변수 선언 |
| 오류 438 | 객체는 있지만 요청한 멤버를 지원하지 않음 | 실제 객체 형식과 속성·메서드 조합 |
오류 438에서는 무조건 Set을 추가하는 방식으로 해결되지
않습니다. 이미 설정된 객체가 무엇인지 확인하고, 그 객체가 점 뒤의 멤버를
실제로 지원하는지 확인해야 합니다.
TypeName으로 점 왼쪽 객체의 실제 형식 확인
변수 이름만 보고 객체 형식을 추측하지 마세요. 특히 변수를
As Object나 Variant로 선언한 코드에서는
실행 중에 실제로 어떤 객체가 들어 있는지 확인해야 합니다.
디버그 상태에서 Ctrl + G를 눌러 직접 실행 창을 연 뒤
다음과 같이 입력합니다.
? TypeName(target)
실행 결과에 따라 확인할 위치가 달라집니다.
WorksheetRange, Cells, Rows처럼
Worksheet가 지원하는 멤버인지 확인합니다.
WorkbookWorksheets, Save, Close처럼
Workbook이 지원하는 멤버인지 확인합니다.
RangeValue, Copy, Offset처럼
Range에서 사용할 수 있는 멤버인지 확인합니다.
객체를 변수에 할당한
Set 줄로 돌아가 잘못된 객체가
들어간 원인을 확인합니다.
직접 실행 창 대신 코드에 다음 줄을 잠시 넣어 실행 로그를 확인할 수도 있습니다.
Debug.Print TypeName(target)
Workbook에서 Range를 직접 호출한 경우
Excel의 객체 구조는 일반적으로 다음 순서로 이어집니다.
Application
└─ Workbook
└─ Worksheet
└─ Range
Range는 Worksheet에서 사용할 수 있는 속성입니다.
Workbook 객체에서 바로 Range를 호출하면 객체 계층이 맞지 않습니다.
오류가 발생할 수 있는 코드
Sub WriteResultWrong()
Dim target As Object
Set target = ThisWorkbook
target.Range("A1").Value = "완료"
End Sub
target에는 Workbook 객체가 들어 있습니다. Workbook은
Range 속성을 직접 지원하지 않으므로 실행 시 오류 438이
발생할 수 있습니다.
Worksheet 객체를 거치도록 수정
Option Explicit
Sub WriteResultCorrect()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Worksheets("결과")
ws.Range("A1").Value = "완료"
End Sub
이 코드에서는 Workbook의 Worksheets에서 Worksheet
객체를 먼저 가져온 뒤, Worksheet의 Range를 사용합니다.
예제의
결과 시트가 실제 파일에 없으면 오류 438이 아니라
일반적으로 첨자 범위 오류 9가 발생합니다. 오류 번호에 따라 점검 위치를
구분하세요.
Range와 Worksheet의 역할을 뒤섞은 경우
변수가 Range 객체를 가리키는데 Worksheet에서만 사용할 수 있는 멤버를 호출해도 문제가 발생할 수 있습니다.
객체 종류와 맞지 않는 코드
Sub CheckObjectWrong()
Dim target As Object
Set target = ThisWorkbook.Worksheets("결과").Range("A1")
Debug.Print target.Worksheets.Count
End Sub
target은 Range입니다. Range 객체에는
Worksheets 컬렉션이 없으므로 객체와 멤버가 맞지 않습니다.
해당 셀이 속한 Worksheet가 필요하다면 Range의
Worksheet 속성을 사용합니다.
Sub CheckObjectCorrect()
Dim target As Range
Dim ws As Worksheet
Set target = ThisWorkbook.Worksheets("결과").Range("A1")
Set ws = target.Worksheet
Debug.Print ws.Name
End Sub
철자가 맞아 보여도 객체가 다르면 오류가 납니다
오류 438을 발견하면 점 오른쪽 이름의 철자만 확인하는 경우가 많습니다. 철자가 정확해도 그 멤버가 다른 객체에 속해 있으면 오류가 발생합니다.
다음 질문을 순서대로 확인하세요.
- 점 왼쪽 변수에는 실제로 어떤 객체가 들어 있는가?
- 점 오른쪽 이름은 속성인가, 메서드인가?
- 그 객체가 해당 속성이나 메서드를 지원하는가?
- 해당 멤버를 사용하기 전에 Worksheet나 Range를 더 거쳐야 하는가?
- 같은 이름의 사용자 정의 함수와 혼동한 것은 아닌가?
예를 들어 Workbook.Close는 Workbook의 메서드이고,
Range.ClearContents는 Range의 메서드입니다. 이름이
올바르더라도 객체의 종류가 맞지 않으면 사용할 수 없습니다.
F2 개체 찾아보기에서 지원 멤버 확인
객체가 어떤 속성과 메서드를 지원하는지 확실하지 않다면 Visual Basic Editor의 개체 찾아보기를 사용합니다.
Alt + F11을 눌러 Visual Basic Editor를 엽니다.F2를 눌러 개체 찾아보기를 엽니다.- 왼쪽 위 라이브러리에서 Excel을 선택합니다.
- 검색창에
Workbook,Worksheet또는Range를 입력합니다. - 클래스를 선택합니다.
- 오른쪽 멤버 목록에서 사용하려는 속성이나 메서드를 찾습니다.
멤버 목록에 이름이 없다면 해당 객체에서는 사용할 수 없습니다. 비슷한 이름의 멤버가 있더라도 매개변수와 반환 형식이 다를 수 있으므로 아래쪽 설명도 함께 확인하세요.
As Object를 구체적인 객체 형식으로 변경
다음처럼 모든 객체를 As Object로 선언하면 실행 전에는
해당 객체가 어떤 멤버를 지원하는지 확인하기 어렵습니다.
Dim wb As Object
Dim ws As Object
Dim target As Object
Excel 내부 객체의 종류를 알고 있다면 다음처럼 구체적으로 선언합니다.
Dim wb As Workbook
Dim ws As Worksheet
Dim target As Range
구체적인 형식으로 선언하면 코드 편집기에서 점을 입력했을 때 사용할 수 있는 멤버 목록이 표시됩니다. 지원하지 않는 멤버를 작성한 경우에는 실행하기 전 컴파일 단계에서 발견할 가능성도 높아집니다.
명시적인 객체 선언 예제
Option Explicit
Sub UpdateStatus()
Dim wb As Workbook
Dim ws As Worksheet
Dim target As Range
Set wb = ThisWorkbook
Set ws = wb.Worksheets("결과")
Set target = ws.Range("B2")
target.Value = "처리 완료"
target.Font.Bold = True
End Sub
Option Explicit도 함께 사용하면 변수 이름의 오타나 선언
누락을 실행 전에 찾는 데 도움이 됩니다.
후기 바인딩으로 바꾸는 것은 일반 해결책이 아닙니다
외부 프로그램을 제어하는 코드에서 참조 문제를 피하기 위해 변수를
As Object로 바꾸라는 안내를 볼 수 있습니다.
이것은 후기 바인딩 방식이며, 특정 배포 상황에서는 사용할 수 있습니다. 그러나 객체가 지원하지 않는 멤버를 자동으로 지원하게 만드는 기능은 아닙니다.
다음 코드에서 externalApp은 실행 시점에 객체가 결정됩니다.
Dim externalApp As Object
Set externalApp = CreateObject("Word.Application")
externalApp.Visible = True
후기 바인딩에서는 코드 작성 중 사용할 수 있는 멤버 목록이 표시되지 않을 수 있습니다. 설치된 프로그램 버전에서 지원하지 않는 멤버를 호출하면 실행 시점에 오류 438이 나타날 수 있습니다.
Excel의 Workbook, Worksheet와 Range처럼 형식을 분명히 알 수 있는 객체는 구체적인 형식으로 선언하는 편이 디버깅에 유리합니다.
참조 누락은 오류 438의 기본 원인이 아닙니다
기존 글에서는 외부 라이브러리의 참조 누락을 오류 438의 핵심 원인처럼
설명했지만, 일반적인 참조 누락은 프로젝트 또는 라이브러리를 찾을
수 없습니다와 같은 별도의 컴파일 문제로 나타날 수 있습니다.
다른 컴퓨터로 파일을 옮긴 뒤 외부 프로그램 관련 코드가 실행되지 않는다면 다음 위치에서 참조 상태를 별도로 확인할 수 있습니다.
Alt + F11로 Visual Basic Editor를 엽니다.- 도구 → 참조를 선택합니다.
- 목록 위쪽에
누락또는MISSING이 표시되는지 확인합니다. - 사용하지 않는 누락 참조라면 코드 의존성을 확인한 뒤 해제합니다.
- 필요한 라이브러리라면 해당 프로그램과 버전이 설치됐는지 확인합니다.
참조 문제를 해결한 후에도 오류 438이 남는다면 다시 노란색 줄의 객체 형식과 멤버 이름을 확인해야 합니다.
With 블록 안에서 다른 객체가 섞였는지 확인
With 블록을 사용할 때 점으로 시작하는 멤버는
With 뒤에 적힌 객체를 기준으로 실행됩니다.
With ThisWorkbook
.Worksheets("결과").Range("A1").Value = "완료"
End With
이 코드의 첫 번째 점은 ThisWorkbook을 의미합니다.
Workbook은 Worksheets를 지원하므로 올바른 객체 계층으로
이어집니다.
반대로 With 대상과 점 뒤 멤버의 객체 종류가 맞지 않으면 오류가 발생할 수 있습니다.
With ThisWorkbook
.Range("A1").Value = "완료"
End With
ThisWorkbook은 Workbook이므로 Worksheet의
Range를 바로 사용할 수 없습니다. 시트를 지정해
수정합니다.
With ThisWorkbook.Worksheets("결과")
.Range("A1").Value = "완료"
.Cells(2, 1).Value = Date
End With
디버그용 오류 처리에서 438을 숨기지 마세요
다음처럼 모든 오류를 무시하면 오류 438이 발생한 줄이 실행되지 않았는데도 매크로가 계속 진행할 수 있습니다.
On Error Resume Next
target.Range("A1").Value = "완료"
디버깅 중에는 On Error Resume Next를 제거하고 오류가
발생한 줄에서 멈추게 해야 합니다.
오류 내용을 기록해야 한다면 번호, 설명과 프로시저 이름을 남기세요.
Option Explicit
Sub RunTask()
On Error GoTo ErrorHandler
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("결과")
ws.Range("A1").Value = "완료"
Exit Sub
ErrorHandler:
Debug.Print "오류 번호: " & Err.Number
Debug.Print "오류 내용: " & Err.Description
Debug.Print "프로시저: RunTask"
MsgBox _
"매크로 실행 중 오류가 발생했습니다." & vbCrLf & _
"번호: " & Err.Number & vbCrLf & _
"내용: " & Err.Description, _
vbExclamation
End Sub
이 코드는 오류를 자동으로 해결하지 않습니다. 다만 실패한 사실을 숨기지 않고 정확한 오류 번호와 설명을 확인할 수 있게 합니다.
코드를 다시 실행하기 전 컴파일 확인
객체 선언과 멤버 이름을 수정했다면 매크로를 바로 실행하기 전에 VBA 프로젝트를 컴파일합니다.
- Visual Basic Editor에서 디버그 메뉴를 선택합니다.
- VBAProject 컴파일을 선택합니다.
- 문제가 표시되면 해당 줄을 먼저 수정합니다.
- 컴파일 메뉴가 비활성화되면 현재 프로젝트의 컴파일이 완료된 상태입니다.
- 통합 문서 복사본에서 매크로를 다시 실행합니다.
구체적인 객체 형식으로 선언했다면 지원하지 않는 멤버 중 일부를 실행 전에
발견할 수 있습니다. 다만 As Object로 선언된 후기 바인딩
코드의 멤버 오류는 실행 시점까지 나타나지 않을 수 있습니다.
노란색 줄에 따른 수정 위치
wb.Range(...)에서 멈춤Workbook에서 Range를 직접 호출하지 말고
wb.Worksheets("시트명").Range(...)처럼 Worksheet를
지정합니다.
target.메서드에서 멈춤직접 실행 창에서
? TypeName(target)을 실행하고, 실제
객체가 해당 메서드를 지원하는지 F2 개체 찾아보기에서 확인합니다.
With 블록의 점으로 시작하는 줄에서 멈춤With 뒤에 있는 객체 종류와 점 뒤 멤버가 맞는지
확인합니다.
설치된 프로그램 버전이 해당 멤버를 지원하는지 공식 객체 모델 문서에서 확인합니다. 후기 바인딩 자체를 해결책으로 간주하지 않습니다.
현재 문제는 오류 438보다 객체 설정 오류 91에 가깝습니다. 객체를 할당한
Set 줄과 객체 검색 결과를 확인합니다.
내용 확인에 사용한 Microsoft 공식 자료
공식 문서 확인일: 2026년 7월 28일
댓글 쓰기