【実務・中級編】【上級プロ向け】DrawingDocとModelDoc2の双方向トラバーサル:図面から参照モデルの寸法を逆駆動するVBA – SolidWorks VBA解析バイブル

スポンサーリンク
スポンサーリンク

【極限の知見】DrawingからModelへの「逆駆動」を制御せよ:双方向トラバーサルの設計論

図面自動化の領域において、多くの開発者が最初にぶつかる「壁」がある。それは、「図面(DrawingDoc)を操作しているつもりが、背後の3Dモデル(ModelDoc2)の制御を見失う」という問題だ。

単にシートを生成し、ビューを配置する。そこまでは「作業の自動化」だ。しかし、図面上のビューから特定のフィーチャーを特定し、その3Dモデル側でパラメータを書き換え、あるいはフィーチャーをハイライトさせる。これこそが、真の「アソシエイティブ(関連付け)制御」であり、設計プロセスそのものをハックするエンジニアリングの本質である。

本稿では、DrawingDocとModelDoc2の間の「双方向トラバーサル(探索)」を、バグを許さない堅牢なアーキテクチャで実装するための設計思想と、プロダクションレベルのコードを伝授する。

1. アーキテクチャの本質:オブジェクトの「コンテキスト」を理解せよ

初心者はよく、`swApp.ActiveDoc` を盲信してコードを書く。しかし、これは極めて危険な設計だ。図面操作を行っている最中に、背後のモデルを操作しようとすると、APIのコンテキスト(現在どのドキュメントがアクティブか)の不一致により、`SelectionMgr` が空を掴む、あるいは予期せぬエラーを吐く原因となる。

図面ビューからモデルへアクセスする際、我々が辿るべき正解のパスは以下の通りだ。

1. DrawingDoc を取得する。
2. 選択された View オブジェクトを取得する。
3. `View.GetModelDoc2` メソッドを使い、そのビューが参照している ModelDoc2 のインスタンスを直接、かつ厳格に取得する。
4. 重要: モデル操作を行う際は、`DrawingDoc` のコンテキストから一時的に離脱し、取得した `ModelDoc2` に対して操作を完結させる設計にする。

この「コンテキストの分離」こそが、堅牢な自動化ツールの生命線である。

2. 実践:ビューからモデルのフィーチャーを逆駆動する

以下のコードは、図面上で選択された「ビュー」を起点とし、その背後にある3Dモデル内から特定の名前を持つフィーチャーを検索し、モデル側でハイライトさせるという、実務で極めて需要の高いロジックを実装したものである。

単なるコピペ用ではない。エラーハンドリングとオブジェクトの型判定を徹底した、「壊れない」ための設計を施してある。

'**
' Module: DrawingToModelTraversal
' Description: 図面ビューから参照モデルのフィーチャーを特定・制御する
' Author: Chief Architect
'**
Option Explicit

