Python PDF Generator: Create Professional Reports from Data in 10 Lines
Stop manually creating PDF reports. Here's how to generate professional documents from your data automatically.
Basic PDF with ReportLab
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle, Spacer
from reportlab.platypus import Image
import io
def create_report(filename: str, title: str, data: list, headers: list):
"""Create a professional PDF report from tabular data."""
doc = SimpleDocTemplate(
filename,
pagesize=letter,
rightMargin=72,
leftMargin=72,
topMargin=72,
bottomMargin=18
)
styles = getSampleStyleSheet()
story = []
# Title
story.append(Paragraph(title, styles['Title']))
story.append(Spacer(1, 12))
# Add date
from datetime import datetime
date_str = datetime.now().strftime("%B %d, %Y")
story.append(Paragraph(f"Generated: {date_str}", styles['Normal']))
story.append(Spacer(1, 24))
# Create table data
table_data = [headers] + data
# Build table
table = Table(table_data)
table.setStyle(TableStyle([
# Header row
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#2C3E50')),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
# Data rows
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('TEXTCOLOR', (0, 1), (-1, -1), colors.black),
('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
('FONTSIZE', (0, 1), (-1, -1), 10),
('GRID', (0, 0), (-1, -1), 1, colors.black),
# Alternating row colors
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.HexColor('#ECF0F1')]),
]))
story.append(table)
doc.build(story)
print(f"PDF saved: {filename}")
# Usage
headers = ["Month", "Revenue", "Expenses", "Profit"]
data = [
["January", "$12,400", "$8,200", "$4,200"],
["February", "$15,600", "$9,100", "$6,500"],
["March", "$18,200", "$10,400", "$7,800"],
["April", "$14,800", "$8,900", "$5,900"],
]
create_report("quarterly_report.pdf", "Q1 Financial Report", data, headers)
Invoice Generator
Create invoices automatically:
def generate_invoice(
invoice_data: dict,
output_file: str
):
"""Generate a professional invoice PDF."""
doc = SimpleDocTemplate(output_file, pagesize=letter)
styles = getSampleStyleSheet()
story = []
# Company header
story.append(Paragraph(invoice_data['company_name'], styles['Heading1']))
story.append(Paragraph(invoice_data['company_address'], styles['Normal']))
story.append(Spacer(1, 24))
# Invoice number and date
invoice_info = [
[f"Invoice #: {invoice_data['invoice_number']}", ""],
[f"Date: {invoice_data['date']}", ""],
[f"Due: {invoice_data['due_date']}", ""],
]
# Client info
client_section = Table([
["Bill To:"],
[invoice_data['client_name']],
[invoice_data['client_address']],
[invoice_data['client_email']],
])
story.append(client_section)
story.append(Spacer(1, 24))
# Line items
items_data = [["Description", "Qty", "Rate", "Amount"]]
subtotal = 0
for item in invoice_data['items']:
amount = item['qty'] * item['rate']
subtotal += amount
items_data.append([
item['description'],
str(item['qty']),
f"${item['rate']:.2f}",
f"${amount:.2f}"
])
# Add totals
tax = subtotal * 0.20
total = subtotal + tax
items_data.append(["", "", "Subtotal:", f"${subtotal:.2f}"])
items_data.append(["", "", "Tax (20%):", f"${tax:.2f}"])
items_data.append(["", "", "Total:", f"${total:.2f}"])
items_table = Table(items_data, colWidths=[3.5*inch, 0.75*inch, 1*inch, 1*inch])
items_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('GRID', (0, 0), (-1, -2), 0.5, colors.grey),
('FONTNAME', (0, -3), (-1, -1), 'Helvetica-Bold'),
('LINEABOVE', (0, -3), (-1, -3), 1, colors.black),
]))
story.append(items_table)
doc.build(story)
# Example usage
invoice_data = {
"company_name": "My Freelance Business",
"company_address": "123 Main St, City, Country",
"invoice_number": "INV-001",
"date": "2025-01-15",
"due_date": "2025-01-30",
"client_name": "Client Corp Ltd",
"client_address": "456 Business Ave",
"client_email": "billing@client.com",
"items": [
{"description": "Python automation script", "qty": 1, "rate": 500},
{"description": "API integration", "qty": 3, "rate": 150},
{"description": "Testing & documentation", "qty": 2, "rate": 75},
]
}
generate_invoice(invoice_data, "invoice_001.pdf")
Convert HTML to PDF
If you have HTML templates, convert them directly:
# pip install weasyprint
from weasyprint import HTML, CSS
def html_to_pdf(html_content: str, output_file: str, base_url: str = None):
"""Convert HTML string to PDF."""
css = CSS(string='''
@page {
size: A4;
margin: 1in;
}
body {
font-family: Arial, sans-serif;
font-size: 11pt;
line-height: 1.5;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #4CAF50;
color: white;
}
''')
html = HTML(string=html_content, base_url=base_url)
html.write_pdf(output_file, stylesheets=[css])
print(f"PDF created: {output_file}")
# Usage
with open("report.html", "r") as f:
html_content = f.read()
html_to_pdf(html_content, "report.pdf")
Practical Applications
- Monthly financial reports sent automatically by email
- Automated invoice generation with your branding
- Converting web pages to PDF archives
- Generating certificates or contracts programmatically
Ready-Made Automation Scripts?
PDF generation is one part of the automation toolkit I use daily.
👉 Get 50+ Python automation scripts — invoice generator, report builder, email sender, web scraper, data processor, and 45+ more.
Install and use immediately — no setup required beyond pip install.
Top comments (0)