Arbeitsanleitung
A1.Starten Sie Microsoft EXCEL und legen Sie ein neues Makro an, das Sie dem Namen
"Aufgabe1" geben.
Sie sehen nun (ungefähr) den Bildschirminhalt der folgenden Abbildung
Was sollten Sie verstehen?
1) Was ist eine Prozedur? Eine Prozedur ist ein mit einem Namen versehener
Programmteil, der für die Erledigung bestimmter Aufgaben programmiert wurde.
Von unserer EXCEL-Übung kennen Sie bereits die Wenn- Funktion. Hierbei handelt es sich um eine "Funktionsprozedur".
Die Syntax der Wenn-Funktion lautet:
WENN(Prüfung;Dann_Anweisung;Sonst_Anweisung)
Wichtig ist die offene Klammer nach dem Wort "WENN"; die offene Klammer leitet die Parameterliste ein. Im Fall der Wenn- Funktion übergeben Sie drei Parameter (= 3 Informationen:
1) was soll geprüft werden?
2) was passiert, wenn die Prüfung das Ergebnis "wahr"
liefert?
3) was passiert, wenn die Prüfung das Ergebnis "falsch"
liefert?
2) Warum steht hinter
"Aufgabe1" das Klammerpaar ()
Würde nur der Text 'Aufgabe1' an dieser Stelle stehen, würde VBA 'vermuten', daß dort ein Variablenname steht. Mit dieser Variablen müßte jedoch etwas "passieren", d.h. VBA erwartet, daß der Variablen ein Wert zugewiesen wird, z.B. in folgender Art:
Aufgabe1 = a^2 + b^2
So etwas wollen wir aber nicht. Wir wollen nur dem
Programmabschnitt zwischen SUB und END SUB den Namen Aufgabe1 geben. Wir müssen also kenntlich machen, daß es sich um eine Prozedur handelt. Dies geschieht mit dem Klammerpaar.
Anders als bei der o.g. WENN-Funktion übergeben wir der Prozedur Aufgabe1() jedoch keine Parameter – die
Parameterliste ist leer.
3) Warum muß man einer Prozedur nicht unbedingt Parameter übergeben?
Man kann die notwendigen Werte innerhalb der Prozedur als Konstante definieren und/oder vom Anwender abfragen.
"Sub" ist ein Schlüsselwort, durch die eine Sub- Prozedur (hier mit dem Namen Aufgabe1)
eingeleitet wird. Das Ende der Prozedur wird durch
"End Sub" gekennzeichnet.
Zwischen "Sub" und "End Sub" können Sie nun Ihre gewünschten VBA-Deklarationen und
Programmanweisungen eintragen, je nachdem, was die Prozedur Aufgabe1 leisten soll.
Wir wollen nun die Prozedur Aufgabe1() dazu verwenden, eine Arbeitsaufgabe zu erledigen:
Der Anwender soll 10 Zahlen (z.B. die täglichen Überstunden – nur ganze Zahlen) eingeben können. Diese sollen aufsummiert und die Summe ausgegeben werden.
Was sollten Sie sich an dieser Stelle überlegen?
1) Welche Variablen benötige ich?
1) Eine Variable (= ein Speicherplatz; analog einer Zelle im Excel-Arbeitsblatt), in die ich die Angaben des Anwenders einlese. Diese Variable muß ganze Zahlen speichern können (Datentyp Integer oder Long). Benötige ich 10 Variable für die Überstunden? In diesem Fall nicht, denn ich muß nur die Einzelwerte aufsummieren. Ich muß nicht mehr auf die Einzelwerte zugreifen können.
2) Eine Variable, in die ich die Summe eintrage.
3) Ich muß den Anwender mehrfach nach seinen Überstunden befragen. Ich benötige also eine Kontrollstruktur, die mir dies ermöglicht.
2) Welche
Kontrollstrukturen benötige ich?
Eine Schleife. In VBA gibt’s verschiedene Schleifen-Typen. Die Unterschiede werden später gezeigt. Wir wollen zunächst eine For...Next-Schleife verwenden. Dieser Schleifentyp ist dann geeignet, wenn ich bereits vor der Schleife weiß, wie oft ich sie durchlaufen muß (entweder hat's der Anwender uns über eine Eingabe vorher mitgeteilt – oder in unserem Fall wissen wir, daß wir 10 Durchgänge zu absolvieren haben)
3) Weitere Variable ? Damit der Anwender nicht bis in die Unendlichkeit nach seinen Überstunden gefragt wird, müssen wir mitzählen, wie oft wir ihn bereits gefragt haben. Wir benötigen also einen
Schleifenzähler.
Sie können also Ihre Prozedur wie folgt erweitern:
Sub Aufgabe1()
Dim int_einzelueberstunde%, int_gesamtueberstunden%, int_i as integer For int_i = 1 to 10
next int_i End Sub
Hinweis: Es erleichtert die Suche nach Fehlern, die auf der Unverträglichkeit von Datentypen beruhen (wenn Sie z.B. eine Anweisung schreiben, in der eine Variable, die die Zahl 100 enthält, durch eine Variable teilen, die den Text "Käse" enthält), wenn zu jeder Variablen eine Abkürzung ihres Datentyps (hier int_ für "Integer") vorangestellt wird. Sie können dann leicht mittels des Debuggers (Fehlersuchtool) erkennen, ob in der jeweiligen Variablen der Wert in der gewünschten Form abgespeichert wird.
Was benötigen wir jetzt noch?
Eine Eingabefunktion für die einzelnen Überstunden. Hierzu steht z.B. die InputBox zur Verfügung.
Die Allgemeine Syntax lautet:
InputBox(prompt[, title] [, default] [, xpos] [, ypos] [, helpfile, context])
Für Ganzzahlen bis ca. 32.000 verwenden Sie INTEGER; für Zahlen bis rund 2 Mrd LONG; Ansonsten ist für Sie derzeit (2. SEM.) nur wichtig:
DatentypSTRING für Zeichenketten und Datentyp DOUBLE für
Gleitkommazahlen. Variablen sind vom Typ Variant. Benötigen viel Platz und VBA konvertiert nicht in jedem Fall richtig
Um die Eingabe des Anwenders in der Variablen int_einzelueberstunde zu speichern, schreiben Sie folgende Anweisung:
int_einzelueberstunde = InputBox("Geben Sie die Überstunden eines Tages ein") Frage: In welche Zeile (vor, innerhalb oder nach der For...Next-Schleife) muß diese Anweisung stehen?
Hinweis: Alles, was über die InputBox vom Anwender eingegeben wird, wird zunächst als Textstring behandelt. D.h. auch Zahlen sind zunächst Text. VBA muß in unserem Fall eine Typumwandlung von String nach Integer vornehmen. VBA ist nicht fehlerfrei. Eine explizite Typumwandlung (Sie programmieren, in welchen Typ die Eingabe umzuwandeln ist) ist deshalb besser:
Die Anweisung lautet jetzt:
int_einzelueberstunde = int(InputBox("Geben Sie die Überstunden eines Tages ein")) Sub Aufgabe1()
Dim int_einzelueberstunde%, int_gesamtueberstunden%, int_i as integer For int_i = 1 to 10
int_einzelueberstunde = Cint(InputBox("Geben Sie die Überstunden eines Tages ein")) next int_i
End Sub
Nun muß die Anwendereingabe aufsummiert werden. Die Anweisungen werden dabei (anders als in mathematischen Gleichungen) von rechts nach links abgearbeitet. D.h. Ihre Prozedur sieht jetzt wie folgt aus:
Sub Aufgabe1()
Dim int_einzelueberstunde%, int_gesamtueberstunden%, int_i as integer For int_i = 1 to 10
int_einzelueberstunde = Cint(InputBox("Geben Sie die Überstunden eines Tages ein")) int_gesamtueberstunden = int_gesamtueberstunden + int_einzelueberstunde
next int_i End Sub
Wenn der Anwender alle 10 Werte eingegeben hat, ist die Gesamtsumme auszugeben.
Hierzu steht z.B. die MsgBox (=Message Box) zur Verfügung. Die Syntax lautet:
MsgBox(prompt[, buttons] [, title] [, helpfile, context]) In unserem konkreten Fall würde die Zeile lauten:
MsgBox("Gesamtüberstunden: " & int_gesamtueberstunden)
Frage: An welcher Stelle (vor, innerhalb oder nach der For...Next-Schleife muß die MsgBox stehen, wenn sie nur die Gesamtsumme ausgeben wollen/sollen?
das Pfundzeichen verknüpft zwei Konstanten und/oder Variablen.
Letztlich – mit etwas mehr Verfeinerung der InputBox – könnte sich folgender Stand ergeben:
(Hinweis: Die Initialisierung int_i = 0, int_einzelueberstunde = 0, int_gesamtueberstunden = 0 ist in diesem Fall "Luxus". In umfangreichen Programmen ist die Initialisierung von Variablen sehr wichtig. Denken Sie z.B. an ein Lohnabrechnungsprogramm, in dem Löhne für
verschiedene Mitarbeiter zum Auszahlungsbetrag aufsummiert werden. Würde nicht nach jedem Mitarbeiter die Summe wieder zurückgesetzt werden, möchte ich natürlich gerne der letzte Mitarbeiter sein, der bearbeitet wird).
Sub Aufgabe1()
' Der Anwender soll 10 Ganzzahlen eingeben. Diese werden aufsummiert und als Summe ' ausgegeben.
Dim int_einzelueberstunde%, int_gesamtueberstunden%, int_i As Integer int_i = 0
int_einzelueberstunde = 0 int_gesamtueberstunden = 0 For int_i = 1 To 10
int_einzelueberstunde = Cint(InputBox("Bitte " & int_i & "-te ganze Zahl eingeben")) int_gesamtueberstunden = int_gesamtueberstunden + int_einzelueberstunde Next
MsgBox ("Die Summe lautet: " & int_gesamtueberstunden) End Sub
Hinweis: Die Option Explicit-Anweisung" wird auf Modulebene verwendet, um die explizite Deklaration aller Variablen in diesem Modul zu erzwingen.
Was sollten Sie verstehen?
1) Sie sollen den Programmablauf
nachvollziehen können und ggf. Fehler entdecken.
Beispiel: Es wird die nebenstehende Prozedur verwendet. Der Anwender gibt z.B. 10 Mal
hintereinander die Ziffer 2 ein. Statt der
Gesamtsumme 20 wird 2222222222 ausgegeben.
Wo liegt der Fehler?
Sub Aufgabe1a()
' Der Anwender soll 10 Ganzzahlen eingeben. Diese werden aufsummiert und als ' Summe ausgegeben.
Dim int_gesamtueberstunden, int_i As Integer Dim int_einzelueberstunde As String For int_i = 1 To 10
int_einzelueberstunde = Cint(InputBox("Bitte " & int_i & "-te ganze Zahl eingeben")) int_gesamtueberstunden = int_gesamtueberstunden + int_einzelueberstunde Next
MsgBox ("Die Summe lautet: " & int_gesamtueberstunden) End Sub
2) Die o.g. Frage könnte auch allgemeiner gestellt werden: Warum liefert die betreffende Prozedur nicht die Gesamtsumme von den 10 eingegebenen Zahlen?
Wie müsste der Prozedur
Variablendeklaration
Datentyp
Allgemeine Syntax:
InputBox(prompt[, title] [, default] [, xpos]
[, ypos] [, helpfile, context])
Allgemeine Syntax:
MsgBox(prompt[, buttons] [, title] [, helpfile, context])
umgeschrieben werden?
3) Analog dem aus der Testklausur bekannten Fehler #DIV/0! ist auch die Suche nach der Division durch Null in einer VBA- Prozedur denkbar. Beispiel s. nebenstehende Prozedur:
Welchen Vorschlag haben Sie, dieses Problem zu lösen?
(naheliegenderweise:
dbl_Kalkzins durch
dbl_Kalkulationszins ersetzen
"toller Vorschlag" für Bonus:
Option Explicit im Deklarationsteil verwenden
Fachlicher Hintergrund (der für die Fehlersuche aber unbedeutend ist): Der Ertragswert eines Grundstücks
berechnet sich aus dem jährlichen Ertrag dividiert durch einen Kalkulationszins. Beides soll vom Datentyp Double sein. Der Prozedurcode sieht folgendermaßen aus:
Sub Aufgabe1b()
' Der Anwender soll den jährlichen Ertrag und den Kalkulationszins eingeben.
' Die Prozedur soll den Ertragswert berechnen.
Dim dbl_jaehrlicherErtrag#, dbl_Ertragswert As Double
dbl_jaehrlicherErtrag = CDbl(InputBox("Bitte jährlichen Ertrag eingeben")) dbl_Kalkulationszins = CDbl(InputBox("Bitte Kalkulationszins eingeben")) dbl_Ertragswert = dbl_jaehrlicherErtrag / dbl_Kalkzins
MsgBox ("Der Ertragswert beträgt: " & dbl_Ertragswert) End Sub
Aufgabe bis zum nächsten Crash-Kurs: Sie überlegen sich (und schreiben möglichst die Prozedur), wie in der Prozedur Aufgabe1() der Anwender eine beliebige Anzahl von Überstunden eingeben kann.