ReportLabPDF生成库Skill reportlab

ReportLab 是一个用于 Python 的 PDF 生成库,允许用户以编程方式创建各种 PDF 文档,如发票、报告、证书、表格、图表、条形码和 QR 码。它提供 Canvas 和 Platypus 两种 API,支持精确布局和流动文档,适用于专业文档自动化。关键词:PDF 生成、Python 库、文档自动化、报告生成、条形码、QR 码、表格、图表。

后端开发 0 次安装 0 次浏览 更新于 3/16/2026

name: reportlab description: “PDF生成工具包。创建发票、报告、证书、表单、图表、表格、条形码、QR码、Canvas/Platypus API,用于专业文档自动化。”

ReportLab PDF 生成

概述

ReportLab 是一个强大的 Python 库,用于程序化生成 PDF 文档。可以创建从简单文档到包含表格、图表、图像和交互式表单的复杂报告。

两种主要方法:

  • Canvas API(低层级):基于坐标的直接绘图 - 用于精确布局
  • Platypus(高层级):带有自动分页的流动文档布局 - 用于多页文档

核心能力:

  • 带有丰富格式和自定义字体的文本
  • 具有复杂样式和单元格跨度的表格
  • 图表(条形图、折线图、饼图、面积图、散点图)
  • 条形码和 QR 码(Code128、EAN、QR 等)
  • 带透明度的图像
  • PDF 功能(链接、书签、表单、加密)

选择正确的方法

使用 Canvas API 当:

  • 创建标签、名片、证书
  • 精确定位至关重要(x、y 坐标)
  • 单页文档或简单布局
  • 绘制图形、形状和自定义设计
  • 在特定位置添加条形码或 QR 码

使用 Platypus 当:

  • 创建多页文档(报告、文章、书籍)
  • 内容应自动跨页流动
  • 需要在每页重复的页眉/页脚
  • 处理可以跨页拆分的段落
  • 构建带有目录的复杂文档

同时使用两者当:

  • 复杂报告需要流动内容和精确定位
  • 为 Platypus 文档添加页眉/页脚(使用 onPage 回调与 Canvas)
  • 在流动文档(Platypus)中嵌入自定义图形(Canvas)

快速开始示例

简单 Canvas 文档

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

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

# 绘制文本
c.setFont("Helvetica-Bold", 24)
c.drawString(inch, height - inch, "Hello ReportLab!")

# 绘制矩形
c.setFillColorRGB(0.2, 0.4, 0.8)
c.rect(inch, 5*inch, 4*inch, 2*inch, fill=1)

# 保存
c.showPage()
c.save()

简单 Platypus 文档

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

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

# 添加内容
story.append(Paragraph("文档标题", styles['Title']))
story.append(Spacer(1, 0.2*inch))
story.append(Paragraph("这是正文文本,带有 <b>粗体</b> 和 <i>斜体</i>。", styles['BodyText']))

# 构建 PDF
doc.build(story)

常见任务

创建表格

表格可与 Canvas(通过 Drawing)和 Platypus(作为 Flowables)一起使用:

from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.units import inch

# 定义数据
data = [
    ['产品', 'Q1', 'Q2', 'Q3', 'Q4'],
    ['Widget A', '100', '150', '130', '180'],
    ['Widget B', '80', '120', '110', '160'],
]

# 创建表格
table = Table(data, colWidths=[2*inch, 1*inch, 1*inch, 1*inch, 1*inch])

# 应用样式
style = TableStyle([
    # 表头行
    ('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'),

    # 数据行
    ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey]),
    ('GRID', (0, 0), (-1, -1), 1, colors.black),
])

table.setStyle(style)

# 添加到 Platypus story
story.append(table)

# 或在 Canvas 上绘制
table.wrapOn(c, width, height)
table.drawOn(c, x, y)

详细表格参考: 查看 references/tables_reference.md 了解单元格跨度、边框、对齐和高级样式。

创建图表

图表使用图形框架,可添加到 Canvas 和 Platypus:

