2.2.1 Was sind Prozeduren und Funktionen?
Prozeduren und Funktionen sind grundlegende Bestandteile eines Programmes. Mit Hilfe von Prozeduren und Funktionen werden bestimmte Aufgaben in sich abgeschlossen Unterprogrammen gekapselt. Mit der Hilfe von Prozeduren und Funktionen kann man sich einen eigenen Befehlsvorrat für ständig wiederkehrende Aufgaben anlegen. Bei Prozeduren dienen zum Ausführen weiterer Aufgaben, aber man erhält kein direktes Ergebnis zurück.Bei  Funktion wird zum Schluß ein Ergebnis zurückgegeben. An beide kann man Parameter übergeben.

Aufbau von Prozeduren

Prozeduren werden mit "Sub Prozedurname" eingeleitet und mit "End Sub" beendet. Dazwischen kommt der Programmcode.

Hier ein Beispiel:

Sub TestProzedur
    msgbox "Heute ist der " & Date
End Sub


graphic

Diese Prozedur zeigt in einer MessageBox das aktuelle Datum an. Das ist natürlich nicht der Idealfall für eine Prozedur, da hier eigentlich außer einer Programmzeile ( msgbox "Heute ist der " & Date) drei Zeilen werden. Prozeduren sind dann sinnvoll wenn Aufgaben im Programm mehrfach aufgerufen werden oder wenn man durch Prozeduren das Programm in übersichtliche Teilaufgaben zerlegen kann. Das Hauptprogramm ruft dann nur nach einander die Prozeduren auf oder wiederholt bei Bedarf wieder den Aufruf.

Sie wollen zum Beispiel eine Datei speichern und müssen dazu erst den Dateinamen und dann der Speicherort abfragen. Das ist ja eindeutig eine Aufgabe die öfter vorkommen soll. Also erstes wird nach dem Dateinamen gefragt, danach nach dem Speicherort und zum Schluß wird die Datei gespeichert.

Hier der Code als Aufgabenbeschreibung:

Sub Speichern
     Abfrage des Dateiname
     Abfrage des Speicherortes
     Zusammensetzen des Dateinamens und Speicherortes
     Speichern der Datei
     Bestätigung des Speicherns
End Sub

Als StarBasiccode

Sub Speichern
   Dateiname = InputBox ("Geben Sie bitte den Dateinamen ein:")
   Speicherort = InputBox ("Geben Sie bitte ein Verzeichnis ein:")
   mydoc = ThisComponent
   myUrl=  Speicherort + Dateiname
   mydoc.storeasurl(myurl,args())  
   msgbox "Ihre Datei wurde gespeichert"
End Sub
     
So jetzt haben wir eine Prozedur von sechs Zeilen die man jederzeit mit einer Zeile ( "Speichern") im Programm aufrufen kann. Bitte jetzt nicht nach den Details zu Speichern fragen, dazu komme ich weiter hinten im Buch. Und selbstverständlich gibt es für Speichern ja den Menüpunkt "Speichern", der eigentlich auch eine Prozedur ist, aber ich wollte ein Beispiel das man sofort nachvollziehen kann.

Diese Prozedur wollen wir jetzt noch ein wenig ergänzen. Zum Beispiel liegt der Speicherort schon fest. Das heißt diesen müssen sie nicht abfragen. Jetzt haben sie zwei Möglichkeiten. Sie können den Speicherort in der Prozedur festlegen. Statt der Abfrage "  Speicherort = InputBox ("Geben Sie bitte den Dateinamen ein:")" kommt dann zum Beispiel "Speicherort = "C:\". Dann müssen sie aber für jeden neuen Speicherort eine neue Prozedur schreiben ( SpeichernC, SpeichernD etc). Die zweite Möglichkeit ist, das sie den Speicherort der Prozedur als Paramter übergeben. Sie können an Prozeduren Parameter nach folgendem Syntax übergeben: Sub Prozedurname (Paramater1 as Typ, Parameter2 as Typ,....). In unserem Beispiel übergeben wir den Speicherort als String:

Sub Speichern ( Speicherort as String)
   Dateiname = InputBox ("Geben Sie bitte den Dateinamen ein:")
   mydoc = ThisComponent
   myUrl=  Speicherort + Dateiname
   mydoc.storeasurl(myurl,args())  
   msgbox "Ihre Datei wurde gespeichert"
End Sub

