reportlab

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ReportLab

ReportLab

Overview

概述

ReportLab is a powerful open-source Python library for creating PDF documents programmatically. Generate professional PDFs with precise control over layout, typography, graphics, tables, and charts. Perfect for automated report generation, invoices, certificates, and custom documents.
ReportLab是一款功能强大的开源Python库,用于以程序化方式创建PDF文档。您可以通过它生成专业的PDF文档,对布局、排版、图形、表格和图表进行精确控制。非常适合自动生成报告、发票、证书和自定义文档。

When to Use This Skill

何时使用该技能

Activate when the user:
  • Wants to generate PDF documents programmatically
  • Needs to create invoices, reports, or receipts
  • Asks to create certificates, labels, or forms
  • Mentions ReportLab explicitly
  • Wants custom PDF layouts with tables, charts, or graphics
  • Needs to automate document generation
  • Wants precise control over PDF layout and styling
当用户有以下需求时启用该技能:
  • 想要以程序化方式生成PDF文档
  • 需要创建发票、报告或收据
  • 要求创建证书、标签或表单
  • 明确提及ReportLab
  • 需要包含表格、图表或图形的自定义PDF布局
  • 需要实现文档生成自动化
  • 希望对PDF布局和样式进行精确控制

Installation

安装

Check if ReportLab is installed:
bash
python3 -c "import reportlab; print(reportlab.Version)"
If not installed:
bash
pip3 install reportlab
For additional fonts and features:
bash
pip3 install reportlab[renderPM,rlPyCairo]
检查ReportLab是否已安装:
bash
python3 -c "import reportlab; print(reportlab.Version)"
如果未安装:
bash
pip3 install reportlab
如需额外字体和功能:
bash
pip3 install reportlab[renderPM,rlPyCairo]

Two Approaches: Canvas vs Platypus

两种实现方式:Canvas vs Platypus

ReportLab provides two APIs:
Canvas API (Low-Level)
  • Direct drawing on PDF pages
  • Precise positioning with x, y coordinates
  • Like painting on a canvas
  • Best for: Simple documents, custom layouts, graphics-heavy PDFs
Platypus API (High-Level)
  • Flowable document elements
  • Automatic layout and pagination
  • Easier for complex multi-page documents
  • Best for: Reports, articles, documents with lots of text
ReportLab提供两种API:
Canvas API(底层)
  • 直接在PDF页面上绘图
  • 使用x、y坐标进行精确定位
  • 类似于在画布上绘画
  • 最适合:简单文档、自定义布局、图形密集型PDF
Platypus API(高级)
  • 支持流式文档元素
  • 自动布局和分页
  • 更易于创建复杂的多页文档
  • 最适合:报告、文章、包含大量文本的文档

Canvas API (Low-Level Drawing)

Canvas API(底层绘图)

Basic Canvas Usage

Canvas基础用法

python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch
python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch

Create PDF

Create PDF

c = canvas.Canvas("output.pdf", pagesize=letter) width, height = letter
c = canvas.Canvas("output.pdf", pagesize=letter) width, height = letter

Draw text

Draw text

c.drawString(100, height - 100, "Hello, World!")
c.drawString(100, height - 100, "Hello, World!")

Set font

Set font

c.setFont("Helvetica-Bold", 24) c.drawString(100, height - 150, "Large Bold Text")
c.setFont("Helvetica-Bold", 24) c.drawString(100, height - 150, "Large Bold Text")

Save PDF

Save PDF

c.save()
undefined
c.save()
undefined

Drawing Shapes and Lines

绘制形状和线条

python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors

c = canvas.Canvas("shapes.pdf", pagesize=letter)
width, height = letter
python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors

c = canvas.Canvas("shapes.pdf", pagesize=letter)
width, height = letter

Line

Line

c.line(50, height - 50, width - 50, height - 50)
c.line(50, height - 50, width - 50, height - 50)

Rectangle

Rectangle

c.rect(50, height - 200, 200, 100, stroke=1, fill=0)
c.rect(50, height - 200, 200, 100, stroke=1, fill=0)

Filled rectangle with color

Filled rectangle with color

c.setFillColor(colors.lightblue) c.setStrokeColor(colors.blue) c.rect(300, height - 200, 200, 100, stroke=1, fill=1)
c.setFillColor(colors.lightblue) c.setStrokeColor(colors.blue) c.rect(300, height - 200, 200, 100, stroke=1, fill=1)

Circle

Circle

c.circle(150, height - 350, 50, stroke=1, fill=0)
c.circle(150, height - 350, 50, stroke=1, fill=0)

