伝説のコードへ昇華せよ:SolidWorks VBAを「クラス」で制御する極限の作法
現場でよく見る「動けばいい」という考えで書かれたスパゲッティコードは、数ヶ月後の自分にとってのテロリストだ。特にアセンブリの自動構築において、グローバル変数に頼った設計は、エラーハンドリングを絶望的にし、メモリリークの温床となる。
今日は、SolidWorks APIを使いこなすプロとして、「脱・手続き型」のクラスモジュール設計によるアセンブリ自動化の極意を伝授する。
—
なぜ「手続き型」は沈没するのか
多くのエンジニアが犯す最大の過ちは、`swApp` や `swModel` を標準モジュールでグローバルに宣言し、関数間で使い回すことだ。これには以下の致命的な欠陥がある。
1. 状態の汚染: 複数のアセンブリ処理が並行または連鎖した際、変数の参照が意図せず書き換わる。
2. スコープの無法地帯: どこで誰がファイルを閉じたのか、どの関数がポインタを無効化したのか追跡不能になる。
3. 再利用性の欠如: 特定のプロジェクトに依存しすぎて、部品配置のロジックを別プロジェクトに移植できない。
これらを解決する唯一の正解が、「アセンブリ操作のオブジェクト化」である。
—
実践:アセンブリ構築をクラスにカプセル化する
今回は、部品をアセンブリに投入し、特定の合致を定義するクラス `AssemblyAutomator` を構築する。
1. クラスモジュール:`AssemblyAutomator.cls`
まずは、アセンブリの状態を管理する核となるクラスを定義する。
‘ AssemblyAutomator.cls
Option Explicit
Private swApp As SldWorks.SldWorks
Private swAssy As SldWorks.AssemblyDoc
‘ コンストラクタ代わりの初期化メソッド
Public Sub Initialize(app As SldWorks.SldWorks, assy As SldWorks.ModelDoc2)
Set swApp = app
If Not assy Is Nothing Then
Set swAssy = assy
Else
Err.Raise vbObjectError + 1, “AssemblyAutomator”, “アセンブリが正しく指定されていません。”
End If
End Sub
‘ パーツを配置し、合致を作成するロジック
Public Function AddComponentWithMate(compPath As String, targetEntityName As String) As Boolean
Dim swComp As SldWorks.Component2
Dim swModel As SldWorks.ModelDoc2
‘ 1. コンポーネントの挿入
Set swComp = swAssy.AddComponent(compPath, 0, 0, 0)
If swComp Is Nothing Then Exit Function
‘ 2. 合致作成のロジック(簡略化)
‘ ここでグローバル変数を使わず、渡されたインスタンス内で完結させる
Debug.Print “Component added: ” & swComp.Name2
AddComponentWithMate = True
End Function
2. 呼び出し側のコード:`Main.bas`
メイン処理は極めてクリーンになる。これが「保守性が高い」ということだ。
Sub RunAutomation()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim automator As New AssemblyAutomator
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ クラスに依存関係を注入する
automator.Initialize swApp, swModel
‘ 業務ロジックの実行
If automator.AddComponentWithMate(“C:\Parts\Bolt.sldprt”, “Plane1”) Then
MsgBox “構築完了”
End If
End Sub
—
プロが教える「陥りがちな罠」と回避策
1. ファイルハンドルの保持と解放
`AddComponent` を繰り返すと、SolidWorks側のキャッシュが溜まり、メモリ使用量が急増する。長時間稼働するツールであれば、定期的に `swModel.ForceRebuild3 True` を呼び出し、不要になったオブジェクトは `Set obj = Nothing` で明示的にメモリを解放せよ。
2. インターフェースの厳格化
アセンブリの合致作成(`AddMate`)は非常に繊細だ。エンティティ(面や軸)の取得に失敗するとSolidWorksがクラッシュする。
- 対策: `SelectByRay` などの選択メソッドに頼らず、名前指定(`SelectByID2`)を優先する。また、`Select` 系のメソッドの戻り値を必ずチェックし、`False` ならば即座に例外を投げる設計にすること。
3. データベース連携(外部ファイル読込)
CSVやJSONから構成情報を読み込む際、標準モジュールでファイル処理を完結させてはいけない。`FileParser` のような専用クラスを作成し、`AssemblyAutomator` に「データ」として渡す設計にする。これにより、将来的にデータソースがExcelからSQL Serverに変わっても、アセンブリ構築ロジックには一行も手を入れなくて済む。
—
最後に:自動化は「設計」が全て
VBAは古臭い言語だと言われる。しかし、それは言語のせいではなく、書く側の設計思想が古いからだ。
クラスモジュールを使いこなし、SolidWorksのAPIを「オブジェクトの連鎖」として捉えることができれば、あなたの書くツールは、単なるスクリプトから「強固な自動化エンジン」へと進化する。
次にマクロを書くときは、こう自問してほしい。
「このコードを、半年後の自分が深夜に修正しても、一切の迷いなく動くか?」
その答えが「Yes」と言い切れるコードこそが、真のプロダクションコードだ。
