SKILL.md
SKILL.mdBrowse 8 files
2,850 tokens
10,781 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: powerpoint3description: Create, read, edit .pptx decks with python-pptx.4version: 1.1.05author: Nous Research6license: MIT7platforms: [linux, macos, windows]8metadata:9 hermes:10 tags: [pptx, powerpoint, presentations, slides, office, python-pptx]11 category: productivity12 related_skills: [docx, xlsx, pdf]13---14 15# Powerpoint Skill16 17Create, inspect, and edit PowerPoint (.pptx) presentations using the18python-pptx library. Five helper scripts cover deck creation from a JSON19spec, structured read-back, in-place edits, template-driven brand decks,20and slide rendering — all offline, no PowerPoint installation required.21 22## When to Use23 24- The user asks to build a slide deck, report presentation, or pitch deck.25- You need to extract text, notes, tables, chart data, or images from a26 .pptx someone shared.27- You need to update an existing deck: replace text, refresh or patch28 chart data, swap a logo, duplicate/remove/reorder slides, set29 backgrounds, footers, hyperlinks, or speaker notes.30- You must produce an on-brand deck from a company .pptx template.31- Do NOT use this for .ppt (legacy binary) files — convert them first with32 `soffice --convert-to pptx old.ppt` if LibreOffice is available.33 34## Prerequisites35 36- Python 3.10+ with `python-pptx` installed37 (`pip install python-pptx`).38- Optional: LibreOffice (`soffice`) plus poppler (`pdftoppm` or39 `pdftocairo`) for rendering slides to PNGs and for PDF export.40 `pptx_render.py` detects both with `shutil.which` and degrades41 gracefully (reports `{"rendered": false, "missing": [...]}`, exit 0)42 when absent — all create/read/edit operations work without them.43- Check availability via `terminal`:44 `python -c "import pptx; print(pptx.__version__)"` and `which soffice pdftoppm`.45 46## How to Run47 48All scripts live in `scripts/`, take `--help`, print JSON to stdout, and49exit non-zero on failure. Run them with `terminal`:50 51```bash52python scripts/pptx_create.py deck.json out.pptx53python scripts/pptx_read.py deck.pptx --outline # full JSON outline54python scripts/pptx_read.py deck.pptx --notes # speaker notes55python scripts/pptx_read.py deck.pptx --images ./img # export pictures56python scripts/pptx_edit.py deck.pptx --replace-text "Old Corp" "New Corp"57python scripts/pptx_edit.py deck.pptx --chart-data update.json58python scripts/pptx_edit.py deck.pptx --duplicate-slide 259python scripts/pptx_edit.py deck.pptx --remove-slide 3 --move-slide 2 060python scripts/pptx_from_template.py brand.pptx out.pptx --values vals.json61python scripts/pptx_render.py deck.pptx --outdir ./render # slide PNGs62```63 64Author JSON specs with `write_file`; inspect script output and generated65JSON with `read_file`.66 67## Quick Reference68 69| Task | Command |70|---|---|71| New deck from spec | `pptx_create.py spec.json out.pptx` |72| 16:9 vs 4:3 | `"slide_size": "16:9"` or `"4:3"` in the spec |73| Outline as JSON | `pptx_read.py deck.pptx --outline` |74| Export images | `pptx_read.py deck.pptx --images DIR` |75| Replace text | `pptx_edit.py deck.pptx --replace-text OLD NEW` |76| Replace chart data | `pptx_edit.py deck.pptx --chart-data spec.json` |77| Patch one series | same flag, spec with `"ops"` (see below) |78| Swap picture | `pptx_edit.py deck.pptx --swap-image N NAME new.png` |79| Duplicate slide | `pptx_edit.py deck.pptx --duplicate-slide N` |80| Remove slide | `pptx_edit.py deck.pptx --remove-slide N` |81| Reorder slide | `pptx_edit.py deck.pptx --move-slide FROM TO` |82| Slide background | `pptx_edit.py deck.pptx --set-background N RRGGBB` |83| Hyperlink runs | `pptx_edit.py deck.pptx --hyperlink N TEXT URL` |84| Slide number on | `pptx_edit.py deck.pptx --enable-slide-number N` |85| Footer text | `pptx_edit.py deck.pptx --set-footer N TEXT` |86| Set notes | `pptx_edit.py deck.pptx --set-notes N TEXT` |87| Append notes | `pptx_edit.py deck.pptx --append-notes N TEXT` |88| Fill template | `pptx_from_template.py tpl.pptx out.pptx --values v.json` |89| Render slide PNGs | `pptx_render.py deck.pptx --outdir DIR` |90 91## Procedure92 93### 1. Create a deck94 95Write a JSON spec (see `pptx_create.py --help` for the full format), then96run `pptx_create.py`. Per slide you can set: `layout` (title,97title_content, section, two_content, title_only, blank), `title`,98`subtitle`, `bullets` (strings, or dicts with `level` 0-4, `size` pt,99`bold`, `italic`, `font`, `color` hex, `link` URL for a hyperlink),100`background` (solid hex), `footer` (text; enables the layout's footer101placeholder), `slide_number` (true; enables the layout's slide-number102placeholder), `images` (path + left/top/width/height in inches), `tables`103(`rows` as list-of-lists), `shapes` (rectangle, rounded_rectangle, oval,104diamond, right_arrow, chevron, with `fill` hex + optional `text`),105`charts` (bar, bar_h, line, pie with `categories` + `series`), and106`notes` (speaker notes).107 108### 2. Read a deck109 110`pptx_read.py deck.pptx --outline` returns slide size, layout inventory,111and per slide: layout name, all shape texts, table cells, image inventory112(filename/ext/bytes), chart categories/series/values, and speaker notes.113Use `--images DIR` to dump embedded pictures to files, then114`vision_analyze` on any exported image if you need to see its content.115 116### 3. Edit a deck117 118`pptx_edit.py` combines operations in one pass; use `--output` to keep the119original. Text replacement scans slide shapes, table cells, and notes.120Image swap retargets the picture's relationship id so position and size121are preserved. Slide removal drops the relationship and the `<p:sldId>`122entry; reorder moves the `<p:sldId>` element within `<p:sldIdLst>`123(python-pptx has no public API for either — the script does the XML-level124work). `--duplicate-slide N` appends an independent deep copy of slide N:125shape XML plus image/media/hyperlink relationships are cloned and rIds126remapped, so editing the copy never touches the original. Chart slides127are refused (see Pitfalls). `--set-notes`/`--append-notes` edit speaker128notes; `--set-background`, `--hyperlink`, `--enable-slide-number`, and129`--set-footer` handle deck polish.130 131Chart updates take a JSON spec via `--chart-data`. Full replace:132`{"slide": 0, "chart": 0, "categories": [...], "series": {...}}`. For133surgical edits, pass `"ops"` instead — a list of134`{"op": "update_series", "name": ..., "values": [...]}`,135`add_series`, `remove_series`, `rename_category` (`from`/`to` or136`index`), and `set_title`. python-pptx can only swap a chart's entire137dataset (`replace_data`), so ops are implemented as read-existing →138modify → replace; the per-part UX is a wrapper, and any chart data not139expressible as categories + numeric series will be normalized by the140round-trip.141 142### 4. Build from a template143 144`pptx_from_template.py` opens a brand .pptx, replaces every145`{{token}}` from a values JSON across slides/tables/notes, and can append146new slides that use the template's own layouts (by layout name or index)147so they inherit the master's fonts and colors. Tip: to start from a148template with zero slides, delete existing ones afterward with149`pptx_edit.py --remove-slide`.150 151### 5. Visual verification152 153`pptx_render.py deck.pptx --outdir ./render` converts the deck to PDF154with `soffice --headless` and splits it into one PNG per slide with155`pdftoppm` (or `pdftocairo`). Output JSON lists the PNG paths — review156each with `vision_analyze`. When either tool is missing the script exits1570 with `{"rendered": false, "missing": [...]}` and guidance; fall back to158the JSON outline from `pptx_read.py`, which verifies content and159structure, just not visuals.160 161## Converting to PDF162 163If LibreOffice is installed, export the finished deck to PDF directly:164 165```bash166soffice --headless --convert-to pdf --outdir ./out deck.pptx167```168 169The output lands at `./out/deck.pdf`. Fonts not installed on the host are170substituted, so render-verify (Procedure step 5) before shipping the PDF.171There is no offline pure-Python .pptx→PDF path; if `soffice` is absent,172say so rather than approximating.173 174## Pitfalls175 176- **Run splitting**: PowerPoint fragments paragraph text into runs at177 spell-check and edit boundaries. `--replace-text` first merges adjacent178 runs whose formatting is identical, so matches split across such runs179 are replaced with formatting fully preserved. Only when a match spans180 *genuinely differently-formatted* runs is the paragraph rewritten with181 the first run's formatting — verify those slides after replacement.182- **Chart slides cannot be duplicated**: each chart relationship embeds a183 separate XLSX workbook part; cloning that graph reliably is not184 supported, so `--duplicate-slide` refuses chart slides cleanly instead185 of corrupting the deck. Rebuild the chart on a new slide instead.186 External-hyperlink and image/media rels are carried over; layout and187 notes rels are recreated fresh.188- **Chart ops are a wrapper**: python-pptx replaces the whole dataset;189 `"ops"` round-trips existing plot data through `replace_data`, and190 changing chart *type* is not possible.191- **Reordering is XML-level**: python-pptx has no supported reorder API.192 `--move-slide` manipulates `<p:sldIdLst>` directly; safe for ordinary193 decks but re-read the deck afterward to confirm.194- **Copying slides between decks is unsupported** — duplication works195 only within one deck, where layouts and masters are shared.196- Footer/slide-number enablement copies the placeholder from the slide's197 layout; on layouts without those placeholders, `--set-footer` fails198 with a clear message (add a textbox instead).199- Hyperlinks apply to whole runs; `--hyperlink` links every run200 containing the given text on that slide.201- The default python-pptx template is 4:3; the create script sets 16:9202 unless the spec says otherwise. Custom templates keep their own size.203- Layout indexes vary by template. For brand templates, list layout names204 first: `pptx_read.py template.pptx --outline` (`layouts_available`).205- `slide.shapes.title` is None on blank layouts — the create script206 handles this, but remember it when writing ad-hoc python-pptx code.207- Always pass `encoding="utf-8"` when writing spec files; tokens like208 `{{city}}` may be filled with non-ASCII values.209 210## Verification211 2121. After any create/edit, run `pptx_read.py OUT.pptx --outline` and check213 slide count, texts, tables, notes, and chart values match intent.2142. `--images DIR` then file-size check confirms pictures embedded.2153. Render every slide with `pptx_render.py deck.pptx --outdir ./render`216 and review each PNG with `vision_analyze` — this catches overlapping217 shapes, truncated text, and color problems the outline cannot. If the218 render tools are missing, the script says so; rely on the outline.2194. The bundled test suite is the full contract:220 `python -m pytest tests/ -q` (requires python-pptx + pytest).221 Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.