Public Sub HighlightFeatureFromView()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim swSelMgr As SldWorks.SelectionMgr
    Dim swView As SldWorks.View
    Dim swRefModel As SldWorks.ModelDoc2
    Dim swFeat As SldWorks.Feature
    Dim targetFeatName As String
    
    ' --- 設定:検索したいフィーチャー名を定義 ---
    targetFeatName = "Extrude1" 
    ' ---------------------------------------

    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc

    ' 1. ドキュメント型の厳格なチェック
    If swModel Is Nothing Then
        MsgBox "ドキュメントが開かれていません。", vbCritical
        Exit Sub
    End If

    If swModel.GetType <> swDocDRAWING Then
        MsgBox "図面ファイルを開いた状態で実行してください。", vbExclamation
        Exit Sub
    End If

    Set swDraw = swModel
    Set swSelMgr = swModel.SelectionManager

    ' 2. 選択されたオブジェクトが「ビュー」であるかを確認
    ' 図面では、ビュー自体が選択対象となる
    If swSelMgr.GetSelectedObjectType3(1, -1) <> swSelDRAWINGVIEW Then
        MsgBox "図面ビューを選択してから実行してください。", vbExclamation
        Exit Sub
    End If

    Set swView = swSelMgr.GetSelectedObject6(1, -1)

    ' 3. ビューから参照モデル(ModelDoc2)を抽出
    ' これがトラバーサルの核心である
    Set swRefModel = swView.GetModelDoc2

    If swRefModel Is Nothing Then
        MsgBox "このビューには参照モデルが存在しません。", vbCritical
        Exit Sub
    End If

    ' 4. モデル側へのコンテキスト・スイッチ
    ' 参照モデル内でのフィーチャー探索
    Set swFeat = swRefModel.FirstFeature

    Dim found As Boolean
    found = False

    Debug.Print "--- Traversal Start: " & swRefModel.GetTitle & " ---"

    Do While Not swFeat Is Nothing
        If swFeat.Name = targetFeatName Then
            ' フィーチャー発見
            Debug.Print "Found Feature: " & swFeat.Name
            
            ' モデル側でハイライトさせるための処理
            ' 注意:swRefModelをアクティブにする必要がある場合がある
            swRefModel.ClearSelection2 True
            swFeat.Select2 True, 0
            
            ' モデルを前面に出す(ユーザーへのフィードバック)
            ' swApp.ActivateDoc3 swRefModel.GetTitle, False, swRebuildOnActivation, 0
            
            found = True
            Exit Do
        End If
        Set swFeat = swFeat.GetNextFeature
    Loop

    ' 5. 結果の報告
    If found Then
        MsgBox "モデル内のフィーチャー [" & targetFeatName & "] を特定し、ハイライトしました。", vbInformation
    Else
        MsgBox "モデル内に指定されたフィーチャー [" & targetFeatName & "] が見つかりませんでした。", vbExclamation
    End If
    
    Debug.Print "--- Traversal End ---"
End Sub

3. プロダクション実装における「落とし穴」と回避策

このコードを実務に投入する際、設計者として以下の3点を考慮しなければならない。

① モデルの「読み取り専用」問題

図面が参照しているモデルが、他のプロセスによって「読み取り専用」で開かれている場合、`swRefModel` に対する変更操作(寸法変更やフィーチャー削除など)はすべて失敗する。
対策: 操作前に `swRefModel.IsReadOnly` をチェックし、読み取り専用であればユーザーに警告を発するか、あるいは「情報の参照(ハイライトのみ)」にモードを切り替える設計にする。

② パフォーマンスの重み:Feature Traversal

上記のコードでは `FirstFeature` から `GetNextFeature` で線形探索を行っている。フィーチャー数が数千に及ぶ大規模アセンブリの場合、このループは無視できないコストになる。
対策: 特定のフィーチャーを探す目的が明確であれば、`swModel.FeatureByName(targetFeatName)` を直接叩くべきだ。ただし、名前が動的に変わる環境(自動生成フィーチャーなど)では、今回のようなトラバーサルが必要になる。使い分けがプロの判断だ。

③ SelectionManager の競合

図面でビューを選択している状態で、モデル側のフィーチャーを `Select2` すると、SelectionManager の状態が混乱することがある。
対策: モデル側の操作を行う直前には必ず `swRefModel.ClearSelection2 True` を実行し、モデル側の選択状態をクリーンな状態からスタートさせること。これは「副作用を最小限に抑える」というソフトウェア設計の鉄則である。

結論:エンジニアリングとしての自動化

図面からモデルへの逆駆動は、単なる「便利な機能」ではない。それは、「データの一貫性を保証するための制御手段」である。

図面上の寸法変更がモデルに反映されない、あるいはモデルの変更が図面に正しく伝わらない。こうした不整合は、APIの使い方が甘い設計から生まれる。オブジェクトのライフサイクルを理解し、コンテキストを意識的に切り替える。この一段上のレイヤーでの実装こそが、世界中の設計現場で求められる「堅牢な自動化」を実現する唯一の道である。

次に君がコードを書くとき、そのオブジェクトは「今、どのドキュメントの、どのコンテキストに属しているか」を、自分自身に問いかけてほしい。

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