猿问

reportlab SimpleDocTemplate - 使用可变行数设置表格的固定高度

我尝试Python使用reportlab.


发票只有一页,而且单页上的空间永远不会有更多的细节;我的代码在生成 PDF 之前检查最大详细信息数。


现在我正在使用SimpleDocTemplate将所有内容添加到页面,并使用Table. 这是一个简化的代码示例:


from reportlab.lib.units import mm

from reportlab.platypus import Paragraph, Spacer, Table, TableStyle

from reportlab.platypus import SimpleDocTemplate


# add invoice header

flowable_list = [

    Spacer(1, 5*mm),

    Paragraph('Date: ...', pg_style_1),

    Spacer(1, 5*mm),

]


# add invoice details

detail_list = [

    ('Item 1', 8, 45),

    ('Item 2', 1, 14),

]

row_list = [

    [

        Paragraph(desc, pg_style_1),

        quantity,

        amount,

    ]

    for desc, quantity, amount in detail_list]

story.append(

    Table(

        data=row_list,

        colWidths=[100*mm, 40*mm, 40*mm],

        style=TableStyle([

            ('VALIGN', (0, 0), (-1, -1), 'TOP'),

            ... some other options ...

        ])))


# add invoice footer; this should be at a specific position on the page

flowable_list.append(Spacer(1, 5*mm))

flowable_list.append(Paragraph('Total: 0', pg_style_1))


# build PDF

buffer = io.BytesIO()

doc = SimpleDocTemplate(buffer)

doc.build(flowable_list)

我的问题:底部的总金额每次都必须位于特定位置(类似于x*mm底部),但可能有可变数量的详细信息,导致详细信息表具有非固定高度。


我目前的解决方案:Spacer在表后添加一个;这个间隔的高度必须根据表格中的行数来计算(更多的行意味着间隔会更小;更少的行产生更大的间隔)。但是,如果其中一行环绕并占用比单行更多的空间,则此操作将失败。


我的问题:有没有办法为详细信息表设置固定高度,无论有多少行,但仍然继续使用SimpleDocTemplate?


这个类似的问题显示了一个将所有内容手动绘制到画布上的解决方案,但SimpleDocTemplate如果可能的话,我想要一种继续使用 的方法。


慕娘9325324
浏览 533回答 2
2回答

翻翻过去那场雪

试试这个使用“TopPadder”的可行示例,(结果是 Total 被推到 Frame 的底部,我假设你可以在它下面添加一个垫子,以控制底部的高度):########################################################################from reportlab.lib.units import mmfrom reportlab.platypus import Paragraph, Spacer, Table, TableStylefrom reportlab.lib.styles import getSampleStyleSheetfrom reportlab.platypus import SimpleDocTemplatefrom reportlab.platypus.flowables import TopPadderimport iodef create_pdf():    styles=getSampleStyleSheet()    # add invoice header    flowable_list = [        Spacer(1, 5 * mm),        Paragraph(f'Date: ...', styles['Normal']),        Spacer(1, 5 * mm),    ]    # add invoice details    detail_list = [        ('Item 1', 8, 45),        ('Item 2', 1, 14),    ]    row_list = [        [            Paragraph(f'desc', styles['Normal']),            # quantity,            # amount,        ]        for desc, quantity, amount in detail_list]    story = []    story.append(        Table(            data=row_list,            colWidths=[100 * mm, 40 * mm, 40 * mm],            style=TableStyle([                ('VALIGN', (0, 0), (-1, -1), 'TOP'),                # ... some other options...            ])))    # add invoice footer; this should be at a specific position on the page    flowable_list.append(Spacer(1, 5 * mm))    flowable_list.append(TopPadder(Paragraph(f'Total: 0', styles['Normal'])))    # build PDF    buffer = io.BytesIO()    doc = SimpleDocTemplate("test2.pdf")    doc.build(flowable_list)    # ----------------------------------------------------------------------if __name__ == "__main__":    create_pdf()  # Printing the pdf

吃鸡游戏

我还没有找到更好的方法,所以我将添加我当前的解决方案;也许它会帮助一些未来有类似问题的读者。...story.append(    Table(        data=row_list,        colWidths=[100*mm, 40*mm, 40*mm],        style=TableStyle([            ('VALIGN', (0, 0), (-1, -1), 'TOP'),            ... some other options ...        ])))# calculate real height of details table, so we can add a 'Spacer' for the missing# part to have the invoice totals at the correct height at the bottom of the page_, real_height = story[-1].wrap(doc_width, doc_height)height_reserved_for_details = 100*mmremaining_height = max(0, height_reserved_for_details - real_height)story.append(Spacer(1, remaining_height))flowable_list.append(Paragraph('Total: 0', pg_style_1))
随时随地看视频慕课网APP

相关分类

Python
我要回答