Skill v1.0.1
currentLLM-judged scan100/1001 files
version: "1.0.1" name: reportlab description: "PDF generation toolkit. Create invoices, reports, certificates, forms, charts, tables, barcodes, QR codes, Canvas/Platypus APIs, for professional document automation."
ReportLab PDF Generation
Overview
ReportLab is a powerful Python library for programmatic PDF generation. Create anything from simple documents to complex reports with tables, charts, images, and interactive forms.
Two main approaches:
- Canvas API (low-level): Direct drawing with coordinate-based positioning - use for precise layouts
- Platypus (high-level): Flowing document layout with automatic page breaks - use for multi-page documents
Core capabilities:
- Text with rich formatting and custom fonts
- Tables with complex styling and cell spanning
- Charts (bar, line, pie, area, scatter)
- Barcodes and QR codes (Code128, EAN, QR, etc.)
- Images with transparency
- PDF features (links, bookmarks, forms, encryption)
Choosing the Right Approach
Use Canvas API when:
- Creating labels, business cards, certificates
- Precise positioning is critical (x, y coordinates)
- Single-page documents or simple layouts
- Drawing graphics, shapes, and custom designs
- Adding barcodes or QR codes at specific locations
Use Platypus when:
- Creating multi-page documents (reports, articles, books)
- Content should flow automatically across pages
- Need headers/footers that repeat on each page
- Working with paragraphs that can split across pages
- Building complex documents with table of contents
Use Both when:
- Complex reports need both flowing content AND precise positioning
- Adding headers/footers to Platypus documents (use
onPagecallback with Canvas) - Embedding custom graphics (Canvas) within flowing documents (Platypus)
Quick Start Examples
Simple Canvas Document
from reportlab.pdfgen import canvasfrom reportlab.lib.pagesizes import letterfrom reportlab.lib.units import inchc = canvas.Canvas("output.pdf", pagesize=letter)width, height = letter# Draw textc.setFont("Helvetica-Bold", 24)c.drawString(inch, height - inch, "Hello ReportLab!")# Draw a rectanglec.setFillColorRGB(0.2, 0.4, 0.8)c.rect(inch, 5*inch, 4*inch, 2*inch, fill=1)# Savec.showPage()c.save()
Simple Platypus Document
from reportlab.lib.pagesizes import letterfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacerfrom reportlab.lib.styles import getSampleStyleSheetfrom reportlab.lib.units import inchdoc = SimpleDocTemplate("output.pdf", pagesize=letter)story = []styles = getSampleStyleSheet()# Add contentstory.append(Paragraph("Document Title", styles['Title']))story.append(Spacer(1, 0.2*inch))story.append(Paragraph("This is body text with <b>bold</b> and <i>italic</i>.", styles['BodyText']))# Build PDFdoc.build(story)
Common Tasks
Creating Tables
Tables work with both Canvas (via Drawing) and Platypus (as Flowables):
from reportlab.platypus import Table, TableStylefrom reportlab.lib import colorsfrom reportlab.lib.units import inch# Define datadata = [['Product', 'Q1', 'Q2', 'Q3', 'Q4'],['Widget A', '100', '150', '130', '180'],['Widget B', '80', '120', '110', '160'],]# Create tabletable = Table(data, colWidths=[2*inch, 1*inch, 1*inch, 1*inch, 1*inch])# Apply stylingstyle = TableStyle([# Header row('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),('ALIGN', (0, 0), (-1, -1), 'CENTER'),# Data rows('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey]),('GRID', (0, 0), (-1, -1), 1, colors.black),])table.setStyle(style)# Add to Platypus storystory.append(table)# Or draw on Canvastable.wrapOn(c, width, height)table.drawOn(c, x, y)
Detailed table reference: See references/tables_reference.md for cell spanning, borders, alignment, and advanced styling.
Creating Charts
Charts use the graphics framework and can be added to both Canvas and Platypus:
from reportlab.graphics.shapes import Drawingfrom reportlab.graphics.charts.barcharts import VerticalBarChartfrom reportlab.lib import colors# Create drawingdrawing = Drawing(400, 200)# Create chartchart = VerticalBarChart()chart.x = 50chart.y = 50chart.width = 300chart.height = 125# Set datachart.data = [[100, 150, 130, 180, 140]]chart.categoryAxis.categoryNames = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5']# Stylechart.bars[0].fillColor = colors.bluechart.valueAxis.valueMin = 0chart.valueAxis.valueMax = 200# Add to drawingdrawing.add(chart)# Use in Platypusstory.append(drawing)# Or render directly to PDFfrom reportlab.graphics import renderPDFrenderPDF.drawToFile(drawing, 'chart.pdf', 'Chart Title')
Available chart types: Bar (vertical/horizontal), Line, Pie, Area, Scatter Detailed charts reference: See references/charts_reference.md for all chart types, styling, legends, and customization.
Adding Barcodes and QR Codes
from reportlab.graphics.barcode import code128from reportlab.graphics.barcode.qr import QrCodeWidgetfrom reportlab.graphics.shapes import Drawingfrom reportlab.graphics import renderPDF# Code128 barcode (general purpose)barcode = code128.Code128("ABC123456789", barHeight=0.5*inch)# On Canvasbarcode.drawOn(c, x, y)# QR Codeqr = QrCodeWidget("https://example.com")qr.barWidth = 2*inchqr.barHeight = 2*inch# Wrap in Drawing for Platypusd = Drawing()d.add(qr)story.append(d)
Supported formats: Code128, Code39, EAN-13, EAN-8, UPC-A, ISBN, QR, Data Matrix, and 20+ more Detailed barcode reference: See references/barcodes_reference.md for all formats and usage examples.
Working with Text and Fonts
from reportlab.platypus import Paragraphfrom reportlab.lib.styles import ParagraphStylefrom reportlab.lib.enums import TA_JUSTIFY# Create custom stylecustom_style = ParagraphStyle('CustomStyle',fontSize=12,leading=14, # Line spacingalignment=TA_JUSTIFY,spaceAfter=10,textColor=colors.black,)# Paragraph with inline formattingtext = """This paragraph has <b>bold</b>, <i>italic</i>, and <u>underlined</u> text.You can also use <font color="blue">colors</font> and <font size="14">different sizes</font>.Chemical formula: H<sub>2</sub>O, Einstein: E=mc<sup>2</sup>"""para = Paragraph(text, custom_style)story.append(para)
Using custom fonts:
from reportlab.pdfbase import pdfmetricsfrom reportlab.pdfbase.ttfonts import TTFont# Register TrueType fontpdfmetrics.registerFont(TTFont('CustomFont', 'CustomFont.ttf'))# Use in Canvasc.setFont('CustomFont', 12)# Use in Paragraph stylestyle = ParagraphStyle('Custom', fontName='CustomFont', fontSize=12)
Detailed text reference: See references/text_and_fonts.md for paragraph styles, font families, Asian languages, Greek letters, and formatting.
Adding Images
from reportlab.platypus import Imagefrom reportlab.lib.units import inch# In Platypusimg = Image('photo.jpg', width=4*inch, height=3*inch)story.append(img)# Maintain aspect ratioimg = Image('photo.jpg', width=4*inch, height=3*inch, kind='proportional')# In Canvasc.drawImage('photo.jpg', x, y, width=4*inch, height=3*inch)# With transparency (mask white background)c.drawImage('logo.png', x, y, mask=[255,255,255,255,255,255])
Creating Forms
from reportlab.pdfgen import canvasfrom reportlab.lib.colors import black, white, lightgreyc = canvas.Canvas("form.pdf")# Text fieldc.acroForm.textfield(name="name",tooltip="Enter your name",x=100, y=700,width=200, height=20,borderColor=black,fillColor=lightgrey,forceBorder=True)# Checkboxc.acroForm.checkbox(name="agree",x=100, y=650,size=20,buttonStyle='check',checked=False)# Dropdownc.acroForm.choice(name="country",x=100, y=600,width=150, height=20,options=[("United States", "US"), ("Canada", "CA")],forceBorder=True)c.save()
Detailed PDF features reference: See references/pdf_features.md for forms, links, bookmarks, encryption, and metadata.
Headers and Footers
For Platypus documents, use page callbacks:
from reportlab.platypus import BaseDocTemplate, PageTemplate, Framedef add_header_footer(canvas, doc):"""Called on each page"""canvas.saveState()# Headercanvas.setFont('Helvetica', 9)canvas.drawString(inch, height - 0.5*inch, "Document Title")# Footercanvas.drawRightString(width - inch, 0.5*inch, f"Page {doc.page}")canvas.restoreState()# Set up documentdoc = BaseDocTemplate("output.pdf")frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal')template = PageTemplate(id='normal', frames=[frame], onPage=add_header_footer)doc.addPageTemplates([template])# Build with storydoc.build(story)
Helper Scripts
This skill includes helper scripts for common tasks:
Quick Document Generator
Use scripts/quick_document.py for rapid document creation:
from scripts.quick_document import create_simple_document, create_styled_table# Simple document from content blockscontent = [{'type': 'heading', 'content': 'Introduction'},{'type': 'paragraph', 'content': 'Your text here...'},{'type': 'bullet', 'content': 'Bullet point'},]create_simple_document("output.pdf", "My Document", content_blocks=content)# Styled tables with presetsdata = [['Header1', 'Header2'], ['Data1', 'Data2']]table = create_styled_table(data, style_name='striped') # 'default', 'striped', 'minimal', 'report'
Template Examples
Complete working examples in assets/:
Invoice Template
assets/invoice_template.py - Professional invoice with:
- Company and client information
- Itemized table with calculations
- Tax and totals
- Terms and notes
- Logo placement
from assets.invoice_template import create_invoicecreate_invoice(filename="invoice.pdf",invoice_number="INV-2024-001",invoice_date="January 15, 2024",due_date="February 15, 2024",company_info={'name': 'Acme Corp', 'address': '...', 'phone': '...', 'email': '...'},client_info={'name': 'Client Name', ...},items=[{'description': 'Service', 'quantity': 1, 'unit_price': 500.00},...],tax_rate=0.08,notes="Thank you for your business!",)
Report Template
assets/report_template.py - Multi-page business report with:
- Cover page
- Table of contents
- Multiple sections with subsections
- Charts and tables
- Headers and footers
from assets.report_template import create_reportreport_data = {'title': 'Quarterly Report','subtitle': 'Q4 2023','author': 'Analytics Team','sections': [{'title': 'Executive Summary','content': 'Report content...','table_data': {...},'chart_data': {...}},...]}create_report("report.pdf", report_data)
Reference Documentation
Comprehensive API references organized by feature:
- `references/canvas_api.md` - Low-level Canvas: drawing primitives, coordinates, transformations, state management, images, paths
- `references/platypus_guide.md` - High-level Platypus: document templates, frames, flowables, page layouts, TOC
- `references/text_and_fonts.md` - Text formatting: paragraph styles, inline markup, custom fonts, Asian languages, bullets, sequences
- `references/tables_reference.md` - Tables: creation, styling, cell spanning, borders, alignment, colors, gradients
- `references/charts_reference.md` - Charts: all chart types, data handling, axes, legends, colors, rendering
- `references/barcodes_reference.md` - Barcodes: Code128, QR codes, EAN, UPC, postal codes, and 20+ formats
- `references/pdf_features.md` - PDF features: links, bookmarks, forms, encryption, metadata, page transitions
Best Practices
Coordinate System (Canvas)
- Origin (0, 0) is lower-left corner (not top-left)
- Y-axis points upward
- Units are in points (72 points = 1 inch)
- Always specify page size explicitly
from reportlab.lib.pagesizes import letterfrom reportlab.lib.units import inchwidth, height = lettermargin = inch# Top of pagey_top = height - margin# Bottom of pagey_bottom = margin
Choosing Page Size
from reportlab.lib.pagesizes import letter, A4, landscape# US Letter (8.5" x 11")pagesize=letter# ISO A4 (210mm x 297mm)pagesize=A4# Landscapepagesize=landscape(letter)# Custompagesize=(6*inch, 9*inch)
Performance Tips
- Use `drawImage()` over `drawInlineImage()` - caches images for reuse
- Enable compression for large files:
canvas.Canvas("file.pdf", pageCompression=1) - Reuse styles - create once, use throughout document
- Use Forms/XObjects for repeated graphics
Common Patterns
Centering text on Canvas:
text = "Centered Text"text_width = c.stringWidth(text, "Helvetica", 12)x = (width - text_width) / 2c.drawString(x, y, text)# Or use built-inc.drawCentredString(width/2, y, text)
Page breaks in Platypus:
from reportlab.platypus import PageBreakstory.append(PageBreak())
Keep content together (no split):
from reportlab.platypus import KeepTogetherstory.append(KeepTogether([heading,paragraph1,paragraph2,]))
Alternate row colors:
style = TableStyle([('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey]),])
Troubleshooting
Text overlaps or disappears:
- Check Y-coordinates - remember origin is bottom-left
- Ensure text fits within page bounds
- Verify
leading(line spacing) is greater thanfontSize
Table doesn't fit on page:
- Reduce column widths
- Decrease font size
- Use landscape orientation
- Enable table splitting with
repeatRows
Barcode not scanning:
- Increase
barHeight(try 0.5 inch minimum) - Set
quiet=1for quiet zones - Test print quality (300+ DPI recommended)
- Validate data format for barcode type
Font not found:
- Register TrueType fonts with
pdfmetrics.registerFont() - Use font family name exactly as registered
- Check font file path is correct
Images have white background:
- Use
maskparameter to make white transparent - Provide RGB range to mask:
mask=[255,255,255,255,255,255] - Or use PNG with alpha channel
Example Workflows
Creating an Invoice
- Start with invoice template from
assets/invoice_template.py - Customize company info, logo path
- Add items with descriptions, quantities, prices
- Set tax rate if applicable
- Add notes and payment terms
- Generate PDF
Creating a Report
- Start with report template from
assets/report_template.py - Define sections with titles and content
- Add tables for data using
create_styled_table() - Add charts using graphics framework
- Build with
doc.multiBuild(story)for TOC
Creating a Certificate
- Use Canvas API for precise positioning
- Load custom fonts for elegant typography
- Add border graphics or image background
- Position text elements (name, date, achievement)
- Optional: Add QR code for verification
Creating Labels with Barcodes
- Use Canvas with custom page size (label dimensions)
- Calculate grid positions for multiple labels per page
- Draw label content (text, images)
- Add barcode at specific position
- Use
showPage()between labels or grids
Installation
uv pip install reportlab# For image supportuv pip install pillow# For chartsuv pip install reportlab[renderPM]# For barcode support (included in reportlab)# QR codes require: uv pip install qrcode
When to Use This Skill
This skill should be used when:
- Generating PDF documents programmatically
- Creating invoices, receipts, or billing documents
- Building reports with tables and charts
- Generating certificates, badges, or credentials
- Creating shipping labels or product labels with barcodes
- Designing forms or fillable PDFs
- Producing multi-page documents with consistent formatting
- Converting data to PDF format for archival or distribution
- Creating custom layouts that require precise positioning
This skill provides comprehensive guidance for all ReportLab capabilities, from simple documents to complex multi-page reports with charts, tables, and interactive elements.