【テクニカル・上級編】【マクロ最適化】Early Binding(早期バインディング)の導入によるSolidWorks型ライブラリ参照設定と実行速度の極限追求 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBA極限最適化】早期バインディング(Early Binding)による実行速度の限界突破と型安全性の追求

レガシーなVBAコードのメンテナンスに疲弊し、巨大なアセンブリや複雑なコンフィギュレーションを持つパーツの自動生成で「応答なし」の砂時計を眺め続ける日々に別れを告げる時が来た。

世に溢れる大半のSolidWorks VBAマクロは、いまだに `CreateObject(“SldWorks.Application”)` という遅延バインディング(Late Binding)の呪縛にとらわれている。この手法は参照設定の手間を省くという名目の下で、実行時パフォーマンスの著しい低下、コード補完(IntelliSense)の喪失、そして型安全性の完全な崩壊を引き起こしている。

本稿では、SolidWorks APIの根底にあるCOM(Component Object Model)のメカニズムを紐解き、早期バインディング(Early Binding)への移行による劇的なパフォーマンス向上と、シニアエンジニアが押さえておくべきメモリ管理の極意を解説する。

1. なぜ遅延バインディングは「悪」なのか:COMの裏側

遅延バインディングでは、変数宣言が曖昧な `Dim swApp As Object` や `Dim swModel As Object` となり、実際のメソッドやプロパティの解決が「実行時(Run-time)」に行われる。

VBAの裏側では何が起きているのか?
オブジェクトに対してメソッドを呼び出すたびに、COMランタイムは `IDispatch::GetIDsOfNames` を介して文字列としてのメソッド名から関数ポインタ(DispID)を動的に引き当て、その後に `IDispatch::Invoke` で実行するという極めて重いオーバーヘッドを毎回発生させている。

これが、数百回・数千回のフィーチャ生成ループを回すマクロにおいて、致命的なボトルネックとなる正体である。

早期バインディング(SldWorks Type Libraryの参照)の優位性

事前にVBEの「ツール」>「参照設定」から `SldWorks 20xx Type Library` および `SolidWorks 20xx Constants Type Library` を明示的にプロジェクトに組み込むと、状況は一変する。

  • Vtable(仮想メソッドテーブル)直接呼び出し: 実行時の名前解決がバイナリレベルで解決され、C++並みのダイレクトコールに近づく。
  • 完全なIntelliSenseの復活: メソッドの引数、戻り値の型、そして膨大なSolidWorks定数(`swExtRefStatus_e` や `swWithDraft_e` など)が自動補完され、マジックナンバーの記述から解放される。
  • コンパイル時エラー検出: タイプミスや不正な引数の割り当てを、実行する前にVBEが検知できる。

2. 【実践】環境構築と実装コード

まずは、開発環境の準備から始める。

参照設定の手順

1. VBE(Visual Basic Editor)を開く。
2. 「ツール」 > 「参照設定」 をクリック。
3. 以下の2つにチェックを入れる(バージョンヌードルはインストール環境に合わせる)。

  • `SldWorks x.x Type Library`
  • `SolidWorksConstants x.x Type Library`

極限まで最適化されたパーツ生成テンプレート

以下に、早期バインディングと厳密なオブジェクト解放、そしてエラーハンドリングを網羅したプロダクション品質のコードを示す。

Option Explicit

‘ =========================================================================
‘ 模範的 SolidWorks VBA モジュール: 早期バインディングによる高速パーツ生成
‘ アーキテクチャ設計: チーフチーフアーキテクト
‘ =========================================================================

Sub CreateOptimizedPart_EarlyBinding()
‘ 早期バインディングによる型宣言(Object型は一切排除)
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim swSkMgr As SldWorks.SketchManager
Dim swFeatMgr As SldWorks.FeatureManager

Dim lErrors As Long
Dim lWarnings As Long

‘ 実行時間計測用(パフォーマンス検証用)
Dim startTime As Double
startTime = Timer

‘ 1. Applicationインスタンスの取得
‘ すでに起動しているプロセスをフックし、新規インスタンスの乱立を防ぐ
On Error Resume Next
Set swApp = GetObject(, “SldWorks.Application”)
If swApp Is Nothing Then
Set swApp = New SldWorks.SldWorks
End If
On Error GoTo ErrorHandler

If swApp Is Nothing Then
MsgBox “SolidWorksのセッションを確立できませんでした。”, vbCritical
Exit Sub
End If

‘ バックグラウンド処理の高速化(画面描画の凍結)
swApp.UserControl = True
swApp.Visible = True

‘ 2. 新規パーツドキュメントの作成(定数はSolidWorksConstantsライブラリにより自動解決)
Set swModel = swApp.NewDocument(swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplatePart), 0, 0, 0)

If swModel Is Nothing Then
MsgBox “パーツテンプレートの読み込みに失敗しました。”, vbCritical
GoTo CleanUp
End If

Set swPart = swModel

‘ 画面描画と再構築の無効化(ジオメトリ生成の爆速化の極意)
swModel.Extension.EnableGraphicsUpdate = False
swModel.LockSelectionSet = True

‘ 3. ジオメトリ生成プロセス(例:ベースとなるスケッチとボス・押し出し)
Set swSkMgr = swModel.SketchManager

‘ フロント平面を選択してスケッチモードへ
Dim swSelData As SldWorks.SelectionData
Set swSelData = swModel.Extension.CreateSelectionData

If swModel.Extension.SelectByID2(“フロント”, “PLANE”, 0, 0, 0, False, 0, Nothing, 0) Then
swSkMgr.InsertSketch True

‘ 原点を中心とした中心矩形の描画(単位はメートル系:SolidWorks内部単位)
‘ swSkMgr.CreateCenterRectangle(X, Y, Z, X_Width, Y_Width, 0)
Dim vRect As Variant
vRect = swSkMgr.CreateCenterRectangle(0, 0, 0, 0.1, 0.05, 0)

