Seriál - 3. díl
Základní příkazy, funkce, procedury a události

V dnešním dílu si ukážeme některé často používané příkazy z VB, např. FOR..NEXT, IF..THEN atd. V další kapitole se dozvíte, jak vytvářet procedury a funkce ve VB, co to jsou události a vlastnosti a jak je používat.

V minulém dílu jsme chybně uvedli čísla kapitol. Tímto se omlouváme a pokud máte zájem, zkopírujte si opravenou verzi.

6. Základní příkazy
    6.1. Příkazy cyklu
    6.2. Větvení programu
    6.3. Dialogy
7. Procedury, funkce, události
    7.1. Procedury a funkce
    7.2. Vlastnosti
    7.3. Události


6. Základní příkazy

V této kapitole se vás budeme snažit naučit nejběžněji používané příkazy ve VB. Půjde o příkazy cyklu, tedy iterační příkazy a o příkazy, které umožňují větvení programu. Také, aby bylo naše programování alespoň trochu spojeno s okny, vám ukážeme dvě funkce pro použití dialogů.

Chcete-li vyzkoušet příklady uvedené v této kapitole, vytvořte nový projekt, a vložte kód příkladu do události Form_Load formuláře Form1. Pokud si už nevzpomínáte jak na to, klikněte dvakrát na Form1 a hned se Vám otevře kód této události. Příklad je potom proveden při startu aplikace. Můžete také na formulář vložit tlačítko (CommandButton) a vložit kód do jeho události Click. Kód se potom provede při jeho stisku.


6.1. Příkazy cyklu

VB má mnoho možností, jak vytvořit opakující se cyklus. Dalo by se říci, že ze všech jazyků má nejvíce způsobů pro jeho vytvoření (možná až příliš mnoho).

FOR .. NEXT

For pocitadlo = zacatek To konec [Step krok]
  [příkazy]
  [Exit For]
  [příkazy]
Next [pocitadlo]

pocitadlo je proměnná, která nabývá hodnot od zacatek po konec. Nepovinná část Step krok určuje, o kolik se bude pocitadlo zvětšovat. Standardně je to 1. Příkaz Exit For způsobí ukončení cyklu a skok na řádek za příkazem Next.

Příklad:

Dim x As Long

'vypíše do okna Immediate hodnoty 1, 2, 3, ... , 9, 10
For x=1 to 10
  Debug.Print x
Next x

'vypíše do okna Immediate hodnoty 0, 5, 10, 15, 20
For x=0 to 20 Step 5
  Debug.Print x
Next x

'vypíše do okna Immediate hodnoty 1, 2, 3
For x=1 to 5
  Debug.Print x
  If x=3 Then Exit For
Next x

DO .. LOOP

VB nemá příkaz Until. Cykly, které jsou v jiných jazycích dělány pomocí Until a While, se ve VB dělají pomocí Do .. Loop.

Do [{While | Until} podmínka]
  [příkazy]
  [Exit Do]
  [příkazy]
Loop

nebo

Do
  [příkazy]
  [Exit Do]
  [příkazy]
Loop [{While | Until} podmínka]

Vykonává příkazy uvedené mezi Do a Loop, dokud platí podmínka uvedená za While, tzn. její vyhodnocení je True, nebo, v případě použití Until, dokud není vyhodnocení podmínky True. While nebo Until mohou být uvedeny buď za Do nebo za Loop. Obojí zároveň není možné. Stejně jako u For .. Next je i zde možno z cyklu vyskočit, a to pomocí Exit Do.

Příkaz lze také použít bez Until i While, takže cyklus bude probíhat neustále. Ukončit půjde pouze pomocí Exit Do.

Příklad:

Dim x As Long

'Do okna Immediate vypíše hodnoty 1, 2, 3, 4
x=1
Do While x<5
  Debug.Print x
  x=x+1
Loop

'Do okna Immediate vypíše hodnoty 1, 2, 3, 4
x=1
Do
  Debug.Print x
  x=x+1
Loop While x<5

WHILE .. WEND

Příkaz je zjednodušenou obdobou příkazu Do .. Loop.

While podmínka
  [příkazy]
Wend

Dokud platí podmínka, jsou vykonávány příkazy mezi While a Wend.

