【実務・中級編】【初心者】開いているすべてのプレゼンテーションを、未保存の変更があるものだけ確認ダイアログを出して一括保存して閉じる「お片付け」マクロ – PowerPoint VBA解析バイブル

スポンサーリンク

【PowerPoint VBA】散らかったウィンドウを秒速で整理!未保存だけをスマートに閉じる「お片付け」マクロ

マルチタスクで資料作成を進めていると、気づけばデスクトップは何枚ものPowerPointウィンドウで埋め尽くされている。夕方の退勤時や別のプロジェクトに切り替える際、1枚ずつ「×」ボタンを押して「保存しますか?」のダイアログと格闘するのは、エンジニアの貴重な時間を奪う最も非生産的なタスクの一つだ。

「開いているプレゼンテーションを、変更があったものだけ判定し、適切に確認しながら一括で保存して閉じる」

今回は、PowerPoint VBAのオブジェクトモデルの挙動、そして実務で絶対に踏んではいけない「地雷」を回避した、プロダクション品質の「お片付け」マクロを授けよう。

—

1. なぜ「力技の全閉じ」では実務で破綻するのか?

初心者がやりがちなコードとして、すべてのプレゼンテーションに対して無条件に `.Save` を実行したり、確認なしに `.Close` したりするアプローチがある。

‘ 【アンチパターン】絶対にやってはいけない例
Dim prs As Presentation
For Each prs In Presentations
prs.Save ‘ 変更がなかろうが強制上書きセーブ。危険極まりない。
prs.Close
Next prs

このコードが実務で致命的な理由を挙げる。

1. 変更がないファイルまで上書きタイムスタンプが更新される
閲覧しただけのファイルや、誤って触ってしまっただけのファイルも上書きされ、Gitや社内サーバーの履歴が汚染される。
2. 新規未保存ファイル(「プレゼンテーション1」など)でエラーが起きる
一度も保存されていないファイルに対して強制セーブを走らせると、予期せぬ名前で保存ダイアログがフリーズの原因になったり、意図せぬパスにゴミファイルを生み出したりする。
3. ユーザーの「やっぱり保存したくない」という意思決定を無視している

プロのエンジニアが書くべきコードは、「ファイルの健康状態(Savedプロパティ)」を正確に観測し、適切なライフサイクル管理を行うものだ。

—

2. 堅牢な設計の要:`Saved` プロパティとコレクションの逆順ループ

今回のマクロを支える技術的要件は以下の2点。

① `Presentation.Saved` プロパティの活用

PowerPointの各Presentationオブジェクトは、最後に保存されてからの変更有無を持つ `Saved` という真偽値プロパティを持っている。

  • `True` : 変更なし(そのまま閉じられる)
  • `False` : 未保存の変更あり(ユーザーへの確認、あるいは保存処理が必要)

このフラグを事前にチェックすることで、無駄なI/O(ディスクアクセス)や不要なダイアログの抑制が可能になる。

② コレクション操作の鉄則「後ろから回せ(逆順ループ)」

ウィンドウやプレゼンテーションを閉じる(=コレクションから要素を削除する)処理を、通常の `For Each` や先頭からのループで行うと、インデックスのズレによる致命的なスキップやランタイムエラー(インデックスが範囲外です)が発生する。
そのため、必ず「後ろから前へ(カウントダウン)」のループを組む必要がある。

—

3. 【コピペ即稼働】プロダクション品質「お片付け」マクロ

以下のコードをVBAエディタ(標準モジュール)に貼り付けてほしい。エラーハンドリングと、ユーザーへの丁寧なフィードバック(イミディエイトウインドウへのログ出力)を完備した実用コードだ。

Option Explicit

‘ ==============================================================================
‘ 処理名 : 変更のあるプレゼンテーションを確認しながら一括保存・閉じるマクロ
‘ 概要 : 開いているすべてのPowerPointファイルを走査し、
‘ 未保存の変更があるものだけ対話的に保存して閉じます。
‘ ==============================================================================
Sub CleanupPresentations()
‘ 画面描画をロックしてパフォーマンスを最大化
With Application
.ScreenUpdating = False
.DisplayAlerts = ppAlertsNone ‘ 一部の標準警告を抑制(安全管理はコード内で担保)
End With

On Error GoTo ErrorHandler

Dim i As Long
Dim targetPrs As Presentation
Dim closedCount As Long
Dim savedCount As Long

closedCount = 0
savedCount = 0

‘ 開いているプレゼンテーションがない場合は早期脱出
If Application.Presentations.Count = 0 Then
MsgBox “閉じ対象のプレゼンテーションは開かれていません。”, vbInformation, “お片付けマクロ”
GoTo Finally
End If

