【テクニカル・上級編】【実務中級】アセンブリ内のすべての非表示部品の状態を一時保存し、特定の検査工程後に元の表示状態へ復元するマクロ – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks APIの深淵:非表示状態の完全なる「スナップショット」と「復元」の技術

SolidWorks APIを扱う際、多くのエンジニアが陥る罠がある。それは「表示/非表示」という極めて単純に見える状態管理を、単なるプロパティの反転として捉えてしまうことだ。

特にアセンブリの大規模化が進む現場では、非表示部品の再表示は単なるUIの更新ではない。それはメモリの再割り当てと再描画、そしてコンポーネントのライフサイクルに関わる重い処理だ。今回は、私が長年培ってきた「状態の完全保存と復元」のアーキテクチャを公開する。

—

なぜ「単純なループ」では不十分なのか

多くの初学者は `Component.Visible = True` をループで回す。しかし、これではアセンブリの階層構造や「抑制(Suppression)」状態と混同し、予期せぬ再計算を誘発する。

シニアエンジニアとして設計すべきは、「現在の表示状態を辞書(Dictionary)に閉じ込め、処理が終われば不可逆的に元に戻す」というトランザクション処理だ。

実装の鍵:Collectionオブジェクトと再帰処理

大規模アセンブリにおいては、再帰的にコンポーネントを巡回し、一意のID(Component.GetID)をキーとして状態を保持する必要がある。

Option Explicit

‘ 状態保存用のコレクション
Private m_VisibleState As Object

‘ 実行のメインルーチン
Public Sub PerformInspectionTask()
Dim swApp As SldWorks.SldWorks
Dim swAssy As SldWorks.AssemblyDoc

Set swApp = Application.SldWorks
Set swAssy = swApp.ActiveDoc

If swAssy Is Nothing Then Exit Sub

‘ 1. 現在の状態をスナップショットとして保存
Set m_VisibleState = CreateObject(“Scripting.Dictionary”)
CaptureVisibility swAssy.GetComponents(False)

‘ 2. 検査のための強制表示ロジック(例:特定の部品を表示)
‘ … ここに解析ロジックを記述 …

‘ 3. 処理終了後に復元
RestoreVisibility swAssy

‘ 4. メモリ解放
Set m_VisibleState = Nothing
End Sub

‘ 再帰的な状態取得
Private Sub CaptureVisibility(comps As Variant)
Dim i As Long
Dim comp As SldWorks.Component2

For i = LBound(comps) To UBound(comps)
Set comp = comps(i)
‘ コンポーネントの表示状態(0:非表示, 1:表示)をIDと共に記録
m_VisibleState.Add comp.GetID, comp.Visible

‘ サブアセンブリがある場合は再帰
If comp.GetChildrenCount > 0 Then
CaptureVisibility comp.GetChildren
End If
Next i
End Sub

‘ 状態の復元(トランザクションのコミット)
Private Sub RestoreVisibility(swAssy As SldWorks.AssemblyDoc)
Dim comp As SldWorks.Component2
Dim vKeys As Variant
Dim key As Variant

‘ 既存の表示状態を全走査して、保存した状態に戻す
‘ ※パフォーマンス向上のため、必要に応じて再帰ではなくコンポーネントリストを取得して比較
Dim comps As Variant
comps = swAssy.GetComponents(False)

‘ … (以下、保存したDictionaryを用いてComponent.Visibleを更新)
End Sub

—

アーキテクトの視点:パフォーマンスと堅牢性への配慮

1. メモリ最適化とオブジェクト解放

VBAにおいて、`SldWorks.Component2` などのCOMオブジェクトは保持し続けるとメモリリークの温床となる。上記の `CaptureVisibility` 内では、ループごとに `Set comp = Nothing` を明示的に呼び出す癖をつけよ。大規模アセンブリで数千のオブジェクトをスタックに積めば、VBAのヒープ領域は即座に枯渇する。

2. 再描画の抑制(Suspension of Graphics)

API実行中、`swApp.Visible = False` を一時的に行い、`swAssy.GraphicsRedraw` を制御することで、処理速度は劇的に向上する。特に大規模アセンブリでは、表示状態が変わるたびにSolidWorksはレンダリングパイプラインを更新しようとする。これを抑制することが、伝説的自動化エンジニアの嗜みだ。

3. Windows APIによる「フリーズ」制御

さらに極限を求めるなら、`LockWindowUpdate`(User32.dll)を呼び出し、マクロ実行中の画面更新を強制的にフリーズさせるべきだ。これにより、ユーザーはマクロが裏で暴れている間、意図しないちらつきに悩まされることがない。

If VBA7 Then
Private Declare PtrSafe Function LockWindowUpdate Lib “user32” (ByVal hwndLock As LongPtr) As Long
Else
Private Declare Function LockWindowUpdate Lib “user32” (ByVal hwndLock As Long) As Long
End If

‘ 実行直前に LockWindowUpdate(hwnd) を呼び出し、終了後に 0 を渡して解除する。

—

結論:安定したシステムを構築するために

このコードは単なる「表示/非表示」のマクロではない。アセンブリという不安定な物理状態を、論理的な静的状態として安全に隔離(Isolation)するためのテンプレートである。

レガシーなVBA環境であっても、オブジェクト指向の設計思想を適応させることで、システムの保守性は飛躍的に向上する。次のステップとして、このロジックをクラスモジュールにパッケージ化し、`IVisibilityManager` インターフェースとして実装することを強く推奨する。

技術は常に「動く」ものから「制御できる」ものへと昇華させるべきだ。健闘を祈る。

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