Ejemplo n.º 1
0
    def __init__(self, data, colWidths=None, rowHeights=None, style=None,
                repeatRows=0, repeatCols=0, splitByRow=1, emptyTableAction=None, ident=None,
                hAlign=None,vAlign=None, normalizedData=0, cellStyles=None):

        row_heights = self.get_row_heights()
        table_style = self.get_table_style()
        LongTable.__init__(self, data, [reduce(lambda x, y: x + y, ValuationTable.column_widths)], row_heights,
                           style=table_style, repeatRows=1, ident='valtable')
Ejemplo n.º 2
0
 def AddStoryElement(self, element):
     if element.tag == "para":
         styleName = element.get("style", "default")
         style = self.paragraphStyles[styleName]
         element.attrib.clear()
         text = cElementTree.tostring(element)
         rotated = self._ConvertNumber(element, "rotate", 0)
         cls = RotatedParagraph if rotated else Paragraph
         para = cls(text, style)
         self.story.append(para)
     elif element.tag == "nextPage":
         self.story.append(PageBreak())
     elif element.tag == "nextFrame":
         self.story.append(FrameBreak())
     elif element.tag == "spacer":
         length = self._ConvertNumber(element, "length", 0)
         self.story.append(Spacer(length, length))
     elif element.tag == "setNextTemplate":
         name = element.attrib["name"]
         self.story.append(NextPageTemplate(name))
     elif element.tag == "blockTable":
         styleName = element.get("style", "default")
         style = self.tableStyles[styleName]
         if self.tableCommands:
             style = TableStyle(self.tableCommands, style)
         repeatRows = self._ConvertNumber(element, "repeatRows", 0)
         hAlign = element.get("hAlign", "CENTER")
         vAlign = element.get("vAlign", "MIDDLE")
         columnWidths = self._ConvertNumberList(element, "colWidths", [])
         pageRows = self._ConvertNumber(element, "pageRows")
         if not pageRows:
             self.story.append(
                 LongTable(self.tableRows,
                           columnWidths,
                           self.tableRowHeights,
                           style=style,
                           hAlign=hAlign,
                           vAlign=vAlign,
                           repeatRows=repeatRows))
         else:
             headerRows = self.tableRows[:repeatRows]
             headerRowHeights = self.tableRowHeights[:repeatRows]
             rows = self.tableRows[repeatRows:]
             rowHeights = self.tableRowHeights[repeatRows:]
             while rows:
                 table = LongTable(headerRows + rows[:pageRows],
                                   columnWidths,
                                   headerRowHeights + rowHeights[:pageRows],
                                   style=style,
                                   hAlign=hAlign,
                                   vAlign=vAlign)
                 self.story.append(table)
                 rows = rows[pageRows:]
                 rowHeights = rowHeights[pageRows:]
Ejemplo n.º 3
0
 def add_table(self, rows, width=None, col_widths=None, align=CENTER,
               extra_style=[]):
     style = self.theme.table_style + extra_style
     if width and col_widths is None:  # one cannot spec table width in rLab only col widths
         col_widths = calc_table_col_widths(rows, width)  # this helper calcs it for us
     table = LongTable(rows, col_widths, style=style, hAlign=align)
     self.add(table)
Ejemplo n.º 4
0
 def add_table(self, rows, percentage_col_widths, align=CENTER, extra_style=[]):
     real_column_width = []
     for w in percentage_col_widths:
         real_column_width.append((self.content_width() * w)/100)
     style = self.theme.table_style + extra_style
     table = LongTable(rows, real_column_width, style=style, hAlign=align, repeatRows=1)
     self.add(table)
