【入門編】【対話型バッチ処理】”Application.FileDialog”で選択された複数フォルダ内のプレゼンに対し、メモリを節約しながら順次処理を行うバッチ処理フレームワーク – PowerPoint VBA解析バイブル

スポンサーリンク

こんにちは!PowerPoint VBAの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、「自分でコードを書きたい」と思ったあなたへ。今回は、実務で間違いなく直面する「大量のプレゼンファイルを安全に、メモリを枯渇させずに一括処理する(バッチ処理する)フレームワーク」を一緒に作っていきましょう。

「マクロを実行したら、途中でパソコンがフリーズした…」
「大量のファイルを開いたら、PowerPointが重くなって強制終了した…」

こんな恐怖を味わったことはありませんか?
大丈夫。メモリのライフサイクルを正しく理解し、適切なクローズ処理を挟みさえすれば、PowerPoint VBAはどんなに膨大なファイル群も軽々と、正確に処理してくれます。

ここをクリアすれば、あなたのVBAスキルは「初学者」の領域を完全に抜け出します。さあ、最高のアーキテクチャを一緒に見ていきましょう!

1. なぜ「複数ファイルのバッチ処理」でPowerPointは壊れるのか?

まず、敵を知ることから始めましょう。
VBAで複数のプレゼンテーションを操作するとき、私たちはつい次のようなコードを書きがちです。

‘ 【やってはいけないアンチパターン例】
Dim i As Long
For i = 1 To 100
‘ 毎回ファイルを開くが、メモリの解放や参照の切断を意識していない
Presentations.Open “C:\Folder\Presentation” & i & “.pptx”
‘ 何か処理…
Next i

これの何が問題か分かりますか?
PowerPointの裏側では、ファイルを1つ開くたびに「オブジェクト(実体)」がメモリ上に生成されます。人間で言うと、部屋に入るたびにゴミを散らかし、掃除をせずに次の部屋へ移動している状態です。これではあっという間にメモリがパンクし、エラーかフリーズが起きます。

プロのエンジニアが守るべき鉄則はただ一つ。
「開いたものは、必ず閉じる。変数に入れたオブジェクトは、使い終わったら `Nothing` で解放する」

この鉄則を美しく組み込んだのが、今回紹介する「対話型バッチ処理フレームワーク」です。

2. フレームワークの全体像

私たちが目指すプログラムのフローはこうです。

1. 対話型でフォルダを選ぶ: `Application.FileDialog` を使って、ユーザーに処理したいフォルダをGUIで選ばせる。
2. ファイルを探す: 選ばれたフォルダの中にあるPowerPointファイル(`.pptx`, `.ppt`)をリストアップする。
3. 安全にループ処理する: 1つずつ開き、処理し、即座に閉じ、メモリを解放する
4. 完了を告げる: 何件処理できたかをスマートに通知する。

では、実際のコードを見てみましょう。あなたの開発環境(VBE)にそのままコピペして動かせる実用コードです。

3. 実装コード:メモリを支配する堅牢なバッチ処理

以下のコードを、標準モジュールに貼り付けてください。

Option Explicit

‘ =====================================================================
‘ 処刑台の無い安全地帯:複数フォルダ・ファイル一括処理フレームワーク
‘ =====================================================================
Sub RunBatchPresentationProcessor()
Dim fd As FileDialog
Dim selectedItem As Variant
Dim targetFiles As Collection
Dim fileCount As Long

‘ 1. Application.FileDialogでフォルダを選択させる(複数選択可)
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
fd.Title = “一括処理を行うフォルダを選択してください(複数選択可)”
fd.AllowMultiSelect = True ‘ 複数選択を許可

If fd.Show = -1 Then ‘ ユーザーがOKを押した場合
‘ ファイルパスを格納するコレクションを初期化
Set targetFiles = New Collection

‘ 選択されたフォルダを巡回し、内部の対象ファイルを集める
For Each selectedItem In fd.SelectedItems
Call GetPowerPointFiles(CStr(selectedItem), targetFiles)
Next selectedItem

fileCount = targetFiles.Count

If fileCount = 0 Then
MsgBox “処理対象となるPowerPointファイルが見つかりませんでした。”, vbExclamation, “終了”
Exit Sub
End If

‘ 2. ユーザーに実行確認
If MsgBox(fileCount & “個のファイルが見つえました。バッチ処理を開始しますか?”, _
vbQuestion + vbYesNo, “確認”) = vbNo Then Exit Sub

‘ 3. 画面描画を停止してパフォーマンスを爆発的に上げる
With Application
.ScreenUpdating = False
.DisplayAlerts = ppAlertsNone
End With

On Error GoTo ErrorHandler ‘ 予期せぬエラーでも画面描画が戻るようにする

‘ 4. メモリ節約型メインループの実行
Dim filePath As Variant
Dim targetPres As Presentation
Dim processedCount As Long
processedCount = 0

