[reportlab-users] Long word or URI doesn't wrap inside table cell

Robin Becker robin at reportlab.com
Fri Dec 1 06:12:05 EST 2023


On 30/11/2023 14:00, Manuel Koch wrote:
> Creating a table with cells that contain long words doesn’t seem to work as expected, i.e. the words are not wrapped automatically inside the paragraphs and the table cell breaks page layout by being too wide.
> Additionally the rendered text of the URI contains strange characters ( „;“ ) that are not in the original text used to create the paragraph.
> 
> How can long word wrapping by controlled for a paragraph inside a table cell ?
> 
> Here is a minimal code ( using macOS Sonoma, arm64, python==3.10, reportlab==3.6.11 ):
> 
Hi Manuel,

again thanks for this report. I looked at the _calcPreliminaryWidths code and it seems we need to handle the case when 
the predicted remaining space is non-positive. I tried this diff which seems to fix your example.

It seems obvious that we cannot do anything if the defined column widths exceed the availWidth, but if there is space we 
can apply it to the unspecified columns  proportionately. I'm uncertain as to whether we should just try and scale the 
totalMinimum/minimums at line 849 to make the if remaining > 0: true.


This is simple patch to handle the scaling directly.
diff -r 2575e5f684b1 src/reportlab/platypus/tables.py
--- a/src/reportlab/platypus/tables.py	Mon Nov 13 13:15:30 2023 +0000
+++ b/src/reportlab/platypus/tables.py	Fri Dec 01 10:57:32 2023 +0000
@@ -925,8 +925,10 @@
                      assert adjusted >= minimum
                      W[colNo] = adjusted
          else:
+            remaining = availWidth - totalDefined
+            adj = 1 if remaining<=0 else remaining/totalMinimum
              for colNo, minimum in minimums.items():
-                W[colNo] = minimum
+                W[colNo] = minimum * adj
          #if verbose: print('new widths are:', W)
          self._argW = self._colWidths = W
          return W




> import re
> from pathlib import Path
> 
> from reportlab.lib import colors
> from reportlab.lib.pagesizes import portrait, A4
> from reportlab.lib.styles import getSampleStyleSheet
> from reportlab.lib.units import cm
> from reportlab.platypus import Paragraph, TableStyle, Table, Image
> 
> PAGE_SIZE = portrait(A4)
> PAGE_MARGIN_TOP = 2 * cm
> PAGE_MARGIN_LEFT = 0.7 * cm
> PAGE_MARGIN_RIGHT = 0.7 * cm
> PAGE_MARGIN_BOTTOM = 1 * cm
> PAGE_CONTENT_WIDTH = PAGE_SIZE[0] - PAGE_MARGIN_LEFT - PAGE_MARGIN_RIGHT
> PAGE_CONTENT_HEIGHT = PAGE_SIZE[1] - PAGE_MARGIN_TOP - PAGE_MARGIN_BOTTOM
> 
> LEADING_FACTOR = 1.25
> 
> BODY_TEXT_STYLE_NAME = "BodyText"
> BODY_TEXT_FONT_NAME = "Roboto" # you can use "Courier" too, same problem
> BODY_TEXT_FONT_SIZE = 12
> 
> STYLES = getSampleStyleSheet()
> BODY_TEXT_STYLE = STYLES[BODY_TEXT_STYLE_NAME]
> BODY_TEXT_STYLE.fontName = BODY_TEXT_FONT_NAME
> BODY_TEXT_STYLE.fontSize = BODY_TEXT_FONT_SIZE
> BODY_TEXT_STYLE.leading = BODY_TEXT_FONT_SIZE * LEADING_FACTOR
> BODY_TEXT_STYLE.wordWrap = True # this has no effect whatsoever, commenting it out does not improve anything
> BODY_TEXT_STYLE.splitLongWords = True # this has no effect whatsoever, commenting it out does not improve anything
> BODY_TEXT_STYLE.uriWasteReduce = 0.0001 # using a greater value make things sometimes even worse
> 
> 
> def create_pdf():
>     output_path = Path.home() / "tmp" / "test.pdf"
>     doc = DocTemplate(
>         output_path.as_posix(),
>         pagesize=PAGE_SIZE,
>         topMargin=PAGE_MARGIN_TOP,
>         leftMargin=PAGE_MARGIN_LEFT,
>         rightMargin=PAGE_MARGIN_RIGHT,
>         bottomMargin=PAGE_MARGIN_BOTTOM,
>         showBoundary=True,
>     )
>     paragraphs = [
>         Paragraph("Test Text", style=BODY_TEXT_STYLE),
>         Paragraph(
>             "Test Text averyveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryvveryveryverylongword",
>             style=BODY_TEXT_STYLE),
>         Paragraph(
> 
>             "Label: This is text with a long URI https://www.foo.com/hello/world/this/is/a/very/long/website/path/11111/222222/?abc=123&def=756&ghj=888",
>             style=BODY_TEXT_STYLE),
>     ]
>     cells = [
>         [
>             paragraphs,
>             [Image(create_placeholder_image(200, 200), width=3.5 * cm, height=3.5 * cm)],
>         ]
>     ]
>     table = Table(
>         cells,
>         colWidths=[
>             "*",
>             4 * cm,
>         ],
>     )
>     table.setStyle(
>         TableStyle(
>             [
>                 # align image and qr
>                 ("ALIGN", (0, 0), (-1, -1), "CENTER"),
>                 ("VALIGN", (0, 0), (-2, -1), "CENTER"),
>                 ("VALIGN", (-1, 0), (-1, -1), "TOP"),
>                 # force padding
>                 ("TOPPADDING", (0, 0), (-1, -1), 0),
>                 ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
>                 ("LEFTPADDING", (0, 0), (-1, -1), 0),
>                 ("RIGHTPADDING", (0, 0), (-1, -1), 0),
>                 # table borders, for debugging
>                 ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.red),
>                 ("BOX", (0, 0), (-1, -1), 0.25, colors.red),
>             ]
>         )
>     )
>     flowables = [table]
>     doc.build(flowables)
>     print(f"Saved {output_path}")
> 
> 
> if __name__ == "__main__":
>     create_pdf()
> 
> [cid:5591b93c-b892-4172-bd9b-c8f4878ff8cf at EURP191.PROD.OUTLOOK.COM]
> 
> 
> _______________________________________________
> reportlab-users mailing list
> reportlab-users at lists2.reportlab.com
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users

-- 
Robin Becker



More information about the reportlab-users mailing list