我正在尝试将“全宽”表格拆分为2页甚至更多。我使用ReportLab的Platypus库和BaseDocTemplate类。
我有一个“全宽”的元素表,如果表有足够的行,应该将它绘制到第一页的框架中。它应该在第二页中继续。我的问题是第一页的框架与其他框架的高度和位置不同,因为在第一页的顶部我需要显示更多信息(是的......我在谈论发票或订单)。
经过数千次尝试之后,我所拥有的只是一个带有唯一页面的pdf,只有8个项目/行,这正是他们在第一页所需的空间,但如果表格超过8行,那么我得到一个只有1页而没有表格的pdf(这意味着一个空框架,虽然我看到了日志中的所有数据)。
我已经使用了split()和wrap()方法,但可能是错误的方式,因为我是ReportLab的新手。我告诉你我的代码的最后一个版本:
from django.http import HttpResponse
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.platypus import BaseDocTemplate, PageTemplate, Table, Spacer, Frame, TableStyle,\
NextPageTemplate, PageBreak, FrameBreak
PAGE_WIDTH = A4[0]
PAGE_HEIGHT = A4[1]
MARGIN = 10*mm
class ThingPDF(BaseDocTemplate):
def header(self, canvas, subheader=True):
# print 'header()'
data = [('AAAA', 'Thing %s' % (self.thing.name)), ]
s = []
t = Table(data, colWidths=[95 * mm, 95 * mm], rowHeights=None, style=None, splitByRow=1,
repeatRows=0, repeatCols=0)
t.setStyle(TableStyle([
('BACKGROUND', (0, 0), (0, 0), colors.red),
('BACKGROUND', (1, 0), (1, 0), colors.blue),
('ALIGN', (1, 0), (1, 0), 'RIGHT'),
]))
s.append(t)
# if subheader:
# print 'subheader'
self.head.addFromList(s, canvas)
def data_table(self, canvas, items):
# print 'data_table()'
d = [[u'col0', u'col1', u'col2', u'col3', u'col4', ],]
for item in items:
d.append([item.col0, item.col1, item.col2, item.col3, item.col4])
s = []
t = Table(d, colWidths=[20*mm, 100*mm, 20*mm, 20*mm, 30*mm], rowHeights=20*mm, style=None,\
splitByRow=1, repeatRows=0, repeatCols=0)
t.setStyle([('BACKGROUND', (0,0), (-1,0), ('#eeeeee'))])
h=187*mm #TODO
w=A4[0] - (2*MARGIN)
splitter = t.split(w, h)
# print '\n\nresult of splitting: ', len(splitter)
for i in splitter:
print 'i: ', i
self.dataframeX.addFromList(s, canvas)
s.append(t)
self.dataframe0.addFromList(s, canvas)
def on_first_page(self, canvas, doc):
canvas.saveState()
self.header(canvas)
self.data_table(canvas, self.items)
canvas.restoreState()
def on_next_pages(self, canvas, doc):
canvas.saveState()
self.header(canvas, subheader=False)
canvas.restoreState()
def build_pdf(self, thing=None, items=None, user=None):
self.thing = thing
self.items = items
self.doc = BaseDocTemplate('%s.pdf' % (thing.name),
pagesize=A4,
pageTemplates=[self.first_page, self.next_pages,],
showBoundary=1,
rightMargin=MARGIN,
leftMargin=MARGIN,
bottomMargin=MARGIN,
topMargin=MARGIN,
allowSplitting=1,
title='%s' % 'title')
self.story.append(Spacer(0*mm, 2*mm))
self.doc.build(self.story)
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=%s.pdf' % (reference)
return response
def __init__(self):
self.thing = None
self.items = None
self.story = []
#========== FRAMES ==========
self.head = Frame(x1=MARGIN, y1=A4[1] - (2*MARGIN), width=A4[0] - (2*MARGIN), height=10*mm,
leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0, id='header',
showBoundary=1)#, overlapAttachedSpace=None, _debug=None)
self.dataframe0 = Frame(x1=MARGIN, y1=10*mm, width=A4[0] - (2*MARGIN), height=187*mm,
leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0,
id='body', showBoundary=1)
self.dataframeX = Frame(x1=MARGIN, y1=MARGIN, width=A4[0] - (2*MARGIN), height=257*mm,
leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0,
id='body', showBoundary=1)
#========== PAGES ==========
self.first_page = PageTemplate(id='firstpage', frames=[self.head, self.dataframe0], onPage=self.on_first_page)
self.next_pages = PageTemplate(id='nextpages', frames=[self.head, self.dataframeX], onPage=self.on_next_pages)
提前谢谢!!
答案 0 :(得分:0)
您发布的代码缺少一些数据并且本身不可运行,所以我无法确定我的答案是否正确。如果这不起作用,请扩展您的代码!
首先,您根本不必使用wrap
和split
方法!当doc.build
消费故事时,该表将自行分裂。另外,split不会拆分表 inline ,而只返回表列表。因此,在您的情况下,splitter
是您迭代的表的列表,然后将空列表附加到该帧。我建议你跳过那一部分。您正在向各个帧添加不同的元素。因此,您可以将拆分表添加到dataframeX,但可能永远不会使用dataframeX,因为您永远不会使用next_pages
PageTemplate
。为此,您必须在完成第一页后为故事添加NextPageTemplate()
。我会让platypus为你做这些事情:让你的方法返回带有生成元素的列表并在将它们传递给doc.build()
之前将它们连接起来。