Взаимная конвертация и обработка электронных документов

    LibreOfficeВ корпоративном секторе иногда возникает задача автоматической конвертации документов из одного формата в другой, а так же задача их програмной обработки и модификации. Казалось бы, в чём проблема: для нормальных форматов давным-давно написаны полнофункциональные библиотеки для работы — так что Perl или Python в руки и вперёд.

    Но, к превеликому сожалению для всех системных администраторов и программистов различных бизнес-приложений, огромная масса документооборота в данный момент всё ещё осуществляется с использованием закрытых и плохо поддающихся модификации и разбору форматов. Что уж тут лукавить — речь идёт о doc, xls и иже с ними, а так же во многом о docx, xlsx и подобных. Что делать с такими файлами, особенно если у вас нету свободной Windows с установленной последней версией Office, — совершенно непонятно. Безусловно, если у вас есть Windows, Visual Studio и навыки работы в C#, то проблем с анализом документов Microsoft будет значительно меньше. Зато возникнут проблемы с ODF. Плюс часто хочется сохранять результат в формате PDF, дабы уже никто не мог его изменить.

    К счастью, есть достаточно универсальный способ работы практически с любыми распространёнными форматами документов на любой платформе. О нём и пойдёт речь дальше.

    Без сомнения все знают про OpenOffice и его прогрессивное ответвление — LibreOffice. Последние версии этих пакетов отлично справляются с документами Microsoft — по крайней мере гораздо лучше многих бесплатных библиотек парсинга.

    Но не многие знают, что у OpenOffice и конечно же у LibreOffice есть API, позволяющий работать с документами напрямую из Python. В частности, с помощью этого API можно преспокойно конвертировать документы из одного формата в другой.

    Таким образом для разбора любого документа достаточно преобразовать его в соответствующий формат ODF, затем с помощью любимого языка программирования выполнить все необходимые изменения, а затем, при необходимости, сконвертировать результат в PDF или формат MS Office 2003 (doc, xls).

    Другой сценарий: у вас есть куча документов в редактируемых форматах (doc, docx, odt), а вам надо сделать из них PDF. Всё тот же скрипт позволит вам без проблем автоматически выполнить такое преобразование. Или же вы для внутреннего документооборота используете стандартизированный ODF, но ваши партнёры до сих пор даже до docx не доросли. Ничего страшного — LibreOffice поможет автоматически сконвертировать ODF в формат MS Office.

    Вообще сценариев применения API LibreOffice превеликое множество — так что круг возможных задач для решения очень широк.

    Что потребуется


    В статье описывается использование LibreOffice на Ubuntu, хотя с небольшой модификацией все инструкции переносятся как на другие дистрибутивы Linux и OpenOffice, так и на Windows и MacOS.

    Всё, что нужно — это установленные LibreOffice и Python, а так же базовое умение писать скрипты.

    Собственно сам bash скрипт конвертации выглядит так:

    #!/bin/bash
    
    # Скрипт конвертации различных форматов офисных документов
    # с помощью LibreOffice.
    #
    # Использование: libre-converter.sh infile outfile
    
    LIBREOFFICE=`which libreoffice`
    PYTHON=`which python`
    DIR=`dirname "$0"`
    
    if [ ! -e "$1" ]
    then
     echo "Could not find source file $1"
     exit
    fi
    
    if [ ! -x "$LIBREOFFICE" ]
    then
     echo "Could not find LibreOffice binary"
     exit
    fi
    
    if [ ! -x "$PYTHON" ]
    then
     echo "Could not find Python"
     exit
    fi
    
    # Закрываем все запущенные копии LibreOffice
    killall -u `whoami` -q soffice
    
    # Нам нужен дополнительный скрипт-обёртка для работы с LibreOffice API
    test -f $DIR/DocumentConverter.py || wget http://www.artofsolving.com/files/DocumentConverter.py
    
    # Запускаем LibreOffice в режиме прослушки 8100 порта TCP
    $LIBREOFFICE "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -norestore -nofirststartwizard -nologo -headless  &
    
    # Немного ждём, чтобы убедиться, что LibreOffice точно запустился
    sleep 5s
    
    # Конвертируем...
    echo -n "   Converting $1 to $2... "
    $PYTHON $DIR/DocumentConverter.py "$1" "$2"
    echo "Done!"
    
    # Закрываем LibreOffice
    killall -u `whoami` soffice
    

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

    Например, мне нужно было добавить к большому количеству doc документов титульные листы одинакового формата и сохранить результат в формате PDF. Для добавления титульных листов я использовал скрипт на Perl и библиотеку OpenOffice::OODoc (доступную в Ubuntu как пакет libopenoffice-oodoc-perl). В итоге получился такой скрипт пакетной обработки:

    #!/bin/bash
    
    DIR=`dirname "$0"`
    TOOLS="$DIR/tools"
    
    INFILE="$1"
    FILENAME=`echo "$1" | sed 's/\.[^.]*$//'`
    SHORTNAME=`basename "$FILENAME"`
    OUTPATH=`dirname "$FILENAME"`
    
    if [ ! -e "$INFILE" ]
    then
     echo "Could not find source file $INFILE"
     exit
    fi
    
    echo ""
    echo "### Converting $INFILE ###"
    
    # Преобразуем DOC в ODT:
    echo "1. Converting DOC to ODT:"
    $TOOLS/libre-converter.sh "$INFILE" "$FILENAME.odt"
    if [ $? -ne 0 ];
    then
    	echo "ERROR!"
    	echo "Ошибка преобразования $INFILE с помощью LibreOffice!"
    	rm "$FILENAME.odt"
    	exit
    fi
    
    # Добавляем титульный лист
    echo -n "2. Add first page to ODT... "
    $TOOLS/add-1st-page.pl "$FILENAME.odt"
    if [ $? -ne 0 ];
    then
    	echo "ERROR!"
    	echo "Ошибка добавления титульного листа в файл $INFILE!"
    	rm "$FILENAME.odt"
    	exit
    fi
    echo "Done!";
    
    # Преобразуем ODT в PDF
    echo "3. Converting ODT to PDF:"
    $TOOLS/libre-converter.sh "$FILENAME.odt" "$OUTPATH/$SHORTNAME.pdf"
    if [ $? -ne 0 ];
    then
    	echo "ERROR!"
    	echo "Ошибка преобразования $FILENAME.odst с помощью LibreOffice!"
    	rm "$FILENAME.odt"
    	exit
    fi
    
    # Удаляем временные файлы
    echo -n "4. Do some cleaning... "
    rm "$FILENAME.odt"
    
    echo "All done! :)"

    Теперь достаточно выполнить

    find /my/doc/path -type f -iname "*.doc" -exec ./convert.sh {} \;

    и на выходе получим набор PDF файлов с красивыми титульными листами.

    Другие возможности


    С помощью описанной техники можно не только конвертировать различные форматы документов между собой, но и выполнять экспорт в файлы изображений, как то JPEG или PNG. Для этого потребуется поставить ImageMagic, затем с помощью описанного скрипта сконвертировать документ в PDF, а с помощью ImageMagic сконвертировать PDF в нужный формат изображений:

    convert sample.pdf sample.png
    convert sample.pdf sample.jpg
    convert sample.pdf sample.tif

    Чуть больше информации об автоматической конвертации документов с использованием LibreOffice или OpenOffice можно найти тут:

    http://www.oooninja.com/2008/02/batch-command-line-file-conversion-with.html

    Упоминаемый выше Python API для LibreOffice (который, к слову, называется PyUNO), можно использовать для прямого редактирования документов из Python, хотя зачастую это не очень удобно. Подробнее можно почитать в этом хабратопике.

    UPD: Как подсказали в комментариях: добрые люди упростили конвертацию документов с помощью OpenOffice (LibreOffice), написав скрипт-обёртку unoconv. Эта утилитка делает ровно то же и ровно таким же способом, что и описаные выше скрипты. Но она безусловно будет удобней в большинстве случаев, если нормально запустится на вашей системе.

    Комментарии 13

      +9
      не хочется огорчать, но есть unoconv.
        +7
        Почему ж огорчать? Радовать! ПИсать на Хабр стоит только ради того, чтобы почитать комментарии и узнать много нового. Я никогда не натыкался на эту утилиту почему-то(( Хотя перелопатил кучу материалов по обработке документов. Хотя по сути она просто делает ровно то же, что описано в статье ровно тем же способом)
          +1
          Плюс, похоже, unoconv пока что для Libre не всегда применим без напильника. А так коннектимся напрямую к Libre (OpenOffice).
        0
        Было бы оно так просто в жизни:(
          0
          Если бы еще избавиться от зависимости к LibreOffice\OpenOffice. Тогда уж точно цены не было бы такому конвертору. А иногда ставить данные пакеты только ради конвертации не имеет смысла.
            0
            Особенно на сервер…
            –2
            Нормальный формат PDF… Долго смеялся

            PDF нормален ровно потому, что его спецификация открыта. А так — еще один формат с кучей тараканов. КОторый кроме Apple'а и самого Adobe еще никто и отображать нормально не может (и то — не все PDF'ы откроются, как надо, на всех компьютерах)
              +5
              ЕМНИП даже CUPS на PDF перешёл. Чем плох-то PDF? Спецификация полностью открыта, косяков в ней вроде нет, софта для работы — навалом. Чтобы PDF нормально не отображался — я уже много лет не видел (у меня Evince и Foxit). Все переходят на PDF. Собственно потому что адекватных альтернатив-то и нет.
                +1
                > Чтобы PDF нормально не отображался — я уже много лет не видел (у меня Evince и Foxit).

                У нас это — легко. Мы тут генернируем счета в PDF. За-ма-на-лись. Причем это то глюки PDF-а то глюки «многих программ, которые с PDF работают»

                То кириллица не отображается, или отображается у разных по-разному.
                То PDF в винде отображается, а на Маках — пустая белая страница, то наоборот.

                > Собственно потому что адекватных альтернатив-то и нет.

                С этим соглашусь. Потому что он один, по сути, не зависит ни от системы, ни от шрифтов, ни от чего-либо другого

                З.Ы. На самом деле я резко так выразился именно из-за того, что для генерации PDF программно практически нет нормальных средств. С чем это связано — хз.
                  +4
                  Ну, если подумать, то я PDF никогда не генерировал программно напрямую. Либо из LaTeX, либо из odt (doc), либо в некоторых случаях PDF принтером — ну и косяков никогда не встречал, если честно.

                  В целом формат-то однозначно хороший. Я проблемы есть везде.
                    +1
                    > В целом формат-то однозначно хороший. Я проблемы есть везде.

                    Когда я в особо философском настроении, а обычно говорю, что все — г.но, но что-то меньшее г.но, чем другие :)
              0
              делали генерацию pdf через формирование odt (который суть есть zip архив с xml файлами схем, структуры и формата текста, а так же вложений, если такие есть), библиотек для работы с xml — валом, дальше перепаковка в zip и описанная выше конвертация odt2pdf. Почему не pisa? Сильно присесть пришлось с кириллицей и собственным толкованием html/css разметки у этого волшебного пакета.
                0
                Другой сценарий: у вас есть куча документов в редактируемых форматах (doc, docx, odt), а вам надо сделать из них PDF. Всё тот же скрипт позволит вам без проблем автоматически выполнить такое преобразование.
                Тут лучше использовать pdf-принтер, и не только потому, что проще, но и потому, что лучше. Я как-то для интереса взял один документ и сконвертировал его с помощью OOo, а потом из последнего же распечатал на dopdf. Разница минимальная, но все же результат dopdf чуть менее корявый.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое