【実務・中級編】【ボディ分割とマルチボディ制御】IMachiningOperationsやDeleteBody2を使った鋳造・溶接モデルの自動分割 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBA極限解説】マルチボディ完全制覇:`DeleteBody2`とファイル分割自動化の要諦

開発現場のリーダーである私から、ハッキリと言わせてもらう。
「1つの部品ファイルに複数のソリッドボディを詰め込み、手動で不要なボディを消して別名保存する」――この泥臭い作業を、いつまでエンジニアに手作業でやらせているのか?

鋳造品の荒取り、溶接構造物のサブアセンブリ展開、あるいは樹脂金型のキャビ・コア分割。マルチボディ環境の制御は、SolidWorksマクロ開発において避けて通れない最重要領域だ。

しかし、ネット上に転がっている「適当なAPIを並べただけの脆弱なコード」をそのまま現場に投入すれば、メモリリーク、突然のクラッシュ、そして「なぜか意図しないボディが消えた」という致命的なサイレントエラーの嵐に見舞われることになる。

今回は、SolidWorks APIのオブジェクトライフサイクルを熟知したプロだけが知る、バグを寄せ付けない堅牢なマルチボディ制御と自動分割の極意を授けよう。

1. なぜ「あのコード」は動かなくなるのか?(APIの罠)

マルチボディの制御で最もやりがちで、最も罪深いミス。それは「アクティブな選択状態(SelectionMgr)への過度な依存」だ。

「画面上でボディをクリックして選択し、削除する」――人間がUIで行う操作をそのままVBAで再現しようとしてはならない。APIの世界において、画面の選択状態は非常に不安定であり、ビューの再描画タイミングやフィーチャーの再構築(Rebuild)によって容易にロストする。

堅牢なエンジニアが守るべき3つの鉄則

1. 画面(UI)に頼るな、メモリ(オブジェクト)を直叩きしろ: `Extension.SelectByID2` ではなく、ボディのポインタ(`Body2`オブジェクト)を直接操作・配列化しろ。
2. 削除は `DeleteBody2` を使え: フィーチャーとしての削除ではなく、モデルドキュメントレベルでの確実な非表示・消去アプローチをとれ。
3. エラーハンドリングなきファイル保存は悪: 別名保存(`SaveAs3`)の成否だけでなく、保存前のドキュメント状態を厳密に監視しろ。

2. 実務直結!マルチボディ自動分割・個別保存マクロ

それでは、現場で即座に稼働し、数千回の実行にも耐えうるプロダクションコードを公開する。

このコードは、1つの部品ファイル内に存在するすべてのソリッドボディを走査し、「1つのボディを残して他のすべてを削除し、指定フォルダへ別名保存する」という処理を、元ファイルを汚すことなく(インメモリでの安全な復元を考慮して)高速に実行する。

Option Explicit

‘ =================================================================================
‘ 専門家向けプロダクションコード:マルチボディ自動分割・個別保存ツール
‘ 前提条件:アクティブドキュメントがマルチボディの部品(PartDoc)であること
‘ =================================================================================
Sub Main_AutoSplitMultiBody()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc

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)」ドキュメントでのみ実行可能です。”, vbCritical, “型不一致エラー”
Exit Sub
End If

‘ 編集中の変更が失われないよう、保存確認を推奨
If swModel.GetPathName = “” Then
MsgBox “一度も保存されていないファイルです。先に名前を付けて保存してください。”, vbExclamation, “中断”
Exit Sub
End If

‘ 2. 出力先ディレクトリの指定(実務ではINIファイルやDBから動的取得を推奨)
Const OUTPUT_DIR As String = “C:\Work\OutputBodies\”
If Dir(OUTPUT_DIR, vbDirectory) = “” Then
MkDir OUTPUT_DIR
End If

‘ 3. 処理の高速化と安定化(画面描画・イベントの抑制)
swApp.Visible = False
swModel.LockRefresh = True

Dim lErrors As Long
Dim lWarnings As Long
Dim originalPath As String
Dim originalTitle As String

originalPath = swModel.GetPathName
originalTitle = swModel.GetTitle

On Error GoTo ErrorHandler

Set swPart = swModel

‘ ボディ配列の取得(True = ソリッドボディのみ)
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swSolidBody, False)

If IsEmpty(vBodies) Then
MsgBox “対象となるソリッドボディが存在しません。”, vbExclamation, “警告”
GoTo Finally
End If

Dim bodyCount As Long
bodyCount = UBound(vBodies) – LBound(vBodies) + 1

If bodyCount <= 1 Then MsgBox "ボディが1つしか存在しません。分割対象外です。", vbExclamation, "警告" GoTo Finally End If Dim i As Long Dim j As Long Dim swBody As SldWorks.Body2 Dim targetBodies() As SldWorks.Body2 ' 4. メインループ:各ボディを独立させて別名保存 For i = 0 To bodyCount - 1 ' 元のファイルを汚さないため、毎回オリジナルを開き直す、 ' もしくはコピーに対して処理を行うのが鉄則。 ' ここではメモリ上で安全に処理するため、一度閉じて開き直すアプローチをとる。 If i > 0 Then
‘ 2回目以降は一度変更を破棄して開き直す
swApp.CloseDoc swModel.GetTitle
Set swModel = swApp.OpenDoc6(originalPath, swDocPART, swOpenDocOptions_Silent, “”, lErrors, lWarnings)
Set swPart = swModel
vBodies = swPart.GetBodies2(swSolidBody, False)
End If

