hlavicka.png, 18 kB

obsah


Calc - Seriál o objektech v makrech

03. Sešity

V minulém díle jsme mimo jiné procházeli komponenty ze StarDesktop. Pokud jste si kód vyzkoušeli, při několika otevřených dokumentech, zjistili jste, že vlastnost .ImplementationName nám poskytuje celkem dobrý identifikátor pro odlišení typu dokumentu. Upravíme si tedy tento kód pro procházení pouze otevřených sešitů. V následujícím kódu jsou řádky označeny čísly. Táto čísla nejsou součástí kódu.

01  sub ProjdiSesity
02  dim oDoc as object, eDocs as object
03    set eDocs = StarDesktop.Components.CreateEnumeration
04    on error goto DALSI
05    do while eDocs.hasMoreElements
06      set oDoc = eDocs.NextElement
07      if oDoc.ImplementationName="ScModelObj" then
08        msgbox oDoc.URL & " >> " & _
                 oDoc.CurrentController.Frame.Title
09      end if
10  DALSI:
11    loop
12  end sub
Popis kódu:
01 sub ProjdiSesity
toto je definice procedury - více viz nápověda, jak jsem psal v úvodu k seriálu
02 dim oDoc as object, eDocs as object
toto je deklarace proměnných - více viz nápověda
oDoc - proměnná pro komponentu, protože to je vlastně dokument
eDocs - proměnná pro enumerovanou kolekci všech dokumentů (Components)
03 set eDocs = StarDesktop.Components.CreateEnumeration
nastavíme proměnnou na kolekci (enumerační objekt), příkaz set je nepovinný, používá se pro důraznější odlišení, že se jedná o přiřazení do objektové proměnné, mohli bychom použit klidně i toto:
eDocs = StarDesktop.Components.CreateEnumeration
04 on error goto další
obsluha chyby. Pokud některá komponenta nepodporuje námi použitou vlastnost, pak by došlo k chybě (vyjímce) a kód by skončil s chybovou hláškou. Toto chování nepotřebujeme, tak jednoduše takovou komponentu přeskočíme na návěští DALSI. Můžeme si to dovolit, protože budeme používat vlastnosti, které jsou podporovány sešity a tím máme zajištěno, že žádný sešit nebude přeskočen.
05 do while eDocs.hasMoreElements
Definice cyklu s podmínkou existence dalšího dokumentu v kolekci
06 set oDoc = eDocs.NextElement
V každém průchodu smyčkou nastavíme proměnnou oDoc na další dokument z kolekce
07 if oDoc.ImplementationName="ScModelObj" then
Zde zjistíme zda dokument je sešit "ScModelObj"
08 msgbox oDoc.URL & " >> " &
     oDoc.CurrentController.Frame.Title
pokud je dokument sešitem provedeme s ním akce které jsme měli v úmyslu. V našem případě si pouze zobrazíme URL a titulek okna dokumentu
09 end if
ukončení podmíněného příkazu if
10 DALSI:
label, zde program skočí, pokud se objeví nějaká chyba
11 loop
ukončení těla smyčky, odsud se program bude vracet na řádek 05 tak dlouho, dokud budou k dispozici ještě neprozkoumané dokumenty v kolekci
12 end sub
ukončení procedury

Naše procedura projde postupně všechny otevřené dokumenty a pro sešity zobrazí URL a titulek okna sešitu. Pokud potřebujete pouze cestu k souboru můžete použit v řádku 08 toto:

msgbox ConvertFromURL(oDoc.URL) & " >> " & _
       oDoc.CurrentController.Frame.Title

Pokud již máte nainstalován nástroj X-Ray Tool změňte řádek 08 předchozího makra na :
    xray oDoc
a můžete zkoumat sešity.

Do teď již umíme vytvořit nový sešit, otevřít stávající sešit a procházet otevřené sešity. Takže bychom měli umět sešit uložit a zavřít.
Upravte si cestu k souboru v obou následujících procedurách dle sebe a spusťe UlozNovySesit, pro vytvoření a uložení nového sešitu:

sub UlozNovySesit
dim sURL as string, oDoc as object
  sURL = "private:factory/scalc"
  set oDoc = StarDesktop.loadComponentFromURL(sURL, " ", 0, Array())
  ' zde bychom provedli nejake upravy, kdybychom to uz umeli
  sURL = ConvertToURL("C:\testy2.ods")
  oDoc.StoreAsURL(sURL, Array()) ' ulozit jako
  oDoc.Close(true)
