【実務・中級編】【中級者】複数のPPTXファイルをPDF化する際、ファイル名に「作成者名」や「最終更新日」などのメタデータを自動付与してエクスポートするマクロ – PowerPoint VBA解析バイブル

スポンサーリンク

はじめに:なぜ、そのPDF一括変換マクロは「現場で使い物にならない」のか

業務効率化の一環として、複数のPowerPoint(PPTX)ファイルを一括でPDF化するマクロを組んだことはないだろうか。ネットを検索すれば、`ActivePresentation.ExportAsFixedFormat` をループさせるだけのコードは山のように見つかる。

しかし、実務の現場にそれを投入した瞬間、次のような悲鳴が聞こえてくる。

  • 「どのファイルが最新版か分からない」
  • 「ファイル名がバラバラで、文書管理システム(DMS)にインポートできない」
  • 「作成者ごとにフォルダを分ける仕分け作業で、結局残業が増えた」

素人が書いたスクリプトは、単に「PPTXを開いてPDFとして保存する」だけで終わる。しかし、プロが作る自動化ツールは、「ファイルのメタデータ(作成者、最終更新日)を吸い上げ、命名規則に則った堅牢なファイル名へ動的にエクスポートする」ところまでをスコープに収める。

今回は、PowerPoint VBAの隠れた強力な機能である `BuiltInDocumentProperties` をしゃぶり尽くし、現場のドキュメントガバナンスを一撃で最適化する「プロダクション品質」のPDF一括変換エンジンを伝授しよう。

—

1. アーキテクチャ設計:なぜ `BuiltInDocumentProperties` なのか?

ファイル名に「作成者名」や「最終更新日」を付与する場合、多くの人はファイルシステム上の情報(`FileDateTime` など)を使おうとする。だが、これは大きな罠だ。

ファイルシステムの日時は、「ファイルをコピーしたり移動したりした瞬間」に書き換わる。本当に信用すべきなのは、Officeドキュメントの内部に刻まれたメタデータ、すなわち `BuiltInDocumentProperties` である。

押さえておくべき設計上の要点

1. メタデータの欠落対策: 作成者(Author)や最終更新日(Last Save Time)は、作成者のPC環境やテンプレートによっては空欄のケースがある。ここをハンドリングしないと、コードは容赦なく実行時エラー(Runtime Error)でクラッシュする。
2. ファイル名に使えない文字のサニタイズ: メタデータに `/` や `:` などのパス禁止文字が含まれている場合、文字列置換で事前に無害化(Sanitizing)しなければならない。
3. APIの適切な選択: `ExportAsFixedFormat` は非常に重い処理である。余計な描画を走らせないよう、画面更新(`ScreenUpdating`)の完全な制御が不可欠となる。

—

2. プロダクションコード:メタデータ自動付与型PDFエクスポートエンジン

以下のコードは、指定したフォルダ内にあるすべてのPPTXファイルを走査し、内部プロパティから「作成者」と「最終更新日(YYYYMMDD形式)」を抽出し、あらかじめ定義された命名規則に従って安全にPDF出力するマクロである。

適当なモジュールに貼り付けて実行してほしい。

Option Explicit

‘ —————————————————————–
‘ 業務自動化プロフェッショナル向け:メタデータ連動PDF一括エクスポート
‘ —————————————————————–
Sub ExportPptxToPdfWithMetadata()
Dim fso As Object
Dim targetFolder As Object
Dim file As Object
Dim targetPath As String
Dim appPpt As PowerPoint.Application
Dim pres As PowerPoint.Presentation
Dim exportPath As String

‘ — 設定エリア —
‘ 変換対象のPPTXファイルが格納されているフォルダパス
targetPath = “C:\Work\Presentations\”
‘ ——————

‘ FileSystemObjectの初期化
Set fso = CreateObject(“Scripting.FileSystemObject”)

If Not fso.FolderExists(targetPath) Then
MsgBox “指定されたフォルダが存在しません: ” & targetPath, vbCritical, “パスエラー”
Exit Sub
End If

Set targetFolder = fso.GetFolder(targetPath)

