How to fill a pdf with python

174 Views Asked by At

I don't have a concrete project yet, but in anticipation I would like to know if it is possible to fill a pdf with data stored in mysql?

It would be a question of a form with several lines and column history not to simplify the thing... If yes, what technology/language to use?

I found several tutorials which however start from a blank pdf. I have the constraint of having to place the data in certain specific places.

3

There are 3 best solutions below

0
On

Using PyMuPDF makes it easy to place text at any desired position using any desired font.

To e.g. put some text on a page starting at position (x, y) do this:

import fitz  # import the package
doc = fitz.open("your.pdf")
page = doc[0]  # desired page, here: page 0
# insert starti 50 points from left, 36 points from top
page insert_text((50, 36), text)  # insert starts here

Or insert into a rectangle with automatic line breaks at word boundaries

rect = fitz.Rect(50, 36, 150, 236)  # define rectangle
page.insert_textbox(rect, text)

Rectangles are defined by their top-left (50,36) and bottom-right (150, 236) coordinates. So in the above case a 100 x 200 rectangle.

0
On

Try using PyFPDF or ReportLab to create and manipulate PDF documents in Python.

0
On

Disclaimer: I am the author of borb, the library used in this answer.

You are essentially trying to build a customized PDF based on some data. Let's use the example of generating concert tickets.

  1. You have a website that sells tickets,
  2. the data ends up in a database,
  3. whenever someone wants to print their tickets, you need to build a PDF with their custom data (name, first name, seat numbers, QR code, etc)

There are several things you could do to achieve your goal:

  1. Build the PDF from scratch every time
  2. Have a template PDF (all the artwork is done, there are some empty slots that can be filled with data)
  3. Have a template PDF (all the artwork is done, the PDF contains form elements that can be filled with data)

Option 2 and 3 and typically used in industry, because the people designing the tickets (artwork, layout, etc) are not the people that will write the code needed to build the PDF.

Using borb, you can place content at exact locations:

from borb.pdf import Document
from borb.pdf import Page
from borb.pdf import Paragraph
from borb.pdf import PDF
from borb.pdf.canvas.geometry.rectangle import Rectangle

from decimal import Decimal


def main():
    # create Document
    doc: Document = Document()

    # create Page
    page: Page = Page()

    # add Page to Document
    doc.add_page(page)

    # define layout rectangle
    # fmt: off
    r: Rectangle = Rectangle(
        Decimal(59),                # x: 0 + page_margin
        Decimal(848 - 84 - 100),    # y: page_height - page_margin - height_of_textbox
        Decimal(595 - 59 * 2),      # width: page_width - 2 * page_margin
        Decimal(100),               # height
    )
    # fmt: on

    # the next line of code uses absolute positioning
    Paragraph("Hello World!").paint(page, r)

    # store
    with open("output.pdf", "wb") as pdf_file_handle:
        PDF.dumps(pdf_file_handle, doc)


if __name__ == "__main__":
    main()

You can also fill forms:

from decimal import Decimal

from borb.pdf import HexColor
from borb.pdf import PageLayout
from borb.pdf import Document
from borb.pdf import Page
from borb.pdf import PDF


def main():

    # open document
    doc: typing.Optional[Document] = None
    with open("output.pdf", "rb") as pdf_file_handle:
        doc = PDF.loads(pdf_file_handle)
    assert doc is not None

    # set
    doc.get_page(0).set_form_field_value("name", "Schellekens")
    doc.get_page(0).set_form_field_value("firstname", "Joris")
    doc.get_page(0).set_form_field_value("country", "Belgium")

    # store
    with open("output.pdf", "wb") as pdf_file_handle:
        PDF.dumps(pdf_file_handle, doc)


if __name__ == "__main__":
    main()