【SldWorksオブジェクト完全攻略】AppオブジェクトとActiveDocの正しい取得と使い分け
SolidWorks VBAの自動化において、すべての起点となるのが `SldWorks.SldWorks` アプリケーションオブジェクトと、現在作業対象となっている `ModelDoc2`(ActiveDoc)の制御である。
多くのプログラマや社内SEは、ネット上の散在する断片的なサンプルコードを継ぎ接ぎし、`GetObject(, “SolidWorks.Application”)` や `ActiveDoc` の乱用によって、メモリリーク、ゾンビプロセスの発生、あるいは予期せぬドキュメントの誤操作という致命的な罠に陥っている。
本稿では、SolidWorksのプロセスモデル、COMオブジェクトのライフサイクル、そしてWindows APIの介入領域まで踏み込み、現場で即座に通用する「真に堅牢なSolidWorks VBAアーキテクチャ」を構築するための極限の知見を公開する。
—
1. SldWorksオブジェクトの正体とプロセスモデルの理解
SolidWorksは、WindowsのCOM(Component Object Model)アーキテクチャに基づいて構築されている。
VBAからSolidWorksを操作する場合、大きく分けて2つのアプローチが存在する。
1. 早期バインディング(Early Binding): 参照設定を行い、静的な型解決を行う方法。
2. 遅延バインディング(Late Binding): `CreateObject` や `GetObject` を用いて動的にインターフェースを取得する方法。
シニアエンジニアとして断言するが、保守性とバージョン依存性の排除を考慮するならば、プロダクション環境では遅延バインディング、あるいは厳密な参照設定管理が必須となる。特に異なるSolidWorksのバージョンが混在する企業インフラにおいては、不用意な早期バインディングは型ライブラリの不整合(Error 429など)を引き起こす主原因となる。
危険な `ActiveDoc` 依存症からの脱却
多くの初心者が犯す最大の過ちは、次のようなコードを書くことだ。
‘ 【アンチパターン】絶対にやってはいけないコード
Dim swApp As Object
Dim swModel As Object
Set swApp = GetObject(, “SolidWorks.Application”)
Set swModel = swApp.ActiveDoc ‘ ← ユーザーの操作に完全に依存している
`ActiveDoc` は、その名の通り「現在画面上でアクティブになっているドキュメント」を返す。しかし、バックグラウンド処理やバッチ処理において、ユーザーが意図せず別のウィンドウをクリックしたり、モーダルダイアログが開いている状態でこのコードが走ると、全く意図しない図面やアセンブリに対してマクロが暴走する。
真に堅牢なシステム連携では、`ActiveDoc` に頼るのではなく、明示的にドキュメントのパスを指定してオープンするか、現在開いているセッションからドキュメントのタイトルの合致を厳密に検証して取得するべきである。
—
2. 安全なSldWorksインスタンスの取得とエラーハンドリング
実務において、SolidWorksがすでに起動しているかどうかに応じて処理を分岐させる必要がある。ここでWindows APIの知識やCOM例外処理の知見が活きてくる。
以下のコードは、SolidWorksのセッションを安全に捕捉し、存在しない場合は新規起動、あるいは適切にエラーハンドリングを行うプロダクション品質のテンプレートである。
‘ ==============================================================================
‘ 堅牢なSldWorksアプリケーションインスタンスの取得
‘ ==============================================================================
Public Function GetSolidWorksApplication(ByRef outApp As Object) As Boolean
On Error GoTo ErrorHandler
Dim swApp As Object
‘ 1. 稼働中のSolidWorksインスタンスの取得を試みる
On Error Resume Next
Set swApp = GetObject(, “SolidWorks.Application”)
On Error GoTo ErrorHandler
‘ 2. インスタンスが存在しない場合は新規起動
If swApp Is Nothing Then
Set swApp = CreateObject(“SolidWorks.Application”)
If swApp Is Nothing Then
MsgBox “SolidWorksの起動に失敗しました。”, vbCritical, “致命的エラー”
GetSolidWorksApplication = False
Exit Function
End If
‘ 自動化時は画面描画を非表示にしてパフォーマンスを極限まで高める(必要に応じて制御)
swApp.Visible = True
End If
Set outApp = swApp
GetSolidWorksApplication = True
Exit Function
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “System Error”
Set outApp = Nothing
GetSolidWorksApplication = False
End Function
—
3. メモリ管理とCOMオブジェクトの明示的解放(極限の最適化)
VBAのガベージコレクションは参照カウンタ方式(Reference Counting)に依存しているが、特にSolidWorks APIのような巨大なCOMオブジェクトを扱う場合、VBAが自動的にメモリを解放するタイミングは極めて曖昧である。
マクロの実行を繰り返すうちにSolidWorksの動作が重くなり、最終的にVBAがクラッシュする現象(メモリリーク)に直面した開発者も多いはずだ。これを防ぐためには、取得したオブジェクト階層(`SldWorks` -> `ModelDoc2` -> `Configuration` -> `Component2` など)を、取得した順序とは逆の順序で `Nothing` を代入して明示的に解放しなければならない。
正しいオブジェクト解放のイディオム
Public Sub ProcessActiveModel_Optimized()
Dim swApp As Object
Dim swModel As Object
Dim swPart As Object
‘ 1. アプリケーション取得
If Not GetSolidWorksApplication(swApp) Then Exit Sub
On Error GoTo CleanUp
‘ 2. ドキュメント取得(ActiveDocを使う場合でも局所的に限定する)
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbExclamation
GoTo CleanUp
End If
‘ ドキュメントタイプが部品(Part)であるか検証
If swModel.GetType() <> 1 Then ‘ 1 = swDocPART
MsgBox “このマクロは部品ドキュメントでのみ実行可能です。”, vbExclamation
GoTo CleanUp
End If
Set swPart = swModel
‘ — ここに実際の重い処理を記述 —
‘ 例: 独自のプロパティ追加やジオメトリ解析など
CleanUp:
‘ 3. 逆順での厳密な参照解除(メモリリークの完全防止)
If Not swPart Is Nothing Then Set swPart = Nothing
If Not swModel Is Nothing Then Set swModel = Nothing
If Not swApp Is Nothing Then Set swApp = Nothing
‘ 強制的なガベージコレクションの誘発(VBA単体では完全ではないが有効)
DoEvents
End Sub
—
4. レガシー環境とシステム間連携における実践的知見
社内のPDM/PLMシステムや外部ERP、あるいはExcelマクロからSolidWorksをバッチ処理で制御する場合、GUIスレッドとバックグラウンドCOMプロセスの衝突が問題になる。
1. ユーザーインタラクションの無効化 (`UserControl` / `Visible`)
外部から `CreateObject` で起動されたSolidWorksは、デフォルトでバックグラウンドプロセスとして動作する可能性がある。マクロ実行中はユーザーの誤操作を防ぎ、かつ描画負荷を軽減するために以下のプロパティを制御せよ。
swApp.UserControl = False ‘ ユーザーによる直接操作を一時的に制限(※注意して使用すること)
swApp.Interactive = False ‘ 画面描画やポップアップを抑制し、処理速度を最大化
※注意: 処理の最後やエラーハンドリング時には必ず `True` に戻すこと。これを怠るとSolidWorksプロセスがゾンビ化し、タスクマネージャーからの強制終了を余儀なくされる。
2. ファイルオープン時のサイレントモード活用
外部システム連携において、エラーメッセージダイアログ(「参照ファイルが見つかりません」など)でVBAの処理が完全にフリーズする現象は、自動化における最大の悪夢である。ドキュメントを開く際は、必ずオプションを指定してサイレントモードで実行すること。
Dim errors As Long
Dim warnings As Long
Dim swModel As Object
‘ 完全にサイレント(UIを出さず、デフォルト動作で開く)
Set swModel = swApp.OpenDoc6(“C:\Data\Sample.sldprt”, 1, 1, “”, errors, warnings)
If swModel Is Nothing Then
‘ エラーコード(errors)をビット演算で解析し、ログに記録する
Call WriteErrorLog(errors)
End If
—
総括
SolidWorks VBAの開発において、`SldWorks` オブジェクトとドキュメントの制御は単なる「お作法」ではない。それはシステムの安定性、メモリの整合性、そして業務インフラとしての信頼性を担保する唯一の防衛線である。
- `ActiveDoc` への盲目的な依存を捨てよ。
- オブジェクトは必ずスコープの最後で逆順に `Nothing` を代入して解放せよ。
- 例外発生時を見据えたクリーンアップパス(`GoTo CleanUp`)を絶対に実装せよ。
この極限の知見を実装に落とし込むことで、あなたの書くSolidWorksマクロは、単なる「お遊びのスクリプト」から、過酷な製造業の現場を支える「堅牢なエンタープライズ・オートメーション」へと昇華する。
