リンク切れの恐怖に終止符を。SolidWorksアセンブリ「健全性診断」の真髄
アセンブリを開くたびに表示される「ファイルが見つかりません」のダイアログ。あれは単なる警告ではない。設計者の工数を奪い、データの整合性を蝕む「静かなる時限爆弾」だ。
共有サーバーの移行、フォルダ階層の整理、あるいは無意識のファイル移動。これらによって引き起こされる参照エラーに対し、GUIの再リンク機能で対症療法を繰り返すのは、エンジニアの仕事ではない。
今回は、SolidWorks APIを深層で操作し、アセンブリ内の全コンポーネントのパスと参照状態を網羅的にスキャンする、実務レベルの診断エンジンを構築する。
1. 探索のアーキテクチャ:再帰構造とメモリの最適化
アセンブリを走査する際、単に `GetComponents` を呼ぶだけでは不十分だ。サブアセンブリが深くネストされた構造を完全に掌握するには、再帰関数(Recursive Function)が必須となる。
しかし、ここで多くの開発者が陥る罠がある。それは「オブジェクトの解放漏れ」だ。SolidWorksのCOMオブジェクトは強力だが、VBAのガベージコレクションを信用してはいけない。数千部品のアセンブリを回せば、メモリリークは確実にシステムを鈍らせる。
実装の要諦
- 再帰呼び出しの最適化: `ModelDoc2` を引数に渡し、常に現在のコンテキストを維持する。
- 明示的解放: `Set obj = Nothing` を徹底し、COM参照カウンタをゼロに近づける。
- 状態取得のAPI: `GetPathName` だけでなく、`GetReferencedModelName` と `GetCorrespondingMode` を使い分け、メモリ上の状態とディスク上のパスを厳密に比較する。
2. 実践:アセンブリ健全性スキャンコード
以下に、再帰的にコンポーネントを巡回し、パスの存在確認を行うエンジンを示す。
‘ 必要な参照設定: SolidWorks 20xx Type Library
Option Explicit
Public Sub RunAssemblyDiagnostic()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Or swModel.GetType <> swDocASSEMBLY Then
MsgBox “アセンブリを開いた状態で実行してください。”, vbCritical
Exit Sub
End If
Set swAssy = swModel
Debug.Print “— 診断開始: ” & swModel.GetPathName & ” —”
‘ 再帰的にコンポーネントを巡回
TraverseComponents swAssy.GetComponents(False)
Debug.Print “— 診断終了 —”
End Sub
Private Sub TraverseComponents(comps As Variant)
Dim i As Long
Dim swComp As SldWorks.Component2
Dim compPath As String
If IsEmpty(comps) Then Exit Sub
For i = LBound(comps) To UBound(comps)
Set swComp = comps(i)
‘ コンポーネントのフルパスを取得
compPath = swComp.GetPathName
‘ ファイルが存在するか、FSOで検証
If Not FileExists(compPath) Then
Debug.Print “[ERROR] リンク切れ検知: ” & swComp.Name2 & ” -> ” & compPath
Else
Debug.Print “[OK] ” & swComp.Name2
End If
‘ 子コンポーネントがあれば再帰
If swComp.GetChildrenCount > 0 Then
TraverseComponents swComp.GetChildren
End If
‘ オブジェクトの明示的解放
Set swComp = Nothing
Next i
End Sub
‘ Windows API/FSOを用いた高速存在確認
Private Function FileExists(path As String) As Boolean
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
If path = “” Then
FileExists = False
Else
FileExists = fso.FileExists(path)
End If
Set fso = Nothing
End Function
3. シニアエンジニアが意識すべき「隠れた仕様」
上記のコードは氷山の一角だ。真に堅牢なシステムを構築するなら、以下の点も考慮する必要がある。
外部参照の不整合(Suppressedの状態)
`GetPathName` は、コンポーネントが「抑制(Suppressed)」状態であってもパスを返す。しかし、ロードされていないコンポーネントのパスが正しいかどうかは、ファイルが存在するだけでは判断できない。`IsLoaded` プロパティを併用し、現在のメモリ状況との整合性をチェックするロジックを組み込むべきだ。
ネットワークI/Oのボトルネック
共有サーバー上の数千ファイルに対して `FileExists` を連発すると、ネットワークトラフィックがスパイクする。大規模アセンブリを扱う場合は、診断結果を一時的に辞書オブジェクト(`Scripting.Dictionary`)にキャッシュし、同一パスの重複チェックを省くことで、処理速度を劇的に向上させることができる。
開発の現場へ:なぜVBAなのか
今どきはPythonやC#が主流かもしれない。だが、SolidWorksのプロセス内で直接実行されるVBAには、「CADエンジニアがその場で即座に修正・実行できる」という圧倒的な保守の利点がある。
このコードをベースに、ログをCSVへ出力する、あるいはエラー時に自動で代替パスを検索するルーチンを付加すれば、あなたの設計環境は「属人化された管理」から「システムによる自動統制」へと進化するはずだ。
技術は裏切らない。ただ、深く理解し、正しく実装する者にのみ、その恩恵を与えるのだ。健闘を祈る。
