Re: Patch to support tables with oversize cells
Robin Becker <[email protected]> Tue, 19 Apr 2022 10:45:25 +0100
| Newsgroups | gmane.comp.python.reportlab.user |
|---|---|
| Message-ID | <[email protected]> |
Hi Lennart, I put your data for the spanning case into my test program which is attached; I can use the following commands to see the behavior python lennart-example.py --splitByRow=0 --splitInRow=1 --split=55 --pdfn=ttt.pdf --useData=1 this works and splits the column spanned row 3 (row=2 in python). The cell is split OK, but it gets styles from the splitfirst, splitlast styles. I'm not sure that's right for a split in the row when the split row is neither a first row or last. I don't really know what the correct styling should be, but I think the style that would have applied in the non-splitting case should be used. If I use python lennart-example.py --splitByRow=0 --splitInRow=1 --split=22 --pdfn=ttt.pdf --useData=1 then the split fails because it crosses the spanned row cell On 12/04/2022 11:12, Lennart Regebro wrote: > Hi! Have you been able to look more at this? > > I'm feeling pretty good about the patch now, with added tests and better > command handling. > > ....... -- Robin Becker
lennart-example.py
(text/x-python, 5.5 KB)
def main():
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import Paragraph, Table, SimpleDocTemplate, Spacer, HRFlowable
from reportlab.lib.styles import getSampleStyleSheet
import os, sys, getopt
try:
opts, args = getopt.getopt(sys.argv[1:], '', 'splitByRow= splitInRow= split= useData= pdfn='.split())
except getopt.GetoptError as err:
# print help information and exit:
print(err)
print(f'Usage {os.path.basename(sys.argv[0])} [--splitByRow=num] [--splitInRow=num] [--split=num] [--useData=] --pdfn=')
sys.exit(2)
else:
splitByRow = 1
splitInRow = 0
split = 36
pdfn = None
useData = 0
for k, v in opts:
if k=='--splitByRow':
splitByRow = int(v)
elif k=='--splitInRow':
splitInRow = int(v)
elif k=='--split':
split = float(v)
if int(split)==split: split=int(split)
elif k=='--useData':
useData = int(v)
elif k=='--pdfn':
pdfn = v
else:
raise ValueError(f'Unknown option name {k}={v}')
class IndicatorTable(Table):
def draw(self):
Table.draw(self)
c = self.canv
x = self._width
y = self._height - split
c.setStrokeColor(colors.toColor('red'))
c.setLineWidth(0.5)
c.setDash([2,2])
c.line(0,y,x+13,y)
story = []
storyAdd = story.append
styleSheet = getSampleStyleSheet()
btStyle = styleSheet['BodyText']
def makeTable(klass=Table):
if useData==0:
data= [['00', '01', '02', '03', '04'],
['10', '11', '12', '13', '14'],
['20', '21', '22', '23', '24'],
['30', '31', '32', '33', '34']]
data= [['00\n\naa', '01', '02', '03', '04'],
['10', '11\nbb', '12', '13', '14'],
['20', '21', '22\ncc', '23', '24'],
['30', '31', '32', '33\ndd', '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),
('BACKGROUND', (1, 1), (1, 2), colors.lavender),
('BACKGROUND', (2, 2), (2, 3), colors.orange),
('TEXTCOLOR',(0,-1),(-2,-1),colors.green),
]
elif useData==1:
data= [['A', 'BBBBB', 'C', 'D', 'E'],
['00', '01', '02', '03', '04'],
['10\n11', ],
['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 row 3 across all columns
('SPAN',(0,2),(-1,2)),
#span 'AAA' down first two rows
('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'),
]
else:
raise ValueError(f'useData should be in [0,1] not {useData}')
return klass(data,
style=sty,
splitInRow=splitInRow,
splitByRow=splitByRow,
)
storyAdd(Paragraph("Illustrating splits: nosplit", btStyle))
storyAdd(makeTable(klass=IndicatorTable))
storyAdd(Spacer(0,6))
def addSplitTable(size=30):
t = makeTable()
S = t.split(4*inch,size)
if not S:
storyAdd(Paragraph(f"<span color=red>Illustrating splits failed</span>: split(4in,{size}) {splitByRow=} {splitInRow=}", btStyle))
storyAdd(Spacer(0,6))
#print('!!!!! Failed')
else:
#print('##### OK')
storyAdd(Paragraph(f"Illustrating splits: split(4in,{size}) {splitByRow=} {splitInRow=}", btStyle))
storyAdd(Spacer(0,6))
for s in S:
storyAdd(s)
storyAdd(Spacer(0,6))
addSplitTable(split)
pdfn = pdfn or f'{os.path.basename(os.path.splitext(sys.argv[0])[0])}-{splitByRow!s}-{splitInRow!s}-{split!s}.pdf'
doc = SimpleDocTemplate(pdfn, showBoundary=0)
doc.build(story)
print(f'Saved {pdfn}')
if __name__=='__main__':
main()