【SolidWorks VBA極限optimization】SwApp.SetUserPreferenceToggleによる画面描画・再計算の完全凍結とマクロ最大化の数理
レガシーなVBA環境であれ、最新のAPIラッパーであれ、数千のフィーチャを持つ複雑なパーツモデルを自動生成する際、多くの開発者が直面する最大の障壁は「処理の重さ」ではない。「無駄なグラフィック描画と、フィーチャ追加ごとのトポロジー再計算(Rebuild)による深刻なオーバーヘッド」である。
画面がバクバクと点滅し、タスクマネージャーのCPU使用率が無駄に跳ね上がり、1つのパーツ生成に数分を要する――。この非効率なコードを放置することは、エンジニアリングリソースの深刻な無駄遣いである。
今回は、SldWorksアプリケーションの内部グラフィックパイプラインとイベント駆動のライフサイクルを強制的にバイパスし、マクロ実行速度を理論値の限界まで引き上げる極限のテクニックを授ける。
—
1. なぜSolidWorksマクロは遅いのか?(根本原因の解析)
SolidWorks VBAの裏側では、COM(Component Object Model)を介してC++ネイティブのParasolidカーネルが動作している。標準状態では、マクロから1つのAPIメソッド(例えば `CreateExtrusion2` など)を叩くたびに、以下の重厚なプロセスが同期的に実行される。
1. ジオメトリの演算(Parasolid Kernel)
2. フィーチャツリーの整合性検証(FeatureManager Tree Update)
3. グラフィックバッファのフラッシュとビューポートの再描画(OpenGL Pipeline)
4. UIスレッドへの制御権の返還とイベントメッセージの処理
特に3と4のコストは、幾何学的計算そのものよりも遥かに重い。この「目に見える親切心」こそが、自動化スクリプトの足を引っる最大の元凶なのだ。これを断ち切るのが、`SwApp.SetUserPreferenceToggle` による描画・再計算の完全凍結である。
—
2. 核心API:`SetUserPreferenceToggle` の全貌
画面の更新を止め、SolidWorksを「サイレント・バッチモード」に変貌させるために使用するのが以下のシステム設定トグルだ。
- `swUserPreferenceToggle_e.swViewUpdateAfterModeChange` (ビュー更新の抑止)
- `swUserPreferenceToggle_e.swInteractiveMode` (インタラクティブモードの制御)
しかし、単にこれらを切り替えるだけでは不十分である。ドキュメントレベルでの再計算抑制(`AutoRebuild`)や、モデルの表示状態管理を組み合わせる必要がある。
—
3. 【実装コード】極限まで最適化されたパーツ生成テンプレート
以下のコードは、単なるリファレンスのコピーではない。オブジェクトのライフサイクル管理、例外発生時の安全な状態復旧(Error Handlerの確実な実行)、そして画面描画の完全なフリーズ&アンフリーズを網羅した、チーフアーキテクト水準の実用コードである。
Option Explicit
‘ ==============================================================================
‘ 伝説的チーフアーキテクトによる SolidWorks VBA 高速パーツ生成テンプレート
‘ テーマ: 画面描画停止と再計算抑止によるパフォーマンスの極限追求
‘ ==============================================================================
Public Sub ExecuteHighSpeedPartGeneration()
Dim swApp As SldWorks.SldWorks
Dim swPart As SldWorks.PartDoc
Dim longstatus As Long
‘ 処理時間計測用
Dim startTime As Double
startTime = Timer
‘ 1. SldWorks アプリケーションインスタンスの取得
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical
Exit Sub
End If
‘ ==========================================================================
‘ 【極限最適化フェンス】環境の完全凍結
‘ ==========================================================================
On Error GoTo ErrorHandler
‘ A. 画面の自動再描画を完全停止 (UIスレッドの切り離し)
swApp.Visible = True ‘ アプリケーション自体は隠さないが描画を止める
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewUpdateAfterModeChange, False
‘ B. バックグラウンドでの図面・パーツの自動再計算を抑止
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDocumentDefaultsAlwaysRebuild, False
‘ C. ユーザーインタラクション(マウス・キーボード入力)のロック
swApp.UserControl = False
‘ 2. 新規パーツドキュメントの作成 (テンプレートを指定して高速化)
Dim templatePath As String
templatePath = swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplatePart)
Set swPart = swApp.NewDocument(templatePath, 0, 0, 0)
If swPart is Nothing Then
Err.Raise 1000, “PartCreation”, “パーツドキュメントの生成に失敗しました。”
End If
‘ 3. ドキュメントレベルでのフィーチャ自動再構築をオフに設定
Dim swModel As SldWorks.ModelDoc2
Set swModel = swPart
swModel.FeatureManager.EnableFeatureTree = False ‘ フィーチャツリーの視覚的更新を停止
‘ ==========================================================================
‘ 【高負荷処理セクション】 ここに重いジオメトリ生成処理を記述
‘ ==========================================================================
Debug.Print “— ジオメトリ生成ループ開始 —”
Dim i As Long
For i = 1.0 To 100
‘ ※ここに実際の押し出しやカットなどの重いAPI処理が入る想定
‘ 例: 複雑なスケッチエンティティの追加、フィーチャ生成など
‘ 処理中は画面が更新されないため、驚異的なスピードで処理が完了する
Next i
Debug.Print “— ジオメトリ生成ループ終了 —”
‘ ==========================================================================
‘ 【クリーンアップ&システム復旧フェーズ】
‘ ==========================================================================
‘ フィーチャツリーの更新を再有効化
swModel.FeatureManager.EnableFeatureTree = True
‘ 最後に1度だけ明示的に強制再構築(ForceRebuild3)を実行し、整合性を保証
Dim status As Boolean
status = swModel.ForceRebuild3(False)
‘ 環境を元に戻す (必ず実行されるようにErrorHandlerまたは直書きする)
Call RestoreEnvironment(swApp)
‘ 完了ログ
MsgBox “処理が正常終了しました。\n実行時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation
Exit Sub
ErrorHandler:
‘ 異常終了時でも必ずSolidWorksのUIを元の安全な状態に戻す
‘ これを怠ると、SolidWorksがフリーズしたままロックされる致命的なバグに繋がる
Call RestoreEnvironment(swApp)
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End Sub
‘ ==============================================================================
‘ 環境復旧プロシージャ (例外安全性担保の要)
‘ ==============================================================================
Private Sub RestoreEnvironment(ByRef swApp As SldWorks.SldWorks)
On Error Resume Next ‘ 復旧中のエラーで止まらないようにする
If Not swApp Is Nothing Then
‘ 描画フラグを元に戻す
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewUpdateAfterModeChange, True
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDocumentDefaultsAlwaysRebuild, True
‘ ユーザーコントロールを復帰
swApp.UserControl = True
‘ 画面の強制リフレッシュ
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.ActiveDoc
If Not swModel Is Nothing Then
swModel.GraphicsRedraw2
End If
End If
On Error GoTo 0
End Sub
—
4. シニアエンジニアが押さえるべき「罠」とメモリ最適化の極意
この手法を実務のシステムに組み込む際、以下の「落とし穴」を理解しているか否かでエンジニアとしての格が分かれる。
① 例外発生時の「UIデッドロック」の回避
`SetUserPreferenceToggle` や `UserControl = False` を適用した状態でVBAコードがエラー(ゼロ除算やオブジェクト参照エラーなど)で予期せぬ中断を起こした場合、SolidWorksの画面が描画停止・入力ロックされたまま永遠にフリーズした状態(ゾンビプロセス)になる。
必ず上記コードのように `On Error GoTo` を駆使し、異常系であっても確実に `RestoreEnvironment` がコールされる堅牢な設計(RAIIのVBA的実装)を義務付けなければならない。
② 複数ドキュメント連携時のスコープ管理
もし外部のPDMシステムやデータベースから連鎖的に複数のパーツ(親子関係)を生成・アセンブリに組み込むバッチ処理を行う場合、アプリケーションスコープの設定(`SwApp` レベル)を変更すると、裏で開いている無関係なドキュメントの挙動にも影響を与える。
大規模なシステム連携においては、グローバルな設定変更に頼るだけでなく、`ModelDocExtension.SetUserPreferenceToggle` など、可能な限りドキュメントスコープ単位での制御を検討すべきである。
③ COMオブジェクトの明示的解放(メモリリーク対策)
VBAのガベージコレクションは極めて怠惰である。数千回のループ内で `Set swFeat = …` や `Set swSketch = …` のようにCOMオブジェクトを変数に格納し続けると、VBAの背後にあるCOMラッパーの参照カウンタが溢れ、メモリリーク(メモリフットプリントの肥大化)を引き起こす。
大量のオブジェクトを生成・破棄するループ内では、不要になったオブジェクト変数に `Set xxx = Nothing` を明示的に代入し、メモリの肥大化を極限まで抑制せよ。
—
総括
画面描画の抑止は、単なる「画面のちらつき防止」というチープなテクニックではない。これは、OSのメッセージキューとSolidWorksのグラフィックパイプラインの結合度を意図的に切り離し、CPUとメモリの演算能力を「純粋なジオメトリ生成」に100%集中させるための高度なアーキテクチャ制御である。
この知見をあなたのマクロシステムに導入した瞬間から、これまで「重すぎて実用に耐えない」と切り捨てられていた自動化領域への扉が音を立てて開くだろう。コードは常に、美しく、冷徹で、暴力的に速くなければならない。
