2012-06-17 19 views
7

Sto creando tabelle PDF con Platypus Reportlab. Non lo so, quando la pagina è piena a causa del contenuto dinamico. Come posso verificare, se sono alla fine della pagina?Interruzione pagina condizionale in reportlab

C'è qualche metodo in ornitorinco per controllare la fine della pagina?

Ho un elenco di società e ogni azienda ha più unità aziendali con le loro tariffe.

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

questo elenco dovrebbe generare 3 tavoli ciascuno per aziende, ma se questa lista ha più società che volontà genera più tabelle e se qualsiasi tavolo raggiunge il termine della pagina, che si 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

posso ottenere alcuna soluzione? – Asif

+0

A meno che non vedrai il tuo commento a meno che tu * modifichi * la tua domanda. Vedi anche [faq # bounty] su altre opzioni per ottenere risposte. –

risposta

4

È necessario fornire un codice di esempio in modo da sapere cosa si sta tentando di realizzare. Perché vuoi sapere quando la pagina è finita? Per disegnare nuovi contenuti? Per stampare alcune informazioni diagnostiche?

Supponendo che si desideri disegnare qualcosa dopo aver eseguito il rendering di una pagina, è possibile utilizzare il metodo afterPage(), fornito nella classe BaseDocTemplate. Dalla documentazione di ReportLab:

Questo viene chiamato dopo l'elaborazione della pagina e immediatamente dopo il metodo afterDrawPage del modello di pagina corrente. Una classe derivata potrebbe usarla per fare cose che dipendono dalle informazioni nella pagina come la prima e l'ultima parola sulla pagina di un dizionario.

Fondamentalmente, è chiamato da BaseDocTemplate dopo che una pagina è stata disegnata. Nel codice sorgente, include self, poiché fa parte della classe BaseDocTemplate, quindi è possibile accedere alla relativa area di disegno!

È possibile sovrascrivere la classe nel proprio script e quindi disegnare direttamente sulla tela.

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

Ora è possibile utilizzare MyDocTemplate allo stesso modo si usa BaseDocTemplate nella vostra logica principale:

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

Posso chiedere perché MyDocTemplate definisce un'estensione null \ _ \ _ init \ _ \ _ quando potrebbe semplicemente ereditare \ _ \ _ init \ _ \ _ da BaseDocTemplate? Ho visto questo schema un bel po ', e non sono mai abbastanza sicuro di cosa dovrebbe raggiungere. – holdenweb

+0

@holdenweb Sinceramente in questo esempio non c'è scopo. Credo di averlo lasciato lì perché l'ho copiato da uno dei miei script. Stavo assegnando alcuni attributi personalizzati alla classe figlia, quindi ho dovuto eseguire l'override di '__init__'. Sono sicuro che potrebbe essere rimosso senza risultati negativi. – Nitzle

0

Devi contare le linee di te utilizzati. Io uso una procedura che comprende:

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

Conoscendo il numero di righe di una tabella utilizza si può sapere se si adatta nel resto della pagina.

Uso il conteggio dei "punti" in modo da poter gestire linee di diversa altezza.

+0

Nel caso generale, le celle di una tabella possono contenere altri Flowable rispetto al testo e quindi sarà necessario tracciare l'altezza della cella dal suo contenuto, possibilmente duplicando gran parte del lavoro all'interno delle librerie ReportLab. Anche quando si imposta il testo non è facile sapere quanto spazio occuperà un paragrafo. – holdenweb

0

automatica longtable spaccata a più pagine, in questo modo:

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