使用python将.doc转换为pdf

使用python将.doc转换为pdf,python,pdf,automation,ms-word,win32com,Python,Pdf,Automation,Ms Word,Win32com,我的任务是将成吨的.doc文件转换为.pdf。我的主管希望我这样做的唯一方式是通过MSWord 2010。我知道我应该能够通过python COM自动化来实现这一点。唯一的问题是我不知道如何开始,从哪里开始。我试图搜索一些教程,但没有找到任何(可能是我有,但我不知道我在找什么) 现在我正在通读。不知道这会有多有用。如果您不介意使用,请看一看。提供的代码可用于使用WdSaveFormat的wdFormatPDF枚举值(请参阅)。 提供了相同想法的不同实现。我建议忽略您的主管,使用具有Python

我的任务是将成吨的.doc文件转换为.pdf。我的主管希望我这样做的唯一方式是通过MSWord 2010。我知道我应该能够通过python COM自动化来实现这一点。唯一的问题是我不知道如何开始,从哪里开始。我试图搜索一些教程,但没有找到任何(可能是我有,但我不知道我在找什么)

现在我正在通读。不知道这会有多有用。

如果您不介意使用,请看一看。提供的代码可用于使用
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"]