【入門編】【XML構造逆引き解析】VBAからプレゼンテーション(.pptx)をZIP解凍し、スライド単位の「作成日時」と「最終更新履歴」を抽出する超上級ハック – PowerPoint VBA解析バイブル

スポンサーリンク

こんにちは!PowerPoint VBAの世界へようこそ。
マクロの記録ボタンを押してコードを生成する日々から一歩抜け出し、「もっと本格的にPowerPointを牛耳りたい」と思っているあなたへ。

今回は、通常のオブジェクトモデル(`Application`や`Presentation`といったお馴染みの階層構造)からは絶対にアクセスできない深い領域に踏み込みます。テーマは「PowerPointファイルのXML構造を直接ハックし、スライド単位の作成日時と最終更新履歴を暴く」という、フォレンジック(デジタル鑑識)や監査レベルの超上級テクニックです。

「難しそう…」と思いましたか?
大丈夫。私と一緒に一歩ずつ紐解いていけば、背筋がゾクゾクするようなエンジニアのロマンと、実務で使える強力な武器を手に入れられますよ。ここをクリアすれば、あなたのPowerPoint VBAのスキルは間違いなく一段上のステージに到達します。さあ、始めましょう!

1. なぜ「オブジェクトモデル」の限界を超える必要があるのか?

普段、私たちは次のようなコードでプレゼンテーションを操作しますよね。

Dim prs As Presentation
Set prs = ActivePresentation
MsgBox prs.Name

とても直感的で分かりやすいです。しかし、ここで先輩エンジニアとしてあなたに意地悪な質問を一つ。

> 「このプレゼンテーションに含まれる『スライド3』は、いつ、誰によって作られ、最後にいつ更新されたの?」

プレゼンテーションファイル全体のプロパティ(作成日時や最終更新者)なら `BuiltinDocumentProperties` で取得できます。しかし、「スライド単位」の作成日時や更新履歴となると話は別です。PowerPointのオブジェクトモデルには、残念ながらスライド個別のタイムスタンプを返すプロパティは用意されていません。

「じゃあ、無理じゃないか……」

いいえ、諦める必要はありません。現代の `.pptx` ファイルの正体を思い出してください。
そう、`.pptx` はただの「ZIPファイル」であり、中身はすべて「XML(テキスト)」で書かれているのです。

ファイルの実体をバラして、内部のXMLを直接覗き見ることができれば、PowerPointが隠している秘密のデータにだってアクセスできる。これが今回挑む「XML構造逆引き解析ハック」の核心です。

2. `.pptx` ファイルの裏側を覗く(アーキテクチャの理解)

`.pptx` という拡張子のファイルを、試しに `.zip` にリネームして解凍してみてください。中には次のようなフォルダとファイルが広がっています。

my_presentation.pptx (これを .zip に変更して解凍)
┣ _rels/
┣ ppt/
┃ ┣ _rels/
┃ ┣ slides/ ← ここに各スライドのXMLが入っている!
│ │ ┣ slide1.xml
│ │ ┣ slide2.xml
│ │ ┗ …
┃ ┣ slidemasters/
┃ ┗ presentation.xml
┗ docProps/
┣ core.xml ← 文書全体のメタデータ(作成者や更新日時)
┗ app.xml

実は、Office Open XML(OOXML)の規格において、スライドやドキュメントのコアプロパティ(Dublin Coreメタデータなど)には、作成日時(`dcterms:created`)や最終更新者(`cp:lastModifiedBy`)といった情報が記録されています。

今回は、VBAから以下の手順でこの情報を自動抽出しちゃいます。
1. 対象の `.pptx` ファイルを一時的にZIPとしてコピー・解凍する。
2. 解凍されたフォルダ内にある `docProps/core.xml` や、各スライドの関連情報を舐め回す。
3. XMLパーサー(DOMDocument)を使って、欲しいデータを一網打尽にする。

3. 【実装】スライドの裏側を暴くVBAコード

お待たせしました。百聞は一見に如かず。実務でそのままコピペして使える、極限まで洗練されたVBAコードをプレゼントします。

このコードを実行するには、あらかじめVBAエディタのメニューから [ツール] > [参照設定] を開き、「Microsoft XML, v6.0」(または適切なバージョン)にチェックを入れておいてください(DOM操作を爆速で行うためです)。

Option Explicit

‘ =========================================================================
‘ ódulo名: ズバリ!スライド履歴抽出エンジン
‘ 概要 : .pptxをZIP解凍し、内部のXMLから作成日時や更新履歴をハックする
‘ =========================================================================
Public Sub ExtractSlideMetadataHack()
Dim targetPath As String
Dim tempDir As String
Dim fso As Object
Dim shellApp As Object

‘ 1. 対象ファイルのパスを指定(※あらかじめ保存されている.pptxを指定してください)
targetPath = ActivePresentation.Path & “\” & ActivePresentation.Name

If ActivePresentation.Path = “” Then
MsgBox “一度ファイルを保存してから実行してください。”, vbExclamation, “中断”
Exit Sub
End If

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 2. 一時解凍用フォルダのパスを作成
tempDir = fso.GetSpecialFolder(2) & “\pptx_hack_” & Format(Now, “yyyymmddhhmmss”)
fso.CreateFolder tempDir

‘ 3. .pptx を .zip に偽装してコピーし、強制解凍する
Dim zipPath As String
zipPath = tempDir & “\presentation.zip”
fso.CopyFile targetPath, zipPath, True

