【PowerPoint VBA】スライド1枚目の表題から「ファイル名を自動生成して上書きを防ぐ」要塞型セーブマクロ
開発プロジェクトの現場において、最も排除すべき人災は何だと思うかね?
それは、「最新版です」と称して送られてきたファイルが、実は昨日のドラフト版であり、重要な顧客への提出直前に上書きミスが発覚する絶望的な瞬間だ。
「社外秘」「ドラフト」「レビュー中」――。プレゼンテーションのステータスや内容はスライドごとに異なるにもかかわらず、人間はファイル名を手動で変えるのを忘れる。そして上書きし、過去のデータを闇に葬る。
今回は、このヒューマンエラーを根絶するための「スライド1枚目の表題テキストを自動取得し、ファイル名に組み込んで安全に別名保存(または自動命名保存)する堅牢なVBAマクロ」を授けよう。
ただ動くだけのコードではない。PowerPointのオブジェクトモデルの癖や、ファイルパス構築の罠を回避した、プロダクション品質のコードだ。
—
なぜ「手動保存」や「適当なVBA」では破綻するのか?
初心者がやりがちな失敗はこうだ。
`ActivePresentation.SaveAs` を安易に呼び出し、表題のテキストボックスから文字列をそのまま取得してファイル名にする。
これには3つの致命的な地雷が埋まっている。
1. 文字列の汚染(Forbidden Characters)
Windowsのファイル名に使えない文字(`\`, `/`, `:`, “, `?`, `”`, `<`, `>`, `|`)や、改行コードが表題に含まれている場合、容赦なく「実行時エラー」でマクロがクラッシュする。
2. 未保存プレゼンテーション(Untitled)への無慈悲な挙動
一度も保存していない新規ファイルをいきなり操作すると、パスの概念が存在せず、カレントディレクトリの特定でバグる。
3. オブジェクトのライフサイクルとエラーハンドリングの欠如
「表題となるテキストボックスがそもそも存在しない」「1枚目が図形だらけでどれがタイトルかわからない」といった異常系への配慮がない。
プロのエンジニアであれば、これら全ての例外を予測し、「水漏れしないコード」を書かなければならない。
—
現場で即採用できるプロダクションコード
以下のコードを、PowerPointのVBAエディタ(`Alt + F11`)の標準モジュールに貼り付けてほしい。
Option Explicit
‘ =========================================================================
‘ プロシージャ名 : SaveWithAutoGeneratedTitle
‘ 概要 : 1枚目のスライドの表題を抽出し、プレフィックスを付与して安全に保存する
‘ =========================================================================
Public Sub SaveWithAutoGeneratedTitle()
‘ 1. アクティブなプレゼンテーションの存在確認
If Application.Presentations.Count = 0 Then
MsgBox “保存対象のプレゼンテーションが開かれていません。”, vbCritical, “処理中断”
Exit Sub
End If
Dim targetPres As Presentation
Set targetPres = Application.ActivePresentation
‘ 2. 保存先フォルダの決定(未保存ならデスクトップ、保存済みなら同階層)
Dim targetDir As String
If targetPres.Path = “” Then
‘ 一度も保存されていない場合はデスクトップをフォールバック先にする
targetDir = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”)
Else
targetDir = targetPres.Path
End If
‘ 3. ステータスプレフィックスの選択(実務に合わせてカスタマイズせよ)
Dim statusPrefix As String
statusPrefix = SelectDocumentStatus()
If statusPrefix = “CANCEL” Then Exit Sub ‘ ユーザーがキャンセルした場合
‘ 4. 1枚目のスライドから表題を安全に抽出
Dim rawTitle As String
rawTitle = ExtractFirstSlideTitle(targetPres)
‘ 5. ファイル名に使用できない文字のサニタイズ(浄化処理)
Dim safeTitle As String
safeTitle = SanitizeFileName(rawTitle)
‘ 6. 最終的なファイル名の組み立て(例: [Draft] 2023年度事業計画書_編集者A.pptx)
Dim timeStamp As String
timeStamp = Format(Now, “yyyymmdd_HHMM”)
Dim newFileName As String
newFileName = “[” & statusPrefix & “] ” & safeTitle & “_” & timeStamp & “.pptx”
Dim fullPath As String
fullPath = targetDir & “\” & newFileName
‘ 7. エラーハンドリングを伴う保存実行
On Error GoTo ErrorHandler
‘ 上書き確認を回避しつつ、別名で確実に保存
targetPres.SaveAs FileName:=fullPath, FileFormat:=ppSaveAsPresentation
MsgBox “以下のファイルとして安全に保存しました。” & vbCrLf & vbCrLf & fullPath, _
vbInformation, “保存完了”
Exit Sub
ErrorHandler:
MsgBox “保存中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ =========================================================================
‘ 内部関数 : ドキュメントステータスの選択UI
‘ =========================================================================
Private Function SelectDocumentStatus() As String
Dim result As VbMsgBoxResult
‘ 簡易的な分岐(必要に応じてUserFormに拡張せよ)
result = MsgBox(“この資料のステータスを選択してください。” & vbCrLf & _
“【はい】 = ドラフト (Draft)” & vbCrLf & _
“【いいえ】 = 社外秘 (Confidential)” & vbCrLf & _
“【キャンセル】 = 中止”, _
vbYesNoCancel + vbQuestion, “ステータス選択”)
Select Case result
Case vbYes
SelectDocumentStatus = “Draft”
Case vbNo
SelectDocumentStatus = “Confidential”
Case Else
SelectDocumentStatus = “CANCEL”
End Select
End Function
‘ =========================================================================
‘ 内部関数 : 1枚目のスライドからタイトル文字列を強靭に抽出する
‘ =========================================================================
Private Function ExtractFirstSlideTitle(pres As Presentation) As String
On Error GoTo FallbackTitle
If pres.Slides.Count = 0 Then
ExtractFirstSlideTitle = “UntitledPresentation”
Exit Function
End If
Dim firstSlide As Slide
Set firstSlide = pres.Slides(1)
‘ プレースホルダーからタイトルを探す(最も確実)
Dim shp As Shape
For Each shp In firstSlide.Shapes
If shp.Type = msoPlaceholder Then
If shp.PlaceholderFormat.Type = ppPlaceholderCenterTitle Or _
shp.PlaceholderFormat.Type = ppPlaceholderTitle Then
If shp.HasTextFrame Then
If shp.TextFrame.HasText Then
ExtractFirstSlideTitle = Trim(shp.TextFrame.TextRange.Text)
Exit Function
End If
End If
End If
End If
Next shp
‘ プレースホルダーで取れなかった場合、最初のテキストフレームを持つ図形をフォールバックとして探す
For Each shp In firstSlide.Shapes
If shp.HasTextFrame Then
If shp.TextFrame.HasText Then
ExtractFirstSlideTitle = Trim(shp.TextFrame.TextRange.Text)
Exit Function
End If
End If
Next shp
FallbackTitle:
‘ 何も見つからない場合のデフォルト値
ExtractFirstSlideTitle = “無題のプレゼンテーション”
End Function
‘ =========================================================================
‘ 内部関数 : Windowsのファイル名に使用不可な文字を除去・置換するサニタイズ
‘ =========================================================================
Private Function SanitizeFileName(ByVal inputStr As String) As String
Dim invalidChars As Variant
Dim i As Long
‘ Windowsファイル名に使用できない文字配列
invalidChars = Array(“\”, “/”, “:”, “”, “?”, “”””, “<", ">“, “|”, vbCr, vbLf, vbTab)
For i = LBound(invalidChars) To UBound(invalidChars)
inputStr = Replace(inputStr, invalidChars(i), “_”)
Next i
‘ 長すぎるタイトルはファイルシステムエラーを誘発するため50文字に丸める
If Len(inputStr) > 50 Then
inputStr = Left(inputStr, 50)
End If
SanitizeFileName = inputStr
End Function
—
チーフアーキテクトが解説する「設計の急所」
なぜこのコードが「実務で耐えうる」と言えるのか、その設計思想を解説しよう。
1. サニタイズ(`SanitizeFileName`)の徹底
PowerPointのタイトルには、しばしば改行や長文、あるいは「/(スラッシュ)」が含まれる(例:「2023/10/15 進捗報告」)。これをそのままファイル名に使うとWindowsが例外を吐く。
このコードでは、禁止文字を一括してアンダーバー(`_`)に置換し、さらに最大50文字という安全な長さに切り詰めている。ファイルシステムの制約を完全にハックした実装だ。
2. フォローバック機構(`ExtractFirstSlideTitle`)
「タイトルプレースホルダー」が存在しないレイアウト(完全な白紙スライドなど)であっても、コードがクラッシュしないように二段階の探索ロジックを組んでいる。
1. プレースホルダーとしてのタイトル(`ppPlaceholderTitle` 等)を優先探索。
2. なければ、スライド上の任意のテキストボックスから最初の文字列を強引に強奪する。
3. それすらなかった場合のデフォルト文字列を用意。
この「絶対に止まらない防御力」が業務自動化においては最も重要だ。
3. 保存先の自動判定
未保存の新規ファイルであれば、勝手にデスクトップを保存先に指定し、すでにディレクトリが存在するファイルであれば、その「同じ階層」に別名保存(またはバージョン違いとしての安全な保存)を行う。ユーザーに無駄なファイルダイアログを強要しないスマートな導線だ。
—
実運用への展開:アドイン(.ppam)化のすゝめ
このマクロを毎回VBAエディタでコピペして使うのはナンセンスだ。
チーム全員に展開する、あるいは自身の業務効率を極限まで高めるためには、以下の手順でPowerPointアドイン(.ppam)として組み込むべきだ。
1. 上記のコードを記述したプレゼンテーションを、ファイルの種類 「PowerPoint アドイン (.ppam)」 として保存する。
2. PowerPointのオプション > アドイン > PowerPoint アドインの管理「設定」から、保存した `.ppam` ファイルを有効化する。
3. クイックアクセスツールバーやリボンにこのマクロ(`SaveWithAutoGeneratedTitle`)を割り当てる。
これだけで、ワンクリックで「絶対に上書き事故を起こさない、美しく体系化されたファイル名」の生成システムがあなたの手元に常駐する。
面倒なファイル管理のルーティンワークはコードに任せ、君たちは「中身のプレゼンテーションの質」を高めることに全力を注ぎたまえ。
