3

I'm using Python and PyPDF2 to generate a set of PDFs based on a template with form fields. The PDFs are created and all of the fields are filled correctly, but when I open the PDFs in Adobe Acrobat they show changes made to the file (i.e., the "Save" menu option is enabled, and when I try to close the file Adobe asks if I want to save changes, even if I haven't touched anything).

It's mostly just a slight annoyance, but is there a way to prevent this from happening? From my research it seems like this means (1) there's JavaScript modifying the file (there isn't), or (2) the file is corrupted and Adobe is fixing it.

A simplified version of my code is below. I set /NeedAppearances to True in both the reader and writer because otherwise the values didn't appear in the PDF unless I clicked on the field. I also set the annotations so that the fields are read-only and appear as regular text.

from PyPDF2 import PdfFileReader, PdfFileWriter
from PyPDF2.generic import BooleanObject, NameObject, IndirectObject, NumberObject

data = {'field1': 'Text1', 'field2': 'Text2'}

with open('template.pdf', 'rb') as read_file:

    pdf_reader = PdfFileReader(read_file)
    pdf_writer = PdfFileWriter()

    # Set /NeedAppearances to make field values visible
    try:
        if '/AcroForm' in pdf_reader.trailer['/Root']:
            pdf_reader.trailer['/Root']['/AcroForm'][NameObject('/NeedAppearances')] = BooleanObject(True)
        if '/AcroForm' not in pdf_writer._root_object:
            root = pdf_writer._root_object
            acroform = {NameObject('/AcroForm'): IndirectObject(len(pdf_writer._objects), 0, pdf_writer)}
            root.update(acroform)
        root['/AcroForm'][NameObject('/NeedAppearances')] = BooleanObject(True)
    except:
        print('Warning: Error setting PDF /NeedAppearances value.')

    # Add first page to writer
    pdf_writer.addPage(pdf_reader.getPage(0))
    page = pdf_writer.getPage(0)

    # Update form fields
    pdf_writer.updatePageFormFieldValues(page, data)

    # Make fields read-only
    for i in range(len(page['/Annots'])):
        annot = page['/Annots'][i].getObject()
        annot.update({NameObject('/Ff'): NumberObject(1)})

    # Write PDF
    with open('result.pdf', 'wb') as write_file:
        pdf_writer.write(write_file)
  • By setting /NeedAppearances to True, you are asking Acrobat to create formatted appearances based on the field values. You are literally telling Acrobat to change the file. That's why it's asking to save. – joelgeraci Jun 25 '21 at 20:49
  • 2
    I am running into the same thing. Has this been solved yet? – Kyvex May 20 '22 at 12:55

0 Answers0