Tutorial2026-04-139 min

Automate PowerPoint Reports from Excel with Python

Stop copy-pasting charts into slides. Two approaches: python-pptx (free, 500 lines) vs SlideForge API (10 lines, $0.03/slide). Plus: cron, Airflow, email delivery.

You can automate your weekly PowerPoint reports from Excel data with 10 lines of Python — no manual formatting, no copy-pasting charts, no last-minute slide tweaks.This guide shows two approaches: python-pptx for full control, and SlideForge's API for consulting-quality output in seconds. Both connect to pandas for data extraction and work with any scheduler (cron, Airflow, n8n).

The problem: manual report decks

Every Monday morning, someone on your team opens an Excel file, copies numbers into a PowerPoint template, screenshots a chart, pastes it, adjusts the alignment, fixes the font, updates the date. For a 15-slide weekly report, this takes 1-2 hours. Every week. Forever.

The fix is a Python script that reads the data, generates the slides, and emails the deck. Run it via cron at 7 AM Monday. Your team walks into a meeting with the deck already in their inbox.

Approach 1: python-pptx (free, full control)

python-pptx gives you pixel-level control over every shape. The tradeoff: you manage all layout, fonts, colors, and alignment yourself.

pip install python-pptx pandas openpyxl
import pandas as pd
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor

# 1. Read data from Excel
df = pd.read_excel("weekly_metrics.xlsx", sheet_name="Summary")

# 2. Create presentation
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

# 3. Title slide
slide = prs.slides.add_slide(prs.slide_layouts[6])  # blank
txBox = slide.shapes.add_textbox(Inches(1), Inches(2), Inches(10), Inches(2))
tf = txBox.text_frame
tf.text = "Weekly Report — Week " + str(df['week'].iloc[0])
tf.paragraphs[0].font.size = Pt(36)
tf.paragraphs[0].font.color.rgb = RGBColor(0x1E, 0x3A, 0x5F)

# 4. KPI slide — manually position each metric
slide = prs.slides.add_slide(prs.slide_layouts[6])
metrics = [
    ("Revenue", "$" + format(df['revenue'].iloc[0], ',.0f')),
    ("Clients", format(df['clients'].iloc[0], ',')),
    ("Margin",  format(df['margin'].iloc[0], '.1f') + "%"),
]

for i, (label, value) in enumerate(metrics):
    left = Inches(1 + i * 4)
    txBox = slide.shapes.add_textbox(left, Inches(2), Inches(3), Inches(1))
    txBox.text_frame.text = value
    txBox.text_frame.paragraphs[0].font.size = Pt(32)
    txBox.text_frame.paragraphs[0].font.bold = True
    txBox = slide.shapes.add_textbox(left, Inches(3), Inches(3), Inches(0.5))
    txBox.text_frame.text = label
    txBox.text_frame.paragraphs[0].font.size = Pt(14)
    # ... repeat for trend arrows, colors, alignment

# 5. Save
prs.save("weekly_report.pptx")
# That's ~60 lines for ONE slide type. A 15-slide deck = 500+ lines.

This works, but maintaining 500+ lines of layout code per report is a burden. Every font change, color update, or new metric means touching Python code.

Approach 2: SlideForge API (10 lines, consulting-quality)

SlideForge handles the layout, design, and rendering. You send data, you get back a .pptx.

import pandas as pd
import requests

# 1. Read data from Excel
df = pd.read_excel("weekly_metrics.xlsx", sheet_name="Summary")
row = df.iloc[0]

# 2. Generate KPI slide via API ($0.03, <1s)
resp = requests.post(
    "https://api.slideforge.dev/v1/render",
    headers={"Authorization": "Bearer sf_live_YOUR_KEY"},
    json={
        "template": "kpi_dashboard",
        "params": {
            "title": "Week %d Performance" % int(row['week']),
            "metrics": [
                {"value": "$%s" % format(row['revenue'], ',.0f'), "label": "Revenue",
                 "trend": "%+.1f%%" % row['revenue_growth'], "trend_dir": "up"},
                {"value": "%s" % format(int(row['clients']), ','), "label": "Clients",
                 "trend": "%+.1f%%" % row['client_growth'], "trend_dir": "up"},
                {"value": "%.1f%%" % row['margin'], "label": "Margin",
                 "trend": "%+.1fpp" % row['margin_change'], "trend_dir": "down"},
            ],
        },
        "theme_id": "consulting_blue",
        "chrome": {"footer": "Confidential", "kicker": "WEEKLY REVIEW"}
    },
)
data = resp.json()
print("Slide ready:", data['pptx_url'])  # download link