For Each filePath in targetFiles
‘ 【重要】非表示(Windowなし)で開くことでメモリと描画コストを最小化
Set targetPres = Presentations.Open(Filename:=filePath, ReadOnly:=msoFalse, WithWindow:=msoFalse)

‘ =========================================================
‘ 【ここに個別の処理を記述します】
‘ 例:すべてのスライドの背景を白にする、特定の文字を置換するなど
‘ =========================================================
Call ExecuteCustomProcess(targetPres)
‘ =========================================================

‘ 5. 変更を保存して閉じる(メモリの即時解放)
targetPres.Save
targetPres.Close

‘ 6. オブジェクト変数を完全に消去(メモリリーク防止の決定打)
Set targetPres = Nothing

processedCount = processedCount + 1
Next filePath

‘ 正常終了処理
GoTo CleanUp

End If
Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “異常終了”

CleanUp:
‘ 7. 必ず環境を元に戻す(最重要)
With Application
.ScreenUpdating = True
.DisplayAlerts = ppAlertsAll
End With

If processedCount > 0 Then
MsgBox “バッチ処理が完了しました。” & vbCrLf & _
“処理件数: ” & processedCount & ” / ” & fileCount, vbInformation, “完了”
End If
End Sub

‘ =====================================================================
‘ サブルーチン:フォルダ内のPowerPointファイルを再帰的/または直下に取得
‘ =====================================================================
Private Sub GetPowerPointFiles(ByVal folderPath As String, ByRef col As Collection)
Dim fileName As String

‘ パスの末尾に “\” がない場合の考慮
If Right(folderPath, 1) <> “\” Then folderPath = folderPath & “\”

‘ Dir関数でファイルを取得
fileName = Dir(folderPath & “.ppt”)

Do While fileName <> “”
‘ 一時ファイル(~$で始まるもの)は除外する
If Left(fileName, 2) <> “~$” Then
col.Add folderPath & fileName
End If
fileName = Dir()
Loop
End Sub

‘ =====================================================================
‘ 個別処理のテンプレート(ここにあなたの業務ロジックを書く)
‘ =====================================================================
Private Sub ExecuteCustomProcess(ByRef pres As Presentation)
‘ サンプルとして、すべてのスライドに何らかの処理をするフックを用意
Dim sld As Slide
For Each sld In pres.Slides
‘ 例:スライドに対して行う処理をここに書く
‘ プレースホルダーの文字いじり、図形の整列など
Next sld
End Sub

4. コードの深掘りポイント:なぜこの書き方が「最強」なのか?

初心者から一歩進んだあなたに、このコードに隠された3つの「プロの技」を解説します。

① `FileDialog` による堅牢なパス取得

`InputBox` に手動でファイルパスを打ち込ませるシステムは、もう時代遅れです。`Application.FileDialog(msoFileDialogFolderPicker)` を使うことで、OS標準の綺麗な画面でユーザーに対話的にフォルダを選ばせることができます。しかも `AllowMultiSelect = True` にすれば、複数のフォルダを一度に選択させることも可能です。

② `WithWindow:=msoFalse` という秘密兵器

`Presentations.Open` メソッドを使うとき、実は引数を指定できます。
ここで `WithWindow:=msoFalse` を指定すると、画面上にプレゼンテーションのウィンドウを表示させずに、裏側(メモリ上だけ)でファイルを開くことができます。
これによるメリットは絶大です。

  • 画面がパカパカ切り替わらない(チラつかない)
  • ウィンドウを描画するリソースを使わないため、処理速度が圧倒的に速い

③ トラップ回避の `On Error GoTo` と `CleanUp`

バッチ処理の大敵は「途中でファイルがパスワード保護されていて開けない」といった予期せぬエラーです。もしエラーでプログラムが止まったとき、`ScreenUpdating = False`(画面描画停止)のまま放置されると、PowerPointの画面がフリーズしたように見え、ユーザーは絶望します。
このコードでは、エラーが起きようとも必ず `CleanUp` ラベルを通り、画面描画とアラート設定を元に戻す保険(フェイルセーフ)が組み込まれています。

ここをクリアすれば、PowerPoint VBAの基本はバッチリですよ!

お疲れ様でした!少し長めのコードでしたが、ここに書かれているのは「実務で生き残るための知見」そのものです。

  • ユーザーとの対話(`FileDialog`)
  • パフォーマンスの最適化(`ScreenUpdating`, `WithWindow:=msoFalse`)
  • メモリの保護と解放(`Close`, `Set … = Nothing`)
  • エラーハンドリング(`On Error GoTo`)

これらをマスターしたあなたなら、もう「マクロの記録」に頼る必要はありません。ご自身の業務を自動化するだけでなく、同僚の面倒な手作業をも一瞬で終わらせる「自動化のエンジニア」として活躍できるはずです。

明日からのあなたのVBAライフが、よりスマートで快適なものになりますように。それでは、また次の極限の知見でお会いしましょう!

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