

Jinou možností je vytvořit si certifikát.


Změna zabezpečení se projeví až po zavření a otevření aplikace Word nebo Excel.

















Zamknou se jednotlivé listy s formulářem pomocí nabídky na kartě Revize.

Po zamknutí není možné vkládat informace do buněk kromě tech, které jsou propojené s ovládacími prvky, a ty se mění podle toho, jak uživatel nastaví propojený ovládací prvek.
Formuláře vrácené od respondentů se zpracují tak, aby vznikla excelovská tabulka s řádky patřícími jednotlivým respondentům a sloupky patřícími jednotlivým otázkám. Pro tuto úlohu existuje doplněk aplikace Excel zvaný Průvodce šablonou se sledováním dat, který již není dodáván s programovým balíkem MS Office a od roku 2012 již ani není oficiálně dostupný na stránkách firmy Microsoft.
Doplněk se jmenuje WZTEMPLT.XLA a je ve formě samorozbalovacího programu TMPLWIZ.EXE, ale po jeho spuštění kliknutím na něj se soubory v něm zabalené nikde neobjeví kvůli nekompatibilitě s novými operačními systémy Windows. Proto je nutné soubory z něj vyjmout nějakou externí aplikací, například programem 7-Zip.

V adresáři, kde Excel hledá dodatečné doplňky, se vytvoří adresář TemplateWizard a do něj se zkopírují soubory z archivu TMPLWIZ.EXE.

Použití je zhruba takové, že se doplněk připojí k aplikci Excel,




potom se na pásu karet objeví nová karta Doplňky s tlačítkem Template Wizard.

Po kliknutí na tlačítko Template Wizard se určí název a umístění šablony, kterou průvodce vytvoří,

název a umístění databáze (výsledné tabulky s daty formulářů), kterou průvodce vytvoří,

nadefinují se buňky ve formuláři, které obsahují data formulářů.

Průvodce také umožňuje více souborů s vyplněnými dotazníky uložit do databáze najednou.





Výsledná databáze je umístěna v adresáři, který byl nastaven pomocí průvodce.

Ve starších verzích Excelu fungovalo ještě otevření formuláře na základě šablony vytvořené Průvodcem šablonou se sledováním dat (pomocí nabídky Nový pod Tlačítkem Office),

po jehož vyplnění a uložení se data automaticky odeslala do databáze. V případě, že budou data sbírána rozesláním formulářů a jejich následným hromadným zpracováním, je to však funkčnost, kterou nepotřebujeme.
Vhodné akce pro makra:
Například
Range("a1").Select

Jen málokdy je nutné přistupovat k objektu vypsáním celé hierarchie:
Application.ActiveWorkbook.ActiveSheet.Range("a1").Value = "ahoj"
Chceme-li vyplnit buňku A1 na aktivním listu, tak stačí kód
Range("a1").Value = "ahoj"
Chceme-li vyplnit buňku na jiném než aktivním listu, musíme tento list do hierarchie uvést a to lze 2 způsoby:
Worksheets(1).Range("a1").Value = "ahoj"Worksheets("List1").Range("a1").Value = "ahoj"Range("a1").Select
Typickým použitím funkce je výpočet hodnoty a její předání do proměnné. i = Len("ahoj")
Programy obsahují názvy (identifikátory) objektů, metod, vlastností a procedur, konstanty, proměnné, řídící struktury a komentáře.ActiveWindow.WindowState = xlMaximizedV podobných příkazech jsou možné konstanty nabízeny funkcí IntelliSense, takže si je není třeba pamatovat.
Const DISCOUNT As Single = 0.4Konstantami mohou být pouze primitivní datové typy a řetězce, nikoliv objekty.
Do proměnné lze přiřadit
Option ExplicitProměnné je možné deklarovat kdekoli v kódu, ale je dobrým zvykem deklarovat je na začátku programu.
Dim inebo jméno i datový typ proměnné
Dim i As IntegerDeklarování jména spolu s datovým typem proměnné je lepší než neúplná nebo žádná deklarace, protože
Dim a, b As Integerje a typu Variant, protože jeho typ nebyl deklarován, a b je typu Integer.
Dim a As Integer, b As Integer
"první řádek" & _
"druhý řádek"
Řídící struktury by se měly zvýrazňovat odsazováním řádků podle příkladů z nápovědy.
MsgBox(prompt[, buttons] [, title] [, helpfile, context])Funkce MsgBox má argumenty pojmenované prompt, buttons, title, helpfile, context.
MsgBox "Ahoj", , "Pozdrav"

MsgBox Title:="Pozdrav", prompt:="Ahoj"Jsou-li argumenty pojmenované, je možné je uvádět v libovolném pořadí. Smysluplné použití je však v situaci, kdy z nabízeného většího množství argumentů potřebujeme specifikovat jen několik málo.
a = MsgBox("Ahoj", vbAbortRetryIgnore + vbExclamation + vbDefaultButton3, "Pozdrav")

a = MsgBox("Ahoj", 562, "Pozdrav")
Je lepší první způsob volání message boxu, protože
b = InputBox("Zadej něco", "Zadávání", "něco")

