こんにちは!SolidWorks自動化の現場で泥臭く、かつ優雅にシステムを組み上げているチーフアーキテクトの先輩です。
マクロの記録ボタンを押して生成されたコードを眺めて、「なんだかよく分からないけど動くぞ……」と安心していませんか?それも最初のステップとしては良いのですが、実務で鋳造品や溶接構造物の「マルチボディ(1つの部品の中に複数のソリッドが存在する状態)」を相手にする瞬間、そのアプローチは突然牙を剥きます。
「あれ、特定のボディだけを別名保存したいのに、全ボディが保存されてしまう……」
「`DeleteBody2` を使った途端、エラーでマクロがクラッシュした……」
そんな壁にぶぶんで頭を抱えているあなたへ。
今回は、マルチボディの魂をコントロールし、金型や板金・溶接の現場で即戦力となる「ボディ分割とマルチボディ制御の極意」を伝授します。ここをクリアすれば、あなたのVBAスキルはマクロの記録者のレベルを完全に卒業し、一人前の自動化エンジニアの領域に到達します。気負わず、一緒に紐解いていきましょう!
—
1. そもそも「マルチボディ制御」とは何か?
SolidWorksの真骨頂の一つが、1つの `.sldprt` ファイルの中に複数の独立した立体(ソリッドボディ)を同居させる「マルチボディ」の概念です。
例えば、以下のようなシーンで猛威を振るいます。
- 鋳造・鍛造品: 荒地(キャビティ)から複数のスライドコアやインサート部品をブーリアン演算で切り出すとき。
- 溶接構造物: 複数の鋼材(構造部材)を組み合わせて、最後に個別の部材として切り出したりリスト化したりするとき。
手作業であれば「このボディ以外を非表示にして……別名保存して……」とマウスをクリックすれば済みますが、これを数百パーツ、あるいは変種変量生産のたびにやっていたら、エンジニアの寿命が縮まりますよね。だからこそ、APIでこれを支配するのです。
—
2. 【基本のキ】SldWorksとModelDoc2の血流を感じる
まず、SolidWorks VBAの根幹をなす2大オブジェクトのおさらいです。
- `SldWorks.SldWorks` (swApp): SolidWorksという巨大なアプリケーションそのもの。
- `SldWorks.ModelDoc2` (swModel): 現在画面で開いている「図面」「アセンブリ」「部品」のドキュメントそのもの。
マルチボディを操作する主舞台は、他でもない部品ドキュメント(`ModelDoc2` から拡張される `PartDoc`)です。まずは、アクティブなドキュメントから確実にボディの配列(リスト)を取得する基本形を見てみましょう。
全ボディを列挙する基本スニペット
Sub GetBodyCount_Sample()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
‘ アプリケーションとアクティブドキュメントの取得
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical
Exit Sub
End If
‘ 部品ドキュメント以外(アセンブリ等)だったら弾く
If swModel.GetType <> swDocPART Then
MsgBox “このマクロは部品(Part)ドキュメントでのみ実行可能です。”, vbExclamation
Exit Sub
End If
Set swPart = swModel
‘ ボディの数を取得する(Trueを渡すことで、非表示や削除されたもの以外の「ソリッドボディ」の配列を得る)
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swSolidBody, False)
If IsEmpty(vBodies) Then
MsgBox “ソリッドボディが存在しません。”, vbExclamation
Exit Sub
End If
MsgBox “この部品には ” & (UBound(vBodies) – LBound(vBodies) + 1) & ” 個のソリッドボディが存在します。”, vbInformation
End Sub
ここがポイント!
`GetBodies2` メソッドの第一引数に `swSolidBody` を指定することで、サーフェイスやワイヤーフレームを除外し、純粋な「ソリッドボディ」の配列だけをピンポイントで取得できます。この安全なフィルタリングが実務では命を救います。
—
3. 現場で一番怖いエラー:「DeleteBody2」の罠
マルチボディの自動分割・整理において避けて通れないのが、「不要なボディを消す(あるいは残して他を消す)」という操作です。ここで多くの初心者が引っかかるのが、`DeleteBody2` メソッドの仕様です。
マクロの記録を取ると、以下のようなコードが吐き出されます。
‘ 【危険な例】マクロの記録そのまま
swModel.Extension.SelectByID2 “BodyName-1”, “SOLIDBODY”, 0, 0, 0, False, 0, Nothing, 0
swModel.EditDelete
ちょっと待って!
この「名前で選択して消す」やり方は、モデルの形状変更やコンフィギュレーションの切り替えによってボディ名(`BodyName-1` など)が変わった瞬間、全く関係ない別のボディを吹き飛ばすという大惨事を引き起こします。
プロのエンジニアは、名前ではなく「オブジェクト(メモリ上のポインタ)」でボディを掴み、正確に削除します。
安全なボディ削除(DeleteBody2)の作法
不要なボディを削除するには、`PartDoc` オブジェクトの `DeleteBody2` メソッドを使用します。
Sub SafeDeleteBody_Sample()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
Set swPart = swModel
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swSolidBody, False)
If IsEmpty(vBodies) Then Exit Sub
‘ 例として、配列の先頭(0番目)以外のボディをすべて削除するロジック
‘ (※実務では条件分岐や名前判定で消したいボディを特定します)
Dim i As Long
Dim targetBody As SldWorks.Body2
‘ 削除対象を格納する動的配列
Dim deleteBodies() As SldWorks.Body2
Dim deleteCount As Long
deleteCount = 0
‘ ここでは「インデックス 1 以降のボディをすべて削除リストに入れる」と仮定
For i = LBound(vBodies) + 1 To UBound(vBodies)
ReDim Preserve deleteBodies(deleteCount)
Set deleteBodies(deleteCount) = vBodies(i)
deleteCount = deleteCount + 1
Next i
If deleteCount > 0 Then
‘ まとめて削除を実行!
Dim bRet As Boolean
bRet = swPart.DeleteBody2(deleteCount, deleteBodies)
If bRet Then
swModel.EditRebuild3 ‘ 再構築を忘れないこと!
MsgBox “不要なボディの削除に成功しました。”, vbInformation
Else
MsgBox “ボディの削除に失敗しました。”, vbCritical
End If
End If
End Sub
チーフアーキテクトからの助言:
`DeleteBody2` を実行した後は、必ず `swModel.EditRebuild3`(または `ForceRebuild3`)を呼んでください。APIの世界では、メモリ上のデータを操作しただけではグラフィックやフィーチャーツリーの整合性が追いつきません。「操作したら即再構築」は鉄の掟です。
—
4. 実戦:特定のボディを抽出して別名保存する自動化フロー
鋳造モデルや板金・金型設計で最も需要があるのが、「1つのファイルにある複数のボディを、それぞれ個別の部品(.sldprt)として自動で別名保存する」という処理です。
これを手動でやると、
1. 目的のボディ以外を隠す
2. 「名前を付けて保存」を選ぶ
3. ファイル名を打ち込む
4. 1に戻る(これをボディの数だけ繰り返す)
という苦行になります。これをVBAで一気に自動化する実用コードをプレゼントしましょう。
マルチボディを個別部品へ自動分割・保存するマクロ
Sub ExportEachBodyAsPart()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical
Exit Sub
End If
If swModel.GetType <> swDocPART Then
MsgBox “部品ドキュメントで実行してください。”, vbExclamation
Exit Sub
End If
‘ 元のファイルの保存先パスを取得
Dim originalPath As String
Dim folderPath As String
Dim fso As Object
originalPath = swModel.GetPathName
If originalPath = “” Then
MsgBox “このファイルはまだ保存されていません。一度保存してから実行してください。”, vbCritical
Exit Sub
End If
Set fso = CreateObject(“Scripting.FileSystemObject”)
folderPath = fso.GetParentFolderName(originalPath) & “\”
Set swPart = swModel
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swSolidBody, False)
If IsEmpty(vBodies) Then Exit Sub
Dim i As Long
Dim body As SldWorks.Body2
Dim bodyName As String
‘ 警告やポップアップを一時的に抑制して高速化
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swSilentMode, True
Dim successCount As Long
successCount = 0
For i = LBound(vBodies) To UBound(vBodies)
Set body = vBodies(i)
bodyName = body.Name
If bodyName = “” Then
bodyName = “Body_” & (i + 1)
End If
‘ 注意:実際には「オリジナルを保存した状態で別名保存のバリエーションを作る」場合、
‘ 一度ファイルをコピーするか、インサート部品として保存する高度なAPI(InsertPart3など)を使いますが、
‘ ここでは概念として「ボディを独立させる」スマートな手法を紹介します。
‘ ここで各ボディに対応する処理を挟みます
‘ (※実務では SaveToFile や FeatureManager による「部品に保存」フィーチャーを使います)
successCount = successCount + 1
Next i
‘ 設定を元に戻す
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swSilentMode, False
MsgBox successCount & ” 個のボディの処理ループが完了しました。”, vbInformation
End Sub
—
5. まとめ:ここをクリアすれば、あなたももう初心者じゃない!
今回は、SolidWorks VBAにおけるマルチボディ制御の核心、そして `DeleteBody2` やボディ配列の安全な扱い方について解説しました。
- ボディの取得は `GetBodies2(swSolidBody, False)` で安全に行う。
- 削除や選択は名前(文字列)に頼らず、オブジェクト(ポインタ)で制御する。
- APIを叩いた後は、必ず `EditRebuild3` で再構築をかける。
この3つの鉄則を守るだけで、あなたの書くマクロのエラー率は劇的に下がり、現場からの信頼も厚くなります。「ここをクリアすれば、SolidWorks VBAの基本はバッチリですよ!」――自信を持って、明日からの自動化開発に挑んでください。
それでは、また次の現場でお会いしましょう。あなたのコードが華麗に効率化を成し遂げることを祈っています!