‘ 処理の高速化とチラつき防止
With Application
.ScreenUpdating = False
.DisplayAlerts = ppAlertsNone
End With

Dim successCount As Long
Dim errorCount As Long
successCount = 0
errorCount = 0

‘ フォルダ内の全ファイルをループ
For Each file In targetFolder.Files
‘ 拡張子が .pptx または .ppt の場合のみ処理(一時ファイル “~$” は除外)
If (LCase(fso.GetExtensionName(file.Name)) = “pptx” Or LCase(fso.GetExtensionName(file.Name)) = “ppt”) And _
(Left(file.Name, 2) <> “~$”) Then

On Error GoTo ErrorHandler

‘ プレゼンテーションをバックグラウンド(ウィンドウ非表示)で開く
‘ ※ PowerPointの仕様上、完全に隠すことはできないが、ウィンドウ状態を最小化等で制御
Set pres = Presentations.Open(file.Path, ReadOnly:=True, WithWindow:=False)

‘ メタデータの安全な取得とファイル名への適用
exportPath = GenerateExportPath(targetPath, file.Name, pres)

‘ PDFとしてエクスポート
pres.ExportAsFixedFormat _
Path:=exportPath, _
FixedFormatType:=ppFixedFormatTypePDF, _
Intent:=ppFixedFormatIntentPrint, _
FrameSlides:=msoTrue, _
HandoutOrder:=ppPrintHandoutVerticalFirst, _
OutputType:=ppPrintOutputSlides, _
PrintHiddenSlides:=msoTrue, _
Range:=Nothing, _
SlideShowName:=””, _
IncludeDocProperties:=False, _
KeepIRMSettings:=True, _
DocStructureTags:=True, _
BitmapMissingFonts:=True, _
UseISO19005_1:=False

‘ プレゼンテーションを閉じる
pres.Close
Set pres = Nothing
successCount = successCount + 1
GoTo NextFile

ErrorHandler:
‘ 個別ファイルの破損やエラーを全体のクラッシュにさせない
errorCount = errorCount + 1
If Not pres Is Nothing Then
pres.Close
Set pres = Nothing
End If
‘ エラーログをイミディエイトウィンドウに出力して継続
Debug.Print “Error processing: ” & file.Name & ” -> ” & Err.Description
Resume Next

NextFile:
End If
Next file

‘ 終了処理
With Application
.ScreenUpdating = True
.DisplayAlerts = ppAlertsAll
End With

‘ 完了レポート
MsgBox “PDFエクスポートが完了しました。” & vbCrLf & _
“成功: ” & successCount & ” 件” & vbCrLf & _
“失敗: ” & errorCount & ” 件”, vbInformation, “処理完了”

Set fso = Nothing
Set targetFolder = Nothing
End Sub

‘ —————————————————————–
‘ 内部関数:メタデータを解析し、安全な出力パスを生成する
‘ —————————————————————–
Private Function GenerateExportPath(ByVal rootDir As String, ByVal originalName As String, ByVal pres As PowerPoint.Presentation) As String
Dim baseName As String
Dim author As String
Dim lastSaveDate As String
Dim fso As Object

Set fso = CreateObject(“Scripting.FileSystemObject”)
baseName = fso.GetBaseName(originalName)

‘ 1. 作者名の取得 (BuiltInDocumentProperties)
On Error Resume Next
author = pres.BuiltInDocumentProperties(ppPropertyAuthor).Value
If Err.Number <> 0 Or Trim(author) = “” Then
author = “UnknownAuthor”
End If
On Error GoTo 0

‘ 2. 最終更新日の取得 (BuiltInDocumentProperties)
On Error Resume Next
lastSaveDate = pres.BuiltInDocumentProperties(ppPropertyLastSaveTime).Value
If Err.Number <> 0 Or Not IsDate(lastSaveDate) Then
lastSaveDate = Format(Now, “YYYYMMDD”)
Else
lastSaveDate = Format(CDate(lastSaveDate), “YYYYMMDD”)
End If
On Error GoTo 0

