1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【前編】PowerPointの中身は「入れ子の箱」だった ── python-pptxでスライド構造を丸裸にする

1
Last updated at Posted at 2026-04-11

PowerPointファイルの拡張子を .zip に変えて解凍すると、中にはXMLファイルがずらりと並んでいる。
テキストも図形も画像も、すべてが 構造化されたデータ として格納されている。
python-pptx はこの構造を Python オブジェクトとして操作するライブラリだ。
前編では、PPTXの内部構造を探検し、python-pptx の基本操作、そして テンプレートという絶対に外せない概念 を押さえる。

先に要点

  • .pptx は ZIP 内に XML が詰まった構造化ファイル
  • 中身は Slide → Shape → TextFrame → Paragraph → Run の5層構造
  • python-pptx はこの階層を Python オブジェクトとして読み書きできる
  • テンプレートがないと、デザイン情報がゼロになる ── これが最大の落とし穴

この記事で分かること

  • PPTXファイルの内部構造と、python-pptx がそれをどう扱うか
  • スライドを走査して情報を抽出する実際のコード
  • 「テンプレートなし」だと何が起きるのか、なぜテンプレートが必須なのか
  • 後編(JSON変換+LLM連携)に向けた前提知識

今回使う Mermaid 図の種類

図の種類 用途
flowchart PPTXの内部構成、テンプレート有無の分岐
classDiagram PPTXの5層オブジェクト構造
sequenceDiagram python-pptx の読み取り処理フロー
stateDiagram-v2 テンプレート内のデザイン継承
mindmap python-pptx の機能全体像

1. PPTXファイルの正体 ── ZIP の中の XML 群

PowerPointファイルは、見た目はひとつの塊だが、実態は XMLファイルの集合体をZIPで圧縮したもの だ。

スライド本体(slide*.xml)とは別に、デザインを司る「マスター」「レイアウト」「テーマ」が独立したファイルとして存在している。この分離が、後述するテンプレートの概念に直結する。

python-pptx は、このZIP内のXML群を Python の Presentation オブジェクトに変換してくれる。開発者は XML を意識せずに、Python のオブジェクト操作だけでスライドを読み書きできる。


2. PPTXの5層構造 ── コードで辿る入れ子の箱

PPTXの中身は、マトリョーシカのような入れ子構造を持っている。python-pptx はこれを忠実にオブジェクトモデルとして表現する。

文字の装飾(太字・色・サイズ)は最下層の Run 単位で管理される。1段落の中で「ここだけ赤太字」にしたい場合、その部分が別の Run として分離される。

実際に走査するコード

この5層構造を、python-pptx で辿るコードはこうなる。

from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE_TYPE

prs = Presentation("sample.pptx")

for slide in prs.slides:                          # レイヤー1: Slide
    for shape in slide.shapes:                     # レイヤー2: Shape
        print(f"シェイプ: {shape.name}, 種類: {shape.shape_type}")
        if shape.has_text_frame:
            tf = shape.text_frame                  # レイヤー3: TextFrame
            for para in tf.paragraphs:             # レイヤー4: Paragraph
                for run in para.runs:              # レイヤー5: Run
                    print(f"  テキスト: {run.text}")
                    print(f"  太字: {run.font.bold}, サイズ: {run.font.size}")

prs.slidesslide.shapesshape.text_frametf.paragraphspara.runs と、5層を順にネストして辿る。python-pptx のオブジェクトモデルがPPTXの内部構造とそのまま対応しているため、直感的に読める。

ここで重要なのが、Shape にはテキスト以外にも画像・図形・グラフなどがある という点だ。shape.shape_type で種類を判別し、MSO_SHAPE_TYPE.PICTURE なら画像処理、AUTO_SHAPE なら図形処理、というように分岐させる。


3. Shape の多様性 ── テキストだけではない

1枚のスライドに載っている「部品」は、すべて Shape として管理されている。

for shape in slide.shapes:
    shape_data = {
        "name": shape.name,
        "left": shape.left.pt, "top": shape.top.pt,
        "width": shape.width.pt, "height": shape.height.pt,
        "shape_type": shape.shape_type.name,
        "is_placeholder": shape.is_placeholder,
    }
    
    # 画像の場合
    if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
        image_bytes = shape.image.blob  # バイナリ画像データ
    
    # オートシェイプ(四角形、角丸など)の場合
    if shape.shape_type == MSO_SHAPE_TYPE.AUTO_SHAPE:
        shape_data["auto_shape_type"] = shape.auto_shape_type.name
    
    # プレースホルダーの場合
    if shape.is_placeholder:
        ph = shape.placeholder_format
        shape_data["placeholder"] = {"type": ph.type.name, "idx": ph.idx}

