mcpField
R
reportlab

reportlab

github.com/ovachiever文档处理56136 次安装48 周前更新
代码仓库

关于 reportlab

这是使用 Python PDF 生成库 ReportLab 的指导技能,帮助开发者选择 Canvas 精确绘制或 Platypus 流式排版,并提供复杂文档示例。

主要功能

  1. 01Canvas 与 Platypus 指南
  2. 02格式化文本和自定义字体
  3. 03表格、图表与图像
  4. 04条形码和 QR 码
  5. 05交互式 PDF 功能

适用场景

  1. 01制作多页报告
  2. 02创建发票和证书
  3. 03设计可填写表单
  4. 04生成带条形码的标签

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ovachiever/droid-tings --skill reportlab

安装后在 Claude Code 中输入/reportlab确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
invoice_template.py
report_template.py
references/
barcodes_reference.md
canvas_api.md
charts_reference.md
pdf_features.md
platypus_guide.md
tables_reference.md
text_and_fonts.md
scripts/
quick_document.py

详细介绍

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)
性能提示
  1. 优先使用 drawImage(),而非 drawInlineImage() - 可缓存图像以供重复使用
  2. 为大型文件启用压缩: canvas.Canvas("file.pdf", pageCompression=1)
  3. 重复使用样式 - 创建一次,在整个文档中使用
  4. 对重复图形使用 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

示例工作流

创建发票
  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()

安装

uv pip install reportlab

# For image support
uv pip install pillow

# For charts
uv pip install reportlab[renderPM]

# For barcode support (included in reportlab)
# QR codes require: uv pip install qrcode

何时使用此技能

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

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

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

评论

支持 Markdown