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

スポンサーリンク

【SolidWorks VBA極限解説】CustomPropertyManager.Delete2で実現する、カスタムプロパティ重複地獄からの完全脱却

業務自動化エンジニアの皆さん、日々のSolidWorksマクロ開発、ご苦労様です。
PDM連携、自動図面生成、BOM(部品表)出力――。業務効率化の要となるプロセスにおいて、パーツやアセンブリの「カスタムプロパティ(メタデータ)」の操作は避けて通れない領域です。

しかし、あなたは何気なくこんなコード書いていませんか?

‘ 駄目な例:古いプロパティの存在を無視してAdd3を叩く愚行
Dim swCustPropMgr As SldWorks.CustomPropertyManager
Set swCustPropMgr = swModel.Extension.CustomPropertyManager(“”)
swCustPropMgr.Add3 “材質”, swCustomInfoText, “SS400”, swCustomPropertyAddOption_DeleteAndAdd

「`swCustomPropertyAddOption_DeleteAndAdd` を使っているから上書きされるはずだ」――そう信じて疑わなかったあなた。現実の現場はどうですか?
気づけば同じ名前のプロパティがコンフィギュレーション別とカスタムタブで二重計上され、BOMには「材質」が文字化けや空白となって乱立し、下流工程のERPやCAMシステムが盛大に爆発する……。この「プロパティ重複地獄」に頭を抱えた夜が一度や二度ではないはずです。

今回は、SolidWorks APIの深層を知り尽くしたチーフアーキテクトの視点から、`CustomPropertyManager.Delete2` を完全に手なづけ、「古いメタデータの確実な消去と重複防止ロジック」を担保する、実務投入レベルの堅牢なコードと設計思想を伝授します。

なぜ `Add` 系メソッド単体では破綻するのか?

SolidWorksのメタデータ構造は、一見シンプルに見えて極めて複雑です。
プロパティは以下の2つのスコープに分かれています。

1. ファイル全体のカスタムプロパティ(Global)
2. コンフィギュレーション固有のプロパティ(Configuration-Specific)

さらに、APIの歴史的経緯から、`Add`、`Add2`、`Add3`、そして各種 `Set` メソッドは、内部のインデックス管理やキャッシュの挙動において、既存の同名キーに対して「スマートな上書き」をしてくれないケースが多々あります。特に、コンフィギュレーション名の大文字・小文字の揺れや、過去のマクロでゴミデータ(空文字列や不正な型定義)が残存している場合、`Add3` のオプションだけでは防衛しきれません。

プロフェッショナルが守るべき鉄則

> 「書き込む前に、まず消す。それも完全な一致確認をもって。」

この原則を具現化するのが、`CustomPropertyManager.Delete2` です。

堅牢なプロパティ操作のアーキテクチャ

実務で耐えうるコードとは、「エラーが出ない」ことではなく、「予期せぬ状態でも自己修復し、確実に意図したデータ構造を作り上げる」ものです。

以下のプロダクションコードは、私が実際のプラント設計・機械装置メーカーの自動化基盤で採用している、極めて安全性の高いカスタムプロパティ設定モジュールです。

プロダクションコード例:安全確実なプロパティ更新関数

Option Explicit


色彩・型番・材質などのメタデータを、重複やゴミを残さずに安全に書き込むプロフェッショナル関数
@param swModel 対象のModelDoc2オブジェクト(Part / Assembly)
@param propName 設定するプロパティ名
@param propValue 設定する値
@param configName 対象コンフィギュレーション名(””を指定した場合はファイル全体=Global)
@return Boolean 成功時はTrue、失敗時はFalse
Public Function SetCustomPropertySafely( _
ByVal swModel As SldWorks.ModelDoc2, _
ByVal propName As String, _
ByVal propValue As String, _
Optional ByVal configName As String = “”) As Boolean

SetCustomPropertySafely = False

If swModel Is Nothing Then Exit Function

Dim swCustPropMgr As SldWorks.CustomPropertyManager
Dim activeConfig As String

‘ 1. CustomPropertyManagerの取得(スコープの分岐)
If configName = “” Then
‘ ファイル全体のカスタムプロパティマネージャーを取得
Set swCustPropMgr = swModel.Extension.CustomPropertyManager(“”)
Else
‘ 特定コンフィギュレーションのカスタムプロパティマネージャーを取得
‘ ※注意: アセンブリやパーツでコンフィギュレーションが存在するか事前に確認すべきだが簡略化
Set swCustPropMgr = swModel.Extension.CustomPropertyManager(configName)
End If

If swCustPropMgr Is Nothing Then Exit Function

‘ 2. 既存プロパティの存在確認と確実な削除 (Delete2の極意)
‘ 既に同名のプロパティが存在するかチェックする
Dim valOut As String
Dim resolvedValOut As String
Dim былValFound As Long

