background image

Open Office

Macro w służbie autora

66

czerwiec 2009

Open Office

Macro w służbie autora

67

www.lpmagazine.org

lin

ux

@

so

ftw

ar

e.

co

m

.p

l

J

ęzyk Makr OpenOffice.org (OOo) powstał na bazie ję-
zyka programowania BASIC, podobnie jak język Vi-
sual  BASIC  stosowany  jako  język  makropoleceń  w 
pakiecie MS Office, a także AppleScript w systemie 

MacOS X. Pomimo iż języki te, a zwłaszcza OOo BASIC i Vi-
sual BASIC, pochodzą od tego samego przodka, to nie są one 
wzajemnie  kompatybilne,  choć  istnieją  projekty  pozwalające 
na pewne przenoszenie makr pomiędzy tymi językami.

Cechą charakterystyczną OOo BASIC jest jego niesamo-

wita prostota, która czasami, moim zdaniem, jest największą 
wadą tego języka. Jednak narzekając na ograniczenia OOo BA-
SICa, należy wziąć pod uwagę cel, dla którego powstał – budo-
wanie krótkich procedur upraszczających i automatyzujących 
pracę w OOo, nie zaś do budowania skomplikowanych wie-
lowątkowych aplikacji. Aby sprostać temu drugiemu zadaniu, 
OOo udostępnia IDE, które może być wykorzystane do two-
rzenia makr, nawet najbardziej rozbudowanych, w innych języ-
kach programowania: JavaScript, Python oraz JAVA. Ja w tym 
artykule skupię się na wykorzystaniu OOo BASICa do automa-
tyzacji pracy w pakiecie biurowym OpenOffice.org, a zwłasz-
cza w programie OOo Writer. Opisywane w tym artykule ma-
kra były tworzone za pomocą OOo w wersji 3.0.0 w Gentoo. 

Jednak w porównaniu do VisualBASICa – działającego tylko 
pod Windows, mogą one być wykorzystane w każdym syste-
mie operacyjnym, w którym działa OpenOffice.org – niezależ-
nie od zainstalowanej wersji.

Trochę podstaw

Nie każdy z korzystających z OpenOffice.org, nawet w najbar-
dziej zaawansowany i profesjonalny sposób, zna język OOo 
BASIC. Wynika to po prostu z jego potrzeb. Warto jednak za-
znajomić się z tym językiem, gdyż w pewnym momencie sa-
modzielnie napisane makra staną się nieodzowne w codzien-
nej pracy z tym pakietem biurowym. Zanim zaczniemy praco-
wać z makrami, należy pamiętać, iż ich stosowanie wiąże się z 
zagrożeniem w postaci wirusów. Z tego też powodu domyśl-
nie obsługa makr w OpenOffice jest wyłączona. Aby to zmie-
nić, należy zmodyfikować ustawienia bezpieczeństwa. Dostęp 
do tych ustawień uzyskujemy poprzez menu Narzędzia, pozy-
cję Opcje. W oknie ustawień pakietu OpenOffice wybieramy 
pozycję Bezpieczeństwo, a następnie klikamy przycisk Bezpie-
czeństwo makr
. Zalecanym poziomem bezpieczeństwa jest Po-
ziom średni
. Jednak jeśli mamy pewność, że uruchamiane ma-
kra pochodzą od zaufanych dostawców (tj. są całkowicie bez-

Macro w służbie autora

Praca autora artykułów do Linux+ ma swoje blaski i cienie. W moim przekonaniu niezbyt przyjemnym 
etapem pracy jest konieczność otagowania tekstu przed wysłaniem go do druku. Ja tę czynność 
postanowiłem sobie uprościć, stosując zestaw makr w OpenOffice Word, które znacząco automatyzują 
ten proces, zmniejszając zarówno nakład pracy, jak i uprzyjemniając tę, którą musimy wykonać.

Grzegorz Madajczak

background image

Open Office

Macro w służbie autora

66

czerwiec 2009

Open Office

Macro w służbie autora

67

www.lpmagazine.org

pieczne), możemy ustawić Niski poziom bezpie-
czeństwa
. Wtedy to wszystkie makra będą auto-
matycznie uruchamiane bez pytania się o pozwo-
lenie. Należy pamiętać, że makra takie mają bez-
graniczny dostęp do plików, zgodnie z uprawnie-
niami użytkownika, który je uruchamia. Tak więc 
root, stosując makra OOo, może nawet modyfi-
kować i kasować pliki systemowe, których obec-
ność  i  poprawność  jest  krytyczna  dla  działania 
całego systemu.

Makra OOo mogą być przechowywane na 

trzech poziomach: na poziomie bieżącego doku-
mentu, w przestrzeni użytkownika (makra użyt-
kownika)  oraz  jako  makra  pakietu  OpenOffi-
ce.org  –  dostępne  dla  wszystkich  użytkowni-
ków pakietu na danym komputerze. Makra bie-
żącego dokumentu przechowywane są w konte-
nerze dokumentu. Przypomnę, że zarówno pliki 
OOo w wersji 1.x, jak i pliki ODF (stosowane 
od wersji 2.x) są skompresowanymi zipem fol-
derami  o  ściśle  określonej  strukturze.  Znajduje 
się tam między innymi folder 

Basic

 ,zawierają-

cy makra zapisane w danym dokumencie. Makra 
użytkownika są przechowywane w jego folderze 
domowym, w katalogu 

.ooo3

 (lub 

.ooo-2.0

 dla 

starszej wersji pakietu), w folderze 

user/basic

