【SolidWorks VBA】アセンブリの表示状態を「完全復元」するプロフェッショナルな設計術
SolidWorks APIを扱うエンジニアにとって、アセンブリの状態管理は避けて通れない関門だ。特に、特定の検査工程で非表示部品を一時的に強制表示させ、その後「元の状態に完全に戻す」という処理は、一見単純だが、甘く見ると必ずバグを招く。
なぜなら、アセンブリの表示状態はコンポーネント単体のフラグだけでなく、表示状態(Display States)やコンフィギュレーションとの相関で決定されるからだ。今回は、現場で「動けばいい」レベルを卒業し、堅牢かつ保守性の高い「状態復元アーキテクチャ」を伝授する。
—
1. なぜ「力技」での復元は失敗するのか?
多くの初学者が陥るミスは、コンポーネントをループして `Component.Visible` プロパティを直接操作し、それを配列に保存しようとすることだ。
- 問題点1: コンポーネントが非表示の際、その「親」が非表示である場合、子コンポーネントを強制表示させてもアセンブリ上で反映されないケースがある。
- 問題点2: 実行中にコンフィギュレーションが切り替わると、復元先を見失う。
- 問題点3: 処理中のエラーでマクロが中断されると、表示状態が「変更されたまま」で放置され、ユーザーが手動で復元しなければならなくなる。
我々プロフェッショナルは、「状態の保存(Snapshot)」と「例外処理(Error Handling)」を分離し、トランザクションとして設計する必要がある。
—
2. 実装コード:堅牢な表示状態の管理クラス
以下は、`Dictionary` オブジェクトを用いて、コンポーネントのパスをキーに、表示状態を安全にバックアップ・復元するプロダクションコードだ。
Option Explicit
‘ — 状態復元のためのメインプロシージャ —
Public Sub ExecuteTaskWithRestoration()
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.GetType <> swDocASSEMBLY Then Exit Sub
Set swAssy = swModel
‘ 状態保存用辞書
Dim compStates As Object
Set compStates = CreateObject(“Scripting.Dictionary”)
On Error GoTo ErrorHandler
‘ 1. 現在の状態を保存
Call SaveVisibilityState(swAssy, compStates)
‘ 2. 検査・解析工程(例:全部品を強制表示)
swAssy.ShowAllComponents
Debug.Print “解析中:すべての部品を表示しました。”
‘ — ここに本来の業務ロジックを記述 —
‘ 3. 状態を復元
Call RestoreVisibilityState(swAssy, compStates)
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラー発生。表示状態を強制復元します。”, vbCritical
RestoreVisibilityState swAssy, compStates
End Sub
‘ — 非表示コンポーネントの状態保存 —
Private Sub SaveVisibilityState(assy As SldWorks.AssemblyDoc, dict As Object)
Dim comps As Variant
comps = assy.GetComponents(False)
Dim i As Long
Dim comp As SldWorks.Component2
For i = 0 To UBound(comps)
Set comp = comps(i)
‘ コンポーネントの表示状態を取得 (1: 表示, 0: 非表示)
If comp.Visible = 0 Then
dict.Add comp.GetPathName, comp.Visible
End If
Next i
End Sub
‘ — 状態復元 —
Private Sub RestoreVisibilityState(assy As SldWorks.AssemblyDoc, dict As Object)
Dim comps As Variant
comps = assy.GetComponents(False)
Dim i As Long
Dim comp As SldWorks.Component2
For i = 0 To UBound(comps)
Set comp = comps(i)
‘ 辞書に存在すれば(非表示対象であれば)、復元
If dict.Exists(comp.GetPathName) Then
comp.Visible = dict(comp.GetPathName)
End If
Next i
assy.ForceRebuild3 False
End Sub
—
3. 設計のポイントと技術的知見
A. `Scripting.Dictionary` の採用
配列ではなく `Dictionary` を使用することで、検索時間を O(1) に抑えている。大規模アセンブリにおいて、数千個の部品に対してインデックスでループを回すのは愚策だ。パス名をキーにすることで、コンポーネントの順序が入れ替わっても正確に復元できる。
B. `On Error GoTo` によるトランザクションの保護
業務自動化ツールの最大の罪は「中途半端な状態でマクロが止まること」だ。必ず `ErrorHandler` を経由させ、エラーが発生しても `RestoreVisibilityState` が確実に呼ばれる設計にしている。これは、製造現場のエンジニアに対する最低限の礼儀である。
C. パフォーマンスへの配慮
`ForceRebuild3` は重い処理だ。状態復元のループ内で何度も呼び出すのではなく、最後に一回だけ実行するように設計している。APIの呼び出し回数は、そのままツールが「重い」か「速い」かを決定する要因となる。
—
結びに代えて
自動化とは、単にコードを書くことではない。「作業者が本来行うべき『元の状態に戻す』という管理コストを、マクロに肩代わりさせること」である。
今回紹介したコードは、単なるスニペットではなく、「例外時にもシステムを整合性の取れた状態へ戻す」という設計思想の具現化だ。この構造をベースにすれば、表示状態だけでなく、色、コンフィギュレーション、抑制状態など、あらゆる属性のバックアップ・復元に応用が可能になるだろう。
君の作るツールが、現場のストレスを一つでも減らすことを期待している。次回の設計も、妥協のないものを期待してほしい。