Příklad:

'Vypíše do okna Immediate hodnoty 1, 2, 3, 4, 5
Dim x As Long

x=1
While x<=5
  Debug.Print x
  x=x+1
Wend

Zpět na obsah


6.2. Větvení programu

VB má dva základní příkazy pro větvení programu. Příkaz If a příkaz Select. If je lépe použít pro méně větví, Select naopak pro více.

IF .. THEN .. ELSE

If podmínka Then [příkazy] [Else příkazy]

nebo

If podmínka Then
  [příkazy]
[ElseIf podmínka-n Then
  [příkazy]
[Else
  [příkazy]
End If

Příkaz vykoná ten blok programu, pro nějž je platná podmínka. podmínka-n v části ElseIf znamená, že tato část se může opakovat vícekrát. Ze syntaxe příkazu vyplývá, je-li příkaz na jeden řádek, nemusí být ukončen End If.

Příklad:

'V závislosti na hodnotě x vypíše do okna Immediate buď "prvni" nebo "druhy"
Dim x As Long

Randomize 'Inicializuje generátor náhodných čísel
x = Int((2 * Rnd) + 1) 'Generuje náhodné celé číslo od 1 do 2
If x=1 Then Debug.Print "prvni" Else Debug.Print "druhy"

nebo zapsáno přehledněji

If x=1 Then
  Debug.Print "prvni"
Else
  Debug.Print "druhy"
End If

'Stejně jako předchozí příklad zapíše do okna Immediate hodnotu závislou na hodnotě x
Dim x As Long

Randomize 'Inicializuje generátor náhodných čísel
x = Int((4 * Rnd) + 1) 'Generuje náhodné celé číslo od 1 do 4
If x=1 Then
  Debug.Print "prvni"
ElseIf x=2 Then
  Debug.Print "druhy"
ElseIf x=3 Then
  Debug.Print "treti"
Else
  Debug.Print "ctvrty"
End If

SELECT

Příkaz Select vykonává prakticky stejnou funkci jako If. Je lepší ho použít v případě více variant testované podmínky a ve stejném případě také pro lepší čitelnost zdrojového kódu.

Select Case testovaný_výraz
  [Case seznam1
    [příkazy-1]]
  [Case seznam2
    [příkazy-2]]
  .
  .
  [Case Else
    [příkazy-n]]
End Select

testovaný_výraz je proměnná nebo výraz, na jehož základě se program dále rozděluje na více bloků. seznam1, seznam2 atd. jsou možné varianty testované proměnné nebo výrazu. Za každým slovem Case může být jedna hodnota nebo více hodnot oddělených čárkou. Můžete zadat také interval, např. 1 to 10. Pro lepší pochopení si opět pomůžeme příkladem.

'Stejně jako příklad pro IF zapíše do okna Immediate hodnotu závislou na hodnotě x
Dim x As Long

Randomize 'Inicializuje generátor náhodných čísel
x = Int((4 * Rnd) + 1) 'Generuje náhodné celé číslo od 1 do 4
Select Case x
  Case 1
    Debug.Print "prvni"
  Case 2,3
    Debug.Print "prostredni"
  Case 4
    Debug.Print "posledni"
End Select

'Vyhodnotí výraz a vypíše zprávu do okna Immediate. V tomto případě je vhodnější použít příkaz IF
Dim x As Long

Randomize 'Inicializuje generátor náhodných čísel
x = Int((10 * Rnd) + 1) 'Generuje náhodné celé číslo od 1 do 10
Select Case x < 5
  Case True
    Debug.Print "X je mensi nez 5"
  Case False
    Debug.Print "X je vetsi nebo rovno 5"
End Select

Do této kapitoly by se daly zařadit ještě další příkazy které existují ve VB. Nemá příliš velký význam uvádět jejich syntaxi a jak se používají, to můžete zjistit z nápovědy. Abyste alespoň věděli kde hledat, jsou to tyto příkazy: Choose, IIf a Switch.

Zpět na obsah


6.3. Dialogy

Funkce MsgBox

Tato funkce slouží pro zobrazení dialogu s textem a tlačítky které si vyberete. Vrací hodnotu typu Integer, která indikuje, které tlačítko uživatel stiskl. Funkce může být volána i jako procedura.

MsgBox(text[, tlačítka] [, titulek] [, nápověda, kontext])

text je zpráva, která se zobrazí přímo v okně.
tlačítka je číslo, které je součtem všech hodnot, určujících zobrazená tlačítka a ikony. Zde je nejlépší použít konstanty.
titulek je zpráva, která se zobrazí v záhlaví okna. Pokud neuvedete tento parametr, zobrazí se v titulku název projektu.
nápověda je cesta k souboru nápovědy.
kontext je číslo, které specifikuje část nápovědy, která se má zobrazit.

Příklad:

'Ukáže dialog s tlačítkem OK (standardně) a textem "Moje zpráva"
MsgBox "Moje zpráva", , "Zpráva"

'Ukáže dialog s tlačítkem OK, s ikonou I v kolečku
MsgBox "Moje zpráva", vbInformation

'Zobrazí dialog s tlačítky Ano a Ne a ikonou otazníku v kolečku
'Pokud uživatel zvolí Ano, ukončí se program
If MsgBox("Ukončit program?", vbQuestion + vbYesNo, "Dotaz") = vbYes Then End

'Stejný příklad jako výše, pouze lépe čitelný
Dim i As Integer

i=MsgBox("Ukončit program?", vbQuestion + vbYesNo, "Dotaz")
If i=vbYes Then
  End
End If

Funkce InputBox

Funkce zobrazí dialog s textovým polem, a čeká na uživatele. Pokud stiskne OK, vrací řetězec, který je obsahem textového pole, tedy toho, co uživatel napsal, stiskne-li Cancel, je navrácená hodnota rovna "", prázdný řetězec.

InputBox(zpráva[, titulek] [, default] [, x] [, y] [, nápověda, kontext])

Není třeba vysvětlovat parametry, které jsou stejné s funkcí MsgBox. Další parametry znamenají:

default je hodnota, která je předvyplněna v textovém poli.
x je hodnota na ose x obrazovky, kam bude umístěn levý horní roh dialogu.
y je stejné jako x, pouze na ose y.

Příklad:

'Zobrazí výzvu pro vložení jména
Dim jmeno As String

jmeno=InputBox("Vložte jméno", "Jméno")
If jmeno="" Then
  MsgBox "Nebylo vloženo žádné jméno"
Else
  MsgBox jmeno
End If

'Zobrazí výzvu pro vložení data s nastaveným dnešním datem na pozici x=10, y=20
'Dnešní datum vrací funkce Now
Dim datum As String 'pouze pro názornost, lépe samozřejmě použít typ date

datum=InputBox("Vložte datum", "Datum", Now, 10, 20)

Zpět na obsah


7. Procedury, funkce, události

Vzhledem k tomu, že VB je poměrně členitý jazyk, je název této kapitoly poměrně zavádějící. V kapitole bude zabráno trochu širší spektrum. Správný název, i když ne až tak srozumitelný by mohl znít Způsoby členění kódu a jejich použití.

K čemu slouží procedury a funkce by mělo být každému čtenáři tohoto seriálu jasné. Proto pouze krátkou rekapitulaci. Procedury a funkce slouží pro strukturované rozdělení programu na menší logické části. Tyto jsou vhodné především pro takové části programu, které se často opakují nebo jsou používány ruznými částmi programu, případně i jinými aplikacemi. Rozdíl mezi funkcemi a procedurami je jednodduchý, funkce vrací hodnotu a procedura ne.

Procedury a funkce můžeme ve VB dělit podle způsobu a místa použití (nebudeme zde brát příliš zřetel na to, kdy se spíše jedná o klasickou proceduru z pohledu strukturovaného programování a kdy jde již o metodu z pohledu OOP).

7.1. Procedury a funkce

Výskyt:Form, MDIForm, Module, ClassModule, User Control, Property Page

Funkce:

[Private|Public] [Static] Function jméno_funkce (argumenty) [As type]
  [Exit Function]
End Function

Procedura:

[Private|Public] [Static] Sub jméno_funkce (argumenty)
  [Exit Sub]
End Sub

Klauzule Private a Public stejně jako u proměnných určují zdali jsou na úrovni daného modulu (nechápejte zde modul jako Module, ale pouze jako volné označení rámce vymezujícího kód v rámci nějakého prvku jako Form, PropertyPage nebo i Module.) privátní či veřejné. To znamená, že určují, zdali budou přístupné z vnějšku daného modulu.

V další části se nachází slovo Static. V případě, že se objeví v deklaraci, znamená to, že všechny proměnné v ní deklarované jsou Static, čímž si uchovávají svou hodnotu i v době, kdy není daná funkce či procedura prováděna.

Po indikátoru, který určuje zdali se jedná o funkci či proceduru, následuje jméno funkce. Za tímto jsou argumenty, které se mezi sebou oddělují čárkou.

[Optional] [ByRef|ByVal] jméno_argumentu [AS datový_typ]

Klauzule Optional určuje zdali je parametr nepovinný. Je li použito nepovinných parametrů, mohou být v deklaraci uvedeny až po posledním povinném argumentu. Testování, zdali byl parametr zadán, je možné provádět funkcí IsMissing(), která vrací hodnotu True, jestliže parametr nebyl zadán. Slova ByRef a ByVal stanovují jakým způsobem bude parametr předán. V prvním případě je argument předán odkazem, což znamená, že je předán odkaz do paměti. Díky tomu je možné, aby funkce nebo procedura změnila její hodnotu. Přesto, že tento způsob je ve VB standardní, pro optimalizaci kódu je vhodnější zvolit druhou možnost. V tomto případě je předávána pouze kopie, takže při změně hodnoty argumentu se tato změna projeví jen na této kopii. Stejně jako u každé proměnné se definuje typ i u argumentů. V případě, že je vynechán, je automaticky přiřazen typ Variant. Stejně tomu je i u funkcí, kde se narozdíl od procedur definuje i typ návratové hodnoty.

ParamArray jméno_pole_argumentů()

Jestliže je počet argumentů pohyblivý, a použití klauzule Optional by bylo značně nepraktické, je možno použít pole parametrů. Tento typ parametrů se deklaruje slovem ParamArray. Typ jeho prvků je vždy a jedině Variant. Pro jeho použití navíc platí pravidla, že může být uveden až jako poslední argument, a předcházet mu mohou jedině parametry povinné. Když pak budeme chtít ve funkci nebo proceduře procházet jednotlivé prvky pole, je nejlepší a nejrychlejší metoda, znázorněná v příkladu.

Public Function Suma(ParamArray pole()) As Long
  Dim Soucet As Long
  For Each prvek In pole
    Soucet = Soucet + prvek
  Next
  Suma = Soucet
End Function

Nedílnou součástí této kapitoly je i volání procedur a funkcí z kódu. VB zde nabízí několik možností. První dvě možnosti platí pro funkce, kde není důležitá návratová hodnota a pro procedury.

jméno_funkce první_argument, druhý argument
Call jméno_funkce(první_argument, druhý argument)

U funkcí, kde je třeba získat návratovou hodnotu se použije jednoduché přiřazení jako u proměnných. Je li návratovým typem objekt nesmíme zapomenout na klíčové slovo Set.

jméno_proměnné = jméno_funkce(první_argument, druhý argument)
Set jméno_proměnné = jméno_funkce(první_argument, druhý argument)

Poslední dvě možnosti se týkájí způsobu zadávání nepovinných parametrů. V případě, že chceme některý z prostředních parametrů vynechat, může to vypadat takto (obě uvedená použití jsou ekvivalentní).

Public Function Suma3(Optional a As Long, Optional b As Long, Optional c As Long) As Long
...
  Print Suma3(22,,6)
  Print Suma3(22,c:=6)

Z uvedeného je zřetelné, že buď hodnotu parametru prostě nenapíšeme nebo přiřadíme identifikátoru argumentu pomocí ":=" hodnotu.

Zpět na obsah


7.2. Vlastnosti

Výskyt:Form, MDIForm, Module, ClassModule, User Control, Property Page

Už v minulém díle jsme se zmínili o vlastnostech objektu. Tato možnost velice zpřehledňuje kód. Kdyby jsme měli například nastavení barvy realizovat pomocí metod (pro naši věc ji můžeme nazvat i funkcí), mohlo by to vypadat asi takto.

x=Objekt.GetBarva()
Objekt.SetBarva(x)

Jelikož se navenek jeví jako proměnné příslušející nějakému objektu, je zápis mnohem přehlednější. Posuďte sami, o co lépe vypadá uvedený kód napsaný při využití vlastností.

x=Objekt.Barva
Objekt.Barva=x

Ačkoli to tak nevypadá, nevyhneme se rozdělení kódu vlastnosti na dvě části (ve výjmečných případech dokonce na tři). První část se stará o zjištění hodnoty vlastnosti a druhá o její nastavení. Ani zde nesmíme zapomenout na případy, kdy je vlastnost typu objekt a nastavovat a psát vlastnosti s ohledem na to.

[Private|Public] [Static] Property Get jmeno_vlastnosti(1,..., n) As typ
[Private|Public] [Static] Property Let jmeno_vlastnosti(1,..., n, n+1)
[Private|Public] [Static] Property Set jmeno_vlastnosti(1,..., n, n+1)

Co se týče deklarace vlastností, ničím zásadním se od procedur a funkcí neliší, pouze identifikátor je Property Get|Let|Set. Dalším rysem je rozdíl v počtu argumentů mezi částmi, kde se hodnota zjišťuje a kde se nastavuje. U Property Get je n parametrů vlastnosti a její návratový typ musí být shodný s typem parametru n+1 u Property Let|Set. Tento poslední parametr se narozdíl od jiných nachází za rovnítkem a zprostředkovává předání hodnoty pro kód. Pro snadnější pochopení uvedu kód, na kterém uvidíte způsob použití vlastností.

'První část kódu je modul třídy s názvem Pole
Private mMax as Long 'Maximální počet prvků v poli
Private mPoleVar() As Variant 'Dynamické pole pro uložení prvků libovolného typu

'První vlastnost slouží pro určení počtu prvků pole.
Public Property Get Maximum() As Long
  Maximum=mMax
End Property

Public Property Let Maximum(NoveMax As Long)
  mMax=NoveMax
  Redim Preserve mPoleVar(1 to mMax) 'Změna velikosti pole
End Property

'Tato vlastnost se stará o ukládání a získávání prvků pole. Jelikož může jít o proměnnou jednoduchého typu nebo o objekt má jak část Let tak i Set.
Public Property Get PoleVariant(Index As Long) As Variant
  If Index<=mMax Then PoleVariant=mPoleVar(Index)
End Property

Public Property Let PoleVariant(Index As Long, NovyPrvek As Variant)
  If Index<=mMax Then mPoleVar(Index)=NovyPrvek
End Property

Public Property Set PoleVariant(Index As Long, NovyPrvek As Variant)
  If Index<=mMax Then Set mPoleVar(Index)=NovyPrvek
End Property

'Tato část kódu se nachází například v modulu formuláře
...
  Dim i As Long
  Dim Pokus As New Pole
  Pokus.Maximum=10
  Pokus.PoleVariant(1) = "Hello, world!"
...
  Pokus.PoleVariant(10) = 666
  For i=1 To Pokus.Maximum 'Prochází prvky vlastnosti PoleVariant
    Print Typename(Pokus.PoleVariant(i)) 'Tiskne typ proměnné
  Next i
...

Zpět na obsah


7.3. Události

Události dávají objektům schopnost, která jim umožňuje přenechat reakci na určitou akci či změnu stavu (může přicházet od uživatele, systému nebo od jiných objektů) na programátorovi. Ten může obsloužit událost libovolným způsobem. Samozřejmě nemusí na událost reagovat vůbec. Toto je znamenitý způsob, jak spolu mohou spolupracovat a reagovat na sebe nezávislé objekty.

Součástí většiny ActiveX prvků ve VB jsou události, které vám umožní spojit s nimi kód a tím je také obsloužit. Ve vlastních objektech můžete vytvářet i vlastní události a to tak, že buď "přesměrujete" události jiných objektů a nebo uděláte svoji, která se třeba vyvolá při změně stavu.

Pro příklad přesměrování události vytvořte nový projekt, přidejte ActiveX Control (menu Project | Add User Control) a na něj umístíte dvě tlačítka. První se bude jmenovat cmdOK a druhé cmdStorno. Do vlastnosti Caption zapíšete u prvního "OK" a u druhého "Storno". Hotový prvek vložíte na formulář, pojmenujete ho jako Pokus a doplníte následující kód. Poté aplikaci můžete spustit (prvek přidáte na formulář jeho vybráním v okně nástrojů a standardním umístěním někde na formulář).

'Tato část kódu se nachází v modulu vytvořeného ActiveX Control
'Deklarace vlastních událostí
Event OK()
Event Storno()

Private Sub cmdOK_Click()
  RaiseEvent OK() 'Vyvolá událost OK
End Sub

Private Sub cmdStorno_Click()
  RaiseEvent Storno() 'Vyvolá událost Strono
End Sub

'Následující část kódu se nachází v modulu formuláře
Private Sub Pokus_OK()
  MsgBox "Uživatel zmáčkl OK."
End Sub

Private Sub Pokus_Storno()
  MsgBox "Uživatel zmáčkl Storno."
End Sub

Syntaxe deklarace události vypadá takto. Dále je uvedena hlavička pro obsloužení události.

[Public] Event jméno_události [(argumenty)]

[Private] Sub názevobjektu_názevudálosti [(argumenty)]

Podtržítko u hlavičky události je nutné pro oddělení názvu objektu a události. Jinak platí stejná pravidla jako u procedur a funkcí.

Určitě jste si všimli, že když vytvoříte třídu a použijete ji třeba v modulu formuláře, nevidíte v horních rozbalovacích nabídkách ani její název ani vytvořené události. V tomto případě je třeba v deklaraci instance uvést klíčové slovo WithEvents. To způsobí, že se události objeví v horních nabídkách a je možno s těmito událostmi pracovat.

Pro lepší pochopení uvedu příklad. Po jeho vytvoření se můžete podívat, zdali se v nabídkách objevila instance třídy a její události. Vytvořte třídu a nazvěte ji "Zasobnik". Na formulář vložte tlačítko se jménem cmdRun a do vlastnosti caption vložte text "Spusť". Dála vložte na formulář ListBox a nazvěte jej lstEvents. Poté přidejte do projektu následující kód.

'Tento kód patří do třídy Zasobnik
Private zas(1 To 10) As Long 'Pole pro zásobník
Private pocet As Long 'Pocet hodnot v zásobníku

'Událost nastávající při přetečení zásobníku
Event Pretekl()
'Událost nastávající při nemožnosti odebrat hodnotu z prázdného zásobníku
Event Prazdny()
'Událost nastávající při vložení hodnoty
Event Vlozeno(hodnota As Long)
'Událost nastávající při odebrání hodnoty
Event Odebrano(hodnota As Long)

Public Sub Vloz(hodnota As Long)
  If pocet = 10 then
    RaiseEvent Pretekl
  Else
    pocet = pocet + 1
    zas(pocet) = hodnota
    RaiseEvent Vlozeno(hodnota)
  End If
End Sub

Public Function Odeber() As Long
  If pocet = 0 then
    RaiseEvent Prazdny
  Else
    Odeber = zas(pocet)
    RaiseEvent Odebrano(zas(pocet))
    pocet = pocet - 1
  End If
End Sub

'Tento kód patří do modulu formuláře
'Deklarace instance třídy včetně událostí
Private WithEvents z As Zasobnik

Private Sub Form_Load()
  Set z = New Zasobnik
End Sub

Private Sub cmdRun_Click()
  Dim i As Long
  Randomize
'Naplnění zásobníku
  For i = 1 To 11
    z.Vloz Clng(Rnd*1000)
  Next
'Vyprázdnění zásobníku
  For i = 1 To 11
    z.Odeber
  Next
End Sub

Private Sub z_Odebrano(hodnota As Long)
  lstEvents.AddItem "Byla odebrána tato hodnota:" & hodnota
End Sub

Private Sub z_Prazdny()
  lstEvents.AddItem "Zásobník je prázdný. Nelze odebrat hodnotu."
End Sub

Private Sub z_Pretekl()
  lstEvents.AddItem "Zásobník přetekl. Nelze přidat hodnotu."
End Sub

Private Sub z_Vlozeno(hodnota As Long)
  lstEvents.AddItem "Byla vložena tato hodnota:" & hodnota
End Sub

Zpět na obsah