SolidWorks APIの深淵:コンフィギュレーション一括抽出が暴く設計の不整合
設計の現場において、アセンブリ内の各構成部品が「どのコンフィギュレーションで呼び出されているか」を把握することは、単なるリスト作成ではない。それは、設計の意図が正しく継承されているか、あるいは意図せぬ「過去の遺物」がアセンブリ内に潜んでいないかを監視する、極めて重要な検閲作業である。
本稿では、Activeなアセンブリから全てのコンポーネント構成を抽出し、Excelへ高速展開するVBAコードを提示する。単に動くコードをコピペする段階を脱し、メモリ管理と再帰構造の最適化という「シニアの視点」で実装を解説する。
—
1. 再帰処理の罠とメモリ最適化の極意
アセンブリには「サブアセンブリ」という構造が存在する。多くのエンジニアが陥る罠は、`GetComponents`を単純に呼び出し、再帰的に処理しようとしてスタックオーバーフローや循環参照で自滅することだ。
我々は `IComponent2` インタフェースを介して、再帰的に子要素を探索するが、ここで重要なのはオブジェクトの参照を明示的に解放することである。VBAのガベージコレクションは頼りにならない。大規模アセンブリでは、参照の蓄積が即座にメモリリークとなり、SolidWorksのプロセスを不安定にさせる。
2. 実装:高速構成エクスポート・アーキテクチャ
以下に示すコードは、パフォーマンスを最大化するために、`Application.ScreenUpdating`を抑制し、Variant配列を利用してExcelへの転送回数を最小限に抑える設計としている。
Option Explicit
‘ SolidWorks API 定数 (必要に応じてタイプライブラリ参照設定を追加すること)
‘ SldWorks.dll, SolidWorks.Interop.sldworks, SolidWorks.Interop.swconst
Public Sub ExportAllComponentConfigs()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swRootComp As SldWorks.Component2
‘ Excel用変数
Dim wb As Workbook
Dim ws As Worksheet
Dim dataArray() As Variant
Dim rowIdx As Long
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
Set swRootComp = swAssy.GetRootComponent3(True)
‘ カウンタの初期化とデータ配列の確保
ReDim dataArray(1 To 10000, 1 To 3)
rowIdx = 1
‘ 画面描画と再計算を停止し、処理を高速化
Application.ScreenUpdating = False
‘ 再帰処理開始
TraverseComponents swRootComp, dataArray, rowIdx
‘ Excelへの一括書き出し
Set ws = ThisWorkbook.ActiveSheet
ws.Cells.Clear
ws.Range(“A1:C1”).Value = Array(“Component Name”, “Configuration Name”, “Path”)
ws.Range(“A2”).Resize(rowIdx – 1, 3).Value = dataArray
Application.ScreenUpdating = True
‘ オブジェクト解放の徹底
Set swRootComp = Nothing
Set swAssy = Nothing
Set swModel = Nothing
Set swApp = Nothing
End Sub
Private Sub TraverseComponents(ByVal comp As SldWorks.Component2, ByRef arr() As Variant, ByRef rIdx As Long)
Dim vChildren As Variant
Dim i As Long
vChildren = comp.GetChildren
If IsEmpty(vChildren) Then Exit Sub
For i = LBound(vChildren) To UBound(vChildren)
Dim swChildComp As SldWorks.Component2
Set swChildComp = vChildren(i)
‘ データを配列に格納
arr(rIdx, 1) = swChildComp.Name2
arr(rIdx, 2) = swChildComp.ReferencedConfiguration
arr(rIdx, 3) = swChildComp.GetPathName
rIdx = rIdx + 1
‘ 再帰呼び出し
TraverseComponents swChildComp, arr, rIdx
‘ 参照の明示的解放(VBAの限界を補う唯一の手段)
Set swChildComp = Nothing
Next i
End Sub
—
3. シニアアーキテクトからの助言
1. `ReferencedConfiguration`の注意点
`ReferencedConfiguration`プロパティは、コンポーネントが実際に保持しているコンフィギュレーション名のみを返す。もしアセンブリが「読み込み専用」で開かれていたり、構成が破損している場合、この値は空になることがある。実務環境では、エラーハンドリング(`On Error Resume Next`)を適切に配置し、未解決状態のパスをログに残す工夫が必要だ。
2. 大規模アセンブリへの対応
もしアセンブリの階層が数千を超える場合、`ReDim`をループ内で行うのは愚策だ。上記コードのようにあらかじめ十分なサイズの配列を確保するか、`Scripting.Dictionary`を用いて重複排除や高速なインデックス検索を行うアーキテクチャへの昇華を検討せよ。
3. Windows APIとの連携
もし「特定のコンフィギュレーション名が変更された際にExcelへ通知したい」という要件があるなら、`swApp.SetAddinCallbackInfo`や、`DAssemblyDocEvents`を用いたイベント駆動設計が必須となる。VBAだけで完結させようとせず、外部プロセスとのパイプラインを意識した設計こそが、真の自動化エンジニアの嗜みである。
—
結びに
技術は目的ではない。設計上の不整合を可視化し、エンジニアが「本来の創造的な作業」に集中できる時間を捻出することこそが、我々アーキテクトのミッションである。
このコードが、貴方の現場における「設計のブラックボックス」を解明する一助となることを願う。コードは動けば良いものではない。保守可能であり、かつ美しいものであるべきだ。
