我们有一个 pdf 表单文件
example.pdf
,其中有 3 列:
名称_1, 公司_1,以及 客户_1
我们要填写的数据有希伯来语和英语。 我们的目标是拥有一个可以在浏览器和 Acrobat Reader 中以 RTL 方式打开的文件。 当我们通过以下代码手动保存导出的文件时,我们的目标就达到了,但是我们 不想手动保存它,或者如果没有其他选择,则以编程方式保存它。
import pdfrw
INVOICE_TEMPLATE_PATH = 'example.pdf'
INVOICE_OUTPUT_PATH = 'output.pdf'
ANNOT_KEY = '/Annots'
ANNOT_FIELD_KEY = '/T'
ANNOT_VAL_KEY = '/V'
ANNOT_RECT_KEY = '/Rect'
SUBTYPE_KEY = '/Subtype'
WIDGET_SUBTYPE_KEY = '/Widget'
def write_fillable_pdf(input_pdf_path, output_pdf_path, data_dict):
template_pdf = pdfrw.PdfReader(input_pdf_path)
template_pdf.Root.AcroForm.update(pdfrw.PdfDict(NeedAppearances=pdfrw.PdfObject('true')))
annotations = template_pdf.pages[0][ANNOT_KEY]
for annotation in annotations:
if annotation[SUBTYPE_KEY] == WIDGET_SUBTYPE_KEY:
if annotation[ANNOT_FIELD_KEY]:
key = annotation[ANNOT_FIELD_KEY][1:-1]
if key in data_dict.keys():
annotation.update(
pdfrw.PdfDict(AP=data_dict[key], V='{}'.format(data_dict[key]), Ff=1)
)
pdfrw.PdfWriter().write(output_pdf_path, template_pdf)
data_dict = {
'name_1': 'עידו',
'company_1': 'IBM',
'client_1': 'אסם'
}
if __name__ == '__main__':
write_fillable_pdf(INVOICE_TEMPLATE_PATH, INVOICE_OUTPUT_PATH, data_dict)
我们认为
NeedAppearances
与需要手动保存有关。
在 Acrobat Reader 中打开导出的文件时,Acrobat Reader 会对该文件应用特定的工作。因此,退出时程序会询问我们是否要保存文件。
此操作对我们来说至关重要,但我们自动需要它。
这个操作是什么以及如何在我们的代码中以编程方式执行它?出口之前或之后..
当我将 NeedAppearances 设置为 true 时,我遇到了同样的问题。我发现下面的代码适用于我的 pdf。请告诉我这是否适合您。
from pikepdf import Pdf
with Pdf.open('source_pdf.pdf') as pdf:
pdf.generate_appearance_streams()
pdf.save('output.pdf')
我认为 generate_appearance_streams() 能够生成外观流,而不是让 PDF 阅读器来做,因此使用 Adobe Acrobat Reader 打开时不需要手动保存。
使用
pdfrw
,您可以使用以下代码将 NeedAppearances 设置为 True :
from pdfrw import PdfReader, PdfDict, PdfObject
def set_need_appearances(pdf_reader: PdfReader):
pdf_reader.Root.AcroForm.update(PdfDict(NeedAppearances=PdfObject("true")))
return pdf_reader
使用PyPDF2
,您可以使用
PdfWriter
类上的内置方法设置需要的外观:
pdf_writer = PdfWriter()
pdf_writer.set_need_appearances_writer()
我尝试使用 pdfrw 保存文件并使用 pikepdf 和 PyPDF2 重新打开,但出现了更多问题。我尝试设置
annotation["/AP"] = ""
取得了一些成功,设置
del annotation["/AP"]
取得了更大的成功,但它并不完整/绝对 - 仍然有人问我是否要保存。解决方案是让 Adobe 以编程方式保存文件。当我最终对其进行编程时,表单字段中的值随处可见(除了常见的 PDF 查看器之外,Explorer PDF 预览器、SharePoint 预览器等),并且不再要求我保存文件。
这适用于当前版本的 Acrobat。如果您仍在使用旧版本,则需要使用 ArcoExch.AVDoc 并且不需要创建 PDDoc 对象的实例:
import pdfrw
import win32com.client
pdf = PdfReader("your path")
output_path = "your path"
<actions on the PDF here>
pdf.Root.AcroForm.update(PdfDict(NeedAppearances=PdfObject("true")))
PdfWriter().write(output_path, pdf)
# Create an instance of the Acrobat Application object
acrobat_app = win32com.client.Dispatch("AcroExch.App")
# Create an instance of the PDDoc object
pdf_doc = win32com.client.Dispatch("AcroExch.PDDoc")
# Open the PDF file
pdf_doc.Open(output_path)
# Save the PDF
pdf_doc.Save(1, output_path)
# Close the PDF
pdf_doc.Close()
# Quit Acrobat
acrobat_app.Exit()
'NeedAppearances = true'可以在读取和写入PDF之间的任何位置,这似乎并不重要。我什至尝试使用此解决方案将其完全删除,但它仍然有效。