Makra w OpenOffice.org 7


LinuxMagazine-styczen

Od Redakcji: artykuł pochodzi ze styczniowego wydania Linux Magazine. Kompletną listę artykułów możecie znaleźć na stronach miesięcznika.

Co prawda OpenOffice.org jest przede wszystkim pakietem biurowym, możemy jednak wykorzystać jego zdolność łączenia się z zewnętrznymi systemami zarządzania bazami danych, jak MySQL, by stworzyć wygodne rozwiązania, rozszerzające jego funkcje poza zwyczajne redagowanie dokumentów. Możemy na przykład połączyć OpenOffice’a z bazą danych aplikacji do blogowania, co pozwoli pisać i publikować posty bezpośrednio z Writera. Brzmi to może jak zadanie dla zawodowego programisty, ale w rzeczywistości wystarczy kilka prostych makr.

Rysunek 1: Doskonałym kandydatem do naszego zadania będzie Bilboblog.

Elementy układanki

By ułatwić zrozumienie działania tego projektu, podzielę jego wykonanie na kilka kroków. Najpierw powinniśmy zainstalować i skonfigurować aplikację do blogowania. Teoretycznie do naszych celów nada się każda z nich, o ile korzysta z bazy danych MySQL. W praktyce powinniśmy jednak wybrać niezbyt skomplikowany program, posługujący się prostą bazą danych. W naszym przykładzie użyjemy nieco zmodyfikowanej wersji aplikacji do blogowania Bilboblog (Rysunek 1) [1]. Przechowuje ona treści w prostej tabeli z zaledwie trzema polami, dzięki czemu nadaje się idealnie do wykorzystania w naszym projekcie.

Będziemy również potrzebować serwera PHP / MySQL lub konta na odpowiednim serwisie, gdzie będziemy mogli zainstalować Bilbobloga. By to zrobić, wystarczy stworzyć bazę danych MySQL (na przykład bilboblog), pobrać najnowszą wersję aplikacji, rozpakować archiwum i przenieść jego zawartość (katalog bilboblog) do katalogu głównego na serwerze. Nadajemy mu prawa zapisu i poprzez przeglądarkę przechodzimy do http://twojserwer/bilboblog. Tu wypełniamy wymagane pola i klikamy Install.

Rysunek 2: Konfiguracja połączenia z MySQL-em za pomocą aplikacji Database Wizard.

Następnie musimy połączyć OpenOffice’a z bazą danych Bilbobloga. W tym celu potrzebujemy rozszerzenia Sun MySQL Connector dla OpenOffice.org [2], które integruje się bezpośrednio z naszym pakietem biurowym i umożliwia połączenie z bazą danych (Rysunek 2). By go zainstalować, pobierzmy najnowszą wersję rozszerzenia. W OpenOffice.org wchodzimy w Narzędzia | Menedżer rozszerzeń, wciskamy przycisk Dodaj i wybieramy pobrany plik .oxt. Teraz wystarczy zrestartować OpenOffice – i gotowe.

Rysunek 3: Struktura bazy danych bilboblog.

Na koniec tworzymy prosty plik bazy danych (Base), łączący pakiet biurowy z bazą danych Bilbobloga (domyślnie bilboblog). W tym celu w OpenOffice.org wybieramy Plik | Nowy | Baza danych, zaznaczamy opcję Połącz z istniejącą bazą danych i wyszukujemy na liście rozwijanej MySQL. Teraz wciskamy Dalej i zaznaczamy opcję Connect native. W kolejnym kroku określamy ustawienia połączenia z bazą danych i nazwę użytkownika, a następnie zaznaczamy pole Wymagane hasło.

