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)
性能提示
- 使用
drawImage()而非drawInlineImage()- 缓存图像以供重用 - 为大文件启用压缩:
canvas.Canvas("file.pdf", pageCompression=1) - 重用样式 - 创建一次,在整个文档中使用
- 使用 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
示例工作流
创建发票
- 从
assets/invoice_template.py开始发票模板 - 自定义公司信息、徽标路径
- 添加项目及其描述、数量、价格
- 如适用,设置税率
- 添加备注和付款条款
- 生成 PDF
创建报告
- 从
assets/report_template.py开始报告模板 - 定义带标题和内容的章节
- 使用
create_styled_table()添加数据表格 - 使用图形框架添加图表
- 使用
doc.multiBuild(story)构建以生成目录
创建证书
- 使用 Canvas API 进行精确定位
- 加载自定义字体以优雅排版
- 添加边框图形或图像背景
- 定位文本元素(姓名、日期、成就)
- 可选:添加 QR 码用于验证
创建带条形码的标签
- 使用 Canvas 和自定义页面大小(标签尺寸)
- 计算每页多个标签的网格位置
- 绘制标签内容(文本、图像)
- 在特定位置添加条形码
- 在标签或网格之间使用
showPage()
安装
pip install reportlab
# 用于图像支持
pip install pillow
# 用于图表
pip install reportlab[renderPM]
# 用于条形码支持(包含在 reportlab 中)
# QR 码需要:pip install qrcode
何时使用此技能
此技能应在以下情况下使用:
- 以编程方式生成 PDF 文档
- 创建发票、收据或账单文档
- 构建带表格和图表的报告
- 生成证书、徽章或凭证
- 创建带条形码的运输标签或产品标签
- 设计表单或可填写的 PDF
- 制作具有一致格式的多页文档
- 将数据转换为 PDF 格式用于存档或分发
- 创建需要精确定位的自定义布局
此技能提供了 ReportLab 所有功能的全面指导,从简单文档到包含图表、表格和交互元素的复杂多页报告。