Rounded rectangle

Rounded rectangle

c.roundRect(300, height - 400, 200, 100, 10, stroke=1, fill=0)
c.save()
undefined
c.roundRect(300, height - 400, 200, 100, 10, stroke=1, fill=0)
c.save()
undefined

Working with Text

文本处理

python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors

c = canvas.Canvas("text.pdf", pagesize=letter)
width, height = letter
python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors

c = canvas.Canvas("text.pdf", pagesize=letter)
width, height = letter

Different fonts and sizes

Different fonts and sizes

c.setFont("Helvetica", 12) c.drawString(50, height - 50, "Helvetica 12pt")
c.setFont("Helvetica-Bold", 16) c.drawString(50, height - 80, "Helvetica Bold 16pt")
c.setFont("Times-Roman", 14) c.drawString(50, height - 110, "Times Roman 14pt")
c.setFont("Helvetica", 12) c.drawString(50, height - 50, "Helvetica 12pt")
c.setFont("Helvetica-Bold", 16) c.drawString(50, height - 80, "Helvetica Bold 16pt")
c.setFont("Times-Roman", 14) c.drawString(50, height - 110, "Times Roman 14pt")

Colored text

Colored text

c.setFillColor(colors.red) c.drawString(50, height - 140, "Red text")
c.setFillColor(colors.blue) c.drawString(50, height - 170, "Blue text")
c.setFillColor(colors.red) c.drawString(50, height - 140, "Red text")
c.setFillColor(colors.blue) c.drawString(50, height - 170, "Blue text")

Text alignment

Text alignment

text = "Right-aligned text" text_width = c.stringWidth(text, "Helvetica", 12) c.setFont("Helvetica", 12) c.setFillColor(colors.black) c.drawString(width - text_width - 50, height - 200, text)
text = "Right-aligned text" text_width = c.stringWidth(text, "Helvetica", 12) c.setFont("Helvetica", 12) c.setFillColor(colors.black) c.drawString(width - text_width - 50, height - 200, text)

Multi-line text with textobject

Multi-line text with textobject

textobject = c.beginText(50, height - 250) textobject.setFont("Helvetica", 12) textobject.textLines("""This is multi-line text. Each line will be rendered separately. Great for paragraphs!""") c.drawText(textobject)
c.save()
undefined
textobject = c.beginText(50, height - 250) textobject.setFont("Helvetica", 12) textobject.textLines("""This is multi-line text. Each line will be rendered separately. Great for paragraphs!""") c.drawText(textobject)
c.save()
undefined

Adding Images

添加图片

python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch

c = canvas.Canvas("images.pdf", pagesize=letter)
width, height = letter
python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch

c = canvas.Canvas("images.pdf", pagesize=letter)
width, height = letter

Draw image

Draw image

c.drawImage("logo.png", 50, height - 200, width=2inch, height=1inch)
c.drawImage("logo.png", 50, height - 200, width=2inch, height=1inch)

Image with preserved aspect ratio

Image with preserved aspect ratio

c.drawImage("photo.jpg", 50, height - 400, width=3*inch, preserveAspectRatio=True)
c.save()
undefined
c.drawImage("photo.jpg", 50, height - 400, width=3*inch, preserveAspectRatio=True)
c.save()
undefined

Platypus API (High-Level Documents)

Platypus API(高级文档)

Basic Document Structure

基础文档结构

python
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
python
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch

Create document

Create document

doc = SimpleDocTemplate("document.pdf", pagesize=letter) story = [] # Container for flowable elements
doc = SimpleDocTemplate("document.pdf", pagesize=letter) story = [] # Container for flowable elements

Get styles

Get styles

styles = getSampleStyleSheet()
styles = getSampleStyleSheet()

Add content

Add content

story.append(Paragraph("Document Title", styles['Title'])) story.append(Spacer(1, 0.2*inch)) story.append(Paragraph("This is a paragraph of text.", styles['Normal'])) story.append(Paragraph("This is another paragraph.", styles['Normal']))
story.append(Paragraph("Document Title", styles['Title'])) story.append(Spacer(1, 0.2*inch)) story.append(Paragraph("This is a paragraph of text.", styles['Normal'])) story.append(Paragraph("This is another paragraph.", styles['Normal']))

Build PDF

Build PDF

doc.build(story)
undefined
doc.build(story)
undefined

Working with Paragraphs and Styles

段落与样式处理

python
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
from reportlab.lib.units import inch
from reportlab.lib import colors

doc = SimpleDocTemplate("styled_doc.pdf", pagesize=letter)
story = []
styles = getSampleStyleSheet()
python
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
from reportlab.lib.units import inch
from reportlab.lib import colors

