【入門編】【上級プロ向け】図面自動生成における非同期・バックグラウンド処理とSolidWorksイベントハンドリング – SolidWorks VBA解析バイブル

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

【極限の知見】SolidWorks VBAで「フリーズ」を克服する。イベント駆動型図面自動生成への道

こんにちは。現場の設計自動化に取り組むエンジニアの皆さん、日々、膨大な図面作成やPDF変換の作業と戦っていることと思います。

「マクロの記録」から一歩踏み出し、コードを書き始めた皆さんが、必ずと言っていいほどぶつかる巨大な壁があります。それは……「実行中にSolidWorksが固まって(フリーズして)動かなくなる」という問題です。

重いアセンブリから図面を生成したり、数百枚の図面をPDF化しようとしたりすると、画面が真っ白になり、マウス操作も受け付けなくなる。そして、本当にフリーズしたのか、処理中なのか分からず、最悪の場合、タスクマネージャーで強制終了してデータを失う……。

「そんなの、プログラミングが難しいから仕方ない」なんて思わないでください。これは、VBAの書き方ではなく、「SolidWorksというソフトウェアの生命周期(ライフサイクル)」を理解していないことが原因なのです。

今日は、単なるコードの書き方ではなく、プロフェッショナルが実践する「イベントハンドリング」という概念を使って、SolidWorksを制御する極限の技術を伝授します。ここをクリアすれば、あなたはもう「マクロを作る人」ではなく、「自動化システムを設計するエンジニア」へと進化できます。

1. なぜ、あなたのマクロは「フリーズ」するのか?

まず、敵を知ることから始めましょう。なぜフリーズが起きるのか。

多くの初学者が書くコードは、以下のような「命令型(Imperative)」のスタイルです。

1. 図面を開け
2. ビューを配置せよ
3. 尺度を変更せよ
4. PDFで保存せよ

この命令が実行されている間、SolidWorksのメインスレッド(計算を行う中心部)は、あなたの書いたコードの指示を一つずつ消化することに全力を注ぎます。その間、「マウスのクリック」や「画面の更新」といった、ユーザーとの対話(UI処理)は完全に後回しにされるのです。これがフリーズの正体です。

プロのエンジニアは、ここで「命令」を投げっぱなしにしません。「処理が終わったら、教えてね」という「イベント駆動型(Event-Driven)」の考え方を導入します。

2. 「イベント駆動型」という魔法の考え方

「イベント駆動」とは、簡単に言えば「待ち伏せ」です。

例えば、あなたがレストランのシェフだとしましょう。

  • 命令型: 料理ができるまで、厨房の入り口にずっと立ち尽くして見張っている(これでは他のお客さんの注文が取れません=フリーズ)。
  • イベント駆動: 料理ができたら「ベル」を鳴らすようシェフに頼んでおき、自分はホールで接客する。ベルが鳴ったときだけ、料理を取りに行く(これがプロの動きです)。

SolidWorks VBAにおける「ベル」こそが、Event Handler(イベントハンドラー)です。図面が作成された、ビューが配置された、ファイルが保存された……といった「特定の出来事(イベント)」が発生した瞬間に、あらかじめ用意しておいたプログラムを自動的に起動させる仕組みです。

3. 【実践】図面イベントを検知するプロフェッショナルな実装

では、具体的にどう実装するか。ここでは、図面(DrawingDoc)に対して何かが起きたことを検知する、クラスモジュールを用いた高度なパターンを紹介します。

VBAでイベントを扱うには、「クラスモジュール」を使うのが鉄則です。標準モジュールに書くだけでは、イベントの「待ち伏せ」はできません。

ステップ1:イベントを監視する「監視役」クラスを作る

まず、挿入メニューから「クラスモジュール」を追加し、名前を `CDrawingEventHandler` に変更してください。

' --- クラスモジュール: CDrawingEventHandler ---
Option Explicit

' SolidWorksのイベントをキャッチするための変数
Private WithEvents swApp As SldWorks.SldWorks
Private swDrawingDoc As SldWorks.DrawingDoc

' 監視を開始するメソッド
Public Sub Initialize(ByVal App As SldWorks.SldWorks)
    Set swApp = App
    Debug.Print "監視を開始しました。図面操作を待機中..."
End Sub

