使用python将.doc转换为pdf
我的任务是将成吨的.doc文件转换为.pdf。我的主管希望我这样做的唯一方式是通过MSWord 2010。我知道我应该能够通过python COM自动化来实现这一点。唯一的问题是我不知道如何开始,从哪里开始。我试图搜索一些教程,但没有找到任何(可能是我有,但我不知道我在找什么) 现在我正在通读。不知道这会有多有用。如果您不介意使用,请看一看。提供的代码可用于使用使用python将.doc转换为pdf,python,pdf,automation,ms-word,win32com,Python,Pdf,Automation,Ms Word,Win32com,我的任务是将成吨的.doc文件转换为.pdf。我的主管希望我这样做的唯一方式是通过MSWord 2010。我知道我应该能够通过python COM自动化来实现这一点。唯一的问题是我不知道如何开始,从哪里开始。我试图搜索一些教程,但没有找到任何(可能是我有,但我不知道我在找什么) 现在我正在通读。不知道这会有多有用。如果您不介意使用,请看一看。提供的代码可用于使用WdSaveFormat的wdFormatPDF枚举值(请参阅)。 提供了相同想法的不同实现。我建议忽略您的主管,使用具有Python
WdSaveFormat
的wdFormatPDF
枚举值(请参阅)。
提供了相同想法的不同实现。我建议忽略您的主管,使用具有Python api的OpenOffice。OpenOffice内置了对Python的支持,有人为此创建了一个库()
如果他对输出不满意,告诉他使用word可能需要几周时间。你应该从调查所谓的虚拟PDF打印驱动程序开始。 一旦你找到一个,你应该能够编写批处理文件,将你的文档文件打印成PDF文件。您可能也可以在Python中执行此操作(在MSWord中设置打印机驱动程序输出并发出document/print命令,稍后可以使用命令行AFAIR执行)。一个简单的示例,使用转换单个文件,输入和输出文件名作为命令行参数:
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()
您也可以使用,除以下情况外,其他情况相同:
import win32com.client
然后:
word = win32com.client.Dispatch('Word.Application')
值得注意的是,Stevens answer可以工作,但请确保使用for循环导出多个文件以将ClientObject或Dispatch语句放在循环之前-只需创建一次-请参阅我的问题:unoconv(用python编写)和openoffice作为无头守护进程运行。 非常适合doc、docx、ppt、pptx、xls、xlsx。
如果您需要在服务器上转换文档或保存/转换为某些格式,这非常有用我已经研究了半天这个问题,因此我想我应该分享一些我在这方面的经验。史蒂文的回答是对的,但在我的电脑上会失败。这里有两个关键点需要解决: (1) 。当我第一次创建“Word.Application”对象时,我应该在打开任何文档之前使它(Word app)可见。(事实上,即使我自己也无法解释为什么这样做。如果我不在我的计算机上这样做,当我试图在不可见模型中打开文档时,程序将崩溃,然后操作系统将删除“Word.Application”对象。) (2) 。完成(1)后,程序有时会运行良好,但可能经常失败。崩溃错误
“COMError:(-2147418111,'呼叫被被叫方拒绝',(无,无,无,0,无))”
意味着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
我尝试了公认的答案,但并不特别热衷于Word正在生成的臃肿的PDF,它通常比预期的要大一个数量级。在研究了如何在使用虚拟PDF打印机时禁用对话框之后,我遇到了Bullzip PDF打印机,它的功能给我留下了深刻的印象。它现在取代了我以前使用的其他虚拟打印机。你可以在他们的下载页面上找到“免费社区版” 可以找到COM API,并可以找到可用设置的列表。设置会写入“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")
导入操作系统、re、时间、日期时间、win32com.client
def打印到(文件):
util=win32com.client.Dispatch(“Bullzip.PDFUtil”)
设置=win32com.client.Dispatch(“Bullzip.PDFSettings”)
settings.PrinterName=util.DefaultPrinterName#确保我们控制的是正确的PDF打印机
outputFile=re.sub(“\.[^.]+$”,“.pdf”,文件)
statusFile=re.sub(“\.[^.]+$”,“.status”,文件)
settings.SetValue(“输出”,outputFile)
settings.SetValue(“ConfirmOverwrite”、“no”)
settings.SetValue(“ShowSaveAS”、“never”)
settings.SetValue(“ShowSettings”、“never”)
settings.SetValue(“ShowPDF”、“no”)
settings.SetValue(“显示进度”、“否”)
settings.SetValue(“ShowProgressFinished”、“no”)#禁用气球提示
settings.SetValue(“StatusFile”,StatusFile)#打印作业后创建
settings.WriteSettings(True)#将设置写入runonce.ini
util.PrintFile(file,util.DefaultPrinterName)#发送到Bullzip虚拟打印机
#等待打印作业完成后再继续
#否则,可能无法使用下一个作业的设置
timestamp=datetime.datetime.now()
while((datetime.datetime.now()-timestamp).seconds<10):
如果os.path.exists(状态文件)和os.path.isfile(状态文件):
error=util.ReadIniString(状态文件,“状态”,“错误”,“错误”)
如果出现错误!="0":
raise IOError(“创建PDF时有错误”)
删除操作系统(状态文件)
返回
睡眠时间(0.1)
引发IOError(“PDF创建超时”)
作为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”等
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
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)
word_extensions = [".doc", ".odt", ".rtf", ".docx", ".dotm", ".docm"]
ppt_extensions = [".ppt", ".pptx"]