Jetzt können Sie diese Prozedure beliebig oft mit verschiedenen Speicherorten aufrufen. Z.B. speichern ( "C:\"), speichern("C:\MeineDaten"), etc.

Beim Aufrufen von Prozeduren mit Paramtern müssen Sie nur darauf achten das sie die gleiche Anzahl an Parametern und die gleichen Typen übergeben, wie Sie in der Deklaration angeben haben. In unserem Beispiel kann ich zum Beispiel als Speicherort keine Zahl übergeben ( Speichern( 12) ), da eine Zahl kein String ist.

Was sind nun Funktionen? Eigentlich auch Prozeduren, nur das diese ein Ergebnis zurück liefern. Eine Procedure führt etwas aus. Eine Funktion führt etwas aus und erzeugt ein Ergebnis. Um dieses Ergebnis richtig zuordnen zu können muss die Art des Ergebnisses vorher festgelegt werden. Daher hat eine Funtion folgenden Aufbau:

Function Name ( Parameter1, Paramater2,...) as Typ
  Name=Ergebnis
End Function

Sie sieht also der Prozedur sehr ähnlich, nur das statt sub function steht und das der Typ noch festgelegt wird. Und das innerhalb der Funktion das Ergebnis übergeben werden muß.

Machen wir hierzu auch ein Beispiel.

Nehmen wir an wir brauchen für unsere Programm eine bestimmte Berechnung mehrmals. Zum Beispiel die Mehrwertsteuer eines Bruttobetrages abhängig vom Mehrwertsteuersatz.
( Bruttobetrag 116,- Eur Nettobetrag 100,- Eur, Mehrwersteuer 16,- Eur, 16% Mwst).
Ein Weg zum Ergebnis:
 
  Bruttobetrag - Nettobetrag = Mehrwertsteuer
  Nettobetrag = Bruttobetrag / (1+ 1/100 Zinsatz)

Bei der Funhtion müssen wir als Parameter den Bruttobetrag und den Zinsatz übergeben, als Ergebnis erhalten wie eine Zahl mit Kommastellen.

Function Mehrwertsteuer ( Brutto as Double, Zinssatz as double) as double
Dim Zinsfaktor as double
Zinsfaktor = 1 +  Zinssatz / 100
Netto = Brutto / Zinsfaktor
Mehrwertsteuer = Brutto - Netto
End Function

Diese Funktion wird dann im Programnm mit "variable = mehrwertsteuer (Bruttobetrag, Zinssatz)" aufgerufen. Zum Beispiel:

steuer = mehrwertsteuer( 1234, 16)

Dann bekommt steuer den Wert 170,206.....

Jetzt können Sie jeder Zeit mit einer Programmzeile die Mehrwertsteuer eines Betrages ausrechnen lassen.
Funktion können zum Beispiel für mathematische Aufgaben, Textverarbeitungen und  für Wahrheitsprüfungen verwendet werden. Bei eine Wahrheits- Boolschen Funktion wird der Zustand Wahr oder Falsch ( true oder false) zurückgeben.



Jetzt kommen noch zusätzliche Eigenschaften beim Aufruf von Prozeduren und Funktionen hinzu. Diese betreffen die Parameter.

a. Optional

Parameter mit der Beigabe "Optional" müssen beim Aufruf nicht übergeben werden. Diese werden, wenn sie nicht gefüllt sind automatisch mit einem Leerwert versehen. Ob der Parameter gefüllt worden ist kann man mit der Funtkion "ismissing" testen. Dieses verhalten gilt sowohl für Prozeduren, wie auch Funktionen.

if IsMissing(mytext2) then
    myText2 = "Keine Text"
end if

Ist der Parameter jetzt nicht gefüllt wird der Text "Kein Text" eingetragen. Umgekehrt kann man mit "not IsMissing()" auch die positive Fragen stellen.


b. ByVal

Paramater die mit dem Vorsatz "ByVal" übergeben werden, können keinen neuen Wert annehmen. Was bedeutet das?
Normalerweise werden die Parameter an Funktionen als Referenz übergeben. Man könnte es als ausleihen beschreiben. Blöderweise kann aber die Prozedur oder Funktion den geliehenen Parameter auch ändern. Auf diese Weise kann man zum Beispiel auch eine Prozedur als Funktion verwenden.

Diese  Prozedur
Sub NeuerWert( Zahl as Integer)
  Zahl = Zahl*100
End Sub

führt genauso zu einem neuen Wert von "Zahl" wie diese Funktion

Function funcNeuerWert(Zahl as Integer)
funcNeuerWert=Zahl*100
End Function

Wenn man diese beiden "Funktionen" ein Programm einbindet:

Sub TestNeuerWert
   MyWert=10
   NeuerWert(MyWert)
   ErsteZahl=MyWertl
   MyWert=fNeuerWert(myWert)
   ZweiteZahl=MyZahl
   MsgBox "Erste Zahl: " +ErsteZahl+" Zweite Zahl: "+ZweiteZahl
end sub  

kommt die vielleicht gar nicht gewollte Vervielfachung des Ausgangswertes heraus.
graphic

Dies kann man durch zwei Wege verhindern. Der erste ist, wie es sich gehört für einen guten Programmierer, ordentlich programmieren und niemals Parameter einer Prozedur oder Funktion mit neuen Werten belegen, wenn es nicht die Absicht der Prozedur ist. Eine Funktion sollte nie einen Parameter als versteckte Rückgabe ändern. Eine Funktion gibt ein Ergebnis zurück und sollte ansonsten auch nichts ändern.
Der zweite Weg ist der Parameter ByVal. Mit diesem wird der Parameter als Wert übergeben und nach dem durchlaufen der Prozedur oder Funktion, wird der alte Wert wieder gesetzt. Wenn man also sicher sein will das sich der Parameter nicht ändern kann, setzt man ByVal davor. Dies ist auch sinnvoll wenn man eine Funktion oder Prozedur schreibt die man in mehreren Programmen verwenden will.

Verwendet man in unserem Beispiel in der Prozedur jetzt ByVal

Sub NeuerWert(ByVal Zahl as Integer)
  Zahl = Zahl*100
End Sub

Kommen zum Schluß weniger große Zahl heraus.

graphic