【问题标题】:Reportlab - Table extend to multiple frames and pagesReportlab - 表格扩展到多个框架和页面
【发布时间】:2021-02-12 18:49:19
【问题描述】:

我正在尝试在 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')

【问题讨论】:

    标签: python reportlab


    【解决方案1】:

    我认为您遇到的问题是画布是单页。您需要使用一个文档模板,以便 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

    【讨论】:

    • 感谢一百万亚历克斯,非常感谢对此的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2015-12-06
    • 2012-08-11
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    相关资源
    最近更新 更多