用Python快速自动生成图文并茂的PDF文件

用Python快速自动生成图文并茂的PDF文件

您想要用Python快速自动生成丰富、有吸引力且完全定制的PDF文件?

在工作中,你是否遇到过这样的工作场景:

  1. 自动化测试设备,将测试信息自动生成测试报告。
  2. 从XML一步生成PDF文件
  3. 生成包括表格、图片和文字的报告和论文等。
  4. 等等。

那我们今天要学习的Python第三方库ReportLab,就是为你量身打造的,这个库可以解决你在工作中自动生成报告的问题。我曾在某个时期大量使用这个库生成PDF文件。

这个Python库的功能强大,是一个用于生成PDF和图形的开源Python库。每个月使用ReportLab生成的文档超过500万份。

本文中的开发环境是Python 3.8,ReportLab的版本号是3.5.55。文中的代码全部经过验证,你可以直接使用,如果有什么问题,可以私信我。

ReportLab功能强大,但是限于篇幅,本文仅选取最常用的功能:段落、表格和图片。本文按照如下的顺序进行展开:

  1. 安装
  2. 功能概述
  3. PLATYPUS
  4. 段落
  5. 表格
  6. 图片

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/

我们选取其中的“Seychelles Travel Guides“作为例子,点击进去后,查看效果。

这个例子的链接是:

https://link.zhihu.com/?target=https%3A//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、段落、表格和图片。

在使用过程中,还会遇到很多问题,比如在使用中文时,需要首先注册字体等问题,需要大家自己摸索,当然也可以留言一起讨论哦。

文章来源----好学青年

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