‘ 削除対象のボディリストを作成
Dim deleteList() As SldWorks.Body2
Dim deleteCount As Long
deleteCount = 0

Dim currentTargetBodyName As String
currentTargetBodyName = “”

For j = 0 To bodyCount – 1
Set swBody = vBodies(j)
If j = i Then
currentTargetBodyName = swBody.Name
Else
‘ 削除リストに追加
ReDim Preserve deleteList(deleteCount)
Set deleteList(deleteCount) = swBody
deleteCount = deleteCount + 1
End If
Next j

‘ DeleteBody2 APIによる確実な一括削除
If deleteCount > 0 Then
Dim swFeatMngr As SldWorks.FeatureManager
Set swFeatMngr = swModel.FeatureManager

‘ DeleteBody2の引数に配列を渡し、フィーチャーとして削除を実行
Dim success As Boolean
success = swPart.DeleteBody2(deleteCount, deleteList)

If Not success Then
Err.Raise 9999, “DeleteBody2”, “ボディの削除に失敗しました: ” & currentTargetBodyName
End If
End If

‘ モデルの強制再構築
swModel.ForceRebuild3 False

‘ 別名保存の実行
Dim savePath As String
savePath = OUTPUT_DIR & currentTargetBodyName & “.sldprt”

‘ SaveAs3(FileName, Version, Options)
‘ swSaveAsOptions_Silent : ダイアログを出さずにサイレント保存
‘ swSaveAsOptions_Copy : コピーとして保存(元の参照を維持)
Dim saveSuccess As Boolean
saveSuccess = swModel.Extension.SaveAs3(savePath, 0, swSaveAsOptions_Silent, Nothing, Nothing, lErrors, lWarnings)

If Not saveSuccess Then
Err.Raise 9998, “SaveAs3”, “ファイルの保存に失敗しました: ” & savePath
End If

Debug.Print “出力完了: ” & savePath
Next i

Finally:
‘ 5. クリーンアップ処理(確実なリソース解放とUI復元)
If Not swModel Is Nothing Then
‘ 最終状態としてオリジナルを開き直しておく
swApp.CloseDoc swModel.GetTitle
swApp.OpenDoc6 originalPath, swDocPART, swOpenDocOptions_Silent, “”, lErrors, lWarnings
End If

swModel.LockRefresh = False
swApp.Visible = True
MsgBox “すべてのボディの分割・保存が正常に完了しました。”, vbInformation, “完了”
Exit Sub

ErrorHandler:
‘ 異常系ハンドリング
swModel.LockRefresh = False
swApp.Visible = True
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的エラー”

‘ セーフティクローズ
On Error Resume Next
If Not swModel Is Nothing Then
swApp.CloseDoc swModel.GetTitle
swApp.OpenDoc6 originalPath, swDocPART, swOpenDocOptions_Silent, “”, lErrors, lWarnings
End If
End Sub

3. チーフアーキテクトが教える「実務連携の極意」

このコードをそのまま社内ニッチなツールとして展開するだけでは、真のプロフェッショナルとは言えない。外部システムやデータベース(DB)、Pdm(Product Data Management)と連携させる際の「プロの知見」を授ける。

① 命名規則の統制とデータベース連携

コード内では `swBody.Name` をそのままファイル名に使用しているが、実際の現場では「部品番号_Rev_ボディ名」といった厳格なコーディングルールが存在する。

  • 対策: ボディ名に不正文字(`\`、`/`、`:`など)が含まれている場合、VBA側で正規表現や置換関数(`Replace`)を用いてサニタイジング(無害化)する処理を必ず挟むこと。
  • DB連携: 分割したボディのファイルパスと、元のアセンブリ情報をSQL ServerやSQLite、あるいはExcel管理台帳に自動インサートするログ出力機能を、`Finally`ブロックの手前に組み込むのがアーキテクトの作法だ。

② 大規模アセンブリ・マルチボディでのメモリ管理

鋳造モデルや複雑な配管・溶接構造物では、1つのボディあたりの面数が数千〜数万に及ぶ。ループ内でドキュメントの開閉を繰り返すと、VBAのガベージコレクションが追いつかず、メモリリークを起こすことがある。

  • 対策: ループの節目で `DoEvents` を挟み、Windowsメッセージキューを処理させつつ、オブジェクト変数を明示的に `Nothing` に解放する(例: `Set swBody = Nothing`)ことを徹底せよ。

終わりに:自動化は「設計」で決まる

VBAはレガシーな言語だと言われることがある。しかし、裏側で動いている SolidWorks COM API は、現代の超高速CADエンジンそのものだ。
APIのライフサイクルを理解し、メモリとドキュメントの状態を完全に支配下に置いたコードを書けば、手作業で何時間もかかっていた金型・鋳造モデルの分割作業を、わずか数秒のバックグラウンド処理へと昇華させることができる。

「動けばいい」のフェーズはもう終わりだ。
堅牢で、美しく、保守性の高いコードで、あなたのチームの生産性を圧倒的に引き上げたまえ。

タイトルとURLをコピーしました