'`reportlab` table cell's height exceeding height of the page
I have data for some applications and I want to generate PDF files of the applications using reportlab
.
The template to create PDF files was given to me and has nested tables. And these tables are created dynamically. (I know neither how man tables are there nor I know how many rows has a table.)
As a result I get Flowable <Table@0x7FF8E07B5210 1 rows x 1 cols(tallest row 1305)> with cell(0,0) containing
error. Because at least height of one table exceeds height of the page.
This table could have a second Sequence
and that would definitely make the height of the table bigger than the page.
How to make a table spread between multiple pages using reportlab
?
Solution 1:[1]
It is not possible to render any portion of some particular table on finite page size, without changing the structure of the table. "Spread between multiple pages" actually means that - changing structure of the table.
For example if we have problematic table
| foo | bar |
| |-----|
| | baz |
it needs to be changed to
| foo | bar |
|-----|-----|
| foo | baz |
to overcome this limitation.
Reportlab cannot do that as it is tricky (although doesn't feel tricky). It has splitByRow
option but it just raises NotImplementedError
for falsy values.
You can try to preprocess data, capture sizes and modify structure.
Here's concept how it could be done for simple cases:
from reportlab.lib.randomtext import chomsky
from reportlab.platypus.tables import Table, GRID_STYLE
from reportlab.platypus import SimpleDocTemplate, LayoutError
from reportlab.lib import pagesizes
import random
def split_heights(vs, availableHeight):
res = []
for v in vs:
if sum(res) + v < availableHeight:
res.append(v)
else:
yield res
res = [v]
yield res
def split_data(data, rowHeights):
i = 0
for item in rowHeights:
chunk = []
for _ in item:
chunk.append(data[i])
i += 1
yield chunk
def phase1(data, dest):
template = SimpleDocTemplate(dest, pagesize=pagesizes.A4)
inner_table = Table(data, style=GRID_STYLE)
outer_table = Table([['Sequences', inner_table]], style=GRID_STYLE)
flowables = [outer_table]
try:
template.build(flowables)
except LayoutError as e:
rowHeights = inner_table._rowHeights
frame = template.frame
availableHeight = frame._aH
return list(split_heights(rowHeights, availableHeight))
def phase2(data, dest, rowHeights):
tables = []
for chunk in split_data(data, rowHeights):
tables.append(Table(chunk, style=GRID_STYLE))
data_ = [['Sequences', table] for table in tables]
flowables = [Table(data_, style=GRID_STYLE)]
template = SimpleDocTemplate(dest, pagesize=pagesizes.A4)
template.build(flowables)
def main():
data = [[chomsky(random.randint(2,5))] for c in range(10)]
dest = "test1.pdf"
rowHeights = phase1(data, dest)
if rowHeights is None:
return
phase2(data, dest, rowHeights)
if __name__ == "__main__":
main()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | mugiseyebrows |