[reportlab-users] RE: Page Totals

Andy Robinson reportlab-users@reportlab.com
Wed, 25 Aug 2004 22:51:05 -0700


Clifford,

You're right, we do need an example.  I am asking a colleague to try 
and work something out in the next few days.

You've highlighted something we can't do very neatly in Platypus  :-(  
Doing this right in tables generally involves some kind of look-ahead 
where you can say "I am now 1 inch from the bottom of the frame, output 
a totals row", but still have the totals row butt together exactly with 
the main table.  It can be done with careful control of table size and 
location and by faking a bottom row in the afterPage event, but ideally 
a smarter 'nested table' object would be able to o this as Crystal 
Reports does.

A really easy workaround is to compute a running total column in your 
data set before laying things out.  E.g if I was doing a bank statement 
and had a database query returning lists of [date, comment, amount] 
tuples, I would compute and add a fourth column

Andy Robinson
CEO/Chief Architect
RepoortLab Europe Ltd.
tel +44 20 8544 8049

-----Original Message-----
From: CLIFFORD ILKAY <clifford_ilkay@dinamis.com>
To: reportlab-users@reportlab.com
Sent: Wed, 25 Aug 2004 07:15:13 -0400
Subject: Re: [reportlab-users] RE: Page Totals

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 whole report. e.g. if you have a report where you have subtotals on 
each page for some column, I refer to that, as do many of the report 
generators that I have seen, as a page total.

In this particular case, I have a column in a table that is displayed 
on each page called "Amount Due". I want a subtotal at the bottom of 
each page for that column and a grand total at the end of the report. I 
guess this would be done with afterPage(), as per your example below. 
So mine would look something like:

def afterPage(self):
  subtotal = 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 during the report, placed on the page header on every page. I 
think this is what I have to do:

def beforePage(self, xpiry):
  expiryDate = xpiry

Again, I am not sure how beforePage is going to be invoked so that I 
can pass expiryDate to it from my main method and I am not sure how 
expiryDate is going to appear on the page header.

>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__=''' $$ Revision $$ '''
>
>__doc__="""Vorlage für Tabellarische Berichte.
>
>Die hier definierten Klassen definieren das grundsätzliche 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="../images"
>
>class EinspaltigTemplate(PageTemplate):
> def __init__(self, id, pageSize):
> self.numPages = 0
> self.pageWidth = pageSize[0]
> self.pageHeight = pageSize[1]
>
> # Seitenrand links/rechts 2cm, oben 2cm, unten 1.5cm,
> frame1 = Frame(20*mm,
> 15*mm,
> self.pageWidth - 40*mm,
> self.pageHeight - 35*mm, id='normal')
> PageTemplate.__init__(self, id, [frame1]) # note lack of onPage
>
> def afterDrawPage(self, canvas, doc):
> # Titel und Seitenzahl in der Kopfzeile ausgeben
> y = 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äre es eigentlich, ein IndexingFlowable zu verwenden,
> dass als allerletztes Element hinzugefügt wird.
> """
>
> def progresshandler(self, what, arg):
> if what in ["PASS", "PAGE"]:
> print what, arg
> #print "numPages=%d" % self.numPages
> if what=='STARTED':
> self._lastnumPages = self.numPages
>
> def afterInit(self):
> # Standard: ohne Deckblatt
> self.addPageTemplates(EinspaltigTemplate('Einspaltig',
>self.pagesize))
>
> #just playing
> self.numPages = 1
> self._lastnumPages = 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 = 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
_______________________________________________
reportlab-users mailing list
reportlab-users@reportlab.com
http://two.pairlist.net/mailman/listinfo/reportlab-users