【テクニカル・上級編】【カスタムプロパティ操作】CustomPropertyManager.Delete2を用いた古いメタデータの確実な消去と重複防止ロジック – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAを掌握する極限の知見

【カスタムプロパティ操作】CustomPropertyManager.Delete2を用いた古いメタデータの確実な消去と重複防止ロジック

SolidWorksを用いた大規模な設計自動化や、PDM(製品データ管理)システム、ERPとの連携基盤を構築する際、エンジニアの前に必ず立ちはだかる壁がある。それが「カスタムプロパティの整合性維持」だ。

特に、レガシーなCADデータや、複数の設計者が社内の異なるプロセスで改変を重ねたモデルには、意図しないゴミメタデータや、同名で大文字小文字が異なるゾンビプロパティが蔓延している。これらを無策のままVBAから上書きしようとすると、SolidWorksの内部データベース(Extensionオブジェクト)内で一意性が崩壊し、PDM連携時のメタデータ同期エラーや、図面枠の自動連記トラブルを引き起こす。

今回は、`CustomPropertyManager.Delete2`メソッドを軸に、古いメタデータを完全に消去し、重複を完全に排除する「実務で使える極限のクリーンアップ&書き込みロジック」を公開する。

1. SolidWorksカスタムプロパティの深層:なぜ「上書き」だけでは破綻するのか?

多くの初学者は、プロパティを更新する際にいきなり `Add3` メソッドを叩くか、既存の存在確認を怠ったまま値を代入しようとする。これが実務の現場でシステム障害を誘発する最大の原因である。

SolidWorksのカスタムプロパティマネージャーは、内部的に「設定固有(Configuration-specific)」と「ファイル指定(Custom / 全コンフィギュレーション共通)」の2つの空間を持っている。さらに厄介なことに、APIの仕様上、同一プロパティ名で異なるデータ型の値が混在したり、コンフィギュレーション特有の値とカスタム値が競合することがある。

ここで `Delete2` を適切に使わず、単なる「値の置き換え」を行っていると、以下のような致命的な現象が発生する。

  • ゾンビプロパティの増殖: 古い設定値が隠しデータとして残り続け、ファイルサイズを肥大化させる。
  • 取得値の不安定化: `Get5` や `Get6` で値を取得する際、意図しないコンフィギュレーションの値が優先され、図面と3Dモデルで値が乖離する。

したがって、プロパティの更新は「完全な削除(Delete2) $\rightarrow$ 厳格な新規追加(Add3)」の2ステップを不可分のトランザクションとして実装するのが、シニアアーキテクトの鉄則である。

2. 実装コード:完全防御型プロパティ・マネージャー

以下に、コンフィギュレーション別、およびファイル全体の双方に対応し、確実に古いメタデータをパージした上で安全に値を注入するVBAコードを示す。エラーハンドリングとメモリ(オブジェクト)のライフサイクル管理まで配慮されたプロダクションクオリティのコードだ。

Option Explicit

‘ =================================================================================
‘ módulo: ModPropertyManager
‘ 概要: CustomPropertyManager.Delete2を用いた安全なプロパティ更新エンジン
‘ =================================================================================

Public Enum PropertyScope
swScopeCustom = 0 ‘ ファイル全体のカスタムプロパティ
swScopeConfig = 1 ‘ 現在のアクティブコンフィギュレーション固有
End Enum

Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2

‘ 1. アプリケーションインスタンスの取得
Set swApp = Application.SldWorks
If swApp Is Nothing Then Exit Sub

Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “API Error”
Exit Sub
End If

‘ 2. テストデータの書き込み(ファイル全体スコープ)
Dim targetPropName As String
targetPropName = “Part_Revision”

‘ 古いデータを確実に消去し、新しい値を設定する
Dim success As Boolean
success = SetCustomPropertyRobust(swModel, targetPropName, “Rev.B-01”, swScopeCustom, “”)

If success then
MsgBox “カスタムプロパティの更新が正常に完了しました。”, vbInformation, “Success”
Else
MsgBox “プロパティの更新に失敗しました。イミディエイトウィンドウを確認してください。”, vbCritical, “Error”
End If

‘ オブジェクトの明示的解放(VBAのCOM参照リーク防止)
Set swModel = Nothing
Set swApp = Nothing
End Sub

/

  • 指定されたカスタムプロパティを安全に削除し、再作成(または新規作成)する
  • @param swModel 対象のModelDoc2オブジェクト
  • @param propName プロパティ名
  • @param propValue 設定する値
  • @param scope 適用スコープ (swScopeCustom または swScopeConfig)
  • @param configName コンフィギュレーション名(scopeがswScopeConfigの場合のみ有効。空欄の場合はアクティブ)
  • @return 成功時True

/
Public Function SetCustomPropertyRobust( _
ByVal swModel As SldWorks.ModelDoc2, _
ByVal propName As String, _
ByVal propValue As String, _
ByVal scope As PropertyScope, _
Optional ByVal configName As String = “” _
) As Boolean

SetCustomPropertyRobust = False

