Uwaga: przeglądasz tę stronę na urządzeniu o niewielkim ekranie (szerokość < 640px). Niektóre zamieszczone w artykule ilustracje i animacje mogą stać się nieczytelne po dopasowaniu ich do rozdzielczości tego ekranu.
Opracowanie powstało z wykorzystaniem wersji oprogramowania istniejącej w trakcie jego pisania. Był to LibreOffice 24.2.5.
W pakiecie LibreOffice od wersji 7. do kontenera „Makra i okna dialogowe aplikacji” włączono nowe biblioteki nazywane skrótowo ScriptForge. Taką nazwę ma główna biblioteka tego zestawu a pozostałe, skojarzone z nią, mają nazwy rozpoczynające się od wielkich liter SF. Zestaw tych bibliotek usprawnia pisanie makr przez użytkowników słabiej znających interfejs API. Z tych bibliotek, mogą także korzystać osoby piszące w języku Python.
Produkt ten nie jest dostępny w Apache OpenOffice, więc makra utworzone z wykorzystaniem ScriptForge nie mogą być uruchomione w środowisku Apache OpenOffice, chociaż same dokumenty można wczytać i przetwarzać w tradycyjny sposób, z uwzględnieniem różnic w rozwoju obu wersji aplikacji.
W styczniu 2021 roku na blogu The Document Foundation tak zapowiedziano pojawienie się tego produktu:
„Biblioteki ScriptForge to rozszerzalny i solidny zbiór zasobów skryptów makr dla LibreOffice, które można wywoływać z makr użytkownika Basic. Użytkownicy zaznajomieni z innymi wariantami makr w języku BASIC często mają trudności z zagłębieniem się w rozbudowany interfejs programowania aplikacji LibreOffice, nawet w przypadku najprostszych operacji. Gromadząc najbardziej wymagane operacje na dokumentach w zestawie łatwych w użyciu i czytelnych procedur, użytkownicy mogą teraz programować makra dokumentów przy znacznie mniejszym wysiłku i szybciej uzyskiwać wyniki. Bogate metody ScriptForge są zorganizowane w moduły wielokrotnego użytku, które w przejrzysty sposób izolują konstrukcje języka programowania Basic od dostępu do treści dokumentów ODF i funkcji interfejsu użytkownika (UI)” [
https://blog.documentfoundation.org/blog/2021/01/28/introducing-the-scriptforge-basic-libraries].
Niniejsze opracowanie jest zorientowane na osoby programujące w Basicu, ale jeszcze raz podkreślę to, co napisałem na wstępie, że korzystanie z tej biblioteki możliwe jest także dla piszących w języku Python.
Wszystkie procedury z bibliotek są uruchamiane jako usługi obsługujące wybrany obiekt.
Usługi te podzielono umownie na cztery kategorie mówiące, do jakiego typu obiektu mogą zostać zastosowane. Oto ten podział.
Tak więc np. usługa o nazwie Array dotyczy wektorów i tablic przetwarzanych w Basicu, usługa Calc – działań dotyczących arkusza kalkulacyjnego, usługa Document – dokumentu jako takiego a usługa Menu pozwala utworzyć własne menu w tworzonym projekcie.
Każda usługa ma swoje właściwości i metody, które można wykorzystać w stosunku do obiektu, któremu została przypisana.
Do wywołania usługi służy ogólny konstruktor usług o postaci:
a do zakończenia korzystania z niej i zwolnienia zasobów, które usługa zawłaszczyła, służy metoda Dispose() dostępna w każdej usłudze.
Biblioteka oraz udostępnione usługi są dobrze opisane w systemie pomocy. Każdy opis zawiera sposób wywołania usługi, jej właściwości, metody oraz przykłady jej użycia uwzględniając programowanie w Basicu i Pythonie.
Korzystanie z biblioteki wymaga oczywiście jej załadowania, dlatego koniecznym jest umieszczenie w Basicu, przed pierwszym odwołaniem do biblioteki, instrukcji:
Artykuł przeznaczony jest dla osób mających już pewne doświadczenia z programowaniem w Basicu, nie rości sobie praw do bycia podręcznikiem ScriptForge, lecz ma zaprezentować możliwości tkwiące w procedurach tej biblioteki. Chcę to przedstawić, wykorzystując konkretny, może niezbyt wyszukany, problem. Najwięcej projektów programistycznych związanych z LibreOffice dotyczy arkusza kalkulacyjnego, dlatego to na jego przykładzie postaram się to przedstawić.
Najpierw jednak opiszę, jakie zagadnienie chcę rozwiązać.
Istniejący skoroszyt składa się z trzech arkuszy o nazwach: Baza, Ark1 i Ark2.
W arkuszu Baza znajduje się pewna baza danych.
Rys. 1: Fragment bazy danych.
Rekordy w bazie zawierają pięć pól. Trzy, to pola zawierające zawartość bezpośrednią (wprowadzaną przez użytkownika) są to „Nazwa”, „Cena U$” i „Ilość”, i dwa pola, których zawartość wyznaczają formuły; pierwsze z nich o nazwie „Razem U$”, jest wynikiem iloczynu Cena U$ × Ilość i drugie o nazwie „Razem PLN”, jest iloczynem obliczonego już Razem U$ i kursu wymiany zapisanego w komórce B1 tego arkusza. Komórce B1 nadałem nazwę „przelicznik”. Zawartość bazy podlega różnego rodzaju filtrowaniu, a odfiltrowane dane umieszczane są w arkuszu Ark1 zaczynając od komórki D3. Tej komórce nadałem nazwę: „Wyciąg”. Taki efekt filtrowania można uzyskać za pomocą filtrowania standardowego albo zaawansowanego. Wiadome jest, że jeśli dane źródłowe zawierały komórki z formułami, to odfiltrowane dane także zawierają te formuły.
To, co chcę oprogramować, to możliwość przekopiowania odfiltrowanych danych do innej lokalizacji. Skopiowane mają zostać tylko wartości oraz ich atrybuty (kolor, pogrubienie itp. bez formuł), a wybrać należy jedną z dwóch możliwości kopiowania:
Kopiowanie odfiltrowanych danych do arkusza o nazwie „Ark2”, znajdującego się w tym samym skoroszycie. Komórką początkową dla odfiltrowanych rekordów będzie B5.
Kopiowanie odfiltrowanych danych do nowego pliku. Utworzony plik ma mieć nazwę pliku macierzystego uzupełnioną o datę i czas jego utworzenia. Plik ma zostać zapisany w tej samej lokalizacji, co skoroszyt macierzysty.
Wybór jednego z powyżej wymienionych działań nastąpi przez wykorzystanie nowej pozycji o nazwie „Moje menu” dodanej do menu głównego programu Calc. Przedstawia to poniższa ilustracja.
Rys. 2: Zmodyfikowane menu główne programu Calc.
„Moje menu”, zawiera dwie możliwości wyboru. Wywołanie tej pozycji jest możliwe także z wykorzystaniem skrótu klawiaturowego ALT(lewy)+u (litera „u” w nazwie jest podkreślona), a wybór konkretnej akcji po naciśnięciu klawisza „W” lub „K” (podkreślone litery w nazwach).
Samo filtrowanie danych nie jest oprogramowane, gdyż to użytkownik sam wybiera sposób i zasady filtrowania. Jedynym wymogiem jest, aby odfiltrowane dane były przekopiowane w ustalone miejsce. Więc opcje filtru powinny być ustawione jak poniżej.
Rys. 3: Przykładowe kryteria filtrowania.
Powyższy przykład przedstawia kryteria filtra standardowego do odfiltrowania tych rekordów z bazy, w których „Ilość” jest liczbą nieparzystą, ale kluczowe jest tutaj zaznaczenie opcji „Kopiuj wyniki do” i wskazanie tego ustalonego miejsca.
Oprogramowanie
.
W ogólnym podejściu do tego zagadnienia oprogramowanie wymaga trzech podstawowych procedur.
Procedury, która utworzy, na potrzeby tego skoroszytu, nowe menu i opcje wyboru.
Procedury kopiującej wyniki do arkusza Ark2.
Procedury tworzącej nowy plik zawierający odfiltrowane rekordy bazy.
Powyższa lista wskazuje, że zostaną wykorzystane co najmniej usługi: Menu (utworzenie menu), Calc (działania na skoroszycie) i Document (działania na dokumencie). W rzeczywistości zostaną użyte jeszcze inne usługi i zostaną one omówione w dalszej części.
W tym miejscu należy wspomnieć, że w stosunku do arkusza kalkulacyjnego usługi ScriptForge korzystają z odwołań zapisywanych w notacji naturalnej, a więc np. A3, B10:F45, Arkusz2.C3:C8.
Utworzenie własnego menu.
Pierwszą procedurą, która zostanie wykonana, jest procedura „NoweMenu” tworząca nową pozycję w menu głównym Calca.
Tu należy powiedzieć o funkcjonowaniu tak utworzonego menu. Otóż jest ono dostępne wyłącznie w skoroszycie, w którym je utworzono i nie jest zapisywane z dokumentem. W związku z tym, po zamknięciu skoroszytu i ponownym jego otwarciu, to menu się nie pojawi. Ponadto każda zmiana interfejsu użytkownika spowodowana np. wywołaniem akcji tworzenia wykresu albo aktywowaniem obiektu OLE, sprawi, że po powrocie do ekranu podstawowego tego menu także już nie będzie. To oznacza, że w takich sytuacjach należałoby ponownie uruchomić procedurę.
W wersji ostatecznej tego skoroszytu procedurę przypisałem do zdarzenia „Otwórz dokument”, co oznacza, że będzie ona automatycznie uruchomiona przy każdym ładowaniu skoroszytu i dzięki temu użytkownik od razu zobaczy pozycję „Moje menu”. Ponieważ jest to w ogóle pierwsza procedura uruchamiana w skoroszycie, to w niej znajduje się kod ładujący bibliotekę ScriptForge.
Warto pamiętać, że załadowanie każdej biblioteki LibreOffice z kontenera „Makra i okna dialogowe aplikacji” lub „Moje okna dialogowe i makra” udostępnia ją wszystkim aplikacjom i skryptom, aż do zakończenia sesji LibreOffice. Dlatego procedura ładowania biblioteki jest wykonywana warunkowo, wykona się tylko wtedy, gdy biblioteka nie została już wcześniej załadowana.
Oto ta procedura.
Public oDok as Object, FSO As Object
Public sPlik$, sNazwa$, sFolder$
1. Sub NoweMenu()
2. Dim oMenu as Object
3. With GlobalScope.BasicLibraries
4. If Not .IsLibraryLoaded("ScriptForge") Then .LoadLibrary("ScriptForge")
5. End With
6. oDok = CreateScriptService("Document",ThisComponent)
7. oDok.RemoveMenu("Moje menu")
8. oMenu = oDok.CreateMenu("Moje men~u","Pomoc")
9. With oMenu
10. .AddItem("Wykonaj kopię w arkuszu", Script :=_"vnd.sun.star.script:Standard.Module1.WykonajKopie?language=Basic&location=document",Icon := "cmd/sc_grid.svg")
11. .AddItem("Kopia przez schowek do pliku", Script :="vnd.sun.star.script:Standard.Module1.PrzezSchowek?language=Basic&location=document",Icon := "cmd/sc_save.svg")
12. End With
13. oDok.Dispose()
14. End Sub
Dwa nienumerowane wiersze to deklaracja zmiennych typu Public. Numerowanie dodałem wyłącznie w celu łatwego omówienia poszczególnych fragmentów makra.
Wiersze 3 – 5.
Odpowiadają za załadowanie biblioteki ScriptForge, jeżeli wcześniej nie została już załadowana.
Wiersz 6.
Zmiennej obiektowej oDok (zadeklarowanej jako zmienna Public) zostaje przypisana usługa „Document” „obsługująca” obiekt ThisComponent, czyli aktualnie otwarty skoroszyt.
Wiersz 7.
Na obiekcie oDok zostaje wykonana funkcja (metoda) usunięcia z menu pozycji „Moje menu”. Dlaczego? Przecież żadne menu jeszcze nie powstało... Jest to zabezpieczenie przed sytuacją, kiedy użytkownik wykonałby polecenie „Załaduj ponownie” (co spowodowałoby ponowne uruchomienie procedury), albo spróbowałby ręcznie uruchomić procedurę „NoweMenu”. Te działania utworzyłyby ponownie nowe menu i w aplikacji istniałyby dwie, albo i więcej, pozycji „Moje menu”. Wywołanie funkcji RemoveMenu() na wszelki wypadek najpierw usuwa to menu, a jeśli takiego menu nie ma, instrukcja jest ignorowana nie zgłaszając żadnego błędu.
Wiersz 8.
Zmienna obiektowa oMenu (zadeklarowana w wierszu 2.) staje się obiektem utworzonym przez funkcję CreateMenu() obiektu oDok. Utworzonemu menu zostaje nadana nazwa „Moje menu”. Znak tyldy (~) poprzedzający literę „u” w tej nazwie oznacza, że to ta litera będzie przypisana do skrótu klawiaturowego (Lewy ALT+litera) aktywującego polecenie „Moje menu”. W wyświetlanej w interfejsie nazwie litera ta będzie podkreślona. Drugi parametr tej funkcji określa, przed jaką pozycją w menu głównym ma pojawić się to nowe menu. W metodzie tej niestety pojawia się także błąd. Mianowicie drugi parametr metody, zgodnie z opisem, powinien móc być także liczbą całkowitą, wskazującą, przed którą kolejną pozycją menu głównego ma zostać dodane to nowe menu. Niestety, zastosowanie tej wersji parametru jest sygnalizowane jako błąd, a jest to dość istotna możliwość gdyż pozwala na umieszczenie własnego menu w konkretnym miejscu, niezależnie od języka aplikacji.
Wiersze 9 – 12.
Obiekt oMenu, będący instancją funkcji CreateMenu() zawiera metodę (funkcję) AddItem(), która utworzy nową pozycję na liście menu. Pierwszym argumentem tej metody jest tekst tej pozycji w rozwiniętym menu. Każdy AddItem() tworzy nową pozycję listy. Metoda AddItem() automatycznie wybiera litery do wykorzystania w skrócie klawiaturowym.
Na etapie tworzenia tego modułu, gdy nieznane są jeszcze szczegóły dalszych działań, ten jedyny parametr wystarczy do przetestowania tego, czy menu się pojawia. Po utworzeniu procedur (makr), które mają realizować funkcje poszczególnych pozycji z listy, można uzupełnić tę instrukcję o kolejny parametr, który przypisze makro do wybranej pozycji.
Przy wskazywaniu makra właściwym parametrem jest script:="ścieżka dostępu do makra". Do pozycji menu można także przypisać polecenie pakietu LibreOffice, takie jak np. Copy, Scal komórki, czy inne dostępne. W takim przypadku musi zostać użyty parametr command:="polecenie". Te dwa parametry wykluczają się wzajemnie.
Przy przypisywaniu makra należy parametr podać w następującej postaci:
Parametr „location” może przyjąć wartość „document” wówczas makro pobierane jest z kontenera dokumentu lub „application”, wówczas makro pobierane jest z kontenerów „Moje makra” lub „Makra aplikacji”.
Innym wykorzystanym przeze mnie parametrem jest Icon. Pozwala on dodać do opisu wybraną ikonę, widać je na rys. 1. Parametr zapisywany jest w postaci: Icon:="cmd/nazwa_pliku_ikony".
Jak znaleźć potrzebne ikony? Oprogramowanie LibreOffice dostarczane jest z zestawem motywów, a użytkownik może wybrać ten, który mu najbardziej odpowiada. Każdy motyw ma swój zestaw ikon zapisany w pliku typu zip, którego nazwa zaczyna się od „images_”. Pliki te (w systemie Windows) znajdują się w następującej strukturze folderów zainstalowanego pakietu LibreOffice: \share\config. W każdym skompresowanym pliku znajduje się folder „cmd” i to on zawiera wszystkie pliki ikon. Ikony funkcjonalnie sobie odpowiadające, mają taką samą nazwę pliku w każdym zestawie. Można więc podejrzeć obrazy ikon w dowolnym pliku i wybrać wymaganą nazwę. W rzeczywistości wyświetlona zostanie ikona należąca do aktualnie używanego motywu. Ten parametr można oczywiście zdefiniować wcześniej, jeszcze na etapie wstępnego tworzenia menu, albowiem wartości parametrów, które są poprzedzone nazwą parametru (nazwa:=wartość) można wprowadzać w dowolnej kolejności.
Motyw ustalany jest w ustawieniach LibreOffice.
Rys.4: Umiejscowienie opcji wyboru motywu.
Wiersz 13.
Nowe menu zostało utworzone w związku z czym obiekt oDok zwalania wszystkie zasoby zawłaszczone przez usługę Document.
Utworzenie kopii w arkuszu Ark2.
Makro ma przekopiować odfiltrowane rekordy w wybrane miejsce w arkuszu Ark2 z zachowaniem atrybutów pól (takich jak np. pogrubienie tekstu, zmiana wielkości czcionki lub jej koloru albo tła pola). Procedura nie jest skomplikowana, ale trzeba wykonać dwa działania. Pierwsze, przekopiować odfiltrowane dane, ta funkcja (metoda) kopiuje wartości, atrybuty i formuły. Drugie – ponownie wstawić „czyste” wartości do docelowego obszaru, ta funkcja (metoda), zachowując przypisane atrybuty, wstawi tylko wartości pól. W tej procedurze chciałem pokazać dodatkowe możliwości wykorzystania biblioteki. Uzupełniłem więc tę procedurę o wygenerowanie komunikatu, z ilu wierszy i kolumn składa się obszar odfiltrowanych rekordów oraz komunikatu podającego położenie pierwszej i ostatniej komórki tego obszaru.
1. Sub WykonajKopie()
2. oDok=CreateScriptService("Calc", ThisComponent)
3. sReg=oDok.Region("Wyciąg")
4. lw=oDok.Height(sReg)
5. lk=oDok.Width(sReg)
6. msgBox ("Znaleziony obszar zawiera: " & chr(10) & LiczbyMnogie(lw,"wiersz","","e","y") & chr(10) & "i " & LiczbyMnogie(lk,"kolumn", "ę","y",""),64, "Znaleziony obszar")
7. msgBox ("Pierwsza komórka w tym obszarze to: " & oDok.FirstCell(sReg) & chr(10) & " a ostatnia to: " & oDok.LastCell("Ark1"),64, "Adres obszaru")
8. oDok.ClearAll("Ark2.*")
9. oDok.CopyToCell(sReg,"Ark2.B5")
10. arrTab=oDok.getValue(sReg)
11. sReg=oDok.Region("Ark2.B5")
12. oDok.setValue(sReg,arrTab)
13. oDok.Dispose()
14. End Sub
Wiersz 2.
Zmiennej obiektowej oDok tym razem przypisana zostaje usługa „Calc”, związana z bieżącym dokumentem (ThisComponent).
Wiersz 3.
oDok, będący instancją usługi „Calc” ma właściwość o nazwie Region(). Parametrem tej właściwości jest dowolnie wskazana komórka w arkuszu. Region() wyznacza adres obszaru, który otacza wskazaną komórkę granicami pustych wierszy i kolumn.
Przykład, jak taki adres jest wyznaczany, przedstawia rys. 5. Rys. 5: Wyznaczanie obszaru właściwością „Region”. W tym przykładzie komórka, względem której zostanie wyznaczony adres obszaru, to ta wyróżniona na ilustracji (F16). Granice obszaru wyznaczają puste kolumny i wiersze, do których można dotrzeć, przemieszczając się wyłącznie poprzez komórki wypełnione. W przypadku tej ilustracji adres obszaru wyglądałby tak: „Arkusz.$D$6:$J$21”. W arkuszu kalkulacyjnym można zobaczyć działanie tego mechanizmu, naciskając skrót klawiaturowy CTRL+* (symbol gwiazdki z klawiatury numerycznej!).
W kodzie instrukcji parametrem jest nazwa komórki: „Wyciąg”. Jest to lewy górny róg obszaru zajętego przez odfiltrowane rekordy. Właściwość Region() wyznaczy zatem prostokątny obszar w którym znajdzie się ostatni wiersz i ostatnia kolumna odfiltrowanych rekordów. Użycie tej instrukcji jest zasadne, bo proces filtrowania tworzy obszar odfiltrowanych rekordów zależny od parametrów filtrowania, więc z góry nie można określić, ile rekordów spełni warunki, czyli jak duży będzie obszar wynikowy.
Adres tego obszaru jest przekazywany do zmiennej tekstowej sReg.
Wiersze 4 – 7.
Te instrukcje nie są potrzebne do wykonania kopiowania. Wstawiłem je, aby pokazać przydatne właściwości usługi. I tak w wierszu 4. do zmiennej lw wstawiana jest liczba wierszy znajdujących się w wyznaczonym obszarze, a w wierszu 5. do zmiennej lk – liczba kolumn. Wiersz 6. generuje komunikat, informujący z ilu wierszy i kolumn składa się obszar. Utworzyłem w tym celu dodatkową funkcję, której zadaniem jest przedstawienie wynikowej liczby z właściwym dla naszego języka dopełnieniem, a więc odpowiednio: 1 wiersz, 2 wiersze, 5 wierszy i analogicznie dla kolumn. Samą funkcję opisałem poniżej.
W wierszu 7. wykorzystałem kolejną właściwość usługi pozwalającą na uzyskanie adresu komórki początkowej i końcowej zadanego obszaru.
Wiersz 8.
Została tu wykorzystana metoda ClearAll(), która czyści zadany obszar arkusza. Parametr w postaci „Ark2.*” oznacza, że mają zostać wyczyszczone wszystkie komórki w arkuszu Ark2, w ten sposób tworzone jest puste miejsce, na nowe dane, bez analizowania tego co należałoby wyczyścić.
Wiersz 9.
Metoda CopyToCell() kopiuje obszar wskazany przez pierwszy argument do miejsca, którego położenie definiuje adres komórki, podany w drugim argumencie. Ta metoda przekopiowuje wszystko, a więc formatowanie i formuły. Gdyby rekordy bazy nie zawierały wewnętrznych formuł, to ta instrukcja kończyłaby procedurę. W tym przypadku należy wykonać dodatkowe działania, takie by wszystkie pola zawierały tylko wartości.
Wiersz 10.
Do zmiennej arrTab reprezentującej tablicę, metoda getValue() przenosi wszystkie wartości znajdujące się w obszarze, który jest jej parametrem. Jest to ciągle obszar w arkuszu Ark1.
Wiersz 11.
Do zmiennej sReg wstawiany jest teraz adres obszaru otaczającego komórkę B5 w arkuszu Ark2. Ten obszar to w istocie dopiero co skopiowane dane. Użycie tej instrukcji jest związane z zasadami realizacji instrukcji występującej w następnej linii.
Wiersz 12.
Przy pomocy metody setValue() do obszaru wyznaczonego poprzednią instrukcją, wstawiane są wartości zapisane w zmiennej arrTab. W ten sposób formuły zostają zastąpione wartościami, a istniejące już formatowania pozostają niezmienione. Metoda setValue() wypełnia wskazany obszar zawartością tablicy. Jeśli docelowy obszar jest większy niż tablica, „nadmiarowe” komórki są opróżniane, a gdy obszar jest mniejszy niż tablica, wypełniane są tylko komórki we wskazanym obszarze.
Wiersz 13.
Zasoby zawłaszczone przez usługę „Calc” zostają zwolnione.
Na potrzeby wyświetlanego komunikatu utworzyłem dedykowaną funkcję, która ma zaprezentować liczbę wraz z właściwym dopełnieniem. Ta funkcja nie jest związana z biblioteką ScriptForge, ale na jej przykładzie chciałem zaprezentować pewne możliwości nadawania nazw zmiennym, o których wiele osób nie pamięta, albo nawet nie wie, że są. Utarło się przekonanie, że nazwa zmiennej może składać się wyłącznie z liter alfabetu łacińskiego, cyfr oraz znaku podkreślnika, przy czym pierwszym znakiem nazwy musi być litera albo podkreślnik. W rzeczywistości nazwa może zawierać dowolne znaki i symbole, warunkiem wykorzystania takiej nazwy jest ujęcie jej w nawiasy kwadratowe. I taką właśnie nazwę, wykorzystałem w tej funkcji. Funkcja, na podstawie liczby ma utworzyć treść zgodną z zasadami języka polskiego. W naszym języku dopełnienie liczebnika zależy od jego liczności, tak więc np. przy liczności 1 napiszemy: 1 wiersz, przy licznościach między 2 a 4 napiszemy 2, 3 lub 4 – wiersze. Przy licznościach powyżej 4, napiszemy 5, 6 itd. wierszy. Zasada dotycząca liczności 2 – 4 obowiązuje także dla wszystkich liczb, w których pozycja dziesiątków jest inna niż 1 a ostatnimi cyframi są 2, 3 lub 4, czyli dla liczb np. 23, 44 lub 52, ale nie 14.
Napisana funkcja wymaga czterech parametrów: liczby, dla której ma zostać wyznaczone dopełnienie oraz trzech postaci dopełnień. Parametr czwarty w tej funkcji ma nazwę utworzoną z wykorzystaniem litery spoza alfabetu łacińskiego.
Oto ta funkcja:
Function LiczbyMnogie (liczba, jeden, dwa, [pięć]) As String
If Liczba=1 Then
LiczbyMnogie= jeden
ElseIf liczba >1 and liczba <5 Then
LiczbyMnogie= dwa
Elseif liczba mod 100 > 20 and liczba mod 10 > 1 and liczba mod 10 <5 Then
LiczbyMnogie=dwa
Else
LiczbyMnogie= [pięć]
End If
LiczbyMnogie=liczba & " " & LiczbyMnogie
End Function
Procedura zapisania odfiltrowanych rekordów w nowym pliku.
W tej procedurze wykorzystałem inny sposób uzyskania kopii, mianowicie z wykorzystaniem operacji „Kopiuj”, a następnie operacji „Wklej specjalnie” ze wskazaniem, że mają zostać wklejone wyłącznie wartości i formaty. Taką operację można wykonać w arkuszu przy pomocy poleceń arkusza „Edycja → Kopiuj” oraz „Edycja → Wklej specjalnie → Wklej specjalnie → Wartości i formaty”. Oczywiście, że ten sposób mógł być wykorzystany już w poprzedniej procedurze, ale chodziło mi o pokazanie różnych możliwości zawartych w bibliotece ScriptForge.
Ta procedura jest najbardziej złożona, wymaga skopiowania odfiltrowanych danych, utworzenia nowej nazwy dla dokumentu, który tę kopię będzie zawierał, wklejeniu danych oraz zapisaniu dokumentu z przygotowaną nazwą. Te operacje wymagają więcej zasobów biblioteki ScriprForge.
Wiersz 2. i 3.
wystąpił już w procedurze „WykonajKopie”. Wyznacza adres obszaru zawierającego odfiltrowane dane.
Wiersz 4.
Właściwość CurrentSelection aktywuje (zaznacza) w dokumencie obszar, którego adres zawiera zmienna sReg. W ten sposób zostaje przygotowany obszar dla polecenia „Kopiuj”.
Wiersz 5.
Możliwość korzystania z poleceń systemu dostępna jest w usłudze „Document”, dlatego nowej zmiennej obiektowej zostaje przypisana ta właśnie usługa, ona także dotyczy bieżącego dokumentu.
Wiersz 6.
Obiekt oDok2 udostępnia metodę RunCommand(), której argumentem jest nazwa żądanej do wykonania funkcji, w tym przypadku „Copy”. W efekcie, w schowku znajdzie się zawartość zaznaczonego obszaru.
Przy pomocy tej metody można wywołać każde polecenie pakietu. Nazwa funkcji musi być podana w języku angielskim z uwzględnieniem wielkości liter. Jeśli nazwa zostanie uznana za błędną, instrukcja zostanie zignorowana i nie zostanie zgłoszony żaden błąd. Formalnie w interfejsie API nazwa funkcji prezentowana jest z przedrostkiem .uno:, w metodzie RunCommand() można ten przedrostek pomijać. Aby poznać nazwy funkcji, jakie należy wykorzystać w tej metodzie można przejść do okna dialogowego „Narzędzia → Dostosuj… → Klawiatura”. Wskazanie wybranego polecenia w okienku „Funkcja” wyświetli przez chwilę „dymek” podpowiedzi, w którym znajduje się nazwa funkcji. Widać to na poniższej animowanej ilustracji. Rys. 6: Identyfikowanie nazw funkcji przypisanych do polecenia. Efektem wykonania instrukcji z tego wiersza jest skopiowanie zaznaczonego obszaru do schowka systemowego.
Wiersze 7. i 8.
Ponieważ schowek zawiera już wybrany obszar, można zwolnić zasoby obu usług.
Wiersze 9. – 17.
W tym fragmencie utworzona zostanie nazwa pliku, do którego zostanie wklejona zawartość schowka oraz utworzona pełna ścieżka do jego zapisu.
Wiersz 9.
Do zmiennej tekstowej sPlik pobierana jest pełna identyfikacja pliku źródłowego. Zawiera ona ścieżkę dostępu wraz z nazwą bieżącego dokumentu. Ta instrukcja nie jest elementem ScriptForge. Tę informację uzyskamy z właściwości Location obiektu ThisCpmponent.
Wiersz 10.
Do zmiennej FSO przypisywana jest usługa „FileSystem”. Usługa ta pozwala zarządzać plikami i folderami.
Wiersz 11.
Właściwość FileNaming() określa stosowaną notację dotycząca plików i folderów. Przypisana notacja jest obowiązująca do końca sesji LibreOffice. Notacja zakodowana jako „URL” jest niezależna od systemu operacyjnego.
Wiersz 12 i 13.
Do zmiennej tekstowej sNazwa wstawiana jest nazwa dokumentu, bez rozszerzenia. Realizuje to metoda getBaseName(), do zmiennej tekstowej sFolder, metoda getParentFolderName() wstawia ścieżkę folderów prowadzącą do pliku.
Wiersz 14.
Nazwa pliku zostaje uzupełniona o datę i czas bieżący. Data wstawiona jest w postaci „dd.mm.rrrr” natomiast czas w postaci „gg:mm:ss”.
Wiersz 15.
W celu uniknięcia nieporozumień przy interpretacji nazw plików, utworzona nazwa zostanie zmieniona w ten sposób, że wszystkie znaki kropki i dwukropka zostaną zamienione na znak podkreślnika. Do tego celu wykorzystana zostanie metoda ReplaceRegex() usługi „SF_String”. Po załadowaniu biblioteki ScriptForge ta usługa jest zawsze dostępna i nie ma potrzeby aktywowania jej poleceniem CreateScriptService. Metoda ReplaceRegex() jest odpowiednikiem funkcji Regex() w aspekcie zamiany znalezionych ciągów na inną treść.
Wiersz 16.
Zmienna sFolder zawierać będzie pełną ścieżkę dostępu do nowo tworzonego pliku. Metoda BuildPath() tworzy na podstawie zawartości zmiennych sFolder oraz sNazwa właściwy ciąg tekstowy, który należy uzupełnić o rozszerzenie nazwy.
Wiersz 17.
Usługa „FileSystem” zostaje zwolniona.
Wiersz 18.
Deklaracja zmiennej obiektowej ui
Wiersz 19.
Zmiennej ui zostaje przypisana usługa „UI”.
Wiersz 20.
Do zmiennej oDok zostaje przypisany nowo utworzony obiekt programu Calc. Trzeci argument metody CreateDocument() (drugi argument jest pominięty) o wartości True oznacza, że utworzony arkusz ma być ukryty.
Wiersz 21.
Zmiennej Otwarte_dokumenty zostanie przypisana wartość właściwości Documents. Będzie to tablica zawierająca nazwy wszystkich dokumentów LibreOffice otwartych w bieżącej sesji.
Tu małe wyjaśnienie, do czego jest to potrzebne. By przypisać jakąś usługę do dokumentu, można w jej drugim parametrze podać nazwę okna, w którym ten dokument się znajduje. Dokument utworzony w wierszu 20., chociaż ukryty, znajduje się w oknie o nazwie „Bez nazwy nr.ods”, gdzie nr to liczba mówiąca o kolejnym nowo utworzonym dokumencie. W uruchomionej sesji LibreOffice może być równocześnie utworzonych więcej dokumentów, utworzonych np. przez Writera, Impres-a lubCalc-a. Wszystkie one mają nazwę rozpoczynająca się od tekstu: „Bez nazwy” z kolejnym numerem dokumentu wyznaczanym w ramach sesji, a nie aplikacji. W tej sytuacji nie możemy być pewni, że utworzony przez nas w wierszu 20. dokument znajduje się w oknie „Bez nazwy 1.ods”. To dlatego pobieramy tablicę nazw wszystkich dokumentów. Tablica reprezentuje stos dokumentów, w którym na pierwszej pozycji znajduje się nazwa okna ostatniego otwieranego lub utworzonego dokumentu.
Wiersz 22.
Zmiennej obiektowej oDok2 przypisuję usługę „Calc”, dotyczącą ostatnio otwartego dokumentu, stąd indeks zerowy tej tablicy.
Wiersz 23.
Można zwolnić usługę „UI”.
Wiersz 24.
Do komórki A1 tego nowego dokumentu wstawiam tekst.
Wiersz 25.
Aktywuję komórkę B4 w dokumencie.
Wiersz 26.
Do zmiennej obiektowej oDok przypisują usługę „Documents” powiązaną z nowo otwartym dokumentem, tym samym, który jest już powiązany ze zmienną oDok2. Robię to, gdyż następne polecenie wykorzysta metodę dostępną tylko w tej usłudze.
Wiersz 27.
W schowku systemowym cały czas znajduje się skopiowany obszar odfiltrowanych rekordów. Wykorzystując metodę RunCommand() wklejam zawartość schowka. Zostanie ona wstawiona, poczynając od aktywowanej komórki B4. Wykorzystuję polecenie „InsertContents” z podanymi parametrami. Odpowiada ono wykonaniu działania „Wklej specjalnie wartości i formaty”. Pojawia się pytanie, skąd wziąć potrzebne parametry? Przebijanie się przez dokumentację jest niezwykle skomplikowane, najprościej jest zarejestrować tę czynność jako makro i w jego kodzie odnaleźć wymagane parametry. Odpowiedni zarejestrowany fragment kodu wygląda tak: Rys. 7: Kod nagranej sekwencji „Wklej specjalnie wartości i formaty”. Widać tu nazwę każdego parametru i wymaganą wartość.
Proszę zwrócić uwagę na to, że w metodzie RunCommand() należy podać zawsze pary: nazwa parametru → wartość. Kolejność tych par nie ma natomiast znaczenia.
Wiersz 28.
Na zmiennej oDok2, czyli nowym dokumencie, wykonana zostanie metoda Save(), której parametrami jest pełna ścieżka dostępu do pliku oraz parametr o wartości „True”, oznaczający, że plik może nadpisać istniejący już plik o takiej samej nazwie.
Wiersze 29 i 30.
To sekwencja zamykająca dokument. Ponieważ dokument jest ukryty, to aby go zamknąć, trzeba go najpierw aktywować.
Wiersze 31. i 32.
Następuje zwolnienie obu usług.
Podany obok link do pliku pozwala pobrać skoroszyt zawierający omówiony projekt
SF.ods
Jeżeli chcecie Państwo pobrać plik, pamiętacie, że za taką możliwość odpowiada kliknięcie odnośnika (łącza) prawym przyciskiem myszki i wybranie z wyświetlonego menu pozycji w rodzaju „Zapisz element docelowy jako...” lub „Zapisz link jako...”. Kliknięcie lewym przyciskiem może spowodować inne działania niż pobieranie, gdyż przeglądarka może próbować bezpośredniego odczytania pliku. W szczególności, większość przeglądarek ma obecnie włączoną możliwość bezpośredniego odczytywania plików PDF.
Przedstawione rozwiązanie to tylko niewielka demonstracja możliwości wykorzystania biblioteki ScriptForge. Czytelnik zainteresowany tym tematem powinien zapoznać się z opisem tej biblioteki. Jak już napisałem na wstępie system pomocy szczegółowo omawia każdą z usług.