AutoCAD VBAを掌握する:ダイナミックブロック制御の深淵
AutoCADのオートメーションにおいて、最も「現場を苦しめる」かつ「最強の武器になる」のがダイナミックブロックの制御だ。多くのエンジニアは`GetDynamicBlockProperties`メソッドを呼んで満足するが、それは入り口に過ぎない。
真の自動化エンジニアは、オブジェクトのライフサイクルを管理し、メモリリークを恐れず、非同期に近い挙動を制御下に置く。今日は、ダイナミックブロックのプロパティをVBAで完全に支配するための「極限の知見」を共有する。
—
1. ダイナミックブロックの構造を「見抜く」
`DynamicBlockReferenceProperty`は、通常の`AcadEntity`のプロパティとは異なり、VARIANT型の配列として管理されている。これを安易にループで回すのは素人の所業だ。
まず、対象のブロックが本当にダイナミックブロックであるかを確認し、`GetDynamicBlockProperties`を取得した後は、必ずオブジェクトの解放を意識せよ。VBAのガベージコレクションは頼りにならない。
核心的コード:プロパティの安全な取得と更新
Public Sub UpdateDynamicProperty(ByRef blockRef As AcadBlockReference, propName As String, newValue As Variant)
Dim props As Variant
Dim i As Long
‘ 1. ダイナミックブロックか否かの厳密な判定
If Not blockRef.IsDynamicBlock Then Exit Sub
‘ 2. プロパティ配列の取得
props = blockRef.GetDynamicBlockProperties
‘ 3. メモリ効率を考慮したループ(配列の境界に注意)
For i = LBound(props) To UBound(props)
Dim prop As AcadDynamicBlockReferenceProperty
Set prop = props(i)
If prop.PropertyName = propName Then
‘ 値の妥当性チェックを忘れずに(ReadOnlyプロパティの回避)
If Not prop.ReadOnly Then
prop.Value = newValue
‘ 更新後の再計算を強制(必要に応じてUpdateメソッドを呼ぶ)
blockRef.Update
End If
Exit For
End If
‘ オブジェクト参照の明示的破棄
Set prop = Nothing
Next i
‘ 配列の解放(VBAの仕様上、明示的にクリアする習慣を)
Erase props
End Sub
—
2. パフォーマンスの重み:なぜ「更新」で落ちるのか
大規模図面で数百のブロックをバッチ処理する場合、`blockRef.Update`をループ内で叩くのは自殺行為だ。AutoCADの再描画エンジンは、イベント駆動で動く。
- 解決策: `Application.ScreenUpdating`(AutoCADでは `SysVar: PICKFIRST` や `SysVar: REGENMODE` の制御)を駆使し、トランザクションが終了するまで再描画を抑制せよ。
- 極意: `AcadDocument`の`SendCommand`を多用するのは避けよ。内部的なAPI呼び出しが、スタックを圧迫し「致命的なエラー」を招く元凶となる。
—
3. レガシー環境におけるWindows APIとの共鳴
VBA単体では、AutoCADの非同期イベント(ブロックが変更された直後の座標計算など)を拾いきれないことがある。その場合、`User32.dll`を用いて、AutoCADのメインウィンドウメッセージをフックするアプローチが有効だ。
‘ 必要なAPI宣言
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
‘ 大量更新時の「待ち」を最適化する
Public Sub BatchUpdateProcess(ByRef colBlocks As Collection)
Dim b As Variant
‘ 再描画をOFFにして高速化
ThisDrawing.SetVariable “REGENMODE”, 0
For Each b In colBlocks
UpdateDynamicProperty b, “距離1”, 500.0
Next b
‘ 最後に一括再描画
ThisDrawing.SetVariable “REGENMODE”, 1
ThisDrawing.Regen acActiveViewport
End Sub
—
4. チーフアーキテクトからの忠告
あなたがもし、このコードを保守性の低い「1つの巨大なプロシージャ」に記述しているなら、今すぐ修正が必要だ。
1. クラスモジュールの活用: `DynamicBlockManager`のようなクラスを作成し、`blockRef`をラップせよ。
2. 型安全性の確保: `Variant`の乱用はデバッグを困難にする。プロパティの型(`acAllowedValues`など)を事前に列挙型で管理する仕組みを作ること。
3. エラーハンドリングの哲学: 「エラーが出ない」ではなく「エラーを握りつぶさず、ログに吐き出し、どこまで処理が完了したかを復元できる」状態を目指せ。
最後に
AutoCAD VBAはレガシーと言われる。だが、APIの深い部分を突き詰めれば、現代の設計現場においても依然として最強の爆速ツールだ。
コードは「書く」ものではなく「構築する」ものだ。オブジェクトのライフサイクルを掌握し、AutoCADという巨大なエンジンをあなたの手足のように動かしてほしい。
次回の講義では、`ObjectARX`とVBAをブリッジするパイプライン設計について掘り下げるとしよう。それまでは、このコードで現場の自動化を極めてくれ。