from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.lib import colors

# 创建绘图
drawing = Drawing(400, 200)

# 创建图表
chart = VerticalBarChart()
chart.x = 50
chart.y = 50
chart.width = 300
chart.height = 125

# 设置数据
chart.data = [[100, 150, 130, 180, 140]]
chart.categoryAxis.categoryNames = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5']

# 样式
chart.bars[0].fillColor = colors.blue
chart.valueAxis.valueMin = 0
chart.valueAxis.valueMax = 200

# 添加到绘图
drawing.add(chart)

# 在 Platypus 中使用
story.append(drawing)

# 或直接渲染到 PDF
from reportlab.graphics import renderPDF
renderPDF.drawToFile(drawing, 'chart.pdf', '图表标题')

可用图表类型: 条形图(垂直/水平)、折线图、饼图、面积图、散点图 详细图表参考: 查看 references/charts_reference.md 了解所有图表类型、样式、图例和自定义。

添加条形码和 QR 码

from reportlab.graphics.barcode import code128
from reportlab.graphics.barcode.qr import QrCodeWidget
from reportlab.graphics.shapes import Drawing
from reportlab.graphics import renderPDF

# Code128 条形码(通用)
barcode = code128.Code128("ABC123456789", barHeight=0.5*inch)

# 在 Canvas 上
barcode.drawOn(c, x, y)

# QR 码
qr = QrCodeWidget("https://example.com")
qr.barWidth = 2*inch
qr.barHeight = 2*inch

# 包装在 Drawing 中以用于 Platypus
d = Drawing()
d.add(qr)
story.append(d)

支持格式: Code128、Code39、EAN-13、EAN-8、UPC-A、ISBN、QR、Data Matrix 及 20 多种更多 详细条形码参考: 查看 references/barcodes_reference.md 了解所有格式和使用示例。

处理文本和字体

from reportlab.platypus import Paragraph
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_JUSTIFY

# 创建自定义样式
custom_style = ParagraphStyle(
    'CustomStyle',
    fontSize=12,
    leading=14,           # 行间距
    alignment=TA_JUSTIFY,
    spaceAfter=10,
    textColor=colors.black,
)

# 带内联格式的段落
text = """
这个段落有 <b>粗体</b>、<i>斜体</i> 和 <u>下划线</u> 文本。
你还可以使用 <font color="blue">颜色</font> 和 <font size="14">不同大小</font>。
化学公式:H<sub>2</sub>O,爱因斯坦:E=mc<sup>2</sup>
"""

para = Paragraph(text, custom_style)
story.append(para)

使用自定义字体:

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# 注册 TrueType 字体
pdfmetrics.registerFont(TTFont('CustomFont', 'CustomFont.ttf'))

# 在 Canvas 中使用
c.setFont('CustomFont', 12)

# 在 Paragraph 样式中使用
style = ParagraphStyle('Custom', fontName='CustomFont', fontSize=12)

详细文本参考: 查看 references/text_and_fonts.md 了解段落样式、字体系列、亚洲语言、希腊字母和格式化。

添加图像

from reportlab.platypus import Image
from reportlab.lib.units import inch

# 在 Platypus 中
img = Image('photo.jpg', width=4*inch, height=3*inch)
story.append(img)

# 保持宽高比
img = Image('photo.jpg', width=4*inch, height=3*inch, kind='proportional')

# 在 Canvas 中
c.drawImage('photo.jpg', x, y, width=4*inch, height=3*inch)

# 带透明度(遮罩白色背景)
c.drawImage('logo.png', x, y, mask=[255,255,255,255,255,255])

创建表单

from reportlab.pdfgen import canvas
from reportlab.lib.colors import black, white, lightgrey

c = canvas.Canvas("form.pdf")

# 文本字段
c.acroForm.textfield(
    name="name",
    tooltip="输入您的姓名",
    x=100, y=700,
    width=200, height=20,
    borderColor=black,
    fillColor=lightgrey,
    forceBorder=True
)