That's one slide for $0.03. For a full deck, use the deck endpoint to generate all slides in parallel:

# Generate a 5-slide weekly report deck ($0.15-$0.25, ~3s)
resp = requests.post(
    "https://api.slideforge.dev/v1/deck",
    headers={"Authorization": "Bearer sf_live_YOUR_KEY"},
    json={
        "slides": [
            {"render": {"template": "title_slide", "brief": "Weekly Report — Week 14"}},
            {"render": {"template": "kpi_dashboard", "params": kpi_data}},
            {"render": {"template": "bar_chart", "params": chart_data}},
            {"render": {"template": "data_table", "params": table_data}},
            {"render": {"template": "next_steps", "params": actions_data}},
        ],
        "theme_id": "consulting_blue",
        "title": "Weekly Report W14"
    },
)
deck = resp.json()
# Poll GET /v1/jobs/<job_id> for completion -> pptx_url

Scheduling the pipeline

Cron (simplest)

# Run every Monday at 7 AM
0 7 * * 1 /usr/bin/python3 /opt/reports/weekly_report.py

GitHub Actions (free for public repos)

# .github/workflows/weekly-report.yml
name: Weekly Report
on:
  schedule:
    - cron: '0 7 * * 1'  # Monday 7 AM UTC
jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install requests pandas openpyxl
      - run: python generate_weekly_report.py
        env:
          SLIDEFORGE_API_KEY: ${{ secrets.SLIDEFORGE_API_KEY }}

Airflow / n8n / Zapier

Any orchestrator that can run Python works. Airflow: create a DAG with a PythonOperator. n8n: use the Code node. Zapier: use the Code by Zapier step (Python).

Adding email delivery

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# Download the generated PPTX
pptx_bytes = requests.get(data["pptx_url"]).content

# Send via SMTP
msg = MIMEMultipart()
msg["Subject"] = "Weekly Report — Week " + str(int(row['week']))
msg["From"] = "reports@yourcompany.com"
msg["To"] = "team@yourcompany.com"

attachment = MIMEBase("application",
    "vnd.openxmlformats-officedocument.presentationml.presentation")
attachment.set_payload(pptx_bytes)
encoders.encode_base64(attachment)
attachment.add_header("Content-Disposition",
    "attachment; filename=weekly_report.pptx")
msg.attach(attachment)

with smtplib.SMTP("smtp.yourcompany.com", 587) as server:
    server.starttls()
    server.login("reports@yourcompany.com", "password")
    server.send_message(msg)

Cost comparison

A 15-slide weekly report using template rendering:

  • python-pptx: Free, but 500+ lines of layout code. 2-4 hours initial build, ongoing maintenance.
  • SlideForge templates: $0.03-$0.05/slide = $0.45-$0.75/week = $23-39/year. Zero layout code.
  • Manual creation: 1-2 hours/week × $50/hr = $2,500-5,000/year. The most expensive option by far.

Browse templates for reports

50 templates cover the most common report slide types: browse the gallery. Popular for reports:

  • kpi_dashboard — 2-6 metric cards with trends
  • data_table — structured data in rows and columns
  • bar_chart / stacked_bar — visual comparisons
  • waterfall_chart — revenue bridges, P&L walkthroughs
  • timeline — milestones and deadlines

Get started

Sign up for $3 free credit (enough for 60-100 template slides), or read the render API docs. Need help picking templates? Read the briefs guide.

Frequently asked questions

How much does it cost to automate weekly PowerPoint reports?

With SlideForge template rendering at $0.03-$0.05/slide, a 15-slide weekly report costs $0.45-$0.75/week — less than $39/year. Compare to 1-2 hours of manual work per week.

Can I schedule automated slide generation?

Yes. Use cron, GitHub Actions, Airflow, n8n, or Zapier to run your Python script on a schedule. The SlideForge API is stateless — just make the HTTP call and download the result.

Do I need python-pptx to use SlideForge?

No. SlideForge is a REST API — you send JSON, you get a .pptx download URL. No python-pptx, no layout code, no font management. Works from any language (Python, Node.js, Go, Ruby, curl).

Try SlideForge free

$3 credit, no card required. Generate your first slide in under a minute.