使用Python进行多个.doc文件转换为.docx文件。

11
我想将特定文件夹中的所有.doc文件转换为.docx文件。
我尝试使用以下代码:
import subprocess
import os
for filename in os.listdir(os.getcwd()):
    if filename.endswith('.doc'):
        print filename
        subprocess.call(['soffice', '--headless', '--convert-to', 'docx', filename])

但是它给了我一个错误: OSError: [Errno 2] No such file or directory

5个回答

21

这里有一个对我有效的解决方案。其他提出的解决方案在我使用Python 3的Windows 10计算机上无效。

from glob import glob
import re
import os
import win32com.client as win32
from win32com.client import constants

# Create list of paths to .doc files
paths = glob('C:\\path\\to\\doc\\files\\**\\*.doc', recursive=True)

def save_as_docx(path):
    # Opening MS Word
    word = win32.gencache.EnsureDispatch('Word.Application')
    doc = word.Documents.Open(path)
    doc.Activate ()

    # Rename path with .docx
    new_file_abs = os.path.abspath(path)
    new_file_abs = re.sub(r'\.\w+$', '.docx', new_file_abs)

    # Save and Close
    word.ActiveDocument.SaveAs(
        new_file_abs, FileFormat=constants.wdFormatXMLDocument
    )
    doc.Close(False)

for path in paths:
    save_as_docx(path)

我遇到了这个错误 --> com_error: (-2147352567, '发生异常。', (0, 'Microsoft Word', "抱歉,我们找不到您的文件。它是否被移动、重命名或删除?\r (C:\//Users/shreyajain/Documents/Docum...)", 'wdmain11.chm', 24654, -2146823114), None) 有什么建议吗? - shreyans jain
根据错误信息,我猜测您输入的文件路径不正确。但是,如果没有看到您的代码,很难确定。 - dshefman
1
  1. 这也允许您将PDF文件转换为DOCX,使您能够阅读PDF文档的内容。
  2. 我建议在程序开头添加一个TRY,以检查是否安装了MS-Word: MSWord_OK = True try: word = win32.gencache.EnsureDispatch('Word.Application')
- Origami

4

我更喜欢使用 glob 模块来完成此类任务。将其放入一个名为 doc2docx.py 的文件中。要使它可执行,设置 chmod +x。并且可以选择将该文件放在您的 $PATH 中,以使其“随处可用”。

#!/usr/bin/env python

import glob
import subprocess

for doc in glob.iglob("*.doc"):
    subprocess.call(['soffice', '--headless', '--convert-to', 'docx', doc])

尽管理想情况下你应该让shell自己来扩展,然后通过文件参数调用doc2docx.py,例如doc2docx.py *.doc

#!/usr/bin/env python

import subprocess
import sys

if len(sys.argv) < 2:
    sys.stderr.write("SYNOPSIS: %s file1 [file2] ...\n"%sys.argv[0])

for doc in sys.argv[1:]:
    subprocess.call(['soffice', '--headless', '--convert-to', 'docx', doc])

根据@pyd的要求,将输出到目标目录myoutputdir使用以下命令:

#!/usr/bin/env python

import subprocess
import sys

if len(sys.argv) < 2:
    sys.stderr.write("SYNOPSIS: %s file1 [file2] ...\n"%sys.argv[0])

for doc in sys.argv[1:]:
    subprocess.call(['soffice', '--headless', '--convert-to', 'docx', '--outdir', 'myoutputdir', doc])

从我的测试中发现,只有在工作/目标目录位于文件系统的根目录时才会失败,例如直接使用“C:\”或“D:\”。任何其他文件夹都能正常工作。看起来是“soffice”的一个错误。您可以使用选项“--outdir <directory-name>”指定输出目录。 - Jan Christoph Terasa
我需要再传递一个参数吗?您能编辑您的答案吗? - Pyd

3
如果您不喜欢依赖于子进程调用,则可以使用带有COM客户端的版本。 如果您的目标是没有安装LibreOffice的Windows用户,则这非常有用。
#!/usr/bin/env python

import glob
import win32com.client

word = win32com.client.Dispatch("Word.Application")
word.visible = 0

for i, doc in enumerate(glob.iglob("*.doc")):
    in_file = os.path.abspath(doc)
    wb = word.Documents.Open(in_file)
    out_file = os.path.abspath("out{}.docx".format(i))
    wb.SaveAs2(out_file, FileFormat=16) # file format for docx
    wb.Close()

word.Quit()

2
它很干净。但是,我想知道是否有任何平台无关的方法将doc转换为docx? - longbowking
1
@longbowking,去年我查找时没有找到一个万能库来解决这个问题。一种可能的方法是使用sys.platform检测操作系统,并尝试Jan Christoph Terasa的Linux方法或我的Windows方法。不确定Mac上是否适用。 - James Parker
刚试了一下使用 这个 docker 镜像 运行 unoconv,将 doc 转换为 docx,但生成的 docx 文件已经损坏(文件里包含我需要保留的注释)。 - lucid_dreamer

2

基于dshefman的代码,

import re
import os
import sys
import win32com.client as win32
from win32com.client import constants

# Get path from command line argument
ABS_PATH = sys.argv[1]

def save_as_docx(path):
    # Opening MS Word
    word = win32.gencache.EnsureDispatch('Word.Application')
    doc = word.Documents.Open(path)
    doc.Activate ()

    # Rename path with .docx
    new_file_abs = os.path.abspath(path)
    new_file_abs = re.sub(r'\.\w+$', '.docx', new_file_abs)

    # Save and Close
    word.ActiveDocument.SaveAs(new_file_abs, FileFormat=constants.wdFormatXMLDocument)
    doc.Close(False)

def main():
    source = ABS_PATH

    for root, dirs, filenames in os.walk(source):
        for f in filenames:
            filename, file_extension = os.path.splitext(f)

            if file_extension.lower() == ".doc":
                file_conv = os.path.join(root, f)
                save_as_docx(file_conv)
                print("%s ==> %sx" %(file_conv,f))

if __name__ == "__main__":
    main()

1
使用 os.path.join 来指定正确的目录。
import os, subprocess

main_dir = os.path.join('/', 'Users', 'username', 'Desktop', 'foldername')

for filename in os.listdir(main_dir):
    if filename.endswith('.doc'):
        print filename
        subprocess.call(['soffice', '--headless', '--convert-to', 'docx', filename])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接