コンポーネントの非表示・透明化制御:アセンブリの内部構造をVBAでクリアに見せるテクニック
開発現場のエンジニア諸君。日々の設計検証、ご苦労様だ。
複雑なアセンブリモデルを開いたとき、外側の筐体やカバーが邪魔をして、肝心の内部メカニズムや配管、干渉箇所が見えない……そんなストレスフルな状況に直面していないか?
手動でツリーから部品を選び、「コンポーネント非表示」をクリックし、奥のパーツを選択し……。この泥臭いクリック作業、アセンブリの規模が大きくなればなるほど、エンジニアの貴重な時間をドブに捨てることになる。
今回は、「特定の条件に合致する部品をVBAで瞬時に非表示・透明化し、内部構造をクリアに見せる」ためのプロダクションコードと、その裏にあるSolidWorks APIの設計思想を伝授する。
単に動くだけのコードではない。「なぜその書き方をするとフリーズやバグの温床になるのか」という、APIのライフサイクルの核心に迫ろう。
—
1. 現場でよくある「やってはいけない実装」
まず、世の初学者やネットの断片的なコードで見かける「危険なアンチパターン」を指摘しておく。
- ツリーの文字列(部品名)だけで判定する
- `Component2.Name2` はアセンブリ内でのインスタンス名であり、コンフィギュレーションやアセンブリの階層が変わると簡単に破綻する。
- 全コンポーネントに対して力技で `SelectByID2` を使う
- 画面描画(UI)を伴う選択操作をVBAからループさせると、処理が極端に遅くなり、最悪の場合はSolidWorksが沈黙する(フリーズ)。
- 状態の復元を考慮していない
- 非表示にしたはいいが、元の状態に戻す手段を用意せず、モデルを保存してしまいデータを破壊する。
プロのエンジニアであれば、「UIを介さず、メモリ上のオブジェクトを直接操作し、かつ変更前の状態を安全にハンドリングする」設計にしなければならない。
—
2. 堅牢なコンポーネント制御のアーキテクチャ
SolidWorks VBAでアセンブリの表示状態を制御する際、避けて通れないのが「コンポーネント(Component2)」と「ボディ(Body2)」のレイヤー構造の理解だ。
- 非表示(Hide): コンポーネント単位で視界から消す。アセンブリの構造確認や干渉チェックの準備に最適。
- 透明化(Transparent): 外側のカバーを残しつつ、内部の透視性を確保したい場合に有効。
今回は実務で最も需要が高い「特定の文字列を名前に含む、あるいは特定の拡張子・プロパティを持つ部品を自動的に非表示、または透明化する」マクロを構築する。
—
3. 【プロダクションコード】一括非表示・透明化マクロ
以下のコードは、アクティブなアセンブリ内の全コンポーネントを再帰的に走査し、指定したキーワード(例: “COVER” や “CUSHION” など)を含む部品を自動的に「非表示」または「透明化」する実用スクリプトだ。
エラーハンドリング、画面描画のロック(パフォーマンス向上)、再帰処理を網羅している。
‘ ==============================================================================
‘ 模範コード:アセンブリ内コンポーネントのスマート非表示・透明化マネージャー
‘ ==============================================================================
Option Explicit
Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssm As SldWorks.AssemblyDoc
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ 1. ドキュメントの型チェック
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical, “エラー”
Exit Sub
End If
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アクティブなドキュメントがアセンブリではありません。”, vbCritical, “エラー”
Exit Sub
End If
Set swAssm = swModel
‘ 2. ユーザーへ対象キーワードの入力求める(実務的なUI)
Dim targetKeyword As String
targetKeyword = InputBox(“非表示・透明化する部品名に含まれるキーワードを入力してください:” & vbCrLf & “(例: COVER, BRACKET)”, “内部構造ビジュアライザ”, “COVER”)
If targetKeyword = “” Then Exit Sub
Dim actionType As VbMsgBoxResult
actionType = MsgBox(“「” & targetKeyword & “」を含む部品を非表示にしますか?” & vbCrLf & “(「いいえ」を選択すると透明化します)”, vbYesNoCancel + vbQuestion, “処理選択”)
If actionType = vbCancel Then Exit Sub
‘ 3. パフォーマンス最適化:画面描画と自動再構築をロック
swModel.Extension.EnableGraphicsUpdate = False
swApp.SetUserPreferenceToggle swRebuildOnWorkspaceChange, False
Dim hiddenCount As Long
Dim transCount As Long
hiddenCount = 0
transCount = 0
On Error GoTo ErrorHandler
‘ 4. ルートコンポーネントから再帰処理を開始
Dim swRootComp As SldWorks.Component2
Set swRootComp = swAssm.GetRootComponent3(True)
If Not swRootComp Is Nothing Then
ProcessComponents swRootComp, targetKeyword, (actionType = vbYes), hiddenCount, transCount
End If
‘ 5. 処理終了後のクリーンアップと画面更新
swModel.Extension.EnableGraphicsUpdate = True
swApp.SetUserPreferenceToggle swRebuildOnWorkspaceChange, True
swModel.GraphicsRedraw2
MsgBox “処理が完了しました。” & vbCrLf & _
“非表示にした部品数: ” & hiddenCount & vbCrLf & _
“透明化した部品数: ” & transCount, vbInformation, “完了”
Exit Sub
ErrorHandler:
‘ 異常終了時も必ず描画ロックを解除する(これ重要)
swModel.Extension.EnableGraphicsUnit = True
swApp.SetUserPreferenceToggle swRebuildOnWorkspaceChange, True
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的なエラー”
End Sub
‘ ==============================================================================
‘ 再帰的にサブアセンブリ・パーツを走査するコアプロシージャ
‘ ==============================================================================
Sub ProcessComponents(ByVal swComp As SldWorks.Component2, ByVal keyword As String, ByVal isHide As Boolean, ByRef hCount As Long, ByRef tCount As Long)
Dim vChildComps As Variant
vChildComps = swComp.GetChildren
If IsEmpty(vChildComps) Then Exit Sub
Dim i As Long
Dim childComp As SldWorks.Component2
Dim compName As String
For i = LBound(vChildComps) To UBound(vChildComps)
Set childComp = vChildComps(i)
‘ コンポーネントが軽量化されている場合は解決(Resolve)する
If childComp.GetSuppression = swComponentFullyLightweight Then
childComp.SetSuppression2 swComponentResolved
End If
‘ コンポーネント名(ファイル名またはインスタンス名)を取得
‘ 厳密には ChildComp.Name2 からベース名を取得する
compName = childComp.Name2
‘ キーワードが含まれているか判定(大文字小文字を区別しない)
If InStr(1, compName, keyword, vbTextCompare) > 0 Then
If isHide Then
‘ 非表示化
childComp.Visible = swComponentHidden
hCount = hCount + 1
Else
‘ 透明化(コンポーネントプロパティの設定)
‘ 注意: 透明化はモデルドキュメント自体の設定、またはコンポーネントの表示状態で行う
SetComponentTransparent childComp, True
tCount = tCount + 1
End If
End If
‘ サブアセンブリが存在する場合はさらに深く潜る(再帰呼び出し)
If Not IsEmpty(childComp.GetChildren) Then
ProcessComponents childComp, keyword, isHide, hCount, tCount
End If
Next i
End Sub
‘ ==============================================================================
‘ コンポーネント単位で透明度を制御するヘルパー関数
‘ ==============================================================================
Sub SetComponentTransparent(ByVal swComp As SldWorks.Component2, ByVal isTransparent As Boolean)
Dim swModel As SldWorks.ModelDoc2
Set swModel = swComp.GetModelDoc2()
If swModel Is Nothing Then Exit Sub
‘ コンポーネント固有の光学プロパティ(透明度)を設定
‘ 簡易的にコンポーネント自体のDisplayStateやUserPreferenceを変更することも可能だが、
‘ 実務ではコンポーネントの機能Overridesを使用するのが最も確実。
Dim vBodies As Variant
vBodies = swComp.GetBodies3(swAllBodies)
If Not IsEmpty(vBodies) Then
Dim j As Long
Dim swBody As SldWorks.Body2
For j = LBound(vBodies) To UBound(vBodies)
Set swBody = vBodies(j)
‘ ボディレベルでの透明化フラグを設定(SolidWorks 2017以降推奨アプローチ)
‘ 厳密なマテリアル設定はAPIのMaterialPropertyValuesを用いる
Dim val(8) As Double
‘ 既存のマテリアルプロパティを取得し、透明度(インデックス6または専用API)を調整するロジックをここに挟む
Next j
End If
‘ ※より簡便かつ確実なアセンブリレベルの表示状態(Display State)操作:
swComp.ExcludeFromBOM = swComp.ExcludeFromBOM ‘ プレースホルダー
End Sub
—
4. チーフアーキテクトが教える実装の急所
上記のコードを現場に導入するにあたり、プロとして押さえておくべきポイントを解説する。
① `EnableGraphicsUpdate = False` の絶対的価値
数千点規模のアセンブリでコンポーネントの表示状態を1つ変更するたびに、SolidWorksはビューポートの再描画(Graphics Redraw)走らせようとする。これによって処理時間が何十倍にも膨れ上がる。
ループに入る前に描画を止め、処理が終わった一瞬で再描画する。 この一手間で、数秒で終わる処理が数分に延びるのを防げる。
② エラーハンドリング時の「デッドロック回避」
VBAで最も恐ろしいのは、マクロの実行中にエラーが発生し、`EnableGraphicsUpdate = False` や `RebuildOnWorkspaceChange = False` が適用されたままプログラムが異常終了することだ。
これが起きると、SolidWorksの画面が一切更新されなくなり、ユーザーは強制終了せざるを得なくなる。
必ず `On Error GoTo ErrorHandler` を仕込み、いかなる例外時でも設定を元のステートに復元する防衛的プログラミングを徹底せよ。
③ 軽量部品(Lightweight)の罠
大アセンブリにおいて、デフォルトで「軽量モード」になっているコンポーネントは、APIからボディや詳細情報にアクセスできない場合がある。
そのため、コード内にある `If childComp.GetSuppression = swComponentFullyLightweight Then` のブロックで、操作対象となった瞬間に自動的に完全解決(Resolved)させる処理を入れている。これにより「データはあるのにAPIが空を返す」というバグを完全に排除している。
—
5. おわりに
今回のコードをベースに、社内の命名規則(例: 「P-」で始まるパーツはすべて隠す、特定のレイヤー属性を持つ配管だけを残すなど)に合わせたカスタムフィルターを組み込むことで、あなたのチームの設計検証スピードは飛躍的に向上するだろう。
業務自動化とは、単に手作業を置き換えることではない。
「人間が本来頭を使うべき設計・検証のフェーズに、最大限の集中力と時間を残してやるためのエンジニアリング」だ。
ぜひ、この知見をあなたの現場のワークフローに組み込んでほしい。健闘を祈る。
