Skip to main content

EasyPPTX

Release Build status codecov Commit activity License

A Python library for easily creating and manipulating PowerPoint presentations programmatically with simple APIs, designed to be easy for both humans and AI assistants to use.

Features

  • Simple, intuitive API for PowerPoint manipulation
  • Grid-first layout system: spans, weighted rows/columns, auto-flow, cell styling
  • Markdown → deck conversion (Presentation.from_markdown)
  • Percentage positions as plain numbers (x=10 is 10%); inches via in_(1.5)
  • Bullet lists with nesting, speaker notes, and multi-series charts
  • Reusable style objects and built-in themes (light / dark / corporate)
  • Support for reference PowerPoint templates and TOML template files
  • Loud, predictable errors — unknown parameters warn instead of vanishing
  • Optimized for use with AI assistants and LLMs
  • Built on top of python-pptx with a more user-friendly interface

Installation

pip install easypptx

# With optional extras:
pip install "easypptx[dataframe]"  # pandas support (tables/charts from DataFrames)
pip install "easypptx[plot]"       # matplotlib figure support
pip install "easypptx[all]"        # everything

Quick Start

The fastest way to build a deck is the grid workflow — one call creates a slide with a title and a grid, then grid[row, col] places content:

from easypptx import Presentation

pres = Presentation()

# One call: slide with title + 2x2 grid
slide, grid = pres.add_grid_slide(rows=2, cols=2, title="Quarterly Review")

grid[0, 0].add_text("Revenue up 12%", font_size=20, align="center", vertical="middle")
grid[0, 1].add_table([["Region", "Sales"], ["East", 120], ["West", 95]], has_header=True)
grid[1, :].add_text("Next steps: expand pilot", font_size=18)  # spans the bottom row

pres.save("review.pptx")

Positions are percentages — as plain numbers or strings — and physical units use in_():

from easypptx import in_

slide.add_text("Centered band", x=10, y=45, width=80, height=10)   # 10% / 45% / ...
slide.add_image(image_path="logo.png", x=in_(0.5), width=in_(1.5))  # absolute inches

Markdown → deck

from easypptx import Presentation

pres = Presentation.from_markdown("deck.md")   # or a markdown string
pres.save("deck.pptx")
---
theme: dark
---

# Q3 Review

Finance team

## Highlights <!-- notes: keep this section short -->

- Revenue up 12%
  - EMEA strongest region
- Costs down 3%

::: columns
![trend](trend.png)

| Region | Sales |
|--------|-------|
| East   | 120   |
:::

Data → charts and tables

add_chart and add_table accept pandas / polars DataFrames, pandas Series, numpy arrays, dicts of sequences, or plain lists — one adapter, no required dependencies:

slide.add_chart(data=df, value_columns=["Revenue", "Expenses"],   # native & editable
                show_values=True, number_format="#,##0", y_title="USD (k)")
slide.add_chart(data=np_matrix, chart_type="heatmap",             # auto-routed to matplotlib
                columns=["Mon", "Tue", "Wed"])
slide.add_table(df, number_format={"Sales": "{:,.0f}"},
                shade_columns=["Sales"])                          # value-tinted cells

df.pptx.chart(slide, kind="column")                               # pandas accessor
df.pptx.table(slide)

Native PowerPoint charts stay the default (editable, colored by the deck theme); chart types PowerPoint can't draw (heatmap, histogram, box, violin) render via matplotlib into the same slot. Long text shrinks to fit its box automatically (fit="shrink"), so decks render correctly in every viewer.

Themes and styles

from easypptx import Presentation, TextStyle

pres = Presentation(theme="dark")              # light / dark / corporate, or a custom Theme
heading = TextStyle(font_size=28, font_bold=True, color="cyan")

slide = pres.add_slide(title="Styled")
slide.add_text("Reusable styling", style=heading)
slide.add_bullets(["First point", ("Nested detail", 1), "Second point"])
slide.notes = "Speaker notes go here."

Content can also be placed directly on a slide with percentage-based positions:

from easypptx import Presentation
import pandas as pd

# Create a new presentation (uses 16:9 aspect ratio by default)
pres = Presentation()

# Add a slide with a title
slide = pres.add_slide(title="EasyPPTX Demo")

# Add text directly to the slide
slide.add_text(
    text="This presentation was created with EasyPPTX",
    x="10%",
    y="20%",
    width="80%",
    height="10%",
    font_size=24
)

