「マクロが止まったら終わり」を卒業する。図面自動生成をプロのシステムへと昇華させる「堅牢なリトライ機構」の実装術
こんにちは。現場の自動化設計を支えるエンジニアの皆さん。
今日は、少し踏み込んだ、でも「現場で生き残るために絶対に避けては通れない」極めて重要なテーマについてお話ししましょう。
皆さんは、こんな経験はありませんか?
「30分かけて走らせた大規模な図面自動生成マクロが、終了間際でネットワークの瞬断が起き、エラーを吐いて真っ白な状態で止まってしまった……」
「マクロの記録で作ったコードを、なんとなく `On Error Resume Next` でエラーを無視するように書き換えたけれど、どこで何が起きたか分からず、結局データが壊れてしまった……」
もし心当たりがあるなら、おめでとうございます。あなたは今、「スクリプト作成者」から「自動化エンジニア」へ脱皮する境界線に立っています。
今日は、単なるコードの書き方ではなく、「失敗することを前提とした、プロフェッショナルな設計思想」を伝授します。
1. なぜ「マクロの記録」では、プロの現場で通用しないのか?
SolidWorksの「マクロの記録」は、素晴らしい学習ツールです。しかし、記録されたコードには決定的な欠落があります。それは「例外(エラー)への対処」と「状態の管理」です。
「On Error Resume Next」という名の劇薬
初学者が最初に手にする魔法の言葉が `On Error Resume Next` です。これは「エラーが出ても無視して次の行へ進め」という命令です。
しかし、図面生成のような重いプロセスにおいて、これは非常に危険です。
- ネットワーク切断: 図面を開く瞬間にサーバーとの通信が切れた場合、オブジェクト(`DrawingDoc`)は `Nothing` になります。
- COM例外: SolidWorksの内部処理が追いつかず、APIが一時的に応答不能になることがあります。
ここでエラーを無視して進むと、存在しないオブジェクトに対して「ビューを配置せよ」という命令が飛び、プログラムは制御不能なクラッシュを引き起こします。「エラーを隠す」のではなく、「エラーを検知し、正しく対処する」。これがプロの設計です。
2. 究極の設計思想:イベント駆動型リトライと例外安全
今回私たちが実装するのは、以下の3つの柱を持つ「セーフティネット機構」です。
1. State Machine(状態管理): 今、図面のどの工程(ファイル作成中、ビュー配置中、保存中)にいるのかを常に記録します。
2. Exponential Backoff Retry(指数バックオフ・リトライ): エラーが起きた際、即座に再試行するのではなく、少し間隔を空けて(例:1秒、2秒、4秒…)再試行します。これにより、ネットワークの復帰を待ちます。
3. Exception Safety(例外安全): もしリトライしてもダメだった場合、中途半端なファイルを残さず、安全にクリーンアップ(終了処理)を行います。
3. 実装コード:堅牢な図面生成エンジンのテンプレート
ここでは、クラスモジュールを活用した高度な構造を紹介します。VBAでクラスを使うのは、プロフェッショナルへの第一歩です。
手順1:クラスモジュール `clsDrawingAutomator` の作成
このクラスが、図面生成の「司令塔」となり、エラーを監視します。
' --- Class Module: clsDrawingAutomator ---
Option Explicit
' 状態を定義するための列挙型
Public Enum GenerationState
State_Idle
State_CreatingFile
State_AddingViews
State_Saving
State_Completed
State_Failed
End Enum
Private swApp As SldWorks.SldWorks
Private currentState As GenerationState
Private maxRetries As Integer
' 初期化
Private Sub Class_Initialize()
currentState = State_Idle
maxRetries = 3 ' 最大3回までリトライ
End Sub
' メインの実行メソッド
Public Sub ExecuteDrawingProcess(templatePath As String, savePath As String)
Dim retryCount As Integer
Dim success As Boolean
Set swApp = Application.SldWorks
success = False
retryCount = 0
' --- メインループ(リトライ機構) ---
Do While retryCount <= maxRetries And Not success
On Error GoTo ErrorHandler
' 状態に応じて処理を分岐(ステートマシン)
Select Case currentState
Case State_Idle, State_CreatingFile
currentState = State_CreatingFile
Call CreateDrawingStep(templatePath)
Case State_AddingViews
Call AddViewsStep()
Case State_Saving
Call SaveStep(savePath)
currentState = State_Completed
success = True
End Select
' 成功したらループを抜ける
If success Then Exit Do
ErrorHandler:
retryCount = retryCount + 1
Debug.Print "Error encountered at State: " & currentState & ". Attempt: " & retryCount
' エラーの種類に応じた高度な判定(ここでは簡易的に全てリトライ対象とする)
If retryCount <= maxRetries Then
' 指数バックオフ:リトライ間隔を徐々に伸ばす (1s, 2s, 4s...)
Dim waitTime As Double
waitTime = (2 ^ (retryCount - 1))
Debug.Print "Waiting " & waitTime & " seconds before retry..."
' VBAで待機するための簡易的なSleep(実際にはAPIを使用)
Dim startTime As Double
startTime = Timer
Do While Timer < startTime + waitTime
DoEvents ' SolidWorksの操作をブロックしないために重要!
Loop
' 状態を「最初からやり直し」にするか「中断した所から」にするかは設計次第
' 今回は安全のため、ファイル作成からやり直す設計にします
currentState = State_Idle
Else
' リトライ上限に達した場合
currentState = State_Failed
MsgBox "致命的なエラーが発生しました。リトライ上限に達しました。", vbCritical
Call Cleanup
Exit Sub
End If
Loop
If success Then
MsgBox "図面生成が正常に完了しました!", vbInformation
End If
End Sub
' --- 各ステップの個別メソッド(ここに具体的なAPI操作を記述) ---
Private Sub CreateDrawingStep(path As String)
Dim swDoc As SldWorks.DrawingDoc
Set swDoc = swApp.NewDocument(path, 0, 0, 0)
If swDoc Is Nothing Then Err.Raise vbObjectError + 513, "CreateDrawing", "Template not found or COM error"
Debug.Print "Step: File Created"
' 次のステートへ
currentState = State_AddingViews
End Sub
Private Sub AddViewsStep()
' ここにビュー配置の複雑なAPI処理を記述
' 例: swDoc.CreateDrawViewFromModelView3(...)
Debug.Print "Step: Views Added"
currentState = State_Saving
End Sub
Private Sub SaveStep(path As String)
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.ActiveDoc
Dim errors As Long, warnings As Long
' 保存実行
Dim status As Boolean
status = swModel.SaveAs3(path, 0, 2) ' 2 = swSaveAsOptions_Silent
If Not status Then Err.Raise vbObjectError + 514, "SaveStep", "Save failed (Network issue?)"
Debug.Print "Step: Saved"
End Sub
' 異常終了時のクリーンアップ
Private Sub Cleanup()
Debug.Print "Cleaning up resources..."
' 未保存のドキュメントを閉じるなどの処理
On Error Resume Next
swApp.CloseDoc swApp.ActiveDoc.GetTitle
End Sub
手順2:標準モジュールからの呼び出し
' --- Standard Module ---
Sub RunProfessionalAutomation()
Dim automator As New clsDrawingAutomator
Dim template As String
Dim destination As String
template = "C:\Templates\A3_Standard.drwdot"
destination = "C:\Output\Part_Drawing_001.SLDDRW"
' 実行!
automator.ExecuteDrawingProcess template, destination
End Sub
4. ここが「プロ」の分かれ道:技術的ポイントの解説
このコードには、初心者が陥りがちな罠を回避するための「知恵」が詰まっています。
① `DoEvents` の重要性
リトライ待機中に `Wait` を使う際、ただのループではなく `DoEvents` を入れています。これがないと、待機中にSolidWorksが「応答なし」状態になり、ユーザーが強制終了せざるを得なくなります。「ユーザーの操作権を奪わない」のも、優れたエンジニアの配慮です。
② ステートマシンによる「再開ポイント」の管理
`currentState` 変数によって、「今どこまで進んだか」を管理しています。これにより、エラーが起きた際に「最初からやり直すべきか」「中断した箇所からリトライすべきか」をロジカルに判断できます。
③ 指数バックオフ(Exponential Backoff)
`waitTime = (2 ^ (retryCount – 1))` の部分です。
ネットワークが一時的に不安定な場合、即座に再試行しても失敗する確率が高いです。少しずつ待ち時間を増やすことで、システムが自然に復旧するのを待つ、非常にスマートな回避策です。
5. まとめ:次は、あなた自身のシステムを構築しよう
いかがでしたでしょうか?
「マクロの記録」で得た知識は、いわば「単語」です。しかし、今回紹介したようなリトライ機構や状態管理は、それらを組み合わせて物語を作る「文法」にあたります。
「エラーは起きるもの。だからこそ、どう起きても大丈夫な仕組みを作る」
このマインドセットを持てたとき、あなたの書くコードは「ただの自動化」から「信頼されるシステム」へと進化します。
最初は難しく感じるかもしれません。でも、一つずつクラスモジュールを使い、エラーハンドリングを丁寧に書いていくことで、必ず習得できます。もしエラーにぶつかったら、それは成長のチャンスです。
応援しています。さあ、次の自動化プロジェクトへ踏み出しましょう!
