Python Reportlab 中的动态帧大小 [英] Dynamic framesize in Python Reportlab

查看:71
本文介绍了Python Reportlab 中的动态帧大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用

第 2 页:

示例如下:

(如果有一个用于 Reportlab 的 SO 文档,这将是完美的)

 from reportlab.lib.pagesizes import A4从 reportlab.lib.styles 导入 getSampleStyleSheet从 reportlab.lib.units 导入厘米从 reportlab.lib 导入颜色从 reportlab.platypus 导入 BaseDocTemplate、Frame、PageTemplate、NextPageTemplate、Paragraph、PageBreak、Table、\表格样式类 ShippingListReport(BaseDocTemplate):def __init__(self, filename, their_adress, objects, **kwargs):super().__init__(filename, page_size=A4, _pageBreakQuick=0, **kwargs)self.their_adress = their_adressself.objects = 对象self.page_width = (self.width + self.leftMargin * 2)self.page_height = (self.height + self.bottomMargin * 2)样式 = getSampleStyleSheet()# 设置框架,框架用于动态内容而不是固定页面元素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')# 创建页面模板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])# 告诉 Reportlab 使用后面页面上的另一个模板,# 默认情况下,添加的第一个模板用于第一页.故事 = [NextPageTemplate(['*', 'LaterPages'])]table_grid = [[产品",数量"]]# 添加对象对于 self.objects 中的 shipping_object: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, colours.black),('BOX', (0,0), (1,0), 1.0, colours.black),])))self.build(故事)def on_first_page(自我,画布,文档):canvas.saveState()# 添加标志和其他默认的东西self.add_default_info(画布,文档)canvas.drawString(doc.leftMargin, doc.height, 我的地址")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, 公司名称")canvas.restoreState()如果 __name__ == '__main__':ShippingListReport('example.pdf', 他们的地址", [产品", 产品"] * 50)

I tried to generate a shipping list with in Python. I was trying to put all parts (like senders address, receivers address, a table) in place by using Platypus Frames.

The first problem that I ran into was that I needed a lot of Frames to position everything the right way, is there a better way using Platypus? Because I want the senders address and my address to be on the same height and if I just add them to my story = [] they get aligned one below the other.

The next problem is that the table I'm drawing is dynamic in size and when I reach the end of the Frame ( space I want the table to go) it just does a FrameBreak and continuous in the next frame. So how can I make the Frame (space for my table ) dynamic?

解决方案

Your use case is a really common one, so Reportlab has a system to help you out.

If you read the user guide about platypus it will introduce you to 4 main concepts:

DocTemplates the outermost container for the document;

PageTemplates specifications for layouts of pages of various kinds;

Frames specifications of regions in pages that can contain flowing text or graphics.

Flowables Using PageTemplates you can combine "static" content with dynamic on a page in a sensible way like for example logo's, addresses and such.

You already discovered the Flowables and Frames but propably you did not start on fancyPageTemplates or DocTemplates yet. This makes sense because it isn't necessary for most simple documents. Saddly a shippinglist isn't a simple document, it holds address, logos and important info that has to be on every page. This is where PageTemplates come in.

So how do you use these templates? The concept is simple each page has a certain structure that might differ between pages, for example on page one you want to put the addresses and then start the table while on the second page you only want the table. This would be something like this:

Page 1:

Page 2:

A example would look like this:

(This would be perfect for the SO Documentation if there was one for Reportlab)

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)

这篇关于Python Reportlab 中的动态帧大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