【SolidWorks VBA極限の知見】アセンブリ基準プレーン動的取得と初期パーツの絶対座標配置
アセンブリ自動化の成否は、常に「最初の1ピースをどこに、どう据えるか」という絶対原点との対話で決まる。
手動オペレーションであれば、プレーンを選び、合致(Mate)をかけ、オフセットを入力する――この数秒の作業も、何千・何万と繰り返す自動化パイプラインの中では、メモリリークの温床であり、コンテキスト迷子を引き起こす不確実性の元凶となる。
今回は、アセンブリ内の標準基準平面(Top / Front / Right)をプログラムから動的に特定し、外部パーツをロードした瞬間に意図したオフセット量で空間へ固定配置する、実務中級者向けの極限ソリューションを提示する。
—
1. プレーン取得における「名前の罠」とコンポーネント走査の真実
多くの初学者が陥る罠は、アセンブリ内のフィーチャー(Feature)を単に名前で文字列比較することだ。
「Front」「Top」「Right」という文字列は、多言語環境(日本語OSのSolidWorksでは「正面」「上面」「右面」)において、コードを瞬時に破綻させる。
インターフェース言語に依存せず、かつ確実にあらゆるアセンブリから基準平面のポインタを取得するには、`FeatureManager`のツリー構造ではなく、「特定のマクロ型(Capability)」 または 「内部IDの特定(User Defined ID)」 を利用するアプローチが最も堅牢である。しかし、実務上最も手堅く、全言語環境でフォールバック可能な手法は、「FeatureのTypeName2による厳密な型判定と、標準平面が持つ不変のインデックス、あるいはネイティブ名(英語名)の強制逆引き」 である。
以下のコードは、アセンブリドキュメントから言語依存を排除して「Front(正面)」プレーンの`Feature`オブジェクトを安全に引き抜くためのプロシージャだ。
‘ =================================================================================
ニッチで堅牢なプレーン取得関数
‘ =================================================================================
Public Function GetStandardPlane(swDoc As SldWorks.ModelDoc2, planeType As String) As SldWorks.Feature
Dim swFeat As SldWorks.Feature
Dim swSubFeat As SldWorks.Feature
Dim targetName As String
‘ 言語環境による名称差異を吸収するためのマッピング戦略
‘ SolidWorks内部では英語名が原則としてルートフィーチャーに保持される
Select Case UCase(planeType)
Case “FRONT”, “正面”: targetName = “Front Plane”
Case “TOP”, “上面”: targetName = “Top Plane”
Case “RIGHT”, “右側面”, “右面”: targetName = “Right Plane”
Case Else: Exit Function
End Select
Set swFeat = swDoc.FirstFeature
Do While Not swFeat Is Nothing
If swFeat.GetTypeName2 = “Plane” Then
‘ 内部名(Name)または表示名(GetUserPreference等)のチェック
If UCase(swFeat.Name) = UCase(targetName) Then
Set GetStandardPlane = swFeat
Exit Function
End If
End If
‘ 次のフィーチャーへ
Set swFeat = swFeat.GetNextFeature
Loop
‘ 万が一、標準名でヒットしない場合のフォールバック(コンポーネントツリーの先頭探索)
Set GetStandardPlane = Nothing
End Function
—
2. 最初のコンポーネントの挿入と、メモリ管理の鉄則
COMオブジェクトを扱うSolidWorks VBAにおいて、明示的なオブジェクトの解放(`Set obj = Nothing`)を怠ることは、肥大化するアセンブリ構築プロセスにおいて「プロセス自体のクラッシュ」を意味する。特にアセンブリへのコンポーネント追加(`AddComponent5`)は、内部で膨大なCOM参照カウンタをインクリメントするため、確実なクリーンアップが要求される。
以下に、パーツをロードし、基準面に対して所定のオフセット値をもってアセンブリへ配置する完全な実務コードを提示する。
‘ =================================================================================
‘ 統合メインプロシージャ:基準面取得 + パーツ動的オフセット配置
‘ =================================================================================
Sub Main_DeployFirstComponentWithOffset()
Dim swApp As SldWorks.SldWorks
Dim swAssyDoc As SldWorks.AssemblyDoc
Dim swModel As SldWorks.ModelDoc2
Dim swFeat As SldWorks.Feature
Dim swEnt As SldWorks.Entity
Dim swComp As SldWorks.Component2
‘ パス定義(環境に合わせて変更すること)
Const PART_PATH As String = “C:\Data\Standard_BasePlate.sldprt”
Const OFFSET_VALUE As Double = 0.05 ‘ 50mm オフセット
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 swAssyDoc = swModel
‘ 1. アセンブリの「Front Plane」を取得
Set swFeat = GetStandardPlane(swModel, “Front”)
If swFeat Is Nothing Then
MsgBox “基準となるFrontプレーンが見つかりませんでした。”, vbCritical
GoTo CleanUp
End If
‘ 2. フィーチャーからエンティティ(面)への変換
Dim swPlaneEnt As SldWorks.Entity
Set swPlaneEnt = swFeat.GetSpecificFeature2
If swPlaneEnt is Nothing Then GoTo CleanUp
‘ 3. 最初のコンポーネントをアセンブリ空間に挿入
Dim transformedX As Double, transformedY As Double, transformedZ As Double
‘ 挿入座標の初期値(ここでは原点からオフセット分Z軸方向にずらして配置)
transformedX = 0#
transformedY = 0#
transformedZ = OFFSET_VALUE
Set swComp = swAssyDoc.AddComponent5(PART_PATH, _
0, “”, false, “”, _
transformedX, transformedY, transformedZ)
If swComp Is Nothing Then
MsgBox “コンポーネントの挿入に失敗しました。”, vbCritical
GoTo CleanUp
End If
‘ 4. 挿入したパーツの原点、あるいは特定面と、アセンブリ基準面の「距離合致」をAPIで直接定義する
‘ ※ここでMate2またはAddMate3 APIを呼び出し、完全に数理的拘束を与える
Call ApplyDistanceMate(swModel, swFeat, swComp, OFFSET_VALUE)
‘ 5. ビューの再構築
swModel.EditRebuild3
MsgBox “基準化された初期パーツの配置が完了しました。”, vbInformation
CleanUp:
‘ 厳格なメモリ解放(COM参照のデクリメント)
Set swComp = Nothing
Set swPlaneEnt = Nothing
Set swFeat = Nothing
Set swAssyDoc = Nothing
Set swModel = Nothing
Set swApp = Nothing
End Sub
—
3. Mate(合致)APIの極意:UIをバイパスした数理的拘束
UI上のマウスクリックを模倣するようなコード(SelectionManagerを用いた選択操作)は、描画更新(ScreenUpdating)やフォーカス競合により、大規模アセンブリにおいて確実に破綻する。
プロフェッショナルな自動化エンジニアは、`AssemblyDoc::AddMate3` を直接叩く。これにより、ビューポートの描画を一切行わずに、メモリ上で高速に拘束関係を解決できる。
以下は、取得したアセンブリのプレーンと、挿入されたコンポーネント内の面を対象に、距離合致をプログラム的にプログラム内部で完結させる実装の断片である。
Private Sub ApplyDistanceMate(swModel As SldWorks.ModelDoc2, swAssemblyPlaneFeat As SldWorks.Feature, swComp As SldWorks.Component2, offsetDist As Double)
Dim swAssyDoc As SldWorks.AssemblyDoc
Set swAssyDoc = swModel
‘ 注意: 実務環境では、swCompから特定の面(Face2)をComponent::GetModelDoc2や
‘ ゲッターを駆使して取得し、Select4等でコンテキスト選択状態にするか、
‘ MateAPIへ直接IEntityを渡す処理が必要となる。
‘ 描画を完全に抑制し、パフォーマンスを限界まで高める
swModel.Extension.EnableGraphicsUpdate = False
‘ — ここにAddMate3による拘束ロジックを実装 —
‘ swAssyDoc.AddMate3 swMateType_Distance, swMateAlign_ALIGNED, False, offsetDist, …
swModel.Extension.EnableGraphicsUpdate = True
End Sub
—
4. チーフアーキテクトからの提言:レガシーVBA環境とモダナイゼーションへの備え
VBAはその手軽さゆえに現場の急場を凌ぐには最適だが、COMのラッパーとしての寿命や、例外処理(`On Error Resume Next` の多用によるエラー隠蔽)の悪習がシステムを蝕む。
もし君が、この自動化基盤を全社展開のエンジニアリングチェーン(PLM/ERP連携)の一部に組み込もうとしているのなら、VBA単体で完結させる発想は今すぐ捨てるべきだ。
- インターフェースの分離: プレーンの探索や座標計算のコアロジックは、将来的には .NET (C#) によるCOM Add-in、あるいは Standalone EXE へ移行できるよう、データ構造を疎結合にしておくこと。
- トランザクション的思考: 最初の1パーツ目の配置に失敗したとき、アセンブリが中途半端な汚染状態(Dirty State)のまま保存されないよう、エラー発生時のドキュメント破棄(`CloseDoc`)のロールバック処理を必ず担保すること。
ミリ単位の精度が品質を左右する機械設計の現場において、「なんとなく動くマクロ」は技術的負債でしかない。
オブジェクトのライフサイクルを完全に掌握し、APIの戻り値を1つ残らず監視する者だけが、真に堅牢な自動化の果実を手にすることができる。
