Python学习——使用ReportLab生成带表格和图文的PDF

项目环境:

环境:Anaconda Python 3.10

编辑器:PyCharm 2021.2.3

Packages:Reportlab 3.6.2

ReportLab简介

“This is a software library that lets you directly create documents in Adobe’s Portable Document Format (PDF)using the Python programming language. It also creates charts and data graphics in various bitmap and vectorformats as well as PDF.”

ReportLab是一个可以让你使用Python语言直接生成AdobePDF文档软件库。它还可以创建图片或者PDF格式的图表或者数据图。

ReportLab对PDF的操作分为了几个层级,从上到下,依次为:

DocTemplates:文档的最外层容器;

PageTemplates:各种页面布局容器;

Frames:页面中放置文本,图像的区块;

Flowables:可排列的文本或者图像元素,包含图片、段落、表格、分隔符等等,但不包含页脚和固定位置的页面图像。

Canvas:接收所有其它层级信息并绘制文档的最底层。

用图层表示如下:

img

上述内容和本文涉及的接口都可以参考ReportLab用户指南

开发思路要点:

  1. 中文字体注册及使用
  2. 创建文档并加入标题
  3. 绘制页脚
  4. 表格绘制
  5. 饼图绘制
  6. 简单段落、图片
  7. 横向多图排布

开始正式编程,先看结果:

img
成品效果

中文字体注册及使用

首先,下载或者在C:\Windows\Fonts或其它途径找到字体文件,比如“宋体”,然后将其复制到你的Python环境中的reportlab包里的fonts目录下,比如我的是D:\ProgramData\Anaconda3\envs\py10\Lib\site-packages\reportlab\fonts:

img

然后再脚本里面写入以下内容:

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
song = "simsun"
pdfmetrics.registerFont(TTFont(song, "simsun.ttc"))

这个字体就注册好了,同理你可以注册一些其它的字体,比如这样。

msyh = "msyh"
msyhbd = "msyhbd"
song = "simsun"
pdfmetrics.registerFont(TTFont(song, "simsun.ttc"))
pdfmetrics.registerFont(TTFont(msyh, "msyh.ttc"))
pdfmetrics.registerFont(TTFont(msyhbd, "msyhbd.ttc"))

你只需要在需要使用的地方将字体设置为song就可以使用了,比如:

labelStyle = ParagraphStyle(
    name="label",
    fontName=song,
    fontSize=6,
)
canvas.setFont(song, 8)

创建文档并加入标题

首先,我们使用SimpleDocTemplate创建文档,在bulid的onFirstPage事件里,设置好字体和填充色,使用canvas.drawCentredString绘制标题。

from reportlab.lib import colors
from reportlab.lib.colors import HexColor
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import Spacer, SimpleDocTemplate

# 注册字体
msyh = "msyh"
msyhbd = "msyhbd"
song = "simsun"
pdfmetrics.registerFont(TTFont(song, "simsun.ttc"))
pdfmetrics.registerFont(TTFont(msyh, "msyh.ttc"))
pdfmetrics.registerFont(TTFont(msyhbd, "msyhbd.ttc"))

PAGE_HEIGHT = A4[1]
PAGE_WIDTH = A4[0]

def myFirstPage(c: Canvas, doc):
    c.saveState()
    # 设置填充色
    c.setFillColor(colors.orange)
    # 设置字体大小
    c.setFont(msyhbd, 30)
    # 绘制居中标题文本
    c.drawCentredString(300, PAGE_HEIGHT - 80, "新年快乐")
    c.restoreState()


def myLaterPages(c: Canvas, doc):
    c.saveState()
    c.restoreState()


# 创建文档
doc = SimpleDocTemplate("output/pdftest.pdf")
Story = [Spacer(1, 2 * inch)]
# 保存文档
doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)

运行后,就得到一个包含标题的基本文档了,如下。

img

绘制页脚

接下来绘制页脚的线条和文字,因为页脚的内容是一个在每页上固定的位置的内容,所以使用Canvas的接口来绘制。这里涉及到Canvas.line和Canvas.drawString两个方法。定义一个方法如下:

def DrawPageInfo(c: Canvas, date=datetime.date.today):
    """绘制页脚"""
    # 设置边框颜色
    c.setStrokeColor(colors.dimgrey)
    # 绘制线条
    c.line(30, PAGE_HEIGHT - 790, 570, PAGE_HEIGHT - 790)
    # 绘制页脚文字
    c.setFont(song, 8)
    c.setFillColor(colors.black)
    c.drawString(30, PAGE_HEIGHT - 810, f"生成日期:{date}")

然后再每页的事件里面调用它。如下:

