如何使用 Python 填写 PDF 表单
How to fill PDF forms using Python
我有一个 PDF form
使用 Adobe LiveCycle Designer ES 10.4
创建的。我需要使用 Python
来填充它,这样我们就可以减少体力劳动。我在网上搜索并阅读了一些文章,其中大部分都是围绕 pdfrw
库,我尝试使用它并从 PDF form
中提取了一些信息,如下所示
代码
from pdfrw import PdfReader
pdf = PdfReader('sample.pdf')
print(pdf.keys())
print(pdf.Info)
print(pdf.Root.keys())
print('PDF has {} pages'.format(len(pdf.pages)))
输出
['/Root', '/Info', '/ID', '/Size']
{'/CreationDate': "(D:20180822164509+05'30')", '/Creator': '(Adobe LiveCycle Designer ES 10.4)', '/ModDate': "(D:20180822165611+05'30')", '/Producer': '(Adobe XML Form Module Library)'}
['/AcroForm', '/MarkInfo', '/Metadata', '/Names', '/NeedsRendering', '/Pages', '/Perms', '/StructTreeRoot', '/Type']
PDF has 1 pages
我不确定如何进一步使用 pdfrw
从 PDF 表单访问可填写字段并使用 Python
填写它们是否可行。任何建议都会有所帮助。
使用 PDFix SDK
基于 AcroForm 的表单
def SetFormFieldValue(email, key, open_path, save_path):
pdfix = GetPdfix()
if pdfix is None:
raise Exception('Pdfix Initialization fail')
if not pdfix.Authorize(pdfix_email, pdfix_license):
raise Exception('Authorization fail : ' + pdfix.GetError())
doc = pdfix.OpenDoc(open_path, "")
if doc is None:
raise Exception('Unable to open pdf : ' + pdfix.GetError())
field = doc.GetFormFieldByName("Text1")
if field is not None:
value = field.GetValue()
value = "New Value"
field.SetValue(value)
if not doc.Save(save_path, kSaveFull):
raise Exception(pdfix.GetError())
doc.Close()
pdfix.Destroy()
您可以在此处找到表单字段:
pdf.Root.AcroForm.Fields
或此处
pdf.Root.Pages.Kids[page_index].Annots
这是一个 PdfArray 对象。基本上是一个列表。
字段名称可在此处找到:
pdf.Root.AcroForm.Fields[field_index].T
其他键包括值.V
.AP.N.Resources
下面有一堆显示信息,比如字体等等
但是,如果您更新字段的值并输出 pdf 文件。它可能仅在字段具有焦点时显示值,即被单击。
我还没有想出如何解决这个问题。
此处提供了完整的解决方案:How to edit editable pdf using the pdfrw library?
关键部分是:
template_pdf.Root.AcroForm.update(pdfrw.PdfDict(NeedAppearances=pdfrw.PdfObject('true')))
如果每个字段已编入索引,请使用它来填充它们。
template = PdfReader('template.pdf')
page_c = 0
while page_c < len(template.Root.Pages.Kids): #LOOP through pages
annot_c = 0
while annot_c < len(template.Root.Pages.Kids[page_c].Annots): #LOOP through fields
template.Root.Pages.Kids[page_c].Annots[annot_c].update(PdfDict(V=str(annot_c)+'-'+str(page_c)))
annot_c=annot_c+1
page_c=page_c+1
PdfWriter().write('output.pdf', template)
我写了一个基于以下内容的库:'pdfrw'、'pdf2image'、'Pillow'、'PyPDF2' 称为 fillpdf(pip install fillpdf
和 poppler 依赖项 conda install -c conda-forge poppler
)
基本用法:
from fillpdf import fillpdfs
fillpdfs.get_form_fields("blank.pdf")
# returns a dictionary of fields
# Set the returned dictionary values a save to a variable
# For radio boxes ('Off' = not filled, 'Yes' = filled)
data_dict = {
'Text2': 'Name',
'Text4': 'LastName',
'box': 'Yes',
}
fillpdfs.write_fillable_pdf('blank.pdf', 'new.pdf', data_dict)
# If you want it flattened:
fillpdfs.flatten_pdf('new.pdf', 'newflat.pdf')
更多信息在这里:
https://github.com/t-houssian/fillpdf
如果某些字段未填写,您可以使用 fitz (pip install PyMuPDF
) 和 PyPDF2 (pip install PyPDF2
),如下所示根据需要更改点:
import fitz
from PyPDF2 import PdfFileReader
file_handle = fitz.open('blank.pdf')
pdf = PdfFileReader(open('blank.pdf','rb'))
box = pdf.getPage(0).mediaBox
w = box.getWidth()
h = box.getHeight()
# For images
image_rectangle = fitz.Rect((w/2)-200,h-255,(w/2)-100,h-118)
pages = pdf.getNumPages() - 1
last_page = file_handle[pages]
last_page._wrapContents()
last_page.insertImage(image_rectangle, filename=f'image.png')
# For text
last_page.insertText(fitz.Point((w/2)-247 , h-478), 'John Smith', fontsize=14, fontname="times-bold")
file_handle.save(f'newpdf.pdf')
我有一个 PDF form
使用 Adobe LiveCycle Designer ES 10.4
创建的。我需要使用 Python
来填充它,这样我们就可以减少体力劳动。我在网上搜索并阅读了一些文章,其中大部分都是围绕 pdfrw
库,我尝试使用它并从 PDF form
中提取了一些信息,如下所示
代码
from pdfrw import PdfReader
pdf = PdfReader('sample.pdf')
print(pdf.keys())
print(pdf.Info)
print(pdf.Root.keys())
print('PDF has {} pages'.format(len(pdf.pages)))
输出
['/Root', '/Info', '/ID', '/Size']
{'/CreationDate': "(D:20180822164509+05'30')", '/Creator': '(Adobe LiveCycle Designer ES 10.4)', '/ModDate': "(D:20180822165611+05'30')", '/Producer': '(Adobe XML Form Module Library)'}
['/AcroForm', '/MarkInfo', '/Metadata', '/Names', '/NeedsRendering', '/Pages', '/Perms', '/StructTreeRoot', '/Type']
PDF has 1 pages
我不确定如何进一步使用 pdfrw
从 PDF 表单访问可填写字段并使用 Python
填写它们是否可行。任何建议都会有所帮助。
使用 PDFix SDK
基于 AcroForm 的表单def SetFormFieldValue(email, key, open_path, save_path):
pdfix = GetPdfix()
if pdfix is None:
raise Exception('Pdfix Initialization fail')
if not pdfix.Authorize(pdfix_email, pdfix_license):
raise Exception('Authorization fail : ' + pdfix.GetError())
doc = pdfix.OpenDoc(open_path, "")
if doc is None:
raise Exception('Unable to open pdf : ' + pdfix.GetError())
field = doc.GetFormFieldByName("Text1")
if field is not None:
value = field.GetValue()
value = "New Value"
field.SetValue(value)
if not doc.Save(save_path, kSaveFull):
raise Exception(pdfix.GetError())
doc.Close()
pdfix.Destroy()
您可以在此处找到表单字段:
pdf.Root.AcroForm.Fields
或此处
pdf.Root.Pages.Kids[page_index].Annots
这是一个 PdfArray 对象。基本上是一个列表。 字段名称可在此处找到:
pdf.Root.AcroForm.Fields[field_index].T
其他键包括值.V .AP.N.Resources
下面有一堆显示信息,比如字体等等但是,如果您更新字段的值并输出 pdf 文件。它可能仅在字段具有焦点时显示值,即被单击。
我还没有想出如何解决这个问题。
此处提供了完整的解决方案:How to edit editable pdf using the pdfrw library?
关键部分是:
template_pdf.Root.AcroForm.update(pdfrw.PdfDict(NeedAppearances=pdfrw.PdfObject('true')))
如果每个字段已编入索引,请使用它来填充它们。
template = PdfReader('template.pdf')
page_c = 0
while page_c < len(template.Root.Pages.Kids): #LOOP through pages
annot_c = 0
while annot_c < len(template.Root.Pages.Kids[page_c].Annots): #LOOP through fields
template.Root.Pages.Kids[page_c].Annots[annot_c].update(PdfDict(V=str(annot_c)+'-'+str(page_c)))
annot_c=annot_c+1
page_c=page_c+1
PdfWriter().write('output.pdf', template)
我写了一个基于以下内容的库:'pdfrw'、'pdf2image'、'Pillow'、'PyPDF2' 称为 fillpdf(pip install fillpdf
和 poppler 依赖项 conda install -c conda-forge poppler
)
基本用法:
from fillpdf import fillpdfs
fillpdfs.get_form_fields("blank.pdf")
# returns a dictionary of fields
# Set the returned dictionary values a save to a variable
# For radio boxes ('Off' = not filled, 'Yes' = filled)
data_dict = {
'Text2': 'Name',
'Text4': 'LastName',
'box': 'Yes',
}
fillpdfs.write_fillable_pdf('blank.pdf', 'new.pdf', data_dict)
# If you want it flattened:
fillpdfs.flatten_pdf('new.pdf', 'newflat.pdf')
更多信息在这里: https://github.com/t-houssian/fillpdf
如果某些字段未填写,您可以使用 fitz (pip install PyMuPDF
) 和 PyPDF2 (pip install PyPDF2
),如下所示根据需要更改点:
import fitz
from PyPDF2 import PdfFileReader
file_handle = fitz.open('blank.pdf')
pdf = PdfFileReader(open('blank.pdf','rb'))
box = pdf.getPage(0).mediaBox
w = box.getWidth()
h = box.getHeight()
# For images
image_rectangle = fitz.Rect((w/2)-200,h-255,(w/2)-100,h-118)
pages = pdf.getNumPages() - 1
last_page = file_handle[pages]
last_page._wrapContents()
last_page.insertImage(image_rectangle, filename=f'image.png')
# For text
last_page.insertText(fitz.Point((w/2)-247 , h-478), 'John Smith', fontsize=14, fontname="times-bold")
file_handle.save(f'newpdf.pdf')