通过Acrobat COM接口用Python为PDF添加页脚(AddWatermarkFromText)
编辑补充:我已找到解决方案,详见下方内容。
原帖内容
我可以通过以下VBA代码为PDF添加页脚:
Dim PDDocDestination As Object Dim JSO As Object Dim i As Long, numPages As Long Set PDDocDestination = CreateObject("AcroExch.PDDoc") Set JSO = PDDocDestination.GetJSObject numPages = PDDocDestination.GetNumPages ' Loop through each page and add the footer For i = 1 To numPages JSO.addWatermarkFromText cText:="text", cFont:="CenturyGothic", nFontSize:=7, nHorizAlign:=1, nVertAlign:=4, nVertValue:=12.5, nStart:=i - 1, nEnd:=i - 1 Next i 'Save destination (merged) PDF PDDocDestination.Save PDSaveFull, mergedPDF PDDocDestination.Close 'Cleanup Set PDDocDestination = Nothing Set JSO = Nothing
然而,当我尝试将这段代码转换为Python版本时,调用addWatermarkFromText方法时出现错误:pywintypes.com_error: (-2147467263, 'Not implemented', None, None)。我尝试了各种可能的写法,以下是我的Python代码:
def add_footer_to_pdf(pdf_path, output_path, text, font="CenturyGothic", font_size=7, horiz_align=1, vert_align=4, vert_value=12.5): # Create COM object to interact with Acrobat try: AcroApp = Dispatch("AcroExch.App") AcroPDDoc = Dispatch("AcroExch.PDDoc") AcroPDDoc.Open(pdf_path) JSO = AcroPDDoc.GetJSObject() num_pages = AcroPDDoc.GetNumPages() # Loop through each page and add the footer for i in range(num_pages): JSO.addWatermarkFromText(cText=f"{text}, page {i+1}", cFont=font, nFontSize=font_size, nHorizAlign=horiz_align, nVertAlign=vert_align, nVertValue=vert_value, nStart=i, nEnd=i) # Save the modified PDF AcroPDDoc.Save(1, output_path) # if not AcroPDDoc.Save(1, output_path): # print("Failed to save the PDF") finally: AcroPDDoc.Close() AcroApp.Exit() del AcroApp, AcroPDDoc
我不确定是否因为该方法无法通过pywin32/win32com调用,但既然VBA中可用,理论上Python也应该支持。我检查过PDDoc对象初始化和文档打开都没问题——AcroPDDoc.GetNumPages()能返回正确页数。尝试过带/不带参数、带/不带括号、调整方法名首字母大小写,都无效。
解决方案
问题根源是Python的win32com在处理Acrobat JS方法的命名参数时存在兼容问题,改用位置参数传递即可解决。修正后的代码如下:
def add_footer_to_pdf(pdf_path, output_path, text, font="CenturyGothic", font_size=7, horiz_align=1, vert_align=4, vert_value=12.5): try: AcroApp = Dispatch("AcroExch.App") AcroPDDoc = Dispatch("AcroExch.PDDoc") if not AcroPDDoc.Open(pdf_path): print("无法打开目标PDF文件") return JSO = AcroPDDoc.GetJSObject() if JSO is None: print("无法获取Acrobat JS对象,请确认安装了Acrobat Pro(Reader不支持编辑操作)") return num_pages = AcroPDDoc.GetNumPages() # 按位置顺序传递参数,避免命名参数的兼容问题 for i in range(num_pages): JSO.addWatermarkFromText( f"{text}, page {i+1}", # cText font_size, # nFontSize horiz_align, # nHorizAlign vert_align, # nVertAlign vert_value, # nVertValue font, # cFont i, # nStart i # nEnd ) # 保存修改后的PDF(1对应PDSaveFull常量) if not AcroPDDoc.Save(1, output_path): print("保存PDF文件失败") finally: # 确保资源正确释放 if 'AcroPDDoc' in locals() and AcroPDDoc.IsOpen(): AcroPDDoc.Close() if 'AcroApp' in locals(): AcroApp.Exit() del AcroApp, AcroPDDoc
额外注意事项:
- 必须使用Acrobat Pro,Acrobat Reader不支持JS编辑PDF的功能
- 调用
GetJSObject()后务必检查返回值,避免后续空对象调用报错 - 增加文件打开、保存的状态检查,提升代码容错性
内容的提问来源于stack exchange,提问作者Sassbearilla
相关产品推荐
相关产品推荐