# Add an image
slide.add_image(
    image_path="path/to/image.png",
    x="10%",
    y="35%",
    width="40%"
)

# Create a table
data = [["Name", "Value"], ["Item 1", 100], ["Item 2", 200]]
slide.add_table(
    data=data,
    x="60%",
    y="35%",
    width="30%",
    has_header=True
)

# Add a slide with a chart from pandas DataFrame
chart_slide = pres.add_slide(title="Chart Example")

df = pd.DataFrame({"Category": ["A", "B", "C"], "Value": [10, 20, 30]})
chart_slide.add_chart(
    data=df,
    chart_type="pie",
    category_column="Category",
    value_column="Value",
    x="20%",
    y="20%",
    width="60%",
    height="60%",
    title="Sample Chart"
)

# Save the presentation
pres.save("example.pptx")

Aspect Ratio Options

EasyPPTX supports multiple aspect ratios for presentations:

# Default 16:9 widescreen presentation
pres = Presentation()

# Standard 4:3 presentation
pres = Presentation(aspect_ratio="4:3")

# Other supported options: "16:10", "A4", "LETTER"
pres = Presentation(aspect_ratio="16:10")

# Custom dimensions (width and height in inches)
pres = Presentation(width_inches=12, height_inches=9)

Reference Templates

You can use multiple template formats with EasyPPTX for consistent presentation designs.

Custom Reference PPTX Files

Use custom PPTX files as references for your presentations:

# Use a custom reference PPTX file (keeping all layouts and styles)
pres = Presentation(reference_pptx="path/to/your/reference.pptx")

# Specify a custom blank layout index (if the default auto-detection doesn't work)
pres = Presentation(
    reference_pptx="path/to/your/reference.pptx",
    blank_layout_index=2  # Use the third layout as blank
)

# When opening existing presentations, you can also specify blank layout
pres = Presentation.open(
    "path/to/existing.pptx",
    blank_layout_index=4  # Use the fifth layout as blank
)

TOML Template Initialization

You can initialize a presentation with a TOML template file, which will be used for all slides by default:

# Create a presentation with a default template
pres = Presentation(template_toml="templates/business_title.toml")

# Add a slide - it will automatically use the template
slide = pres.add_slide(title="Slide with Default Template")

# Add a slide with a different template, overriding the default
slide2 = pres.add_slide(
    title="Slide with Different Template",
    template_toml="templates/tech_dark.toml"
)

# Add a slide without any template
slide3 = pres.add_slide(
    title="Standard Slide",
    template_toml=False  # Explicitly disable the default template for this slide
)

TOML Template Reference PPTX Specification

You can also specify reference PPTX files in TOML template files:

# Specify the reference PPTX file path (absolute or relative to the TOML file)
reference_pptx = "../references/my_template.pptx"

# Optionally specify the blank layout index
blank_layout_index = 3

# Rest of your template content
[title]
text = "Presentation Title"
position = { x = "10%", y = "30%", width = "80%", height = "20%" }
font = { name = "Meiryo", size = 44, bold = true }
align = "center"
# ...

Then use the template in your code:

from easypptx import Presentation
from easypptx.template import TemplateManager

# Load the template file
template_manager = TemplateManager()
template_name = template_manager.load("path/to/template.toml")

# Create a presentation and use the template
pres = Presentation()
slide = pres.add_slide_from_template(template_name)
# The reference PPTX specified in the TOML is automatically loaded

Percentage-Based Positioning

Position and size elements using percentages of the slide dimensions:

# Add text at 20% from the left, 30% from the top, 60% width, 10% height
text.add_paragraph("Positioned with percentages", x="20%", y="30%", width="60%", height="10%")

# Add an image at 10% from the left, 50% from the top, 40% width
img.add("image.png", x="10%", y="50%", width="40%")

# Add a shape using percentages
slide.add_shape(
    x="70%",
    y="50%",
    width="20%",
    height="20%",
    fill_color="blue"
)

Auto-Alignment of Multiple Objects

Easily align multiple objects in a grid, horizontal, or vertical layout:

# Define objects to be added
objects = [
    {"type": "text", "text": "Item 1", "color": "black"},
    {"type": "text", "text": "Item 2", "color": "red"},
    {"type": "text", "text": "Item 3", "color": "blue"},
    {"type": "shape", "shape_type": MSO_SHAPE.RECTANGLE, "fill_color": "green"}
]

