Журнал LinuxFormat - перейти на главную

LXF121:OpenOffice

Материал из Linuxformat
Версия от 17:05, 17 июня 2011; Ewgen (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск
OpenDocument Раскрываем потенциал OpenOffice.org

Содержание

OOo: Работаем автоматом

Марко Фиоретти автоматически создает уйму счетов и тестовых заданий с вариантами ответов в формате OpenDocument, избегая рутинной работы.

Мы часто применяем компьютер для создания нескольких разных версий одного и того же документа, но ручные обновления ваших файлов имеют смысл, только если они редки. Ведь имеется множество способов сэкономить драгоценные секунды – как мы показали в LXF119 при рассмотрении автоматического обновления электронных таблиц. А на данном уроке мы займемся более объемной задачей: перенесем набор «сырых» данных в какой-либо полезный документ с минимумом усилий. Вдобавок мы избежим открытия OpenOffice.org (ну, почти), благодаря свойствам его стандартного формата файлов: OpenDocument, или ODF.

Документ ODF – просто zip-архив, с картинками и макросами в собственных каталогах, а сам текст – записанный в формате XML – находится в файле с именем content.xml. Для создания новой версии документа следует открыть архив, изменить текст в content.xml, поместить несколько новых картинок в их каталог и запаковать вновь. Здесь мы покажем, как выполнить это с помощью текстовых документов ODF и действительно простых сценариев оболочки.

Тесты с выбором ответа в ODF

Давайте начнем с практической задачи: создания форматированного теста с выбором из нескольких вариантов ответа и случайно генерируемыми вопросами. Ради простоты предположим, что тест содержит всего один вопрос и представляет собой документ, содержащий название теста, его описание, вопрос и три варианта ответа, каждый со своей картинкой и подписью. Его файл (дадим ему имя sample_multiple_choice.odt) будет нашим исходным шаблоном. Чтобы использовать файл для генерации нашего теста в формате OpenDocument, сначала надо записать все строки, которое войдут в тест, в файле формата ASCII (назовем его my_test_data_1) следующим образом:

marco => cat my_test_data_1
TEST_NAME=’Тест на совместимость с GNU/Linux’
DESCRIPTION=‘Это весьма научный тест, выявляющий скрытые оттенки вашего отношения к свободному ПО'
QUESTION_NAME='Какой дистрибутив GNU/Linux вы предпочитаете?’
FIRST_CAPTION='Это Ubuntu?'
SECOND_CAPTION='...или Mandriva?'
THIRD_CAPTION=”А может, вы поклонник Fedor’ы?”

Формат данного файла достаточно прост, но есть пара моментов, которые следует отметить: во-первых, это вполне корректный синтаксис команд оболочки. Каждая строка этого файла присваивает значение некоторой переменной среды, которая будет использоваться в основном скрипте. Во-вторых, хотя общих правил нет, будьте аккуратны в использовании кавычек. Например, в последней строке нужно использовать двойные кавычки, поскольку в тексте вопроса уже встречается одинарная [или ее необходимо экранировать, заменив на \', – прим. ред.].

Подготовка картинок

Кроме строк, необходимо также припасти три картинки – в том порядке, в каком они появятся в документе. В нашем примере они находятся в каталоге Linux_Test_Pictures, и мы назвали их 01_ubuntu_logo.png, 02_mandriva_logo.png и 03_fedora_logo.png соответственно. Нумерация необходима для гарантии их использования в правильном порядке. Пристроив все по местам, выполните следующую команду:

marco => test_generator.sh sample_multiple_choice.odt my_test_data_1 Linux_Test_Pictures/*

для завершения вашего первого теста.

Употребим скрипт иначе

Лучшее в этом процессе то, что метод применим для всех случаев, пока структура документа неизменна. В качестве доказательства, разместим три соответствующие картинки (первая – горы, вторая – пляж, третья – исторические места) в каталоге Holiday_Pictures и добавим следующий ASCII-текст в файл с именем my_holiday_data_1:

marco => cat my_holyday_data_1
TEST_NAME=’Тест на предпочтения в отдыхе’
DESCRIPTION=’Выясняет, как вам лучше провести отпуск’
QUESTION_NAME=’Какое из предложенных мест вы бы посетили в первую очередь?’
FIRST_CAPTION=’Дикие горы?’
SECOND_CAPTION=’Солнечные тропические пляжи?’
THIRD_CAPTION=”Или исторические места?”

Закончите процесс запуском:

marco => test_generator.sh sample_multiple_choice.odt my_holyday_data_1 Holiday_Pictures/*

Разве не круто? Теперь, чтобы сгенерировать 1000 подобных файлов, осталось только запустить приведенный ниже скрипт в цикле.


 Листинг 1: test_generator.sh
 1 WORK_DIR=odt_test_generator_temp_dir
 2
 3 rm -rf $WORK_DIR
 4 mkdir $WORK_DIR
 5 FILENAME=`basename $1 .odt`
 6
 7 cp $1 $WORK_DIR/my_template.odt
 8 cp $2 $WORK_DIR/my_data.sh
 9 shift # удаляем $1 из списка  аргументов
 10 shift # удаляем $2 из списка аргументов
 11
 12 ## копируем все картинки в рабочий каталог
 13 touch $WORK_DIR/new_pictures_list
 14 for VAR in “$@”
 15 do
 16 CURRENT_FIG=`basename $VAR`
 17 cp $VAR $WORK_DIR/
 18 echocp ../$CURRENT_FIG>> $WORK_DIR/new_pictures_list
 19 done
 20
 21 ## подготовка
 22 cd $WORK_DIR
 23 mkdir work
 24 mv my_template.odt work
 25 cd work
 26 source ../my_data.sh
 27 unzip my_template.odt > /dev/null
 28 rm my_template.odt
 29
 30 ## заменяем текстовые строки 
 31 sed “s|Test Name|$TEST_NAME|” content.xml \
 32 | sed “s|Question|$QUESTION_NAME|” \
 33 | sed “s|Test description and general conditions|$DESCRIPTION|” \
 34 | sed “s|first caption|$FIRST_CAPTION|” \
 35 | sed “s|second caption|$SECOND_CAPTION|” \
 36 | sed “s|third caption|$THIRD_CAPTION|” \
 37 > custom_content.xm
 38 mv custom_content.xml content.xml
 39
 40 ## получаем имена внедренных картинок и заменяем их
 41 tr>” “\012” < content.xml | grep 'draw:image xlink:href' | cut '-d”' -f2 > ../pictures_list
 42 paste ../new_pictures_list ../pictures_list > ../copy_pictures
 43 source ../copy_pictures
 44
 45 ## архивируем все, переименовываем в файл .odt и очищаем
 46 find . -type f -print0 | xargs -0 zip ../$FILENAME > /dev/null
 47 cd ..
 48 mv $FILENAME.zip ../new_$FILENAME.odt
 49 cd ..
 50 rm -rf $WORK_DIR

Скрипт test_generator.sh принимает в качестве аргумента шаблон в ODF, ASCII-файл, содержащий текстовые строки, и все изображения, которые следует поместить в новый документ. Первые 10 строк определяют временный каталог и копируют в него все необходимые файлы. Команды shift в строках 9 и 10 удаляют шаблон ODF и файл с данными из переменной, хранящей список аргументов, $@. Это необходимо для создания цикла в строках с 14 по 19, обрабатывающих только графические файлы. Здесь создается локальная копия каждой картинки, но более важная часть находится в строке 18: она генерирует файл new_pictures_list, имеющий вид наподобие

marco => cat new_pictures_list
cp ../01_ubuntu_logo.png
cp ../02_mandriva_logo.png
cp ../03_fedora_logo.png

Скоро вы узнаете, зачем нужно создавать такой файл, а пока вернемся к коду. Строки с 22 по 28 перемещают нас в каталог work, загружают набор переменных из файла данных (строка 26), распаковывают шаблон, а затем, наконец-то, мы можем приступить к генерации нового ODF-файла.

Обратите внимание на раздел замены текстовых строк (строки с 30 по 38), состоящий из нескольких команд sed, соединенных конвейером. Каждый вызов sed заменяет одну строку текста-местозаполнителя в файле content.xml содержимым одной из переменных, входящих в набор, определенный в файле my_test_data_1. Если вы позднее захотите приспособить данный скрипт для создания других документов, то это именно тот раздел кода и файл с данными, которые следует изменять.

После создания нового файла content.xml исходные картинки заменяются на те, которые мы хотим поместить в шаблон. Это делается за два шага. Строка 41 использует команды tr и grep для извлечения и записи имен всех картинок в файл pictures_list. Имена содержатся в XML-атрибуте xlink внутри content.xml, и в результате должно получиться нечто вроде

marco => cat pictures_list
Pictures/100000000000008F0000008A1DC84E9A.png
Pictures/10000000000000910000008EDC1B9151.png
Pictures/10000000000000810000008C06E4E423.png

После этого остается лишь склеить new_pictures_list и picture_list вместе, строка за строкой (строки с 42 по 43), чтобы получить командный файл, формируемый в строке 43:

marco => cat copy_pictures
cp ../01_ubuntu_logo.png Pictures/100000000000008F0000008A1DC84E9A.png
cp ../02_mandriva_logo.png Pictures/10000000000000910000008EDC1B9151.png
cp ../03_fedora_logo.png Pictures/10000000000000810000008C06E4E423.png

Теперь все части готовы. В остатке скрипта все просто запаковывается, а расширение результирующего файла меняется на ODT. В порядке второго примера давайте рассмотрим, как создавать счета в формате ODF. О том, как это сделать, статей уже полно, но во всех требуют запуска OOo и ручной правки. А мы хотим, чтобы компьютер выполнял всю работу за нас. Процедура похожа на уже обсужденную, только проще, потому что нет картинок. Для начала настройте шаблон, а затем создайте такой файл с данными:


marco => cat my_invoice_data_file
INVOICE_DATE='2009/03/20'
VENDOR_CODE='007'
PO_NUMBER='LXF 10541'
TOTAL=100
ISSUE=150
DESCRIPTION=’Не иначе как за лучший из учебников Linux Format!’

для преобразования шаблона в счет.

Теперь запустите скрипт, приведенный ниже – он получен из сценария оболочки test_generator.sh, рассмотренного в первом примере:

 Листинг 2:
 1 WORK_DIR=odt_invoice_generator_temp_dir
 2
 3 rm -rf $WORK_DIR
 4 mkdir $WORK_DIR
 5 FILENAME=`basename $1 .odt`
 6
 7 cp $1 $WORK_DIR/my_template.odt
 8 cp $2 $WORK_DIR/my_data.sh
 9
 10 ## Подготовка
 11 cd $WORK_DIR
 12 mkdir work
 13 mv my_template.odt work
 14 cd work
 15 source ../my_data.sh
 16 unzip my_template.odt > /dev/null
 17 rm my_template.odt
 18
 19 ## заменяем текстовые строки
 20 sed “s|__INVOICE_DATE|$INVOICE_DATE|” content.xml \
 21 | sed “s|__VENDOR_CODE|$VENDOR_CODE|” \
 22 | sed “s|__PO_NUMBER|$PO_NUMBER|” \
 23 | sed “s|__TOTAL|$TOTAL|g” \
 24 | sed “s|__ISSUE_NUMBER|$ISSUE|” \
 25 | sed “s|__DESCRIPTION|$DESCRIPTION|” \
 26 > custom_content.xml
 27 mv custom_content.xml content.xml
 28
 29 ## запаковываем все, меняем у полученного файла расширение на .odt и очищаем
 30 find . -type f -print0 | xargs -0 zip ../$FILENAME > /dev/null
 31 cd ..
 32 mv $FILENAME.zip ../new_$FILENAME.odt
 33 cd ..
 34 rm -rf $WORK_DIR


Многое из этого должно быть вам знакомо по описанию Листинга 1, но приглядимся к строкам с 19 по 25. Как уже упоминалось, при изменении шаблона надо добавить команду sed для каждой заменяемой строки. Если одна и та же строка встречается несколько раз, как это имеет место для нашей итоговой суммы, не забудьте добавить к sed опцию g (глобальный), в противном случае будет заменено только первое вхождение данной строки (см. строку 23).

А что с версиями MS Office?

В идеальном мире все перейдут на OpenDocument и безбумажные офисы, и в этом раю не надо будет вникать в форматы файлов, используемых другими людьми, или в лицензии, разрешающие открытие таких документов. Но пока эти деньки не наступили (эх…), не обойтись без распечатки файлов или их конвертирования для бедолаг, прикованных к приложениям, которые понимают только форматы Microsoft Office.

К счастью, и конвертировать, и печатать можно автоматически. Однако, в отличие от генерации ODF-файлов, на этом шаге необходим OpenOffice.org. Требуется добавить к вашему скрипту строку, которая будет запускать OpenOffice.org без графического интерфейса, затем выполнять макрос OOo для конвертирования ODF-файла в форматы PDF (для печати) или DOC. Для достижения этой цели имеется несколько макросов; два лучших – SaveAsPDF и SaveAsDoc, с сайта http://www.xml.com/pub/a/2006/01/11/from-microsoftto-openoffice.html. Альтернативный макрос генерации PDF имеется на сайте http://linux.derkeiler.com/Mailing-Lists/Fedora/2008‑06/msg00561.html.

Чтобы распечатать PDF-файл из скрипта, его можно просто «скормить» команде lPr. Использование OpenOffice.org в командной строке описано в http://tinyurl.com/rybr9d, но я, так и быть, покажу вам корректный синтаксис:

soffice -invisible macro://путь-к-макросу($FILE)

Опция -invisible заставляет OpenOffice.org запускаться без графического интерфейса. Обрабатываемый файл должен передаваться как аргумент ($FILE) макроса.

Что мы узнали?

На данном уроке мы изучили метод автоматизации повторяющихся задач с документами, имеющий несколько важных преимуществ. Прежде всего, он работает без запуска OpenOffice.org (за исключением печати), то есть его можно выполнять на сервере. Метод также не опирается ни на какие реляционные базы данных; а кроме этого, весьма прост! Во многих случаях, когда XML-инструменты (вроде описанных во врезке Ресурсы внизу) слишком сложны для изучения и установки, использование приведенных здесь уловок поможет хотя бы избежать потери времени на повторяющееся редактирование. По сути, кто угодно, имея начальный уровень знаний о сценариях оболочки, может генерировать, изменять и анализировать сотни текстовых ODF-документов, покодировав пару минут.

Но приведенный процесс привлекателен не только благодаря легкости использования. Во-первых, основы данного процесса по идее достаточно хорошо вам знакомы. Мы считаем, что большинство пользователей Linux комфортнее чувствуют себя со скриптами Bash, чем в StarBasic – языке написания макросов OOo. Что приводит нас к основной причине, по которой мы избегаем макросов OOo: реализация логики решения вне OpenOffice.org придает намного большую силу, гибкость и потенциал интеграции с другими инструментами, от заданий Cron до массовых рассылок и обработки графики. Например, можно запросто добавить в первый скрипт инструменты ImageMagick (LXF116LXF117) и масштабировать и кадрировать изображения, прежде чем помещать их в ODF-документ!

Понятно, два представленных скрипта не идеальны. Они не особо гибкие или расширяемые, и в данном виде не совсем надежны. Прежде всего, здесь нет обработки ошибок: если один из файлов отсутствует, или генератору тестов выдано больше картинок, чем имеется в исходном шаблоне, то все пойдет наперекосяк, без всякого сообщения о случившемся.

Вы, конечно, можете улучшить их, но цель данной серии не в разработке промышленных решений. Прежде всего, наш урок доказывает, что OpenDocument не имеет скрытых глубин: ODF-файл – обычный zip-архив, содержащий простой текст и изображения, совместимые с любыми программами. Храните свои данные в формате ODF, и их будет легко восстановить, даже если завтра OpenOffice.org исчезнет с лица земли. Во-вторых, что более важно, мы показали вам: ODF можно быстро и легко подстроить под ваши нужды, и с ним можно экспериментировать. LXF

Ресурсы

Если вы намерены серьезно изучить обработку ODF, трюков данного учебника для ваших нужд будет недостаточно. В этом случае обратитесь к XML-инструментам типа Odfpy (http://odfpy.forge.osor.eu) или к книге Дэвида Айзенберга [J David Eisenberg] OpenDocument Essentials: ее можно купить по адресу http://www.lulu.com/content/207835 или прочесть онлайн на http://develop.opendocumentfellowship.com/book

Персональные инструменты
купить
подписаться
Яндекс.Метрика