python reportlab模块----操作PDF文件

reportlab模块----操作PDF文件

  • [一. 安装模块](#一. 安装模块)
  • [二. reportlab相关介绍](#二. reportlab相关介绍)
  • [三. 扩展canvas类](#三. 扩展canvas类)
  • [四. 水平写入完整代码](#四. 水平写入完整代码)
  • [五. 垂直写入完整代码](#五. 垂直写入完整代码)

一. 安装模块

shell 复制代码
pip install reportlab

二. reportlab相关介绍

python 复制代码
# 1. letter 生成A4纸张尺寸
from reportlab.lib.pagesizes import letter
print(letter)    # (612.0, 792.0)  X轴大小,Y轴大小

# 2. TTFont 设置字体
from reportlab.pdfbase import pdfmetrics        # 注册字体方法
from reportlab.pdfbase.ttfonts import TTFont	# 获取字体类
pdfmetrics.registerFont(TTFont('song', 'simsun.ttc'))

# 3. reportlab自带的颜色库
from reportlab.lib import colors

# 4. Canvas画布,相当于工作区
from reportlab.pdfgen import canvas
canvas.Canvas('新PDF文件名称.pdf', pagesize=letter)  # letter=A4纸大小

# 5. 设置字体
c = canvas.Canvas(filename, pagesize=letter)
c.setFont('song', 12)  # 参数1:已注册字体名称,参数2:字体大小

# 6. TableStyle 给表格设置样式
tab_style = TableStyle([
	('FONTNAME', (0, 0), (-1, 0), 'song-Bold', 12),		 # 表头字体
	('TOPPADDING', (0, 1), (-1, -1), 1),				 # 表头顶部填充
	('BOTTOMPADDING', (0, 0), (-1, 0), 1),				 # 表头底部填充
	('BACKGROUND', (0, 0), (-1, 0), colors.grey),        # 表头背景色
    ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),   # 表头文字颜色
    ('ALIGN', (0, 0), (-1, -1), 'CENTER'),               # 单元格文本居中
    ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),              # 单元格文本垂直居中
    ("FONT", (0, 0), (-1, -1), 'song', 8),               # 单元格字体
    ('BACKGROUND', (0, 1), (-1, -1), colors.beige),      # 行背景色
    ('BOX', (0, 0), (-1, -1), 0.5, colors.black),        # 表格边框颜色
    ('INNERGRID', (0, 0), (-1, -1), 0.5, colors.black),  # 表格单元格颜色
])
# ('FONTNAME', (0,     0),     (-1,    0),     'song-Bold', 12)
#   样式名称,   (开始列,开始行), (结束列, 结束行), 字体,         字体大小)   对应关系

# 7. Table 绘制表格
# Table(数据,style=样式,colWidths=[列宽],rowHeights=[行高])
table_data= [
	('姓名', '性别', '年龄', '民族'),
	('张三', '男', 20, '汉'),
	('李四', '男', 21, '汉'),
	('王小小', '女', 18, '汉'),
]
colWidths = [20, 15, 13, 15]
rowHeights = [29]*len(table_data)
x = 30
y = 600
table1 = Table(table_data, style=table_style, colWidths=colWidths, rowHeights=rowHeights)
table1.wrapOn(self, letter[0], letter[1]) 
table1.drawOn(self, x, y)  # 起始点(x,y)

# 8. 添加图片
filepath = 'd:\images\tttt.png'
image = ImageReader(filepath)
c.drawImage(image, x, y, width=120, height=60)  
# 起始点(x,y) width=图片宽度,height=高度
 
# 9. 添加文本
c.drawString(x, y, text) # 起始点(x,y)

# 10. 垂直写入内容的 语法糖
def translate(func):
    def wrapper(*args, **kwargs):
        ox = letter[0] / 2
        oy = letter[1] / 2
        args[0].saveState()
        args[0].translate(ox, oy)   # 将中心点设置为工作区原点
        args[0].rotate(90)			# 然后按照原点顺时针旋转90度
        func(args[0], *args[1:], **kwargs)
        args[0].restoreState()
    return wrapper

三. 扩展canvas类

python 复制代码
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.utils import ImageReader

# 水平写入扩展
class PDFCanvas(canvas.Canvas):
    FONTS_DIR = r"D:\fonts"
    font_path = os.path.join(FONTS_DIR, 'simsun.ttc')
    pdfmetrics.registerFont(TTFont('song', font_path))

    def __init__(self, filename, **kwargs):
        super().__init__(filename, **kwargs)

    def draw_image(self, filename, **kwargs):
        IMAGES_DIR = r'C:\下载图片'
        filepath = os.path.join(IMAGES_DIR, filename)
        x = kwargs.get('x', 20)                                 # x轴位置
        y = kwargs.get('y', 756)                                # y轴位置
        width = kwargs.get('width', 48)                         # 图片宽度
        height = kwargs.get('height', 18)
        image = ImageReader(filepath)
        self.drawImage(image, x, y, width=width, height=height)

    def draw_text(self, text, **kwargs):
        x = kwargs.get('x', None)
        y = kwargs.get('y', None)
        font = kwargs.get('font', 'song')
        font_size = kwargs.get('font_size', 12)
        self.setFont(font, font_size)
        text_width = self.stringWidth(text, font, font_size)
        x = x if x else (letter[0] - text_width) / 2
        self.drawString(x, y, text)

    def draw_table(self, table_data, **kwargs):
        title = kwargs.get('title', '')
        if title:
            table_data = [(title,), *table_data]
        x = kwargs.get('x', 30)  # 表格X轴位置
        y = kwargs.get('y', 650)  # 表格Y轴位置
        colWidths = kwargs.get('colWidths', 120)
        table_style = kwargs.get('table_style', tab_style)  # 表格样式
        table_h = Table(table_data, style=table_style, colWidths=colWidths, rowHeights=[29]*len(table_data))
        table_h.wrapOn(self, letter[0], letter[1])
        table_h.drawOn(self, x, y)


# 垂直写入扩展
def translate(func):
    def wrapper(*args, **kwargs):
        ox = letter[0] / 2
        oy = letter[1] / 2
        args[0].saveState()
        args[0].translate(ox, oy)   # 将中心点设置为工作区原点
        args[0].rotate(90)			# 然后按照原点顺时针旋转90度
        func(args[0], *args[1:], **kwargs)
        args[0].restoreState()
    return wrapper


class PDFCanvas(canvas.Canvas):

    font_path = os.path.join(FONTS_DIR, 'simsun.ttc')
    pdfmetrics.registerFont(TTFont('song', font_path))

    def __init__(self, filename, **kwargs):
        super().__init__(filename, **kwargs)

    @translate
    def draw_image(self, filename, **kwargs):
    	IMAGES_DIR = r'C:\下载图片'
        filepath = os.path.join(IMAGES_DIR, filename)
        x = kwargs.get('x', 20)                                 # x轴位置
        y = kwargs.get('y', 756)                                # y轴位置
        width = kwargs.get('width', 48)                         # 图片宽度
        height = kwargs.get('height', 18)                       # 图像路径
        x1 = -(letter[1] / 2 - y)
        y = letter[0] / 2 - x
        image = ImageReader(filepath)
        self.drawImage(image, x1, y, width=width, height=height)

    @translate
    def draw_text(self, text, **kwargs):
        x = kwargs.get('x', 20)
        y = kwargs.get('y', None)
        font = kwargs.get('font', 'song')
        font_size = kwargs.get('font_size', 12)
        self.setFont(font, font_size)
        text_width = self.stringWidth(text, font, font_size)
        x1 = -(letter[1] / 2 - y) if y else -int(text_width / 2)
        y = letter[0] / 2 - x
        self.drawString(x1, y, text)

    @translate
    def draw_table(self, table_data, **kwargs):
        title = kwargs.get('title', '')
        if title:
            table_data = [(title,), *table_data]
        x = kwargs.get('x', 30)  # 表格X轴位置
        y = kwargs.get('y', 650)  # 表格Y轴位置
        colWidths = kwargs.get('colWidths', 120)
        table_style = kwargs.get('table_style', tab_style)  # 表格样式
        x1 = -(letter[1] / 2 - y)
        y = letter[0] / 2 - x
        table1 = Table(table_data, style=table_style, colWidths=colWidths, rowHeights=[29]*len(table_data))
        table1.wrapOn(self, letter[0], letter[1])
        table1.drawOn(self, x1, y)

四. 水平写入完整代码

python 复制代码
import os
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.utils import ImageReader

# 水平写入内容
tab_style = TableStyle([
	('FONTNAME', (0, 0), (-1, 0), 'song-Bold', 12),		 # 表头字体
	('TOPPADDING', (0, 1), (-1, -1), 1),				 # 表头顶部填充
	('BOTTOMPADDING', (0, 0), (-1, 0), 1),				 # 表头底部填充
	('BACKGROUND', (0, 0), (-1, 0), colors.grey),        # 表头背景色
    ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),   # 表头文字颜色
    ('ALIGN', (0, 0), (-1, -1), 'CENTER'),               # 单元格文本居中
    ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),              # 单元格文本垂直居中
    ("FONT", (0, 0), (-1, -1), 'song', 8),               # 单元格字体
    ('BACKGROUND', (0, 1), (-1, -1), colors.beige),      # 行背景色
    ('BOX', (0, 0), (-1, -1), 0.5, colors.black),        # 表格边框颜色
    ('INNERGRID', (0, 0), (-1, -1), 0.5, colors.black),  # 表格单元格颜色
])

class PDFCanvas(canvas.Canvas):
    FONTS_DIR = r"D:\fonts"
    font_path = os.path.join(FONTS_DIR, 'simsun.ttc')
    pdfmetrics.registerFont(TTFont('song', font_path))

    def __init__(self, filename, **kwargs):
        super().__init__(filename, **kwargs)

    def draw_image(self, filename, **kwargs):
        IMAGES_DIR = r'C:\下载图片'
        filepath = os.path.join(IMAGES_DIR, filename)
        x = kwargs.get('x', 20)                                 # x轴位置
        y = kwargs.get('y', 756)                                # y轴位置
        width = kwargs.get('width', 48)                         # 图片宽度
        height = kwargs.get('height', 18)
        image = ImageReader(filepath)
        self.drawImage(image, x, y, width=width, height=height)

    def draw_text(self, text, **kwargs):
        x = kwargs.get('x', None)
        y = kwargs.get('y', None)
        font = kwargs.get('font', 'song')
        font_size = kwargs.get('font_size', 12)
        self.setFont(font, font_size)
        text_width = self.stringWidth(text, font, font_size)
        x = x if x else (letter[0] - text_width) / 2
        self.drawString(x, y, text)

    def draw_table(self, table_data, **kwargs):
        title = kwargs.get('title', '')
        if title:
            table_data = [(title,), *table_data]
        x = kwargs.get('x', 30)  # 表格X轴位置
        y = kwargs.get('y', 650)  # 表格Y轴位置
        colWidths = kwargs.get('colWidths', 120)
        table_style = kwargs.get('table_style', tab_style)  # 表格样式
        table_h = Table(table_data, style=table_style, colWidths=colWidths, rowHeights=[29]*len(table_data))
        table_h.wrapOn(self, letter[0], letter[1])
        table_h.drawOn(self, x, y)


if __name__ == '__main__':
    c = PDFCanvas('水平写入.pdf', pagesize=letter)
    image_name = '123.png'
    c.draw_image(image_name, x=70, y=400, width=320, height=240)
    text1 = '我现在需要回答用户关于"reportlab letter"的问题'
    c.draw_text(text1,  y=700, font_size=16)
    table1 = [
        ('姓名', '性别', '年龄', '民族'),
        ('张三', '男', 20, '汉'),
        ('李四', '男', 21, '汉'),
        ('王小小', '女', 18, '汉'),
    ]

    c.draw_table(table1, x=100, y=200, colWidths=[80, 80, 80, 80])
    c.save()

五. 垂直写入完整代码

python 复制代码
import os
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.utils import ImageReader


# 垂直写入内容
def translate(func):
    def wrapper(*args, **kwargs):
        ox = letter[0] / 2
        oy = letter[1] / 2
        args[0].saveState()
        args[0].translate(ox, oy)   # 将中心点设置为工作区原点
        args[0].rotate(90)			# 然后按照原点顺时针旋转90度
        func(args[0], *args[1:], **kwargs)
        args[0].restoreState()
    return wrapper
    
tab_style = TableStyle([
	('FONTNAME', (0, 0), (-1, 0), 'song-Bold', 12),		 # 表头字体
	('TOPPADDING', (0, 1), (-1, -1), 1),				 # 表头顶部填充
	('BOTTOMPADDING', (0, 0), (-1, 0), 1),				 # 表头底部填充
	('BACKGROUND', (0, 0), (-1, 0), colors.grey),        # 表头背景色
    ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),   # 表头文字颜色
    ('ALIGN', (0, 0), (-1, -1), 'CENTER'),               # 单元格文本居中
    ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),              # 单元格文本垂直居中
    ("FONT", (0, 0), (-1, -1), 'song', 8),               # 单元格字体
    ('BACKGROUND', (0, 1), (-1, -1), colors.beige),      # 行背景色
    ('BOX', (0, 0), (-1, -1), 0.5, colors.black),        # 表格边框颜色
    ('INNERGRID', (0, 0), (-1, -1), 0.5, colors.black),  # 表格单元格颜色
])


