コンフィギュレーションの深淵を制御する:全設定一括図面展開におけるアーキテクチャ設計
設計自動化の現場において、多くのエンジニアが最初に直面する壁は「ループ処理によるリソースの枯渇」である。
単一の部品、あるいは単一のコンフィギュレーションに対して図面を作成するコードを書くのは容易だ。しかし、数百のコンフィギュレーションを持つ複雑なアセンブリに対し、それらを同一図面内の各シート、あるいは一連のビューとして自動展開するタスクとなると、話は別である。単純な `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、そしてユーザーの時間をいかに尊重するかを設計する者である。
「動くことは最低条件であり、安定して動き続けることこそが、真の設計である。」
