Некоторые гос. структуры формируют отчёты в doc файлах. Где-то это делается руками, а где-то автоматически. Представим, что вам поручено обработать тонну таких документов. Это может быть необходимо для вычленения какой-то конкретной информации или просто проверки содержимого. Нам нужно вынуть только неформатированный текст без графиков и картинок. К примеру, такие данные проще засовывать в нейронную сеть для дальнейшего анализа.

Вот некоторые варианты для самого обычного человека:

  • Ручками перебрать все файлы по одному. Уже после десятого документа к вам придёт мысль о том, что вы делаете что-то не так.
  • Попробовать найти в интернете специальную библиотеку (расширение) для работы с doc файлами на языке программирования, которым вы владеете. Потратить часок другой на понимание, как работать с этой библиотекой. Также вам ещё предстоит столкнуться с тем, что принципы работы с doc и docx слегка отличаются.
  • Попытаться автоматизированно пересохранить все документы в другой формат, с которым будет удобнее работать.

Как раз о последнем варианте и пойдёт речь.

И на помощь к нам спешит vbs скрипт. vbs скрипт можно вызвать из командной строки, что можно сделать в любом языке программирования.

Создадим файл converter.vbs

Const wdFormatText = 2
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open(Wscript.Arguments.Item(0), True)
objDoc.SaveAs WScript.Arguments.Item(1), wdFormatText
objWord.Quit

В первой строке мы указываем, в какой формат будем конвертировать: 2 — в txt, 17 — в pdf.
Все форматы можно посмотреть тут. Во второй строке мы открываем непосредственно word. После открытия можно добавить следующую строку:

objWord.Visible = TRUE

Это приведёт к тому, что мы будем видеть процесс открытия Word. Это может быть полезно в том случае, если в какой-то момент произойдёт ошибка, word не закроется сам, и без этой строчки процесс можно будет убить только через диспетчер задач, а так мы просто сможем нажать на крестик.

В командной строке скрипт будет запускаться следующим образом:

converter.vbs полный_путь_к_файлу\имя_файла.docx полный_путь_куда_сохранить\имя_файла_без_расширения

Wscript.Arguments.Item(0) — это полный_путь_к_файлу\имя_файла.docx
WScript.Arguments.Item(1) — полный_путь_куда_сохранить\имя_файла_без_расширения
Соответственно, в третьей строке нашего скрипта мы открываем файл, и на следующей строке сохраняем в указанный формат. И в завершении закрываем word.

Есть ещё одна маленькая нужная хитрость. Иногда из-за разницы в версиях word или по другим причинам, word может ругнуться, сказав, что файл повреждён. При ручном открытии файла мы увидим предупреждение «повреждена таблица, продолжить открытие файла?». И нужно лишь нажать на «Да», но скрипт уже на этом моменте прекратит свою работу.

В vbs очень корявая конструкция «try catch». Обойти данную проблему можно, добавив всего две строчки. Итого полноценный стабильный скрипт выглядит следующим образом:

Const wdFormatText = 2
Set objWord = CreateObject("Word.Application")
objWord.Visible = TRUE
On Error Resume Next
Set objDoc = objWord.Documents.Open(Wscript.Arguments.Item(0), True)
Set objDoc = objWord.Documents.Open(Wscript.Arguments.Item(0), True)
objDoc.SaveAs WScript.Arguments.Item(1), wdFormatText
objWord.Quit

Как вы можете заметить, продублировано открытие файла. В случае, когда с файлом всё в порядке, файл просто откроется два раза, а в случае ошибки просто продолжит открытие файла.

И на всякий пожарный, пример того, как может выглядеть функция на Python

import os
#folder_from = os.getcwd() + r'\words' - папка, где лежит тонна word файлов
#folder_to = os.getcwd() + r'\txts' - папка, куда будем сохранять 
def convert(file_name):
    str1 = folder_from + r"/" + file_name
    str2 = folder_to + r"/" + file_name[:file_name.rfind('.')] 
    os.system('converter.vbs  "' + str1 + '" "' + str2 + '"') #запуск скрипта

Далее просто применяем эту функцию ко всем файлам, которые нужно конвертнуть.

Итог


  1. Данное решение подходит под все форматы word.
  2. На прочтение этой статьи вы потратили не более 10 минут.
  3. Можно реализовать зная любой язык программирования.