# Add objects in a grid layout (2x2)
slide.add_multiple_objects(
    objects_data=objects,
    layout="grid",
    padding_percent=5.0,
    start_x="10%",
    start_y="30%",
    width="80%",
    height="60%"
)

# Add objects in a horizontal layout (row)
slide.add_multiple_objects(
    objects_data=objects,
    layout="horizontal",
    start_y="50%",
    height="20%"
)

Enhanced Grid Layout System

EasyPPTX provides a powerful Grid layout system for creating complex and responsive layouts:

Creating Grids with Add Grid Slide

Create a slide with a grid layout in one step:

# Create a slide with a 2x2 grid
slide, grid = pres.add_grid_slide(
    title="Grid Layout Example",
    rows=2,
    cols=2,
    title_height="10%",
    padding=5.0
)

# Add content directly to grid cells using the enhanced access API
grid[0, 0].add_text(
    text="Top Left Cell",
    font_size=18,
    align="center",
    vertical="middle"
)

grid[0, 1].add_image(
    image_path="path/to/image.jpg",
    maintain_aspect_ratio=True
)

# Generate a matplotlib figure
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])
ax.set_title("Sample Plot")

# Add the matplotlib figure to a grid cell
grid[1, 0].add_pyplot(figure=fig, dpi=150)

# Add a table to the remaining cell
grid[1, 1].add_table(
    data=[["A", "B"], [1, 2]],
    has_header=True
)

Grid Iteration and Indexing

Easily access and iterate through grid cells:

# Access cells using indexing
cell1 = grid[0, 0]  # Row 0, Column 0
cell2 = grid[3]     # Flat index (row-major order)

# Iterate through all cells
for cell in grid:
    print(f"Cell at {cell.row}, {cell.col}")

# Use the flat property for flat iteration
for cell in grid.flat:
    print(f"Cell content: {cell.content}")

# Merge cells to create larger areas
merged_cell = grid.merge_cells(0, 0, 1, 1)  # 2x2 merged area

Row-Based Grid Access

Easily add content to grid rows without specifying exact column indices:

# Create a slide with a 3x3 grid
slide, grid = pres.add_grid_slide(
    title="Row-Based Grid Access",
    rows=3,
    cols=3,
    padding=5.0
)

# Add content to the first row using row-level access
# This automatically adds each item to the next available cell in the row
grid[0].add_text(
    text="First item in row 0",
    font_size=16,
    align="center"
)

grid[0].add_text(
    text="Second item in row 0",
    font_size=16,
    align="center"
)

grid[0].add_text(
    text="Third item in row 0",
    font_size=16,
    align="center"
)

# Add content to the second row
grid[1].add_text(
    text="First item in row 1",
    font_size=16,
    align="center"
)

grid[1].add_text(
    text="Second item in row 1",
    font_size=16,
    align="center"
)

Templates

EasyPPTX supports multiple template formats for consistent presentation design.

Reference PowerPoint Templates

Use existing PowerPoint files as templates:

# Create a presentation using an existing template
pres = Presentation(template_path="template.pptx")

# Add a slide with a title
slide = pres.add_slide(title="Presentation with Template")

# Add content to the slide
slide.add_text(
    text="Content using the template styles",
    x="10%",
    y="30%",
    width="80%",
    height="30%",
    font_size=24
)

# Save the presentation
pres.save("output.pptx")

TOML-Based Templates

Create, share, and reuse templates using human-readable TOML files:

from easypptx import Presentation
from easypptx.template import TemplateManager

# Initialize template manager with template directory
tm = TemplateManager(template_dir="templates")

# Load a template from a TOML file
template_name = tm.load("templates/business_title.toml")

# Create a presentation
pres = Presentation()

# Create a slide using the loaded template
slide = pres.add_slide_from_template(template_name)

# Add content to the templated slide
slide.add_text(
    text="Quarterly Business Review",
    x="10%",
    y="30%",
    width="80%",
    height="20%",
    font_size=44,
    font_bold=True,
    align="center",
    color="white"
)

slide.add_text(
    text="Q2 2025 Financial Results",
    x="10%",
    y="55%",
    width="80%",
    height="10%",
    font_size=24,
    align="center",
    color="#66ccff"
)

# Save the presentation
pres.save("output.pptx")

Sample TOML template (business_title.toml):

# Business Template - Title Slide
bg_color = "#003366"  # Dark blue background

