【SolidWorks VBA極限活用】3Dモデルのユーザー定義プロパティを表題欄へ完全同期させる実務自動化アーキテクチャ
SolidWorksを用いた設計現場において、3Dモデル(部品・アセンブリ)に紐づく「材質」「質量」「設計者名」「図番」といったユーザー定義プロパティを、2D図面の表題欄(ノートやカスタムプロパティ)へいかに正確かつ高速に同期させるかは、ヒューマンエラーを根絶し上流工程と下流図面をシームレスに繋ぐための生命線である。
世に溢れる初心者向けのVBA解説記事では、`ModelDoc2` や `DrawingDoc` の表面的なメソッドを並べただけの、メモリリークを誘発する脆弱なコードが散見される。
本稿では、シニアエンジニアおよび社内CADインフラの管理者に向けて、オブジェクトのライフサイクルを完全に制御し、パフォーマンスの重みを熟知した者だけが実装できる、真に堅牢なプロパティ動的連動システムの全貌を解説する。
—
1. 根本的アーキテクチャ:なぜ単純なリンクでは実務で破綻するのか?
SolidWorksの標準機能である `$PRPSHEET:` を用いた図面テンプレート側のプロパティ参照は、アセンブリ構造が複雑化したり、コンフィギュレーションが多重にネストしたりすると、意図した親モデルの値を参照できずに空欄になる現象(いわゆる「参照切れ」)が頻発する。
特に、以下のような実務上のハードルが存在する。
- 図面ビューの揺らぎ: 図面に複数のビューが配置されている場合、どのモデルのプロパティを主参照(Master)とすべきか決定論的に指定する必要がある。
- コンフィギュレーション固有のプロパティ: アセンブリの特定コンフィギュレーションにおける質量や材質を拾うには、ビューが指すコンフィギュレーション名(`ReferencedConfiguration`)を明示的にトラバースしなければならない。
- オブジェクトの寿命管理: VBAにおけるCOMオブジェクトの解放漏れは、長時間のバッチ処理や大規模図面の連続生成時にSolidWorks自体のメモリリーク(最悪の場合はプロセス異常終了)を引き起こす。
これらをコードレベルで完全に制御するのが、今回構築するVBAアーキテクチャである。
—
2. 実装コード:堅牢性と速度を極限まで高めた同期モジュール
以下のコードは、アクティブな図面ドキュメントからルートビュー(または選択されたビュー)を特定し、その参照先3Dモデルのカスタムプロパティ(またはコンフィギュレーション固有プロパティ)を取得、図面側の指定ノート(表題欄)へ直接書き込む、あるいはリンク式を動的に構築する実務直結のプロシージャである。
Option Explicit
‘ ==============================================================================
‘ 処理名: SyncModelPropertiesToDrawingTitleBlock
‘ 概要 : 図面ビューから参照3Dモデルを特定し、指定されたカスタムプロパティを
‘ 図面側のノート(表題欄)へ安全かつ高速に同期する。
‘ ==============================================================================
Sub SyncModelPropertiesToDrawingTitleBlock()
Dim swApp As SldWorks.SldWorks
Dim swDraw As SldWorks.DrawingDoc
Dim swSheet As SldWorks.Sheet
Dim swView As SldWorks.View
Dim swModel As SldWorks.ModelDoc2
Dim swModelDocExt As SldWorks.ModelDocExtension
‘ エラーハンドリングとCOMオブジェクトの確実な解放を担保するための初期化
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ 1. アクティブドキュメントの型チェック(図面以外は即座に弾く)
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “API Error”
Exit Sub
End If
If swModel.GetType <> swDocDRAWING Then
MsgBox “このマクロは図面ドキュメント(DrawingDoc)でのみ実行可能です。”, vbCritical, “Type Mismatch”
Exit Sub
End If
Set swDraw = swModel
Set swSheet = swDraw.GetCurrentSheet
‘ 2. シート上の最初の子ビュー(通常はモデルのルートビュー)を取得
‘ ※実務では特定の名前を持つビューや、アクティブなビューを動的に判定するロジックに拡張可能
Dim vViews As Variant
vViews = swSheet.GetViews
If IsEmpty(vViews) Then
MsgBox “図面にビューが配置されていません。”, vbExclamation, “Warning”
Exit Sub
End If
‘ 最初のビューを主参照モデルの取得元とする (vViewsのアレイの0番目はシート名)
Set swView = vViews(0)
Dim swRefModel As SldWorks.ModelDoc2
Set swRefModel = swView.ReferencedDocument
If swRefModel Is Nothing Then
MsgBox “図面ビューに関連付けられた3Dモデルが見つかりません。”, vbCritical, “Reference Error”
Exit Sub
End If
‘ 3. 3Dモデルから取得したいプロパティ群を定義し、図面側へ反映
‘ ここでは例として “Material”, “Weight”, “Designer” を同期対象とする
Dim targetProps(2) As String
targetProps(0) = “Material”
targetProps(1) = “Weight”
targetProps(2) = “Designer”
Dim i As Long
Dim propVal As String
Dim configName As String
configName = swView.ReferencedConfiguration
Set swModelDocExt = swRefModel.Extension
‘ トランザクション処理の開始(パフォーマンス向上とアンドゥスタックの整理)
swModel.Extension.StartCursorUndo
On Error GoTo ErrorHandler
For i = LBound(targetProps) To UBound(targetProps)
propVal = GetCustomPropertyVal(swModelDocExt, configName, targetProps(i))
‘ 取得したプロパティ図面側の対応するノート(表題欄)へ書き込む
‘ 実務ではノートオブジェクトの名称(Annotation名)を特定してテキストを書き換える
Call UpdateDrawingNoteText(swDraw, “TITLE_” & targetProps(i), propVal)
Next i
swModel.Extension.CommitCursorUndo
MsgBox “表題欄プロパティの同期が正常に完了しました。”, vbInformation, “Success”
CleanUp:
‘ 4. メモリリーク防止:オブジェクト変数の明示的解放
Set swModelDocExt = Nothing
Set swRefModel = Nothing
Set swView = Nothing
Set swSheet = Nothing
Set swDraw = Nothing
Set swModel = Nothing
Set swApp = Nothing
Exit Sub
ErrorHandler:
swModel.Extension.AbortCursorUndo
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “Fatal Error”
Resume CleanUp
End Sub
‘ ==============================================================================
‘ 補助関数: カスタムプロパティ(コンフィギュレーション固有対応)の取得
‘ ==============================================================================
Private Function GetCustomPropertyVal(ByRef swExt As SldWorks.ModelDocExtension, ByVal config As String, ByVal propName As String) As String
Dim val As String
Dim resolvedVal As String
Dim wasResolved As Boolean
Dim linkStatus As Long
‘ まずコンフィギュレーション固有のプロパティを狙い、存在しない場合は一般プロパティにフォールバック
Dim swCustPropMgr As SldWorks.CustomPropertyManager
Set swCustPropMgr = swExt.CustomPropertyManager(config)
swCustPropMgr.Get4 propName, False, val, resolvedVal
If resolvedVal = “” And config <> “” Then
‘ コンフィギュレーション名が空、または該当がない場合はグローバル(標準)プロパティを探索
Set swCustPropMgr = swExt.CustomPropertyManager(“”)
swCustPropMgr.Get4 propName, False, val, resolvedVal
End If
GetCustomPropertyVal = IIf(resolvedVal <> “”, resolvedVal, val)
Set swCustPropMgr = Nothing
End Function
‘ ==============================================================================
‘ 補助関数: 指定した名称を持つ図面ノートのテキストを更新
‘ ==============================================================================
Private Sub UpdateDrawingNoteText(ByRef swDrawDoc As SldWorks.DrawingDoc, ByVal noteName As String, ByVal newText As String)
‘ 注記(Note)のトラバース処理をここに実装
‘ 実務においては、NoteオブジェクトのGetName()等で一致するものを探し、
‘ swNote.SetText3() メソッド等を用いてテキストを書き換える。
‘ (※コードの冗長化を防ぐため核心ロジックの骨子を提示)
End Sub
—
3. シニアエンジニアが押さえるべき「メモリ最適化」と「APIの罠」
上記のコードおよび実務システム構築において、以下の3点を見落とすと、数ヶ月稼働した後に「CADが突然フリーズする」「タスクマネージャのメモリ消費量が異常に膨れ上がる」といった致命的な障害に直面する。
① COMオブジェクトの参照解放(`Set ◯◯ = Nothing`)の徹底
VBAのガベージコレクションは非決定的(Deterministicではない)である。特にSolidWorks APIのラッパーオブジェクトは、ループ内やサブルーチンを抜ける際に明示的に `Nothing` を代入して参照カウンターをデクリメントしなければ、内部のC++側ポインタがメモリ上に残留し続ける。
特に `GetViews` などの配列を返すメソッドの要素や、`CustomPropertyManager` のような派生オブジェクトは確実に解放すること。
② コンテキストの不一致によるクラッシュ回避
図面ドキュメントと3Dモデルドキュメントでは、取得できる `CustomPropertyManager` のスコープが異なる。アセンブリの部品レベル(コンポーネント)のプロパティを引き出す必要がある高度な要件では、`Component2::GetModelDoc2` を経由して下位コンポーネントのコンテキストへ潜る必要がある。
今回のサンプルはルートモデルを対象としているが、マルチボディや複雑なアセンブリ構成図面では、ビューが指すコンポーネントのパス(`ComponentPath`)を意識した設計が不可欠である。
③ 処理速度を劇的に改善するトランザクション制御
プロパティの書き換えや図面テキストの更新を大量に行う際、画面の再描画(Redraw)やアンドゥバッファの生成が毎回走ると、実行速度が著しく低下する。
実務レベルのバッチ処理では、`ModelDocExtension::StartCursorUndo` や一時的な画面描画停止(`SwApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllAnnotations, True` など)を組み合わせ、I/OおよびGUIのオーバーヘッドを極限まで削ぎ落とすべきである。
—
4. 総括
SolidWorks VBAによるプロパティ自動連携は、単なる「マクロによる手間の削減」にとどまらない。それは、3Dから2Dへ流れるデータの信頼性を担保し、社内のPLM/PDMシステムやERPとのデータ整合性を維持するための「インフラストラクチャ」である。
安易なテンプレート機能の流用にとどまらず、APIのライフサイクルとオブジェクト構造を完全に支配したVBAコードを構築することこそが、真の業務自動化エンジニアに求められる要件なのである。
