Pptx Author: Build Headless PowerPoint Decks with python-pptx
Build PowerPoint decks headless with python-pptx.
Written by Neura Market from the official Hermes Agent documentation for Pptx Author. Commands, paths, and version numbers are reproduced from the source unchanged.
Read the official documentationGenerating Model-Bound Financial Decks with python-pptx
This reference describes how to produce a .pptx file on disk using python-pptx for financial decks—pitch decks, IC memos, or earnings notes—where every number traces to a source workbook. The skill is designed for headless environments without Office or MCP for live PowerPoint.
When to Use This Skill
Use this skill when you need to produce a PowerPoint file as an artifact, not a live session. It is appropriate for building financial pitch decks, IC memos, or earnings notes where numbers must be bound to a model workbook. Use it in a headless environment without Office or MCP for live PowerPoint. Every figure on a slide must trace to a specific cell or named range in an Excel model.
Prerequisites
Before using this skill, ensure you have:
- A Python environment with
python-pptx>=0.6 installed. openpyxlinstalled if binding to an Excel model.- An Excel model workbook at
./out/model.xlsxwith named ranges or specific cells defined. - The model workbook recalculated before reading (via
excel-authorrecalc helper or manual open/save). - Optional: a firm template at
./templates/firm-template.pptx. - Optional: pre-rendered chart PNGs at
./out/charts/for embedding.
Installation
Install the required library with:
pip install "python-pptx>=0.6"
Capabilities
The skill can:
- Create a
.pptxfile from Python usingpython-pptx. - Load a firm template from
./templates/firm-template.pptxif present; otherwise start blank. - Add slides with title and content (title slide, title-only, table, image).
- Add tables with headers and data rows.
- Embed PNG images (e.g., charts rendered from the model).
- Bind deck numbers to an Excel model via
openpyxlreading named ranges or cells. - Write output to
./out/<filename>.pptx, creating./out/if missing. - Return the relative path of the output file in the final message.
Parameters
- template path: Path to firm template file (
./templates/firm-template.pptx). If it exists, the deck inherits branded colors, fonts, and master layouts. Optional; if missing, start blank. - model workbook path: Path to the Excel model (
./out/model.xlsx) from which to read numbers via named ranges or cells. Optional; if used, must recalc the workbook first. - output filename: Name of the
.pptxfile to write inside./out/(e.g.,pitch-aurora.pptx). Required.
Procedure: Create a Pitch Deck Bound to an Excel Model
Follow these steps in order:
- Install
python-pptx(>=0.6) via pip. - Check if
./templates/firm-template.pptxexists; if yes, load it asPresentation(str(template)), elsePresentation(). - Create slides using
prs.slides.add_slide(prs.slide_layouts[<index>]). - For each slide, set
slide.shapes.title.textto a takeaway sentence (one idea per slide). - For a title slide, set
slide.placeholders[1].textfor the subtitle. - For tables, use
slide.shapes.add_table(rows, cols, left, top, width, height)then populate cells. - For embedded charts, use
slide.shapes.add_picture(png_path, left, top, width=Inches(8)). - Read model values from
./out/model.xlsxusingopenpyxl:load_workbook(data_only=True), define a helper to resolve named ranges (wb.defined_names[name], iterate destinations, read cell value). - Recalculate the workbook before reading (use
excel-authorrecalc helper or open/save in Excel) becauseopenpyxlonly sees computed values if the sheet was already calculated. - Build slide titles and table content using those values (e.g., f-string with
${value:.2f}). - Ensure every figure footnotes its source, for example:
Revenue: $1,250M (Source: model.xlsx, Inputs!C3). - Create
./out/directory if not exists:Path('./out').mkdir(exist_ok=True). - Save the presentation:
prs.save('./out/<filename>.pptx'). - Return the relative path of the saved file.
Loading a Template or Starting Blank
The following code loads the firm template if it exists, or starts with a blank presentation:
from pptx import Presentation
from pathlib import Path
template = Path("./templates/firm-template.pptx")
prs = Presentation(str(template)) if template.exists() else Presentation()
Building a Complete Deck
The following example creates a pitch deck with a title slide, valuation summary table, and an embedded chart:
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pathlib import Path
template = Path("./templates/firm-template.pptx")
prs = Presentation(str(template)) if template.exists() else Presentation()
# Title slide
slide = prs.slides.add_slide(prs.slide_layouts[0])
slide.shapes.title.text = "Project Aurora — Strategic Alternatives"
slide.placeholders[1].text = "Preliminary Discussion Materials"
# Valuation summary slide (title-only layout)
slide = prs.slides.add_slide(prs.slide_layouts[5])
slide.shapes.title.text = "Valuation implies $38–$52 per share across methodologies"
# Add a table bound to model outputs
rows, cols = 5, 4
tbl_shape = slide.shapes.add_table(rows, cols,
Inches(0.5), Inches(1.5),
Inches(9), Inches(3))
tbl = tbl_shape.table
headers = ["Methodology", "Low ($)", "Mid ($)", "High ($)"]
for c, h in enumerate(headers):
tbl.cell(0, c).text = h
# In a real deck, read these from the model workbook with openpyxl
data = [
("Trading comps", "35", "41", "48"),
("Precedent M&A", "39", "45", "52"),
("DCF (base)", "36", "43", "51"),
("LBO (10% IRR)", "33", "38", "44"),
]
for r, row in enumerate(data, start=1):
for c, val in enumerate(row):
tbl.cell(r, c).text = val
# Embed a chart rendered from the model
slide = prs.slides.add_slide(prs.slide_layouts[5])
slide.shapes.title.text = "Football field — current price $42"
slide.shapes.add_picture("./out/charts/football_field.png",
Inches(1), Inches(1.8), width=Inches(8))
Path("./out").mkdir(exist_ok=True)
prs.save("./out/pitch-aurora.pptx")
In this example, the valuation summary table shows a range from $38 to $52 per share. The football field chart is embedded at the current price of $42. The LBO row uses a 10% IRR assumption. The trading comps methodology shows a low of $35, mid of $41, and high of $48. The precedent M&A row shows a low of $39, mid of $45, and high of $52. The DCF base case shows a low of $36, mid of $43, and high of $51. The LBO row shows a low of $33, mid of $38, and high of $44.
Binding Numbers to an Excel Model
Use openpyxl to read values from the model workbook. The following helper resolves named ranges:
from openpyxl import load_workbook
wb = load_workbook("./out/model.xlsx", data_only=True)
def nr(name):
"""Resolve a named range to its current computed value."""
rng = wb.defined_names[name]
sheet, coord = next(rng.destinations)
return wb[sheet][coord].value
revenue_fy24 = nr("RevenueFY24")
implied_mid = nr("ImpliedSharePriceBase")
Then use the values in slide titles:
slide.shapes.title.text = f"Implied share price of ${implied_mid:.2f} (base case)"
Every number on a slide must trace to the model workbook (sheet and cell). Never transcribe from memory or summary.
Embedding Charts
Use PNG-from-model for charts when fidelity matters. Native pptx.chart charts are fragile and may not match firm conventions. Embed a chart with:
from pptx.util import Inches
slide.shapes.add_picture("./out/charts/football_field.png",
Inches(1), Inches(2),
width=Inches(8))
Constraints and Caveats
- Output must be written to
./out/<filename>.pptx; create./out/if missing. - Return the relative path in the final message.
- Every number on a slide must trace to the model workbook (sheet and cell). Never transcribe from memory or summary.
- Use PNG-from-model for charts (not native pptx charts) when fidelity matters; native charts are fragile and may not match firm conventions.
- This skill only writes a file; never emails, uploads, or posts.
- Do not use for live PowerPoint sessions (use Office MCP instead).
- Do not use for non-financial slideware (use broader
powerpointskill). - Do not use for decks requiring heavy animation, transitions, or speaker notes (use broader
powerpointskill). openpyxlonly sees computed values if the workbook was already calculated; recalc before reading (useexcel-authorrecalc helper or open/save in Excel).- One idea per slide: the title states the takeaway, the body supports it.
Failure Modes
- Missing template file causes fallback to blank presentation (no error).
- Model workbook not recalculated before reading yields stale or
Nonevalues fromopenpyxl. - Named range not found in workbook raises
KeyErrorwhen iterating destinations. - Output directory
./out/not created before save causesFileNotFoundError. python-pptxnot installed or wrong version causesImportError.- Image file (PNG) not found at specified path causes
add_pictureto fail.
Slide-Type Checklist for Pitch Decks
A typical pitch deck includes: cover, disclaimer, TOC, situation overview, company snapshot, market context, valuation summary (football field), trading comps detail, precedent transactions detail, DCF summary, illustrative LBO, process considerations, and appendix.
Authoring a Pitch Deck
When authoring a pitch deck, use the pptx-author skill to produce the file. The output filename should reflect the deck type, for example pitch-deck. The final file is saved to ./out/.pptx.