Tam zlokalizowane są foldery odpowiadające bi-
bliotekom  (np.  domyślny  folder 

Standard

  od-

powiadający  bibliotece  Standard.  Przechowy-
wane tam pliki z rozszerzeniami 

*.xlb

*.xba

 

są zwykłymi plikami XML, które można edyto-
wać w każdym edytorze tekstu. Jednak nie zaleca 
się tego robić, gdyż błędna składnia tak wprowa-
dzonego kodu uniemożliwi jego otwarcie w IDE 
OOo, a także korzystanie z tychże makr.

OpenOffice dostarcza bowiem wygodne w 

użyciu  środowisko  programistyczne  służące  do 
pisania i debugowania makr napisanych w OOo 
BASICu. Uruchamiamy je poprzez menu Narzę-
dzia | Makra | Zarządzaj makrami | Makro
. W 
otwartym w ten sposób oknie (Rysunek 1) moż-
na wybrać bibliotekę oraz moduł. Jeśli dokument 
nie posiada makr, przycisk Nowy służy do utwo-
rzenia biblioteki, jak i modułu. W głównej części 
tak otwartego IDE wyświetlony jest kod makr w 
danym module.

Najszybszym  sposobem  uruchomienia  ma-

kra jest skorzystanie z menadżera makr, wybie-
rając pozycję Wykonaj makro z menu Narzędzia 
| Makra
. Z otwartego w ten sposób okna nale-
ży wybrać makro, które chcemy uruchomić. Je-
śli jednak dane makro będziemy wykorzystywa-
li wielokrotnie, przedzieranie się przez poszcze-
gólne pozycje menu będzie na dłuższą metę mę-
czące. Można tego uniknąć tworząc na pasku na-
rzędziowym skrót do wybranego makro. W tym 
celu  z  menu  paska  narzędziowego  należy  wy-
brać pozycję Dostosuj pasek narzędzi. W otwar-
tym oknie Dostosuj  należy kliknąć przycisk Do-

daj,  następnie w kolejnym oknie z pola Kate-
gorie
  należy wybrać pozycję Makra OpenOffi-
ce.org
, a następnie właściwą bibliotekę i moduł 
zawierający makro, do którego chcemy utworzyć 
skrót. Po wybraniu modułu w prawym polu Pole-
cenia
 pojawią się wszystkie makra w danym mo-
dule. Wybór właściwego makra należy potwier-
dzić klikając przycisk Dodaj. Spowoduje to do-
danie skrótu do makra na modyfikowanym pa-
sku narzędziowym.

Jak wygląda makro w OOo BASIC

Każde  makro  stanowi  podprogram  (Subrouti-
nes
), którego klamrą są dwa polecenia: 

Sub na-

zwa_makro

 oraz 

End  Sub

. Nazwa makro musi 

być jednym wyrazem, najlepiej bez polskich zna-
ków. W OOo Basic możliwe jest również tworze-
nie funkcji (Function), czyli poleceń (podprogra-
mów), których zasadniczym celem jest zwróce-
nie jakiejś wartości.

Podstawy OOo BASIC

OOo BASIC charakteryzuje się łatwą do zrozu-
mienia  składnią,  dość  swobodnym  podejściem 
do sposobu pisania poleceń (np. brak zróżnico-
wania na małe i duże litery). Dość typową ce-
chą dla BASIC jest to, że ten język interpretowa-
ny (nie kompilowany, jak np. Java) wykonywa-
ny jest linia po linii – jedna linia poleceń jedno-
razowo. Oznacza to, że nie można dłuższych po-
leceń przenosić do nowej linijki. Jeśli polecenie 
nie mieści się na ekranie, można na końcu dodać 
znak _, który oznacza kontynuację polecenia w 
następnym wierszu.

Ograniczeniem powyższej zasady jest zakaz 

łamania linii wewnątrz bloku tekstu objętego cu-
dzysłowem. Znacznym udogodnieniem w pisa-
niu, poprawiającym czytelność kodu OOo Basic, 
jest możliwość definiowania wielu zmiennych w 
jednej linii przez rozdzielanie ich dwukropkiem.

Do wstawiania pojedynczej linii komentarza 

służy  polecenie 

REM

,  przy  czym,  jak  wcześniej 

zaznaczyłem,  nie  ma  znaczenia  wielkość  uży-
tych znaków, czyli napisanie 

rem

REM

, a nawet 

rEm

, będzie tak samo interpretowane. Dla czytel-

ności kodu i tak zwanej dobrej maniery progra-
mistycznej proponuję nie mieszać małych i du-
żych znaków w ostatni sposób.

Tradycyjnie we wszystkich językach progra-

mowania, pierwszym programem, skryptem, jaki 
uczymy się pisać, jest wyświetlenie tekstu Hel-
lo World
. Nie będę odbiegał od rutyny i zapro-
ponuję to samo.

W pierwszej linii utworzyliśmy makro o na-

zwie helloworld. Drugą linię zajmuje komentarz. 
Trzecia  linia  makra  jest  najważniejsza.  W  niej 
znajduje się polecenie 

Print

 wyświetlające okno 

dialogowe z tekstem zawartym w cudzysłowie. 
Ostatni wiersz zamyka makro.

Oficjalnie nazwy zmiennych mogą mieć dłu-

gość do 255 znaków, lecz nie wydają mi się być 
uzasadnione tak długie nazwy. Jak już wielokrot-
nie zaznaczałem, nazwy zmiennych nie różnicu-
ją małych i dużych liter, więc 

zmienna

 oznacza 

dokładnie to samo co 

ZMIENNA

. Nazwy zmien-

nych nie powinny zawierać spacji, a jeśli już, to 
nazwę  zmiennej  należy  zamknąć  w  nawiasach 
kwadratowych, co jednak nie jest dobra praktyką 
i z pewnością nie poprawia czytelności kodu. Za-
miast spacji z powodzeniem można użyć znaku 
dolnego podkreślenia. Nazwy zmiennych mogą 
zawierać cyfry, lecz nie na początku nazwy, nie 
mogą  natomiast  zawierać  znaków  specjalnych 
(np. kropka, przecinek, ukośnik, myślnik itd). 

Do  lokalnego  deklarowania  zmiennych  w 

OOo  BASICc  służy  polecenie 

DIM

.  Domyślnie 

brak jest deklaracji typu zmiennej, co można zro-
bić poprzez polecenie 

AS nazwa_typu

, Domyśl-

na zmienna jest typu Variant, co oznacza dowol-
ny typ danych. W jednym poleceniu Dim moż-
na zadeklarować kilka zmiennych, dla każdej z 
osobna ustanawiając ten sam lub inny typ. Jed-
norazowe podanie typu zmiennej nie nadaje te-
go typu wszystkim zmiennym zadeklarowanym 
w danej linii. Brak deklaracji typu zmiennej trak-
towane jest jako deklaracja typu Variant. W przy-
padku zmiennych typu String, możliwe jest wsta-
wianie znaku $ bezpośrednio po nazwie zmien-
nej zamiast 

As  String

. Obie formy są równo-

znaczne. W przypadku zmiennych typu Double, 
w podobny sposób używamy znaku #. Znaki dla 
innych typów danych podane zostały w Tabeli 1. 

Listing 1. 

Wygląd makro w OOo BASIC

Sub

 

moje_makro

   

print

 ''

Witaj

!''

End

 

Sub

Function

 

nazwa_funkcji

(

dbl

)

 

As

 

Double

   

nazwa_funkcji

 = 

dbl

 * 

2

End

 

Function

Listing 2. 

Przenoszenie polecenia do kolejne-

go wiersza

Sub

 

Main

Dim

 

d1

,

 

d2

,

 

d3

,

 

d4

,

 

d5

,

 

d6

,

 

d7

,

 

_

   

d8

,

 

d9

,

 

d10

,

 

d11

,

 

d12

,

 

d13

End

 

Sub

Listing 3. 

Deklarowanie zmiennych przy użyciu 

dwukropka

Sub

 

Main

Dim

 

d1

,

 

d2

,

 

d3

,

 

d4

,

 

d5

,

 

d6

,

 

d7

,

 

_

   

d8

,

 

d9

,

 

d10

,

 

d11

,

 

d12

,

 

d13

   

d1

=

1

 : 

d2

=

2

 : 

d3

=

3

 : 

d4

=

4

 : 

d5

=

5

 

d6

=

6

End

 

Sub

background image

68

Open Office

Macro w służbie autora

czerwiec 2009

69

Open Office

Macro w służbie autora

www.lpmagazine.org

Istnieje jeszcze możliwość krótkiego deklarowa-
nia niektórych typów zmiennych za pomocą jed-
nego polecenia 

Def <typ zmiennej>

.

W  OOo  Basic  sterować  możemy  również 

zasięgiem  zmiennych,  to  znaczy,  na  jakim  po-
ziomie one obowiązują. Polecenie 

Dim

 deklaru-

je zmienną, która obowiązuje w obrębie modu-
łu i biblioteki, w której została zadeklarowana, 
lecz zgodnie z jej lokalnym zasięgiem (np. dzia-
ła tylko w obrębie funkcji, pętli for – zgodnie z 
powszechnie przyjętymi zasadami). Szerszy za-
sięg ma polecenie 

Global

, przy użyciu którego 

utworzymy zmienną, z której będzie można ko-
rzystać we wszystkich modułach i bibliotekach. 
Przeciwieństwem  deklaracji  zmiennej  global-
nej jest zmienna utworzona za pomocą polece-
nia 

Private

. Jest ona widoczna tylko w obrębie 

modułu, w którym została utworzona. Inicjaliza-
cja zmiennej 

Global

 następuje wraz z kompilo-

waniem makra, natomiast zmiennej utworzonej 
przy użyciu poleceń 

Dim

 i 

Private

 – w trakcie 

uruchomienia makra.

Napisałem, że zmienna zadeklarowana bez 

typu jest domyślnie zmienną typu Variant z do-
wolnym typem danych. Co w sytuacji, gdy chce-
my przekształcać dane różnych typów? Otóż ję-
zyk OOo BASIC jest w tym względzie bardzo 
elastyczny, do czego trudno jest się przyzwycza-
ić  programistom  Java  czy  C++  (nawiązuje  do 
tych dwóch języków, ponieważ akurat te znam). 
W OOo BASIC w bardzo łatwy sposób można 
rzutować jedne typy danych na drugie za pomocą 
odpowiednich funkcji przekształcających. Funk-
cje te mają znaczenie zwłaszcza w przypadku ob-
sługi formularzy. Dane pochodzące z takiego po-
la  są  zawsze  typu  tekstowego.  Sumowanie  za-
wartości tych pól będzie się odbywało w ten spo-
sób, że będą połączone w jeden łańcuch teksto-
wy. Np. zawartość pola 1 to 10, pola nr 2 to 10, 
a wynik sumowania zawartości tych pól to 1010, 

nie zaś 20. Aby przekształcić dane tekstowe na 
dane typu liczbowego, należy użyć jednej z funk-
cji opisanej w Tabeli 1.

Siła makr dla OOo tkwi w tych trzech liter-

kach. UNO (Uniwersalne Obiekty Sieciowe) to 
niezależny  od  języka  programowania  interfejs, 
pozwalający między innymi na dostęp do obiek-
tów  występujących  w  dokumentach  OpenOffi-
ce.org. OOo BASIC oczywiście również korzy-
sta z UNO, lecz ze względu na swą prostotę je-
dynie w ograniczonym stopniu. Jednak dla prze-
ciętnego  programisty,  chcącego  napisać  makro 
dla  OOo  –  dostępne  funkcje  są  wystarczające. 
Dzięki UNO programista OOo BASIC ma moż-
liwość korzystania ze wszelkich elementów ak-
tualnie edytowanego dokumentu, np. tekstu czy 
komórek tabeli.

Okna dialogowe w OOo

Wraz z OOo Basic do dyspozycji dostajemy bar-
dzo funkcjonalne narzędzie do tworzenia okien 
dialogowych, które mogą być później wykorzy-
stywane w tworzeniu własnych makr. Okna dia-
logowe w OOo można tworzyć za pomocą gra-
ficznego edytora, dostępnego w menu Narzędzia 
Makra | Zarządzaj oknami dialogowymi. Wy-
wołanie  tej  funkcji  sprawi,  że  otwarte  zostanie 
znane już nam okno zarządzania makrami, lecz 
tym razem z aktywną zakładką Okna dialogowe
Jak poprzednio, w oknie tym będziemy mieli do-
stęp do wszystkich okien dialogowych, które zo-
stały utworzone w systemie. Również tutaj są one 
podzielone na kategorie odpowiadające katego-
riom makr. Naciśnięcie przycisku Nowy lub Edy-
tuj
 (jeśli wybierzemy już istniejące okno dialogo-
we) otworzy okno edycji okna dialogowego. W 
rzeczywistości do okna edycji makr została do-
dana zakładka z nazwą utworzonego lub wybra-
nego do edycji okna dialogowego. Rozwiązanie 
takie pozwala nam w łatwy sposób przełączać się 
pomiędzy edycją okien a edycją kodu makra. Do 
tworzenia okna dialogowego wykorzystywane są 
standardowe elementy formularza OOo.

Dokument OpenOffice.org

API OOo BASIC w prosty sposób umożliwia do-
stęp  użytkownikowi  do  aktywnego  dokumentu 
poprzez obiekt będący referencją interfejsu UNO 
::com::sun::star::lang::XComponent.  Wywoła-
nie aktywnego obiektu, bez znaczenia, czy jest to 
dokument Writera, czy arkusz Calca, odbywa się 
poprzez  polecenie 

ThisComponent.Current-

Controler

.  W  opisywanych  poniżej  makrach 

obiekt ten, będący reprezentacją dokumentu, bę-
dzie wykorzystywany wielokrotnie. W przypad-
ku dokumentu tekstowego programu OOo Wri-
ter obiekt ten posiada właściwość 

Text

 będącą 

odzwierciedleniem  samego  tekstu  w  opisywa-
nym dokumencie.

tekst_dokumentu = ThisComponent.Cur-

rentControler.Text

Należy  dodać,  iż  powyższy  obiekt  nie  ma 
właściwości  łańcucha  znaków  (obiektu  typu 
String). Obiekt ten możemy rzutować na obiekt 
typu String za pomocą polecenia 

getString()

Należy jednak bardzo uważać ze stosowaniem 
tej metody ze względu na ograniczenie co do 
maksymalnej  długości  łańcucha  znaków.  Li-
mit ten narzucony przez ograniczenia standar-
du UNICODE wynosi nieco ponad 65 tysięcy 
znaków. Przy standardzie czterech i pół tysię-
cy znaków na stronę (tekstu w postaci jedne-
go akapitu na całą stronę, czcionki Times New 
Roman, 12pt, odstęp 1 wiersz) stanowi to oko-
ło czternaście stron tekstu, co nie jest znaczącą 
ilością. Jak więc widać, obiekt typu String nie 
jest najlepszą formą przechowywania długiego 
tekstu.  Ponadto  właściwość 

Text

  ma  tę  prze-

wagę nad obiektem typu String, iż przechowuje 
więcej informacji – na przykład o stosowanym 
formatowaniu czy też implementuje nasłuch na 
zdarzenia oraz obsługuje obecność kursora.

Przybornik autora

Nadszedł czas, aby po pobieżnym zaznajomieniu 
się z językiem OOo BASIC zabrać się do praw-
dziwej pracy – pisania makr. Ja stworzyłem bi-
bliotekę  makr,  które  przydadzą  się  wszystkim 
osobom piszącym artykuły do Linux+. Pozwala-
ją one na zautomatyzowanie procesu wstawiania 
znaczników (tagów) do tekstu. Całość składa się 
z kilkunastu makr, z czego dziewięć wywoływa-
nych jest bezpośrednio. Korzystać można z nich 
w  dwojaki  sposób.  Przede  wszystkim  wszyst-
kie makra zebrałem w postaci okna dialogowe-
go (Rysunek 1), z którego można wywołać każdą 
z dostępnych funkcji. Wadą takiego rozwiązania 
jest fakt, iż okna dialogowe w OOo obligatoryj-
nie mają charakter modalny, co oznacza, iż akty-
wacja takiego okna blokuje dostęp do głównego 
okna programu (jest ono nieaktywne).

Przyznaję, że jest to mało komfortowa sytu-

acja. Z konsultacji na forach dyskusyjnych do-
wiedziałem się, że problem ten miał być rozwią-
zany w OOo 3.0, co jednak się nie stało. Dewelo-
perzy projektu tłumaczą, iż na razie nie jest moż-
liwe jest stworzenie okien dialogowych nie-mo-
dalnych,  gdyż  może  zachwiać  to  stabilnością 
programu. W zamian, niezależni deweloperzy na 
stronach forum OpenOffice.org proponują dość 
karkołomne rozwiązanie – stworzenie kontene-
ra w języku JAVA, a następnie umieszczenie w 
nim widgetów (pól formularza, elementów gra-
ficznych, itd.) komunikujących się z dokumen-
tem OOo za pomocą wspomnianego wyżej me-
chanizmu UNO. Powyższy dyskomfort używa-
nia  okien  dialogowych  może  być  usunięty  po-

Listing 4. 

Komentarze w OOo BASIC

Sub

 

Main

REM

 

To

 

jest

 

komentarze

rem

 

To

 

r

ó

wnie

ż 

jest

 

komentarz

End

 

Sub

Listing 5. 

Pierwsze makro w OOo BASIC

Sub

 

helloworld

REM

 

To

 

jest

 

komentarz

Print

 

"Hello World!"

End

 

Sub

Listing 6. 

Deklarowanie zmiennej

Sub

 

Main

Dim

 

[

nazwa

 

zmiennej

 

ze

 

spacjami

]

[

nazwa

 

zmiennej

 

ze

 

spacjami

]

 = 

1

End

 

Sub

background image

68

Open Office

Macro w służbie autora

czerwiec 2009

69

Open Office

Macro w służbie autora

www.lpmagazine.org

przez zastosowanie opisanego uprzednio sposo-
bu dodawania do paska narzędziowego skrótów 
do makr. Ja w tym celu utworzyłem osobny pa-
sek narzędziowy, do którego dodałem skróty do 
odpowiednich makr, a następnie, aby było ładniej 
i wygodniej – przypisałem do nich ikonki. Roz-
wiązanie to prezentuje Rysunek 2. Tak przygoto-
wane skróty do makropoleceń działają niezawod-
nie i wygodnie – jest to zdecydowanie lepsze roz-
wiązanie, niż modalne okno dialogowe.

Wstawianie sekcji

Pierwszymi makrami, które chciałbym opisać są 
polecenia wstawiające sekcje  oraz . W zasadzie 
oba  te  makra  działają  w  bardzo  podobny  spo-
sób. Przed ich wywołaniem wymagają zaznacze-
nia fragmentu tekstu, który zostanie poprzedzo-
ny  znacznikiem  otwierającym  i  zamykającym. 
Makra 

setTitleSection

 oraz 

setLeadSection

 

odwołują się do innego makra 

setTag

, którego 

zadaniem jest wstawianie na początku i na końcu 
zaznaczenia znaczników początku i końca sekcji. 
To zaś makro wykorzystuje z kolei trzy inne ma-
kra – 

isAnythingSelected

GetLeftMostCur-

sor

 oraz 

GetRightMostCursor

. Pierwsze z tych 

makr sprawdza, czy w tekście został zaznaczony 
fragment tesktu. Makro to wykorzystuje metodę 

getCurrentSelection()

  interfejsu  com::sun::

star::lang::XComponent, zwracającą obiekt bę-
dący tablicą aktualnych zaznaczeń w tekście.

allSelections = ThisComponent.Current
Controller.getCurrentSelection()

Jeśli  w  danym  dokumencie  znajduje  się  tyl-
ko  jedno  zaznaczenie,  to  powyższe  polecenie 
zwróci  jednoelementową  tablicę  –  zawierają-
cą dane zaznaczenie. Odwołanie do niego wy-
korzystuje metodę 

getByIndex()

, której para-

metr będzie miał oczywiście wartość 0.

oSelection = allSelections.getByIndex(0)

Wspomniane makro setTags wykorzystuje po-
nadto dwa inne makra, które określają początek 
zaznaczenia i jego koniec, co wcale nie jest ta-
ką prostą sprawą, jakby się wydawało. Obydwa 
te makra działają bardzo podobnie. Tworzą one 
obiekt Zakres (Range) na podstawie przekaza-
nego przy wywoływaniu parametru – konkret-
nego zaznaczenia. Ten z kolei służy do utwo-
rzenia  innego  obiektu  –  kursora  tekstowego 
–  odwzorowania  interfejsu  UNO  ::com::sun:
:star::text::XTextCursor
. Kursor ten zwracany 
jest w zależności od makra – jako skrajny pra-
wy lub skrajny lewy kursor.

Przy tej okazji nie sposób jest nie wspomnieć 

o idei kursorów w API OpenOffice.org. Najważ-
niejszą  kwestią  konieczną  do  zrozumienia  me-

chanizmu obsługi kursorów w OOo jest rozróż-
nienie dwóch jego typów. Oprócz wspomniane-
go w poprzednim akapicie kursora tekstowego, 
API OOo dostarcza jeszcze kursor widoczny – in-
terfejs UNO com::sun::star::text::XViewCursor
Jaka jest różnica pomiędzy obydwoma interfej-
sami? Kursor widoczny, jak sama nazwa wska-
zuje,  jest  odzwierciedleniem  kursora  migające-
go (na przykład) gdzieś w tekście, gdzie aktual-
nie wstawimy go kliknięciem myszki. Kursor ten 
jest więc jedynie punktem, którego współrzędne 
można określić za pomocą długości łańcucha po-
przedzającego  kursor  czy  długości  łańcucha  za 
kursorem.  W  przeciwieństwie  do  niego  kursor 
tekstowy jest kursorem niewidocznym, będącym 
niczym innym jak wspomnianym uprzednio za-
kresem tekstu. Nie należy jednak mylić kursora 
tekstowego z omówionym uprzednio zaznacze-
niem, gdyż ono jest właśnie zakresem, na pod-
stawie  którego  możemy  utworzyć  kursor  tek-
stowy.  Właśnie  ta  metoda  –  createTextCursor-
ByRange()  została  wykorzystana  w  omawia-

nych  makrach  GetLeftMostCursor  oraz  GetRi-
ghtMostCursor. 

We  wspomnianym  makrze 

setTags

  do 

wstawienia tekstu – tu znacznika otwierającego 
lub zamykającego sekcję – wykorzystana została 
metoda 

insertString(XTextRange,  String, 

boolean)

. Metoda ta wymaga trzech argumen-

tów. Pierwszy z nich to zakres tekstu (interfejs 
UNO ::com::sun:: star :: text::XTextRange), któ-
ry w opisywanym makro został zwrócony z me-
tody 

getStart()

 określającej początek kursora 

tekstowego.  Zakres  ten  jest  odzwierciedleniem 
pozycji, w której będzie wstawiony tekst. Dru-
gim parametrem jest łańcuch tekstowy, który ma 
być  wstawiony.  Trzecim  parametrem  jest  war-
tość logiczna (wartość typu boolean), która okre-
śla, czy wstawiany łańcuch tekstowy ma zastą-
pić zakres tekstu (true), czy poprzedzony tymże 
tekstem (false). Należy wspomnieć, iż wstawiany 
łańcuch tekstowy może zawierać oprócz znaków 
drukowanych także znaki typu Whitespaces, np. 
spację lub tabulator, a także znak łamania wiersza 

Tabela. 1 

Funkcje konwertujące różnego rodzaju dane

Funkcja

Opis

CDbl(txt)

Przekształca dane tekstowe 

txt

 na dane typu Double

CInt(txt)

Przekształca dane tekstowe 

txt

 na dane typu Integer

CLng(txt)

Przekształca dane tekstowe 

txt

 na dane typu Long

CSng(txt) Przekształca dane tekstowe 

txt

 na dane typu Single

Int(licz-
ba)

Przekształca wartość liczbową 

liczba

 na wartość typu Integer

Val(txt)

Przekształca dane tekstowe 

txt

 na dane typu Double. Funkcja bardzo tolerancyjna w sto-

sunku do wartości nienumerycznych.

CStr(obj)

Przekształca obiekt 

obj

 na dane typu String

Tabela 2. 

Znaki specjalne

Znak specjalny

Opis

PARAGRAPH_BREAK

Znak łamania paragrafu

LINE_BREAK

Znak łamania wiersza

HARD_HYPHEN

Znak twardego łącznika

SOFT_HYPHEN

Ten znak kontrolny określa punkt dzielenia wyrazów. Stosowany, 
jeśli słowa zawierające muszą być rozdzielone na końcu wiersza.

HARD_SPACE

Wstawia twardą spację (spacja ta nie zmienia rozmiaru podczas ju-
stowania wiersza oraz łączy ze sobą dwa wyrazy przy przenosze-
niu do nowego wiersza)

APPEND_PARAGRAPH

Wstawia nowy akapit

Tabela 3. 

Znaki specjalne wyrażeń regularnych zastosowane w opisywanych makrach

Znak

Opis

*

Dowolna liczba znaków, np. a*b odpowiada aab, jak i abbcccb

[abc123]

Wyszukuje dowolny ze znaków zapisanych pomiędzy nawiasami kwadratowymi

a-z

Myślnik oznacza zakres, tu wszystkie litery alfabetu od a do z, lecz 0-9 oznacza wszystkie 
cyfry

(abc)

Wyszukuje sekwencji abc

/>

Koniec wyrazu

[:space:]

Wyszukuje dowolny znak typu Whitespace

background image

70

Open Office

Macro w służbie autora

czerwiec 2009

71

Open Office

Macro w służbie autora

www.lpmagazine.org

(lf), jak i łamania paragrafu(cr). Makro to zawiera 
również bardzo podobną metodę – 

insertCon-

trolCharacter(XTextRange,ControlCha-
racter,boolean)

, która różni się od omawianej 

uprzednio tym, iż wstawia znak specjalny – jeden 
z przedstawionych w Tabeli 2.

Omawiane  makra 

setTitleSection

  oraz 

setLeadSection

  zawierają  dodatkowo  bardzo 

użyteczną funkcję liczenia tekstu, który ma być 
wprowadzony do danej sekcji. Jak wiadomo, re-
dakcja Linux+ narzuca limit dla tytułu 45 zna-
ków, a dla wprowadzenia – 700 znaków. Oby-
dwa  wspomniane  makra  poinformują  nas,  jeśli 
limity te zostaną przekroczone. W tym momen-
cie z pomocą przyjdzie nam opracowany prze-
ze  mnie  bardzo  prosty  edytor  tekstu  w  postaci 
okienka  dialogowego  uruchamianego  makrem 

TextEditor

Zaletą tego prostego edytora jest stały na-

słuch co do zmian we wprowadzanym tekście. 
Za każdą zmianą w polu tekstowym pod polem 
do edycji pojawia się informacja na temat ak-
tualnej liczby znaków. Przyciskiem Wklej tekst 
można wkleić poprawiony tekst do dokumentu 
– w miejscu wstawienia kursora. Warto zwrócić 
uwagę na kod tego makra, gdyż po raz pierw-
szy w tym artykule wykorzystane zostaną in-
terfejsy:  UNO  XTextListener  i  XActionListe-
ner 
będące pochodnymi interfejsu ::com::sun:
:star::lang::XEventListener
.  Zasada  stosowa-
nia nasłuchu zdarzeń w OOo jest bardzo pro-
sta. Do danej kontrolki okna dialogowego (czy 
też innego obiektu UNO) należy przypisać me-
todę typu add_Listener – różną w zależności od 
typu obsługiwanego zdarzenia. Parametrem tej 

metody jest obiekt powstały na bazie interfejsu 
obsługującego konkretne zdarzenie. Konstruk-
tor takiego obiektu nasłuchu wymaga podania 
dwóch parametrów. Pierwszy z nich to przed-
rostek  metod  implementujących  daną  obsłu-
gę zdarzeń, drugi zaś to klasa danego zdarze-
nia. Na koniec należy dodać makra obsługujące 
zdarzenia – z konkretnymi ustalonymi w kon-
struktorze  przedrostkami.  Niesamowitą  zaletą 
obsługi zdarzeń w OOo BASIC jest  łatwość, 
z jaką uzyskujemy dostęp do kontrolki wywo-
łującej zdarzenie – poprzez właściwość 

Source

 

obiektu zdarzenia (jednej z klas implementują-
cych  interfejs  ::com::sun::star::lang::XEven-
tListener
).  Z  podobną  łatwością  uzyskuje  się 
dostęp  do  kontenera,  na  którym  umieszczona 
jest dana kontrolka, to jest na przykład do okna 
dialogowego, gdzie się znajduje. Służy do tego 
właściwość 

Context

.

Nieco bardziej skomplikowana sytuacja ma 

miejsce  w  przypadku  sekcji  <<LISTING>>  i 
<<TABELA>>.  W  tych  to  sekcjach  wymaga-
ne  jest  podanie  dodatkowych  informacji  –  ta-
kich  jak  numer  tabeli/listingu  czy  też  tytuł.  In-
teraktywność makra setTags została rozwiązana 
poprzez zastosowanie okna dialogowego 

setTe-

xtDialog

 oraz funkcji 

getDialog()

, zwracają-

cej wprowadzony łańcuch znakowy. Okno dialo-
gowe 

setTextDialog

 jest zastąpieniem brakują-

cego w API OOo gotowego okna dialogowego 
typu INPUT, zwracającego wprowadzony tekst. 
Na całe szczęście tworzenie okien dialogowych 
w IDE OOo oraz ich obsługa są tak proste, że nie 
należy specjalnie płakać nad tą stratą.

Spis ilustracji

Najbardziej skomplikowanym przykładem okna 
dialogowego  i  zestawu  makr  je  obsługujących 
jest  okno,  które  wprowadza  spis  ilustracji  uży-
tych w artykule. Podstawowym makrem wywo-
ływanym jako pierwsze w tym celu jest makro 

ChoosePictureFiles

.  Makro  to  tworzy  okno 

dialogowe wyboru plików będące instancją ser-
wisu  UNO  ::com::sun::star::ui::dialogs::XFi-
lePicker
. Instancja ta ma dwie odmiany – klasę 
OfficeFilePicker  oraz  SystemFilePicker.  Pierw-
sza tworzy okno wyboru plików o GUI jak w ca-
łym pakiecie OpenOffice.org, druga zaś korzysta 
z systemowego okna wyboru. Zasadniczo nie po-
winno być różnicy pomiędzy obydwoma klasa-
mi, ale... Ja osobiście zauważyłem na MacOS X 
10.5.6 Leopard problemy ze stabilnością System-
FilePicker
. Nic się nie działo natomiast z Office-
FilePicker
.

Tworzone przeze mnie okno wyboru plików 

ma włączoną właściwość wielokrotnego wybo-
ru  (

setMultiSelectionMode(True)

).  Dodat-

kowo, aby ułatwić pracę z tym oknem, ustawi-
łem  filtr  plików  zezwalających  na  wyświetla-

nie  jedynie  plików  zakwalifikowanych  za  po-
mocą  rozszerzenia  jako  pliki  graficzne.  Innym 
istotnym  elementem  omawianego  makra  jest 
serwis ::com::sun::star::ucb::SimpleFileAccess 
zezwalający  na  pewne  proste  operacje  na  pli-
kach. W naszym przypadku operacją tą będzie 
sprawdzenie, czy dany plik jest rzeczywiście pli-
kiem, czy też katalogiem (folderem). Służy do 
tego metoda 

isFolder(File)

, która jako para-

metr przyjmuje obiekt typu File. W przypadku, 
gdy ma do czynienia z folderem (katalogiem), 
zwracana  jest  wartość  True.  Przyznaję  w  tym 
momencie,  że  obsługa  okna  dialogowego  wy-
boru plików początkowo nastręczyła mi pewne 
trudności, łatwe do pokonania, jeśli ma się wie-
dzę, którą chcę przekazać teraz. Otóż domyślnie 
okno dialogowe wyboru plików zwraca tablicę 
zawierającą  wybrane  pliki.  Nawet  jeżeli  pozo-
stawimy domyślną możliwość wyboru pojedyn-
czego pliku – nadal zwracana będzie tablica, ty-
le że jednoelementowa. Tablica ta zwracana jest 
jako efekt wywołania metody 

getFiles()

 dla 

obiektu okna dialogowego. Tutaj następuje pew-
na nieścisłość. W przypadku okna z wielokrot-
nym wyborem, jak w omawianym przykładzie, 
pierwszym elementem tablicy jest folder, a na-
stępnie nazwy wybranych plików w obrębie da-
nego folderu. Jeśli chcemy mieć pełną ścieżkę 
dostępu  do  wybranych  plików,  musimy  ręcz-
nie skleić sobie jedno z drugim – istna głupo-
ta! Tak też robię w omawianym makrze. Posia-
dając już tablicę z plikami obrazków, utworzo-
na jest pętla for, która kolejno wywołuje funk-
cję 

openPictureDialog

,  która  jako  argumen-

ty wymaga podania URL rysunku, nazwy pliku 
oraz kolejnego numeru rysunku (wartość indek-
su pętli for). Funkcja ta uruchamia okno dialo-
gowe, w którym wyświetlona zostaje miniaturka 
ilustracji oraz pola tekstowe z kolejnym (propo-
nowanym) numerem ilustracji, nazwą pliku ilu-
stracji i polem do wprowadzenia podpisu do ilu-
stracji. Po zatwierdzeniu przyciskiem Zatwierdź
uruchamiane jest kolejne makro – 

AddPicture-

Section

, które odpowiedzialne jest za wstawia-

nie sekcji opisującej rysunek z danymi podany-
mi uprzednio w oknie dialogowym.

Sekcja w sieci

Wstawienie tej sekcji do edytowanego artykułu 
potraktowałem na dwie możliwości. Pierwsza z 
nich  wykorzystuje  mechanizm  wyszukiwania 
użytych w tekście adresów internetowych, druga 
zaś wstawia adresy na podstawie podanych da-
nych w oknie dialogowym.

W  przypadku  przeszukiwania  tekstu  pod 

kątem adresów internetowych należy uruchomić 
makro SearchHTTP. Makro to jako podstawowy 
mechanizm  wykorzystuje  obiekt 

oDescriptor

 

będący  implementacją  interfejsu  UNO  ::com:

Rysunek 1. 

Okno dialogowe Przybornik autora

Rysunek 2. 

Pasek narzędziowy ze skrótami do opi-

sywanych makropoleceń

background image

70

Open Office

Macro w służbie autora

czerwiec 2009

71

Open Office

Macro w służbie autora

www.lpmagazine.org

:sun::star::util::SearchDescriptor.  Obiekt  ten 
przeszukuje tekst dokumentu pod kątem wystę-
powania  łańcucha  znakowego  zdefiniowanego 
we właściwości 

SearchString

 (tu przy pomocy 

polecenia 

Witch

). Inną właściwością tego obiek-

tu jest 

SearchRegularExpression

, której war-

tość True oznacza, że szukany łańcuch jest wy-
rażeniem regularnym. Jeśli ktoś do tej pory nie 
spotkał  się  z  pojęciem  wyrażenia  regularnego 
– nadszedł najwyższy czas, aby to zrobić. Wy-
rażenie regularne jest zapisem sekwencji znako-
wej za pomocą specjalnie zdefiniowanych sym-
boli, w ten sposób, aby istniała możliwość przy-
najmniej jednokrotnego odnalezienia sekwencji 
spełniającej założone warunki, co jednak nie jest 
konieczne (wyrażenie regularne może nie zostać 
odnalezione  w  przeszukiwanym  łańcuchu  zna-
kowym).  Zastosowane  przeze  mnie  wyrażenie 
regularne opiera się na zasadzie, iż adres inter-
netowy rozpoczyna się (przynajmniej powinien) 
od znaków http:// lub https://, po których nastę-
puje sekwencja liter, cyfr i/lub innych znaków. 
Wyrażenie regularne  odnajdujące adresy inter-
netowe wygląda następująco: (http[s]*://)[a-z0-
9._%+-/]*\>
. Szczegółowe wyjaśnianie znacze-
nia poszczególnych znaków specjalnych stoso-
wanych w wyrażeniach regularnych przekroczy-
łoby zakres tego artykułu, skoncentruję się więc 
jedynie na znakach użytych w danym wyraże-
niu.  Znaczenie  poszczególnych  znaków  przed-
stawia Tabela 3.

Aby przeszukać dokument pod kątem wy-

stępowania  zadanej  frazy,  należy  wywołać  dla 
obiektu 

ThisComponent

  jedną  z  metod,  z  któ-

rych każda, jako parametr, wymaga podania zde-
finiowanego  obiektu  interfejsu  SearchDescrip-
tor
. Metody te są następujące: 

findFirst()

 – wy-

szukująca pierwsze napotkane wyrażenie, 

find-

Next()

 - wyszukująca sekwencyjnie kolejne od-

powiadające wyrażenia, oraz 

findAll()

 – zwra-

cająca tablicę odpowiadających wyrażeń. W opi-
sywanym makrze została zastosowana ostatnia z 
metod – której iterator wykorzystywany jest na-

stępnie w pętli for, wstawiającej adres wraz z opi-
sem podanym w oknie dialogowym.

Zupełnie  inne  podejście  stosuje  makro  I

n-

WebSection

. Ono bowiem wyświetla na samym 

początku małe okno dialogowe, w którym za po-
mocą suwaka ustala się liczbę adresów, które ma-
ją się znaleźć w sekcji <<W_SIECI>>. W kodzie 
tego makro należy zwrócić szczególną uwagę na 
zaimplementowany nasłuch zdarzenia – zmiany 
wartości  suwaka  (XChangeEvent).  Wadą  kon-
trolki  suwaka  w  OOo  jest  fakt,  iż  poza  warto-
ścią  maksymalną  i  minimalną  niewiele  więcej 
(poza wyglądem graficznym) da się z nim zro-
bić.  Nie ma na przykład możliwości wyświetla-
nia aktualnej pozycji (wartości suwaka). Z tego 
też  powodu  zaimplementowany  nasłuch  wpro-
wadza dynamicznie odczytaną aktualną wartość 
suwaka do pola tekstowego. Wciśnięcie przyci-
sku Zatwierdź uruchamia kolejne makro – Cre-
ateDialog
. Makro to służy dynamicznemu zbu-
dowaniu okna dialogowego – bez użycia kreatora 
– bezpośrednio z kodu OOo BASIC. Jak widać, 
nie jest to specjalnie trudne, a daje dużo większe 
możliwości obsługi tak zbudowanego okna dia-
logowego. Okno to zawiera odpowiednią liczbę 
powtórzeń par pól tekstowych – do których na-
leży wprowadzić adres i opis pola. Zatwierdze-
nie wpisanych wartości powoduje wstawienie do 
tekstu  adresów  wraz  z  opisami,  z  wykorzysta-
niem tych samych metod, jak opisane uprzednio.

Podwójne spacje, 

usuwanie cudzysłowów

Mechanizm  wyszukiwania  za  pomocą  wyra-
żenia  regularnego  stosuje  również  inne  makro 
– 

FindDoubleSpaces

 – wyszukujące w tekście 

podwójnych  spacji.  Makro  to  jednak  wykorzy-
stuje  interfejs  UNO  ::com::sun::star::util::Re-
placeDescriptor
.  W  tym  konkretnym  przypad-
ku szukamy podwójnych spacji, które przez wy-
rażenie regularne zapisane jest w postaci [:spa-
ce:][:space:].  Właściwość  tego  deskryptora  Re-
placeString
  stosuje  znak  specjalny  &  oznacza-

jący tę samą wartość, co wyszukiwana. Jedyną 
zmianą jaką się tutaj wprowadza jest formatowa-
nie – wstawienie czerwonego tła w miejscu po-
dwójnej spacji. Błąd ten należy usunąć już oso-
biście. Do ustawienia czerwonego koloru tła zna-
ków służy  właściwość 

CharBackColor

, przypi-

sana do deskryptora zastępującego.

Ostatnim  makrem  wykorzystującym  wyra-

żenia regularne jest makro wyszukujące cudzy-
słowy drukarskie i adresy http:// i formatujące te 
łańcuchy na kursywę.

Inspektor akapitów

Ostatnim  makrem,  które  chciałbym  przybliżyć 
na łamach tego artykułu jest inspektor akapitów. 
Makro to przegląda akapit za akapitem, wyświe-
tla w oknie dialogowym, jaki styl został zastoso-
wany dla niego oraz umożliwia zmianę tego sty-
lu na jeden z trzech: DomyślnyNagłówek 1 i Na-
główek  2
.  Makro  akapity  w  swojej  konstrukcji 
wykorzystuje metodę createEnumeration(), któ-
ra  zwraca  kolejne  tablice  kolejnych  akapitów. 
Dostęp do poszczególnych akapitów odbywa się 
za pomocą 

nextElement()

, zwracającego para-

graf. Wadą metody createEnumeration() jest nie-
możliwość bezpośredniego odwołania się do ko-
lejnego akapitu poprzez index (brak takiej funk-
cji w API OOo).

Podsumowanie

Mam nadzieję, iż wszyscy piszący artykuły do 
Linux+  zaczną  stosować  napisane  przeze  mnie 
makra. Choć z pewnością nie są one doskonałe, 
to i tak stanowią wyśmienite ułatwienie pracy. In-
ne osoby, które nie skorzystają z tych makr bez-
pośrednio, z opisanych przeze mnie przykładów 
będą mogły czerpać wiedzę w zakresie stosowa-
nia makr w pracy z OpenOffice Writer. Na sam 
koniec dodam, iż powyższy tekst przygotowałem 
przy zastosowaniu opisywanych makr. 

Listing 7. 

Deklarowanie zmiennych różnych typów

Sub

 

Main

Dim

 

zmienna

Dim

 

zmienna1

 

As

 

String

,

 

zmienna2

$

Dim

 

zmienna4

 

As

 

Single

,

 

zmienna5

 

As

 

Double

DefInt

 

zmienna6

End

 

Sub

Listing 8. 

Zmienne o różnym zasięgu

Global

 

oForm

Sub

 

Main

oForm

 = 

thisComponent

.

getDrawPage

().

getForms

().

getByName

(

"Standard"

)

Private

 

component

 = 

oForm

.

getByName

(

"poletxt"

)

End

 

Sub

Grzegorz Madajczak jest z wykształcenia le-
karzem weterynarii i mikrobiologiem. Linuk-
sem  i  ogólnym  oprogramowaniem  Open-
Source
 pasjonuje się od 2001 roku. Na co 
dzień używa Linuksa zarówno w pracy, jak 
i w domu. Jego ulubione dystrybucje to Gen-
too i Slackware.
Kontakt z autorem: madajczak@gmail.com

O autorze

•   http://www.madajczak.eu/download/

przybornik_autora.odt – plik ODT z 
opisywanymi makrami.

W Sieci