【レガシーコードの近代化】古いSolidWorks APIの洗い出しとリファクタリング
開発プロジェクトのリーダーである私のもとに、よくこんな相談が持ち込まれる。
「先輩が遺したマクロが、特定のモデルを開くときだけフリーズする」
「SolidWorksを2024や2025にアップデートしたら、動かない機能が出てきた」
原因のほとんどは、過去の遺物――「レガシーAPIの放置」だ。
インターネットの片隅や、古い書籍からコピペされたコードが、世代を超えてエンジニアの足を引っ張る。SolidWorks APIは進化している。かつて通用した力技のコードは、現在のマルチスレッド環境や巨大アセンブリにおいては「百害あって一利なし」だ。
今回は、古いSolidWorks VBAコードを現代的な水準へ引き上げ、「落ちない、速い、保守しやすい」プロダクションコードへと生まれ変わらせるための極限の知見を伝授しよう。
—
1. 廃止予定(Obsolete)・非推奨APIの現実
なぜ古いコードは動かなくなるのか、あるいは動作が不安定になるのか。理由は明確である。
1. 内部アーキテクチャの乖離: 昔のAPIは、現在のSolidWorksの非同期処理や大容量アセンブリの軽量モード(Large Assembly Mode / Lightweight)を考慮していない。
2. メモリリークの温床: 適切にオブジェクトを解放(`Nothing`代入)しないと、COMコンポーネントがメモリ上に残留し、SolidWorks自体の強制終了を引き起こす。
3. エラーハンドリングの欠如: 戻り値の成否(True/False)を無視した「祈祷系コード」が多すぎる。
特に、ファイルのオープン、フィーチャーの走査、コンフィギュレーションの切り替えにおいて、この傾向が顕著に見られる。
—
2. 現代的リファクタリングの3大原則
レガシーコードを近代化するにあたり、以下の3つのルールを厳守してほしい。
① `Extension` オブジェクトの積極的活用
古いコードでは `ModelDoc2` のメソッドを直接叩いているケースが多いが、近年のAPIでは `ModelDocExtension`(`ModelDoc2::Extension`)経由で実行する方が高速かつ安全な場合が多い。特にファイル保存や選択処理はその傾向が強い。
② 厳格なエラーハンドリングと戻り値の検証
「動けばいい」ではなく、「失敗したときにどうリカバリーするか」をコードに書く。APIの戻り値(エラーコードや長整数)を必ず変数に受け、条件分岐を行うこと。
③ 適切なオブジェクト解放
VBAのガベージコレクションは頼りにならない。不要になった `SldWorks`、`ModelDoc2`、`SelectionMgr` などのCOMオブジェクトは、スコープを抜ける前、あるいはループの反復ごとに `Set obj = Nothing` を明示的に実行する。
—
3. 【実践】レガシーコードからモダンコードへの書き換え
実際のコードを見ながら、具体的な違いを確認しよう。
悪い例:レガシーなコード(動くが、重く、不安定)
以下のコードは、アクティブなドキュメントの特定部品を一括で非表示にする処理のつもりだが、典型的なアンチパターンが詰まっている。
‘ 【アンチパターン満載のレガシーコード】
Sub HideSpecificPart_Legacy()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ エラーチェックなし!図面やパーツが開いていたら即クラッシュ
Dim swSelMgr As SldWorks.SelectionMgr
Set swSelMgr = swModel.SelectionManager
‘ 古い選択・非表示メソッド
swModel.ClearSelection2 True
‘ …ここに強引な処理が続く(省略)
‘ オブジェクトの解放をしていない!
End Sub
良い例:モダンで堅牢なプロダクションコード
上記の問題点をすべてクリアし、API仕様に則った堅牢なコードが以下だ。
‘ ==============================================================================
‘ 担当者: シニアCAD自動化エンジニア
‘ 概要: アクティブなアセンブリ内の指定コンポーネントを安全かつ高速に非表示にする
‘ 特徴: 厳格なドキュメントタイプチェック、拡張機能の活用、確実なメモリ解放
‘ ==============================================================================
Sub HideSpecificPart_Modern()
‘ 1. アプリケーションとモデルの取得
Dim swApp As SldWorks.SldWorks
Set swApp = Application.SldWorks
If swApp Is Nothing Then Exit Sub
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “APIエラー”
Exit Sub
End If
‘ 2. ドキュメントタイプの検証(アセンブリ [swDocASSEMBLY = 2] 以外は弾く)
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “このマクロはアセンブリドキュメントでのみ実行可能です。”, vbExclamation, “実行中断”
Exit Sub
End If
‘ 3. 拡張機能(ModelDocExtension)の取得
Dim swExt As SldWorks.ModelDocExtension
Set swExt = swModel.Extension
If swExt Is Nothing Then GoTo CleanUp
‘ 4. 処理の実行(例:トランザクション開始による高速化と安全性確保)
swModel.EditRebuild3 ‘ 最新状態への更新
Dim longstatus As Long
‘ 最新のAPI仕様に則った一括処理の例(安全なコンポーネント操作)
‘ ※実際の業務ロジックに応じてここに処理を記述
MsgBox “処理が正常に完了しました。”, vbInformation, “完了”
CleanUp:
‘ 5. 確実なCOMオブジェクトの解放(メモリリーク防止)
Set swExt = Nothing
Set swModel = Nothing
Set swApp = Nothing
End Sub
—
4. メンテナンス性を爆発的に高める設計のコツ
実務で自動化ツールを運用する場合、コードの美しさだけでなく「誰がメンテナンスしても壊れない構造」が求められる。
- 定数の外部化・列挙体(Enum)の活用: マジックナンバー(例: `swDocASSEMBLY` の代わりに `2` と書くなど)は絶対に排除し、SolidWorksが提供する標準Enum、または自作の `Enum` を使うこと。
- ログ出力の実装: `Debug.Print` だけでなく、処理の成否や処理時間をテキストファイルやデータベースに記録する仕組みを組み込むことで、万が一のトラブルシューティングが容易になる。
結びにかえて
「動いているから触らない」は、ソフトウェア開発において最大のリスクだ。SolidWorksのバージョンアップのたびにヒヤヒヤするのではなく、今すぐ手元のレガシーコードを洗い出し、モダンなAPIと堅牢なエラーハンドリングで武装し直してほしい。
あなたの書いたそのコードが、設計者たちの手足を解放し、真のクリエイティブな業務へと導く武器になることを期待している。
