【実務・中級編】【初心者向け】図面ビューごとの表示スタイル(ワイヤーフレーム/シェード)を個別制御するVBA – SolidWorks VBA解析バイブル

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

【Architect’s Insight】図面ビューの表示モードを支配せよ:堅牢な描画制御の実装戦略

多くのエンジニアが「マクロの記録」から自動化の第一歩を踏み出す。しかし、そこから一歩も進めず、現場で使い物にならない「動けばいいだけのツール」を量産してしまう。

今回のテーマは、SolidWorks図面における「ビューごとの表示スタイル(シェーディング、隠線、ワイヤーフレーム等)の個別制御」だ。

一見、単純なAPIの呼び出しに見えるだろう。しかし、大量のビューを持つ複雑な図面に対して、場当たり的なコードを投げれば、メモリの不整合や処理速度の著しい低下、最悪の場合はアプリケーションのクラッシュを招く。

本記事では、単なる「コードの書き方」ではなく、プロフェッショナルとして「いかにバグを排除し、計算資源を最適に使い、保守性の高い設計を行うか」という設計思想(アーキテクチャ)を伝授する。

1. 陥りやすい「素人レベル」の設計ミス

まず、初心者が書きがちなコードの構造を批判的に検討しよう。

' ❌ アンチパターン:典型的な「動けばいいだけ」のコード
Sub BadExample()
    Dim swApp As SldWorks.SldWorks
    Set swApp = Application.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Set swModel = swApp.ActiveDoc
    
    Dim swDraw As SldWorks.DrawingDoc
    Set swDraw = swModel
    
    Dim v As Variant
    Dim swView As SldWorks.View
    ' 全てのビューをループして、無理やり全部シェーディングにする
    For Each v In swDraw.GetViews ' ※実際にはGetViewsというメソッドは存在しない(正しくはGetFirstViewから辿る)
        Set swView = v
        swView.SetDisplayMode 3 ' 魔法の数字(リテラル)の使用
    Next
End Sub

なぜこのコードは「ゴミ」なのか?

1. オブジェクトの型チェックが皆無: `ActiveDoc` が図面(Drawing)でない場合、即座にランタイムエラーで落ちる。
2. APIの理解不足: SolidWorksのViewオブジェクトの走査は、`GetFirstView` から `GetNextView` を辿るリンクドリスト構造である。`For Each` で適当に回せるものではない。
3. マジックナンバーの乱用: `SetDisplayMode 3` の「3」が何を意味するか、コードを読んだ者に伝わらない。保守性が皆無だ。
4. パフォーマンスへの無配慮: ビューのスタイルを変更するたびに、SolidWorksはグラフィックスの再構築を試みる。大量のビューがある場合、描画更新の制御を行わないと、処理時間は指数関数的に増大する。

2. プロダクション・グレードの設計思想

プロのエンジニアとして、以下の3点を設計の柱に据える。

① 型の安全性とバリデーション

「入力が正しい」という前提を捨てろ。対象が図面か? ファイルは開いているか? ビューは存在するか? これらを徹底的に検証する。

② 列挙型(Enum)による可読性の確保

APIの定数は、必ず意味のある名前で定義するか、SolidWorksが提供する列挙型を使用せよ。

③ 描画更新のバッチ処理

スタイル変更は「一括」で行う。一回変更するたびに画面を更新させるのではなく、すべての変更を終えてから、最後に一度だけリフレッシュさせるのが鉄則だ。

3. 実践:堅牢なビュー制御エンジンの実装

以下に、そのままプロダクション環境に投入できるレベルのコードを示す。このコードは、特定の条件(例えば「等角投影図ならシェーディング、直交投影図なら隠線」)に基づいてビューを制御するロジックを組み込めるように設計している。

Option Explicit

' ==============================================================================
' Module: DrawingViewController
' Description: 図面ビューの表示スタイルを高度に制御するためのモジュール
' ==============================================================================

