現場の「不可視」を制御せよ:SolidWorksアセンブリにおける状態管理の極意
大規模アセンブリを扱うエンジニアにとって、設計のボトルネックは「意図しないツリーの乱れ」にある。検査工程や特定の自動化処理において、非表示状態の部品を一括で制御し、処理後に完璧な形で復元する。これは単なるユーティリティではなく、「アセンブリのステート管理」というアーキテクチャの根幹に関わる課題だ。
今回は、数千部品を超えるアセンブリでもメモリを浪費せず、かつ堅牢に「非表示状態」をスナップショットとして保持・復元する極限のテクニックを伝授する。
—
1. なぜ「状態の退避」が必要なのか
大規模なアセンブリにおいて、`Component.Visible`を闇雲に操作すれば、SolidWorksの内部キャッシュは肥大化し、最悪の場合、グラフィックス領域の更新処理(`Rebuild`)が連鎖して数分のフリーズを招く。
我々が目指すべきは、「最小限のオブジェクト参照」による状態管理だ。部品の名称(`Name2`)をキーに、`Collection`オブジェクトを用いてハッシュマップを構築する。このアプローチは、再帰呼び出しを多用するような非効率な探索を排除し、処理速度を劇的に向上させる。
2. 状態管理のアーキテクチャ設計
以下のコードでは、`Scripting.Dictionary`を活用する。VBA標準の配列よりも高速に検索でき、かつ構造化に適しているためだ。
‘ ——————————————————————
‘ AssemblyStateManager: 非表示コンポーネントの状態を完全管理する
‘ ——————————————————————
Option Explicit
Private m_HiddenComponents As Object ‘ Scripting.Dictionaryを格納
‘ 状態の退避
Public Sub SnapshotHiddenComponents(swAssy As SldWorks.AssemblyDoc)
Dim swRootComp As SldWorks.Component2
Dim swModel As SldWorks.ModelDoc2
Set m_HiddenComponents = CreateObject(“Scripting.Dictionary”)
Set swModel = swAssy
Set swRootComp = swModel.ConfigurationManager.ActiveConfiguration.GetRootComponent3(True)
‘ 再帰的に全コンポーネントを探索
TraverseAndStore swRootComp
End Sub
Private Sub TraverseAndStore(swComp As SldWorks.Component2)
Dim vChildComps As Variant
Dim swChildComp As SldWorks.Component2
Dim i As Long
vChildComps = swComp.GetChildren
If IsEmpty(vChildComps) Then Exit Sub
For i = 0 To UBound(vChildComps)
Set swChildComp = vChildComps(i)
‘ 非表示(Visible = 0)であれば辞書に登録
If swChildComp.Visible = 0 Then
m_HiddenComponents.Add swChildComp.Name2, True
End If
‘ 子要素を再帰的に追跡
TraverseAndStore swChildComp
Next i
End Sub
3. オブジェクトライフサイクルとメモリ最適化の極致
ここでの最大の禁忌は、`GetChildren`で取得した配列の要素を、明示的に解放せずに放置することだ。COMインターフェースを介したSolidWorks APIにおいて、参照カウントの管理は死活問題である。
「使い終わったオブジェクトは、即座にNothingへ代入する」。これが、メモリリークを許さないシニアエンジニアの流儀である。
4. 復元処理の実装:高速化の鍵
復元処理においては、`ModelDocExtension.SelectByID2`を使って一つずつ選択して表示を切り替えるような「愚策」は避けるべきだ。コンポーネントの参照を直接保持し、メソッドを叩く。
‘ 復元処理:辞書に基づき、非表示状態を再適用する
Public Sub RestoreHiddenComponents(swAssy As SldWorks.AssemblyDoc)
Dim swModel As SldWorks.ModelDoc2
Set swModel = swAssy
‘ 全コンポーネントを一度表示状態にする(リセット)
‘ ※ここで全表示することで、辞書にないものは「表示」される
swAssy.CompConfigProperties(swCompVisibilityState_Show, Nothing)
‘ 辞書にあるコンポーネントのみを再非表示化
Dim key As Variant
For Each key In m_HiddenComponents.Keys
Dim swComp As SldWorks.Component2
Set swComp = swAssy.GetComponentByName(key)
If Not swComp Is Nothing Then
swComp.Visible = 0
End If
Next key
‘ メモリの明示的解放
Set m_HiddenComponents = Nothing
End Sub
5. チーフアーキテクトからの提言
このコードをそのまま使うのも良いが、実務においては以下の点に留意してほしい。
1. コンフィギュレーションの不一致: `GetComponentByName`は現在の構成(Configuration)でのみ有効だ。アセンブリが構成を切り替えた直後にこの関数を呼ぶと、正しいインスタンスを掴めない可能性がある。必ず`ActiveConfiguration`の整合性を確認せよ。
2. Windows APIの併用: もし大規模アセンブリで操作が重いと感じるなら、`DoEvents`を要所に挟むのではなく、`SendMessage`等でSolidWorksの描画更新を一時停止(`Freeze`)させる手法も検討すべきだ。これにより、ツリー更新に伴う再描画負荷を劇的に抑えられる。
3. エラーハンドリング: `GetChildren`が`Nothing`を返すケースは意外と多い。`IsArray`や`UBound`のチェックを怠ることは、即座にランタイムエラーへ繋がる。
自動化は「魔法」ではない。コンポーネントというオブジェクトの命を、どれだけ正確に管理できるかという「規律」である。このアーキテクチャが、君の現場の生産性を極限まで高めることを期待している。
