xmlhack.ru logo
>> статьи на xmlhack.ru

Переход к OpenOffice: пакетное преобразование существующих документов

Автор: Боб ДюШарм
Перевод: А.Скробов
Опубликовано на XML.com (11.01.2006, англ.): http://www.xml.com/pub/a/2006/01/11/from-microsoft-to-openoffice.html
Опубликовано на xmlhack.ru (29.01.2006, рус.): http://xmlhack.ru/texts/06/from-microsoft-to-openoffice/from-microsoft-to-openoffice.html
В закладки:   Del.icio.us   reddit

Широко известно, что при помощи OpenOffice 2.0, открытой альтернативы пакету Microsoft Office, можно открывать файлы, созданные в Microsoft Office, и затем сохранять их в родном формате OpenOffice — zip-архиве, содержащем документ в виде XML-файла, соответствующего стандарту OpenDocument от OASIS. Таким образом можно преобразовывать в новый формат существующие документы Word, таблицы Excel и презентации PowerPoint. (В статье Opening Open Formats with XSLT на XML.com приводится пример простого приложения, использующего эти возможности: XSL-шаблон, который извлекает заголовки слайдов и заметки из файла с презентацией и сохраняет их в отдельный файл, который вы могли бы использовать как план своего выступления.) Более того, OpenOffice позволяет экспортировать все эти виды файлов в формат PDF.

Если вы собираетесь преобразовывать ваши файлы в новый формат по одному, то вам придётся открыть и заполнить несколько диалоговых окон для каждого файла. Если вам требуется преобразовать несколько сотен файлов, то такой подход окажется затруднительным. Что же делать, если у вас есть большая куча документов Word, таблиц Excel и презентаций PowerPoint, и вам нужно загрузить XML-версии всех файлов в одну базу данных, которая поддерживала бы запросы к содержимому этих XML-документов? Например, если вы — это штат Массачусетс или фирма IBM?

Как и в продукте фирмы Microsoft, в OpenOffice есть макроязык. При запуске OpenOffice из командной строки Linux или Windows можно указывать, чтобы выполнился определённый макрос. Можно даже передать этому макросу в качестве параметра имя файла. Далее, если использовать ключ -invisible при запуске OpenOffice из командной строки, то его графический интерфейс (GUI) не будет отображаться. А если задействовать обе этих возможности вместе, то получится командная строка, которая преобразует файл Microsoft Office в файл OpenOffice (или в файл Acrobat) безо всякого GUI. Теперь, чтобы преобразовать сотню файлов, достаточно простого скрипта (например, на языке Perl), чтобы создать пакетный файл либо шелл-скрипт из сотни команд, каждая из которых преобразует один файл.

(Замечание: макросы, который вдохновили меня на создание этой статьи, явно были написаны для OpenOffice 1. x, — но тот макрос, который я из них собрал, был протестирован мной в OpenOffice 2.0 в Windows и в Linux.)

Создание макросов для преобразования

Все процедуры, которые понадобятся в ваших макросах, приведены ниже. Чтобы создать в OpenOffice модуль макросов и сохранить в него эти процедуры, выберите пункт меню Tools→Macros и затем Organize Macros, OpenOffice.org Basic, Organizer, New. Создастся новый модуль макросов. Назовите его MyConversions и закройте диалоговое окно.

Новый модуль будет отображаться в дереве макросов под именем /My Macros/Standard/MyConversions, как показано ниже:

OpenOffice Macro module dialog box

Выберите модуль MyConversions и нажмите кнопку Edit. В появившемся скрипте строчки Sub Main и End Main служат шаблоном для будущего макроса. Замените их следующим кодом, после чего сохраните модуль:


' За основу взят код с
http://www.oooforum.org/forum/viewtopic.phtml?t=3772

