バルーンの「番号の乱れ」を根絶せよ:アセンブリツリーとBOMを完全に同期させる設計思想
設計自動化の現場に携わるエンジニアなら、一度は直面したことがあるはずだ。
「自動バルーン配置を実行した結果、図面上の番号が、アセンブリのツリー順(設計者の意図した順序)と全く噛み合っていない」という、あの絶望的な状況を。
標準機能の「自動バルーン」は、多くの場合、空間的な配置や部品番号の昇順で番号を振ろうとする。しかし、実務における図面の「正解」は、常にアセンブリの構成(FeatureManager Design Tree)に基づいている。
もし君が、単に「バルーンを置いて、番号を書き換える」という、力技のスクリプトを書こうとしているなら、今すぐその手を止めてほしい。それは、保守性が皆無で、アセンブリ構成が変わるたびに崩壊する、脆弱な「偽の自動化」だ。
本稿では、プロフェッショナルなエンジニアが取るべき、「データ駆動型」の解決策を伝授する。
1. なぜ「力技」は失敗するのか?:オブジェクトのライフサイクルを理解せよ
多くの初級者が陥る罠は、以下のロジックだ。
1. 図面上のバルーンを取得する
2. ループを回して、バルーンのテキストを一つずつ手動で書き換える
これは、設計思想として致命的な欠陥がある。
SolidWorksにおいて、バルーンに表示される「部品番号(Item Number)」は、図面上のテキストではない。それはBOM(部品表)のインデックス(行番号)と密接に紐付いた動的な参照値だ。
BOMの並び順が変われば、バルーンの番号も自動的に変わる。それなのに、バルーンのテキストを直接書き換えてしまうと、BOMとのリンクが断絶し、設計変更時に図面が「嘘」をつき始める。これは製造現場において、誤部品の取り出しを招く致命的なバグとなる。
プロフェッショナルが進むべきルート
我々が制御すべきは「バルーン」ではない。「BOMのソート順」である。
アセンブリのツリー順を、BOMのソート基準として強制的に流し込む。これこそが、堅牢な設計の正解だ。
2. アーキテクチャ設計:カスタムプロパティによる「順序のインジェクション」
SolidWorksのBOMには「ツリー順に並べる」という直接的なオプションは存在しない。ならば、どうするか?
「ツリーの階層順序を、カスタムプロパティとして各コンポーネントに書き込む」
これが最も美しく、かつ確実な戦略だ。
設計フロー
1. Assembly Traversal: アセンブリをツリー順に再帰的に走査する。
2. Index Injection: 走査した順序に基づき、各コンポーネントに `BOM_ORDER` というカスタムプロパティを書き込む。
3. BOM Re-configuration: 図面内のBOMに対し、「`BOM_ORDER` プロパティを第一優先でソートせよ」という命令を出す。
この設計であれば、たとえ図面が更新されても、BOMのソート基準が「ツリー順の数値」である限り、バルーンの番号は常にツリーと完全に同期し続ける。
3. 実装:プロダクション・クオリティのVBAコード
以下に、このロジックを具現化したコードを示す。単なるコピペ用ではない。エラーハンドリングとオブジェクトの解放を考慮した、実務に耐えうる設計だ。
'**
' Module: Automation_BalloonOrderSync
' Description: アセンブリのツリー順に基づきカスタムプロパティを付与し、
' BOMのソート順を強制的に同期させる。
'**
Option Explicit
Sub SyncBalloonOrderWithTree()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swDraw As SldWorks.DrawingDoc
Dim swView As SldWorks.View
Dim swBomAnn As SldWorks.BomTableAnnotation
Dim swComp As SldWorks.Component2
Dim i As Long
Dim counter As Long
On Error GoTo ErrorHandler
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
' 1. 文脈チェック:アクティブなドキュメントは図面か?
If swModel Is Nothing Then Exit Sub
If swModel.GetType <> swDocDRAWING Then
MsgBox "アセンブリ図面を開いた状態で実行してください。", vbCritical
Exit Sub
End If
Set swDraw = swModel
' 2. 図面からBOMを取得
' 注: 複数のBOMがある場合は、最初のもの、あるいは特定のビューをターゲットにする設計が必要
Set swView = swDraw.GetFirstView ' Sheet View
Set swView = swView.GetNextView ' First Model View
If swView Is Nothing Then
MsgBox "図面内にビューが見つかりません。", vbExclamation
Exit Sub
End If
' BOM注釈の取得を試みる
On Error Resume Next
Set swBomAnn = swView.GetBomTableAnnotation
On Error GoTo ErrorHandler
If swBomAnn Is Nothing Then
MsgBox "指定したビューにBOMが見つかりません。", vbExclamation
Exit Sub
End If
' 3. BOMが参照しているアセンブリモデルを取得
Dim swAssyModel As SldWorks.ModelDoc2
Set swAssyModel = swBomAnn.ModelReference
If swAssyModel Is Nothing Or swAssyModel.GetType <> swDocASSEMBLY Then
MsgBox "BOMがアセンブリを参照していません。", vbCritical
Exit Sub
End If
Set swAssy = swAssyModel
' 4. アセンブリのツリーを走査し、カスタムプロパティ(BOM_ORDER)を注入
' ここでは単純化のため、ルート直下のコンポーネントを対象とするが、
' 本来は再帰関数を用いて全階層を走査すべきである。
Debug.Print "--- Tree Traversal Start ---"
counter = 1
Dim vComps As Variant
vComps = swAssy.GetComponents(False) ' False = Top-level only
If Not IsEmpty(vComps) Then
For i = 0 To UBound(vComps)
Set swComp = vComps(i)
' 各コンポーネントのカスタムプロパティマネージャを取得
Dim swCustPropMgr As SldWorks.CustomPropertyManager
Set swCustPropMgr = swComp.CustomPropertyManager
' インデックスを書き込み (文字列として格納)
' 既存の値を上書きすることで、常に最新のツリー順を維持する
swCustPropMgr.Add3 "BOM_ORDER", swCustomInfoText, CStr(counter), swCustomPropertyReplaceValue
Debug.Print "Component: " & swComp.Name2 & " -> BOM_ORDER: " & counter
counter = counter + 1
Next i
End If
' 5. BOMのソート設定を変更
' 注意: BOMのソート列に "BOM_ORDER" を指定する。
' API経由での詳細なソート列指定は複雑なため、ここでは「再構築」の概念を示す。
' 実務上は、BOMのプロパティでBOM_ORDERを第一ソートキーに設定しておく運用が最も堅牢。
' 図面の更新
swModel.ForceRebuild3 True
MsgBox "同期完了: " & (counter - 1) & " 個のコンポーネントに順序プロパティを注入しました。" & vbCrLf & _
"BOMのソート設定で 'BOM_ORDER' を第一キーに設定してください。", vbInformation
Exit Sub
ErrorHandler:
MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical
End Sub
4. 運用における「極限の知見」:バグを防ぐための3箇条
このコードをプロダクション環境に投入する際、君が守るべき鉄則を教えよう。
① 再帰処理の重みを知れ
上記のコードは簡略化のためトップレベルのコンポーネントのみを対象としている。しかし、サブアセンブリが存在する場合、`swAssy.GetComponents(True)` を用いた再帰的な走査が必要だ。ただし、大規模アセンブリ(数千パーツ)で全パーツにカスタムプロパティを書き込むと、ファイル保存時に顕著なパフォーマンス低下を招く。
「どの階層まで同期が必要か」を設計段階で定義せよ。
② カスタムプロパティの「汚染」を防げ
自動化ツールは、しばしば「ゴミ(不要なプロパティ)」をファイルに残す。
ツールを実行する前に、あるいは実行後に、古い `BOM_ORDER` が残っていないか、あるいは意図しない値になっていないかをチェックするロジック(`swCustPropMgr.Delete`)を検討すべきだ。
③ BOMの「ソート定義」は手動か、APIか
APIでBOMのソート列を動的に変更するのは、SolidWorks APIの中でも非常に扱いにくい領域だ。
最も賢明な運用は、「BOMのテンプレート(または標準設定)」として、あらかじめ `BOM_ORDER` をソートキーに含めたものを用意しておくことだ。ツールは「データの注入」に徹し、「表示の制御」はSolidWorksの標準機能に委ねる。これが、最もバグが少なく、メンテナンスしやすい設計だ。
結言
自動化エンジニアの価値は、「動くコードを書くこと」ではなく、「変化に強いシステムを設計すること」にある。
バルーンの番号を書き換えるだけのコードは、単なる「作業の置き換え」に過ぎない。しかし、データの整合性を保ち、SolidWorksの設計思想(BOMと参照の関係)に基づいたコードを書くことは、「プロセスの変革」である。
常に、「データはどこにあり、誰がその真実を握っているのか?」を自問自答せよ。それが、伝説的なアーキテクトへの第一歩だ。
