用Python制作PDF【全】

CSDN


前言

reportlab库是一个专门使用Python来制作,修改PDF的库。我们使用这些库,可以产生与Adobe Acrobat DC相同的效果。今天的文章先介绍如何用reportlab库来新建PDF文件,在PDF文件里写上文字。

一. 下载reportlab库

打开命令提示符,输入:

pip install reportlab -i https://pypi.tuna.tsinghua.edu.cn/simple
 
 

安装完再输入pip list,看看有没有安装成功。 

二. reportlab新建一个PDF文件

1. 导入reportlab库

因为reportlab库里有许多功能,所以在这篇文章里导入一个就够了。

from reportlab.pdfgen import canvas
 
 

2. 创建PDF类

我们把类名叫做c。在canvas.Canvas里我们要加上PDF文件的名字。

c = canvas.Canvas('demo.pdf')
 
 

3. 保存

直接调用这个方法,程序结束后在程序旁边就有一个demo.pdf了。

c.save()
 
 

4. 问题解决

这时候有些人打开后会出现这样的界面

这是因为我们没有对里面进行写入操作。虽然里面什么都没有,但这样打开是会报错的。

所以,我们要在c.save()之前加上这一行代码

c.showPage()
 
 

这一个会让PDF转到下一页,同时如果前面什么也没有就只显示上一页。

&nbs完成!

三. 写上文字

1. 解释

我们在写字时会有两种方法


 
 
  1. c.drawString(x, y, content)
  2. c.drawCentredString(x, y, content)
  • x: 文字的x坐标值
  • y: 文字的y坐标值
  • content: 文字的内容

这两个方法的不同之处在于第一个是对准文字的左下角,第二个是对准文字的正中间。

2. 运用

这里注意,如果你在第一页写了东西,且不想创建新页的话就不要加c.showPage()了。


 
 
  1. from reportlab.pdfgen import canvas
  2. import webbrowser
  3. import os
  4. c = canvas.Canvas( 'demo.pdf')
  5. c.drawString( 0, 0, 'Hello, world!')
  6. c.save()
  7. webbrowser. open( 'file://' + os.path.realpath( 'demo.pdf'))

这里的最后一行是直接用程序打开这个PDF文件。

 成功!

3. 写入中文字体

如果把第5行的文字改成中文,会出现和matplotlib一样的黑色的字。

①找出一个TTF文件字体

解决这个问题,首先需要一个含有中文字体的TTF文件 。如果没有现成的可以在windows系统下

设置>>个性化>>字体管理>>打开一个有中文字体示例的文件>>在其信息里找到保存的位置

 ②导入reportlab的相关font库


 
 
  1. from reportlab.pdfbase.ttfonts import TTFont
  2. from reportlab.pdfbase.pdfmetrics import registerFont

 ③设置字体


 
 
  1. registerFont(TTFont(name, file))
  2. c.setFont(font, size)
  • name: 字体文件导入后的名字
  • file: 字体文件的路径
  • font: 在已有的字体文件里选出一个
  • size: 字体的大小

第一行是把这个字体文件导入到程序里。

第二行是设置画布(PDF的类)的字体及大小。

4. 调整字体大小

如果要调整字体的大小,可以直接使用这个方法

c.setFontSize(size)
 
 
  • size: 字体的大小

当然,这个字体是里面设置的字体。

5. 运用


 
 
  1. from reportlab.pdfgen import canvas
  2. import webbrowser
  3. import os
  4. from reportlab.pdfbase.ttfonts import TTFont
  5. from reportlab.pdfbase.pdfmetrics import registerFont
  6. c = canvas.Canvas( 'demo.pdf')
  7. registerFont(TTFont( 'fangzheng', 'fangzheng.TTF'))
  8. c.setFont( 'fangzheng', 35)
  9. c.drawString( 0, 0, '你好,世界')
  10. c.save()
  11. webbrowser. open( 'file://' + os.path.realpath( 'demo.pdf'))

成功! 

四. 画布的大小

