使用Python生成PDF-reportlab篇

最近遇到一个需求是要生成一个PDF报表,网上找了几个库,最终使用了reportlab,这篇文章主要记录使用代码。

安装

使用pip直接安装

1
pip install reportlab
使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# -*- coding: utf-8 -*-  
from reportlab.pdfgen.canvas import Canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
from reportlab.pdfbase.ttfonts import TTFont
# 这里是要导入字体文件 下方我会给出地址
pdfmetrics.registerFont(TTFont('msyh', 'msyh.ttf'))
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer,Image,Table,TableStyle
import time

def rpt():
# 生成一个存储的对象集合
story=[]
# 生成样式表
stylesheet=getSampleStyleSheet()
# 字体的样式
normalStyle = stylesheet['Normal']

curr_date = time.strftime("%Y-%m-%d", time.localtime())

#标题:段落的用法详见reportlab-userguide.pdf中chapter 6 Paragraph
rpt_title = f'<para autoLeading="off" fontSize=15 align=center><b><font face="msyh">XX项目日报{curr_date}</font></b><br/><br/><br/></para>'

# 将我们的标题文本样式追加到story
story.append(Paragraph(rpt_title,normalStyle))

text = '''<para autoLeading="off" fontSize=8><font face="msyh" >程度定义:</font><br/>
<font face="msyh" color=red>1.Blocker:指系统无法执行。</font><br/><font face="msyh" fontsize=7>例如:系统无法启动或退出等</font><br/>
<font face="msyh" color=orange>2.Critical:指系统崩溃或严重资源不足、应用模块无法启动或异常退出、无法测试、造成系统不稳定。</font><br/>
<font face="msyh" fontsize=7>例如:各类崩溃、死机、应用无法启动或退出、按键无响应、整屏花屏、死循环、数据丢失、安装错误等
</font><br/>
<font face="msyh" color=darkblue>3.Major:指影响系统功能或操作,主要功能存在严重缺陷,但不会影响到系统稳定性、性能缺陷</font><br/><font face="msyh" fontsize=7>例如:功能未做、功能实现与需求不一致、功能错误、声音问题、流程不正确、兼容性问题、查询结果不正确、性能不达标等
</font><br/>
<font face="msyh" color=royalblue>4.Minor:指界面显示类问题</font><br/>
<font face="msyh" fontsize=7>例如:界面错误、边界错误、提示信息错误、翻页错误、兼容性问题、界面样式不统一、别字、排列不整齐,字体不符规范、内容、格式、滚动条等等
</font><br/>
<font face="msyh" color=grey>5.Trivial:本状态保留暂时不用</font><br/>
</para>'''

# 生成的段落文本样式加到story
story.append(Paragraph(text,normalStyle))

text = '<para autoLeading="off" fontSize=9><br/><br/><br/><b><font face="msyh">五、BUGLIST:</font></b><br/></para>'

# 生成的段落文本样式加到story
story.append(Paragraph(text,normalStyle))

