PowerPointの.pptxファイルは、専用のバイナリ形式に見えます。
しかし、実際のPPTXは、複数のXML、画像、テーマ、リンク情報などをまとめたZIPパッケージです。
この構造を理解すると、次のような処理が可能になる理由が分かります。
- スライド内のテキストを抽出する
- 画像や動画を取り出す
- ハイパーリンクを確認する
- スライドマスターを編集する
- 全スライドに共通する図形を探す
- GammaからエクスポートしたPPTXの構造を確認する
この記事では、自分で作成したGammaのPPTXエクスポートを例に、slide、slideLayout、slideMaster、relationshipの関係を整理します。
PPTXの正体はZIPパッケージ
PPTXはOffice Open XML形式を利用しています。
拡張子を.zipに変更するか、unzipコマンドを使うと、内部ファイルを確認できます。
cp presentation.pptx presentation.zip
unzip presentation.zip -d presentation
展開すると、概ね次のような構造が見つかります。
presentation/
├── [Content_Types].xml
├── _rels/
├── docProps/
└── ppt/
├── presentation.xml
├── slides/
├── slideLayouts/
├── slideMasters/
├── media/
├── theme/
└── _rels/
主なディレクトリの役割は次のとおりです。
| パス | 内容 |
|---|---|
ppt/slides/ |
各スライド本体 |
ppt/slideLayouts/ |
スライドレイアウト |
ppt/slideMasters/ |
スライドマスター |
ppt/media/ |
画像や動画 |
ppt/theme/ |
配色やフォントテーマ |
_rels/ |
ファイル同士の関連付け |
[Content_Types].xml |
パッケージ内ファイルの種類 |
PPTXは1つのXMLだけで構成されているわけではありません。
複数のXML、画像、relationshipを組み合わせて、1つのプレゼンテーションを作っています。
全スライドに同じ要素が表示される理由
PowerPointでは、共通デザインをスライドマスターやスライドレイアウトで管理できます。
例えば次のような要素です。
- ロゴ
- フッター
- ページ番号
- 背景
- 共通テキスト
- 共通リンク
- 装飾用の図形
スライドマスターやレイアウトに配置された要素は、複数のスライドへ反映されます。
そのため、すべてのスライドの同じ位置に表示があっても、各スライドに同じ図形がコピーされているとは限りません。
構造としては、概ね次のような関係になります。
slide
↓
slideLayout
↓
slideMaster
↓
theme
各スライドはレイアウトを参照し、そのレイアウトはスライドマスターを参照します。
共通要素を確認するときは、ppt/slides/だけでなく、次のディレクトリも確認する必要があります。
ppt/slideLayouts/
ppt/slideMasters/
文字列を検索して構造を調べる
PPTXを展開したあと、grepなどを使って文字列を検索できます。
grep -Rni \
-E "Made with Gamma|gamma\.app" \
presentation/ppt
検索結果がslideMasterやslideLayoutに含まれていれば、その要素が複数スライドで共有されている可能性があります。
ただし、文字列だけを削除対象の判断に使うべきではありません。
ユーザー自身が本文中に次のような文章を書いている可能性もあるためです。
This presentation was made with Gamma.
本文まで変更しないためには、次のような条件を組み合わせます。
-
gamma.appへの外部リンクがある - マスターまたはレイアウトに存在する
- スライドの端に配置されている
- 複数スライドへ共通表示されている
- 図形のサイズや座標が想定範囲内である
- 対応するrelationshipが存在する
文字列、外部リンク、配置位置、階層を組み合わせることで、誤検出の可能性を下げられます。
relationshipとは何か
PPTXでは、画像、リンク、スライド、レイアウトなどの関連を.relsファイルで管理します。
例えば、図形にハイパーリンクが設定されている場合、図形本体のXMLにURLが直接書かれているとは限りません。
図形側にはrelationship IDだけが記録される場合があります。
<a:hlinkClick r:id="rId5"/>
対応する.relsファイルには、実際のリンク先が記録されます。
<Relationship
Id="rId5"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
Target="https://gamma.app/"
TargetMode="External"
/>
つまり、リンク付きの図形を確認するときは、次の両方を見る必要があります。
- 図形本体のXML
- 図形が参照しているrelationship
図形だけを変更してrelationshipを残すと、不要な参照がパッケージ内に残る可能性があります。
反対に、relationshipだけを削除すると、PowerPointが参照エラーとして扱う場合があります。
ブラウザ内で処理する流れ
PPTXはZIPパッケージなので、ブラウザでも展開・解析・再生成ができます。
基本的な流れは次のとおりです。
PPTXファイルを選択
↓
ArrayBufferとして読み込む
↓
ZIPをメモリ上で展開する
↓
slide / layout / master XMLを解析する
↓
relationshipを確認する
↓
条件に一致する図形を処理する
↓
ZIPを再生成する
↓
PPTXとしてダウンロードする
TypeScript風の疑似コードでは、次のようになります。
const buffer = await file.arrayBuffer()
const archive = await openZip(buffer)
const directories = [
"ppt/slides/",
"ppt/slideLayouts/",
"ppt/slideMasters/",
]
for (const directory of directories) {
const files = archive.findXmlFiles(directory)
for (const file of files) {
const xml = await file.text()
const document = parseXml(xml)
const relationships = await loadRelationships(
archive,
file.path
)
const candidates = findBrandingCandidates(
document,
relationships
)
for (const candidate of candidates) {
if (isSupportedGammaBranding(candidate)) {
removeShape(document, candidate)
removeUnusedRelationship(
relationships,
candidate
)
}
}
archive.write(
file.path,
serializeXml(document)
)
saveRelationships(
archive,
file.path,
relationships
)
}
}
const output = await archive.generate()
downloadPptx(output)
これは処理の考え方を示す疑似コードです。
実際にはXML名前空間、relationshipの相対パス、画像参照、コンテンツタイプなども考慮する必要があります。
XMLを変更するときの注意点
PPTXは複数のファイルが参照し合っているため、単純な文字列置換にはリスクがあります。
XML名前空間を維持する
PowerPointのXMLには複数の名前空間があります。
<p:sldMaster>
<a:sp>
<r:Relationship>
XMLを再生成するときに名前空間やプレフィックスが失われると、PowerPointで開けなくなる場合があります。
relationship IDを不用意に変更しない
rId1、rId2などのIDは、他のXMLから参照されています。
並び替えや再採番を行うと、画像やリンクの参照先がずれる可能性があります。
mediaファイルをすぐ削除しない
対象の図形が画像を参照していても、その画像を別のスライドが共有している可能性があります。
参照数を確認せずにppt/media/内のファイルを削除すると、別のスライドの画像まで表示されなくなる場合があります。
ZIPのルート構造を維持する
再圧縮するときは、[Content_Types].xmlやppt/がZIPのルートに存在する必要があります。
誤った構造:
presentation/ppt/
presentation/[Content_Types].xml
正しい構造:
ppt/
[Content_Types].xml
余分な親ディレクトリを含めて圧縮すると、PowerPointがPPTXとして認識できない場合があります。
PowerPointで手動確認する方法
共通要素を手動で確認する場合は、PowerPointのスライドマスター表示を利用できます。
- PPTXをPowerPointで開く
- 「表示」を選択する
- 「スライドマスター」を開く
- マスターと各レイアウトを確認する
- 対象となる図形やリンクを確認する
- 通常表示へ戻る
- 別名で保存する
要素が個別スライド、レイアウト、マスターのどこに保存されているかは、ファイルによって異なります。
個別スライドで見つからない場合は、スライドマスターとレイアウトも確認する必要があります。
処理後に確認する項目
処理後のPPTXでは、見た目だけでなく編集状態も確認します。
- スライド数が変わっていないか
- テキストを編集できるか
- 画像が欠けていないか
- フォントが維持されているか
- レイアウトが崩れていないか
- ハイパーリンクが動作するか
- 発表者ノートが残っているか
- アニメーションが残っているか
- 画面切り替えが残っているか
- PowerPointで警告なく開けるか
- Google Slidesへ読み込めるか
Google Slidesへインポートすると、フォントや配置が変わる場合があります。
ツールによる変更と、別サービスへのインポートによる変化を分けて確認することが重要です。
実際にブラウザで確認する
自分で作成したGammaのPPTXエクスポートをブラウザ上で確認する場合は、次のページを利用できます。
基本的な流れは次のとおりです。
- GammaからPPTXをエクスポートする
- 元のPPTXをバックアップする
- PPTXファイルを選択する
- ブラウザ内で処理する
- 処理後のPPTXをダウンロードする
- PowerPointで内容を確認する
利用する場合は、自分で作成したファイル、または編集する権限のあるファイルだけを対象にしてください。
まとめ
PPTXは単一のバイナリファイルではなく、XML、画像、テーマ、relationshipなどを含むZIPパッケージです。
全スライドへ表示される要素は、個別スライドではなく、スライドマスターやレイアウトに保存されている場合があります。
確認や処理を行うときは、次の点が重要です。
-
slidesだけでなくslideLayoutsとslideMastersも確認する - 文字列だけで対象を判断しない
- 外部リンク、位置、階層を組み合わせて確認する
- 図形とrelationshipをセットで扱う
- 共有されているmediaファイルを不用意に削除しない
- 元ファイルを残して処理後のPPTXを確認する
- 自分が所有する、または編集権限を持つファイルだけを扱う
PPTXの構造を理解すると、リンク監査、テンプレート編集、画像抽出、スライド自動生成、プレゼンテーション解析などにも応用できます。
