pythonborb

Make a full width table using Borb


I'm trying to reduce the margins of a page using borb, that works, but my Table then is not taking the full width of the page.

Please note that not only Table is shifted and not covering the full width, HorizontalRule as well etc...

What's the fix for that ?

from decimal import Decimal

from borb.pdf import Document, Page, SingleColumnLayout, PageLayout, Paragraph, Image, PDF


def main():

    # Create document
    pdf = Document()

    # Add page
    page = Page()
    pdf.add_page(page)

    # create PageLayout
    page_layout: PageLayout = SingleColumnLayout(page)

    for i in [Decimal(0), Decimal(16), Decimal(32), Decimal(64)]:

        page_layout._margin_left = i
        page_layout._margin_right = i
        page_layout._margin_bottom = i
        page_layout._margin_top = i

        # Add Paragraph
        page_layout.add(Paragraph(f"padding set at {int(i)}"))
        page_layout.add(
            FixedColumnWidthTable(
                number_of_columns=3, number_of_rows=3
            )
        )

    with open("output.pdf", "wb") as out_file_handle:
        PDF.dumps(out_file_handle, pdf)

if __name__ == "__main__":
    main()

Here's what I would like.


Solution

  • disclaimer: I am the author of borb

    The "issue" you are running into is that borb applies a sensible default for margins (on Image objects).

    Looking at the (constructor) code in Image:

                margin_bottom=margin_bottom if margin_bottom is not None else Decimal(5),
                margin_left=margin_left if margin_left is not None else Decimal(5),
                margin_right=margin_right if margin_right is not None else Decimal(5),
                margin_top=margin_top if margin_top is not None else Decimal(5),
    

    So you explicitly need to pass margin_left=Decimal(0) (and other) to have an Image whose total distance to the page-boundary is exactly as specified.

    Update (for adding Table objects):

    The main issue is that PageLayout also keeps track of the available width, which is used by a FixedColumnWidthTable but not by the Image.

    So, your code needs to change that as well.

    from decimal import Decimal
    
    from borb.pdf import Document, Page, SingleColumnLayout, PageLayout, Paragraph, Image, PDF, FixedColumnWidthTable
    
    
    def main():
    
        # Create document
        pdf = Document()
    
        # Add page
        page = Page()
        pdf.add_page(page)
    
        # create PageLayout
        page_layout: PageLayout = SingleColumnLayout(page)
    
        for i in [Decimal(0), Decimal(16), Decimal(32), Decimal(64)]:
    
            # change margin
            # IMPORTANT:    you are not supposed to do this after having created
            #               the PageLayout
            page_layout._margin_left = i
            page_layout._margin_right = i
            page_layout._margin_bottom = i
            page_layout._margin_top = i
            page_layout._column_widths = [Decimal(595) - i - i]
    
            # Add Paragraph
            page_layout.add(Paragraph(f"padding set at {int(i)}"))
            page_layout.add(
                FixedColumnWidthTable(
                    number_of_columns=2, number_of_rows=3
                ).add(Paragraph("Lorem"))
                .add(Paragraph("Ipsum"))
                .add(Paragraph("Dolor"))
                .add(Paragraph("Sit"))
                .add(Paragraph("Amet"))
                .add(Paragraph("Consectetur"))
            )
    
        with open("output.pdf", "wb") as out_file_handle:
            PDF.dumps(out_file_handle, pdf)
    
    if __name__ == "__main__":
        main()
    

    Which outputs the following PDF:

    enter image description here