DEV Community

Brad
Brad

Posted on

Python PDF Generator: Create Professional Reports from Data in 10 Lines

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)
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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)