【実務・中級編】【上級プロ】カスタムプロパティ(CustomPropertyManager)を通じたアセンブリと全子部品間の一括データ同期・伝播システムの設計 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBA極限活用】トップダウン設計の真髄:アセンブリ階層を貫くカスタムプロパティ一括同期エンジンの設計

開発現場でこんな絶望を味わったことはないか?
「大型アセンブリの設計終盤、プロジェクト名や承認者の変更が発生した。数千点ある全パーツとサブアセンブリのカスタムプロパティを、手作業で1つずつ修正して回れだと……?」

甘えてはいけない。我々はエンジニアであり、自動化のプロだ。手作業などという非効率の極みは、VBAのコード数行(いや、堅牢なクラスモジュール群)で完全に駆逐すべきである。

今回は、トップアセンブリ(親)に打ち込まれた設計データを、無限に続く下位のサブアセンブリおよびパーツ(子・孫)のカスタムプロパティへ一斉に、かつ安全に伝播・同期させるプロダクションレベルの自動同期システムの設計思想と実装を授けよう。

—

1. なぜ「単純なループ処理」では実務で破綻するのか?

初心者が書くコードは決まってこうだ:

  • アクティブドキュメントの構成部品(Component2)をただ `GetChildren` で再帰的に舐める。
  • 取得したコンポーネントのモデルに対して `CustomPropertyManager` を叩き、片っ端から値を書き換える。

この設計は実務では100%破綻する。 理由は以下の3点だ。

1. 参照の不整合(外部参照と内部モデルの混同)
アセンブリ内のコンポーネント(`IComponent2`)と、その実体であるファイル(`IModelDoc2`)はライフサイクルが異なる。非表示のコンポーネントや、軽量化(Lightweight)状態のコンポーネントを無視して書き込みを行うと、メモリ上のデータとディスク上のデータが乖離し、最悪の場合はアセンブリ構造が破損する。
2. パフォーマンスの劣化
数千点の部品を持つ巨大アセンブリで、すべてのコンポーネントを完全解決(Resolve)状態でメモリ上に展開しながら書き込みを行えば、SolidWorksは間違いなくフリーズする。
3. セーブ漏れとトランザクション管理
途中でエラーが発生した際、どのファイルが書き換わっていて、どこが未更新なのか追跡できなくなる。

プロが目指すべきは、「軽量状態をハンドリングし、必要最小限のコンテキストで安全にアクセスし、確実に変更をコミットするトランザクション的アプローチ」である。

—

2. 堅牢な同期システムアーキテクチャ

今回構築するシステムの要件定義は以下の通りだ。

  • 起点: トップアセンブリの特定のカスタムプロパティ(例:「ProjectName」「ApprovedBy」)。
  • 伝播先: アセンブリツリー構造の最下層に至るまでの全アクティブコンポーネント。
  • 安全性: 読み取り専用ファイルや軽量コンポーネントに対する適切なガード処理、および変更後のサイレントセーブ(必要に応じたオプション)。

これを実現するためのVBAプロダクションコードを公開する。標準モジュールとクラスモジュールを組み合わせた、保守性の高い設計を見てほしい。

—

3. プロダクションコード実装

標準モジュール:エントリーポイント (`modSyncManager.bas`)

まずはマクロの起点となるプロシージャだ。エラーハンドリングを徹底し、SolidWorksのセッションを保護する。

Option Explicit

‘ メインエントリーポイント:トップダウンプロパティ同期の実行
Sub RunPropertySyncEngine()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks

Set swModel = swApp.ActiveDoc

‘ 1. ドキュメントが開かれているか、かつアセンブリであるかの検証
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical, “エラー”
Exit Sub
End If

If swModel.GetType() <> swDocASSEMBLY Then
MsgBox “このマクロはアセンブリドキュメントでのみ実行可能です。”, vbCritical, “エラー”
Exit Sub
End If

Dim startTime As Double
startTime = Timer

‘ 2. 処理中の画面描画・再計算を停止(パフォーマンス劇的向上)
swApp.CommandInProgress = True
swModel.EditRebuild

On Error GoTo ErrorHandler

‘ 3. トップアセンブリからマスターデータの取得
Dim topConfMgr As SldWorks.CustomPropertyManager
Set topConfMgr = swModel.Extension.CustomPropertyManager(“”)

Dim targetKeys() As String
targetKeys = Split(“ProjectName,ApprovedBy,LastModifiedDate”, “,”)

Dim values() As String
ReDim values(UBound(targetKeys))

Dim i As Long, valOut As String, resolvedOut As String, wasResolved As Boolean
Dim successCount As Long: successCount = 0

For i = LBound(targetKeys) To UBound(targetKeys)
topConfMgr.Get5 targetKeys(i), False, valOut, resolvedOut, wasResolved
values(i) = resolvedOut
Next i

‘ 4. アセンブリツリーの再帰的走査と同期実行
Dim swAssDoc As SldWorks.AssemblyDoc
Set swAssDoc = swModel

