こんにちは!AutoCAD VBAの世界へようこそ。
マクロの記録ボタンを押すだけのステージから抜け出し、「自分の手で図面を自在に操りたい」と願うあなたなら、きっとこの扉を開ける準備ができているはずです。
今回は、AutoCAD VBAの基礎とオブジェクトモデルの真髄に迫るテーマ、「図面内の全ブロック参照のリスト化」を一緒に紐解いていきましょう。
「図面のあちこちに配置されたブロックの数を数えたい」「どのブロックがどこにあるのか一覧で確認したい」――実務でそんな壁にぶつかったことはありませんか?
ここをクリアすれば、AutoCAD VBAの基本オブジェクトモデル(`AcadApplication` や `AcadDocument`)の扱い方はもうバッチリです。さあ、一歩ずつ進んでいきましょう!
—
1. 最初に知るべき「AutoCADオブジェクトの階層構造」
AutoCAD VBAでコードを書くとき、私たちは「図面の中のどこを操作しているのか」という現在地を常に意識する必要があります。これは、Windowsのフォルダ階層に似ています。
最高司令官である `AcadApplication`(AutoCAD自体)の下に、現在開いている図面である `AcadDocument` がぶら下がっています。
AcadApplication (AutoCAD アプリケーション)
┗ AcadDocument (現在アクティブな図面)
┣ ModelSpace (モデル空間:作図領域)
┗ PaperSpace (レイアウト空間:図面枠など)
┗ ズラリと並ぶ図形たち (AcadEntity: 線、文字、そしてブロック参照)
私たちが今回やりたいのは、「現在の図面のモデル空間(あるいはペーパー空間)に飛び込み、そこに配置されている数ある図形の中から『ブロック参照(INSERT)』だけを正確に見つけ出すこと」です。
—
2. 実践!ブロック参照をリスト化するVBAコード
百聞は一見にしかず。まずは、開発の現場でそのままコピペして使える実用的なコードをお見せします。
AutoCADのVBAエディタ(Alt + F11)を開き、標準モジュールに以下のコードを貼り付けてみてください。
Sub ListUpBlockReferences()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument
Dim ent As AcadEntity
Dim blockRef As AcadBlockReference
Dim ws As Object ‘ Excel連携を見据えた汎用変数(今回はイミディエイト窓に出力)
Dim count As Long
On Error GoTo ErrorHandler
‘ 1. 現在稼働中のAutoCADアプリケーションとアクティブドキュメントを取得
Set acadApp = ThisDrawing.Application
Set acadDoc = acadApp.ActiveDocument
count = 0
‘ イミディエイトウィンドウを見出しでクリア
Debug.Print “— 図面内ブロック参照リスト —”
Debug.Print “ブロック名, 挿入X座標, 挿入Y座標, 挿入Z座標, 尺度(X)”
‘ 2. モデル空間内のすべてのエンティティ(図形)を総当たりでスキャン
For Each ent In acadDoc.ModelSpace
‘ 3. その図形が「ブロック参照 (AcDbBlockReference)」であるか判定
If TypeOf ent Is AcadBlockReference Then
‘ 型変換(キャスト)を行い、ブロック専用のプロパティにアクセスできるようにする
Set blockRef = ent
‘ 4. 必要な情報を抽出してイミディエイトウィンドウに出力
Debug.Print blockRef.EffectiveName & “,” & _
blockRef.InsertionPoint(0) & “,” & _
blockRef.InsertionPoint(1) & “,” & _
blockRef.InsertionPoint(2) & “,” & _
blockRef.XScaleFactor
count = count + 1
End If
Next ent
‘ 完了メッセージ
MsgBox “処理が完了しました。計 ” & count & ” 個のブロック参照を検出しました。”, vbInformation, “ブロックリスト化”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
—
3. コードのキモを徹底解説!初心者が押さべき3つのポイント
先輩エンジニアとして、このコードの特に重要なポイントを3つに絞って解説します。ここが理解できれば、他の図形(線や文字など)の抽出も自由自在になりますよ。
① `ThisDrawing.Application` と `AcadDocument` の関係
コードの冒頭で `ThisDrawing` を使っていますが、より厳密に `AcadApplication` から `AcadDocument` を取得する書き方(`acadApp.ActiveDocument`)をあえて採用しています。
複数の図面を開きながら自動処理を行うような「少し高度なマクロ」にステップアップする際、このアプリケーション階層を意識しているかどうかが命運を分けるからです。
② `For Each` と `TypeOf … Is` による「宝探し」
モデル空間には、直線(Line)、円(Circle)、文字(Text)など、様々なオブジェクトが混ざっています。
`For Each ent In acadDoc.ModelSpace` でゴソッと全図形を拾い上げ、その中から `If TypeOf ent Is AcadBlockReference Then` というフィルターをかけて、目的の「ブロック参照」だけをすくい上げています。
この「総当たりして型を判別する」というアプローチは、AutoCAD VBAの王道にして最強のテクニックです。
③ 動的ブロックにも対応する `EffectiveName`
ここが実務で一番重要なポイントです!
AutoCADには「ダイナミックブロック」という、形状が変化する賢いブロックが存在します。通常の `Name` プロパティを取得すると、内部的な無機質な名前が返されてしまうのですが、`EffectiveName` プロパティを使うことで、私たちが普段目にする「本来のブロック名」を正確に取得できます。
—
4. 陥りやすいエラーと、現場のプロが教える回避術
現場でこのコードを走らせるとき、いくつかの「罠」にハマることがあります。あらかじめ知っておけば怖くありません。
- 罠1:ペーパー空間(レイアウト図面枠など)のブロックが漏れる
- 解説: 今回のコードは `ModelSpace` だけをループしています。もしレイアウトタブ側に配置されたブロックも拾いたい場合は、`acadDoc.PaperSpace` も同様にループ処理してあげる必要があります。
- 罠2:ネストされた(入れ子になった)ブロックが見つからない
- 解説: ブロックの中に別のブロックが入っている場合、単純なモデル空間のループでは最外層しかヒットしません。これらを完璧に網羅するには「再帰処理(関数が自分自身を呼び出す仕組み)」が必要になります。まずは今回の基本コードで単層のブロックを制覇してから挑戦しましょう!
- 罠3:オブジェクトの解放忘れによるメモリリーク
- 解説: 大規模な図面を何枚も連続処理する場合、`Set blockRef = Nothing` のようにオブジェクト変数をこまめに解放してあげると、AutoCADの動作が軽快になります(VBAのガベージコレクションを優しくアシストするイメージです)。
—
おわりに:ここをクリアすれば、あなたはもう初心者じゃない!
お疲れ様でした!
「図面内の全ブロック参照をリスト化する」という一見難しそうな課題も、オブジェクトモデルの階層を理解し、適切なフィルター(`TypeOf`)を通すことで、こんなにもスッキリと記述できることが体感できたかと思います。
ここをクリアしたあなたなら、抽出したデータをExcelに書き出して集計表を作ったり、特定のブロックの属性(Attribute)を書き換えたりする自動化へと、自信を持って進んでいけるはずです。
分からないことがあれば、いつでも何度でもこのコードを読み返し、自分の手で改造してみてください。
あなたのAutoCADライフが、もっとスマートでクリエイティブなものになりますように。先輩エンジニアとして、いつも応援しています!
