壊れたステンシルに怯えないために —— Visio VBAによる「自動復旧&バックアップ」の極意
こんにちは。現場で設計図や自動化ツールを構築しているエンジニアの皆さん、今日もコードを書いていますか?
Visioを使って大規模な図面を自動生成していると、必ずと言っていいほど直面する「厄介な問題」があります。それは、「自作したステンシルファイル(.vssx)が、何らかの理由で開けなくなる(破損する)」という事態です。
ネットワーク越しの保存失敗、突然のPCフリーズ、あるいはファイル共有の競合……。これらが原因で、昨日まで動いていたマクロが突然「ファイルが見つかりません」や「ファイルが破損しています」と悲鳴を上げ、業務が止まってしまう。これは、ツールを「便利」から「不安定」へと一気に引き下げてしまう致命的なトラブルです。
今日は、そんなトラブルを未然に防ぎ、もし壊れても自動で「バックアップから復旧」させる、プロフェッショナルな堅牢(ロバスト)な運用フローをVBAで実装する方法を伝授します。
「マクロの記録」から一歩踏み出し、システムの「信頼性」を設計するエンジニアの視点を手に入れましょう。
1. なぜ「ただ開くだけ」では不十分なのか?
初学者のうちは、以下のようなコードを書きがちです。
' 初心者レベル:壊れたら止まってしまうコード
Sub SimpleOpen()
Dim st As Visio.Document
Set st = Visio.Documents.Open("C:\MyStencil.vssx")
' もしここでファイルが壊れていたら、エラーでマクロが強制終了する
End Sub
このコードの最大の問題は、「エラーが発生したときの出口(エラーハンドリング)がない」ことです。
エンジニアとして一段上のステージに立つには、「失敗することを前提とした設計」が必要です。
1. 整合性チェック: ファイルが正常に開けるか確認する。
2. 自動バックアップ: 正常な状態を常に別の場所に保存しておく。
3. 自動復旧: 失敗したら、バックアップを本番ファイルとして上書き・再ロードする。
この3段構えこそが、現場で通用する「プロの設計」です。
2. 実装の全貌:堅牢なステンシル管理エンジン
それでは、実際に使えるコードを見ていきましょう。ここでは、ファイルの操作を強力に行える `FileSystemObject` (FSO) を活用します。
【完全版】ステンシル・ガード・プロトコル
このコードを標準モジュールに貼り付けてください。
Option Explicit
' --- 設定エリア ---
Private Const STENCIL_PATH As String = "C:\Automation\MyCustomStencil.vssx" ' 本番ファイル
Private Const BACKUP_DIR As String = "C:\Automation\Backups\" ' バックアップ保存先
' ------------------
''' <summary>
''' ステンシルを安全に読み込むメインルーチン
''' </summary>
Sub SafeStencilLoader()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim targetStencil As Visio.Document
Dim isSuccess As Boolean
Debug.Print "--- ステンシル読み込みプロセス開始 ---"
' 1. まずは本番ファイルを読み込めるか試みる
isSuccess = TryOpenStencil(STENCIL_PATH, targetStencil)
If isSuccess Then
Debug.Print "成功: 本番ステンシルを正常にロードしました。"
Else
Debug.Print "警告: 本番ファイルに問題を検知。復旧プロセスを開始します..."
' 2. 失敗した場合、バックアップを探して復旧を試みる
isSuccess = AttemptRecovery(fso, targetStencil)
If Not isSuccess Then
MsgBox "致命的なエラー: バックアップファイルも見つからないか、破損しています。" & vbCrLf & _
"手動での復旧が必要です。", vbCritical, "システムエラー"
Exit Sub
End If
Debug.Print "成功: バックアップからの復旧に成功しました。"
End If
' 3. 読み込み成功後の処理(例:マスターの取得など)
MsgBox "ステンシルが準備できました。業務を開始できます。", vbInformation
' 後片付け(オブジェクトの解放)
Set targetStencil = Nothing
Set fso = Nothing
End Sub
''' <summary>
''' ステンシルを開くことを試みる関数(エラーをトラップする)
''' </summary>
Private Function TryOpenStencil(filePath As String, ByRef doc As Visio.Document) As Boolean
On Error Resume Next ' エラーが起きても次に進む(ここが肝!)
Set doc = Visio.Documents.Open(filePath)
If Err.Number = 0 And Not doc Is Nothing Then
TryOpenStencil = True
Else
' エラー内容をデバッグ出力
Debug.Print "エラー発生 (" & Err.Number & "): " & Err.Description
TryOpenStencil = False
End If
On Error GoTo 0 ' エラーハンドリングを通常に戻す
Err.Clear
End Function
''' <summary>
''' バックアップからファイルを復元し、本番ファイルを書き換えるプロセス
''' </summary>
Private Function AttemptRecovery(fso As Object, ByRef doc As Visio.Document) As Boolean
Dim backupFile As String
backupFile = BACKUP_DIR & "Backup_Latest.vssx"
' バックアップが存在するか確認
If Not fso.FileExists(backupFile) Then
AttemptRecovery = False
Exit Function
End If
' --- 復旧フロー ---
' 1. 壊れた可能性がある本番ファイルを一旦削除(またはリネーム)
' ※ここではシンプルに削除してバックアップで上書きします
On Error Resume Next
If fso.FileExists(STENCIL_PATH) Then fso.DeleteFile STENCIL_PATH, True
On Error GoTo 0
' 2. バックアップを本番のパスにコピー
fso.CopyFile backupFile, STENCIL_PATH
' 3. 再度、新しくなった(復旧した)ファイルを読み込む
AttemptRecovery = TryOpenStencil(STENCIL_PATH, doc)
End Function
''' <summary>
''' 【重要】正常な状態のステンシルをバックアップとして保存する
''' </summary>
Sub CreateManualBackup()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
' ディレクトリがなければ作成
If Not fso.FolderExists(BACKUP_DIR) Then
' ※実際にはフォルダ作成が必要(簡略化のためここでは存在前提)
End If
' 現在開いているステンシルをバックアップとして保存
' ※運用上、定期的に実行するか、正常終了時に呼び出すのがベスト
On Error Resume Next
Dim doc As Visio.Document
Set doc = Visio.Documents.Open(STENCIL_PATH)
If Not doc Is Nothing Then
doc.SaveAs BACKUP_DIR & "Backup_Latest.vssx"
MsgBox "バックアップを最新状態に更新しました。", vbInformation
Else
MsgBox "バックアップ対象のファイルが開けません。", vbExclamation
End If
On Error GoTo 0
Set fso = Nothing
End Sub
3. アーキテクトの視点:コードの「重み」を理解する
このコードをただコピペするだけでは、あなたはまだ「使い手」です。「作り手」になるために、なぜこのような書き方をしているのか、その本質を解説します。
① `On Error Resume Next` の正しい使い方
多くの初心者は、エラーを回避するためにこの命令を多用してしまいます。しかし、これは「エラーを無視する」のではなく、「エラーが起きることを予期して、制御下に置く」ために使うものです。
今回の `TryOpenStencil` 関数では、ファイルが開けるかどうかを「判定」するために、あえてエラーを無視して `Err.Number` をチェックしています。これが、エラーを「制御」するということです。
② `FileSystemObject (FSO)` の採用
VBA標準の `Dir` 関数は軽量ですが、ネットワークパスや特殊なファイル属性の扱いに弱いです。`Scripting.FileSystemObject` を使うことで、ファイルの存在確認、削除、コピーといった操作を、より堅牢(プロフェッショナル)に行うことができます。
③ オブジェクトのライフサイクル
コードの最後で `Set doc = Nothing` としている部分に注目してください。Visioのようなメモリを大量に消費するアプリケーションでは、使い終わったオブジェクトを明示的に解放することは、長時間動かし続ける自動化ツールにおいて、「メモリリーク(動作がどんどん重くなる現象)」を防ぐための鉄則です。
4. 陥りやすい罠(トラブルシューティング)
この仕組みを運用する上で、以下の点に注意してください。
- ファイルロック問題: 他のユーザーがステンシルを開いている最中に、VBAがバックアップを上書きしようとするとエラーになります。運用ルールとして「ステンシル使用中は編集中に閉じてもらう」などの運用設計もセットで考えましょう。
- 権限の問題: `C:\Automation\` などのフォルダに対して、実行ユーザーに「書き込み権限」があることを必ず確認してください。権限がないと、バックアップ作成時に静かに失敗します。
- バックアップの世代管理: 今回のコードは `Backup_Latest.vssx` という名前で最新の1つだけを保存していますが、より高度なシステムにするなら、ファイル名に `Format(Now, “yyyymmdd_hhnnss”)` を付けて、日付ごとに保存するように改良しましょう。
最後に:ここをクリアすれば、Visio VBAの基本はバッチリです
「動けばいい」というコードから、「壊れても大丈夫」というシステムへ。
この考え方を持つだけで、あなたの作るツールの価値は劇的に変わります。ユーザー(同僚やクライアント)は、エラーで止まらないツールに対して、絶大な信頼を寄せてくれるはずです。
まずは、小さなプログラムからで構いません。`On Error` を使いこなし、失敗のケースを想定してコードを書いてみてください。その積み重ねが、あなたを伝説的なエンジニアへと導いてくれます。
さあ、次の自動化に向けて、一歩踏み出しましょう!応援していますよ。
