Ač je databáze v Lotus Notes dokumentová a vývoj nám umožňuje poměrně solidní práci s formuláři a pohledy, zhusta potřebujeme pracovat s daty takovým způsobem, který se z hlubin Lotus Notes doluje velmi nesnadno. Spoustu operací provedete v nějakém kancelářském balíku lépe a rychleji. Není tedy od věci, mít možnost rychle vyexpedovat data ven, popř. je naopak importovat do databáze.
Kancelářské balíky, které stojí za úvahu, máme v současnosti na trhu v podstatě dva. V tomto článku popíšu zásadní body vývoje wrapperu pro ten druhý – OpenOffice.org. Použijeme OLE/COM model, takže hned zapomeňte na linuxové či macovské klienty.
Zaměřím se na záseky, best practice, problémy, které jinde než v Lotus Scriptu nenajdete atd.
Základem všeho je služba
Open Office API je striktně typové a konvenční. Základní strukturou jsou services, neboli služby, které se volají při otevírání dokumentu. Jednoduše řečeno, o vše se stará nějaká služba. Pro inicializaci služeb potřebujeme třídu ServiceManager. Instanci této třídy zavoláme takto:
CreateObject je univerzální funkce, která inicializuje OLE objekt s danou signaturou. Aplikace s volaným API musí být vždy na daném počítači nainstalována. V případě, že tento OLE objekt není nalezen, vrátí funkce chybu číslo 208 – Cannot create automation object. Poté, co zavoláme tuto funkci, máme v proměnné SM ServiceManager, který sám o sobě neznamená nic, ale umožní nám volat potřebné služby pro práci s dokumenty OpenOffice.
Základem všeho ostatního je dokument
Základem práce s kancelářským balíkem je dokument. Pro práci s dokumentem je OOo potřeba iniciovat několik služeb.
Jak je vidět, těch služeb je celá řada, ale naštěstí to není tak komplikované, jak to na první pohled vypadá. Postačí zavolat službu Desktop a ta se postará o zbytek.
O inicializaci dokumentu se stará třída com.sun.star.frame.Desktop, která implementuje rozhraní com.sun.star.frame.XComponentLoader, jednou jedinou metodou. Open Office API nerozlišuje otevírání stávajícího dokumentu od vytváření nového dokumentu jinak než parametrem této metody.
Parametr URL je string, který určuje buď cestu k dokumentu, anebo typ nového dokumentu. Další dva parametry (název okna a příznak pro typ vyhledávání) není potřeba příliš řešit, v drtivé většině případů stačí zadat „_blank“ a 0. Poslední parametr je sada argumentů, které určují chování a vzhled otevíraného dokumentu. Je to pole objektů typu com.sun.star.beans.PropertyValue, kterým se jednotlivé parametry předávají formou vlastností Name a Value. Těch parametrů je celá řada a zhusta není potřeba je vůbec využívat. Pro takový případ postačí poslat do tohoto parametru prázdné pole. Ovšem občas tyto argumenty budeme potřebovat a tudíž si musíme umět vytvořit objekt PropertyValue. Budeme k tomu potřebovat objekt typu CoreReflection pro inicializaci vnitřních struktur, na které nevedou přímé reference. K tomuto účelu si zavedeme jednoduchou funkci CreateStruct.
Dále si pomocí této funkce vytvoříme instanci třídy PropertyValue, do které nasázíme potřebné parametry startu dokumentu.
Jak je vidět, nemít Variant, byl by Lotus script ztracený
Vytvořit nový, nebo otevřít stávající? Vše v jednom
A teď si můžeme ukázat jednoduchou funkci pro vytvoření nového dokumentu OpenOffice Calc, který otevřeme skrytý.
Jak jsem řekl, rozdíl mezi otevíráním a vytvářením dokumentu je pouze v parametru URL. Funkce pro otevření dokumentu je tedy velmi podobná jako funkce pro vytvoření nového. Abych to nekomplikoval, předpokládejme, že opět chceme dokument otevřít skrytě.
Jak jste si všimli, prohnal jsem zadanou cestu jakousi záhadnou funkcí ConvertToURL. API Open Office je totiž velmi citlivé na zadané cesty, nesnese některé znaky, potřebuje speciální prefix a co je hlavní, zásadně neuznává zpětné lomítko, neboli backslash, čemuž naprosto rozumím . A protože každá cesta na OS Windows je tvořena zpětnými lomítky, je potřeba zadanou cestu upravit.
Jak vidíte, práce s API Open Office má svou logiku. Vše je zde čistě objektové. Na závěr prvního dílu vytvoříme bázovou třídu, která bude mít za úkol obsluhovat základní operace s dokumenty Open Office.
Co všechno budeme do hrnečku potřebovat?
Popsali jsme si základní mechanismy vytváření a otevírání dokumentů. Popsali jsme si práci se službami a strukturami. Zbývá určit si operace, které budeme po našem objektu požadovat.
Bude to bázová třída, chceme tedy pouze jednoduché operace Open, Create, Save, SaveAs, Close. Také by se hodil Print, i když to už je trochu za hranicí základních operačních primitiv. Určitě chceme umět nastavit viditelnost dokumentu. Pak možná nějaké drobnosti jako SelectAll, CopyToClipboard, Paste apod., abychom si ukázali jak na to.
OpenDocument a CreateDocument jsem již nastínil, zaměřím se tedy rovnou na Save a SaveAs. To je v Lotus Scriptu trochu tricky záležitost. Nebo alespoň bývala ve verzi 8.0 – na 8.5.x jsem netestoval.
O co jde? Jde o to, že uložení dokumentu bez udání cesty – tedy klasický Save, nikoliv SaveAs – se volá document.store(). Ten však v LS z neznámého důvodu nefunguje. Je potřeba tedy volat SaveAs a zadat cestu. Cestu si musíme pamatovat v globální proměnné třídy. V případě, že jde o nový dokument, zachováme se správně a neuděláme nic .
Všimněte si vlastnosti dokumentu hasLocation(). Ta vrací true/false, zda jde o existující dokument, nebo jestli pracujeme s novým. PropertyValue jsme si již představili, já jen k názvu funkce přidal OO, abych rozlišil pomocné metody. A jinak se samozřejmě SaveAs v OpenOffice nejmenuje SaveAs, ale StoreAsURL. Jak jinak, že?
Dále stojí za povšimnutí metoda, jak se sestavuje prázdné pole argumentů. V Lotus Scriptu neexistuje klasický null, je tedy potřeba vytvořit inicializované pole s jednou hodnotou, která je prázdná.
Jak takový otevřený dokument zavřeme? Jednoduše.
A co ten tisk? Není nic jednoduššího.
Visibility, neboli viditelnost dokumentu. Tedy atribut, zda je při práci ten dokument vidět nebo ne. Ptáte se nač to? Pro pochopení problematiky je potřeba vědět, co se stane, když uživatel spustí akci, která pomocí OLE zobrazí třeba OpenOffice Calc a začne do něj cpát data. Ten skript běží třeba 20 sekund, uživatel nevydrží a začne do toho dokumentu chudákovi skriptovi hamtat kurzorem. Začne prostě s tím dokumentem pracovat, aniž by počkal, než export doběhne. V tu ránu celá operace spadne a skript uraženě zahlásí OLE Automation object error. Proto je lepší provést operaci na pozadí a zobrazit uživateli dokument až nakonec. Mezitím mu můžete přehrát nějakou animaci, třeba s pomocí klasického NEMProgressBaru.
Pro volání operací jako je SelectAll, Copy, Cut, nebo Paste je potřeba vytvořit instanci dispatcheru – tedy čas na další OO helper.
URL je v tomto případě opět nějaký příkaz, který má dispatcher nad dokumentem vykonat a vykonává je nad framem, což není nic jiného, než viewport našeho dokumentu.
Zavolat zmíněné oparece je pak už triviální.
No a to by pro dnešek bylo vše. Příště bychom si mohli popsat pokročilejší operace, konstanty, které OpenOffice používá a zkusit postavit nějaký sofistikovanější framework pro exporty a importy dat.
Na závěr přidám na ukázku celou bázovou třídu OpenOfficeBase. Enjoy.
Komentování je uzavřeno.