''' <summary>
''' 指定した図面内のビューに対して、表示モードを一括制御する。
''' </summary>
Public Sub ApplySmartViewStyles()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    
    On Error GoTo ErrorHandler

    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 "エラー: アクティブなドキュメントが図面ではありません。", vbCritical
        Exit Sub
    End If

    Set swDraw = swModel

    ' 2. グラフィックス更新の抑制(パフォーマンス最適化)
    ' 描画の更新を一時的に止めることで、ループ中の再計算コストを最小化する
    swModel.LockGraphics = True

    Dim swView As SldWorks.View
    Dim swSheet As SldWorks.Sheet
    
    ' 3. ビューの走査 (GetFirstViewはシート自体を指すため注意が必要)
    Set swView = swDraw.GetFirstView ' これは「Sheet」ビュー
    
    ' シートビュー自体はスキップし、モデルビューから処理を開始する
    Set swView = swView.GetNextView

    Do While Not swView Is Nothing
        ' 4. ビジネスロジック: ビューのタイプに基づいた条件分岐
        ' ここでは例として「等角投影図(IsIsometric)」か否かで切り分ける
        
        Dim viewType As String
        viewType = swView.Type ' 必要に応じてビュー名を判定材料にする
        
        ' 表示モードの決定
        ' swDisplayMode_e の定数を利用
        ' 0: Wireframe, 1: Shaded, 2: Hidden Lines Removed, etc.
        Dim targetMode As Long
        
        If IsIsometricView(swView) Then
            targetMode = swDisplayMode_e.swDisplayMode_Shaded
        Else
            targetMode = swDisplayMode_e.swDisplayMode_HiddenLinesRemoved
        End If

        ' 5. API実行
        swView.SetDisplayMode2 targetMode
        
        ' 次のビューへ
        Set swView = swView.GetNextView
    Loop

    ' 6. 後処理: 描画のロック解除と再描画
    swModel.LockGraphics = False
    swModel.GraphicsRedraw2
    
    MsgBox "ビューの更新が完了しました。", vbInformation

CleanUp:
    Exit Sub

ErrorHandler:
    ' エラー発生時も必ずロックを解除してプロセスを正常終了させる
    swModel.LockGraphics = False
    MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical
    Resume CleanUp
End Sub

''' <summary>
''' ビューが等角投影図であるかを判定するヘルパー関数
''' </summary>
Private Function IsIsometricView(view As SldWorks.View) As Boolean
    ' 実務ではビューの名前や、投影方向のベクトルから判定するロジックをここに実装する
    ' 今回は簡略化のため、ビュー名に "ISO" が含まれているかで判定する例とする
    If InStr(1, view.Name, "ISO", vbTextCompare) > 0 Then
        IsIsometricView = True
    Else
        IsIsometricView = False
    End If
End Function

4. アーキテクトからのアドバイス

パフォーマンスの鍵:`LockGraphics`

コード内で使用した `swModel.LockGraphics = True`。これは、大規模なアセンブリ図面を扱う際に「命」となるプロパティだ。これを怠ると、ビューを1つ変えるたびにSolidWorksが全画面の再計算を行うため、100個のビューがある図面では、処理時間が数分から数秒へと劇的に変わる。

拡張性:ロジックの分離

`ApplySmartViewStyles` というメインルーチンの中に、判定ロジック(`IsIsometricView`)を直接書き込んではいけない。今回のように、判定ロジックを「ヘルパー関数」として切り出すことで、将来的に「ビューの名前ではなく、レイヤー名で判定したい」「特定の属性に基づいて判定したい」といった仕様変更が来た際、メインのフローを壊さずに修正が可能になる。これが「保守性の高いコード」の正体だ。

データベース連携への布石

もし、このツールを「Excelのリストに基づいた自動生成ツール」へと昇華させるなら、`targetMode` を決定する部分を、Excelから読み込んだパラメータ(`swDisplayMode_e` の値)に置き換えるだけでいい。設計が分離されていれば、この移行は容易だ。

結論

VBAは単なる「自動化の手段」ではない。それは、複雑なエンジニアリングプロセスを制御するための「ソフトウェア開発」そのものである。

型を意識し、エラーを予見し、計算資源を敬え。この規律を守る者だけが、現場で真に信頼されるツールを構築できる。

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