def myFirstPage(c: Canvas, doc):
    c.saveState()
    # 设置填充色
    c.setFillColor(colors.orange)
    # 设置字体大小
    c.setFont(msyhbd, 30)
    # 绘制居中标题文本
    c.drawCentredString(300, PAGE_HEIGHT - 80, "新年快乐")
    # 绘制页脚
    DrawPageInfo(c)
    c.restoreState()


def myLaterPages(c: Canvas, doc):
    c.saveState()
    # 绘制页脚
    DrawPageInfo(c)
    c.restoreState()

然后运行,就可以在PDF页面的底部看到如下图像:

img
页脚

表格绘制

同样创建一个表格绘制方法,使用的是platypus中的Table类。

# 绘制用户信息表
def drawUserInfoTable(c: Canvas, x, y):
    """绘制用户信息表"""
    data = [["姓名", "龙在天涯"],
            ["出生日期", "2000-01-01"],
            ["性别", "男"],
            ["身高", 175],
            ["体重", 65],
            ["年龄", 20]]
    t = Table(data, style={
        ("FONT", (0, 0), (-1, -1), msyhbd, 8),
        ("TEXTCOLOR", (0, 0), (-1, -1), colors.black),
        ('ALIGN', (1, 0), (1, -1), 'CENTER')
    })
    t._argW[1] = 200
    t.wrapOn(c, 0, 0)
    t.drawOn(c, x, y)

然后在首页绘制页脚前调用它,就会得到如下结果。

img

绘制饼图

使用graphics.charts.piecharts中的Pie类绘制一个只有两个数据的饼图,把第二块的填充色设置为透明,然后用一个圆Circle覆盖中心的部分,**饼图Pie和圆Circle都需要用一个Drawing的对象来承载。**再在上层写上文字,就实现了这样的效果。

img

方法代码如下:

def drawScorePie(canvas: Canvas, x, y, score):
    """绘制评分饼图"""
    d = Drawing(100, 100)
    # 画大饼图
    pc = Pie()
    pc.width = 100
    pc.height = 100
    # 设置数据
    pc.data = [score, 100 - score]
    pc.slices.strokeWidth = 0.1
    # 设置颜色
    color = colors.seagreen
    if (score < 60):
        color = colors.orangered
    elif (score < 85):
        color = colors.orange
    pc.slices.strokeColor = colors.transparent
    pc.slices[0].fillColor = color
    pc.slices[1].fillColor = colors.transparent
    d.add(pc)
    # 画内圈
    circle = Circle(50, 50, 40)
    circle.fillColor = colors.white
    circle.strokeColor = colors.transparent
    d.add(circle)
    # 把饼图画到Canvas上
    d.drawOn(canvas, x, y)
    # 写字
    canvas.setFont(msyh, 30)
    canvas.setFillColor(color)
    canvas.drawCentredString(x + 50, y + 40, f"2022")

然后在绘制表格后调用,就实现了如下效果。

img

绘制饼图后

添加顺序排布的段落和图片

这里就比较简单了,只需要先设置好段落的格式ParagraphStyle。

# 设置段落格式
titleStyle = ParagraphStyle(
    name="titleStyle",
    alignment=1,
    fontName=msyhbd,
    fontSize=10,
    textColor=colors.black,
    backColor=HexColor(0xF2EEE9),
    borderPadding=(5, 5)
)

然后创建platypus中的Paragraph对象和Image对象,让后将他们一次添加到Story里面就可以了。如下:

