【AutoCAD VBA】ブロックの深淵を覗く:GetSubEntityによるネスト図形の直接操作術
AutoCADの自動化において、最も初歩的かつ「罠」が多いのが、ブロックや外部参照(XRef)の内部構造へのアクセスだ。
「ブロック内の線分一本の色を変えたい」。この単純な要求に対し、初心者は決まって「一度分解(Explode)してから処理し、再度ブロック化する」という破壊的で低効率なコードを書く。だが、それはプロの設計ではない。DWGの整合性を破壊し、Undoログを汚し、何より後続の設計者に多大な迷惑をかける。
本稿では、`Utility.GetSubEntity` を用い、ブロックを分解することなく、その深層にある個別の図形をピンポイントで操作する「外科手術レベル」のVBA実装を伝授する。
—
なぜ「分解」は悪手なのか
まず、アーキテクトとしての忠告だ。`Explode` は最後の手段であるべきだ。
- 非可逆性: 複雑なブロックを分解すると、属性定義や制約が失われ、再構築時に元の図形と同一性を維持できない。
- パフォーマンス: 大規模な図面で数百のブロックを分解・再結合すれば、計算リソースを無駄に消費する。
- データベースの汚染: `Explode` は新しいID(Handle)を生成する。既存の外部データベース連携や、属性値の追跡を行っているシステムにとって、これは破壊的な変更だ。
「直接触る」こと。これが唯一にして至高の解決策である。
—
GetSubEntity:階層を貫く鍵
`GetSubEntity` は、ユーザーが選択した「ネストされたオブジェクト」の情報を取得するための特殊なメソッドだ。通常の `GetEntity` と異なり、単にオブジェクトを返すだけでなく、`ObjectPath` という配列を返す。これが、どのブロックの、どのインスタンスの中にある要素かという「住所」を特定する唯一の指標となる。
実装コード:ネスト図形の直接プロパティ変更
以下のコードは、選択したブロック内のネストされた要素の画層を、現在画層に強制変更する実務的なサンプルだ。
Public Sub ModifyNestedEntity()
Dim pickObj As Object
Dim pickPoint As Variant
Dim objPath As Variant
Dim subEntity As AcadEntity
On Error Resume Next
‘ 1. ネストされたオブジェクトをユーザーに選択させる
ThisDrawing.Utility.GetSubEntity pickObj, pickPoint, objPath, “対象となるネスト図形を選択してください:”
If Err.Number <> 0 Then
MsgBox “選択がキャンセルされました。”, vbExclamation
Exit Sub
End If
‘ 2. 取得したパスから末尾の要素(個別の図形)を特定
‘ objPath(UBound(objPath)) が、選択された最下層の図形を指す
Set subEntity = objPath(UBound(objPath))
‘ 3. 堅牢なプロパティ操作(型チェックを忘れずに)
‘ ここでは画層を変更する例だが、色や線種も同様に操作可能
On Error GoTo Cleanup
subEntity.Layer = ThisDrawing.ActiveLayer.Name
subEntity.Update
MsgBox “図形の画層を ” & subEntity.Layer & ” に変更しました。”, vbInformation
Exit Sub
Cleanup:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
—
現場で勝つための「3つの鉄則」
このコードをプロダクション環境に投入する際、以下の3点を意識しなければならない。
1. `ObjectPath` の解析を怠るな
`objPath` 配列の末尾には、必ず操作対象の `AcadEntity` が格納されている。しかし、その親階層(`objPath(0)` から `objPath(UBound – 1)`)を辿れば、どのブロック参照(`AcadBlockReference`)を経由しているかも特定できる。もし「特定の名前のブロック内にある線分のみを許可する」といった制御が必要なら、この配列をループで走査し、親の `Name` プロパティを検証せよ。
2. トランザクションとエラーハンドリング
AutoCAD VBAにおいて、`GetSubEntity` は時折不安定な挙動を見せる。特にロックされた画層や、読み取り専用の外部参照に対して実行した際の例外処理は必須だ。「なぜ動かないか」をユーザーに伝えるための `Err.Description` のフィルタリングを怠るな。
3. 「Update」のタイミングを制御せよ
`subEntity.Update` を呼び出すと、AutoCADは画面の再描画を行う。ループ処理の中でこれを呼ぶとパフォーマンスが著しく低下する。複数の図形を連続で処理する場合は、ループを抜けた後に一度だけ `Regen` をかけるか、各オブジェクトの `Update` を最小限に抑える設計にすること。
—
最後に:エンジニアとしての矜持
AutoCADを単なる「絵を描くツール」と見るか、「空間データを持つデータベース」と見るか。
`GetSubEntity` を使いこなせるようになれば、あなたは後者の視点に立っている。ブロックというブラックボックスを分解せずに内部を制御するこの技術は、設計変更が頻発する日本の現場において、あなたのツールを唯一無二の存在へと昇華させるだろう。
さあ、コードを書き換えろ。そして、GUI上の作業時間を徹底的に削り出せ。それが、自動化エンジニアに課せられた使命だ。
