使用Python和ReportLab生成PDF报告的基础类
- 代码介绍
- 项目目录
- 项目环境
- 完整代码
- 运行效果
代码介绍
这个Python代码使用 ReportLab 和 PyPDF4 库来生成 PDF 文件。代码创建一个 PDFGenerator 类,用于添加文本、图片和表格到 PDF 文件中。
初始化 PDFGenerator 对象时,它会注册“STXINGKA”字体,并创建一个新的 PDF writer 对象、内存中的 PDF 文件对象和画布对象以在 PDF 上绘制。然后,它初始化当前坐标(x,y),以便添加文本、图片和表格时知道要将它们放在哪里。
方法_add_text用于添加文本到 PDF 文件中。它将文本分割成行并逐行添加。如果文本的高度超过页面的高度,则它会在新页面上开始一个新的文本块。
方法_add_image用于将图像添加到 PDF 文件中。如果图像的高度超过页面的高度,则它会在新页面上开始一个新的图像块。
方法_add_table用于将表格添加到 PDF 文件中。它需要一个包含表格数据的列表和可选的列宽列表和行高。如果未提供列宽,则列将具有相等的宽度。它计算表格的总宽度和高度,并在 PDF 中绘制一个带边框的矩形。然后,它绘制表格中的单元格并更新当前坐标。
方法save_pdf用于将 PDF 文件保存到磁盘上。它将画布保存到 PDF 文件并使用 PyPDF4 的 PdfFileReader 类从输出文件中读取 PDF。然后,它将报告页面添加到 PDF writer 对象中,并将更新后的 PDF 保存到文件中。
在主函数中,它创建一个 PDFGenerator 对象,然后添加文本、图片和表格。最后,它保存文件。
项目目录
注:STXINGKA.TTF:字体文件是在系统的字体目录复制的,可自行更改为其他字体,使用字体的前提是你的电脑安装了该字体。
项目环境
# 这是我自己使用的环境
Python 3.10
PyPDF4==1.27.0
reportlab==3.6.12
完整代码
from io import BytesIO
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from PyPDF4 import PdfFileWriter, PdfFileReader
class PDFGenerator:
def __init__(self):
# 注册宋体字体
pdfmetrics.registerFont(TTFont('STXINGKA', 'STXINGKA.TTF'))
pdfmetrics.registerFontFamily('STXINGKA', normal='song', italic=None, boldItalic=None)
# 创建一个新的PDF writer对象
self.pdf_writer = PdfFileWriter()
# 创建一个新的内存中的PDF文件对象
self.pdf_output = BytesIO()
# 创建一个新的画布对象以在PDF上绘制
self.pdf_canvas = canvas.Canvas(self.pdf_output, pagesize=A4)
# 初始化当前坐标
self.x = 50
self.y = 750
def _add_text(self, text):
# 设置字体为宋体
self.pdf_canvas.setFont("STXINGKA", 14)
# 计算文本高度并检查是否适合页面
text_width = self.pdf_canvas.stringWidth(text)
text_height = 14
if self.y - text_height < 50:
self.pdf_canvas.showPage()
self.y = 750
# 将文本添加到页面并更新当前坐标
self.pdf_canvas.drawString(self.x, self.y, text)
self.y -= text_height
def add_text(self, text):
# 将文本分割成行并逐行添加
for line in text.split('\n'):
self._add_text(line)
def _add_image(self, image_path):
# 检查图片是否适合页面
img_width, img_height = 400, 300
if self.y - img_height < 50:
self.pdf_canvas.showPage()
self.y = 750
# 在页面上绘制图片并更新当前坐标
self.pdf_canvas.drawImage(image_path, self.x, self.y - img_height, width=img_width, height=img_height)
self.y -= img_height
def add_image(self, image_path):
self._add_image(image_path)
def save_pdf(self, filename):
# 将画布保存到PDF文件
self.pdf_canvas.save()
# 从输出文件中读取PDF
pdf_reader = PdfFileReader(self.pdf_output)
# 将报告页面添加到PDF writer对象中
for page in pdf_reader.pages:
self.pdf_writer.addPage(page)
# 将更新后的PDF保存到文件中
with open(filename, "wb") as output_file:
self.pdf_writer.write(output_file)
def add_table(self, data, col_widths=None, row_height=20):
"""
添加一个表格到PDF文件中。
:param data: 一个列表的列表,其中每个列表表示表格中的一行数据。
:param col_widths: 表格的列宽列表。如果未提供,则列将具有相等的宽度。
:param row_height: 表格中每行的高度。
"""
# 如果未提供列宽,则将其设置为相等的宽度
if not col_widths:
num_cols = max(len(row) for row in data)
col_widths = [A4[0] / num_cols] * num_cols
# 计算表格总宽度
table_width = sum(col_widths)
# 根据表格的行数计算表格的高度
table_height = len(data) * row_height
# 计算表格开始绘制的 x 和 y 坐标
x_start = (A4[0] - table_width) / 2
y_start = self.y - table_height
# 绘制表格边框
self.pdf_canvas.rect(x_start, y_start, table_width, table_height)
# 设置表格单元格的字体和字体大小
# self.pdf_canvas.setFont(self.font_name, self.font_size)
# 开始绘制表格单元格
data.reverse()
for i, row in enumerate(data):
y = y_start + (i * row_height)
x = x_start
for j, cell in enumerate(row):
# 绘制单元格内容
self.pdf_canvas.drawString(x, y, str(cell))
# 移动到下一个单元格
x += col_widths[j]
# 更新y
self.y -= table_height
if __name__ == '__main__':
# 创建PDFGenerator对象
pdf_generator = PDFGenerator()
# 添加文本
pdf_generator.add_text("我的报告")
pdf_generator.add_text("你好世界")
pdf_generator.add_text("这是我的第一个PDF报告")
# 添加图片
pdf_generator.add_image("sample_image.png")
# 添加表格
data = [["姓名", "年龄", "性别"], ["Tom", "18", "男"], ["Lucy", "20", "女"]]
pdf_generator.add_table(data)
# 保存文件
pdf_generator.save_pdf("my_report.pdf")
运行效果