python生成PDF报告

前言

最近接到了一个需求-将项目下的样本信息汇总并以PDF的形式展示出来,第一次接到这种PDF的操作的功能,还是有点慌的,还好找到了reportlab这个包,可以定制化向PDF写内容!

让我们由简入深进行讲解

一、reportlab是什么?

reportlab是久经考验的,超强大的开源引擎,用于创建复杂的,数据驱动的 PDF 文档和自定义矢量图形。它是免费的,开源的,并且是用 Python 编写的。

二、canvas绘制图形文字元素

  • 页面绘制是以坐标系为基准,左下角坐标为(0, 0)

2.1 样式预览

2.2、代码

python 复制代码
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics, ttfonts
from reportlab.lib.colors import red, blue

# pagesize可以指定创建的画布尺寸
pdfObj = canvas.Canvas("test.pdf", pagesize=A4)  # 也可以自定义尺寸,如pdfObj.setPageSize((1200,800))


#################################START字符串绘制#################################
# 绘制字符串左对齐,以给定坐标为起始点
pdfObj.drawString(300, 750, "Welcome! Ladies and gentlemen 0")
# 绘制字符串居中,以给定坐标系为字符串中心
pdfObj.drawCentredString(300, 700, "Welcome! Ladies and gentlemen 1")
# 绘制字符串右对齐,以给定坐标系为字符串结束点
pdfObj.drawRightString(300, 650, "Welcome! Ladies and gentlemen 2")
# 绘制<<中文>>字母,需要注册字体并配置字号,注simsun.ttc文件的存储位置可以是绝对或相对路径
pdfmetrics.registerFont(ttfonts.TTFont("宋体", "simsun.ttc"))
# 配置字号
pdfObj.setFont("宋体", 30)
pdfObj.drawString(300, 600, "大学生开学季")
#################################END字符串绘制#################################

#################################START图片的绘制#################################
# 绘制图片
pdfObj.drawImage(r"D:\test\baidu.png", 300, 400, 190, 72)
#################################END图片的绘制#################################

#################################START图形的绘制#################################
# 绘制中横线,参数为起点,终点坐标
pdfObj.line(50, 350, 300, 350)
pdfObj.setLineWidth(1)  # 中横线厚度
# 绘制长方形
pdfObj.setFillColor(red)  # 颜色对象
pdfObj.rect(300, 300, 190, 20, stroke=0, fill=1)  # 长方形区域属性
# 附加属性
pdfObj.setFillColor(blue)  # 颜色对象
# pdfObj.setFillGray(0.75)  # 灰度配置,用的少,先关掉了
pdfObj.setFillAlpha(0.3)  # 透明度配置
pdfObj.rect(300, 650, 200, 50, stroke=0, fill=1)  # 长方形区域属性
#################################END图形的绘制#################################

#################################START继承的绘制#################################
# 将form内包含的绘制保存,以便再下一页继续应用。可用在页眉、页脚、背景色等处
pdfObj.beginForm("new")  # 创建继承体
pdfObj.line(50, 200, 300, 200)
pdfObj.setLineWidth(1)  # 中横线厚度
pdfObj.endForm()  # 结束并保存继承体

for i in range(2):
    pdfObj.doForm("new")  # 应用继承体
    pdfObj.showPage()  # 结束本页翻转下一页
#################################END继承的绘制#################################
# 保存生效
pdfObj.save()

三、页面布局platypus应用

在第一章中,所有的元素都基于坐标进行绘制,每次的排版都需要计算,应用起来有点复杂及繁琐,所以为了减少这种重复劳动,引入模板和样式platypus(Page Layout and Typography Using Scripts),它致力于把文档的样式和内容分开,段落、表格都直接套用相应的格式,页面也可以套用页面模版。
  • 明晰platypus几大层面划分,包含关系由小到大。页面元素(flowables)、页面框架(Frame)、页面模板(PageTemplate)、文档模板(DocTemplate)
  • 页面元素(flowables),如段落、表格、空白、分页符、图片等

3.1、段落Paragraph

3.1.1、样式预览

3.1.2、代码

python 复制代码
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics, ttfonts
from reportlab.platypus import Paragraph

# 文本数据
txt1 = "尊敬的家长,亲爱的同学们:"
txt2 = "在硕果累累的金秋时节,伴着纤云翩翩,伴着枫红菊香,你们怀揣着无限的憧憬,来到了xx学校。你们的到来,犹如徐徐清风,让我们的校园更为清新宜人,璀璨多姿。xx学院全体师生期盼着你们的到来,我们用比较诚挚的心意衷心的祝福你们,欢迎你们!"
txt3 = "当你跨进这所美丽的校园,你就成了我们大伙庭的一员,在这个大伙庭里,充满着真情,充满着友爱,充满着对一切美好事物的追求。在这个大伙庭里,你将在这优美的校园环境中陶冶你的情操,情发挥你的特长,丰富你的学识,攀登科学的高峰,实现你的梦想。"
txt4 = "新的.面孔、新的价值观念和标准,新的生活方式,需要你用理性的目光和胆识、用辛勤的劳动和汗水,去实现你走向人生成功与辉煌的又一起点。"
txt5 = "谢谢大家!"

# 创建样式对象
styleObj = getSampleStyleSheet()
# <<中文>>需要注册字体并配置字号,注simsun.ttc文件的存储位置可以是绝对或相对路径
pdfmetrics.registerFont(ttfonts.TTFont("宋体", "simsun.ttc"))

