【テクニカル・上級編】【上級プロ向け】図面ドキュメントのオープン・クローズ速度を極限まで高める「軽量モード」制御VBA – SolidWorks VBA解析バイブル

スポンサーリンク
スポンサーリンク

巨大図面を「制圧」する:SolidWorks VBAにおける軽量モード制御とメモリ最適化の極致

大規模なプラント設計や複雑な機械アセンブリを扱うエンジニアにとって、SolidWorksの「図面(Drawing)」の処理速度は、単なる利便性の問題ではない。それは、自動化システムの「生存戦略」そのものである。

数千個のコンポーネントを含むアセンブリの図面を、標準的な `OpenDocument6` で愚直に開き、そのまま処理を行う。そんな実装は、シニアエンジニアの仕事ではない。それはメモリの浪費であり、OSのページファイルへの過度な依存を招き、最終的には「SolidWorksの応答なし」という、自動化プロセスにおける最も忌むべき死を招く。

本稿では、図面ドキュメントのオープン・クローズ速度を極限まで高め、メモリ消費を最小限に抑えるための「軽量モード(Lightweight)制御」と、「Windows APIを用いたメモリ管理」の深淵について解説する。

1. 思考の転換:すべてを「解決(Resolved)」してはならない

一般的な開発者は、図面内のビューが正しく表示されるよう、すべてのモデルを「解決(Resolved)」状態にすることを望む。しかし、データ抽出や属性情報の取得、あるいはシートフォーマットの制御が目的であれば、モデルがフルロードされている必要はない。

図面処理の高速化における鉄則は、「必要な情報(メタデータやジオメトリの構成)だけを、最小のメモリコストで取得する」ことだ。

Lightweight制御の戦略的アプローチ

SolidWorks APIにおいて、図面を開く際の動作を制御するには、ドキュメントを開く「前」にシステム環境(User Preferences)を操作するか、あるいは開いた直後にコンポーネントの状態を強制的に軽量化するアプローチが必要となる。

特に、大量の図面をバッチ処理する場合、以下のプロセスを厳守せよ。
1. システム設定の事前注入: `SetUserPreferenceToggle` を用い、コンポーネントのデフォルトロード設定を「軽量」に変更する。
2. サイレント・オープンの徹底: ダイアログによる割り込みを完全に排除する。
3. 参照モデルの強制軽量化: 図面内のビューが参照しているモデルを、メモリ上に展開される前に軽量状態へ誘導する。

2. 実装:高速図面処理エンジン(VBAアーキテクチャ)

以下に、プロフェッショナルな現場で実装すべき、メモリ効率を極限まで高めた図面オープン・プロセスの雛形を示す。単なるコードの羅列ではない。オブジェクトのライフサイクルを意識した構造である。

' --- Module: DrawingAutomationEngine ---
Option Explicit

' Windows APIの宣言: プロセスのワーキングセット(物理メモリ使用量)を強制的に整理する
' これにより、メモリリークに近い挙動を抑え込み、長時間のバッチ処理を安定させる
Private Declare PtrSafe Function SetProcessWorkingSetSize Lib "kernel32" ( _
    ByVal hProcess As LongPtr, _
    ByVal dwMinimumWorkingSetSize As LongPtr, _
    ByVal dwMaximumWorkingSetSize As LongPtr) As Long

Private Declare PtrSafe Function GetCurrentProcess Lib "kernel32" () As LongPtr

