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