【実務・中級編】【上級プロ向け】レガシーSolidWorks APIバージョン差異(2018〜2024+)を動的バインディングで完全に吸収するラッパー – SolidWorks VBA解析バイブル

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

バージョン差異の呪縛を解け:SolidWorks APIにおける「動的バインディング・ラッパー」による極限の堅牢設計

開発現場において、我々エンジニアを最も苦しめるのは「新機能の追加」ではない。「環境の不一致」だ。

ある設計部門ではSolidWorks 2024が導入され、別の現場ではまだ2018が現役で動いている。このような混在環境で、特定のバージョンに依存した「参照設定(Early Binding)」によるツールを配布した瞬間、そのツールはゴミ同然の「コンパイルエラーの塊」へと成り下がる。

もし君が、単なる「動くスクリプト」ではなく、企業の基幹業務を支える「プロダクション・グレードの自動化システム」を構築したいのであれば、このバージョンの壁をどう抽象化するかという設計思想を、今すぐ脳に刻み込む必要がある。

本稿では、SolidWorks 2018から2024+までのAPI仕様変更を、実行時型判定(Late Binding)を用いて完全に吸収する、「Version-Agnostic Wrapper(バージョン非依存ラッパー)」の設計手法を伝授する。

1. なぜ「参照設定」はプロの設計において「負債」なのか

多くの入門書では、`Dim swApp As SldWorks.SldWorks` と宣言することを推奨している。これは「Early Binding(事前バインディング)」と呼ばれ、IntelliSense(入力補完)が効くため、開発効率は高い。

しかし、これには致命的な弱点がある。

1. 参照の硬直性: `SldWorks.tlb` を参照した時点で、そのプロジェクトは特定のバージョンのライブラリに紐付けられる。ユーザーの環境がそれより古い、あるいは新しい場合に、参照エラーを引き起こす。
2. APIの破壊的変更への脆弱性: SolidWorksのアップデートにより、特定のメソッドが非推奨(Deprecated)になったり、引数の型が変わったりすることがある。事前バインディングでは、これらは即座に実行時エラー、あるいはコンパイルエラーとして牙を剥く。

プロフェッショナルは、「ロジック」と「APIの実装」を分離する。

2. アーキテクチャ設計:アダプター・パターンによる抽象化

我々が採用すべきは、「ラッパー・クラス」による抽象化である。
メインのロジックは「何がしたいか(What)」だけを記述し、APIとの具体的なやり取り(How)は、すべてラッパー・クラスの中に隠蔽する。

設計の三原則

1. 全てのSolidWorksオブジェクトを `Object` 型で保持する: これにより、参照設定によるコンパイルエラーを物理的に回避する。
2. メソッド呼び出しの「安全な試行」: `On Error Resume Next` を乱用するのではなく、メソッドの存在や戻り値を検証するロジックを組み込む。
3. 定数の自前定義: APIの列挙型(Enum)に依存せず、ラッパー内で定数を定義することで、バージョン間の定数定義の差異を吸収する。

3. 実装例:堅牢なDrawing操作ラッパー

以下に、図面(Drawing)の生成とビュー配置を例とした、実戦投入可能なラッパー構造を示す。

Step 1: クラスモジュール `clsSwWrapper` の作成

このクラスが、APIの荒波からメインロジックを守る「盾」となる。

' ==============================================================================
' Class Name: clsSwWrapper
' Description: SolidWorks APIのバージョン差異を吸収する抽象化ラッパー
' ==============================================================================
Option Explicit

Private swApp As Object ' SldWorks.SldWorks を Object 型で保持

' --- API定数の自前定義 (Enumに依存しない) ---
Public Const swDwgViewScale_e_Default As Long = 1 
Public Const swDrawingViewScale_e_Default As Long = 1

' ------------------------------------------------------------------------------
' 初期化: SolidWorksインスタンスの取得
' ------------------------------------------------------------------------------
Public Function Initialize() As Boolean
    On Error Resume Next
    ' 実行中のSolidWorksを取得、なければ新規起動を試みる
    Set swApp = GetObject(, "SldWorks.Application")
    If swApp Is Nothing Then
        Set swApp = CreateObject("SldWorks.Application")
    End If
    On Error GoTo 0
    
    Initialize = Not swApp Is Nothing
End Function

' ------------------------------------------------------------------------------
' メソッド: 図面ドキュメントの新規作成
' ------------------------------------------------------------------------------
Public Function CreateNewDrawing(templatePath As String) As Object
    ' templatePath: 使用する図面テンプレートのフルパス
    Dim swDoc As Object
    
    If swApp Is Nothing Then Exit Function

    On Error Resume Next
    ' Late Bindingによるメソッド呼び出し
    Set swDoc = swApp.NewDocument(templatePath, 0, 0, 0)
    On Error GoTo 0
    
    If swDoc Is Nothing Then
        Debug.Print "Error: 図面の作成に失敗しました。パスを確認してください。"
    End If
    
    Set CreateNewDrawing = swDoc
End Function

' ------------------------------------------------------------------------------
' メソッド: 図面ビューの安全な挿入
' ------------------------------------------------------------------------------
Public Function InsertDrawingView(swDrawing As Object, modelPath As String, _
                                 viewType As Long, x As Double, y As Double) As Boolean
    Dim swModelDocExt As Object
    Dim swView As Object
    
    On Error Resume Next
    ' 1. ModelDocExtensionの取得
    Set swModelDocExt = swDrawing.Extension
    
    ' 2. ビューの挿入 (APIバージョンによって引数が異なる可能性を考慮)
    ' ここでは標準的な InsertDrawingView3 を試行
    Set swView = swDrawing.CreateDrawViewFromModelView3(modelPath, viewType, x, y, 0)
    
    ' 3. 万が一失敗した場合、古いバージョンのメソッドを試行するフォールバックロジック
    If swView Is Nothing Then
        Debug.Print "Warning: InsertDrawingView3 failed. Attempting fallback to legacy method..."
        Set swView = swDrawing.InsertDrawingView2(modelPath, viewType, x, y, 0)
    End If
    On Error GoTo 0

    InsertDrawingView = Not swView Is Nothing
End Function

' ------------------------------------------------------------------------------
' プロパティ: swAppへのアクセス
' ------------------------------------------------------------------------------
Public Property Get App() As Object
    Set App = swApp
End Property

Step 2: 標準モジュールでのメインロジック

メインロジックは、`clsSwWrapper` の存在さえ知っていればよく、SolidWorksの内部構造の変更には一切関知しない。

' ==============================================================================
' Module: modMain
' Description: 業務ロジックの記述(APIに直接触れない)
' ==============================================================================
Option Explicit

Sub ExecuteDrawingAutomation()
    Dim swWrapper As New clsSwWrapper
    Dim swDrawing As Object
    Dim templatePath As String
    Dim modelPath As String
    Dim success As Boolean
    
    ' 1. 環境の初期化
    If Not swWrapper.Initialize() Then
        MsgBox "SolidWorksの起動に失敗しました。", vbCritical
        Exit Sub
    End If
    
    ' 2. パスの設定 (実務ではDBや設定ファイルから取得)
    templatePath = "C:\SW_Templates\A3_Standard.drwdat"
    modelPath = "C:\Projects\Part_A.SLDPRT"
    
    ' 3. 図面作成
    Set swDrawing = swWrapper.CreateNewDrawing(templatePath)
    If swDrawing Is Nothing Then
        MsgBox "図面作成に失敗しました。", vbExclamation
        Exit Sub
    End If
    
    ' 4. ビュー配置 (フォールバック機能により、バージョン差異を吸収済み)
    ' 引数の viewType はラッパー内の定数、あるいは直接数値を指定
    success = swWrapper.InsertDrawingView(swDrawing, modelPath, 1, 0.1, 0.1)
    
    If success Then
        MsgBox "自動生成が完了しました。", vbInformation
    Else
        MsgBox "ビューの配置に失敗しました。", vbCritical
    End If
End Sub

4. 運用における「極限の注意点」

この設計を採用したとしても、以下の2点に触れる場合は細心の注意を払え。

A. データベース・外部連携の整合性

自動生成ツールは、多くの場合、PDM(Product Data Management)やExcel、SQL Serverと連携する。APIのバージョン差異を吸収しても、「データの整合性」が崩れればシステムは崩壊する。
特に、図面内の「プロパティ(Custom Property)」の取得において、APIの戻り値が `Variant` なのか `String` なのか、あるいは `Null` を返すのかを厳密にチェックするロジックを、ラッパー内に必ず組み込め。

B. パフォーマンスのオーバーヘッド

Late Bindingは、Early Bindingに比べてわずかに実行速度が遅い。しかし、数千個の部品をループで回すような極限のケースを除き、人間が体感できる差ではない。
「速度のために堅牢性を捨てる」という判断は、エンジニアリングにおける敗北である。 速度が必要なら、ラッパー内でオブジェクトの参照をキャッシュ(再利用)する設計にせよ。

結論:保守性の高いコードこそが最強の武器である

「動けばいい」というコードを書く人間は、開発者(Developer)だ。
「変化に耐え、数年後の運用を保証する」コードを書く人間が、アーキテクト(Architect)である。

今回紹介した動的バインディングによるラッパー構造は、一見すると記述量が増えるように見えるかもしれない。しかし、将来のSolidWorksアップデートに伴う「修正作業の地獄」を回避するための、最も安価で、最も強力な投資である。

設計に妥協するな。堅牢性を追求せよ。

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