Excel VBAでAutoCADの参照(Type Library)がバージョンごとに違うせいで壊れ、毎回ユーザーに手修正を強いる――そんな“現場あるある”を、設定・コード・運用の三位一体で根本解決します。Trust Centerの前提から、壊れた参照の安全な除去、パス差異・x86/×64差異への耐性、さらには遅延バインディングでの根本回避まで、配布・保守を見据えた実装とベストプラクティスをまとめました。
Excel VBAでAutoCAD参照が壊れる——原因と全体像
AutoCADのType Library(例:acax20enu.tlb、acax23enu.tlb など)はバージョンごとにファイル名が異なるため、ブックに保存される参照の絶対パスが配布先PCの実態とズレると「参照が壊れた状態」になります。さらにVBE(VBプロジェクト)へのプログラム的アクセスは既定でブロックされ、壊れた参照は名前や説明が取得できず、削除も失敗しがちです。そのまま新しい参照を追加しようとすると競合やエラー(典型的には “参照を追加できませんでした”)が発生します。
| 現象 | 発生タイミング | 主な影響 |
|---|---|---|
| 参照設定が「見つかりません」になっている | 配布先でブックを開いた直後 | コンパイル不可、実行時エラー、IntelliSense消失 |
| VBEへのアクセスが拒否 | 参照修復コードを実行したとき | 参照列挙・削除・追加が行えない |
| 壊れた参照のプロパティ取得に失敗 | 参照の状態確認時 | 名前/説明を指標に削除するロジックが組めない |
| 壊れた参照を残したまま追加でエラー | 新しいTLBをAddFromFileしたとき | 競合・重複・エラーで自動修復が中断 |
なぜ壊れるのか:COM参照とTLBの仕組み
VBAの「参照設定」は、ビルド時に型情報を取り込む早期バインディングの仕組みです。参照は「特定パスのTLB/OLB/OCX」に結び付いており、ブックを配布してもその絶対パスが配布先の環境と完全一致するとは限りません。AutoCADはメジャーバージョンごとにacaxXXenu.tlbのXXが変わるため、これが破綻の主因になります。さらにWindowsのProgram FilesとProgram Files (x86)の差、言語リソースの差、ユーザー権限やUACも絡み、参照復旧を難しくします。
| 要素 | ポイント |
|---|---|
| 早期バインディング | コンパイル時に型情報が必要。配布先に同一TLBが無いと参照が壊れる。 |
| TLBファイル | AutoCADごとにファイル名・配置が異なる(例:…\Autodesk Shared\acax23enu.tlb)。 |
| Trust Center | 「VBAプロジェクト オブジェクトモデルへのアクセス」を既定でブロック。 |
| 壊れた参照 | IsBroken=Trueになる。Name/Description等の取得・削除が失敗しやすい。 |
解決の全体戦略
- Trust Center設定の有効化:Excel → ファイル → オプション → セキュリティセンター → セキュリティセンターの設定 → マクロの設定 → 「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」にチェック。
- 壊れた参照を必ず削除してから追加:
References.Removeで壊れた参照を先に取り除き、次にAddFromFileで現存する最新TLBを追加。 - 複数パス・複数バージョン・x86/×64を横断探索:Common Files\Autodesk Shared(x64/x86)など複数候補をサーチ。
- 遅延バインディングで根本回避:配布先差異を吸収し、参照そのものを不要にする(IntelliSenseは犠牲)。
| チェック項目 | 目的 | できない場合の代替 |
|---|---|---|
| VBOMアクセスを許可 | 参照の列挙・削除・追加 | 遅延バインディング(参照不要化) |
| 壊れ参照を全削除 | 競合・重複を防止 | 手動で一時的に解除 |
| TLB横断探索 | パス差・言語差・x86/×64差の吸収 | GUID指定AddFromGuid(GUIDが分かる場合) |
| ログと例外処理 | 配布後のトラブルシュート | UIメッセージで回避手順を案内 |
最小コード(シンプル版)
まずは「壊れ参照を先に削除してから追加」の原則を満たす最小実装です。Trust Centerの設定が有効であることが前提です。
Option Explicit
Private Sub Workbook_Open()
FixAcadReferenceSimple
End Sub
Public Sub FixAcadReferenceSimple()
Dim vbProj As Object ' VBIDE.VBProject を遅延バインド
Dim ref As Object ' VBIDE.Reference
Dim folder As String, tlb As String
On Error GoTo ErrHandler
Set vbProj = ThisWorkbook.VBProject
' AutoCAD TLB を検索(英語リソース優先)
folder = Environ$("CommonProgramFiles") & "\Autodesk Shared\"
tlb = Dir$(folder & "acax*enu.tlb")
If tlb = "" Then
' ローカライズ等に備えてワイドに検索
tlb = Dir$(folder & "acax*.tlb")
End If
If tlb = "" Then
MsgBox "AutoCAD の TLB が見つかりません", vbExclamation
Exit Sub
End If
' 壊れた参照を探して差し替え
For Each ref In vbProj.References
If ref.IsBroken Then
vbProj.References.Remove ref ' ← 先に削除
vbProj.References.AddFromFile folder & tlb
Debug.Print "AutoCAD 参照を修復しました: " & tlb
Exit For
End If
Next
Exit Sub
ErrHandler:
MsgBox "参照修復エラー: " & Err.Description, vbCritical
End Sub
この最小版は、配布先に1つのTLBがあり、壊れた参照が1件だけの想定であれば十分に機能します。ただし、複数の壊れた参照、x86/×64混在、言語リソース差、既に有効なAutoCAD参照が別バージョンで存在…といった現実の配布では、より堅牢な実装が必要です。
堅牢版:複数パス・複数バージョン・x86/×64対応
以下のコードは、次の要件を満たします。
- Trust Centerの許可がない場合はユーザーに明示し退出。
- 壊れた参照をすべて除去(For逆順、安全なRemove)。
- x64/x86のCommon Files\Autodesk Sharedなど複数フォルダを走査。
acax*.tlbを広く検出し、もっとも新しい番号のTLB(例:acax23…>acax20…)を自動選択。- 既に有効なAutoCAD参照がある場合は重複追加を回避。
- 詳細なユーザーフィードバック(Debug.PrintとMsgBox)。
Option Explicit
' エントリーポイント:起動時に自動修復
Private Sub Workbook_Open()
RepairAutoCADReference
End Sub
Public Sub RepairAutoCADReference()
If Not TryAccessVBOM() Then
MsgBox "VBE へのプログラム的アクセスが拒否されています。" & vbCrLf & _
"Excel → ファイル → オプション → セキュリティ センター → セキュリティ センターの設定 → マクロの設定 → " & _
"「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」にチェックを入れてください。", vbExclamation
Exit Sub
End If
On Error GoTo EH
Dim vbProj As Object ' VBIDE.VBProject
Dim refs As Object ' VBIDE.References
Set vbProj = ThisWorkbook.VBProject
Set refs = vbProj.References
' まず壊れた参照をすべて削除
RemoveAllBrokenReferences refs
' 既に有効なAutoCAD参照があれば追加不要
If HasWorkingAcadReference(refs) Then
Debug.Print "有効な AutoCAD 参照が既に存在します。追加はスキップしました。"
Exit Sub
End If
' 候補TLBを探索
Dim candidates As Collection
Set candidates = FindAcadTlbCandidates()
If candidates Is Nothing Or candidates.Count = 0 Then
MsgBox "AutoCAD の TLB が見つかりませんでした。" & vbCrLf & _
"AutoCAD が未インストール、または TLB の配置が標準と異なる可能性があります。", vbExclamation
Exit Sub
End If
' 最新TLBを選択して参照追加
Dim latest As String
latest = PickLatestTlb(candidates)
Debug.Print "AutoCAD TLB 候補のうち最新を選択: " & latest
refs.AddFromFile latest
Debug.Print "AutoCAD 参照を追加しました: " & latest
Exit Sub
EH:
MsgBox "参照修復エラー: (" & Err.Number & ") " & Err.Description, vbCritical
End Sub
Private Function TryAccessVBOM() As Boolean
On Error Resume Next
Dim n As Long
n = ThisWorkbook.VBProject.VBComponents.Count
TryAccessVBOM = (Err.Number = 0)
Err.Clear
On Error GoTo 0
End Function
Private Sub RemoveAllBrokenReferences(ByVal refs As Object)
On Error Resume Next
Dim i As Long
For i = refs.Count To 1 Step -1
If refs(i).IsBroken Then
Debug.Print "壊れた参照を削除: index=" & i
refs.Remove refs(i)
End If
Next i
On Error GoTo 0
End Sub
Private Function HasWorkingAcadReference(ByVal refs As Object) As Boolean
On Error Resume Next
Dim i As Long
For i = 1 To refs.Count
' 壊れていない参照のみ評価
If Not refs(i).IsBroken Then
Dim nm As String, desc As String, f As String
nm = refs(i).Name
desc = refs(i).Description
f = refs(i).FullPath
If InStr(1, LCase$(f), "acax", vbTextCompare) > 0 _
Or InStr(1, LCase$(nm), "acad", vbTextCompare) > 0 _
Or InStr(1, LCase$(desc), "autocad", vbTextCompare) > 0 Then
HasWorkingAcadReference = True
Exit Function
End If
End If
Next i
On Error GoTo 0
End Function
Private Function FindAcadTlbCandidates() As Collection
Dim col As New Collection
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim folders As Variant
folders = Array( _
Environ$("CommonProgramFiles") & "\Autodesk Shared\", _
Environ$("CommonProgramFiles(x86)") & "\Autodesk Shared\", _
"C:\Program Files\Common Files\Autodesk Shared\", _
"C:\Program Files (x86)\Common Files\Autodesk Shared\" _
)
Dim i As Long
For i = LBound(folders) To UBound(folders)
AddTlbFromFolder CStr(folders(i)), "acax*enu.tlb", dict, col
AddTlbFromFolder CStr(folders(i)), "acax*.tlb", dict, col ' ローカライズ等も拾う
Next i
Set FindAcadTlbCandidates = col
End Function
Private Sub AddTlbFromFolder(ByVal folder As String, ByVal pattern As String, _
ByVal dict As Object, ByVal col As Collection)
On Error Resume Next
Dim f As String
f = Dir$(folder & pattern)
Do While LenB(f) > 0
If Not dict.Exists(LCase$(folder & f)) Then
dict.Add LCase$(folder & f), 1
col.Add folder & f
Debug.Print "TLB候補: " & folder & f
End If
f = Dir$()
Loop
On Error GoTo 0
End Sub
Private Function PickLatestTlb(ByVal candidates As Collection) As String
Dim bestPath As String
Dim bestVer As Long
Dim i As Long
For i = 1 To candidates.Count
Dim p As String: p = CStr(candidates(i))
Dim v As Long: v = GetTlbNumericVersion(p)
If v > bestVer Then
bestVer = v
bestPath = p
End If
Next i
' バージョン番号が取れない場合は先頭を返す
If bestPath = "" Then bestPath = CStr(candidates(1))
PickLatestTlb = bestPath
End Function
Private Function GetTlbNumericVersion(ByVal path As String) As Long
' ファイル名から acax** の ** 数字を抽出
Dim fn As String: fn = GetFileName(path)
fn = LCase$(fn)
If Left$(fn, 4) = "acax" Then fn = Mid$(fn, 5)
Dim i As Long, ch As String, buf As String
For i = 1 To Len(fn)
ch = Mid$(fn, i, 1)
If ch Like "#" Then
buf = buf & ch
ElseIf Len(buf) > 0 Then
Exit For
End If
Next i
If Len(buf) > 0 Then GetTlbNumericVersion = CLng(buf)
End Function
Private Function GetFileName(ByVal path As String) As String
Dim p As Long
p = InStrRev(path, "\")
If p > 0 Then
GetFileName = Mid$(path, p + 1)
Else
GetFileName = path
End If
End Function
この堅牢版は、壊れた参照を全削除 → 有効なAutoCAD参照が既にあればスキップ → 無ければ最新TLBを追加の順序で安全に復旧します。探索パターンは広め(acax*enu.tlbとacax*.tlb)にしているため、言語差や配置差にもある程度耐性があります。
運用ノウハウ:ログと例外の扱い
- ユーザー向けには
MsgBoxで最小限を通知、詳細はDebug.Printでイミディエイトウィンドウに出すと解析しやすいです。 - 参照の追加に失敗する典型(32813など)は、壊れ参照の取り残しか、既に有効なAutoCAD参照の重複が原因。上記関数で両方に配慮しています。
- ブックを配布する前に「信頼できる場所」配下へ配置、または署名済みVBAプロジェクトにする運用も効果的です。
遅延バインディングで根本回避(参照不要化)
配布先のAutoCADバージョン差を完全に吸収したい場合は、AutoCADオブジェクトの生成を遅延バインディングに切り替えます。IntelliSenseや定数は失われますが、参照破損自体が起きません。
Public Sub Sample_LateBinding_AutoCAD()
Dim acApp As Object
On Error Resume Next
Set acApp = GetObject(, "AutoCAD.Application")
If acApp Is Nothing Then
Set acApp = CreateObject("AutoCAD.Application")
End If
On Error GoTo 0
If acApp Is Nothing Then
MsgBox "AutoCAD が起動できません。インストールを確認してください。", vbExclamation
Exit Sub
End If
acApp.Visible = True
' 以降は Object 型でメソッド・プロパティを呼ぶ(早期バインディングの代わり)
' 例: acApp.Documents.Add など(バージョン差に依存しない範囲で利用)
End Sub
現実的な折衷案は、開発(社内)では早期バインディング+IntelliSenseで生産性を確保し、配布(社外)では遅延バインディング分岐を用意しておく方法です。コンパイル定数やフラグで切り替えると保守しやすくなります。
Trust CenterとExtensibility参照
- Trust Center:「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」を有効化しない限り、参照の列挙・削除・追加は行えません。ユーザーへの配布時は必ず手順を明記しましょう。
- Extensibility 5.3:本稿の堅牢版はVBIDEを遅延バインドしているため参照が必須ではありませんが、開発時のIntelliSense目的で「Microsoft Visual Basic for Applications Extensibility 5.3」をチェックしておくのは有用です。
x86/×64・言語差・配置差への備え
| 差異 | 想定される相違点 | 対策 |
|---|---|---|
| x64 vs x86 Office | Common Filesのルートが異なる | Environ$("CommonProgramFiles")とEnviron$("CommonProgramFiles(x86)")の両パスを探索 |
| AutoCADの言語 | acax*enu.tlb以外のTLBが配置される場合 | acax*.tlbのワイドパターンで検出 |
| ベンダー独自配置 | 標準外のインストール先 | 必要に応じレジストリからインストールルートをRegReadで読取(配布先で検証) |
よくあるエラーと対処
| 症状/エラー | 原因の典型 | 対処 |
|---|---|---|
| 1004: Programmatic access is not trusted | Trust CenterでVBOMが無効 | ユーザーに設定変更を案内(権限ポリシーも要確認) |
| 32813: 参照を追加できない | 壊れた参照が残存/既に有効な参照と重複 | 先に壊れた参照を全削除、既存の有効参照を検知して追加をスキップ |
| 53/48: ファイルが見つからない/読み込めない | パス差異・権限・TLB未配置 | 探索パスを増やす、インストール状態の確認、管理者権限 |
| コンパイルエラー(ユーザー定義型が未定義) | 早期バインディング前提で参照が無い | 遅延バインディングへの切替または参照の自動修復を先に実行 |
テスト手順(配布前チェックリスト)
- 開発機で参照を一旦壊す(AutoCAD参照を外す/仮パスにすり替える)。
RepairAutoCADReferenceを実行し、壊れ参照の全削除 → 最新TLB追加が成功することを確認。- 既に有効なAutoCAD参照がある状態で再実行し、重複追加スキップになることを確認。
- x64/x86、言語違いの複数環境で検証(VMやテスト端末)。
- Trust Center無効時のガード表示とフェイルセーフを確認。
運用設計:配布・保守のベストプラクティス
- 自動修復を起動時イベントに組み込む:
Workbook_Openで毎回チェックすれば、配布後の差異にも自動追従します。 - 署名・信頼済みロケーション:マクロ実行性とVBOM許可の周知を組み合わせ、問い合わせを削減。
- 遅延バインディングのバックアップ経路:修復に失敗した場合の退避経路としてCreateObjectを用意。
- ログ方針:Debug.Printと簡易ログ(シートやテキスト)を併用すると現場対応が早くなります。
FAQ
| 質問 | 回答 |
|---|---|
| Extensibility 参照は必須? | 本稿の実装は遅延バインディングでVBIDE型を回避しているため必須ではありません。開発時の利便性のために追加するのは有りです。 |
GUID指定(AddFromGuid)は使わないの? | GUIDを正確に把握でき、配布先に該当TypeLibが登録済みであれば有効です。環境差異が大きい現場ではパス探索のほうが成功率が高い場面もあります。 |
| TLBが複数見つかったら? | 数字が最大のacax**.tlbを「最新」とみなし採用します。要件次第では「最小サポート版」に固定するポリシーも検討してください。 |
| 参照を都度追加するのは重い? | 起動時に1度実行する程度なら実務上のオーバーヘッドは僅少です。不要な追加を避けるため「既存の有効参照を検知してスキップ」しています。 |
まとめ
- AutoCAD参照の破損はバージョン差×パス差の必然。Trust Centerの許可が前提です。
- 修復は「壊れた参照の全削除 → 競合回避 → 最新TLBの追加」という順序が鉄則です。
- x64/x86・言語差・配置差に備えてacax*.tlbを横断探索し、冪等なロジックで運用しましょう。
- 根本回避として遅延バインディングを併用すれば、配布先の差異に強い仕組みになります。
付録:配布テンプレ(コピペ用)
以下は、Workbook_Openに組み込むだけで最低限の自動修復を実施するミニマムテンプレです。必要に応じて堅牢版と差し替えてください。
Option Explicit
Private Sub Workbook_Open()
If Not TryAccessVBOM() Then
MsgBox "VBE へのアクセスが拒否されています。Trust Center の設定を見直してください。", vbExclamation
Exit Sub
End If
RepairAutoCADReference
End Sub
これらを実装すれば、AutoCADのバージョン差に起因する壊れた参照を自動で検出・修復でき、Excelマクロ実行時の不安定さを大幅に削減できます。開発・配布・保守の各段階で「設定・コード・運用」の三拍子を揃えることが、現場で効く最短ルートです。

コメント