# 复选框
c.acroForm.checkbox(
    name="agree",
    x=100, y=650,
    size=20,
    buttonStyle='check',
    checked=False
)

# 下拉菜单
c.acroForm.choice(
    name="country",
    x=100, y=600,
    width=150, height=20,
    options=[("美国", "US"), ("加拿大", "CA")],
    forceBorder=True
)

c.save()

详细 PDF 功能参考: 查看 references/pdf_features.md 了解表单、链接、书签、加密和元数据。

页眉和页脚

对于 Platypus 文档,使用页面回调:

from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame

def add_header_footer(canvas, doc):
    """在每个页面上调用"""
    canvas.saveState()

    # 页眉
    canvas.setFont('Helvetica', 9)
    canvas.drawString(inch, height - 0.5*inch, "文档标题")

    # 页脚
    canvas.drawRightString(width - inch, 0.5*inch, f"第 {doc.page} 页")

    canvas.restoreState()

# 设置文档
doc = 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])

# 用 story 构建
doc.build(story)

帮助脚本

此技能包括用于常见任务的帮助脚本:

快速文档生成器

使用 scripts/quick_document.py 进行快速文档创建:

from scripts.quick_document import create_simple_document, create_styled_table

# 从内容块创建简单文档
content = [
    {'type': 'heading', 'content': '引言'},
    {'type': 'paragraph', 'content': '您的文本在这里...'},
    {'type': 'bullet', 'content': '项目符号点'},
]

create_simple_document("output.pdf", "我的文档", content_blocks=content)

# 使用预设样式化表格
data = [['Header1', 'Header2'], ['Data1', 'Data2']]
table = create_styled_table(data, style_name='striped')  # 'default'、'striped'、'minimal'、'report'

模板示例

完整工作示例在 assets/

发票模板

assets/invoice_template.py - 专业发票包含:

  • 公司和客户信息
  • 带计算的项目表格
  • 税金和总计
  • 条款和备注
  • 徽标放置
from assets.invoice_template import create_invoice

create_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': '服务', 'quantity': 1, 'unit_price': 500.00},
        ...
    ],
    tax_rate=0.08,
    notes="感谢您的业务!",
)

报告模板

assets/report_template.py - 多页商业报告包含:

  • 封面页
  • 目录
  • 多个章节和子章节
  • 图表和表格
  • 页眉和页脚
from assets.report_template import create_report

report_data = {
    'title': '季度报告',
    'subtitle': '2023年第四季度',
    'author': '分析团队',
    'sections': [
        {
            'title': '执行摘要',
            'content': '报告内容...',
            'table_data': {...},
            'chart_data': {...}
        },
        ...
    ]
}

create_report("report.pdf", report_data)

参考文档

按功能组织的综合 API 参考:

  • references/canvas_api.md - 低层级 Canvas:绘图基元、坐标、变换、状态管理、图像、路径
  • references/platypus_guide.md - 高层级 Platypus:文档模板、框架、可流动元素、页面布局、目录
  • references/text_and_fonts.md - 文本格式化:段落样式、内联标记、自定义字体、亚洲语言、项目符号、序列
  • references/tables_reference.md - 表格:创建、样式、单元格跨度、边框、对齐、颜色、渐变
  • references/charts_reference.md - 图表:所有图表类型、数据处理、坐标轴、图例、颜色、渲染
  • references/barcodes_reference.md - 条形码:Code128、QR 码、EAN、UPC、邮政码及 20 多种格式
  • references/pdf_features.md - PDF 功能:链接、书签、表单、加密、元数据、页面过渡

最佳实践

坐标系(Canvas)

  • 原点 (0, 0) 是左下角(不是左上角)
  • Y 轴指向向上
  • 单位是(72 点 = 1 英寸)
  • 始终明确指定页面大小
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch

width, height = letter
margin = inch

# 页面顶部
y_top = height - margin

# 页面底部
y_bottom = margin

选择页面大小

from reportlab.lib.pagesizes import letter, A4, landscape

