- 공유 링크 만들기
- X
- 이메일
- 기타 앱
이 글의 목적은 엑셀에서 매크로(VBA) 코드를 다른 통합 문서로 복사·붙여넣기 한 뒤 발생하는 “잘못된 참조”, “MISSING: …”, “정의되지 않은 사용자 정의 형식”, “개체 라이브러리를 찾을 수 없음” 등 참조 오류를 원인별로 진단하고 재현 가능한 절차로 해결하는 것이다.
왜 복사·붙여넣기 후 참조가 깨지는가
VBA 프로젝트는 코드만으로 동작하지 않으며, 코드가 기대하는 형식 라이브러리(TypeLib)와 개체 라이브러리(Object Library), ActiveX 컨트롤, 프로젝트 구조에 강하게 의존한다. 통합 문서 간에 모듈만 이동하면 다음과 같은 불일치가 발생한다.
- VBE 메뉴 도구 → 참조에 “MISSING”으로 표시되는 라이브러리 버전 불일치이다.
- 32비트/64비트 Office 및 Windows 차이로
Declare문, 포인터 크기,PtrSafe선언이 다르다. - 폼/컨트롤(예: Microsoft Forms 2.0, ActiveX) 재배치에 따른
GUID차이와.exd캐시 충돌이다. - 프로젝트 이름, 클래스명, WithEvents 멤버명, 시트 개체 코드네임 충돌이다.
- 조기 바인딩(예:
Dim d As Scripting.Dictionary)이 대상 PC에 해당 라이브러리가 설치·등록되어 있지 않아 실패한다.
증상으로 빠르게 분류하기
| 증상 메시지 | 주요 원인 | 즉시 조치 |
|---|---|---|
| MISSING: Microsoft Scripting Runtime | 조기 바인딩 의존 | 참조 해제 후 CreateObject로 지연 바인딩 전환 |
| 사용자 정의 형식 정의되지 않음 | 외부 TypeLib 구조체·Enum 누락 | 참조 추가 또는 해당 형식 재정의 |
| 개체 라이브러리를 찾을 수 없음 | Office 버전·언어·비트수 차이 | 대상 버전 라이브러리로 교체 |
| ActiveX 컨트롤 로드 실패 | .exd 캐시 충돌 | %TEMP%의 *.exd 삭제 |
| 컴파일 오류: Sub 또는 Function이 정의되지 않음 | 모듈 누락/이름 충돌 | 모듈 재삽입, 프로젝트 이름 정리 |
| 런타임 오류 429 / 자동화 오류 | COM 등록 누락 | 해당 구성 요소 재설치·등록 |
표준 해결 절차(현장 체크리스트)
- 백업을 만든다.
- VBE에서 디버그 → VBAProject 컴파일을 실행한다. 실패 메시지를 기록한다.
- 도구 → 참조에서 MISSING 항목을 모두 해제한다. 가능한 경우 동일 기능의 상위 호환 라이브러리로 대체한다.
- 조기 바인딩을 지연 바인딩으로 전환한다. 예:
New Scripting.Dictionary→CreateObject("Scripting.Dictionary")로 교체한다. - 64비트 환경이면 모든 Windows API
Declare에PtrSafe및LongPtr를 적용한다. - 시트 코드네임과 UserForm/클래스 이름 충돌을 제거한다. 중복은 컴파일러가 올바른 모듈을 찾지 못하게 한다.
- ActiveX 오류가 보이면
%TEMP%폴더 내Excel8.0,Excel9.0등 하위 폴더의*.exd캐시 파일을 삭제한다. - 다시 컴파일 후 저장한다. 컴파일이 통과될 때까지 3~7단계를 반복한다.
조기 바인딩을 지연 바인딩으로 전환하는 예시
타 PC에서 라이브러리 설치 상태를 보장할 수 없다면 지연 바인딩이 안전하다.
' [변경 전] Microsoft Scripting Runtime 필요 Dim d As Scripting.Dictionary ' 조기 바인딩 Set d = New Scripting.Dictionary
' [변경 후] 참조 불필요
Dim d As Object ' 지연 바인딩(권장)
Set d = CreateObject("Scripting.Dictionary")
d.CompareMode = 1 ' TextCompare
64비트 호환 Declare 문 템플릿
32비트 코드를 붙여넣으면 포인터 크기 차이로 “잘못된 참조” 또는 컴파일 오류가 발생한다. 아래 템플릿을 사용한다.
#If VBA7 Then ' 64비트/32비트 공용, VBA7 이상 Private Declare PtrSafe Function GetTickCount64 Lib "kernel32" () As LongLong Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _ ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr #Else ' VBA6 이하(아주 구형) Private Declare Function GetTickCount Lib "kernel32" () As Long Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _ ByVal lpClassName As String, ByVal lpWindowName As String) As Long #End If LongPtr로 선언하고, 핸들형 인수/반환형을 Long으로 남겨두면 64비트에서 즉시 실패한다.시트 개체 코드네임과 참조 오류
코드에서 Sheets("매출")로 참조하던 것을 코드네임으로 바꾸면 구조 변경에도 강하다.
' [권장] VBE 속성 창에서 Sheet1(CodeName: shSales) shSales.Range("A1").Value = "OK"
' [취약] 시트 이름이 바뀌면 깨짐
Worksheets("매출").Range("A1").Value = "OK"
프로젝트 이름, 클래스, WithEvents 충돌 정리
- VBE 프로젝트 탐색기에서 대상 프로젝트를 선택하고 도구 → VBAProject 속성 → 일반에서 프로젝트 이름을 고유하게 바꾼다.
- 같은 이름의 클래스 모듈이 둘 이상이면 컴파일러가 참조 해석을 실패한다. 중복을 제거한다.
WithEvents멤버를 다른 모듈에서 Public으로 노출해 이름이 겹치면 이벤트 바인딩이 끊어진다. 이름을 명확히 분리한다.
ActiveX 컨트롤 오류와 .exd 캐시 초기화
Excel은 컨트롤의 버전별 정보를 .exd 캐시에 저장한다. 프로젝트를 이동하면 이전 캐시 때문에 로드에 실패한다.
1) 엑셀 종료 2) Windows + R → %TEMP% 입력 후 실행 3) \Excel8.0, \Excel9.0 등 폴더 내 *.exd 모두 삭제 4) 엑셀 재실행 후 통합 문서 열기 “참조”를 코드로 점검·정리하기
대상 PC에서 자동으로 MISSING 참조를 감지·해제하는 루틴이다.
Sub RemoveMissingReferences() Dim ref As Reference For Each ref In ThisWorkbook.VBProject.References If ref.IsBroken Then ThisWorkbook.VBProject.References.Remove ref End If Next ref MsgBox "Broken references removed" End Sub 조기 바인딩을 유지해야 할 때의 안전한 대안
성능이나 IntelliSense 때문에 조기 바인딩이 필요하다면, 개발 환경에서는 조기 바인딩을 쓰고 배포 시에는 지연 바인딩으로 전환하는 이중 전략을 사용한다.
#Const EarlyBind = False
Sub GetJsonText()
#If EarlyBind Then
Dim http As MSXML2.XMLHTTP60
Set http = New MSXML2.XMLHTTP60
#Else
Dim http As Object
Set http = CreateObject("MSXML2.XMLHTTP")
#End If
http.Open "GET", "https://example.com", False
http.Send
Debug.Print http.responseText
End Sub
형식 재정의로 외부 의존도 줄이기
외부 TypeLib의 Enum이나 Type만 필요하다면 필요한 최소 정의를 코드 내부에 재정의한다.
Public Enum FileMode fmRead = 1 fmWrite = 2 End Enum
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
모듈 이동 시 권장 순서(안전 마이그레이션)
- 원본에서 프로젝트 이름, 시트 코드네임, 클래스명을 목록화한다.
- 대상 통합 문서에서 동일 구조를 선행 생성한다. 폼/클래스부터 만든다.
- 표준 모듈(.bas) → 클래스(.cls) → 폼(.frm) 순서로 가져온다.
- 출처와 대상의 도구 → 참조 스냅샷을 비교하여 필요한 항목만 추가한다.
- 컴파일 후 유닛 테스트 매크로를 실행한다.
유닛 테스트 매크로 예시
핵심 함수의 계약을 보장하면 참조 오류를 조기에 탐지한다.
Sub Test_All() Debug.Assert Test_Dictionary() Debug.Assert Test_SheetBinding() MsgBox "All tests passed" End Sub
Private Function Test_Dictionary() As Boolean
Dim d As Object
Set d = CreateObject("Scripting.Dictionary")
d("k") = 1
Test_Dictionary = (d.Exists("k") And d("k") = 1)
End Function
Private Function Test_SheetBinding() As Boolean
On Error GoTo FAIL
shSales.Range("A1").Value = "TEST"
Test_SheetBinding = True
Exit Function
FAIL:
Test_SheetBinding = False
End Function
오류 메시지별 정밀 처방
1) “MISSING: …” 항목 존재
- 체크 해제 → 지연 바인딩으로 대체 → 필요 시 동일 기능 라이브러리(상위 버전)로 교체한다.
2) “정의되지 않은 사용자 정의 형식”
Type,Enum, 클래스가 외부 라이브러리에만 있을 때 발생한다. 로컬에 최소 정의를 추가하거나 참조를 복원한다.
3) “개체 라이브러리를 찾을 수 없음”
- Office 버전/언어 차이이다. 예:
Excel 16.0 Object LibraryvsExcel 15.0. 상위 버전으로 갈아탄다.
4) ActiveX 컨트롤 로드 불가
*.exd삭제, 동일 컨트롤 버전 설치, 대체 컨트롤로 치환을 검토한다.
5) API Declare 컴파일 오류
PtrSafe,LongPtr,LongLong재선언과 조건부 컴파일을 적용한다.
분석 자동화 스니펫: 누락 참조와 버전 보고서
Sub ReportReferences() Dim ref As Reference, msg As String For Each ref In ThisWorkbook.VBProject.References msg = msg & IIf(ref.IsBroken, "[MISSING] ", "") & _ ref.Description & " | " & ref.Major & "." & ref.Minor & vbCrLf Next Debug.Print msg End Sub 배포 체크리스트
| 항목 | 기준 | 확인 방법 |
|---|---|---|
| 지연 바인딩 | 외부 COM 필수 없음 | 도구 → 참조에 사용자 추가 참조 0개 |
| 64비트 호환 | PtrSafe·LongPtr 적용 | 컴파일 통과 |
| 코드네임 사용 | 시트·폼 이름 안정화 | 하드코딩된 캡션/이름 최소화 |
| ActiveX 의존 | 가능한 대체 | 컨트롤 버전 기록 |
| 유닛 테스트 | 핵심 기능 Pass | Test_All 결과 |
자주 사용하는 안전한 대체 패턴
' 파일 선택: 조기 바인딩(FileDialog) 대신 Application.GetOpenFilename Dim p As Variant p = Application.GetOpenFilename("Excel Files (*.xlsx;*.xlsm),*.xlsx;*.xlsm", , "파일 선택") If p <> False Then Debug.Print p
' 클립보드: Forms.DataObject 대신 텍스트는 WorksheetFunction 이용 또는 API 최소화
' JSON: 외부 라이브러리 없이 단순 파싱은 Split, InStr, Replace로 처리
실패를 줄이는 구조적 설계
- 경계 컨텍스트를 분리한다. 외부 COM 호출은 한 모듈로 모아 교체 비용을 낮춘다.
- 계약 기반으로 Public 프로시저 입출력을 고정하고 내부 구현을 교체한다.
- 의존성 역전을 적용해 외부 라이브러리 생성은 팩토리 함수를 거치게 한다.
현장 트러블슈팅 시나리오
- 컴파일 실패 메시지를 캡처한다.
- MISSING 참조를 모두 해제한다.
- 에러 라인에서 외부 형식 사용 여부를 확인한다.
- 지연 바인딩으로 변환 후 재컴파일한다.
- 여전히 실패하면 .exd 초기화 및 프로젝트·모듈 이름 충돌을 제거한다.
- 마지막으로 64비트 Declare 변환을 확인한다.
FAQ
엑셀을 재설치하면 해결되는가
COM 등록 문제나 Office 개체 라이브러리 손상에는 유효하나, 코드의 조기 바인딩 의존과 구조적 충돌은 해결하지 못한다. 먼저 참조 정리와 지연 바인딩 전환을 수행해야 한다.
참조를 모두 제거하면 성능이 떨어지는가
일부 시나리오에서 조기 바인딩 대비 미세한 오버헤드가 있으나, 일반적인 업무 자동화에서는 체감 차이가 없다. 유지보수성과 배포 안정성이 더 큰 이점이다.
회사 보안 정책으로 “VBA 프로젝트 개체 모델 신뢰”를 켤 수 없다
코드로 참조를 조작하는 루틴 사용은 불가하다. 대신 수동으로 참조 창에서 MISSING을 해제하고, 지연 바인딩으로 코드를 바꾸어 해당 설정 의존을 제거한다.
64비트 선언을 모두 바꿨는데도 오류가 난다
반환형이나 구조체 내부의 포인터 필드를 Long으로 남겨둔 경우가 흔하다. 핸들·포인터는 LongPtr, 64비트 카운터는 LongLong으로 치환했는지 재검토한다.
ActiveX를 쓰지 않고 대체할 수 있는가
가능하다. 폼 컨트롤이나 표준 UI 대체, 셀 기반 인터랙션, WPF·.NET 연동을 포기하고 엑셀 네이티브 기능 중심으로 설계하면 배포 문제가 급감한다.
- 공유 링크 만들기
- X
- 이메일
- 기타 앱