Search code examples
pythonpdf-form

Python PDF form flattening


How do I "flatten" a PDF-form? I have a PDF form which needs to be filled. I have a simple example where TEMP_FORM.pdf is the from and data_dict is the value to be filled in TEMP_FORM.pdf. The output file is saved as FORM1.pdf but is still editable I need flatten that file so that the value cannot be edited.

from PyPDF2 import PdfFileReader, PdfFileWriter

TEMPLATE_PATH = 'TEMP_FORM.pdf'
OUTPUT_PATH = 'FORM1.pdf'
data_dict = {
    'name': 'XYZ',
    'address': 'PQR',
    'email': '[email protected]',
    'send_date': '2018-02-13',
    'due_date': '2018-03-13'
}

if __name__ == '__main__':
    input_file = PdfFileReader(open(TEMPLATE_PATH, "rb"))

    output_file = PdfFileWriter()
    output_file.addPage(input_file.getPage(0))
    output_file.updatePageFormFieldValues(output_file.getPage(0), data_dict)
    output_stream = open(OUTPUT_PATH, "wb")

    output_file.write(output_stream)
    output_stream.close()

Solution

  • Per the Adobe Docs, you can change the Bit Position of the Editable Form Fields to 1 to make them ReadOnly. I provided a full solution here, but it uses Django:

    https://stackoverflow.com/a/55301804/8382028

    Adobe Docs (page 552):

    https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/pdf_reference_archives/PDFReference.pdf

    Use PyPDF2 to fill the fields, then loop through the annotations and do this:

    for j in range(0, len(output_file['/Annots'])):
        writer_annot = output_file['/Annots'][j].getObject()
        for field in data_dict: 
            if writer_annot.get('/T') == field:
                writer_annot.update({
                    NameObject("/Ff"): NumberObject(1)   # make ReadOnly
                })