By sprawdzić, czy połączenie funkcjonuje prawidłowo, wciskamy przycisk Testuj połączenie, po czym upewniamy się, że zaznaczona jest opcja Tak, zarejestruj bazę danych, odznaczamy pole Otwórz bazę danych do edycji i zapisujemy efekt końcowy jako Bilboblog.odb. Powstały plik nie tylko łączy się z bazą danych bilbobloga, ale też pozwala przyjrzeć się jej strukturze. Otwórzmy Bilboblog.odb i przejdźmy do sekcji Tabele. Jeśli klikniemy dwukrotnie na bazę danych bilboblog, powinna pojawić się tabela articles (Rysunek 3). Jej strukturę także możemy podejrzeć poprzez podwójne kliknięcie.

Piszemy makra

Tabela articles składa się z trzech pól: num_article, gdzie znajdują się numery ID postów, article_pub z czasem publikacji oraz article_content, przechowująca treść postów. Na początek musimy napisać proste makro w języku OpenOffice.org Basic. Będzie ono tworzyć rekord w tabeli articles i zapisywać zawartość otwartego dokumentu Writer w polu article_content. Makro ma wykonywać trzy czynności: pobierać tekst z otwartego dokumentu Writer, łączyć się z bazą danych bilboblog i zapisywać tekst w polu article_content tabeli articles. Pierwszy krok – pobranie zawartości aktywnego dokumentu – wymaga trzech prostych linii kodu:

ThisDoc=ThisComponent
ThisText=ThisDoc.Text
Article=ThisText.String

Teraz musimy połączyć się z bazą danych. Tu również wystarczą trzy instrukcje:

DBContext=createUnoService ("com.sun.star.sdb.DatabaseContext")
DataSource=DBContext.getByName ("Bilboblog")
DB=DataSource.GetConnection ("użytkownik", "hasło")

W miejscu ciągów „użytkownik” i „hasło” wpisujemy nazwę użytkownika i hasło do bazy danych. Podanie tych elementów na stałe sprawia, że makro staje się mniej elastyczne (jeśli zmienimy któreś z nich, musimy ręcznie edytować makro), możemy więc pokusić się o zmodyfikowanie go tak, by samo pytało o dane do logowania. W takim wypadku kod umożliwiający połączenie z bazą danych przybierze następującą postać:

DBContext=createUnoService ("com.sun.star.sdb.DatabaseContext")
DataSource=DBContext.getByName("Bilboblog")
UserName=InputBox ("Użytkownik MySQL", "Attention")
UserPassword=InputBox ("Hasło", "Attention")
DB=DataSource.GetConnection (UserName, UserPassword)

Do manipulowania bazą danych OpenOffice.org Basic wykorzystuje zapytania SQL, więc aby zapisać pobrany tekst w polu article_content, makro posługuje się zapytaniem opartym na poleceniu INSERT INTO o następującym formacie:

INSERT INTO articles (pole1, pole2) VALUES ('wartość1', 'wartość2')

W naszym przypadku zapytanie INSERT INTO wyglądać będzie tak:

SQLQuery="INSERT INTO articles (article_content) VALUES ('" + Article + "')"

W języku OpenOffice.org Basic po zapytaniu INSERT INTO następują dwie instrukcje, służące do jego wykonania:

SQLStatement=DB.createStatement
Result=SQLStatement.executeQuery (SQLQuery)

Kiedy kwerenda zostanie już wykonana, makro sprząta po sobie, zamykając połączenie z bazą danych:

DB.close
DB.dispose

Cały kod przedstawiony jest w Listingu 1.

Sub PostToBilboblog
ThisDoc=ThisComponent
ThisText=ThisDoc.Text
Article=ThisText.String
DBContext=createUnoService("com.sun.star.sdb.DatabaseContext")
DataSource=DBContext.getByName("Bilboblog")
UserName=InputBox("Użytkownik MySQL", "Attention")
UserPassword=InputBox("Hasło", "Attention")
DB=DataSource.GetConnection (UserName, UserPassword)
SQLQuery="INSERT INTO articles (article_content) VALUES ('" + Article + "')"
SQLStatement=DB.createStatement
Result=SQLStatement.executeQuery (SQLQuery)
DB.close
DB.dispose
End Sub

