2012-06-17 31 views
7

Tôi đang tạo bảng PDF với Reportlab platypus. Tôi không biết, khi trang đầy vì nội dung động. Làm thế nào tôi có thể kiểm tra, nếu tôi ở cuối trang?Ngắt trang có điều kiện trong reportlab

Có phương pháp nào trong thú mỏ vịt để kiểm tra cuối trang không?

Tôi có danh sách các công ty và mỗi công ty có nhiều đơn vị kinh doanh với các khoản phí của họ.

companies = [('company1', 'businessunit1', 500), 
       ('company1', 'businessunit2',400), 
       ('company2', 'businessunit3',200), 
       ('company2', 'businessunit4', 700), 
       ('company3', 'businessunit5', 800) 
       ] 

Danh sách trên sẽ tạo ra 3 bảng cho mỗi công ty, nếu bảng nào đến cuối trang sẽ bị hỏng.

 fields = ['company name', 'business unit name', 'charge'] 
     for i, comp in enumerate(companies): 
      charges = [] 
      document.append(Paragraph("<b>%s</b>" %comp[i][0], STYLES['COMPANY_NAME'])) 
      document.append(Spacer(1, 5)) 
      charges.append(comp[i][0]) 
      charges.append(comp[i][1]) 
      charges.append(comp[i][2]) 
      charges_table = LongTable([fields] + charges, colWidths=(30,150,100)) 
      charges_table.setStyle(TableStyle([ 
          ('BACKGROUND', (0, 0), (-1, 0), colors.gray), 
          ('FONTSIZE', (0, 0), (-1, 0), 6), 
          ('GRID', (0, 0), (-1, -1), 1, colors.gray), 
          ('FONTSIZE', (0, 0), (-1, -1), 7), 
          ('TEXTCOLOR',(0,-1),(-1,-1),'#FF4500'), 
          ]) 
         ) 

      charges_table.hAlign = 'CENTER' 
      document.append(charges_table) 
+0

tôi có thể nhận được bất kỳ giải pháp? – Asif

+0

