簡體   English   中英

Python Reportlab 中的動態幀大小

[英]Dynamic framesize in Python Reportlab

我嘗試在 Python 中使用生成發貨清單。我試圖通過使用 Platypus Frames將所有部分(如發件人地址、收件人地址、表格)放在適當的位置。

我遇到的第一個問題是我需要很多Frames到 position 一切都正確,有沒有更好的方法使用 Platypus? 因為我希望發件人地址和我的地址在同一高度,如果我只是將它們添加到我的story = [] ,它們就會一個一個地對齊。

下一個問題是我正在繪制的表格的大小是動態的,當我到達Frame的末尾(我希望表格移動的空間)時,它只是在下一幀中執行FrameBreak和連續。 那么我怎樣才能使Frame (我的桌子的空間)動態化呢?

您的用例非常常見,因此Reportlab有一個系統可以幫助您。

如果您閱讀有關platypus的用戶指南,它將向您介紹4個主要概念:

DocTemplates文檔的最外層容器;

PageTemplates各種頁面布局的規范;

Frames中可包含流動文本或圖形的頁面區域的規范。

Flowables使用PageTemplates可以在例如像標志的,地址,這樣一個合理的方式組合頁上的“靜態”的內容與動態。

你已經發現了FlowablesFrames ,但propably你沒有花哨的啟動PageTemplatesDocTemplates呢。 這是有道理的,因為大多數簡單文檔都沒有必要。 令人遺憾的是,發貨清單不是一個簡單的文件,它包含必須在每個頁面上的地址,徽標和重要信息。 這就是PageTemplates

那么你如何使用這些模板? 概念很簡單,每個頁面都有一定的結構可能會在頁面之間有所不同,例如在第一頁上要放置地址,然后在第二頁上啟動表格,只需要表格。 這將是這樣的:

第1頁: 在此輸入圖像描述

第2頁: 在此輸入圖像描述

示例如下所示:

(如果有一個Reportlab,這對SO文檔來說是完美的)

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, NextPageTemplate, Paragraph, PageBreak, Table, \
    TableStyle


class ShippingListReport(BaseDocTemplate):
    def __init__(self, filename, their_adress, objects, **kwargs):
        super().__init__(filename, page_size=A4, _pageBreakQuick=0, **kwargs)
        self.their_adress = their_adress
        self.objects = objects

        self.page_width = (self.width + self.leftMargin * 2)
        self.page_height = (self.height + self.bottomMargin * 2)


        styles = getSampleStyleSheet()

        # Setting up the frames, frames are use for dynamic content not fixed page elements
        first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height - 6 * cm, id='small_table')
        later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height, id='large_table')

        # Creating the page templates
        first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.on_first_page)
        later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame], onPage=self.add_default_info)
        self.addPageTemplates([first_page, later_pages])

        # Tell Reportlab to use the other template on the later pages,
        # by the default the first template that was added is used for the first page.
        story = [NextPageTemplate(['*', 'LaterPages'])]

        table_grid = [["Product", "Quantity"]]
        # Add the objects
        for shipped_object in self.objects:
            table_grid.append([shipped_object, "42"])

        story.append(Table(table_grid, repeatRows=1, colWidths=[0.5 * self.width, 0.5 * self.width],
                           style=TableStyle([('GRID',(0,1),(-1,-1),0.25,colors.gray),
                                             ('BOX', (0,0), (-1,-1), 1.0, colors.black),
                                             ('BOX', (0,0), (1,0), 1.0, colors.black),
                                             ])))

        self.build(story)

    def on_first_page(self, canvas, doc):
        canvas.saveState()
        # Add the logo and other default stuff
        self.add_default_info(canvas, doc)

        canvas.drawString(doc.leftMargin, doc.height, "My address")
        canvas.drawString(0.5 * doc.page_width, doc.height, self.their_adress)

        canvas.restoreState()

    def add_default_info(self, canvas, doc):
        canvas.saveState()
        canvas.drawCentredString(0.5 * (doc.page_width), doc.page_height - 2.5 * cm, "Company Name")

        canvas.restoreState()


if __name__ == '__main__':
    ShippingListReport('example.pdf', "Their address", ["Product", "Product"] * 50)

您可以使用 Platypus 的 KeepInFrame class 到 position 元素,例如在同一高度上的發送者和接收者的地址。 KeepInFrame 允許您指定您想要的元素的寬度和高度 position,它會自動調整元素的 position 以適應該空間。 以下是如何使用它的示例:

from reportlab.lib.units import cm
from reportlab.platypus import KeepInFrame

sender_address = "123 Main St, Anytown USA 12345"
receiver_address = "456 Park Ave, Anytown USA 67890"

# Create a KeepInFrame object with a width of 10cm and a height of 2cm
sender_address_frame = KeepInFrame(10*cm, 2*cm, [sender_address])
receiver_address_frame = KeepInFrame(10*cm, 2*cm, [receiver_address])

# Add the KeepInFrame objects to your story
story = [sender_address_frame, receiver_address_frame]

對於表格,您可以使用 KeepTogether 將表格的所有行保持在同一框架中。

    from reportlab.platypus import KeepTogether

    # Create a table
    table = Table(data)

    # Create a KeepTogether object with the table
    table_frame = KeepTogether(table)

    # Add

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM