【実務・中級編】【ModelDoc2の基本】PartDoc、AssemblyDoc、DrawingDocへのキャストとインターフェース制御 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBAを掌握する極限の知見】ModelDoc2の幻想を断つ:安全かつ高速なインターフェース・キャストの極意

開発現場でこんなコードを見たことはないだろうか。

「アクティブなドキュメントを取得し、それが何であろうと力技で特定のメソッドを叩く。エラーが出たら `On Error Resume Next` でねじ伏せる」

――これこそが、SolidWorksマクロが「不安定で保守できない」と揶揄される最大の原因だ。
SolidWorks APIの根幹をなす `SldWorks` と `ModelDoc2`。この汎用インターフェースの海の中で、私たちは常に「今、手元にあるドキュメントの正体は何なのか」を正確に把握し、適切に型を制御(キャスト)しなければならない。

今回は、`ModelDoc2` から `PartDoc`、`AssemblyDoc`、`DrawingDoc` へと安全に、そしてパフォーマンスを犠牲にせずにインターフェースを制御する「プロフェッショナル・デザインパターン」を伝授する。

1. なぜ `ModelDoc2` だけでは実務の自動化に耐えられないのか?

SolidWorks VBAの入口である `SldWorks.Application.ActiveDoc`(または `IModelDoc2`)は、部品(Part)、アセンブリ(Assembly)、図面(Drawing)のすべてを包括する「汎用ラッパー」に過ぎない。

`ModelDoc2` のレイヤーでも、寸法値の変更やプロパティの書き込みといった共通操作は可能だ。しかし、実務で必要とされる以下のような「踏み込んだ自動化」を行おうとした瞬間、壁に突き当たる。

  • 部品 (PartDoc): ユーザー定義フィーチャーの走査、ボディの数や体積の厳密な取得、板金展開パラメータの操作。
  • アセンブリ (AssemblyDoc): コンポーネントの階層構造の走査、合致(Mete)の強制解決、軽量コンポーネントの強制解決(Resolve)。
  • 図面 (DrawingDoc): シートの切り替え、ビューのスケール変更、図面枠(フォーマット)の一括置換。

これらはすべて、`ModelDoc2` からそれぞれの専用インターフェースへ正確にキャスト(型変換)して初めてアクセスできる領域だ。ここで型安全性を軽視した設計を行うと、アセンブリを開いているのに部品用のメソッドを誤爆させ、メモリリークやSolidWorks自体の強制終了(クラッシュ)を引き起こす。

2. 堅牢なキャストを実現する「タイプ安全ガード」の設計思想

VBAは動的型付け言語の側面を持つため、オブジェクトの型判定を怠りがちになる。しかし、SolidWorks APIを扱う上では、厳格な型チェックと「Enum(列挙体)」を活用した状態管理が不可欠だ。

実務で破綻しないコードを書くための鉄則は以下の3つ。

1. 早期リターン(Guard Clause): 対象ドキュメントが `Nothing` でないか、期待するドキュメントタイプと一致するかを処理の最上流で厳格に検証する。
2. 適切な型への明示的キャスト: `TypeOf … Is` 演算子を用いて安全にダウンキャストを行う。
3. エラーハンドリングの局所化: 予期せぬCOM例外に備え、トランザクション単位で安全にロールバックできる構造にする。

3. 【プロダクションコード】安全なキャストと型別制御の実装例

以下のコードは、現在アクティブなドキュメントの種別を自動判別し、それぞれの専用インターフェースへ安全にキャストした上で、固有の処理を実行する実用的なモジュールだ。

コピペしてそのままVBAエディタ(標準モジュール)に貼り付け、実務のベースとして活用してほしい。

Option Explicit

‘ ==============================================================================
‘ 担当者必携:ModelDoc2安全キャスト&インターフェース制御テンプレート
‘ ==============================================================================

‘ ドキュメント種別を明確に定義するEnum
Public Enum SwDocType_e
swDocNONE = 0
swDocPART = 1
swDocASSEMBLY = 2
swDocDRAWING = 3
End Enum

Sub Main_InterfaceController()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2

‘ 1. アプリケーションインスタンスの取得
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical
Exit Sub
End If

‘ 2. アクティブドキュメントの取得
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbExclamation
Exit Sub
End If

‘ 3. ドキュメントタイプに応じた安全な分岐とキャスト
Select Case swModel.GetType
Case swDocPART
Call ProcessPartDocument(swModel)

Case swDocASSEMBLY
Call ProcessAssemblyDocument(swModel)

Case swDocDRAWING
Call ProcessDrawingDocument(swModel)

Case Else
MsgBox “サポートされていないドキュメントタイプです。”, vbCritical
End Select
End Sub

