【上級プロ向け】図面ファイルの完全バッチ処理エンジン:破損ファイル・エラーの例外安全な自動リトライ機構
深夜、静まり返ったオフィス。あなたは「数千枚の図面を自動生成し、PDF化して保存する」という壮大なバッチジョブを走らせました。
朝、意気揚々と出社したあなたを待っていたのは、「SolidWorksが応答なし(ハングアップ)になり、10枚目の処理で止まっている画面」でした。
原因は、たった一つの「参照ファイルが見つかりません」というダイアログ。あるいは、たった一つの「破損した部品ファイル」。
「マクロの記録」からステップアップしたあなたが次に目指すべきは、単に「動くコード」を書くことではありません。「予期せぬ事態に直面しても、止まらずに最後まで走り抜ける、強靭なエンジン」を設計することなのです。
今日は、プロの自動化エンジニアが現場で使う「例外安全(Exception Safe)」なバッチ処理の設計思想を、魂を込めて伝授します。ここをクリアすれば、あなたのVBAは「便利ツール」から「信頼されるシステム」へと進化します。
1. なぜ、あなたのマクロは「止まって」しまうのか?
一般的なマクロ(マクロの記録で作ったようなコード)には、致命的な弱点が2つあります。
① 「ダイアログの壁」
SolidWorksは、ファイルを開く際に「参照が見つかりません」「ファイルが読み取り専用です」といったダイアログを頻繁に出します。マクロがこれらを検知できないと、ユーザーの操作を待つ状態になり、プログラムは事実上の「停止(ハングアップ)」に陥ります。
② 「連鎖的な崩壊」
1つのファイルでエラーが起きたとき、そのエラーを適切に「捕まえて(Catch)」処理しないと、VBA全体の実行が強制終了してしまいます。1,000枚のうち1枚のミスで、残り999枚の処理を諦めるのは、エンジニアとしてあまりに惜しいことです。
2. 堅牢なエンジンのための「3つの設計思想」
プロの設計では、以下の3つの柱を実装します。
| 設計思想 | 役割 | 具体的な手法 |
|---|---|---|
| 例外処理(Error Handling) | エラーが起きても、プログラムを止めずに次のファイルへ進める。 | `On Error GoTo` による制御 |
| ダイアログの抑制(Suppression) | SolidWorksの「おせっかい」な警告を、プログラム側で黙らせる。 | `swApp.SetUserPreferenceToggle` |
| リトライ機構(Retry Logic) | 一時的なネットワークエラーやファイルロックに対し、数回再試行する。 | `For…Next` ループによる再試行 |
3. 【実践】完全バッチ処理エンジンの実装例
それでは、実際に使えるレベルのコードを見ていきましょう。このコードは、単なる例ではなく、実務でそのまま「骨組み」として使えるように構成しています。
' =================================================================
' 業務自動化エンジニア向け:堅牢な図面バッチ処理エンジン
' 設計思想:エラーを捕まえ、ログを残し、決して止まらない。
' =================================================================
Option Explicit
' 処理結果を定義するための列挙型(コードの可読性を劇的に上げます)
Enum ProcessResult
Success = 0
Error_FileOpen = 1
Error_Processing = 2
Error_RetryFailed = 3
End Enum
Sub MainBatchProcess()
Dim swApp As SldWorks.SldWorks
Dim fileList As Collection
Dim targetFile As Variant
Dim result As ProcessResult
Dim retryCount As Integer
Dim maxRetries As Integer: maxRetries = 3 ' 最大リトライ回数
Set swApp = Application.SldWorks
' 1. 環境の最適化:ダイアログを極限まで抑制する
SetupEnvironment swApp
' 2. ファイルリストの取得(本来はフォルダスキャン等で行う)
Set fileList = GetFileList("C:\Work\Drawings\")
Debug.Print "--- バッチ処理開始: " & Now & " ---"
' 3. メインループ
For Each targetFile In fileList
result = ErrorSafeProcess(swApp, CStr(targetFile), maxRetries)
' 4. ログ出力(後でExcel等に書き出すのがプロの仕事)
LogResult targetFile, result
If result <> Success Then
Debug.Print "⚠️ 警告: " & targetFile & " はスキップされました。"
Else
Debug.Print "✅ 成功: " & targetFile
End If
Next targetFile
Debug.Print "--- バッチ処理完了: " & Now & " ---"
MsgBox "全ての処理が終了しました。ログを確認してください。"
End Sub
' -----------------------------------------------------------------
' 【核心部】例外安全な個別ファイル処理関数
' -----------------------------------------------------------------
Function ErrorSafeProcess(swApp As SldWorks.SldWorks, filePath As String, maxRetries As Integer) As ProcessResult
Dim swModel As SldWorks.ModelDoc2
Dim attempt As Integer
Dim success As Boolean
success = False
' リトライループ
For attempt = 1 To maxRetries
On Error GoTo ErrorHandler ' エラーが発生したら ErrorHandler へジャンプ
' ファイルを開く(OpenDoc6を使用。これがAPI操作の定石です)
' swOpenDocOptions_Silent を指定することで、可能な限りダイアログを抑止
Set swModel = swApp.OpenDoc6(filePath, swDocDRAWING, swOpenDocOptions_Silent, "", 0, 0)
If Not swModel Is Nothing Then
' --- ここに図面操作のメインロジックを書く ---
' 例: ビュー配置、シートフォーマット変更、PDF保存など
PerformDrawingLogic swModel
' -----------------------------------------
' 正常終了
success = True
swApp.CloseDoc swModel.GetTitle
Exit For
Else
' ファイルが開けなかった場合
Err.Raise vbObjectError + 513, "ErrorSafeProcess", "ファイルを開けませんでした。"
End If
ErrorHandler:
' エラーが発生した場合の挙動
Debug.Print " [Attempt " & attempt & "] Error in " & filePath & ": " & Err.Description
' モデルが開いていたら閉じる(メモリリーク防止。これが非常に重要!)
If Not swModel Is Nothing Then
swApp.CloseDoc swModel.GetTitle
Set swModel = Nothing
End If
' リトライ待ち(少し時間を置くとネットワークエラー等に有効)
DoEvents
' 最後の試行で失敗した場合は、結果を返して終了
If attempt = maxRetries Then
ErrorSafeProcess = Error_RetryFailed
Exit Function
End If
Next attempt
If success Then
ErrorSafeProcess = Success
Else
ErrorSafeProcess = Error_FileOpen
End If
End Function
' -----------------------------------------------------------------
' 環境設定:SolidWorksの「おせっかい」を封印する
' -----------------------------------------------------------------
Sub SetupEnvironment(swApp As SldWorks.SldWorks)
' ユーザーの操作を介入させない設定(バッチ処理の鉄則)
swApp.UserControl = False
' 参照エラーなどのダイアログを抑制する設定(API経由での制御)
' ※環境によって設定可能な項目は異なります
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisplayMissingFilesDialog, False
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swMissingFilesDialog, False
End Sub
' -----------------------------------------------------------------
' ダミー関数群(実装のイメージを掴むためのもの)
' -----------------------------------------------------------------
Sub PerformDrawingLogic(swModel As SldWorks.ModelDoc2)
' ここに実際の図面操作ロジックを記述
' 例: swModel.Extension.SelectByID2 "Sheet1", "SHEET", 0, 0, 0, False, 0, Nothing, 0
End Sub
Function GetFileList(folderPath As String) As Collection
' 本来は FileSystemObject を使用してファイル一覧を取得する
Dim col As New Collection
col.Add folderPath & "PartA.slddrw"
col.Add folderPath & "BrokenPart.slddrw" ' 破損を想定
col.Add folderPath & "PartC.slddrw"
Set GetFileList = col
End Function
Sub LogResult(filePath As String, res As ProcessResult)
' 本来はCSVやExcelに書き出す。ここではイミディエイトウィンドウへ
' 実務では、エラー内容とタイムスタンプを必ず残してください
End Sub
4. プロが教える「ここが落とし穴」
コードを読み解く際に、特に意識してほしいポイントを解説します。
① なぜ `OpenDoc6` を使うのか?
`OpenDoc` ではなく `OpenDoc6` を使うのが、プロの流儀です。`OpenDoc6` には `swOpenDocOptions_Silent` という引数があり、これを指定することで「可能な限りダイアログを出さずに開く」という指示をSolidWorksに送ることができます。
② 「メモリリーク」という静かなる敵
エラーが発生したとき、`Set swModel = Nothing` を忘れていませんか?
エラーが起きたまま次のファイルへ進むと、メモリ上に「開こうとして失敗した、あるいは中途半端な状態のモデル」が残り続け、数千枚の処理中にSolidWorksがメモリ不足でクラッシュします。「エラーが起きたら、必ず閉じて、必ずNothingを入れる」。これは鉄則です。
③ `On Error GoTo` の使いどころ
`On Error Resume Next`(エラーを無視して進む)は、デバッグ中には便利ですが、バッチ処理では「禁忌」です。何が起きたのかが分からなくなるからです。
今回のように、エラーをキャッチして「リトライするのか」「ログを残してスキップするのか」という意志を持った制御を行ってください。
5. おわりに:一歩先へ進むあなたへ
今回の実装は、少し複雑に見えたかもしれません。しかし、この「エラーハンドリング」と「リトライ」の構造を一度身につけてしまえば、あなたの作るツールは「誰が、いつ、どんな環境で動かしても、最後まで走り抜ける」という、プロフェッショナルな品質を手に入れます。
「マクロの記録」は、あくまで「操作の書き出し」に過ぎません。
そこから一歩踏み出し、「コンピュータが失敗すること」を前提とした設計ができるようになったとき、あなたは本当の意味で、SolidWorks VBAを掌握したと言えるでしょう。
大丈夫、一歩ずつ進めばいいんです。応援していますよ。
