こんにちは!SolidWorks自動化の現場で、日々数千パーツを抱える巨大アセンブリと格闘しているチーフアーキテクトです。
「マクロの記録」ボタンを押して操作を記録してみたものの、いざ再生するとエラーが出たり、画面がチラつくだけで動かなかったり……そんな壁にぶつかっていませんか?
今回は、大規模アセンブリの設計現場で絶対に避けて通れない「サブアセンブリや部品の動的制御(抑制と固定)」について解説します。ここをマスターすれば、重たいモデルの軽量化や、オプション違いのバリエーション自動生成が驚くほどスムーズになりますよ。
ここをクリアすれば、SolidWorks VBAの基本はバッチリです。一緒に本質を理解していきましょう!
—
1. なぜ「抑制」と「固定」の制御が必要なのか?
設計の現場では、次のような要望が常につきまといます。
- 「オプションAの仕様だから、オプションB用のサブアセンブリは全部消したい(でもファイル自体は消したくない)」
- 「最初はフリーで動かしたい部品だけど、計算時は特定の場所にガッチリ固定(IsFixed)したい」
これを手動でやっていると、ツリーから該当部品を探し出し、右クリックして「抑制(Suppress)」を選び……と、膨大な時間がかかりますよね。さらに、ヒューマンエラーで必要な部品まで消してしまうリスクもあります。
これをVBAで一瞬にして、しかも正確に実行するのが今回のテーマです。
—
2. SolidWorks APIの心臓部:オブジェクトの階層構造
VBAからアセンブリを操作するとき、SolidWorksの内部ではどのようなオブジェクトが動いているのでしょうか。イメージ図で見てみましょう。
[SldWorks.SldWorks] (SolidWorksアプリケーション本体)
└─ [ModelDoc2] (現在開いているアセンブリのドキュメント)
└─ [Configuration] (現在のコンフィギュレーション)
└─ [Component2] (アセンブリに配置された個々の部品・サブアセンブリ) ★ここを操作!
私たちが操作するのは、アセンブリの中にある個々の部品を指す `IComponent2` インターフェース です。
この `IComponent2` に対して、「抑制する(ファイルの読み込みをメモリから解放する)」 や 「固定する(位置を動かないようにロックする)」 という命令を送ります。
—
3. 実践!コンポーネントを「抑制」・「固定」するVBAコード
それでは、実際に動くコードを見てみましょう。
このコードは、現在アクティブなアセンブリ内を巡回し、指定した名前の部品(またはサブアセンブリ)を見つけ出して、「固定を解除」し、「抑制(非表示&メモリ解放)」するサンプルです。
Sub ControlAssemblyComponents()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssDoc As SldWorks.AssemblyDoc
Dim vComps As Variant
Dim i As Long
Dim swComp As SldWorks.Component2
Dim compName As String
‘ 1. SolidWorksアプリケーションとアクティブドキュメントの取得
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ ドキュメントが開いていない、またはアセンブリではない場合は終了
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれています。”, vbCritical
Exit Sub
End If
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アクティブなドキュメントがアセンブリではありません。”, vbCritical
Exit Sub
End If
Set swAssDoc = swModel
‘ 2. アセンブリ内の全コンポーネント(最上位)を取得
vComps = swAssDoc.GetComponents(True) ‘ Trueを指定すると子孫コンポーネントも全て取得
If IsEmpty(vComps) Then
MsgBox “コンポーネントが見つかりませんでした。”, vbExclamation
Exit Sub
End If
‘ 3. ループ処理で目的のコンポーネントを探して制御する
For i = LBound(vComps) To UBound(vComps)
Set swComp = vComps(i)
‘ コンポーネントの名前を取得(例: “Bracket-1<1>” のような形式)
compName = swComp.Name2
‘ —————————————————-
‘ 例:特定の名前(例: “OptionalPart”)が含まれる部品を制御
‘ —————————————————-
If InStr(compName, “OptionalPart”) > 0 Then
‘ A. まず位置の固定(IsFixed)を解除する
‘ ※固定されたまま抑制しようとすると予期せぬ挙動を防ぐため、先に解除が安全な場合もあります
If swComp.IsFixed() = True Then
swComp.Selected2 False, 0 ‘ 一度選択状態にする
swModel.UnfixComponent
Debug.Print compName & ” の固定を解除しました。”
End If
‘ B. コンポーネントを「抑制(Suppress)」する
‘ 引数: swComponentSuppress (2) = 抑制, swComponentFullyResolved (0) = 完全に解決
Dim status As Long
status = swComp.SetSuppression2(swComponentSuppress)
If status = True Then
Debug.Print compName & ” を抑制しました。”
End If
End If
Next i
‘ 4. 画面を再描画して変更を反映
swModel.EditRebuild
MsgBox “コンポーネントの動的制御が完了しました!”, vbInformation
End Sub
—
4. コードの重要ポイントと「現場の知見」
初心者の方がハマりやすいポイントや、プロが必ず押さえている極意をいくつか解説します。
① `GetComponents(True)` の「True」が持つ意味
`swAssDoc.GetComponents(True)`.
この引数に `True` を渡すと、トップレベルのアセンブリだけでなく、サブアセンブリの中にある深層の部品まですべてフラットに配列として取得してくれます。
大規模アセンブリをくまなくスキャンしたい場合は、この `True` が魔法の杖になります。
② 状態変更後の `EditRebuild`
APIでモデルの構造(抑制状態やフィーチャー)をゴリゴリ書き換えたあとは、SolidWorksの画面側がまだその変更を視覚的・内部的に計算しきっていないことがあります。
処理の最後には必ず `swModel.EditRebuild`(または `ForceRebuild3`)を挟むことで、エラーや表示崩れを防ぐことができます。
③ 抑制(Suppress)と軽量化の本質
パーツを「非表示(Hide)」にするのと、「抑制(Suppress)」するのでは、PCにかかる負荷が天と地ほど違います。
- 非表示: 見えていないだけで、メモリにはパーツのデータがロードされている。
- 抑制: メモリ上からそのパーツのデータをアンロードし、リソースを完全に解放する。
数千パーツあるアセンブリで「使わないオプション部品」を非表示にしても軽くなりません。必ず `SetSuppression2` でメモリから追い出すこと。これが大規模アセンブリ自動化の鉄則です。
—
まとめ
今回は、`IComponent2.IsFixed` と `SetSuppression2` を使ったコンポーネントの動的制御について解説しました。
- アセンブリ内の全パーツは `GetComponents(True)` で一網打尽にできる。
- パーツの軽量化には「非表示」ではなく「抑制(Suppress)」を使う。
- 処理の後は必ずリビルドを入れる。
ここさえ押さえておけば、あなたのアセンブリ自動化マクロは見違えるほど実用的なものになります。ぜひ、お手元の環境で試してみてくださいね。
それでは、次回の高度なSolidWorks VBAでお会いしましょう。良き自動化ライフを!
