SolidWorks VBAを極限まで加速させる:描画負荷を封じ込める「不可視」のアーキテクチャ
SolidWorks APIを操るエンジニアにとって、最大の敵は「無駄な再描画」だ。数千のフィーチャを生成するマクロを組んだ際、画面が激しく点滅し、処理が止まったように見える経験はないだろうか。それは単なる演出上の問題ではない。APIが不必要にグラフィックパイプラインを叩いている証拠であり、実行速度を著しく低下させている。
本稿では、レガシーなVBA環境下であっても、SolidWorksの描画ロジックを強制的に制御し、処理速度を限界まで引き出すための「プロフェッショナル・プラクティス」を伝授する。
—
1. 描画更新の完全停止:`EnableGraphicsUpdate` の落とし穴
多くのエンジニアが `ModelDoc2.EnableGraphicsUpdate = False` を使うが、これだけでは不十分だ。このメソッドは描画を抑制するが、内部的なジオメトリ計算やキャッシュの再構築までを完全に止めるわけではない。
真に高速化を求めるなら、描画停止と合わせて「再計算のトリガー」を制御する必要がある。
実践的なラッパークラス(構造体)の定義
マクロの開始時にグラフィックを殺し、終了時に復帰させるための定型文を以下に示す。
‘ 描画・更新の完全封鎖を行うための管理クラス
Public Sub OptimizeMacroStart(ByRef swModel As SldWorks.ModelDoc2)
‘ 1. グラフィック更新を即座に停止
swModel.EnableGraphicsUpdate = False
‘ 2. フィーチャの自動再構築を抑制(重要:大量生成時は必須)
‘ これにより、生成ごとの再ビルドコストを排除する
swModel.FeatureManager.EnableFeatureTree = False
End Sub
Public Sub OptimizeMacroEnd(ByRef swModel As SldWorks.ModelDoc2)
‘ 1. 最終的なリビルドを一度だけ実行
swModel.ForceRebuild3 True
‘ 2. 描画を復帰
swModel.EnableGraphicsUpdate = True
swModel.FeatureManager.EnableFeatureTree = True
‘ 3. 最後に一度だけフィット表示(無駄な連呼は不要)
swModel.ViewZoomtofit2
End Sub
—
2. `ViewZoomtofit2` の呪縛を解く
初心者がやりがちなミスは、ループ内で `ViewZoomtofit2` を呼び出すことだ。これはグラフィックエンジンに対して「現在の全オブジェクトをスキャンして画面に収めろ」という重い演算を要求する。100回ループすれば100回、GPUが悲鳴を上げる。
鉄則:再描画は「最小限のタイミング」で一度だけ行う。
もし進行状況をユーザーに見せたい場合でも、`DoEvents` と組み合わせて「N回に一度」だけ更新するロジックを挿入すること。
‘ 100フィーチャごとに更新する設計
If i Mod 100 = 0 Then
swModel.EnableGraphicsUpdate = True
swModel.GraphicsRedraw2 ‘ 全体フィットより軽量なRedrawを使用
swModel.EnableGraphicsUpdate = False
DoEvents ‘ ユーザーの操作介入を許可しつつ、フリーズを防ぐ
End If
—
3. メモリ解放の神髄:COMオブジェクトの寿命管理
VBAはガベージコレクションが極めて脆弱だ。大規模なパーツ生成を行う際、COMオブジェクトを明示的に解放しないと、SolidWorksのメモリ使用量は右肩上がりに増え続け、最終的にプロセスがクラッシュする。
シニアエンジニアが守るべき記述
`Nothing` を代入するだけでは不十分な場合がある。特に `IFeature` や `ISketch` をループで回す際は、スコープを意識せよ。
Dim swFeat As SldWorks.Feature
‘ … 生成処理 …
‘ ループ終了後には確実にメモリを解放する
Set swFeat = Nothing
‘ さらに、メモリを明示的に強制回収する(Win32API利用の代替案)
‘ アプリケーションが重い場合は、適宜DoEventsを挟んでOSに制御を返す
—
4. なぜ「レガシー」が速いのか:アーキテクチャの真実
VB.NETではなくあえてVBAを選ぶ場合、そこには「SolidWorksプロセス内での実行」という最大の利点がある。外部プロセスからの呼び出し(RPC)は、オブジェクトのシリアライズ/デシリアライズにより数十倍のオーバーヘッドが生じる。
- API通信量を減らす: `SelectionManager` で複数のアイテムを一度に選択してから処理するのと、一つずつ処理するのでは、通信の回数が異なり、結果として実行時間が数倍変わる。
- キャッシュの活用: `ModelDoc2` の情報を取得する際、同じプロパティをループ内で何度も呼ぶな。一度ローカル変数に格納し、それを参照せよ。
結びに:伝説は「細部」に宿る
「画面を止め、再計算を止め、不要な通信を排除する」。
これら基本的な規約を徹底するだけで、マクロの実行時間は劇的に改善する。私がこれまで見てきた「数分かかる重いマクロ」のほとんどは、コードが悪いのではなく、SolidWorksに対する「余計な命令」が多すぎただけだ。
あなたが書くコードは、単なるスクリプトではない。SolidWorksという巨大なCADエンジンの心臓部に直接命令を下す、極めて繊細な制御プログラムである。その自覚を持って、一撃の重みを意識したコーディングを心がけてほしい。
次回の記事では、大規模アセンブリにおける「コンポーネント抑制状態」をAPIで制御し、メモリリークを皆無にするための極意を解説する。期待していてほしい。