# 美国信纸 (8.5" x 11")
pagesize=letter

# ISO A4 (210mm x 297mm)
pagesize=A4

# 横向
pagesize=landscape(letter)

# 自定义
pagesize=(6*inch, 9*inch)

性能提示

  1. 使用 drawImage() 而非 drawInlineImage() - 缓存图像以供重用
  2. 为大文件启用压缩: canvas.Canvas("file.pdf", pageCompression=1)
  3. 重用样式 - 创建一次,在整个文档中使用
  4. 使用 Forms/XObjects 用于重复图形

常见模式

在 Canvas 上居中文本:

text = "居中文本"
text_width = c.stringWidth(text, "Helvetica", 12)
x = (width - text_width) / 2
c.drawString(x, y, text)

# 或使用内置
c.drawCentredString(width/2, y, text)

Platypus 中的分页:

from reportlab.platypus import PageBreak

story.append(PageBreak())

保持内容在一起(不拆分):

from reportlab.platypus import KeepTogether

story.append(KeepTogether([
    heading,
    paragraph1,
    paragraph2,
]))

交替行颜色:

style = TableStyle([
    ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey]),
])

故障排除

文本重叠或消失:

  • 检查 Y 坐标 - 记住原点是左下角
  • 确保文本适合页面边界
  • 验证 leading(行间距)大于 fontSize

表格不适合页面:

  • 减少列宽
  • 减小字体大小
  • 使用横向方向
  • 使用 repeatRows 启用表格拆分

条形码无法扫描:

  • 增加 barHeight(尝试至少 0.5 英寸)
  • 设置 quiet=1 用于静区
  • 测试打印质量(推荐 300+ DPI)
  • 验证条形码类型的数据格式

字体未找到:

  • 使用 pdfmetrics.registerFont() 注册 TrueType 字体
  • 完全按注册名称使用字体系列名
  • 检查字体文件路径是否正确

图像有白色背景:

  • 使用 mask 参数使白色透明
  • 提供 RGB 范围进行遮罩:mask=[255,255,255,255,255,255]
  • 或使用带 alpha 通道的 PNG

示例工作流

创建发票

  1. assets/invoice_template.py 开始发票模板
  2. 自定义公司信息、徽标路径
  3. 添加项目及其描述、数量、价格
  4. 如适用,设置税率
  5. 添加备注和付款条款
  6. 生成 PDF

创建报告

  1. assets/report_template.py 开始报告模板
  2. 定义带标题和内容的章节
  3. 使用 create_styled_table() 添加数据表格
  4. 使用图形框架添加图表
  5. 使用 doc.multiBuild(story) 构建以生成目录

创建证书

  1. 使用 Canvas API 进行精确定位
  2. 加载自定义字体以优雅排版
  3. 添加边框图形或图像背景
  4. 定位文本元素(姓名、日期、成就)
  5. 可选:添加 QR 码用于验证

创建带条形码的标签

  1. 使用 Canvas 和自定义页面大小(标签尺寸)
  2. 计算每页多个标签的网格位置
  3. 绘制标签内容(文本、图像)
  4. 在特定位置添加条形码
  5. 在标签或网格之间使用 showPage()

安装

pip install reportlab

# 用于图像支持
pip install pillow

# 用于图表
pip install reportlab[renderPM]

# 用于条形码支持(包含在 reportlab 中)
# QR 码需要:pip install qrcode

何时使用此技能

此技能应在以下情况下使用:

  • 以编程方式生成 PDF 文档
  • 创建发票、收据或账单文档
  • 构建带表格和图表的报告
  • 生成证书、徽章或凭证
  • 创建带条形码的运输标签或产品标签
  • 设计表单或可填写的 PDF
  • 制作具有一致格式的多页文档
  • 将数据转换为 PDF 格式用于存档或分发
  • 创建需要精确定位的自定义布局

此技能提供了 ReportLab 所有功能的全面指导,从简单文档到包含图表、表格和交互元素的复杂多页报告。