このコードは3つのことをしている。

  1. すべての Shape に共通する情報(名前、位置、サイズ、種類)を辞書に格納
  2. Shape の種類に応じた分岐 で、画像データやオートシェイプの形状を追加取得
  3. プレースホルダーかどうか を判定し、タイプとインデックスを記録

is_placeholder は特に重要だ。プレースホルダーとは、レイアウトで「ここにタイトルを入れてね」と予約された領域のこと。idx でどのプレースホルダーかを特定し、テキストを流し込む際の宛先になる。


4. テンプレートの3層構造 ── デザインの設計図

python-pptx を使ううえで 最も理解が必要な概念 がテンプレートだ。テンプレートの中には、3つの設計図が階層的に格納されている。

デザインは「テーマ → マスター → レイアウト → プレースホルダー」と段階的に継承される。レイアウトを選ぶだけで、テーマの配色やマスターのデザインルールが自動的に適用される。

テンプレートの構造を読み取るコード

後編で使う analyze_pptx() 関数は、このテンプレート構造も解析する。マスターとレイアウトの走査部分を抜粋する。

for master in prs.slide_masters:
    master_data = {"layouts": []}
    for layout in master.slide_layouts:
        layout_data = {"name": layout.name, "shapes": []}
        for shape in layout.shapes:
            shape_data = {
                "name": shape.name,
                "type": shape.shape_type.name,
                "is_placeholder": shape.is_placeholder
            }
            if shape.is_placeholder:
                ph_format = shape.placeholder_format
                shape_data["placeholder_type"] = PP_PLACEHOLDER(ph_format.type).name
            layout_data["shapes"].append(shape_data)
        master_data["layouts"].append(layout_data)

このコードは slide_mastersslide_layoutsshapes と辿り、各レイアウトがどんなプレースホルダーを持っているかを記録する。この情報があれば、「どのレイアウトを使い、どの idx にテキストを入れるか」をプログラム的に判断できる。


5. テンプレートなしだと何が起きるか

テンプレートなしだと、配色テーマ・フォント定義・カスタムレイアウトがすべて消える。プロが作ったPowerPointを再現するのは、テンプレートなしではほぼ不可能。

具体的に失われるもの:

要素 テンプレートあり テンプレートなし
フォント 游ゴシック、メイリオなど指定通り Calibri(日本語で文字化けリスク)
配色テーマ ACCENT_1〜6 が企業カラーに設定 Office 標準の地味な配色
レイアウト プロ設計のカスタムレイアウト多数 最低限の4種類のみ
装飾 背景画像、ロゴ、ヘッダー/フッター 一切なし

だから python-pptx でスライドを生成する際は 「テンプレートとなる .pptx を渡し、そのレイアウトに中身を流し込む」 のが鉄則になる。


6. python-pptx の全体像

python-pptx は「読み取り」「書き込み」「テンプレート活用」の3軸で整理できる。読み取りで得た情報を辞書に変換すれば、後編で扱うJSON化の土台になる。


一言で言うと何者か

python-pptx は、PowerPoint内部の5層構造を Python オブジェクトとして読み書きするライブラリ だ。ただし見た目の再現には テンプレートという設計図 が不可欠であり、テンプレートがなければ「中身はあるが見た目のない」骨だけのスライドしか作れない。

まとめ

  • PPTXの正体は ZIP内のXML群。python-pptx はそれを Python オブジェクトに変換する
  • 中身は Slide → Shape → TextFrame → Paragraph → Run の5層構造
  • Shape には画像・図形・プレースホルダーなど多様な種類があり、shape_typeis_placeholder で分岐する
  • テンプレートは「テーマ → マスター → レイアウト → プレースホルダー」の3層設計図。なしだとデザイン情報がゼロになる
  • テンプレートのレイアウトとプレースホルダーの idx を理解すれば、デザインを維持したまま中身を流し込める

後編では、この5層構造をまるごと JSON に変換する analyze_pptx() 関数のコードを読み解き、LLM にスライドを読ませて編集させるアプローチを実装レベルで解説する。


GitHub リポジトリ

この記事で解説しているコードの全体は、以下のリポジトリで公開しています。
pptx_processor.pyllm_handler.py、Streamlit アプリ、CLI 実行スクリプトなど、すべてのソースコードを参照できます。


後編はこちら → PowerPointをJSONに変換してLLMに読ませる ── 実装コードで理解するAIスライド編集【後編】

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?