有些读者再写字的时候会想把字写在右下角,左上角等等。但是,这下二位置的坐标是多少呢?我们要追根求源找一下。
reportlab官网里对canvas.Canvas的类__init__方法有这么一个解释

在__init__里面有一个叫pagesize的参数。而这里的默认参数是按照A4纸张的大小来确定的。所以,我肯定地告诉大家,这个画布的大小是 (595.27, 841.89)
当然,如果想要改变画布的大小,可以在c = canvas.Canvas() 里面加上pagesize的参数。注意,参数是需要元组哦。

1. 运用

这里就把字符Hello, world打印在画布的正中间。

①代码示例

from reportlab.pdfgen import canvas
import webbrowser
import os


width = 595.27  # 画布的宽
height = 841.89  # 画布的高
c = canvas.Canvas('demo.pdf')
c.drawCentredString(width/2, height/2, 'Hello, world!')


c.save()
webbrowser.open('file://'+os.path.realpath('demo.pdf'))

②运行结果

在这里插入图片描述

成功!

五. 在画布上画线

在这里reportlab给出了两个方法

第一个:line()方法

c.line(x1, y1, x2, y2)
  • x1: 线段起点的x坐标值。
  • y1: 线段起点的y坐标值。
  • x2: 线段终点的x坐标值。
  • y2: 线段终点的y坐标值。

第二个:setLineWidth()方法

c.setLineWidth(width)
  • width: 线段的宽度。
    注意!我们要先设置宽度再画线!

运用

①代码示例

from reportlab.pdfgen import canvas
import webbrowser
import os

width = 595.27  # 画布的宽
height = 841.89  # 画布的高
c = canvas.Canvas('demo.pdf')
c.setLineWidth(3)  # 加粗线段
c.line(0, height/2, width, height/2)  # 横向分割线
c.line(width/2, 0, width/2, height)  # 纵向分割线


c.save()
webbrowser.open('file://'+os.path.realpath('demo.pdf'))

②运行结果

在这里插入图片描述
成功!

六. 总结运用

这里使用经典的工作安排四象限来做示例

1. 代码示例

①task.txt:

{
    "Do": [
        "test",
        "homework"
    ],
    "Plan": [
        "read",
        "gym"
    ],
    "Delegate": [
        "movie"
    ],
    "Eliminate": [
        "game",
        "shopping"
    ]
}

②main.py:

from reportlab.pdfgen import canvas
import webbrowser
import os
import json


with open('task.txt', 'r') as f:
    task = json.load(f)
print(task)


c = canvas.Canvas("todolist.pdf")  # 生成默认大小的画布
c.setLineWidth(3)  # 加粗线段
c.line(0, 421, 595, 421)  # 横向分割线
c.line(298, 0, 298, 841)  # 纵向分割线
# 写上对应的四象限标注
c.drawCentredString(446, 841 - 30, "Do")  # 第一象限
c.drawCentredString(149, 841 - 30, "Plan")  # 第二象限
c.drawCentredString(149, 421 - 30, "Eliminate")  # 第三象限
c.drawCentredString(446, 421 - 30, "Delegate")  # 第四象限
# 自动书写内容
for i in task:
    print(i)
    if i == 'Do':
        for j in range(len(task[i])):
            c.drawCentredString(446, 841 - 30 - 40 *
                                (j + 1), task[i][j])  # 第一象限
    if i == 'Plan':
        for j in range(len(task[i])):
            c.drawCentredString(149, 841 - 30 - 40 *
                                (j + 1), task[i][j])  # 第二象限
    if i == 'Eliminate':
        for j in range(len(task[i])):
            c.drawCentredString(149, 421 - 30 - 40 *
                                (j + 1), task[i][j])  # 第三象限
    if i == 'Delegate':
        for j in range(len(task[i])):
            c.drawCentredString(446, 421 - 30 - 40 *
                                (j + 1), task[i][j])  # 第四象限
c.save()  # 保存pdf文件
webbrowser.open("file://" + os.path.realpath("todolist.pdf"))

