python - Reportlab - 表格扩展到多个框架和页面

标签 python reportlab

我正在尝试在 Reportlab 中创建一个简单的表格,其中列出了学生姓名。然而,该表有 100 多行长,因此在一页上放不下。我正在寻找当表格太大而无法容纳在一页上时将其拆分,并继续在第二页上,依此类推。我还希望将“学生报告:”标题保留在每页顶部。

我已经使用下面的代码来执行此操作,但是当我为大于一页的表运行代码时,它会无限期地运行。我希望有人能够帮助我解决这个问题。

预先感谢一百万,我真的很感激!


import os
import pandas as pd
import numpy as np
from datetime import datetime as dt
from reportlab.pdfgen.canvas import Canvas
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
from reportlab.platypus import Paragraph, Frame, Table, TableStyle, Image, Spacer
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

#Pull in Student Names
student_names = pd.read_csv("test_names.csv")

#Define table style
tblstyle = TableStyle([('INNERGRID', (0,0), (-1,-1), 0.25, colors.white),
                           ('BOX', (0,0), (-1,-1), 0.25, colors.white),
                           ('FONTSIZE', (0, 0), (-1, 0), 6),
                           ('FONTSIZE', (0, 1), (-1, -1), 6),
                           ('TEXTFONT', (0, 0), (-1, 0), 'Calibri-Bold'),
                           ('TEXTFONT', (0, 1), (0, -1), 'Calibri-Bold'),
                           ('TEXTFONT', (0, 1), (-1, -1), 'Calibri'),
                           ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
                           ('TEXTCOLOR', (1, 1), (0, -1), colors.black),
                           ('LEFTPADDING', (0, 0), (-1, -1), 1),
                           ('RIGHTPADDING', (0, 0), (-1, -1), 1),
                           ('TOPPADDING', (0, 0), (-1, -1), 0),
                           ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
                           ('ROWBACKGROUNDS', (0, 0), (-1, -1), (colors.HexColor('#e8e9ec'), colors.HexColor('#CED1D6'))),
                           ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#3A5675')),
                           ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
                           ('ALIGN', (0, 1), (-1, -1), 'CENTER'),
                           ('VALIGN', (0, 0), (-1, -1), 'BOTTOM'),
                           ])

#Create a document
c = canvas.Canvas("student_list.pdf")
dtstring = dt.date.today().strftime("%B %d, %Y")

#create header on first page
c.drawString(55,750,"Student Report: "+dtstring)
c.line(50,740,530,740)

# turn datatable the table into a list of lists which is the format reportlab wants
data_summary = [pd.DataFrame(student_names).columns.values.tolist()] + pd.DataFrame(student_names).values.tolist()

# config the widths and heights of this specific table
colwidths_2 = [300] * len(data_summary)
rowheights_2 = [15] * len(data_summary)
    
# create table using the platypus Table object & set the style
tbl_summary = Table(data_summary,colwidths_2,rowheights_2,hAlign='LEFT', repeatRows=1)
tbl_summary.setStyle(tblstyle)

# Create frame empty story       
frame = Frame(50, 15, 500, 700, showBoundary=1)
story = []

story.append(tbl_summary)

for t in story:
    while frame.add(t, c) == 0:
        frame.split(t, c)
        frame = Frame(50, 15, 500, 700, showBoundary=1)

# save pdf
c.save()

os.startfile('student_list.pdf')

最佳答案

我认为您遇到的情况是 Canvas 是单个页面。您需要使用文档模板,以便 Flowable 知道到达页面末尾时要做什么。

...我没有 Pandas 或 Numpy,所以我无法测试这个,并且第一页标题和间隔符可能需要调整,但我认为你想要类似的东西:

import os
import pandas as pd
import numpy as np
from datetime import datetime as dt
from reportlab.pdfgen.canvas import Canvas
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
from reportlab.platypus import Paragraph, Frame, Table, TableStyle, Image, Spacer, SimpleDocTemplate
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# Pull in Student Names
student_names = pd.read_csv("test_names.csv")

# Define table style
tblstyle = TableStyle([('INNERGRID', (0, 0), (-1, -1), 0.25, colors.white),
                       ('BOX', (0, 0), (-1, -1), 0.25, colors.white),
                       ('FONTSIZE', (0, 0), (-1, 0), 6),
                       ('FONTSIZE', (0, 1), (-1, -1), 6),
                       ('TEXTFONT', (0, 0), (-1, 0), 'Calibri-Bold'),
                       ('TEXTFONT', (0, 1), (0, -1), 'Calibri-Bold'),
                       ('TEXTFONT', (0, 1), (-1, -1), 'Calibri'),
                       ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
                       ('TEXTCOLOR', (1, 1), (0, -1), colors.black),
                       ('LEFTPADDING', (0, 0), (-1, -1), 1),
                       ('RIGHTPADDING', (0, 0), (-1, -1), 1),
                       ('TOPPADDING', (0, 0), (-1, -1), 0),
                       ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
                       ('ROWBACKGROUNDS', (0, 0), (-1, -1), (colors.HexColor('#e8e9ec'), colors.HexColor('#CED1D6'))),
                       ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#3A5675')),
                       ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
                       ('ALIGN', (0, 1), (-1, -1), 'CENTER'),
                       ('VALIGN', (0, 0), (-1, -1), 'BOTTOM'),
                       ])



# Create a document
c = canvas.Canvas("student_list.pdf")

# turn datatable the table into a list of lists which is the format reportlab wants
data_summary = [pd.DataFrame(student_names).columns.values.tolist()] + pd.DataFrame(student_names).values.tolist()

# config the widths and heights of this specific table
colwidths_2 = [300] * len(data_summary)
rowheights_2 = [15] * len(data_summary)

# create table using the platypus Table object & set the style
tbl_summary = Table(data_summary, colwidths_2, rowheights_2, hAlign='LEFT', repeatRows=1)
tbl_summary.setStyle(tblstyle)


# Build Story - Add a spacer at the beginning for your heading
story = [
    Spacer(1, 1 * inch)
]

story.append(tbl_summary)

# Create Page 1 Formatting
def myFirstPage(canvas: canvas.Canvas, doc):
    canvas.saveState()

    dtstring = dt.date.today().strftime("%B %d, %Y")

    # create header on first page
    canvas.drawString(55, 750, "Student Report: " + dtstring)
    canvas.line(50, 740, 530, 740)


# Use a Document Template so the flowable can flow to the next page.  
doc = SimpleDocTemplate(
    "student_list.pdf",
    pageSize=letter,
    rightMargin=0.5 * inch, leftMargin=0.5 * inch, topMargin=0.5 * inch, bottomMargin=0.5 * inch,
)

# Build and save
doc.build(story, onFirstPage=myFirstPage)


编辑:添加一个关于跨多个页面布局的精彩答案的链接: https://stackoverflow.com/a/39268987/5679079

关于python - Reportlab - 表格扩展到多个框架和页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66177443/

相关文章:

Python 脚本无法从 XML 中提取数据

python - 使用 resample 为 pandas 数据框中的不同列聚合具有不同规则的数据

python - 使用 Python 持续更改环境变量

python Pandas 调用 groupby.agg 中的复杂函数

python-2.7 - 如何将 python Reportlab 表定位在位置 10,100 并使用 drawString

python - ReportLab 表的列跨越 PDF 页面上的所有行?

python - 如何从古腾堡自动下载书籍

Python:PDF:如何读取带有单选按钮的表单

python-2.7 - Reportlab pdf编码

django - 渲染从 SimpleDocTemplate 构建的 ReportLab pdf