LXF80:OOo Basic

Материал из Linuxformat.

Перейти к: навигация, поиск
OOo Basic

АВТОМАТИЗАЦИЯ OPENOFFICE.ORG СЕРИЯ: «СЦЕНАРИИ НА BASIC»

Содержание

OOo Basic Макросы в Writer`е

ЧАСТЬ 1

Марк Бэйн смеется над ничтожествами, которые все еще не умеют пользоваться скриптами в текстовом процессоре. А вы сейчас научитесь!

Доступ к макросам, диалоговым окнам и библиотекам через Macro Organizer.
Доступ к макросам, диалоговым окнам и библиотекам через Macro Organizer.

Недавно произошло важное событие – заключен очередной контракт в пользу OpenOffice.org. Это должно принести нам много радости: офисный пакет OOo появился на свет в период зрелости движения Open Source, то есть не так давно, поэтому чем больше людей им пользуются, тем ближе знакомятся с открытыми программами. Однако многие пользователи пакета не знают, что в OpenOffice.org встроен мощный язык программирования – и в этой новой серии статей мы, счастливчики, научимся им пользоваться. Язык называется OpenOffice.org Basic, и в первой части мы используем его в текстовом процессоре ООо Writer.

Basic: основы основ

Вам, наверное, интересно, с чего бы это пользователю OOo Writer интересоваться программированием. Ответ прост: автоматизация. Представьте, что вам нужно готовить ежедневные отчеты, куда нужно включать информацию об использовании дискового пространства или список активных пользователей. Это – несложная работа: можно использовать команды who и df, а потом вставить результаты в Writer. Тем не менее это скучно и требует времени – пять минут здесь, пять минут там. Не правда ли, было бы здорово, если бы Writer делал всю работу сам, а вы бы шли в пивную немного раньше?

В OpenOffice.org есть простой редактор Basic.
В OpenOffice.org есть простой редактор Basic.

В этом учебнике вы узнаете, что в 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.

Organizer можно использовать не только для написания кода, но и для создания новых диалоговых окон с набором кнопок.
Organizer можно использовать не только для написания кода, но и для создания новых диалоговых окон с набором кнопок.

Изменяем документ

От пустого файла мало проку, к тому же его можно легко создать вручную, нажав 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
Воспользуйтесь окном настроек (Properties) кнопки, чтобы назначить ей выполняемый код.
Воспользуйтесь окном настроек (Properties) кнопки, чтобы назначить ей выполняемый код.

Я уверен, что теперь вы запустили основной макрос и обнаружили, что поле со списком работает, но при нажатии на кнопку ничего не происходит. Скорее всего, с ней пока не ассоциирован никакой код. Перейдите в окно свойств кнопки и на вкладке 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.
  • После того, как вы создали кнопку и написали для нее код, не забудьте зайти в свойства кнопки и ассоциировать этот код с ней.
Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию