[Python] PYPDF Form Filling: Checkboxes and Text Not Displaying Correctly in all PDF Viewers

Discussão em 'Python' iniciado por Stack, Julho 1, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to fill a PDF with text fields and checkboxes using Python. While the text fields and checkboxes are correctly filled and appear in the printed version of the PDF, these modifications do not display in PDF viewers such as Acrobat or online viewers. The checkboxes are particularly complex, and despite manipulating the correct data, the appearance of these fields is not maintained.

    This is my code:

    from pypdf import PdfReader, PdfWriter
    from pypdf.generic import NameObject, TextStringObject, BooleanObject, IndirectObject
    import os

    # Dummy data simulating Excel input for text fields
    field_values = {
    "id": "TEST #1",
    "name_rep": "TEST #2",
    "name_aff": "TEST #3",
    "1007_1": "614",
    }

    # Dictionary for checkbox states
    checkbox_states = {
    "checkbox_2_614": "On",
    }

    def set_need_appearances_writer(writer):
    try:
    catalog = writer._root_object
    if "/AcroForm" not in catalog:
    writer._root_object.update({
    NameObject("/AcroForm"): IndirectObject(len(writer._objects), 0, writer)})
    need_appearances = NameObject("/NeedAppearances")
    writer._root_object["/AcroForm"][need_appearances] = BooleanObject(True)
    except Exception as e:
    print("set_need_appearances_writer() catch: ", repr(e))

    # SharePoint file details
    selected_pdf = "126 BRAZIL.pdf"
    pdf_found = False

    # Iterate over files in SharePoint
    for file_info in file_list:
    if file_info['Name'] == selected_pdf:
    pdf_found = True
    pdf_content = input_folder.get_file(selected_pdf)

    print(f"Selecting {selected_pdf} File from SharePoint...")
    print("-------------------------------------------------------------------")

    # Save the PDF to a temporary local file
    temp_pdf_path = '/tmp/temp_form.pdf'
    with open(temp_pdf_path, 'wb') as f:
    f.write(pdf_content)

    # Read the PDF
    reader = PdfReader(temp_pdf_path)

    #Update NeedAppearances flag in the reader
    if "/AcroForm" in reader.trailer["/Root"]:
    reader.trailer["/Root"]["/AcroForm"].update(
    {NameObject("/AS"): BooleanObject(True)}
    )
    writer = PdfWriter()

    # Process the first two pages to update field names and values
    #Manually find checkboxes in form - checkboxes not found via BTN only AS. Checkboxes do not contain set Names, so update names for filling.
    for page_number, page in enumerate(reader.pages[:2]):
    if "/Annots" in page:
    annotations = page["/Annots"]
    for i, annotation_ref in enumerate(annotations):
    annotation = annotation_ref.get_object()
    additional_info = annotation.get('/AP') # Appearance dictionary

    # Extract numerical `/AP` values - this is all checkboxes inscript
    if additional_info:
    normal_appearance = additional_info.get('/N')
    if normal_appearance:
    for key in normal_appearance.keys():
    if key.lstrip('/').isdigit():
    identifier = f"checkbox_{page_number + 1}_{key.strip('/')}"
    annotation.update({
    NameObject('/T'): NameObject(identifier)
    })
    print(f"Updated NameObject for annotation at index {i} to '{identifier}'")

    # Update text fields and checkboxes
    field_name = annotation.get('/T')
    if field_name:
    # Update text fields
    if field_name in field_values:
    value = TextStringObject(field_values[field_name])
    annotation.update({
    NameObject('/V'): value
    })
    print(f"PDF Filled: {field_name} updated with {field_values[field_name]}")

    # Update checkboxes based on field name
    if field_name in checkbox_states:
    state = checkbox_states[field_name]
    appearance_value = field_name.split('_')[-1]
    annotation.update({
    NameObject("/V"): NameObject(f"/{state}"),
    NameObject("/AS"): NameObject(f"/{appearance_value}")
    })
    print(f"Checkbox {field_name} set to {state} and {appearance_value}")


    writer.add_page(page)
    set_need_appearances_writer(writer)

    filled_pdf_name = "updated_form.pdf"
    filled_pdf_path = os.path.join('/tmp', filled_pdf_name)

    # Write the filled form to a new PDF
    with open(filled_pdf_path, 'wb') as f:
    writer.write(f)
    print("-------------------------------------------------------------------")
    print(f"Filled form saved as {filled_pdf_path}")


    The PDF in question:https://www.bea.gov/sites/default/files/2018-04/BE-11B-Fillable.pdf . Specifically Page 2 of the PDF is being tackled above.

    Any guidance on updating the appearance streams would be amazing. Filled output is currently only available in printed views while all fillable content in Adobe Acrobat Online refuse to appear with error "Content is still loading. Please try again once loading is complete."

    Continue reading...

Compartilhe esta Página