Activate a Select jsou sesterské metody, se kterými se potkáváme pod VBA. Jejich cílem je zjednodušeně řečeno vybrat objekt. My se budeme zabývat aktivací (výběrem) oblasti buněk a (ouška) listu v Excelu.
Na metodu Select narazíme už ve výstupním kódu ze Záznamníku maker (Excel 2010). Příklad ukazuje výběr Listu1, buňky B5, a následné obarvení jejího pozadí na žluto.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Sub Makro1() ' ' Makro1 Makro ' Sheets("List1").Select Range("B5").Select With Selection.Interior .Pattern = xlSolid .PatternColorIndex = xlAutomatic .Color = 65535 .TintAndShade = 0 .PatternTintAndShade = 0 End With End Sub |
Nahrané makro tedy nejprve vybírá List1 (Select, klepli jsme na ouško listu), buňku B5 (Select, klepli jsme na buňku myší), a následně pracuje s výběrem (Selection, konstrukce With..End With). Jak si ukážeme, celá stavba makra je ale zbytečně komplikovaná a lehce nebezpečná. Navíc, v případě výběru listu bychom se měli bavit spíše o jeho aktivaci (metoda Activate).
Začínající programátor, který příklad odkouká ze Záznamníku maker, pak použije něco v tomto duchu:
1 2 3 4 5 6 7 8 9 10 11 12 13 | Sub KlasickyPriklad() 'aktivace třetího listu Worksheets(3).Activate 'výběr oblasti B2:D6 aktivního listu Range("B2:D6").Select 'práce s pozadím (vybrané oblasti) Selection.Interior.ColorIndex = 6 Selection.Interior.ColorIndex = xlNone End Sub |
Nevýhody
Jestliže zapomenete na aktivaci požadovaného listu a u objektu Range neuvedete rodiče, dosadí si za něj Excel aktivní list.
Pokud nevyberete oblast buněk, může se stát, že pod objektem Selection bude třeba obrázek.
Neustálé přepínaní se mezi listy a výběry buněk velmi výrazně zpomaluje vaši proceduru (dochází k překreslování obrazovky a musíme sáhnout po známé syntaxi Application.ScreenUpdating = False).
Pozn. Výběr nelze provádět na neaktivním listu.
1 2 3 4 5 6 7 8 9 10 | Sub SelectNeaktivniList() 'aktivace prvního listu Worksheets(1).Activate 'výběr nelze provádět na neaktivním listu 'chyba Worksheets(3).Range("B2:D6").Select End Sub |
Rozdíl mezi Activate a Select se dobře demonstruje na oblasti buněk.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Sub RozdilActivateSelect() 'aktivace prvního listu Worksheets(1).Activate 'výběr oblasti B2:D6 aktivního listu Range("B2:D6").Select 'lze, nepoužívá se 'Range("B2:D6").Activate 'aktivace buňky B5 (se zachováním výběru) Range("B5").Activate End Sub |
Ručně lze změny aktivní buňky ve výběru docílit klávesou TAB nebo například klávesovou zkratkou CTRL + . (tečka), která prochází rohové buňky výběru.
A teď průšvih, na který mě upozornil klient v nefunkčním kódu. Představme si, že druhý list ze tří je skryt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Sub BugPrikladA() 'tři listy, druhý skrytý 'aktivace prvního listu Worksheets(1).Activate Worksheets(1).Select 'aktivace druhého viditelného, tedy třetího listu! Worksheets(2).Activate 'chyba: Worksheets(2).Select 'aktivace třetího listu Worksheets(3).Activate Worksheets(3).Select End Sub |
A vyložený bug:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Sub BugPrikladB() 'tři listy, druhý skrytý 'aktivace prvního listu Worksheets(1).Activate 'aktivace druhého viditelného, tedy třetího listu! Worksheets(2).Activate 'při krokování hodnota zapsána do třetího listu! 'při spuštění celé procedury zapsána hodnota do druhého listu! Cells(1) = 10 End Sub |
Abyste měli vše pod kontrolou, zvykněte si používat objektové proměnné (pro přiřazení nutný příkaz Set).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | Sub KlasickyPrikladLepe() Dim wshList As Worksheet Dim rngOblast As Range 'aktivace prvního listu 'zde pouze pro ukázku! Worksheets(1).Activate 'přiřazení třetího listu do objektové proměnné Set wshList = Worksheets(3) 'přiřazení oblasti buněk do objektové proměnné Set rngOblast = wshList.Range("B2:D6") 'žádný Activate pro třetí list... 'žádný Select pro oblast buněk... 'práce s pozadím (vybrané oblasti) 'konstrukce With..End With With rngOblast .Interior.ColorIndex = 6 .Interior.ColorIndex = xlNone End With End Sub |
Uvedenou techniku používejte i v rámci přenosu dat mezi dvěma listy a oblastmi (zpravidla zdroj a cíl). Na aktivní list se sice můžete odvolat jako na ActiveSheet, nicméně tento postup doporučuji jen v případě jistoty volání procedury z daného listu (makro přiřazené tlačítku) nebo u obecných maker. V případě obsluhy dvou různých sešitů definujte objektovou proměnnou i pro ně a nespoléhejte se pokud možno na odkaz ActiveWorkbook (aktivní sešit). Naopak vhodný je odkaz na ThisWorkbook (sešit nebo doplněk, z něhož je makro voláno). K aktivní buňce (aktivního listu) můžete přistoupit přes ActiveCell. Objektovou proměnnou na úrovni aplikace se zde nebudeme zabývat.
Pozn. Pro objekt ActiveSheet nefunguje pod VBA automatický seznam členů (nabídka po zápisu tečky).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Sub AktivniObjekty() Dim wkbSesit As Workbook Dim wshList As Worksheet Dim rngBunka As Range 'přiřazení aktivního sešitu do objektové proměnné Set wkbSesit = ActiveWorkbook 'přiřazení sešitu, v němž leží tato procedura 'do objektové proměnné 'Set wkbSesit = ThisWorkbook 'přiřazení aktivního listu do objektové proměnné Set wshList = ActiveSheet 'přiřazení aktivního buňky do objektové proměnné Set rngBunka = ActiveCell End Sub |
Ačkoliv to v proceduře uvedeno není, nezapomínejte na konci práce korektně objektové proměnné „resetovat“ (uvolňovat pro ně vyhrazenou paměť) příkazem Set objPromenna = Nothing.
Tipy pro odkazy na sešit a oblast buněk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Sub TipyNaOdkazy() Dim wshList As Worksheet Dim rngOblast As Range 'není vhodné spoléhat se na pořadí 'nepřehledné Set wshList = Worksheets(3) 'lépe je použít název Set wshList = Worksheets("List3") 'nejlepší je odkazovat se na kódové jméno listu 'kdy není potřeba ani objektová proměnná 'viz VBA, okno Properies 'vlastnost Name pro vybraný modul listu wshMujList.Range("B10") = "mrkev" 'odkaz na pojmenovanou buňku 'viz Definované názvy na listu wshMujList.Range("MojeBunka") = "celer" End Sub |
V případě kódového jména listu se tak nemusíte bát, že vám někdo listu přejmenuje. Odkaz na pojmenovanou buňku zajistí platnost odkazu i v případě posunu buňky.
Zlozvyk číslo jedna máte tedy za sebou a nyní k dalšímu – kopírování hodnot.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Sub PrikladKopirovaniHodnoty() 'aktivace prvního listu Worksheets(1).Activate 'zkopírování buňky B5 Range("B5").Copy 'aktivace třetího listu Worksheets(3).Activate 'vložení hodnoty do buňky B10 Range("B10").PasteSpecial (xlPasteValues) 'zrušení režimu kopírování Application.CutCopyMode = False End Sub |
Pokud kopírujeme něco jiného, než čistě hodnotu, pak se práci s Copy/Paste nevyhneme. Nicméně pro přenos hodnot/vzorců (Value, Formula) se nabízí mnohem efektivnější způsob.
1 2 3 4 5 6 | Sub PrikladKopirovaniHodnotyLepe() 'přímé převzetí obsahu buňky Worksheets(3).Range("B10").Value = Worksheets(1).Range("B5").Value End Sub |
Jak prosté. I zde bychom měli lépe řídit zdroj a cíl přes objektovou proměnnou. Podotýkám, že takto je možné pracovat i se skrytým listem.
Pozn. Metoda Copy umožňuje přímé zadání cíle.
1 2 3 4 5 6 | Sub PrikladKopirovaniBunky() 'překopírování buňky Worksheets(1).Range("B5").Copy Worksheets(3).Range("B10") End Sub |
Nyní příklady na vytváření nového sešitu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Sub NovySesit() 'vytvoření nového sešitu 'stane se aktivním Workbooks.Add 'práce s novým sešitem... ActiveWorkbook.Worksheets(1).Cells(1) = 10 End Sub Sub NovySesitLepe() Dim wkbNovySesit As Workbook 'vytvoření nového sešitu 'a jeho přiřazení do objektové proměnné Set wkbNovySesit = Workbooks.Add 'práce s novým sešitem... wkbNovySesit.Worksheets(1).Cells(1) = 10 End Sub |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Sub NovySesitZKopieListu() 'vytvoření nového sešitu z kopie stávajícího listu Worksheets(1).Copy 'práce s listem... ActiveSheet.Cells(1) = 10 End Sub Sub NovySesitZKopieListuLepe() Dim wshSesit As Workbook Dim wshList As Worksheet 'vytvoření nového sešitu z kopie stávajícího listu 'a jeho přiřazení do objektové proměnné 'nelze uskutečnit, metoda Copy nevrací objekt 'Set wshList = Worksheets(1).Copy 'vytvoření nového sešitu z kopie stávajícího listu Worksheets(1).Copy 'přiřazení aktivního listu do objektové proměnné Set wshList = ActiveSheet 'přiřazení sešitu do objektové proměnné (odkaz na rodiče) Set wshSesit = wshList.Parent 'alternativně 'Set wshSesit = ActiveWorkbook 'práce s listem... wshList.Cells(1) = 10 End Sub |
Doufám tedy, že tímto článkem už jste si „vybrali“ tu správnou cestu a že daný režim zůstane „aktivován“. A nezapomínejte, že Záznamník maker je dobrý sluha i pro pokročilé programátory, ale špatný pán.