AutoCADの「闇」を断つ:再帰的Purgeによる図面軽量化の極意
AutoCADの図面が、なぜか肥大化する。標準の`PURGE`コマンドを実行しても、ファイルサイズが数MBから減らない。そんな経験はないだろうか?
その原因は、「ブロックの中に潜む、さらに別のブロック(ネスト)」だ。
標準のPurgeメソッドは、トップレベルのオブジェクトを一度走査するだけでは、深層の依存関係まで完全には断ち切れないことがある。業務自動化エンジニアとして断言する。図面を「真に」クリーンにするためには、オブジェクトモデルを再帰的に走査し、依存関係の根源から刈り取るアルゴリズムが必要だ。
今日は、AutoCAD VBAで「再帰的PurgeAll」を実装するための、プロ仕様の設計思想を伝授する。
—
1. なぜ標準の「PURGE」では足りないのか
AutoCADのオブジェクトモデルにおいて、ブロック(`AcadBlock`)は単なる図形ではない。それは独立した名前空間を持つ「小さな図面」だ。
- ネストの深さ: ブロックAの中にブロックBがあり、その中に未使用のレイヤーや線種が含まれている場合、一度の走査ではこれらが「使用中」と誤認されるか、あるいは参照が残ったままになる。
- 循環参照の罠: 不適切に管理された図面では、循環参照や孤立した参照がデータベースのメタデータを肥大化させる。
これを解決するには、「ブロックの依存関係を木構造と見なし、末端から順に削除(再帰的走査)」を行う必要がある。
—
2. 実装の設計指針:バグを避けるための「3つの鉄則」
コードを書く前に、以下の原則を守らなければならない。守らなければ、AutoCADがクラッシュするか、重要な図形が消滅する。
1. トランザクション管理の意識: VBAには明示的なトランザクションロールバックは存在しない。削除対象を事前にリスト化し、`Delete`メソッドを呼ぶ順序を「子から親へ」徹底する。
2. アクティブな選択セットの回避: ループ中に`SelectionSet`を操作するとメモリリークや動作不安定を招く。削除対象のオブジェクトIDを配列に退避させてから処理する。
3. エラーハンドリング: システム変数(`FILEDIA`や`CMDECHO`)の変更時は、必ず`Finally`相当のブロックで復元すること。
—
3. 実践コード:再帰的PurgeAllの実装
以下に、実務でそのまま導入可能な再帰的クリーンアップ関数を示す。
Option Explicit
‘ メイン実行ルーチン
Public Sub ExecuteDeepPurge()
Dim doc As AcadDocument
Set doc = ThisDrawing
‘ エラーハンドリングの徹底
On Error GoTo ErrorHandler
‘ 図面が読み取り専用でないか確認
If doc.ReadOnly Then
MsgBox “この図面は読み取り専用です。保存できません。”, vbCritical
Exit Sub
End If
‘ 再帰的にブロックを走査して未使用を削除
‘ ネストが深い場合、複数回繰り返すのが最も確実
Dim i As Integer
For i = 1 To 3 ‘ 3回走査でほぼ全ての依存を解消可能
Call RecursivePurge(doc)
Next i
MsgBox “クリーンアップ完了。図面を保存してください。”, vbInformation
Exit Sub
ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
End Sub
‘ 再帰的走査ロジック
Private Sub RecursivePurge(doc As AcadDocument)
Dim blk As AcadBlock
‘ Xref(外部参照)やレイアウト用のブロックを除外し、ユーザー定義ブロックのみを走査
For Each blk In doc.Blocks
If Not blk.IsXRef And Not blk.IsLayout Then
‘ 参照数を確認し、0であれば削除を検討
‘ ※実務ではここで「名前のフィルタリング」を追加するとより安全
If blk.Count = 0 Then
On Error Resume Next ‘ 削除失敗(他から参照されている場合)を無視
blk.Delete
On Error GoTo 0
End If
End If
Next blk
‘ 未使用のレイヤー、線種なども併せてPurge
doc.PurgeAll
End Sub
—
4. プロフェッショナルとしての注意点
ファイル・データベース連携の罠
このツールを大規模な図面管理システムの一部として組み込む場合、`PurgeAll`を実行した直後に`SaveAs`を行うと、データベースの整合性チェックに引っかかることがある。
- 解決策: `PurgeAll`の実行後、`doc.AuditInfo`を実行し、データベースの整合性をプログラム的にチェックするフローを挟むこと。
なぜ「3回ループ」なのか
AutoCADの内部オブジェクトデータベースは、オブジェクトの削除時に参照関係を即座に再計算しない。`Purge`をループさせることは、実務においては「物理メモリへの負荷」と「整合性の確保」の間の妥協点として最も効率的なのだ。
最後に:自動化の真髄
「コードが動く」のは当たり前だ。重要なのは、「なぜそのコードが、何千回実行しても図面を壊さないのか」を論理的に説明できること。
今回紹介した再帰的走査のアプローチは、AutoCADのオブジェクトモデルを深く理解している証左となる。このコードをベースに、皆さんの現場のルール(特定のブロックは削除しない等)を条件分岐として追加してほしい。
技術は、使う者の意志の強さに応じてその性能を変える。さあ、図面の海に溜まった淀みを、コードの力で一掃しよう。
