アセンブリの「外形寸法」を支配せよ:SolidWorks APIでバウンディングボックスを抽出する極意
設計現場において、「アセンブリに含まれる全パーツの外形寸法をリスト化せよ」という指示は、梱包設計や搬送レイアウト検討の現場で頻繁に発生する。しかし、これを手作業で行うのは愚策だ。
SolidWorks APIを使えば、数千のパーツがあろうとも数分で正確なリストが手に入る。だが、単に「コードを動かす」ことと「実務に耐えうる堅牢なツールを作る」ことの間には、深い溝がある。
今回は、単なるサンプルコードの羅列ではない、「メモリ管理を意識し、複雑なアセンブリにも耐えうる」プロフェッショナルな設計手法を伝授する。
—
1. なぜバウンディングボックス抽出は「重い」のか?
SolidWorksのAPIで `GetBox` を叩く際、多くの初心者が陥る罠がある。それは、「コンポーネントをいちいち開いて(Suppress解除して)処理する」という非効率な実装だ。
巨大なアセンブリでこれをやると、メモリは食い尽くされ、SolidWorksはフリーズする。我々が目指すべきは、「コンポーネントの参照を正しく管理し、必要最小限のアクセスで情報を吸い上げる」ことだ。
実務で守るべき3つの鉄則
1. ModelViewの更新を止める: `swApp.Visible = False` や `ModelDoc2.Visible = False` を使うのではなく、`swApp.UserControl = False` 等でUI更新を抑制し、パフォーマンスを最大化せよ。
2. 参照の解放を忘れるな: VBAではCOMオブジェクトが残りやすい。`Set swComp = Nothing` を徹底し、メモリリークを未然に防ぐ。
3. エラーハンドリング: 非表示の構成部品や、そもそもソリッドボディを持たない部品(スケッチのみの部品など)に遭遇した際、コードが即死しない設計が必要だ。
—
2. 実装コード:堅牢なバウンディングボックス抽出エンジン
以下のコードは、アクティブなアセンブリ内の全パーツを再帰的に走査し、各パーツの「X, Y, Z方向の最大サイズ」をイミディエイトウィンドウに出力する。Excelへの書き出しは、この結果を受け取って最後に一括で行うのが定石だ。
Option Explicit
‘ メインプロシージャ
Public Sub ExportBoundingBoxes()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Or swModel.GetType <> swDocASSEMBLY Then
MsgBox “アセンブリを開いて実行してください。”
Exit Sub
End If
‘ パフォーマンス向上のため再構築を抑制
swApp.UserControl = False
‘ 再帰的に全構成部品を走査
TraverseComponents swModel.GetComponents(False)
swApp.UserControl = True
MsgBox “抽出完了”
End Sub
‘ 構成部品を再帰的にトラバース
Private Sub TraverseComponents(comps As Variant)
Dim i As Long
Dim swComp As SldWorks.Component2
Dim swPart As SldWorks.ModelDoc2
Dim vBox As Variant
If IsEmpty(comps) Then Exit Sub
For i = LBound(comps) To UBound(comps)
Set swComp = comps(i)
‘ サブアセンブリの場合は再帰呼出し
If swComp.GetChildrenCount > 0 Then
TraverseComponents swComp.GetChildren
End If
‘ パーツのみを対象にする
If Not swComp.IsSuppressed Then
Set swPart = swComp.GetModelDoc2
If Not swPart Is Nothing Then
If swPart.GetType = swDocPART Then
‘ バウンディングボックス取得 (単位はメートル)
vBox = swPart.GetPartBox(True)
‘ 結果の表示(実際にはここで配列やCollectionに格納してExcelへ渡す)
Debug.Print swComp.Name2 & “: ” & _
Format((vBox(1) – vBox(0)) 1000, “0.00”) & “mm x ” & _
Format((vBox(3) – vBox(2)) 1000, “0.00”) & “mm x ” & _
Format((vBox(5) – vBox(4)) 1000, “0.00”) & “mm”
End If
End If
End If
Set swComp = Nothing
Next i
End Sub
—
3. 開発者としての更なる高みへ
このコードを「動かして終わり」にしないために、以下の視点を加えてほしい。
① 単位系の考慮
`GetPartBox` はメートル法で値を返す。実務ではミリメートル変換が必須だが、ここをハードコーディングせず、定数として管理することで保守性を担保せよ。
② Excelとの疎結合
上記のコードをクラスモジュール化し、出力先を `Scripting.Dictionary` などのオブジェクトとして持たせる設計を推奨する。そうすれば、出力先がExcelであろうが、JSONファイルであろうが、将来的な仕様変更に柔軟に対応できる。
③ なぜ「GetPartBox」なのか
SolidWorks APIには `GetBox` も存在するが、パーツ単体の外形を知るには `GetPartBox` が最も適している。ただし、コンフィギュレーションによっては外形が変化する場合があるため、「どのコンフィギュレーションがアクティブになっているか」を事前にチェックするロジックを組み込むと、さらに信頼性が増す。
—
結論:自動化は「設計の一部」である
業務自動化ツールを作ることは、単なるコーディングではない。「設計者が手作業でやっている判断のプロセスを、コードとして記述し直すこと」だ。
バウンディングボックスの抽出一つをとっても、構成部品の抑制状態やサブアセンブリの階層構造を意識した設計を行えば、あなたのツールは「壊れにくい」資産となる。
次にあなたがこのツールを拡張するなら、次は「重心位置の算出」や「部品名の抽出によるBOM自動生成」に挑戦してみるといい。SolidWorks APIの世界は、あなたの設計業務を劇的に変える可能性を秘めている。
さあ、エディタを開け。そして、手作業という名の無駄をコードで駆逐せよ。
