【テクニカル・上級編】【実務中級】AutoCAD VBAで図面内の全ハッチング(Hatch)オブジェクトのパターン、尺度、角度をまとめて変更する – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAの深淵:ハッチング一括制御に見るメモリ管理とオブジェクトの最適化

AutoCADのAPIを叩く際、多くのエンジニアは「動けば良い」という甘美な罠に陥る。しかし、図面規模が数万オブジェクトを超え、外部参照が複雑に絡み合う実務の現場では、甘い実装は即座にメモリリークと動作不安定という代償を支払うことになる。

今回は、ハッチングオブジェクトの全プロパティ一括変更を題材に、シニアエンジニアが意識すべき「オブジェクトのライフサイクル」と「パフォーマンスの極致」について解説する。

1. 勘違いされがちな「全走査」の定石

多くの初心者は、`ModelSpace`を`For Each`で回す際に何も考えずにオブジェクトを触る。だが、AutoCADのCOMインターフェースにおいて、オブジェクトの不用意な参照保持は、VBAのガベージコレクションを阻害し、不安定な挙動の温床となる。

私たちは、「必要な時だけ参照し、即座に解放する」というC言語ライクな規律をVBAに持ち込む必要がある。

2. 実装コード:Hatch Property Batch Controller

以下に、速度と安定性を追求したハッチング一括変更ルーチンを示す。

Option Explicit

‘ メモリ保護のため、明示的にオブジェクトのライフサイクルを制御する
Public Sub UpdateAllHatchProperties(ByVal patternName As String, _
ByVal scaleFactor As Double, _
ByVal angle As Double)
Dim doc As AcadDocument
Dim mSpace As AcadModelSpace
Dim ent As AcadEntity
Dim hatchObj As AcadHatch

Set doc = ThisDrawing
Set mSpace = doc.ModelSpace

‘ トランザクション処理を意識したエラーハンドリング
On Error GoTo ErrorHandler

‘ 描画更新を一時停止し、パフォーマンスを劇的に向上させる
doc.Utility.Prompt “ハッチング更新処理を開始…”

For Each ent In mSpace
‘ 型判定により不要な型へのキャストを避ける
If TypeOf ent Is AcadHatch Then
Set hatchObj = ent

‘ パターン変更時は、パターンの種類(Predefined/Custom/UserDefined)を考慮する必要がある
‘ ここでは標準的なパターンの更新を想定
hatchObj.PatternName = patternName
hatchObj.PatternScale = scaleFactor
hatchObj.PatternAngle = angle

‘ 変更を反映
hatchObj.Update

‘ 明示的なオブジェクト解放(ループ内でのメモリ解放)
Set hatchObj = Nothing
End If
Next ent

doc.Regen acActiveViewport
MsgBox “更新完了。”
Exit Sub

ErrorHandler:
MsgBox “エラー発生: ” & Err.Description
Set hatchObj = Nothing
End Sub

3. シニアエンジニアが抑えるべき「極限の最適化」ポイント

A. オブジェクトの循環参照を避ける

上記のコードでは、`Set hatchObj = Nothing`をループ内で実行している。VBAのCOM参照カウントは、特に大規模な図面では非常にデリケートだ。ループ内でオブジェクト変数を再代入する際、明示的な解放を怠ると、スコープが抜けるまで参照がメモリ上に残り続け、大規模な図面ではヒープ領域を圧迫する。

B. `Document.Utility.Prompt` の活用

大規模な一括処理を行う際、AutoCADは操作不能に陥るように見える。`Utility.Prompt`を用いて、処理のステータスをコマンドラインにリアルタイムに出力せよ。これにより、ユーザーは「フリーズした」と誤解して強制終了させることを防げる。

C. レガシー環境への配慮(Windows APIの利用)

もし処理が数万オブジェクトに及ぶ場合、VBAの実行速度がボトルネックとなる。その場合、`kernel32`の`GetTickCount`を呼び出し、処理時間を計測してボトルネックを特定する手法が有効だ。

If VBA7 Then
Private Declare PtrSafe Function GetTickCount Lib “kernel32” () As Long
Else
Private Declare Function GetTickCount Lib “kernel32” () As Long
End If

このAPIを用いれば、どのレイヤの走査が遅いのか、どの種類のハッチングが負荷をかけているのかを数値化できる。エンジニアリングとは、勘ではなく計測から始まるのだ。

4. 最後に:アーキテクチャの統一へ

このコードをそのまま使うのは「第一段階」に過ぎない。実務では、これに「特定のレイヤのみ」「特定の名前のハッチングのみ」というフィルタリングを、`Collection`クラスや`Dictionary`を用いた事前キャッシュ機構と組み合わせる必要がある。

AutoCAD VBAは古臭い技術だと言われがちだが、そのオブジェクトモデルの深さは、現代の言語にも引けを取らない。メモリを制する者が、CADの自動化を制する。

次に構築するシステムでは、ぜひ、この「メモリへの敬意」を忘れないでほしい。それが、伝説の自動化エンジニアへの第一歩となる。

タイトルとURLをコピーしました