您的用例非常常见,因此 Reportlab 有一个系统可以帮助您。
如果您阅读了有关的用户指南platypus
它将向您介绍 4 个主要概念:
DocTemplates
文档的最外层容器;
PageTemplates
各种页面布局的规范;
Frames
页面中可以包含流动文本或图形的区域的规范。
Flowables
Using PageTemplates
您可以以合理的方式将“静态”内容与页面上的动态内容结合起来,例如徽标、地址等。
你已经发现了Flowables
and Frames
但你可能一开始并没有幻想PageTemplates
or DocTemplates
然而。这是有道理的,因为对于大多数简单的文档来说这是不必要的。遗憾的是,发货清单并不是一个简单的文档,它包含地址、徽标和必须出现在每一页上的重要信息。这是哪里PageTemplates
进来。
那么如何使用这些模板呢?这个概念很简单,每个页面都有一定的结构,这些结构可能在页面之间有所不同,例如,在第一页上您想要放置地址,然后启动表,而在第二页上您只需要表。这将是这样的:
Page 1:
Page 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)