Listing 1: Makro w języku OpenOffice.org Basic

Wszystko pięknie, ale powstałe makro ma jedno poważne ograniczenie: odziera tekst z wszelkiego formatowania, więc jeśli chcemy, by zachowane zostały pogrubienia, kursywa, podkreślenia i inne style tekstowe, będziemy potrzebować trochę więcej kodu. Bilboblog formatuje tekst za pomocą podzbioru znaczników BBCode, w tym pogrubienia (znaczniki [b] i [/b]), kursywy ([i] i [/i]) oraz podkreślenia ([u] i [/u]). Możemy oczywiście użyć tychże znaczników w trakcie pisania tekstu w Writerze, ale byłoby znacznie wygodniej, gdyby makro potrafiło przetworzyć tekst automatycznie, w momencie wstawiania jego zawartości do tabeli articles. W tym celu musimy zmodyfikować makro, aby odnajdywało wszystkie fragmenty sformatowane za pomocą pogrubienia, kursywy i podkreślenia i otaczało je odpowiednimi znacznikami. Bez zbędnych ceregieli przyjrzyjmy się Listingowi 2, który zawiera przykładowe makro wyszukujące pogrubione fragmenty tekstu i oznaczające je znacznikami [b] i [/b].

Sub ReplaceBold
Dim SearchAttributes(0) As New com.sun.star.beans.PropertyValue
ThisDoc=ThisComponent
SearchAttributes(0).Name="CharWeight"
SearchAttributes(0).Value=com.sun.star.awt.FontWeight.BOLD
ReplaceObj=ThisDoc.createReplaceDescriptor
ReplaceObj.SearchStyles=false
ReplaceObj.SearchAll=true
ReplaceObj.SearchRegularExpression=true
ReplaceObj.SetSearchAttributes(SearchAttributes)
ReplaceObj.SearchString=".*"
ReplaceObj.ReplaceString="[b]&[/b]"
ThisDoc.replaceAll(ReplaceObj)
End Sub

Listing 2: Makro zachowujące pogrubienie

Makro zaczyna się od określenia atrybutów wyszukiwania name i value i stworzenia obiektu ReplaceObj. Jego parametry definiują operacje wyszukania i zastąpienia. Ustawienie opcji SearchStyles na false zapobiega wyszukiwaniu przez makro konkretnych stylów, zaś aktywowanie parametru SearchAll pozwala na przeszukanie całego dokumentu. SearchRegularExpression umożliwia wykorzystanie wyrażeń regularnych, więc makro może posłużyć się wartością .* opcji SearchString, by przeszukać cały tekst. Parametr ReplaceString definiuje ciąg, którym zostanie zastąpiony odnaleziony fragment tekstu. Następnie ThisDoc.replaceAll(ReplaceObj) przeprowadza operację wyszukania i zamiany.

By tak samo postąpić z tekstem kursywą, wystarczy następująco zmodyfikować wartości SearchAttributes(0).Name, SearchAttributes(0).Value i ReplaceObj.ReplaceString:

SearchAttributes(0).Name="CharPosture"
SearchAttributes(0).Value=com.sun.star.awt.FontSlant.ITALIC
ReplaceObj.ReplaceString="[i]&[/i]"

Zamiast pisać kilka podprocedur dla każdego stylu, możemy z łatwością zmienić makro w funkcję i wywołać ją z podprocedury głównej – wystarczy, że zastąpimy wartości zmiennymi (Listing 3).

Function MarkupStr(SearchAttrName, SearchAttrValue, ReplaceStr)
Dim SearchAttributes(0) As New com.sun.star.beans.PropertyValue
ThisDoc=ThisComponent
SearchAttributes(0).Name=SearchAttrName
SearchAttributes(0).Value=SearchAttrValue
ReplaceObj=ThisDoc.createReplaceDescriptor
ReplaceObj.SearchStyles=false
ReplaceObj.SearchAll=true
ReplaceObj.SearchRegularExpression=true
ReplaceObj.SetSearchAttributes(SearchAttributes)
ReplaceObj.SearchString=".*"
ReplaceObj.ReplaceString=ReplaceStr
ThisDoc.replaceAll(ReplaceObj)
End Function

