pptx-merge
pptx-merge
Splice selected slides from multiple PPTX files into a single editable deck. Each slide keeps its original native shapes (text, charts, SmartArt, pictures, tables) and its source layout, master, theme, and embedded media — fully editable in PowerPoint.
This skill is a composer for existing decks. For authoring brand-new Oracle-branded slides from a brief, use the sibling oracle-pptx skill.
When to use
Use when the user wants to:
- Merge / combine / splice / assemble slides from multiple PPTX sources into one deck
- Build a "best of" deck from corp / marketing / partner decks
- Reorder selected slides from one or more sources
- Audit an existing PPTX for PowerPoint "Repair this presentation" errors
- Audit a deck where slides appear uneditable (one full-bleed image per slide)
Do not use this for authoring new slides from scratch — that's oracle-pptx.
What gets preserved
| Preserved | Notes |
|---|---|
| Native shapes (text frames, auto-shapes, freeforms, groups) | Fully editable |
| Charts, SmartArt, tables, OLE-embedded objects | Round-trip via referenced parts |
| Pictures and embedded media | Copied byte-for-byte |
| Slide layout, slide master, theme | Copied per source — see Caveats |
| Notes slides + notes master | First source's notes master becomes deck-primary |
What is not preserved: comments, revisions, handout master, custom XML parts, presentation-level macros.
Quick start
-
Write a
manifest.json(see reference/manifest-schema.md):{ "sources": { "corp": "../decks/CorpPresentation.pptx", "product": "../decks/ProductOverview.pptx" }, "slides": [ { "source": "corp", "slide_index": 1, "role": "Cover" }, { "source": "product", "slide_index": 5, "role": "Architecture" }, { "source": "corp", "slide_index": 8, "role": "Pricing" } ], "output_pptx": "merged.pptx" } -
Run the merger:
python3 scripts/merge.py manifest.json # override the output path: python3 scripts/merge.py manifest.json --output /tmp/out.pptx # override slide size (default is 16:9): python3 scripts/merge.py manifest.json --size 4:3 python3 scripts/merge.py manifest.json --size auto # match first source python3 scripts/merge.py manifest.json --size 13.33x7.5in -
Always audit the result before delivering:
python3 scripts/audit.py merged.pptxExit code 0 = clean. Non-zero means an issue worth investigating before you hand the deck off.
Manifest fields
| Field | Required | Purpose |
|---|---|---|
sources |
yes | Map of key → path to source .pptx. Paths are relative to the manifest file. |
slides |
yes | Ordered list of slide entries. Each entry has source (key from sources) and slide_index (1-based). |
output_pptx |
yes (or pass --output) |
Output path, relative to the manifest file. |
slide_size |
optional | Output slide size. Preset ("16:9" [default], "4:3", "16:10", "a4", "letter"), "auto" (adopt first source's size), or {"cx": <emu>, "cy": <emu>}. CLI --size overrides. |
slides[].role |
optional | Free-form description; printed in the build log. |
slides[].position |
optional | Free-form integer for human-readable ordering; not enforced. |
Any extra top-level fields (deck_title, audience, version, etc.) are ignored — keep them for documentation.
Full schema: reference/manifest-schema.md.
Caveats — read before using on production decks
Read reference/caveats.md for the full list. The most important ones:
- Multiple slide masters in the output. Each source brings its own master/theme. Valid OOXML, but the merged deck won't have a single unified visual theme. Acceptable for "best of" decks; not acceptable if the user expects one consistent look.
- Unused layouts retained. A source's master pulls in all its layouts (often 50–100), even if only 2 are used by the slides you picked. Inflates file size.
- Single notes master. Schema only allows one in
<p:notesMasterIdLst>. The first source's notes master becomes deck-primary; other notes slides still render via per-slide rels. - Mixed-aspect-ratio sources. Output is one fixed slide size (default 16:9). Slides from sources with a different aspect ratio (e.g. a 4:3 source merged into a 16:9 deck) will keep their original layout coordinates and may render off-center or with letterboxing. The merger prints a warning listing any size mismatches; pick
--sizeto match the dominant source, or use--size autoto adopt the first source's size. - No comments / revisions / handout master carried over.
Auditing a deck for PowerPoint errors
When the user reports "PowerPoint found a problem with content" or "slides aren't editable / they're images", run the auditor first:
python3 scripts/audit.py path/to/deck.pptx
It catches:
| Failure mode | Detected? |
|---|---|
<p:notesMasterIdLst> has > 1 <p:notesMasterId> (PowerPoint corruption) |
yes |
Missing <p:defaultTextStyle> |
yes |
| Missing presentation-level theme rel | yes |
Missing required ancillary parts (presProps, viewProps, tableStyles) |
yes |
| Slides flattened to a single full-bleed image (uneditable) | yes |
The auditor is independent of the merger — it audits any PPTX, including ones produced by other tools.
Composition with the oracle-pptx skill
A common pipeline:
oracle-pptx— author new branded slides (cover, sections, value-prop, summaries, thank-you).pptx-merge— splice those new slides with extracted slides from corp / marketing / partner decks into one deliverable.
The two skills are deliberately split: oracle-pptx enforces a single brand-compliant theme; pptx-merge preserves source styling per slide. Trying to enforce brand compliance during merge would conflict with the merge's job.
Verifying after a merge
Recommended post-merge checks:
# 1. Schema audit
python3 scripts/audit.py output.pptx
# 2. Render to PDF (sanity check; LibreOffice is optional)
soffice --headless --convert-to pdf --outdir /tmp output.pptx
pdfinfo /tmp/output.pdf | grep -E '^Pages|^Page size'
# 3. Open in PowerPoint
# If PowerPoint asks to "Repair", re-run audit.py — the schema check
# is built specifically to catch the issues PowerPoint enforces.
Dependencies
- Python ≥ 3.10
lxml(XML/rels manipulation)
Install: pip install lxml. No python-pptx, PptxGenJS, or LibreOffice required for the merger itself; LibreOffice is optional for the post-merge PDF render check.
Examples
See examples/manifest-example.json for a minimal 3-slide manifest. The example references examples/sources/ PPTXs which you'd substitute with real decks.
Reference
- reference/manifest-schema.md — full manifest JSON schema
- reference/caveats.md — multi-master output, unused layouts, notes-master collision, what's not preserved
- reference/how-it-works.md — OOXML deep-copy algorithm explainer