doc = SimpleDocTemplate("styled_doc.pdf", pagesize=letter)
story = []
styles = getSampleStyleSheet()

Built-in styles

Built-in styles

story.append(Paragraph("Title Style", styles['Title'])) story.append(Paragraph("Heading 1", styles['Heading1'])) story.append(Paragraph("Heading 2", styles['Heading2'])) story.append(Paragraph("Normal paragraph text.", styles['Normal'])) story.append(Spacer(1, 0.2*inch))
story.append(Paragraph("Title Style", styles['Title'])) story.append(Paragraph("Heading 1", styles['Heading1'])) story.append(Paragraph("Heading 2", styles['Heading2'])) story.append(Paragraph("Normal paragraph text.", styles['Normal'])) story.append(Spacer(1, 0.2*inch))

Custom style

Custom style

custom_style = ParagraphStyle( 'CustomStyle', parent=styles['Normal'], fontSize=14, textColor=colors.blue, alignment=TA_CENTER, spaceAfter=10, ) story.append(Paragraph("Centered blue text", custom_style))
custom_style = ParagraphStyle( 'CustomStyle', parent=styles['Normal'], fontSize=14, textColor=colors.blue, alignment=TA_CENTER, spaceAfter=10, ) story.append(Paragraph("Centered blue text", custom_style))

Justified paragraph

Justified paragraph

justified_style = ParagraphStyle( 'Justified', parent=styles['Normal'], alignment=TA_JUSTIFY, ) long_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " * 10 story.append(Paragraph(long_text, justified_style))
doc.build(story)
undefined
justified_style = ParagraphStyle( 'Justified', parent=styles['Normal'], alignment=TA_JUSTIFY, ) long_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " * 10 story.append(Paragraph(long_text, justified_style))
doc.build(story)
undefined

Creating Tables

创建表格

python
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet

doc = SimpleDocTemplate("table.pdf", pagesize=letter)
story = []
styles = getSampleStyleSheet()

story.append(Paragraph("Sales Report", styles['Title']))
python
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet

doc = SimpleDocTemplate("table.pdf", pagesize=letter)
story = []
styles = getSampleStyleSheet()

story.append(Paragraph("Sales Report", styles['Title']))

Table data

Table data

data = [ ['Product', 'Q1', 'Q2', 'Q3', 'Q4'], ['Widget A', '$1,000', '$1,200', '$1,100', '$1,300'], ['Widget B', '$800', '$900', '$950', '$1,000'], ['Widget C', '$1,500', '$1,600', '$1,700', '$1,800'], ['Total', '$3,300', '$3,700', '$3,750', '$4,100'], ]
data = [ ['Product', 'Q1', 'Q2', 'Q3', 'Q4'], ['Widget A', '$1,000', '$1,200', '$1,100', '$1,300'], ['Widget B', '$800', '$900', '$950', '$1,000'], ['Widget C', '$1,500', '$1,600', '$1,700', '$1,800'], ['Total', '$3,300', '$3,700', '$3,750', '$4,100'], ]

Create table

Create table

table = Table(data)
table = Table(data)

Style table

Style table