[title]
text = "Presentation Title"
position = { x = "10%", y = "30%", width = "80%", height = "20%" }
font = { name = "Meiryo", size = 44, bold = true }
align = "center"
vertical = "middle"
color = "white"

[subtitle]
text = "Subtitle or Presenter Information"
position = { x = "10%", y = "55%", width = "80%", height = "10%" }
font = { name = "Meiryo", size = 24, bold = false }
align = "center"
vertical = "middle"
color = "#66ccff"  # Light blue for subtitle

Dark Theme Support

Create modern presentations with dark backgrounds and vibrant colors:

# Create a presentation with black background
pres = Presentation(default_bg_color="black")

# Add a slide with default black background and a title
slide1 = pres.add_slide(
    title="Dark Theme Example",
    title_color="cyan"
)

# Add high-contrast text directly to the slide
slide1.add_text(
    text="High contrast text on dark background",
    x="10%",
    y="30%",
    width="80%",
    height="20%",
    font_size=24,
    color="white"
)

# Add a slide with a custom background color
slide2 = pres.add_slide(
    title="Custom Dark Background",
    title_color="white",
    bg_color=(0, 20, 40)  # Dark blue
)

# Add content with vibrant colors
slide2.add_text(
    text="Text with vibrant color",
    x="10%",
    y="30%",
    width="80%",
    height="20%",
    font_size=24,
    color="lime"
)

# Add a shape with custom color
slide2.add_shape(
    shape_type="ROUNDED_RECTANGLE",
    x="30%",
    y="60%",
    width="40%",
    height="15%",
    fill_color="purple"
)

# Set background color for an existing slide
slide1.set_background_color("darkgray")

Getting started with development

1. Create a New Repository

First, create a repository on GitHub with the same name as this project, and then run the following commands:

git init -b main
git add .
git commit -m "init commit"
git remote add origin git@github.com:Ameyanagi/EasyPPTX.git
git push -u origin main

2. Set Up Your Development Environment

Then, install the environment and the lefthook git hooks with

make install

This will also generate your uv.lock file. Code quality is enforced with ruff (lint + format) and ty (type checking); run everything with make check.

3. Run tests

uv run pytest

Project Structure

  • src/easypptx/ - Main package
    • presentation.py - Core presentation handling and slide factories
    • slide.py - Slide content methods (text, images, shapes, tables, charts)
    • grid.py - Grid layout system for complex arrangements
    • positioning.py - Shared percentage/inch position arithmetic
    • common.py - Shared constants (colors, alignment, fonts) and helpers
    • text.py - Text elements and formatting
    • image.py - Image handling
    • table.py - Table creation from data
    • chart.py - Chart generation
    • pyplot.py - Integration with matplotlib plots
    • template.py - Template management and utilities
    • template_generator.py - Generating starter TOML templates
  • examples/ - Example scripts, organized by topic
    • basics/ - Quickstart and core features
    • grid/ - Grid layout workflow (start with 008_quick_slide_deck.py)
    • templates/ - Template system examples
    • layouts/, styling/, advanced/ - Positioning, styling, and advanced usage

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.


Repository initiated with fpgmaas/cookiecutter-uv.

Release files for EasyPPTX 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for EasyPPTX 0.9.0
File Size Uploaded
easypptx-0.9.0.tar.gz 314.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for EasyPPTX 0.9.0
File Interpreter ABI Platform
easypptx-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 455.7 kB

Release files / easypptx-0.9.0.tar.gz

Download URL easypptx-0.9.0.tar.gz
Size 314.8 kB
Tags Source
SHA-256 checksum
How to use checksums
463b39a1baf88ed5e9e19308ad5e838f06e13f2bc313aecf40865c201dbbc326
BLAKE2b-256 checksum
How to use checksums
1038ccbd8b8f82cf3f2aefa35cc21e66c8aec38f48d19483b6234860f83a5037
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / easypptx-0.9.0-py3-none-any.whl

Download URL easypptx-0.9.0-py3-none-any.whl
Size 140.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
72f5ff2a89a7dd42d647c3f17259c93fc6d5779b356a553cd895182d92bb10e6
BLAKE2b-256 checksum
How to use checksums
714bf9815c8e18b003ee0fae3c95a13c5c0aef2181b41c95b7aaad68ea900911
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.11.0

2 release files

0.10.0

2 release files

This release

0.9.0 This release

2 release files

0.8.4

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.1.0

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page