【テクニカル・上級編】【パフォーマンス改善】SldWorks.CommandInProgressを用いたマクロ実行中のユーザ介入ブロックと処理高速化 – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAの極致:`CommandInProgress`による実行の不可侵性とバッチ処理の最適化

業務自動化の現場において、SolidWorksマクロは時として「脆いガラス細工」のような挙動を見せる。特に数千単位のパーツを生成・編集するバッチ処理において、プログラミングされていないユーザーのクリック一つが、数時間の計算を水泡に帰すことは珍しくない。

多くのエンジニアは `SldWorks.UserControl = False` で満足するが、真に堅牢なシステムを構築するには、より深いレイヤーでの制御が必要だ。今回は、`CommandInProgress` を軸に、SolidWorksの内部状態を掌握し、処理を高速化するための「禁断の知見」を共有する。

1. なぜ `CommandInProgress` なのか

SolidWorksのGUIプロセスとAPI実行プロセスは、本質的に非同期的な側面を持つ。`CommandInProgress` は、現在SolidWorksがコマンド実行中であるかを示すフラグだが、これを能動的に利用することで、マクロの実行優先度を物理的に保護できる。

単純なフラグ管理ではなく、Windows APIを併用した「システムレベルのロック」こそが、真のシニアエンジニアが到達すべき領域だ。

2. 実装の要諦:不可侵のバッチ処理エンジン

以下のコードは、単なるフラグチェックを超え、マクロ実行中のユーザー介入を排し、さらにメモリリークを根絶するためのテンプレートである。

‘ 伝説的な堅牢性を実現するためのマクロテンプレート
Option Explicit

If VBA7 Then
Private Declare PtrSafe Function BlockInput Lib “user32” (ByVal fBlock As Long) As Long
Else
Private Declare Function BlockInput Lib “user32” (ByVal fBlock As Long) As Long
End If

Public Sub ExecuteHighPerformanceBatch()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2

‘ オブジェクトの初期化と最適化
Set swApp = Application.SldWorks

‘ 1. ユーザー介入のブロック(最優先)
‘ 注意:この関数は管理者権限で実行する必要がある
On Error Resume Next
BlockInput 1
On Error GoTo 0

‘ 2. 画面更新とユーザー制御の完全停止
swApp.UserControl = False
swApp.Visible = True ‘ 完全バックグラウンドより、可視化しつつ制御を奪う方がデバッグ時は安全

‘ 3. CommandInProgressによる保護
‘ 処理開始前に状態を強制監視
If swApp.CommandInProgress Then
Debug.Print “Warning: Another command is running. Proceeding with caution…”
End If

‘ — メインロジック —
‘ ここで大量のパーツ生成・フィーチャ操作を行う
Call ProcessLargeScaleGeometry(swApp)
‘ ———————-

‘ 終了処理:リソースの解放は明示的に行う
BlockInput 0
swApp.UserControl = True
Set swModel = Nothing
Set swApp = Nothing
End Sub

Private Sub ProcessLargeScaleGeometry(swApp As SldWorks.ModelDoc2)
‘ ジオメトリ生成時のメモリ消費を抑えるため、
‘ 不要な再構築(Rebuild)を抑制する
swApp.FeatureManager.EnableFeatureTree = False

‘ [ここに高速なジオメトリ操作コードを記述]

swApp.FeatureManager.EnableFeatureTree = True
End Sub

3. パフォーマンスを極限まで引き上げるための「3つの規律」

単に `BlockInput` を呼ぶだけでは不十分だ。大規模なパーツ処理を行う際、以下の規律を遵守しなければ、SolidWorksはメモリリークを起こし、最終的にクラッシュする。

① フィーチャツリーの描画抑止

`swApp.FeatureManager.EnableFeatureTree = False` は必須である。ツリーの更新はUIスレッドを激しく消費する。バッチ処理中はこれを完全に遮断せよ。

② 明示的なメモリ解放の徹底

VBAのガベージコレクションを信じてはいけない。`Nothing` を代入するだけではなく、大量に生成した `swFeature` や `swBody` オブジェクトは、ループ内で適宜クリアする必要がある。

  • `Set swBody = Nothing` をループの最後で必ず呼ぶこと。
  • `DoEvents` を極力排すること。頻繁な `DoEvents` は、Windowsのメッセージループを再開させ、処理速度を劇的に低下させる。

③ レガシー環境における例外ハンドリング

古いSolidWorks APIでは、大規模な `ModelDoc2` の操作時に予期せぬCOM例外が発生することがある。`Err.Number` を監視し、特定のコードで失敗した場合は `swApp.ExitApp` を呼ぶのではなく、該当ファイルのみをスキップする「安全装置」を構築しておくことが、システム管理者の責務である。

最後に:エンジニアの誇りについて

「マクロが止まるのはユーザーのせいではない、制御しきれないエンジニアのせいだ」。

この思想を胸に刻んでほしい。`CommandInProgress` を制御下に置くことは、単なる小手先のテクニックではなく、アプリケーションのライフサイクルを完全に掌握しているという証左である。

もし、貴殿がさらに高度な並列処理(マルチスレッドによるSolidWorksの複数起動など)に挑むのであれば、次は `Pipe` 通信によるプロセス間連携について語ろう。現場の最前線で戦う諸君、健闘を祈る。

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