‘ 【重要】要素が減るコレクション操作は必ず「後ろから前へ(逆順)」ループする
For i = Application.Presentations.Count To 1 Step -1
Set targetPrs = Application.Presentations(i)

‘ デバッグ用:処理対象のファイル名を出力
Debug.Print “検査中: ” & targetPrs.Name & ” (Saved: ” & targetPrs.Saved & “)”

‘ 変更がある(Saved = False)場合のみ処理を行う
If targetPrs.Saved = False Then

‘ パスが未設定(一度も保存されていない新規ファイル)の場合のハンドリング
If targetPrs.Path = “” Then
Dim userChoice As VbMsgBoxResult
userChoice = MsgBox(“未保存の新規ファイル [” & targetPrs.Name & “] があります。” & vbCrLf & _
“名前を付けて保存しますか?” & vbCrLf & _
“「いいえ」を選択した場合、保存せずに閉じます。”, _
vbYesNoCancel + vbExclamation, “新規ファイルの保存確認”)

If userChoice = vbYes Then
‘ ダイアログを出してユーザーに保存場所を指定させる
targetPrs.Save
savedCount = savedCount + 1
ElseIf userChoice = vbCancel Then
‘ ユーザーが全体処理をキャンセルした場合
MsgBox “お片付け処理を中断しました。”, vbInformation, “中断”
GoTo Finally
End If
‘ 「いいえ」の場合は保存せずにそのまま閉じるフローへ

Else
‘ 既に保存されているファイルで、変更が加えられている場合
Dim saveChoice As VbMsgBoxResult
saveChoice = MsgBox(“[” & targetPrs.Name & “] に変更が加えられています。” & vbCrLf & _
“上書き保存して閉じますか?”, _
vbYesNoCancel + vbQuestion, “変更の保存確認”)

If saveChoice = vbYes Then
targetPrs.Save
savedCount = savedCount + 1
ElseIf saveChoice = vbCancel Then
MsgBox “お片付け処理を中断しました。”, vbInformation, “中断”
GoTo Finally
End If
‘ 「いいえ」の場合は保存せずに閉じる
End If
End If

‘ ファイルを閉じる(変更破棄または保存完了後)
‘ ※ 保存ダイアログが二重に出ないよう、閉じる前にSavedをTrueに擬似設定するか、
‘ SaveChanges引数を制御する手もあるが、今回はダイアログ制御済みのためそのまま閉じる
targetPrs.Close
closedCount = closedCount + 1

Next i

‘ 完了メッセージ
MsgBox “お片付けが完了しました。” & vbCrLf & _
“閉じたファイル数: ” & closedCount & vbCrLf & _
“保存したファイル数: ” & savedCount, vbInformation, “完了”

Finally:
‘ 画面描画の復元(絶対に忘れてはならない)
With Application
.ScreenUpdating = True
.DisplayAlerts = ppAlertsAll
End With
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“Error: ” & Err.Description, vbCritical, “エラー”
Resume Finally
End Sub

—

4. チーフアーキテクトが教える実装の急所

このコードが「プロダクション品質」を名乗る所以である、細部の設計思想を解説する。

画面描画のロック (`ScreenUpdating = False`)

大量のプレゼンテーションを順番に閉じるとき、OS側でウィンドウのアクティブ切り替えや描画が発生し、画面がチラつき、処理速度が著しく低下する。
先頭で `ScreenUpdating = False` をかけ、最後に必ず `True` に戻す(`Finally` ラベルを通す構造にする)ことで、爆速かつエレガントに処理が完了する。これを怠るプログラマーは二流と言わざるを得ない。

途中で「キャンセル」された場合の安全な脱出

ユーザーがファイルごとの確認ダイアログで「キャンセル」を選んだ場合、そこから先のお片付けを継続してはならない。`vbCancel` を検知した瞬間に `GoTo Finally` で安全に安全装置を解除し、処理を中断する設計にしている。

—

5. さらなる高みへ:アドイン化とショートカット割り当て

このマクロを毎回VBEから実行するのはスマートではない。以下の手順でPowerPointの独自機能(アドイン)として常駐させ、ワンクリック、あるいはショートカットキーで呼び出せるようにしてこそ真の自動化エンジニアだ。

1. 上記のコードを記述したファイルを、PowerPointアドイン形式(`.ppam`)として保存する。
2. PowerPointの「ファイル」>「オプション」>「アドイン」から、PowerPointアドインとして登録する。
3. クイックアクセスツールバーにこのマクロを登録する。

マルチタスクで疲弊した脳みそに、この「お片付けマクロ」という名の慈悲を。あなたのデスクワークのストレスをゼロにする武器として、ぜひ現場に導入してほしい。

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