Широко известно, что при помощи 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, как показано ниже:
Выберите модуль
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 с этим файлом прекрасно справился.
Теперь, когда у вас есть открытый многоплатформенный инструмент для преобразования новых и старых (по крайней мере, вплоть до 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, перед нами должны открываться огромные новые возможности.