


Document file nazwa_pliku.odt is locked for editing By użytkownik (DD.MM.YYYY HH:MM)
Plik dokument "nazwa_pliku.odt" w dniu 05.04.2010 01:12 został przez Ciebie na innym systemie zablokowany przed edycją
"..~lock.nazwa_pliku.odt#
i zwyczajnie go usuwamy.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.
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.
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
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
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
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
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].
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.