VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ FAKULTA STAVEBNÍ
INFORMATIKA II MODUL 02 ALGORITMIZACE A PROGRAMOVÁNÍ V INŽENÝRSKÝCH ÚLOHÁCH
STUDIJNÍ OPORY PRO STUDIJNÍ PROGRAMY S KOMBINOVANOU FORMOU STUDIA
Informatika II • Modul 02 • Algoritmizace a programování
© Jiří Macur, Miroslav Menšík
2
Obsah
OBSAH OBSAH
3
VSTUPNÍ INFORMACE K MODULU
5
Cíle
5
Požadované znalosti
5
Doba potřebná ke studiu
5
Klíčová slova
5
Použitá terminologie
5
Metodický návod na práci s textem
5
1
7
OBJEKTOVĚ ORIENTOVANÉ PROGRAMOVÁNÍ
1.1 Třída jako zobecněný typ 1.1.1 Instance třídy 1.1.2 Atributy 1.1.3 Metody
7 8 8 9
1.2
Vznik a zánik objektu
10
1.3
Zapouzdření, polymorfismus, dědičnost
11
1.4
Programování řízené událostmi
12
2
APLIKAČNÍ MODELY
2.1
Hierarchie objektů
15
2.2
Kolekce objektů
15
3
DŮLEŽITÉ OBJEKTY APLIKACE MS EXCEL
15
16
3.1 Sešity, listy, množiny buněk 3.1.1 Kolekce a prvky kolekce Worbooks 3.1.2 Procházení kolekce 3.1.3 Kolekce a prvky kolekce Worksheets 3.1.4 Kolekce buněk Range
17 17 19 20 21
3.2
List jako kontejner pro vstup a výstup dat
23
3.3
Využití grafu pro prezentaci dat
26
4
PRÁCE SE SOUBORY PROSTŘEDNICTVÍM FSO
4.1
Metody pro práci se složkami a soubory
29 31
3
Informatika • Modul 01 • Počítačové a operační systémy 4.2
Výběrový objekt třídy FileDialog
34
4.3
Zápis a čtení dat ze souboru
36
5
DŮLEŽITÉ OBJEKTY APLIKACE MS WORD
5.1
Vybrané postupy programování textu
39
5.2
Použití objektového modelu z jiné aplikace
41
4
38
Objektové modely
Vstupní informace k modulu Cíle Čtenář by měl získat základní dovednost využívat aplikační objektové knihovny MS Office v prostředí jazyka Visual Basic při řešení inženýrských úloh. Text je určen pro studenty technicky orientovaných oborů mimo oblast informačních technologií.
Požadované znalosti K přečtení a porozumění tomuto textu jsou potřebné znalosti uvedené v modulu CU01_M01 – strukturované programování v jazyce Visual Basic, práce v prostředí VBA.
Doba potřebná ke studiu Je velmi individuální podle znalostí čtenáře. Pro velmi skromné znalosti je uvedená doba cca 20 hodin.
Klíčová slova Algoritmizace, programovací jazyk Visual Basic, strukturované programování, objektově orientované programování, objektový model aplikace, knihovny objektů, implementace inženýrských úloh
Použitá terminologie Diskutovaná problematika se rychle vyvíjí, proto je česká terminologie značně neustálená. V textu je většinou uváděna i ekvivalentní anglická terminologie spolu s příslušnými zkratkami.
Metodický návod na práci s textem Text je určen zejména pro osvojení základů algoritmického myšlení, získání všeobecné programátorské dovednosti a schopnosti využívat bohatých objektových knihoven v běžně používaných aplikacích. Je třeba si uvědomovat tvořivou podstatu programátorské práce, kdy lze dospět k cíli mnoha různými způsoby. Čtenář by se neměl nechat odradit zdánlivě složitou strukturou používaných objektových modelů. Jsou to jenom nástroje a vznikly proto, aby uživatelům usnadnily život. Jsou koncipovány tak, aby si každý mohl vybrat (většinou 5
Informatika • Modul 01 • Algoritmizace a programování
relativně chudou) podmnožinu objektů pro své účely – je zapotřebí se orientovat na logické souvislosti a nikoli na encyklopedické znalosti.
6
Objektové modely
1
Objektově orientované programování
Text v prvním modulu se týkal tzv. procedurálního programování. Od začátku tohoto století však dominuje metoda objektově – orientovaného programování (OOP), která se postupně stala standardem. Pro efektivní programování není třeba zabíhat do teoretických podrobností – hlavním aspektem je používání tzv. objektů, které mají následující rysy: Vnitřní struktura – až dosud jsme používali skalární proměnné, později pole. Objekt je obecnější pojem: sestává z tzv. vlastností (atributů) a metod. Vlastnosti jsou v podstatě datové proměnné, svázané dohromady tím, že patří k témuž objektu. Popis objektu pomocí určitých jeho vlastností je přirozený – chceme-li popsat objekt reálného světa, také používáme tento přístup (např. člověk může být popsán souborem svých fyzických a duševních vlastností). Okamžitý soubor hodnot vlastností vyjadřuje stav objektu (např. vlastnost "barva vlasů" člověka může postupně nabýt hodnot blond, brunet, šedivé, žádné). Objekt se tedy může v čase měnit prostřednictvím změn hodnot svých vlastností. Soubor vlastností objektu může být tvořen souborem proměnných tak, jak jsme se s nimi seznámili v části o procedurálním programování. Vlastností objektu však může být také jiný objekt, tj. vlastnost může být dále strukturovaná (např. vlastnost "inteligence" může být dále vnitřně členěna jako soubor inteligence sociální, logické, emoční ap.). Tímto způsobem vzniká určitá objektová hierarchie. Metody objektu představují jeho "vnitřní dovednosti". Jsou tvořeny obvykle podprogramy, které mj. pracují s vlastnostmi objektu. Např. člověk (zdravý) je schopen chůze, práce atd. Výsledkem procesu metody je změna stavu objektu (např. chůze člověka přemístí z jednoho místa – vlastnost polohy – na jiné). Uvedený přístup k programování podstatně mění celou metodiku: zatímco v případě procedurálního programování jsme tvořili algoritmus "shora – dolů", tj. postupně jsme obecný problém dekomponovali až na jednotlivé příkazy, v případě OOP se spíše snažíme o "simulaci chování" navržených objektů. Výsledkem je pak spíše návrh "zdola – nahoru". Řešení vzniká jako výsledek chování objektů.
1.1
Třída jako zobecněný typ
Objekt má tedy svou strukturu a chování (něco "dovede"). Tato struktura a zmíněné chování jsou popsány v tzv. třídě objektu (class). Nejčastěji se třída ztotožňuje se "šablonou" objektu. Na třídu však můžeme nahlížet také jako na zobecnění datového typu. Např. datový typ Double určuje pravidla pro uložení reálného čísla v paměti a nelze ho zaměnit s konkrétním číslem. Stejně tak třída není vlastním objektem – nezahrnuje stav objektu (hodnoty jeho vlastností). Tak, jako mají datové typy své názvy, mají názvy i třídy. V tomto případě jsou však názvy tvořeny programátory (nejsou součástí jazyka). U rozsáhlejších programů je velmi důležité, aby byly názvy tříd voleny pečlivě a byla pořizována dokumentace o jejich zamýšleném účelu (softwarová analýza).
7
Informatika • Modul 01 • Algoritmizace a programování
1.1.1
Instance třídy
Objekt dané třídy se nazývá také instance třídy. Jedná se o strukturovaná data v paměti obsahující konkrétní hodnoty (stav). Stav objektu se v čase mění, ať už prostřednictvím metod objektu nebo přímou změnou ze strany jiných programů a objektů v paměti. Současně můžeme používat libovolný počet objektů stejné třídy. Budou se lišit umístěním v paměti (budou mít různé identifikátory) a také stavem. Instance třídy se vytváří speciálním operátorem New (viz dále). Název (identifikátor) objektu se od názvu třídy liší (stejně jako nevytváříme proměnnou s názvem Integer). Identifikátor objektu obsahuje adresu umístění objektu v paměti obdobně jako u proměnné typu String. Důvodem je vnitřní struktura objektu a možnosti změny rozsahu objektu za doby jeho života v paměti počítače.
1.1.2
Atributy
Třída je tvořena množinou vlastností objektu. Ve skutečnosti jsou zde atributy objektu deklarovány, tj. je uveden jejich název a datový typ. Třídu definujeme ve VB v modulu tříd, který musíme nejprve do projektu vložit:
Následně musíme třídu vhodně pojmenovat postupem podle níže uvedeného obrázku, implicitní název Class1 rozhodně není vhodný:
Nyní lze do modulu třídy vložit atributy:
8
Objektové modely
Vidíme, že atributy mají charakter deklarace, pouze klíčové slovo Dim je nahrazeno klíčovým slovem Public (tím povolujeme přístup k atributům třídy z vnějšího prostředí; atributy lze také znepřístupnit klíčovým slovem Private, pro naše účely je však tato problematika nepodstatná). Nyní je již možné s třídou programově pracovat, např. takto:
Deklarace proměnné zamestnanec třídy osoba pro práci s objektem nestačí. Musíme ještě vytvořit instanci třídy příkazem Set s použitím operátoru New (viz 3. řádek programu). Od této chvíle existuje v paměti objekt s názvem zamestnanec a lze pracovat s jeho atributy, které identifikujeme názvem objektu a atributu odděleným tečkou. Znak "." se někdy nazývá také selektor – vybírá z objektu patřičnou část.
1.1.3
Metody
Dále třída objektu obsahuje definici jeho metod – soubor podprogramů. Původní myšlenka OOP byla založena na principu skrývání stavu objektu – všechny vlastnosti definující stav měly být pro vnější prostředí (jiné objekty a programy) černou skříňkou, k nimž by byl přístup pouze prostřednictvím metod objektu. Význam tohoto opatření tkví zejména v bezpečnosti – metody mohou ověřit oprávnění vnějšího objektu přistupovat (číst, či měnit) vlastnosti daného objektu. V dnešní době však toto pravidlo není rigidně dodržováno. Programátor (tvůrce třídy) určuje, zda lze obsah vlastnosti přečíst nebo změnit přímo, bez prostředníka v podobě metody objektu. K definici třídy přidáme metodu pro výstup atributů např. takto:
9
Informatika • Modul 01 • Algoritmizace a programování
Protože metoda bude součástí objektu, má k dispozici všechny jeho atributy. Proto při jejich používání nepoužíváme žádná bližší určení pomocí selektoru. Nyní lze použít novou metodu třídy v programu:
Vidíme, že použití metody se ze syntaktického hlediska neliší od používání atributů – opět používáme tečkový selektor pro výběr potřebné metody. Metoda však může mít parametry, pro které platí vše, co bylo uvedeno v modulu CU01_M01 v kapitole o předávání parametrů. Upravíme metodu naší třídy pro různé druhy tisku:
Použití upravené metody pak může být následující:
1.2
Vznik a zánik objektu
Vznik objektu (instance třídy) v našem případě vyvolal příkaz Set zamestnanec = New osoba Atributy zaměstnance však nejsou po vzniku objektu naplněny definovanými hodnotami, což může vést ke zmatkům při použití objektu. Proto bývá zvykem použít v definici třídy speciální metodu, která při vzniku objektu automaticky definuje jeho počáteční stav (naplní atributy počátečními hodnotami). Metoda takové inicializace objektu se nazývá konstruktor a v jazyce VB musí být nazvána Class_Initialize:
10
Objektové modely
Nyní můžeme vyzkoušet automatické uplatnění konstruktoru:
Pokud potřebujeme za běhu programu existenci objektu ukončit (uvolnit paměť), použijeme příkaz Set zamestnanec = Nothing Poznámka Klíčové slovo Nothing ve skutečnosti pouze odstraní ukazatel na objekt v paměti (objektová proměnná zamestnanec obsahuje speciální prázdnou adresu). V prostředí VB se periodicky aktivuje tzv. garbage collector, který likviduje takové objekty v paměti, na které neexistuje žádný odkaz.
1.3
Zapouzdření, polymorfismus, dědičnost
Na stav objektu se lze dívat jako na černou skřínku, k níž máme pouze omezený přístup zejména pomocí metod objektu. Tento princip "zapouzdření" (encapsulation) dat i metod do jednoho kompaktního celku je pokládán za jednu z významných výhod OOP. V této souvislosti je uváděna také vlastnost polymorfismu operací s objekty. V podstatě jde o různé chování různých objektů ve stejných souvislostech. Na polymorfismus jsme již narazili např. při používání operátoru "+". Sečítáme-li celá čísla, je výsledkem celé číslo. Sečítáme-li reálná čísla, bude výsledkem reálné číslo – operátor "+" tedy pracuje jinak pro různé datové typy. Nejvýraznější je však tato vlastnost při "sečítání" řetězců, kdy je výsledkem operace spojený řetězec (i když bychom měli v této roli používat raději operátor "&"). Stejně tak si můžeme představit např. objekt obsahující v podobě atributů koeficienty matice, který obsahuje metodu tisk pro výstup (zobrazení) vhodně zformátované matice. Stejnou metodu tisk však může obsahovat objekt obsahující vektor, nebo odstavec textu. Způsob provedení metody se stejným názvem tedy určuje objekt. Dědičnost je mechanizmus, kterým lze z definice jedné třídy odvozovat jiné podobné třídy. Používá se zejména v souvislosti s hierarchií obecnosti. Např. 11
Informatika • Modul 01 • Algoritmizace a programování
třída osoba obsahuje obecné atributy člověka, avšak třída pacient obsahuje navíc atributy chorobopisu a metody léčení. Abychom nemuseli definovat pořád znovu stejné atributy a metody, nabízí OOP mechanizmus dědění (inheritance), kdy definujeme v podstatě pouze rozdíly mezi třídami.
1.4
Programování řízené událostmi
Volání metod objektů je standardně dáno sekvenčním prováděním algoritmů. Objekt v paměti však podléhá určitému vývoji (evoluci), který často v algoritmu předvídat nemůžeme – nejčastěji se jedná o asynchronní zásahy v době života objektu vyvolané operačním systémem nebo jinými objekty. Pro programovou reakci na vybrané změny stavu objektu máme k dispozici mechanizmus událostí (angl. events). Pozorný čtenář si jistě domyslel, k čemu tato kapitola směřuje: prakticky vše, s čím manipulujeme v aplikacích, lze považovat za objekty, které mají své vlastnosti a metody. Např. okno aplikace je objektem, který má své atributy (geometrii, barvu rámečku apod.) a metody (schopnost zobrazit se na obrazovce, změnit svůj tvar apod.). Některé z metod jsou však závislé na činnosti uživatele – ten prostřednictvím myši okno přesune nebo minimalizuje; metody okna pak musí reagovat na požadavky, které oknu zasílá operační systém. Právě operační systém se totiž stará o zobrazení grafického kurzoru, sleduje polohu myši a jejích tlačítek a vyhodnotí, kterého objektu v paměti se vzniklá událost týká. Mechanizmus událostí je založen na vazbě mezi typem události a speciální metodou objektu, která je automaticky spuštěna při výskytu této události (tato metoda se někdy nazývá také událostní procedura). Ve VB je uvedená vazba realizována předepsaným názvem metody a my jsme se již s tímto mechanizmem setkali – konstruktor s předepsaným názvem Class_Initialize lze také pokládat za událostní proceduru, která se automaticky spustí při události vzniku objektu.
12
Objektové modely
V levém horním rohu obrázku vidíme seznam událostí, pro které lze vytvořit událostní procedury. Události se týkají objektu listu s názvem "Data". Lze tedy vytvořit metody tohoto objektu, které se spustí při aktivaci listu (za předpokladu, že list "Data" předtím nebyl aktivní), při změně dat v listu, při poklepání myší apod. Vytvořit událostní proceduru lze jednoduše výběrem názvu události (např. Change) – v modulu listu je automaticky vytvořena prázdná metoda Worksheet_Change, do které zbývá vepsat kód:
Pak otevřeme list a zapíšeme libovolný údaj do libovolné buňky listu. Po opuštění buňky se automaticky vykoná událostní procedura. Totéž se bude opakovat při jakékoli změně v obsahu listu:
13
Informatika • Modul 01 • Algoritmizace a programování
Důležitá poznámka V našich příkladech nebudeme tvořit ani nové třídy, ani reakce na události. Budeme však používat třídy a objekty již hotových aplikací. Je proto nutné osvojit si stručné teoretické zázemí OOP.
14
Objektové modely
2
Aplikační modely
Moderní aplikace jsou vyvíjeny tak, aby byly uživatelsky rozšiřitelné – výrobce pak nemusí poskytovat různé mutace pro nejrůznější specializace, kde je trh příliš úzký, a přesto lze aplikaci přizpůsobit na míru nejrůznějším potřebám. Vzhledem k tomu, že objektový přístup je dnes při vývoji aplikací dominantní, je i prostředí pro rozšiřování a přizpůsobení programových produktů vytvořeno v podobě množiny objektů. Tato množina má obvykle hierarchickou strukturu a nazývá se objektovým modelem aplikace, někdy též objektové aplikační rozhraní nebo objektová knihovna. Kvalita návrhu struktury objektů rozhoduje o tom, zda bude možné tvořit rozšíření a nadstavby aplikace snadno, nebo bude tento proces průchodný jen pro hrstku profesionálů. Aplikační model obsahuje často desítky až stovky objektů, není proto možné, aby měl programátor detailní znalosti o všech jejich schopnostech a vazbách. Mnoho informací musí mít intuitivní charakter, aby se daly logicky odvodit a případně dohledat pouze detaily.
2.1
Hierarchie objektů
Na vrcholu hierarchického modelu aplikace bývá tradičně objekt třídy Application, který reprezentuje běh aplikace. V podobě atributů pak obsahuje další podobjekty, které realizují dílčí činnosti aplikace. Objekt třídy Application je přímo k dispozici v době, kdy je aplikace spuštěna. V případě potřeby však můžeme objekt třídy Application také vytvořit – většinou tehdy, když potřebujeme v programu použít objekty jiné aplikace (viz dále). Objekt, který v podobě vlastností obsahuje jiné objekty, se někdy nazývá také objektový kontejner.
2.2
Kolekce objektů
Často je zapotřebí pracovat s "polem" objektů stejné třídy. Pro tyto účely se používá speciální objekt nazývaný kolekce. Kromě možnosti přistupovat k prvkům kolekce pomocí indexu má kolekce obvykle metody umožňující zejména přidat další prvek, odstranit prvek z kolekce apod.
15
Informatika • Modul 01 • Algoritmizace a programování
3
Důležité objekty aplikace MS Excel
Objektový model aplikace MS Excel je poměrně složitý:
Obr. 3.1 – Začátek a konec první úrovně objektů, které obsahuje třída Application jako své vlastnosti Většina vlastností, za nimiž se skrývá kolekce jiných objektů, se nazývá množným číslem (-s na konci názvu). Některé podobjekty obsahují jako svou vlastnost z pragmatických důvodů opět nadřízený objekt (kruhové odkazy). Vzhledem k tomu, že vlastnost v podobě objektu obsahuje ve skutečnosti pouze adresu objektu, je tato konstrukce naprosto legitimní. Některé objekty jsou umístěny v hierarchii současně více způsoby, např. aktivní sešit ActiveWorkbook je vlastností Application, ale zároveň je členem kolekce Workbooks, která je také vlastností třídy Application. Naštěstí k našim účelům bude zapotřebí osvojit si práci jen s velmi malým počtem kolekcí a objektů. 16
Objektové modely
3.1
Sešity, listy, množiny buněk
Naše programy spouštíme ve vývojovém prostředí MS Excel, který musí být v dané chvíli pochopitelně spuštěn. Zastupuje ho objekt třídy Application, který máme v našich programech k dispozici. K ostatním objektům aplikačního modelu se dostaneme prostřednictvím jeho vlastností.
3.1.1
Kolekce a prvky kolekce Worbooks
V běžící aplikaci mohou být otevřeny různé soubory se sešity, které jsou přístupné pomocí kolekce Workbooks. Tato kolekce má (podobně jako většina ostatních kolekcí objektů) obecnou vlastnost Count, která obsahuje počet položek v kolekci (zde počet současně otevřených souborů v aplikaci MS Excel):
Obr. 3.2 – Programové určení počtu položek v kolekci Otevřeli jsme tedy tři soubory a krátkým programem zobrazili obsah vlastnosti Count. Všimněte si hierarchického zápisu: objekt Application má objektovou vlastnost Workbooks, která má vlastnost Count. Při výběru používáme posloupnost vnořených tříd s použitím tečky, není třeba používat žádné závorky. Vzhledem k tomu, že Application zastupuje samotnou aplikaci, lze ho při identifikaci vynechat – v programu použijeme zkráceně Workbooks.Count Důležité metody objektu Workbooks jsou následující:
Add – vytvoří nový sešit Open – otevírá existující soubor se sešitem Close – zavře všechny otevřené sešity
Na metodě pro vytvoření nového sešitu můžeme demonstrovat základní postupy práce s objektovou knihovnou. Metoda Add provede programově stejnou činnost, jako tlačítko "Nový" v základní nabídce aplikace, tj. vznikne nový sešit se třemi listy a implicitním názvem. Avšak metoda je funkcí – vrací nově vytvořený objekt sešitu v paměti, který můžeme uložit do objektové proměnné správné třídy (Workbook) a dále pracovat s jeho vlastnostmi, aniž bychom byli svazováni vazbami na hierarchickou síť. Vytvořili jsme tedy nový objekt sešitu (instanci třídy Worbook) a nepotřebovali jsme žádný operátor New ani konstruktor – metoda Add se o vše potřebné k vytvoření a inicializaci datové struktury postará. 17
Informatika • Modul 01 • Algoritmizace a programování
Proto nemusíme konstruovat nové objekty, obvykle nám nabídka poskytovaná aplikačním modelem stačí.
Obr. 3.3 – Programové přidání nové sešitu V příkladu nejprve deklarujeme objekt třídy Workbook. Dalším příkazem zavoláme metodu Add a výsledek přiřadíme naší objektové proměnné. V tomto přiřazení se obsahem proměnné stane ve skutečnosti adresa datové reprezentace (objektu) sešitu. Příkaz je rozšířen o klíčové slovo Set, které zatím nelze vynechat a zdůrazňuje jiný vnitřní mechanizmus operací s objekty, než se skalárními proměnnými. Nový objekt sesit má již velmi mnoho vlastností a metod – v příkladu jsme použili pouze obecnou vlastnost Name obsahující název sešitu (po uložení to bude jméno souboru). Metoda Open pracuje obdobně jako metoda Add, používá se však s parametrem označujícím jméno souboru, v němž je sešit uložen:
Obr. 3.4 – Programové otevření sešitu a zjištění jeho vlastnosti Kolekce nám tedy pomáhá při vytváření a zavírání nových sešitů. Potřebujeme ještě mechanizmus, jak pracovat s konkrétním prvkem v kolekci. Nejjednodušeji můžeme použít vlastnost Workbooks.Item(index), která si nese index analogicky jako při práci s polem. 18
Objektové modely
Obr. 3.5 – Člen kolekce určený pomocí indexu Členy kolekce jsou objekty třídy Workbook, s nimiž lze pracovat pomocí jejich indexu (postupně otevírané soubory jsou číslovány od jedničky výše). Tento způsob se však používá zřídka. Indexy jsou přiřazovány postupně, takže po sérii zrušení a otevření souborů již nevíme, který sešit má který index. Častěji hledáme objekt kolekce pomocí jména (vlastnost Name bývá k dispozici ve všech objektech, kde má smysl). Zobrazování vlastnosti jména v našich programech tedy nebylo samoúčelné. Vidíme, že vlastnost jména je naplněna názvem souboru (bez cesty). Toto jméno může sloužit rovněž v roli indexu. Vlastnost Item lze v této souvislosti navíc vynechat a dostáváme se k nejčastěji používanému způsobu zpřístupnění objektu z kolekce: Set sesit = Workbooks("sesit.xls") Poznámky Zavádět objektovou proměnnou bychom v posledním příkladu nemuseli, protože instance Workbook existuje. Programátor VB by patrně použil bez deklarací přímo příkaz: MsgBox("Nový sešit má jméno: " & Workbooks(2).Name) Dále je zapotřebí striktně rozlišovat mezi kolekcí a jejími prvky. Kolekce je objekt, který má obvykle úplně jiné vlastnosti než mají objekty, které jsou v kolekci obsaženy. Tyto techniky je zapotřebí vstřebat, budou nás doprovázet prakticky ve všech programech.
3.1.2
Procházení kolekce
Velmi často potřebujeme provést nějakou operaci se všemi prvky kolekce. K tomu máme k dispozici variantu počítaného cyklu For Each
In … tělo … Next V těle takového cyklu používáme název proměnné, do které je postupně dosazován další a další prvek kolekce, dokud zpracováním v těle neprojdou všechny prvky. Pohodlí, které tento druh cyklu poskytuje v souvislosti s procházením kolekcí, přivedlo vývojáře k implementaci tohoto cyklu i v jiných, rigidnějších programovacích jazycích.
19
Informatika • Modul 01 • Algoritmizace a programování
Obr. 3.6 – Procházení všech členů kolekce Cyklus procházení kolekce. Proměnná sesit postupně reprezentuje všechny prvky v kolekci. V těle cyklu tak můžeme použít metody a vlastnosti ve skutečnosti různých objektů, i když jsou pojmenovány stejně.
3.1.3
Kolekce a prvky kolekce Worksheets
V otevřeném souboru máme k dispozici kolekci pracovních listů Worksheets, která má obdobnou strukturu jako kolekce Workbooks. Obsahuje také vlastnost Count s počtem listů v sešitu a metodu Add pro přidání nového pracovního listu. Spektrum metod kolekce je samozřejmě bohatší, v našich programech však s nimi pracovat nebudeme. Prvky kolekce jsou pracovní listy (třída Worksheet). Pokud potřebujeme pracovat s konkrétním listem, můžeme ho identifikovat stejně jako v předcházejícím případě indexem nebo názvem. Nejčastěji použijeme konstrukci: Dim list As Worksheet Set list = Worksheets("List1") kde řetězec "List1" obsahuje název listu. Vidíme, že mnoho údajů lze při identifikaci objektu v objektovém modelu vynechat, ve skutečnosti by celý identifikátor objektu listu mohl vypadat následovně: Application.Workbooks.Item("mujSesit.xls").Worksheets.Item("List1")
20
Objektové modely
(aplikace obsahuje kolekci sešitů, z nichž jeden s požadovaným názvem obsahuje kolekci listů, z nichž jeden s požadovaným názvem je list, s nímž chceme pracovat) Vynechání objektů Application a Item jsme již diskutovali, jak ale můžeme vynechat identifikaci sešitu? Při zamlčeném nadřízeném objektu v celé hierarchii doplní VB automaticky tzv. aktivní objekt. V tomto případě sešit, s nímž pracujeme (jeho okno je aktivní). Stejně tak může být aktivní jeden list v rámci sešitu, buňka v listu apod. Takové objekty obvykle obsahují metodu Activate, kterou lze objekt prohlásit za aktivní programově (samozřejmě lze při interaktivní práci dosáhnout téhož výběrem myší). Při tvorbě programů, které využívají v identifikátorech metodu zamlčených objektů, musíme být opatrní – pokud nevíme, zda uživatel programu nebude používat více prvků kolekce současně, měli bychom používat co nejúplnější část hierarchie. Třída pracovního listu Worksheet obsahuje desítky vlastností a desítky metod. Výběr užitečných vlastností:
Cells – kolekce všech buněk v listu (má dva indexy: řádek, sloupec) Rows – kolekce všech řádků v listu Columns – kolekce všech sloupců v listu Range – vybraný soubor buněk v listu Name – název listu Index – index listu v rámci kolekce sešitu Visible – vlastnost určující, zda je list viditelný nebo skrytý
Uvedené vlastnosti budou blíže diskutovány při použití v programech. Výběr užitečných metod:
Activate – nastaví list jako aktivní Copy – zkopíruje list na jiné místo v sešitu Delete – odstraní list i s daty z kolekce Move – přesune list na jiné místo v kolekci PrintOut – vytiskne list SaveAs – uloží list i s daty do souboru
Metody mohou mít mnoho parametrů, my však programovou práci s listy provádět nebudeme. Zájemce si snadno dohledá příklady použití.
3.1.4
Kolekce buněk Range
Objekty této třídy, které budeme používat prakticky v každém programu, reprezentují soubor buněk v listu. Objekt této třídy není dále dělen na jednotlivé buňky – každá buňka je opět kolekcí buněk, i když obsahuje pouze jedinou. Tuto koncepci tvůrců objektového modelu si musíme osvojit – i když budeme pracovat pouze s jednou buňkou, bude to objekt třídy Range. Pokud tedy budeme potřebovat údaje uložené v určité buňce nebo souboru buněk, identifikujeme je prostřednictvím kolekce Range. Kolekce má opět vlastnosti Count a Item (a mnoho dalších), indexovat prvky v kolekci lze pomo21
Informatika • Modul 01 • Algoritmizace a programování
cí dvojice čísel řádku a sloupce, nebo názvem, který je zadán standardně podle konvencí aplikace MS Excel:
Obr. 3.7 – Vytvoření kolekce buněk v listu Z listu s indexem 1 tedy vybereme pravoúhlou oblast buněk 3 x 3, která se stane naší kolekcí rozsah. Pokud v našem příkladu potřebujeme, aby rozsah obsahoval jedinou buňku, můžeme použít příkaz Set rozsah = Worksheets(1).Range("C2") Pro určení jediné buňky můžeme použít ještě jednu možnost: Set rozsah = Worksheets(1).Cells(2,3) Tímto způsobem určíme tutéž buňku v notaci Cells(číslo řádku, číslo sloupce). Tento způsob je užitečný zejména tam, kde potřebujeme určit souřadnice buňky pomocí výpočtu. Vybrat do rozsahu celý sloupec lze např. takto: Set rozsah = Worksheets(1).Range("C:C") analogicky řádek Set rozsah = Worksheets(1).Range("2:2") Existuje mnoho dalších možností, jak vytvořit množinu buněk třídy Range, množina se může skládat z více oblastí, dokonce může být rozložena na více listech apod. Pro naše programy budou však výše uvedené postupy dostačující. Z desítek vlastností obsažených ve třídě Range nám v programech většinou postačí jediná: Value – vlastní obsah objektu. Vlastnosti určující velikost buněk, font a barvu písma, pozadí apod. budeme používat jen zřídka. V tomto případě lze totiž vše potřebné obvykle nastavit interaktivně přímo v listu. Naše použití programů bude orientováno zejména na výpočty orientující se na obsah buněk.
Obr. 3.8 – Nastavení obsahu buněk v kolekci Range 22
Objektové modely
3.2
List jako kontejner pro vstup a výstup dat
List Excelu lze využít jako prostředí pro vstup a výstup dat z našich programů. Dále je často výhodné do listu zařadit graf, který ihned interpretuje vypočítané výsledky. Jak programy, tak uvedené listy lze uložit do jednoho souboru, který pak lze chápat jako interaktivní aplikaci:
Obr. 3.9 – List jako výpočetní miniaplikace Příklad předpokládá vložení koeficientů rovnice do naformátovaných vstupních polí B1:B3. Po kliknutí na tlačítko "výpočet kořenů" se z vložených koeficientů zformuluje tvar rovnice, který se zapíše do buňky D1. Nakonec se vypočítá hodnota kořenů a uloží do buněk B7 a B8. Hodnoty vložené do listu načteme do proměnných programu například takto:
Obr. 3.10 – Vložení dat z listu do proměnných Pokud uživatel do patřičných buněk vloží nevhodné znaky, program zhavaruje:
(hodnotu buňky nelze vložit do proměnné deklarovaného typu Single).
23
Informatika • Modul 01 • Algoritmizace a programování
Pokud potřebujeme uvedený typ havárií ošetřit, můžeme použít např. následující konstrukci: If IsNumeric(Worksheets("QE").Range("B1").Value) Then a = Worksheets("QE").Range("B2").Value Else MsgBox ("V poli B2 musí být číselný údaj!") Exit Sub End If Vestavěná funkce isNumeric testuje, zda lze parametr převést na číselnou hodnotu. Vrací logickou hodnotu. Příkazy Exit … umožňují násilně ukončit prováděnou část programu, v níž jsou zařazeny (např. Exit Do, Exit Function, Exit For). Program pak pokračuje až za touto částí. Zde jsme příkaz použili pro ukončení celého programu. Výstupní hodnoty kořenů vložíme do předformátovaných buněk listu analogickým způsobem:
Obr. 3.11 – Vložení dat do listu Při vkládání obsahu proměnné do buňky listu není třeba provádět žádná přizpůsobení, obsah se automaticky naformátuje stejně, jako bychom data do buňky vkládali interaktivně. Pro vložení tlačítka, spouštějícího program z listu, použijeme nabídku interaktivních formulářových prvků v záložce Vývojář:
24
Objektové modely
Obr. 3.12 – Vložení tlačítka pro spuštění programu Vložené tlačítko lze přizpůsobit pomocí pravého tlačítka myši (umístění, velikost, text na tlačítku).
Obr. 3.13 – Manipulace s tlačítkem Nejdůležitější je však nastavení vazby mezi aktivací tlačítka a spuštěním potřebného programu:
Obr. 3.14 – Přiřazení podprogramu k události aktivace tlačítka V zobrazeném formuláři vybereme program, který se má spustit (pokud bychom vytvořili v sešitu více programů, nabídnou se všechny). Uvedený postup ve skutečnosti není nic jiného, než vytvoření vazby mezi událostní procedurou 25
Informatika • Modul 01 • Algoritmizace a programování
a událostí "kliknutí na tlačítko". V tomto případě se stane událostní procedurou náš program.
3.3
Využití grafu pro prezentaci dat
Pro vizualizaci programově generovaných dat lze s výhodou využít nástroje pro vytváření grafů. V rámci aplikačního modelu odpovídá grafu objekt třídy Chart. Třída obsahuje vlastnosti a podobjekty, které umožňují programově zkonstruovat všechny prvky grafu, nastavit popisky os, legendy apod. Většinou je však zbytečné vytvářet graf programově. Pro zobrazení dat totiž používáme většinou pouze jeden graf, který můžeme zkonstruovat v listu interaktivně a programově přizpůsobíme pouze data, která jsou v grafu prezentována. V našich programech budeme pracovat výhradně s bodovými X-Y grafy, tj. takovými, které prezentují datové řady se dvěma částmi: řadou hodnot nezávisle proměnné X a řadou závisle proměnné Y:
Obr. 3.15 – Vložení bodového grafu do pracovního listu Je výhodné vložit graf do téhož listu, v němž vkládáme parametry programu, resp. spouštíme program tak, aby uživatel při prohlížení vypočtených dat nemusel přepínat mezi listy. Při tvorbě grafu můžeme použít libovolnou oblast dat pro vytvoření potřebné datové řady (může to být jediná buňka). Naše programy tuto oblast při svém běhu automaticky aktualizují. Po vložení grafu do listu je objekt grafu přístupný pomocí hierarchie Worksheets(1).ChartObjects(1).Chart neboli v listu je k dispozici kolekce grafů ChartObjects, s nimiž pracujeme pomocí indexu (v případě jediného grafu v listu má index hodnotu 1). Samotný graf (objekt Chart) je vlastností prvku této kolekce.
26
Objektové modely Poznámka Graf není přímo členem kolekce ChartObjects proto, že může být uložen také ve speciálním samostatném listu sešitu (kolekce těchto listů se nazývá Charts). Pokud je graf uložen samostatně, má poněkud jiné geometrické vlastnosti než v případě, že je jedním z vložených grafů v pracovním listu.
V rámci objektu grafu budeme obvykle pracovat pouze s datovou řadou, která je uložena jako prvek v kolekci SeriesCollections (datových řad může být více) a má vlastnosti Chart.SeriesCollections(1).XValues Chart.SeriesCollections(1).Values Chart.SeriesCollections(1).Name První z nich označuje řadu hodnot nezávisle proměnné, druhý hodnoty závisle proměnné (pozor, název této vlastnosti je Values, nikoli YValues). Třetí uvedená vlastnost umožňuje změnit název datové řady, což se projeví v případné legendě grafu apod. Hodnotu vlastnosti s obsahem datové řady lze zadat několika způsoby. Jednoduše lze použít rozsah buněk Range obsahující potřebná data. Např. With Worksheets("vstup").ChartObjects(1).Chart.SeriesCollection(1) .XValues = Worksheets("data").Range("A1:A" & i) .Values = Worksheets("data").Range("B1:B" & i) End With
V tomto případě graf v listu s názvem "vstup" použije data v listu "data" ve sloupci A pro nezávisle proměnnou X a data ve sloupci B pro proměnnou Y počínaje prvním řádkem pracovního listu. Počet bodů bude dán obsahem proměnné i. Tento způsob použijeme v případě, že program předtím uvedené sloupce naplnil relevantními hodnotami. V roli hodnot datové řady lze však použít také pole, jehož prvky bude objekt grafu automaticky považovat za hodnoty bodů v grafu. Jedná se o jeden z mála případů, kdy lze pracovat s polem jako celkem: Dim poleX(100) as Single, poleY(100) as Single … naplnění prvků polí … With Worksheets("vstup").ChartObjects(1).Chart.SeriesCollection(1) .XValues = poleX .Values = poleY End With
Uvedený způsob je elegantní a rychlý – pokud program nemusí plnit obsah listu, ušetří se množství času. Poznámka Bohužel, je tento postup omezený na malý rozsah polí (max. několik set prvků). Je to dáno tím, že pole jsou grafu předávána v podobě textového řetězce seznamu hodnot, jehož délku tvůrci aplikace omezili na 4096 znaků.
Pokud nechceme do grafu v listu interaktivně vkládat "prázdné" datové řady, můžeme po vytvoření prázdného grafu (bez dat) použít metodu Add kolekce SeriesCollection: With Worksheets("vstup").ChartObjects(1).Chart .SeriesCollection.Add Range("A1:B1") .SeriesCollection(1).XValues = Worksheets("data").Range("A1:A" & i) .SeriesCollection(1).Values = Worksheets("data").Range("B1:B" & i) End With 27
Informatika • Modul 01 • Algoritmizace a programování
Příkazy automaticky přidají do grafu datovou řadu s irelevantním rozsahem dat (uvedený rozsah buněk A1:B1 lze zvolit libovolně). Rozsah buněk (zdroj dat pro graf) totiž vzápětí program přepíše na relevantní vypočtené hodnoty.
28
Objektové modely
4
Práce se soubory prostřednictvím FSO
Všechny programovací jazyky mají nástroje pro práci se složkami a soubory v podobě nejrůznějších příkazů a knihoven. V prostředí VB jsou k dispozici příkazy Open, Close, Seek apod., s jejichž pomocí lze pracovat se vstupněvýstupními zařízeními a tedy i se soubory. Tento přístup je však z programátorského hlediska náročný, výhodnější je použít univerzální objektovou knihovnu firmy Microsoft, poskytující mj. přístup k souborovému systému počítače. Knihovna poskytuje objekt třídy FileSystemObject, jejíž model umožňuje programově provádět prakticky všechny operace se systémem souborů (vytvářet, rušit a kopírovat složky a soubory, číst, zapisovat a měnit jejich atributy apod.). Zároveň lze na použití knihovny ilustrovat postup při používání tzv. ActiveX komponent z prostředí VB. Vytvořit objekt, který není součástí VB ani aplikace s vývojovým prostředím, lze dvěma způsoby: Způsob časné vazby (early binding) Dim fso As FileSystemObject Set fso = New FileSystemObject Deklarujeme objektovou proměnnou patřičné třídy. Dále vytvoříme objekt (instanci třídy) pomocí operátoru New, kterému předáme název třídy. Od této chvíle lze s objektem a jeho vlastnostmi a metodami pracovat. Uvedený způsob má však jednu nevýhodu: abychom mohli pracovat s knihovnou tříd, musíme ji v prostředí VB zaregistrovat. V nabídce "Tools – References…" vyhledáme a zatrhneme potřebnou knihovnu s názvem Microsoft Scripting Runtime podle obrázku:
Obr. 4.1 – Registrace knihovny v prostředí VB pro práci s jejími objekty.
29
Informatika • Modul 01 • Algoritmizace a programování
Registrace se bohužel netýká sešitu, ale nastavení vývojového prostředí jako celku. V příštích programech používajících knihovnu již nic registrovat nemusíme, ale pokud soubor s programy použije jiný uživatel, který knihovnu ve své verzi registrovánu nemá, dojde k chybě. Proto častěji používáme metodu zvanou pozdní vazba (late binding): Dim fso As Object Set fso = CreateObject("Scripting.FileSystemObject") V tomto případě použijeme vestavěnou funkci VB CreateObject, která vyhledá potřebnou knihovní třídu až při běhu programu, a poté vytvoří instanci knihovního objektu stejně jako v případě včasné vazby. Knihovnu nyní již nemusíme registrovat a vše bude funkční i při přenosu souboru s aplikací na jiný počítač. Malá nevýhoda je v tomto případě v zanedbatelném zpomalení a v absenci kontextové nápovědy VB pro použité třídy knihovny (prostředí "neví", že v programu jsou použity knihovní objekty). Všimněme si také obecné deklarace objektové proměnné, kterou lze použít, pokud třída objektu není v době překladu k dispozici. Třídu FileSystemObject v deklaraci použít nemůžeme, neboť nebyla zaregistrována. Obě uvedené metody použití cizí knihovny nebo aplikace v programu VB lze použít jen u produktů, které podporují technologii tzv. rozhraní Automation (také ActiveX) – u produktů Microsoft jsou to prakticky všechny. Třída FileSystemObject obsahuje jedinou vlastnost – kolekci připojených svazků Drives. Kolekce má pouze vlastnosti Count a Item (jako všechny dosud probírané kolekce). Prvky kolekce jsou dle očekávání objekty třídy Drive, jejíž atributy popisují připojené disky, např.:
AvailableSpace – použitelný prostor na disku DriveLetter – přiřazené písmeno disku DriveType – typ disku (číselník rozlišující např. optický, síťový, pevný disk apod.) FileSystem – instalovaný souborový systém na disku (NTFS, FAT32 apod.) FreeSpace – volný počet bajtů IsReady – logická hodnota určující, zda lze s diskem pracovat SerialNumber – sériové číslo disku ShareName – název síťového svazku v případě, že je připojen jako sdílený TotalSize – celková kapacita disku v bajtech VolumeName – název disku
30
Objektové modely
Příklad
Obr. 4.2 – Využití objektu FileSystemObject pro výpis připojených disků Program vypíše pro připojené a aktivní disky vybrané atributy a shromáždí je v řetězci seznam, který nakonec zobrazí. Neaktivní disky je třeba při zjišťování jejich vlastností vyloučit (pomocí atributu IsReady), jinak dojde k chybě za běhu programu.
4.1
Metody pro práci se složkami a soubory
Spektrum metod třídy FileSystemObject je na rozdíl od jediného atributu bohatší. Pomocí klávesy F2 si můžeme ve vývojovém prostředí zobrazit prohlížeč objektů (object browser), který všechny metody objektu souhrnně uvádí takto:
31
Informatika • Modul 01 • Algoritmizace a programování
Obr. 4.3 – Vlastnost a metody třídy FileSystemObject Činnost většiny uvedených metod je zřejmá z jejich názvu. Strukturu jejich základního použití znázorňuje následující tabulka: Správa souborů a složek CopyFile MoveFile DeleteFile
CopyFolder MoveFolder DeleteFolder
Vytvoření souboru a složky CreateTextFile
CreateFolder
Práce s existujícím souborem a složkou GetFile
GetFolder
Testy na existenci souboru a složky FileExists
FolderExists
Práce s textovým souborem OpenTextFile
32
Objektové modely
Použití metod ozřejmíme na několika příkladech: Kopírování souboru
Program ověřuje, zda soubor a cílová složka existují, potom vytvoří vlastní kopii souboru. Metoda CopyFile má tři parametry: určení zdrojového souboru, určení cílové složky; třetí parametr určuje, zda bude přepsán soubor v cílové složce, pokud již existuje. Uvedeme-li hodnotu False u třetího parametru, dostaneme při pokusu o další kopii téhož souboru do stejné cílové složky následující chybové ukončení programu:
Program samozřejmě skončí chybou také v případě, že k operaci se soubory chybí dostatečné oprávnění:
Při kopírování lze použít v názvech souborů rovněž zástupné znaky. Příkaz fso.CopyFile "C:\pracovni\*.doc", "C:\dopisy\", True zkopíruje všechny dokumenty ze složky pracovni do složky dopisy. Uživatelské vkládání názvů souborů včetně cesty je pracné; později si ukážeme komfortnější metodu výběru souboru či složky.
33
Informatika • Modul 01 • Algoritmizace a programování
Odstranění složky
Metoda DeleteFolder je značně destruktivní – odstraní složku i s případnými soubory a podsložkami. Proto je v programu vložen jednoduchý dotaz na potvrzení požadované operace. Konstanty VB modifikující funkci MsgBox jsou vysvětleny v modulu CU01_M01.
4.2
Výběrový objekt třídy FileDialog
Pro uživatelsky komfortní výběr programu nebo složky máme k dispozici objekt třídy FileDialog, který je k dispozici ve všech aplikacích MS Office. Při použití objektu se zobrazí standardní panel, v němž lze procházet souborovým systémem počítače a vybrat požadovaný prvek. Výsledkem je kolekce názvů souborů (resp. složek), které uživatel vybral (může označit i více prvků než jeden). Pro vytvoření objektu použijeme metodu Application.FileDialog() která vrací požadovaný objekt (instance třídy FileDialog). Parametr určuje typ panelu – k dispozici je číselník konstant:
msoFileDialogFilePicker – panel umožní vybrat soubor msoFileDialogFolderPicker – panel umožní vybrat složku msoFileDialogOpen – panel umožní otevření souboru msoFileDialogSaveAs – panel umožní uložení souboru
Vytvořený objekt se zobrazí až při volání jeho metody Show, která vrátí logickou hodnotu, zda uživatel výběr provedl, nebo stiskl tlačítko "Storno" (resp. "Cancel"). Po provedení výběru panel na obrazovce zanikne, ale objekt je dále k dispozici a názvy vybraných souborů (resp. složek) jsou včetně cesty uloženy v kolekci SelectedItems. Použití objektu je zřejmé z následujícího příkladu: 34
Objektové modely
Po vytvoření objektu fd můžeme nastavit jeho vlastnosti. V této fázi objekt ještě není zobrazen, jeho rozkreslení provede až metoda Show. Program nyní čeká na výběr souborů uživatelem a pokračuje až po uzavření panelu. Po převzetí názvů vybraných souborů můžeme objekt zrušit (v paměti existuje, i když není žádný panel zobrazen) – šetříme tím zdroje (paměť) počítače.
Obr. 4.4 – Panel objektu FileDialog
Obr. 4.5 – Procházení kolekce SelectedItems
35
Informatika • Modul 01 • Algoritmizace a programování
4.3
Zápis a čtení dat ze souboru
Programové čtení dat ze souboru použijeme zejména při zpracování textových dat z různých typů automatizovaných měření apod. Prostředí VB není příliš vhodné pro přímou práci s binárními soubory – tam používáme spíše aplikace, v nichž byly souboru vytvořeny. Abychom mohli s textovým souborem pracovat, musíme ho nejdříve vytvořit nebo otevřít (pokud existuje). K tomu používáme metodu CreateTextFile, resp. OpenTextFile třídy FileSystemObject. Obě metody vyžadují jako parametr název otevíraného souboru a vracejí nový objekt třídy TextStream, který obsahuje potřebné nástroje pro práci s textovým souborem. V našich úlohách budeme potřebovat následující metody tohoto objektu:
Read – přečte ze souboru zadaný počet znaků ReadLine – přečte ze souboru jeden řádek Write – zapíše do souboru zadaný počet znaků WriteLine – zapíše do souboru jeden řádek Close – uzavře soubor
Z vlastností objektu použijeme pouze AtEndOfStream – logická hodnota vyjadřuje, zda jsme při čtení dosáhli konec souboru. Příklad vytvoření souboru a vložení znaků do souboru:
Vidíme, že metoda CreateTextFile má ještě další parametr s logickou hodnotou. Hodnota True povolí přepsání souboru, pokud vytváříme soubor se jménem, které už v dané složce existuje. Metoda soubor vytvoří a otevře – nyní do něj lze zapisovat znaky metodami Write nebo WriteLine. Metoda WriteLine se od metody Write liší pouze tím, že za vložené znaky přidá ještě znak konce řádku (již zmiňovaná konstanta vbCrLf). Po ukončení zápisu musíme soubor zavřít metodou Close. V opačném případě riskujeme, že po ukončení programu zůstane soubor poškozený. Pokud program v pořádku proběhne, nalezneme v patřičném adresáři nový soubor, jehož obsah si můžeme prohlédnout libovolným textovým editorem. Programové čtení souboru provedeme podle následujícího příkladu: 36
Objektové modely
Program načítá jednotlivé řádky ze souboru a zapisuje jejich obsah do buněk v prvním sloupci listu. Vlastní čtení ze souboru probíhá následovně: metoda ReadLine přečte znaky ze souboru až po řídící znak nového řádku (vbCrLf). Při dalším volání metody ReadLine pokračuje čtení od tohoto znaku dále. Soubor si tedy udržuje informaci o počtu přečtených znaků a volání metody ReadLine vždy pokračuje ve čtení dalších znaků od této pozice. Atribut AtEndOfStream objektu informuje, zda jsme při čtení již dosáhli konce souboru. Pokud bychom se po dosažení konce souboru pokusili o další volání metody ReadLine, dojde k chybě. Alternativní méně užívané metody Read (resp. Write) vyžadují jako parametr číslo určující počet přečtených znaků.
37
Informatika • Modul 01 • Algoritmizace a programování
5
Důležité objekty aplikace MS Word
Vývojové prostředí VB je k dispozici rovněž v aplikaci MS Word. Objektový model textového procesoru je pochopitelně odlišný od MS Excel, určité logické souvislosti zde nicméně nalezneme. Na vrcholu hierarchie pod objektem Application je zde kolekce dokumentů Documents se zcela obdobnými vlastnostmi a metodami, jako má kolekce sešitů Worksheets v aplikaci MS Excel. Prvky této kolekce tvoří objekty třídy Document. V rámci dokumentu hraje stejně jako v Excelu důležitou roli objekt třídy Range – tentokrát však neodpovídá množině buněk, ale spojité oblasti znaků. Kromě toho máme k dispozici důležité kolekce odstavců (Paragraphs), vět (Sentences), slov (Words) a znaků (Characters). Aplikace si pochopitelně vytváří uvedené kolekce podle oddělovacích znaků – v případě odstavců je oddělovačem znak nového řádku, v případě vět tečka, v případě slov mezera (resp. čárka, tečka apod.). Programová práce v rámci zpracování textů není tak častá jako v případě sešitů tabulkových kalkulátorů, někdy je však užitečná a může ušetřit hodiny času zejména při speciálních úpravách rozsáhlých dokumentů. Použití si ukážeme na několika jednoduchých příkladech, komplexnější program nalezne čtenář v modul CU01_M03. Většinu programových změn v dokumentu provádíme tak, že nejprve vybereme oblast znaků Range, s níž pak provedeme zamýšlené operace. Objekt třídy Range lze vytvořit mnoha způsoby. Nejjednodušeji lze použít metodu Range(<Start>,<End>) třídy Document (všimněme si polymorfismus stejného názvu, označujícího jak třídu Range, tak metodu vedoucí k její instanci): Dim oblast As Range Set oblast = ActiveDocument.Range(0, 100) Rozsah oblasti v dokumentu zde definujeme počáteční a koncovou pozicí znaků, které vytvoří danou oblast. Poznámka Objekt ActiveDocument zde označuje aktivní dokument aplikace. Objekt třídy Document lze samozřejmě zpřístupnit i pomocí kolekce, například: Documents("mujDokument.docx"), Documents(1) apod.
Vytvořit instanci Range lze také pomocí prvků kolekce odstavců: Set oblast = ActiveDocument.Paragraphs(1).Range V tomto případě ovšem identifikátor Range neznamená metodu, ale objekt, který zahrnuje celý první odstavec dokumentu. Zmíněné kolekce vět, slov, znaků lze použít v rámci oblasti např. takto Dim oblast As Range, slovo As Range Set oblast = ActiveDocument.Paragraphs(2).Range Set slovo = oblast.Words(2)
38
Objektové modely
Vidíme, prvky kolekce slov (jako i dalších výše uvedených kolekcí) jsou přímo objekty typu Range. Výběr druhého slova v druhém odstavci lze samozřejmě provést také přímo příkazem Set oblast = ActiveDocument.Paragraphs(2).Range.Words(2)
(bez vytváření objektu odstavce).
5.1
Vybrané postupy programování textu
Třída Range obsahuje množství vlastností a metod, jejich použití ilustrují následující příklady: Sub triOdstavce() Dim oblast As Range Set oblast = ActiveDocument.Range( _ ActiveDocument.Paragraphs(1).Range.Start, _ ActiveDocument.Paragraphs(3).Range.End) oblast.Font.Name = "Times New Roman" oblast.Font.Italic = True oblast.Font.Size = 12 End Sub Pro definici oblasti jsme zde využili vlastnosti Start a End třídy Range, které obsahují aktuální pozici začátku a konce objektu této třídy. Z pozice začátku prvního odstavce a konce třetího odstavce jsme tedy zkonstruovali novou oblast třídy Range. Z objektu oblasti využijeme podobjekt Font, jehož vlastnosti určují formát písma podle příkladu. Analogií třídy Font pro nastavení vlastností písma je třída ParagraphFormat určena pro nastavení vlastností odstavce (např. řádkování, zarovnání, ohraničení, stínování apod.): Sub formatOdstavce() Dim oblast As Range Set oblast = ActiveDocument.Paragraphs(1).Range oblast.ParagraphFormat.Alignment = wdAlignParagraphCenter oblast.ParagraphFormat.SpaceBefore = 12 End Sub Uvedený příklad zarovná první odstavec na střed a před první řádek vloží vertikální odsazení 12 bodů (pointů). V rámci dokumentu lze programově pracovat ještě s jedním typem oblasti, který reprezentuje výběr při interaktivní práci. Odpovídající třída Selection má podobné vlastnosti jako Range, lze ji dále použít pro kopírování, vkládání a jiné operace prováděné pomocí schránky (clipboard) – obsahuje metody Copy, Cut a Paste, jejichž použití je zřejmé. Jak ve třídě Range, tak i Selection je k dispozici vlastnost Text, která zhruba odpovídá vlastnosti Value, s níž jsme pracovali dříve. Jedná se o textový obsah oblasti:
39
Informatika • Modul 01 • Algoritmizace a programování
Sub obsahVyberu() MsgBox "Vybraný text: " & Selection.Text End Sub
V jednoduchém případě lze tuto vlastnost použít pro změnu obsahu oblasti prostým přiřazením: Selection.Text = "toto je text vložený programem" Vybraný text je pak programem nahrazen textem na pravé straně přiřazení. Častěji se však pro dynamické vložení textu do dokumentu používají metody InsertBefore(<řetězec>) a InsertAfter(<řetězec>), které definovanou oblast rozšíří na začátku, resp. na konci o zadaný text v podobě parametru. Formátování v oblasti se zachová. Následující příklad před každý odstavec vloží řádek s obsahem §n, kde n je číslo odstavce: Sub vlozPredOdstavce() Dim odstavec As Paragraph Dim i As Integer i = 0 For Each odstavec In ActiveDocument.Paragraphs i = i + 1 odstavec.Range.InsertBefore ("§" & i & vbCrLf) Next End Sub Velmi krátkým programem jsme dosáhli úpravy dokumentu, která by se manuálně prováděla pracně. Výsledek běhu programu je změněný dokument, který lze dále běžně upravovat včetně programem vložných částí. Navzdory různým metodám automatických oprav v aplikaci MS Word je často jednodušší vytvořit program řešící náš problém přesně tak, jak potřebujeme. Následující program odstraní krátké sekvence znaků na konci řádku (např. osamělé předložky): Sub osamelePredlozky2() Dim slovo As Range, znak As Range, Dim obsah As String, delka As Integer For Each slovo In Selection.Words delka = slovo.End - slovo.Start If delka <= 3 Then Set znak = slovo.Characters(delka) If slovo.Text <> ". " _ And slovo.Text <> ", " _ 40
Objektové modely
And znak.Text = " " Then znak.Text = ChrW(160) end if End If Next End Sub Program pracuje následovně: ve vybraném textu prochází jednotlivá slova (kolekce Words). Délku slova stanoví jako rozdíl poslední a první pozice oblasti slova. Jestliže je slovo kratší než tři znaky, nahradí mezeru za slovem pevnou mezerou (kód 160). Na takové mezeře pak MS Word řádek nezalamuje, tj. slova před tímto druhem mezery nebudou stát na konci řádku. Oblast posledního znaku slova nalezneme snadno pomocí kolekce Characters (vlastnost každé oblasti), jejíž poslední prvek má zřejmě index s hodnotou delka. Poslední podmíněný příkaz je založen na následující konstrukci: součásti slova (prvku kolekce Words) je i oddělovací znak ukončující slovo, většinou tedy mezera. Tato mezera je oním posledním znakem, jehož hodnotu vyměníme za kód nezlomitelné mezery. Bohužel, tvůrci aplikace za další slovo považují i interpunkci (čárka, tečka, středník apod.). Za tato "slova" pochopitelně pevnou mezeru dávat nesmíme.
5.2
Použití objektového modelu z jiné aplikace
Občas je výhodné využít známý objektový model i z jiné aplikace, která má objektový model jiný. Používáme přitom obvykle postup pozdní vazby (použili jsme ho již v objektu FileSystemObject). Předpokládejme, že potřebujeme v programu v prostředí MS Excel načíst věty z textového dokumentu a vložit je do série buněk v listu. Implementace řešení problému může být následující: Sub CtiVety() Dim nazev As String, i As Integer Dim mujWord As Object, mujDokument As Object Dim slovo As Object nazev = InputBox("zadej název dokumentu .docx") Set mujWord = CreateObject("Word.Application") mujWord.Visible = True Set mujDokument = mujWord.Documents.Open _ (Filename:=nazev, ReadOnly:=True) i = 0 For Each veta In mujDokument.Sentences i = i + 1 Worksheets(1).Cells(i, 1).Value = veta.Text Next mujDokument.Close mujWord.Quit Set mujDokument = Nothing Set mujWord = Nothing End Sub 41
Informatika • Modul 01 • Algoritmizace a programování
V programu vytvoříme instanci aplikace MS Word metodou pozdní vazby: Set mujWord = CreateObject("Word.Application") Objekt mujWord nyní zastupuje spuštěnou aplikaci, kterou v této fázi nalezneme rovněž v seznamu procesů operačního systému. Celá aplikace může být spuštěna ve skrytém režimu, tj. není zobrazeno žádné okno ani jiný viditelný vizuální prvek. Pokud však chceme vidět, jak náš program funguje, nastavíme atribut Visible objektu na hodnotu True. Potřebný dokument otevřeme metodou Open kolekce Documents: Set mujDokument = mujWord.Documents.Open(nazev) kde parametr nazev obsahuje název souboru včetně cesty. (Pro jeho komfortnější zjištění lze použít objekt FileDialog – viz dříve.) Bezpečnostní bariéry nám však obvykle povolí programově otevřít dokument pouze v režimu "jen pro čtení" (Read Only). K tomu se zobrazí panel žádající o povolení operace. Pokud spustíme aplikaci ve skrytém režimu, nevidíme ani okno s dokumentem ani panel, přesto bude aplikace čekat na odpověď uživatele. Abychom se těmto problémům vyhnuli, otevřeme dokument přímo v režimu pro čtení: Set mujDokument = mujWord.Documents.Open _ (Filename:=nazev, ReadOnly:=True) Metoda Open má množství parametrů, proto použijeme jejich názvy, abychom mohli naplnit pouze požadované hodnoty. Ostatní příkazy programu jsou již snadno pochopitelné, procházíme kolekci vět v dokumentu a jejich obsah ukládáme do patřičných buněk listu. Nakonec uzavřeme dokument metodou Close a ukončíme aplikaci metodou Quit. Objektové proměnné uvolníme přiřazením klíčového slova Nothing (není nezbytné, ale programátoři se snaží nic neponechat náhodě).
42