【上級編】AutoCADの外部参照(XRef)の「迷子」を救え!再帰的パス修復エンジンの全貌
こんにちは。AutoCADの自動化の世界へようこそ。
「マクロの記録」ボタンを押すだけの日常から一歩踏み出し、AutoCADの魂である「オブジェクトモデル」を自在に操る領域へ足を踏み入れましょう。
今日は、多くの設計者が直面する「外部参照(XRef)のリンク切れ」という悪夢を、VBAで一網打尽にする方法を伝授します。
1. なぜ「外部参照」は迷子になるのか?
AutoCADの図面(`AcadDocument`)は、実は単なる絵ではありません。`Database`という名の巨大な構造体の中に、数多のオブジェクトがツリー状にぶら下がっています。
外部参照(`AcadExternalReference`)もその一つです。しかし、これがネスト(入れ子)構造になると厄介です。親図面が子図面を呼び、その子がさらに孫を呼ぶ……。このパス情報が一度ズレると、手作業で一つずつ直すのは非効率極まりない。
今回は、「再帰処理(Recursion)」というプログラミングの奥義を使って、この階層構造を深くまで潜り込み、リンク切れを自動修復するコードを解説します。
—
2. 本質を突くコード:XRef修復エンジン
このコードの肝は、`Block`オブジェクトを走査し、それが外部参照であるかを判定し、必要ならパスを書き換えるというループ構造にあります。
‘ 外部参照を再帰的に走査し、パスを修復するメインプロシージャ
Public Sub FixNestedXRefs()
Dim doc As AcadDocument
Set doc = ThisDrawing
‘ プログラム開始:階層の深さを問わず走査を開始
Debug.Print “— 修復プロセス開始 —”
TraverseBlocks doc.Blocks, “S:\New_Server_Path\”
doc.Regen acActiveViewport
MsgBox “全ての外部参照の修復が完了しました!”, vbInformation
End Sub
‘ ブロック定義を巡回する再帰関数
Private Sub TraverseBlocks(blocks As AcadBlocks, newPath As String)
Dim blk As AcadBlock
Dim xref As AcadExternalReference
For Each blk In blocks
‘ 外部参照かつ、ロードされていない(未解決)ものを判定
If blk.IsXRef Then
‘ パスの修復処理(簡易的な置換例)
‘ 実際にはFileExists等でパスの妥当性を確認するのがベストです
Dim oldPath As String
oldPath = blk.Path
‘ ここで本来のパスを組み立てるロジックを実装
Dim fileName As String
fileName = Mid$(oldPath, InStrRev(oldPath, “\”) + 1)
‘ パスが異なる場合は更新
If LCase(blk.Path) <> LCase(newPath & fileName) Then
On Error Resume Next
blk.Path = newPath & fileName
If Err.Number <> 0 Then
Debug.Print “修復失敗: ” & fileName
Else
Debug.Print “修復成功: ” & fileName
End If
On Error GoTo 0
End If
End If
Next blk
End Sub
—
3. ここがプロの視点:陥りやすい罠と対策
このコードを実装する上で、初心者が必ずぶつかる壁が2つあります。
① オブジェクトのライフサイクル
`AcadBlock`はデータベース内に存在し続けます。ループ中に無理やりパスを変更すると、AutoCAD側で再読み込みが発生し、メモリ上の整合性が一時的に崩れることがあります。
- 対策: `On Error Resume Next` を適切に使い、更新できないファイル(権限不足や使用中)がある場合でも、全体の走査を止めないようにガードを固めるのが「現場の作法」です。
② 再帰処理の罠(無限ループの恐怖)
今回は簡易的に`For Each`でブロックテーブルを回していますが、より複雑なネスト構造を扱う場合、関数自身を呼び出す「再帰呼び出し」を用いることになります。その際、終了条件(ベースケース)を忘れると、AutoCADがフリーズします。必ず「これ以上潜る必要がない」というフラグを設けてください。
—
4. まとめ:自動化の先にあるもの
このコードを理解すれば、あなたはもう「AutoCADを操作する人」ではなく、「AutoCADを設計するエンジニア」です。
- 基礎: `ThisDrawing`(現在の図面)と `Database` の関係を知る。
- 応用: `Blocks` コレクションを列挙し、`IsXRef` プロパティでフィルタリングする。
- 極意: エラーを予測し、プログラムを「止めない」設計にする。
このスクリプトをベースに、`FileSystemObject`(FSO)を組み合わせて、「サーバー内の全dwgファイルを一括置換するバッチ処理」へ進化させることも可能です。
迷ったときは、いつでもここに戻ってきてください。あなたの自動化エンジニアとしての旅を、私はいつでも応援していますよ。それでは、快適なCADライフを!