end sub
poté uložený soubor otevřete ručně, proveďte v něm nějaké změny, nezavírejte jej a proveďte následující kód, nezapomeňte i v něm upravit cestu k souboru dle první procedury.
sub UlozSesit
dim sURL as string, oDoc as object, eDocs as object
' vytvor kolekci otevrenych dokumentu
  set eDocs = StarDesktop.Components.CreateEnumeration
  on error goto DALSI
' projdi kolekci dokumentu
  do while eDocs.hasMoreElements
    set oDoc = eDocs.NextElement
  ' pokud je to sesit
    if oDoc.ImplementationName="ScModelObj" then
    ' a je to hledany sesit
      if LCase(ConvertFromURL(oDoc.URL))="c:\testy2.ods" then
        oDoc.Store() ' tak jej uloz
        oDoc.Close(true) ' a zavri
        exit sub ' udelali jsme co jsme chteli, koncime
      end if
    end if
DALSI:
  loop
end sub

Nyní již umíte sešit uložit, uložit jako a zavřít jej. Přesto si neodpustím pár poznámek. Prvním kódem jsme vytvořili prázdný sešit a ihned jsme jej uložili jako a zavřeli. Druhý kód ukazuje uložení existujícího sešitu. V podmínce pro zjištění našeho sešitu jsem použil funkci LCase protože nikdy dopředu nevím, jak mi windows vráti cestu, takže to vždy raději testuji s malými písmeny. Zde to nevadí. Na linuxu by to ovšem mohla být fatální chyba, protože tam je velikost písmen v názvech souborů důležitá(Linuxáci prominou, jistě si cesty upraví dle sebe a vyhodí to LCase).

Abychom věděli zda je sešit nutno ukládat máme k dispozici jednu vlastnost pouze pro zápis 'Modified' a dvě metody 'IsModified' a 'SetModified'.

  oDoc.Modified = true
  oDoc.SetModified(true)
  promenna = oDoc.IsModified

Vlastnost Modified je vlastně pseudo-vlastnost založená na metodě SetModified, z tohoto důvodu je pouze pro zápis. Pomocí obou tedy můžeme nastavit, zda byl sešit změněn, či nikoli. Metoda IsModified nám pak vrací logickou hodnotu o tom zda byl sešit změněn.

Další metodou, kterou využijeme při ukládání sešitu je HasLocation.

  promenná = oDoc.HasLocation
Metoda vrací true, pokud sešit již byl uložen. Pokud se jedná o nový, ještě neuložený sešit, metoda vráti false.

Další metodou vztahující se k ukládání dokumentu je IsReadOnly.

  promenná = oDoc.IsReadOnly
Metoda vrací true, pokud je sešit určen pouze pro čtení.

Úsek kódu pro ukládání dokumentu, by pak mohl vypadat takto:

  with oDoc
    if (.isModified) then ' sesit byl zmenen
    ' pokud jeste nebyl ulozen, nebo je jen pro cteni
      if (not .hasLocation) and .isReadOnly then
        .storeAsURL(sURL, Array()) ' ulozit jako
      else
        .store() ' ulozit
      end if
    end if
  end with

Kód je myslím jasný, zastavím se na chvílí u příkazu SB with. Tento příkaz vytvoří skrytou objektovou proměnnou, která se stane výchozí. V celém bloku mezi příkazy with a end with, pak nemusíme vypisovat pokaždé objektovou proměnnou. Vlastností a metody, které chceme na tomto objektu použít, musímu uvozovat tečkou. Příkazy with mohou být vnořené.

V rychlosti si ještě probereme několik vlastností a metod sešitů:

CharLocale
řetězcová vlastnost pro čtení i zápis, určuje výchozí znakovou sadu pro dokument
promenna = oDoc.CharLocale
IgnoreCase
logická vlastnost pro čtení i zápis, určuje zda se bude v dokumentu brát ohled na velikost písmen
noDoc.IgnoreCase = true
RegularExpression
logická vlastnost pro čtení i zápis, určuje zda se ve vzorcích sešitu mohou používat regulární výrazy
promenna = oDoc.RegularExpression
Protect
metoda pro zamknutí dokumentu
oDoc.Protect("heslo")
Unprotect
metoda pro odemknutí dokumentu
oDoc.Unprotect("heslo")
IsProtected
metoda vrácí true, pokud je dokument zamknut.
promenna = oDoc.IsProtected()

Sešity a obecně dokumenty mají ještě další vlastností a metody, dají se na ně použit i rozhraní, služby a událostí. O tom si povíme určitě v některých dalších dílech. Nyní však musíme spěchat abychom se dostali k buňkám, a to máme před sebou ještě listy. Nicméně ještě si něco povíme o tisku.

