こんにちは!SolidWorks自動化の世界へようこそ。
日々、膨大な数のアセンブリやパーツを開き、同じプロパティをポチポチと手入力していませんか?「プロジェクト名が変わったから、すべての部品のカスタムプロパティを書き換えなきゃ……」「うっかり入力を忘れて図面作成時に大慌てした」なんて経験、きっと一度や二度ではないはずです。
今回は、そんな地獄のような手作業をワンクリックで根絶やしにする「トップアセンブリから全子部品へのカスタムプロパティ一括同期システム」の設計図と、実戦でそのまま使えるVBAコードを授けます。
ここをクリアすれば、単なる「マクロの記録の貼り付け屋さん」から、現場を救う「自動化エンジニア」への大きな一歩を踏み出せますよ。温かく、そして妥協のないプロの技を一緒に見ていきましょう!
—
1. なぜ「手作業」や「マクロの記録」では限界なのか?
初学者がまず陥る罠、それは「マクロの記録」に頼ることです。
画面上でパーツを選択し、プロパティタブを開いて文字を入力する……この動作を記録すると、SolidWorksは「どの画面上の、どのパーツか」をガチガチに固定したコード(ハードコーディング)を吐き出します。
しかし、実務のアセンブリは生き物です。
- 部品が追加されたり削除されたりする
- サブアセンブリの中にさらに小さなサブアセンブリがある(階層構造)
これらに対応するには、VBAの「再帰処理(Recursive Processing)」という概念を使い、プログラム自身がアセンブリのツリー構造を上から下へ、まるでツララのように自動で潜っていく仕組みを作る必要があります。
—
2. アーキテクチャの全体像:どうやってデータを伝播させるか?
今回構築するシステムのロジックは非常にシンプルです。
1. 親(トップアセンブリ)の捕獲: 今開いているアセンブリの`CustomPropertyManager`から、同期させたい値(例: 「PROJECT_NAME」「AUTHOR」など)を取得する。
2. 構成部品の列挙: `GetComponents`メソッドを使い、アセンブリ直下にあるすべてのコンポーネント(パーツおよびサブアセンブリ)をリストアップする。
3. 子(コンポーネント)への書き込み: 各コンポーネントの参照先ドキュメント(ModelDoc2)を取り出し、同様に`CustomPropertyManager`を通じてデータを書き込む。
4. 再帰的アプローチ(サブアセンブリ対応): もしリストアップした部品が「サブアセンブリ」だった場合、その中に入っている孫パーツたちにも同じ処理を連鎖させる。
この構造図を頭に思い浮かべながら、次のコードを見ていきましょう。
—
3. 実戦投入可能な最強VBAコード
以下のコードをSolidWorksのVBAエディタ([Alt] + [F11])の標準モジュールに貼り付けてください。
Option Explicit
‘ ==============================================================================
‘ 【メイン処理】トップアセンブリのプロパティを全子部品へ一括伝播する
‘ ==============================================================================
Sub PropSync_MasterTrigger()
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 swAssy As SldWorks.AssemblyDoc
Set swAssy = swModel
‘ 2. 同期したいプロパティ名の定義(必要に応じて変更してください)
Dim targetPropName As String
targetPropName = “PROJECT_NAME”
‘ 3. トップアセンブリから値を取得
Dim swTopCustPropMgr As SldWorks.CustomPropertyManager
Set swTopCustPropMgr = swModel.Extension.CustomPropertyManager(“”)
Dim valOut As String
Dim resolvedValOut As String
Dim wasResolved As Boolean
Dim resultCode As Long
‘ カスタムプロパティの値を取得(存在しない場合は空文字になる)
resultCode = swTopCustPropMgr.Get6(targetPropName, False, valOut, resolvedValOut, wasResolved, 0)
If resolvedValOut = “” Then
MsgBox “トップアセンブリにプロパティ ‘” & targetPropName & “‘ が存在しないか、値が空です。”, vbExclamation, “中断”
Exit Sub
End If
‘ 4. 処理開始の確認
If MsgBox(“トップアセンブリの [” & targetPropName & ” = ” & resolvedValOut & “]” & vbCrLf & _
“を、全ての子部品に伝播・上書きしますか?”, vbYesNo + vbQuestion, “一括同期の確認”) = vbNo Then
Exit Sub
End If
‘ 5. 処理の実行(ルートコンポーネントの取得)
Dim swRootComp As SldWorks.Component2
Set swRootComp = swAssy.GetConfigurationByName(swModel.ConfigurationManager.ActiveConfiguration.Name).GetRootComponent3(True)
If Not swRootComp Is Nothing Then
Call ProcessChildren(swRootComp, targetPropName, resolvedValOut)
End If
‘ 6. 変更を反映するためにアセンブリを再構築
swModel.ForceRebuild3 (False)
MsgBox “カスタムプロパティの同期が完了しました!”, vbInformation, “成功”
End Sub
‘ ==============================================================================
‘ 【再帰処理】子コンポーネントを巡回し、プロパティを書き込むコアロジック
‘ ==============================================================================
Sub ProcessChildren(ByVal swParentComp As SldWorks.Component2, ByVal propName As String, ByVal propValue As String)
Dim vChildren As Variant
vChildren = swParentComp.GetChildren
If IsEmpty(vChildren) Then Exit Sub
Dim i As Long
Dim swChildComp As SldWorks.Component2
Dim swChildModel As SldWorks.ModelDoc2
Dim swChildCustPropMgr As SldWorks.CustomPropertyManager
For i = LBound(vChildren) To UBound(vChildren)
Set swChildComp = vChildren(i)
‘ コンポーネントの参照先ドキュメント(ModelDoc2)を取得
‘ ※ 軽量モード(Lightweight)対策として、必要に応じて解決させる処理を入れるとより堅牢になります
Set swChildModel = swChildComp.GetModelDoc2
If Not swChildModel Is Nothing Then
‘ コンポーネント固有(Configuration-specific)ではなく、ファイル全体のカスタムプロパティを対象とする場合
Set swChildCustPropMgr = swChildModel.Extension.CustomPropertyManager(“”)
‘ プロパティを追加または上書き (Add3引数: Name, Type, Value, OverwriteOptions)
‘ swCustomInfoText = 30 (テキスト型)
‘ swCustomPropertyReplaceValue = 1 (既存があれば上書き)
swChildCustPropMgr.Add3 propName, 30, propValue, 1
‘ もしその子コンポーネントがさらにサブアセンブリなら、さらに奥へ潜る(再帰呼び出し)
If swChildModel.GetType = swDocASSEMBLY Then
Call ProcessChildren(swChildComp, propName, propValue)
End If
End If
Next i
End Sub
—
4. 陥りやすいエラーと、プロが教える「現場の知見」
このコードを実務で動かす際、SolidWorks特有の「罠」にいくつか直面する可能性があります。ここを知っているかどうかが、エンジニアとしての腕の見せ所です。
罠①:軽量モード(Lightweight)の罠
大アセンブリを開いたとき、メモリ節約のために部品が「軽量状態」になっていることがあります。この状態のままだと、`GetModelDoc2` が `Nothing` を返し、プロパティの書き込みに失敗します。
- 対策: 大規模アセンブリを扱う場合は、処理の前にアセンブリ全体を「図解解決(Resolve)」するコード(`swModel.ResolveAllLightWeightComponents`)を挟むのがプロの鉄則です。
罠②:ファイルが「読み取り専用(ReadOnly)」になっている
PDMや共有サーバーで管理されている図面は、他の人が開いていると読み取り専用になり、VBAからの書き込みが弾かれます。
- 対策: `swChildModel.IsReadonly` などのプロパティで事前にチェックし、書き込み可能か判定するエラーハンドリングを実装すると、マクロが途中でクラッシュするのを防げます。
—
5. まとめ
今回は、トップアセンブリから全子部品へカスタムプロパティを一括伝播させるSolidWorks VBAの設計と実装を解説しました。
- マクロの記録の限界を知る
- `CustomPropertyManager` を適切に呼び出す
- 再帰処理を使ってアセンブリのツリー構造を網羅する
この3つをマスターすれば、あなたの設計業務における「単純作業のストレス」は劇的に減り、本当に頭を使うクリエイティブな設計業務に集中できるようになります。
「ここをもっとこうしたい」「こんな応用はできる?」といった疑問があれば、いつでもエンジニア仲間として相談してくださいね。
それでは、快適なSolidWorks自動化ライフを!
