こんにちは!AutoCADの自動化設計を担当している先輩エンジニアです。
日々の業務で、こんなストレスを感じたことはありませんか?
「共有サーバーからローカルPCに図面を移動したら、外部参照(Xref)がごっそりリンク切れを起こした……」
「取引先から送られてきた図面を開いたら、絶対パスのままで赤くエラーが出ている……」
外部参照(Xref)のパス問題は、CADオペレーターや設計者にとって永遠の悩みですよね。特にプロジェクトフォルダをごっそり別の場所に移動させたり、他社とデータやり取りをしたりする際、パスが「絶対パス」のままだと確実にリンクが外れてしまいます。
これを手作業で1枚ずつ「パスの種類を変更」していくなんて、エンジニアの仕事ではありません。
今回は、図面を開いた際に自動(またはワンクリック)で、すべての外部参照のパスを「相対パス」に一括変換し、安全に保存・メンテナンスする実用的なVBAマクロを授けましょう。
ここをクリアすれば、AutoCAD VBAを使った「ファイルとオブジェクトの制御」の本質がグッと見えてきますよ。一緒にバッチリマスターしていきましょう!
—
1. なぜ「相対パス」への変換が必要なのか?
まずは背景の整理です。AutoCADの外部参照には、主に2つのパス保存形式があります。
1. 絶対パス (Absolute Path)
- 例: `C:\Projects\2023\A-Building\Drawings\B-Floor.dwg`
- デメリット: フォルダをごっそり別のドライブや別PCに移した瞬間、参照先のドライブレターや階層が変わるため即座にリンク切れします。
2. 相対パス (Relative Path)
- 例: `..\Drawings\B-Floor.dwg`
- メリット: 親図面からの相対的な位置関係を記憶するため、フォルダごと別の場所に移動してもリンクが切れにくいという最強の特性を持っています。
実務のファイル管理においては、原則として「相対パス運用」がデファクトスタンダードです。これをVBAで強制的に一括変換できれば、納品前やバックアップ前のルーチンワークから解放されます。
—
2. AutoCAD VBAにおける「外部参照」の構造を理解する
コードを書く前に、AutoCADのデータベース構造(ObjectARXのラッパー)における外部参照の正体を知っておく必要があります。
AutoCADの図面には、線や円だけでなく、「ブロックテーブル(BlockTable)」という領域が存在します。実は、外部参照もこのブロックの一種(`IsDependent` や `Path` プロパティを持つブロック)として扱われています。
VBAでは、以下のような階層を辿って外部参照にアクセスします。
- `ThisDrawing.Blocks`(図面内の全ブロック定義)
- 各ブロックをループし、`IsExternalReference = True` のものだけをピックアップする
- 該当するブロックの `Path` プロパティ書き換える、またはメソッドを叩く
—
3. 【実践】外部参照パス一括変換マクロの全コード
それでは、実務の現場でそのままコピー&ペーストして使える実用コードを公開します。
このマクロは、現在アクティブな図面(`ThisDrawing`)に含まれるすべての外部参照をスキャンし、パスを相対パス(または指定した形式)へ強制変換するものです。
標準モジュールに貼り付けるコード
Option Explicit
” ====================================================================
” 外部参照(Xref)のパスを強制的に「相対パス」へ一括変換するマクロ
” 対象: 現在アクティブな図面
” ====================================================================
Public Sub ConvertXrefToRelativePath()
On Error GoTo ErrorHandler
Dim blk As AcadBlock
Dim xrefCount As Long
Dim currentPath As String
Dim newPath As String
xrefCount = 0
‘ 1. 現在の図面が一度でも保存されているかチェック(パスがないと相対パス化できないため)
If ThisDrawing.Path = “” Then
MsgBox “この図面はまだ一度も保存されていません。” & vbCrLf & _
“一度保存してから実行してください。”, vbExclamation, “警告”
Exit Sub
End If
‘ 2. 図面内の全ブロック定義を走査
For Each blk In ThisDrawing.Blocks
‘ 外部参照(Xref)であるかを判定
If blk.IsExternalReference Then
currentPath = blk.Path
‘ デバッグ用(イミディエイトウィンドウに現在のパスを表示)
Debug.Print “発見した外部参照: ” & blk.Name & ” -> パス: ” & currentPath
‘ 3. パスの変換処理(ここでは簡易的にファイル名のみを抽出し、相対パス化のベースを作成)
‘ ※AutoCAD 2015以降は、Pathプロパティに適切な相対パス文字列を代入するか、
‘ 専用のメソッドを適用することでパス形式を制御できます。
‘ ※注意: 完全な相対パス文字列の生成はOSのパス解決則に従うため、
‘ ファイル名ベースで同一階層またはサブフォルダにある前提の処理例を示します。
newPath = GetRelativePathString(ThisDrawing.Path, currentPath)
If newPath <> “” Then
blk.Path = newPath
xrefCount = xrefCount + 1
End If
End If
Next blk
‘ 4. 処理結果の通知と図面の更新
ThisDrawing.Regen acAllViewports
MsgBox “処理が完了しました。” & vbCrLf & _
“変換された外部参照の数: ” & xrefCount & “件”, vbInformation, “完了”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub
” ====================================================================
” ヘルパー関数: 絶対パスから相対パス文字列を算出する簡易ロジック
” ====================================================================
Private Function GetRelativePathString(ByVal drawingPath As String, ByVal targetPath As String) As String
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ すでに相対パス形式(”..\…” や “./…”)になっている場合はそのまま返す
If Left(targetPath, 2) = “..” Or Left(targetPath, 2) = “.” Then
GetRelativePathString = targetPath
Exit Function
End If
‘ ここでは実務上最も多い「同一フォルダ内またはすぐ近く」を想定し、
‘ ファイル名のみを抽出してカレントからの相対(.\ファイル名)にするロジック例を示します。
‘ ※高度なドライブ間またぎの相対パス計算はFSOのGetRelativePath(vbs標準にはないため自作)が必要ですが、
‘ 通常は図面と同じプロジェクトフォルダ内にXrefを配置するため、ファイル名抽出で十分機能します。
Dim fileName As String
fileName = fso.GetFileName(targetPath)
‘ 同一階層にあるとみなして相対パス化(例: “.\filename.dwg”)
‘ ※AutoCADの仕様により、純粋なファイル名のみ、あるいは “.\” プレフィックスが有効です。
GetRelativePathString = “.\” & fileName
End Function
—
4. コードの重要ポイントと、陥りやすい罠(エラー対策)
ここで、プログラミング初学者やマクロ記録からステップアップした方が陥りがちな「3つの罠」について解説しておきます。
罠1: 「まだ保存されていない図面」で実行してしまう
AutoCAD VBAで最も多いエラーの一つが、新規作成しただけで一度も名前をつけて保存していない図面(`ThisDrawing.Path = “” `)でパス操作を行おうとすることです。
相対パスの基準となる「親の居場所(起点)」が存在しないため、計算不能になりエラー落ちします。
上記のコードでは、第1ステップで `ThisDrawing.Path = “”` のガードを挟んでいるため、安全に弾くことができます。
罠2: 外部参照と通常のブロック(Block)を混同する
AutoCADの中では、通常のブロック図形も、外部から読み込んだ図面(Xref)も、内部的には同じ `AcadBlock` オブジェクトとして管理されています。
そのため、すべてのブロックをループする際に `blk.IsExternalReference` というプロパティでフィルタリングをかけないと、通常のブロックに対してパス変更を試みてしまい、予期せぬエラーや無視できないバグを生みます。このフィルタリングは鉄則です。
罠3: AutoCADのバージョンによるパスの挙動の違い
AutoCAD 2014以前と、2015以降では、外部参照パスの内部仕様(相対パスの解釈方法)に微細な違いがあります。
特に近代のAutoCADでは、`Path` プロパティに `.\` や `..\` を含んだ相対パス文字列を代入することで、データベース側が自動的に正しくパスタイプ(絶対/相対)を切り替えてくれます。
—
5. さらに実務で使うための発展形:一括バッチ処理へ
今回紹介したコードは「現在開いている1枚の図面」に対するものですが、実務では「フォルダ内にある100枚の図面すべての外部参照を相対パスに直して上書き保存したい」というニーズがあるはずです。
その場合は、ModelessなVBAフォームから、または外部のVBScriptから `AcDocument.Open` を使い、裏で図面を次々と開いてこの処理をループさせる「バッチ処理エンジン」へと昇華させることができます。
ここをクリアすれば、あなたも立派なAutoCAD自動化エンジニアです。ぜひ手元の図面でテストし、イミディエイトウィンドウの出力結果を確認してみてくださいね。
それでは、快適なCAD自動化ライフを!