K tomu zde najdeme vlastnost Printer a metodu Print. Vlastnost Printer vráti strukturované pole typu com.sun.star.beans.PropertyValue, pomocí nějž lze nastavovat, nebo číst některé vlastností tiskárny. Položky struktury:

Name
Název tiskárny, dle OS
PaperOrientation
vrací, nebo umožní nastavit orientaci papíru. Možnostmi jsou konstanty com.sun.star.view.PaperOrientation.PORTRAIT nebo com.sun.star.view.PaperOrientation.LANDSCAPE
PaperFormat
vrací, nebo nastavuje formát papíru. Možnostmi jsou konstanty z com.sun.star.view.PaperFormat.USER
PaperSize
vrací, nebo nastavuje velikost papíru, pokud byla nastavena konstanta pro uživatelský formát v PaperFormat. PaperSize je struktura typu com.sun.star.awt.Size s položkami Width(šířka) a Height(výška). (Rozměry se zadávají v setinách milimetru [100ths of a millimeter.])
IsBusy
jen pro čtení, boolean. Říká zda tiskárna tiskne
CanSetPaperOrientation
jen pro čtení, boolean. Říká zda je možno změnit orientaci papíru
CanSetPaperFormat
jen pro čtení, boolean. Říká zda je možno změnit formát papíru
CanSetPaperSize
jen pro čtení, boolean. Říká zda je možno změnit rozměry papíru
sub CtiPrinter
dim oDoc as object, sMsg as string
  set oDoc = ThisComponent
  on error resume next
  for i=0 to 7
    sMsg = i &": " & oDoc.Printer(i).Name & " -> " 
    sMsg = sMsg & oDoc.Printer(i).Value
    msgbox sMsg
  next i
end sub
Některé vlastností nemusí být nastaveny, proto jsem použil obsluhu chyby.

Metoda Print vytiskne dokument. Nejjednoduchší tisk provedete takto:

oDoc.Print(Array())
Tím vytisknete dokument s defaultními hodnotami, jako by jste klikli na ikonku tisk. Metoda Print jako argument vyžaduje strukturu typu com.sun.star.beans.PropertyValue, Jak ale vidíte pro defaultní tisk stačí prázdné pole.

Položky pro strukturu:
Pages
definuje stránky, ktere se budou tisknout.Lze definovat rozsah pomocí pomlčky a jednotlivé stránky oddělujeme středníky.
FileName
název souboru, pokud chceme tisknout do souboru
CopyCount
počet kopií
Sort
logická, true udává, že se budou stránky třídit. Toto má smysl při dvou a více kopiích.

Dejme tomu, že chceme vytisknout stránky 1, 2, 3 a 5. Že je chceme tisknout na šířku a budeme tisknout na tiskárnu Epson LQ-550, která není výchozí.

sub tiskni
' nastaveni tiskarny
dim argPrinter(1) as new com.sun.star.beans.PropertyValue
  argPrinter(0).Name = "Name"
  argPrinter(0).Value = "Epson LQ-550"
  argPrinter(1).Name = "PaperOrientation"
  argPrinter(1).Value = com.sun.star.view.PaperOrientation.LANDSCAPE
  ThisComponent.Printer = argPrinter()
' nastaveni stranky
dim argPrint(0) as new com.sun.star.beans.PropertyValue
  argPrint(0).Name = "Pages": argPrint(0).Value = "1-3;5"
' a tiskneme
  ThisComponent.Print(argPrint())
end sub

Samozřejmě, že název tiskárny můžete použit pouze takový, který máte definovaný v operačním systému. Další věcí je, že automaticky předpokládám, že tiskárna umí tisknout na ležato. Správnější by bylo napřed tuto možnost otestovat pomocí CanSetPaperOrientation. Ale to si již jistě doplnite do kódu sami. A na konec poznámku: U dokumentu Calcu se tiskne pouze aktívní list, jak nastavíme libovolný list, aby byl aktívní, to si řekneme až příště.

Takže nejdůležitější práce se sešity již umíme. Za pomoci nástroje X-Ray Tool prozkoumejte další vlastnosti a metody, k některým se ještě v dalších dílech jistě vrátím.
Příště si něco řekneme o práci s listy sešitu.

Jo ještě něco. Dostali jste se ke StarDesktop na konci minulého dílu. Mělo by to být takto:

set oDesk = ThisComponent.CurrentController.Frame.Creator
.CurrentController.Frame
nás přenese do okna
.Creator
nás přenese do StarDesktop
je to k ničemu, ale je to užitečné pro pochopení, jak to chodí v objektovém modelu.

<< Desktop | Listy >>

vgraf2@cbox.cz

28.09.2006

stránky

hlavní stránka

Calc