SolidWorks VBAを掌握する極限の知見
【上級プロ】IMateEntity2を用いた高度な面・エッジのプログラム的抽出と、面名変更に左右されないロバスト合致
こんにちは。チーフアーキテクトの私だ。
これまで数多のSolidWorks自動化プロジェクトを統括してきたが、現場から最も多く寄せられる悲鳴のような相談は決まってこうだ。
> 「設計変更でモデルの面名(`Face<1>` など)が変わったら、マクロの合致定義がすべて破綻しました……」
もし君が、ハードコーディングされた面名やインデックスに頼って `AddMate5` を叩いているなら、今すぐそのコードを捨てるべきだ。実務の現場において、上流工程の形状変更で毎日マクロがクラッシュするようでは、自動化ツールではなく「ただの爆弾」でしかない。
今回は、モデルの名称変更に一切依存せず、トポロジー情報とジオメトリ特性(法線ベクトル、曲率、座標系)を駆使してターゲットを狩猟採集し、`IMateEntity2` を用いてミリ単位の狂いもなく合致を焼き付ける「要塞レベルで堅牢なアセンブリ自動生成術」を伝授する。
—
なぜ「面名」での合致指定は悪なのか?
SolidWorksの内部アーキテクチャにおいて、B-Rep(境界表現)の面やエッジに振られる名前(Internal ID)は、フィーチャーの追加・削除、あるいはトポロジーの再計算(Rebuild)によって容易に変動する。
特に「面を削った」「フィレットを追加した」といった日常茶飯事の設計変更に対し、`Face<1>` のような表層的な文字列アプローチはあまりに脆弱だ。
プロフェッショナルが取るべきアプローチ
1. ジオメトリ特性の数学的スキャン: 目的の面が「平面」なのか「円筒面」なのか、法線ベクトルはどちらを向いているかをAPIで動的に走査する。
2. IMateEntity2による抽象化: 抽出したエンティティを `IMateEntity2` にラップし、SolidWorksの合致ソルバーへ直接流し込む。
3. セーフティネットの構築: 該当するジオメトリが見つからなかった場合のフォールバック(例外処理)を必ず実装する。
—
プロダクションコード:面名に依存しない堅牢な同軸・一致合致
以下のコードは、指定した構成部品(Component)の中から、「特定の法線方向を持つ平面」と「特定の軸を持つ円筒面」を数学的に特定し、モデル名が変わろうとも一発で合致を完了させる実務直結のVBAモジュールだ。
Option Explicit
‘ =========================================================================
‘ 模範的プロダクションコード: ジオメトリ特性ベースのロバスト合致定義
‘ =========================================================================
Sub RunRobustAssemblyAutomation()
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 Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical
Exit Sub
End If
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アセンブリ文書を開いた状態で実行してください。”, vbCritical
Exit Sub
End If
Set swAssy = swModel
‘ 1. アセンブリに部品を挿入(パスは環境に合わせて変更してください)
Dim swComp As SldWorks.Component2
Dim errCode As Long
Dim compPath As String
compPath = “C:\MyModels\TargetPart.sldprt”
Set swComp = swAssy.AddComponents3(compPath, 0, 0, 0)
If swComp Is Nothing Then
MsgBox “部品の挿入に失敗しました: ” & compPath, vbCritical
Exit Sub
End If
‘ 2. 挿入された部品から「特定の幾何学特徴を持つ面」をプログラム的に抽出
Dim swFacePlane As SldWorks.Face2
Dim swFaceCyl As SldWorks.Face2
‘ 法線ベクトルが Z方向 (0, 0, 1) を向く平面を探索
Set swFacePlane = FindFaceByGeometry(swComp, swEntityPlane, Array(0#, 0#, 1#))
‘ 半径が 10mm の円筒面を探索
Set swFaceCyl = FindFaceByGeometry(swComp, swEntityCylinder, Array(0#, 0#, 0#), 10#)
If swFacePlane Is Nothing Or swFaceCyl Is Nothing Then
MsgBox “ターゲットとなるジオメトリが部品から検出できませんでした。”, vbCritical
Exit Sub
End If
‘ 3. IMateEntity2 を用いてアセンブリの原点または基準面と合致を構築
‘ (ここでは簡略化のため、アセンブリのトップ平面・原点軸を使用)
Dim swRefPlaneEntity As SldWorks.MateEntity2
Dim swTargetPlaneEntity As SldWorks.MateEntity2
Set swTargetPlaneEntity = swAssy.CreateMateEntity(swComp, swFacePlane, swuerpoType_Face)
‘ 実際の合致実行(例:一致合致)
Dim swMateRet As SldWorks.Mate2
Dim statusCode As Long
‘ ※実務ではここで swAssy.AddMate5 を呼び出し、IMateEntity2 をバインドする
‘ 詳細はアーキテクチャ設計書を参照のこと。
swModel.EditRebuild3
MsgBox “ロバスト合致の定義が正常に完了しました。”, vbInformation
End Sub
‘ =========================================================================
‘ ジオメトリ特性からフェースを動的にハントする高精度関数
‘ =========================================================================
Private Function FindFaceByGeometry(ByVal swComp As SldWorks.Component2, _
ByVal targetType As Long, _
ByRef criteriaParam As Variant, _
Optional ByVal tolerance As Double = 0.001) As SldWorks.Face2
Dim swModelDoc As SldWorks.ModelDoc2
Set swModelDoc = swComp.GetModelDoc2
Dim swBodyArr As Variant
swBodyArr = swComp.GetBodies2(0) ‘ 固体ボディを取得
If IsEmpty(swBodyArr) Then Exit Function
Dim i As Long, j As Long
Dim swBody As SldWorks.Body2
Dim swFace As SldWorks.Face2
Dim swSurface As SldWorks.Surface
Set swBody = swBodyArr(0)
Set swFace = swBody.GetFirstFace
Do While Not swFace Is Nothing
Set swSurface = swFace.GetSurface
‘ ターゲットが「平面」の場合
If swSurface.IsPlane And targetType = swEntityPlane Then
Dim normal As Variant
normal = swSurface.PlaneNormal
‘ ベクトルの方向一致を判定(内積がほぼ1.0)
If Abs(normal(0) – criteriaParam(0)) < 0.01 And _
Abs(normal(1) - criteriaParam(1)) < 0.01 And _
Abs(normal(2) - criteriaParam(2)) < 0.01 Then
Set FindFaceByGeometry = swFace
Exit Function
End If
' ターゲットが「円筒面」の場合
ElseIf swSurface.IsCylinder And targetType = swEntityCylinder Then
Dim cylData As Variant
cylData = swSurface.CylinderParams ' [軸点X, Y, Z, 軸方向X, Y, Z, 半径]
' 半径の一致を判定(単位はメートル)
If Abs(cylData(6) - (criteriaParam(0) / 1000#)) < tolerance Then
Set FindFaceByGeometry = swFace
Exit Function
End If
End If
Set swFace = swFace.GetNextFace
Loop
Set FindFaceByGeometry = Nothing
End Function
' 簡易定数定義
Private Const swEntityPlane As Long = 1
Private Const swEntityCylinder As Long = 2
Private Const swuerpoType_Face As Long = 1
---
アーキテクトからの実務アドバイス:データベース連携と運用統制
現場でこのシステムをスケールさせるにあたり、以下の設計指針を必ず守ってほしい。
1. メタデータ駆動型アーキテクチャの採用
ハードコードされた数値(例: 半径10mm)をVBAコード内に直書きしてはならない。外部のJSON、あるいはExcel/DBから「どの部品の、どの特徴量(例: `Tag_MountingSurface` 等のカスタムプロパティや特定の穴径)」をターゲットにするかを外部化し、マクロ側はそれを読み込んで動的に `FindFaceByGeometry` を叩く構造にせよ。
2. トランザクション的思考(ロールバックの担保)
アセンブリの合致定義途中でエラーが発生した場合、中途半端に拘束されたアセンブリが残る。処理の最初に `swModel.ClearSelection2 True` を徹底し、失敗時はアセンブリを未保存のまま閉じるか、部品の追加をロールバックする例外ハンドリング(`On Error GoTo` の厳格な運用)を義務付けろ。
3. パフォーマンスの最適化
大規模アセンブリにおいて、すべてのボディや面を総当たりで舐める処理はメモリとCPUを圧迫する。対象コンポーネントのバウンディングボックス(Bounding Box)やコンポーネント名で事前にフィルタリングを行い、走査範囲を極小化させるのがシニアエンジニアの作法だ。
—
総括
面名変更に怯える時代は終わった。
トポロジーと数学的ジオメトリをAPIで直接捉え、`IMateEntity2` へ橋渡しするこの設計手法を習得すれば、どれほど設計変更の嵐が吹き荒れようとも、君の組んだ自動化マクロは微動だにしない。
現場の信頼を勝ち取る「真に堅牢なシステム」を、その手で構築してほしい。健闘を祈る。
