アセンブリのロード時間短縮:Large Assembly Mode(大規模アセンブリモード)のVBAプログラムからの強制制御と軽量化
SolidWorks VBAによる大規模アセンブリのバッチ処理において、開発者が最も直面する絶望は「メモリ不足によるフリーズ」と「果てしなく続くI/O待ち」である。
数千点におよぶ部品を持つアセンブリを、GUIの初期設定やデフォルトのセッション状態のまま `OpenDoc6` で開けば、Windowsは瞬く間にスワップ地獄に陥る。実メモリを食いつぶし、CPUがアイドル状態のままディスクアクセスだけが唸りを上げる光景は、マクロ自動化の現場では悪夢でしかない。
本稿では、SolidWorks APIとWindows環境の底を支えるメモリ管理のメカニズムを解体し、プログラムの力で「大規模アセンブリモード(Large Assembly Mode)」および軽量化設定を強制的にねじ込み、バッチ処理のスループットを極限まで引き上げる手法を伝授する。
—
1. 大規模アセンブリモードの正体とAPI制御の限界
SolidWorksの「大規模アセンブリモード」は、単なるUIのトグルスイッチではない。内部的には、以下のようなグラフィックス、再構築、および干渉に関する数十のシステムオプションが一括してオーバーライドされるセッションステートである。
- 自動再構築の無効化
- 軽量部品(Lightweight)としてのロード
- キャビティやコスメティックねじ山の非表示
- グラフィックスの最適化(VBOの制御など)
しかし、VBAから単純にファイルをサイレントオープン(`SwApp.OpenDoc7` など)しただけでは、このモードが完全に適用されない、あるいは環境変数や前回のセッションを引きずって挙動が不安定になるという致命的な問題がある。
真にロバストな自動化システムを構築するには、「SolidWorksを完全なバックグラウンド(Headlessに近い状態)で起動し、ドキュメントオープン前に明示的にシステム環境を最適化する」というアプローチが不可欠となる。
—
2. メモリ最適化とオブジェクトのライフサイクルの鉄則
VBAのガベージコレクション(COM参照カウント方式)は、SolidWorksのドキュメントやコンポーネントのような「超重量級オブジェクト」を扱う際にはあまりにも無力だ。
`Set swModel = Nothing` と書いたところで、背後で動いているC++のCOMサーバー側でメモリが即座に解放されるとは限らない。これを怠ると、2ファイル目、3ファイル目を開いた瞬間にVBAの実行時エラー「メモリ不足です (Out of memory)」が爆誕する。
究極のメモリ解放イディオム
1. 変数スコープの極限までの局所化: ドキュメント変数はプロシージャレベルで完全に使い捨て、処理が終わるごとに即座に `Nothing` を代入する。
2. 強制ガベージコレクション: COMオブジェクトの参照を断ち切った後、`DoEvents` を挟んでメッセージキューを処理し、OSへのメモリ返還を促す。
3. セッションの定期リセット(プロセス再起動): 数百ファイルのバッチ処理を行う場合、VBAからSolidWorksプロセス自体を定期的に再起動(`App.Exit` → `Shell` で再起動)させることが、メモリリークを完全になかったことにする唯一にして最大の現実解である。
—
3. 実装コード:大規模アセンブリ高速ロード・バッチ処理エンジンプリセット
以下のコードは、指定したフォルダ内のアセンブリファイルを強制的に「大規模アセンブリモード」の閾値内に組み込み、軽量化された状態でサイレントロードして処理するためのプロダクション品質のVBAモジュールである。
Option Explicit
‘ ==============================================================================
‘ 大規模アセンブリ高速ロード & バッチ処理エンジン
‘ Architecture Chief Architect tuned.
‘ ==============================================================================
Public Sub ExecuteLargeAssemblyBatch()
Dim swApp As SldWorks.SldWorks
Dim targetDir As String
Dim fileName As String
Dim fso As Object
Dim folder As Object
Dim file As Object
‘ 処理対象ディレクトリ(環境に合わせて変更すること)
targetDir = “C:\LargeAssemblies\”
‘ 1. SolidWorks アプリケーションのインスタンス取得
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical
Exit Sub
End If
‘ 2. バッチ処理前の極限環境最適化(システムプロパティの強制書き換え)
Call OptimizeSessionForMassiveData(swApp)
‘ サイレントモード(画面描画・警告の抑制)を有効化
swApp.UserControl = False
swApp.Visible = False
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set folder = fso.GetFolder(targetDir)
‘ 3. ファイルループによるバッチ実行
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “sldasm” Then
Debug.Print “Processing: ” & file.Name
Call ProcessSingleAssembly(swApp, file.Path)
End If
Next file
‘ 4. セッション復元
swApp.Visible = True
swApp.UserControl = True
MsgBox “バッチ処理が正常に完了しました。”, vbInformation
End Sub
Private Sub OptimizeSessionForMassiveData(ByRef swApp As SldWorks.SldWorks)
On Error Resume Next
‘ 大規模アセンブリモードのしきい値(コンポーネント数)を強制的に「1」に設定し、
‘ どんな小さなアセンブリであっても大規模アセンブリの最適化アルゴリズムを強制適用する
swApp.SetUserPreferenceIntegerValue swLargeAssemblyModeThreshold, 1
‘ 自動再構築をオフ(メモリとCPUの無駄な消費を防ぐ)
swApp.SetUserPreferenceToggleValue swRebuildOnDocumentLoad, False
‘ 軽量部品としてロードする設定を強制
swApp.SetUserPreferenceIntegerValue swOpenAssemblyLightweight, 2 ‘ 2: 常に軽量
‘ 図面やアセンブリのバックグラウンド保存を無効化
swApp.SetUserPreferenceToggleValue swBackgroundSave, False
On Error GoTo 0
End Sub
Private Sub ProcessSingleAssembly(ByRef swApp As SldWorks.SldWorks, ByVal filePath As String)
Dim swModel As SldWorks.ModelDoc2
Dim openError As Long
Dim openWarning As Long
‘ ドキュメントオープンオプションの設定
‘ 軽量(Lightweight)かつ読み取り専用(ReadOnly)で開くことでI/Oとメモリを最小化
Dim loadOptions As Long
loadOptions = swOpenDocOptions_Silent + _
swOpenDocOptions_LoadLightweight + _
swOpenDocOptions_ReadOnly
‘ ドキュメントのオープン
Set swModel = swApp.OpenDoc6(filePath, swDocASSEMBLY, loadOptions, “”, openError, openWarning)
If swModel Is Nothing Then
Debug.Print ” -> 失敗: ファイルを開けませんでしたエラーコード: ” & openError
Exit Sub
End If
‘ —————————————————-
‘ ここにアセンブリに対するカスタム処理(合致検証、軽量化解除、エクスポート等)を記述
‘ 例: 簡易的な再構築なしのドキュメント情報取得など
‘ —————————————————-
‘ 処理終了後の厳格なメモリ解放シーケンス
Dim docTitle As String
docTitle = swModel.GetTitle
‘ ドキュメントを閉じる(変更を破棄してメモリから完全にアンロード)
swApp.CloseDoc docTitle
‘ オブジェクト変数の完全破棄
Set swModel = Nothing
‘ Windowsメッセージキューを処理し、COMメモリの解放を促す
DoEvents
End Sub
—
4. チーフアーキテクトからの実務的忠告
1. `swOpenDocOptions_LoadLightweight` の罠:
軽量モードで開いたアセンブリに対し、特定の合致(Mate)のジオメトリエンティティを直接触るようなAPI(例: `Face2` や `Edge` の正確なトポロジー評価)を呼び出すと、SolidWorksは勝手に裏でフルパーツ(Resolved)へのロードを勝手に開始する。これがメモリリークとスラッシングの元凶となる。軽量モードを維持したまま扱えるAPIの境界線をリファレンスで常に意識すること。
2. アンチウイルスソフトの除外設定:
大規模アセンブリのバッチ処理において、ファイルI/Oのボトルネックの半分以上はSolidWorks本体ではなく、WindowsDefender等のリアルタイムスキャンによるファイルロックにある。自動化対象のワークスペースディレクトリは、必ずセキュリティソフトのスキャン除外リストに登録せよ。
速度こそ正義であり、安定性こそがエンジニアの信頼である。レガシーなVBA環境であっても、APIの挙動とメモリのライフサイクルを完全に掌握していれば、最新のC#製アプリケーションに匹敵する堅牢な自動化基盤を構築することは十分に可能だ。妥協なきコードで、日々の膨大な設計業務を圧倒的なスピードで征服してほしい。