Listing 3: Zmieniamy podprocedurę w funkcję

Teraz możemy wywołać funkcję w głównej podprocedurze i podać odpowiednie wartości. Poniższy fragment kodu wyszukuje pogrubione, podkreślone i przekreślone fragmenty tekstu oraz kursywę za pomocą funkcji MarkupStr i stosuje w nich odpowiednie znaczniki.

MarkupStr("CharWeight", com.sun.star.awt.FontWeight.BOLD, "[b]&[/b]")
MarkupStr("CharPosture", com.sun.star.awt.FontSlant.ITALIC, "[i]&[/i]")
MarkupStr("CharUnderline", com.sun.star.awt.FontUnderline.SINGLE, "[u]&[/u]")
MarkupStr("CharStrikeout", com.sun.star.awt.FontStrikeout.SINGLE, "[s]&[/s]")

Makro jest prawie gotowe, powinniśmy jednak naprawić jeszcze jeden niewielki mankament. Bilboblog zapisuje datę i czas w tak zwanym uniksowym formacie czasowym, określanym jako liczba sekund, które upłynęły od północy 1 stycznia 1970 roku. Jeśli wrzucimy do tabeli articles rekord bez podania właściwego znacznika czasu, domyślnie wyświetlony zostanie właśnie 1 stycznia 1970 roku, co nie jest zbyt praktyczne. By uniknąć tego problemu, powinniśmy dodać instrukcję, która przypomina o podaniu daty i czasu:

Timestamp=InputBox ("Podaj znacznik czasu", "Attention")

Musimy również zmodyfikować zapytanie SQL, by wpisywało pobraną wartość znacznika czasu w polu article_pub:

SQLQuery="INSERT INTO articles (article_content, article_pub) VALUES ('" + Article + "', '" + Timestamp + "')"

Sub PostToBilboblog
MarkupStr("CharWeight", com.sun.star.awt.FontWeight.BOLD, "[b]&[/b]")
MarkupStr("CharPosture", com.sun.star.awt.FontSlant.ITALIC, "[i]&[/i]")
MarkupStr("CharUnderline", com.sun.star.awt.FontUnderline.SINGLE, "[u]&[/u]")
MarkupStr("CharStrikeout", com.sun.star.awt.FontStrikeout.SINGLE, "[s]&[/s]")
ThisDoc=ThisComponent
ThisText=ThisDoc.Text
Article=ThisText.String
DBContext=createUnoService("com.sun.star.sdb.DatabaseContext")
DataSource=DBContext.getByName("Bilboblog")
UserName=InputBox("Użytkownik MySQL", "Attention")
UserPassword=InputBox("Hasło", "Attention")
DB=DataSource.GetConnection (UserName, UserPassword)
Timestamp=InputBox("Podaj znacznik czasu", "Attention")
SQLQuery="INSERT INTO articles (article_content, article_pub) VALUES ('" + Article + "', '" + Timestamp + "')"
SQLStatement=DB.createStatement
Result=SQLStatement.executeQuery (SQLQuery)
DB.close
DB.dispose
End Sub
Function MarkupStr(SearchAttrName, SearchAttrValue, ReplaceStr)
Dim SearchAttributes(0) As New com.sun.star.beans.PropertyValue
ThisDoc=ThisComponent
SearchAttributes(0).Name=SearchAttrName
SearchAttributes(0).Value=SearchAttrValue
ReplaceObj=ThisDoc.createReplaceDescriptor
ReplaceObj.SearchRegularExpression=true
ReplaceObj.searchStyles=false
ReplaceObj.searchAll=true
ReplaceObj.SetSearchAttributes(SearchAttributes)
ReplaceObj.SearchString=".*"
ReplaceObj.ReplaceString=ReplaceStr
ThisDoc.replaceAll(ReplaceObj)
End Function