Ejemplo n.º 5
0
    def test(self):
        outPDF = "test_autocolwidths.pdf"

        # Column widths in mm
        colWidths = None

        # Some test data in German.
        testdata = \
        [u"<para>Mit <i>Silbentrennungsverfahren</i> werden extrem lange W\xF6rter, die im deutschen Sprachgebrauch allt\xE4glich sind, automatisch in kleinere Bestandteile zerlegt, wobei die Lesbarkeit nach M\xF6glichkeit erhalten bleiben sollte.</para>",
         u"<para>Dieser Absatz hat nur sehr kurze Wörter.</para>",
         u"<para>Der hier erst recht!</para>",
         u"<para>Der Bundeskanzler arbeitet im <font size='12'>Bundeskanzler</font>amt.</para>",
        ]

        pagesize = pagesizes.portrait(pagesizes.A4)

        tablestyle = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'TOP'),
            ('BOX', (0, 0), (-1, -1), 1, colors.black),
            ('BACKGROUND', (0, 0), (-1, 0), colors.orange),
            ('INNERGRID', (0, 1), (-1, -1), 0.5, colors.black),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])

        doc = SimpleDocTemplate(outPDF,
                                title="Hyphenation for styled text paragraphs",
                                pagesize=pagesize,
                                allowSplitting=1)
        story = []

        header = ["Col%d" % (i + 1) for i in range(4)]
        tabContent = [header]
        row = [makeParagraphs(txt, cellStyle) for txt in testdata]
        tabContent.append(row)
        row = [
            makeParagraphs((u"Zeile 2 Spalte %i" % (i + 1)), cellStyle)
            for i in range(4)
        ]
        tabContent.append(row)
        table = LongTable(tabContent,
                          colWidths=colWidths,
                          style=tablestyle,
                          repeatRows=1)
        story.append(table)
        doc.build(story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
Ejemplo n.º 6
0
def doLayout(title, data, colWidths, outPDF):
    """Create a tabular PDF file from the given data.
    """
    pagesize = pagesizes.portrait(pagesizes.A4)

    tablestyle = TableStyle([
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('BOX', (0, 0), (-1, -1), 1, colors.black),
        ('BACKGROUND', (0, 0), (-1, 0), colors.orange),
        ('INNERGRID', (0, 1), (-1, -1), 0.5, colors.black),
        ('LEFTPADDING', (0, 0), (-1, -1), 3),
        ('RIGHTPADDING', (0, 0), (-1, -1), 3),
    ])

    doc = SimpleDocTemplate(outPDF,
                            title=title,
                            pagesize=pagesize,
                            allowSplitting=1)
    story = []

    header = ["%d mm" % w for w in colWidths]
    colWidths = [w * mm for w in colWidths]
    if sum(colWidths) > pagesize[0]:
        raise ValueError("Overall column width too wide!")

    tabContent = [header]
    for txt in data:
        row = []
        # Note: we have to create copies by calling makeParagraphs for each cell.
        # We cannot just create one Paragraph and reference it several times.
        for col in colWidths:
            row.append(makeParagraphs(txt, cellStyle))
        tabContent.append(row)
    table = LongTable(tabContent,
                      colWidths=colWidths,
                      style=tablestyle,
                      repeatRows=1)
    story.append(table)
    doc.build(story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
Ejemplo n.º 7
0
    def build_pdf(self, response):

        cleaned_data = self.filterset.form.cleaned_data

        agrupamento = cleaned_data['agrupamento']

        elements = []

        #print('data ini', datetime.now())
        data = self.get_data()
        #print('data fim', datetime.now())

        style = TableStyle([
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('LEADING', (0, 0), (-1, -1), 7),
            ('GRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])
        style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE')

        #print('enumerate ini', datetime.now())
        for i, value in enumerate(data):
            if len(value) <= 1:
                style.add('SPAN', (0, i), (-1, i))

            if len(value) == 0:
                style.add('INNERGRID', (0, i), (-1, i), 0, colors.black),
                style.add('GRID', (0, i), (-1, i), -1, colors.white)
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

            if len(value) == 1:
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

        #print('enumerate fim', datetime.now())
        # if not agrupamento or agrupamento == 'sem_agrupamento':
        #    style.add('ALIGN', (0, 0), (0, -1), 'CENTER')

        #print('table ini', datetime.now())
        rowHeights = 20
        t = LongTable(data, rowHeights=rowHeights, splitByRow=True)
        t.setStyle(style)
        if len(t._argW) == 5:
            t._argW[0] = 1.8 * cm
            t._argW[1] = 6 * cm
            t._argW[2] = 6.5 * cm
            t._argW[3] = 9.5 * cm
            t._argW[4] = 2.4 * cm
        elif len(t._argW) == 4:
            t._argW[0] = 2 * cm
            t._argW[1] = 10 * cm
            t._argW[2] = 11.5 * cm
            t._argW[3] = 3 * cm

        for i, value in enumerate(data):
            if len(value) == 0:
                t._argH[i] = 7
                continue
            for cell in value:
                if isinstance(cell, list):
                    t._argH[i] = (rowHeights) * (
                        len(cell) - (0 if len(cell) > 1 else 0))
                    break

        elements.append(t)
        #print('table fim', datetime.now())

        #print('build ini', datetime.now())
        doc = SimpleDocTemplate(
            response,
            pagesize=landscape(A4),
            rightMargin=1.25 * cm,
            leftMargin=1.25 * cm,
            topMargin=1.1 * cm,
            bottomMargin=0.8 * cm)
        doc.build(elements)
Ejemplo n.º 8
0
    def build_pdf(self, response):

        cleaned_data = self.filterset.form.cleaned_data

        agrupamento = cleaned_data['agrupamento']

        elements = []

        #print('data ini', datetime.now())
        data = self.get_data()
        #print('data fim', datetime.now())

        style = TableStyle([
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('LEADING', (0, 0), (-1, -1), 7),
            ('GRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])
        style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE')

        #print('enumerate ini', datetime.now())
        for i, value in enumerate(data):
            if len(value) <= 1:
                style.add('SPAN', (0, i), (-1, i))

            if len(value) == 0:
                style.add('INNERGRID', (0, i), (-1, i), 0, colors.black),
                style.add('GRID', (0, i), (-1, i), -1, colors.white)
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

            if len(value) == 1:
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

        #print('enumerate fim', datetime.now())
        # if not agrupamento or agrupamento == 'sem_agrupamento':
        #    style.add('ALIGN', (0, 0), (0, -1), 'CENTER')

        #print('table ini', datetime.now())
        rowHeights = 20
        t = LongTable(data, rowHeights=rowHeights, splitByRow=True)
        t.setStyle(style)
        if len(t._argW) == 5:
            t._argW[0] = 1.8 * cm
            t._argW[1] = 6 * cm
            t._argW[2] = 6.5 * cm
            t._argW[3] = 9.5 * cm
            t._argW[4] = 2.4 * cm
        elif len(t._argW) == 4:
            t._argW[0] = 2 * cm
            t._argW[1] = 10 * cm
            t._argW[2] = 11.5 * cm
            t._argW[3] = 3 * cm

        for i, value in enumerate(data):
            if len(value) == 0:
                t._argH[i] = 7
                continue
            for cell in value:
                if isinstance(cell, list):
                    t._argH[i] = (rowHeights) * (len(cell) -
                                                 (0 if len(cell) > 1 else 0))
                    break

        elements.append(t)
        #print('table fim', datetime.now())

        #print('build ini', datetime.now())
        doc = SimpleDocTemplate(response,
                                pagesize=landscape(A4),
                                rightMargin=1.25 * cm,
                                leftMargin=1.25 * cm,
                                topMargin=1.1 * cm,
                                bottomMargin=0.8 * cm)
        doc.build(elements)
Ejemplo n.º 9
0
def old_tables_test():
    from reportlab.lib.units import inch, cm
    from reportlab.platypus.flowables import Image, PageBreak, Spacer, XBox
    from reportlab.platypus.paragraph import Paragraph
    from reportlab.platypus.xpreformatted import XPreformatted
    from reportlab.platypus.flowables import Preformatted
    from reportlab.platypus.doctemplate import SimpleDocTemplate
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.platypus.tables import GRID_STYLE, BOX_STYLE, LABELED_GRID_STYLE, COLORED_GRID_STYLE, LIST_STYLE, LongTable
    rowheights = (24, 16, 16, 16, 16)
    rowheights2 = (24, 16, 16, 16, 30)
    colwidths = (50, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32)
    data = (
        ('', 'Jan', 'Feb', 'Mar','Apr','May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
        ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89),
        ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119),
        ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13),
        ('Hats', 893, 912, '1,212', 643, 789, 159, 888, '1,298', 832, 453, '1,344','2,843')
        )
    data2 = (
        ('', 'Jan', 'Feb', 'Mar','Apr','May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
        ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89),
        ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119),
        ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13),
        ('Hats\nLarge', 893, 912, '1,212', 643, 789, 159, 888, '1,298', 832, 453, '1,344','2,843')
        )
    lst = []
    lst.append(Paragraph("Tables", styleSheet['Heading1']))
    lst.append(Paragraph(__doc__, styleSheet['BodyText']))
    lst.append(Paragraph("The Tables (shown in different styles below) were created using the following code:", styleSheet['BodyText']))
    lst.append(Preformatted("""
    colwidths = (50, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32)
    rowheights = (24, 16, 16, 16, 16)
    data = (
        ('', 'Jan', 'Feb', 'Mar','Apr','May', 'Jun',
           'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
        ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89),
        ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119),
        ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13),
        ('Hats', 893, 912, '1,212', 643, 789, 159,
             888, '1,298', 832, 453, '1,344','2,843')
        )
    t = Table(data, colwidths, rowheights)
    """, styleSheet['Code'], dedent=4))
    lst.append(Paragraph("""
    You can then give the Table a TableStyle object to control its format. The first TableStyle used was
    created as follows:
    """, styleSheet['BodyText']))
    lst.append(Preformatted("""
GRID_STYLE = TableStyle(
    [('GRID', (0,0), (-1,-1), 0.25, colors.black),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT')]
    )
    """, styleSheet['Code']))
    lst.append(Paragraph("""
    TableStyles are created by passing in a list of commands. There are two types of commands - line commands
    and cell formatting commands. In all cases, the first three elements of a command are the command name,
    the starting cell and the ending cell.
    """, styleSheet['BodyText']))
    lst.append(Paragraph("""
    Line commands always follow this with the weight and color of the desired lines. Colors can be names,
    or they can be specified as a (R,G,B) tuple, where R, G and B are floats and (0,0,0) is black. The line
    command names are: GRID, BOX, OUTLINE, INNERGRID, LINEBELOW, LINEABOVE, LINEBEFORE
    and LINEAFTER. BOX and OUTLINE are equivalent, and GRID is the equivalent of applying both BOX and
    INNERGRID.
    """, styleSheet['BodyText']))
    lst.append(Paragraph("""
    Cell formatting commands are:
    """, styleSheet['BodyText']))
    lst.append(Paragraph("""
    FONT - takes fontname, fontsize and (optional) leading.
    """, styleSheet['Definition']))
    lst.append(Paragraph("""
    TEXTCOLOR - takes a color name or (R,G,B) tuple.
    """, styleSheet['Definition']))
    lst.append(Paragraph("""
    ALIGNMENT (or ALIGN) - takes one of LEFT, RIGHT, CENTRE (or CENTER) or DECIMAL.
    """, styleSheet['Definition']))
    lst.append(Paragraph("""
    LEFTPADDING - defaults to 6.
    """, styleSheet['Definition']))
    lst.append(Paragraph("""
    RIGHTPADDING - defaults to 6.
    """, styleSheet['Definition']))
    lst.append(Paragraph("""
    BOTTOMPADDING - defaults to 3.
    """, styleSheet['Definition']))
    lst.append(Paragraph("""
    A tablestyle is applied to a table by calling Table.setStyle(tablestyle).
    """, styleSheet['BodyText']))
    t = Table(data, colwidths, rowheights)
    t.setStyle(GRID_STYLE)
    lst.append(PageBreak())
    lst.append(Paragraph("This is GRID_STYLE\n", styleSheet['BodyText']))
    lst.append(t)

    t = Table(data, colwidths, rowheights)
    t.setStyle(BOX_STYLE)
    lst.append(Paragraph("This is BOX_STYLE\n", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Paragraph("""
    It was created as follows:
    """, styleSheet['BodyText']))
    lst.append(Preformatted("""
BOX_STYLE = TableStyle(
    [('BOX', (0,0), (-1,-1), 0.50, colors.black),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT')]
    )
    """, styleSheet['Code']))

    t = Table(data, colwidths, rowheights)
    t.setStyle(LABELED_GRID_STYLE)
    lst.append(Paragraph("This is LABELED_GRID_STYLE\n", styleSheet['BodyText']))
    lst.append(t)
    t = Table(data2, colwidths, rowheights2)
    t.setStyle(LABELED_GRID_STYLE)
    lst.append(Paragraph("This is LABELED_GRID_STYLE ILLUSTRATES EXPLICIT LINE SPLITTING WITH NEWLINE (different heights and data)\n", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Paragraph("""
    It was created as follows:
    """, styleSheet['BodyText']))
    lst.append(Preformatted("""
LABELED_GRID_STYLE = TableStyle(
    [('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
     ('BOX', (0,0), (-1,-1), 2, colors.black),
     ('LINEBELOW', (0,0), (-1,0), 2, colors.black),
     ('LINEAFTER', (0,0), (0,-1), 2, colors.black),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT')]
    )
    """, styleSheet['Code']))
    lst.append(PageBreak())

    t = Table(data, colwidths, rowheights)
    t.setStyle(COLORED_GRID_STYLE)
    lst.append(Paragraph("This is COLORED_GRID_STYLE\n", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Paragraph("""
    It was created as follows:
    """, styleSheet['BodyText']))
    lst.append(Preformatted("""
COLORED_GRID_STYLE = TableStyle(
    [('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
     ('BOX', (0,0), (-1,-1), 2, colors.red),
     ('LINEBELOW', (0,0), (-1,0), 2, colors.black),
     ('LINEAFTER', (0,0), (0,-1), 2, colors.black),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT')]
    )
    """, styleSheet['Code']))

    t = Table(data, colwidths, rowheights)
    t.setStyle(LIST_STYLE)
    lst.append(Paragraph("This is LIST_STYLE\n", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Paragraph("""
    It was created as follows:
    """, styleSheet['BodyText']))
    lst.append(Preformatted("""
LIST_STYLE = TableStyle(
    [('LINEABOVE', (0,0), (-1,0), 2, colors.green),
     ('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black),
     ('LINEBELOW', (0,-1), (-1,-1), 2, colors.green),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT')]
    )
    """, styleSheet['Code']))

    t = Table(data, colwidths, rowheights)
    ts = TableStyle(
    [('LINEABOVE', (0,0), (-1,0), 2, colors.green),
     ('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black),
     ('LINEBELOW', (0,-1), (-1,-1), 3, colors.green,'butt'),
     ('LINEBELOW', (0,-1), (-1,-1), 1, colors.white,'butt'),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT'),
     ('TEXTCOLOR', (0,1), (0,-1), colors.red),
     ('BACKGROUND', (0,0), (-1,0), colors.Color(0,0.7,0.7))]
    )
    t.setStyle(ts)
    lst.append(Paragraph("This is a custom style\n", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Paragraph("""
    It was created as follows:
    """, styleSheet['BodyText']))
    lst.append(Preformatted("""
   ts = TableStyle(
    [('LINEABOVE', (0,0), (-1,0), 2, colors.green),
     ('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black),
     ('LINEBELOW', (0,-1), (-1,-1), 3, colors.green,'butt'),
     ('LINEBELOW', (0,-1), (-1,-1), 1, colors.white,'butt'),
     ('ALIGN', (1,1), (-1,-1), 'RIGHT'),
     ('TEXTCOLOR', (0,1), (0,-1), colors.red),
     ('BACKGROUND', (0,0), (-1,0), colors.Color(0,0.7,0.7))]
    )
    """, styleSheet['Code']))
    data = (
        ('', 'Jan\nCold', 'Feb\n', 'Mar\n','Apr\n','May\n', 'Jun\nHot', 'Jul\n', 'Aug\nThunder', 'Sep\n', 'Oct\n', 'Nov\n', 'Dec\n'),
        ('Mugs', 0, 4, 17, 3, 21, 47, 12, 33, 2, -2, 44, 89),
        ('T-Shirts', 0, 42, 9, -3, 16, 4, 72, 89, 3, 19, 32, 119),
        ('Key Ring', 0,0,0,0,0,0,1,0,0,0,2,13),
        ('Hats', 893, 912, '1,212', 643, 789, 159, 888, '1,298', 832, 453, '1,344','2,843')
        )
    c = list(colwidths)
    c[0] = None
    c[8] = None
    t = Table(data, c, [None]+list(rowheights[1:]))
    t.setStyle(LIST_STYLE)
    lst.append(Paragraph("""
        This is a LIST_STYLE table with the first rowheight set to None ie automatic.
        The top row cells are split at a newline '\\n' character. The first and August
        column widths were also set to None.
    """, styleSheet['BodyText']))
    lst.append(t)

    lst.append(Paragraph("""
        This demonstrates a number of features useful in financial statements. The first is decimal alignment;
        with ALIGN=DECIMAL the numbers align on the points; and the points are aligned based on
        the RIGHTPADDING, which is usually 3 points so you should set it higher.  The second is multiple lines;
        one can specify double or triple lines and control the separation if desired. Finally, the coloured
        negative numbers were (we regret to say) done in the style; we don't have a way to conditionally
        format numbers based on value yet.
    """, styleSheet['BodyText']))


    t = Table([['Corporate Assets','Amount'],
               ['Fixed Assets','1,234,567.89'],
               ['Company Vehicle','1,234.8901'],
               ['Petty Cash','42'],
               [u'Intellectual Property\u00ae','(42,078,231.56)'],
               ['Overdraft','(12,345)'],
               ['Boardroom Flat Screen','60 inches'],
               ['Net Position','Deep Sh*t.Really']
               ],
              [144,72])

    ts = TableStyle(
        [#first the top row
         ('ALIGN', (1,1), (-1,-1), 'CENTER'),
         ('LINEABOVE', (0,0), (-1,0), 1, colors.purple),
         ('LINEBELOW', (0,0), (-1,0), 1, colors.purple),
         ('FONT', (0,0), (-1,0), 'Times-Bold'),

        #bottom row has a line above, and two lines below
         ('LINEABOVE', (0,-1), (-1,-1), 1, colors.purple),  #last 2 are count, sep
         ('LINEBELOW', (0,-1), (-1,-1), 0.5, colors.purple, 1, None, None, 4,1),
         ('LINEBELOW', (0,-1), (-1,-1), 1, colors.red),
         ('FONT', (0,-1), (-1,-1), 'Times-Bold'),

        #numbers column
         ('ALIGN', (1,1), (-1,-1), 'DECIMAL'),
         ('RIGHTPADDING', (1,1), (-1,-1), 36),
         ('TEXTCOLOR', (1,4), (1,4), colors.red),

        #red cell
        ]
        )

    t.setStyle(ts)
    lst.append(t)
    lst.append(Spacer(36,36))
    lst.append(Paragraph("""
        The red numbers should be aligned LEFT &amp; BOTTOM, the blue RIGHT &amp; TOP
        and the green CENTER &amp; MIDDLE.
    """, styleSheet['BodyText']))
    XY  =   [['X00y', 'X01y', 'X02y', 'X03y', 'X04y'],
            ['X10y', 'X11y', 'X12y', 'X13y', 'X14y'],
            ['X20y', 'X21y', 'X22y', 'X23y', 'X24y'],
            ['X30y', 'X31y', 'X32y', 'X33y', 'X34y']]
    t=Table(XY, 5*[0.6*inch], 4*[0.6*inch])
    t.setStyle([('ALIGN',(1,1),(-2,-2),'LEFT'),
                ('TEXTCOLOR',(1,1),(-2,-2),colors.red),

                ('VALIGN',(0,0),(1,-1),'TOP'),
                ('ALIGN',(0,0),(1,-1),'RIGHT'),
                ('TEXTCOLOR',(0,0),(1,-1),colors.blue),

                ('ALIGN',(0,-1),(-1,-1),'CENTER'),
                ('VALIGN',(0,-1),(-1,-1),'MIDDLE'),
                ('TEXTCOLOR',(0,-1),(-1,-1),colors.green),
                ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                ])
    lst.append(t)
    data = [('alignment', 'align\012alignment'),
            ('bulletColor', 'bulletcolor\012bcolor'),
            ('bulletFontName', 'bfont\012bulletfontname'),
            ('bulletFontSize', 'bfontsize\012bulletfontsize'),
            ('bulletIndent', 'bindent\012bulletindent'),
            ('firstLineIndent', 'findent\012firstlineindent'),
            ('fontName', 'face\012fontname\012font'),
            ('fontSize', 'size\012fontsize'),
            ('leading', 'leading'),
            ('leftIndent', 'leftindent\012lindent'),
            ('rightIndent', 'rightindent\012rindent'),
            ('spaceAfter', 'spaceafter\012spacea'),
            ('spaceBefore', 'spacebefore\012spaceb'),
            ('textColor', 'fg\012textcolor\012color')]
    t = Table(data)
    t.setStyle([
            ('VALIGN',(0,0),(-1,-1),'TOP'),
            ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
            ('BOX', (0,0), (-1,-1), 0.25, colors.black),
            ])
    lst.append(t)
    t = Table([ ('Attribute', 'Synonyms'),
                ('alignment', 'align, alignment'),
                ('bulletColor', 'bulletcolor, bcolor'),
                ('bulletFontName', 'bfont, bulletfontname'),
                ('bulletFontSize', 'bfontsize, bulletfontsize'),
                ('bulletIndent', 'bindent, bulletindent'),
                ('firstLineIndent', 'findent, firstlineindent'),
                ('fontName', 'face, fontname, font'),
                ('fontSize', 'size, fontsize'),
                ('leading', 'leading'),
                ('leftIndent', 'leftindent, lindent'),
                ('rightIndent', 'rightindent, rindent'),
                ('spaceAfter', 'spaceafter, spacea'),
                ('spaceBefore', 'spacebefore, spaceb'),
                ('textColor', 'fg, textcolor, color')])
    t.repeatRows = 1
    t.setStyle([
                ('FONT',(0,0),(-1,1),'Times-Bold',10,12),
                ('FONT',(0,1),(-1,-1),'Courier',8,8),
                ('VALIGN',(0,0),(-1,-1),'MIDDLE'),
                ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                ('BACKGROUND', (0, 0), (-1, 0), colors.green),
                ('BACKGROUND', (0, 1), (-1, -1), colors.pink),
                ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
                ('ALIGN', (0, 1), (0, -1), 'LEFT'),
                ('ALIGN', (-1, 1), (-1, -1), 'RIGHT'),
                ('FONT', (0, 0), (-1, 0), 'Times-Bold', 12),
                ('ALIGN', (1, 1), (1, -1), 'CENTER'),
                ])
    lst.append(t)
    lst.append(Table(XY,
            style=[ ('FONT',(0,0),(-1,-1),'Times-Roman', 5,6),
                    ('GRID', (0,0), (-1,-1), 0.25, colors.blue),]))
    lst.append(Table(XY,
            style=[ ('FONT',(0,0),(-1,-1),'Times-Roman', 10,12),
                    ('GRID', (0,0), (-1,-1), 0.25, colors.black),]))
    lst.append(Table(XY,
            style=[ ('FONT',(0,0),(-1,-1),'Times-Roman', 20,24),
                    ('GRID', (0,0), (-1,-1), 0.25, colors.red),]))
    lst.append(PageBreak())
    data=  [['00', '01', '02', '03', '04'],
            ['10', '11', '12', '13', '14'],
            ['20', '21', '22', '23', '24'],
            ['30', '31', '32', '33', '34']]
    t=Table(data,style=[
                    ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                    ('GRID',(1,1),(-2,-2),1,colors.green),
                    ('BOX',(0,0),(1,-1),2,colors.red),
                    ('BOX',(0,0),(-1,-1),2,colors.black),
                    ('LINEABOVE',(1,2),(-2,2),1,colors.blue),
                    ('LINEBEFORE',(2,1),(2,-2),1,colors.pink),
                    ('BACKGROUND', (0, 0), (0, 1), colors.pink),
                    ('BACKGROUND', (1, 1), (1, 2), colors.lavender),
                    ('BACKGROUND', (2, 2), (2, 3), colors.orange),
                    ('TEXTCOLOR',(0,-1),(-2,-1),colors.green),
                    ])
    lst.append(Paragraph("Illustrating splits: nosplit", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits: split(4in,30)", styleSheet['BodyText']))
    for s in t.split(4*inch,30):
        lst.append(s)
        lst.append(Spacer(0,6))
    lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits: split(4in,36)", styleSheet['BodyText']))
    for s in t.split(4*inch,36):
        lst.append(s)
        lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits: split(4in,56)", styleSheet['BodyText']))
    lst.append(Spacer(0,6))
    for s in t.split(4*inch,56):
        lst.append(s)
        lst.append(Spacer(0,6))

    lst.append(Paragraph("Illustrating splits: repeated split(4in,30)", styleSheet['BodyText']))
    lst.append(Spacer(0,6))
    S = t.split(4*inch,30)
    s = S.pop(-1)
    S.extend(s.split(4*inch,30))
    s = S.pop(-1)
    S.extend(s.split(4*inch,30))

    for s in S:
        lst.append(s)
        lst.append(Spacer(0,6))

    lst.append(PageBreak())
    data=  [['00', '01', '02', '03', '04'],
            ['', '11', '12', '13', '14'],
            ['20', '21', '22', '23', '24'],
            ['30', '31', '', '33', '34']]
    sty=[
                    ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                    ('GRID',(1,1),(-2,-2),1,colors.green),
                    ('BOX',(0,0),(1,-1),2,colors.red),
                    ('BOX',(0,0),(-1,-1),2,colors.black),
                    ('LINEABOVE',(1,2),(-2,2),1,colors.blue),
                    ('LINEBEFORE',(2,1),(2,-2),1,colors.pink),
                    ('BACKGROUND', (0, 0), (0, 1), colors.pink),
                    ('SPAN',(0,0),(0,1)),
                    ('BACKGROUND', (2, 2), (2, 3), colors.orange),
                    ('SPAN',(2,2),(2,3)),
                    ]
    t=Table(data,style=sty)
    lst.append(Paragraph("Illustrating splits with spans: nosplit", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits with spans: split(4in,30)", styleSheet['BodyText']))
    for s in t.split(4*inch,30):
        lst.append(s)
        lst.append(Spacer(0,6))
    lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits with spans: split(4in,36)", styleSheet['BodyText']))
    for s in t.split(4*inch,36):
        lst.append(s)
        lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits with spans: split(4in,56)", styleSheet['BodyText']))
    lst.append(Spacer(0,6))
    for s in t.split(4*inch,56):
        lst.append(s)
        lst.append(Spacer(0,6))

    data=  [['00', '01', '02', '03', '04'],
            ['', '11', '12', '13', ''],
            ['20', '21', '22', '23', '24'],
            ['30', '31', '', '33', ''],
            ['40', '41', '', '43', '44']]
    sty=[
        ('GRID',(0,0),(-1,-1),0.5,colors.grey),
        ('GRID',(1,1),(-2,-2),1,colors.green),
        ('BOX',(0,0),(1,-1),2,colors.red),
        ('BOX',(0,0),(-1,-1),2,colors.black),
        ('LINEABOVE',(1,2),(-2,2),1,colors.blue),
        ('LINEBEFORE',(2,1),(2,-2),1,colors.pink),
        ('BACKGROUND', (0, 0), (0, 1), colors.pink),
        ('SPAN',(0,0),(0,1)),
        ('BACKGROUND',(-2,1),(-1,1),colors.palegreen),
        ('SPAN',(-2,1),(-1,1)),
        ('BACKGROUND',(-2,3),(-1,3),colors.yellow),
        ('SPAN',(-2,3),(-1,3)),
        ('BACKGROUND', (2, 3), (2, 4), colors.orange),
        ('SPAN',(2,3),(2,4)),
        ]

    t=Table(data,style=sty,repeatRows=2)
    lst.append(Paragraph("Illustrating splits with spans and repeatRows: nosplit", styleSheet['BodyText']))
    lst.append(t)
    lst.append(Spacer(0,6))
    if  1:
        lst.append(Paragraph("Illustrating splits with spans and repeatRows: split(4in,30)", styleSheet['BodyText']))
        for s in t.split(4*inch,30):
            lst.append(s)
            lst.append(Spacer(0,6))
        lst.append(Spacer(0,6))
        lst.append(Paragraph("Illustrating splits with spans and repeatRows: split(4in,36)", styleSheet['BodyText']))
        for s in t.split(4*inch,36):
            lst.append(s)
            lst.append(Spacer(0,6))
    lst.append(Paragraph("Illustrating splits with spans and repeatRows: split(4in,56)", styleSheet['BodyText']))
    lst.append(Spacer(0,6))
    for s in t.split(4*inch,56):
        lst.append(s)
        lst.append(Spacer(0,6))

    lst.append(PageBreak())
    from reportlab.lib.testutils import testsFolder
    I = Image(os.path.join(os.path.dirname(testsFolder),'tools','pythonpoint','demos','leftlogo.gif'))
    I.drawHeight = 1.25*inch*I.drawHeight / I.drawWidth
    I.drawWidth = 1.25*inch
    #I.drawWidth = 9.25*inch #uncomment to see better messaging
    P = Paragraph("<para align=center spaceb=3>The <b>ReportLab Left <font color=red>Logo</font></b> Image</para>", styleSheet["BodyText"])
    B = TableBarChart()
    BP = Paragraph("<para align=center spaceb=3>A bar chart in a cell.</para>", styleSheet["BodyText"])

    data=  [['A', 'B', 'C', Paragraph("<b>A pa<font color=red>r</font>a<i>graph</i></b><super><font color=yellow>1</font></super>",styleSheet["BodyText"]), 'D'],
            ['00', '01', '02', [I,P], '04'],
            ['10', '11', '12', [I,P], '14'],
            ['20', '21', '22', '23', '24'],
            ['30', '31', '32', '33', '34'],
            ['40', '41', '42', [B,BP], '44']]

    t=Table(data,style=[('GRID',(1,1),(-2,-2),1,colors.green),
                    ('BOX',(0,0),(1,-1),2,colors.red),
                    ('LINEABOVE',(1,2),(-2,2),1,colors.blue),
                    ('LINEBEFORE',(2,1),(2,-2),1,colors.pink),
                    ('BACKGROUND', (0, 0), (0, 1), colors.pink),
                    ('BACKGROUND', (1, 1), (1, 2), colors.lavender),
                    ('BACKGROUND', (2, 2), (2, 3), colors.orange),
                    ('BOX',(0,0),(-1,-1),2,colors.black),
                    ('GRID',(0,0),(-1,-1),0.5,colors.black),
                    ('VALIGN',(3,0),(3,0),'BOTTOM'),
                    ('BACKGROUND',(3,0),(3,0),colors.limegreen),
                    ('BACKGROUND',(3,1),(3,1),colors.khaki),
                    ('ALIGN',(3,1),(3,1),'CENTER'),
                    ('BACKGROUND',(3,2),(3,2),colors.beige),
                    ('ALIGN',(3,2),(3,2),'LEFT'),
                    ])

    t._argW[3]=1.5*inch
    lst.append(t)

    # now for an attempt at column spanning.
    lst.append(PageBreak())
    data=  [['A', 'BBBBB', 'C', 'D', 'E'],
            ['00', '01', '02', '03', '04'],
            ['10', '11', '12', '13', '14'],
            ['20', '21', '22', '23', '24'],
            ['30', '31', '32', '33', '34']]
    sty = [
            ('ALIGN',(0,0),(-1,-1),'CENTER'),
            ('VALIGN',(0,0),(-1,-1),'TOP'),
            ('GRID',(0,0),(-1,-1),1,colors.green),
            ('BOX',(0,0),(-1,-1),2,colors.red),

            #span 'BBBB' across middle 3 cells in top row
            ('SPAN',(1,0),(3,0)),
            #now color the first cell in this range only,
            #i.e. the one we want to have spanned.  Hopefuly
            #the range of 3 will come out khaki.
            ('BACKGROUND',(1,0),(1,0),colors.khaki),

            ('SPAN',(0,2),(-1,2)),


            #span 'AAA'down entire left column
            ('SPAN',(0,0), (0, 1)),
            ('BACKGROUND',(0,0),(0,0),colors.cyan),
            ('TEXTCOLOR', (0,'splitfirst'), (-1,'splitfirst'), colors.cyan),
            ('TEXTCOLOR', (0,'splitlast'), (-1,'splitlast'), colors.red),
            ('BACKGROUND', (0,'splitlast'), (-1,'splitlast'), colors.pink),
            ('LINEBELOW', (0,'splitlast'), (-1,'splitlast'), 1, colors.grey,'butt'),
           ]
    t=Table(data,style=sty, colWidths = [20] * 5, rowHeights = [20]*5)
    lst.append(t)
    lst.append(Spacer(18,18))

    t=Table(data,style=sty, colWidths = [20] * 5, rowHeights = [20]*5)
    for s in t.split(4*inch,72):
        lst.append(s)
        lst.append(Spacer(0,6))

    # now for an attempt at percentage widths
    lst.append(Spacer(18,18))
    lst.append(Paragraph("This table has colWidths=5*['14%']!", styleSheet['BodyText']))
    t=Table(data,style=sty, colWidths = ['14%'] * 5, rowHeights = [20]*5)
    lst.append(t)

    lst.append(Spacer(18,18))
    lst.append(Paragraph("This table has colWidths=['14%','10%','19%','22%','*']!", styleSheet['BodyText']))
    t=Table(data,style=sty, colWidths = ['14%','10%','19%','22%','*'], rowHeights = [20]*5)
    lst.append(t)

    # Mike's test example
    lst.append(Spacer(18,18))
    lst.append(Paragraph('Mike\'s Spanning Example', styleSheet['Heading1']))
    data=  [[Paragraph('World Domination: The First Five Years', styleSheet['BodyText']), ''],
            [Paragraph('World <font color="green">Domination</font>: The First Five Years', styleSheet['BodyText']),''],
            [Paragraph('World Domination: The First Five Years', styleSheet['BodyText']), ''],
            ]
    t=Table(data, style=[('SPAN',(0,0),(1,0)),('SPAN',(0,1),(1,1)),('SPAN',(0,2),(1,2)),], colWidths = [3*cm,8*cm], rowHeights = [None]*3)
    lst.append(t)

    lst.append(Spacer(18,18))
    lst.append(Paragraph('Mike\'s Non-spanning Example', styleSheet['Heading1']))
    data=  [[Paragraph('World Domination: The First Five Years', styleSheet['BodyText'])],
            [Paragraph('World <font color="magenta">Domination</font>: The First Five Years', styleSheet['BodyText'])],
            [Paragraph('World Domination: The First Five Years', styleSheet['BodyText'])],
            ]
    t=Table(data, style=[], colWidths = [11*cm], rowHeights = [None]*3)
    lst.append(t)

    lst.append(Spacer(18,18))
    lst.append(Paragraph('xpre example', styleSheet['Heading1']))
    data=  [    [
                XPreformatted('Account Details', styleSheet['Heading3']),
                '', XPreformatted('Client Details', styleSheet['Heading3']),
                ],  #end of row 0
            ]
    t=Table(data, style=[], colWidths = [80,230.0,80], rowHeights = [None]*1)
    lst.append(t)

    lst.append(PageBreak())

    lst.append(Paragraph('Trying colour cycling in background', styleSheet['Heading1']))
    lst.append(Paragraph("This should alternate pale blue and uncolored by row", styleSheet['BodyText']))
    data=  [['001', '01', '02', '03', '04', '05'],
            ['002', '01', '02', '03', '04', '05'],
            ['003', '01', '02', '03', '04', '05'],
            ['004', '01', '02', '03', '04', '05'],
            ['005', '01', '02', '03', '04', '05'],
            ['006', '01', '02', '03', '04', '05'],
            ['007', '01', '02', '03', '04', '05'],
            ['008', '01', '02', '03', '04', '05'],
            ['009', '01', '02', '03', '04', '05'],
            ['010', '01', '02', '03', '04', '05'],

            ]
    t=Table(data,style=[
                    ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                    ('ROWBACKGROUNDS', (0, 0), (-1, -1), (0xD0D0FF, None)),
                    ])
    lst.append(t)
    lst.append(Spacer(0,6))
    lst.append(Paragraph("And this should pale blue, pale pink and None by column", styleSheet['BodyText']))
    data=  [['001', '01', '02', '03', '04', '05'],
            ['002', '01', '02', '03', '04', '05'],
            ['003', '01', '02', '03', '04', '05'],
            ['004', '01', '02', '03', '04', '05'],
            ['005', '01', '02', '03', '04', '05'],
            ['006', '01', '02', '03', '04', '05'],
            ['007', '01', '02', '03', '04', '05'],
            ['008', '01', '02', '03', '04', '05'],
            ['009', '01', '02', '03', '04', '05'],
            ['010', '01', '02', '03', '04', '05'],

            ]
    t=Table(data,style=[
                    ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                    ('COLBACKGROUNDS', (0, 0), (-1, -1), (0xD0D0FF, 0xFFD0D0, None)),
                    ])
    lst.append(t)

    lst.append(PageBreak())
    lst.append(Paragraph("This spanning example illustrates automatic removal of grids and lines in spanned cells!", styleSheet['BodyText']))
    lst.append(Spacer(0,6))
    data=  [['Top\nLeft', '', '02', '03', '04', '05', '06', '07'],
            ['', '', '12', 'Span (3,1) (6,2)', '','','','17'],
            ['20', '21', '22', '', '','','','27'],
            ['30', '31', '32', '33', '34','35','36','37'],
            ['40', 'In The\nMiddle', '', '', '44','45','46','47'],
            ['50', '', '', '', '54','55','56','57'],
            ['60', '', '', '','64', '65', 'Bottom\nRight', ''],
            ['70', '71', '72', '73','74', '75', '', '']]
    t=Table(data,style=[
            ('GRID',(0,0),(-1,-1),0.5,colors.grey),
            ('BACKGROUND',(0,0),(1,1),colors.palegreen),
            ('SPAN',(0,0),(1,1)),
            ('BACKGROUND',(-2,-2),(-1,-1), colors.pink),
            ('SPAN',(-2,-2),(-1,-1)),
            ('SPAN',(1,4),(3,6)),
            ('BACKGROUND',(1,4),(3,6), colors.lightblue),
            ('SPAN',(3,1),(6,2)),
            ('BACKGROUND',(3,1),(6,2), colors.peachpuff),
            ('VALIGN',(3,1),(6,2),'TOP'),
            ('LINEABOVE', (0,2),(-1,2), 1, colors.black, 0, None, None, 2, 2),
            ('LINEBEFORE', (3,0),(3,-1), 1, colors.black, 0, None, None, 2, 2),
            ])
    lst.append(t)

    lst.append(PageBreak())

    lst.append(Paragraph("und jetzt noch eine Tabelle mit 5000 Zeilen:", styleSheet['BodyText']))
    sty = [ ('GRID',(0,0),(-1,-1),1,colors.green),
            ('BOX',(0,0),(-1,-1),2,colors.red),
           ]
    data = [[str(i), Paragraph("xx "* (i%10), styleSheet["BodyText"]), Paragraph("blah "*(i%40), styleSheet["BodyText"])] for i in range(500)]
    t=LongTable(data, style=sty, colWidths = [50,100,200])
    lst.append(t)

    #Yuan Hong's bug tester
    lst.append(PageBreak())
    lst.append(Paragraph('Yian Hong\'s Bug Case (should not blow up)', styleSheet['Heading2']))
    data = ([['Col1', 'Col2', 'Col3', 'Col4', 'Col5']]+
                [['01', Paragraph('This is cell one that contains a paragraph.', styleSheet['Normal']), '02', '03', '04']
                    for i in range(50)])

    t = Table(data, ['20%']*5, repeatRows=1)
    t.setStyle(TableStyle([
        ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
        ('BOX', (0,0), (-1,-1), 0.25, colors.black),
        ('SPAN', (0,50), (-2,50)),
        ]))

    lst.append(t)
    lst.append(PageBreak())

    #Volker Haas' example extended
    #the optimal row heights are the solution of an LP similar to
    #
    #Objective function
    #   min: 3*h0+3*h1+3*h2+2*h3;
    #
    #constraints
    #   h0>=12;
    #   h1>=12;
    #   h2>=12;
    #   h3>=12;
    #   h0+h1+h2>=48;
    #   h0+h1>=12;
    #   h2+h3>=60;
    #
    #the solution H=[12,12,24,36]
    def makeTable(x,y):
        return Table([
                ['00', '01', '02', '03', '04', '05\nline2\nline3\nline4'],
                ['', '11', '12', x, '',''],
                ['20', '21', y, '23', '24',''],
                ['30', '31', '', '33', '34','35'],
                ],
                style=[
                    ('TOPPADDING',(0,0),(-1,-1),0),
                    ('BOTTOMPADDING',(0,0),(-1,-1),0),
                    ('RIGHTPADDING',(0,0),(-1,-1),0),
                    ('LEFTPADDING',(0,0),(-1,-1),0),
                    ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                    ('BACKGROUND', (0, 0), (0, 1), colors.pink),
                    ('SPAN',(0,0),(0,1)),
                    ('BACKGROUND', (2, 2), (2, 3), colors.orange),
                    ('SPAN',(2,2),(2,3)),
                    ('SPAN',(3,1),(4,1)),
                    ('SPAN',(5,0),(5,2)),
                ])
    p_style= ParagraphStyle('Normal')
    lst.append(makeTable(
            Paragraph('This is a string',p_style),
            Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style)
            ))

    lst.append(Spacer(10,10))
    lst.append(makeTable(
            XPreformatted('This is a string',p_style),
            Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style)
            ))
    lst.append(Spacer(10,10))
    lst.append(makeTable(
            'This is a string',
            '22\nblub\nasfd\nafd\nasdfs',
            ))
    lst.append(Spacer(10,10))
    lst.append(makeTable(
            'This is a string',
            Paragraph('22<br/>blub<br/>asfd<br/>afd<br/>asdfs', p_style)
            ))
    SimpleDocTemplate(outputfile('test_platypus_tables_2.pdf'), showBoundary=1).build(lst)
Ejemplo n.º 10
0
def table(rows,
          w=None,
          h=None,
          grid=1,
          head=0,
          count=0,
          zebra=0,
          auto_align=1,
          blank=u'-',
          a=None,
          fontSize=8):
    """
    w: colWidths
    h: rowHeight
    grid: mostrar grades da tabela
    head: indica se a primeira lista de `rows` é o cabeçalho
    count: mostra o contador das linhas
    zebra: a tabela fica zebrada
    auto_align: alinha automaticamente a célula de acordo com seu valor
    blank: valor caso a célula esteja em branco (ou None)
    a: alinhamentos
    """
    number_of_columns = len(rows[0])

    # Validating rows
    for row_n, row in enumerate(rows[1:]):
        if len(row) != number_of_columns:
            raise Exception('Rows must have %d columns, got %d on row %d' \
                            % (number_of_columns, len(row), row_n + 2))

    # Validating w
    if w:
        if len(w) != number_of_columns:
            raise Exception('Param `w` must have len %d, got %d' \
                            % (number_of_columns, len(w)))

    # Validating a
    if a:
        if len(a) != number_of_columns:
            raise Exception('Param `a` must have len %d, got %d' \
                            % (number_of_columns, len(a)))

    def get_auto_align(value):
        if isinstance(value, basestring):
            # String: 0,00 or 0.00
            return value.replace(',', '').replace('.', '').isdigit() and \
                'right' or 'left'
        return isNumberType(value) and 'right' or 'left'

    formatted_rows = []

    for index, row in enumerate(rows):  # Body
        # HEAD
        if index == 0 and head:
            if count and w:
                w = [10] + w
            formatted_row = []
            row = count and ([u'#'] + row) or row
            for cell in row:
                text = '<para fontSize="%s" alignment="center"><b>%s</b></para>' % (
                    fontSize, cell)
                formatted_row.append(para(text))
            formatted_rows.append(formatted_row)
            continue

        # ROW
        formatted_row = []
        if count:
            order = head and index or index + 1
            text = '<para fontSize="%s" alignment="right">%s</para>' % (
                fontSize, order)
            formatted_row = [para(text)]
        for row_count, cell in enumerate(row):
            # If cell insn't a reportlab element
            if not cell.__class__.__module__.split('.')[0] == 'reportlab':
                para_args = dict(fontSize=fontSize)
                if not cell:  # valor em branco
                    cell = blank
                    if a:
                        para_args['align'] = a[row_count]
                    else:
                        para_args['align'] = 'c'
                else:
                    if a:
                        para_args['align'] = a[row_count]
                    elif auto_align:
                        para_args['align'] = get_auto_align(cell)
                cell = para(cell, **para_args)
            formatted_row.append(cell)
        formatted_rows.append(formatted_row)

    # Constructor args to table <LongTable>
    constructor_args = {}
    if w:
        constructor_args['colWidths'] = [i * mm for i in w]
    if h:
        constructor_args['rowHeights'] = h * mm
    if head:
        # repeat table header after page breaks
        constructor_args['repeatRows'] = 1

    # Creating the table
    table = LongTable(formatted_rows, **constructor_args)
    table.setStyle(
        TableStyle([('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                    ('BOTTOMPADDING', (0, 0), (-1, -1), 0.25, 0.25),
                    ('TOPADDING', (0, 0), (-1, -1), 0.25, 0.25)]))

    if grid:
        table.setStyle(
            TableStyle([
                ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.gray),
                ('BOX', (0, 0), (-1, -1), 0.25, colors.black),
            ]))

    if head:
        table.setStyle(
            TableStyle([
                ('ROWBACKGROUNDS', (0, 0), (-1, 0), (0xCCCCCC, )),
            ]))

    if zebra:
        table.setStyle(
            TableStyle([('ROWBACKGROUNDS', (0, 1), (-1, -1), (0xEEEEEE, None))
                        ]))

    return table
Ejemplo n.º 11
0
def table(
    rows,
    w=None,
    h=None,
    grid=1,
    head=0,
    count=0,
    zebra=0,
    auto_align=1,
    blank="-",
    a=None,
    fontSize=8,
    title_red=False,
):
    """
    w: colWidths
    h: rowHeight
    grid: mostrar grades da tabela
    head: indica se a primeira lista de `rows` é o cabeçalho
    count: mostra o contador das linhas
    zebra: a tabela fica zebrada
    auto_align: alinha automaticamente a célula de acordo com seu valor
    blank: valor caso a célula esteja em branco (ou None)
    a: alinhamentos
    """
    number_of_columns = len(rows[0])

    # Validating rows
    for row_n, row in enumerate(rows[1:]):
        if len(row) != number_of_columns:
            raise Exception("Rows must have %d columns, got %d on row %d" %
                            (number_of_columns, len(row), row_n + 2))

    # Validating w
    if w:
        if len(w) != number_of_columns:
            raise Exception(
                f"Param `w` must have len {number_of_columns}, got {len(w)}")

    # Validating a
    if a:
        if len(a) != number_of_columns:
            raise Exception(
                f"Param `a` must have len {number_of_columns}, got {len(a)}")

    def get_auto_align(value):
        if isinstance(value, str):
            # String: 0,00 or 0.00
            return (value.replace(",", "").replace(".", "").isdigit()
                    and "right" or "left")
        return isinstance(value, numbers.Number) and "right" or "left"

    formatted_rows = []

    for index, row in enumerate(rows):  # Body
        # HEAD
        if index == 0 and head:
            if count and w:
                w = [10] + w
            formatted_row = []
            row = count and (["#"] + row) or row
            for cell in row:
                text = f'<para fontSize="{fontSize}" alignment="center"><b>{cell}</b></para>'
                formatted_row.append(para(text))
            formatted_rows.append(formatted_row)
            continue

        # ROW
        formatted_row = []
        if count:
            order = head and index or index + 1
            text = f'<para fontSize="{fontSize}" alignment="right">{order}</para>'
            formatted_row = [para(text)]
        for row_count, cell in enumerate(row):
            # If cell insn't a reportlab element
            if not (isinstance(cell, Image) or isinstance(cell, Rect)):
                cell = str(cell)  # force string
                if (not cell.__class__.__module__.split(".")[0] == "reportlab"
                        and not cell.__class__ == Rect):
                    para_args = dict(fontSize=fontSize)
                    if not cell:  # valor em branco
                        cell = blank
                        if a:
                            para_args["align"] = a[row_count]
                        else:
                            para_args["align"] = "c"
                    else:
                        if a:
                            para_args["align"] = a[row_count]
                        elif auto_align:
                            para_args["align"] = get_auto_align(cell)
                    cell = para(cell, **para_args)
            formatted_row.append(cell)
        formatted_rows.append(formatted_row)

    # Constructor args to table <LongTable>
    constructor_args = {}
    if w:
        constructor_args["colWidths"] = [i * mm for i in w]
    if h:
        constructor_args["rowHeights"] = h * mm
    if head:
        # repeat table header after page breaks
        constructor_args["repeatRows"] = 1

    # Creating the table
    table = LongTable(formatted_rows, **constructor_args)
    table.setStyle(
        TableStyle([
            ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
            ("BOTTOMPADDING", (0, 0), (-1, -1), 0.25, 0.25),
            ("TOPADDING", (0, 0), (-1, -1), 0.25, 0.25),
        ]))

    if grid:
        table.setStyle(
            TableStyle([
                ("INNERGRID", (0, 0), (-1, -1), 0.1, colors.gray),
                ("BOX", (0, 0), (-1, -1), 0.25, colors.black),
            ]))

    if head:
        table.setStyle(
            TableStyle([("ROWBACKGROUNDS", (0, 0), (-1, 0), (0xCCCCCC, ))]))

    if zebra:
        table.setStyle(
            TableStyle([("ROWBACKGROUNDS", (0, 1), (-1, -1), (0xEEEEEE, None))
                        ]))

    if title_red:
        table.setStyle(
            TableStyle([("ROWBACKGROUNDS", (0, 0), (-1, 0), (colors.red, None))
                        ]))

    return table
Ejemplo n.º 12
0
    def generatePDF(self, model_data):
        """
        Dieses Beispiel zeigt nicht annähernd die Möglichkeiten von ReportLab!
        Es demonstriert nur, wie einfach es sein kann.
        """
        stylesheet = getSampleStyleSheet()
        # Formatstil für die Überschrift festlegen
        sth1 = stylesheet['Heading1']
        # Formatstil für den Absatz festlegen
        stn = stylesheet['Normal']
        stn.fontName = 'Helvetica'
        stn.fontSize = 10
        stn.leading = 12
        #print stn.spaceAfter
        #print stn.spaceBefore
        #print stn.leading

        print("TODO: Why is the text so close to the top of the cells?")

        # Automatische Silbentrennung für diesen Stil einschalten
        stn.language = 'DE'
        stn.hyphenation = True

        # Wir machen erstmal einen Fake,
        # nämlich den ASCII-Text zeilenweise.
        self.generateDUMP(model_data)
        pure_text = "".join(self.text)
        story = []
        para = Paragraph(
            "Beispiel für einen Datenbankbericht".decode("iso-8859-1"), sth1)
        '''
        story.append(para)
        
        para = Paragraph("""Dies ist ein längerer Absatz, der eigentlich nur den Zweck hat,
die automatische Silbentrennung von WordAxe zu demonstrieren. Aus diesem Grund enthält dieser
Absatz auch einige besonders schöne lange Wörter wie etwa "Donaudampfschifffahrtsgesellschaftskapitän"
oder "Bundeskanzleramt" oder "Landesgesundheitsbehörden", sogar gleich mehrfach:
Schiff Dampfschiff Dampfschifffahrt Donaudampfschiffahrt oder Donaudampfschiffahrtsgesellschaft
Donaudampfschiffahrtsgesellschaftsvorsitzender (Ha! damit habt Ihr wohl nicht gerechnet, oder?)
und nebenbei auch HTML-Formatierung wie <b>fett</b> oder <i>kursiv!</i>
Mal sehen, ob das Euro-Zeichen geht - ich befürchte aber, dass das auf Anhieb nicht funktioniert.
Hier kommt es: € - nee, das sehe ich schon im Quelltext nicht richtig.
""".decode("iso-8859-1"), stn)        
        story.append(para)
        for line in pure_text.splitlines():
            para = Paragraph(line.decode("iso-8859-1"), stn)
            story.append(para)
        '''

        # Jetzt mal anders:
        # Ausgabe als Master-Detail-Liste, wobei die Details
        # eine Spalte weiter eingerückt sind.
        if model_data:
            headers1 = [Paragraph(toUnicode(x), stn) for x in DEPT.headers()]
            headers2 = [None] + [
                Paragraph(toUnicode(x), stn) for x in EMP.headers()
            ]
            nColumns = max(len(headers1), len(headers2))
            fill1 = ([None] * (nColumns - len(headers1)))
            fill2 = ([None] * (nColumns - len(headers2)))
            headers1 += fill1
            headers2 += fill2
            tableData = [headers1, headers2]
            colWidths = [None] * nColumns
            colWidths[-1] = 40 * mm
            nRows = len(model_data)
            tableStyle = TableStyle([
                ('BOX', (0, 0), (-1, -1), 1, colors.black),
                ('BACKGROUND', (0, 0), (-1, 1), colors.orange),
                ('BACKGROUND', (0, 1), (-1, 1), colors.yellow),
                ('INNERGRID', (0, 0), (-1, -1), 0.5, colors.black),
                ('LEFTPADDING', (0, 0), (-1, -1), 3),
                ('RIGHTPADDING', (0, 0), (-1, -1), 3),
                ('VALIGN', (0, 0), (-1, -1), 'TOP'),
            ])
            for dept in model_data:
                tableData.append(dept.genParagraphList(stn) + fill1)
                tableStyle.add('BACKGROUND', (0, len(tableData) - 1),
                               (-1, len(tableData) - 1), colors.orange)
                for emp in dept.children["emp"]:
                    tableData.append([""] + emp.genParagraphList(stn) + fill2)
            table = LongTable(tableData,
                              style=tableStyle,
                              colWidths=colWidths,
                              repeatRows=2)
            story.append(table)
        self.story = story
Ejemplo n.º 13
0
    def build_pdf(self, response):
        CONTATO = 0
        TELEFONES_PREFERENCIAL = 1

        CIDADE = 0
        ENDERECO = 1
        BAIRRO = 2
        NUMERO = 3
        GRUPO = 4
        ID = 5
        NOME = 6

        self.set_headings()
        self.set_styles()
        self.set_cabec(self.h5)
        estilo = self.h_style

        corpo_relatorio = []
        self.add_relat_title(corpo_relatorio)

        registros = self.get_data()
        for dados in registros:
            endereco = ','.join(dados[CONTATO][ENDERECO:NUMERO])

            item = [
                Paragraph(dados[CONTATO][CIDADE], estilo),
                Paragraph(dados[CONTATO][GRUPO], estilo),
                Paragraph(dados[CONTATO][NOME], estilo),
                Paragraph(endereco, estilo),
                Paragraph(dados[TELEFONES_PREFERENCIAL], estilo),
            ]
            corpo_relatorio.append(item)

        style = TableStyle([
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('LEADING', (0, 0), (-1, -1), 7),
            ('GRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])
        style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE')

        for i, value in enumerate(corpo_relatorio):
            if len(value) <= 1:
                style.add('SPAN', (0, i), (-1, i))

            if len(value) == 0:
                style.add('INNERGRID', (0, i), (-1, i), 0, colors.black),
                style.add('GRID', (0, i), (-1, i), -1, colors.white)
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

            if len(value) == 1:
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

        rowHeights = 20
        t = LongTable(corpo_relatorio, rowHeights=rowHeights, splitByRow=True)
        t.setStyle(style)
        if len(t._argW) == 5:
            t._argW[0] = 1.8 * cm
            t._argW[1] = 6 * cm
            t._argW[2] = 6.5 * cm
            t._argW[3] = 9.5 * cm
            t._argW[4] = 2.4 * cm
        elif len(t._argW) == 4:
            t._argW[0] = 2 * cm
            t._argW[1] = 10 * cm
            t._argW[2] = 11.5 * cm
            t._argW[3] = 3 * cm

        for i, value in enumerate(corpo_relatorio):
            if len(value) == 0:
                t._argH[i] = 7
                continue
            for cell in value:
                if isinstance(cell, list):
                    t._argH[i] = (rowHeights) * (len(cell) -
                                                 (0 if len(cell) > 1 else 0))
                    break

        elements = [t]

        doc = SimpleDocTemplate(response,
                                pagesize=landscape(A4),
                                rightMargin=1.25 * cm,
                                leftMargin=1.25 * cm,
                                topMargin=1.1 * cm,
                                bottomMargin=0.8 * cm)
        doc.build(elements)
Ejemplo n.º 14
0
def table(rows, w=None, h=None, grid=1, head=0, count=0, zebra=0, 
          auto_align=1, blank=u'-', a=None):
    """
    w: colWidths
    h: rowHeight
    grid: mostrar grades da tabela
    head: indica se a primeira lista de `rows` é o cabeçalho
    count: mostra o contador das linhas
    zebra: a tabela fica zebrada
    auto_align: alinha automaticamente a célula de acordo com seu valor
    blank: valor caso a célula esteja em branco (ou None)
    a: alinhamentos
    """
    number_of_columns = len(rows[0])
    
    # Validating rows
    for row_n, row in enumerate(rows[1:]):
        if len(row) != number_of_columns:
            raise Exception('Rows must have %d columns, got %d on row %d' \
                            % (number_of_columns, len(row), row_n + 2))
    
    # Validating w
    if w:
        if len(w) != number_of_columns:
            raise Exception('Param `w` must have len %d, got %d' \
                            % (number_of_columns, len(w)))
    
    # Validating a
    if a:
        if len(a) != number_of_columns:
            raise Exception('Param `a` must have len %d, got %d' \
                            % (number_of_columns, len(a)))
        
    
    def get_auto_align(value):
        return isNumberType(value) and 'right' or 'left'
    
    fontSize = 8
    formatted_rows = []
    
    for index, row in enumerate(rows): # Body
        # HEAD
        if index == 0 and head:
            if count and w:
                w = [10] + w
            formatted_row = []
            row = count and ([u'#'] + row) or row
            for cell in row:
                text = '<para fontSize="%s" alignment="center"><b>%s</b></para>' % (fontSize, cell)
                formatted_row.append(para(text))
            formatted_rows.append(formatted_row)
            continue
        
        # ROW
        formatted_row = []
        if count:
            order = head and index or index + 1
            text = '<para fontSize="%s" alignment="right">%s</para>' % (fontSize, order)
            formatted_row = [para(text)]
        for row_count, cell in enumerate(row):
            # If cell insn't a reportlab element
            if not cell.__class__.__module__.split('.')[0] == 'reportlab':
                para_args = dict(fontSize=fontSize)
                if not cell: # valor em branco
                    cell = blank
                    para_args['align'] = 'center'
                else:
                    if a:
                        para_args['align'] = a[row_count]
                    elif auto_align:
                        para_args['align'] = get_auto_align(cell)
                cell = para(cell, **para_args)
            formatted_row.append(cell)
        formatted_rows.append(formatted_row)
    
    # Constructor args to table <LongTable>
    constructor_args = {}
    if w:
        constructor_args['colWidths'] = [i*mm for i in w]
    if h:
        constructor_args['rowHeights'] = h*mm
    if head:
        # repeat table header after page breaks
        constructor_args['repeatRows'] = 1
    
    # Creating the table
    table = LongTable(formatted_rows, **constructor_args)
    table.setStyle(TableStyle([
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('BOTTOMPADDING', (0,0), (-1,-1), 0.25, 0.25),
        ('TOPADDING', (0,0), (-1,-1), 0.25, 0.25)
    ]))
    
    if grid:
        table.setStyle(TableStyle([
            ('INNERGRID', (0,0), (-1,-1), 0.1, colors.gray),
            ('BOX', (0,0), (-1,-1), 0.25, colors.black),
        ]))
    
    if head:
        table.setStyle(TableStyle([
            ('ROWBACKGROUNDS', (0, 0), (-1, 0), (0xCCCCCC,)),
        ]))
    
    if zebra:
        table.setStyle(TableStyle([
            ('ROWBACKGROUNDS', (0, 1), (-1, -1), (0xEEEEEE, None))
        ]))
    
    return table
Ejemplo n.º 15
0
   def GeneratePdf(self, apiToken, projectId, stories, filename ):
   
      self.response.headers['Content-Type'] = 'application/pdf'
      
      doc = SimpleDocTemplate(self.response.out,pagesize = letter, allowSplitting=1, title='User Stories', author='Pivotal PDF (http://pivotal-pdf.appspot.com)')
      
      #Create a list of flowables for the document
      flowables = []
      
      #Create a list for our rows, this will be a list of lists or an array which makes up the table
      tableData = []      
      
      #Create a row for our stories
      storyRow = []
      #add some flowables
      storyRow.append(Paragraph("Story",self.styleHeader))
      storyRow.append(Paragraph("Iteration Start",self.styleHeader))
      storyRow.append(Paragraph("Iteration End",self.styleHeader))
      storyRow.append(Paragraph("Description", self.styleHeader))
      tableData.append(storyRow)
      
      #Add the Done Stories
      doneStories = self.GetDoneStories( stories, apiToken, projectId )
      
      for storyInfo in doneStories :
         
         # Paragraphs can take HTML so the mark-up characters in the text must be escaped
         storyName = escape ( storyInfo['story']['name'] )

         storyDescription = self.BuildDescription( storyInfo )
         
         storyRow = []
         storyRow.append(Paragraph( storyName,self.styleName))
         storyRow.append(Paragraph(storyInfo['start'].strftime(self.iterationDateFormat),self.styleNormal))
         storyRow.append(Paragraph(storyInfo['finish'].strftime(self.iterationDateFormat),self.styleNormal))
         storyRow.append( storyDescription )
         tableData.append(storyRow)
      
      #Add the Current Stories
      currentStories = self.GetCurrentStories( stories, apiToken, projectId )
      
      for storyInfo in currentStories :
         
         # Paragraphs can take HTML so the mark-up characters in the text must be escaped
         storyName = escape ( storyInfo['story']['name'] )

         storyDescription = self.BuildDescription( storyInfo )
        
         storyRow = []
         storyRow.append(Paragraph( storyName,self.styleName))
         storyRow.append(Paragraph("Current",self.styleNormal))
         storyRow.append(Paragraph("Current",self.styleNormal))
         
         storyRow.append(storyDescription)
   
         tableData.append(storyRow)
      
      #Add the Future Stories
      futureStories = self.GetFutureStories( stories, apiToken, projectId )
      
      for storyInfo in futureStories :

         # Paragraphs can take HTML so the mark-up characters in the text must be escaped
         storyName = escape ( storyInfo['story']['name'] )

         storyDescription = self.BuildDescription( storyInfo )
         
         storyRow = []
         storyRow.append(Paragraph( storyName,self.styleName))
         storyRow.append(Paragraph(storyInfo['start'].strftime(self.iterationDateFormat),self.styleNormal))
         storyRow.append(Paragraph(storyInfo['finish'].strftime(self.iterationDateFormat),self.styleNormal))
         storyRow.append( storyDescription )
         tableData.append(storyRow)
      
      #Add the Icebox Stories
      iceboxStories = self.GetIceboxStories( stories, apiToken, projectId )
      
      for storyInfo in iceboxStories :

         # Paragraphs can take HTML so the mark-up characters in the text must be escaped
         storyName = escape ( storyInfo['story']['name'] )

         storyDescription = self.BuildDescription( storyInfo )
         
         storyRow = []
         storyRow.append(Paragraph( storyName,self.styleName))
         storyRow.append(Paragraph("Icebox",self.styleNormal))
         storyRow.append(Paragraph('Icebox',self.styleNormal))
         storyRow.append( storyDescription )
         tableData.append(storyRow)

      table = LongTable(tableData, colWidths=[2*inch,1*inch,1*inch,3.5*inch] )  
      
      table.setStyle(TableStyle([
                        ('BACKGROUND',(0,0),(-1,0),colors.darkslategray),        #Give the header row a grey background
                        ('BACKGROUND',(0,1),(-1, len(doneStories) ),colors.lightgrey),  #Shade the Done stories in light grey
                        ('BACKGROUND',(0, len(doneStories) + len(currentStories) + 1 ),(-1, -1 ),colors.grey),  #Shade the backlog stories in light grey
                        ('BACKGROUND',(0, len(doneStories) + len(currentStories) + len(futureStories) + 1 ),(-1, -1 ),colors.dimgrey),  #Shade the backlog stories in light grey
                        ('TEXTCOLOR',(0,0),(-1,0),colors.white),        #Give the header row white text
                        ('ALIGNMENT',(0,0),(-1,0),'CENTRE'),            #Horizontally align the header row to the center
                        ('VALIGN',(0,0),(-1,0),'MIDDLE'),               #Vertically align the header row in the middle
                        ('TEXTCOLOR',(0,1),(-1,-2),colors.black),       #Make the rest of the text white
                        ('VALIGN',(0,1),(-1,-1),'TOP'),                 #Make the rest of the cells vertically aligned to the top
                        ('ALIGN',(0,1),(-1,-2),'LEFT'),                 #Generally align everything to the right
                        ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                        ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                        ]))
                              
      flowables.append( table )
      
      try :
         doc.build(flowables)
      except LayoutError as exception:
         nameMatch = re.search(r"""('[^']*')""", str(exception), re.M)
                  
         if nameMatch != None :
            template_values = {'storyName': nameMatch.group(0) }
         else :
            template_values = {}
               
         path = os.path.join(os.path.dirname(__file__), 'error.html')
         self.response.headers['Content-Type'] = 'html'
         self.response.out.write(template.render(path, template_values))