为reportlab flowables定义可打印区域

时间:2015-01-26 20:31:39

标签: python-3.x reportlab

我第一次使用reportlab作为申请的一部分,我正在建立商业信函。我有一个玩具示例如下:

# -*- coding: utf-8 -*-
import sys
import time
from reportlab.lib.enums import TA_JUSTIFY, TA_LEFT, TA_RIGHT
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm
from reportlab.platypus import (
        Image,
        Paragraph,
        SimpleDocTemplate,
        Spacer,
        Table,
    )


class NumberedCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        canvas.Canvas.__init__(self, *args, **kwargs)
        self._saved_page_states = []

    def showPage(self):
        self._saved_page_states.append(dict(self.__dict__))
        self._startPage()

    def save(self):
        """add page info to each page (page x of y)"""
        num_pages = len(self._saved_page_states)
        for state in self._saved_page_states:
            self.__dict__.update(state)
            self.draw_page_number(num_pages)
            canvas.Canvas.showPage(self)
        canvas.Canvas.save(self)

    def draw_page_number(self, page_count):
        # Change the position of this to wherever you want the page number to be
        self.drawRightString(
                195 * mm,
                15 * mm,
                "Page %d of %d" % (self._pageNumber, page_count)
            )


class MyPrint(object):
    def __init__(self):
        self.pagesize = A4
        self.width, self.height = self.pagesize

    @staticmethod
    def _first_page(canvas, doc):
        # Save the state of our canvas so we can draw on it
        canvas.saveState()
        styles = getSampleStyleSheet()

        # Footer
        footer = Paragraph('Return address, Where we live, City, Postcode', styles['Normal'])
        w, h = footer.wrap(doc.width, doc.bottomMargin)
        footer.drawOn(canvas, doc.leftMargin, h)

        # Release the canvas
        canvas.restoreState()

    @staticmethod
    def _subsequent_pages(canvas, doc):
        # Save the state of our canvas so we can draw on it
        canvas.saveState()
        styles = getSampleStyleSheet()

        # Header
        header = Paragraph('Letter type' * 5, styles['Normal'])
        w, h = header.wrap(doc.width, doc.topMargin)
        header.drawOn(canvas, doc.leftMargin, doc.height + doc.topMargin - h)

        # Footer
        footer = Paragraph('Return address, Where we live, City, Postcode' * 5, styles['Normal'])
        w, h = footer.wrap(doc.width, doc.bottomMargin)
        footer.drawOn(canvas, doc.leftMargin, h)

        # Release the canvas
        canvas.restoreState()

    def coord(self, x, y, unit=1):
        """
        # https://stackoverflow.com/questions/4726011/wrap-text-in-a-table-reportlab
        Helper class to help position flowables in Canvas objects
        """
        x, y = x * unit, self.height - y * unit
        return x, y

    def print_lipsum(self):
        doc = SimpleDocTemplate(
                "form_letter.pdf",
                rightMargin=72,
                leftMargin=72,
                topMargin=72,
                bottomMargin=72,
                pagesize=self.pagesize
            )

        # Our container for 'Flowable' objects
        elements = []

        # A large collection of style sheets pre-made for us
        styles = getSampleStyleSheet()
        styles.add(ParagraphStyle(
            name='align_right',
            fontName='Helvetica',
            alignment='TA_RIGHT')
        )

        # Draw things on the PDF. Here's where the PDF generation happens.
        # See the ReportLab documentation for the full list of functionality.

        # Logo block
        logo = Image(
                'http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/280px-PNG_transparency_demonstration_1.png',
            )
        logo.drawWidth = 70*mm
        logo.drawHeight = 50*mm

        # create recipient address
        address = """Jack Spratt\n
        Some address\n
        Some address\n
        Some address\n
        Some postcode\n
        """
        recipient_address = Paragraph(address, styles["align_right"])

        # create a table for our header elementsj
        header_elements = [[logo, address]]
        table = Table(header_elements)
        elements.append(table)

        lipsum = [
            'Donec nec nunc eu ante luctus sodales eu ac massa. Duis id auctor sapien. Sed vel faucibus sem. Suspendisse potenti. Proin ut augue condimentum, semper leo sed, laoreet odio. Nam lobortis vel elit sit amet egestas. Vestibulum congue nisi non semper sollicitudin.',
            ]

        elements.append(Paragraph('My User Names', styles['Heading1']))
        for i, par in enumerate(lipsum):
            elements.append(Paragraph(par, styles['Normal']))
            elements.append(Spacer (1,12))

        doc.build(
                elements,
                onFirstPage=self._first_page,
                onLaterPages=self._subsequent_pages,
                canvasmaker=NumberedCanvas
            )

       # # Get the value of the BytesIO buffer and write it to the response.
       # pdf = buffer.getvalue()
       # buffer.close()
       # return pdf


if __name__ == '__main__':
    test = MyPrint()
    test.print_lipsum()

answer referenced in the code comments对某些定位非常有用。但我真正想做的是定义一个可打印区域'适用于_first_page_subsequent_page方法中的flowables。这样我就可以通过一次build调用构建主体文本并知道布局得到了处理。我还没有在文档中找到这样做的方法。这可能吗?我使用的是Python 3.4,如果相关的话。

编辑:Frames似乎与我喜欢的内容非常匹配,但我担心警告不要同时在多个文档中使用它们,因为我和建立一个多用户网络应用程序。这里的任何人都可以扩展这个警告在实践中意味着什么吗?

0 个答案:

没有答案