【エンティティ選択の自動化】Extension.SelectByID2の引数を完全理解して要素を確実に掴む
SolidWorks VBA自動化において、多くの開発者が最初の、そして最大の壁として直面するのが「要素の選択(Selection)」である。
特に `ModelDoc2.Extension.SelectByID2` メソッドは、マクロ記録機能を使うと必ず生成される基本中の基本であるにもかかわらず、その引数の意味を正確に理解しているエンジニアは少ない。
「なぜか昨日動いていたコードが、モデルを微修正した途端にエラーになる」
「面やエッジの内部IDが変わり、意図しないジオメトリが選択されて設計変更が破壊される」
このようなレガシーな課題に対し、単なるリファレンスの引き写しではなく、SolidWorks APIのオブジェクトモデルの深層とメモリ管理の鉄則を踏まえた「確実なエンティティ選択の極意」を伝授する。
—
1. SelectByID2 の引数構造と「見えない罠」
まずは `SelectByID2` のシグネチャを完全に分解する。
Dim boolstatus As Boolean
boolstatus = swModel.Extension.SelectByID2( _
Name As String, _
Type As String, _
X As Double, _
Y As Double, _
Z As Double, _
Append As Boolean, _
Mark As Long, _
Callout As Object, _
SelectOption As Long _
)
このメソッドの挙動を支配しているのは、`Name`、`Type`、そして `(X, Y, Z)` の三位一体の関係である。ここを誤解していると、APIは意図した要素を掴んでくれない。
引数の詳細な解剖
- `Name` (String):
フィーチャー名(例: `”Extrude1″`)や面・エッジの内部名(例: `”<1>“` や面につけられた名前)。
- `Type` (String):
選択するエンティティのカテゴリ。`”FACE”`, `”EDGE”`, `”BODY”`, `”COMPONENT”`, `”SKETCH”` など。ここを文字列で指定するため、タイプミスがそのままバグにつながる。
- `X, Y, Z` (Double):
ここが最大の肝である。 `Name` だけでは空間上の特定の一意な面を指し示せない場合(対称形状や同一形状の配列など)、SolidWorksはこの3次元座標を元に「どの位置にあるエンティティか」を解決する。単位は常にメートル(Meter)であることに注意せよ。
- `Append` (Boolean):
`True` の場合、既存の選択に追加(マルチセレクト)。`False` の場合、既存の選択をクリアして新規選択。
- `Mark` (Long):
フィーチャーの機能定義(合致の作成やフィレットの適用など)において、どのスロットにそのエンティティを渡すかを決定するビットマスク。実務ではここを意識的に制御することが堅牢なコードへの第一歩となる。
—
2. なぜ「名前と座標」だけでは破綻するのか?
実務の現場で最も恐ろしいのは、「トポロジー変更(Topology Changes)」によるモデルの再計算(Rebuild)だ。
SolidWorksの内部では、モデルの形状が変更されると、面やエッジの内部ID(Persistent ID)が再割り当てされることがある。マクロ記録されたハードコーディングされた名前(`”Face<1>“` 等)に頼っていると、モデルを少し修正しただけで選択が外れるか、全く関係のない面を選択してしまう。
これを回避するためには、以下の2つのアプローチを使い分ける必要がある。
1. 一意に確定しているフィーチャー名+座標の動的取得
2. Persistent ID(PID)を用いた完全な追跡(上級向け)
今回は、現場で最も費用対効果が高い「確実に要素を掴むための実践的ラッパー関数」の設計コードを提示する。
—
3. 【実用コード】耐障害性に優れた安全な選択関数の実装
以下のコードは、指定した座標とタイプをもとに、確実にモデル上のエンティティを捕捉し、メモリリークを排除したプロフェッショナルグレードの実装である。
‘ ==============================================================================
‘ 堅牢なエンティティ選択ラッパー関数
‘ ==============================================================================
Public Function SafeSelectEntity( _
ByRef swModel As SldWorks.ModelDoc2, _
ByVal entityName As String, _
ByVal entityType As String, _
ByVal x As Double, _
ByVal y As Double, _
ByVal z As Double, _
ByVal mark As Long, _
ByVal append As Boolean _
) As Boolean
If swModel Is Nothing Then
SafeSelectEntity = False
Exit Function
End If
Dim ext As SldWorks.ModelDocExtension
Set ext = swModel.Extension
‘ 選択前のエラークリアと確実な実行
‘ SelectByID2の引数: Name, Type, X, Y, Z, Append, Mark, Callout, SelectOption
Dim success As Boolean
success = ext.SelectByID2(entityName, entityType, x, y, z, append, mark, Nothing, swSelectOption_Default)
If Not success Then
Debug.Print “【警告】エンティティの選択に失敗しました: ” & entityName & ” (” & entityType & “)”
End If
SafeSelectEntity = success
‘ — 【メモリ最適化の鉄則】 —
‘ VBA環境であっても、COMオブジェクトの参照はスコープ抜けたタイミングに頼らず
‘ 大規模処理やループ内では明示的にNothingを代入してRCW(Runtime Callable Wrapper)を解放する
Set ext = Nothing
End Function
—
4. 現場のプロが実践するメモリ最適化とパフォーマンスの極意
SolidWorks VBAの開発において、見落とされがちなのがCOMオブジェクトのライフサイクル管理である。
`ModelDocExtension` や `SelectionMgr` などのオブジェクトをループ内で頻繁に取得・破棄せず、適切なスコープで再利用すること、あるいは不要になった時点で即座に `Set obj = Nothing` を実行することが、数千回におよぶバッチ処理中のメモリリークや突然のクラッシュ(Fatal Error)を防ぐ唯一の盾となる。
Mark値の厳格な管理
例えば、アセンブリの合致(Mate)をAPIで自動生成する場合、`Mark` の指定ミスは致命傷になる。
- 面Aの選択:`Mark = 1`
- 面Bの選択:`Mark = 2`
このように明確に役割を分離し、`SelectByID2` の第7引数(Mark)をコントロールしなければ、SolidWorksのソルバーはどの面をどう拘束すべきか混乱し、APIは静かに `False` を返すか、最悪の場合は不正終了を引き起こす。
—
5. 総括:システム間連携を見据えた堅牢なアーキテクチャへ
今回解説した `SelectByID2` の精密なコントロールは、単なるVBAマクロの安定化にとどまらない。
将来的にC# (.NET Add-in) や外部システム(PLM/PDM)からの連携へとステップアップする際も、この「エンティティを特定し、選択状態を担保する」という根本思想はそのまま継承される。
場当たり的なコード記述を捨て去り、引数の意味を完全に掌握した上で、プロフェッショナルな設計思想に基づいた自動化コードを構築してほしい。それこそが、レガシーを制し、真に安定した設計環境を支えるエンジニアの姿である。
