【テクニカル・上級編】【レガシーコードの近代化】古いSolidWorks API(廃止予定・推奨されないメソッド)の洗い出しとリファクタリング – SolidWorks VBA解析バイブル

スポンサーリンク

【レガシーコードの近代化】古いSolidWorks APIの洗い出しとリファクタリング:負債を断ち切り、実行速度を極限まで引き上げる技術

長年運用されてきた製造業のVBAマクロ資産は、企業の競争力の源泉であると同時に、技術的負債の温床でもある。特にSolidWorksのAPIは、バージョンアップの歴史の中で数多くのメソッドやインターフェースが「非推奨(Obsolete)」となり、あるいは「サイレント・デグレッション(動作仕様の静かな変更)」を経験してきた。

「昔は動いていたのに、SolidWorks 2024/2025環境に変えた途端にフリーズする」
「メモリリークを起こし、数回実行するとSolidWorksごと落ちる」

これらは、レガシーなAPIの呪縛を引きずったままのコードを現代のOS・CAD環境で動かしていることが主因だ。
本稿では、シニアエンジニアおよびCADシステム管理者に向けて、廃止予定・推奨されないAPIの洗い出し手法と、メモリ最適化、そしてWindows APIの近代的な協調を網羅した「レガシーコード近代化の極限知見」を提示する。

1. レガシーAPIの害悪:なぜ「古いコード」は遅く、危険なのか

SolidWorks VBA(SldWorks/ModelDoc2)のコードベースにおいて、パフォーマンス低下と不安定化を引き起こす主要因は以下の3点に集約される。

1. 暗黙のCOMオブジェクト参照と解放漏れ
`SldWorks.Application` から派生する無数のオブジェクト(`ModelDocExtension`, `SelectionMgr`, `Feature` など)は、VBAのガベージコレクションに完全に依存してはならない。特にループ内で生成されたオブジェクトが即時解放されない場合、COMラッパーがメモリ上に残存し、プロセス肥大化とCOM例外を引き起こす。
2. `Extension.SelectByID2` への過度な依存
画面上のピッキングをシミュレートする `SelectByID2` は、グラフィックの再描画(Viewport Update)を伴うため極めて重い。近代的なAPIでは、バックグラウンドでのダイレクト操作や、コンテキストを維持したポインタ操作へ置き換えるべきである。
3. エラーハンドリングの欠如とモーダルダイアログの暴走
旧来のコードによく見られる `On Error Resume Next` の乱用は、APIの失敗を隠蔽し、不正なメモリ状態のまま後続処理を実行させる最悪のアンチパターンである。

2. 廃止予定・非推奨APIの特定とモダンAPIへの置換

実務で頻繁に遭遇する「即座に書き換えるべきレガシーパターン」を、具体的な対比コードとともに解説する。

パターンA:ファイルオープン・アクティブ化の近代化

古いコードでは `OpenDoc6` の戻り値や挙動の解釈が曖昧であり、エラー時のハンドリングが不完全なことが多い。また、開いたドキュメントのポインタ管理がずさんである。

【レガシー実装】

‘ 【危険】エラーハンドリングがなく、返り値の型安全性も低い古いオープン方法
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks

‘ 戻り値のキャストが曖昧で、失敗時のプロセスゾンビ化リスクがある
Set swModel = swApp.OpenDoc6(“C:\Parts\Assembly1.sldasm”, 2, 0, “”, 0, 0)

【モダンリファクタリング実装】

‘ 【推奨】明示的な定数定義、エラーチェック、および戻り値の厳密なハンドリング
Public Sub ModernOpenDocument()
Dim swApp As SldWorks.SldWorks
Set swApp = Application.SldWorks
If swApp is Nothing Then Exit Sub

Dim docPath As String
docPath = “C:\Parts\Assembly1.sldasm”

Dim errorCode As Long
Dim warningCode As Long

‘ DocView = False でバックグラウンドロードし、パフォーマンスを劇的に向上させる
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.OpenDoc7(docPath, swDocumentAssembly, swOpenDocOptions_Silent, “”, errorCode, warningCode)

If swModel Is Nothing Then
‘ 失敗時の詳細なエラーコード解析 (swFileLoadError_e)
MsgBox “ドキュメントのオープンに失敗しました。Error Code: ” & errorCode, vbCritical
Exit Sub
End If

‘ 処理後に必ずローカル変数をクリア(後述のメモリ最適化)
Set swModel = Nothing
Set swApp = Nothing
End Sub

パターンB:遅延の元凶 `SelectByID2` からの脱却

アセンブリの合致(Mate)操作やコンポーネントの操作において、画面を選択状態(Selection)にする必要性は本来ない。

【レガシー実装】

‘ 画面上の描画とセレクションマネージャを強制的に介するため、非常に遅い
boolstatus = swModel.Extension.SelectByID2(“Part1-1@Assembly1”, “COMPONENT”, 0, 0, 0, False, 0, Nothing, 0)
Dim swFeat As SldWorks.Feature
Set swFeat = swSelMgr.GetSelectedObject6(1, -1)
swFeat.SetName2 “NewName”