If swModel Is Nothing Then Exit Function
If Trim(propName) = “” Then Exit Function

Dim swCustPropMgr As SldWorks.CustomPropertyManager
Dim swExt As SldWorks.ModelDocExtension
Set swExt = swModel.Extension

‘ スコープに応じたCustomPropertyManagerの取得
If scope = swScopeConfig Then
If configName = “” Then
configName = swModel.GetActiveConfiguration.Name
End If
Set swCustPropMgr = swExt.CustomPropertyManager(configName)
Else
‘ “” を指定することでファイル全体のカスタムプロパティマネージャーを取得
Set swCustPropMgr = swExt.CustomPropertyManager(“”)
End If

If swCustPropMgr Is Nothing Then
Debug.Print “Error: CustomPropertyManager could not be retrieved.”
GoTo CleanUp
End If

‘ 【核心】Delete2を用いた古いメタデータの完全消去
‘ 戻り値: 0 = 成功, 1 = プロパティなし(無視してよい), その他 = エラー
Dim deleteResult As Long
deleteResult = swCustPropMgr.Delete2(propName)

If deleteResult > 1 Then
Debug.Print “Warning: Failed to delete property ‘” & propName & “‘. Error code: ” & deleteResult
‘ 致命的なエラーでない限り続行を試みるが、ログに残す
End If

‘ 【核心】Add3を用いた厳格な新規作成
‘ 引数: FieldName, Type (3=Text), Value
Dim addResult As Long
Const swCustomInfoText As Long = 3

addResult = swCustPropMgr.Add3(propName, swCustomInfoText, propValue, swSpecifyConfigurationActionAddOrModify)

If addResult = swCustomInfoAddResult_Added_Successfully Or _
addResult = swCustomInfoAddResult_Changed_Successfully Then
SetCustomPropertyRobust = True
Else
Debug.Print “Error: Failed to add property ‘” & propName & “‘. Result code: ” & addResult
End If

CleanUp:
‘ COMオブジェクトの参照解放(メモリ最適化の鉄則)
Set swCustPropMgr = Nothing
Set swExt = Nothing
End Function

3. チーフアーキテクトが解説するコードの急所とエンジニアリング思想

① `Delete2` の戻り値仕様の正確な把握

多くの開発者は `Delete2` の戻り値を無視する。しかし、SolidWorks API仕様において、このメソッドは「対象が存在しなかった場合」にも特定のステータスを返す。
戻り値が `1`(プロパティが存在しない)の場合は例外ではなく「正常系の通過点」として処理し、無駄なエラーハンドリングに処理を分岐させないのがスマートだ。

② `Add3` と `swSpecifyConfigurationAction` の組み合わせ

古い値を `Delete2` で完全に物理消去しているため、`Add3` を呼ぶ際の動作モードは実質的に「新規追加」となる。しかし、APIの競合を防ぐために `swSpecifyConfigurationActionAddOrModify` を明示的に指定することで、万が一の競合状態(Race Condition)に対しても強靭な耐性を持たせている。

③ COMオブジェクトのライフサイクルとメモリ最適化

VBAランタイムはCOMオブジェクトの参照カウント(Reference Counting)を自動管理している「ように見えて」、実際には背後で強烈なメモリリークを引き起こす。
特にSolidWorksのような重厚長大なCOMサーバーを操作する場合、関数内で取得した `ModelDocExtension` や `CustomPropertyManager` をローカル変数として放置すると、ファイルを開閉するうちにVBAのメモリ空間が肥大化し、最終的に「メモリ不足(Out of Memory)」でSolidWorksごとクラッシュする。
コードの末尾にある `Set swCustPropMgr = Nothing` と `Set swExt = Nothing` は、単なるおまじないではなく、大規模アセンブリ処理時にプロセスを生存させ続けるための生命線である。

4. システム間連携(PDM / ERP)における実務的アドバイス

この `SetCustomPropertyRobust` 関数をベースにして、Excelからのバッチ処理や、外部DBからの夜間一括メタデータ同期バッチを構築する場合、以下の設計指針を必ず守ってほしい。

1. トランザクション的ファイル保存の回避
プロパティを書き換えた後は、必要に応じて `swModel.Save3` を呼び出すことになるが、自動バッチ処理の場合は「変更フラグ(Modified)」の制御に注意すること。意図しない無関係な修正が保存されないよう、処理のスコープを厳格に限定すること。
2. 大文字・小文字の正規化
SolidWorksのカスタムプロパティ名は大文字・小文字を区別しない場合と区別する外部システム(PDM等)の間でトラブルになりやすい。システム全体で `Part_Revision` なのか `PART_REVISION` なのか、必ずアッパーケース等に正規化するラッパーレイヤーを一枚噛ませるべきだ。

プロパティ操作という一見地味な処理であっても、APIの仕様の裏側まで突き詰めて設計されたコードは、10万点規模のアセンブリを扱う現場においてすら、一切の破綻を見せない。妥協のないエンジニアリングを、あなたのVBA環境にも実装してほしい。

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