''' <summary>
''' 図面を軽量モードで高速にオープンし、情報を抽出する
''' </summary>
Public Sub FastProcessDrawing(ByVal filePath As String)
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim errors As Long
    Dim warnings As Long
    
    Set swApp = Application.SldWorks
    
    ' 1. 環境の最適化 (Pre-emptive Optimization)
    ' コンポーネントを軽量モードでロードする設定を強制
    ' これにより、OpenDocument6実行時のメモリ爆発を防ぐ
    swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swComponentLoadLightweight, True
    
    ' 2. サイレント・オープン
    ' swOpenDocOptions_Silent (1) を使用し、あらゆる警告ダイアログを抑制
    Set swModel = swApp.OpenDoc6(filePath, swDocDRAWING, swOpenDocOptions_Silent, "", errors, warnings)
    
    If swModel Is Nothing Then
        Debug.Print "Error: Failed to open document. Error code: " & errors
        Exit Sub
    End If
    
    ' 3. ドキュメント・ハンドリング
    Set swDraw = swModel
    
    On Error GoTo CleanUp
    
    ' --- ここに図面操作のロジックを記述 ---
    ' 例: 全シートのプロパティ取得、ビューの配置制御など
    ProcessDrawingContent swDraw
    ' --------------------------------------

CleanUp:
    ' 4. オブジェクトの明示的解放 (Explicit Release)
    ' VBAのGC(ガベージコレクション)を待たず、COM参照カウントを即座に減らす
    ' これができていないと、Closeしたはずのファイルがメモリに残り続ける
    Set swDraw = Nothing
    Set swModel = Nothing
    
    ' 5. ファイルのクローズ
    ' 保存せずに閉じることで、I/O負荷を最小化
    swApp.CloseDoc swModel.GetTitle
    
    ' 6. Windows APIによるメモリの強制整理 (The Nuclear Option)
    ' 長時間のバッチ処理中に、OSレベルでワーキングセットを整理させる
    Call ScrubMemory
    
    Debug.Print "Successfully processed: " & filePath
    Exit Sub

ErrorHandler:
    Debug.Print "Critical Error in " & filePath & ": " & Err.Description
    Resume CleanUp
End Sub

''' <summary>
''' 図面内部のロジック(軽量モデルを前提とした処理)
''' </summary>
Private Sub ProcessDrawingContent(ByVal swDraw As SldWorks.DrawingDoc)
    ' ここでは、モデルをResolvedにする操作は絶対に行わない
    ' 必要なのは、図面の構成情報や、軽量状態のまま取得できるプロパティである
    Dim vSheets As Variant
    vSheets = swDraw.GetSheetNames
    ' ... シート操作 ...
End Sub

''' <summary>
''' Windows APIを用いてプロセスの物理メモリ使用量を整理する
''' </summary>
Private Sub ScrubMemory()
    Dim hProcess As LongPtr
    hProcess = GetCurrentProcess()
    ' 最小・最大を-1に設定することで、OSにメモリの整理を促す
    Call SetProcessWorkingSetSize(hProcess, -1, -1)
End Sub

3. 伝説的アーキテクトの知見:メモリリークとの戦い

オブジェクトの「死」を管理せよ

VBAにおける `Set obj = Nothing` は、あくまで「参照を消す」行為に過ぎない。SolidWorksのような巨大なCOMサーバーにおいては、内部的な参照カウントが複雑に絡み合い、オブジェクトが実質的に「ゾンビ化」することが多々ある。

特に、`SelectionManager` や `View` オブジェクトをループ内で生成した場合、それらを明示的に解放しきれなければ、メモリ消費量は指数関数的に増大する。ループの各イテレーションの終わりに、使用したすべての変数に対して `Nothing` を代入することを、習慣ではなく「義務」として捉えよ。

Windows API `SetProcessWorkingSetSize` の真価

上記のコードに組み込んだ `ScrubMemory` は、レガシーなシステム管理者が好んで使う、いわば「劇薬」だ。
長時間稼働する自動化サーバーにおいて、SolidWorksはどれほど適切に設計されたコードであっても、メモリの断片化(Fragmentation)を避けられない。`SetProcessWorkingSetSize` を呼び出すことで、OSに対して「現在使っていないメモリページを物理RAMからページファイルへ退避させろ」と命令できる。これにより、数千枚の図面を処理しても、メモリ不足でクラッシュするリスクを劇的に低減できる。

ネットワークI/Oのボトルネック

軽量モードの恩恵は、RAMだけでなく、ネットワーク帯域にも及ぶ。大規模なPDM(Product Data Management)環境下では、図面が参照するモデルのフルロードは、ネットワークトラフィックの暴走を意味する。軽量モードによる「必要なデータのみの転送」は、システム全体のパフォーマンスを担保する極めて重要な戦略である。

結論

図面自動化の極致とは、単に「動くコード」を書くことではない。「リソースの消費を予測し、制御下に置くこと」である。

軽量モードを戦略的に活用し、Windows APIによってOSの挙動をコントロールする。この視点を持てたとき、君の書くコードは単なるスクリプトから、堅牢な「エンタープライズ・ソリューション」へと昇華する。

現場からの挑戦を待っている。

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