Události v Excelu
|
Jak již bylo řečeno hned v úvodu článků o VBA, objekty modelu podporují nejen metody a vlastnosti, ale i události, tj. umí reagovat na změnu (klepnutí myši, přechod na jiný list, obsahu buňky, ukládání sešitu apod.). Pod objektem si přitom můžete představit aplikaci Excel, sešit, listy ale i ovládací prvky ActiveX. Využití některých metod si dnes ukážeme. Události na úrovni aplikaceNarazili jsem hned na to nejtěžší, alespoň z pohledu teorie. Jak poznáte dále, události sešitu i jeho listů jsou programátorovi dostupné v příslušných modulech. Aplikace ale nic takového nemá. Ono běžně ani není třeba události na úrovni aplikace zpracovávat a pokud ano, pak je nutné zajistit nastartování sledovacích procedur při každém spuštění Excelu. To se dá zařídit prakticky jen dvěma způsoby - šablonou nebo doplňkem. VBA znalí programátoři mi snad odpustí poněkud neúplný další výklad, resp. komentář k ukázce. Ke sledování událostí na úrovni samotné aplikace používáme tzv. modul třídy (Class Module). Vkládáme jej stejně jako standardní moduly s pomocí ikony na panelu nebo z menu Insert / Class Module). Excelem navržený název modulu Class1 doporučuji vzápětí ručně přepsat na smysluplnější. Děje se tak v okně Properties. V daném případě jsem zvolil název UdalostiAppClass. ![]() V hlavním okně modulu třídy vepíšeme hned zkraje následující kód: Public WithEvents Aplikace As ApplicationAno, jedná se o deklaraci veřejně dostupného objektu Aplikace typu aplikace, kdy klíčové slovo WithEvents říká, že si přejeme podporu událostí. V momentě, kdy tento kód jak se říká odentrujeme, levá horní roletka okna začne tento objekt nabízet k použití a její sestřička napravo doplní události pro tento objekt. Výchozí událostí je NewWorkbook (Excel ji hned nabídne při výběru položky Aplikace z roletky).
![]() Kód pro tuto proceduru může vypadat následovně: Private Sub Aplikace_NewWorkbook(ByVal Wb As Workbook) MsgBox "Díky za každý nový sešit..." End Sub Ono to ale nestačí, zatím jsme si uložili recepturu na cukroví, musíme ještě podle ní dokázat péct. Odborně řečeno, musíme vytvořit tzv. novou instanci třídy. To už se děje ve standardním modulu. Public UdalostiExcel As UdalostiAppClass Sub IniUdalostiAppClass() Set UdalostiExcel = New UdalostiAppClass Set UdalostiExcel.Aplikace = Application MsgBox "Proběhla inicializace třídy." End Sub Nejprve provedeme deklaraci proměnné Pozn. Za roky zkoušení ve mě stále není stoprocentní důvěra v to, že sledované události neproběhnou pasivně a Excel zareaguje. Navíc k některým událostem může dojít současně a pak je těžké říci, co se stane. Uživatel je ostatně rovněž nevyzpytatelný a nikdy nevíte, ze které strany vám poklepe na rameno... Události na úrovni sešituUdálostí, které je sešit Excelu schopen zaznamenat, je skutečně hodně. Mezi nejpoužívanější patří ![]() Podívejme se na příklady. Private Sub Workbook_Open() MsgBox "Vítejte v sešitu s ukázkami událostních procedur." End Sub Private Sub Workbook_BeforeClose(Cancel As Boolean) MsgBox "Snad Vám tento sešit byl k užitku. Pěkný den." End Sub Zatímco první procedura neočekává žádný parametr, druhá ano. Narozdíl od vlastních funkcí, přestože parametr není uvozen slovem Pozn. Velké množství událostí je typu "Before...". To znamená že náš kód navržený pro událostní procedury proběhne těsně předtím, než k události dojde. Je to logické, pokud si takovou akci přejeme zakázat. Události na úrovni listůProcedury, které mají proběhnout na základě událostí listu, umísťujeme do jejich patřičného modulu. Jsou to události pro konkrétní listy vnímané samostatně. Nejčastěji sem zařazujeme zpracování buněk daného listu na základě jejich změny. Z levé roletky hlavního okna vybereme Worksheet. Excel vloží úvodní kód přednastavené procedury pro událost ![]() Opět se podívejte rovnou na příklad. Vysvětlivku najdete pod výpisem kódu. Private Sub Worksheet_Change(ByVal Target As Range) Dim Oblast As Range 'definice sledované oblasti Set Oblast = Range("B2:D5") 'test výběru If Union(Oblast, Target).Address = Oblast.Address Then MsgBox "Změněna hodnota v buňce " & Target.Address(0, 0) End If End Sub Vidíme, že procedura očekává proměnnou Pozn. Když už jsem načal přirovnání Excelu s ježibabou... ona nevidí do každého koutu. Nenachytala by nás třeba, jak jí chaloupku zdobíme grafiti. Totiž, Excel nebere jako událost změnu vizuálního formátování buňky (barevnost, ohraničení, číselný formát buňky apod.). Další ukázka využívá události dvojkliku. Procedura opět očekává oblast a pravdivostní hodnotu pro proměnnou Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'zakázaná akce
Cancel = True
End Sub
Události prvků ActiveXJak bylo již řečeno, i pro prvky pro formulář UserForm umožňují sledování určitých aktivit, kterých se na nich dopouštíme. Stejně tak samotný UserForm podporuje sledování událostí. Nejdůležitější je událostní procedura Private Sub UserForm_Initialize() 'zde je kód posledních příprav před zobrazením formuláře End SubUdálostí pro prvky ActiveX je mnoho a tak si ukážeme klasický příklad události Click (klepnutí myší) zaškrtávacího políčka (CheckBox). Tato událost je pro většinu prvků výchozí, proto, pokud provedeme dvojklik na prvek v návrhovém zobrazení, Excel nás přenese do prostředí samotného kódu a dosadí obálku pro tuto událostní proceduru. I zde platí, že ostatní události pro daný prvek vybíráme z pravé roletky. Malá ukázka:
Private Sub CheckBox1_Click() MsgBox "Nech mě na pokoji, neklepej na mě!" End Sub ![]() Pozn. Programová změna obsahu prvku má často za následek vyvolání události, přestože ručně k ní nedošlo. Na to je třeba si dávat pozor. Že k tomu, dochází, lze rozpoznat během krokování kódu. Častá úloha aneb příklad na závěrLze zakázat uzavření formuláře klepnutím na křížek v pravém horním rohu?
Ano, je třeba využít zmiňovaný parametr Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) Cancel = True End Sub I zde ale řešení není stoprocentní, neboť existuje možnost přerušení stiskem Ctrl+Break. Je tedy nutné zařadit ještě někde jinde kód Sub UserForm_Initialize()
'vlastní kód
Application.EnableCancelKey = xlDisabled
End Sub
Pozor! V případě nekonečného cyklu nebo jinak chybujícího makra je možnost zrušení běhu procedury velmi důležitá. Nezbavujte se jí. |
Officír pro časopis CHIP.