hlavicka.png, 18 kB

Calc - Seriál o objektech v makrech

04 Listy

6.10.2006

V minulém díle jsme stručně probrali práci se sešity. Listy jsou součástí sešitů. SB poskytuje pro dokumenty Calcu (sešity), pseudo-vlastnost jen pro čtení Sheets. Sheets vrací kolekci listů. Kolekce Sheets je úplná, takové kolekce již umíme procházet.

sub ProjdiListy
dim oSheet as object, i as integer
  with  ThisComponent.Sheets
    for i = 0 to .Count -1
      set oSheet = .GetByIndex(i)
      msgbox oSheet.Name
    next
  end with
end sub

Protože jsem použil skrytou objektovou proměnnou pomocí with, musel jsem sešity indexovat metodou .GetByIndex.

Pokud znáte pořadí listů v sešitu lze sešit přiřadit přímo do proměnné:

  set oSheet = ThisComponent.Sheets(0)
Všimněte si, že první list se indexuje pomoci nuly, tak jako většina věcí v SB. Většinou budeme spíše znát název listu, než jeho pořadí, Pak by to mohlo vypadat takto:
  set oSheet = ThisComponent.Sheets.GetByName("NazevListu")
Vtomto případě nelze vynechat metodu .GetByName, pokud se o to pokusíte bude vždy vrácen první list, bez ohledu na to jaký název použijete.

V minulém díle jsem slíbil, že si dnes ukážeme jak se dostat na aktívní list. Když budete zkoumat sešit pomoci xray, nic takového jako ActiveSheet tam není, jak tedy na to? V některém z minulých dílů jsme si řekli, že odkaz na aplikaci dokumentu získáme pomoci objektu Controller. Při procházení vlastností nalezneme vlastnost CurrentController, pokud se přepneme pomocí ní do Aplikace, tak tam již objevíme vlastnost ActiveSheet:

  set oSheet = ThisComponent.CurrentController.ActiveSheet
