https://docs.reportlab.com/reportlab/userguide/
依赖
- reportlab
- pyrxp https://www.reportlab.com/ftp/
- preppy https://www.reportlab.com/ftp/
安装与使用
您想要用Python快速自动生成丰富、有吸引力且完全定制的PDF文件?
在工作中,你是否遇到过这样的工作场景:
- 自动化测试设备,将测试信息自动生成测试报告。
- 从XML一步生成PDF文件
- 生成包括表格、图片和文字的报告和论文等。
- 等等。
那我们今天要学习的Python第三方库ReportLab,就是为你量身打造的,这个库可以解决你在工作中自动生成报告的问题。我曾在某个时期大量使用这个库生成PDF文件。
这个Python库的功能强大,是一个用于生成PDF和图形的开源Python库。每个月使用ReportLab生成的文档超过500万份。
本文中的开发环境是Python 3.8,ReportLab的版本号是3.5.55。文中的代码全部经过验证,你可以直接使用,如果有什么问题,可以私信我。
ReportLab功能强大,但是限于篇幅,本文仅选取最常用的功能:段落、表格和图片。本文按照如下的顺序进行展开:
- 安装
- 功能概述
- PLATYPUS
- 段落
- 表格
- 图片
1.安装
用键盘按Win+R打开运行窗口,输入cmd命令。
C:\Users\Administrator>pip install reportlab
执行结果
Collecting reportlab
Using cached reportlab-3.5.55-cp38-cp38-win_amd64.whl (2.3 MB)
Requirement already satisfied: pillow>=4.0.0 in d:\anaconda3\lib\site-packages (from reportlab) (7.2.0)
Installing collected packages: reportlab
Successfully installed reportlab-3.5.55
在命令行中输入python,进入python编译环境后,输入如下命令:
>>> import reportlab
>>>
如果没有报错,则确认安装成功。
2.概述
在开始学习ReportLab之前,需要先回答下面几个问题:
- 什么是ReportLab?
- 我为什么要使用它?
- 怎么样才能够学会使用这个库?
什么是ReportLab?
简单来说,这个一个允许您使用Python编程语言直接创建PDF格式文件的软件库,它也可以创建各种表格、数据图和位图。
众所周知,PDF是一种电子文档的全球标准,它支持高质量打印,同时又能够很好的在不同的平台之间传播。然而,除了使用Word、专业版的Adobe PDF软件生成PDF文件,直接生成PDF比较困难。
今天要介绍的ReportLab可以通过图形命令行直接生成PDF,并且不需要其他辅助,ReportLab可以极快地生成报告。
ReportLab可以使用于下面的应用场景:
- 通过网页动态生成PDF文档
- 大量的报告和数据发布
- 用XML一步生成PDF
我们在官网上看ReportLab的案例。官网地址:
https://www.reportlab.com/casestudies/www.reportlab.com/casestudies/
我们选取其中的“Seychelles Travel Guides“作为例子,点击进去后,查看效果。
这个例子的链接是:
https://www.reportlab.com/casestudies/seychelles/www.reportlab.com/casestudies/seychelles/
这个例子真的是图文并茂,该有的要素一应俱全。
ReportLab功能这么强大。为了学会这个库,我们需要具备扎实的Python编程基础,同时按照我的教程,自己动手实践。
知识是一宝库,而实践就是开启宝库大门的钥匙。 — 富勒
ReportLab中包含的知识点非常多,为了方便大家快速掌握最常见的核心知识点,方便大家快速掌握最常用的核心知识点,我提炼出了最常用的80%的功能:Platypus、段落、表格和图片。
3.PLATYPUS
Platypus是“Page Layout and Typography Using Scripts”,是使用脚本的页面布局和印刷术的缩写,这是一个高层次页面布局库,它可以让你通过编程创造复杂的文档,并且毫不费力。
Platypus设计的目的是尽可能地将高层布局设计与文档内容分离,比如,段落使用段落格式构造,页面使用页面模板,这样做是有好处的,在仅仅修改几行代码的情况下,包含数百个页面的数百个文档就能够被构造成不同的风格。
Platypus从上到下,可以被看成具备多个层次。
DocTemplates:文档最外层的容器
PageTemplates:各种页面布局的规格
Frames:包含流动的文本和图形的文档区域规范
Flowables:能够被“流入文档”的文本、图形和段落等。
我们常常用DocTemplate、PageTemplates和Flowables来构建文档。
先看一个简单的例子,来见识下ReportLab的威力。
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
# 调用模板,创建指定名称的PDF文档
doc = SimpleDocTemplate("Hello.pdf")
# 获得模板表格
styles = getSampleStyleSheet()
# 指定模板
style = styles['Normal']
# 初始化内容
story =[]
# 将段落添加到内容中
story.append(Paragraph("This is the first Document!",style))
# 将内容输出到PDF中
doc.build(story)
在这个Python文件的同目录下,生成一个文件名为”Hello.pdf“的文件,我们打开看看,执行结果如下:
4. 段落
段落是一种重要的Flowables,它可以格式化任意的文本。
段落中主要包括两种信息:文本和格式。
下面的语句可以用来创建一个段落的实例。
Paragraph(text, style)
text参数提供了段落的文本,末尾和换行处的空白都会被删除。
style参数用于设置段落的格式,这里段落的格式是指参数的集合,包括字体大小、行间距、首行缩进等参数。我们可以调用如下语句来获得默认段落格式。
from reportlab.lib.styles import ParagraphStyle
那ParagraphStyle中究竟包含哪些参数呢?
class ParagraphStyle(PropertySet):
defaults = {
'fontName':_baseFontName,
'fontSize':10,
'leading':12,
'leftIndent':0,
'rightIndent':0,
'firstLineIndent':0,
'alignment':TA_LEFT,
'spaceBefore':0,
'spaceAfter':0,
'bulletFontName':_baseFontName,
'bulletFontSize':10,
'bulletIndent':0,
#'bulletColor':black,
'textColor': black,
'backColor':None,
'wordWrap':None, #None means do nothing special
#CJK use Chinese Line breaking
#LTR RTL use left to right / right to left
#with support from pyfribi2 if available
'borderWidth': 0,
'borderPadding': 0,
'borderColor': None,
'borderRadius': None,
'allowWidows': 1,
'allowOrphans': 0,
'textTransform':None, #uppercase lowercase (captitalize not yet) or None or absent
'endDots':None, #dots on the last line of left/right justified paras
#string or object with text and optional fontName, fontSize, textColor & backColor
#dy
'splitLongWords':1, #make best efforts to split long words
'underlineWidth': _baseUnderlineWidth, #underline width
'bulletAnchor': 'start', #where the bullet is anchored ie start, middle, end or numeric
'justifyLastLine': 0, #n allow justification on the last line for more than n words 0 means don't bother
'justifyBreaks': 0, #justify lines broken with <br/>
'spaceShrinkage': _spaceShrinkage, #allow shrinkage of percentage of space to fit on line
'strikeWidth': _baseStrikeWidth, #stroke width
'underlineOffset': _baseUnderlineOffset, #fraction of fontsize to offset underlines
'underlineGap': _baseUnderlineGap, #gap for double/triple underline
'strikeOffset': _baseStrikeOffset, #fraction of fontsize to offset strikethrough
'strikeGap': _baseStrikeGap, #gap for double/triple strike
'linkUnderline': _platypus_link_underline,
#'underlineColor': None,
#'strikeColor': None,
'hyphenationLang': _hyphenationLang,
#'hyphenationMinWordLength': _hyphenationMinWordLength,
'embeddedHyphenation': _embeddedHyphenation,
'uriWasteReduce': _uriWasteReduce,
}
我们选取几个重要的参数进行说明:
- fontName:字体名称
- fontSize:字体大小
- leading:行间距
- leftIndent:左缩进
- rightIndent:右缩进
- firstLineIndent:首行缩进
- alignment:对齐方式
- spaceBefore:段前间隙
- spaceAfter:段后间隙
- bulletFontName:列表名称
- bulletFontSize:列表字体大小
- bulletIndent:列表缩进
- textColor:字体颜色
- backColor:背景色
- borderWidth:边框粗细
- borderPadding:边框间距
- borderColor:边框颜色
ParagraphStyle是段落的默认格式,也就是在调用Paragraph(text, style)语句时,如果不传入style参数,默认的段落格式。
我们还有其他方式获得ReportLab提供的段落格式。
from reportlab.lib.styles import getSampleStyleSheet
stylesheet=getSampleStyleSheet()
normalStyle = stylesheet['Normal']
这里就是获得系统提供的Normal格式,其实Normal格式与ParagraphStyle是一模一样的,除了Normal格式,还可以获得其他的格式。
- Normal
- BodyText
- Italic
- Heading1
- Title
- Heading2
- Heading3
- Heading4
- Heading5
- Heading6
- Bullet
- Definition
- Code
- UnorderedList
- OrderedList
假如想要获得Title格式,我们只需要按照如下格式调用即可
from reportlab.lib.styles import getSampleStyleSheet
stylesheet=getSampleStyleSheet()
titleStyle = stylesheet['Title']
那这些格式究竟是效果?可以用两种方法验证,一是直接使用看效果,二是查看源代码。
比如Title的源代码:
stylesheet.add(ParagraphStyle(name='Title',
parent=stylesheet['Normal'],
fontName = _baseFontNameB,
fontSize=18,
leading=22,
alignment=TA_CENTER,
spaceAfter=6),
alias='title')
可以看到,Title的效果是:字体18号;行间距22;对齐方式:居中;段落后间距:6。
5.表格
表格是Flowable的派生类,是一种简单文本表格机制。表格可以保存所有能被转换为字符串或Flowerable是所有事物。
如果我们不提供行高,它们可以根据数据自动计算出行高。
如果需要,它们可以跨页分割,你可以指定跨页分割后,需要重复的行数。
表格风格和表格数据是分离的,因此你可以声明一系列的风格,然后将它们用于一大堆报告。
表格使用如下代码进行创建:
Table(data, colWidths=None, rowHeights=None, style=None, splitByRow=1,
repeatRows=0, repeatCols=0, rowSplitRange=None, spaceBefore=None,
spaceAfter=None)
这里挑选几个关键参数进行讲解。
- data:数据参数是一系列的表格值,每个表格值能够被转换为字符串或者Flowable实例。data值的第一行是data[0],第i行j列表格值是data[i] [j]。
- colWidths:是一系列值,这些值代表每列的宽度。如果传递的是None,则对应列宽需要被自动计算。
- rowHeights:是一系列值,这些值代表每行的高度。如果传递的是None,则对应的行高需要被自动计算。
- style:表格被创建时的初始样式值。
- splitByRow:布尔值,当指定值为1时,允许跨页分割表格,当指定指为0时,不允许跨页分割表格。
- repeatRows:指定跨页分行时,需要重复的行数。
- repeatCols:暂时没用。
- spaceBefore:指定表格前的行数。
- spaceAfter:指定表格后的行数。
先来看个例子。
from reportlab.platypus import SimpleDocTemplate, Table
from reportlab.lib.styles import getSampleStyleSheet
# 调用模板,创建指定名称的PDF文档
doc = SimpleDocTemplate("Hello.pdf")
# 获得模板表格
styles = getSampleStyleSheet()
# 指定模板
style = styles['Normal']
# 初始化内容
story =[]
# 初始化表格内容
data= [['00', '01', '02', '03', '04'],
['10', '11', '12', '13', '14'],
['20', '21', '22', '23', '24'],
['30', '31', '32', '33', '34']]
# 根据内容创建表格
t = Table(data)
# 将表格添加到内容中
story.append(t)
# 将内容输出到PDF中
doc.build(story)
执行结果是:
打开“Hello.pdf”,看到是一个无边框的表格。如果我们需要指定表格的显示方式呢?细看下一节的表格格式。
表格格式
指定表格格式有两种方式,一种是在调用创建表格接口时,传入style参数,一种是在创建完表格后,调用如下接口:
Table.setStyle(tblStyle)
直接传入style参数
from reportlab.platypus import SimpleDocTemplate, Table
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("Hello.pdf")
styles = getSampleStyleSheet()
style = styles['Normal']
story =[]
data= [['00', '01', '02', '03', '04'],
['10', '11', '12', '13', '14'],
['20', '21', '22', '23', '24'],
['30', '31', '32', '33', '34']]
t=Table(data,style=[
('GRID',(0,0),(-1,-1),1,colors.grey),
('GRID',(1,1),(-2,-2),1,colors.green),
('BOX',(0,0),(1,-1),2,colors.red),
('BACKGROUND', (0, 0), (0, 1), colors.pink),
('BACKGROUND', (1, 1), (1, 2), colors.lavender),
('BACKGROUND', (2, 2), (2, 3), colors.orange),
])
story.append(t)
doc.build(story)
查看执行结果:
调用setStyle
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("Hello.pdf")
styles = getSampleStyleSheet()
style = styles['Normal']
story =[]
data= [['00', '01', '02', '03', '04'],
['10', '11', '12', '13', '14'],
['20', '21', '22', '23', '24'],
['30', '31', '32', '33', '34']]
t=Table(data)
t.setStyle(TableStyle(
[('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
('BOX', (0,0), (-1,-1), 2, colors.black),
('LINEBELOW', (0,0), (-1,0), 2, colors.yellow),
('LINEAFTER', (0,0), (0,-1), 2, colors.blue),
('ALIGN', (1,1), (-1,-1), 'RIGHT')]
))
story.append(t)
doc.build(story)
查看执行结果:
看到这里,小伙伴们可能一头雾水,这里需要补充基础知识。
表格的位置索引方式与列表的索引方式一致,即左上角第一个是data[0] [0],第二行第一个是data[1] [0],最后一行第一个位置是data[-1] [0],依次类推。
上面的例子中,列举了不少的表格格式化命令,这里将我知道的命令都列举完毕,方便大家学习掌握。
- FONTNAME:字体名称
- FONTSIZE:字体大小
- LEADING:行间距
- TEXTCOLOR:字体颜色
- ALIGNMENT:水平对齐方式(可选值:”LEFT”,”RIGHT“,”CENTER“)
- LEFTPADDING:左边填充
- RIGHTPADDING:右边填充
- BOTTOMPADDING:底部填充
- TOPPADDING:顶部填充
- BACKGROUND:背景色
- VALIGN:垂直对齐方式(可选值:”TOP”,“MIDDLE”,“BOTTOM”)
- GRID:表格颜色,被指定的行列中的所有子行和子列都被设置成相应颜色
- INNERGRID:表格颜色,仅仅修改指定的子行和子列的相应颜色(不包括边框)
- BOX:边框颜色,被指定的边框的颜色
- LINEBELOW:指定块底部的行颜色
- LINEAFTER:指定块右边的行颜色。
6.图片
图片的调用接口比较简单,在调用该接口时,支持默认的jpeg格式。接口如下:
Image(filename, width=None, height=None)
- filename:指定文件名
- width:指定图片的宽度
- height:指定图片的高度
如果宽度和高度有一个没有被指定,则参考原来的图片像素。
先举一个例子:
from reportlab.platypus import SimpleDocTemplate, Image
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("Hello.pdf")
styles = getSampleStyleSheet()
style = styles['Normal']
story =[]
t = Image("C:\\Users\\Administrator\\Desktop\\timg.jpg")
story.append(t)
doc.build(story)
打开指定的PDF文件,查看效果如下:
后记:本文介绍了ReportLab中最常用的4个功能:Platypus、段落、表格和图片。
在使用过程中,还会遇到很多问题,比如在使用中文时,需要首先注册字体等问题,需要大家自己摸索,当然也可以留言一起讨论哦。
中文问题
https://www.jianshu.com/p/41284e4e25f5
用reportlab生成pdf文件,碰到中文就会变成黑色的小方块,如下图。
解决方法
1.下载中文字体SimSun.ttf
2.把下载下来的字体放到/Library/Python/2.7/site-packages/reportlab/fonts文件夹下。(文件夹根据自己安装的reportlab的路径来)
3.注册字体并使用
from reportlab.platypus import SimpleDocTemplate, Image, Paragraph
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont('SimSun', 'SimSun.ttf')) #注册字体
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(fontName='SimSun', name='Song', leading=20, fontSize=12)) #自己增加新注册的字体
Paragraph(describe, styles['Song']), #使用新字体
还有文字换行问题,暂时用了下面的方式
Paragraph(u'<br/>%s<br/>' % describe, styles['Song'])
参考
https://zhaobugs.com/2018/07/09/%E4%BD%BF%E7%94%A8Python%E7%94%9F%E6%88%90PDF-reportlab%E7%AF%87/