ReportLab is a powerful, open-source Python library designed for programmatic creation of PDF documents. It allows developers to generate complex, dynamic PDF files from scratch, making it ideal for automating report generation, invoices, labels, data visualization, and other types of documents that require precise layout and styling.
The library offers two primary interfaces:
1. Low-level `canvas` API: This provides fine-grained control over PDF elements. Developers can draw shapes (lines, circles, rectangles), place text at exact coordinates, embed images, and manipulate font properties directly on a "canvas" object. This is suitable for simple, fixed-layout documents or specific graphic elements.
2. High-level `Platypus` (Page Layout and TypeSetting Utilities) API: This is a document template system built on top of the canvas API, designed for more complex, flowing documents. Platypus handles page breaks, paragraph flow, tables, lists, and styles, significantly simplifying the creation of multi-page documents. It uses "Flowables" (e.g., Paragraph, Table, Image, Spacer) which are content elements that can flow down the page.
Key features of ReportLab include:
- Dynamic Content: Generate PDFs based on data from databases, APIs, or other sources.
- Rich Text and Styling: Support for various fonts, colors, text alignment, and advanced paragraph formatting.
- Tables: Powerful table generation capabilities with customizable cell styles, spanning, and headers.
- Images: Embed various image formats (JPEG, PNG, GIF) into documents.
- Drawing Primitives: Draw lines, shapes, and paths.
- Templates: Define page templates for consistent headers, footers, and background elements.
- Cross-Platform: Works wherever Python runs.
ReportLab is widely used in business applications for its flexibility and ability to automate document creation processes, reducing manual effort and ensuring consistency across generated documents.
Example Code
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib import colors
from reportlab.pdfgen import canvas
def create_reportlab_pdf(filename="reportlab_example.pdf"):
--- Using pdfgen.canvas (Low-level API) ---
Initialize a canvas object
c = canvas.Canvas(filename, pagesize=letter)
Set font and draw a string directly on the canvas
c.setFont("Helvetica", 24)
c.drawString(100, 750, "ReportLab Canvas Example")
Draw a rectangle
c.setStrokeColorRGB(0.2, 0.5, 0.3) Set stroke color (R, G, B)
c.setLineWidth(2) Set line width
c.rect(100, 700, 400, 30, stroke=1, fill=0) x, y, width, height, stroke, fill
Add another string below the rectangle
c.setFont("Helvetica", 12)
c.drawString(100, 680, "This text and rectangle are drawn directly on the canvas.")
The canvas content will be saved, but for this example, we'll overwrite the file
with a Platypus document for a more comprehensive demonstration.
--- Using Platypus (High-level API) ---
Create a SimpleDocTemplate object
doc = SimpleDocTemplate(filename, pagesize=letter)
styles = getSampleStyleSheet() Get a set of standard paragraph styles
story = [] A 'story' is a list of Flowables that will be built into the document
Add a title using a paragraph style
story.append(Paragraph("ReportLab Platypus Example", styles['h1']))
story.append(Spacer(1, 0.2 - letter[1])) Add some vertical space (width, height)
Add a paragraph with longer text
paragraph_text = (
"Platypus (Page Layout and TypeSetting Utilities) is ReportLab's "
"high-level API for creating complex, flowing documents. "
"It handles page breaks, styles, and content flow automatically, "
"making it easier to build multi-page reports with structured content."
)
story.append(Paragraph(paragraph_text, styles['Normal']))
story.append(Spacer(1, 0.2 - letter[1]))
Add a table
data = [
['Header 1', 'Header 2', 'Header 3'],
['Row 1, Col 1', 'Row 1, Col 2', 'Row 1, Col 3'],
['Row 2, Col 1', 'Row 2, Col 2', 'Row 2, Col 3'],
['Row 3, Col 1', 'Row 3, Col 2', 'Row 3, Col 3']
]
table = Table(data) Create a table from the data
Apply table styles for visual formatting
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey), Header row background
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), Header row text color
('ALIGN', (0, 0), (-1, -1), 'CENTER'), Center align all cells
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), Header font
('BOTTOMPADDING', (0, 0), (-1, 0), 12), Padding for header
('BACKGROUND', (0, 1), (-1, -1), colors.beige), Data rows background
('GRID', (0, 0), (-1, -1), 1, colors.black) All borders
]))
story.append(table)
story.append(Spacer(1, 0.1 - letter[1]))
Another paragraph at the end
story.append(Paragraph("This PDF was generated using ReportLab in Python. "
"The content above the first title was drawn directly on the canvas.",
styles['Normal']))
Build the PDF document using the list of Flowables in 'story'
The canvas operations done earlier will effectively be overwritten or ignored
by SimpleDocTemplate's build method if it opens and writes to the same file.
For a combined approach, you'd typically define a 'page_template' for SimpleDocTemplate
that includes canvas operations.
doc.build(story, canvasmaker=lambda fn, s: canvas.Canvas(fn, pagesize=letter))
print(f"PDF '{filename}' created successfully using ReportLab.")
if __name__ == "__main__":
create_reportlab_pdf()








ReportLab