【テクニカル・上級編】【サブアセンブリの動的制御】IComponent2.SetSuppression2とIsFixedによるコンポーネントの高度な状態管理 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBAを掌握する極限の知見】サブアセンブリの動的制御:IComponent2.SetSuppression2とIsFixedによる極限の軽量化と状態管理

幾重にも入れ子になった数万パーツの大規模アセンブリを前に、SolidWorksの画面が固まる。その瞬間を見据え、背筋が凍るような思いをしたことはないか。
シミュレーション、干渉チェック、あるいは自動コンフィギュレーション生成の現場において、手動でのコンポーネント抑制や固定(Fix)の切り替えは、もはやエンジニアの時間を浪費する拷問に等しい。

我々はプログラマーである。手動のGUI操作などという非効率な原始的行為はAPIの荒波に沈め、VBAのコード一閃でアセンブリの命脈を完全に支配下に置くべきだ。

今回は、`IComponent2.SetSuppression2` と `IsFixed` を軸に、メモリの深淵を覗き込みながら、サブアセンブリの動的制御の真髄を解き明かす。

1. 抑制(Suppression)と固定(Fix)のAPIアーキテクチャ

SolidWorks APIにおけるコンポーネント制御の基本単位は `IComponent2` インターフェースである。しかし、このオブジェクトのライフサイクルとメモリ管理、そして状態遷移の挙動を誤ると、VBAランタイムは容易にメモリリークや「RPCサーバーは利用できません」という冷酷なエラーを吐き捨てる。

抑制状態(Suppression State)の深層

`SetSuppression2` メソッドは、コンポーネントの状態(完全解決、軽量、抑制など)を動的に変更する。
ここで重要なのは、「どのレベルのコンテキストで抑制するか」という定数(`swComponentSuppressionState_e`)の選択である。

  • `swComponentFullyResolved`: 完全解決。メモリを食いつぶすが、幾何公差や詳細なフィーチャーにアクセス可能。
  • `swComponentLightweight`: 軽量。大規模アセンブリの救世主だが、API経由での詳細ジオメトリ取得に制限がある。
  • `swComponentSuppressed`: 完全に抑制。メモリからモデルがアンロードされ、実質的にアセンブリから存在しない状態になる。

大規模アセンブリの動的制御において、不要なサブアセンブリを `swComponentSuppressed` に叩き落とすことで、RAMの消費量を劇的に削減し、後続の処理速度を数倍から数十倍へと跳ね上げることが可能となる。

固定状態(IsFixed)の罠

サブアセンブリやパーツの位置を空間に縛り付ける `IsFixed` プロパティ。これは一見ただの真偽値(Boolean)のプロパティに見えるが、実はアセンブリのコンテキスト(マイト関係)と密接に絡み合う危険な代物だ。
ルートアセンブリから見て、どのレベルのコンポーネントに対して `IsFixed = True` を叩くかによって、下位パーツの自由度が予期せぬ挙動を引き起こす。動的シミュレーションの前段階では、すべての浮動パーツのアンカーとして正確に制御されなければならない。

2. メモリ最適化とCOMオブジェクトの厳格な解放

VBAにおけるSolidWorks API開発で最も恐れられるのは、背後で肥大化し続けるCOMの参照カウンタ(Reference Counter)の暴走である。
`IAssemblyDoc::GetComponents` や `IComponent2::GetChildren` を呼び出すたびに、メモリ空間には無数のCOMポインタが生成される。これらを放置すれば、数回のループでSolidWorksごとVBAホストプロセスが沈没する。

「取得したオブジェクトは、そのスコープの終了時に必ず `Nothing` を代入して解放する」
これは宗教儀式ではなく、生き残るための鉄則である。

3. 実践コード:大規模アセンブリの動的制御エンジン

以下に、指定した名称のサブアセンブリを動的に検索し、非抑制(完全解決)状態にした上で固定し、さらに不要な子コンポーネント群をメモリ最適化を考慮しながら一括制御する実用的なVBAコードを提示する。

‘ =================================================================================
‘ módulo: ModSubAssemblyController
‘ 概要: サブアセンブリの抑制・非抑制および固定状態を動的に制御するチーフアーキテクト級サンプル
‘ =================================================================================
Option Explicit

Sub ExecuteDynamicComponentControl()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssDoc As SldWorks.AssemblyDoc
Dim rootComp As SldWorks.Component2

‘ 1. 接続の確立 (GetApplicationの極意)
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical
Exit Sub
End If

Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbWarning
Exit Sub
End If

‘ アセンブリドキュメントであることの型チェック
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アクティブなドキュメントはアセンブリではありません。”, vbCritical
Exit Sub
End If

Set swAssDoc = swModel

