【テクニカル・上級編】【中級者向け】複数の設定(Configurations)を持つモデルから全設定分の図面ビューを自動展開するVBA – SolidWorks VBA解析バイブル

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

コンフィギュレーションの深淵を制御する:全設定一括図面展開におけるアーキテクチャ設計

設計自動化の現場において、多くのエンジニアが最初に直面する壁は「ループ処理によるリソースの枯渇」である。

単一の部品、あるいは単一のコンフィギュレーションに対して図面を作成するコードを書くのは容易だ。しかし、数百のコンフィギュレーションを持つ複雑なアセンブリに対し、それらを同一図面内の各シート、あるいは一連のビューとして自動展開するタスクとなると、話は別である。単純な `For Each` ループは、メモリリークを引き起こし、SolidWorksのプロセスを不安定化させ、最終的には「応答なし」という名の死を招く。

本稿では、単なる「動くコード」ではない。エンタープライズ環境での運用に耐えうる、メモリ管理とオブジェクトのライフサイクルを徹底的に制御した、極限の自動化手法について詳説する。

1. 概念設計:オブジェクト・ライフサイクルの厳格な管理

SolidWorks APIはCOM(Component Object Model)に基づいている。VBAにおいて、オブジェクト変数がスコープを抜けても、参照カウントがゼロにならない限り、背後のSolidWorksプロセスはメモリ内にそのオブジェクトを保持し続ける。

大量のビューやシートを生成する際、`DrawingDoc` や `View` オブジェクトを適切に解放(`Set obj = Nothing`)しなければ、メモリ使用量は指数関数的に増大し、システムのページファイルへのスワップが発生、パフォーマンスは壊滅的な低下を見せる。

我々が目指すべきは、「最小限の生存期間(Lifetime)を持つオブジェクトの局所化」である。

2. 実装:全設定展開エンジン

以下に、モデルの全コンフィギュレーションを走査し、それぞれに対して新しいシートを作成してビューを配置する、堅牢な実装例を示す。

Option Explicit

' Windows APIの宣言: 画面の描画更新を抑制し、処理速度を向上させ、フリッカーを防ぐ
Private Declare PtrSafe Function LockWindowUpdate Lib "user32" (ByVal hwndLock As LongPtr) Modulo
Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr

