DEV Community

Brad
Brad

Posted on

Python Invoice Generator: Create Professional PDFs from CSV in Seconds

Python Invoice Generator: Create Professional PDFs from CSV in Seconds

Creating invoices manually takes 15-30 minutes each. Python generates professional PDFs in seconds.

Install

pip install reportlab
Enter fullscreen mode Exit fullscreen mode

Complete Invoice Generator

from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
from datetime import datetime, timedelta

def generate_invoice(client_data, line_items, output_file):
    doc = SimpleDocTemplate(output_file, pagesize=letter)
    styles = getSampleStyleSheet()
    story = []

    # Header
    story.append(Paragraph('INVOICE', styles['Title']))
    story.append(Spacer(1, 0.2*inch))

    # Metadata
    invoice_num = f"INV-{datetime.now().strftime('%Y%m%d')}-{client_data.get('id', '001')}"
    due_date = (datetime.now() + timedelta(days=30)).strftime('%B %d, %Y')

    meta = [['Invoice #:', invoice_num], ['Date:', datetime.now().strftime('%B %d, %Y')], ['Due:', due_date]]
    story.append(Table(meta, colWidths=[2*inch, 3*inch]))
    story.append(Spacer(1, 0.3*inch))

    # Client
    story.append(Paragraph('Bill To: ' + client_data['name'], styles['Heading2']))
    story.append(Paragraph(client_data['email'], styles['Normal']))
    story.append(Spacer(1, 0.3*inch))

    # Line items
    headers = ['Description', 'Qty', 'Rate', 'Amount']
    data = [headers]
    subtotal = 0

    for item in line_items:
        qty = float(item['quantity'])
        rate = float(item['rate'])
        amount = qty * rate
        subtotal += amount
        data.append([item['description'], str(qty), f'${rate:.2f}', f'${amount:.2f}'])

    tax = subtotal * 0.1
    total = subtotal + tax
    data.extend([['', '', 'Subtotal:', f'${subtotal:.2f}'],
                 ['', '', 'Tax (10%):', f'${tax:.2f}'],
                 ['', '', 'TOTAL:', f'${total:.2f}']])

    table = Table(data, colWidths=[4*inch, inch, 1.2*inch, 1.3*inch])
    table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#2c3e50')),
        ('TEXTCOLOR', (0,0), (-1,0), colors.white),
        ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
        ('FONTNAME', (2,-1), (-1,-1), 'Helvetica-Bold'),
        ('GRID', (0,0), (-1,-4), 0.5, colors.grey),
    ]))
    story.append(table)
    story.append(Spacer(1, 0.3*inch))
    story.append(Paragraph('Payment Terms: Net 30 | Methods: Bank, PayPal, Check', styles['Normal']))

    doc.build(story)
    return output_file

# Example
client = {'id': '042', 'name': 'Acme Corp', 'email': 'accounts@acme.com'}
items = [
    {'description': 'Web Development', 'quantity': 1, 'rate': 1500},
    {'description': 'Python Automation', 'quantity': 3, 'rate': 250},
    {'description': 'Monthly Maintenance', 'quantity': 1, 'rate': 200},
]
output = generate_invoice(client, items, 'invoice_042.pdf')
print(f'Invoice created: {output}')
Enter fullscreen mode Exit fullscreen mode

Time Savings

Method Per Invoice 50/month
Manual 20 min 1000 min
Python 2 sec 100 sec
Saved 20 min 16+ hours

At $50/hr, that's $800/month saved.

Batch from CSV

import csv, os

def batch_generate(csv_file):
    with open(csv_file, 'r') as f:
        for row in csv.DictReader(f):
            items = [{'description': p.split('|')[0], 'quantity': p.split('|')[1], 'rate': p.split('|')[2]}
                     for p in row['line_items'].split(';') if len(p.split('|')) == 3]
            os.makedirs('invoices', exist_ok=True)
            generate_invoice(row, items, f'invoices/{row["name"].replace(" ", "_")}.pdf')

# CSV: name,email,id,line_items
# Acme,acme@example.com,001,Web Dev|1|1500;Python|3|250
Enter fullscreen mode Exit fullscreen mode

Get the Complete Toolkit

Part of the Python Business Automation Toolkit — $9 for invoice generation + email automation + file scripts + web scraping.

Drop your biggest admin time-sink in the comments!

Top comments (0)