Listing 4: Makro i funkcja

Na Listingu 4 znajduje się ostateczna wersja makra i dołączonej do niego funkcji. Pytanie brzmi: jak wyliczyć wartość znacznika czasu? Możemy wprawdzie napisać kod konwertujący bieżącą datę i czas na znacznik czasu w formacie uniksowym, ale może to być problematyczne. Najprostszym rozwiązaniem jest skorzystanie z polecenia date %s w terminalu lub zainstalowanie rozszerzenia TimeStamp Converter dla Firefoksa [3].

Ostateczny szlif

Na koniec przyjrzyjmy się makru, które analizuje linki w dokumencie Writer i nadaje im formatowanie Bilbobloga. W odróżnieniu od funkcji zajmującej się formatowaniem tekstu, makro przetwarzające hiperłącza wykorzystuje obiekt Enumeration, za pomocą którego możemy po kolei przejrzeć paragrafy dokumentu, pobrać wartości parametru HyperlinkURL, a następnie zastosować określone formatowanie (Listing 5).

Sub MarkupURL
ThisDoc=ThisComponent
ThisText=ThisDoc.Text
ParaEnum=ThisText.createEnumeration
While ParaEnum.hasmoreElements
 Para=ParaEnum.nextElement
  PortionEnum=Para.createEnumeration
   While PortionEnum.hasMoreElements
    Portion=PortionEnum.nextElement
     If Portion.HyperlinkURL <> "" then
       Portion.String = "[url=" + Portion.HyperlinkURL +"]" +Portion.String + "[/url]"
      End if
   Wend
Wend
End Sub

Listing 5: Analiza i formatowanie hiperłączy

By przetworzyć hiperłącza za pomocą tego makra, wystarczy wywołać je z głównej podprocedury PostToBilboblog.

Info

Autor: Dmitri Popov

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

7 komentarzy do “Makra w OpenOffice.org

  • command_dos

    Artykuł git. Muszę popracować nieco nad moim wordpress’em, może uda mi się coś wymiodzić… Zastanawia mnie, co będzie dalej z doskonałym openoffice’em i mysql’em – teraz oracle przejęło pałeczkę. Mam nadzieję, że podejdą do tematu bardzo wyrozumiale, choć ich działania zawsze były sprowadzane do nabijania kasy… Pożyjemy zobaczymy. Niemniej jednak, w artykule mamy pokazaną siłę i możliwości jednego i drugiego produktu, z których głównie znany był sun – dzięki za przydatne informacje, oceniam na maxa.

  • Michal

    mam pytanie. Jak napisać makro, które by zapisywało arkusze z pobraniem tytułu z wskazanej komórki (np D1) z umieszczeniem takiego przycisku na arkuszu. Takie coś chcę wykorzystać przy rejestrowaniu faktur w OpenOffice. Serdecznie dziękuję z góry za pomoc.

  • boo

    Ło matko!
    „Brzmi to może jak zadanie dla zawodowego programisty, ale w rzeczywistości wystarczy kilka prostych makr.”
    No prościutkie rzeczywiście.

  • Akacz

    [quote post=”11083″]W tym celu potrzebujemy rozszerzenia Sun MySQL Connector dla OpenOffice.org [2], które integruje się bezpośrednio z naszym pakietem biurowym i umożliwia połączenie z bazą danych (Rysunek 2). By go zainstalować, pobierzmy najnowszą wersję rozszerzenia. W OpenOffice.org wchodzimy w Narzędzia | Menedżer rozszerzeń, wciskamy przycisk Dodaj i wybieramy pobrany plik .oxt. Teraz wystarczy zrestartować OpenOffice – i gotowe.[/quote]

    Dla WinXP i OpenOffice.org 3.1 – wszystko gra. Ale w przypadku OpenOffice.org 3.2 pod Ubuntu dostaję
    „loading component library failed.
    I co z tym zrobić?