' Сохранить документ в формате Acrobat PDF.
Sub SaveAsPDF( cFile )
   cURL = ConvertToURL( cFile )
   ' Открыть документ. Мы предполагаем, что тип документа
   ' будет корректно распознан, и поэтому не указываем
   ' конкретный фильтр импорта.
   oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, _
            Array(MakePropertyValue( "Hidden", True ),))

   cFile = Left( cFile, Len( cFile ) - 4 ) + ".pdf"
   cURL = ConvertToURL( cFile )
   
   ' Сохранить документ, используя фильтр экспорта.
   oDoc.storeToURL( cURL, Array(_
            MakePropertyValue( "FilterName", "writer_pdf_Export"
),)
   
   oDoc.close( True )
End Sub

' Сохранить документ в формате Microsoft Word. 
Sub SaveAsDoc( cFile ) 
   ' практически совпадает с SaveAsPDF
   cURL = ConvertToURL( cFile )
   oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, (_
            Array(MakePropertyValue( "Hidden", True ),))


   cFile = Left( cFile, Len( cFile ) - 4 ) + ".doc"
   cURL = ConvertToURL( cFile )
   
   oDoc.storeToURL( cURL, Array(_
            MakePropertyValue( "FilterName", "MS WinWord 6.0" ),)
   oDoc.close( True )

End Sub


' Сохранить документ в формате OpenOffice 2.
Sub SaveAsOOO( cFile ) 
   ' практически совпадает с SaveAsPDF
   cURL = ConvertToURL( cFile )
   oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, _
            Array(MakePropertyValue( "Hidden", True ),))

   ' Расширение нового файла выбирается на основании расширения
   ' исходного файла, переведённого в нижний регистр.
   Select Case LCase(Right(cFile,3))
     Case "ppt"         ' PowerPoint file.
       cFileExt = "odp"
     Case "doc"         ' Word file.
       cFileExt = "odt"
     Case "xls"         ' Excel file.
       cFileExt = "ods"
     Case Else
       cFileExt = "xxx"
    End Select
       
   cFile = Left( cFile, Len( cFile ) - 3 ) + cFileExt
   cURL = ConvertToURL( cFile )
   
   oDoc.storeAsURL( cURL, Array() )
   oDoc.close( True )

End Sub


Function MakePropertyValue( Optional cName As String,
Optional uValue ) _
   As com.sun.star.beans.PropertyValue
   Dim oPropertyValue As New com.sun.star.beans.PropertyValue
   If Not IsMissing( cName ) Then
      oPropertyValue.Name = cName
   EndIf
   If Not IsMissing( uValue ) Then
      oPropertyValue.Value = uValue
   EndIf
   MakePropertyValue() = oPropertyValue
End Function

Язык OpenOffice Basic похож на VBA — язык макросов в Microsoft Office; VBA похож на Visual Basic, а он, в свою очередь, — на тот самый BASIC, который для тех из нас, кто постарше, был первым изученным языком программирования. Я не углублялся ни в один из этих языков, но если вам что-то будет неясно в отношении их синтаксиса, то ответы достаточно легко находятся несколькими запросами к Google. Например, я совершенно не представлял себе, как записать оператор выбора в процедуре SaveAsOOO, но нашёл всю необходимую информацию с помощью Google и справки OpenOffice.

Весь код состоит из трёх процедур и одной функции. Процедура SaveAsPDF и функция MakePropertyValue взяты из сообщения на форуме OpenOffice. Процедура SaveAsDoc отличается от SaveAsPDF только параметром, передаваемым в MakePropertyValue, — названием фильтра экспорта. Если вы хотите добавить процедуры для сохранения таблиц OpenOffice в файлы Excel, или презентаций OpenOffice Impress в файлы PowerPoint, то всё что вам потребуется — взять копию одной из этих процедур и изменить в ней название фильтра экспорта и расширение нового файла.

Что замечательно в процедуре SaveAsOOO — это её универсальность. Вам не нужно определять, чем является входной файл — документом Word, таблицей Excel или презентацией PowerPoint, и не нужно указывать формат для нового файла. OpenOffice определит всё это сам. И как вы видите, единственное существенное отличие этой процедуры от SaveAsPDF — то, что я добавил код, определяющий для нового файла правильное расширение.

Запуск преобразования

Макросы можно запускать из командной строки вне зависимости от того, открыт ли в этот момент OpenOffice, или вы из него уже вышли. Примерно так должна выглядеть командная строка для преобразования файла Word в формат OpenOffice на компьютере с Windows, разбитая здесь на две строки:


"C:\Program Files\OpenOffice.org 2.0\program\soffice" 
  -invisible
macro:///Standard.MyConversions.SaveAsOOO(c:\temp\sample.doc)

На моём компьютере файл soffice.exe не находится в пути поиска исполняемых файлов, поэтому я вынужден указывать для него полный путь — заключённый в кавычки, потому что он содержит пробелы. Ключ -invisible указывает OpenOffice, что не нужно показывать экран с приветствием, создавать документ по умолчанию, и вообще отображать какой-либо GUI. (Чтобы увидеть список всех доступных ключей, попробуйте запустить soffice.exe из командной строки, задав единственный параметр -?) Имя макроса указывается в виде, похожем на URL: сначала путь в дереве макросов до нужного макроса, затем параметр в скобках — имя файла, который требуется преобразовать. Указывать имя для нового файла не нужно — макрос выберет его сам в зависимости от исходного имени и выполняемого преобразования.

Поскольку макрос дописывает http:// в начало имени исходного файла, чтобы получить его URL, то это имя должно содержать полный путь к файлу, как показано в примере, — иначе вы получите сообщение об ошибке «Недопустимый URL».

В Linux в командной строке нужно указывать другое имя исполняемого файла. Установщик OpenOffice в моей Ubuntu поместил файл ooffice2 в путь поиска исполняемых файлов, так что мне не приходится указывать при его запуске полный путь. Я заключил вызов макроса в кавычки, потому что иначе находящиеся в нём скобки неправильно обрабатывались оболочкой. Во всех других отношениях те же самые макросы, что были созданы описанным выше способом, работали превосходно.


ooffice2 -invisible 
 
"macro:///Standard.MyConversions.SaveAsOOO(/home/bob/temp/sample.doc)"

Я попытался преобразовать несколько разных файлов. Тестовый файл sample.doc лежит у меня уже несколько лет для испытания программ и сервисов, которые предлагают преобразовывать файлы Word в XML. В этом файле используются встроенные и пользовательские стили для абзацев и знаков, вложенные маркированные списки, изображение, таблица с объединёнными ячейками, вложенная таблица Excel, и ещё несколько вещей, на которых может споткнуться программа для преобразования. SaveAsOOO с этим файлом прекрасно справился.

Давайте преобразуем файлы MS Office

Теперь, когда у вас есть открытый многоплатформенный инструмент для преобразования новых и старых (по крайней мере, вплоть до Office 97) файлов MS Office в XML-документы открытого стандарта, как же лучше всего воспользоваться этим инструментом? Всё, что может запускаться из командной строки, может использоваться в пакетном режиме — без вмешательства пользователя. Можно создать Perl-скрипт, который бы принимал список входных файлов и создавал пакетный файл либо шелл-скрипт из последовательности команд, подобных приведённым выше, которые бы преобразовывали по одному файлу. Если то, что вам на самом деле нужно — сам XML-документ, то этот скрипт может заодно извлекать его из zip-архива, которым является файл OpenOffice, и переименовывать соответствующим образом. Шелл-скрипт, выполняющий всё это, выглядит так:


# Не забудьте: $1 должен содержать имя файла
# с полным путём, но без расширения
ooffice2 -invisible 
"macro:///Standard.MyConversions.SaveAsOOO($1.doc)"
unzip -o $1.odt content.xml
cp content.xml $1.xml

Пакетный файл для Windows:


REM Не забудьте: %1 должен содержать имя файла
REM с полным путём, но без расширения
set OooExe="C:\Program Files\OpenOffice.org 2.0\program\soffice"
%OOOExe%  -invisible
macro:///Standard.MyConversions.SaveAsOOO(%1.doc)
unzip -o %1.odt content.xml
copy content.xml %1.xml

Если вы собираетесь регулярно преобразовывать большое число документов, то запуск нового экземпляра OpenOffice для каждого преобразования будет существенно замедлять весь процесс. В Windows файл soffice.exe можно запустить в режиме «быстрого старта» (с ключом -quickstart); тогда запускаемые после этого преобразования будут выполняться быстрее. Кроме этого, можно с помощью ключа -accept указать строку Universal Network Objects, которая позволила бы, используя API, управлять запущенным экземпляром OpenOffice из программы, написанной на C++, OpenOffice Basic, Python, Java или других языках. В этом случае можно было бы передавать имена документов для преобразования в запущенный экземпляр OpenOffice, используя вызовы API.

Наиболее интересной возможностью, которую предоставляет этот подход, мне кажется даже не преобразование присылаемых мне новых файлов Word и Excel в XML-формат OpenOffice, — а преобразование имеющихся старых документов. Сколько у вас есть старых файлов Microsoft Office? Сколько новых применений вы нашли бы содержащейся в них информации, если бы она была представлена в открытом и документированном XML-формате, и вы могли бы использовать для работы с этой информацией любые XML-инструменты? Учитывая, что всё это теперь возможно с использованием открытого программного обеспечения, работающего и в Windows, и в Linux, перед нами должны открываться огромные новые возможности.



XML.com Copyright © 1998-2007 O'Reilly Media, Inc.
Перевод: xmlhack.ru Copyright © 2000-2007 xmlhack.ru