[reportlab-users] RE: Page Totals

Henning von Bargen reportlab-users@reportlab.com
Thu, 26 Aug 2004 09:00:28 +0200


> From: CLIFFORD ILKAY <clifford_ilkay@dinamis.com>
> Subject: Re: [reportlab-users] RE: Page Totals
> Reply-To: reportlab-users@reportlab.com
> 
> Hello Henning,
> 
> At 08:52 AM 25/08/2004 +0200, Henning von Bargen wrote:
> >What do you mean with "Page Totals"?
> 
> I mean totals for a given column in a table for the page, as opposed to
the=
> =20
> whole report. e.g. if you have a report where you have subtotals on
each=20
> page for some column, I refer to that, as do many of the report
generators=
> =20
> that I have seen, as a page total.
> 
> In this particular case, I have a column in a table that is displayed
on=20
> each page called "Amount Due". I want a subtotal at the bottom of each
page=
> =20
> for that column and a grand total at the end of the report. I guess
this=20
> would be done with afterPage(), as per your example below. So mine
would=20
> look something like:
> 
> def afterPage(self):
>          subtotal =3D subtotal + amountDue
> 
> I am not sure how subtotal actually gets placed on the page footer though.
> 
> Similarly, I want a variable called expiryDate, which can change many
times=
> =20
> during the report, placed on the page header on every page. I think this
is=
> =20
> what I have to do:
> 
> def beforePage(self, xpiry):
>          expiryDate =3D xpiry
> 
> Again, I am not sure how beforePage is going to be invoked so that I
can=20
> pass expiryDate to it from my main method and I am not sure how
expiryDate=
> =20
> is going to appear on the page header.

Please take a look at my example again.
You can use the templates as follows
(I think the same idea can be used for your particular problem, too).

# A shortened example!

from reportlab.platypus import Spacer, Table, TableStyle, PageBreak
from reportlab.lib.units import inch,cm,mm
from reportlab.lib import colors
from reportlab.lib import pagesizes
from reportlab.lib import enums
from reportlab.lib.styles import getSampleStyleSheet

import sys
import os
import copy
import xml.sax.saxutils

import vorlage   # this is the example from my last posting (see below)

stylesheet=getSampleStyleSheet()

def layoutFunc (data, outPDF, imagePath=""):

     pagesize = pagesizes.portrait(pagesizes.A4)

     # Create document based on our template
     vorlage.imagePath = os.path.join (imagePath, "../html/images")
     doc = vorlage.StandardDocTemplate (outPDF, pagesize=pagesize,
allowSplitting=1)
     doc.title = "This is my title"
     story = []

     # now create the story
     story.append(...)
     story.append(...)

     # build the PDF document
     # plain "build" is not enough, because the page count would not be
correct
     doc.multiBuild(story)

if __name__ == "__main__":
    layoutFunc (data, "out.pdf", ".")

-----
Henning

