【実務・中級編】【中級・実務】CutExtrusion機能における「サーフェスまで」「オフセット」指定時の参照面ロストを防ぐスマート参照管理術 – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAを掌握する極限の知見

こんにちは。大規模なCAD自動化プロジェクトを幾度となく救ってきたチーフアーキテクトの私だ。

日々の業務でSolidWorksのVBAマクロを書き、ワンクリックで3Dモデルを生成することに成功して悦に入っている開発者も多いだろう。しかし、そのマクロが「設計変更(モデルの改修)」の嵐を生き延びられるかどうか、考えたことはあるか?

特に、`CutExtrusion`(押し出しカット)の終端条件として「サーフェスまで(Up To Surface)」「オフセット(Offset)」を指定した際、ベースとなる面がモデルツリーの再構築(Rebuild)によって消滅したり、内部IDが変わり、マクロが突然クラッシュしたという苦い経験は、実務開発者なら誰もが通る道だ。

今回は、この「参照面ロスト」という悪夢を完全に克服し、実務の現場でビクともしない堅牢なコードを書くための「スマート参照管理術」を授けよう。

なぜ従来のコードは設計変更に弱いのか?

多くの開発者は、マクロ記録を取るか、ネットのサンプルをコピペして次のようなコードを書く。

‘ 【アンチパターン】名前や固定インデックスで面を指定する愚行
Dim swFace As ModelDocExtension
‘ 面の名前(あるいはトポロジー上の順序)で選択する
boolstatus = swModel.Extension.SelectByID2(“Face1@Extrude1@Part1.sldprt”, “FACE”, 0, 0, 0, False, 0, Nothing, 0)

‘ サーフェスまでの押し出しカットを実行
boolstatus = swFeatureMgr.FeatureCut3( _
True, False, False, _
swEndCondUpToSurface, 0, 0, 0, _
False, False, False, False, _
0.01, 0.01, False, False, _
False, False, True, False, False)

このアプローチがなぜ実務で破綻するのか。理由は明確だ。
SolidWorksのフィーチャーツリーが再構築されるとき、面やエッジに割り振られる内部ID(Persistent ID / Entity ID)は動的に変動しうる。「Face1」という名前は単なる一時的なラベルに過ぎず、上流でフィーチャが追加・削除された瞬間に、この文字列は全く別の面を指すか、あるいは「ロスト(消失)」してエラーを吐き出す。

プロのエンジニアであれば、名前ではなく「幾何学的特徴(面の位置、法線、属するフィーチャのトポロジー)」を追跡するか、SolidWorksが提供する「永続ID(Persistent Reference)」のメカニズムをコードレベルで制御しなければならない。

堅牢性を極めるための設計思想:スマート参照管理

今回提示するアーキテクチャの核心は以下の3点だ。

1. 名前依存からの脱却: 面の名称ではなく、フィーチャの特定面(例:ボス形状のトップ面、特定のオフセット基準面)をAPIのトラバーサル(走査)によって動的に特定する。
2. 安全なエラーハンドリングとフォールバック: 参照面が万が一消失していた場合、即座に例外を発生させるのではなく、代替の終端条件(寸法指定など)へ安全にフォールバック、またはログを残して処理を中断する。
3. トランザクション的思考: ジオメトリ生成の前後に状態の整合性を確認する。

【プロダクションコード】参照面ロストを防ぐCutExtrusion実装

以下のコードは、特定の基準面(今回は「Cst_RefSurface」という名前を持つサーフェス、あるいは特定のフィーチャから生成された面)を安全に探索し、それを参照してカット&フィルを行う実務レベルのモジュールである。

Option Explicit

‘ SolidWorks定数の定義(必要に応じて参照設定または直値)
Const swEndCondUpToSurface = 1
Const swEndCondOffset = 9
Const swSelectType_FACE = 1

Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swFeatMgr As SldWorks.FeatureManager
Dim targetFace As SldWorks.Face2

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 “このマクロはパーツファイルでのみ実行可能です。”, vbCritical
Exit Sub
End If

Set swFeatMgr = swModel.FeatureManager

‘ 1. 動的に「安全な参照面」を探索する(名前やIDのハードコーディングを避ける)
Set targetFace = GetRobustReferenceFace(swModel, “Target_Cut_Surface”)

If targetFace Is Nothing Then
MsgBox “致命的エラー: ターゲットとなる参照面が見つかりません。モデルが変更された可能性があります。”, vbCritical
Exit Sub
End If

‘ 2. 面を安全に選択状態にする(API経由での参照渡し)
Dim swEntity As SldWorks.Entity
Set swEntity = targetFace

‘ 選択のクリアとターゲット面の選択(Mark = 1 は通常、終端条件や参照面選択で使われる)
swModel.ClearSelection2 True
Dim selectSuccess As Boolean
selectSuccess = swEntity.Select4(False, Nothing)

If Not selectSuccess Then
MsgBox “参照面の選択に失敗しました。”, vbCritical
Exit Sub
End If