# 绘制段落
Story.append(Paragraph("我是龙在天涯,在这里祝大家:", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
Story.append(Paragraph("新年快乐", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
Story.append(Paragraph("恭喜发财", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
Story.append(Paragraph("虎年大吉", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
# 绘制顺序排列的图像
Story.append(Image("data/img1.png", 6 * inch, 3 * inch))

我们还可以添加各种分隔符如空行符Spacer、分页符PageBreak,或者ListFlowable,ListItem等等所有继承于Flowable的元素,包括自定义的继承于Flowable的类。一个比较有用的就是可以使用Drawing去承载多种不同种类的元素,然后混排在一起,比如将图像和图像横排,图像和表格横排等等。然后将这个Drawing顺序排列到段落之中。

添加横向排列的图片

上面已经提到了一些,要将两个图像横向排列有两种比较便捷的方法:

1,用一个Drawing将两个图像Image都放在其中,然后把这个Drawing排列到段落之中。

2, 用一个没有边框的表格Table,将图像Image作为表格的一个格子,然后将表格排列到段落之中。

注意这里得Image和前面直接拿去排序的Image不同,它是graphics.shapes.Image类,它并不继承于Flowable,而可以直接排序的是继承于Flowable的platypus.Image类,两者的构造函数也不同。

这里采用前一种方法。实现方法如下:

from reportlab.graphics.shapes import Image as DrawingImage
d = Drawing()
d.add(DrawingImage(0, 0, 200, 200, "data/img2.png"))
d.add(DrawingImage(200, 0, 200, 200, "data/img3.png"))
Story.append(d)

把这部分添加到主逻辑里面,然后运行脚本,就可以得到最开始的PDF效果了。主体部分完整版如下:

# 创建文档
doc = SimpleDocTemplate("output/pdftest.pdf")
Story = [Spacer(1, 2 * inch)]
# 绘制段落
Story.append(Paragraph("我是龙在天涯,在这里祝大家:", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
Story.append(Paragraph("新年快乐", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
Story.append(Paragraph("恭喜发财", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
Story.append(Paragraph("虎年大吉", titleStyle))
Story.append(Spacer(1, 0.2 * inch))
# 绘制顺序排列的图像
Story.append(Image("data/img1.png", 6 * inch, 3 * inch))
# 绘制两个横向排布的图像
d = Drawing()
d.add(DrawingImage(0, 0, 200, 200, "data/img2.png"))
d.add(DrawingImage(200, 0, 200, 200, "data/img3.png"))
Story.append(d)
# 保存文档
doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)

工程源码:

链接:https://pan.baidu.com/s/1iblWCjVUG1MENd_uPMK5Sw

提取码:7m62

祝大家新年快乐,虎年大吉!

  • 18
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: reportlab是一个PythonPDF生成库,可以用来生成PDF文件,下面是一个简单的示例代码: ```python from reportlab.pdfgen import canvas # 创建一个PDF文档对象 pdf = canvas.Canvas("example.pdf") # 设置字体 pdf.setFont("Helvetica", 12) # 写入文本 pdf.drawString(100, 750, "Welcome to Reportlab!") # 画一个矩形 pdf.rect(50, 50, 200, 100) # 保存PDF文件 pdf.save() ``` 这个示例代码创建了一个PDF文档对象,设置了字体,写入了文本并画了一个矩形,最后保存PDF文件。 你可以根据自己的需求,修改文本内容、字体、位置、颜色等等。更多的使用方法可以查看reportlab的官方文档。 ### 回答2: Python中的reportlab库可以用于生成PDF文件。reportlab是一个强大的工具,可以帮助开发者在Python中创建和定制各种类型的PDF文档。 首先,需要安装reportlab库。可以通过使用pip命令在命令行中运行以下命令来安装reportlab: ```python pip install reportlab ``` 安装完毕后,可以在Python代码中导入reportlab库: ```python from reportlab.pdfgen import canvas ``` 接下来,可以创建一个canvas对象来构建PDF文件。Canvas是reportlab库中最基本的对象之一,它允许开发者在PDF页面上进行各种操作。通过调用canvas对象的方法,可以绘制文本、图片、图形等。 例如,以下代码演示了如何创建一个PDF文件并在其中添加一些文本: ```python from reportlab.pdfgen import canvas # 创建一个canvas对象,指定PDF文件路径和名称 pdf = canvas.Canvas("example.pdf") # 在(100, 750)位置添加一段文本 pdf.setFont('Helvetica', 12) pdf.drawString(100, 750, "Hello, World!") # 关闭canvas对象,保存PDF文件 pdf.save() ``` 运行以上代码后,将在当前目录下生成一个名为example.pdfPDF文件。在该文件中,将添加一个位置在(100, 750)的文本“Hello, World!”。 总结:使用reportlab库中的canvas对象和相应的方法,可以轻松地在Python生成并定制各种类型的PDF文件。以上是一个简单的示例,你可以根据自己的需求进一步扩展和定制PDF文档。 ### 回答3: 使用python中的第三方库ReportLab可以很方便地生成PDF文件。ReportLab是一个用于创建PDF文档的强大工具,可以在Python使用它来生成报告、统计图表、标签等。 首先,在使用ReportLab之前,需通过pip安装ReportLab库。 ``` pip install reportlab ``` 然后,我们需要创建一个画布对象来绘制我们的PDF文件。 ```python from reportlab.pdfgen import canvas # 创建一个PDF文件 pdf = canvas.Canvas("output.pdf") # 绘制文本 pdf.drawString(100, 750, "Hello World!") # 保存PDF文件 pdf.save() ``` 以上示例代码创建了一个名为output.pdfPDF文件,并在画布上绘制了一个"Hello World!"的文本。使用`drawString`方法,可以设置文本的位置和内容。在绘制完所需内容后,通过`save`方法可以保存生成PDF文件。 除了绘制文本,ReportLab还提供了许多其他功能,如绘制图像、绘制表格、设置页面布局等。可以通过查阅ReportLab的官方文档来学习更多相关的用法,进一步定制生成自己需要的PDF文件。 使用ReportLab生成PDF文件是一种简单而强大的方法,可以应用于许多场景,如生成报告、生成标签、生成图表等。无论是个人使用还是商业应用,ReportLab提供了丰富且灵活的功能来满足不同的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值