Re: Large table with totals in page footer

Tony Middleton via reportlab-users <[email protected]>
Newsgroups gmane.comp.python.reportlab.user
Message-ID <[email protected]>
I've now got a solution to this - example attached.  Thank you to Robin
Becker for his help.

To recap, I need to create a document which is one big table
approximately 600 pages long.  On the footer of each page I need to
include something derived from the rows printed on that page.  I need to
include page breaks at certain points;  there doesn't seem to be a way
of doing this within a table so my document is a sequence of separate
tables which has made the solution more complicated.

The solution isn't terribly elegant but it seems to work.

Regards

Tony Middleton

On 29/03/17 14:41, Tony Middleton via reportlab-users wrote:
>
> I am trying to create a document with a multipage table.  At the
> bottom of each page I need a footer which includes some information
> derived from rows printed on that page.  I am using the Table() class
> and rows are variable height so I don't know which rows will print on
> a page.
>
> I've looked around and can't find any way to do this.  Any pointers
> would be greatly appreciated.
>
> Regards
>
> Tony Middleton
>
>
>
> _______________________________________________
> reportlab-users mailing list
> [email protected]
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users
example.py (text/x-python, 4.5 KB)
from reportlab.lib.pagesizes import A4,landscape
from reportlab.lib.units import mm
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, PageBreak

###################################################################
###################################################################

class TableDocTemplate(SimpleDocTemplate):

    def afterPage(self):

###############
#
#  Amend this as required to create your page footer
#
###############

        page = self.page 
        data = self.TBconnect.get().getdata()
        pagesum = sum([x[1] for x in data[1:]])

        canvas = self.canv
        canvas.saveState()
        canvas.drawString(65, 65, "Page %s - value %s" % (page,pagesum))
        canvas.restoreState()

    def Docinit(self,connector):
        self.TBconnect=connector


class TBTable(Table):

    def onSplit(self,T,byRow=1):
        '''
        This method will be called when the Table is split.
        Called twice. First with Table() to fit on page then with Table() containing remaining data.
        '''
        T.TBconnect = self.TBconnect
        T.TBid      = self.TBid
        T.TBconnect.put(T)

    def TBinit(self,connector):
        self.TBconnect = connector
        self.TBid = connector.addtable(self)

    def getdata(self):
        return self._cellvalues

    def getid(self):
        return self.TBid

class TBConnect:

    def __init__(self):
        self.tables = []
        self.currtable = 0
        self.splitstatus = 0
        self.first = None
        self.second = None

    def addtable(self,table):
        self.tables.append(table)
        return len(self.tables)

    def put(self,table):
        if self.splitstatus == 0:
###############
#
#  First of pair of onSplit calls when TBTable() can't fit on page - first split of TBTable().
#
###############
            self.currtable += 1
            if self.currtable != table.getid():
               raise Exception("Unexpected table : Expected %s, received %s" % (self.currtable, table.getid()))
            self.first = table
            self.second = None
            self.splitstatus = 1
        elif self.splitstatus == 1:
###############
#
#  Second of pair of onSplit calls when TBTable() can't fit on page.
#
###############
            if self.currtable != table.getid():
               raise Exception("Unexpected table : Expected %s, received %s" % (self.currtable, table.getid()))
            self.second = table
            self.splitstatus = 2
        elif self.splitstatus == 3:
###############
#
#  First of pair of onSplit calls when remainder of TBTable() can't fit on page.
#
###############
            if self.currtable != table.getid():
               raise Exception("Unexpected table : Expected %s, received %s" % (self.currtable, table.getid()))
            self.first = table
            self.second = None
            self.splitstatus = 1
        else:
            raise Exception("TBConnect put when split status = %s" % self.splitstatus)

    def get(self):
        if self.splitstatus == 0:
###############
#  
#  Table isn't being split so return whole original data table.
#
###############
            self.currtable += 1
            if self.currtable > len(self.tables):
                raise Exception("TBConnect No data left")
            return self.tables[self.currtable - 1]
        elif self.splitstatus == 2:
###############
#
#  Table split - return first table to fit on page.
#
###############
            self.splitstatus = 3
            return self.first
        elif self.splitstatus == 3:
###############
#
#  Table split - return last part of table to fit on page.
#
###############
            self.splitstatus = 0
            return self.second
        else:
            raise Exception("TBConnect get when split status = %s" % self.splitstatus)

###################################################################
###################################################################


def printtables(datalist,widths):

###############
#
#  datalist is a list of tuples (table data, table style data)
#
###############

    connector = TBConnect()

    elements = []

    for data, style in datalist:

        t = TBTable(data,colWidths=widths,repeatRows=1)
        t.setStyle(TableStyle(style))
        t.TBinit(connector)

        if elements:
            elements.append(PageBreak())
        elements.append(t)

    doc = TableDocTemplate("filename.pdf" ,pagesize=landscape(A4),
               topMargin=15*mm, bottomMargin=10*mm, leftMargin=12*mm,rightMargin=12*mm)

    doc.Docinit(connector)

    doc.build(elements)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.