‘ 3. ファイル名に使えない文字をアンダースコアに置換(サニタイズ処理)
author = SanitizeString(author)

‘ 4. 命名規則の適用: [元のファイル名]_[最終更新日]_[作成者].pdf
Dim newFileName As String
newFileName = baseName & “_” & lastSaveDate & “_” & author & “.pdf”

‘ 出力先フォルダ(同階層の “PDF_Output” フォルダへ集約する設計)
Dim outputDir As String
outputDir = rootDir & “PDF_Output\”

If Not fso.FolderExists(outputDir) Then
fso.CreateFolder (outputDir)
End If

GenerateExportPath = outputDir & newFileName
Set fso = Nothing
End Function

‘ —————————————————————–
‘ 内部関数:ファイルシステム禁止文字のサニタイズ
‘ —————————————————————–
Private Function SanitizeString(ByVal txt As String) As String
Dim invalidChars As Variant
Dim i As Long

‘ Windowsのファイル名に使えない文字
invalidChars = Array(“\”, “/”, “:”, “”, “?”, “”””, “<", ">“, “|”, ” “)

For i = LBound(invalidChars) To UBound(invalidChars)
txt = Replace(txt, invalidChars(i), “_”)
Next i

SanitizeString = txt
End Function

—

3. コードのキモ:プロが仕込む「3つの防御壁」

上記のコードが「実務に耐えうる」所以は、単に動くだけではなく、予期せぬ例外を完全にねじ伏せる設計思想にある。

① `On Error Resume Next` の限定的かつ安全な利用

`BuiltInDocumentProperties` は、ドキュメントのステータスや作成方法によっては、特定のプロパティが存在しない(あるいはアクセスするとエラーを吐く)という厄介な仕様を持つ。
ここではエラートラップを局所的に挟み、プロパティの取得に失敗した場合でも、デフォルト値(`UnknownAuthor` や本日の日付)にフォールバックする堅牢性を確保している。

② ファイル名サニタイズ(`SanitizeString`)の徹底

作成者名に「山田 太郎 (開発部)」のようにスペースや括弧が含まれている場合、そのままファイルパスに組み込むとWindows APIが悲鳴を上げる。
禁止文字だけでなく、トラブルの元凶になりやすい「半角スペース」をもアンダースコアに置換する処理を挟むことで、DMSやクラウドストレージ(SharePoint/OneDrive等)への同期エラーを未然に防いでいる。

③ エラーの局所化(バッチ処理の無停止原則)

100個のファイルを処理する際、95番目のファイルが破損していたためにマクロ全体がアボート(強制終了)したらどうなるか? 現場の担当者は絶望するだろう。
このコードでは、1つのファイルでエラーが発生しても `ErrorHandler` がそれをキャッチしてイミディエイトウィンドウにログを吐き出し、即座に `Resume Next` で次のファイルの処理へ移行する。実務のバッチ処理において「止まらないこと」は正義なのだ。

—

4. 運用上の注意点とさらなる高みへ

このマクロを実務導入するにあたり、以下のポイントをチームに共有しておくと、トラブルをゼロに抑えられる。

  • PowerPointのモーダルダイアログに注意:

ファイルのオープン時に「リンクの更新」や「フォントの置換」といったダイアログがポップアップすると、`ppAlertsNone` を指定していてもマクロが一時停止することがある。マスターデータ側であらかじめリンク切れやフォントの埋め込みを解消しておくことが、真の自動化の前提条件となる。

  • 出力先フォルダの分離:

元ファイルと同じ場所にPDFを吐き出すと、フォルダ内がカオスになる。コード内では自動的に `PDF_Output` サブディレクトリを切る設計にしているため、成果物の回収が極めてスムーズに行える。

おわりに

「ただ動くコード」を書く時代は終わった。
業務自動化エンジニアに求められるのは、「現場の運用ルールをコードの構造で強制し、例外ですらシステムの一部として包み込む」というエンジニアリングだ。

このスクリプトをあなたの現場に導入し、手作業によるファイルリネームという不毛な労働を今すぐ過去のものにしてほしい。

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