鈍器のような「PurgeAll」を捨てよ:AutoCADの画層を外科手術的に浄化する極限手法
AutoCADのAPIを叩く際、初心者は決まって`ThisDrawing.PurgeAll`という魔法の杖を振るいたがる。だが、大規模な設備図面や、他社から受け継いだレガシー図面において、それは「魔法」ではなく「無差別爆撃」だ。
必要な画層設定、プロットスタイル、さらには外部参照と密接に絡み合ったメタデータまで、一瞬で蒸発させる。業務自動化の現場で求められるのは、「何を残し、何を捨てるか」という明確な意思決定をコードに実装することだ。
今回は、全パージを排し、特定の条件に合致する「未使用画層」のみを外科手術的に除去する、実務レベルで最も安全かつ高速なアプローチを伝授する。
—
1. オブジェクトのライフサイクルと「削除不能」の壁
AutoCADにおいて、`Layer`オブジェクトを削除するには、単に`Delete`メソッドを呼ぶだけでは足りない。以下の条件が一つでも欠ければ、容赦なく「E_FAIL」が返される。
- その画層が「現在画層」ではないこと。
- その画層に一つでもエンティティ(線や文字など)が存在しないこと。
- 画層が「0」画層や「Defpoints」ではないこと。
- 外部参照(Xref)に依存していないこと。
多くの開発者がここで躓く。`PurgeAll`を使えばこれらを無視して強行できるが、それは「ゴミが溜まっているから部屋ごと焼き払う」ようなものだ。我々は、「未使用であること」を論理的に証明してから消去するという手続きを踏む。
—
2. 外科手術的クリーンアップの実装コード
以下のコードは、指定したプレフィックスを持つ画層のうち、実際に図面内で使用されていないものだけをピンポイントで排除する設計だ。
‘ @brief 特定の命名規則を持つ未使用画層のみをクリーンアップする
‘ @note 参照カウンタを回す必要はなく、Deleteメソッドの成否で判定する外科的手法
Public Sub TargetedLayerCleanup(ByVal targetPrefix As String)
Dim doc As AcadDocument: Set doc = ThisDrawing
Dim layer As AcadLayer
Dim i As Long
‘ エラーハンドリング:削除不可の画層(現在画層等)をスキップするための保険
On Error Resume Next
‘ AutoCADのコレクションは反復処理中の削除に弱いため、逆順でループする
For i = doc.Layers.Count – 1 To 0 Step -1
Set layer = doc.Layers.Item(i)
‘ 0画層やDefpointsは保護対象
If Not (layer.Name = “0” Or layer.Name = “Defpoints”) Then
‘ 特定の命名規則(例: “TEMP_”で始まる画層)に合致するか確認
If InStr(layer.Name, targetPrefix) = 1 Then
‘ 削除を試みる
layer.Delete
‘ Deleteが成功したかを確認
If Err.Number = 0 Then
Debug.Print “Deleted: ” & layer.Name
Else
‘ 削除失敗(使用中、あるいは現在画層)の場合はエラーをクリア
Err.Clear
End If
End If
End If
Next i
On Error GoTo 0
Set layer = Nothing
End Sub
—
3. パフォーマンスとメモリの極限最適化
VBAのガーベッジコレクションは優秀ではない。特にAutoCADのCOMオブジェクトを大量に扱う場合、メモリリークは「突然のクラッシュ」として現れる。
- 明示的解放の徹底: `Set layer = Nothing` は単なる行儀の問題ではない。ループの各イテレーションで確実に参照カウンタを操作し、メモリ空間を解放せよ。
- 逆順ループの鉄則: `For i = doc.Layers.Count – 1 To 0 Step -1` を使用するのは、インデックスのズレによるアクセス違反を防ぐためだけではない。コレクションの先頭から削除すると再インデックス処理が走り、パフォーマンスが著しく低下する。末尾からの削除は、メモリ管理上も極めて効率が良い。
- Windows APIによる制御: もし処理が極端に重い図面を相手にするなら、`DoEvents`を挟むことも検討すべきだが、多用は禁物だ。Windowsのメッセージキューを乱す原因となるため、1000層を超えるような異常な図面でない限り、純粋なCOMインターフェースの叩き込みに徹するのが正解だ。
—
4. シニアエンジニアへの提言
AutoCAD VBAはレガシーな技術と揶揄されることもあるが、その内部にあるCOM/ActiveXの構造は極めて堅牢だ。
「とりあえず動くコード」と「数万枚の図面を扱ってもメモリリークゼロで完走するコード」の差は、こうしたオブジェクトの特性をどれだけ理解しているかにある。全パージという安易な妥協を捨て、各オブジェクトが図面という空間の中でどのような制約を受けているか、その境界線(Boundary)を意識すること。
それが、伝説的な自動化エンジニアへの第一歩だ。次は、`BlockTableRecord`の未使用ブロック定義を同様の手法で精査するロジックについて深掘りするとしよう。
諸君、コードを汚すな。設計を汚すな。図面を美しく保て。