2. 运行结果

在这里插入图片描述
成功!

七. 插入图片

插入图片再制作PDF时是非常实用的方法,应用面也非常得广。但它使用起来非常简单。

drawImage(image, x, y, width, height, mask)
  • image: 图片的位置。
  • x: 图片放置的x坐标(图片的左下角)。
  • y: 图片放置的y坐标(图片的左下角)。
  • width: 图片放置后的宽度。
  • height: 图片放置后的高度。
  • mask: 优化图片。

1.基础运用

①图片

在这里插入图片描述

②代码示例

from reportlab.pdfgen import canvas
import webbrowser
import os

c = canvas.Canvas('demo.pdf')  # 创建canvas对象
c.drawImage('reportlab.png', 0,0)  # 插入图片

c.save()
webbrowser.open('file://'+os.path.realpath('demo.pdf'))

③运行结果

在这里插入图片描述
成功!

八. 参数运用

1. 讲解

再插入时,可能会出现许多特殊的情况,这时候使用里面的参数就可以轻松解决这些问题。

在官方文档里有对缩放图片的方法:

如果没有给出宽度和高度,则以像素为单位的图像的宽度和高度以1点对1像素的比例使用。
如果给定了宽度和高度,则图像将被拉伸以填充以(x,y,x+width,y-height)为界的给定矩形。
如果提供负的宽度和/或高度,它会反转它们并相应地调整x和y。

这里的话就是这个参数width, height就是插入的长,宽的大小。但是,像素为单位的图像的宽度和高度以1点对1像素的比例像素又是什么“长度单位”?
其实,里面的点是PDF文件里的长度单位。在上一篇文章里讲过在reportlab里一张A4纸的大小是 (595.27, 841.89) ,但笔者没有讲过这里的单位。现在可以肯定地说,这里的单位是点。

2. 运用

①代码

from reportlab.pdfgen import canvas
import webbrowser
import os

width = 595.27  # 画布的宽
height = 841.89  # 画布的高
c = canvas.Canvas('demo.pdf')
c.drawImage('reportlab.png', 0, 0, 500, 500)
c.save()
webbrowser.open('file://' + os.path.realpath('demo.pdf'))

②运行结果

在这里插入图片描述

九. 问题解决

1. 问题描述

有些读者在插入一些有透明图层的图片时会遇到这种问题
在这里插入图片描述
为什么这些透明的地方会变成黑色的?不是“透明”码?

2. 问题解释

其实,reportlab官方在插入图片时是不会有透明度的,也就是原本是透明的,看不见的。而现在却能看见。但也不是全都会是透明的,得看像素点的坐标才能确定。

3. 问题解决

记得我在上面还没有讲的mask参数吗?其实只要在方法里把那参数设置为’auto’就可以了。对!就是这么简单!

4. 运用

①代码示例

from reportlab.pdfgen import canvas
import webbrowser
import os

width = 595.27  # 画布的宽
height = 841.89  # 画布的高
c = canvas.Canvas('demo.pdf')
c.drawImage('demo.png', 0, 0, mask='auto')  # 开启透明模式
c.save()
webbrowser.open('file://' + os.path.realpath('demo.pdf'))

②运行结果

在这里插入图片描述
成功!

十. 二维码的结构

我们先看一看这一个是 Hello, world! 的二维码

zzz没办法,二维码全部显示会违规只能打码显示。看一下就行了zzz

这里的三个“回”字形的方块,它们是用来告诉扫描器的大小的。有这三个,即使是倒着的,斜着的二维码,我们都可以识别出来。

十一. 生成二维码

官方在生成二维码方面有些复杂,但理解后上手也是十分简单。

1. 导入库

这里不详解了,就自己看看下文做一下阅读理解吧。

from reportlab.graphics.barcode import qr
from reportlab.graphics.shapes import Drawing
from reportlab.graphics import renderPDF

2. 生成说明解释