' 図面ドキュメントがアクティブになった時に呼ばれるイベント
' (注: 実際の実装では、より詳細な IDrawingDocEventHandler インターフェースを使用します)
Private Sub swApp_ActiveDocChangeNotify(ByVal DocumentType As Long)
    Dim swModel As SldWorks.ModelDoc2
    Set swModel = swApp.ActiveDoc
    
    ' アクティブなドキュメントが「図面」かどうかを判定
    If Not swModel Is Nothing Then
        If swModel.GetType = swDocDRAWING Then
            Debug.Print "【検知】図面がアクティブになりました: " & swModel.GetTitle
            
            ' ここに「図面が開かれた直後に自動で行いたい処理」を記述する
            ' 例: 自動でシートフォーマットを適用する、など
            Call AutoFormatDrawing(swModel)
        End If
    End If
End Sub

' 図面を自動整形するプロフェッショナルな処理(例)
Private Sub AutoFormatDrawing(ByVal swModel As SldWorks.ModelDoc2)
    Dim swDraw As SldWorks.DrawingDoc
    Set swDraw = swModel
    
    ' ここで重い処理を行う前に、UIへの通知を検討する
    ' プロの技: 処理中にユーザーが操作しても壊れないよう、エラーハンドリングを徹底する
    On Error GoTo ErrorHandler
    
    Debug.Print "自動フォーマットを実行中..."
    
    ' --- ここに実際の図面操作ロジックを記述 ---
    ' 例: swDraw.SetupSheet ...
    
    Debug.Print "フォーマット完了。"
    Exit Sub

ErrorHandler:
    Debug.Print "エラー発生: " & Err.Description
End Sub

ステップ2:標準モジュールから監視を開始する

次に、通常の標準モジュールから、この「監視役」を呼び出します。

' --- 標準モジュール ---
Option Explicit

' 監視役のインスタンスを保持するための変数(重要:プロシージャが終わると消えてしまうため)
Dim Watcher As CDrawingEventHandler

Sub StartDrawingMonitor()
    Dim swApp As SldWorks.SldWorks
    Set swApp = Application.SldWorks
    
    ' 監視役のインスタンスを生成
    Set Watcher = New CDrawingEventHandler
    
    ' 監視を開始
    Watcher.Initialize swApp
    
    MsgBox "図面監視モードに入りました。" & vbCrLf & _
           "図面ファイルを開くと、自動的に処理が走ります。", vbInformation
End Sub

Sub StopMonitor()
    ' 監視を終了(インスタンスを破棄)
    Set Watcher = Nothing
    MsgBox "監視を終了しました。", vbExclamation
End Sub

4. ここがプロの分かれ道:陥りやすい罠と回避策

この実装をマスターするために、絶対に忘れてはいけない「3つの黄金律」があります。

① オブジェクトの生存期間(ライフサイクル)を管理せよ

上記のコードで、`Dim Watcher As CDrawingEventHandler` を標準モジュールの最上部(宣言部)に書いた理由に気づきましたか?
もしこれを `StartDrawingMonitor` の中(ローカル変数)に書いてしまうと、マクロの実行が終わった瞬間に `Watcher` 変数がメモリから消え、監視役(イベントハンドラー)も死んでしまいます。「イベントを待ち続けるなら、そのオブジェクトは生き続けさせなければならない」。これが鉄則です。

② `DoEvents` の使いすぎに注意せよ

フリーズを防ぐための「おまじない」として、ループの中に `DoEvents` を入れる手法をよく見かけます。

Do While Processing
    DoEvents ' ユーザーの操作を一時的に受け付ける
Loop

これは小規模な処理なら有効ですが、大規模な自動化では「ユーザーが意図しない操作(図面を閉じる、設定を変える等)」を割り込ませてしまい、コードがクラッシュする原因になります。今回紹介した「イベント駆動」こそが、最も安全でスマートな解決策なのです。

③ 重い処理は「分割」して考える

たとえイベント駆動であっても、一つのイベント内で10分かかる処理を走らせれば、その間はやはりフリーズします。
プロは、「大きなタスクを、小さなイベントの連鎖に分解する」ことを考えます。
「図面を開く」→「(イベント検知)」→「ビューを置く」→「(イベント検知)」→「PDF化」……というように、一気にやろうとせず、SolidWorksの動作に寄り添う設計を心がけてください。

最後に:エンジニアとしての第一歩

いかがでしたか?
「マクロの記録」で生成されたコードは、あくまで「何をしたか」の記録です。しかし、今回学んだ手法は「どのようにシステムを制御するか」という設計思想です。

最初はクラスモジュールやイベントハンドリングは難しく感じるかもしれません。しかし、一度これをマスターすれば、あなたの作るツールは「壊れにくく、使いやすい、プロ仕様のアプリケーション」へと劇的に進化します。

「動けばいい」から、「美しく、堅牢に動かす」へ。
その挑戦を、私は心から応援しています。さあ、コードを書き直してみましょう!

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