Комментарии (17)


  1. GnuriaN
    26.02.2019 00:23
    +1

    Прошу меня понять и простить:


    import sys
    import os,os.path
    import comtypes.client
    
    wdFormatPDF = 17
    
    input_dir = 'input directory'
    output_dir = 'output directory'
    
    for subdir, dirs, files in os.walk(input_dir):
        for file in files:
            in_file = os.path.join(subdir, file)
            output_file = file.split('.')[0]
            out_file = output_dir+output_file+'.pdf'
            word = comtypes.client.CreateObject('Word.Application')
    
            doc = word.Documents.Open(in_file)
            doc.SaveAs(out_file, FileFormat=wdFormatPDF)
            doc.Close()
            word.Quit()

    Взято тут: https://stackoverflow.com/questions/29637626/converting-rtf-to-pdf-using-python


    1. RadioRedFox Автор
      26.02.2019 00:38

      Интересный вариант, спасибо.
      Моё решение не только для питонистов.


      1. wtpltd
        26.02.2019 07:16

        С другой стороны, ваше решение только для винды и только для винды с установленным офисом. Как и у камрада GnuriaN
        Большой минус обеих вариантов — запуск и убийство ворда на каждый файл. Не знаю, связано это с какими-то особенностями или так, но лопатить «тонну документов» будет значительно дольше, чем читать формат напрямую. Под тот же Python есть кучка библиотек.


        1. saege5b
          26.02.2019 10:03

          Там совместимость между версиями вордов — так себе.
          Пока идёт простыня текста или простенькая таблица — всё хорошо. А как документ составит какой-нибудь извращеннец-умелец, тут оно и может поломаться.
          Принтер, шрифты, монитор, версии Офиса и Винды (кто сохранял, кто открыл) — мал-мала влияют на результат.


  1. Fails
    26.02.2019 00:35

    Напомнило то, как я лет 6 назад дергал из C++ объект 'Word.Application' для автоматизации генерации отчетов по лабам)


    1. QtRoS
      26.02.2019 07:47

      Есть ощущение, что с таким уровнем лабы как минимум по программированию можно было не делать ;)


      1. San_tit
        26.02.2019 08:33

        Уровень уровнем, а учебный план (в т.ч. лабы) никто не отменял =) разве что досрочно сдать можно (экзамен в том числе).

        П.С. можно конечно заморочится и сделать индивидуальный, но я не представляю что для этого нужно =)


  1. forcewake
    26.02.2019 10:45

    Если пакета Office не стоит на машине пользователя/сервере или нужно делать такую операцию «в облаке», то задача приобретает иные краски.
    Когда-то использовал вот это github.com/zrrrzzt/tfk-api-unoconv

    На очень сложных документах «вёрстка», конечно, может сломаться. Но у меня были документы со сложными таблицами/графиками — работало неплохо.


  1. zartarn
    26.02.2019 10:51

    Но ворд же со времен версии 2007 ставит виртуальный PDF принтер через который и так всё превращается в нормальный PDF


  1. Newcss
    26.02.2019 13:30

    Если честно, то посыла статьи толком не понял. Сначала хотели

    Это может быть необходимо для вычленения какой-то конкретной информации или просто проверки содержимого
    , потом решили конвертировать из одного формата в другой, да причем на VBS… Язык был выбран скорее всего по причине — когда-то его учили…

    Если нужно переводить из одного формата в другой очень большое количество документов, то можно поставить на компьютер документооборот Alfresco (бесплатный). И настроить правило — все что попадает в одну папку, конвертируется и кладется в другую папку.
    Удобно тем, что — можно настроить сборщик с почты, примонтировать папки и ни кто даже и знать не будет что все идет через документооборот, полностью автоматизировав процесс) без программирования.


  1. mihdan
    26.02.2019 20:17

    Каким боком тут WordPress?


  1. garcia
    26.02.2019 23:55

    В Open/LibreOffice появился headless режим, что сильно ускорило запуск для подобных задач

    ext = 'html'
    os.chdir(oo_path)
    try:
        subprocess.check_call(oo_executable + ' --headless --convert-to ' + ext + ' --outdir ' + destPath + ' ' + srcFile, shell=True)
    except subprocess.CalledProcessError as e:
        print(e.output)
    

    Конвертит все что сможет открыть. Кросплатформенно. Бесплатно.


  1. RumataEstora
    27.02.2019 17:39

    Возможно вам понравится: doc2html. Из недостатков
    — некроссплатформенно, потому что использует jscript и
    — требует наличие установленного в системе ворда


    Из плюсов
    — быстр (скорость загрузки опредяется скоростью открытия/закрытия документов)
    — оптимально использует одну копию ворда


    Хотя имеет смысл посмотреть в сторону других утилит, например, pandoc


  1. bopoh13
    27.02.2019 17:51

    Все форматы, во что сохраняет Word, есть в справке.


    1. RadioRedFox Автор
      28.02.2019 11:55

      Спасибо, дополнил статью этой ссылкой


  1. goodmy
    27.02.2019 21:05

    Вроде у питона есть расширение для работы с docx, которое позволяет пересохранять в другие форматы. К тому же есть python-oletools, который позволяет работать с установленным ms office (и не только) напрямую, без прослойки на vbs) Ну в целом ваше решение норм, очень нестандартное)


  1. taranarmo
    27.02.2019 21:08

    .docx можно в plain text (или во множество других форматов, в их числе TeX, HTML и markdown) перегонять с помощью pandoc, правда .doc он не умеет