Pro sebe si to vysvětluji takto. I když je aktívní list součást dokumentu, dokument sám nemá ponětí o tom který z jeho listů je aktívní, protože přepínání listů se neděje na úrovní dokumentu, ale na úrovní aplikace, která dokument spravuje, tak nastavení aktívního listu bude takto:
with ThisComponent
  .CurrentController.setActiveSheet(.Sheets.GetByName("NazevListu")
end with

Na začátku této lekce jsme si ukázali procházení listů pomocí jejich indexů. Není to jediná možnost, úplné kolekce lze procházet rovněž pomocí enumeračního objektu:

sub EnumListy
Dim oSheet as object, eSheets as object, sMsg as string
  eSheets = ThisComponent.Sheets.createEnumeration
  do while eSheets.hasMoreElements
    set oSheet = eSheets.nextElement()
    sMsg = sMsg & oSheet.getName & ", "
  loop
  msgbox sMsg
end sub

Za předpokladu, že máme nastavenou proměnnou oSheets na kolekci listu:

dim oSheets as object
  set oSheets = ThisComponent.Sheets
můžeme pomocí této kolekce např. i toto:
' přidat list - zde na první pozici
  oSheets.insertNewByName("NázevListu",0)
' přidat list - zde na poslední pozici
  oSheets.insertNewByName("NázevListu",oSheets.Count)
' přesunout list - zde na druhou pozici
  oSheets.MoveByName("NázevListu",1)
' zkopírovat list - zde na poslední pozici
  oSheets.copyByName("NázevListu", "NázevZkopirovanéhoListu", _
                      oSheets.Count)
' odstranit list
  oSheets.RemoveByName("NázevListu")
' přejmenovat list
  oSheets.GetByName("NázevListu").SetName("NovýNázevListu")

U přejmenování listu jsem použil malou kličku. Když se podíváme blíže, tak zjistíme, že

oSheets.GetByName("NázevListu")
vrací list, takže metoda .SetName není metodou kolekce Sheets, ale je metodou objektu ScTableSheetObj tedy listu.

Listy poskytují několik kolekcí:

  Annotations - komentáře
  CellFormatRanges
  Charts - Grafy
  Columns - Sloupce
  ConditionalFormat
  DataPilotTables
  DrawPage
  NumberingRules
  Rows - Řádky
  Scenarios - Scénaře
  UniqueCellFormatRanges
  UserDefinedAttributes
asi je jich ještě více, určitě se na některé ještě podíváme v příštích dílech, při nejmenším na Sloupce a Řádky.

Listy lze stejně jako dokumenty zamknout, takže poskytují metody pro zamknutí a odemknutí listu a metodu pro zjištění zda je list zamknut.

  oSheet.Protect(Password as string)   
  oSheet.UnProtect(Password as string)
  LogPromenna = oSheet.isProtected()

Asi zde nebudu probírat všechny vlastností a metody, ale odkážu vás na nástroj X-Ray Tool, pomocí kterého lze tyto zjišťovat a dopátrat se nápovědy v angličtině. O některých se však zmíním. Vlastnosti:

.CellBackColor as long
vrátí, nebo nastaví barvu pozadí buněk. Výchozí je -1, je to index pro barvu danou systémem pro pozadí dokumentů.
Lze použít funkci SB, RGB
  oSheet.CellBackColor = RGB(255,0,0)
nastaví pozadí všech buněk listu na červenou
.CellStyle
určuje výchozí styl pro formátování všech buněk listu

Všechny vlastností, které začínají na Char se tykají globálních vlastností písma listu. Např.:

  CharColor as long, CharContoured as boolean, 
  CharCrossedOut as boolean, CharFontName as string, 
  CharHeight as float, CharUnderline as SHORT, 
  a další.
CharLocale
je strukturou typu com.sun.star.lang.Locale, kde položky jsou Country, Language a Variant. U Variantu neznám význam pro ostatní vyzkoušejte:
  msgbox oSheet.CharLocale.Country & ", " _
          & oSheet.CharLocale.Language

Není tak docela pravda, že vše co začíná na Char se týká písma, je tam i několik vlastností začínajících na Chart, tyto se samozřejmě týkají vložených grafů v listu.

ImplementationName
u listu vrací řetězec ScTableSheetObj

Listy obsahují mimo jiné i tyto logické vlastnosti:

  IsActive, IsCellBackgroundTransparent, IsMerged, 
  IsScenario, IsTextWrapped, IsVisible

Jak už jsme si řekli u dokumentu, že neví který jeho list je aktívní, zřejmě to neví ani sám list o sobě. Vlastnost IsActive je totiž neustále nenastavená, takže jako by ani neexistovala. Ostatní fungují tak jak mají. Vlastnost IsActive lze ovšem snadno nahradit vlastní funkcí:

function IsActiveSheet(mySheet as object)
  IsActiveSheet=( _
    ThisComponent.CurrentController.ActiveSheet.Name = mySheet.Name)
end function

Vlastnost IsVisible nám říká zda je list viditelný či ne, jak ale viditelnost listu ovlivnit programově? Svého času jsem se s tím nepáral a upravil jsem si procedury nahrané makro-záznamníkem (k němu se jistě ještě vrátím):

sub ShowSheet(sName as string, bShow as boolean)
dim oDoc as object, oDisp as object
dim args1(0) as new com.sun.star.beans.PropertyValue
  oDoc = ThisComponent.CurrentController.Frame
  oDisp = createUnoService("com.sun.star.frame.DispatchHelper")
  args1(0).Name = "aTableName": args1(0).Value = sName
  oDisp.executeDispatch( _
        oDoc, ".uno:" & iif(bShow,"Show","Hide"), "", 0, args1())
end sub
kde sName je název sešitu a bShow je proměnná určující zda chci list zobrazit - true, nebo skrýt - false. Bohužel tento způsob mění aktívní listy.

Pořád jsem hledal metody jako např. Show, Hide nebo Visible, ale nic jsem nenašel. Teprve později mě trklo, že IsVisible je vlastnost pro čtení i zápis, tak jsem ji zkusil změnit a ono to funguje. Dost mě zmátlo to Is, měl jsem za to, že je to pouze informační vlastnost jen pro čtení.
Při použití této vlastnosti se nemění aktívní list, pokud ovšem neskrýváme právě aktivní list.

  oSheet.IsVisible = false 'skryje list
  oSheet.IsVisible = true  'zobrazí list
  'vrátí logickou hodnotu, zda je list skrytý
  logPromenna = oSheet.IsVisible

Další vlastnosti si zajisté zjistíte sami, a až se dostaneme k programování maker(pevně v to doufám), tak asi na další vlastnosti listů jistě narazíme.

Zmíním ještě pár metod

.ClearContents(nContentFlags as long)
- vymaže data z celého listu, v závislosti na konstantě nContentFlags. Dostupné konstanty:
com.sun.star.sheet.CellFlags.VALUE = 1
- číselné hodnoty, které nejsou formátovány jako datum nebo čas
com.sun.star.sheet.CellFlags.DATETIME = 2
- číselné hodnoty, formátované jako datum nebo čas
com.sun.star.sheet.CellFlags.STRING = 4
- řetězcové hodnoty
com.sun.star.sheet.CellFlags.ANNOTATION = 8
- komentáře
com.sun.star.sheet.CellFlags.FORMULA = 16
- vzorce
com.sun.star.sheet.CellFlags.HARDATTR = 32
- explicitní formátování, mimo implicitních stylů listu
com.sun.star.sheet.CellFlags.STYLES = 64
- formátování pomocí stylů
com.sun.star.sheet.CellFlags.OBJECTS = 128
- objekty
com.sun.star.sheet.CellFlags.EDITATTR = 256
- formátování v obsahu buňky
com.sun.star.sheet.CellFlags.FORMATTED = 512
- formátování uvnitř buněk, případně s více odstavci uvnitř buněk
pokud bychom chtěli odstranit pouze veškerá data, včetně komentářů, mohli bychom psát:
  oSheet.ClearContents(31)
Toto ovšem nemohu doporučit. Nikdo nám nezaručí, že v dalších verzích se hodnoty konstant nezmění, případně nerozšíří. Z tohoto důvodu jsou konstanty definovány objektovým modelem a je lépe je používat. Já to dělám takto:
dim CF as long
  with com.sun.star.sheet.CellFlags
    CF = .VALUE + .DATETIME + .STRING + .ANNOTATION + .FORMULA
  end with
  oSheet.ClearContents(CF)
Je to sice více psaní, ale do budoucna je možno se vyvarovat nevysvětlitelných chyb, kdy kód najednou přestane fungovat v nové verzi OOo respektive SB.

Prozatím jsme si ukazovali vždy jen jednoduché vlastnosti a metody nevyžadující speciální parametry. Zkusíme si tedy nastavit standardní filtr. Pro další výklad již je nutný nástroj X-Ray tool. Nenapíši zde jednoduše kód ale odvodíme si jak jsem k němu vlastně přišel. Ještě podotknu, že nastavení filtru se mi nepodařilo zaznamenat macro-zaznámníkem.

Vytvořme si nový list, nazvěme jej 'Filtr'. Vytvořte na něm jednoduchou tabulku začínající v buňce A1, tak jak ji vidíte níže.

  zakazka        firma  hmotnost
  103-2415-2000  Perex  1800
  103-2450-2000  Perex  2000
  459-0027-2001  Perex  1500
  125-1234-2002  Perex  500
  125-1235-2002  Perex  1500
  459-0028-2002  Rex    1200
  603-1000-2003  Rex    1100
  603-1001-2003  Rex    1150
  225-3248-2004  Merex  2500
  225-3250-2004  Merex  2300
  008-2121-2004  Ferex  2000
  008-2123-2004  Ferex  2100
  118-1254-2004  Ferex  1950
  118-1255-2005  Ferex  2000
  328-5642-2005  Merex  2200
  328-5643-2005  Merex  2450

V sešitu si vytvořte nový modul Basicu s názvem mdlFiltr. Otevřete si tento modul v IDE Basicu a přejmenujte makro Main na NastavFiltr. Začneme zkoumáním vlastností a metod listu.

Sub NastavFiltr
dim oSheet as object
  set oSheet = ThisComponent.Sheets.GetByName("Filtr")

xray oSheet
End SUB

Spusťte proceduru, a když naskočí Xray, měl by být jako původní objekt nastaven 'ScTableSheetObj' a jeho vlastnost Name by měla být nastavena na 'Filtr'. V okénku vlevo nahoře se přepněte na metody. Ve spodním seznamu vyhledejte heslo 'filter'. Pokud nemáte zobrazené detaily měl by řádek vypadat nějak takto:

filter  ( xDescriptor as object )
s detaily pak takto
filter  ( xDescriptor as com.sun.star.sheet.XSheetFilterDescriptor )
               com.sun.star.sheet.XSheetFilterable 

Vidíme, že metoda filter vyžaduje jeden parametr 'xDescriptor' z rozhraní 'XSheetFilterDescriptor' a sama metoda by měla být obsažena v rozhraní 'XSheetFilterable'. Předpokládám, že jste si stáhli i SDK dokumentaci a máte v Xray správně nastavenou cestu k SDK. Zkusíte-li prozkoumat tuto metodu obdržíte zprávu, že nelze prozkoumat metodu. Nevadí. Klikneme tedy na tlačítko 'SDK_dokumentace'. V internetovém prohlížeči by se měla zobrazit stránka z SDK s informacemi o filtru:

(SDK/docs/common/ref/com/sun/star/sheet/
XSheetFilterable.html#filter).

Ze stránky zjistíme, že se jedná o rozhraní
com.sun.star.sheet.XSheetFilterable, a obsahuje dvě metody:

createFilterDescriptor(bEmpty as boolean)
- vytvoří descriptor(popisovač) filtru, parametr bEmpty při true vytvoří prázdný descriptor pro filtr, pří false se použije předchozí nastavení aktuálního objektu
filter(xDescriptor as XSheetFilterDescriptor)
- vykoná operaci filtru, s použitím nastavení v deskriptoru filtru parametr xDescriptor obsahuje nastavení pro filtrační operaci.

Vidíme, že před použitím filtru musíme nastavit parametr xDescriptor, z předchozího víme, že to bude nějaký objekt, musíme tedy zjistit jak jej používat. Klikneme ve stránce na odkaz 'XSheetFilterDescriptor'. Na nové stránce zjišťujeme že descriptor je součásti rozhraní com.sun.star.sheet.XSheetFilterDescriptor a obsahuje dvě metody:

getFilterFields()
- vrací kolekcí filtrovaných polí v sekvenci třídy TableFilterField
setFilterFields(aFilterFields as TableFilterField)
- nastavuje novou kolekci pro filtrovaná pole

Opět potřebujeme zjistit informace o dalším objektu. Tentokrát klikneme na odkaz 'TableFilterField'. Z nové stránky zjišťujeme, že se jedná o strukturované pole třídy com.sun.star.sheet.TableFilterField, která popisuje jednotlivé podmínky filtračního deskriptoru. Struktura obsahuje tyto položky:

Connection as FilterConnection
- specifikuje navázání této podmínky na předchozí podmínku, je to nějaký objekt prozkoumáme jej později
Field as long
- specifikuje pole(sloupec), použitý pro tuto podmínku
Operator as FilterOperator
- specifikuje typ podmínky, opět nějaký objekt, prozkoumáme jej později
IsNumeric as boolean
- vybírá zda bude použito TableFilterField.NumericValue nebo TableFilterField.StringValue tj. zda použijeme numerickou nebo textovou hodnotu pro podmínku
NumericValue as double
- specifikuje číselnou hodnotu pro podmínku
StringValue as string
- specifikuje textovou hodnotu pro podmínku

Pomalu se začíná rýsovat použití filtru v kódu, je třeba prozkoumat neprozkoumané. Klikneme tedy na odkaz 'FilterConnection'. Vidíme, že se jedná o kolekci com.sun.star.sheet.FilterConnection obsahující dvě konstanty:

AND
- obě podmínky musí být splněné
OR
- alespoň jedná z podmínek musí být splněná

Vrátime se na předchozí stránku a klikneme na odkaz 'FilterOperator'. Opět se jedná o kolekci konstant com.sun.star.sheet.FilterOperator:

EMPTY
vybere prázdné položky
NOT_EMPTY
vybere neprázdné položky
EQUAL
rovná se specifikované hodnotě
NOT_EQUAL
nerovná se specifikované hodnotě
GREATER
je větší než specifikovaná hodnota
GREATER_EQUAL
je větší nebo rovno specifikované hodnotě
LESS
je menší než specifikovaná hodnota
LESS_EQUAL
je menší nebo rovno specifikované hodnotě
TOP_VALUES
vybere specifikované množství největších hodnot
TOP_PERCENT
vyber specifikované procento s největšími hodnotami
BOTTOM_VALUES
vybere specifikované množství nejmenších hodnot
BOTTOM_PERCENT
vyber specifikované procento s nejmenšími hodnotami

Takže jsme prozkoumali skoro vše, co potřebujeme pro vytvoření filtru programovými prostředky. Nyní ještě zbývá definovat podmínky pro filtr. Pro začátek si stanovíme pouze jednu. Chceme vybrat z pole 'zakazka' pouze ty které začínají '1' (jedničkou).

Abychom mohli použit filtr musíme nastavit deskriptor, prozkoumáním metod objektu oSheet zjistíme, že listy mají metodu createFilterDescriptor. Upravíme tedy proceduru NastavFiltr takto:

sub NastavFiltr
dim oSheet as object
  set oSheet = ThisComponent.Sheets.GetByName("Filtr")

dim oFDescriptor as object  
  set oFDescriptor = oSheet.createFilterDescriptor(true)

xray oFDescriptor
end sub

Všimněte si, že při tvorbě deskriptoru jsem použil jako parametr true, budeme tvořit nové podmínky. Proceduru spusťte a prozkoumejte vlastnosti a metody deskriptoru. Mimo jiné je zde pseudo-vlastnost FilterFields složená z již výše popsaných metod getFilterFields a setFilterFields. Ve SB použiji vlastnost FilterFields, pokud bych chtěl nastavovat filtr z jiných jazyků musel bych použit metody.

Pomoci vlastnosti ContainsHeader nastavíme že filtrovaná oblast obsahuje záhlaví
  oFDescriptor.ContainsHeader = true

Další vlastnosti která se nám bude hodit je 'UseRegularExpressions' jejím nastavením na true použijeme regulární výraz. Protože hledáme záznamy začínající jedničkou, což bychom ve filtru zapsali = "^1.*" při použití regulárních výrazu.

  oFDescriptor.UseRegularExpressions = true
abychom mohli regulární výraz zapsat musíme nastavit TableFilterFields,
takže nyní bude naše procedura vypadat takto:
sub NastavFiltr
dim oSheet as object
  set oSheet = ThisComponent.Sheets.GetByName("Filtr")

dim oFDescriptor as object  
  set oFDescriptor = oSheet.createFilterDescriptor(true)
' je pouzito zahlavi sloupcu
  oFDescriptor.ContainsHeader = true
' pouzijeme regularni vyrazy
  oFDescriptor.UseRegularExpressions = true
  
dim TFF(0) as new com.sun.star.sheet.TableFilterField
  TFF(0).Field = 0 ' prvni sloupec
  TFF(0).Operator = com.sun.star.sheet.FilterOperator.EQUAL'rovna se
  TFF(0).IsNumeric = false ' textova hodnota
  TFF(0).StringValue = "^1.*" ' s jednickou na zacatku

xray TFF(0)
end sub

Všimněte si jak jsem definoval objekt TFF. Místo

  dim TFF(0) as new com.sun.star.sheet.TableFilterField
jsem mohl napsat:
dim TFF(0) as object
  set TFF(0) = CreateObject("com.sun.star.sheet.TableFilterField")
se stejným efektem.

Spusťte proceduru a prozkoumejte si objekt TFF. Asi jste si všimli, že jsem nenastavoval Connection, to proto, že se jedná o první podmínku a není na co navazovat. Nyní přiřadime podmínku do deskriptoru a zkusíme spustit filtr.

sub NastavFiltr
dim oSheet as object
  set oSheet = ThisComponent.Sheets.GetByName("Filtr")
  
dim TFF(0) as new com.sun.star.sheet.TableFilterField
  TFF(0).Field = 0 ' prvni sloupec
  TFF(0).Operator = com.sun.star.sheet.FilterOperator.EQUAL'rovna se
  TFF(0).IsNumeric = false ' textova hodnota
  TFF(0).StringValue = "^1.*" ' s jednickou na zacatku

dim oFDescriptor as object  
  set oFDescriptor = oSheet.createFilterDescriptor(true)
' je pouzito zahlavi sloupcu
  oFDescriptor.ContainsHeader = true
' pouzijeme regularni vyrazy
  oFDescriptor.UseRegularExpressions = true
' vlozeni podminek do deskriptoru
  oFDescriptor.setFilterFields(TFF())

' spusteni filtru
  oSheet.Filter(oFDescriptor)
end sub

Pokud je vše v pořádku jsou ve sloupci A zobrazeny zakázky začínající na 1, v opačném případě musíte zkontrolovat předchozí kód

Dejme tomu, že bychom potřebovali při této podmínce ještě druhou. Z druhého sloupce 'firma' chceme vybrat jen firmu Perex. Jednoduše rozšíříme objekt TTF o další podmínku, vždyť jsme si řekli, že to je strukturované pole.

sub NastavFiltr
dim oSheet as object
  set oSheet = ThisComponent.Sheets.GetByName("Filtr")
  
dim TFF(1) as new com.sun.star.sheet.TableFilterField
  TFF(0).Field = 0 ' prvni sloupec
  TFF(0).Operator = com.sun.star.sheet.FilterOperator.EQUAL'rovna se
  TFF(0).IsNumeric = false ' textova hodnota
  TFF(0).StringValue = "^1.*" ' s jednickou na zacatku
' musi platit obe podminky
  TFF(1).Connection = com.sun.star.sheet.FilterConnection.AND
  TFF(1).Field = 1 ' druhy sloupec
  TFF(1).Operator = com.sun.star.sheet.FilterOperator.EQUAL'rovna se
  TFF(1).IsNumeric = false ' textova hodnota
  TFF(1).StringValue = "Perex" ' Perex

dim oFDescriptor as object  
  set oFDescriptor = oSheet.createFilterDescriptor(true)
' je pouzito zahlavi sloupcu
  oFDescriptor.ContainsHeader = true 
' pouzijeme regularni vyrazy
  oFDescriptor.UseRegularExpressions = true 
  oFDescriptor.setFilterFields(TFF())

  oSheet.Filter(oFDescriptor)
end sub
Nezapomeňte zvětšit rozsah struktury TTF, v její deklaraci, z nuly na jedničku.

Když umíme filtr programově nastavit, měli bychom umět jej i programově zrušit. Co myslíte bude to složité? Máte pravdu nebude. U vytváření deskriptoru máme jako parametr bEmty, který při true nastaví prazdný deskriptor. Ano to je ono, prostě aplikujeme na filtr prázdný deskriptor.

sub ZrusFiltr
dim oSheet as object
  set oSheet = ThisComponent.Sheets.GetByName("Filtr")

dim oFDescriptor as object  
  set oFDescriptor = oSheet.createFilterDescriptor(true)
  oSheet.Filter(oFDescriptor)
end sub
nebo
sub ZrusFiltr1
  with ThisComponent.Sheets.GetByName("Filtr")
    .Filter(.createFilterDescriptor(true))
  end with
end sub

Obě procedury jsou v podstatě shodné u druhé jsem použil skrytou proměnnou pro list pomocí with a protože používáme prázdný descriptor, není třeba ani pro něj proměnná, ale aplikujeme jej ihned na filtr. Takto lze ušetřit spoustu psaní, a teoreticky by se měla zvýšit rychlost kódu. U našeho kódu se rychlost nijak neprojeví, a proto je vhodnější první zápis je čitelnější. Pokud ale máme nějaký kód např. ve smyčce o mnoha cyklech, pak druhý zápis může výrazně urychlit smyčku. Tolik na okraj.

Tento úsek vám měl ukázat, jak lze zkoumat objekty a jejich metody a vlastnosti. Samozřejmě k tomu není nezbytně potřebný nástroj X-Ray Tool. Ale významně zjednodušuje zkoumání objektů OOo.
SB zavádí pro každý objekt tři pseudo-vlastnosti pouze pro čtení:

Dbg_Methods as string
- poskytuje seznam metod objektu
Dbg_Properties as string
- poskytuje seznam vlastností
Dbg_SupportedInterfaces as string
- poskytuje seznam rozhraní, které lze s objektem použit
vyzkoušejte třeba:
sub testDbg
  msgbox ThisComponent.Dbg_Methods
  msgbox ThisComponent.Dbg_Properties 
  msgbox ThisComponent.Dbg_SupportedInterfaces
end sub

Objektový model je pak popsán v html formátu v SDK. Právě vlastností SB Dbg_xyz v návazností na SDK, x-ray využívá a tím značně urychlí práci při zkoumání objektů oproti manuálnímu vypisování metod a vlastností a jejich hledání v SDK.

Za domácí úkol si přidejte do filtru ještě podmínku pro hmotnost >= 1500. A samozřejmě cvičte s filtrem co to jde. A až vás to přestane bavit najděte si jiné objekty či metody a zkuste je dle předešlého postupu prozkoumat.

Dnešní díl je u konce, dal mi mimořádně zabrat. Přesto se budu snažit, aby další díl nenechal na sebe dlouho čekat. Bude se jednat o rozsahy na listu (Sloupce, Řádky, Buňky atd.) tak abychom již mohli začit zapisovat a číst z a do sešitů Calcu.



<< Sešity | Rozsahy

vgraf2@cbox.cz

23.09.2006

stránky

hlavní stránka

Calc