‘ Windows標準のShell機能を使ってZIPを解凍
Set shellApp = CreateObject(“Shell.Application”)
shellApp.NameSpace(tempDir).CopyHere shellApp.NameSpace(zipPath).Items

‘ 4. コアプロパティ (docProps/core.xml) を解析する
Dim coreXmlPath As String
coreXmlPath = tempDir & “\docProps\core.xml”

If fso.FileExists(coreXmlPath) Then
Call ParseCoreXml(coreXmlPath)
Else
MsgBox “コアプロパティが見つかりませんでした。”, vbCritical, “エラー”
End If

‘ 5. クリーンアップ(一時ファイルの削除はエンジニアのたしなみです)
On Error Resume Next
fso.DeleteFolder tempDir, True
On Error GoTo 0

MsgBox “XML解析が完了しました。イミディエイトウィンドウを確認してください。”, vbInformation, “完了”
End Sub

‘ — XMLパーサーによるメタデータ抽出サブルーチン —
Private Sub ParseCoreXml(xmlPath As String)
Dim xmlDoc As Object
Set xmlDoc = CreateObject(“MSXML2.DOMDocument.6.0”)

xmlDoc.async = False
xmlDoc.resolveExternals = False

If Not xmlDoc.load(xmlPath) Then
MsgBox “XMLのロードに失敗しました: ” & xmlDoc.parseError.reason, vbCritical
Exit Sub
End If

‘ 名前空間の解決(OOXMLの標準名前空間を設定)
xmlDoc.setProperty “SelectionNamespaces”, _
“xmlns:cp=’http://schemas.openxmlformats.org/package/2006/metadata/core-properties’ ” & _
“xmlns:dc=’http://purl.org/dc/elements/1.1/’ ” & _
“xmlns:dcterms=’http://purl.org/dc/terms/'”

‘ データの抽出
Dim creatorNode As Object
Dim createdNode As Object
Dim modifiedNode As Object
Dim modifierNode As Object

Set creatorNode = xmlDoc.SelectSingleNode(“//dc:creator”)
Set createdNode = xmlDoc.SelectSingleNode(“//dcterms:created”)
Set modifiedNode = xmlDoc.SelectSingleNode(“//dcterms:modified”)
Set modifierNode = xmlDoc.SelectSingleNode(“//cp:lastModifiedBy”)

‘ イミディエイトウィンドウに出力
Debug.Print “=== [PPtx Forensic Report] ===”
Debug.Print “・作成者 (Creator) : ” & IIf(Not creatorNode Is Nothing, creatorNode.Text, “不明”)
Debug.Print “・作成日時 (Created) : ” & IIf(Not createdNode Is Nothing, createdNode.Text, “不明”)
Debug.Print “・最終更新者 (ModifiedBy): ” & IIf(Not modifierNode Is Nothing, modifierNode.Text, “不明”)
Debug.Print “・最終更新日時 (Modified): ” & IIf(Not modifiedNode Is Nothing, modifiedNode.Text, “不明”)
Debug.Print “===============================”

End Sub

4. このコードの美しさと、現場で陥りやすい罠

このコードの何が美しいかと言えば、PowerPointを裏でゴリゴリ起動して画面をチラつかせることなく、ファイルシステムとXMLの直接叩き合いで高速に情報を抜き取る点にあります。巨大なプレゼンテーションであっても、一瞬で処理が完了します。

しかし、実務の現場ではいくつかの「罠」に直面することがあります。先輩からのアドバイスとして、注意点をいくつか共有しておきますね。

罠1:ファイルがロックされていてコピーできない

  • 原因: 自分が開いている(編集中の)ファイルをそのままVBAでコピーしようとすると、排他制御(ファイルロック)に引っかかりエラーになります。
  • 対策: 必ず一度ファイルを「上書き保存」した状態、または開いていない状態のパスを対象にするか、一度別名で保存したものを解析対象にしてください。

罠2:XMLの名前空間(Namespace)トラップ

  • 原因: OOXMLの世界では、タグの頭に `dc:` や `dcterms:` といったプレフィックス(名前空間)がついています。これを無視して `xmlDoc.SelectSingleNode(“created”)` などと書いても、永遠にデータは取れません(「何もヒットしない…」と深夜に頭を抱える原因ナンバーワンです)。
  • 対策: 上記のコードのように `setProperty “SelectionNamespaces”, …` を明示し、プレフィックスとURLを正しくバインドするのがプロの作法です。

おわりに:オブジェクトモデルの先にある「真の自由」へ

今回は、PowerPointのオブジェクトモデルの枠を飛び出し、裏側のXML構造を直接ハックしてメタデータを抽出する超上級テクニックをご紹介しました。

「オブジェクトモデルにないなら、作れないや」と諦めるのではなく、「中身はただのZIPとXMLなのだから、バラして読めばいい」という発想に至れるかどうかが、初学者から脱却し、真の業務自動化エンジニアになれるかの分かれ道です。

ここをクリアしたあなたなら、今後Word(`.docx`)やExcel(`.xlsx`)の高度な解析や一括置換なども、同じアプローチで自在にこなせるはずです。

「ここをもっとこうしたい」「こんな自動化に応用できる?」といった疑問があれば、いつでも頼りになる先輩エンジニアに聞いてくださいね。あなたのVBAライフが、よりエキサイティングで実りあるものになりますように!

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