SolidWorks VBAを掌握する極限の知見
【カスタムプロパティ操作】CustomPropertyManager.Set2を用いた材質・質量情報の外部データベース連携と自動同期
こんにちは。開発プロジェクトの現場において、幾重もの泥臭い自動化要件を突破してきたチーフアーキテクトの私だ。
設計部門と生産管理・調達部門の連携において、最も無駄なリソースが消費される瞬間をご存知か?
それは、「3Dモデルの材質変更や形状改修に伴う、図面枠の質量・材質情報の転記漏れ」であり、手動による外部DBやERPへの二重入力だ。
「図面を直したが、PDMやERP側の質量データが古いまま発注されてしまった」
「材質の表記ゆれ(例:A5052、A5052P、AL5052)せいで、データベースの集計が完全に破綻している」
こうした現場の悲鳴を根絶するため、今回はSolidWorksの物理特性エンジンと`CustomPropertyManager.Set2`を完全に同期させ、外部データベース(またはCSV/中間ファイル)へシームレスにデータを流し込む「プロダクション品質の堅牢な自動化フロー」を伝授する。
中途半端なネット上のリファレンスを写経して「動いた気になっている」状態から抜け出し、メモリリークやAPIの罠を回避するプロの設計思想をここに記す。
—
なぜ、安易なマクロは現場で破綻するのか?(設計思想の解説)
多くの初心者が書くコードは、単に「開いているアクティブドキュメントのプロパティを書き換える」だけの短絡的なものだ。しかし、実務の現場では以下の罠が牙を剥く。
1. 質量(Mass)の計算タイミングの罠
SolidWorksの質量プロパティは、モデルが最後にリビルド(Rebuild)され、かつジオメトリが変更された後に明示的に評価(Evaluate)されないかぎり、古いキャッシュ値を返す。これを怠ると、前回の形状の質量がそのまま外部DBに書き込まれる。
2. コンフィギュレーション(Configuration)の非対称性
パーツには複数コンフィギュレーションが存在し得る。カスタムプロパティには「ファイル全体(指定なし)」と「コンフィギュレーション固有」の2種類がある。これを意識せずに叩くと、アセンブリ側で親の質量を取ったつもりが、子パーツのデフォルトコンフィギュレーションの値を取り違える大惨事になる。
3. `CustomPropertyManager.Set2` の戻り値の無視
このAPIは、書き込み成功時に特定の整数値(`swCustomInfoAddResult` や `swCustomInfoModifyResult`)を返す。これをハンドリングせず、エラーログすら残さないコードは、本番環境で「しれっと書き込みに失敗する」という最悪の挙動を引き起こす。
これらを完全にクリアするアーキテクチャが、今回のソリューションだ。
—
プロダクションコード:自動同期エンジン
以下のコードは、アクティブなSolidWorksパーツから正確な質量と材質を抽出し、カスタムプロパティへ確実に焼き付けた上で、外部データベース(今回は実務性を考慮してネットワーク共有フォルダ上のCSV/ログ出力、およびDB接続のシミュレーション)へ同期する完全版のVBAモジュールである。
Option Explicit
‘ ==============================================================================
‘ 業務自動化プロパティ同期モジュール (Production Grade)
‘ ==============================================================================
Sub SyncPartPropertiesToDatabase()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swCustPropMgr As SldWorks.CustomPropertyManager
Dim swConf As SldWorks.Configuration
Dim currentConfName As String
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ 1. ドキュメントの存在・タイプチェック(パーツのみ対象)
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “致命的エラー”
Exit Sub
End If
If swModel.GetType <> swDocPART Then
MsgBox “このマクロは「パーツ(Part)ファイル」でのみ実行可能です。”, vbExclamation, “対象外ファイル”
Exit Sub
End If
‘ 2. 強制リビルドによるジオメトリと質量キャッシュの最新化
‘ ※大規模アセンブリや複雑なパーツでは若干コストがかかるが、データの正確性のために必須
Dim bRet As Boolean
bRet = swModel.ForceRebuild3(False)
‘ 3. 現在のコンフィギュレーション名の取得と固有プロパティマネージャーの取得
Set swConf = swModel.GetActiveConfiguration
currentConfName = swConf.Name
‘ “SldWorks.ModelDocExtension” を経由してカスタムプロパティマネージャーを取得する(現代の推奨手法)
‘ 引数:True = コンフィギュレーション固有, ConfigName = 対象コンフィギュレーション名
Set swCustPropMgr = swModel.Extension.CustomPropertyManager(currentConfName)
‘ 4. 物理特性(質量・材質)の取得
Dim swMassProp As SldWorks.MassProperty
Set swMassProp = swModel.Extension.CreateMassProperty()
If swMassProp Is Nothing Then
MsgBox “質量プロパティオブジェクトの生成に失敗しました。”, vbCritical, “APIエラー”
Exit Sub
End If
‘ 単位系を標準(KG, MM等)に設定して評価
swMassProp.UseSystemUnits = True
Dim rawMass As Double
rawMass = swMassProp.Mass ‘ 単位はドキュメント設定(通常はkgまたはg)
‘ グラム単位に正規化して小数点以下2桁に丸める(実務要件に合わせる)
Dim massGram As Double
massGram = Round(rawMass 1000, 2) ‘ kg前提の場合。環境に合わせて調整
‘ 材質(Material)の取得
Dim materialName As String
Dim dbName As String
materialName = swModel.GetMaterialName(currentConfName, dbName)
If materialName = “” Then materialName = “未設定”
‘ 5. CustomPropertyManager.Set2 を用いたカスタムプロパティへの書き込み
‘ 戻り値の定数: swCustomInfoAddResult_Successful (1), swCustomInfoModifyResult_Successful (2) など
Dim resultCode As Long
‘ プロパティ名: “MASS”
resultCode = swCustPropMgr.Set2(“MASS”, massGram & ” g”)
Call EvaluatePropertyResult(resultCode, “MASS”)
‘ プロパティ名: “MATERIAL_AUTO”
resultCode = swCustPropMgr.Set2(“MATERIAL_AUTO”, materialName)
Call EvaluatePropertyResult(resultCode, “MATERIAL_AUTO”)
‘ プロパティ名: “UPDATED_DATE” (タイムスタンプの自動付与)
resultCode = swCustPropMgr.Set2(“UPDATED_DATE”, Format(Now, “yyyy-mm-dd HH:nn:ss”))
Call EvaluatePropertyResult(resultCode, “UPDATED_DATE”)
‘ 6. 外部データベース / 連携ストレージへの出力処理
Dim partNumber As String
Dim docPath As String
partNumber = swModel.GetCustomInfoValue(currentConfName, “PartNumber”)
If partNumber = “” Then partNumber = swModel.GetTitle ‘ 代替としてファイル名
docPath = swModel.GetPathName
If ExportToExternalDatabase(partNumber, materialName, massGram, docPath) Then
MsgBox “プロパティの更新および外部DBへの同期が正常に完了しました。”, vbInformation, “完了”
Else
MsgBox “プロパティは更新されましたが、外部DBへの同期中に問題が発生しました。”, vbExclamation, “警告”
End If
End Sub
‘ ==============================================================================
‘ 補助関数: CustomPropertyManager.Set2 の戻り値評価
‘ ==============================================================================
Private Sub EvaluatePropertyResult(ByVal result As Long, ByVal propName As String)
‘ swCustomInfoSetError / Success のハンドリング
Select Case result
Case 0 ‘ swCustomInfoSetResult_NotPresent (新規追加された場合等の挙動による)
‘ SolidWorksのバージョンにより挙動が異なるため、実質的に成功・追加・変更を許容
Case 1, 2 ‘ 成功系
‘ 正常終了
Case Else
Debug.Print “Warning: カスタムプロパティ [” & propName & “] の書き込みにコード ” & result & ” で異常が発生しました。”
End Select
End Sub
‘ ==============================================================================
‘ 外部データベース(シミュレーション:CSV/ODBC連携口)
‘ ==============================================================================
Private Function ExportToExternalDatabase(ByVal partNo As String, ByVal mat As String, ByVal mass As Double, ByVal path As String) As Boolean
On Error GoTo ErrorHandler
Dim fso As Object
Dim ts As Object
Dim logFilePath As String
‘ 実務ではここで ADODB.Connection を使って SQL Server / PostgreSQL 等へ直接 INSERT/UPDATE を行う。
‘ 今回は堅牢性のデモンストレーションとして、共有フォルダのCSVへトランザクションログを吐き出す構成をとる。
logFilePath = “C:\SolidWorks_Data\SyncLog\Part_Property_Sync.csv” ‘ ネットワークパス等に変更可能
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ フォルダが存在しない場合は作成
If Not fso.FolderExists(fso.GetParentFolderName(logFilePath)) Then
fso.CreateFolder fso.GetParentFolderName(logFilePath)
End If
‘ ファイルが存在しない場合はヘッダーを作成
If Not fso.FileExists(logFilePath) Then
Set ts = fso.OpenTextFile(logFilePath, 2, True)
ts.WriteLine “Timestamp,PartNumber,Material,Mass_g,FilePath”
ts.Close
End If
‘ 追記モードでオープン
Set ts = fso.OpenTextFile(logFilePath, 8, False)
ts.WriteLine Format(Now, “yyyy-mm-dd hh:nn:ss”) & “,” & EscapeCsv(partNo) & “,” & EscapeCsv(mat) & “,” & mass & “,” & EscapeCsv(path)
ts.Close
ExportToExternalDatabase = True
Exit Function
ErrorHandler:
Debug.Print “DB Sync Error: ” & Err.Description
ExportToExternalDatabase = False
End Function
‘ CSVインジェクション・カンマ対策のエスケープ関数
Private Function EscapeCsv(ByVal val As String) As String
If InStr(val, “,”) > 0 Or InStr(val, “”””) > 0 Then
EscapeCsv = “””” & Replace(val, “”””, “”””””) & “”””
Else
EscapeCsv = val
End If
End Function
—
現場で必ず直面する「3つの技術的急所」
このコードを実務展開するにあたり、チーフアーキテクトとして押さえておくべきポイントを伝授する。
1. `ModelDocExtension.CustomPropertyManager` の優位性
古いマクロでは `ModelDoc2.CustomInfo` や `ModelDoc2.DeleteCustomInfo2` が使われがちだが、これらはコンフィギュレーションの切り替え忘れやスコープのバグを生みやすい。`Extension.CustomPropertyManager(ConfigName)` を使うことで、操作対象のコンフィギュレーションを完全にコードで制御できる。
2. 外部DB接続への拡張性
コード内の `ExportToExternalDatabase` 関数はCSV出力にしているが、ここを `ADODB.Connection` に書き換えるだけで、社内の基幹ERPやPDM(Enterprise PDM / SOLIDWORKS PDM)のSQLデータベースへ、トランザクションを張った安全なレコード更新が可能になる。
3. エラーハンドリングとログの重要性
バックグラウンドで動く自動化ツールにおいて、エラーでサイレント停止する仕様は「最悪の仕様」だ。`On Error GoTo` による例外キャッチと、`Debug.Print` やファイル出力によるトレースを残す設計が、プロと素人を分ける境界線となる。
結びにかえて
カスタムプロパティの同期は、単なる「文字の代入作業」ではない。
3Dモデルの正確な物理特性を、上流(設計)から下流(製造・調達・管理)へと淀みなく流すための「デジタルスレッド(Digital Thread)の神経網」そのものだ。
このコードをベースに、あなたの現場のワークフローに合わせたカスタムプロパティ名(図面枠連動タグなど)にカスタマイズし、今すぐ手作業という非効率の呪縛から開発チームを解放してほしい。