a = InputBox("Zadej číslo", "Zadávání")
b = InputBox("Zadej číslo", "Zadávání")
MsgBox a + b
se v message boxu objeví zřetězení zadaných čísel a ne jejich součet.
a = Val(InputBox("Zadej něco", "Zadávání"))
b = Val(InputBox("Zadej něco", "Zadávání"))
MsgBox a + b
Kdybychom hodnoty číselného typu sčítali pomocí operátoru & pro zřetězení, objevilo by se v message boxu opět zřetězení zadaných čísel a ne jejich součet.
a = Val(InputBox("Zadej něco", "Zadávání"))
b = Val(InputBox("Zadej něco", "Zadávání"))
MsgBox a & b
Další možností, jak zajistit součet hodnot zadaných do input boxu místo zřetězení, je určení typu proměnných v jejich deklaraci. Potom nepotřebujeme funkci Val.
Dim a As Integer, b As Integer
a = InputBox("Zadej něco", "Zadávání")
b = InputBox("Zadej něco", "Zadávání")
MsgBox a + b
Detaily o chování operátorů + a & jsou na stránce http://msdn.microsoft.com/en-us/library/te2585xw%28VS.80%29.aspx.c = Application.InputBox("Zadej číslo:", Type:=1)
Z příkladu je vidět, že i když je Application.InputBox metoda, používá se jako funkce.c = Application.InputBox("Zadej číslo", Type:=1 + 2)
Všechny možné hodnoty pro argument Type jsou rovny mocninám čísla 2. Tato vlastnost umožňuje, aby všechny možné množiny hodnot měly odlišný součet, a tak lze podle součtu identifikovat množinu hodnot.
Option Explicit
Dim a As Integer
Sub Hlavní()
a = Application.InputBox("Zadej číslo:", Type:=1)
Ztrojnásob
MsgBox a, , "Hlavní"
End Sub
Sub Ztrojnásob()
a = a * 3
MsgBox a, , "Ztrojnásob"
End Sub
Volaná procedura může být kdekoli (před i za volající procedurou) ve stejném modulu.
Option Explicit
Dim a As Integer, b As Integer
Sub Hlavní()
a = Application.InputBox("Zadej číslo:", Type:=1)
b = Application.InputBox("Zadej číslo:", Type:=1)
Ztrojnásob_a
Ztrojnásob_b
MsgBox "a = " & a & Chr(13) & Chr(10) & "b = " & b, , "Hlavní"
End Sub
Sub Ztrojnásob_a()
a = a * 3
MsgBox a, , "Ztrojnásob_a"
End Sub
Sub Ztrojnásob_b()
b = b * 3
MsgBox b, , "Ztrojnásob_b"
End Sub
Ve třetím příkladu subprocedura Hlavní již skutečně předává argument subproceduře Ztrojnásob.
Option Explicit
Sub Hlavní()
Dim a As Integer, b As Integer
a = Application.InputBox("Zadej číslo:", Type:=1)
b = Application.InputBox("Zadej číslo:", Type:=1)
Ztrojnásob a
Ztrojnásob b
MsgBox "a = " & a & Chr(13) & Chr(10) & "b = " & b, , "Hlavní"
End Sub
Sub Ztrojnásob(x As Integer)
x = x * 3
MsgBox x, , "Ztrojnásob"
End Sub
Čtvrtý příklad se od třetího liší v tom, že při volání subprocedury Ztrojnásob je její argument v závorkách. Kdyby měla subprocedura Ztrojnásob argumentů víc než jeden, nebylo by možné je dát do závorek a řešilo by se to dle šestého příkladu.
Option Explicit
Sub Hlavní()
Dim a As Integer, b As Integer
a = Application.InputBox("Zadej číslo:", Type:=1)
b = Application.InputBox("Zadej číslo:", Type:=1)
Ztrojnásob (a)
Ztrojnásob (b)
MsgBox "a = " & a & Chr(13) & Chr(10) & "b = " & b, , "Hlavní"
End Sub
Sub Ztrojnásob(x As Integer)
x = x * 3
MsgBox x, , "Ztrojnásob"
End Sub
Třetí a čtvrtý příklad se liší způsobem předávání argumentů. Oba dva druhy jejich odlišného chování jsou v některých situacích potřebné.
Option Explicit
Sub Hlavní()
Dim a As Integer, b As Integer
a = Application.InputBox("Zadej číslo:", Type:=1)
b = Application.InputBox("Zadej číslo:", Type:=1)
Ztrojnásob a
Ztrojnásob b
MsgBox "a = " & a & Chr(13) & Chr(10) & "b = " & b, , "Hlavní"
End Sub
Sub Ztrojnásob(ByVal x As Integer)
x = x * 3
MsgBox x, , "Ztrojnásob"
End Sub
Někdy je předáváných argumentů víc než jeden a některé se mají předat odkazem a některé hodnotou, viz šestý příklad.
Option Explicit
Sub Hlavní()
Dim a As Integer, b As Integer
a = Application.InputBox("Zadej číslo:", Type:=1)
b = Application.InputBox("Zadej číslo:", Type:=1)
Ztrojnásob a, b
MsgBox "a = " & a & Chr(13) & Chr(10) & "b = " & b, , "Hlavní"
End Sub
Sub Ztrojnásob(ByVal x As Integer, ByRef y As Integer)
x = x * 3
y = y * 3
MsgBox "x = " & x & Chr(13) & Chr(10) & "y = " & y, , "Ztrojnásob"
End Sub
Option Explicit
Sub PracujSListy(Listy As Variant, Hodnota As Variant)
Dim IndexListu As Byte
Dim ListSešitu As Worksheet
Dim Zpráva As String
Zpráva = ""
IndexListu = LBound(Hodnota)
For Each ListSešitu In Listy
ListSešitu.Cells(1) = Hodnota(IndexListu)
Zpráva = Zpráva & ListSešitu.Name & vbCrLf
IndexListu = IndexListu + 1
Next ListSešitu
MsgBox Zpráva
Listy.Select
End Sub
Sub PráceSeSkupinouListů()
PracujSListy Worksheets(Array(1, 3)), Array(5, 10)
End Sub
Sub Ukaž_Formulář()
UserForm1.Show
End Sub
Formulář se skryje ale zůstává v paměti a je možné s ním manipulovat makry pomocí příkazu UserForm1.Hide.Label - PopisSlouží pro zobrazování informací pro uživatele. | |
TextBox - Textové poleSlouží pro zadávání informací uživatelem a zobrazování informací, které může uživatel vybrat a kopírovat jinam. | |
ComboBox - Pole se seznamemSlouží pro výběr položky ze seznamu a zadání položky uživatelem. | |
ListBox - SeznamSlouží pro výběr položky ze seznamu.Pole se seznamem a Seznam mají vestavěný Posuvník, viz níže, který se na nich objeví, přesáhne-li počet položek hodnotu vlastnosti ListRows. | |
CheckBox - Zaškrtávací políčkoSlouží pro zadávání informace o hodnotě jeden bit. | |
OptionButton - PřepínačSlouží pro výběr položky ze seznamu, neboli jednoho přepínače ze skupiny přepínačů.Musí se vyskytovat ve skupinách nikoli jednotlivě. Skupiny jsou tvořeny vlastností GroupName nebo jejich umístěním do rámečku. Volně umístěné přepínače se také chovají jako jedna skupina. | |
Frame - RámečekTvoří skupinu z přepínačů.Graficky odděluje části formuláře pro jeho lepší přehlednost. Při tvorbě formuláře umožňuje manipulovat s prvky v něm umístěnými jako s jedním celkem. | |
ScrollBar - PosuvníkSlouží pro plynulé zadávání hodnot z daného rozpětí. | |
SpinButton - ČíselníkSlouží pro zadávání hodnot z daného rozpětí měněných po určitém kroku, například je tak vhodné realizovat zvýšení ceny o 50 haléřů.Inkrementace v oboru jiném než celočíselném se však musí odvozovat z celočíselných hodnot, které jediné jsou přípustné pro vlastnost Value prvku Číselník i Posuvník. Číselník musí být kódem makra propojen s nějakým prvkem zobrazujícím výsledek kliknutí na něj, typicky s Textovým polem. Některé produkty mají tento prvek již v této kombinaci a nazývají jej Spinner. | |
CommandButton - Příkazové tlačítkoSlouží pro spuštění maker. | |
ToggleButton - Přepínací tlačítkoZobrazuje, zda je tlačítko zamáčklé nebo vymáčklé. | |
TabStrip - KartySlouží pro zobrazování datových vět na jednotlivých kartách.Ovládací prvky se na něj přetáhnou jen jednou a potom se zobrazují na všech kartách stejně. Musí se k němu napsat kód propojující jej s tabulkou dat. | |
MultiPage - Vícenásobná stránkaSlouží pro organizaci ovládacích prvků do více stránek, ze kterých si může uživatel vybírat.Na rozdíl od prvku Karty může být na každé stránce jiný obsah. | |
Image - ObrázekSlouží pro zobrazování obrázků. | |
RefEditTento prvek se musí na soupravu nástrojů přidat dodatečně, viz výše.Slouží pro zadávání oblastí buněk, se kterými potom mohou pracovat makra. |

