SolidWorks VBAを掌握する極限の知見
【上級プロ】アセンブリ構築プロセス全体をロールバック可能なトランザクション構造で包み込み、例外発生時に一瞬で初期状態へ復元
SolidWorks VBAによる大規模アセンブリの自動生成において、最大の悪夢は何か。
それは、数千点の部品配置と複雑な合致(Mate)定義の最中、プロセスが中途半端に破綻し、「ゴミデータが散乱した汚染アセンブリ」がディスク上に残される瞬間である。
素人が書いたスクリプトは、エラーが発生した時点で止まる。結果として、画面には不完全なツリー構造と、外部参照エラーの爆弾を抱えたファイルが残骸として放置される。プロのエンジニアが作るべきシステムは、そうではない。トランザクションの概念を持たせ、「全か無か(All-or-Nothing)」を完全に担保する堅牢性こそが、実務に耐えうる唯一のアーキテクチャである。
今回は、SolidWorks APIの深層とVBAの限界を突破し、アセンブリ構築プロセス全体をロールバック可能なトランザクション構造で包み込む極限の設計手法を解説する。
—
1. SolidWorks APIにおける「トランザクション」の幻想と現実
データベースの世界とは異なり、SolidWorksのCOMオブジェクト群には、ネイティブな `BeginTransaction` や `Rollback` といった美しいメソッドは用意されていない(一部のフィーチャー編集を除く)。
そのため、アセンブリ構築のトランザクションは、以下の戦略の組み合わせによって自衛する必要がある。
1. サイレントモード(UI非表示)による爆速処理と安全圏の確保
処理中の画面描画やフィーチャー再構築を完全に抑制し、例外発生時の視覚的ノイズと無駄なリソース消費を排除する。
2. 一時ファイル(サンドボックス)戦略とインメモリ管理
新規アセンブリをディスクに即座に書き込まず、メモリ上で構築を完結させる。途中で異常を検知した場合は、ファイル保存を行わずにドキュメントを破棄する。
3. 厳格なオブジェクト参照の解放(メモリリークの根絶)
VBAのガベージコレクションは頼りにならない。COMラッパーがメモリ上に残存すると、ファイルロックやSolidWorks本体の不安定化を招く。
—
2. 実装アーキテクチャ:トランザクション制御アセンブリビルダー
以下のコードは、エラー発生時に一切のゴミを残さず、かつパフォーマンスを極限まで高めたアセンブリ構築クラスの骨子である。
‘ ==============================================================================
‘ 致命的な例外をハンドリングし、完全なロールバックを保証するトランザクション基盤
‘ ==============================================================================
Option Explicit
Private swApp As SldWorks.SldWorks
Private swModel As SldWorks.ModelDoc2
Private swAssy As SldWorks.AssemblyDoc
‘ トランザクションの状態管理
Private m_IsTransactionActive As Boolean
Public Sub BeginTransaction()
Set swApp = Application.SldWorks
If swApp Is Nothing Then Exit Sub
m_IsTransactionActive = True
‘ 1. パフォーマンス極限最適化:UI更新、再構築、自動プレビューの完全停止
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swInteractiveSelPrehighlight, False
swApp.DocumentVisible False, 1 ‘ 非表示モードで新規ドキュメント作成の布石
‘ 2. メモリ上での新規アセンブリ作成(ディスクを汚染しない)
Dim defaultTemplate As String
defaultTemplate = swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplateAssembly)
Set swModel = swApp.NewDocument(defaultTemplate, 0, 0, 0)
If swModel Is Nothing Then
Call RollbackTransaction
Err.Raise 9999, “Transaction”, “アセンブリドキュメントの生成に失敗しました。”
End If
Set swAssy = swModel
‘ 再構築の凍結(Bulk Editモード)
swModel.EditRebuild
End Sub
Public Sub CommitTransaction()
If Not m_IsTransactionActive Then Exit Sub
On Error GoTo ErrorHandler
‘ 整合性検証と最終再構築
swModel.ForceRebuild3 False
‘ UIの復元と可視化
swApp.DocumentVisible True, 1
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swInteractiveSelPrehighlight, True
m_IsTransactionActive = False
‘ クリーンアップ
Set swAssy = Nothing
Set swModel = Nothing
Set swApp = Nothing
Exit Sub
ErrorHandler:
Call RollbackTransaction
Err.Raise Err.Number, “CommitTransaction”, “コミット中に致命的エラーが発生しました: ” & Err.Description
End Sub
Public Sub RollbackTransaction()
If Not m_IsTransactionActive Then Exit Sub
On Error Resume Next
‘ 1. 開いているドキュメントを保存せずに強制閉じる (Dirtyフラグを無視)
If Not swModel Is Nothing Then
Dim modelTitle As String
modelTitle = swModel.GetTitle()
swApp.CloseDoc modelTitle
End If
‘ 2. UIと環境設定の強制復元
If Not swApp Is Nothing Then
swApp.DocumentVisible True, 1
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swInteractiveSelPrehighlight, True
End If
‘ 3. オブジェクト参照の完全破棄(メモリリーク防止)
Set swAssy = Nothing
Set swModel = Nothing
Set swApp = Nothing
m_IsTransactionActive = False
End Sub
—
3. クライアントコード:エラー発生時の自動ロールバック実証
上記のトランザクションクラス(仮に `AssemblyTransaction` とする)を呼び出すメインルーチンは、以下のように極めてシンプルかつ堅牢に記述されなければならない。
Sub Main_BuildAssemblySafely()
Dim tx As AssemblyTransaction
Set tx = New AssemblyTransaction
‘ 【重要】構造化エラーハンドリングの必須化
On Error GoTo Catch
‘ トランザクション開始(サンドボックス環境の構築)
tx.BeginTransaction
‘ — ここからアセンブリ構築のビジネスロジック —
‘ 例: 大量部品の挿入や合致定義
Call InsertComponentsAndMates_Core()
‘ ———————————————
‘ 正常終了時のみコミット
tx.CommitTransaction
MsgBox “アセンブリの構築が正常に完了しました。”, vbInformation
Exit Sub
Catch:
‘ 異常発生時は即座にロールバック(ディスクには何も残らない)
tx.RollbackTransaction
MsgBox “エラーが発生したため、処理をロールバックしました。” & vbCrLf & _
“詳細: ” & Err.Description, vbCritical
Set tx = Nothing
End Sub
Private Sub InsertComponentsAndMates_Core()
‘ 意図的なエラー発生テスト(例:存在しないパスの指定や不正な合致パラメータ)
‘ ここでエラーが発生すると、呼び出し元の Catch ラベルへジャンプし、
‘ トランザクションクラスが未保存ドキュメントを完全に消去する。
‘ Dim swComponent As SldWorks.Component2
‘ Set swComponent = swAssy.AddComponent5(…)
‘ If swComponent Is Nothing Then Err.Raise 1001, , “部品の配置に失敗”
‘ テスト用意図的エラー
Err.Raise 515, “Core”, “予期せぬ外部例外:コンポーネント配置失敗”
End Sub
—
4. チーフアーキテクトからの実務的助言:メモリ最適化とCOMの呪縛
VBA環境におけるSolidWorks API開発では、変数のスコープとオブジェクトのライフサイクル管理が生死を分ける。
- `Nothing` 代入の徹底
VBAのローカル変数はプロシージャ終了時に解放されるが、COMオブジェクト(特に `SldWorks` や `ModelDoc2`)は参照カウントが複雑に絡み合うため、明示的に `Set xxx = Nothing` を記述しないとメモリ上にゾンビプロセスとして残存する。
- `On Error Resume Next` の乱用禁止
エラーを隠蔽する目的で `Resume Next` を多用すると、トランザクションのロールバックトリガーが機能しなくなる。エラーは必ず捕捉(Catch)し、上位へ伝播させるか、安全な破棄ルーチンへ流し込むこと。
このトランザクション構造をあなたのシステムに導入した瞬間から、「途中で止まったゴミファイル掃除」という無駄なエンジニアリングコストは永久に消滅する。プロたる者、コードの美しさだけでなく、「失敗したときの美しさ(後始末の完璧さ)」にこそこだわれ。
