Tables can be built either using cells
or with write_html
.
There is a method to build tables allowing for multilines content in cells:
from fpdf import FPDF
data = (
("First name", "Last name", "Age", "City"),
("Jules", "Smith", "34", "San Juan"),
("Mary", "Ramos", "45", "Orlando"),
("Carlson", "Banks", "19", "Los Angeles"),
("Lucas", "Cimon", "31", "Saint-Mahturin-sur-Loire"),
)
pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", size=10)
line_height = pdf.font_size * 2.5
col_width = pdf.epw / 4 # distribute content evenly
for row in data:
for datum in row:
pdf.multi_cell(col_width, line_height, datum, border=1, ln=3, max_line_height=pdf.font_size)
pdf.ln(line_height)
pdf.output('table_with_cells.pdf')
An alternative method using fpdf.HTMLMixin
,
with the same data
as above, and column widths defined as percent of the effective width:
from fpdf import FPDF, HTMLMixin
class PDF(FPDF, HTMLMixin):
pass
pdf = PDF()
pdf.set_font_size(16)
pdf.add_page()
pdf.write_html(
f"""<table border="1"><thead><tr>
<th width="25%">{data[0][0]}</th>
<th width="25%">{data[0][1]}</th>
<th width="15%">{data[0][2]}</th>
<th width="35%">{data[0][3]}</th>
</tr></thead><tbody><tr>
<td>{'</td><td>'.join(data[1])}</td>
</tr><tr>
<td>{'</td><td>'.join(data[2])}</td>
</tr><tr>
<td>{'</td><td>'.join(data[3])}</td>
</tr><tr>
<td>{'</td><td>'.join(data[4])}</td>
</tr></tbody></table>""",
table_line_separators=True,
)
pdf.output('table_html.pdf')
The following recipe demonstrates a solution to handle this requirement:
from fpdf import FPDF
TABLE_COL_NAMES = ("First name", "Last name", "Age", "City")
TABLE_DATA = (
("Jules", "Smith", "34", "San Juan"),
("Mary", "Ramos", "45", "Orlando"),
("Carlson", "Banks", "19", "Los Angeles"),
("Lucas", "Cimon", "31", "Angers"),
)
pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", size=16)
line_height = pdf.font_size * 2
col_width = pdf.epw / 4 # distribute content evenly
def render_table_header():
pdf.set_font(style="B") # enabling bold text
for col_name in TABLE_COL_NAMES:
pdf.cell(col_width, line_height, col_name, border=1)
pdf.ln(line_height)
pdf.set_font(style="") # disabling bold text
render_table_header()
for _ in range(10): # repeat data rows
for row in TABLE_DATA:
if pdf.will_page_break(line_height):
render_table_header()
for datum in row:
pdf.cell(col_width, line_height, datum, border=1)
pdf.ln(line_height)
pdf.output("table_with_headers_on_every_page.pdf")
Note that if you want to use multi_cell()
method instead of cell()
,
some extra code will be required: an initial call to multi_cell
with split_only=True
will be needed in order to compute the number of lines in the cell.