ActiveCell.FormulaR1C1 = "=UPPER(RC[-1])"Název funkce je tedy UPPER. Nejdříve se podíváme do seznamu funkcí VBA v nápovědě. Tam funkce Upper není, ale je tam funkce UCase, která dle nápovědy dělá to, co dělá funkce UPPER. Nahraný název tedy nemusí vždy s hledanou funkcí souhlasit. V seznamu Worksheet Functions funkce UPPER ani funkce UCase není.
ActiveCell.FormulaR1C1 = "=TRIM(RC[-1])"Název funkce je tedy TRIM. V seznamu funkcí VBA funkce Trim je, ale odřezává pouze krajní mezery. V seznamu Worksheet Functions funkce Trim také je, a protože je v tomto seznamu, bude mít i stejné chování jako funkce PROČISTIT. Rozdílné chování funkce TRIM můžeme sledovat v tomto makru:
Sub Pročisti()
Dim a As String, b As String
a = " a a "
a = Trim(a)
b = " b b "
b = WorksheetFunction.Trim(b)
End Sub
Chceme-li použít funkci listu, musíme v kódu VBA před ni napsat předponu WorksheetFunction. Funkce listu je metodou objektu WorksheetFunction, který je vlastností objektu Application
Function Fahrenheit(Celsius As Double) As Double
Fahrenheit = Celsius * 9 / 5 + 32
End Function
je možné ji použít jako funkci listu z nabídky kategorie funkcí vlastní,
Sub CelsiusToFahrenheit()
Dim c As Double
c = Application.InputBox("Zadej stupně Celsia", Type:=1)
MsgBox c & " stupňů Celsia = " & Fahrenheit(c) & " stupňů Fahrenheita."
End Sub
Function Fahrenheit_A1() As Double
Fahrenheit_A1 = Range("a1") * 9 / 5 + 32
End Function
Přepočítávaní takové funkce lze zajistit přidáním příkazu Application.Volatile na první řádek funkce.
Function Fahrenheit_A1() As Double
Application.Volatile
Fahrenheit_A1 = Range("a1") * 9 / 5 + 32
End Function
Funkce s metodou Application.Volatile se však na rozdíl od normálních funkcí přepočítává po změně každé buňky na listu (nejen jejích vstupních buněk), což může znamenat přílišnou výpočetní zátěž.
Function Kolikrát(Co As String, Kde As Range) As Integer
Dim Buňka As Range
Kolikrát = 0
For Each Buňka In Kde
If Buňka.Value = Co Then Kolikrát = Kolikrát + 1
Next Buňka
End Function
Function Podmnožina(x As Range, y As Range) As Boolean
Dim BuňkaX As Range, BuňkaY As Range
Podmnožina = False
For Each BuňkaX In x
For Each BuňkaY In y
If BuňkaX = BuňkaY And BuňkaX <> "" Then
Podmnožina = True
Exit Function
End If
Next BuňkaY
Next BuňkaX
End Function
Function Pozpátku(x As String) As String
Dim i As Integer
Pozpátku = ""
For i = 1 To Len(x)
Pozpátku = Pozpátku & Mid(x, Len(x) - i + 1, 1)
Next i
End Function
Function MocninaMatice(x As Range, y As Byte) As Variant
Dim i As Byte
MocninaMatice = x
For i = 1 To y - 1
MocninaMatice = WorksheetFunction.MMult(MocninaMatice, x)
Next i
End Function
Function DnyHodinyMinutySekundy(x As Long) As Variant
Dim b(1 To 4) As Long, SekundVeDni As Long
SekundVeDni = CLng(60) * 60 * 24 '= 86400. Bez CLng (typová konverze) to přeteče.
b(1) = x \ SekundVeDni 'Početní úkony pro každou proměnnou: zpětné lomítko znamená v jazyce VBA opearci DIV (celočíselné dělení bez zbytku).
b(2) = (x - SekundVeDni * b(1)) \ 3600
b(3) = (x - SekundVeDni * b(1) - 3600 * b(2)) \ 60
b(4) = x - SekundVeDni * b(1) - 3600 * b(2) - 60 * b(3)
DnyHodinyMinutySekundy = b
End Function
Function NejbližšíPátek13(ByVal Datum As Date) As Date 'Pokud není uvedeno ByVal, je předáváno jako ByRef.
While Not (Day(Datum) = 13 And Weekday(Datum) = vbFriday)
Datum = Datum + 1
Wend
NejbližšíPátek13 = Datum
End Function
Funke má jako vstup datum, který je číslem, které je vhodné v buňce naformátovat jako datum, a jako výstup Integer.
Function ZaKolikDníJeNejbližšíPátek13(Datum As Date) As Integer
Dim DatumNejbližšíhoPátku13 As Date
DatumNejbližšíhoPátku13 = NejbližšíPátek13(Datum) 'Volání předchozí funkce
ZaKolikDníJeNejbližšíPátek13 = DatumNejbližšíhoPátku13 - Datum
End Function
Sub MakroChyba1()
Dim Oblast As Range
Dim a As Integer, b As Integer
On Error Resume Next
Set Oblast = Application.InputBox("Vyber buněčnou oblast:", Type:=8)
If Oblast Is Nothing Then MsgBox "Nebyla vybána buněčná oblast." Else Oblast.Select
a = Application.InputBox("Zadej čitatel:", Type:=1)
b = Application.InputBox("Zadej jmenovatel různý od 0:", Type:=1)
MsgBox a & " / " & b & " = " & a / b
End Sub
Pokud nějaký příkaz následující kdekoli za příkazem On Error Resume Next způsobí běhovou chybu, program pokračuje v chodu od následujícího příkazu.
Sub MakroChyba2()
Dim Oblast As Range
Dim a As Integer, b As Integer
On Error Resume Next
Set Oblast = Application.InputBox("Vyber buněčnou oblast:", Type:=8)
If Oblast Is Nothing Then MsgBox "Nebyla vybána buněčná oblast." Else Oblast.Select
On Error GoTo 0
a = Application.InputBox("Zadej čitatel:", Type:=1)
b = Application.InputBox("Zadej jmenovatel různý od 0:", Type:=1)
MsgBox a & " / " & b & " = " & a / b
End Sub
Zachytávání chyb by mělo být zapnuto pouze v problémových částech kódu. Jinak se může stát, že nebudou odhaleny sémantické chyby, které lze řešit.
Sub MakroChyba3()
Dim Oblast As Range
Dim a As Integer, b As Integer
On Error Resume Next
Set Oblast = Application.InputBox("Vyber buněčnou oblast:", Type:=8)
If Oblast Is Nothing Then MsgBox "Nebyla vybána buněčná oblast." Else Oblast.Select
On Error GoTo 0
a = Application.InputBox("Zadej čitatel:", Type:=1)
Do
b = Application.InputBox("Zadej jmenovatel různý od 0:", Type:=1)
Loop Until b <> 0
MsgBox a & " / " & b & " = " & a / b
End Sub
Příkaz On Error Resume Next se používá v případě, že příkaz, ve kterém nastala běhová chyba, chceme pouze přeskočit a pokračovat následujícím příkazem. Někdy však potřebujeme běhovou chybu ošetřit větším množstvím příkazů. Potom potřebujeme vytvořit větev programu, která se provede jen v případě běhové chyby. Vstup do této větve programu se obvykle provádí pomocí návěští (label)
Sub MakroChyba4()
Dim Oblast As Range
Dim a As Integer, b As Integer
On Error GoTo ErrorHandler
Set Oblast = Application.InputBox("Vyber buněčnou oblast:", Type:=8)
On Error GoTo 0
Oblast.Select
a = Application.InputBox("Zadej čitatel:", Type:=1)
Do
b = Application.InputBox("Zadej jmenovatel různý od 0:", Type:=1)
Loop Until b <> 0
MsgBox a & " / " & b & " = " & a / b
Exit Sub
ErrorHandler:
MsgBox "Nebyla vybána buněčná oblast." & Chr(13) & Chr(10) & "Bude vybána buněčná oblast automaticky."
Set Oblast = Range("a1:b2")
Resume Next
End Sub
Dojde-li v příkazu Set Oblast = Application.InputBox("Vyber buněčnou oblast:", Type:=8) k běhové chybě, vykonávání kódu se přesune na návěští ErrorHandler:
Sub MakroChyba5()
Dim Oblast As Range
Dim a As Integer, b As Integer
On Error Resume Next
Set Oblast = Application.InputBox("Vyber buněčnou oblast:", Type:=8)
If Err.Number <> 0 Then
MsgBox "Nebyla vybána buněčná oblast." & Chr(13) & Chr(10) & "Bude vybána buněčná oblast automaticky."
Set Oblast = Range("a1:b2")
End If
On Error GoTo 0
Oblast.Select
a = Application.InputBox("Zadej čitatel:", Type:=1)
Do
b = Application.InputBox("Zadej jmenovatel různý od 0:", Type:=1)
Loop Until b <> 0
MsgBox a & " / " & b & " = " & a / b
End Sub
Příkaz On Error GoTo 0 a dle nápovědy i Resume Next, Exit Sub, Exit Function a Exit Property nastaví hodnotu vlastnosti Number objektu Err na nulu, což lze udělat i příkazem Err.Clear.Následující kód lze přiřadit tlačítku na formuláři typu UserForm, které po kliknutí na něj posune vybranou oblast na listu i s formátováním o řádek nahoru.
Option Explicit
Private Sub CommandButton1_Click()
Dim Oblast As Range
Dim List As Worksheet
On Error Resume Next 'Můžeme zapomenout vybrat oblast.
Set Oblast = Range(RefEdit1.Value)
On Error GoTo 0
If Oblast Is Nothing Then
MsgBox "Musíte vybrat oblast!"
Else
Set list = Oblast.Worksheet
List.Activate 'Musíme vybrat list, abychom na něm mohli použít metodu Select.
Oblast.Cut
On Error Resume Next 'Můžeme se posunout za okraj listu.
Oblast.Offset(-1, 0).Select
If Err.Number = 0 Then
ActiveSheet.Paste
RefEdit1.Value = Selection.Address
End If
On Error GoTo 0
End If
End Sub
Function MojeDěleníNeošetřené(Čitatel As Double, Jmenovatel As Double) As Double
MojeDěleníNeošetřené = Čitatel / Jmenovatel
End Function
Function MojeDěleníOšetřené(Čitatel As Double, Jmenovatel As Double) As Variant 'Funkce vracející též chybovou hodnotu musí mít návratový typ Variant.
'MojeDěleníOšetřené = IIf(Jmenovatel = 0, CVErr(xlErrDiv0), Čitatel / Jmenovatel) 'Funkci IIf nelze použít, protože dle nápovědy vyhodnocuje vždy všechny 3 své části.
If Jmenovatel = 0 Then MojeDěleníOšetřené = CVErr(xlErrDiv0) Else MojeDěleníOšetřené = Čitatel / Jmenovatel
End Function
Sub TestChyby()
Dim a As Variant
'If IsError(MojeDěleníNeošetřené(3, 0)) Then If CVErr(MojeDěleníNeošetřené(3, 0)) = CVErr(xlErrValue) Then MsgBox "Chyba!" 'Volání funkce s neošetřenou chybou skončí běhovou chybou při vykonávání funkce.
'Výsledek funkce CVErr se musí porovnávat s chybou, jinak nastane chyba typu Type mismatch, proto se musí porovnávaná hodnota předem otestovat na chybu funkcí IsError.
If IsError(Range("a1")) Then MsgBox "Nějaká chyba v buňce!"
If IsError(Range("a1")) Then If Range("a1") = CVErr(xlErrValue) Then MsgBox "Chyba!" 'V buňce A1 je vzorec "=MojeDěleníNeošetřené(3;0)"
If IsError(Range("a2")) Then If Range("a2") = CVErr(xlErrDiv0) Then MsgBox "Dělení nulou!" 'V buňce A2 je vzorec "=MojeDěleníOšetřené(3;0)"
If IsError(MojeDěleníOšetřené(3, 0)) Then MsgBox "Nějaká chyba ve volané funkci!"
If IsError(MojeDěleníOšetřené(3, 0)) Then If MojeDěleníOšetřené(3, 0) = CVErr(xlErrDiv0) Then MsgBox "Dělení nulou!"
a = MojeDěleníOšetřené(3, 0) 'Lepší než předchozí řádek.
If IsError(a) Then If a = CVErr(xlErrDiv0) Then MsgBox "Dělení nulou!"
End Sub
Sub TestChybyVBuňce()
Dim HodnotaVBuňce As Variant
HodnotaVBuňce = ActiveCell.Value
If IsError(HodnotaVBuňce) Then
Select Case HodnotaVBuňce
Case CVErr(xlErrDiv0): MsgBox "Dělení nulou!"
Case CVErr(xlErrNA): MsgBox "Nedostupná hodnota!" 'Například chyba funkce SVYHLEDAT
Case CVErr(xlErrName): MsgBox "Chyba ve jménu funkce nebo argumentu!"
Case CVErr(xlErrNull): MsgBox "Chybně zadaná oblast!" 'http://spreadsheets.about.com/od/formulatips/qt/null_error.htm
Case CVErr(xlErrNum): MsgBox "Výsledek přetekl!" 'http://www.databison.com/index.php/excel-na-ref-name-div0-null-value-num-error/
Case CVErr(xlErrRef): MsgBox "Oblast v odkazu byla vymazána!" 'http://spreadsheets.about.com/od/formulatips/qt/REF_error.htm
Case CVErr(xlErrValue): MsgBox "Chybná hodnota!"
Case Else: MsgBox "Jiná chyba!"
End Select
Else: MsgBox "Ve vybrané buňce není chyba."
End If
End Sub
Excel označuje buňky s možnou chybovou hodnotou malým zeleným trojůhelníčkem v jejich horním levém rohu. U vybrané buňky s chybovou hodnotou je tlačítko If Range("a1").Errors.Item(xlEvaluateToError).Value = True Then MsgBox "Chybová hodnota!"
Buňka obsahuje objekt Errors, což je kolekce možných chyb, neboť v jedné buňce může být víc chyb (například zároveň chybová hodnota a vzorec odlišný od ostatních vzroců ve sloupci). Je nutné testovat jednotlivě, zda buňka obsahuje určitou chybu z množiny možných chyb, tak že právě testovanou chybu označíme vestavěnou konstantou výčtového typu xlErrorChecks. Následující kód vypíše všechny chyby v aktivní buňce.
Sub TestováníChyb()
Dim Zpráva As String
Zpráva = ""
If ActiveCell.Errors.Item(xlEvaluateToError).Value = True Then Zpráva = Zpráva & "The cell evaluates to an error value. - Chybová hodnota!" & vbCrLf
If ActiveCell.Errors.Item(xlTextDate).Value = True Then Zpráva = Zpráva & "Date entered as text." & vbCrLf
If ActiveCell.Errors.Item(xlNumberAsText).Value = True Then Zpráva = Zpráva & "Number entered as text." & vbCrLf
If ActiveCell.Errors.Item(xlInconsistentFormula).Value = True Then Zpráva = Zpráva & "The cell contains an inconsistent formula for a region. - Nekonzistentní vzorec v oblasti!" & vbCrLf
If ActiveCell.Errors.Item(xlOmittedCells).Value = True Then Zpráva = Zpráva & "Cells omitted. - Vzorec odkazuje na oblast, s níž sousedí další čísla." & vbCrLf
If ActiveCell.Errors.Item(xlUnlockedFormulaCells).Value = True Then Zpráva = Zpráva & "Formula cells are unlocked. - Buňka se vzorcem je odemčená." & vbCrLf
If ActiveCell.Errors.Item(xlEmptyCellReferences).Value = True Then Zpráva = Zpráva & "The cell contains a formula referring to empty cells. - Odkaz na prázdnou buňku!" & vbCrLf
If ActiveCell.Errors.Item(xlListDataValidation).Value = True Then Zpráva = Zpráva & "Data in the list contains a validation error. - Ověřovaná buňka není v seznamu" & vbCrLf
If ActiveCell.Errors.Item(xlInconsistentListFormula).Value = True Then Zpráva = Zpráva & "The cell contains an inconsistent formula for a list. - Nekonzistentní vzorec v seznamu!" & vbCrLf 'Od verze 2007.
MsgBox Zpráva
End Sub
| xlErrorChecks | Co vyvolá chybu |
|---|---|
| xlEvaluateToError | Chybová hodnota všech možných druhů dle funkce CVErr |
| xlTextDate | Do buňky A1 napíšeme datum. Do jiné buňky napíšeme funkci =HODNOTA.NA.TEXT(A1;"d.m.rr"). Podstatné je, že formát musí mít dvoučíslicový rok, tedy ne například obvyklejší "d.m.rrrr". Buňku s funkcí zkopírujeme do jiné buňky pomocí volby Vložit jinak - Hodnoty Výsledná hodnota má tuto chybu. Chyba může být i výsledkem importu z různých databází, proto je užitečné vědět, jak ji odstranit. Odstranění chyby v buňceDo jiné buňky napíšeme číslo 1.Zkopírujeme tuto buňku do schránky pomocí Ctrl+C. Vybereme oblast, ve které jsou všechny nebo některé buňky vložené jako text a měly být vloženy jako datum nebo číslo. Do vybrané oblasti vložíme obsah schránky pomocí volby Vložit jinak - Násobit Stejně funguje i číslo 0 a Vložit jinak - Přičíst Po této operaci se buňka s datumem naformátuje jako číslo, což opravíme tak, že ji naformátujeme jako datum. |
| xlNumberAsText | Do buňky A1 napíšeme číslo. Do jiné buňky napíšeme funkci =ZAOKROUHLIT.NA.TEXT(A1). Buňku s funkcí zkopírujeme do jiné buňky pomocí volby Vložit jinak - Hodnoty Výsledná hodnota má tuto chybu a odstranění této chyby je stejné jako u výše popsané chyby xlTextDate. |
| xlInconsistentFormula | V tabulce je sloupec s funkcí, která se do všech řádků obvykle zadává roztažením z první buňky. Pokud se do nějaké buňky vzorec napíše jinak než do okolních buněk, vznikne tato chyba. |
| xlOmittedCells | Do oblasti A1:A4 napíšeme nějaká čísla. Do buňky A5 vložíme funkci =SUMA(A2:A3). |
| xlUnlockedFormulaCells | Buňku s nějakým vzorcem odemkneme pomocí volby Formát buněk - Zámek - odškrtnout Uzamčeno. Všechny buňky jsou implicitně uzamčené, což se projeví po zamknutí listu. Před zamknutím listu lze některé buňky odemknout, aby do nich mohl uživatel vkládat hodnoty. Z vložených hodnot něco mohou počítat vzorce, které jsou v uzamčených buňkách. Uzamčení brání změně vzorce, ale dovoluje změnu výsledné hodnoty vzorce. |
| xlEmptyCellReferences | V buňce je vzorec, který se odkazuje na jinou buňku, která není vyplněná. Na kartě Kontrola chyb bývá indikátor této chyby implicitně vypnutý, takže by chybu odhalilo pouze výše uvedené makro TestováníChyb |
| xlListDataValidation | Do jednoho sloupečku buněk zapíšeme nějaké hodnoty, například druhy ovoce. Do druhého sloupečku, který nemusí být vedle prvního, napíšeme každý druh ovoce jen jednou. Na první sloupeček nastavíme ověření dat pomocí seznamu, kterým je druhý sloupeček. Pokud jsou v prvním sloupečku hodnoty, které nejsou ve druhém sloupečku, tak se to projeví, až když první sloupeček převedeme na seznam pomocí volby Vložení - Tabulka (ve starších verzích Data - Seznam). |
| xlInconsistentListFormula | Vytvoříme tabulku se sloupečkem s konzistentní funkcí. Tabulku převedeme na seznam pomocí volby Vložení - Tabulka (ve starších verzích Data - Seznam). Ve sloupečku s funkcí změníme jednu funkci. Chyba nebude indikována, když nejdříve vytvoříme nekonzistentní funkci a potom teprv převedeme tabulku na seznam. Tato chyba je novinkou od verze MS Excel 2007. |
Worksheets(3).Range("a3") = 3
Range("a3").Select
Range("a1:b2").Select
Range("a1:a2,c1:c2,e1:e2").Select
Range("a1,e2").Select
Range("a1", "e2").Select
Range("MojeData").Select 'Funguje za předpokladu, že byl definován název "MojeData" pro nějakou oblast.
Range("a1", Selection).Select 'Projeví se, když je před tím vybrána jiná buňka než A1. Vlastnost Range zde má argument Selection, což je objekt.
Range(Range("a1"), Range("e2")).Select 'Druhý příklad využití objektu Range jako argumentu vlastnosti Range
Je možný i zkrácený styl odkazování:
[a3].Select
[a1:b2].Select
[a1:a2,c1:c2,e1:e2].Select
[a1,e2].Select
[MojeData].Select
Zkrácený styl odkazování využívá metodu Evaluate objektu Application. Je to méně flexibilní způsob odkazování než pomocí vlastnosti Range, protože neumožňuje odkazovat se pomocí textových řetězců Range("a3")
které mohou být výsledkem výpočtu
I = 3
Řetězec = "a" & I
Range(Řetězec).Select
a objektů Range("a1", Selection)
Range("a1:b3").Cells(3).Activate
V případě 2 argumentů se buňky adresují pomocí pořadí řádku (1. argument) a sloupku (2. argument). Takže následující příklad aktivuje stejnou buňku jako předcházející příklad.
Range("a1:b3").Cells(2, 1).Activate
Na první (horní levou) buňku v oblasti se odkazujeme jako na Cells(1) nebo Cells(1, 1).
Cells(2, 2).Select
Cells(2, "B").Select
Chceme-li například vybrat oblast s adresou "a1:b3" a potřebujeme tuto adresu vypočíst z indexů levé horní a pravé dolní buňky, použijeme vlastnost Cells následujícím způsobem:
Range(Cells(1, 1), Cells(3, 2)).SelectTento příklad však funguje pouze na aktivním listu.
Worksheets(3).Range(Cells(1, 1), Cells(3, 2)) = "vyplněno"protože adresujeme objekt Range objektu Worksheets(3) pomocí vlastnosti Cells, která je zde vlastností objektu Application, což znamená, že je to vlastnost aktivního listu.
Worksheets(3).Range(Worksheets(3).Cells(1, 1), Worksheets(3).Cells(3, 2)) = "vyplněno"Ještě lepší je použít v tomto kódu konstrukt With...End With. Výsledkem je přehlednější kód, který bude navíc efektivněji vykonáván.
With Worksheets(3)
.Range(.Cells(1, 1), .Cells(3, 2)) = "vyplněno"
End With
Tečky uvnitř konstruktu With...End With musí být před každým objektem, metodou nebo vlastností, která patří objektu za slovem With.
Sub SumyŘádků()
Dim Oblast As Range, Řádek As Range
Set Oblast = Selection
For Each Řádek In Oblast.Rows
Řádek.Select
MsgBox WorksheetFunction.Sum(Řádek)
Next Řádek
Oblast.Select
End Sub
Selection.Offset(0, 0).Select
Selection.Offset(1, 1).Select
Selection.Offset(-1, -1).Select
Selection.Resize(5, 4).Select
Selection.Resize(, 4).Select
Když se vynechá první nebo druhý argument, bude zachován původní počet řádků nebo sloupků.
Const Názevoblasti As String = "MojeData"
With Range(Názevoblasti)
.Resize(.Rows.Count + 1).Name = Názevoblasti
End With
Range("A1").End(xlDown).Select
Je-li v horní části listu tabulka s prázdnými řádky, můžeme se dostat na konec této tabulky pomocí následujícího kódu.
Cells(Rows.Count, "A").End(xlUp).SelectZačíná-li buňkou A1 tabulka, následující kód vybere první sloupec této tabulky.
With Range("A1")
Range(.Cells(1), .End(xlDown)).Select
End With
Stejnou akci provede kód Range("A1").CurrentRegion.Columns(1).Select
Začíná-li na prvním listu v sešitu buňkou A1 tabulka, následující kód zkopíruje záhlaví této tabulky i s formátováním na druhý list.
With Worksheets(1).Range("A1")
.Range(.Cells(1), .End(xlToRight)).Copy Destination:=Worksheets(2).Range("A1")
End With
Sub SumyŘádků()
Set PočátečníVýběr = Selection 'Zapamatujeme si počáteční výběr.
Selection.CurrentRegion.Select 'Vybereme celou tabulku
With Selection 'Vybereme data v tabulce.
Selection.Offset(1, 1).Resize(.Rows.Count - 1, .Columns.Count - 1).Select
End With
Set Data = Selection 'Oblast s daty uložíme do proměnné Data.
With Selection 'Vybereme horní buňku, do které se má doplnit součet.
.Cells(1, .Columns.Count + 1).Select
End With
Selection.Formula = "=sum(" & Data.Rows(1).Address(0, 0) & ")"
With Selection 'Zkopírujeme obsah horní buňky se součtem do buněk pod ní.
.Copy Destination:=.Offset(1, 0).Resize(Data.Rows.Count - 1)
End With
PočátečníVýběr.Select 'Přesuneme se na počáteční výběr.
End Sub
ActiveSheet.UsedRange.Selectvybere nejmenší obdélník, do kterého se vejdou všechny použité buňky (s hodnotou nebo naformátované).
ActiveCell.SpecialCells(xlCellTypeLastCell).Selectvybere pravou dolní buňku tohoto obdélníku.
Selection.Offset(1, 0).Rows(Selection.Rows.Count).Select
PočetSloupků = Selection.Columns.Count
Selection.End(xlDown).Select
Selection.Offset(1, 0).Select
Selection.Resize(1, PočetSloupků).Select
je možné sloučit do jediného:
With Selection
.End(xlDown).Offset(1, 0).Resize(1, .Columns.Count).Select
End With
PočetSloupků = Selection.Columns.Count
With Selection
Do Until IsEmpty(ActiveCell)
ActiveCell.Offset(1, 0).Activate
Loop
End With
Selection.Resize(1, PočetSloupků).Select
Sub PromazáníTabulky()
Const Vymazat As String = "Vymazat"
Const PořadíSloupkuVymazat As Integer = 4
Dim Řádek As Range
Dim AdresaPrvníBuňky As String
Dim PočetDatovýchŘádků As Integer
Dim PočetVymazanýchŘádků As Integer
Dim Hotovo As Boolean
Selection.CurrentRegion.Select
PočetDatovýchŘádků = Selection.Rows.Count - 1
AdresaPrvníBuňky = Selection.Cells(1).Address
PočetVymazanýchŘádků = 0
Hotovo = False
For Each Řádek In Selection.Rows
Řádek.Select
If Selection.Cells(PořadíSloupkuVymazat) = Vymazat Then
Selection.ClearContents
PočetVymazanýchŘádků = PočetVymazanýchŘádků + 1
End If
Next Řádek
If PočetVymazanýchŘádků > 0 And PočetVymazanýchŘádků < PočetDatovýchŘádků Then
Do
Selection.CurrentRegion.Select
Selection.Cut
Selection.End(xlUp).Select
Hotovo = Selection.Address = AdresaPrvníBuňky
Selection.Offset(1, 0).Select
ActiveSheet.Paste
Loop Until Hotovo
Selection.Cut
Selection.Offset(-1, 0).Select
ActiveSheet.Paste
End If
End Sub
Byla by možná jednodušší varianta makra, které by odstraňovalo celé řádky, a aby nepoškodilo obsah vedle a pod tabulkou, tak by tabulku vložilo na nově vložený list, tam by provedlo odstranění celých řádků, vymazalo by původní tabulku na původním listu, výslednou tabulku by z nového listu zkopírovalo na původní list a odstranilo by nový list.
Motivací pro makra, která přenášejí hodnoty mezi datovou strukturou pole a oblastí buněk, je zrychlení zpracování. Odstraňování řádků z velmi velkých tabulek by mohlo mít měřitelný rozdíl v rychlosti maker výše uvedeného typu oproti makrům níže uvedeného typu.
Makro příkazem Data = Selection uloží do proměnné Data všechny datové řádky tabulky (tedy vše kromě záhlaví). Tímto příkazem se z proměnné Data stane dvourozměrné pole s hodnotami z tabulky. První rozměr reprezentuje počet řádků a druhý rozměr reprezentuje počet sloupků, takže je možné přistupovat k jednotlivým hodnotám z buněk tabulky pomocí indexů pole rovných číslům řádků a sloupků v původní tabulce. Když jsou hodnoty v oblasti takto uloženy do proměnné typu Variant, indexy vzniklého pole jsou vždy číslovány od jedné, nikoli od nuly, bez ohledu na příkaz Option Base v deklarační části modulu. Vzniklé pole má také vždy dva rozměry, i když by oblast měla jen jeden řádek nebo sloupek.
Příkaz Data = Selection je jiný než příkaz Set Data = Selection, který by do proměnné Data uložil oblast s daty tabulky jako objekt.
Na začátku jsou v makru deklarovány 2 proměnné typu pole PromazanáData a TransponovanáData bez udání rozměrů, protože není předem známo, jak velká tabulka bude makrem zpracovávána. Vzhledem k tomu, že se do nich bude přenášet obsah buněk, musí být datovým typem v těchto polích Variant.
Příkazem ReDim se upraví velikost polí podle velikosti tabulky. Přitom se využívá pro zjištění počtu řádků a sloupků tabulky funkce UBound.
Ve For cyklu se do pole PromazanáData uloží data z těch rádků tabulky, které nemají být vymazány, a zjistí se počet takových řádků.
V poli PromazanáData jsou po této operaci na prvních řádcích řádky, které mají v tabulce zůstat, a na ostatních jsou prázdné hodnoty. Toto pole se proto může vložit na původní místo datové části tabulky.
Kdybychom potřebovali pole PromazanáData původně dimenzované na celou tabulku zkrátit na počet zachovaných řádků, budeme potřebovat řádky kódu, které jsou zakomentovány. Při této operaci je nutné pole PromazanáData transponovat, protože funkce ReDim může měnit pouze počet sloupků (poslední rozměr) pole, pokud je volána s klíčovým slovem Preserve, se kterým musí být volána, aby byla v poli zachována data. Potom se změní počet řádků původního pole PromazanáData a to bez klíčového slova Preserve, aby bylo možné změnit i počet řádků (nejen počet sloupků), a tím se vynulují data. Data se do pole PromazanáData zkopírují jako výsledek transponování zkráceného pole.
Sub PromazáníTabulkyVPoli()
Const Vymazat As String = "Vymazat"
Const PořadíSloupkuVymazat As Integer = 4
Dim AdresaPrvníBuňky As String
'Dim PočetDatovýchŘádků As Integer
'Dim PočetVymazanýchŘádků As Integer
Dim Data As Variant
Dim PromazanáData() As Variant
'Dim TransponovanáData() As Variant
Dim i As Integer, j As Integer, k As Integer
Selection.CurrentRegion.Select
AdresaPrvníBuňky = Selection.Cells(1).Address
Selection.Offset(1, 0).Select
Selection.Resize(Selection.Rows.Count - 1).Select
'PočetDatovýchŘádků = Selection.Rows.Count
Data = Selection
ReDim PromazanáData(1 To UBound(Data, 1), 1 To UBound(Data, 2))
'ReDim TransponovanáData(1 To UBound(Data, 2), 1 To UBound(Data, 1))
k = 0
For i = 1 To UBound(Data, 1)
If Data(i, PořadíSloupkuVymazat) <> Vymazat Then
k = k + 1
For j = 1 To UBound(Data, 2)
PromazanáData(k, j) = Data(i, j)
Next j
End If
Next i
'PočetVymazanýchŘádků = PočetDatovýchŘádků - k
'If PočetVymazanýchŘádků > 0 And PočetVymazanýchŘádků < PočetDatovýchŘádků Then
' TransponovanáData = WorksheetFunction.Transpose(PromazanáData)
' ReDim Preserve TransponovanáData(1 To UBound(Data, 2), 1 To k)
' ReDim PromazanáData(1 To k, 1 To UBound(Data, 2))
' PromazanáData = WorksheetFunction.Transpose(TransponovanáData)
'End If
Selection.ClearContents
'Range(AdresaPrvníBuňky).Offset(1, 0).Select
'Selection.Resize(UBound(PromazanáData, 1), UBound(PromazanáData, 2)).Select
Selection = PromazanáData
End Sub
Sub VymažList()
ThisWorkbook.Worksheets.Add , Worksheets(Worksheets.Count), 10 'Přidání 10 listů za poslední list
Application.DisplayAlerts = False
Worksheets(Worksheets.Count).Delete 'Odstranění posledního listu
Application.DisplayAlerts = True
End Sub
a = ExecuteExcel4Macro("'C:\Data\[Moje data.xls]List1'!R1C1")
Omezení:
Sub NapišHodnoty()
Dim i As Integer, j As Integer
Dim Počátek As Single, Konec As Single
Počátek = Timer
For i = 1 To 50
For j = 1 To 50
Cells(i, j) = ExecuteExcel4Macro("'C:\Data\[Moje data.xls]List1'!R" & i & "C" & j)
If Cells(i, j) = 0 Then Cells(i, j) = ""
'Prázdné buňky (ty co nemají data) vrátí metoda ExecuteExcel4Macro jako nulu.
'Takto tomu lze zabránit, ale potom budou datové buňky s hodnotou nula prázdné.
'Buňky se vzorcem vrátí metoda ExecuteExcel4Macro jako výslednou hodnotu.
Next j
Next i
Konec = Timer
MsgBox Konec - Počátek, , "Trvání v sekundách"
End Sub
Rychlost tohoto makra není příliš veliká. Bude patrně užitečné v případě, kdy je potřeba z velkého množství excelovských sešitů zjistit jen malé množství dat.a = ExecuteExcel4Macro("'C:\Data\Moje data.xls'!MojeOblast")
Toto řešení vrací jen jedinou hodnotu z jediné buňky, i když je v oblasti s názvem MojeOblast více buněk, takže není dobré.='C:\Data\Moje data.xls'!MojeOblastzadaného do oblasti tak velké, jak je velká oblast MojeOblast. Podobného výsledku dosáhneme, když zkopírujeme oblast pomocí Vložit jinak - Vložit propojení.
Sub NapišHodnotyLink()
Dim i As Integer, j As Integer
Dim Počátek As Single, Konec As Single
Počátek = Timer
For i = 1 To 50
For j = 1 To 50
Cells(i, j).FormulaR1C1 = "='C:\Data\[Moje data.xls]List1'!RC"
If Cells(i, j) = 0 Then Cells(i, j) = ""
Cells(i, j).FormulaR1C1 = Cells(i, j).Value 'Zruší se propojení.
Next j
Next i
Konec = Timer
MsgBox Konec - Počátek, , "Trvání v sekundách"
End Sub
Toto makro je ale o něco pomalejší.