class PDFCanvas(canvas.Canvas):
    FONTS_DIR = r"D:\fonts"
    font_path = os.path.join(FONTS_DIR, 'simsun.ttc')
    pdfmetrics.registerFont(TTFont('song', font_path))

    def __init__(self, filename, **kwargs):
        super().__init__(filename, **kwargs)

    @translate
    def draw_image(self, filename, **kwargs):
        IMAGES_DIR = r'C:\下载图片'
        filepath = os.path.join(IMAGES_DIR, filename)
        x = kwargs.get('x', 20)                                 # x轴位置
        y = kwargs.get('y', 756)                                # y轴位置
        width = kwargs.get('width', 48)                         # 图片宽度
        height = kwargs.get('height', 18)                       # 图像路径
        x1 = -(letter[1] / 2 - y)
        y = letter[0] / 2 - x
        image = ImageReader(filepath)
        self.drawImage(image, x1, y, width=width, height=height)

    @translate
    def draw_text(self, text, **kwargs):
        x = kwargs.get('x', 20)
        y = kwargs.get('y', None)
        font = kwargs.get('font', 'song')
        font_size = kwargs.get('font_size', 12)
        self.setFont(font, font_size)
        text_width = self.stringWidth(text, font, font_size)
        x1 = -(letter[1] / 2 - y) if y else -int(text_width / 2)
        y = letter[0] / 2 - x
        self.drawString(x1, y, text)

    @translate
    def draw_table(self, table_data, **kwargs):
        title = kwargs.get('title', '')
        if title:
            table_data = [(title,), *table_data]
        x = kwargs.get('x', 30)  # 表格X轴位置
        y = kwargs.get('y', 650)  # 表格Y轴位置
        colWidths = kwargs.get('colWidths', 120)
        table_style = kwargs.get('table_style', tab_style)  # 表格样式
        x1 = -(letter[1] / 2 - y)
        y = letter[0] / 2 - x
        table1 = Table(table_data, style=table_style, colWidths=colWidths, rowHeights=[29]*len(table_data))
        table1.wrapOn(self, letter[0], letter[1])
        table1.drawOn(self, x1, y)