#图片,用法详见reportlab-userguide.pdf中chapter 9.3 Image
img = Image('bug_trend.png')
img.drawHeight = 20
img.drawWidth = 28`

#表格数据:用法详见reportlab-userguide.pdf中chapter 7 Table
component_data= [['模块', '', '', '',img,''],
['标记','bug-1','Major','some wrong','open','unresolved'],
['','bug-1','Major','some wrong','closed','fixed'],
]
#创建表格对象,并设定各列宽度
component_table = Table(component_data, colWidths=[20,50,50, 150, 90, 90])
#添加表格样式
component_table.setStyle(TableStyle([
('FONTNAME',(0,0),(-1,-1),'msyh'),#字体
('FONTSIZE',(0,0),(-1,-1),6),#字体大小
('SPAN',(0,0),(3,0)),#合并第一行前三列
('BACKGROUND',(0,0),(-1,0), colors.lightskyblue),#设置第一行背景颜色
('SPAN',(-1,0),(-2,0)), #合并第一行后两列
('ALIGN',(-1,0),(-2,0),'RIGHT'),#对齐
('VALIGN',(-1,0),(-2,0),'MIDDLE'), #对齐
('LINEBEFORE',(0,0),(0,-1),0.1,colors.grey),#设置表格左边线颜色为灰色,线宽为0.1
('TEXTCOLOR',(0,1),(-2,-1),colors.royalblue),#设置表格内文字颜色
('GRID',(0,0),(-1,-1),0.5,colors.red),#设置表格框线为红色,线宽为0.5
]))
story.append(component_table)

doc = SimpleDocTemplate('bug.pdf')
doc.build(story)

if __name__ == '__main__':
rpt()

关于代码的一些说明:

我个人代码暂未贴出,上面代码为参考博客代码:https://blog.csdn.net/jtscript/article/details/45217697

如果你安装好库直接运行代码是不能成功的,因为这里分中文语言包你需要下载一下,中文语言包下载地址我已经帮你找好了:https://github.com/chenqing/ng-mini/blob/master/font/msyh.ttf

下载语言包之后直接放到和代码同一目录即可。

又有小伙伴疑惑了,上面代码中的那些para,font等,具体还有那些怎么获取呢?

我们可以看下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Paragraph(Flowable):
""" Paragraph(text, style, bulletText=None, caseSensitive=1)
text a string of stuff to go into the paragraph.
style is a style definition as in reportlab.lib.styles.
bulletText is an optional bullet defintion.
caseSensitive set this to 0 if you want the markup tags and their attributes to be case-insensitive.

This class is a flowable that can format a block of text
into a paragraph with a given style.

The paragraph Text can contain XML-like markup including the tags:
<b> ... </b> - bold
<i> ... </i> - italics
<u> ... </u> - underline
<strike> ... </strike> - strike through
<super> ... </super> - superscript
<sub> ... </sub> - subscript
<font name=fontfamily/fontname color=colorname size=float>
<span name=fontfamily/fontname color=colorname backcolor=colorname size=float style=stylename>
<onDraw name=callable label="a label"/>
<index [name="callablecanvasattribute"] label="a label"/>
<link>link text</link>
attributes of links
size/fontSize=num
name/face/fontName=name
fg/textColor/color=color
backcolor/backColor/bgcolor=color
dest/destination/target/href/link=target
<a>anchor text</a>
attributes of anchors
fontSize=num
fontName=name
fg/textColor/color=color
backcolor/backColor/bgcolor=color
href=href
<a name="anchorpoint"/>
<unichar name="unicode character name"/>
<unichar value="unicode code point"/>
<img src="path" width="1in" height="1in" valign="bottom"/>
width="w%" --> fontSize*w/100 idea from Roberto Alsina
height="h%" --> linewidth*h/100 <ralsina@netmanagers.com.ar>

The whole may be surrounded by <para> </para> tags

The <b> and <i> tags will work for the built-in fonts (Helvetica
/Times / Courier). For other fonts you need to register a family
of 4 fonts using reportlab.pdfbase.pdfmetrics.registerFont; then
use the addMapping function to tell the library that these 4 fonts
form a family e.g.
from reportlab.lib.fonts import addMapping
addMapping('Vera', 0, 0, 'Vera') #normal
addMapping('Vera', 0, 1, 'Vera-Italic') #italic
addMapping('Vera', 1, 0, 'Vera-Bold') #bold
addMapping('Vera', 1, 1, 'Vera-BoldItalic') #italic and bold

It will also be able to handle any MathML specified Greek characters.
"""

从源码中我们得知Paragraph可以输入XML类的标签。重点关注下img标签哦!

还有代码中一直说的reportlab-userguide.pdf是指reportlab的指导文件,我也已经帮你找到了:

https://www.reportlab.com/docs/reportlab-userguide.pdf

我遇到的需求基本上上面的代码改造下就能完成,不过要有一个超链接功能。下面是增加超链接的一个代码:

1
2
text = "<link href='https://www.baidu.com/' color='blue'><font face="msyh" fontsize=7>百度</font></super></link>"
story.append(Paragraph(text,normalStyle))

注意:凡是用到中文的地方都要指定文字语言。

其他参考文章:

使用reportlab生成每日报表

pyhton之Reportlab模块

Python reportlab.lib.styles.getSampleStyleSheet() Examples

python读取pdf中的文本

使用 Python 处理 pdf

python中解析和生成pdf文件

知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!