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.
- You have a website that sells tickets,
- the data ends up in a database,
- 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:
- Build the PDF from scratch every time
- Have a template PDF (all the artwork is done, there are some empty slots that can be filled with data)
- 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()