【SldWorksオブジェクト完全攻略】AppオブジェクトとActiveDocの正しい取得と使い分け
こんにちは。開発プロジェクトのチーフアーキテクトだ。
現場でSolidWorksの自動化マクロを見ていると、未だに散見されるのが「とりあえず `ActiveDoc` を叩けば動くだろ」という安易な設計思想のコードだ。
その場しのぎのコードは、実務の巨大なアセンブリやバックグラウンド処理、あるいは複数セッションが絡む複雑な自動化において、必ず「原因不明のクラッシュ」や「意図しないドキュメントへの誤爆」という致命傷を引き起こす。
今回は、SolidWorks VBAの根幹をなす `SldWorks`(App)オブジェクトと、ドキュメント操作の起点となる `ModelDoc2`(ActiveDoc)の正体、そしてプロが実践する「絶対にバグらせない堅牢な取得と使い分けの極意」を徹底的に伝授しよう。
—
1. なぜ「とりあえず ActiveDoc」は悪なのか?
初心者が書くコードの典型例を見てみよう。
‘ 【アンチパターン】絶対に真似してはいけないコード
Sub BadExample()
Dim swApp As Object
Set swApp = CreateObject(“SldWorks.Application”) ‘ または Application.SldWorks
‘ アクティブなドキュメントを直接取得して操作
Dim swModel As Object
Set swModel = swApp.ActiveDoc
swModel.EditRebuild
End Sub
このコードの何が問題か? 理由は3つある。
1. オブジェクトの型が `Object`(バリアント型の一種)になっている
IntelliSense(入力補完)が効かないだけでなく、実行時バインディングになるためパフォーマンスが著しく低下する。数千回のループを回す処理では致命傷だ。
2. 「今、何がアクティブか」はユーザーの操作に依存している
マクロ実行の瞬間にユーザーが別のウィンドウをクリックしたり、バックグラウンドで予期せぬアドインがポップアップしたりしただけで、全く意図しない図面や部品に対して処理が走り、最悪の場合、保存前のデータを破壊する。
3. エラーハンドリングが完全に欠落している
SolidWorksで何も開いていない(ドキュメントがゼロの)状態で `ActiveDoc` を呼ぶと、容赦なく `Null`(オブジェクト変数が設定されていません) が返り、マクロは沈黙する。
プロのエンジニアであれば、「アクティブなドキュメントに頼るな。状態を明示的に取得・検証せよ」という鉄則を常に念頭に置くべきだ。
—
2. SldWorksオブジェクト(App)の正しい捉え方
`SldWorks` オブジェクトは、SolidWorksのアプリケーションセッションそのものである。CADの「親玉」であり、すべてのAPIの起点となる。
VBAからSolidWorksを操作する場合、このAppオブジェクトの取得方法には大きく分けて2つのアプローチがある。
① すでに起動しているSolidWorksにフックする(標準的なマクロ)
SolidWorksのVBA環境(IDE)から実行する場合や、すでに立ち上がっているセッションを操作する場合、環境があらかじめ用意してくれているグローバル変数(あるいは明示的な取得)を使用する。
② 外部(Excel等)からSolidWorksを制御する
ExcelのVBAからSolidWorksを動かす場合などは、`GetObject` や `CreateObject` でセッションを掴む必要がある。
‘ 外部プロセス(Excel等)からSolidWorksを安全に掴む実務パターン
Sub ConnectToSolidWorks()
Dim swApp As SldWorks.SldWorks
On Error Resume Next
‘ 起動中のセッションを取得を試みる
Set swApp = GetObject(, “SldWorks.Application”)
On Error GoTo 0
If swApp Is Nothing Then
‘ 起動していなければ新規起動
Set swApp = New SldWorks.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksの起動に失敗しました。”, vbCritical
Exit Sub
End If
‘ 必要に応じてウィンドウを表示
swApp.Visible = True
End If
MsgBox “接続成功: Ver ” + swApp.RevisionNumber
End Sub
—
3. ActiveDoc vs 厳密なドキュメント取得の使い分け
`ActiveDoc` は「現在ユーザーのフォーカスがあたっているドキュメント」を返す。これは「ユーザーの手動操作の補助」には向いているが、「確実性が求められるバッチ処理や自動図面生成」には不向きだ。
実務で堅牢なツールを作るためのアプローチは以下の通りである。
1. 型を明示する(早期バインディング)
`Dim swApp As SldWorks.SldWorks`、`Dim swModel As SldWorks.ModelDoc2` のように、型を明確に宣言する。これにより参照設定(Tools > References から SolidWorks コマンドやタイプライブラリを追加)が必要になるが、恩恵は計り知れない。
2. 戻り値の `Nothing` チェックを絶対に怠らない
3. ファイルパスやタイトルでターゲットを特定する
アクティブなドキュメントに頼るのではなく、開かれているドキュメントのリストから目的のファイルを特定するか、パスを指定してサイレントオープン(裏で開く)する。
—
4. 【プロダクションコード】安全・高速・確実なテンプレート
それでは、実務の現場でそのまま流用できる、極限まで堅牢性を高めたSolidWorks VBAのテンプレートコードを提示しよう。
このコードは、以下の要件を満たしている。
- 早期バインディングによる最高速のパフォーマンス
- 実行時のドキュメント有無の厳密なバリデーション
- エラーハンドリングとリソースの適切な管理
‘ ==============================================================================
‘ モジュール名: Mdl_RobustTemplate
‘ 概要: SldWorksオブジェクトとModelDoc2の安全な取得・制御を行うプロダクションコード
‘ 前提条件: VBAエディタの [ツール] -> [参照設定] から
‘ 「SolidWorks x.x Type Library」にチェックが入っていること
‘ ==============================================================================
Option Explicit
Sub ExecuteRobustProcess()
‘ 1. 宣言(早期バインディングによる型安全と高速化)
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim activeDocType As Long
‘ 2. SldWorksセッションの取得
‘ ※SolidWorks内蔵VBAであれば Application.SldWorks でも可だが、
‘ 外部連携も考慮し安全に取得する
On Error Resume Next
Set swApp = Application.SldWorks
On Error GoTo 0
If swApp Is Nothing Then
MsgBox “SolidWorksセッションが検出できません。”, vbCritical, “致命的なエラー”
Exit Sub
End If
‘ 3. アクティブドキュメントの安全な取得
Set swModel = swApp.ActiveDoc
‘ 【最重要】ドキュメントが開かれていない場合のガード処理
If swModel Is Nothing Then
MsgBox “処理対象となるドキュメントが開かれていません。” & vbCrLf & _
“部品、アセンブリ、または図面を開いてから実行してください。”, vbExclamation, “警告”
Exit Sub
End If
‘ 4. ドキュメント種別の判定(部品:swDocPART, アセンブリ:swDocASSEMBLY, 図面:swDocDRAWING)
activeDocType = swModel.GetType
Select Case activeDocType
Case swDocPART
Debug.Print “現在のアクティブドキュメントは「部品」です: ” & swModel.GetPathName
Case swDocASSEMBLY
Debug.Print “現在のアクティブドキュメントは「アセンブリ」です: ” & swModel.GetPathName
Case swDocDRAWING
Debug.Print “現在のアクティブドキュメントは「図面」です: ” & swModel.GetPathName
Case Else
MsgBox “未知のドキュメントタイプです。”, vbCritical
Exit Sub
End Select
‘ 5. 実処理の実行(例:モデルの強制リビルド)
‘ エラーを考慮し、処理開始前のステータスを保持するなど実務的な配慮を行う
Dim boolstatus As Boolean
boolstatus = swModel.Extension.Rebuild(swRebuildAll)
If Not boolstatus then
MsgBox “リビルド中にエラーが発生しました。”, vbExclamation
Else
MsgBox “処理が正常に完了しました。”, vbInformation, “完了”
End If
‘ 6. クリーンアップ(メモリリーク防止の作法)
Set swModel = Nothing
Set swApp = Nothing
End Sub
—
チーフアーキテクトからの総括
APIを叩くコードを書くとき、私たちは常に「CADの裏側で何が起きているか」を想像しなければならない。
`SldWorks` と `ModelDoc2` は、いわばSolidWorksという巨大なエンジニアリング・プラットフォームの「頭脳」と「心臓部」だ。これらを雑に扱い、場当たり的な `ActiveDoc` 依存のコードを書くことは、時限爆弾を抱えたシステムを構築しているのと同義である。
今回解説した「早期バインディング」「厳密な `Nothing` チェック」「状態のバリデーション」の3原則を徹底すれば、あなたの書くマクロは見違えるほど安定し、現場のエンジニアたちから絶大な信頼を得る自動化ツールへと生まれ変わるだろう。
妥協のないコードで、真の業務効率化を成し遂げてほしい。
