Potprogrami

Potprogrami su zapravo programi unutar programa. Naime, program može da se podeli na logičke celine od kojih je svaka zadužena za izvršavanje specifičnog zadatka. Moguće je da u programu postoji potreba da se isti zadatak obavi više puta, ali na različitim mestima. Umesto da se naredbe za izvršavanje takvog zadatka iznova navode, ideja je da se one izdvoje u posebnu imenovanu celinu, potprogram, i da se po potrebi pozivaju samo navođenjem imena potprograma i eventualnih ulaznih podataka.

Potprogramima se postiže ušteda, mogućnost da se isti niz naredbi ponovo iskoristi, a program postaje čitljiviji jer se ne posmatra samo kao niz naredbi, već i kao niz specifičnih zadataka. Takođe, prilikom pisanja programa, najlakše je tokom analize problema podeliti program na specifične zadatke, a onda za svaki od njih ispisati odgovarajući niz naredbi koji ga realizuju.

U okviru objektno-orijentisanih programskih jezika (kakav je VBA) često se koristi termin "metod" umesto potprogram.

Postoje dve vrste potprograma:

Procedure

Definicija procedure izgleda ovako:

Sub imeProcedure(argumenti)

  naredba

  naredba

  …

  naredba

End Sub

gde argumenti predstavljaju deklaracije promenljivih koje procedura koristi kao ulazne podatke.

Primer: napisati proceduru koja na osnovu zadate vrednosti, menja veličinu prvog pasusa tekućeg dokumenta.

Sub PromeniVelicinu(iSize as Integer)

  ActiveDocument.Paragraphs(1).Range.Font.Size = iSize

End Sub

Da bi se naredbe neke procedure izvršile u programu, potrebno je da se procedura pozove i da se obezbede konkretne vrednosti za njene argumente. Npr. nakon sledećeg poziva

PromeniVelicinu 14
vrednost argumenta iSize postaje 14 i naredba procedure menja veličinu prvog pasusa u 14pt.

Često je potrebno da procedura uradi nekakav posao bez dodatnih informacija, te joj ulazni podaci (argumenti) nisu neophodni.

Sub imeProcedure()

  naredba

  naredba

  …

  naredba

End Sub

Primer: napisati proceduru koja formatira prvi pasus tekućeg dokumenta koristeći italic.

Sub PromeniUItalic()

  ActiveDocument.Paragraphs(1).Range.Italic = True

End Sub

Važno! Prilikom poziva procedure ne koriste se zagrade oko konkretnih vrednosti za njene argumente!

Funkcije

Osnovna razlika između procedura i funkcija je u tome što funkcija vraća vrednost, tj. poziv funkcije može da se tretira kao izraz određenog tipa i da se kao takav koristi u okviru drugih izraza istog tipa.
Function imeFukcije(argumenti) As tipVrednosti

  naredba

  naredba

  …

  naredba

  imeFunkcije = vrednostFunkcije 'naredba kojom funkcija vraća vrednost

End Function
Važno! Prilikom poziva funkcije moguća su dva slučaja:
  1. Koristi se vrednost funkcije u okviru nekog izraza (npr. u naredbi dodele). U tom slučaju je obavezno pisati zagrade oko konkretnih vrednosti za njene argumente! (Ovo je najčešći slučaj sa funkcijom InputBox)
  2. Vrednost funkcije se ignoriše, tj. jedino su bitni efekti naredbi tela funkcije. U tom slučaju ne koriste se zagrade oko konkretnih vrednosti za njene argumente, tj. poziv funkcije se tretira isto kao poziv procedure! (Ovo je čest slučaj sa funkcijom MsgBox)
Primer: napisati funkciju koja računa koliko samoglasnika ima data niska. Ideja: svako slovo niske izvlačimo kao podnisku dužine 1 i proveravamo da li je u pitanju neki od samoglasnika ("a", "e", "i", "o", "u"). Pošto se iste naredbe obavljaju za svako slovo, koristimo For petlju.
Function BrojVokala(niska as String) As Integer

  Dim pozicija As Integer 'pozicija slova u niski

  Dim brVokala As Integer 'brojac samoglasnika u niski

  Dim duzina As Long 'duzina niske

  Dim slovo As String 'slovo kao podniska

  

  duzina = Len(niska)

  brVokala = 0

  

  For pozicija = 1 To duzina

    slovo = Mid(niska, pozicija, 1)

    If (slovo = "a") Or (slovo = "e") Or (slovo = "i") Or (slovo = "o") Or (slovo = "u") Then

       brVokala = brVokala + 1

    End If

  Next

  

  BrojVokala = brVokala 'naredba kojom funkcija vraća vrednost

End Function
S obzirom da je poziv funkcije vrednost ona se može i mora koristiti u izrazu:
Dim brojSuglasnika as Integer

