使用Python pypdf模块填写PDF表单:填充无效与下拉框处理求助
Solution for pypdf Form Filling & Dropdown Conversion Issues
Fixing Form Field Filling Without Duplicate Pages
The core problem is that PdfWriter wasn't inheriting the original PDF's AcroForm dictionary—this structure is mandatory for recognizing and editing form fields. Instead of using both page-adding methods, use one to add pages, then explicitly copy the AcroForm to the writer:
from pypdf import PdfReader, PdfWriter from pypdf import generic as pypdf_generic reader = PdfReader("form.pdf") writer = PdfWriter() # Add all pages from the original PDF to the writer writer.append_pages_from_reader(reader) # Copy the AcroForm dictionary (critical for form field functionality) if "/AcroForm" in reader._root_object: acroform = reader._root_object["/AcroForm"].get_object() writer._root_object[pypdf_generic.NameObject("/AcroForm")] = acroform # Update your form fields as usual writer.update_page_form_field_values( writer.pages[0], {"fieldname": "some filled in text"}, auto_regenerate=False ) with open("filled-out.pdf", "wb") as output_stream: writer.write(output_stream)
This keeps a single copy of each page while retaining the form structure needed to populate fields.
Converting Dropdown (Choice) Fields to Text Fields
Changing a dropdown's type requires modifying both the page annotation and the corresponding entry in the AcroForm dictionary—your original code only updated the annotation. Here's the complete workflow:
from pypdf import PdfReader, PdfWriter from pypdf import generic as pypdf_generic reader = PdfReader("form.pdf") page = reader.pages[0] ### Step 1: Modify the page annotation for the dropdown annots = page.get("/Annots") if annots: # Target the 5th annotation (index 5) - adjust the index for your specific field field_annot = annots.get_object()[5].get_object() # Switch field type from Choice (/Ch) to Text (/Tx) field_annot[pypdf_generic.NameObject("/FT")] = pypdf_generic.NameObject("/Tx") # Remove dropdown-specific properties (like options list) if "/Opt" in field_annot: del field_annot["/Opt"] ### Step 2: Update the matching field in the AcroForm fields = reader.get_fields() for field_name, field_obj in fields.items(): # Replace with your dropdown's actual field name (use reader.get_fields().keys() to list names) if field_name == "your_dropdown_field_name": field_obj[pypdf_generic.NameObject("/FT")] = pypdf_generic.NameObject("/Tx") if "/Opt" in field_obj: del field_obj["/Opt"] ### Step 3: Write the modified PDF writer = PdfWriter() writer.append_pages_from_reader(reader) # Copy the updated AcroForm to the writer if "/AcroForm" in reader._root_object: acroform = reader._root_object["/AcroForm"].get_object() writer._root_object[pypdf_generic.NameObject("/AcroForm")] = acroform # Fill the converted text field writer.update_page_form_field_values( writer.pages[0], {"your_dropdown_field_name": "custom text here"}, auto_regenerate=False ) with open("modified_form.pdf", "wb") as output_stream: writer.write(output_stream)
Notes:
- Repeat the annotation modification step for each dropdown you need to convert (adjust the index in
annots.get_object()[5]as needed). - Use
print(reader.get_fields().keys())to get the exact names of your form fields if you're unsure.
内容的提问来源于stack exchange,提问作者Annabanana
相关产品推荐
相关产品推荐