swSkMgr.InsertSketch True ‘ スケッチ終了
End If

Set swFeatMgr = swModel.FeatureManager

‘ 押し出しフィーチャの作成(50mm押し出し)
‘ 早期バインディングにより、定数 swExtrudeThickGeometry_e 等が完全に機能する
Dim swFeat As SldWorks.Feature
Set swFeat = swFeatMgr.FeatureExtrusion2( _
True, _ ‘ sd (片方向・両方向などのフラグ)
False, _ ‘ flip
False, _ ‘ dir
swEndCondBlind, _ ‘ 終端条件:面指定なし(盲穴)
swEndCondIgnore, _ ‘ 終端条件2
0.05, _ ‘ 深度 (m)
0, _ ‘ 深度2
False, _ ‘ draftOutward
False, _ ‘ draftAngle
False, _ ‘ draft1
False, _ ‘ draft2
0, _ ‘ offset1
0, _ ‘ offset2
False, _ ‘ translateSurface
False, _ ‘ merge
True, _ ‘ useFeatScope
False, _ ‘ useAutoSelect
0, 0, 0 ‘ profile
)

‘ 描画の復元
swModel.Extension.EnableGraphicsUpdate = True
swModel.LockSelectionSet = False
swModel.GraphicsRedraw2

Debug.Print “パーツ生成完了 実行時間: ” & Format(Timer – startTime, “0.000”) & ” 秒”

CleanUp:
‘ 4. 厳密なメモリ解放(COM参照のデクリメント)
‘ 連鎖参照を防ぐため、リーフからアプリケーション層へ向かってNothingを代入していく
Set swFeat = Nothing
Set swFeatMgr = Nothing
Set swSkMgr = Nothing
Set swSelData = Nothing
Set swPart = Nothing
Set swModel = Nothing
Set swApp = Nothing
Exit Sub

ErrorHandler:
‘ 異常系ハンドリング
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
‘ エラー時も確実にグラフィック描画を復元させる
If Not swModel Is Nothing Then
swModel.Extension.EnableGraphicsUpdate = True
swModel.LockSelectionSet = False
End If
Resume CleanUp
End Sub

3. シニアエンジニアが知るべき「メモリ最適化」と「COMの寿命管理」

VBAはガベージコレクション(GC)の挙動が.NET Framework等に比べてブラックボックスであり、COMオブジェクトのメモリ管理を怠ると、バックグラウンドプロセスとして `SLDWORKS.exe` がゾンビのように残存し続け、メモリリークやライセンス枯渇を引き起こす

オブジェクトの明示的解放順序の作法

上記のコードブロック `CleanUp:` ラベルを見てほしい。
オブジェクトの解放は、作成した逆順、かつ下位のインターフェースから上位へ向かって `Set xxx = Nothing` を明示的に実行するのが鉄則である。

1. `Feature` や `SelectionData` などの末端ローカルオブジェクト
2. `FeatureManager` や `SketchManager` などのマネージャークラス
3. `PartDoc` (SldWorks.PartDocなどの派生インターフェース)
4. `ModelDoc2` (親ドキュメントインターフェース)
5. 最後に `SldWorks.SldWorks` (アプリケーションインスタンス)

これを怠り、いきなり `Set swApp = Nothing` を実行すると、参照カウンタが0にならず、SolidWorksのCOMプロセスがメモリ上に宙ぶらりんの状態で残留する。タスクマネージャーに `SLDWORKS.exe` が無限に増殖する現象に悩まされているエンジニアは、大抵この解放順序と変数スコープに欠陥がある。

4. レガシー環境・複数バージョン混在環境における「早期バインディング」の罠と回避策

ここで、エンタープライズ環境特有の深刻な課題に触れておかねばならない。
「社内で SolidWorks 2023 と 2024 が混在している」「開発PC(2024)でコンパイルしたマクロを、現場のPC(2023)で動かしたらコンパイルエラー(型ミスマッチ)で動かない」という問題だ。

タイプライブラリの参照設定は、参照した時点のバージョンGUIDをVBAプロジェクトにハードコードする。そのため、異なるバージョンのSolidWorks環境にマクロを持ち込むと、GUIDの不整合が起きる。

このジレンマを突破する「ハイブリッド・アーキテクチャ(Conditional Compilation)」

この問題をエレガントに解決するのが、条件付きコンパイル(#Const)遅延/早期の動的切り替えである。あるいは、アドイン(C#.NET / VB.NET)への移行が本丸ではあるが、VBAの縛りの中で極限を追求する場合、以下のようにバージョンごとのラッパーを設計する。

しかし、真に高パフォーマンスを求める基幹システムであれば、VBAの枠を脱却し、VB.NET(COM Interop)による外部EXE化、もしくは SolidWorks Add-in(C#)の開発へステップアップすることを強く推奨する。
.NET環境であれば、`Marshal.ReleaseComObject()` を用いた厳密なCOM参照カウントの制御が可能となり、VBAのメモリ管理の不安要素を完全に排除できる。

総括

遅延バインディングから早期バインディングへの移行は、単なる「コードの作法」ではない。それは、CADという巨大なリソースを制御するマクロの「信頼性と速度の限界を引き上げるためのエンジニアリング義務」である。

マジックナンバーを排除し、型安全性を手に入れ、ミリ秒単位の最適化が施されたコードベースこそが、真に保守性の高い自動化基盤を築く。
今日からあなたのVBAプロジェクトの「参照設定」を見直し、`Object` 型の文字をコードベースから駆逐せよ。圧倒的な実行スピードの向上が、あなたの開発者人生の時間を生み出すはずだ。

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