‘ 3. 「サーフェスまで」の押し出しカットを実行
‘ ※引数の詳細な仕様はSolidWorks APIヘルプの FeatureCut4 を参照のこと
Dim myFeature As SldWorks.Feature
Set myFeature = swFeatMgr.FeatureCut3( _
sd:=True, _ ‘ 逆方向へカットするか
Flip:=False, _ ‘ 側面のフリップ
Dir:=False, _ ‘ ドラフトの有無
EndCond:=swEndCondUpToSurface, _ ‘ 終端条件:サーフェスまで
D1:=0#, _ ‘ 深度1
D2:=0#, _ ‘ 深度2
DraftAngle1:=0#, _ ‘ ドラフト角度1
DraftAngle2:=0#, _ ‘ ドラフト角度2
RevD1:=False, _ ‘ 深度1逆転
RevD2:=False, _ ‘ 深度2逆転
CutNamespace:=False, _ ‘ アセンブリ用
UseFeatScope:=False, _ ‘ フィーチャースコープ
UseAutoSelect:=True, _ ‘ 自動選択
AssemblyFeatureScope:=False, _
AutoSelectComponent:=False, _
ImportFeature:=False, _
IncludeConstrained:=True, _
CacheGeom:=False, _
TranslateSurface:=False, _
Merge:=False)

If myFeature Is Nothing Then
MsgBox “CutExtrusionの生成に失敗しました。ジオメトリの干渉を確認してください。”, vbCritical
Else
MsgBox “堅牢なカットフィーチャの生成に成功しました。”, vbInformation
swModel.ForceRebuild3 False
End If

End Sub

/

  • 概要: 指定した条件や属性を持つ面を安全に探索する(トポロジー走査関数)
  • ハードコードされた面名に頼らず、フィーチャ名や面の特性から動的にFace2オブジェクトを取得する。

/
Private Function GetRobustReferenceFace(ByVal model As SldWorks.ModelDoc2, ByVal featureNameHint As String) As SldWorks.Face2
Dim swPart As SldWorks.PartDoc
Set swPart = model

Dim bodies As Variant
bodies = swPart.GetBodies2(swAllBodies, False)

If IsEmpty(bodies) Then Exit Function

Dim i As Long, j As Long
Dim body As SldWorks.Body2
Dim faces As Variant
Dim face As SldWorks.Face2
Dim feat As SldWorks.Feature

‘ すべてのボディを走査
For i = LBound(bodies) To UBound(bodies)
Set body = bodies(i)
faces = body.GetFaces()

If Not IsEmpty(faces) Then
For j = LBound(faces) To UBound(faces)
Set face = faces(j)
Set feat = face.GetFeature()

‘ フィーチャ名がヒントに一致するか、あるいは特定の幾何学的条件を満たすか判定
If Not feat Is Nothing Then
If InStr(1, feat.Name, featureNameHint, vbTextCompare) > 0 Then
‘ 最初に見つかった適切な面を返す(実務ではここに法線方向のチェックなどを加えるとさらに堅牢になる)
Set GetRobustReferenceFace = face
Exit Function
End If
End If
Next j
End If
Next i

Set GetRobustReferenceFace = Nothing
End Function

現場で役立つ!データベース・外部ファイル連携時の注意点

実務において、こうした自動化マクロは「Excelからのパラメータ読み込み」や「PDM/ERPシステムからのデータ連携」と組み合わせて使われることが多い。その際、以下の鉄則を忘れてはならない。

1. 外部ID(GUIDや製品コード)の紐付け:
Excel等で管理するパラメータに「どの面の名前・どのフィーチャを基準にするか」を文字列で直書きさせないこと。代わりに、パラメータ側には「基準フィーチャの役割(例:`Top_Mounting_Plane`)」を持たせ、コード側で上記の `GetRobustReferenceFace` のような抽象化関数を挟んで動的に解決する。
2. サイレントモードでのエラーハンドリング:
バッチ処理などでバックグラウンド実行(UI非表示)させる場合、参照面ロストによる `MsgBox` はフリーズの原因になる。必ずログファイル(Text/CSV)への出力、あるいはステータスコードを返す設計にリファクタリングすること。
3. セッションキャッシュの罠:
マクロが連続して複数のファイルを処理する場合、メモリ上のモデル情報(COMオブジェクトの参照)がリークすることがある。処理の区切りごとに変数を `Nothing` に明示的に解放する作法を徹底してほしい。

チーフアーキテクトからの総括

「動けばいいや」で作られたVBAコードは、設計変更という現場の現実の前に、いとも簡単に崩れ去る。
今回紹介した「名前依存の排除」「動的トポロジー走査」「安全な選択コンテキストの構築」というアプローチを取り入れることで、あなたの書くマクロは単なる「おもちゃの自動化スクリプト」から、工場や設計部隊を支える「堅牢なエンジニアリング・アセット」へと昇華する。

保守性に怯える日々から脱却し、真に価値のある自動化アーキテクチャを構築してほしい。健闘を祈る。

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