当前位置:网站首页>使用 ReportLab 绘制 PDF
使用 ReportLab 绘制 PDF
2022-08-03 19:46:00 【叶赫那拉 赫敏】
背景
因我们在工作中需要用到pdf文件, 而对于复杂的定制的pdf文件往往不好处理. 所以本文介绍如何使用Reportlab生成定制pdf文件。
Reportlab是Python的一个标准库, 可以根据图形命令直接创建PDF. 没有干预步骤。应用程序可以非常快速地生成PDF。
基本组件
pdfgen之canvas
pdfgen包是生成PDF文档的最低级别接口。一个pdfgen引擎本质上是一个将文档"绘制"到页面序列上的指令序列。提供绘画操作的接口对象是pdfgen canvas。canvas 也是我们在绘制PDF中最重要的组件。它将从文档页面的左下角为原点, 使用 X/Y 坐标将元素绝对放置在页面中。
模板
PageTemplate类是一个语义相当简单的容器类。每个实例都包含一个Frames的列表,并且有一些 方法应该在每个页面的开始和结束时被调用, 可以使用此参数绘制我们的页眉和页脚. 绘制复杂Pdf文件时 我们可以为每页设置单独的页面模板。
BaseDocTemplate 创建一个适合创建基本文档的文档模板。它带有相当多的内部机制,但没有默认的页面模板. 所以需要添加定制好的页面模板(PageTemplate)。
实现
from reportlab.graphics import shapes
from reportlab.graphics import widgetbase
from reportlab.graphics.charts.piecharts import Pie
from reportlab.graphics.charts.textlabels import Label
from reportlab.graphics.shapes import Drawing
from reportlab.lib import colors
from reportlab.lib.colors import HexColor
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.lib.pagesizes import A5
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import BaseDocTemplate, Paragraph, Table, Spacer, PageBreak, Image, PageTemplate, \
Frame, NextPageTemplate, FrameBreak
doc = BaseDocTemplate('test.pdf', pagesize=(A5[0], A5[1]), topMargin=15 * mm, bottomMargin=30)
pdfmetrics.registerFont(TTFont('song', r'./STSONG.TTF'))
# 因为reportlab 碰到中文字体会乱码, 所以这里向reportlab注册宋体, 以正常显示中文字体
# 单栏页面对象
frameT = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal')
# 双栏页面对象
frame1 = Frame(doc.leftMargin, doc.bottomMargin, doc.width / 2 - 6, doc.height - doc.bottomMargin, id='col1')
frame2 = Frame(doc.leftMargin + doc.width / 2 + 6, doc.bottomMargin, doc.width / 2 - 6,
doc.height - doc.bottomMargin, id='col2', showBoundary=1)
doc.addPageTemplates([PageTemplate(id='OneCol', frames=frameT, onPage=header, onPageEnd=footer),
PageTemplate(id='TwoCol', frames=[frame1, frame2], onPage=header, onPageEnd=foot2),
])
- 添加页眉页脚, 为了区分单双页面, 添加两个页脚
def footer(canvas, doc):
canvas.saveState()
page_num = canvas.getPageNumber()
content = Paragraph(f"单栏第{page_num}页", styleC)
w, h = content.wrap(doc.width, doc.bottomMargin)
content.drawOn(canvas, doc.leftMargin, h)
canvas.restoreState()
def foot2(canvas, doc):
canvas.saveState()
page_num = canvas.getPageNumber()
content = Paragraph(f"双栏第{page_num}页", styleC)
w, h = content.wrap(doc.width, doc.bottomMargin)
content.drawOn(canvas, doc.leftMargin, h)
canvas.restoreState()
def header(canvas, doc):
canvas.saveState()
header_content = Paragraph("这是页眉", styleC)
w, h = header_content.wrap(doc.width, doc.topMargin)
header_content.drawOn(canvas, doc.leftMargin, doc.height + doc.topMargin - h)
canvas.restoreState()
- 单栏页面填充文本信息, 饼图和reportlab的小组件
def draw_pie(data=[], labels=[], use_colors=[]):
pie = Pie()
pie.x = 30 # x,y饼图在框中的坐标
pie.y = 10
pie.slices.label_boxStrokeColor = colors.white # 标签边框的颜色
pie.data = data # 饼图上的数据
pie.labels = labels # 数据的标签
pie.simpleLabels = 0 # 0 标签在标注线的右侧;1 在线上边
pie.sameRadii = 1 # 0 饼图是椭圆;1 饼图是圆形
pie.slices.strokeColor = colors.red # 圆饼的边界颜色
pie.strokeWidth = 1 # 圆饼周围空白区域的宽度
pie.strokeColor = colors.white # 整体饼图边界的颜色
pie.slices.label_pointer_piePad = 5 # 圆饼和标签的距离
pie.slices.label_pointer_edgePad = 15 # 标签和外边框的距离
pie.width = 220
pie.direction = 'clockwise'
pie.pointerLabelMode = 'LeftRight'
for i, col in enumerate(use_colors):
pie.slices[i].fillColor = col
return pie
data = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
labs = ['0000000', '1111111', '2222222', '3333333', '4444444',
'5555555', '6666666', '7777777', '8888888', '9999999']
color = [HexColor("#696969"), HexColor("#A9A9A9"), HexColor("#D8BFD8"),
HexColor("#DCDCDC"), HexColor('#E6E6FA'), HexColor("#B0C4DE"),
HexColor("#778899"), HexColor('#B0C4DE'), HexColor("#6495ED"),
HexColor("#483D8B")
]
def auto_legender(chart, title='饼图'):
width = 300
height = 150
d = Drawing(width, height)
lab = Label()
lab.x = 140 # x和y是文字的位置坐标
lab.y = 130
lab.setText(title)
lab.fontName = 'song' # 增加对中文字体的支持
lab.fontSize = 10
d.add(lab)
d.add(chart)
return d
def add_face():
d = shapes.Drawing(200, 100)
f = widgetbase.Face()
f.skinColor = colors.yellow
d.add(f)
return d
Elements = []
Elements.append(Paragraph("单栏第一页 " * 5, styleN))
pie = auto_legender(draw_pie(data, labs, color))
face = add_face()
Elements.append(pie)
Elements.append(face)
- 双栏填充文本信息, 图片和表格
Elements.append(PageBreak())
Elements.append(Paragraph("这是双栏第一个区域", styleC))
Elements.append(Spacer(width=doc.width, height=30 * mm)) # 添加空行
Elements.append(Image('default.png', width=40 * mm, height=40 * mm)) # 添加图片
Elements.append(FrameBreak()) # 切换Frame
Elements.append(Paragraph("这是双栏第二个区域<br/>", styleC))
Elements.append(Spacer(width=doc.width, height=10 * mm))
# 添加一个表格
data = [
[1, 2, 3, 4, 5],
['a', 'b', 'c', 'd', 'e'],
[1, 2, 3, 4, 5],
['a', 'b', 'c', 'd', 'e'],
]
Elements.append(Table(data, style=[
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONT', (0, 0), (-1, -1), 'song'),
('GRID', (0, 0), (-1, -1), 1, colors.black),
]))
总结
Reportlab 支持高度自定义生成Pdf文档, 支持HTML, XML文本, 绘制各种图形, 自定义表格等。
边栏推荐
- Shell编程之循环语句
- 京东云发布新一代分布式数据库StarDB 5.0
- List类的超详细解析!(超2w+字)
- Reveal how the five operational management level of hundreds of millions of easily flow system
- 【leetcode】剑指 Offer II 007. 数组中和为 0 的三个数(双指针)
- 揭秘5名运维如何轻松管理数亿级流量系统
- Postgresql源码(64)查询执行——子模块Executor(2)执行前的数据结构和执行过程
- Execute the mysql script file in the docker mysql container and solve the garbled characters
- 力扣刷题之求两数之和
- relocation R_X86_64_PC32 against,/usr/bin/ld: final link failed: Bad value
猜你喜欢
随机推荐
ECCV2022 | 用于视频问题回答的视频图Transformer
CS免杀姿势
Brush the topic of mobile zero power button
Detailed steps for tensorflow-gpu2.4.1 installation and configuration
Postgresql快照优化Globalvis新体系分析(性能大幅增强)
Reveal how the five operational management level of hundreds of millions of easily flow system
力扣刷题之有效的正方形(每日一题7/29)
Power button brush the topic of merging two orderly array
NNLM、RNNLM等语言模型 实现 下一单词预测(next-word prediction)
Postgresql源码(65)新快照体系Globalvis工作原理分析
Postgresql-xl全局快照与GTM代码走读(支线)
awk语法-02-运算、数组、格式化输出
MySQL基础
pytorch框架实现老照片修复功能详细演示(GPU版)
Shell programming loop statement
tensorflow-gpu2.4.1安装配置详细步骤
Compose原理-compose中是如何实现事件分法的
The ecological environmental protection management system based on mobile GIS
Use ControlTemplate or Style from resource file in WPF .cs and find the control
【STM32】标准库-自定义BootLoader