这里再官方文档里,生成的二维码不能像图片一样直接放在canvas里面,生成后需要先传到drawing对象上,最后再渲染在cavas画布上。
这里读者可能有些蒙,笔者在这里做一个比喻。
假如这个二维码是剁椒鱼头,你要吃肯定不会让厨师直接把鱼头扔到你手上叫你直接用手抓着吃,对吧?
在这里插入图片描述
我们按正常人的思路是先把剁椒鱼头做好,然后再放到盘子里,最后在放到桌子上。就像这样
在这里插入图片描述
在我们的代码实现里也是这样的。我们要先把二维码制作好,然后放在图片画布的盘子上。最后在放置到canvas画布上,给人们展示出来。

十二. 解释核心代码

1. 生成二维码

我们这一步骤就像在厨房里制作剁椒鱼头一样。

Qr_code = qr.QrCodeWidget(content, barWidth, barHeight, barBorder)
  • content: 二维码的内容。
  • barWidth: 二维码的宽度。
  • barHeight: 二维码的高度。
  • barBorder: 二维码外面的空白区域的宽度

2. 生成drawing图像画布

这里的图像画布和cavas画布不一样,这类似于盘子与桌子的区别。

drawing = Drawing(width,height)
  • width: 画布的宽度。
  • height: 画布的高度。

3. 把二维码放置到图像画布上

这里就类似于把盘子准备好后把剁椒鱼头放置在盘子上面。

drawing.add(node)
  • xxx.add: 让对象添加东西到上面。
  • node: 要在图片画布上添加的东西。

4.把图片画布渲染到canvas画布上

renderPDF.draw(drawing, canvas, x, y)
  • drawing: 要渲染的东西。
  • canvas: 要渲染到哪个画布上。
  • x: 渲染的x坐标。
  • y: 渲染的y坐标。

十三. 包装函数

以上的操着十分的繁琐,我们可以把它包装成一个函数来使用。

def createQrCodes(content, barWidth, barHeight, barBorer, x, y, self):
    Qr_code = qr.QrCodeWidget(content, barWidth=barWidth, barHeight=barHeight, barBorder=barBorer)
    drawing = Drawing(barWidth,barHeight)
    drawing.add(Qr_code)
    renderPDF.draw(drawing, self, x, y)

这里的参数在上面就有类似的说明,要想知道自己找。

十四. 小试牛刀——代码讲解

1. 导入相关库

其实这里只需要三个库:1. reportlab库,用来处理PDF文档的;2. Pillow库,来获取图片的大小;3. webbrowser库,用来打开PDF文档。

from reportlab.pdfgen import canvas
from PIL import Image
import webbrowser

2. 输入图片文件和PDF文件的路径

这里读者可以自己修改成自己喜欢的样式。

img_file = input('请输入要转换的图片路径:')
pdf_file = input('请输入要保存的PDF文件路径:')

3. 打开图片,并获取它的大小

这里因为后面canvas画布也要访问图片,所以在获取图片大小后就要关闭图片。

img = Image.open(img_file)
size = img.size
img.close()

4. 创建cavas对象

笔者对画布大小的修改也是讲过的。

c = canvas.Canvas(pdf_file, pagesize=img.size)

5. 把图片放置上去

这里为了万一,就把mask设置成了auto,路径就是img_file,xy坐标自然是(0, 0)。

c.drawImage(img_file, 0, 0, mask='auto')

6. 保存,并打开PDF文件

c.save()
print('转换成功!')
webbrowser.open('file://' + pdf_file)

十五. 效果及完整代码

1. 效果

在这里插入图片描述

2. 完整代码

from reportlab.pdfgen import canvas
from PIL import Image
import webbrowser

img_file = input('请输入要转换的图片路径:')
pdf_file = input('请输入要保存的PDF文件路径:')
img = Image.open(img_file)
size = img.size
img.close()
c = canvas.Canvas(pdf_file, pagesize=img.size)
c.drawImage(img_file, 0, 0, mask='auto')
c.save()
print('转换成功!')
webbrowser.open('file://' + pdf_file)

成功!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值