2012-01-11 43 views
15

Cách tốt nhất để có chân trang và tiêu đề trong báo cáo, không chỉ là một dòng, có thể được vẽ bằng canvas.drawString trong hàm onPage. Không tìm được cách để đặt thứ gì đó như Đoạn vào đầu trang/chân trang trong hàm onPage. cách tốt nhất để xử lý này là gì? Có cách nào để đặt một đoạn vào chân trang?Chân trang và đầu trang nhiều dòng (đoạn) trong reportlab

Trả lời

23

Bạn có thể sử dụng các lệnh vẽ tùy ý trong hàm onPage, vì vậy bạn chỉ có thể vẽ một đoạn (xem phần 5.3 trong reportlab user guide) từ hàm của bạn.

Đây là một ví dụ hoàn chỉnh:

from reportlab.lib.pagesizes import letter 
from reportlab.lib.styles import getSampleStyleSheet 
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Paragraph 

styles = getSampleStyleSheet() 
styleN = styles['Normal'] 
styleH = styles['Heading1'] 

def footer(canvas, doc): 
    canvas.saveState() 
    P = Paragraph("This is a multi-line footer. It goes on every page. " * 5, 
        styleN) 
    w, h = P.wrap(doc.width, doc.bottomMargin) 
    P.drawOn(canvas, doc.leftMargin, h) 
    canvas.restoreState() 

doc = BaseDocTemplate('test.pdf', pagesize=letter) 
frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, 
       id='normal') 
template = PageTemplate(id='test', frames=frame, onPage=footer) 
doc.addPageTemplates([template]) 

text = [] 
for i in range(111): 
    text.append(Paragraph("This is line %d." % i, 
          styleN)) 
doc.build(text) 
8

câu trả lời Jochen là tuyệt vời, nhưng tôi thấy nó không đầy đủ. Nó hoạt động cho footers, nhưng không cho các header như Reportlab sẽ vẽ tất cả các flowable trên đầu trang của header. Bạn cần phải chắc chắn kích thước của Frame bạn tạo không bao gồm khoảng trống được lấy bởi header để các flowabls không được in trên đầu trang của header.

Sử dụng mã Jochen của, đây là một ví dụ hoàn chỉnh cho tiêu đề:

from reportlab.lib.pagesizes import letter, cm 
from reportlab.lib.styles import getSampleStyleSheet 
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Paragraph 
from functools import partial 

styles = getSampleStyleSheet() 
styleN = styles['Normal'] 
styleH = styles['Heading1'] 

def header(canvas, doc, content): 
    canvas.saveState() 
    w, h = content.wrap(doc.width, doc.topMargin) 
    content.drawOn(canvas, doc.leftMargin, doc.height + doc.topMargin - h) 
    canvas.restoreState() 

doc = BaseDocTemplate('test.pdf', pagesize=letter) 
frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height-2*cm, id='normal') 
header_content = Paragraph("This is a multi-line header. It goes on every page. " * 8, styleN) 
template = PageTemplate(id='test', frames=frame, onPage=partial(header, content=header_content)) 
doc.addPageTemplates([template]) 

text = [] 
for i in range(111): 
    text.append(Paragraph("This is line %d." % i, styleN)) 
doc.build(text) 

Chú ý đến các decleration của Frame, nó trừ 2 cm từ chiều cao của khung hình để cho phép phòng cho tiêu đề. Các lưu lượng sẽ được in trong khung để bạn có thể thay đổi kích thước của khung để cho phép các kích thước khác nhau của tiêu đề.

Tôi cũng thấy rằng tôi thường cần chuyển các biến vào tiêu đề, vì vậy tôi đã sử dụng một phần chức năng được gán cho onPage để nội dung của tiêu đề có thể được chuyển vào. Bằng cách này, bạn có thể có tiêu đề biến dựa trên nội dung của trang.

0

Tôi biết điều này là một chút cũ nhưng tôi đã gặp phải vấn đề này và đã có thể giải quyết nó. Khi bạn có nhiều trang trong tệp PDF và muốn có chân trang/tiêu đề trên mỗi trang, bạn phải sử dụng NextPageTemplate('template_id'). Tôi chỉ viết mã có liên quan khi phần còn lại được hiển thị trong ví dụ @jochen ở trên.

Trong trường hợp của tôi, tôi đã sử dụng PageBreak() và tôi mất một thời gian để hiểu tại sao tôi chỉ nhận được chân trang trong trang đầu tiên.

from reportlab.platypus import Paragraph, PageBreak, PageTemplate, Frame, NextPageTemplate 

frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal') 
template = PageTemplate(id='footer', onPage=footer, frames=[frame]) 


# add a NextPageTemplate before a PageBreak to have the footer in the next page 

text.append(Paragraph('some text', style)), 
text.append(NextPageTemplate('footer')), # this will make the footer to be on the next page if exists 
text.append(PageBreak()) 
doc.build(text) 
Các vấn đề liên quan