AutoCAD VBAを掌握する極限の知見:永続的「グループ」オブジェクトの完全制御とメモリ最適化
AutoCAD VBAの実務開発において、多くの開発者が陥る最初の罠が「選択セット(SelectionSet)」と「グループ(Group)」の混同である。
`SelectionSets` はセッション限りの一時的なエンティティの集合に過ぎず、図面を閉じれば消滅する。これに対し、`AcadGroup` は図面データベース(DWG)のディクショナリ領域に永続的に常駐するファーストクラスのオブジェクトである。
今回は、実務で数万図面をハンドリングするシニアエンジニア向けに、この「グループ」オブジェクトのライフサイクル管理、パフォーマンスの限界を引き出すメモリ最適化、そしてレガシー環境特有の罠を回避する極限の知見を授ける。
—
1. AutoCADオブジェクトモデルにおける「グループ」の真実
AutoCADの内部アーキテクチャにおいて、グループは `AcadGroups` コレクションによって管理され、各 `AcadGroup` は `AcadEntity` のポインタ配列を保持している。
ここで重要なのは、「グループに属する図形は、それぞれ個別のレイヤや画層に存在しながら、論理的なバインドを維持できる」という点だ。ブロック(Block)のように新しいブロック定義を生成する必要がないため、既存の図形構成を一切破壊せずに「一塊のエンティティ」として扱いたい場合に唯一無二のソリューションとなる。
しかし、COMラッパーであるVBAからこれを操作する場合、不適切なオブジェクト参照の保持は、AutoCADのプロセス(`acad.exe`)内にメモリリークを引き起こし、や実施せざるを得ない「致命的なフリーズ」の温床となる。
—
2. 実装:堅牢なグループ作成・構成図形追加・一括変形コード
以下のコードは、図面上の特定の条件を満たす図形を動的に検索し、永続グループに登録した上で、一括して座標変換(移動・回転)を行う実務水準のプロシージャである。
Option Explicit
‘ ==============================================================================
‘ 処理名: CreateAndTransformPersistentGroup
‘ 概要: 指定した図形群から永続グループを生成し、一括で移動・回転を行う
‘ 備考: オブジェクトの参照解放を徹底し、メモリリークを完全防御する
‘ ==============================================================================
Public Sub CreateAndTransformPersistentGroup()
Dim acadApp As AcadApplication
Dim acadDoc As AcadDocument
Dim acadGroups As acadGroups
Dim targetGroup As AcadGroup
‘ エラーハンドリングの初期化
On Error GoTo ErrorHandler
‘ 1. アプリケーションおよびアクティブドキュメントの安全な取得
Set acadApp = ThisDrawing.Application ‘ または GetObject(, “AutoCAD.Application”)
Set acadDoc = acadApp.ActiveDocument
‘ 2. グループコレクションの取得
Set acadGroups = acadDoc.Groups
‘ 3. 既存グループ名の競合回避(同名が存在する場合は削除して再作成)
Dim groupName As String
groupName = “PRD_ASSEMBLY_GROUP_01”
Dim i As Long
For i = 0 to acadGroups.Count – 1
If acadGroups.Item(i).Name = groupName Then
acadGroups.Item(i).Delete
Exit For
End If
Next i
‘ 4. 新規永続グループの生成
Set targetGroup = acadGroups.Add(groupName)
‘ 5. グループに追加するエンティティの配列を準備
‘ ※ここではモデル空間から特定の条件(例: 画層名が “MECHANICAL”)の図形を収集
Dim ent As AcadEntity
Dim entCount As Long
entCount = 0
‘ 動的配列の初期化
Dim entitiesToAdd() As AcadEntity
ReDim entitiesToAdd(0)
For Each ent in acadDoc.ModelSpace
If ent.Layer = “MECHANICAL” Then
Set entitiesToAdd(entCount) = ent
entCount = entCount + 1
ReDim Preserve entitiesToAdd(entCount)
End If
Next ent
‘ 追加対象が存在する場合のみグループへアタッチ
If entCount > 0
‘ 最後の余分な要素を切り落とす
ReDim Preserve entitiesToAdd(entCount – 1)
‘ グループへエンティティの一括追加
targetGroup.AppendItems entitiesToAdd
‘ 6. グループ単位での一括変形操作(例: X方向へ 500.0, Y方向へ 300.0 移動)
Dim displacement(0 to 2) As Double
displacement(0) = 500.0: displacement(1) = 300.0: displacement(2) = 0.0
‘ グループオブジェクト自体には直接 Move メソッドはないため、
‘ 構成エンティティの配列に対して一括適用するか、またはグループ外接矩形を利用する。
‘ ※安全確実な「配列ループによる一括処理」を実行
Dim memberEnt As Variant
For Each memberEnt in targetGroup
memberEnt.Move displacement(0), displacement(1), displacement(2)
Next memberEnt
acadDoc.Utility.PrintMessage “グループ [” & groupName & “]: ” & entCount & “件の図形を統合・移動しました。” & vbCrLf
Else
acadDoc.Utility.PrintMessage “対象となる図形が見つかりませんでした。” & vbCrLf
targetGroup.Delete ‘ 空のグループはゴミになるため削除
End If
CleanUp:
‘ ==========================================================================
‘ 極限のメモリ最適化:COMオブジェクトの明示的解放
‘ ==========================================================================
On Error Resume Next
Erase entitiesToAdd
Set targetGroup = Nothing
Set acadGroups = Nothing
Set acadDoc = Nothing
Set acadApp = Nothing
Exit Sub
ErrorHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “AutoCAD VBA Error”
Resume CleanUp
End Sub
—
3. チーフアーキテクトが教える「現場の知見」とパフォーマンス最適化
① COMポインタのライフサイクルとメモリリークの根絶
VBAのガベージコレクションは極めて怠惰である。`For Each` や `AcadDocument.ModelSpace` の走査によって生成されたCOMラッパーオブジェクトは、明示的に `Set xxx = Nothing` を呼ぶまでAutoCADのプロセス空間に参照カウントを残し続ける。
これを怠ると、マクロを数回実行しただけでメモリ使用量が数百MB跳ね上がり、最悪の場合 `Automation Error` を引き起こしてAutoCADごと強制終了する。上記のコードのように、例外発生時(`Error Handler`)であっても確実に参照を断ち切る構造化が不可欠である。
② グループ操作における「隠れた制約」
`AcadGroup` はデフォルトでは「選択可能(Selectable)」な状態で作成される。
もしプログラム制御下で、ユーザーが画面上でグループを選択した際に意図せぬ崩壊を防ぎたい場合、または一括選択を強制したい場合は、グループのプロパティを制御する必要がある。しかし、VBAの標準オブジェクトモデルでは `Selectable` プロパティの直接変更が制限されているケースがあるため、実務では `ExtensionDictionary` や `Xdata`(拡張データ)を併用して独自のメタデータを付与するアーキテクチャが推奨される。
③ レガシー環境・マルチドキュメント(MDI)の罠
AutoCAD 2000以降、MDI(マルチドキュメントインターフェイス)環境が標準となった。
これにより、複数の図面が同時にメモリ上に展開される。`ThisDrawing` というグローバルショートカットは「現在アクティブな図面」を指すが、バックグラウンド処理やイベントハンドラ内ではこれが予期せぬ図面を指す致命的なバグ(コンテキストズレ)を引き起こす。
シニアエンジニアたるもの、`ThisDrawing` への依存を断ち切り、必ず `Application.ActiveDocument` または明示的に渡された `AcadDocument` 参照をスコープ内に閉じ込めて処理すべきである。
—
総括
永続グループの制御は、単なるAPIの呼び出しではなく、「AutoCADのデータベース構造」と「VBAのメモリ管理モデル」の双方を熟知した者のみが扱える高精度なメスである。
この知見をあなたの開発環境に組み込むことで、図面自動化スクリプトの信頼性は劇的に向上し、レガシーシステムの呪縛から完全解放されるだろう。コードの美しさと堅牢性を両立させよ。
