我尝试使用reportlab和Playtipus模块从python创建PDF。
问题在于我不了解如何处理布局。 我创建了一个简单的PageTemplate,它是主页面,带有一个简单的Frame 但在这个简单的框架内,我需要一个可流动的"两个Colonne"布局。
页面模板:
class PageOne(PageTemplate):
def __init__(self, context):
self.context = context
self.largeur = self.context.doc.pagesize[0]
self.hauteur = self.context.doc.pagesize[1]
self.simpleFrame = Frame(self.context.doc.leftMargin, self.context.doc.bottomMargin, self.context.doc.width, self.context.doc.height - 3*cm, id='normal');
PageTemplate.__init__(self, id="PageOne", frames=[self.simpleFrame], pagesize = A4, onPage = CommonReportPdf.footer_and_header)
print("here 1 ")
def beforeDrawPage(self, canvas, doc):
canvas.saveState()
try:
print("beforeDrawPage")
finally:
canvas.restoreState()
自定义部分模型(表示具有相关测试的部分):
class CustomSection(Flowable):
def __init__(self, x=0, y=-15, width=80, height=15, title="", flowables=[]):
Flowable.__init__(self)
self.x = x
self.y = y
self.width = width
self.height = height
self.title = title
self.styles = getSampleStyleSheet()
def __repr__(self):
return "CustomSection(w=%s)" % self.width
def _draw_title(self):
print("draw title")
self.canv.rect(self.x, self.y, self.width, self.height)
self.canv.line(self.x, 0, 500, 0)
p = Paragraph(self.title, style=self.styles["Normal"])
p.wrapOn(self.canv, self.width, self.height)
p.drawOn(self.canv, *self.coord(self.x+2, 10, mm))
def draw(self):
self.canv.saveState()
try:
self._draw_title()
# Here add SectionItemWithValue or SectionItemWithoutValue to this flowable
finally:
self.canv.restoreState()
def coord(self, x, y, unit=1):
"""
http://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
流动性:
class SectionItemWithValue(Flowable):
def __init__(self, title, result, value, x=0, y=-15, width=80, height=15):
self.title = title
self.result = result
self.value = value
def draw(self):
self.canv.saveState()
try:
print("ok")
finally:
self.canv.restoreState()
class SectionItemWithoutValue(Flowable):
def __init__(self, title, result, x=0, y=-15, width=80, height=15):
self.title = title
self.result = result
def draw(self):
self.canv.saveState()
try:
print("ok")
finally:
self.canv.restoreState()
Pdf生成类:
class XmlToPdf:
def __init__(self, xml_file):
#self.root_xml = self.init_xml(xml_file)
destination_path = "XmlToPdf.pdf"
self.elements = []
self.doc = BaseDocTemplate(destination_path, showBoundary=0, leftMargin=0.7 * cm, rightMargin=0.7*cm, topMargin=0.7*cm, bottomMargin=0.7*cm, pagesize=A4)
self.simpleFrame = Frame(self.doc.leftMargin, self.doc.bottomMargin, self.doc.width, self.doc.height - 5*cm, id='normal')
def init_xml(self, xml_file):
tree = ET.parse(xml_file)
return tree.getroot()
def create_pdf(self):
styles = getSampleStyleSheet()
_baseFontNameBI = tt2ps(_baseFontName, 1, 1)
styles.add(ParagraphStyle(name='RightAlign', alignment=TA_RIGHT))
styles.add(ParagraphStyle(name='LeftAlign', alignment=TA_LEFT))
self.elements.append(Paragraph("Frame two columns, "*2,styles['LeftAlign'])) # I want both on the same line
self.elements.append(Paragraph("Frame two columns, "*2,styles['RightAlign'])) # I want both on the same line
self.elements.append(PageBreak())
self.elements.append(Paragraph("Une colonne",styles['Normal']))
self.elements.append(PageBreak())
textWidth = stringWidth("Test title 1 ", _baseFontNameBI, 14)
box = CustomSection(title="Contrôle logiciels", width=textWidth)
self.elements.append(box)
self.elements.append(Spacer(0, 20))
self.elements.append(Paragraph("This is a paragraph", styles["Normal"]))
textWidth = stringWidth("Test title 2", _baseFontNameBI, 14)
box = CustomSection(title="Test title 2", width=textWidth)
self.elements.append(box)
self.elements.append(Spacer(0, 1*inch))
textWidth = stringWidth("Test title 3", _baseFontNameBI, 14)
box = CustomSection(title="Test title 3", width=textWidth)
self.elements.append(box)
self.elements.append(Spacer(0, 1*inch))
textWidth = stringWidth("Test title 4", _baseFontNameBI, 14)
box = CustomSection(title="Test title 5", width=textWidth)
self.elements.append(box)
self.elements.append(Spacer(0, 1*inch))
self.doc.totalPages = 4
templates = [PageOne(self)]
self.doc.addPageTemplates(templates)
self.doc.build(self.elements)
我使用正确的组件?你有一些"复杂"文件例子?如何处理布局和段落?我应该用桌子吗?