こんにちは!SolidWorksの自動化ライフ、楽しんでいますか?
マクロの記録から一歩踏み出し、「よし、社内のアセンブリ自動チェックツールや、自動合致マクロを作ろう!」と意気込んで実行した瞬間……数千点の部品を読み込んだところでSolidWorksが完全にフリーズ。タスクマネージャーを見るとメモリ使用率がグングン上昇し、最終的に「メモリ不足」で強制終了(クラッシュ)してしまった——。
大規模アセンブリ(メガ・アセンブリ)を扱い始めると、誰もが一度はこの「メモリの壁」にぶつかります。
でも、安心してください!これはあなたのコードの書き方が悪いのではなく、SolidWorksが内部でパーツのデータをどうメモリに展開しているかを知らないだけなんです。ここをクリアすれば、数千点・数万点規模の巨大モデルでも、驚くほど軽快かつ安全に動くプロフェッショナルなマクロが書けるようになりますよ。
今回は、現場のチーフエンジニアが現場で実践している「ライトウェイト(Lightweight)モードの動的制御とメモリ最適化術」を、基礎から優しく紐解いていきます。
—
1. なぜ巨大アセンブリでVBAが止まるのか?「メモリの仕組み」を知る
まずは、SolidWorksがアセンブリを開くときの3つの状態をおさらいしておきましょう。
【完全解凍 (Resolved)】
[フィーチャー履歴] + [ソリッド形状・B-Rep] + [グラフィックス]
⇒ メモリ消費:特大(すべてのジオメトリ情報が展開される)
【ライトウェイト (Lightweight)】
[グラフィックス] + [最低限のインターフェース情報]
⇒ メモリ消費:極小(フィーチャー履歴や詳細幾何はメモリに載らない)
【抑制 (Suppressed)】
メモリ展開なし(計算から完全に除外)
通常、手動で作業しているときはSolidWorksが裏でよしなに軽量化してくれています。しかし、VBAマクロから無邪気に部品(`Component2` オブジェクト)の面(Face)やエッジ(Edge)を取得しようとしたり、合致(Mate)を追加しようとすると、SolidWorksは「あ、このパーツの完全な情報が必要なんだな!」と判断し、パーツを勝手に「完全解凍(Resolved)」してしまいます。
数千個のパーツが次々と完全解凍されていくと、マシンのメモリ(RAM)はあっという間に枯渇します。
プロフェッショナルのアプローチはこうです。
> 「開くときは全体をライトウェイトで超高速に読み込み、処理が必要なコンポーネントだけをピンポイントで一時的に完全解凍し、処理が終わったら即座にメモリを解放する」
これを「オンデマンド・ロード(On-demand Loading)」と呼びます。
—
2. 実践:VBAでライトウェイトを動的に制御するコア技術
ライトウェイトの切り替えには、SolidWorks APIの `Component2.SetSuppression2` メソッドを使用します。
引数に渡す定数は以下の通りです(`swComponentSuppressionState_e` 列挙型):
- `swComponentLightweight` (1):ライトウェイト状態
- `swComponentFullyResolved` (2):完全解凍状態
- `swComponentSuppressed` (0):抑制状態
【実戦コード】指定パーツだけを解凍して処理し、元に戻すテンプレート
以下のコードは、大規模アセンブリを開いた状態で、特定の部品だけを安全に解凍し、面情報を取得・合致などの処理を行ってから再びライトウェイトに戻す実践的なプロシージャです。
Option Explicit
‘ ==============================================================================
‘ 大規模アセンブリ向け:コンポーネントのオンデマンド解凍・軽量化テンプレート
‘ ==============================================================================
Sub ProcessComponentOptimized()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swRootComp As SldWorks.Component2
Dim vChildren As Variant
Dim swChildComp As SldWorks.Component2
Dim i As Long
‘ SolidWorksアプリケーションのインスタンスを取得
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ ドキュメントが開かれていない、またはアセンブリでない場合は終了
If swModel Is Nothing Then
MsgBox “アセンブリドキュメントを開いてから実行してください。”, vbExclamation, “エラー”
Exit Sub
End If
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アクティブなドキュメントがアセンブリではありません。”, vbExclamation, “エラー”
Exit Sub
End If
Set swAssy = swModel
‘ ————————————————————————-
‘ 画面描画とモデル再構築を一時停止(処理速度を劇的に向上させる黄金の定石)
‘ ————————————————————————-
swModel.FeatureManager.EnableFeatureTree = False ‘ FeatureTreeの更新を停止
Dim modView As SldWorks.ModelView
Set modView = swModel.ActiveView
modView.EnableGraphicsUpdate = False ‘ グラフィックスの再描画を停止
On Error GoTo ErrorHandler
‘ ルート(最上位)コンポーネントから直下の部品群を取得
Dim swConfig As SldWorks.Configuration
Set swConfig = swModel.GetActiveConfiguration
Set swRootComp = swConfig.GetRootComponent3(True)
vChildren = swRootComp.GetChildren
If Not IsEmpty(vChildren) Then
For i = LBound(vChildren) To UBound(vChildren)
Set swChildComp = vChildren(i)
‘ 例として、名前に「BRACKET」を含むパーツだけを処理対象とする
If InStr(1, UCase(swChildComp.Name2), “BRACKET”) > 0 Then
‘ 1. 現在の状態を保存
Dim originalState As Long
originalState = swChildComp.GetSuppression2()
‘ 2. ライトウェイト状態なら一時的に「完全解凍」する
If originalState = swComponentLightweight Then
‘ 第2引数:swComponentFullyResolved (2)
‘ 第3引数:0(このコンポーネントのみに適用)
swChildComp.SetSuppression2 swComponentFullyResolved, 0, Empty
End If
‘ ————————————————————-
‘ 【ここに目的の処理を記述】
‘ 例:ボディや面の取得、寸法チェック、合致参照の作成など
‘ ————————————————————-
DoHeavyGeometryWork swChildComp
‘ 3. 処理が終わったら元の状態(ライトウェイト)へ戻す
If originalState = swComponentLightweight Then
swChildComp.SetSuppression2 swComponentLightweight, 0, Empty
End If
End If
‘ メモリリーク防止:ループごとに個別オブジェクトへの参照を明示的に解放
Set swChildComp = Nothing
Next i
End If
CleanUp:
‘ ————————————————————————-
‘ 停止していた画面描画とツリー表示を必ず元に戻す
‘ ————————————————————————-
If Not modView Is Nothing Then modView.EnableGraphicsUpdate = True
If Not swModel Is Nothing Then swModel.FeatureManager.EnableFeatureTree = True
‘ 画面を最新化
swModel.GraphicsRedraw2
MsgBox “処理が安全に完了しました!”, vbInformation, “完了”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
‘ ジオメトリにアクセスするダミープロシージャ
Private Sub DoHeavyGeometryWork(ByRef swComp As SldWorks.Component2)
‘ 解凍されているため、モデルドキュメントやボディへのアクセスが可能
Dim swCompModel As SldWorks.ModelDoc2
Set swCompModel = swComp.GetModelDoc2
If Not swCompModel Is Nothing Then
‘ ここでFaceやEdgeの探索処理を行う
Debug.Print “アクセス成功: ” & swComp.Name2 & ” (Part: ” & swCompModel.GetTitle & “)”
End If
Set swCompModel = Nothing
End Sub
—
3. アセンブリを開く段階から勝負は決まっている(DocumentSpecification)
既存のアセンブリをVBAで開く際、`swApp.OpenDoc6` をそのまま使うと、思わぬモードで開かれて膨大な時間がかかることがあります。
大規模アセンブリをプログラムで開く際は、`DocumentSpecification` インターフェースを使い、明示的に「ライトウェイトモードで開く」指定を行いましょう。
‘ 大規模アセンブリをライトウェイトモードで高速に開くプロの技法
Sub OpenLargeAssemblyLightweight()
Dim swApp As SldWorks.SldWorks
Dim swDocSpec As SldWorks.DocumentSpecification
Dim swModel As SldWorks.ModelDoc2
Dim filePath As String
Set swApp = Application.SldWorks
filePath = “C:\Projects\MegaAssembly.SLDASM”
‘ DocumentSpecificationオブジェクトを初期化
Set swDocSpec = swApp.GetOpenDocSpec(filePath)
‘ ライトウェイト(Lightweight)モードを強制指定
swDocSpec.LightWeight = True
‘ 読み取り専用で開く(変更不要な場合はメモリ消費とロックを防ぐために必須)
swDocSpec.ReadOnly = True
‘ 非表示で開く場合は Silent = True に設定可能
swDocSpec.Silent = False
‘ 指定した構成でドキュメントを開く
Set swModel = swApp.OpenDoc7(swDocSpec)
If swDocSpec.Error <> 0 Then
MsgBox “ドキュメントのオープンに失敗しました。Error code: ” & swDocSpec.Error, vbCritical
Exit Sub
End If
Debug.Print “高速オープン完了: ” & swModel.GetTitle
End Sub
—
4. 先輩エンジニアが教える「陥りやすい3つの罠」
大規模アセンブリの自動化でバグに悩まされないために、絶対に覚えておきたいポイントを3つまとめました。
① `GetModelDoc2` が `Nothing` を返す罠
ライトウェイト状態のコンポーネントに対して `swComp.GetModelDoc2` を呼び出すと、戻り値は `Nothing` になります。
初心者が一番ハマるポイントです。「コードは合っているのに部品のタイトルやフィーチャーが取れない!」という時は、必ずコンポーネントが解凍されているか確認してください。
② 解凍状態の戻し忘れ
ループ処理の中でコンポーネントを解凍したままループを回し続けると、パーツが次々と解凍されたまま蓄積し、結果として全体を解凍したのと変わらない状態になります。「処理したら即ライトウェイトに戻す」を徹底しましょう。
③ オブジェクト変数の解放漏れ(メモリリーク)
VBAは参照カウント方式のガベージコレクションを持っています。しかし、SolidWorksのCOMオブジェクト(特に巨大アセンブリの階層ツリー)をループ内で大量に生成し、`Set obj = Nothing` を怠ると、メモリ上にゴミが残り続け、処理速度がみるみる低下します。
使い終わったオブジェクトは、ループの終端で必ず `Nothing` に代入する癖をつけておくと安全です。
—
まとめ:ワンランク上の自動化エンジニアへ
今回の要点を振り返りましょう。
1. 大規模アセンブリは「全体をライトウェイトで開き、部分的に解凍する」が鉄則
2. `swComp.SetSuppression2` で必要なパーツのみオンデマンドにロード・アンロードする
3. 処理中は `EnableGraphicsUpdate = False` で描画負荷を徹底的に削る
4. ライトウェイト状態では `GetModelDoc2` は使えないことを理解する
このメモリ管理の勘所さえ押さえてしまえば、1,000点を超えるような複雑なアセンブリでも、クラッシュ知らずで安定して高速動作するツールが作れるようになります。
まずは身近にある中規模のアセンブリで、コンポーネントの状態がサクサク切り替わる様子を体感してみてください。ここをクリアできれば、SolidWorks VBAの基本と実践はバッチリですよ!応援しています!
