【実務・中級編】【上級プロ向け】図面自動化プロセスにおける「SolidWorksイベント(SldWorks_FileSaveNotifyなど)」のフックと処理連動 – SolidWorks VBA解析バイブル

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

SolidWorks VBAを掌握する極限の知見:イベント駆動型設計による「止まらない」自動化アーキテクチャ

業務自動化の現場において、多くのエンジニアが陥る致命的な罠がある。それは、「ユーザーの操作を待つマクロ」を作ろうとして、「ユーザーの操作を妨げるツール」へと成り下がってしまうことだ。

「図面を保存したら、自動的にPDFを出力し、PDMに情報を飛ばし、バックアップを作成する」――。
一見、完璧な要件に見える。しかし、これを単純なマクロとして実装すれば、保存ボタンを押した瞬間にSolidWorksが数秒間フリーズし、ユーザーから「重い」「使いにくい」とクレームが殺到するだろう。

プロフェッショナルなエンジニアが目指すべきは、マクロではない。SolidWorksのライフサイクルに深く根を張り、ユーザーの操作を邪魔することなく、裏側で静かに、かつ確実にタスクを完遂させる「イベント駆動型アーキテクチャ」だ。

本稿では、`SldWorks_FileSaveNotify` 等のシステムイベントをフックし、堅牢かつ高パフォーマンスな自動化プロセスを構築するための、極限の設計思想を伝授する。

1. なぜ「マクロ」では不十分なのか:UIスレッドの支配

SolidWorksはシングルスレッドの性質が強く、VBAの実行はメインのUIスレッドを占有する。

一般的な「ボタンを押して実行するマクロ」は、実行中にSolidWorksの操作をロックする。もし、そのマクロの中で「ネットワーク越しに重いデータベースへ書き込みを行う」コードを書いていたらどうなるか? ネットワークの遅延が発生した瞬間、SolidWorksは「応答なし」の状態に陥る。

設計の鉄則:
イベントハンドラ内で行うべきは、「イベントの検知」と「最小限のデータ抽出」のみである。重い処理(ファイルI/O、DB連携、外部アプリケーションの起動)は、必ずハンドラから切り離し、非同期的に、あるいは別プロセスへと委ねる設計にしなければならない。

2. アーキテクチャ設計:Dispatcher(ディスパッチャ)パターン

堅牢なシステムを構築するために、私は常に「Dispatcher(ディスパッチャ)パターン」を推奨している。