''' <summary>
''' モデルの全コンフィギュレーションに対して図面ビューを自動展開する
''' </summary>
Public Sub AutomateAllConfigurationViews()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDrawing As SldWorks.DrawingDoc
    Dim swSheet As SldWorks.Sheet
    Dim swView As SldWorks.View
    Dim vConfigNames As Variant
    Dim i As Long
    Dim configName As String
    Dim viewPos(2) As Double ' X, Y, Z
    
    On Error GoTo ErrorHandler

    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc

    ' 1. 前提条件チェック
    If swModel Is Nothing Then Exit Sub
    If swModel.GetType <> swDocPART And swModel.GetType <> swDocASSEMBLY Then
        MsgBox "モデルファイルを開いてください。", vbCritical
        Exit Sub
    End If
    
    If swModel.GetType <> swDocDRAWING Then
        ' 図面がなければ新規作成するロジックが必要だが、ここでは既存図面を前提とする
        MsgBox "図面ファイル内で実行してください。", vbCritical
        Exit Sub
    End If

    Set swDrawing = swModel
    
    ' 2. Windows APIによる描画ロック(パフォーマンス最適化)
    ' 画面更新を止めることで、描画負荷を劇的に軽減する
    LockWindowUpdate GetDesktopWindow()

    ' 3. コンフィギュレーション一覧の取得
    vConfigNames = swModel.GetConfigurationNames()

    ' 4. メインループ
    For i = LBound(vConfigNames) To UBound(vConfigNames)
        configName = vConfigNames(i)
        
        ' --- シートの生成 ---
        ' 新しいシートを末尾に追加。シート名はコンフィギュレーション名を使用
        ' 引数: テンプレート名, 投影法, 単位系, シート名
        ' ※テンプレートパスは環境に合わせて最適化すること
        swDrawing.NewSheet configName, swIsometric, swUnitMMGS, configName
        Set swSheet = swDrawing.GetCurrentSheet()
        
        ' --- ビューの配置 ---
        ' 座標の設定(mm単位での指定が必要な場合が多い)
        viewPos(0) = 0.1 ' X
        viewPos(1) = 0.1 ' Y
        viewPos(2) = 0
        
        ' ビューの挿入 (モデル, 配置座標, 投影法, 表示形式)
        ' ここで指定するモデルは、現在開いているモデルそのもの
        Set swView = swDrawing.CreateDrawViewFromModelView3(swModel.GetPathName, "*Isometric", viewPos(0), viewPos(1), viewPos(2))
        
        If Not swView Is Nothing Then
            ' --- コンフィギュレーションの紐付け ---
            ' これが最も重要なステップ。ビューに対して特定のコンフィギュレーションを強制する
            swView.ReferencedConfiguration = configName
            
            ' ビューのスケール調整(必要に応じて)
            ' swView.Scale = 0.5 
        End If

        ' --- メモリ管理の極意 ---
        ' ループの各ステップで、使用したオブジェクトを明示的に解放する
        ' これにより、COM参照カウントが適切にデクリメントされる
        Set swView = Nothing
        Set swSheet = Nothing
    Next i

    ' 5. 後処理
    LockWindowUpdate 0 ' 描画ロック解除
    swModel.ForceRebuild3 True
    MsgBox "全コンフィギュレーションの展開が完了しました。", vbInformation

CleanUp:
    ' オブジェクトの明示的な解放
    Set swDrawing = Nothing
    Set swModel = Nothing
    Set swApp = Nothing
    Exit Sub

ErrorHandler:
    LockWindowUpdate 0
    MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical
    Resume CleanUp
End Sub

3. アーキテクトの視点:なぜこのコードは「強い」のか

3.1 Windows APIによる描画制御 (`LockWindowUpdate`)

通常のVBAコードは、APIが呼び出されるたびにSolidWorksのグラフィックス領域を更新しようとする。数千のビューを生成する場合、この「描画待ち」が最大のボトルネックとなる。`LockWindowUpdate` を使用して描画を一時停止させることで、CPUリソースを計算とAPI通信に集中させ、実行時間を劇的に短縮できる。これは、大規模システムを運用するエンジニアにとっての常識である。

3.2 コンフィギュレーションの「強制」

`CreateDrawViewFromModelView3` を呼び出した直後のビューは、多くの場合「デフォルト」または「現在アクティブな設定」を参照している。ここで `swView.ReferencedConfiguration = configName` を実行することこそが、自動化の核心である。このプロパティ操作を怠ると、すべてのビューが同一の設定を表示するという、初歩的かつ致命的なミスを犯すことになる。

3.3 参照カウントとメモリの「掃除」

`Set swView = Nothing` をループ内に記述している点に注目してほしい。
VBAのガベージコレクションは、COMオブジェクトに対してはそれほど積極的ではない。特にSolidWorksのような巨大なアプリケーションをホストしている場合、解放を怠ると、メモリ上に「幽霊オブジェクト」が残り続け、数分後にはSolidWorksがクラッシュする。ループの各イテレーションを「アトミック(不可分)な単位」として扱い、使い終わったリソースを即座に破棄する。これが、レガシーな環境でも安定して動作し続けるための規律である。

4. さらなる高みへ:システム間連携への布石

このコードは、単体で動作するツールに留まらない。
例えば、Excel上の部品リスト(BOM)から特定のコンフィギュレーションだけを抽出して図面化する、あるいはPDM(Product Data Management)から取得したメタデータに基づき、シート名やタイトルブロックを動的に書き換えるといった、上位システムとの連携への拡張性を備えている。

プロフェッショナルな自動化エンジニアとは、単にコードを書く者ではない。そのコードが、実行されるサーバーやクライアントのメモリ、CPU、そしてユーザーの時間をいかに尊重するかを設計する者である。

「動くことは最低条件であり、安定して動き続けることこそが、真の設計である。」

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