I tried to generate PDF invoices in Python
using reportlab
.
The invoices will be one page only and there will never be more details than there is space on that single page; my code checks max number of details before generating the PDF.
Right now I'm using SimpleDocTemplate
to add everything to the page, and to structure the details I am using a Table
.
Here is a reduced code sample:
from reportlab.lib.units import mm
from reportlab.platypus import Paragraph, Spacer, Table, TableStyle
from reportlab.platypus import SimpleDocTemplate
# add invoice header
flowable_list = [
Spacer(1, 5*mm),
Paragraph('Date: ...', pg_style_1),
Spacer(1, 5*mm),
]
# add invoice details
detail_list = [
('Item 1', 8, 45),
('Item 2', 1, 14),
]
row_list = [
[
Paragraph(desc, pg_style_1),
quantity,
amount,
]
for desc, quantity, amount in detail_list]
story.append(
Table(
data=row_list,
colWidths=[100*mm, 40*mm, 40*mm],
style=TableStyle([
('VALIGN', (0, 0), (-1, -1), 'TOP'),
... some other options ...
])))
# add invoice footer; this should be at a specific position on the page
flowable_list.append(Spacer(1, 5*mm))
flowable_list.append(Paragraph('Total: 0', pg_style_1))
# build PDF
buffer = io.BytesIO()
doc = SimpleDocTemplate(buffer)
doc.build(flowable_list)
My problem: the total amounts at the bottom have to be at a specific location every time (something like x*mm
from the bottom), but there can be a variable number of details which causes the details table to have a non-fixed height.
My current solution: adding a Spacer
after the table; the height of this spacer has to be calculated based on the number of rows in the table (more rows mean that the spacer will be smaller; less rows produce a bigger spacer). But this fails if one of the rows wraps around and takes up more space than a single row.
My question: is there a way to set a fixed height for the details table, no matter how many rows there will be, but still keep using SimpleDocTemplate
?
This similar question shows a solution that draws everything manually onto the canvas, but I would like a way to keep using the SimpleDocTemplate
, if it is possible.