Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multi-lines text in table cells with write_html #91

Closed
Lucas-C opened this issue Jan 23, 2021 · 6 comments
Closed

Support multi-lines text in table cells with write_html #91

Lucas-C opened this issue Jan 23, 2021 · 6 comments

Comments

@Lucas-C
Copy link
Member

Lucas-C commented Jan 23, 2021

Example HTML to use:

<table border="1"><thead><tr>
    <th width="30%">First name</th><th width="30%">Last name</th><th width="15%">Age</th><th width="25%">City</th>
</tr></thead><tbody><tr>
    <td>Jean Abdul William</td><td>Smith</td><td>34</td><td>San Juan</td>
</tr></tbody></table>

The text in the first cell of the first row currently overflows.

A starting point would be to add a dedicated test in test_html.py.

In terms of code, some changes could be made in HTML2FPDF.handle_data in order to call self.pdf.multi_cell(... ln=3) instead of FPDF.cell. Inspiration could be taken from this test: https://github.com/PyFPDF/fpdf2/blob/master/test/cells/test_multi_cell.py#L85 Corresponding output: https://github.com/PyFPDF/fpdf2/blob/master/test/cells/multi_cell_ln_3_table.pdf

This issue can count as part of hacktoberfest

@Lucas-C Lucas-C changed the title Support multi-lines text in write_html Support multi-lines text in table cells with write_html Jan 23, 2021
@RubendeBruin
Copy link

RubendeBruin commented Apr 4, 2021

As contribution, I modified the write-table-example such that the whole row is increased in height:

data = (
    ("First name", "Last name", "Age", "City"),
    ("Jules", "Smith", "34", "San Juan"),
    ("Mary", "Ramos\n \n Ramos \n    Ramos", "45", "Orlando"),
    ("Lucas", "Cimon", "Saint-Mahturin-sur-Loire - it may even be so long that multiple lines are needed to write it down completely", "49"),
    ("Carlson", "Banks", "19", "Los Angeles"),
)

line_height = pdf.font_size * 1.5
col_width = pdf.epw /6   # distribute content evenly

for row in data:

    row_height_lines = 1
    lines_in_row = []
    for datum in row: # determine height of highest cell
        output = pdf.multi_cell(col_width, line_height, datum, border=1, ln=3, split_only=True)
        lines_in_row.append(len(output))
        if len(output) > row_height_lines:
            row_height_lines = len(output)

    for tlines , datum in zip(lines_in_row, row):
        # here you can hack-in the
        text =datum.rstrip('\n') + (1 + row_height_lines - tlines) * '\n'
        pdf.multi_cell(col_width, line_height, text, border=1, ln=3)
    pdf.ln(row_height_lines * line_height)

image

@Lucas-C
Copy link
Member Author

Lucas-C commented Apr 13, 2021

Thank you for sharing this code snippet @RubendeBruin

Yes, I think this is a good start, and this approach could be used in HTML2FPDF.handle_data to implement this feature.

@RubendeBruin
Copy link

Hi @Lucas-C , I've stated to implement this.

Only the text is quite straight forward with multi_cell. Adding the borders and background is more tricky as you need to know the height of the cell which may be dictated by unprocessed cells right of it.

To draw the borders and cell backgrounds you need to parse the whole row. handle_data only gives information about the current cell. I do not see an easy way to look ahead in the parser to see what is coming. This means I need to log all the cell info in handle_data until I reach the end of a row ( tag) and then process it.

Most logical implementation I think is to build a dataset with row data and process that when handle_endtag encounters a tr:

  • handle_starttag : prepare an empty list for cell data
  • _insert_td : adds to the cell-data list, includes the x-position from self._td_x()
  • handle_endtag : processes the cell-data: look at the number of text-rows in each of the cells. Append shorter cells with '\n' to make all the texts have the same number of rows (for drawing the border)

Would this make sense or is there an easier way?

@Lucas-C
Copy link
Member Author

Lucas-C commented Aug 17, 2021

Sounds reasonable to me!

This is very likely to induce some refactoring though.
Feel free to get rid of some properties, like self.table_col_index or self.table_col_width, if they are not needed anymore with this new approach!

@Lucas-C
Copy link
Member Author

Lucas-C commented Mar 23, 2022

Status update: PRs attempts have been closed, this issue is open for contributions!

@Lucas-C
Copy link
Member Author

Lucas-C commented Apr 14, 2023

Since #703 has been released,multi-lines content in cells is now supported!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants