Funktion ◦ Zusammenfassung ◦ ?

### Begriff

Eine Subroutine führt mehrere zusammengehörende Anweisungen aus, ohne einen Wert zurückzugeben. Calculate, eine Methode der Objekthierarchie von Excel, berechnet zum Beispiel alle Formeln des Zellbereichs A:C des Tabellenblatts XY neu:

>     Worksheets(“XY”).Columns(“A:C”).Calculate

zeigeBereichRot() ist hingegen benutzerdefiniert und zeigt den Zellbereich “XY” rot an:

>     Sub zeigeBereichRot()
>       Range(“XY").Select			'Zellenbereich markieren
>       Selection.Font.ColorIndex = 3	'Farbindex des markierten Bereichs auf 3 (rot) setzen
>     End Sub

Eine Funktion gibt im Gegensatz zur Subroutine immer einen Wert zurück. Die Tabellenblatt-Funktion SUMME(3;2) ergibt zum Beispiel die Zahl 5. Wegen des Rückgabewerts kann ein Funktion in einer Formel vorkommen:

>     SUMME(3;2) + 5.

### Beispiel

Dieser Abschnitt veranschaulicht Anweisungen (insbesondere Ablaufstrukturen), Unterprogramme (Subroutinen und Funktionen), Datentypen und Objekte am Programm Wort.xls. Es löscht Wort für Wort einer Textzeile, bis sie leer ist. Der folgende Bildschirmausschnitt veranschaulicht den Ablauf am Beispiel der Textzeile “Oh Klotil de, Du allein sollst und musst die Meine sein”:

Wort.xls gibt den Text auf dem Tabellenblatt “Ausgabeblatt” aus. Jede Zelle des Tabellenblatts beginnt auf dem Schnittpunkt einer Zeile und einer Spalte. Sie lässt sich deshalb mit der Eigenschaft Cells(Zeile, Spalte) eindeutig adressieren: Die Zeilen eines Tabellenblatts sind von oben bis unten und die Spalten von links nach rechts nummeriert. Die erste Zeile des Klotilde-Texts steht in der Zelle (2, 2), die nächste in (3, 2) und die letzte in (11, 2).

Die Benutzerin startet die Hauptprozedur WortFürWortLöschen(), indem Sie den Cursor darauf positioniert und »F5 drückt. Zuerst weist der Code den Text “Oh Klotilde ...” der Zelle (2,2) zu. Dann löscht er solange das erste Wort dieses Texts und gibt ihn auf der nächsten Zeile aus, bis er leer ist. Das Löschen eines Worts und die Prüfung auf das Schleifenende übernimmt die Funktion einWortWeniger(Text).

>     Sub WortFürWortLöschen()
>       Dim Zeile As Integer, Text As String

>       '-- Initialisieren
>       Zeile = 2
>       Text = “Oh Klotilde, Du allein sollst und musst die Meine sein”
>       Ausgabeblatt.Cells(Zeile, 2) = Text		'Text in Zelle (2,2) ausgeben
>       '-- Text fortlaufend amputieren und auf der nächsten Zeile ausgeben
>       Do While einWortWeniger(Text)
>         Zeile = Zeile + 1				'Adresse der neuen Zeile
>         Ausgabeblatt.Cells(Zeile, 2) = Text
>       Loop
>     End Sub

Die Ausführungsbedingung einWortWeniger(Text) trifft solange zu, wie es möglich ist, auf jeder neuen Zeile ein Wort weniger anzuzeigen. Weil eine Bedingung immer wahr oder falsch ist, muss einWortWeniger(Text) True oder False ergeben. Der Rückgabewert hat also den Datentyp Boolean. Das Hilfethema Argumente erwähnt nur Argumente, die nach dem Aufruf nicht geändert werden. Das Argument Text von einWortWeniger(Text)ist hingegen ein Eingabe- und Ausgabeargument. Es wird von einWortWeniger(Text) verändert zurückgegeben - nämlich um ein Wort kürzer. Wir werden dieses Problem später vertiefen.

WortFürWortLöschen() ruft system- und benutzerdefinierte Funktionen auf:

- Cells(Zeile, Spalte) ist eine systemdefinierte Funktion.

- einWortWeniger(Text) ist eine benutzerdefinierte Funktion.

einWortWeniger(Text) ruft ihrerseits die folgenden systemdefinierten Funktionen auf:

Funktionsname und -argumente | Rückgabewert
InStr(Text, String) | Position von String in Text
Right(Text, N) | N rechte Zeichen von Text
Len(Text) | Zeichenzahl (Length) von Text

Die Definition von einWortWeniger folgt der allgemeinen Funktionssyntax:

> Function <Name> ( <Argumente> ) As <Rückgabetyp>
> <Vereinbarungsanweisungen>
> <ausführbare Anweisungen>
> End Function

>     Function einWortWeniger(Text As String) As Boolean
>       Dim PosLeer As Integer

>       PosLeer = InStr(Text, “ ”)
>       If PosLeer <> 0 Then
>         Text = Right(Text, Len(Text) - PosLeer)
>         einWortWeniger = True
>       Else
>         einWortWeniger = False
>       End If
>     End Function

Weil einWortWeniger(Text) den Text ohne das erste Wort zurückgibt, sucht es zuerst die Position der ersten Leerstelle des Texts (PosLeer). Falls eine Leerstelle existiert, weist die Funktion dem Argument Text den bisherigen Text ohne die Zeichen bis und mit der ersten Leerstelle zu. einWortWeniger wird False, falls keine Leerstelle mehr existiert, die den Text in einen linken und rechten Teil trennt.

### Argumentübergabe

Jeder Aufruf von einWortWeniger(Text) ergibt nicht nur einen Rückgabewert True oder False, sondern ändert auch das Argument Text. Grundsätzlich kann ein Aufruf einer Funktion oder Subroutine ein Argument als Adresse oder als Kopie übergeben. Für unser Beispiel heisst dies:

- Text kann als Adresse übergeben werden (engl.call by reference)

> Das Argument steht im Speicherbereich der aufrufenden Subroutine WortFürWortLöschen(). Wenn die aufgerufende Funktion einWortWeniger(Text) dieses Argument ändert, modifiziert es also einen Speicherplatz von WortFürWortLöschen(). einWortWeniger(Text) ändert also direkt eine Variable von WortFürWortLöschen(), das heisst jeder Aufruf löscht unwiderruflich ein Wort des Originaltexts. Die Ausgabe von WortFürWortLöschen() sieht deshalb wie folgt aus:

> Oh Klotilde, Du allein sollst und musst die Meine sein
> Oh Klotilde, Du allein sollst und musst die Meine
> Oh Klotilde, Du allein sollst und musst die
> ...

- Text kann als Kopie übergeben werden (engl. call by value)

> Das aufgerufende Programm würde nur eine Kopie der Variable Text von WortFürWortLöschen() verwenden. Die ursprüngliche Variable Text bliebe also erhalten. Die Ausgabe von WortFürWortLöschen() wäre also auf allen Zeilen die gleiche:

> Oh Klotilde, Du allein sollst und musst die Meine sein
> Oh Klotilde, Du allein sollst und musst die Meine sein
> Oh Klotilde, Du allein sollst und musst die Meine sein
> ...

Die Übergabe einer Adresse (call by reference) sollte nur dann gewählt werden, wenn der Entwickler sicher ist, dass die übergebene Variable geändert werden darf. Call by reference ist allerdings effizienter, weil keine Kopie erstellt werden muss. Es ist deshalb in den meisten Programmiersprachen die Voreinstellung. Ein Argument, das als Kopie übergeben wird, muss in der Vereinbarung mit ByVal eingeleitet werden. In unserem Beispiel hiesse die Vereinbarung Function einWortWeniger(ByVal Text As String) As Boolean.

Die folgende Abbildung veranschaulicht die Übergabe eines Arguments grafisch:

Die folgende Tabelle bewertet die beiden Aufrufarten zusammenfassend:

| By Reference | By Value
Syntax | Voreinstellung | ByVal
Übergabe | Adresse | Kopie
Speichereffizienz | + | -
Laufzeiteffizienz | + | -
Sicherheit | - (Aufrufumgebung beeinflusst) | + (Aufrufumgebung bleibt unbeeinflusst)

Übung WortExperiment