PowerPoint VBAを掌握する極限の知見
第1回:数千枚のスライドを守り抜け——「上書き保存連動型」自動バックアップ世代管理の極意
業務自動化エンジニアの私のもとに、たびたびこんな悲鳴が届く。
「クライアント提出直前の大改修で、誤って上書き保存してしまい、昨日の状態に戻せなくなった」
「社内共有のパワポが何者かに壊され、復旧に半日を費やした」
PowerPointの標準機能である「自動回復用データ」や「旧バージョンの復元」——これらを過信してはならない。ネットワークドライブや共有サーバーの環境下では、タイムラグや同期エラーによって一瞬でデータが灰燼に帰す。
プロのエンジニアであれば、アプリケーションのライフサイクルに自ら介入し、「保存する瞬間に、確実にローカルへ世代バックアップを残す」防衛線を構築すべきだ。
今回は、初心者でもコピペで即導入でき、かつ現場のインフラに負荷をかけない堅牢な「.bak自動生成マクロ」の全貌を授けよう。
—
なぜ「ただのコピー」では実務で破綻するのか?
多くの素人が書くバックアップマクロは、次のような安易なコードになっている。
‘ 【悪手】これでは実務で必ずエラーを起こす
ActivePresentation.Save
FileCopy ActivePresentation.FullName, ActivePresentation.FullName & “.bak”
なぜこれが「悪手」なのか?
1. ファイルが未保存(新規作成直後)の場合に `FullName` が空文字でクラッシュする。
2. 保存(Save)とコピー(FileCopy)が分離しているため、途中でI/Oエラーが起きた場合に不整合が生じる。
3. 拡張子の二重付与(`hoge.pptx.bak.bak`)を考慮していない。
プロのコードは、あらゆる例外を事前に潰す「防御的プログラミング」で書かれていなければならない。
—
【プロダクションコード】堅牢な上書き保存&.bak生成モジュール
以下のコードを、PowerPointの標準モジュール(`Module1`等)にそのまま貼り付けてほしい。
リボンのマクロ登録や、標準の「上書き保存(Ctrl + S)」の挙動を乗っ取る形(イベント利用はスコープ外とするため、今回は明示的な実行、またはクイックアクセスツールバーからの呼び出しを想定)で組み込む。
Option Explicit
‘ ==============================================================================
‘ 処理名 : SaveWithBackup
‘ 概要 : 現在のプレゼンテーションを上書き保存し、同階層に.bakファイルを生成する
‘ 著者 : 業務自動化エンジニアリングチーム
‘ ==============================================================================
Public Sub SaveWithBackup()
Dim targetPres As Presentation
Set targetPres = ActivePresentation
‘ 1. 【ガード節】未保存の新規ファイルチェック
If targetPres.Path = “” Then
MsgBox “このファイルはまだ保存されていません。” & vbCrLf & _
“一度通常の「名前を付けて保存」を実行してから本マクロを使用してください。”, _
vbExclamation, “バックアップ保存エラー”
Exit Sub
End If
Dim originalPath As String
Dim backupPath As String
Dim fso As Object
originalPath = targetPres.FullName
‘ 2. バックアップファイルのパスを構築 (例: presentation.pptx.bak)
backupPath = originalPath & “.bak”
On Error GoTo ErrorHandler
‘ 3. ファイルシステムの操作オブジェクトを取得
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 4. 既存のバックアップが存在する場合は、最新に上書きするため削除
If fso.FileExists(backupPath) Then
fso.DeleteFile backupPath, True
End If
‘ 5. 現在のファイルをバックアップとしてコピー(※保存前の直近状態を退避)
‘ ※厳密には「現在のディスク上の状態」をコピーするため、未保存の変更がある場合は
‘ 先にセーブするか、メモリ上のストリームを吐き出す必要がある。
‘ 今回は「直前の安定版を残す」仕様として、セーブ実行前にコピーを作成する。
fso.CopyFile originalPath, backupPath, True
‘ 6. 本体を上書き保存
targetPres.Save
‘ 7. 正常終了ログ(実務ではステータスバー表示がスマート)
Application.StatusBar = “保存完了 & バックアップ作成成功: ” & fso.GetFileName(backupPath)
‘ オブジェクト解放
Set fso = Nothing
Exit Sub
ErrorHandler:
‘ 異常系ハンドリング
Set fso = Nothing
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, _
vbCritical, “致命的なエラー”
Application.StatusBar = False
End Sub
—
チーフアーキテクトが解説する実装の急所
1. `FileSystemObject (FSO)` の採用理由
VBA標準の `FileCopy` や `Kill` 関数は、ファイルがロックされていたりネットワーク環境が不安定な場合に、容赦なく実行時エラー(201や75など)を吐いて沈没する。
一方、FSOの `CopyFile` および `DeleteFile` メソッドは、第3引数に `True`(上書き許可)を指定することで、ファイル競合によるクラッシュを最小限に抑えることができる。
2. バックアップのタイミングの哲学
上記のコードでは、「上書き保存を実行する直前のディスク上のファイル」を `.bak` として退避させている。
「今まさに編集している最新の変更」をバックアップしたい場合は、先に `targetPres.Save` を実行し、その直後に `FileCopy` を走らせるアプローチもある。
プロジェクトの要件に合わせて使い分けてほしいが、「誤って保存してしまった直前の状態に戻す」という事故防止の観点からは、保存直前のスナップショットを退避させる設計(上記のコード)が極めて合理的である。
3. ユーザー体験(UX)の担保
処理の成否をいちいちモーダルダイアログ(MsgBox)で通知すると、作業テンポが阻害される。そのため、ここではあえて `Application.StatusBar` を利用し、ステータスバーに静かに成功ログを表示する設計としている。プロフェッショナルなツールとは、存在を主張せず、裏で確実に仕事をこなすものだ。
—
さらなる高みへ:運用上の注意点
このマクロを導入するにあたり、現場のリーダーとして以下のガバナンスを効かせてほしい。
1. マクロ有効プレゼンテーション(.pptm)としての保存
当然ながら、このコードを組み込んだファイルは `.pptm` 形式で保存し、マクロのセキュリティ設定を組織内で統一しておく必要がある。
2. 世代管理の肥大化対策
今回はシンプルに `.bak` を1世代のみ上書きする設計にしたが、業務によっては `presentation_20231024_150000.bak` のようにタイムスタンプを付与して複数世代を保持させたいケースもあるだろう。その場合は `Format(Now, “yyyymmdd_hhnnss”)` をファイル名に挟み込むロジックに拡張してほしい。
コードは道具に過ぎない。しかし、その道具の設計思想にエンジニアのプライドが宿る。
あなたの作るプレゼンテーションと、それを扱うチームメンバーの時間を、この数行の堅牢なコードで守り抜いてほしい。
