Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Beginner ⏱ 30 min

📄 Build a PDF Report Generator with Python

🎯 What You'll Build

A Python script that generates a professional PDF report with a title page, summary table, charts, and styled sections — ready to email or share.

📋 What You'll Need

1

Install ReportLab and create a basic PDF

ReportLab is the gold standard for PDF generation in Python — stable since 2000.

pip install reportlab
from reportlab.pdfgen import canvas

# Create a PDF
c = canvas.Canvas("report.pdf")

# Add text
c.setFont("Helvetica-Bold", 24)
c.drawString(100, 750, "Monthly Sales Report")

c.setFont("Helvetica", 12)
c.drawString(100, 720, "Generated: August 2026")
c.drawString(100, 700, "Prepared by: IT Expert Training")

c.save()
print("report.pdf created!")
report.pdf created!
2

Use the high-level Platypus layout engine

Platypus (part of ReportLab) lets you build multi-page documents with paragraphs, tables, and images using a flow-based layout.

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle

doc = SimpleDocTemplate(
    "sales_report.pdf",
    pagesize=A4,
    leftMargin=2*cm, rightMargin=2*cm,
    topMargin=2*cm,  bottomMargin=2*cm
)

styles = getSampleStyleSheet()
story  = []   # list of flowables (content blocks)

# Title
title_style = ParagraphStyle(
    'Title', parent=styles['Heading1'],
    fontSize=22, textColor=colors.HexColor('#162447'),
    spaceAfter=6
)
story.append(Paragraph("Monthly Sales Report — August 2026", title_style))
story.append(Paragraph("Prepared by IT Expert Training", styles['Normal']))
story.append(Spacer(1, 0.8*cm))

doc.build(story)
print("sales_report.pdf created!")
3

Add a styled data table

ReportLab tables accept a 2D list of data and a TableStyle to control colours and borders.

# Sales data
data = [
    ['Product',    'Units Sold', 'Revenue',   'Growth'],
    ['Python Course',  '124',   '₹1,24,000', '+18%'],
    ['Web Dev Course',  '89',   '₹89,000',   '+12%'],
    ['AI Bootcamp',     '56',   '₹1,12,000', '+34%'],
    ['Arduino Kit',     '210',  '₹63,000',   '+5%'],
    ['Total',          '479',   '₹3,88,000', '+17%'],
]

table = Table(data, colWidths=[5*cm, 3*cm, 3.5*cm, 2.5*cm])
table.setStyle(TableStyle([
    # Header row
    ('BACKGROUND',   (0,0), (-1,0),  colors.HexColor('#162447')),
    ('TEXTCOLOR',    (0,0), (-1,0),  colors.white),
    ('FONTNAME',     (0,0), (-1,0),  'Helvetica-Bold'),
    ('FONTSIZE',     (0,0), (-1,-1), 10),
    ('ALIGN',        (0,0), (-1,-1), 'CENTER'),
    ('ROWBACKGROUNDS',(0,1),(-1,-2), [colors.whitesmoke, colors.white]),
    # Total row
    ('BACKGROUND',   (0,-1),(-1,-1), colors.HexColor('#FFF3CD')),
    ('FONTNAME',     (0,-1),(-1,-1), 'Helvetica-Bold'),
    # Grid
    ('GRID',         (0,0), (-1,-1), 0.5, colors.lightgrey),
    ('TOPPADDING',   (0,0), (-1,-1), 6),
    ('BOTTOMPADDING',(0,0), (-1,-1), 6),
]))

story.append(Paragraph("Sales Summary", styles['Heading2']))
story.append(Spacer(1, 0.3*cm))
story.append(table)
story.append(Spacer(1, 0.8*cm))
4

Add a chart using matplotlib

Generate a chart with matplotlib, save it as an image, and embed it in the PDF.

import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg')  # non-interactive backend for saving files
from reportlab.platypus import Image
import io

# Create bar chart
products = ['Python\nCourse', 'Web Dev\nCourse', 'AI\nBootcamp', 'Arduino\nKit']
revenue  = [124000, 89000, 112000, 63000]

fig, ax = plt.subplots(figsize=(6, 3))
bars = ax.bar(products, revenue, color=['#162447','#1E3A6E','#F59C0D','#e74c3c'])
ax.set_title('Revenue by Product', fontweight='bold')
ax.set_ylabel('Revenue (₹)')
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f'₹{x/1000:.0f}K'))
for bar, val in zip(bars, revenue):
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1000,
            f'₹{val//1000}K', ha='center', fontsize=9, fontweight='bold')
plt.tight_layout()

# Save chart to memory buffer (no temp file needed)
buf = io.BytesIO()
fig.savefig(buf, format='png', dpi=150, bbox_inches='tight')
buf.seek(0)
plt.close()

story.append(Paragraph("Revenue Chart", styles['Heading2']))
story.append(Spacer(1, 0.3*cm))
story.append(Image(buf, width=14*cm, height=7*cm))

# Build the final PDF
doc.build(story)
print("sales_report.pdf ready!")
sales_report.pdf ready!
[PDF opens with: title, date, styled table with coloured header and alternating rows, bar chart]
💡 Tip: To send the PDF by email automatically, use Python's smtplib with the PDF attached as a base64-encoded MIMEApplication — check the "Send Automated Emails with Python" tutorial on this site.

🎉 You Did It!

You generated a professional multi-section PDF entirely in Python — no Word, no Excel, no manual formatting. ReportLab has been stable since 2000 and powers PDF generation for banks, governments, and major enterprises.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.