py-pdf / fpdf2

Simple PDF generation for Python
https://py-pdf.github.io/fpdf2/
GNU Lesser General Public License v3.0
1.06k stars 243 forks source link

Multicell wrapping not working #473

Closed mangoez closed 2 years ago

mangoez commented 2 years ago

I tried stack overflow but to no avail, this is probably not a bug but I couldn't find any other way to fix the issue. All I want to automatic raw height and text wrapping! Please let me know what I can do, cheers.

Here is a reproducible example and what it outputs:

from fpdf import FPDF
import pandas as pd

# Detail box
detail_dict = {
    "Pipeline ID": "12345",
    "Date": "31/12/1999",
    "Description": "Meep morp, shoot zappy bois into noggin for science",
    "Dataset": "MNE default finger tapping dataset"
}

detail_col = ["Detail", "Description"]
detail_df = pd.DataFrame(list(zip(list(detail_dict.keys()), list(detail_dict.values()))), columns=detail_col)
detail_df.head()

# A cell is a rectangular area, possibly framed, which contains some text
# Set the width and height of cell
table_cell_width = pdf.epw / detail_df.shape[1]
table_cell_height = pdf.font_size * 2.5

pdf = FPDF()
pdf.add_page()
pdf.set_font('Arial', 'B', 8)

# Loop over to print column names
cols = detail_df.columns
for col in cols:
    pdf.cell(table_cell_width, table_cell_height, col, border=1)

# Line break
pdf.ln(table_cell_height)
# Select a font as Arial, regular, 10
pdf.set_font('Arial', '', 10)

table_cell_heights = [] #list with proper table_cell_height for each row
use_default_height = 0 #flag

#create table_cell_heights of table_cell_heights which size is equal to num rows of data
for row in detail_df.itertuples():
    for col in cols:
        value = str(getattr(row, col))
        word_list = value.split(" ")
        number_of_words = len(word_list) #how many words
        # print(value, number_of_words)
        if number_of_words>2: #names and cities formed by 2 words like Los Angeles are ok)
            use_default_height = 1
            new_table_cell_height = pdf.font_size * (number_of_words) #new height change according to data 
    if not use_default_height:
        table_cell_heights.append(table_cell_height)
    else:
        table_cell_heights.append(new_table_cell_height)
        use_default_height = 0

# Loop over to print each data in the table
# print(table_cell_heights)

row_count = 0
for row in detail_df.itertuples():
    for col in cols:
        value = str(getattr(row, col))
        pdf.multi_cell(table_cell_width, table_cell_heights[row_count], value, border=1, ln=3)
    row_count += 1
    pdf.ln(table_cell_height)

pdf.output('example.pdf')
2022-07-15 13_39_25-example pdf
Lucas-C commented 2 years ago

There is an example in the documentation that could help you: https://pyfpdf.github.io/fpdf2/Tables.html#using-cells

A useful parameter here is max_line_height. There is some starting point code based on what you shared:

from fpdf import FPDF
import pandas as pd

detail_dict = {
    "Pipeline ID": "12345",
    "Date": "31/12/1999",
    "Description": "Meep morp, shoot zappy bois into noggin for science",
    "Dataset": "MNE default finger tapping dataset"
}

detail_col = ["Detail", "Description"]
detail_df = pd.DataFrame(list(zip(list(detail_dict.keys()), list(detail_dict.values()))), columns=detail_col)
detail_df.head()

pdf = FPDF()
pdf.add_page()
pdf.set_font('Helvetica', 'B', 8)

table_cell_width = pdf.epw / detail_df.shape[1]
table_cell_height = pdf.font_size * 2.5

cols = detail_df.columns
for col in cols:
    pdf.cell(table_cell_width, table_cell_height, col, border=1)
pdf.ln(table_cell_height)

pdf.set_font('Helvetica', '', 10)
for row in detail_df.itertuples():
    for col in cols:
        line = str(getattr(row, col))
        pdf.multi_cell(table_cell_width, table_cell_height, line, border=1,
                       new_x="RIGHT", new_y="TOP", max_line_height=pdf.font_size)
    pdf.ln(table_cell_height)

pdf.output('issue_473.pdf')

Does that solve your issue?

Lucas-C commented 2 years ago

@mangoez: are you still facing this problem? Do you still have questions / need help or can this issue be closed?

mangoez commented 2 years ago

Hi @Lucas-C thank you for your assistance! All good :)