hlavicka.png, 18 kB

obsah


Calc - Seriál o objektech v makrech

02. StarDesktop

Na vrcholu objektového modelu OpenOffice.org stojí pracovní plocha (StarDesktop). Z pracovní plochy máme přístup k oknům (Frames) a dokumentům (Components). Pro své potřeby jsem si vytvořil zjednodušené schéma, podle kterého se orientuji při procházení jednotlivými objekty. Zdůrazňuji, opravdu se jedná o zjednodušení, nejsou zde obsaženy všechny poskytované vlastnosti, metody a rozhraní, a už vůbec to není oficiální schéma.

desktopm.jpg, 8 kB

Objekt StarDesktop lze definovat takto:

dim oManager as object, oDesk as object
Set oManager = CreateObject("com.sun.star.ServiceManager")
Set oDesk = oManager.createInstance("com.sun.star.frame.Desktop")
nebo
dim oManager as object, oDesk as object
oManager = GetProcessServiceManager()
oDesk = oManager.createInstance("com.sun.star.frame.Desktop")

Nebudu se zabývat vysvětlováním předchozích kódů, nebudeme to potřebovat, Pouze podotknu, že tyto syntaxe jsou důležité pro programatory jiných jazyků než StarBasic(např. při automatizaci z Visual Basicu). Jak uvidíme dále ve StarBasicu existují různé cesty k dosažení stejného cíle. Tak např. tady můžeme použit UNO Services:

dim oDesk as object
oDesk = CreateUnoService("com.sun.star.frame.Desktop")
nebo lépe použijeme přímo zkratku StarBasicu

dim oDesk as object
oDesk = StarDesktop
Ve StarBasicu budu používat právě tuto poslední možnost.

StarDesktop mimo jiné obsahuje dvě kolekce. Kolekci oken - Frames a kolekci dokumentů - Components. Kolekce Frames je úplná kolekce, můžeme do kolekce přidávat nebo odebírat prvky, a poskytuje vlastnost Count. Ukážeme si procházení okny.

sub ProjdiOkna
dim oDesk as object, oFrames as object, oFrame as object
dim i as integer
  set oDesk = StarDesktop
  set oFrames = oDesk.Frames
  for i=0 to oFrames.Count - 1
    set oFrame = oFrames.getByIndex(i)
    msgbox oFrame.Title 
  next i
end sub
Řádek s
  set oFrame = oFrames.getByIndex(i)
lze zapsat i takto:
  set oFrame = oFrames(i)
getByIndex lze vynechat. Funguje to i v jiných kolekcích.

Kolekce Components neposkytuje metody pro přidání či odebrání prvku, ani vlastnost Count. Pro takovéto kolekce si musíme vytvořit enumerační objekt a pomoci něj pak můžeme procházet jednotlivé prvky kolekce. Dost často se setkávám s následujícím kódem:

sub ProjdiKomponenty
dim oDesk as object, eComponents as object, oDoc as object
  set oDesk = StarDesktop
  set eComponents = oDesk.Components.CreateEnumeration
  do while eComponents.hasMoreElements
    oDoc = eComponents.NextElement
    msgbox oDoc.ImplementationName
  loop
end sub

Nejprve je vytvořen enumerační objekt eComponents. V podmínce smyčky do...loop zjišťujeme pomoci .hasMoreElements zda ještě jsou nějaké prvky kolekce k dispozici a pokud jsou přiřadíme pomocí NextElement další prvek kolekce do objektové proměnné oDoc, jinak smyčka končí. Tento postup procházení kolekcí si zapamatujte bude se vám v mnoha případech hodit.

Toto bude fungovat, jen pokud nebude spuštěna nápověda. Tá totiž obsahuje dvě komponenty, a jedná z nich nepodporuje většinu vlastností. Můj kód proto obsahuje obsluhu chyby, jednoduše přeskočíme takovou komponentu a pokračujeme dál, pokud by byla taková komponenta zobrazena:

sub ProjdiKomponenty
dim eComponents as object, oDoc as object
  set eComponents = StarDesktop.Components.CreateEnumeration
' Jedna z komponent Nápovědy nepodporuje ImplementationName
' proto obslouzime pripadnou chybu
  on error goto DALSI
  do while eComponents.hasMoreElements
    oDoc = eComponents.NextElement
    msgbox oDoc.ImplementationName
DALSI:
  loop
end sub

Pokud StarDesktop potřebujete jen pro přiřazení do jednoho objektu můžete si objektovou proměnnou oDesk ušetřit.

Pokud chcete přiřadit do objektové proměnné aktuální okno, nemusíte procházet celou kolekci.

  dim oFrame as object
  set oFrame = StarDesktop.ActiveFrame
nebo
  set oFrame = StarDesktop.CurrentFrame

Zde si musíme vysvětlit některé pojmy. ActiveFrame a CurrentFrame jsou tzv. pseudo-vlastností StarBasicu. Některé objekty používají metody s předponou get, některé s předponou set a některé s oběma předponami. Metody začínající na get pouze něco vrací, většinou jiný nebo podřízený objekt. Metody začínající na set většinou něco s objektem provádějí. StarBasic zavádí někdy určitá zjednodušení tím, že poskytuje pseudo-vlastnost složenou s metod objektů.
Objekt StarDesktop poskytuje mimo jiné metody getCurrentFrame(), getActiveFrame() a setActiveFrame(Frame). StarBasic na tomto základě poskytuje pseudo-vlastnost CurrentFrame jen pro čtení a pseudo-vlastnost ActiveFrame pro čtení i zápis. StarBasic neposkytuje pseudo-vlastnosti pro veškeré metody get či set. Obecně, pokud StarBasic poskytuje pseudo-vlastnost jen pro čtení existuje pouze metoda se stejným názvem a předponou get. Pokud SB poskytuje pseudo-vlastnost jen pro zápis existuje pouze metoda se stejným názvem a předponou set. Když SB poskytuje pseudo-vlastnost pro zápis i čtení, existují obě metody jak get, tak i set. Nelze ovšem říct, že ke všem metodám s get a set existuje eqivalentní pseudo-vlastností SB.
Pokud používáme StarBasic může být používání pseudo-vlastností výhodou. Pokud ale používáte pro skriptování OOo jiný jazyk musíte používat jen metody z objektového modelu.

Jak to vypadá v praxi. Vlastností objektů můžeme 'přirovnat' k proměnným programovacích jazyků a metody objektů pak k proceduram či funkcím.

' pseudo-vlastnost StarBasicu
  set oFrame = StarDesktop.ActiveFrame
' metoda objektoveho modelu
  set oFrame = StarDesktop.getActiveFrame()

' pseudo-vlastnost StarBasicu
  StarDesktop.ActiveFrame = oFrame
' metoda objektoveho modelu
  StarDesktop.setActiveFrame(oFrame)

' pseudo-vlastnost StarBasicu
  set oFrame = StarDesktop.CurrentFrame
' metoda objektoveho modelu
  set oFrame = StarDesktop.getCurrentFrame()

Zatím co getCurrenFrame je metoda objektu StarDesktop, a proto vrací jen okna pracovní plochy, tak getActiveFrame a setActiveFrame jsou součástí interface:
com.sun.star.frame.XFramesSupplier, mohou být použity i na jiné objekty a mohou pracovat i s dětskými okny, nejen s hlavními okny pracovní plochy.

Podobně u dokumentů můžeme použit pro aktuální dokument:

  dim oDoc as object
  set oDoc = StarDesktop.getCurrentComponent()
a pro tento dokument:
  set oDoc = ThisComponent
Zde jsou také podstatné rozdíly.
  1. getCurrentComponent() je metodou objektu StarDesktop, zatím co ThisComponent je zkratkou Star Basicu, proto ji píšeme přímo.

  2. Pokud je ThisComponent použit v modulu dokumentu, vrací vždy příslušný dokument. getCurrentComponent() vrací vždy aktívní dokument.

  3. Pokud je ThisComponent uložen v modulu OpenOffice.org, vrací vždy dokument, který byl aktivní v době spuštění kódu, i když se v průběhu trvání kódu aktívním dokumentem stane jiný dokument. getCurrentComponent() vždy vrací právě aktívní dokument.

  4. Pokud je ale makro spuštěno z IDE Basicu, nevrací ThisComponent při prvním volání na rozdíl od getCurrentComponent() dokument Basicu, ale naposledy aktívní dokument OOo. Po změně aktivního dokumentu pak kopíruje getCurrentComponent().

Na toto chování je nutno si dát velmi dobrý pozor, zvláště pokud máte rozdílné výsledky při spuštění makra s IDE Basicu a při spuštění třeba formulářovým tlačítkem.
pro getCurrentComponent rovněž existuje pseudo-vlastnost SB CurrentComponent pouze pro čtení

StarDesktop poskytuje dále metodu LoadComponentFromURL. Táto metoda otevře nebo založí nový dokument. Syntaxe:

oDoc = StarDesktop.loadComponentFromURL(URL, _
                               Frame, SearchFlags, FileProperties)
kde:
oDoc
je objektová proměnná pro nový dokument
URL
je řetězec, obsahující adresu dokumentu. URL ještě blíže osvětlím
Frame
je okno ve kterém bude dokument otevřen
SearchFlags
je konstanta typu long ze seznamu
com.sun.star.frame.FrameSearchFlag
FileProperties
je strukturované pole s dalšími parametry dokumentu

URL(Uniform Resource Locator) je vlastně univerzální adresa použiváná v sítí internet. Adresovat můžeme soubory, elekronickou poštu, servery a obecně různá zařízení jako třeba tiskárny atd.
Tvar adresy může vypadat třeba takto:

protokol://server:port/cesta/dokument#značka.
V URL jsou některé znaky zakázané, ty se potom nahrazují znakem '%' nasledovaném hexadecimálním vyjádřením nepovoleného znaku. V objektovém modelu OOo se přednostně používá URL. Protože v mnoha případech budeme potřebovat systémovou cestu k souborům, StarBasic zavádí dvě konverzní funkce :
ConvertToURL(Path as string)
- převede cestu k souboru do tvaru URL
ConvertFromURL(URL)
- převede URL na cestu k souboru
Obě funkce vracejí řetězec. Cesta k souboru (Path) by měla být automaticky ve tvaru jaký používá operační systém ve kterém je OOo spuštěno. Pokud tedy znáte cestu k souboru použijete:
sURL = ConvertToURL("Cesta k souboru")

Frame úzce spolupracuje se SearchFlags. Tyto parametry by měly umožnit otevírání dokumentu v definovaném okně apod. Přiznám se, že se mi to nepovedlo rozchodit, a tak otevírám dokumenty vždy v novém okně. Mám podezření, že je to dědictví ze StarOffice, ale neimplementované do OpenOffice.
Parametry tedy nstavuji takto: Frame = " " a SearchFlags = 0.

FileProperties určuje další vlastnosti dokumentu. Je to strukturované pole typu com.sun.star.beans.PropertyValue, kde jednotlivé položky mohou být tyto:

AsTemplate (Boolean)
– při true vytvoří nový dokument na základě dokumentu v URL, při false otevře přímo dokument z URL k úpravám
CharacterSet (String)
– definuje výchozí znakovou sadu pro dokument
FilterName (String)
– specifikuje souborový filtr pro metodu loadComponentFromURL. Název filtru musí odpovídat některému filtru ze souboru \share\config\registry\instance\org\openoffice\office \TypeDetection.xml
FilterOptions (String)
– definuje rozšiřující vlastnosti filtru
JumpMark (String)
– definuje značku na kterou skočí cursor ihned po otevření souboru
Password (String)
– heslo pro uzamčené dokumenty
ReadOnly (Boolean)
– při true otevře dokument jen pro čtení
příklad na otevření dokumentu, cesty k dokumentům si upravte dle sebe
sub OtevriSoubor
dim sURL as string, oDoc as object
' pro Windows
  sURL = ConvertToURL("C:\WINDOWS\Plocha\testy1.ods")
' pro Linux
'  sURL = ConvertToURL("/home/graf/testy1.ods")
  set oDoc = StarDesktop.loadComponentFromURL(sURL, " ", 0, Array())
end sub
Na místě FileProperties jsem použil příkaz StarBasicu, Array() pro vytvoření prázdného pole.

příklad na vytvoření nového dokumentu na základě šablony

sub OtevriSoubor
dim sURL as string
  sURL = ConvertToURL("C:\WINDOWS\Plocha\testy1.ods")
dim Args(0) as new com.sun.star.beans.PropertyValue
  Args(0).Name = "AsTemplate"
  Args(0).Value = true
dim oDoc as object
  set oDoc = StarDesktop.loadComponentFromURL(sURL, " ", 0, Args())
end sub

Na první pohled to může vypadat, že otevíráme stejný dokument. Ale pokud tento kód spustíte, zjistíte, že v titulku okna není název dokumentu, ale např. toto: 'Bez názvu1 - OpenOffice.org Calc'. Takže jsme vlastně vytvořili nový dokument na základě jiného dokumentu (šablony).

Příklad pro otevření zaheslovaného dokumentu jen pro čtení, sešit testy2.ods byl uložen s heslem 'heslo'

sub OtevriSoubor
dim sURL as string, oDoc as object
dim Args(1) as new com.sun.star.beans.PropertyValue
  sURL = ConvertToURL("C:\WINDOWS\Plocha\testy2.ods")
  Args(0).Name = "Password": Args(0).Value = "heslo"
  Args(1).Name = "ReadOnly": Args(1).Value = true
  set oDoc = StarDesktop.loadComponentFromURL(sURL, " ", 0, Args())
end sub

Z posledních dvou ukázek by vám mělo být jasné jak se pracuje se strukturovanými poli (structures). V podstatě použijeme dimenzi pole jen tak velkou, kolik vlastnosti chceme použit. Je jedno v jakém pořadí vlastnosti do pole uložíme, protože vlastnosti jsou ve struktuře pojmenovány.

Zbývá nám ještě vytvoření prázdného dokumentu. K tomu se používá speciální určení v URL - private:factory

sub VytvorSoubor
dim sURL as string, oDoc as object
  sURL = "private:factory/scalc"
  set oDoc = StarDesktop.loadComponentFromURL(sURL, " ", 0, Array())
end sub

Pro dokument Writeru pak private:factory/swriter pro ostatní dokumenty OOo, si jistě dovtípite. Další práci s dokumenty si ukážeme v příštím díle.

Na konec si ještě ukážeme jak se z okna dostat do dokumentu a naopak. Můžete mít odkaz na dokument, a potřebujete změnit nějakou vlastnost okna dokumentu, nebo naopak můžete mít zjištěné okno a potřebujete něco upravit v dokumentu. Takže pokud máme objekt oFrame tak:

  set oDoc = oFrame.Controller.Model
nám vráti dokument. Pokud máme dokument oDoc pak:

  set oFrame = oDoc.CurrentController.Frame
nám vratí příslušné okno.

Ve zkratce Controller představuje vlastně aplikaci ve které je dokument zpracováván. Pro sešit.ods to je Calc.

Na závěr ke StarDesktop se hodí metoda Terminate(). Táto metoda uzavře všechna okna OOo. Pokud je otevřen neuložený dokument, budete dotázaní na jeho uložení. Po vykonání metody terminate je možno vykonávat další příkazy SB, ale nezdá se mi to moc vhodné. Pokud to však spustíte s IDE Basicu zobrazí se oznámení o tom že okno IDE nelze uzavřít v průběhu vykonávání kódu, a po ukončení kódu zustane okno IDE Basicu spuštěno. Vyzkoušejte:

Sub Main
  StarDesktop.Terminate()
  msgbox "Ahoj"
End Sub

Příště se blíže podíváme na StarDesktop.Components for Calc neboli práci se sešity tj. s dokumenty Calcu. A zatím zkoušejte StarDesktop, možná objevíte i jiné užitečné vlastnosti či metody. Zkuste třeba doplnit následující řádek, tak aby jste v oDesk dostali objekt StarDesktop. Přímo jsme si to tu neříkali, ale pokud jste z předchozího pochopili o co jde tak si to z dříve uvedeného obrázku odvodíte:

  set oDesk = ThisComponent.???

Pokud chcete zkoumat objekty, vřele doporučuji XrayTool viz závěr předchozího dílu.


<< Úvod | Sešity >>

vgraf2@cbox.cz

23.09.2006

stránky

hlavní stránka

Calc