【モダンリファクタリング実装】

‘ 選択を一切行わず、ポインタを直接取得して操作する(Headlessライクな高速処理)
Dim swAssDoc As SldWorks.AssemblyDoc
Set swAssDoc = swModel ‘ ModelDoc2からAssemblyDocへキャスト

Dim swComp As SldWorks.Component2
Set swComp = swAssDoc.GetComponentByName(“Part1-1”)

If Not swComp Is Nothing Then
‘ コンポーネントに対する直接操作(API仕様に準拠)
swComp.SetSuppression2 swComponentFullyResolved
‘ オブジェクトの明示的破棄
Set swComp = Nothing
End If
Set swAssDoc = Nothing

3. メモリ最適化:COMオブジェクトの明示的解放とスコープ管理

VBAのランタイムはプロセス終了時にCOMオブジェクトを解放するが、数千回ループするバッチ処理や大規模アセンブリの走査においては、「使ったら即座に `Set obj = Nothing` で参照カウントをデクリメントする」ことが鉄則である。

チーフアーキテクトが実践する、メモリリークを完全に根絶するコーディングテンプレートを以下に示す。

Sub TraverseAssemblyOptimized(ByVal swAssyModel As SldWorks.ModelDoc2)
If swAssyModel Is Nothing Then Exit Sub

‘ トップレベルアセンブリ
Dim swAssyDoc As SldWorks.AssemblyDoc
Set swAssyDoc = swAssyModel

Dim vComps As Variant
vComps = swAssyDoc.GetComponents(True) ‘ 子コンポーネントを一括取得

If IsEmpty(vComps) Then
Set swAssyDoc = Nothing
Exit Sub
End If

Dim i As Long
Dim swComp As SldWorks.Component2

For i = LBound(vComps) To UBound(vComps)
‘ ループ変数へのアサイン
Set swComp = vComps(i)

‘ — 実際の重い処理をここに記述 —
Debug.Print swComp.Name2
‘ ——————————–

‘ 【極めて重要】ループの各イテレーションの最後にCOM参照を確実に断つ
Set swComp = Nothing
Next i

‘ 親オブジェクトの解放
Set swAssyDoc = Nothing
End Sub

知見: `GetComponents` のような配列を返すAPIを使用する場合、配列内の各要素(COMオブジェクト)はVBAによって強参照される。そのため、ループ内で個別に `Set swComp = Nothing` を行わないと、配列の寿命が尽きるまでメモリが解放されない。

4. Windows APIとの協調:CADプロセスの制御とパフォーマンス監視

大規模マクロの実行中、SolidWorksが「応答なし」状態に陥った際、Windows APIを用いて適切にメッセージキューを処理(DoEventsの高度な代替)させたり、ウィンドウの描画を一時停止して処理速度を最大化する手法は、シニアエンジニアの必須武器である。

以下のコードは、マクロ実行中の画面描画をフリーズさせ、CPUリソースを処理に集中させるためのWindows API連携モジュールである。

‘ — 描画停止・再開のためのWindows API宣言 —
If VBA7 Then
Private Declare PtrSafe Function LockWindowUpdate Lib “user32” (ByVal hwndLock As LongPtr) As Long
Private Declare PtrSafe Function GetActiveWindow Lib “user32” () As LongPtr
Else
Private Declare Function LockWindowUpdate Lib “user32” (ByVal hwndLock As Long) As Long
Private Declare Function GetActiveWindow Lib “user32” () As Long
End If

Public Sub ToggleSolidWorksRedraw(ByVal swApp As SldWorks.SldWorks, ByVal disable As Boolean)
On Error Resume Next
‘ SolidWorks内部の描画フラグ制御
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayUpdateWhileDragging, Not disable

‘ UI全体の描画ロック(Windows API)
Dim hwnd As LongPtr
hwnd = GetActiveWindow()
If disable Then
LockWindowUpdate hwnd
Else
LockWindowUpdate 0
End If
On Error GoTo 0
End Sub

これをマクロの前後で挟むことにより、グラフィックの再描画コストが完全に消え去り、処理速度が 最大で300%以上向上 するケースもある。

5. まとめ:技術的負債を清算し、次世代のCAD自動化基盤へ

レガシーなSolidWorks VBAコードの近代化は、単なる「古い書き方の修正」ではない。それは、CADシステムのバージョンアップ追従性を高め、予期せぬクラッシュやメモリリークから現場のエンジニアを守るための、極めて戦略的な投資である。

本稿で解説した以下の原則を、今すぐ自社のマクロ資産に適用してほしい。

1. `SelectByID2` 依存を捨て、ダイレクトポインタ操作と型安全なキャストへ移行する。
2. すべてのCOMオブジェクトは使い捨ての精神で、スコープを最小限にして `Set obj = Nothing` を徹底する。
3. Windows APIやサイレントロードオプション(`OpenDoc7`)を駆使し、I/Oと描画のオーバーヘッドを極限まで削ぎ落とす。

コードの美しさとパフォーマンスは表裏一体である。洗練されたアーキテクチャこそが、あなたの業務自動化システムを永遠に陳腐化させない唯一の盾となる。

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