Re: Fwd: Patch to support tables with oversize cells

Lennart Regebro via reportlab-users <[email protected]> Mon, 16 May 2022 13:34:03 +0200
Newsgroups gmane.comp.python.reportlab.user
Message-ID <CAHT-kBfTMtUk8DTsgmP+jnsZr7FhTK1cPRPJs8FS7BdL8OO5NA@mail.gmail.com>
I'm glad to hear I don't need to support this case. Yes, the span splitting
seems to work now, but the handling of styling isn't 100% yet.

I redid and attached the test I sent on Friday, if you want to look into
that behavior, but yes, I agree it might not really need fixing, I can't
imagine it's a common usecase.

//Lennart

On Sat, May 14, 2022 at 9:49 AM Robin Becker <[email protected]> wrote:

> On 13/05/2022 13:12, Lennart Regebro wrote:
> > Hi, sorry for the delay in this, I was on vacation.
> >
> > Splitting spanned cells turns out to be not easy at all. Well, the
> > splitting was no problem, it's dealing with the styles.
> >
> > I believe I have found an edge case in Reportlab which I'm not sure if
> it's
> > intended or not, and fixing it will require quite a major refactoring,
> so I
> > would like your opinion on this. Basically, you can color a spanned cell
> > only partially in current Reportlab, but supporting splitting such a cell
> > leads to some weirdness.
> >
> > If you set the background color only on the starting cell for a spanned
> > cell, then that whole cell will get that background color. But if you
> set a
> > background color on only some out of the rows, only that part of the cell
> > will get colored. If you then split that cell, then what parts of that
> > split cell are colored can change,
> >
> > Fixing this would require calculating the colors or all cells before a
> > split, and then, when the table is drawn, not doing any such
> > "recalculation". But the first question is: Is this really supported? Is
> > that how it is supposed to work? That you can set partial background
> colors
> > on spanned cells?
> >
> > Attaching PDF that demonstrates this. I accidentally overwrote the code
> > used to generate it, though. *facepalm*
> >
> > //Lennart
> >
> .........
> Hi Lennart, hope you enjoyed the vacation. Looking at your output I
> believe you have in fact found a bug. I had little
> to do with the original spanned columns/rows implementation, but I know
> it's a source of many bugs.
>
> I don't believe the intent was ever to allow partial styling and I haven't
> seen this before. It seems to me that in a
> span range we should consider the spanned cells to be absent. That would
> mean only the start cell of a span would
> contain content and or styling. If I can work up your example I may see
> how to avoid the partial styling. If your
> example actually shows a row span being split then we're almost there.
> Even without the partial styling fix I would
> always say the the intent is that the styles should cover the cells and
> the partial case is a bug.
>
> If we are able to avoid putting in content for the 'absent' spanned cells
> we should be able to ignore their styles.
> --
> Robin Becker
> _______________________________________________
> reportlab-users mailing list
> [email protected]
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users
>
test_table_bug.pdf (application/pdf, 2.8 KB) - not displayed
test_table_bug.py (text/x-python, 3.6 KB)
from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation
setOutDir(__name__)
import operator, string
from reportlab.platypus import *
from reportlab.lib.styles import PropertySet, getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus.paragraph import Paragraph
from reportlab.platypus.flowables import PageBreak
import os
import unittest

class TableTestCase(unittest.TestCase):

    def test_document(self):
        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)
        GRID_STYLE = TableStyle(
            [('GRID', (0,0), (-1,-1), 0.25, colors.black),
             ('ALIGN', (1,1), (-1,-1), 'RIGHT')]
            )

        styleSheet = getSampleStyleSheet()
        styNormal = styleSheet['Normal']
        styNormal.spaceBefore = 6
        styNormal.spaceAfter = 6
        styCode = styleSheet['Code']
        styCode.spaceAfter = 6
        styCode.leftIndent = 0

        lst = []
        lst.append(Paragraph("""Cell span styling edge case""", styleSheet['Heading2']))
        lst.append(Paragraph("""Let's make a table with spans that cover several rows""", styNormal))
            
        data = [
            ['R0C0', 'R0C1', 'R0C2', 'R0C3', 'R0C4'],
            ['R1C0', 'R1C1', 'R1C2', 'R1C3', 'R1C4'],
            ['R2C0', 'R2C1', 'R2C2', 'R2C3', 'R2C4'],
            ['R3C0', 'R3C1', 'R3C2', 'R3C3', 'R3C4'],
        ]

        sty = [
                ('GRID',(0,0),(-1,-1), 1, colors.green),
                ('SPAN',(0,0), (0, 2)),
                ]
        t=Table(data,style=sty, colWidths = [40] * 5, splitInRow=1, splitByRow=0)
        lst.append(t)

        lst.append(Paragraph("""We can color that cell either by explicitly colouring all rows with""", styNormal))
        lst.append(Paragraph("""[('BACKGROUND', (0, 0), (0, 2), colors.pink)]""", styCode))

        t=Table(data,style=sty+[('BACKGROUND', (0, 0), (0, 2), colors.pink)], colWidths = [40] * 5, splitInRow=1, splitByRow=0)
        lst.append(t)

        lst.append(Paragraph("""Or if we just color the first cell, it also colours all rows""", styNormal))
        lst.append(Paragraph("""[('BACKGROUND', (0, 0), (0, 0), colors.pink)]""", styCode))

        t=Table(data,style=sty+[('BACKGROUND', (0, 0), (0, 0), colors.pink)], colWidths = [40] * 5, splitInRow=1, splitByRow=0)
        lst.append(t)

        lst.append(Paragraph("""However, if we specify just two of the three cells, only those get colored!""", styNormal))
        lst.append(Paragraph("""[('BACKGROUND', (0, 0), (0, 1), colors.pink)]""", styCode))

        t=Table(data,style=sty+[('BACKGROUND', (0, 0), (0, 1), colors.pink)], colWidths = [40] * 5, splitInRow=1, splitByRow=0)
        lst.append(t)

        lst.append(Paragraph("""Now if we split that cell, we get one pink cell spanning just one row, and once cell spanning two rows.""", styNormal))
        lst.append(Paragraph("""But only the first cell of that span has a color, but that's interpreted like the whole cell should have that color!""", styNormal))

        for s in t.split(4*inch, 30):
            lst.append(s)
            lst.append(Spacer(0,6))

        lst.append(Paragraph("""This isn't fixable without pretty major code changes in how these styles are handled.""", styNormal))

        SimpleDocTemplate(outputfile('test_table_bug.pdf'), showBoundary=1).build(lst)

def makeSuite():
    return makeSuiteForClasses(TableTestCase)


#noruntests
if __name__ == "__main__":
    unittest.TextTestRunner().run(makeSuite())
    print('saved '+outputfile('test_table_bug.pdf'))
    printLocation()