我的任务是将大量的.doc文件转换为.pdf。我的主管要我这样做的唯一方法是通过MSWord 2010.我知道我应该能够通过python COM自动化实现自动化。唯一的问题是我不知道如何以及从哪里开始。我试着寻找一些教程,但却找不到(可能是我可能有,但我不知道我在找什么)。
现在我正在阅读this。不知道这会有多大用处。
答案 0 :(得分:53)
使用comtypes的简单示例,转换单个文件,输入和输出文件名作为命令行参数:
import sys
import os
import comtypes.client
wdFormatPDF = 17
in_file = os.path.abspath(sys.argv[1])
out_file = os.path.abspath(sys.argv[2])
word = comtypes.client.CreateObject('Word.Application')
doc = word.Documents.Open(in_file)
doc.SaveAs(out_file, FileFormat=wdFormatPDF)
doc.Close()
word.Quit()
您也可以使用pywin32,除了:
之外,它们都是相同的import win32com.client
然后:
word = win32com.client.Dispatch('Word.Application')
答案 1 :(得分:8)
我已经测试了许多解决方案,但是没有一个可以在Linux发行版上有效地工作。
我推荐此解决方案:
import sys
import subprocess
import re
def convert_to(folder, source, timeout=None):
args = [libreoffice_exec(), '--headless', '--convert-to', 'pdf', '--outdir', folder, source]
process = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout)
filename = re.search('-> (.*?) using filter', process.stdout.decode())
return filename.group(1)
def libreoffice_exec():
# TODO: Provide support for more platforms
if sys.platform == 'darwin':
return '/Applications/LibreOffice.app/Contents/MacOS/soffice'
return 'libreoffice'
然后调用函数:
result = convert_to('TEMP Directory', 'Your File', timeout=15)
所有资源:
https://michalzalecki.com/converting-docx-to-pdf-using-python/
答案 2 :(得分:5)
我已经解决了这个问题半天了,所以我想我应该分享一些关于这个问题的经验。史蒂文的答案是对的,但它会在我的电脑上失败。这里有两个关键点要解决它:
(1)。我第一次创建'Word.Application'对象时,我应该在打开任何文档之前使它(单词app)可见。 (实际上,即使我自己也无法解释为什么会这样。如果我不在我的计算机上执行此操作,当我尝试在隐形模型中打开文档时,程序将崩溃,然后'Word.Application'对象将被删除OS。)
(2)。在执行(1)之后,程序有时会运行良好但可能经常失败。崩溃错误"COMError: (-2147418111, 'Call was rejected by callee.', (None, None, None, 0, None))"
表示COM服务器可能无法如此快速地响应。所以我在尝试打开文档之前添加了延迟。
执行这两个步骤后,程序将完美运行,不再出现故障。演示代码如下。如果遇到相同的问题,请尝试按照以下两个步骤操作。希望它有所帮助。
import os
import comtypes.client
import time
wdFormatPDF = 17
# absolute path is needed
# be careful about the slash '\', use '\\' or '/' or raw string r"..."
in_file=r'absolute path of input docx file 1'
out_file=r'absolute path of output pdf file 1'
in_file2=r'absolute path of input docx file 2'
out_file2=r'absolute path of outputpdf file 2'
# print out filenames
print in_file
print out_file
print in_file2
print out_file2
# create COM object
word = comtypes.client.CreateObject('Word.Application')
# key point 1: make word visible before open a new document
word.Visible = True
# key point 2: wait for the COM Server to prepare well.
time.sleep(3)
# convert docx file 1 to pdf file 1
doc=word.Documents.Open(in_file) # open docx file 1
doc.SaveAs(out_file, FileFormat=wdFormatPDF) # conversion
doc.Close() # close docx file 1
word.Visible = False
# convert docx file 2 to pdf file 2
doc = word.Documents.Open(in_file2) # open docx file 2
doc.SaveAs(out_file2, FileFormat=wdFormatPDF) # conversion
doc.Close() # close docx file 2
word.Quit() # close Word Application
答案 3 :(得分:4)
unoconv(在python中编写)和openoffice作为无头守护进程运行。 http://dag.wiee.rs/home-made/unoconv/
非常适合doc,docx,ppt,pptx,xls,xlsx。 如果您需要转换文档或在服务器上保存/转换为某些格式,这非常有用
答案 4 :(得分:2)
如果您不介意使用PowerShell,请查看此Hey, Scripting Guy! article。可以采用所提供的代码来使用wdFormatPDF
的{{1}}枚举值(请参阅here)。
This blog article提出了同一想法的不同实现。
答案 5 :(得分:2)
值得注意的是,Stevens的回答是有效的,但要确保使用for循环导出多个文件以在循环之前放置ClientObject或Dispatch语句 - 它只需要创建一次 - 请参阅我的问题:{{3} }
答案 6 :(得分:1)
我尝试了接受的答案,但并不是特别热衷于Word生成的臃肿的PDF,这通常比预期的要大一个数量级。在查看如何在使用虚拟PDF打印机时禁用对话框后,我遇到了Bullzip PDF打印机,我对它的功能印象深刻。它现在取代了我之前使用的其他虚拟打印机。您可以在下载页面找到“免费社区版”。
可以找到COM API here,并找到可用设置的列表here。设置将写入“runonce”文件,该文件仅用于一个打印作业,然后自动删除。打印多个PDF时,我们需要确保一个打印作业在启动另一个之前完成,以确保为每个文件正确使用设置。
import os, re, time, datetime, win32com.client
def print_to_Bullzip(file):
util = win32com.client.Dispatch("Bullzip.PDFUtil")
settings = win32com.client.Dispatch("Bullzip.PDFSettings")
settings.PrinterName = util.DefaultPrinterName # make sure we're controlling the right PDF printer
outputFile = re.sub("\.[^.]+$", ".pdf", file)
statusFile = re.sub("\.[^.]+$", ".status", file)
settings.SetValue("Output", outputFile)
settings.SetValue("ConfirmOverwrite", "no")
settings.SetValue("ShowSaveAS", "never")
settings.SetValue("ShowSettings", "never")
settings.SetValue("ShowPDF", "no")
settings.SetValue("ShowProgress", "no")
settings.SetValue("ShowProgressFinished", "no") # disable balloon tip
settings.SetValue("StatusFile", statusFile) # created after print job
settings.WriteSettings(True) # write settings to the runonce.ini
util.PrintFile(file, util.DefaultPrinterName) # send to Bullzip virtual printer
# wait until print job completes before continuing
# otherwise settings for the next job may not be used
timestamp = datetime.datetime.now()
while( (datetime.datetime.now() - timestamp).seconds < 10):
if os.path.exists(statusFile) and os.path.isfile(statusFile):
error = util.ReadIniString(statusFile, "Status", "Errors", '')
if error != "0":
raise IOError("PDF was created with errors")
os.remove(statusFile)
return
time.sleep(0.1)
raise IOError("PDF creation timed out")
答案 7 :(得分:0)
您应该从调查所谓的虚拟PDF打印驱动程序开始。 只要您找到一个,您就应该能够编写将DOC文件打印成PDF文件的批处理文件。您也可以在Python中执行此操作(在MSWord中设置打印机驱动程序输出并发出文档/打印命令,以后可以使用命令行AFAIR完成)。
答案 8 :(得分:0)
作为SaveAs函数的替代方法,您还可以使用ExportAsFixedFormat,它可以访问您通常在Word中看到的PDF选项对话框。通过此,您可以指定书签和其他文档属性。
doc.ExportAsFixedFormat(OutputFileName=pdf_file,
ExportFormat=17, #17 = PDF output, 18=XPS output
OpenAfterExport=False,
OptimizeFor=0, #0=Print (higher res), 1=Screen (lower res)
CreateBookmarks=1, #0=No bookmarks, 1=Heading bookmarks only, 2=bookmarks match word bookmarks
DocStructureTags=True
);
函数参数的完整列表是:'OutputFileName','ExportFormat','OpenAfterExport','OptimizeFor','Range','From','To','Item','IncludeDocProps','KeepIRM' ,'CreateBookmarks','DocStructureTags','BitmapMissingFonts','UseISO19005_1','FixedFormatExtClassPtr'
答案 9 :(得分:0)
您可以使用docx2pdf
python软件包将docx批量转换为pdf。它可以同时用作CLI和python库。它要求安装Microsoft Office,并在Windows上使用COM,在macOS上使用AppleScript(JXA)。
from docx2pdf import convert
convert("input.docx")
convert("input.docx", "output.pdf")
convert("my_docx_folder/")
pip install docx2pdf
docx2pdf input.docx output.pdf
免责声明:我写了docx2pdf软件包。 https://github.com/AlJohri/docx2pdf
答案 10 :(得分:0)
我正在使用此解决方案,但我需要搜索所有.docx,.dotm,.docm,.odt,.doc或.rtf,然后将它们全部转换为.pdf(python 3.7.5)。希望它能起作用...
import os
import win32com.client
wdFormatPDF = 17
for root, dirs, files in os.walk(r'your directory here'):
for f in files:
if f.endswith(".doc") or f.endswith(".odt") or f.endswith(".rtf"):
try:
print(f)
in_file=os.path.join(root,f)
word = win32com.client.Dispatch('Word.Application')
word.Visible = False
doc = word.Documents.Open(in_file)
doc.SaveAs(os.path.join(root,f[:-4]), FileFormat=wdFormatPDF)
doc.Close()
word.Quit()
word.Visible = True
print ('done')
os.remove(os.path.join(root,f))
pass
except:
print('could not open')
# os.remove(os.path.join(root,f))
elif f.endswith(".docx") or f.endswith(".dotm") or f.endswith(".docm"):
try:
print(f)
in_file=os.path.join(root,f)
word = win32com.client.Dispatch('Word.Application')
word.Visible = False
doc = word.Documents.Open(in_file)
doc.SaveAs(os.path.join(root,f[:-5]), FileFormat=wdFormatPDF)
doc.Close()
word.Quit()
word.Visible = True
print ('done')
os.remove(os.path.join(root,f))
pass
except:
print('could not open')
# os.remove(os.path.join(root,f))
else:
pass
try和except是针对那些我直到最后一个文档都无法阅读且不会退出代码的文档。
答案 11 :(得分:0)
我也修改了它以支持ppt。我的解决方案支持所有下面指定的扩展。
word_extensions = [".doc", ".odt", ".rtf", ".docx", ".dotm", ".docm"]
ppt_extensions = [".ppt", ".pptx"]
我的解决方案:Github Link
我修改了来自 Docx2PDF
的代码答案 12 :(得分:-3)
我建议忽略你的主管并使用具有Python api的OpenOffice。 OpenOffice内置了对Python的支持,有人创建了一个专门用于此目的的库(PyODConverter)。
如果他对输出不满意,请告诉他可能需要数周的时间才能完成。