1. Event Watcher (VBA Class): SolidWorksのイベントを監視し、発生した瞬間に「何が起きたか(ファイルパス、イベント種別)」という軽量なパケットを作成する。
2. Queue / Log (Data Layer): パケットを即座にローカルの軽量なファイル(JSONやCSV)、あるいはSQLiteなどのローカルDBに書き出す。ここでVBAの責務は終了する。
3. Worker Process (External): VBAとは独立して動作する外部プログラム(Python, C#, もしくは別のSolidWorksインスタンス)が、Queueを監視し、実際の重い処理を実行する。

この分離により、たとえ外部連携でエラーが起きようとも、SolidWorks本体がクラッシュしたりフリーズしたりすることはない。

3. 実装:堅牢なイベント監視クラスの実装例

ここでは、VBA内で完結させつつも、実務に耐えうる「疎結合」を意識したクラスモジュールの実装例を示す。ここでは `SldWorksEvents` を利用する。

Step 1: Class Module (`clsEventWatcher`) の作成

このクラスは、イベントをキャッチし、重い処理へ渡すためのインターフェースを担う。

' Class Name: clsEventWatcher
Option Explicit

' SolidWorks Events Interface
Private WithEvents swAppEvents As SldWorks.SldWorksEvents
Private swApp As SldWorks.SldWorks

' イベント発生時に呼び出されるメソッド
' ユーザーの操作を止めないよう、極力軽量に保つこと
Private Sub swAppEvents_FileSaveNotify(ByVal FileName As String)
    On Error GoTo ErrorHandler
    
    ' 1. 最小限の情報だけを抽出
    Dim eventInfo As String
    eventInfo = "SAVE|" & FileName & "|" & Now
    
    ' 2. 重い処理を直接呼ばず、ログ(キュー)に書き出すだけにする
    ' これが「非同期」への第一歩。実際の処理は外部プロセスに任せる設計が理想。
    Call WriteToEventQueue(eventInfo)

    Exit Sub

ErrorHandler:
    ' イベントハンドラ内でのエラーは、絶対にメインプロセスに波及させてはいけない
    ' ログ出力のみを行い、静かに終了させる
    Debug.Print "Critical Error in EventWatcher: " & Err.Description
End Sub

' キューへの書き込み(極めて高速なファイルI/Oを想定)
Private Sub WriteToEventQueue(ByVal logLine As String)
    Dim fso As Object
    Dim ts As Object
    Const QUEUE_FILE As String = "C:\Temp\sw_event_queue.log"
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    ' Appendモードで開く。ロック時間を最小限にするため、開いてすぐ閉じる。
    Set ts = fso.OpenTextFile(QUEUE_FILE, 8, True)
    ts.WriteLine logLine
    ts.Close
    
    Set ts = Nothing
    Set fso = Nothing
End Sub

' 初期化メソッド
Public Sub Initialize(ByVal app As SldWorks.SldWorks)
    Set swApp = app
    ' SldWorksEventsオブジェクトの生成
    ' 注意: Add-inとして実装する場合は、API経由でより高度な制御が可能
    Set swAppEvents = swApp.GetAddInObject("SldWorks.SldWorksEvents") ' 概念的な記述
    ' ※実際には、Add-in(C#等)からVBAを呼び出すか、
    ' VBA単体では限界があるため、実務ではC#製のアドインをフロントエンドに置くのが定石。
End Sub

Step 2: Standard Module による起動管理

' Standard Module
Option Explicit

Private Watcher As clsEventWatcher

' マクロ実行時に呼び出す
Sub Main()
    Dim swApp As SldWorks.SldWorks
    Set swApp = Application.SldWorks
    
    ' インスタンスの生成
    Set Watcher = New clsEventWatcher
    Watcher.Initialize swApp
    
    MsgBox "Event Watcher Started. Monitoring FileSave events...", vbInformation
End Sub

4. 実務における「地雷」を回避するための3つの極意

コードが書けたとしても、以下の3点を考慮できていなければ、それは「動くが壊れやすい」未熟なコードだ。

① 再帰呼び出し(無限ループ)の防止

`FileSaveNotify` イベント内で、もしプログラムがファイルを保存するコード(`Save3`)を書いてしまったらどうなるか?
「保存」→「イベント発生」→「保存コード実行」→「またイベント発生」……という無限ループに陥り、SolidWorksは即死する。
イベント内でファイル操作を行う場合は、必ず「自分が発行したイベントではないか」を判定するフラグ管理、あるいは特定の条件下でのみ実行するガード条件を徹底せよ。

② ファイルロックの競合

自動バックアップやPDF生成を行う際、SolidWorksがまだファイルを書き込み中である可能性がある。書き込み中に別のプロセスがファイルにアクセスしようとすれば、`Permission Denied` エラーが発生する。
対策: リトライロジック(指数バックオフ法)を実装するか、あるいはイベント発生から数秒のディレイを設けてから処理を開始する設計を組み込め。

③ オブジェクトの生存期間(Lifecycle)

VBAの変数(上記例の `Watcher`)がプロシージャを抜けて破棄されてしまうと、イベント監視も停止する。監視を継続させるためには、グローバル変数として保持するか、アドインとしてメモリ上に常駐させる必要がある。

結論:エンジニアの価値は「例外」への備えにある

図面自動化の本質は、ハッピーパス(正常系)を走らせることではない。ユーザーが予期せぬタイミングでネットワークを切断し、ファイルを強制終了し、不完全なデータで保存したとき、システムがいかにエレガントに、かつ無害に振る舞えるかにある。

イベント駆動型設計は、一見するとオーバーエンジニアリングに見えるかもしれない。しかし、大規模な設計現場において、数千、数万の図面を扱うプロダクション環境では、この「疎結合」と「非同期」の思想こそが、システムの信頼性を担保する唯一の道である。

「ユーザーの作業を止めるな。しかし、裏側では完璧に仕事をこなせ。」

これが、伝説的なアーキテクトが守り続ける鉄則である。

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