SolidWorks VBAの終焉を告げよ:クラスで再構築する「拡張可能合致ビルダー」への昇華
SolidWorks APIを長年叩いてきた者なら、誰しも一度は「スパゲッティ・アセンブリ」の悪夢を見たことがあるだろう。1000行を超える`Sub Main()`、至る所に散らばる`Set swApp = Application.SldWorks`、そして何より恐ろしい、明示的な解放を怠ったメモリリークの残骸。
レガシーなマクロは、作成者が去った瞬間に負債となる。今日は、その場しのぎのコードを、保守性と拡張性を極めた「クラスベースの合致エンジンのアーキテクチャ」へと昇華させるための極限の知見を授ける。
—
1. なぜ「手続き型」ではいけないのか
VBAはオブジェクト指向言語ではないと嘯く者がいるが、それは無知の産物だ。クラスモジュールを活用すれば、`IComponent2`や`IMateFeatureData`の複雑なライフサイクルを隠蔽し、業務ロジックに集中できる「ドメイン層」を構築できる。
今回目指すのは、「合致の定義」と「SolidWorksへの書き込み」を分離する設計だ。これにより、将来的にUIが変わろうが、Excelからのデータ入力になろうが、コアエンジンは一切改修する必要がなくなる。
—
2. 基盤となる「MateBuilder」クラスの設計
まず、合致の生成という副作用をカプセル化する。ここで重要なのは、`swApp`や`swModel`をグローバル変数として野放しにせず、クラスのプロパティとして厳密に管理することだ。
‘ クラスモジュール: AssemblyMateBuilder
Option Explicit
Private swApp As SldWorks.SldWorks
Private swModel As SldWorks.ModelDoc2
‘ 初期化時にコンテキストを固定する
Public Sub Initialize(ByVal app As SldWorks.SldWorks, ByVal model As SldWorks.ModelDoc2)
Set swApp = app
Set swModel = model
End Sub
‘ 汎用的な合致作成インターフェース
Public Function AddCoincidentMate(comp1 As IComponent2, ent1 As IEntity, _
comp2 As IComponent2, ent2 As IEntity) As Boolean
‘ ここにエラーハンドリングとバリデーションを集中させる
If comp1 Is Nothing Or comp2 Is Nothing Then Exit Function
‘ SolidWorks APIの定型処理をカプセル化
‘ 内部でswModel.AddMate3を使用するが、成功判定を厳格に行う
‘ …(後述のメモリ最適化処理へ)
End Function
—
3. メモリの「解放」という宗教的規律
VBAにおける最大の地雷は、COMオブジェクトの解放漏れだ。特にアセンブリのループ処理で`IComponent2`を取得し続けると、メモリ使用量は右肩上がりに増え、数千の部品を扱うアセンブリではSolidWorksがクラッシュする。
「使い終わったら即座にNothing」。これを徹底せよ。
‘ 修正前: ループ内で変数を宣言し続け、メモリを汚染する悪しき例
‘ 修正後: 処理のスコープを限定し、明示的な解放を行う
Private Sub ClearObject(ByRef obj As Object)
If Not obj Is Nothing Then
Set obj = Nothing
End If
End Sub
‘ 使用例
Dim swComp As SldWorks.Component2
‘ …ループ処理…
Set swComp = swModel.GetComponentByName(…)
‘ 処理実行
ClearObject swComp ‘ 参照カウンタを確実に減らす
—
4. Windows APIを活用したパフォーマンスの極致
大量の合致を生成する際、SolidWorksの画面更新(グラフィックの再描画)がボトルネックとなる。`ModelView.EnableGraphicsUpdate`を操作し、さらにWindows APIの`LockWindowUpdate`を組み合わせることで、処理速度を劇的に向上させるのが「上級プロ」の常套手段だ。
‘ 標準モジュール: WinAPI.bas
Public Declare PtrSafe Function LockWindowUpdate Lib “user32” (ByVal hWndLock As LongPtr) As Long
‘ 実行時の最適化
swModel.EditRebuild3 ‘ モデルの再構築を一時停止
LockWindowUpdate Application.hWnd ‘ Windowsの描画を停止
‘ … 合致生成のループ …
LockWindowUpdate 0 ‘ 描画再開
—
5. 伝説的アーキテクトからの提言:継承と拡張
この設計の真価は「拡張性」にある。`MateBuilder`を継承(VBAではインターフェース実装)することで、`CoincidentMate`だけでなく、`DistanceMate`や`AngleMate`といった特殊な合致クラスをプラグインとして追加できる。
リファクタリングのロードマップ:
1. 分離: 既存のスパゲッティコードから「合致作成部分」をクラスへ移行する。
2. 疎結合: `swModel`をクラス内部で保持し、引数を最小化する。
3. 堅牢化: `Err.Number`を監視し、合致失敗時に即座にログを吐く仕組みを作る。
結びに代えて
VBAは、正しく扱えば強力な自動化の武器となる。しかし、それは「書き捨てのコード」を量産する免罪符ではない。
クラスモジュールを定義し、オブジェクトのライフサイクルを制御し、メモリを慈しむ。その丁寧な積み重ねだけが、数年後の自分や同僚を、スパゲッティコードの呪縛から解放する唯一の道である。
さあ、エディタを開け。君のコードを「芸術」へと昇華させる時が来た。