‘ Get6メソッドで値の有無を確認 (戻り値が0以外なら存在する)
#If VBA7 Then
Dim lRet As Long
lRet = swCustPropMgr.Get6(propName, False, valOut, resolvedValOut, False, 0)
#Else
‘ 32bit環境への配慮が必要な場合は適宜キャスト(現代の開発では64bit前提でOK)
Dim lRet As Long
lRet = swCustPropMgr.Get6(propName, False, valOut, resolvedValOut, False, 0)
#End If

‘ すでに存在する場合は、Delete2で完全に抹殺する
‘ これにより、型違いやマルチコンフィギュレーションのゴミデータを完全にクリア
If lRet <> 0 Then
Dim deleteResult As Long
deleteResult = swCustPropMgr.Delete2(propName)

If deleteResult <> swCustomInfoDeleteResult_Successful Then
‘ 削除失敗時のログ出力や例外処理をここに記述
Debug.Print “Warning: プロパティの削除に失敗しました: ” & propName
End If
End If

‘ 3. クリーンな状態への新規追加 (Add3)
‘ 削除が完了しているため、重複の余地はゼロになる
Dim addResult As Long
addResult = swCustPropMgr.Add3(propName, swCustomInfoText, propValue, swCustomPropertyAddOption_Default)

If addResult = swCustomInfoAddResult_Added Then
SetCustomPropertySafely = True
Else
‘ 追加失敗(書き込み禁止属性がついている場合など)
Debug.Print “Error: プロパティの追加に拒絶されました: ” & propName
SetCustomPropertySafely = False
End If

End Function

コードの解説とアーキテクチャの急所

このコードが「なぜ現場でバグを起こさないのか」、その技術的根拠を3点に絞って解説します。

1. スコープ(`””` vs コンフィギュレーション名)の厳密な分離

`CustomPropertyManager` を取得する際、引数に何を指定するかで挙動がガラリと変わります。

  • 引数が空文字 `””`:図面や親アセンブリから参照されやすい「ファイルプロパティ(Custom)」を操作します。
  • 引数にコンフィギュレーション名:そのコンフィギュレーション固有(Configuration-Specific)の数値を操作します。

この2つを混同すると、ファントムプロパティ(親が見ているプロパティと、コンフィギュレーションが見ているプロパティの乖離)が発生します。引数設計をオプション化し、呼び出し側で明確にコントロールさせることが極めて重要です。

2. `Get6` による事前の存在確認とステータス判定

闇雲に `Delete2` を叩くのではなく、`Get6` を用いて「本当にそのキーが存在するか」をポーリングします。SolidWorks APIは、存在しないキーに対する操作で内部エラーフラグを立てることがあるため、「存在を確認してから叩く」という防衛的プログラミングが動作の安定性を劇的に高めます。

3. `Delete2` の戻り値評価

APIの戻り値を無視するプログラマーは、インフラエンジニアで言えば `rm -rf` をノーチェックで走らせるようなものです。`swCustomInfoDeleteResult_Successful` をしっかりとキャッチし、失敗した場合にはイミディエイトウィンドウやログに吐き出すことで、デバッグの迷宮から一瞬で脱出できるよう設計しています。

実務データベース連携・一括処理における注意点

この関数を実務の「Excel一括インポートツール」や「PDMメタデータ同期バッチ」に組み込む際の実践的なアドバイスを最後に贈ります。

1. ファイルアクセスの排他制御(Read-Onlyチェック)
PDMや共有サーバー上のファイルを開く際、他者がチェックアウトしている、あるいはR/Oで開かれている場合、`Add3` や `Delete2` は容赦なく失敗します。`swModel.IsOpenedReadOnly()` を事前に評価し、書き込み権限がないファイルはスキップ・警告するロジックをラップしてください。

2. 変更後の保存とリビルド
プロパティを変更しただけでは、グラフィックス領域やファイルフラグは「未保存(Dirty)」状態になりません(正確にはモデルの変更としてマークされないことがあります)。必要に応じて `swModel.SetSaveFlag()` を明示的に呼ぶか、保存処理を確実に行うフローを組んでください。

3. 大量処理時のメモリリーク対策
数百、数千のパーツをループ処理してプロパティを一括書き換える場合、SolidWorksのComオブジェクトの参照がメモリ上に残り続け、フリーズを引き起こします。ループの単位ごとに `Set swCustPropMgr = Nothing` を行い、不要になったドキュメントは `swApp.CloseDoc` で適切にメモリから解放するガベージマネジメントを意識してください。

まとめ

`CustomPropertyManager.Delete2` は、単なる削除メソッドではありません。
「過去の呪縛を断ち切り、常にクリーンなメタデータ環境を維持する」ための、SolidWorks自動化における剣なのです。

場当たり的なコードでエラーに怯える日々は今日で終わりにしましょう。
堅牢な設計と正しいAPIの作法を身につけ、あなたのチームの業務効率化を次のステージへと引き上げてください。

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