Contents 호환성 문제의 정의와 증상 분류 즉시 조치 체크리스트(빠른 복구) 파일 형식별 특성과 선택 기준 버전 차이로 인한 기능 손실과 대체 전략 조직 환경 차이: 32/64비트, 추가기능, 보안 정책 CSV·텍스트 파일 호환성: 인코딩·구분 기호·서식 날짜·숫자 변형 방…
글 전체 보기- 공유 링크 만들기
- X
- 이메일
- 기타 앱
Contents 호환성 문제의 정의와 증상 분류 즉시 조치 체크리스트(빠른 복구) 파일 형식별 특성과 선택 기준 버전 차이로 인한 기능 손실과 대체 전략 조직 환경 차이: 32/64비트, 추가기능, 보안 정책 CSV·텍스트 파일 호환성: 인코딩·구분 기호·서식 날짜·숫자 변형 방…
글 전체 보기이 글의 목적은 엑셀에서 매크로(VBA) 코드를 다른 통합 문서로 복사·붙여넣기 한 뒤 발생하는 “잘못된 참조”, “MISSING: …”, “정의되지 않은 사용자 정의 형식”, “개체 라이브러리를 찾을 수 없음” 등 참조 오류를 원인별로 진단하고 재현 가능한 절차로 해결하는 것이다.
VBA 프로젝트는 코드만으로 동작하지 않으며, 코드가 기대하는 형식 라이브러리(TypeLib)와 개체 라이브러리(Object Library), ActiveX 컨트롤, 프로젝트 구조에 강하게 의존한다. 통합 문서 간에 모듈만 이동하면 다음과 같은 불일치가 발생한다.
Declare 문, 포인터 크기, PtrSafe 선언이 다르다.GUID 차이와 .exd 캐시 충돌이다.Dim d As Scripting.Dictionary)이 대상 PC에 해당 라이브러리가 설치·등록되어 있지 않아 실패한다.| 증상 메시지 | 주요 원인 | 즉시 조치 |
|---|---|---|
| MISSING: Microsoft Scripting Runtime | 조기 바인딩 의존 | 참조 해제 후 CreateObject로 지연 바인딩 전환 |
| 사용자 정의 형식 정의되지 않음 | 외부 TypeLib 구조체·Enum 누락 | 참조 추가 또는 해당 형식 재정의 |
| 개체 라이브러리를 찾을 수 없음 | Office 버전·언어·비트수 차이 | 대상 버전 라이브러리로 교체 |
| ActiveX 컨트롤 로드 실패 | .exd 캐시 충돌 | %TEMP%의 *.exd 삭제 |
| 컴파일 오류: Sub 또는 Function이 정의되지 않음 | 모듈 누락/이름 충돌 | 모듈 재삽입, 프로젝트 이름 정리 |
| 런타임 오류 429 / 자동화 오류 | COM 등록 누락 | 해당 구성 요소 재설치·등록 |
New Scripting.Dictionary → CreateObject("Scripting.Dictionary")로 교체한다.Declare에 PtrSafe 및 LongPtr를 적용한다.%TEMP% 폴더 내 Excel8.0, Excel9.0 등 하위 폴더의 *.exd 캐시 파일을 삭제한다.타 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
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 멤버를 다른 모듈에서 Public으로 노출해 이름이 겹치면 이벤트 바인딩이 끊어진다. 이름을 명확히 분리한다.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
핵심 함수의 계약을 보장하면 참조 오류를 조기에 탐지한다.
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
Type, Enum, 클래스가 외부 라이브러리에만 있을 때 발생한다. 로컬에 최소 정의를 추가하거나 참조를 복원한다.Excel 16.0 Object Library vs Excel 15.0. 상위 버전으로 갈아탄다.*.exd 삭제, 동일 컨트롤 버전 설치, 대체 컨트롤로 치환을 검토한다.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 등록 문제나 Office 개체 라이브러리 손상에는 유효하나, 코드의 조기 바인딩 의존과 구조적 충돌은 해결하지 못한다. 먼저 참조 정리와 지연 바인딩 전환을 수행해야 한다.
일부 시나리오에서 조기 바인딩 대비 미세한 오버헤드가 있으나, 일반적인 업무 자동화에서는 체감 차이가 없다. 유지보수성과 배포 안정성이 더 큰 이점이다.
코드로 참조를 조작하는 루틴 사용은 불가하다. 대신 수동으로 참조 창에서 MISSING을 해제하고, 지연 바인딩으로 코드를 바꾸어 해당 설정 의존을 제거한다.
반환형이나 구조체 내부의 포인터 필드를 Long으로 남겨둔 경우가 흔하다. 핸들·포인터는 LongPtr, 64비트 카운터는 LongLong으로 치환했는지 재검토한다.
가능하다. 폼 컨트롤이나 표준 UI 대체, 셀 기반 인터랙션, WPF·.NET 연동을 포기하고 엑셀 네이티브 기능 중심으로 설계하면 배포 문제가 급감한다.