生成含Pandas数据框的PDF并添加页码及代码优化咨询
优化Pandas数据框转PDF并添加页码的方案
你的现有代码存在几个可以改进的地方:重复的表格样式设置、多余的中间PDF文件、合并后添加页码的逻辑有错误。下面是重构后的完整方案,实现每页一个表格、自动添加右下角页码的需求:
核心优化点
- 消除重复代码:把表格样式、CSV读取逻辑封装成函数,避免冗余
- 直接生成单PDF文件:无需分文件再合并,Platypus会自动处理分页
- 原生添加页码:通过ReportLab的页面回调函数,在生成PDF时直接插入页码,比水印方案更高效且原生
完整代码
import pandas as pd import numpy as np from reportlab.lib import colors from reportlab.lib.pagesizes import letter, inch from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, PageBreak from reportlab.pdfgen import canvas # 封装表格样式函数,避免重复代码 def get_table_style(): return TableStyle([ ('ALIGN', (1, 1), (-2, -2), 'RIGHT'), ('TEXTCOLOR', (1, 1), (-2, -2), colors.black), ('VALIGN', (0, 0), (0, -1), 'TOP'), ('TEXTCOLOR', (0, 0), (0, -1), colors.black), ('TEXTCOLOR', (0, -1), (-1, -1), colors.black), ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), ('BOX', (0, 0), (-1, -1), 0.25, colors.black), ]) # 读取CSV并转换为ReportLab Table对象(补上表头) def csv_to_table(csv_path): df = pd.read_csv(csv_path).dropna() # 处理缺失值 table_data = np.array(df).tolist() # 原代码未包含表头,这里补上让表格更完整 table_data.insert(0, df.columns.tolist()) table = Table(table_data) table.setStyle(get_table_style()) return table # 定义页码绘制函数,放在每页右下角 def add_page_number(canvas, doc): page_num = canvas.getPageNumber() # 位置可按需调整:右边距1英寸,底部距0.5英寸 canvas.drawRightString( doc.pagesize[0] - inch, 0.5 * inch, f"Page {page_num}" ) # 主逻辑 if __name__ == "__main__": # 初始化PDF文档 doc = SimpleDocTemplate("result.pdf", pagesize=letter) elements = [] # 添加第一个表格(来自data1.csv) table1 = csv_to_table("data1.csv") elements.append(table1) # 强制分页,确保第二个表格在新页面 elements.append(PageBreak()) # 添加第二个表格(来自data2.csv) table2 = csv_to_table("data2.csv") elements.append(table2) # 生成PDF,指定页码回调函数 doc.build(elements, onFirstPage=add_page_number, onLaterPages=add_page_number)
关键部分解释
- 代码复用:
get_table_style()和csv_to_table()把重复逻辑抽离,后续新增表格只需调用函数,维护更方便 - 表头补充:原代码没有把DataFrame的表头加入表格,重构后补上让输出更符合报表需求
- 原生页码:通过
onFirstPage和onLaterPages参数,在PDF生成时直接绘制页码,比后加水印更稳定,不会出现图层叠加问题 - 分页控制:
PageBreak()确保每个表格单独占一页,满足你每页一个表格的需求
关于水印方案的说明
水印方案属于PDF后处理,需要先生成无页码的PDF再叠加页码,流程繁琐且容易出现显示异常。而我们用的原生回调方案是在生成PDF的过程中直接插入页码,无需中间文件,性能和可靠性都更好。
内容的提问来源于stack exchange,提问作者sam Adams




