- name
- presentation-automation
- description
- Presentation Automation: python-pptx, Google Slides API, automated slide generation from data and templates
- metadata
- {"author":"cosmicstack-labs","version":"1.0.0","category":"presentation","tags":["presentation-automation","python-pptx","google-slides-api","slide-generation","automation"]}
# Presentation Automation
Automate slide generation from data sources, build programmatic presentations, and integrate slide creation into CI/CD pipelines.
## Core Principles
### 1. Templates Are the Foundation
Never build slides from scratch in code. Create a well-designed template (.potx or Google Slides master), then populate it programmatically. Templates enforce consistency; code fills in the blanks.
### 2. Separate Data from Presentation
Keep data extraction, transformation, and presentation logic in distinct layers. CSV/JSON/API → Data transformation → Slide population. This makes both testing and maintenance easier.
### 3. Idempotency Matters
The same input data should always produce the same output slides. Use deterministic logic, avoid random placement, and version your templates alongside your code.
### 4. Validate Before Generating
Validate input data, template placeholders, and output formats before generating slides. A broken slide at 11:59 PM before the board meeting is a career-limiting bug.
---
## Presentation Automation Maturity Model
| Level | Approach | Data Integration | Error Handling | Maintainability |
|-------|----------|-----------------|----------------|-----------------|
| **1: Manual** | Copy-paste into PowerPoint | Manual data entry | Human review | Fragile, one-off |
| **2: Scripted** | Basic python-pptx scripts | CSV/Excel import | Try-except blocks | Single-purpose scripts |
| **3: Templated** | Template-based generation | API/DB connections | Validation, logging | Modular functions |
| **4: Automated** | CI/CD pipeline, scheduled runs | Multiple data sources | Automated testing | Parameterized, configurable |
| **5: Intelligent** | Auto-charting, NLP summaries | Streaming data | Self-healing | Framework with plugins |
Target: **Level 3** for recurring reports. **Level 4** for client-facing and board presentations.
---
## python-pptx Fundamentals
### Installation and Setup
```bash
# Install python-pptx
pip install python-pptx
# For working with images
pip install Pillow
# For data processing
pip install pandas numpy openpyxl
# Verify installation
python -c "import pptx; print(pptx.__version__)"
```
### Basic Slide Creation
```python
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
# Create a presentation
prs = Presentation()
# Set dimensions for 16:9 widescreen
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
# Common aspect ratios
aspect_ratios = {
"standard_4_3": (Inches(10), Inches(7.5)),
"widescreen_16_9": (Inches(13.333), Inches(7.5)),
"widescreen_16_10": (Inches(11.25), Inches(7.03)),
"a4": (Inches(11.69), Inches(8.27)),
}
# Add a blank slide
slide_layout = prs.slide_layouts[6] # 6 = blank layout
slide = prs.slides.add_slide(slide_layout)
# Add a title text box
left = Inches(0.5)
top = Inches(0.5)
width = Inches(12)
height = Inches(1)
txBox = slide.shapes.add_textbox(left, top, width, height)
tf = txBox.text_frame
tf.word_wrap = True
p = tf.paragraphs[0]
p.text = "Hello, Automated World!"
p.font.size = Pt(44)
p.font.bold = True
p.font.color.rgb = RGBColor(0x1A, 0x36, 0x5D)
p.alignment = PP_ALIGN.LEFT
# Save
prs.save("automated_presentation.pptx")
print("Presentation created successfully!")
```
### Working with Slide Layouts and Placeholders
```python
from pptx import Presentation
def inspect_template_layouts(template_path):
"""Inspect all layouts and placeholders in a template."""
prs = Presentation(template_path)
for i, layout in enumerate(prs.slide_layouts):
print(f"\nLayout {i}: {layout.name}")
for j, placeholder in enumerate(layout.placeholders):
print(f" Placeholder {j}: idx={placeholder.placeholder_format.idx}, "
f"name='{placeholder.name}', type={placeholder.placeholder_format.type}")
return prs
# Usage
# inspect_template_layouts("my_template.potx")
def populate_placeholder_slide(template_path, output_path, data):
"""
Populate placeholders in a template slide.
Args:
template_path: Path to .pptx template
output_path: Path for generated file
data: Dict mapping placeholder_idx -> text
"""
prs = Presentation(template_path)
# Use the first layout (index 0 — typically title slide)
layout = prs.slide_layouts[0]
slide = prs.slides.add_slide(layout)
for placeholder in slide.placeholders:
idx = placeholder.placeholder_format.idx
if idx in data:
placeholder.text = data[idx]
prs.save(output_path)
print(f"Generated: {output_path}")
# Example
# populate_placeholder_slide(
# "template.pptx",
# "output.pptx",
# {0: "Q4 2024 Board Report", 1: "Prepared by Analytics Team"}
# )
```
---
## Chart Generation
### Creating Bar Charts
```python
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
def add_bar_chart(slide, categories, values, title="",
chart_type=XL_CHART_TYPE.COLUMN_CLUSTERED):
"""
Add a bar/column chart to a slide.
Args:
slide: pptx Slide object
categories: List of category labels
values: List of numeric values
title: Chart title string
chart_type: XL_CHART_TYPE constant
"""
chart_data = CategoryChartData()
chart_data.categories = categories
chart_data.add_series("Revenue", values)
# Add chart to slide
left = Inches(0.5)
top = Inches(1.5)
width = Inches(12)
height = Inches(5.5)
chart_frame = slide.shapes.add_chart(
chart_type, left, top, width, height, chart_data
)
chart = chart_frame.chart
# Style the chart
chart.has_legend = True
chart.legend.include_in_layout = False
# Style the plot
plot = chart.plots[0]
plot.gap_width = 80 # Gap between bars
# Set colors for each series point
series = plot.series[0]
series.format.fill.solid()
series.format.fill.fore_color.rgb = RGBColor(0x2B, 0x6C, 0xB0)
# Title
chart.has_title = True
chart.chart_title.text_frame.paragraphs[0].text = title
chart.chart_title.text_frame.paragraphs[0].font.size = Pt(16)
chart.chart_title.text_frame.paragraphs[0].font.bold = True
return chart
def add_line_chart(slide, categories, series_data, title=""):
"""
Add a line chart with multiple series.
Args:
slide: Slide object
categories: List of category labels (x-axis)
series_data: List of (name, values) tuples
title: Chart title
"""
chart_data = CategoryChartData()
chart_data.categories = categories
colors = [
RGBColor(0x2B, 0x6C, 0xB0), # Blue
RGBColor(0xE5, 0x3E, 0x3E), # Red
RGBColor(0x38, 0xA1, 0x69), # Green
RGBColor(0xD6, 0x9E, 0x2E), # Amber
]
for i, (name, values) in enumerate(series_data):
chart_data.add_series(name, values)
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.LINE_MARKERS,
Inches(0.5), Inches(1.5),
Inches(12), Inches(5.5),
chart_data
)
chart = chart_frame.chart
# Style series
for i, series in enumerate(chart.series):
series.format.line.color.rgb = colors[i % len(colors)]
series.format.line.width = Pt(2.5)
chart.has_title = True
chart.chart_title.text_frame.paragraphs[0].text = title
chart.chart_title.text_frame.paragraphs[0].font.size = Pt(16)
chart.chart_title.text_frame.paragraphs[0].font.bold = True
return chart
```
### Creating Pie Charts
```python
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LABEL_POSITION
def add_pie_chart(slide, categories, values, title=""):
"""Add a styled pie chart (max 5 slices recommended)."""
chart_data = CategoryChartData()
chart_data.categories = categories
chart_data.add_series("Distribution", values)
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.PIE,
Inches(2), Inches(1.5),
Inches(9), Inches(5.5),
chart_data
)
chart = chart_frame.chart
# Add data labels with percentages
plot = chart.plots[0]
data_labels = plot.data_labels
data_labels.show_percentage = True
data_labels.show_category_name = True
data_labels.font.size = Pt(12)
data_labels.label_position = XL_LABEL_POSITION.OUTSIDE_END
# Colors for slices
colors = [
RGBColor(0x2B, 0x6C, 0xB0),
RGBColor(0x38, 0xA1, 0x69),
RGBColor(0xD6, 0x9E, 0x2E),
RGBColor(0xE5, 0x3E, 0x3E),
RGBColor(0x9B, 0x2C, 0x2C),
]
series = plot.series[0]
for i, point in enumerate(series.points):
point.format.fill.solid()
point.format.fill.fore_color.rgb = colors[i % len(colors)]
chart.has_title = True
chart.chart_title.text_frame.paragraphs[0].text = title
return chart
```
---
## Table Population from Data
### Creating Tables from DataFrames
```python
import pandas as pd
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
def dataframe_to_slide(prs, df, title="",
header_color=RGBColor(0x1A, 0x36, 0x5D),
header_text_color=RGBColor(0xFF, 0xFF, 0xFF),
alt_row_color=RGBColor(0xF7, 0xFA, 0xFC)):
"""
Convert a pandas DataFrame to a PowerPoint table on a new slide.
Args:
prs: Presentation object
df: pandas DataFrame
title: Slide title text
header_color: Background color for header row
header_text_color: Text color for header row
alt_row_color: Alternating row background color
"""
slide_layout = prs.slide_layouts[6] # Blank layout
slide = prs.slides.add_slide(slide_layout)
# Add title
if title:
txBox = slide.shapes.add_textbox(Inches(0.5), Inches(0.3),
Inches(12), Inches(0.8))
tf = txBox.text_frame
p = tf.paragraphs[0]
p.text = title
p.font.size = Pt(28)
p.font.bold = True
p.font.color.rgb = RGBColor(0x1A, 0x36, 0x5D)
# Table dimensions
rows, cols = len(df) + 1, len(df.columns) # +1 for header
left = Inches(0.5)
top = Inches(1.3)
width = Inches(12.3)
row_height = Inches(0.45)
height = row_height * rows
# Create table
table_shape = slide.shapes.add_table(rows, cols, left, top, width, height)
table = table_shape.table
# Set column widths proportionally
col_width = width / cols
for i in range(cols):
table.columns[i].width = col_width
# Header row
for j, col_name in enumerate(df.columns):
cell = table.cell(0, j)
cell.text = str(col_name)
# Format header
for paragraph in cell.text_frame.paragraphs:
paragraph.font.size = Pt(12)
paragraph.font.bold = True
paragraph.font.color.rgb = header_text_color
paragraph.alignment = PP_ALIGN.LEFT
# Header background color
cell.fill.solid()
cell.fill.fore_color.rgb = header_color
# Data rows
for i, (_, row) in enumerate(df.iterrows()):
for j, value in enumerate(row):
cell = table.cell(i + 1, j)
cell.text = str(value) if not pd.isna(value) else ""
for paragraph in cell.text_frame.paragraphs:
paragraph.font.size = Pt(11)
paragraph.font.color.rgb = RGBColor(0x2D, 0x37, 0x48)
paragraph.alignment = PP_ALIGN.LEFT
# Alternating row colors
if i % 2 == 1:
cell.fill.solid()
cell.fill.fore_color.rgb = alt_row_color
else:
cell.fill.solid()
cell.fill.fore_color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
return slide, table
# Usage example
# data = pd.DataFrame({
# "Metric": ["ARR", "MRR", "Users", "Churn"],
# "Value": ["$1.2M", "$100K", "45,000", "3.2%"],
# "Change": ["+40%", "+35%", "+22%", "-0.5%"],
# "Status": ["On Track", "On Track", "Ahead", "Watch"]
# })
# prs = Presentation()
# dataframe_to_slide(prs, data, title="Q4 2024 Key Metrics")
# prs.save("report.pptx")
Auf GitHub ansehen