if __name__ == '__main__':
    c = PDFCanvas('垂直写入.pdf', pagesize=letter)
    image_name = '123.png'
    c.draw_image(image_name, x=280, y=100, width=320, height=200)
    text1 = '我现在需要回答用户关于"reportlab letter"的问题'
    c.draw_text(text1, x=50, font_size=16)
    table1 = [
        ('姓名', '性别', '年龄', '民族'),
        ('张三', '男', 20, '汉'),
        ('李四', '男', 21, '汉'),
        ('王小小', '女', 18, '汉'),
    ]

    c.draw_table(table1, x=400, y=100, colWidths=[80, 80, 80, 80])
    c.save()
相关推荐
实名上网宋凯宣7 小时前
Django
后端·python·django
如若1238 小时前
【论文复现】CoFailMed:从零复现医学图像分割的共享失败审计,含完整代码流程与科研绘图
人工智能·python
砚底藏山河10 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
视觉小萌新10 小时前
AI Class 3 · Chapter 1:变量、字符串、list/dict、if/for(python学习-小白版-有经验可跳过)
python·学习·list
薛定谔的猫-菜鸟程序员10 小时前
软件架构设计师开发资料大全(从入门到精通)
后端·python·系统架构·flask·架构设计师
Ramble_Naylor12 小时前
Rust深度解读:Send 与 Sync 的本质与线程安全边界
python·算法·rust
Allen_LVyingbo13 小时前
NVIDIA CUDA Tile 在医疗计算中的算子形式化、算法重构与内核实现
大数据·python·算法·重构·知识图谱·健康医疗·数据库架构
云和数据.ChenGuang13 小时前
Python 闭包详解:从原理到实战
linux·开发语言·人工智能·python·kubernetes
我命由我1234514 小时前
Python 实用操作 - 文件操作(打开与关闭文件、读取文件、文件写入)
java·开发语言·前端·javascript·数据库·python·java-ee
青少儿编程课堂14 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:倍增法求最近公共祖先LCA解析
c++·python·算法·bfs·信息学竞赛