2012-06-17 53 views
7

Estoy creando tablas de PDF con platypus de Reportlab. No lo sé, cuando la página está llena debido al contenido dinámico. ¿Cómo puedo verificar si estoy al final de la página?Salto de página condicional en reportlab

¿Hay algún método en el ornitorrinco para verificar el final de la página?

Tengo una lista de empresas y cada empresa tiene varias unidades de negocios con sus cargos.

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

La lista anterior debe generar 3 mesas cada uno para una empresa, pero si esta lista tiene varias empresas que voluntad genera varias tablas y si cualquier mesa llega al final de la página que se romperá.

 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

puedo obtener ninguna solución? – Asif

+0

Nadie pero verá su comentario a menos que * edite * su pregunta. También vea [faq # bounty] en otras opciones para obtener respuestas. –

Respuesta

4

Debe proporcionar un código de muestra para que sepamos lo que está tratando de lograr. ¿Por qué quieres saber cuándo ha terminado la página? Para dibujar nuevo contenido? Para imprimir alguna información de diagnóstico?

Suponiendo que desea dibujar algo después de que se haya procesado una página, puede usar el método afterPage(), que se proporciona en la clase BaseDocTemplate. De la documentación de ReportLab:

Esto se denomina después del procesamiento de la página e inmediatamente después del método afterDrawPage de la plantilla de página actual. Una clase derivada podría usar esto para hacer cosas que dependen de la información en la página, como la primera y la última palabra en la página de un diccionario.

Básicamente, se llama por BaseDocTemplate después de que se ha dibujado una página. En el código fuente, incluye self, ya que es parte de la clase BaseDocTemplate, por lo que puede acceder a su lienzo.

Puede anular la clase en su propia secuencia de comandos y luego dibujar en el lienzo directamente.

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

Ahora puede utilizar MyDocTemplate la misma manera que utilizaría BaseDocTemplate en su lógica principal:

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

¿Puedo preguntar por qué MyDocTemplate define una extensión nula \ _ \ _ init \ _ \ _ cuando simplemente podría heredar \ _ \ _ init \ _ \ _ de BaseDocTemplate? He visto este patrón un poco, y nunca estoy seguro de lo que se supone que debe lograr. – holdenweb

+0

@holdenweb Honestamente, en este ejemplo no hay ningún propósito. Creo que lo dejé allí porque copié esto de uno de mis propios guiones. Estaba asignando algunos atributos personalizados a la clase infantil, así que tuve que anular '__init__'. Estoy seguro de que podría eliminarse sin ningún mal resultado. – Nitzle

0

Hay que contar las líneas utilizadas mismo. utilizo un procedimiento que incluye:

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

Al conocer el número de líneas utiliza una tabla se puede saber si va a encajar en el resto de la página.

Utilizo el recuento de 'puntos' para poder trabajar con líneas de diferente altura.

+0

En la tabla de casos generales, las celdas pueden contener otros elementos fluibles que el texto, por lo que habría que rastrear el alto de la celda desde su contenido, posiblemente duplicando gran parte del trabajo dentro de las bibliotecas de ReportLab. Incluso cuando se establece texto, no es fácil saber cuánto espacio vertical ocupará un Párrafo. – holdenweb

0

Longtable división automática de varias páginas, así:

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