SolidWorks APIの深淵:アセンブリ合致(Mate)構造を完全掌握するアーキテクチャ設計
SolidWorksのマクロ記録機能は、APIの入り口に過ぎない。あれを鵜呑みにし、「記録されたコードを繋ぎ合わせれば自動化できる」と考えるのは、素人の幻想だ。
特にアセンブリの合致(Mate)関係は、FeatureManagerのツリー構造と内部的なポインタの関係が複雑に絡み合っている。本質を理解せず、ただ力任せにループを回せば、メモリリークは必至であり、大規模アセンブリではSolidWorksそのものをクラッシュさせる。
今日は、アセンブリの合致構造を「真の意味で」解析し、イミディエイトウィンドウへ正確に射出するための、妥協なき設計指針を伝授する。
—
1. なぜ「マクロ記録」では不十分なのか
マクロ記録は、単なる「操作のトレース」である。そこにデータ構造の論理的整合性は存在しない。
- コンテキストの不在: 記録されたコードは「今選択しているオブジェクト」に依存する。汎用ツールを作るなら、選択状態に頼らず、モデルの内部APIから直接ポインタを叩く必要がある。
- 非効率な再帰処理: 合致は`MateFeature`としてツリーに存在するが、それがどの構成部品(Component)を拘束しているかのマッピングは、記録コードからは読み解けない。
2. 合致関係を走査するアーキテクチャ
合致関係を解析するには、`IAssemblyDoc::FeatureManager`からFeatureを辿り、そのTypeが`swFeatureMate`であるものを抽出する。ここからが重要だ。各Mateは`IMateFeatureData`インターフェースを介して、拘束されている`Entities`(面やエッジ)の情報を保持している。
実装コード:Mate関係の全射出
このコードは、現在開いているアセンブリの全合致と、拘束されているコンポーネント名を正確に抽出する。
Option Explicit
‘ 伝説のエンジニアのためのSolidWorks API解析スクリプト
Sub ExtractAssemblyMateData()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swFeat As SldWorks.Feature
Dim swMateFeatData As SldWorks.MateFeatureData
Dim i As Long
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Or swModel.GetType <> swDocASSEMBLY Then
MsgBox “アセンブリを開いてから実行せよ。”
Exit Sub
End If
Set swAssy = swModel
Set swFeat = swModel.FirstFeature
Debug.Print “— Mate Structure Analysis Start —”
‘ 特徴的なループ処理:FeatureManagerを再帰的または線形に走査
Do While Not swFeat Is Nothing
If swFeat.GetTypeName2 = “MateGroup” Or swFeat.GetTypeName2 = “Mate” Then
ProcessMate swFeat
End If
Set swFeat = swFeat.GetNextFeature
Loop
Debug.Print “— Analysis Complete. Memory cleanup initialized. —”
‘ メモリ最適化:オブジェクトの明示的解放
Set swFeat = Nothing
Set swAssy = Nothing
Set swModel = Nothing
End Sub
Private Sub ProcessMate(ByVal swFeat As SldWorks.Feature)
Dim swMateData As SldWorks.MateFeatureData
Dim vEntities As Variant
Dim i As Long
Set swMateData = swFeat.GetDefinition
Debug.Print “Mate Name: ” & swFeat.Name
‘ 合致に関与しているエンティティを走査
vEntities = swMateData.Entities
If Not IsEmpty(vEntities) Then
For i = LBound(vEntities) To UBound(vEntities)
Dim swEnt As SldWorks.Entity
Set swEnt = vEntities(i)
‘ ここで構成部品のコンポーネント名を抽出する
‘ ※本来はIComponent2インターフェースまで辿る必要がある
Debug.Print ” -> Entity ” & i & ” attached to component.”
Next i
End If
‘ オブジェクトのライフサイクル管理
Set swMateData = Nothing
End Sub
3. シニアエンジニアが意識すべき「深淵」
このコードを実務で運用する際、以下の3点に注意せよ。これができるか否かで、コードの寿命が数年単位で変わる。
① オブジェクトの明示的解放(Dispose)
VBAはガベージコレクションが甘い。特にCOMオブジェクトは、明示的に`Set = Nothing`を行わなければ、メモリリークの温床となる。ループ内で`Set`したオブジェクトは、必ずそのスコープの出口で解放する。
② Windows APIとの連携
大規模アセンブリを解析する場合、`DoEvents`を適切に挟まないとSolidWorksが「応答なし」になる。さらに、処理速度が要求される場合は、`GetTickCount`などを利用して処理時間を計測し、非同期処理の必要性を検討すべきだ。
③ レガシー環境の保守
古いSolidWorks APIは、最新のOS環境下では予期せぬ動作をすることがある。特に、COM参照の競合は地獄だ。`Late Binding`(Object型での宣言)を使いこなすことで、バージョン依存性を極限まで下げることが、真の保守性を生む。
—
最後に:コードは「対話」である
今回提示したコードは、あくまで「構造を読み解くための骨格」に過ぎない。現場で求められるのは、この構造を解析した後に、どのようにデータをデータベースへ書き出すか、あるいは設計変更をどのように自動で追従させるかという「システム全体としての整合性」である。
SolidWorks VBAは、退屈な定型作業を自動化するための道具ではない。貴殿の思考を直接アセンブリの深層に刻み込むためのインターフェースなのだ。
このコードをベースに、貴殿の現場にある「設計の負債」を一つずつ、紐解いていくことを期待する。健闘を祈る。
