2012-06-17 3 views
7

Я создаю таблицы PDFs с утконосом Reportlab. Я не знаю, когда страница заполнена из-за динамического содержимого. Как я могу проверить, если я нахожусь в конце страницы?Условный разрыв страницы в reportlab

Есть ли какой-либо метод в утконосе, чтобы проверить конец страницы?

У меня есть список компаний, и каждая компания имеет несколько бизнес-единиц со своими обязанностями.

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

приведенные выше список должен генерировать 3 таблицы каждой для одной компании, но если этот список имеет несколько компаний, которые генерируют несколько таблиц и если таблица достигает конец страницы, которая сломается.

 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

Может ли я получить какое-либо решение? – Asif

+0

Никто, но вы увидите ваш комментарий, если не будете * редактировать * свой вопрос. Также см. [Faq # bounty] по другим параметрам, чтобы получить ответы. –

ответ

4

Вы должны предоставить примерный код, чтобы мы знали, чего вы пытаетесь выполнить. Почему вы хотите знать, когда страница закончилась? Создать новый контент? Чтобы распечатать некоторую диагностическую информацию?

Предполагая, что вы хотите нарисовать что-то после отображения страницы, вы можете использовать метод afterPage(), который предоставляется в классе BaseDocTemplate. Из документации ReportLab:

Это вызывается после обработки страницы и сразу после метода afterDrawPage текущего шаблона страницы. Производный класс может использовать это для выполнения действий, зависящих от информации на странице, такой как первое и последнее слово на странице словаря.

В принципе, это называется BaseDocTemplate после того, как страница была нарисована. В исходном коде он содержит self, так как он является частью класса BaseDocTemplate, поэтому вы можете получить доступ к его полотну!

Вы можете переопределить класс в своем собственном скрипте, а затем напрямую нарисовать его на холсте.

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() 

Теперь вы можете использовать MyDocTemplate так же, как вы бы использовать BaseDocTemplate в основной логики:

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

Могу ли я спросить, почему MyDocTemplate определяет расширение null \ _ \ _ init \ _ \ _, когда он может просто наследовать \ _ \ _ init \ _ \ _ из BaseDocTemplate? Я видел эту картину совсем немного, и я никогда не уверен, чего она должна достичь. – holdenweb

+0

@holdenweb Честно говоря, в этом примере нет никакой цели. По-моему, я оставил это там, потому что я скопировал это из одного из моих собственных сценариев. Я назначал некоторые пользовательские атрибуты для дочернего класса, поэтому мне пришлось переопределить '__init__'. Я уверен, что его можно было бы удалить без каких-либо плохих результатов. – Nitzle

0

Вы должны рассчитывать строки используются самостоятельно. я использую процедуру, которая включает в себя:

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

Зная, сколько строк таблицы использует вы можете знать, если он будет вписываться в остальной части страницы.

Я использую подсчет «очков», поэтому я могу иметь дело с линиями разной высоты.

+0

В общем случае ячейки таблицы могут содержать другие потоки, кроме текста, и поэтому вам нужно будет отслеживать высоту ячейки из ее содержимого, возможно, дублируя большую часть работы внутри библиотек ReportLab. Даже при настройке текста нелегко узнать, сколько вертикального пространства займет абзац. – holdenweb

0

Разбить таблицу на несколько страниц необходимо использовать свои собственные шаблоны в соответствии с How to split ReportLab table across PDF page (side by side)?

Таблицы должны нарушать автоматически, когда они достигают конца страницы.Но вот еще один пример, который я нашел:

0

автоматического разделение longtable многократной страницу, как это:

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()