pptx
Generate PowerPoint .pptx presentations from structured slide data (title, bullets, layouts).
Downloads: 9 ยท ID: 797e2872fa81139043000000
Generate PowerPoint .pptx presentations from structured slide data (title, bullets, layouts).
Downloads: 9 ยท ID: 797e2872fa81139043000000
<!-- FILE: pptx_skill.md -->
# PPTX Skill โ python-pptx (PowerPoint Generation)
Generates editable `.pptx` presentations using `python-pptx`. Runs in an isolated `uv` environment.
```
uv run make_pptx.py [options]
```
| Option | Default | Description |
|--------|---------|-------------|
| `-o FILE` | `~/Pictures/presentation.pptx` | Output file path |
| `--title TEXT` | "Untitled Presentation" | Title for the first slide (if using defaults) |
| `--slides JSON` | built-in demo slides | JSON array of slide objects. See format below |
## Slide Format (`--slides`)
Each slide is a JSON object:
```json
{
"layout": 1, // 0=Title, 1=Title+Content, 6=Blank
"title": "...", // optional for blank layout
"bullets": ["...", ...] // list of bullet strings (first goes to placeholder[0])
}
```
Example:
```bash
uv run make_pptx.py --slides '[{"layout":0,"title":"Welcome","bullets":["Subtitle here"]},{"layout":1,"title":"Next Slide","bullets":["Bullet 1","Bullet 2"]}]' -o ~/Pictures/demo.pptx
```
## Output
Prints the absolute path to the generated `.pptx` file. Compatible with O365 and Google Drive.
## Examples
```bash
# Generate default demo deck (converting HTML to presentations)
uv run make_pptx.py -o ~/Pictures/html_decks.pptx
# Custom slides from JSON string
uv run make_pptx.py --slides '[{"layout":0,"title":"Q3 Report","bullets":["Generated by AI"]},{"layout":1,"title":"Revenue","bullets":["$2.4M North America","+12% growth"]}]' -o ~/Pictures/q3.pptx
# Blank slide with custom positioning (requires manual shape manipulation in script)
uv run make_pptx.py --slides '[{"layout":6,"title":"","bullets":[]}]' -o ~/Pictures/blank.pptx
```
Deps auto-installed by `uv` on first run.
<!-- FILE: make_pptx.py -->
#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.10"
# dependencies = ["python-pptx"]
# ///
"""Generate PowerPoint presentations (.pptx) from structured slide data."""
import argparse, subprocess, sys, json
from pathlib import Path
def _ensure_uv():
try:
subprocess.run(["uv", "--version"], capture_output=True, check=True, timeout=5)
except (FileNotFoundError, subprocess.CalledProcessError):
print("ERROR: 'uv' (https://docs.astral.sh/uv/) is required.", file=sys.stderr)
print("Install: curl -LsSf https://astral.sh/uv/install.sh | sh", file=sys.stderr)
sys.exit(1)
except subprocess.TimeoutExpired:
pass
_ensure_uv()
from pptx import Presentation
def main():
parser = argparse.ArgumentParser(
description="Create a .pptx presentation. Pass slides as JSON or let it generate defaults."
)
parser.add_argument("-o", "--output", default=Path.home() / "Pictures" / "presentation.pptx")
parser.add_argument("--title", default="Untitled Presentation")
parser.add_argument(
"--slides",
type=str,
help='JSON array of slide objects: [{"layout":0,"title":"...","bullets":["...", ...]}, ...]'
'\nLayout 0 = Title Slide, Layout 1 = Title + Content, Layout 6 = Blank'
)
args = parser.parse_args()
default_slides = [
{"layout": 0, "title": "Converting HTML to Presentations",
"bullets": ["From web pages to editable PowerPoint decks"]},
{"layout": 1, "title": "Approach: Browser Rendering โ PDF",
"bullets": ["Puppeteer / Playwright render HTML in headless Chromium",
"Use CSS page-break-after for slide separation",
"page.pdf() exports multi-page PDF instantly"]},
{"layout": 1, "title": "Approach: Browser Rendering โ PPTX",
"bullets": ["dom-to-pptx (JS) โ high-fidelity DOM extraction",
"html2pptx (Python + Chromium) โ renders then converts",
"PptxGenJS โ programmatic slide building with HTML helpers"]},
{"layout": 1, "title": "Approach: Python-Native Generation",
"bullets": ["python-pptx โ pure Python, MIT-licensed",
"Excellent text/shape/table APIs, no Office needed",
"Limitations: no animations, limited charts, font substitution risk"]},
{"layout": 1, "title": "O365 & Google Drive Compatibility",
"bullets": ["Standard .pptx opens natively in both platforms",
"Stick to safe fonts (Calibri, Arial, Times)",
"Animations won't exist; complex charts may flatten"]},
]
slides_data = json.loads(args.slides) if args.slides else default_slides
prs = Presentation() # defaults to 16:9 widescreen
for slide_cfg in slides_data:
layout_idx = slide_cfg.get("layout", 1)
title_text = slide_cfg.get("title", "")
bullets = slide_cfg.get("bullets", [])
slide_layout = prs.slide_layouts[layout_idx]
slide = prs.slides.add_slide(slide_layout)
if title_text:
slide.shapes.title.text = title_text
body_shape = slide.placeholders[1]
tf = body_shape.text_frame
for i, bullet in enumerate(bullets):
p = tf.add_paragraph() if i > 0 else tf.paragraphs[0]
p.text = bullet
out_path = Path(args.output)
if not out_path.is_absolute():
out_path = Path.home() / "Pictures" / out_path
out_path.parent.mkdir(parents=True, exist_ok=True)
prs.save(str(out_path))
print(f'Generated: {out_path}')
if __name__ == "__main__": main()