26.3.10

Poprawka dla autokorekty w OpenOffice 3.2

Autokorekta – poprawianie w czasie pisania – w OpenOffice.org 3.2 przestała działać z powodu drobnego błędu w pliku. Wystarczy otworzyć Narzędzia > Opcje autokorekty..., aby przekonać się, że na karcie Zamień nie ma żadnych wpisów.

Błąd udało się wykryć i zlikwidować, a tutaj udostępniam proste lekarstwo: wystarczy zapisać ten plik na dysku (po kliknięciu prawym przyciskiem myszy), a następnie kliknąć dwukrotnie (lub jednokrotnie w zależności od systemu). Po zainstalowaniu rozszerzenia (i być może też ponownym uruchomieniu OpenOffice.org) na karcie Zamień pojawią się wpisy.

Poprawka jest niepełna, bo nie można normalnie redagować takiej poprawionej autokorekty, ale lepszy rydz niż nic :)

4.3.10

Tworzymy i publikujemy blog z poziomu OpenOffice.org.

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


Artykuł znaleziono w serwisie czytelnia.ubuntu.pl. Jego autorem jest Dmitri Popov, a sam tekst jest przedrukiem z gazety Linux Magazine 1(71)/2010 i został opublikowany za zgodą redakcji.