SolidWorks VBAの「闇」を可視化せよ:ミリ秒単位でボトルネックを特定する計測基盤の構築
SolidWorksの自動化において、最も忌むべきは「なぜ遅いのか分からない」という状態だ。
数千行に及ぶパーツ生成マクロを実行し、進捗バーを眺めながらコーヒーを淹れる時間は、エンジニアにとっての敗北を意味する。
多くの開発者は、処理の遅延を「フィーチャが複雑だから仕方ない」という主観で片付ける。だが、真のプロフェッショナルは、「どのAPIメソッドが、何ミリ秒を消費しているか」を客観的なデータとして突き止める。
今日は、大規模パーツ生成マクロを科学的に高速化するための「計測ログ基盤」を伝授する。
—
1. なぜ「勘」でのデバッグは失敗するのか
SolidWorksのAPIは、呼び出しのたびにCOM経由でメインプロセスと通信を行う。特に`CreateFeature`や`SelectByID2`といった重いメソッドをループ内で回す際、個々の処理時間はわずかでも、積もり積もれば数分のロスを生む。
「遅い箇所を特定する」ために必要なのは、`Debug.Print`の羅列ではない。スコープの開始と終了を管理し、処理時間を構造化して出力するフレームワークだ。
—
2. 実践:ミリ秒単位の計測ログ基盤(プロダクションコード)
以下のコードは、`FileSystemObject(FSO)`を用いて外部ログファイルにタイムスタンプと経過時間を書き出すためのモジュールだ。イミディエイトウィンドウへの出力だけでなく、履歴を残すことで「昨日より遅くなった」という変化を可視化する。
ログ計測クラス: `clsStopwatch`
‘ 【クラスモジュール: clsStopwatch】
‘ 処理の区間を計測し、ログを生成する役割を担う
Option Explicit
Private m_StartTime As Double
Private m_Label As String
Public Sub StartTask(Label As String)
m_Label = Label
m_StartTime = Timer 1000 ‘ ミリ秒単位に変換
Debug.Print “— 開始: ” & m_Label & ” —”
End Sub
Public Sub EndTask()
Dim endTime As Double
endTime = Timer 1000
Dim duration As Double
duration = endTime – m_StartTime
‘ イミディエイトウィンドウへ出力
Debug.Print “— 終了: ” & m_Label & ” | 経過時間: ” & Format(duration, “0.00”) & “ms —”
‘ FSOでログファイルへ追記
WriteToLog m_Label, duration
End Sub
Private Sub WriteToLog(Label As String, duration As Double)
Dim fso As Object
Dim ts As Object
Dim logPath As String
Set fso = CreateObject(“Scripting.FileSystemObject”)
logPath = Environ(“USERPROFILE”) & “\Desktop\SW_Macro_Log.txt”
Set ts = fso.OpenTextFile(logPath, 8, True) ‘ 8: ForAppending
ts.WriteLine Now & ” | ” & Label & ” | ” & Format(duration, “0.00”) & “ms”
ts.Close
End Sub
—
3. マクロへの組み込み方:責務を分離せよ
メインコードの中に計測ロジックを直接埋め込むのは「スパゲッティコード」の入り口だ。以下のように、処理の塊ごとに計測オブジェクトを呼び出す設計にする。
Sub GenerateComplexPart()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swTimer As New clsStopwatch
Set swApp = Application.SldWorks
‘ 計測開始
swTimer.StartTask “パーツ生成全体”
‘ 1. スケッチ作成処理
swTimer.StartTask “スケッチ生成”
‘ … ここに複雑なスケッチ生成コード …
swTimer.EndTask
‘ 2. フィーチャ押し出し処理
swTimer.StartTask “押し出しフィーチャ生成”
‘ … ここに重いフィーチャ操作コード …
swTimer.EndTask
swTimer.EndTask
End Sub
—
4. プロの視点:この設計の「真の狙い」
この基盤を導入することで、以下のメリットが生まれる。
1. ボトルネックの可視化: どの処理が全体の50%以上の時間を占めているか一目瞭然になる。
2. 保守性の向上: マクロの仕様変更時に、どの工程が重くなったかを即座に判断できる。
3. FSOによる永続化: イミディエイトウィンドウはVBA終了後に消えるが、ログファイルは資産となる。チーム内での最適化の議論が「体感」ではなく「エビデンス」に基づいて行えるようになる。
注意すべきポイント
- ファイルI/Oのコスト: `WriteToLog`自体が頻繁に呼ばれるとオーバーヘッドになる。数万回のループ内部で直接呼ぶのではなく、一定回数ごとにバッファリングする工夫が必要だ。
- Timer関数の限界: VBAの`Timer`関数は精度が低く、0時をまたぐと負の値を返す恐れがある。本番環境ではWindows APIの`QueryPerformanceCounter`を使用する方がより精緻だが、まずはこの基盤で十分にボトルネックを叩けるはずだ。
—
最後に:計測なき最適化は「ギャンブル」である
「コードを短く書く」ことと「速く動くコードを書く」ことは全くの別物だ。
SolidWorksという巨大なエンジンの上で走る我々のコードは、常にリソースの奪い合いの中にいる。
計測ログ基盤を構築せよ。そして、数値データという武器を持ってコードを書き換えろ。
あなたのマクロが、明日には数秒速く動作することを期待している。
