关于 reportlab
reportlab 技能为需要程序化生成 PDF 的开发者提供 ReportLab 使用指南、参考文档和脚本示例,涵盖精确绘制与自动分页文档布局。
主要功能
- 01Canvas 精确定位绘制
- 02Platypus 自动分页排版
- 03生成表格与图表
- 04添加条码和二维码
- 05制作交互式 PDF 表单
适用场景
- 01生成发票和收据
- 02制作多页业务报告
- 03创建证书与标签
- 04设计可填写 PDF 表单
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill reportlab安装后在 Claude Code 中输入/reportlab确认已加载。
附带文件SKILL.json
详细介绍
ReportLab PDF 生成
概述
ReportLab 是一个功能强大的 Python 库,可用于以编程方式生成 PDF。它可以创建从简单文档到包含表格、图表、图片和交互式表单的复杂报告。
两种主要方式:
- Canvas API(低级):通过基于坐标的定位直接绘制,适用于需要精确布局的场景
- Platypus(高级):采用流式文档布局并自动分页,适用于多页文档
核心功能:
- 支持丰富格式和自定义字体的文本
- 支持复杂样式和单元格合并的表格
- 图表(柱状图、折线图、饼图、面积图、散点图)
- 条形码和二维码(Code128、EAN、QR 等)
- 支持透明度的图片
- PDF 功能(链接、书签、表单、加密)
选择合适的方式
在以下情况下使用 Canvas API:
- 创建标签、名片、证书
- 精确定位至关重要(x、y 坐标)
- 单页文档或简单布局
- 绘制图形、形状和自定义设计
- 在特定位置添加条形码或二维码
在以下情况下使用 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
# Draw text
c.setFont("Helvetica-Bold", 24)
c.drawString(inch, height - inch, "Hello ReportLab!")
# Draw a rectangle
c.setFillColorRGB(0.2, 0.4, 0.8)
c.rect(inch, 5*inch, 4*inch, 2*inch, fill=1)
# Save
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()
# Add content
story.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 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
# Define data
data = [
['Product', 'Q1', 'Q2', 'Q3', 'Q4'],
['Widget A', '100', '150', '130', '180'],
['Widget B', '80', '120', '110', '160'],
]
# Create table
table = Table(data, colWidths=[2*inch, 1*inch, 1*inch, 1*inch, 1*inch])
# Apply styling
style = 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 story
story.append(table)
# Or draw on 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
# Create drawing
drawing = Drawing(400, 200)
# Create chart
chart = VerticalBarChart()
chart.x = 50
chart.y = 50
chart.width = 300
chart.height = 125
# Set data
chart.data = [[100, 150, 130, 180, 140]]
chart.categoryAxis.categoryNames = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5']
# Style
chart.bars[0].fillColor = colors.blue
chart.valueAxis.valueMin = 0
chart.valueAxis.valueMax = 200
# Add to drawing
drawing.add(chart)
# Use in Platypus
story.append(drawing)
# Or render directly to PDF
from reportlab.graphics import renderPDF
renderPDF.drawToFile(drawing, 'chart.pdf', 'Chart Title')
可用的图表类型: 柱状图(垂直/水平)、折线图、饼图、面积图、散点图
详细的图表参考: 有关所有图表类型、样式、图例和自定义设置,请参阅 references/charts_reference.md。
添加条形码和二维码
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 (general purpose)
barcode = code128.Code128("ABC123456789", barHeight=0.5*inch)
# On Canvas
barcode.drawOn(c, x, y)
# QR Code
qr = QrCodeWidget("https://example.com")
qr.barWidth = 2*inch
qr.barHeight = 2*inch
# Wrap in Drawing for 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
# Create custom style
custom_style = ParagraphStyle(
'CustomStyle',
fontSize=12,
leading=14, # Line spacing
alignment=TA_JUSTIFY,
spaceAfter=10,
textColor=colors.black,
)
# Paragraph with inline formatting
text = """
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)
使用自定义字体:
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# Register TrueType font
pdfmetrics.registerFont(TTFont('CustomFont', 'CustomFont.ttf'))
# Use in Canvas
c.setFont('CustomFont', 12)
# Use in Paragraph style
style = ParagraphStyle('Custom', fontName='CustomFont', fontSize=12)
详细的文本参考: 有关段落样式、字体系列、亚洲语言、希腊字母和格式设置,请参阅 references/text_and_fonts.md。
添加图片
from reportlab.platypus import Image
from reportlab.lib.units import inch
# In Platypus
img = Image('photo.jpg', width=4*inch, height=3*inch)
story.append(img)
# Maintain aspect ratio
img = Image('photo.jpg', width=4*inch, height=3*inch, kind='proportional')
# In Canvas
c.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])
创建表单
from reportlab.pdfgen import canvas
from reportlab.lib.colors import black, white, lightgrey
c = canvas.Canvas("form.pdf")
# Text field
c.acroForm.textfield(
name="name",
tooltip="Enter your name",
x=100, y=700,
width=200, height=20,
borderColor=black,
fillColor=lightgrey,
forceBorder=True
)
# Checkbox
c.acroForm.checkbox(
name="agree",
x=100, y=650,
size=20,
buttonStyle='check',
checked=False
)
# Dropdown
c.acroForm.choice(
name="country",
x=100, y=600,
width=150, height=20,
options=[("United States", "US"), ("Canada", "CA")],
forceBorder=True
)
c.save()
详细的 PDF 功能参考: 有关表单、链接、书签、加密和元数据,请参阅 references/pdf_features.md。
页眉和页脚
对于 Platypus 文档,请使用页面回调:
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame
def add_header_footer(canvas, doc):
"""Called on each page"""
canvas.saveState()
# Header
canvas.setFont('Helvetica', 9)
canvas.drawString(inch, height - 0.5*inch, "Document Title")
# Footer
canvas.drawRightString(width - inch, 0.5*inch, f"Page {doc.page}")
canvas.restoreState()
# Set up document
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])
# Build with story
doc.build(story)
辅助脚本
此技能包含用于常见任务的辅助脚本:
快速文档生成器
使用 scripts/quick_document.py 快速创建文档:
from scripts.quick_document import create_simple_document, create_styled_table
# Simple document from content blocks
content = [
{'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 presets
data = [['Header1', 'Header2'], ['Data1', 'Data2']]
table = create_styled_table(data, style_name='striped') # 'default', 'striped', 'minimal', 'report'
模板示例
assets/ 中的完整可运行示例:
发票模板
assets/invoice_template.py - 专业发票,包含:
- 公司和客户信息
- 含计算结果的明细表
- 税费和总计
- 条款和备注
- Logo 放置
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': 'Service', 'quantity': 1, 'unit_price': 500.00},
...
],
tax_rate=0.08,
notes="Thank you for your business!",
)
报告模板
assets/report_template.py - 多页业务报告,包含:
- 封面
- 目录
- 带有子章节的多个章节
- 图表和表格
- 页眉和页脚
from assets.report_template import create_report
report_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)
参考文档
按功能整理的综合 API 参考:
references/canvas_api.md- 底层 Canvas:绘图基元、坐标、变换、状态管理、图像、路径references/platypus_guide.md- 高层 Platypus:文档模板、框架、Flowable、页面布局、目录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
# Top of page
y_top = height - margin
# Bottom of page
y_bottom = margin
选择页面尺寸
from reportlab.lib.pagesizes import letter, A4, landscape
# US Letter (8.5" x 11")
pagesize=letter
# ISO A4 (210mm x 297mm)
pagesize=A4
# Landscape
pagesize=landscape(letter)
# Custom
pagesize=(6*inch, 9*inch)
性能提示
- 优先使用
drawImage(),而非drawInlineImage()- 可缓存图像以供重复使用 - 为大型文件启用压缩:
canvas.Canvas("file.pdf", pageCompression=1) - 重复使用样式 - 创建一次,在整个文档中使用
- 对重复图形使用 Forms/XObjects
常见模式
在 Canvas 上居中文本:
text = "Centered Text"
text_width = c.stringWidth(text, "Helvetica", 12)
x = (width - text_width) / 2
c.drawString(x, y, text)
# Or use built-in
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
# For image support
pip install pillow
# For charts
pip install reportlab[renderPM]
# For barcode support (included in reportlab)
# QR codes require: pip install qrcode
何时使用此技能
在以下情况下应使用此技能:
- 以编程方式生成 PDF 文档
- 创建发票、收据或账单文档
- 构建包含表格和图表的报告
- 生成证书、徽章或凭证
- 创建带有条形码的运输标签或产品标签
- 设计表单或可填写的 PDF
- 制作格式统一的多页文档
- 将数据转换为 PDF 格式,以便归档或分发
- 创建需要精确定位的自定义布局
此技能全面介绍了 ReportLab 的所有功能,从简单文档到包含图表、表格和交互元素的复杂多页报告。