# 配置段落标题与正文属性,方式一
styleObj["Title"].fontName, styleObj["Title"].fontSize = "宋体", 15
styleObj["Title"].paragraphObjpaceAfter, styleObj["Normal"].paragraphObjpaceBefore = 30, 10
styleObj["Normal"].fontName, styleObj["Normal"].fontSize = "宋体", 10
styleObj["Normal"].leading = 30
styleObj["Normal"].firparagraphObjtLineIndent = 40

# # 也可以用下面的方式配置段落属性,方式二
# # 中文写入不识别,未查明怎么不生效
# from reportlab.lib.styles import ParagraphStyle
# paragraphStyle = ParagraphStyle(name="A1",fontName="宋体",fontSize=10, firstLineIndent=0)
# styleObj.add(paragraphStyle)

# 创建段落对象
paragraphObj1 = Paragraph(txt1, styleObj["Title"])
paragraphObj2 = Paragraph(txt2, styleObj["Normal"])
paragraphObj3 = Paragraph(txt3, styleObj["Normal"])
paragraphObj4 = Paragraph(txt4, styleObj["Normal"])
paragraphObj5 = Paragraph(txt5, styleObj["Normal"])

# 此处不再使用canvas创建pdf对象,改为文档模板doctemplate模块的SimpleDocTemplate类
doc = SimpleDocTemplate(r"test1.pdf", pagesize=A4)
story_text = [paragraphObj1, paragraphObj2, paragraphObj3, paragraphObj4, paragraphObj5]
doc.build(story_text)

3.2、表格Table

3.2.1、样式预览

3.2.2、代码

python 复制代码
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Table
from reportlab.lib.units import inch, cm, pica
from reportlab.platypus import TableStyle
from reportlab.lib import colors
from reportlab.pdfbase import pdfmetrics, ttfonts

pdfmetrics.registerFont(ttfonts.TTFont("宋体", "simsun.ttc"))
# table数据,二维数组
data = [
    ["姓名", "语文", "数学", "英语", "体育"],
    ["张三", 91, 97, 79, "良好"],
    ["李四", 99, 87, 73, "优秀"],
    ["王五", 86, 89, 83, "良好"],
    ["赵六", 95, 88, 86, "良好"],
    # 当需要将数据在一个单元格分两列的话,可以用下面的语法
    ["孙七", 79, 95, 98, "良"+"\n"+"好"],
]
# 配置行高(第一、第二、第三...行高)、列宽(第一、第二、第三...列宽),如有需要,也可以配置单位,如5 * [3 * cm]
col_widths, row_heights = [80, 100, 100, 100, 100], [60, 50, 50, 50, 50, 50]
# 表格行列的表达形式为,同excel,左上方第一个单元格为(0, 0), 右下角单元格为(-1, -1),围起来就是整个表格
table_style = TableStyle([
    ("FONT", (0, 0), (0, -1), "宋体", 30),  # 配置字体
    ("FONT", (0, 0), (-1, 0), "宋体", 30),
    ("FONT", (1, 1), (-1, -1), "宋体", 15),
    ("ALIGN", (0, 0), (-1, -1), "CENTER"),  # 水平居中
    ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),  #  垂直居中
    ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),  # 单元格分割线
    ("BOX", (0, 0), (-1, -1), 0.25, colors.black),  # 边框
    ("BACKGROUND", (0, 0), (-1, -1), colors.lightgrey),  # 背景色
    ("TEXTCOLOR", (0, 0), (-1, 0), colors.red),  # 区域字体颜色
    ("LINEABOVE", (0, 1), (-1, 1), 1, colors.orange),  # 横线线段
    ('LINEBEFORE', (1, 0), (1, -1), 1, colors.blue)  # 竖线线段
    # ("GRID", (0, 0), (-1, -1), 0.5, colors.black),  #
    # ("SPAN", (0, 3), (-1, 3)),  # 合并单元格
])
table = Table(data, colWidths=col_widths, rowHeights=row_heights, style=table_style)
# 编辑表格标题及样式
tabletitle = """<para alignment=center fontName="宋体" fontSize=20 spaceAfter=30>表1: 学生成绩表</para>"""
# 可以配置上下左右页边距,topMargin=1*cm,bottomMargin=1*cm,leftMargin=1*cm,rightMargin=1*cm
doc = SimpleDocTemplate(r"test2.pdf", pagesize=A4)
story_table = [Paragraph(tabletitle, getSampleStyleSheet()["Normal"]), table]
doc.build(story_table)

3.2、图表

项目没用到,搁置先不写了

3.4、空白

3.5、图片

3.6、升华Frame

四、结束!

相关推荐
Andy2 分钟前
Python基础语法4
开发语言·python
但要及时清醒7 分钟前
ArrayList和LinkedList
java·开发语言
孚亭23 分钟前
Swift添加字体到项目中
开发语言·ios·swift
hweiyu0026 分钟前
Go、DevOps运维开发实战(视频教程)
开发语言·golang·运维开发
mm-q291522272937 分钟前
Python+Requests零基础系统掌握接口自动化测试
开发语言·python
星星火柴9361 小时前
笔记 | C++面向对象高级开发
开发语言·c++·笔记·学习
码界奇点1 小时前
Rust 性能优化全流程从 flamegraph 定位瓶颈到 unsafe 与 SIMD 加速响应快
开发语言·性能优化·rust·simulated annealing
Source.Liu1 小时前
【PDF-rs】pdf子项目的lib.rs文件
pdf
电院工程师2 小时前
SIMON64/128算法Verilog流水线实现(附Python实现)
python·嵌入式硬件·算法·密码学
丛雨要玩游戏2 小时前
字符函数和字符串函数
c语言·开发语言·算法