> 
> >I can give you an example how to
> >output "Page X of Y" on each page.
> 
> Thank you.
> 
> >You'll have to create your subclasses of PageTemplate and
BaseDocTemplate,
> >then use doc.multibuild() with 2 passes to
> >count the total number of pages first,
> >then build once again, this time with the correct number of pages.
> >
> >There may be other ways to achieve this, but this works.
> >
> >It's a pity that one cannot use Platypus in the page headers/footers,
> >it would certainly simplify the task.
> 
> Yes, that would help.
> 
> >HTH
> >Henning
> >
> >#!/bin/env python
> ># -*- coding: iso-8859-1 -*-
> >#
> >#Copyright Triestram&Partner GmbH 2003
> >#
> ># @AUTHOR Henning von Bargen
> >#
> ># @SINCE  13.10.2003
> >#
> ># @VERSION 0.1  $$ Revision                     $$
> >#
> >
> >__version__=3D''' $$ Revision                     $$ '''
> >
> >__doc__=3D"""Vorlage f=FCr Tabellarische Berichte.
> >
> >Die hier definierten Klassen definieren das grunds=E4tzliche Layout
> >der Berichte (z.B. Kopf- und Fusszeilen).
> >"""
> >
> >from reportlab.platypus import PageTemplate, BaseDocTemplate, Frame,
> >Paragraph
> >from reportlab.platypus import Spacer, SimpleDocTemplate, TableStyle
> >
> >from reportlab.lib.units import inch,cm,mm
> >from reportlab.lib import colors
> >from reportlab.lib import pagesizes
> >from reportlab.lib.styles import getSampleStyleSheet
> >
> >import os.path
> >
> >imagePath=3D"../images"
> >
> >class EinspaltigTemplate(PageTemplate):
> >     def __init__(self, id, pageSize):
> >         self.numPages =3D 0
> >         self.pageWidth =3D pageSize[0]
> >         self.pageHeight =3D pageSize[1]
> >
> >         # Seitenrand links/rechts 2cm, oben 2cm, unten 1.5cm,
> >         frame1 =3D Frame(20*mm,
> >                        15*mm,
> >                        self.pageWidth - 40*mm,
> >                        self.pageHeight - 35*mm, id=3D'normal')
> >         PageTemplate.__init__(self, id, [frame1])  # note lack of onPage
> >
> >     def afterDrawPage(self, canvas, doc):
> >         # Titel und Seitenzahl in der Kopfzeile ausgeben
> >         y =3D self.pageHeight - 15*mm
> >         canvas.saveState()
> >         canvas.drawImage(os.path.join(imagePath,'mylogo.jpg'),20*mm,
> >self.pageHeight-14*mm)
> >         canvas.setFont('Helvetica', 12)
> >         canvas.drawString(60*mm, y+8, "My document title")
> >         canvas.line(20*mm, y, self.pageWidth - 20*mm, y)
> >         canvas.setFont('Helvetica', 8)
> >         canvas.drawRightString(self.pageWidth - 20*mm, y+8, "Page
%(page)d
> >of %(numpages)d" % { "page":canvas.getPageNumber(),
> >"numpages":doc.numPages})
> >         canvas.restoreState()
> >
> >class StandardDocTemplate(BaseDocTemplate):
> >     """Hier wird das Standardlayout definiert.
> >
> >        Bemerkenswert bei diesem DocTemplate ist, dass die
Gesamtseitenzahl
> >berechnet wird
> >        und in der Kopzeile ausgegeben werden kann.
> >
> >        Sauberer w=E4re es eigentlich, ein IndexingFlowable zu verwenden,
> >        dass als allerletztes Element hinzugef=FCgt wird.
> >     """
> >
> >     def progresshandler(self, what, arg):
> >         if what in ["PASS", "PAGE"]:
> >             print what, arg
> >         #print "numPages=3D%d" % self.numPages
> >         if what=3D=3D'STARTED':
> >             self._lastnumPages =3D self.numPages
> >
> >     def afterInit(self):
> >         # Standard: ohne Deckblatt
> >         self.addPageTemplates(EinspaltigTemplate('Einspaltig',
> >self.pagesize))
> >
> >         #just playing
> >         self.numPages =3D 1
> >         self._lastnumPages =3D 0
> >         self.setProgressCallBack(self.progresshandler)
> >
> >     def afterPage(self):
> >         """This is called after page processing, and
> >         immediately after the afterDrawPage method
> >         of the current page template."""
> >         self.numPages =3D max(self.canv.getPageNumber(), self.numPages)
> >
> >     def _allSatisfied(self):
> >         """Eine unsaubere Implementierung, aber bevor wir jetzt
anfangen=
>  mit
> >Cross-Referenzen etc.
> >            machen wir es lieber so.
> >            Called by multi-build - are all cross-references resolved?
> >         """
> >         if self._lastnumPages < self.numPages:
> >             return 0
> >         return BaseDocTemplate._allSatisfied(self)
> 
> Regards,
> 
> Clifford Ilkay
> Dinamis Corporation
> 3266 Yonge Street, Suite 1419
> Toronto, Ontario
> Canada M4N 3P6
> 
> Tel: 416-410-3326=20
> 
>