‘ ——————————————————————————
‘ 部品 (PartDoc) 特化型プロシージャ
‘ ——————————————————————————
Private Sub ProcessPartDocument(ByVal swModel As SldWorks.ModelDoc2)
‘ 明示的なダウンキャスト
Dim swPart As SldWorks.PartDoc
Set swPart = swModel

‘ キャスト成功の確認
If swPart Is Nothing Then
MsgBox “PartDocへのキャストに失敗しました。”, vbCritical
Exit Sub
End If

‘ — ここから部品固有の処理 —
Debug.Print “— 部品ドキュメント処理開始 —”
Debug.Print “ファイル名: ” & swModel.GetPathName

‘ 例:ボディ数の取得(PartDoc固有のメソッド)
Dim bodyCount As Long
bodyCount = swPart.GetBodyCount
Debug.Print “ソリッドボディ数: ” & bodyCount

‘ 処理完了の通知
MsgBox “部品ドキュメントの固有処理が完了しました。ボディ数: ” & bodyCount, vbInformation
End Sub

‘ ——————————————————————————
‘ アセンブリ (AssemblyDoc) 特化型プロシージャ
‘ ——————————————————————————
Private Sub ProcessAssemblyDocument(ByVal swModel As SldWorks.ModelDoc2)
‘ 明示的なダウンキャスト
Dim swAssembly As SldWorks.AssemblyDoc
Set swAssembly = swModel

If swAssembly Is Nothing Then
MsgBox “AssemblyDocへのキャストに失敗しました。”, vbCritical
Exit Sub
End If

‘ — ここからアセンブリ固有の処理 —
Debug.Print “— アセンブリドキュメント処理開始 —”

‘ 大規模アセンブリ対策:パフォーマンス向上を目的とした処理の例
‘ 例:軽量コンポーネントをすべて解決する(実務でよくある要件)
‘ swAssembly.ResolveAllComponents True

Dim compCount As Long
‘ コンポーネント配列の取得
Dim vComps As Variant
vComps = swAssembly.GetComponents(True) ‘ TopLevelのみ

If Not IsEmpty(vComps) Then
compCount = UBound(vComps) – LBound(vComps) + 1
Else
compCount = 0
End If

Debug.Print “トップレベル部品点数: ” & compCount
MsgBox “アセンブリドキュメントの固有処理が完了しました。部品点数: ” & compCount, vbInformation
End Sub

‘ ——————————————————————————
‘ 図面 (DrawingDoc) 特化型プロシージャ
‘ ——————————————————————————
Private Sub ProcessDrawingDocument(ByVal swModel As SldWorks.ModelDoc2)
‘ 明示的なダウンキャスト
Dim swDrawing As SldWorks.DrawingDoc
Set swDrawing = swModel

If swDrawing Is Nothing Then
MsgBox “DrawingDocへのキャストに失敗しました。”, vbCritical
Exit Sub
End If

‘ — ここから図面固有の処理 —
Debug.Print “— 図面ドキュメント処理開始 —”

‘ 例:アクティブシート名の取得
Dim vSheetNames As Variant
vSheetNames = swDrawing.GetSheetNames

Debug.Print “シート総数: ” & (UBound(vSheetNames) – LBound(vSheetNames) + 1)
Debug.Print “アクティブシート名: ” & swDrawing.GetCurrentSheet.GetName

MsgBox “図面ドキュメントの固有処理が完了しました。アクティブシート: ” & swDrawing.GetCurrentSheet.GetName, vbInformation
End Sub

4. チーフアーキテクトからの実務アドバイス:ファイル・DB連携時の罠

現場の自動化ツールは、単にSolidWorksを操作するだけでなく、Excel、Access、あるいはPLM/PDMデータベースとの連携を伴うことが多い。その際にこの「インターフェース制御」がどう絡むか、最後に重要な知見を残しておく。

1. 「サイレントモード」の併用:
バックグラウンドでファイルを順次開いて処理するバッチ処理(タスク自動化)では、`swModel.Extension.SaveAs` や `swApp.OpenDoc6` を用いることになる。この際、UIの描画を止める `swApp.Visible = False` や `swModel.Visible` の制御、およびエラーダイアログを抑制する設計が不可欠だ。
2. メモリ解放(オブジェクトの破棄)の徹底:
VBAはガベージコレクションの挙動がブラックボックスであるため、ループ処理の中で `Set swModel = Nothing` や `Set swPart = Nothing` を明示的に行わないと、COMオブジェクトがメモリ上に残留し、「マクロを数回回すとSolidWorksがフリーズする」という悪夢のような現象を引き起こす。大量のファイルを処理するループ内では、必ずインスタンスを解放する習慣をつけよ。

型を制する者は、SolidWorks APIを制する。
甘えたコードを捨て、堅牢なインターフェース制御で、真に信頼できる自動化システムを構築してほしい。

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