brojSuglasnika = Len("maestro") - BrojVokala("maestro") 'u promenljivu se upisuje 7 - 3 = 4

Prenos argumenata potprograma

U prethodnim odeljcima su prikazani primeri definisanja i pozivanja procedura i funkcija. Prilikom definisanja potprograma deklarisane su posebne promenljive koje treba da prihvate ulaz potprograma, a koje smo nazvali argumentima. Te promenljive se još nazivaju formalni parametri potprograma.

S druge strane, prilikom pozivanja potprograma potrebno je obezbediti konkretne vrednosti za argumente; te vrednosti se još nazivaju stvarni parametri potprograma. Stvarnih parametara mora biti koliko i formalnih, moraju biti navedeni u odgovarajućem redosledu, a odgovarajući formalni i stvarni parametri moraju biti istog tipa. (Ukoliko stvarni parametar nije istog tipa kao odgovarajući formalni parametar, VBA pokušava da obavi konverziju tipa, što nije uvek moguće).

Neka je definisana funkcija f. Ona računa izložilac najvećeg stepena broja 2 koji ne prelazi x; tj. vrednost f(x) je n, gde je 2n <= x < 2n+1. Npr, f(46) = 5 jer je 25 = 32 <= 46 < 64 = 26.

Function f(x as Integer) as Integer

    f = 0

    While x >= 2

        x = x \2

        f = f + 1

    Wend

    MsgBox x 'Ispisuje vrednost formalnog parametra x

End Function 

Neka procedura test poziva funkciju f.

Sub test()

    Dim m as Integer 

    m = 46

    MsgBox f(m) 'Ispisuje f(46) = 5

    MsgBox m 'Ispisuje vrednost stvarnog parametra m

End Sub 

Postavlja se pitanje: kolika je vrednost promenljive m posle poziva funkcije f?

Postoje dva načina za prenos argumenata u VBA:

Prenos po adresi bi podrazumevao da formalni i njemu odgovarajući stvarni parametar predstavljaju istu memorijsku lokaciju. Stoga bi formalni i njemu odgovarajući stvarni parametar mogli imati različita imena, ali njihov sadržaj bi se nalazio na istoj adresi u memoriji. Tako bi svaka promena vrednosti formalnog parametra u okviru potprograma dovela i do promene vrednosti odgovarajućeg stvarnog parametra.

U ovom konkretnom primeru, prenos po adresi bi značio da su x i m jedno te isto, te bi prilikom ispisivanja njihovih vrednosti u oba slučaja MsgBox prikazao 1. Dakle, prenos po adresi bi doveo do toga da se vrednost promenljive m promeni u okviru poziva funkcije f(m).

S druge strane, prenos po vrednosti bi podrazumevao da se prilikom poziva potprograma kreira posebna memorijska lokacija za formalni parametar i da se u nju kopira vrednost odgovarajućeg stvarnog argumenta. Na taj način bi formalni i njemu odgovarajući stvarni parametar predstavljali dve različite memorijske lokacije i promena vrednosti formalnog parametra ne bi uticala na vrednost stvarnog parametra.

U ovom konkretnom primeru, prenos po vrednosti bi značio da promenljivama x i m odgovaraju dve različite memorijske lokacije, i promena vrednosti prve ne utiče na drugu, tj. MsgBox x bi prikazao 1, a MsgBox m - vrednost 46. Dakle, prenos po vrednosti ne bi doveo do toga da se vrednost promenljive m promeni u okviru poziva funkcije f(m).

VBA omogućava oba navedena prenosa argumenata, tj. i prenos po referenci i prenos po vrednosti. Da bi se zadao odgovarajući prenos argumenata, prilikom deklaracije formalnog parametra navodi se ByRef (za prenos po adresi/referenci) ili ByValue (za prenos po vrednosti). Ukoliko se ekplicitno ne navede ni ByRef ni ByValue, efekat je isti kao da je navedeno ByRef (tj. u VBA je prenos po adresi podrazumevani način za prenos argumenata potprograma).

Prema tome, u gore navedenom primeru efekat je isti kao da je funkcija definisana sa:

Function f(ByRef x as Integer) as Integer

    f = 0

    While x >= 2

        x = x \2

        f = f + 1

    Wend

    MsgBox x 'Ispisuje vrednost formalnog parametra x

End Function 

Stoga je vrednost na kraju vrednost promenljive m ista kao i za x, tj. 1. Ako ne želimo da se vrednost promenljive m promeni prilikom poziva funkcije f, koristićemo sledeću definiciju:

Function f(ByValue x as Integer) as Integer

    f = 0

    While x >= 2

        x = x \2

        f = f + 1

    Wend

    MsgBox x 'Ispisuje vrednost formalnog parametra x

End Function