こんにちは!AutoCAD VBAの世界へようこそ。
マクロの記録ボタンを押すだけのステージから抜け出し、自分自身のコードで図面を意のままに操りたい――そう思ってこのページを開いてくれたなら、あなたはもう次のステージの入口に立っています。
今回は、業務の現場で最もニーズが高い「条件を指定したオブジェクトの自動削除(図面のクリーンアップ)」をテーマに、AutoCAD VBAの核心に迫ります。
「不要なレイヤのゴミを一掃したい」「特定の文字が含まれるテキストだけを消したい」
手作業でやれば数時間かかる苦行も、オブジェクトモデルの本質を知れば、一瞬で終わる優雅な作業に変わります。さあ、一緒に極限の効率化の世界へ踏み出しましょう!
—
1. AutoCAD VBAの基礎:オブジェクトモデルの「地平線」を捉える
AutoCAD VBAをマスターするためには、まず「何がどこにぶら下がっているのか」という階層構造(オブジェクトモデル)を頭に叩き込む必要があります。ここを曖昧にしたままコードを書くと、必ず「オブジェクトが必要です」というエラーの洗礼を受けることになります。
頂点に君臨するのは、アプリケーション全体を司る `ThisDrawing`(現在の図面)であり、その背後には `AcadApplication` がいます。そして、私たちが操作する線や円、文字といったすべての図形は、`ModelSpace`(モデル空間)または`PaperSpace`(ペーパー空間)という「箱」の中にコレクションとして格納されています。
AcadApplication
└─ AcadDocument (ThisDrawing)
├─ ModelSpace (すべての図形のコレクション)
│ ├─ AcadLine (線)
│ ├─ AcadCircle (円)
│ ├─ AcadText (文字)
│ └─ …
└─ Layers (画層コレクション)
オブジェクトを削除するということは、この `ModelSpace` という巨大な配列(厳密にはコレクション)から、特定の条件に合致する要素を安全に切り離す作業に他なりません。
—
2. 現場で即戦力!条件指定によるオブジェクト削除の全貌
それでは、実務でそのまま使えるコードを見ていきましょう。
今回は、「特定の画層(Layer)に属しており、かつ、特定の文字種(Text)であるオブジェクトを一括削除する」という、実務で頻出するシナリオを実装します。
以下のコードをVBAエディタ(Alt + F11)の標準モジュールに貼り付けてください。
Sub CleanUpDrawingByCondition()
Dim acadObj As AcadEntity
Dim i As Long
Dim deleteCount As Long
‘ 削除対象の条件定義
Const TARGET_LAYER As String = “一時補助線”
Const TARGET_TEXT As String = “DELETE_ME”
deleteCount = 0
‘ 【重要】コレクションを削除しながらループさせる時は「逆順」が鉄則!
For i = ThisDrawing.ModelSpace.Count – 1 To 0 Step -1
Set acadObj = ThisDrawing.ModelSpace.Item(i)
‘ 条件1: 指定した画層に属しているか?
If acadObj.Layer = TARGET_LAYER Then
‘ 条件2: オブジェクトが「文字(Text)」であるか?
‘ (型が一致しないプロパティへのアクセスを防ぐため、TypeNameで厳密に判定)
If TypeName(acadObj) = “AcadText” Then
‘ 条件3: 文字列の内容が一致するか?
If acadObj.TextString = TARGET_TEXT Then
‘ 削除実行
acadObj.Delete
deleteCount = deleteCount + 1
End If
End If
End If
Next i
‘ 処理結果の通知
MsgBox “クリーンアップが完了しました。” & vbCrLf & _
“削除されたオブジェクト数: ” & deleteCount & ” 件”, vbInformation, “AutoCAD VBA 自動化”
End Sub
—
3. コードの急所を解説:なぜこの書き方なのか?
上記のコードには、プログラミング初学者が必ずハマる「地雷」を華麗に回避するための、シニアエンジニアの知見が詰まっています。
① ループは必ず「逆順(Step -1)」で回せ!
これが今回の最も重要な学びです。
もし `For i = 0 To ModelSpace.Count – 1` と正順でループを回し、途中で `acadObj.Delete` を実行するとどうなるでしょうか?
オブジェクトが削除された瞬間、後ろに控えていたすべてのオブジェクトのインデックス番号が「1つずつ前方にズレ」ます。その結果、ループのカウンターが狂い、削除処理をすり抜けるオブジェクトが発生したり、致命的な実行時エラー(インデックスが有効範囲を超えています)を引き起こします。
後ろ(`Count – 1`)から前(`0`)に向かってループを回せば、たとえ要素が消えても、「これから処理しようとしている前方のインデックス」には一切影響が及びません。 コレクション操作の黄金律です。
② `TypeName` による安全な型安全ガード
AutoCADのモデル空間には、線、円、文字、ブロックなど、多種多様なオブジェクトが混在しています。
もし、線(`AcadLine`)に対して `acadObj.TextString` という文字専用のプロパティを呼び出そうとすると、VBAは「そんなプロパティねぇよ!」と怒り出し、エラーで強制終了します。
これを防ぐために、`TypeName(acadObj) = “AcadText”` と挟むことで、「今から料理しようとしている食材が、本当に文字肉(テキスト)なのか?」を厳密にチェックしているのです。
—
4. さらに応用力を高めるためのヒント
このコードをベースにすれば、あなたのアイデア次第で無限の自動化ツールが作れます。
- 色(Color)で条件分岐したい場合:
`acadObj.Color = acRed` のように、AutoCADの標準カラーインデックスと比較します。
- 画層ごと丸ごと消し去りたい場合:
オブジェクト単位ではなく、`ThisDrawing.Layers` から該当画層を `Delete` するアプローチもあります(※ただし、オブジェクトが残っていると消せないため、事前に上記のような一括削除が必要になります)。
—
最後に:ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ!
お疲れ様でした!
今回学んだ「逆順ループによる安全なコレクション操作」と「`TypeName` による型安全なプロパティアクセス」は、AutoCAD VBAを使いこなす上で避けて通れない、いわば「登竜門」です。
ここをクリアしたあなたなら、単なるマクロの記録の域を超え、複雑な図面データをも意のままに調理するエンジニアの仲間入りです。ぜひ手元の図面で実験し、一瞬でゴミが消え去る爽快感を味わってみてください。
それでは、次の自動化の旅でお会いしましょう。あなたの開発ライフが実り多きものになりますように!
