【極限の自動化】「最新版はどれ?」の地獄から脱出する。複数ファイルから最新スライドを集約する究極のマクロ
「最新版_修正済み_final_v2.pptx」
「最新版_修正済み_final_v3_本当にこれ最後.pptx」
……そんなファイル名がフォルダに並んでいる光景、何度見てきましたか?
複数のメンバーが分担してスライドを作成している現場では、必ずと言っていいほど「どのファイルが最新のパーツを持っているのか」を突き止める作業が発生します。これを手作業で一つずつ開き、更新日時を確認して、新しいスライドをコピーして……なんて作業は、エンジニアの魂が泣きます。
今日は、そんな「バージョン管理の迷宮」を、VBAという名の剣で切り裂く方法を伝授しましょう。
単なる「マクロの記録」を超え、「オブジェクトのライフサイクル」と「データ構造」を制御するプロフェッショナルな設計思想を、あなたのものにしてください。
1. 本日のアーキテクチャ(設計図)
今回のミッションは、「特定のルールに従った複数のPPTXファイルをスキャンし、各スライド(または各構成要素)の最新版だけを抽出して、一つのマスタープレゼンテーションに統合する」ことです。
ここで、初心者の方が陥りがちな誤解を解いておきましょう。
実は、PowerPointのスライド単体には「更新日時」というプロパティは存在しません。スライドの更新日時は、「そのスライドが含まれているファイル全体の更新日時」として管理するのが、プログラム設計における定石です。
解決のための3ステップ・アルゴリズム
1. Scan(スキャン): `FileSystemObject` を使い、フォルダ内の全ファイルを巡回する。
2. Compare(比較): `Dictionary` オブジェクトを「脳」として使い、ファイル名から「どのスライドのパーツか」を識別し、更新日時が最も新しいファイルのパスを記憶する。
3. Merge(統合): 記憶した「最新ファイルのリスト」に基づき、`InsertFromFile` メソッドで一気に新しいプレゼンテーションへ流し込む。
2. 実装:最新版マージ・エンジン
それでは、魂を込めたコードを見ていきましょう。このコードは、コピー&ペーストで動作するように設計していますが、コメントを読み飛ばさないでください。コードの「意味」を理解することこそが、脱初学者の唯一の道です。
Option Explicit
''' <summary>
''' 複数ファイルから最新のパーツを集約し、一つのプレゼンテーションを作成する
''' </summary>
Sub MergeLatestSlidesMaster()
' --- 1. 変数定義(アーキテクトの作法) ---
Dim fso As Object
Dim folderPath As String
Dim targetFolder As Object
Dim fileItem As Object
Dim dictLatestFiles As Object ' Key: スライドID, Value: 最新ファイルのフルパス
Dim masterPres As Presentation
Dim latestFilePaths As Variant
Dim i As Integer
Dim fileName As String
Dim slideID As String
Dim fileDate As Date
' --- 2. 環境設定 ---
' フォルダ選択ダイアログを表示
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "PPTXファイルが格納されているフォルダを選択してください"
If .Show = -1 Then
folderPath = .SelectedItems(1)
Else
Exit Sub ' キャンセル時は終了
End If
End With
' オブジェクトの初期化
Set fso = CreateObject("Scripting.FileSystemObject")
Set dictLatestFiles = CreateObject("Scripting.Dictionary")
Set targetFolder = fso.GetFolder(folderPath)
' --- 3. スキャン&比較フェーズ ---
' フォルダ内のファイルを一つずつチェック
For Each fileItem In targetFolder.Files
' 拡張子が .pptx であることを確認(一時ファイルなどは除外)
If LCase(fso.GetExtensionName(fileItem.Name)) = "pptx" And Left(fileItem.Name, 2) <> "~$" Then
' 【重要】ファイル名から「スライドID」を抽出するルールを決める
' 例: "Slide01_田中.pptx" -> "Slide01" をIDとする
' ここでは、最初の "_" までの文字列をIDとみなすロジックにしています
fileName = fileItem.Name
If InStr(fileName, "_") > 0 Then
slideID = Left(fileName, InStr(fileName, "_") - 1)
Else
slideID = fileName ' "_" がない場合はファイル名全体をIDとする
End If
fileDate = fileItem.DateLastModified
' Dictionaryを使って、既に登録されているものより新しい日付か判定
If Not dictLatestFiles.Exists(slideID) Then
' 初めて見るIDなら登録
dictLatestFiles.Add slideID, fileItem.Path
Else
' 既に登録されている場合、更新日時を比較
Dim existingFilePath As String
existingFilePath = dictLatestFiles(slideID)
If fileDate > fso.GetFile(existingFilePath).DateLastModified Then
' 今見ているファイルの方が新しければ、上書き更新
dictLatestFiles(slideID) = fileItem.Path
End If
End If
End If
Next fileItem
' --- 4. マージフェーズ ---
If dictLatestFiles.Count = 0 Then
MsgBox "対象となるPPTXファイルが見つかりませんでした。", vbExclamation
Exit Sub
End If
' 新規プレゼンテーションを作成
Set masterPres = Presentations.Add
' Dictionaryに格納された「最新パス」を順番に処理
' ※注:Dictionaryの順序は追加順。必要に応じてソートロジックを追加してください。
For Each slideID In dictLatestFiles.Keys
Dim targetPath As String
targetPath = dictLatestFiles(slideID)
' InsertFromFile はコピー&ペーストよりも高速で、書式崩れが少ないプロの技
' 引数: ファイルパス, 挿入開始スライド, 挿入終了スライド
On Error Resume Next
masterPres.Slides.InsertFromFile targetPath, masterPres.Slides.Count
If Err.Number <> 0 Then
Debug.Print "Error inserting: " & targetPath
Err.Clear
End If
On Error GoTo 0
Next slideID
' --- 5. 完了処理 ---
MsgBox "統合が完了しました!" & vbCrLf & _
"集約されたパーツ数: " & dictLatestFiles.Count, vbInformation
' メモリ解放
Set fso = Nothing
Set dictLatestFiles = Nothing
Set targetFolder = Nothing
End Sub
3. ここが「プロ」の知見。解説と陥りやすい罠
このコードをただ動かすだけでは、あなたはまだ「マクロ使い」です。このコードの裏側にある設計思想を理解すれば、あなたは「エンジニア」になれます。
① なぜ `Dictionary` を使うのか?
初心者の方は、ファイルを一つずつ見て「これは最新かな?次は……」と、フラグ変数(Boolean)をいくつも作って管理しようとしがちです。しかし、それは拡張性のない設計です。
`Dictionary`(連想配列)を使えば、「スライドID(Key)」と「その最新パス(Value)」をセットで管理できます。これにより、データの検索と更新が爆速になり、コードも劇的にシンプルになります。
② `InsertFromFile` vs `Copy & Paste`
「スライドをコピーして貼り付ける」という操作は、マクロの記録ではよく見られます。しかし、これは非常に危険です。
クリップボードを経由するため、実行中にユーザーが他の操作をするとエラーになりますし、メモリ消費も激しい。
一方、`InsertFromFile` は、ファイルから直接スライドオブジェクトを流し込むため、動作が安定し、速度も圧倒的に速いのです。
③ 陥りやすいエラー:ファイル名の命名規則
このマクロの命運は、「ファイル名の命名規則」にかかっています。
上記のコードでは `slideID = Left(fileName, InStr(fileName, “_”) – 1)` としており、`Slide01_Tanaka.pptx` のようにアンダースコアで区切られていることを前提としています。
もし、メンバーが `Slide01Tanaka.pptx` と命名してしまうと、IDが正しく抽出できず、マージに失敗します。
「自動化を成功させるには、人間側のルール(運用)を固めること」。これが、現場を知るアーキテクトの教えです。
4. 次のステップへ
このマクロをマスターしたら、次は以下のようなカスタマイズに挑戦してみてください。
- ソート機能: `Dictionary` の中身をスライド番号順に並び替えてからマージする。
- ログ出力: どのファイルが採用され、どのファイルが「古い」として捨てられたのかをテキストファイルに書き出す。
- エラーハンドリングの強化: ファイルが開けなかった場合に、ユーザーに通知してスキップする処理をより堅牢にする。
ここをクリアすれば、PowerPoint VBAの基本はバッチリですよ。
一歩ずつ、しかし確実に、自動化の深淵へと進んでいきましょう。応援しています!
