LXF80:OOo Basic
(Новая: '''''АВТОМАТИЗАЦИЯ OPENOFFICE.ORG '''СЕРИЯ: «СЦЕНАРИИ НА BASIC»'' == OOo Basic Макросы в Writer’е == '''ЧАСТЬ 1''' '''''Марк Бэйн'...) |
Версия 14:11, 26 марта 2008
|
|
|
АВТОМАТИЗАЦИЯ OPENOFFICE.ORG СЕРИЯ: «СЦЕНАРИИ НА BASIC»
Содержание |
OOo Basic Макросы в Writer’е
ЧАСТЬ 1
Марк Бэйн смеется над ничтожествами, которые все еще не умеют пользоваться скриптами в текстовом процессоре. А вы сейчас научитесь!
Недавно произошло важное событие – заключен очередной контракт в пользу OpenOffice.org. Это должно принести нам много радости: офисный пакет OOo появился на свет в период зрелости движения Open Source, то есть не так давно, поэтому чем больше людей им пользуются, тем ближе знакомятся с открытыми программами. Однако многие пользователи пакета не знают, что в OpenOffice.org встроен мощный язык программирования – и в этой новой серии статей мы, счастливчики, научимся им пользоваться. Язык называется OpenOffice.org Basic, и в первой части мы используем его в текстовом процессоре ООо Writer.
Basic: основы основ
Вам, наверное, интересно, с чего бы это пользователю OOo Writer интересоваться программированием. Ответ прост: автоматизация. Представьте, что вам нужно готовить ежедневные отчеты, куда нужно включать информацию об использовании дискового пространства или список активных пользователей. Это – несложная работа: можно использовать команды who и df, а потом вставить результаты в Writer. Тем не менее это скучно и требует времени – пять минут здесь, пять минут там. Не правда ли, было бы здорово, если бы Writer делал всю работу сам, а вы бы шли в пивную немного раньше?
В этом учебнике вы узнаете, что в OpenOffice.org Basic можно писать макросы для выполнения любых задач, от открытия документов Writer и вставки внешних объектов до вывода диалоговых окон, работы с динамическими данными и многого другого. Для этой статьи я использовал OpenOffice.org 2.0 (1.9.79) под Linux и версию 1.1.4 под Windows (простите – я лишь хотел проверить, как все заработает).
OpenOffice.org Basic очень похож на любую другую разновидность этого языка. Впервые я стал использовать Basic на Sinclair ZX81 в начале восьмидесятых. Сегодня существует множество версий Basic – Visual Basic, Gambas и другие. Каждая имеет все ту же командную структуру, и поэтому различаются они, как правило, лишь нюансами. Тем не менее, имейте в виду, что с этого момента под словом Basic я понимаю именно OpenOffice.org Basic. Не рассчитывайте, что приведенный в качестве примера код так сразу заработает в другой версии Basic.
Наверно, вы хотите, чтобы я подробно рассказал о функциях и подпрограммах, переменных и объектах и лишь затем приступил к делу? Нет? Вы хотите по-простому во всем разобраться и получить результат?
Хорошо, вот простой пример кода, который создает пустой документ Writer. Используйте Macro Organizer для того, чтобы создать новый модуль (см. врезку вверху справа на этой странице), затем впишите туда следующий код:
Sub Main loadNewFile End Sub Sub LoadNewFile dim doc as object dim desk as object dim url as string dim args() desk = CreateUnoService(“com.sun.star.frame.Desktop”) url = “private:factory/sWriter” doc = desk.loadComponentFromUrl(url, “_blank”, 0, args()) End Sub
Теперь вы можете нажать кнопку Run BASIC (Выполнить код BASIC) на панели инструментов и увидеть обещанный новый документ.
Приведенный в примере код позволяет понять, каким образом можно загрузить любой файл. Важным параметром является URL, например:
url =”file:///home/bainm/test.odt”
Более того, вы можете создать более сложный сценарий, когда скрипт пытается открыть файл и в случае неудачи создает новый документ
Sub LoadNewFile (optional myFile as string) dim doc as object dim desk as object dim url as string dim Dummy() if isMissing(myFile) then myFile = “private:factory/sWriter” end if desk = CreateUnoService(“com.sun.star.frame.Desktop”) url = myFile doc = desk.loadComponentfromurl(url,”_blank”,0,Dummy()) End Sub
Если вы знакомы с Basic, то узнаете общую структуру – мы создали две подпрограммы. Первая (Main) нужен для управления действиями макроса. Вторая (LoadNewFile) делает всю работу. Она определяет новые переменные (doc, desk, url и args), затем создает UNO (Universal Network Object – универсальный сетевой объект), который дает нам доступ к свойствам объектов Writer.
Изменяем документ
От пустого файла мало проку, к тому же его можно легко создать вручную, нажав Ctrl+N. Давайте теперь напишем код для изменения документа:
Sub Insert_words dim doc as object dim cursor as object doc=thisComponent cursor=doc.text.createTextCursor cursor.string=”Hello World” End Sub
Вам также понадобится изменить подпрограмму Main:
Sub Main loadNewFile insert_words End Sub
Видите, как просто управлять Writer при помощи кода! Чтобы извлечь из этого пользу, напишем фрагмент, который будет воспринимать введенный текст как абзац и помещать его в файл.
Sub Add_paragraph (myText as String) dim doc as object dim cursor as object doc=thisComponent cursor=doc.text.createTextCursor cursor.gotoEnd(False) doc.text.insertControlCharacter(cursor, _ com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False) doc.text.insertControlCharacter(cursor, _ com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False) cursor.string = myText End Sub
В данном случае скрипт перемещает курсор в конец документа, создает новый абзац и помещает в него введенный текст. Например:
Sub Main loadNewFile add_paragraph(“This is my first paragraph.”) add_paragraph(“This is my second paragraph.”) End Sub
Знаю, знаю, и в этом случае будет быстрее набрать текст в Writer, но вы уже, наверное, придумали, как можно использовать этот код – он пригодится, если добавить в него подпрограмму загрузки внешних данных.
Если вы уже пользовались какой-либо разновидностью Basic, следующий код покажется вам знакомым:
Sub Load_report_file(myFile as String) dim filenumber As Integer dim iLine As String dim pText As String filenumber = Freefile open myFile For Input As filenumber while not EOF(filenumber) Line Input #filenumber, iLine if (iLine <> “”) then pText = PText & iLine else add_paragraph(pText) pText=”” end if wend if (PText<>””) then add_paragraph(pText) end if close #filenumber End Sub
Этот код работает с определенным файлом, сканируя его на предмет полных абзацев, которые определяется по наличию пустой строки. Когда скрипт находит такой абзац, он вставляет его в новый документ, если не находит – продолжает поиск до конца файла.
Некоторые моменты в этом коде все же нужно прояснить. Начнем с использования значения Freefile. Оператор open подразумевает, что каждому открытому файлу вы можете присвоить уникальный порядковый номер. Это может быть любое число на ваше усмотрение, но вы должны обязательно его запомнить, чтобы оно потом не повторилось (это станет важным, когда у вас будет открыто более одного файла). Вместо этого можно использовать Freefile, и тогда файлу будет просто дан очередной порядковый номер.
Вы также можете спросить, зачем мы второй раз используем выражение add_paragraph за пределами блока while…wend. Это нужно для того, чтобы скрипт не пропускал в файлах последние параграфы, после которых нет пустой строки.
Хорошо, теперь можно использовать этот код для загрузки текста из любых файлов. Вот пример:
Sub Load_report_simple dim rep_dir as String rep_dir = “~/articles/lxf75_OOobasic1/demo/” load_report_file(rep_dir & “manager_header.txt”) load_report_file(rep_dir & “body.txt”) End Sub
Даже сейчас метод ручного ввода текста в Writer имеет преимущество, и вы можете самостоятельно сохранить или распечатать документ. И все же наш код станет гораздо полезнее, если в нем появится возможность выбора:
Sub Load_report (optional reportType as integer) const rep_dir as string = “~/articles/lxf75_OOobasic1/ demo/” if isMissing(reportType) then reportType = 1 end if select case reportType case 1 load_report_file(rep_dir & “manager_header.txt”) case 2 load_report_file(rep_dir & “contractor_header.txt”) end select load_report_file(rep_dir & “body.txt”) End Sub
Теперь загружаться будет один из двух файлов (manager_header.txt или contractor_header.txt), в зависимости от значения переменной reportType. Тем не менее в обоих случаях в текст будет вставлен файл body.txt. Вы можете изменить это, отредактировав подпрограмму Main так:
Sub Main loadNewFile load_report(1) End Sub или так: Sub Main loadNewFile load_report(2) End Sub
Я уверен, что на этом этапе вы заметите несовершенство данного метода: каждый раз, когда вам нужен разный результат, вам необходимо править код. Нам нужен более элегантный способ выбирать нужный файл. Сейчас мы создадим диалоговое окно, контролирующее вывод скрипта.
Создаем диалоговое окно
Для этой цели нам понадобится редактор макросов. До того, как щелкнуть кнопку New, перейдите на вкладку Dialogs (Диалоговые элементы). В случае, если вы задали новому диалогу имя ‘dlgReport’, код будет выглядеть следующим образом:
dim dlgReport as object Sub DlgReport_show basicLibraries.loadLibrary(“Tools”) dlgReport = loadDialog(“Standard”,”dlgReport”) dlgReport.execute() End Sub
Не забудьте также изменить и подпрограмму Main:
Sub Main dlgReport_show End Sub
Диалоговое окно пока еще ничего не делает (нажмите Esc, чтобы закрыть его), но мы можем добавить на него элементы управления – кнопки и списки.
Наш диалог даст нам возможность контролировать тип отчета, который будет открыт в Writer’е. Нам понадобится поле со списком и кнопка. Создайте их, выбрав соответствующие значки на панели инструментов и нарисовав нужные объекты.
Через редактор свойств задайте объектам имена lstReport и btnReport соответственно, а также напишите какой-нибудь текст на кнопке (предлагаю слова «Создать отчет»).
Теперь мы заполним список нужными данными при помощи встроенного метода OOo – addItem. Вам может прийти в голову следующая конструкция:
Sub DlgReport_show basicLibraries.loadLibrary(“Tools”) dlgReport = loadDialog(“Standard”,”dlgReport”) dlgReport.lstReport.AddItem(“Managers”,0) dlgReport.lstReport.AddItem(“Contractors”,1) dlgReport.execute() End Sub
Выглядит логично, но OpenOffice.org Basic работает немного по-другому. Вместо приведенного выше, вам понадобится следующий код:
dim lstReport as object sub DlgReport_show basicLibraries.loadLibrary(“Tools”) dlgReport = loadDialog(“Standard”,”dlgReport”) lstReport = dlgReport.getControl(“lstReport”) lstReport.AddItem(“Managers”,0) lstReport.AddItem(“Contractors”,1) dlgReport.execute() End Sub
Заметьте, что список (list box) необходимо определить как уникальный объект. Воспользоваться им можно только при помощи метода getControl диалогового окна. Также, мы объявили переменную lstReport как глобальную – это значит, что ее можно использовать в любой подпрограмме (вы это еще заметите).
Заряжаем кнопку
Теперь мы напишем код, который будет выполняться при нажатии на кнопку:
Sub BtnReport_Click loadNewFile load_report(lstReport.selectedItemPos) End Sub
Я уверен, что теперь вы запустили основной макрос и обнаружили, что поле со списком работает, но при нажатии на кнопку ничего не происходит. Скорее всего, с ней пока не ассоциирован никакой код. Перейдите в окно свойств кнопки и на вкладке Events (События) выберите подпрограмму, которая должна выполняться при нажатии (для закрытия окна используйте Esc).
Теперь у вас есть полнофункциональный инструмент для контроля над создаваемыми документами.
Идем дальше
Никто не будет спорить с тем, что проделанную работу нужно сохранить. Во всех приведенных примерах мы создавали документы автоматически, но сохраняли их вручную. Поскольку эта статья посвящена автоматизации, мы обратимся к коду, который позволит сохранить созданные файлы. Попробуйте это:
Sub SaveMyFile (fileUrl as string) dim params() doc.saveAsUrl(“file:/” & fileUrl, params()) doc.close(true) End Sub
Возможно, нам понадобится всего лишь распечатать документ, не сохраняя его. Для этого добавим новую подпрограмму:
Sub PrintMyFile dim params() doc.print(params()) doc.close(true) End Sub
Хорошо, мы разобрались с тем, как работать с документами Writer и как извлекать данные из внешних файлов. Все это имело отношение к статической информации, но, что любопытно, мы можем работать и с динамическими данными. Воспользуемся встроенным в OpenOffice.org методом SystemShellExecute:
Sub RunCommand (command as string) dim svc as object svc = createUnoService(“com.sun.star.system. SystemShellExecute”) svc.execute(command, “”, 0) End Sub Sub BtnReport_Click const tmpfile as string = “/tmp/myfile.tmp” loadNewFile load_report(lstReport.getselectedItemPos()) runCommand(“df > “ & tmpfile) load_report_file(tmpfile) End Sub
В этом фрагменте скрипт передает оболочке Linux команду df и сохраняет ее вывод в файл (в данном случае, в /tmp/myfile.tmp).
Затем содержимое этого файла загружается в новый документ Writer, где оно выглядит примерно так:
‘Filesystem 1K-blocks Used Available Use% Mounted on /dev/hda3 3470204 3089264 201816 94% / /dev/hda4 1510060 1064572 368780 75% /opt /dev/hda1 4593600 3732708 860892 82% / WINDOWS.’
Эти данные очень полезны, но выглядят они не слишком привлекательно – было бы лучше увидеть все в виде таблицы. В директории Magazine на нашем диске вы найдете полный вариант кода для загрузки данных из файла в таблицу Writer – эта функция сэкономит вам массу времени, которое вы сможете потратить на прием горячительных напитков.
Этот код слишком велик, чтобы печатать его прямо здесь, но изучив его копию на диске, вы узнаете о новых полезных функциях Basic: например, Chr (возвращает ASCII-код целого числа), Array (создает массив из строковых переменных) и ubound (выдает число элементов в массиве). А теперь домашнее задание: изучите подпрограмму btnReport_Click и выясните, из чего состоит командная переменная и как она передается оболочке. До новых встреч!
РЕДАКТОР МАКРОСОВ
В OOo предусмотрен собственный инструмент для доступа и редактирования макросов, диалоговых окон и даже библиотек. При необходимости вы можете создавать, изменять и удалять новые объекты. Если вы достаточно храбры (звучит несколько самоуверенно), то можете редактировать уже готовые встроенные макросы OOo. Способ запуска редактора макросов, зависит от вашей версии OpenOffice.org. В версии 1.1.4 следует найти пункт Tools > Macros > Macro…> Organizer. В версии 2.0 путь будет немного другим: Tools > Macros > Organize Macros > OpenOffice. org Basic > Organizer.
СВЯЗЬ КОДА С ОБЪЕКТАМИ
Возможно, вы уже имели дело с языками, где код автоматически привязывается к определенным объектам. Это мог быть Delphi, Kylix, Gambas, к примеру (или даже Visual Basic). В OpenOffice.org вы должны сначала написать код, а потом вручную ассоциировать его с нужным объектом (например, кнопкой). Это можно сделать на вкладке Events (События) в окне настроек объекта (оно вызывается через правый щелчок по объекту, при выборе пункта Properties)
СОВЕТЫ
- Язык OpenOffice.org Basic нечувствителен к регистру символов. Поэтому переменная myVariable – это то же самое, что и myvariable и даже MYVARIABLE. Не имеет значения, что вы выберете, просто старайтесь придерживаться какого-либо одного написания.
- Для того, чтобы закрыть диалоговое окно, достаточно нажать клавишу Esc.
- После того, как вы создали кнопку и написали для нее код, не забудьте зайти в свойства кнопки и ассоциировать этот код с ней.