404
+ +Page not found
+ + +diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..67ad7120 --- /dev/null +++ b/404.html @@ -0,0 +1,132 @@ + + +
+ + + + +Page not found
+ + +Similar to text fields discussed in the last chapter, PyPDFForm gives you the ability to +modify some styles of checkboxes and radio buttons without changing the template.
+You can change the size of the selection by specifying a float
value. Consider
+this PDF:
from PyPDFForm import PdfWrapper
+
+form = PdfWrapper("sample_template.pdf")
+form.widgets["check"].size = 50
+form.widgets["check_2"].size = 40
+form.widgets["check_3"].size = 60
+
+form.fill(
+ {
+ "check": True,
+ "check_2": True,
+ "check_3": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(form.read())
+
+The button style is the shape of the selection on a checkbox or radio button. PyPDFForm lets you pick
+three different button styles: check
, circle
, and cross
. Consider
+this PDF:
from PyPDFForm import PdfWrapper
+
+form = PdfWrapper("sample_template_with_radio_button.pdf")
+form.widgets["radio_1"].button_style = "cross"
+form.widgets["radio_2"].button_style = "circle"
+form.widgets["radio_3"].button_style = "check"
+
+form.fill(
+ {
+ "radio_1": 0,
+ "radio_2": 1,
+ "radio_3": 2,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(form.read())
+
+
+ The coordinate system on a single page of a PDF starts at the bottom left of the page as the origin. The unit of +the coordinates is called "points" and there are 72 points/inch. PyPDFForm utilizes this coordinate system in +some of its APIs so that widgets, texts, or images can be created on a PDF.
+To allow a better user experience with the coordinate system, PyPDFForm implements a grid view so that there is a +better idea on where stuffs should be placed on a PDF.
+Consider this PDF, the +coordinate grid view can be generated like this:
+from PyPDFForm import PdfWrapper
+
+grid_view_pdf = PdfWrapper(
+ "sample_template.pdf"
+).generate_coordinate_grid(
+ color=(1, 0, 0), # optional
+ margin=100 # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(grid_view_pdf.read())
+
+The generate_coordinate_grid
method takes two optional parameters. The first one is color
which allows you to pick
+a color for the grid view. The default color is red. The second one is margin
which allows you to change the
+coordinate grid view's margin in points. The default margin is 100 points.
PyPDFForm allows you to draw certain elements on a PDF. The purpose is in case there is a missing widget on your PDF +form, and you need to put certain texts on it, or if you need to draw images.
+This section of the documentation will use +this PDF as an example.
+This section of the documentation requires a basic understanding of the PDF coordinate system.
+All optional parameters will have a comment # optional
after each of them.
NOTE: Due to a known bug in a dependency, it is advised that these draw methods are called after +a PDF form is filled. Otherwise, part (most noticeably radio buttons) or even all widgets of the PDF form might +get removed after drawing things on it.
+from PyPDFForm import PdfWrapper
+
+pdf = PdfWrapper("sample_template.pdf").draw_text(
+ text="random text",
+ page_number=1,
+ x=300,
+ y=225,
+ font="your_registered_font", # optional
+ font_size=12, # optional
+ font_color=(1, 0, 0) # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(pdf.read())
+
+from PyPDFForm import PdfWrapper
+
+pdf = PdfWrapper("sample_template.pdf").draw_image(
+ image="sample_image.jpg",
+ page_number=1,
+ x=100,
+ y=100,
+ width=400,
+ height=225,
+ rotation=0 # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(pdf.read())
+
+
+ PyPDFForm uses a single depth, non-nested dictionary to fill a PDF form. As a result of this process, the filled +PDF form will be flattened and no longer editable. This is to prevent future encoding issues, especially when +multiple PDF forms with overlaps on widget names are combined together.
+As seen when we
+inspected this PDF, a text
+field can be filled with a value of string
, whereas a checkbox can be filled with a boolean
value:
from PyPDFForm import PdfWrapper
+
+filled = PdfWrapper("sample_template.pdf").fill(
+ {
+ "test": "test_1",
+ "check": True,
+ "test_2": "test_2",
+ "check_2": False,
+ "test_3": "test_3",
+ "check_3": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(filled.read())
+
+A radio button group on a PDF form is a collection of radio buttons that share the same name.
+A PDF form
+with radio button groups can be filled using integer
values where the value indicates which radio button to select
+among each radio button group:
from PyPDFForm import PdfWrapper
+
+filled = PdfWrapper("sample_template_with_radio_button.pdf").fill(
+ {
+ "radio_1": 0,
+ "radio_2": 1,
+ "radio_3": 2,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(filled.read())
+
+Similar to radio buttons, a dropdown choice can be selected by specifying an integer
value of the choice. Consider
+this PDF:
from PyPDFForm import PdfWrapper
+
+filled = PdfWrapper("sample_template_with_dropdown.pdf").fill(
+ {
+ "dropdown_1": 1
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(filled.read())
+
+A signature field widget allows you to sign a PDF form in a handwritten format. PyPDFForm lets you use a signature image to populate +any signature field widget.
+Consider this PDF +and this signature image:
+from PyPDFForm import PdfWrapper
+
+signed = PdfWrapper("sample_template_with_signature.pdf").fill(
+ {
+ "signature": "sample_signature.png"
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(signed.read())
+
+NOTE: As described here, the value of the signature in your dictionary can be
+a file path shown above, but also an open file object and a file stream that's in bytes
.
NOTE: This is a beta feature, meaning it still needs to be tested against more PDF forms and may not work for +some of them.
+An image field widget can be filled similarly to a signature field, by providing a value of file path, file object, or +file stream.
+Consider this PDF +and this image:
+from PyPDFForm import PdfWrapper
+
+filled = PdfWrapper("sample_template_with_image_field.pdf").fill(
+ {
+ "image_1": "sample_image.jpg"
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(filled.read())
+
+
+ PyPDFForm is a free and open source pure-Python 3 library for PDF form processing. It contains the essential +functionalities needed to interact with PDF forms:
+It also supports other common utilities such as extracting pages and merging multiple PDFs together.
+After a PDF form is prepared, PyPDFForm can be used to inspect names of all its widgets so that the data +that's needed to fill it can be determined. There are several different methods this can be done with and feel free +to choose the way that fits your needs the most.
+This section of the documentation will use +this PDF as an example.
+The first method of inspecting a PDF form is to generate a preview document. Each PdfWrapper
object contains an
+attribute .preview
which is a file stream that can be written to any disk file or memory buffer. Consider the
+following snippet:
from PyPDFForm import PdfWrapper
+
+preview_stream = PdfWrapper("sample_template.pdf").preview
+
+with open("output.pdf", "wb+") as output:
+ output.write(preview_stream)
+
+The generated preview PDF will have the name of each widget labeled on top of it in red.
+The dictionary that's used to fill a PDF form can be described using a JSON schema. For example:
+import json
+
+from PyPDFForm import PdfWrapper
+
+pdf_form_schema = PdfWrapper("sample_template.pdf").schema
+
+print(json.dumps(pdf_form_schema, indent=4, sort_keys=True))
+
+The above snippet will yield the following output:
+{
+ "properties": {
+ "check": {
+ "type": "boolean"
+ },
+ "check_2": {
+ "type": "boolean"
+ },
+ "check_3": {
+ "type": "boolean"
+ },
+ "test": {
+ "type": "string"
+ },
+ "test_2": {
+ "type": "string"
+ },
+ "test_3": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+}
+
+In this case sample_template.pdf
has three text fields named test
, test_2
, and test_3
because they all have
+a type of string
. It also has three checkboxes check
, check_2
, and check_3
due to their boolean
type.
The JSON schema generated by PyPDFForm can be used to validate against the data you use to fill a PDF form.
+Lastly, PyPDFForm can generate some sample data that can be directly used to fill a PDF form:
+from pprint import pprint
+
+from PyPDFForm import PdfWrapper
+
+pprint(PdfWrapper("sample_template.pdf").sample_data)
+
+The above snippet will give you a sample dictionary:
+{'check': True,
+ 'check_2': True,
+ 'check_3': True,
+ 'test': 'test',
+ 'test_2': 'test_2',
+ 'test_3': 'test_3'}
+
+
+ PyPDFForm is hosted on PyPI and any tool that supports downloading from it can be used. +The most common option is to use pip.
+PyPDFForm requires Python 3.8+.
+It is advised that a virtual environment is always created beforehand. Then you can run the following command to install:
+pip install PyPDFForm
+
+To upgrade PyPDFForm as well as all its dependencies, run:
+pip install -U PyPDFForm
+
+There are two classes provided by the library that abstract a PDF form. The FormWrapper
class allows you to fill a
+PDF form if you don't need any other API. More info about FormWrapper
can be found
+here.
The class that implements most of PyPDFForm's APIs is PdfWrapper
. It takes various optional parameters to instantiate,
+with the most important one being the PDF form "template".
For example, if you download this PDF, +you will want to instantiate your object like this:
+from PyPDFForm import PdfWrapper
+
+pdf = PdfWrapper("sample_template.pdf")
+
+PyPDFForm does implement an adapter for different ways Python interacts with files. So you can pass your PDF form to
+PdfWrapper
in three different ways: a file path, an open file object, and a file stream that's in bytes
.
This means the following two snippets are equivalent to the above:
+from PyPDFForm import PdfWrapper
+
+with open("sample_template.pdf", "rb+") as template:
+ pdf = PdfWrapper(template)
+
+from PyPDFForm import PdfWrapper
+
+with open("sample_template.pdf", "rb+") as template:
+ pdf = PdfWrapper(template.read())
+
+This adaptation is universal across all APIs of PyPDFForm. So in later sections of the documentation whenever you see +a function parameter that's a file path you can safely switch them for a file object or file stream.
+Lastly, PdfWrapper
also implements itself similar to an open file object. So you can write the PDF it holds to another
+file:
from PyPDFForm import PdfWrapper
+
+pdf = PdfWrapper("sample_template.pdf")
+
+with open("output.pdf", "wb+") as output:
+ output.write(pdf.read())
+
+And it doesn't have to be a disk file, it can be a memory buffer as well:
+from io import BytesIO
+
+from PyPDFForm import PdfWrapper
+
+pdf = PdfWrapper("sample_template.pdf")
+
+with BytesIO() as output:
+ output.write(pdf.read())
+
+
+ The most common tool to create a PDF form is Adobe Acrobat. A tutorial can be found +here. +There are other free alternatives like DocFly that support similar functionalities.
+Given a PDF that's not a form yet, PyPDFForm also supports +creating a subset of PDF form widgets on it through coding.
+This section of the documentation will use +this PDF as an example.
+This section of the documentation requires a basic understanding of the PDF coordinate system.
+All optional parameters will have a comment # optional
after each of them.
NOTE: For some PDF prep tools, creating widgets on their PDF forms may result in their original widgets getting +flattened (e.g., this PDF +which was prepared using Sejda). So it is advised that you fill them first +before creating any widget using PyPDFForm.
+A text field widget can be created by downloading the PDF and running the following snippet:
+from PyPDFForm import PdfWrapper
+
+new_form = PdfWrapper("dummy.pdf").create_widget(
+ widget_type="text",
+ name="new_text_field_widget",
+ page_number=1,
+ x=57,
+ y=700,
+ width=120, # optional
+ height=40, # optional
+ max_length=5, # optional
+ font="Courier", # optional
+ font_size=15, # optional
+ font_color=(1, 0, 0), # optional
+ bg_color=(0, 0, 1), # optional
+ border_color=(1, 0, 0), # optional
+ border_width=5 # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(new_form.read())
+
+A checkbox widget can be created using the same method with some changes to the parameters:
+from PyPDFForm import PdfWrapper
+
+new_form = PdfWrapper("dummy.pdf").create_widget(
+ widget_type="checkbox",
+ name="new_checkbox_widget",
+ page_number=1,
+ x=57,
+ y=700,
+ size=30, # optional
+ button_style="check", # optional
+ tick_color=(0, 1, 0), # optional
+ bg_color=(0, 0, 1), # optional
+ border_color=(1, 0, 0), # optional
+ border_width=5 # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(new_form.read())
+
+The button_style
parameter currently supports three options: check
, circle
, and cross
.
A dropdown widget shares a similar set of parameters as a text field, with the only significant difference being
+a list of options
needs to be specified:
from PyPDFForm import PdfWrapper
+
+new_form = PdfWrapper("dummy.pdf").create_widget(
+ widget_type="dropdown",
+ name="new_dropdown_widget",
+ page_number=1,
+ x=57,
+ y=700,
+ options=[
+ "foo",
+ "bar",
+ "foobar",
+ ],
+ width=120, # optional
+ height=40, # optional
+ font="Courier", # optional
+ font_size=15, # optional
+ font_color=(1, 0, 0), # optional
+ bg_color=(0, 0, 1), # optional
+ border_color=(1, 0, 0), # optional
+ border_width=5 # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(new_form.read())
+
+
+ ' + escapeHtml(summary) +'
' + noResultsText + '
'); + } +} + +function doSearch () { + var query = document.getElementById('mkdocs-search-query').value; + if (query.length > min_search_length) { + if (!window.Worker) { + displayResults(search(query)); + } else { + searchWorker.postMessage({query: query}); + } + } else { + // Clear results for short queries + displayResults([]); + } +} + +function initSearch () { + var search_input = document.getElementById('mkdocs-search-query'); + if (search_input) { + search_input.addEventListener("keyup", doSearch); + } + var term = getSearchTermFromLocation(); + if (term) { + search_input.value = term; + doSearch(); + } +} + +function onWorkerMessage (e) { + if (e.data.allowSearch) { + initSearch(); + } else if (e.data.results) { + var results = e.data.results; + displayResults(results); + } else if (e.data.config) { + min_search_length = e.data.config.min_search_length-1; + } +} + +if (!window.Worker) { + console.log('Web Worker API not supported'); + // load index in main thread + $.getScript(joinUrl(base_url, "search/worker.js")).done(function () { + console.log('Loaded worker'); + init(); + window.postMessage = function (msg) { + onWorkerMessage({data: msg}); + }; + }).fail(function (jqxhr, settings, exception) { + console.error('Could not load worker.js'); + }); +} else { + // Wrap search in a web worker + var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); + searchWorker.postMessage({init: true}); + searchWorker.onmessage = onWorkerMessage; +} diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 00000000..1cedb1d9 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Welcome to PyPDFForm PyPDFForm is a free and open source pure-Python 3 library for PDF form processing. It contains the essential functionalities needed to interact with PDF forms: Inspect what data a PDF form needs to be filled with. Fill a PDF form by simply creating a Python dictionary. Create a subset of form widgets on a PDF. It also supports other common utilities such as extracting pages and merging multiple PDFs together. User Guide Installation and setup PDF coordinates Prepare a PDF form Inspect a PDF form Fill a PDF form Fill a PDF form in place Change text field styles Change checkbox and radio button styles Draw stuffs Other utilities","title":"Welcome to PyPDFForm"},{"location":"#welcome-to-pypdfform","text":"PyPDFForm is a free and open source pure-Python 3 library for PDF form processing. It contains the essential functionalities needed to interact with PDF forms: Inspect what data a PDF form needs to be filled with. Fill a PDF form by simply creating a Python dictionary. Create a subset of form widgets on a PDF. It also supports other common utilities such as extracting pages and merging multiple PDFs together.","title":"Welcome to PyPDFForm"},{"location":"#user-guide","text":"Installation and setup PDF coordinates Prepare a PDF form Inspect a PDF form Fill a PDF form Fill a PDF form in place Change text field styles Change checkbox and radio button styles Draw stuffs Other utilities","title":"User Guide"},{"location":"button_style/","text":"Change checkbox and radio button styles Similar to text fields discussed in the last chapter, PyPDFForm gives you the ability to modify some styles of checkboxes and radio buttons without changing the template. Change size You can change the size of the selection by specifying a float value. Consider this PDF : from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\") form.widgets[\"check\"].size = 50 form.widgets[\"check_2\"].size = 40 form.widgets[\"check_3\"].size = 60 form.fill( { \"check\": True, \"check_2\": True, \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read()) Change button style The button style is the shape of the selection on a checkbox or radio button. PyPDFForm lets you pick three different button styles: check , circle , and cross . Consider this PDF : from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template_with_radio_button.pdf\") form.widgets[\"radio_1\"].button_style = \"cross\" form.widgets[\"radio_2\"].button_style = \"circle\" form.widgets[\"radio_3\"].button_style = \"check\" form.fill( { \"radio_1\": 0, \"radio_2\": 1, \"radio_3\": 2, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change checkbox and radio button styles"},{"location":"button_style/#change-checkbox-and-radio-button-styles","text":"Similar to text fields discussed in the last chapter, PyPDFForm gives you the ability to modify some styles of checkboxes and radio buttons without changing the template.","title":"Change checkbox and radio button styles"},{"location":"button_style/#change-size","text":"You can change the size of the selection by specifying a float value. Consider this PDF : from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\") form.widgets[\"check\"].size = 50 form.widgets[\"check_2\"].size = 40 form.widgets[\"check_3\"].size = 60 form.fill( { \"check\": True, \"check_2\": True, \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change size"},{"location":"button_style/#change-button-style","text":"The button style is the shape of the selection on a checkbox or radio button. PyPDFForm lets you pick three different button styles: check , circle , and cross . Consider this PDF : from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template_with_radio_button.pdf\") form.widgets[\"radio_1\"].button_style = \"cross\" form.widgets[\"radio_2\"].button_style = \"circle\" form.widgets[\"radio_3\"].button_style = \"check\" form.fill( { \"radio_1\": 0, \"radio_2\": 1, \"radio_3\": 2, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change button style"},{"location":"coordinate/","text":"PDF coordinates The coordinate system on a single page of a PDF starts at the bottom left of the page as the origin. The unit of the coordinates is called \"points\" and there are 72 points/inch. PyPDFForm utilizes this coordinate system in some of its APIs so that widgets, texts, or images can be created on a PDF. Generate a coordinate grid view To allow a better user experience with the coordinate system, PyPDFForm implements a grid view so that there is a better idea on where stuffs should be placed on a PDF. Consider this PDF , the coordinate grid view can be generated like this: from PyPDFForm import PdfWrapper grid_view_pdf = PdfWrapper( \"sample_template.pdf\" ).generate_coordinate_grid( color=(1, 0, 0), # optional margin=100 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(grid_view_pdf.read()) The generate_coordinate_grid method takes two optional parameters. The first one is color which allows you to pick a color for the grid view. The default color is red. The second one is margin which allows you to change the coordinate grid view's margin in points. The default margin is 100 points.","title":"PDF coordinates"},{"location":"coordinate/#pdf-coordinates","text":"The coordinate system on a single page of a PDF starts at the bottom left of the page as the origin. The unit of the coordinates is called \"points\" and there are 72 points/inch. PyPDFForm utilizes this coordinate system in some of its APIs so that widgets, texts, or images can be created on a PDF.","title":"PDF coordinates"},{"location":"coordinate/#generate-a-coordinate-grid-view","text":"To allow a better user experience with the coordinate system, PyPDFForm implements a grid view so that there is a better idea on where stuffs should be placed on a PDF. Consider this PDF , the coordinate grid view can be generated like this: from PyPDFForm import PdfWrapper grid_view_pdf = PdfWrapper( \"sample_template.pdf\" ).generate_coordinate_grid( color=(1, 0, 0), # optional margin=100 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(grid_view_pdf.read()) The generate_coordinate_grid method takes two optional parameters. The first one is color which allows you to pick a color for the grid view. The default color is red. The second one is margin which allows you to change the coordinate grid view's margin in points. The default margin is 100 points.","title":"Generate a coordinate grid view"},{"location":"draw/","text":"Draw stuffs PyPDFForm allows you to draw certain elements on a PDF. The purpose is in case there is a missing widget on your PDF form, and you need to put certain texts on it, or if you need to draw images. This section of the documentation will use this PDF as an example. This section of the documentation requires a basic understanding of the PDF coordinate system . All optional parameters will have a comment # optional after each of them. NOTE: Due to a known bug in a dependency, it is advised that these draw methods are called after a PDF form is filled. Otherwise, part (most noticeably radio buttons) or even all widgets of the PDF form might get removed after drawing things on it. Draw text from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\").draw_text( text=\"random text\", page_number=1, x=300, y=225, font=\"your_registered_font\", # optional font_size=12, # optional font_color=(1, 0, 0) # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(pdf.read()) Draw image from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\").draw_image( image=\"sample_image.jpg\", page_number=1, x=100, y=100, width=400, height=225, rotation=0 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(pdf.read())","title":"Draw stuffs"},{"location":"draw/#draw-stuffs","text":"PyPDFForm allows you to draw certain elements on a PDF. The purpose is in case there is a missing widget on your PDF form, and you need to put certain texts on it, or if you need to draw images. This section of the documentation will use this PDF as an example. This section of the documentation requires a basic understanding of the PDF coordinate system . All optional parameters will have a comment # optional after each of them. NOTE: Due to a known bug in a dependency, it is advised that these draw methods are called after a PDF form is filled. Otherwise, part (most noticeably radio buttons) or even all widgets of the PDF form might get removed after drawing things on it.","title":"Draw stuffs"},{"location":"draw/#draw-text","text":"from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\").draw_text( text=\"random text\", page_number=1, x=300, y=225, font=\"your_registered_font\", # optional font_size=12, # optional font_color=(1, 0, 0) # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(pdf.read())","title":"Draw text"},{"location":"draw/#draw-image","text":"from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\").draw_image( image=\"sample_image.jpg\", page_number=1, x=100, y=100, width=400, height=225, rotation=0 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(pdf.read())","title":"Draw image"},{"location":"fill/","text":"Fill a PDF form PyPDFForm uses a single depth, non-nested dictionary to fill a PDF form. As a result of this process, the filled PDF form will be flattened and no longer editable. This is to prevent future encoding issues, especially when multiple PDF forms with overlaps on widget names are combined together. Fill text field and checkbox widgets As seen when we inspected this PDF , a text field can be filled with a value of string , whereas a checkbox can be filled with a boolean value: from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template.pdf\").fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read()) Fill radio button widgets A radio button group on a PDF form is a collection of radio buttons that share the same name. A PDF form with radio button groups can be filled using integer values where the value indicates which radio button to select among each radio button group: from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template_with_radio_button.pdf\").fill( { \"radio_1\": 0, \"radio_2\": 1, \"radio_3\": 2, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read()) Fill dropdown widgets Similar to radio buttons, a dropdown choice can be selected by specifying an integer value of the choice. Consider this PDF : from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template_with_dropdown.pdf\").fill( { \"dropdown_1\": 1 }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read()) Fill signature widgets A signature field widget allows you to sign a PDF form in a handwritten format. PyPDFForm lets you use a signature image to populate any signature field widget. Consider this PDF and this signature image : from PyPDFForm import PdfWrapper signed = PdfWrapper(\"sample_template_with_signature.pdf\").fill( { \"signature\": \"sample_signature.png\" }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(signed.read()) NOTE: As described here , the value of the signature in your dictionary can be a file path shown above, but also an open file object and a file stream that's in bytes . Fill image widgets (beta) NOTE: This is a beta feature, meaning it still needs to be tested against more PDF forms and may not work for some of them. An image field widget can be filled similarly to a signature field, by providing a value of file path, file object, or file stream. Consider this PDF and this image : from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template_with_image_field.pdf\").fill( { \"image_1\": \"sample_image.jpg\" }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read())","title":"Fill a PDF form"},{"location":"fill/#fill-a-pdf-form","text":"PyPDFForm uses a single depth, non-nested dictionary to fill a PDF form. As a result of this process, the filled PDF form will be flattened and no longer editable. This is to prevent future encoding issues, especially when multiple PDF forms with overlaps on widget names are combined together.","title":"Fill a PDF form"},{"location":"fill/#fill-text-field-and-checkbox-widgets","text":"As seen when we inspected this PDF , a text field can be filled with a value of string , whereas a checkbox can be filled with a boolean value: from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template.pdf\").fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read())","title":"Fill text field and checkbox widgets"},{"location":"fill/#fill-radio-button-widgets","text":"A radio button group on a PDF form is a collection of radio buttons that share the same name. A PDF form with radio button groups can be filled using integer values where the value indicates which radio button to select among each radio button group: from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template_with_radio_button.pdf\").fill( { \"radio_1\": 0, \"radio_2\": 1, \"radio_3\": 2, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read())","title":"Fill radio button widgets"},{"location":"fill/#fill-dropdown-widgets","text":"Similar to radio buttons, a dropdown choice can be selected by specifying an integer value of the choice. Consider this PDF : from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template_with_dropdown.pdf\").fill( { \"dropdown_1\": 1 }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read())","title":"Fill dropdown widgets"},{"location":"fill/#fill-signature-widgets","text":"A signature field widget allows you to sign a PDF form in a handwritten format. PyPDFForm lets you use a signature image to populate any signature field widget. Consider this PDF and this signature image : from PyPDFForm import PdfWrapper signed = PdfWrapper(\"sample_template_with_signature.pdf\").fill( { \"signature\": \"sample_signature.png\" }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(signed.read()) NOTE: As described here , the value of the signature in your dictionary can be a file path shown above, but also an open file object and a file stream that's in bytes .","title":"Fill signature widgets"},{"location":"fill/#fill-image-widgets-beta","text":"NOTE: This is a beta feature, meaning it still needs to be tested against more PDF forms and may not work for some of them. An image field widget can be filled similarly to a signature field, by providing a value of file path, file object, or file stream. Consider this PDF and this image : from PyPDFForm import PdfWrapper filled = PdfWrapper(\"sample_template_with_image_field.pdf\").fill( { \"image_1\": \"sample_image.jpg\" }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read())","title":"Fill image widgets (beta)"},{"location":"inspect/","text":"Inspect a PDF form After a PDF form is prepared, PyPDFForm can be used to inspect names of all its widgets so that the data that's needed to fill it can be determined. There are several different methods this can be done with and feel free to choose the way that fits your needs the most. This section of the documentation will use this PDF as an example. Generate a preview PDF The first method of inspecting a PDF form is to generate a preview document. Each PdfWrapper object contains an attribute .preview which is a file stream that can be written to any disk file or memory buffer. Consider the following snippet: from PyPDFForm import PdfWrapper preview_stream = PdfWrapper(\"sample_template.pdf\").preview with open(\"output.pdf\", \"wb+\") as output: output.write(preview_stream) The generated preview PDF will have the name of each widget labeled on top of it in red. Generate a JSON schema that describes a PDF form The dictionary that's used to fill a PDF form can be described using a JSON schema. For example: import json from PyPDFForm import PdfWrapper pdf_form_schema = PdfWrapper(\"sample_template.pdf\").schema print(json.dumps(pdf_form_schema, indent=4, sort_keys=True)) The above snippet will yield the following output: { \"properties\": { \"check\": { \"type\": \"boolean\" }, \"check_2\": { \"type\": \"boolean\" }, \"check_3\": { \"type\": \"boolean\" }, \"test\": { \"type\": \"string\" }, \"test_2\": { \"type\": \"string\" }, \"test_3\": { \"type\": \"string\" } }, \"type\": \"object\" } In this case sample_template.pdf has three text fields named test , test_2 , and test_3 because they all have a type of string . It also has three checkboxes check , check_2 , and check_3 due to their boolean type. The JSON schema generated by PyPDFForm can be used to validate against the data you use to fill a PDF form. Generate sample data Lastly, PyPDFForm can generate some sample data that can be directly used to fill a PDF form: from pprint import pprint from PyPDFForm import PdfWrapper pprint(PdfWrapper(\"sample_template.pdf\").sample_data) The above snippet will give you a sample dictionary: {'check': True, 'check_2': True, 'check_3': True, 'test': 'test', 'test_2': 'test_2', 'test_3': 'test_3'}","title":"Inspect a PDF form"},{"location":"inspect/#inspect-a-pdf-form","text":"After a PDF form is prepared, PyPDFForm can be used to inspect names of all its widgets so that the data that's needed to fill it can be determined. There are several different methods this can be done with and feel free to choose the way that fits your needs the most. This section of the documentation will use this PDF as an example.","title":"Inspect a PDF form"},{"location":"inspect/#generate-a-preview-pdf","text":"The first method of inspecting a PDF form is to generate a preview document. Each PdfWrapper object contains an attribute .preview which is a file stream that can be written to any disk file or memory buffer. Consider the following snippet: from PyPDFForm import PdfWrapper preview_stream = PdfWrapper(\"sample_template.pdf\").preview with open(\"output.pdf\", \"wb+\") as output: output.write(preview_stream) The generated preview PDF will have the name of each widget labeled on top of it in red.","title":"Generate a preview PDF"},{"location":"inspect/#generate-a-json-schema-that-describes-a-pdf-form","text":"The dictionary that's used to fill a PDF form can be described using a JSON schema. For example: import json from PyPDFForm import PdfWrapper pdf_form_schema = PdfWrapper(\"sample_template.pdf\").schema print(json.dumps(pdf_form_schema, indent=4, sort_keys=True)) The above snippet will yield the following output: { \"properties\": { \"check\": { \"type\": \"boolean\" }, \"check_2\": { \"type\": \"boolean\" }, \"check_3\": { \"type\": \"boolean\" }, \"test\": { \"type\": \"string\" }, \"test_2\": { \"type\": \"string\" }, \"test_3\": { \"type\": \"string\" } }, \"type\": \"object\" } In this case sample_template.pdf has three text fields named test , test_2 , and test_3 because they all have a type of string . It also has three checkboxes check , check_2 , and check_3 due to their boolean type. The JSON schema generated by PyPDFForm can be used to validate against the data you use to fill a PDF form.","title":"Generate a JSON schema that describes a PDF form"},{"location":"inspect/#generate-sample-data","text":"Lastly, PyPDFForm can generate some sample data that can be directly used to fill a PDF form: from pprint import pprint from PyPDFForm import PdfWrapper pprint(PdfWrapper(\"sample_template.pdf\").sample_data) The above snippet will give you a sample dictionary: {'check': True, 'check_2': True, 'check_3': True, 'test': 'test', 'test_2': 'test_2', 'test_3': 'test_3'}","title":"Generate sample data"},{"location":"install/","text":"Installation and setup PyPDFForm is hosted on PyPI and any tool that supports downloading from it can be used. The most common option is to use pip. Install using pip PyPDFForm requires Python 3.8+. It is advised that a virtual environment is always created beforehand. Then you can run the following command to install: pip install PyPDFForm To upgrade PyPDFForm as well as all its dependencies, run: pip install -U PyPDFForm Create a PDF wrapper There are two classes provided by the library that abstract a PDF form. The FormWrapper class allows you to fill a PDF form if you don't need any other API. More info about FormWrapper can be found here . The class that implements most of PyPDFForm's APIs is PdfWrapper . It takes various optional parameters to instantiate, with the most important one being the PDF form \"template\". For example, if you download this PDF , you will want to instantiate your object like this: from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\") PyPDFForm does implement an adapter for different ways Python interacts with files. So you can pass your PDF form to PdfWrapper in three different ways: a file path, an open file object, and a file stream that's in bytes . This means the following two snippets are equivalent to the above: from PyPDFForm import PdfWrapper with open(\"sample_template.pdf\", \"rb+\") as template: pdf = PdfWrapper(template) from PyPDFForm import PdfWrapper with open(\"sample_template.pdf\", \"rb+\") as template: pdf = PdfWrapper(template.read()) This adaptation is universal across all APIs of PyPDFForm. So in later sections of the documentation whenever you see a function parameter that's a file path you can safely switch them for a file object or file stream. Write to a file Lastly, PdfWrapper also implements itself similar to an open file object. So you can write the PDF it holds to another file: from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\") with open(\"output.pdf\", \"wb+\") as output: output.write(pdf.read()) And it doesn't have to be a disk file, it can be a memory buffer as well: from io import BytesIO from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\") with BytesIO() as output: output.write(pdf.read())","title":"Installation and setup"},{"location":"install/#installation-and-setup","text":"PyPDFForm is hosted on PyPI and any tool that supports downloading from it can be used. The most common option is to use pip.","title":"Installation and setup"},{"location":"install/#install-using-pip","text":"PyPDFForm requires Python 3.8+. It is advised that a virtual environment is always created beforehand. Then you can run the following command to install: pip install PyPDFForm To upgrade PyPDFForm as well as all its dependencies, run: pip install -U PyPDFForm","title":"Install using pip"},{"location":"install/#create-a-pdf-wrapper","text":"There are two classes provided by the library that abstract a PDF form. The FormWrapper class allows you to fill a PDF form if you don't need any other API. More info about FormWrapper can be found here . The class that implements most of PyPDFForm's APIs is PdfWrapper . It takes various optional parameters to instantiate, with the most important one being the PDF form \"template\". For example, if you download this PDF , you will want to instantiate your object like this: from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\") PyPDFForm does implement an adapter for different ways Python interacts with files. So you can pass your PDF form to PdfWrapper in three different ways: a file path, an open file object, and a file stream that's in bytes . This means the following two snippets are equivalent to the above: from PyPDFForm import PdfWrapper with open(\"sample_template.pdf\", \"rb+\") as template: pdf = PdfWrapper(template) from PyPDFForm import PdfWrapper with open(\"sample_template.pdf\", \"rb+\") as template: pdf = PdfWrapper(template.read()) This adaptation is universal across all APIs of PyPDFForm. So in later sections of the documentation whenever you see a function parameter that's a file path you can safely switch them for a file object or file stream.","title":"Create a PDF wrapper"},{"location":"install/#write-to-a-file","text":"Lastly, PdfWrapper also implements itself similar to an open file object. So you can write the PDF it holds to another file: from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\") with open(\"output.pdf\", \"wb+\") as output: output.write(pdf.read()) And it doesn't have to be a disk file, it can be a memory buffer as well: from io import BytesIO from PyPDFForm import PdfWrapper pdf = PdfWrapper(\"sample_template.pdf\") with BytesIO() as output: output.write(pdf.read())","title":"Write to a file"},{"location":"prepare/","text":"Prepare a PDF form The most common tool to create a PDF form is Adobe Acrobat. A tutorial can be found here . There are other free alternatives like DocFly that support similar functionalities. Given a PDF that's not a form yet, PyPDFForm also supports creating a subset of PDF form widgets on it through coding. This section of the documentation will use this PDF as an example. This section of the documentation requires a basic understanding of the PDF coordinate system . All optional parameters will have a comment # optional after each of them. NOTE: For some PDF prep tools, creating widgets on their PDF forms may result in their original widgets getting flattened (e.g., this PDF which was prepared using Sejda ). So it is advised that you fill them first before creating any widget using PyPDFForm. Create a text field widget A text field widget can be created by downloading the PDF and running the following snippet: from PyPDFForm import PdfWrapper new_form = PdfWrapper(\"dummy.pdf\").create_widget( widget_type=\"text\", name=\"new_text_field_widget\", page_number=1, x=57, y=700, width=120, # optional height=40, # optional max_length=5, # optional font=\"Courier\", # optional font_size=15, # optional font_color=(1, 0, 0), # optional bg_color=(0, 0, 1), # optional border_color=(1, 0, 0), # optional border_width=5 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(new_form.read()) Create a checkbox widget A checkbox widget can be created using the same method with some changes to the parameters: from PyPDFForm import PdfWrapper new_form = PdfWrapper(\"dummy.pdf\").create_widget( widget_type=\"checkbox\", name=\"new_checkbox_widget\", page_number=1, x=57, y=700, size=30, # optional button_style=\"check\", # optional tick_color=(0, 1, 0), # optional bg_color=(0, 0, 1), # optional border_color=(1, 0, 0), # optional border_width=5 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(new_form.read()) The button_style parameter currently supports three options: check , circle , and cross . Create a dropdown widget A dropdown widget shares a similar set of parameters as a text field, with the only significant difference being a list of options needs to be specified: from PyPDFForm import PdfWrapper new_form = PdfWrapper(\"dummy.pdf\").create_widget( widget_type=\"dropdown\", name=\"new_dropdown_widget\", page_number=1, x=57, y=700, options=[ \"foo\", \"bar\", \"foobar\", ], width=120, # optional height=40, # optional font=\"Courier\", # optional font_size=15, # optional font_color=(1, 0, 0), # optional bg_color=(0, 0, 1), # optional border_color=(1, 0, 0), # optional border_width=5 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(new_form.read())","title":"Prepare a PDF form"},{"location":"prepare/#prepare-a-pdf-form","text":"The most common tool to create a PDF form is Adobe Acrobat. A tutorial can be found here . There are other free alternatives like DocFly that support similar functionalities. Given a PDF that's not a form yet, PyPDFForm also supports creating a subset of PDF form widgets on it through coding. This section of the documentation will use this PDF as an example. This section of the documentation requires a basic understanding of the PDF coordinate system . All optional parameters will have a comment # optional after each of them. NOTE: For some PDF prep tools, creating widgets on their PDF forms may result in their original widgets getting flattened (e.g., this PDF which was prepared using Sejda ). So it is advised that you fill them first before creating any widget using PyPDFForm.","title":"Prepare a PDF form"},{"location":"prepare/#create-a-text-field-widget","text":"A text field widget can be created by downloading the PDF and running the following snippet: from PyPDFForm import PdfWrapper new_form = PdfWrapper(\"dummy.pdf\").create_widget( widget_type=\"text\", name=\"new_text_field_widget\", page_number=1, x=57, y=700, width=120, # optional height=40, # optional max_length=5, # optional font=\"Courier\", # optional font_size=15, # optional font_color=(1, 0, 0), # optional bg_color=(0, 0, 1), # optional border_color=(1, 0, 0), # optional border_width=5 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(new_form.read())","title":"Create a text field widget"},{"location":"prepare/#create-a-checkbox-widget","text":"A checkbox widget can be created using the same method with some changes to the parameters: from PyPDFForm import PdfWrapper new_form = PdfWrapper(\"dummy.pdf\").create_widget( widget_type=\"checkbox\", name=\"new_checkbox_widget\", page_number=1, x=57, y=700, size=30, # optional button_style=\"check\", # optional tick_color=(0, 1, 0), # optional bg_color=(0, 0, 1), # optional border_color=(1, 0, 0), # optional border_width=5 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(new_form.read()) The button_style parameter currently supports three options: check , circle , and cross .","title":"Create a checkbox widget"},{"location":"prepare/#create-a-dropdown-widget","text":"A dropdown widget shares a similar set of parameters as a text field, with the only significant difference being a list of options needs to be specified: from PyPDFForm import PdfWrapper new_form = PdfWrapper(\"dummy.pdf\").create_widget( widget_type=\"dropdown\", name=\"new_dropdown_widget\", page_number=1, x=57, y=700, options=[ \"foo\", \"bar\", \"foobar\", ], width=120, # optional height=40, # optional font=\"Courier\", # optional font_size=15, # optional font_color=(1, 0, 0), # optional bg_color=(0, 0, 1), # optional border_color=(1, 0, 0), # optional border_width=5 # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(new_form.read())","title":"Create a dropdown widget"},{"location":"simple_fill/","text":"Fill a PDF form in place The FormWrapper class allows you to fill a PDF form in place as if you were filling it manually. Similar to the PdfWrapper class, the FormWrapper also supports widgets including text fields, checkboxes, radio buttons, dropdowns, and paragraphs. However, it does NOT support signature or image widgets. Consider this PDF : from PyPDFForm import FormWrapper filled = FormWrapper(\"sample_template_with_dropdown.pdf\").fill( { \"test_1\": \"test_1\", \"test_2\": \"test_2\", \"test_3\": \"test_3\", \"check_1\": True, \"check_2\": True, \"check_3\": True, \"radio_1\": 1, \"dropdown_1\": 1, }, flatten=False, # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read()) The optional parameter flatten has a default value of False , meaning PDF forms filled using FormWrapper will by default remain editable. Setting it to True will flatten the PDF after it's filled, making all widgets read only. NOTE: Currently there are some known issues with Adobe Acrobat displaying PDF forms filled using this method. Specifically the text content that gets filled into a text field widget will only appear when the text field is clicked and selected. This is not an issue in browsers like Chrome or other PDF viewing apps like Document Viewer (the default PDF app on Ubuntu). It is not 100% clear why such behavior exists for Adobe Acrobat but the speculated reason is that Adobe Acrobat seems to require way more complex metadata than browsers like Chrome for a text field widget to be rendered properly. If you have to use Adobe Acrobat, consider using PdfWrapper instead to fill your PDF forms as this is not something that can be fixed right now.","title":"Fill a PDF form in place"},{"location":"simple_fill/#fill-a-pdf-form-in-place","text":"The FormWrapper class allows you to fill a PDF form in place as if you were filling it manually. Similar to the PdfWrapper class, the FormWrapper also supports widgets including text fields, checkboxes, radio buttons, dropdowns, and paragraphs. However, it does NOT support signature or image widgets. Consider this PDF : from PyPDFForm import FormWrapper filled = FormWrapper(\"sample_template_with_dropdown.pdf\").fill( { \"test_1\": \"test_1\", \"test_2\": \"test_2\", \"test_3\": \"test_3\", \"check_1\": True, \"check_2\": True, \"check_3\": True, \"radio_1\": 1, \"dropdown_1\": 1, }, flatten=False, # optional ) with open(\"output.pdf\", \"wb+\") as output: output.write(filled.read()) The optional parameter flatten has a default value of False , meaning PDF forms filled using FormWrapper will by default remain editable. Setting it to True will flatten the PDF after it's filled, making all widgets read only. NOTE: Currently there are some known issues with Adobe Acrobat displaying PDF forms filled using this method. Specifically the text content that gets filled into a text field widget will only appear when the text field is clicked and selected. This is not an issue in browsers like Chrome or other PDF viewing apps like Document Viewer (the default PDF app on Ubuntu). It is not 100% clear why such behavior exists for Adobe Acrobat but the speculated reason is that Adobe Acrobat seems to require way more complex metadata than browsers like Chrome for a text field widget to be rendered properly. If you have to use Adobe Acrobat, consider using PdfWrapper instead to fill your PDF forms as this is not something that can be fixed right now.","title":"Fill a PDF form in place"},{"location":"style/","text":"Change text field styles PyPDFForm gives you the ability to modify certain styles of text fields through code. This allows you to manipulate appearances of the texts without having to make changes to your PDF form template. All these style changes can be done both globally upon instantiating a PdfWrapper object and individually for each text field widget. This section of the documentation will use this PDF as an example. Change font Some fonts, for example Courier and Helvetica , are builtin as part of the PDF standards. These fonts can be set without registration: from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\", global_font=\"Courier\") form.widgets[\"test\"].font = \"Helvetica\" form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read()) Other non-standard fonts, for example Liberation Serif , will need a TrueType file to be registered before they can be set: from PyPDFForm import PdfWrapper PdfWrapper.register_font(\"new_font_name\", \"LiberationSerif-Regular.ttf\") form = PdfWrapper(\"sample_template.pdf\", global_font=\"new_font_name\") form.widgets[\"test\"].font = \"new_font_name\" form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read()) Change font size PyPDFForm allows setting font size using a numerical float value: from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\", global_font_size=20) form.widgets[\"test\"].font_size = 30.5 form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read()) Change font color PyPDFForm allows setting font color using an RGB numerical tuple : from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\", global_font_color=(1, 0, 0)) form.widgets[\"test\"].font_color = (0.2, 0, 0.5) form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change text field styles"},{"location":"style/#change-text-field-styles","text":"PyPDFForm gives you the ability to modify certain styles of text fields through code. This allows you to manipulate appearances of the texts without having to make changes to your PDF form template. All these style changes can be done both globally upon instantiating a PdfWrapper object and individually for each text field widget. This section of the documentation will use this PDF as an example.","title":"Change text field styles"},{"location":"style/#change-font","text":"Some fonts, for example Courier and Helvetica , are builtin as part of the PDF standards. These fonts can be set without registration: from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\", global_font=\"Courier\") form.widgets[\"test\"].font = \"Helvetica\" form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read()) Other non-standard fonts, for example Liberation Serif , will need a TrueType file to be registered before they can be set: from PyPDFForm import PdfWrapper PdfWrapper.register_font(\"new_font_name\", \"LiberationSerif-Regular.ttf\") form = PdfWrapper(\"sample_template.pdf\", global_font=\"new_font_name\") form.widgets[\"test\"].font = \"new_font_name\" form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change font"},{"location":"style/#change-font-size","text":"PyPDFForm allows setting font size using a numerical float value: from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\", global_font_size=20) form.widgets[\"test\"].font_size = 30.5 form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change font size"},{"location":"style/#change-font-color","text":"PyPDFForm allows setting font color using an RGB numerical tuple : from PyPDFForm import PdfWrapper form = PdfWrapper(\"sample_template.pdf\", global_font_color=(1, 0, 0)) form.widgets[\"test\"].font_color = (0.2, 0, 0.5) form.fill( { \"test\": \"test_1\", \"check\": True, \"test_2\": \"test_2\", \"check_2\": False, \"test_3\": \"test_3\", \"check_3\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(form.read())","title":"Change font color"},{"location":"utils/","text":"Other utilities There are some additional utilities PyPDFForm provides similar to many other PDF libraries. This section of the documentation will use this PDF as an example. Extract pages Each PdfWrapper object has an attribute .pages . It's a list of PdfWrapper objects where each one of them is a single page: from PyPDFForm import PdfWrapper first_page = PdfWrapper(\"sample_template.pdf\").pages[0] first_page.fill( { \"test\": \"test_1\", \"check\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(first_page.read()) Merge multiple PDFs More than one PDF files can be merged by simply adding their PdfWrapper objects. Consider this PDF : from PyPDFForm import PdfWrapper pdf_one = PdfWrapper(\"dummy.pdf\") pdf_two = PdfWrapper(\"sample_template.pdf\") merged = pdf_one + pdf_two with open(\"output.pdf\", \"wb+\") as output: output.write(merged.read()) Or if you wish to re-organize your pages: from PyPDFForm import PdfWrapper pdf_one = PdfWrapper(\"dummy.pdf\") pdf_two = PdfWrapper(\"sample_template.pdf\") merged = pdf_two.pages[0] + pdf_one + pdf_two.pages[1] + pdf_two.pages[2] with open(\"output.pdf\", \"wb+\") as output: output.write(merged.read()) Change PDF version PyPDFForm supports modifying PDF version up to 2.0: from PyPDFForm import PdfWrapper new_version = PdfWrapper(\"sample_template.pdf\").change_version(\"2.0\") with open(\"output.pdf\", \"wb+\") as output: output.write(new_version.read())","title":"Other utilities"},{"location":"utils/#other-utilities","text":"There are some additional utilities PyPDFForm provides similar to many other PDF libraries. This section of the documentation will use this PDF as an example.","title":"Other utilities"},{"location":"utils/#extract-pages","text":"Each PdfWrapper object has an attribute .pages . It's a list of PdfWrapper objects where each one of them is a single page: from PyPDFForm import PdfWrapper first_page = PdfWrapper(\"sample_template.pdf\").pages[0] first_page.fill( { \"test\": \"test_1\", \"check\": True, }, ) with open(\"output.pdf\", \"wb+\") as output: output.write(first_page.read())","title":"Extract pages"},{"location":"utils/#merge-multiple-pdfs","text":"More than one PDF files can be merged by simply adding their PdfWrapper objects. Consider this PDF : from PyPDFForm import PdfWrapper pdf_one = PdfWrapper(\"dummy.pdf\") pdf_two = PdfWrapper(\"sample_template.pdf\") merged = pdf_one + pdf_two with open(\"output.pdf\", \"wb+\") as output: output.write(merged.read()) Or if you wish to re-organize your pages: from PyPDFForm import PdfWrapper pdf_one = PdfWrapper(\"dummy.pdf\") pdf_two = PdfWrapper(\"sample_template.pdf\") merged = pdf_two.pages[0] + pdf_one + pdf_two.pages[1] + pdf_two.pages[2] with open(\"output.pdf\", \"wb+\") as output: output.write(merged.read())","title":"Merge multiple PDFs"},{"location":"utils/#change-pdf-version","text":"PyPDFForm supports modifying PDF version up to 2.0: from PyPDFForm import PdfWrapper new_version = PdfWrapper(\"sample_template.pdf\").change_version(\"2.0\") with open(\"output.pdf\", \"wb+\") as output: output.write(new_version.read())","title":"Change PDF version"}]} \ No newline at end of file diff --git a/search/worker.js b/search/worker.js new file mode 100644 index 00000000..8628dbce --- /dev/null +++ b/search/worker.js @@ -0,0 +1,133 @@ +var base_path = 'function' === typeof importScripts ? '.' : '/search/'; +var allowSearch = false; +var index; +var documents = {}; +var lang = ['en']; +var data; + +function getScript(script, callback) { + console.log('Loading script: ' + script); + $.getScript(base_path + script).done(function () { + callback(); + }).fail(function (jqxhr, settings, exception) { + console.log('Error: ' + exception); + }); +} + +function getScriptsInOrder(scripts, callback) { + if (scripts.length === 0) { + callback(); + return; + } + getScript(scripts[0], function() { + getScriptsInOrder(scripts.slice(1), callback); + }); +} + +function loadScripts(urls, callback) { + if( 'function' === typeof importScripts ) { + importScripts.apply(null, urls); + callback(); + } else { + getScriptsInOrder(urls, callback); + } +} + +function onJSONLoaded () { + data = JSON.parse(this.responseText); + var scriptsToLoad = ['lunr.js']; + if (data.config && data.config.lang && data.config.lang.length) { + lang = data.config.lang; + } + if (lang.length > 1 || lang[0] !== "en") { + scriptsToLoad.push('lunr.stemmer.support.js'); + if (lang.length > 1) { + scriptsToLoad.push('lunr.multi.js'); + } + if (lang.includes("ja") || lang.includes("jp")) { + scriptsToLoad.push('tinyseg.js'); + } + for (var i=0; i < lang.length; i++) { + if (lang[i] != 'en') { + scriptsToLoad.push(['lunr', lang[i], 'js'].join('.')); + } + } + } + loadScripts(scriptsToLoad, onScriptsLoaded); +} + +function onScriptsLoaded () { + console.log('All search scripts loaded, building Lunr index...'); + if (data.config && data.config.separator && data.config.separator.length) { + lunr.tokenizer.separator = new RegExp(data.config.separator); + } + + if (data.index) { + index = lunr.Index.load(data.index); + data.docs.forEach(function (doc) { + documents[doc.location] = doc; + }); + console.log('Lunr pre-built index loaded, search ready'); + } else { + index = lunr(function () { + if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) { + this.use(lunr[lang[0]]); + } else if (lang.length > 1) { + this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility + } + this.field('title'); + this.field('text'); + this.ref('location'); + + for (var i=0; i < data.docs.length; i++) { + var doc = data.docs[i]; + this.add(doc); + documents[doc.location] = doc; + } + }); + console.log('Lunr index built, search ready'); + } + allowSearch = true; + postMessage({config: data.config}); + postMessage({allowSearch: allowSearch}); +} + +function init () { + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", onJSONLoaded); + var index_path = base_path + '/search_index.json'; + if( 'function' === typeof importScripts ){ + index_path = 'search_index.json'; + } + oReq.open("GET", index_path); + oReq.send(); +} + +function search (query) { + if (!allowSearch) { + console.error('Assets for search still loading'); + return; + } + + var resultDocuments = []; + var results = index.search(query); + for (var i=0; i < results.length; i++){ + var result = results[i]; + doc = documents[result.ref]; + doc.summary = doc.text.substring(0, 200); + resultDocuments.push(doc); + } + return resultDocuments; +} + +if( 'function' === typeof importScripts ) { + onmessage = function (e) { + if (e.data.init) { + init(); + } else if (e.data.query) { + postMessage({ results: search(e.data.query) }); + } else { + console.error("Worker - Unrecognized message: " + e); + } + }; +} diff --git a/simple_fill/index.html b/simple_fill/index.html new file mode 100644 index 00000000..60057f2b --- /dev/null +++ b/simple_fill/index.html @@ -0,0 +1,180 @@ + + + + + + + +The FormWrapper
class allows you to fill a PDF form in place as if you were filling it manually.
Similar to the PdfWrapper
class, the FormWrapper
also supports widgets including text fields, checkboxes, radio
+buttons, dropdowns, and paragraphs. However, it does NOT support signature or image widgets.
Consider this PDF:
+from PyPDFForm import FormWrapper
+
+filled = FormWrapper("sample_template_with_dropdown.pdf").fill(
+ {
+ "test_1": "test_1",
+ "test_2": "test_2",
+ "test_3": "test_3",
+ "check_1": True,
+ "check_2": True,
+ "check_3": True,
+ "radio_1": 1,
+ "dropdown_1": 1,
+ },
+ flatten=False, # optional
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(filled.read())
+
+The optional parameter flatten
has a default value of False
, meaning PDF forms filled using FormWrapper
will by
+default remain editable. Setting it to True
will flatten the PDF after it's filled, making all widgets read only.
NOTE: Currently there are some known issues with Adobe Acrobat displaying PDF forms filled using this method.
+Specifically the text content that gets filled into a text field widget will only appear when the text field is clicked
+and selected. This is not an issue in browsers like Chrome or other PDF viewing apps like Document Viewer
+(the default PDF app on Ubuntu). It is not 100% clear why such behavior exists for Adobe Acrobat but the speculated reason
+is that Adobe Acrobat seems to require way more complex metadata than browsers like Chrome for a text field widget to be
+rendered properly. If you have to use Adobe Acrobat, consider using PdfWrapper
instead to fill your PDF forms as this is
+not something that can be fixed right now.
PyPDFForm gives you the ability to modify certain styles of text fields through code. This allows you to manipulate +appearances of the texts without having to make changes to your PDF form template.
+All these style changes can be done both globally upon instantiating a PdfWrapper
object and individually for each
+text field widget.
This section of the documentation will use +this PDF as an example.
+Some fonts, for example Courier
and Helvetica
, are builtin as part of the PDF standards. These fonts can be set
+without registration:
from PyPDFForm import PdfWrapper
+
+form = PdfWrapper("sample_template.pdf", global_font="Courier")
+form.widgets["test"].font = "Helvetica"
+
+form.fill(
+ {
+ "test": "test_1",
+ "check": True,
+ "test_2": "test_2",
+ "check_2": False,
+ "test_3": "test_3",
+ "check_3": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(form.read())
+
+Other non-standard fonts, for example Liberation Serif, will need +a TrueType file +to be registered before they can be set:
+from PyPDFForm import PdfWrapper
+
+PdfWrapper.register_font("new_font_name", "LiberationSerif-Regular.ttf")
+
+form = PdfWrapper("sample_template.pdf", global_font="new_font_name")
+form.widgets["test"].font = "new_font_name"
+
+form.fill(
+ {
+ "test": "test_1",
+ "check": True,
+ "test_2": "test_2",
+ "check_2": False,
+ "test_3": "test_3",
+ "check_3": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(form.read())
+
+PyPDFForm allows setting font size using a numerical float
value:
from PyPDFForm import PdfWrapper
+
+form = PdfWrapper("sample_template.pdf", global_font_size=20)
+form.widgets["test"].font_size = 30.5
+
+form.fill(
+ {
+ "test": "test_1",
+ "check": True,
+ "test_2": "test_2",
+ "check_2": False,
+ "test_3": "test_3",
+ "check_3": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(form.read())
+
+PyPDFForm allows setting font color using an RGB numerical tuple
:
from PyPDFForm import PdfWrapper
+
+form = PdfWrapper("sample_template.pdf", global_font_color=(1, 0, 0))
+form.widgets["test"].font_color = (0.2, 0, 0.5)
+
+form.fill(
+ {
+ "test": "test_1",
+ "check": True,
+ "test_2": "test_2",
+ "check_2": False,
+ "test_3": "test_3",
+ "check_3": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(form.read())
+
+
+ There are some additional utilities PyPDFForm provides similar to many other PDF libraries.
+This section of the documentation will use +this PDF as an example.
+Each PdfWrapper
object has an attribute .pages
. It's a list
of PdfWrapper
objects where each one of them is a
+single page:
from PyPDFForm import PdfWrapper
+
+first_page = PdfWrapper("sample_template.pdf").pages[0]
+first_page.fill(
+ {
+ "test": "test_1",
+ "check": True,
+ },
+)
+
+with open("output.pdf", "wb+") as output:
+ output.write(first_page.read())
+
+More than one PDF files can be merged by simply adding their PdfWrapper
objects. Consider
+this PDF:
from PyPDFForm import PdfWrapper
+
+pdf_one = PdfWrapper("dummy.pdf")
+pdf_two = PdfWrapper("sample_template.pdf")
+merged = pdf_one + pdf_two
+
+with open("output.pdf", "wb+") as output:
+ output.write(merged.read())
+
+Or if you wish to re-organize your pages:
+from PyPDFForm import PdfWrapper
+
+pdf_one = PdfWrapper("dummy.pdf")
+pdf_two = PdfWrapper("sample_template.pdf")
+merged = pdf_two.pages[0] + pdf_one + pdf_two.pages[1] + pdf_two.pages[2]
+
+with open("output.pdf", "wb+") as output:
+ output.write(merged.read())
+
+PyPDFForm supports modifying PDF version up to 2.0:
+from PyPDFForm import PdfWrapper
+
+new_version = PdfWrapper("sample_template.pdf").change_version("2.0")
+
+with open("output.pdf", "wb+") as output:
+ output.write(new_version.read())
+
+
+