Noone nhưng bạn sẽ thấy bình luận của bạn trừ khi bạn * chỉnh sửa * câu hỏi của bạn. Ngoài ra, hãy xem [faq # bounty] trên các tùy chọn khác để nhận câu trả lời. –

Trả lời

4

Bạn nên cung cấp một số mã mẫu để chúng tôi biết những gì bạn đang cố gắng hoàn thành. Tại sao bạn muốn biết khi nào trang đã kết thúc? Để vẽ nội dung mới? Để in ra một số thông tin chẩn đoán?

Giả sử bạn muốn vẽ thứ gì đó sau khi trang được hiển thị, bạn có thể sử dụng phương thức afterPage(), được cung cấp trong lớp BaseDocTemplate. Từ tài liệu của ReportLab:

Điều này được gọi sau khi xử lý trang và ngay sau phương thức afterDrawPage của mẫu trang hiện tại. Một lớp dẫn xuất có thể sử dụng điều này để làm những thứ phụ thuộc vào thông tin trong trang như từ đầu tiên và cuối cùng trên trang của một từ điển.

Về cơ bản, nó được gọi là BaseDocTemplate sau khi trang được vẽ. Trong mã nguồn, nó bao gồm self, vì nó là một phần của lớp BaseDocTemplate, vì vậy bạn có thể truy cập canvas của nó!

Bạn có thể ghi đè lớp học trong tập lệnh của riêng mình và sau đó vẽ trực tiếp lên canvas.

from reportlab.platypus import BaseDocTemplate 
from reportlab.lib.styles import getSampleStyleSheet 
from reportlab.lib.units import inch 
from reportlab.lib.pagesizes import A4 
from reportlab.platypus import Paragraph 

class MyDocTemplate(BaseDocTemplate): 
    """Override the BaseDocTemplate class to do custom handle_XXX actions""" 

    def __init__(self, *args, **kwargs): 
     BaseDocTemplate.__init__(self, *args, **kwargs) 

    def afterPage(self): 
     """Called after each page has been processed""" 

     # saveState keeps a snapshot of the canvas state, so you don't 
     # mess up any rendering that platypus will do later. 
     self.canv.saveState() 

     # Reset the origin to (0, 0), remember, we can restore the 
     # state of the canvas later, so platypus should be unaffected. 
     self.canv._x = 0 
     self.canv._y = 0 

     style = getSampleStyleSheet() 

     p = Paragraph("This is drawn after the page!", style["Normal"]) 

     # Wraps and draws the paragraph onto the canvas 
     # You can change the last 2 parameters (canv, x, y) 
     p.wrapOn(self.canv, 2*inch, 2*inch) 
     p.drawOn(self.canv, 1*inch, 3*inch) 

     # Now we restore the canvas back to the way it was. 
     self.canv.restoreState() 

Bây giờ bạn có thể sử dụng MyDocTemplate giống như cách bạn sẽ sử dụng BaseDocTemplate trong logic chính của bạn:

if __name__ == "__main__": 

    doc = MyDocTemplate(
     'filename.pdf', 
     pagesize=A4, 
     rightMargin=.3*inch, 
     leftMargin=.3*inch, 
     topMargin=.3*inch, 
     bottomMargin=.3*inch 
    ) 

    elements = [ 
     # Put your actual elements/flowables here, however you're generating them. 
    ] 

    doc.addPageTemplates([ 
     # Add your PageTemplates here if you have any, which you should! 
    ]) 

    # Build your doc with your elements and go grab a beer 
    doc.build(elements) 
+0

Tôi có thể hỏi tại sao MyDocTemplate định nghĩa một phần mở rộng rỗng \ _ \ _ init \ _ \ _ khi nó đơn giản có thể kế thừa \ _ \ _ init \ _ \ _ từ BaseDocTemplate? Tôi đã nhìn thấy mô hình này khá một chút, và tôi không bao giờ hoàn toàn chắc chắn những gì nó phải đạt được. – holdenweb

+0

@holdenweb Thành thật mà nói trong ví dụ này không có mục đích. Tôi tin rằng tôi để lại điều đó trong đó bởi vì tôi đã sao chép từ một trong những kịch bản của riêng tôi. Tôi đã gán một số thuộc tính tùy chỉnh cho lớp con, vì vậy tôi phải ghi đè '__init__'. Tôi chắc chắn rằng nó có thể được gỡ bỏ mà không có bất kỳ kết quả xấu. – Nitzle

0

Bạn có để đếm các dòng sử dụng cho mình. tôi sử dụng một thủ tục bao gồm:

lin += inc 
if lin > 580: 
    doc.append(PageBreak()) 
    lin = 5 

Khi biết có bao nhiêu dòng một bảng sử dụng bạn có thể biết nếu nó sẽ phù hợp trong phần còn lại của trang.

Tôi sử dụng tính 'điểm' để tôi có thể xử lý các dòng có chiều cao khác nhau.

+0

Trong các ô bảng trường hợp chung có thể chứa các lưu lượng khác so với văn bản và do đó bạn sẽ phải theo dõi chiều cao của ô từ nội dung của nó, có thể sao chép phần lớn công việc bên trong thư viện ReportLab. Ngay cả khi thiết lập văn bản nó không phải là dễ dàng để biết bao nhiêu không gian dọc một đoạn sẽ chiếm. – holdenweb

0

tự động phân chia longtable cho nhiều trang, như thế này:

from reportlab.platypus import LongTable, TableStyle, BaseDocTemplate, Frame, PageTemplate 
from reportlab.lib.pagesizes import letter 
from reportlab.lib import colors 


def test(): 
    doc = BaseDocTemplate(
     "test.pdf", 
     pagesize=letter, 
     rightMargin=72, 
     leftMargin=72, 
     topMargin=72, 
     bottomMargin=18, 
     showBoundary=True) 

    elements = [] 
    datas = [] 
    for i, x in enumerate(range(1, 50)): 
     datas.append([i, x]) 
    t = LongTable(datas) 

    tableStyle = [ 
     ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), 
     ('BOX', (0, 0), (-1, -1), 0.25, colors.black), 
    ] 
    t.setStyle(TableStyle(tableStyle)) 
    elements.append(t) 

    frame = Frame(
     doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal') 
    doc.addPageTemplates([PageTemplate(id='longtable', frames=frame)]) 
    doc.build(elements) 


if __name__ == '__main__': 
    test()