table.setStyle(TableStyle([ # Header row ('BACKGROUND', (0, 0), (-1, 0), colors.grey), ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), ('ALIGN', (0, 0), (-1, 0), '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, -2), colors.beige),
('ALIGN', (1, 1), (-1, -1), 'RIGHT'),
('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
('FONTSIZE', (0, 1), (-1, -1), 10),
('GRID', (0, 0), (-1, -1), 1, colors.black),

# Total row
('BACKGROUND', (0, -1), (-1, -1), colors.lightgrey),
('FONTNAME', (0, -1), (-1, -1), 'Helvetica-Bold'),
]))
story.append(table) doc.build(story)
undefined
table.setStyle(TableStyle([ # Header row ('BACKGROUND', (0, 0), (-1, 0), colors.grey), ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), ('ALIGN', (0, 0), (-1, 0), '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, -2), colors.beige),
('ALIGN', (1, 1), (-1, -1), 'RIGHT'),
('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
('FONTSIZE', (0, 1), (-1, -1), 10),
('GRID', (0, 0), (-1, -1), 1, colors.black),

# Total row
('BACKGROUND', (0, -1), (-1, -1), colors.lightgrey),
('FONTNAME', (0, -1), (-1, -1), 'Helvetica-Bold'),
]))
story.append(table) doc.build(story)
undefined

Adding Charts

添加图表

python
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.lib import colors

doc = SimpleDocTemplate("charts.pdf", pagesize=letter)
story = []
styles = getSampleStyleSheet()

story.append(Paragraph("Sales Charts", styles['Title']))
python
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.lib import colors

doc = SimpleDocTemplate("charts.pdf", pagesize=letter)
story = []
styles = getSampleStyleSheet()

story.append(Paragraph("Sales Charts", styles['Title']))

Bar chart

Bar chart

drawing = Drawing(400, 200) bar_chart = VerticalBarChart() bar_chart.x = 50 bar_chart.y = 50 bar_chart.height = 125 bar_chart.width = 300 bar_chart.data = [[100, 150, 200, 175, 225]] bar_chart.categoryAxis.categoryNames = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5'] bar_chart.bars[0].fillColor = colors.blue drawing.add(bar_chart) story.append(drawing)
drawing = Drawing(400, 200) bar_chart = VerticalBarChart() bar_chart.x = 50 bar_chart.y = 50 bar_chart.height = 125 bar_chart.width = 300 bar_chart.data = [[100, 150, 200, 175, 225]] bar_chart.categoryAxis.categoryNames = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5'] bar_chart.bars[0].fillColor = colors.blue drawing.add(bar_chart) story.append(drawing)

Pie chart

Pie chart

drawing2 = Drawing(400, 200) pie = Pie() pie.x = 150 pie.y = 50 pie.width = 100 pie.height = 100 pie.data = [30, 25, 20, 15, 10] pie.labels = ['Product A', 'Product B', 'Product C', 'Product D', 'Other'] pie.slices.strokeWidth = 0.5 drawing2.add(pie) story.append(drawing2)
doc.build(story)
undefined
drawing2 = Drawing(400, 200) pie = Pie() pie.x = 150 pie.y = 50 pie.width = 100 pie.height = 100 pie.data = [30, 25, 20, 15, 10] pie.labels = ['Product A', 'Product B', 'Product C', 'Product D', 'Other'] pie.slices.strokeWidth = 0.5 drawing2.add(pie) story.append(drawing2)
doc.build(story)
undefined

Common Patterns

常见模式

See references/patterns.md for common patterns and uses.
如需常见模式和用法,请查看references/patterns.md。

Best Practices

最佳实践

  1. Choose the right API - Use Canvas for simple layouts, Platypus for complex documents
  2. Use constants for measurements - Use
    inch
    ,
    cm
    from
    reportlab.lib.units
  3. Define styles once - Create custom styles and reuse them
  4. Test page sizes - Verify output on different page sizes (letter, A4, etc.)
  5. Handle images carefully - Check image paths exist before adding to PDF
  6. Use tables for layouts - Tables are great for structured layouts
  7. Cache fonts - Register custom fonts once at module level
  1. 选择合适的API - 简单布局使用Canvas,复杂文档使用Platypus
  2. 使用常量进行测量 - 使用
    reportlab.lib.units
    中的
    inch
    cm
    等单位
  3. 一次性定义样式 - 创建自定义样式并重复使用
  4. 测试页面尺寸 - 在不同页面尺寸(如letter、A4等)上验证输出效果
  5. 谨慎处理图片 - 添加到PDF前检查图片路径是否存在
  6. 使用表格进行布局 - 表格非常适合结构化布局
  7. 缓存字体 - 在模块级别注册自定义字体一次即可

Common Issues

常见问题

Issue: Text going off page

问题:文本超出页面

Calculate available space before drawing:
python
from reportlab.lib.pagesizes import letter

width, height = letter
margin = 50  # pixels
usable_width = width - 2 * margin
usable_height = height - 2 * margin
绘制前计算可用空间:
python
from reportlab.lib.pagesizes import letter

width, height = letter
margin = 50  # pixels
usable_width = width - 2 * margin
usable_height = height - 2 * margin

Issue: Images not found

问题:图片未找到

Use absolute paths or verify file existence:
python
import os

image_path = "logo.png"
if os.path.exists(image_path):
    c.drawImage(image_path, x, y, width=w, height=h)
使用绝对路径或验证文件是否存在:
python
import os

image_path = "logo.png"
if os.path.exists(image_path):
    c.drawImage(image_path, x, y, width=w, height=h)

Issue: Unicode characters not displaying

问题:Unicode字符无法显示

Register and use TrueType fonts:
python
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

pdfmetrics.registerFont(TTFont('Arial', 'Arial.ttf'))
c.setFont('Arial', 12)
注册并使用TrueType字体:
python
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

pdfmetrics.registerFont(TTFont('Arial', 'Arial.ttf'))
c.setFont('Arial', 12)

Resources

资源