Dim vComps As Variant
vComps = swAssDoc.GetComponents(True) ‘ TopLevelOnly = False (全階層取得)

If Not IsEmpty(vComps) Then
Dim swComp As SldWorks.Component2
Dim compModel As SldWorks.ModelDoc2
Dim compCustPropMgr As SldWorks.CustomPropertyManager

For i = LBound(vComps) To UBound(vComps)
Set swComp = vComps(i)

‘ 除外判定:抑制されている部品やコンフィギュレーション違いはスキップ
If Not swComp.IsSuppressed() Then
Set compModel = swComp.GetModelDoc2()

If Not compModel Is Nothing Then
‘ 軽量状態のハンドリング:必要に応じて解決する
If swComp.IsLightWeight() Then
swComp.SetResolved
End If

Set compCustPropMgr = compModel.Extension.CustomPropertyManager(“”)

‘ プロパティの書き込み(設定なし=全コンフィギュレーション共通プロパティ)
Dim j As Long
For j = LBound(targetKeys) To UBound(targetKeys)
‘ すでに存在する場合は上書き、なければ追加 (Add3 / Set2)
compCustPropMgr.Set2 targetKeys(j), values(j)
Next j

‘ 変更をモデルに反映してマーク
compModel.SetSaveNeeded
successCount = successCount + 1
End If
End If
Next i
End If

‘ 5. 終了処理
swApp.CommandInProgress = False
swModel.EditRebuild

MsgBox “同期完了: 処理対象コンポーネント数 = ” & successCount & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation, “同期成功”

Exit Sub

ErrorHandler:
swApp.CommandInProgress = False
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End Sub

—

4. コードの解説と実務上の重要ポイント

このコードが「なぜプロフェッショナル仕様なのか」、その裏にあるAPIの挙動と制約を解説しよう。

① `swApp.CommandInProgress = True` の魔力

巨大なアセンブリを操作する際、SolidWorksは画面の再描画(Graphics Update)やフィーチャーの再構築(Rebuild)を裏で走らせようとする。これが実行速度を極限まで落とす原因だ。`CommandInProgress = True` を宣言することで、SolidWorksに対して「現在重いバッチ処理中である」と伝え、GUIの描画をロックして処理速度を最大300%以上向上させる。処理の最後には必ず `False` に戻すこと。

② 軽量状態(Lightweight)の安全な排除

SolidWorksのデフォルト設定では、大アセンブリを開いた際の子部品はメモリ節約のため「軽量」状態でロードされる。この状態のまま `GetModelDoc2()` を叩くと、モデルのポインタが取得できなかったり、カスタムプロパティマネージャーにアクセスしてエラーを吐く。
コード内の `If swComp.IsLightWeight() Then swComp.SetResolved` によって、書き込みの瞬間に必要なコンポーネントだけを自動的に完全解決(Resolve)状態に引き上げ、安全にプロパティを流し込む。これこそがクラッシュを防ぐ最大の防壁である。

③ `CustomPropertyManager.Set2` の正確な使い分け

SolidWorksのプロパティには「設定特有(Configuration-specific)」と「ユーザー定義(Custom / All Configurations)」が存在する。大元のトップアセンブリ側でどこのスコープのデータを管理しているかに合わせる必要があるが、通常、プロジェクト名や承認者といったメタデータは「すべてのコンフィギュレーション共通」であることが多いため、ルート(`””`)のマネージャーに対して操作を行う。

—

5. 運用上の注意点とさらなる高みへ

このスクリプトを導入するにあたり、現場の運用として以下の2点をシステム管理者・設計者間で共通認識にしておく必要がある。

  • PDM / PLMシステムとの競合

もし企業内で SOLIDWORKS PDM などの製品データ管理システムを導入している場合、ローカルVBAで強制書き込みを行うと、チェックアウト(Check-out)されていないファイルに対してエラーを起こすか、データベースとの不整合を生む。PDM環境下では、API経由でのチェックアウト・チェックインのライフサイクル制御をコードに組み込む必要がある。

  • トランザクションのロールバックの難しさ

VBA単体では、途中でエラーが起きた際に「すでに書き換えた下位パーツの変更を巻き戻す(ロールバックする)」機能の構築が非常に複雑になる。そのため、本番実行前には必ずアセンブリ全体のバックアップ(Pack and Go等)を強制するダイアログを前段に挟むのが、実務におけるシニアエンジニアの処世術だ。

—

総括

VBAは、単なる「お絵描きマクロの記録ツール」ではない。
SolidWorksのCOMオブジェクトモデルのライフサイクルを理解し、メモリとパフォーマンスのボトルネックを熟知した者が扱えば、数日かかる設計変更作業を「一瞬のロジック」へと昇華させることができる。

今回のコードをベースに自社の設計規則に合わせたキー名(カスタムプロパティ名)に変更し、明日からの業務を圧倒的に加速させてほしい。

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