‘ ルートコンポーネントの取得 (これがアセンブリツリーの頂点)
Set rootComp = swAssDoc.GetRootComponent3(True)
If rootComp Is Nothing Then
MsgBox “ルートコンポーネントの取得に失敗しました。”, vbCritical
Exit Sub
End If

‘ 処理の開始(画面描画を停止してパフォーマンスを極限まで引き上げる)
swModel.Visible = False
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, True

On Error GoTo ErrorHandler

‘ 対象サブアセンブリの制御実行 (例: “Mechanism_Sub-1”)
Dim targetSubAssemblyName As String
targetSubAssemblyName = “Mechanism_Sub-1”

Call TraverseAndControlComponent(rootComp, targetSubAssemblyName)

‘ 変更の反映と再構築
swModel.ForceRebuild3 True

MsgBox “サブアセンブリの動的制御が正常に完了しました。”, vbInformation, “チーフアーキテクトからの報告”

CleanUp:
‘ 描画の復元とメモリの明示的解放
swModel.Visible = True
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, False

‘ オブジェクトの完全解放 (メモリリークの根絶)
Set rootComp = Nothing
Set swAssDoc = Nothing
Set swModel = Nothing
Set swApp = Nothing
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub

‘ =================================================================================
‘ 再帰的コンポーネント走査・制御プロシージャ
‘ =================================================================================
Private Sub TraverseAndControlComponent(ByVal parentComp As SldWorks.Component2, ByVal targetName As String)
Dim vChildren As Variant
Dim i As Long
Dim childComp As SldWorks.Component2
Dim compName As String

vChildren = parentComp.GetChildren
If IsEmpty(vChildren) Then Exit Sub

For i = LBound(vChildren) To UBound(vChildren)
Set childComp = vChildren(i)

‘ コンポーネント名(インスタンス名またはファイル名)の取得
compName = childComp.Name2

‘ デバッグ出力(必要に応じてイミディエイトウィンドウで確認)
‘ Debug.Print “Checking: ” & compName

‘ ターゲットのサブアセンブリに一致するか判定
If InStr(1, compName, targetName, vbTextCompare) > 0 Then
‘ 【核心】抑制状態の変更 (完全解決状態で非抑制にする)
‘ 引数: swComponentSuppressionState_e (swComponentFullyResolved = 3)
Dim status As Long
status = childComp.SetSuppression2(swComponentFullyResolved)

If status = 0 Then
‘ 固定状態(IsFixed)の動的制御
‘ ※アセンブリの設計意図に合わせてTrue/Falseを切り替える
If Not childComp.IsFixed Then
childComp.IsFixed = True
End If

Debug.Print “Controlled Target: ” & compName & ” -> Resolved & Fixed.”
End If
End If

‘ さらに下位階層へ再帰的に潜る
Call TraverseAndControlComponent(childComp, targetName)

‘ ループ内でのCOMオブジェクトの確実な解放
Set childComp = Nothing
Next i

Erase vChildren
End Sub

4. チーフアーキテクトが直伝する現場の知見とトラブルシューティング

1. `SetSuppression2` がエラーを返すときの隠れた原因

大規模アセンブリにおいて、外部参照(In-Context)のスケッチや合致(Mates)が破損しているコンポーネントに対して突発的に `SetSuppression2` を実行すると、APIはサイレント失敗するか、予期せぬCOM例外を投げる。
これを回避するためには、事前にコンポーネントのファイル存在確認(`IComponent2.GetPathName`)と、ドキュメントの読み込み状態を確認するガード句を挟むのがプロの作法である。

2. 画面描画のロック(`Visible = False` との付き合い方)

コード内でアセンブリの構造をゴリゴリ書き換える際、SolidWorksのGUIがそれをリアルタイムにレンダリングしようとすると、GDIリソースが圧迫され、処理速度が極端に低下する。
上記のサンプルコードの通り、処理の冒頭で `swModel.Visible = False` とし、最後に戻す手法は、大規模アセンブリの自動化において「秒単位の時間を買い取る」ための必須テクニックである。

3. レガシー環境と64bit VBAのメモリ境界

現代のSolidWorks環境は基本的に64bitであるが、過去の遺産である古いVBAアドインやExcelマクロからCOM経由でこれらを叩く場合、Variant型の配列(`GetChildren` が返すもの)のメモリ解放漏れがプロセスを徐々に蝕む。
配列変数 `vChildren` は、使い終わったら明示的に `Erase` を実行し、ポインタの参照を切断することを忘れてはならない。

総括

`IComponent2.SetSuppression2` と `IsFixed` を完全に手懐けること。それは、ただAPIのメソッドを呼び出すことではない。SolidWorksのメモリモデル、アセンブリのツリー構造、そしてCOMのライフサイクルそのものを掌の上で踊らせることに他ならない。

手動操作の限界を突破し、真の「動的・自動化された設計検証基盤」をあなたの手で構築せよ。

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