Convert a Jupyter notebook into a PowerPoint deck. Slides break on markdown # / ## headings; figures, tables, and prose flow into the slide content automatically.
notebook2ppt analysis.ipynb -o deck.pptxnbconvert --to slides produces reveal.js HTML, which is great for the browser but useless when somebody on the other side of an org wants a .pptx they can edit. This tool fills that gap: read the notebook you already wrote, write a real PowerPoint file.
pip install -e .Python ≥ 3.10. Runtime dependencies are nbformat, python-pptx, and Pillow.
The mapping is heading-driven:
| Notebook content | Slide outcome |
|---|---|
# H1 markdown heading |
Sets the deck title and opens a title slide |
## H2 markdown heading |
Opens a new slide with that heading as the title |
| Markdown paragraphs | Become text blocks on the current slide |
| Markdown bullet lists | Become bullet lists (nested levels preserved) |
Code-cell image/png outputs (matplotlib figures, PIL images) |
Embedded as fitted images |
Code-cell text/html DataFrame outputs |
Rendered as native PowerPoint tables |
print(...) / stream outputs |
Become text blocks (truncated past --snippet-chars) |
| Code-cell source | Skipped by default; pass --include-code to include |
If a notebook has no headings at all, every code cell falls through to its own slide as a fallback. If a slide accumulates more content than fits, the builder spills the rest into a continuation slide titled Heading (cont.).
notebook2ppt NOTEBOOK [-o OUTPUT] [--include-code] [--snippet-chars N] [--dry-run]
--dry-runprints the slide outline without writing anything — useful for sanity-checking how a notebook will break apart.--snippet-charscontrols how long a stream/text output can be before truncation (default 600, set 0 to disable).- Default output path is
<notebook>.pptxnext to the source.
from notebook2ppt import convert
convert("analysis.ipynb", "deck.pptx", include_code=False)For finer control, parse first and inspect the intermediate Deck:
from notebook2ppt import parse
from notebook2ppt.builder import build_pptx
deck = parse("analysis.ipynb")
print(deck.title, len(deck.slides))
build_pptx(deck, "out.pptx")examples/build_examples.py regenerates three example notebooks programmatically (so they include real outputs even without running Jupyter):
python examples/build_examples.py
notebook2ppt examples/01_basic_analysis.ipynb
notebook2ppt examples/02_with_figure.ipynb
notebook2ppt examples/03_with_table.ipynbWhat each demonstrates:
01_basic_analysis.ipynb— heading-driven slides plus bullet points and a stream-output text block.02_with_figure.ipynb— a real matplotlib PNG embedded in the notebook output, fitted onto a slide.03_with_table.ipynb— a pandas DataFrame's HTML output rendered as a native PowerPoint table.
notebook (.ipynb)
│
▼
parser.py ──► Deck IR (Slide[Block]) ──► builder.py ──► .pptx
───────── ──────────
nbformat read, python-pptx,
markdown parse, shape placement,
output extraction continuation slides
The parser is independent of python-pptx; the builder is independent of nbformat. The split makes it easy to add other render targets later (Google Slides, reveal.js, plain HTML report) without redoing the parsing work.
pip install -e ".[dev]"
pytest- Cell-tag overrides (e.g.
# slide:break,# slide:title) for precise control. - Master-template support:
--template my-corporate.pptxto inherit fonts/colors. - Better single-block splitting (a 200-bullet markdown list still places as one shape today).
- SVG output support (currently skipped — python-pptx can't accept SVG natively).
- Optional
[execute]extra:notebook2ppt --execute notebook.ipynbto run the notebook before converting.
MIT.