VBA-Programmierung: Objekte von Anfang an

Werbung
Berufsbildende Schule Wirtschaft Trier
Wirtschaftsgymnasium
VBA-Programmierung Objekte von Anfang an
Unterrichtsmaterialien
von Christoph Oberweis
Stand: 21.01.2014
1
Inhalt
1
Modelle der Wirklichkeit
1.1 Anwendungsprogramme und Objektorientierung
1.2 Klassen
1.3 Von der Klasse zu Objekt
2
Implementierung in VBA
3
Module, Klassenmodule und UserForms
4
Die logischen Grundstrukturen
4.1 Algorithmus und Struktogramm
4.2 Sequenz, Abfragen und Schleifen
4.3 Funktionen und Prozeduren (Ergänzungen)
5
Algorithmen mit strukturierten Datentypen
6
VBA und EXCEL
Literatur:
HELD, B. (2000): EXCEL-VBA-Programmierung.- München, Mark und Technik-Verlag
JANKA, A. (2005): VBA mit Word. – Bonn, Galileo Computing - Verlag
MARTIN, R. (1999): VBA mit Office 2000 lernen. – Bonn, Addison-Wesley – Verlag
MINHORST, A. (2005): Das Access 2003 Entwicklerbuch.- Bonn, Addison-Wesley – Verlag
MINHORST, A. (2012): Anwendungen entwickeln mit Access.- Duisburg, André MinhorstVerlag
2
1 Modelle der Wirklichkeit
1.1 Anwendungsprogramme und Objektorientierung
Erst durch eine geeignete Software kann der Computer Probleme der realen
Welt lösen. Hintergrund einer betriebswirtschaftlich orientierten Software sind
letztlich immer Geschäftsprozesse; dies gilt sowohl für Standardsoftware wie
z.B. Officepakete als auch für Individualsoftware wie z. B. eine prozessorientierte Auftragsabwicklung eines Produktionsbetriebs.
Software bildet einen Ausschnitt der realen Welt in einer Modellwelt ab. Diese
Modellwelt ist (im Gegensatz zur realen Welt) auf nur die Notwendigkeiten
reduziert, die benötigt werden, um die jeweiligen Probleme der betrieblichen
Wirklichkeit mit Hilfe von Computern zu lösen. Modellierung ist der Transfer
eines Ausschnittes der realen Welt in ein Modell. Objekte der realen Welt
(Kunde, Artikel usw.) und ihre Eigenschaften (Kundennummer, Artikelbezeichnung) werden zu Objekten inkl. ihrer Attribute in der Modellwelt. Der
Begriff „Objekt“ ist nun allerdings als Fachbegriff der Informatik zu verstehen.
Beispiel: Ein Autohaus der wirklichen Welt, die Autos sind
Objekte. Das Foto ist bereits ein Modell!
Modell: Idealisierte Darstellung der realen Welt zur Veranschaulichung
bestimmter Sachverhalte/Eigenschaften o. Ä.
Das Foto zeigt bestimmte Dinge (z. B. aktuelle Trendfarbe, Design) in
einem bestimmten Maßstab aus einer bestimmte Perspektive usw.:
Ikonisches Modell (bildhaft)
3
Fortschreitende Abstraktion:
23.08.2006, 11:30
Abstraktion: Verzicht auf Details, die Darstellung wird „ungenauer“,
jedoch bleiben z. B. Standort und Silhouette der Fahrzeuge weiterhin
erkennbar. Allerdings wurden nun Datum und Uhrzeit der Aufnahme
hinzugefügt: Mit diesem Modell könnte z. B. dargestellt werden, welche
Arten von Kraftfahrzeugen (PKW, LKW, Bus usw.) zu diesem Zeitpunkt an
diesem Ort abgestellt waren. Farbinformationen wären dann unwichtig,
ebenso Plakate und Fahnen (s. vorheriges Bild).
Viele Aspekte der Wirklichkeit werden modelliert: z. B.: Welche
Stellplätze sind belegt?
Analogmodell: hier eine Lageskizze der Stellplätze, stark vereinfachte
Karte, jedes abgestellte Fahrzeug wird zu einem „X“ („Analogie“:
Analogmodell, eine noch weitere Abstraktion der Wirklichkeit)
4
Eine vorläufige vereinfachte Aussage, was Modellierung in der Praxis bedeutet:
Modellierung ist eine Vorgehensweise, bei der Software-Entwickler versuchen,
einen für sie relevanten realen Ausschnitt der wirklichen Welt so zu
vereinfachen und „in den Griff zu bekommen“, dass aus dem Ergebnis, dem
Modell, möglichst effizient Software entwickelt werden kann. Die Modelle
sollen auch Nicht-Informatikern (z. B. Betriebswirten), die allerdings Fachleute
für das zu lösende Problem sind, verständlich sein. Dies erleichtert Absprachen
hinsichtlich der Lösungen. Zudem sollen sich die Modelle an modernen
Paradigmen der Informatik orientieren (objektorientierte GUIs, Inter-netAnwendungen, Schichtenmodelle usw.).
Eine weitere Betrachtungsweise: Was haben alle Kfzs gemeinsam?
Gemeinsamkeiten: Vier Räder, Lenkrad, Motor, Türen, eine Angabe
hinsichtlich der Leistung usw.
Die Gemeinsamkeiten können in einer „Schablone“ festgelegt werden.
Mit dieser lassen sich dann im Sinne eines Bauplans individuelle Autos
mit unterschiedlichen individuellen Merkmalen „erzeugen“.
5
1.2 Klassen
Zur Erzeugung individueller Fahrzeuge mithilfe der Schablone werden nun
Eigenschaften der Schablone genauer festgelegt:
Kfz
Hersteller: Text
Typ: Text
………
Hubraum: Ganzzahl
………
Farbe: Text
…….
Schablone, nach dieser könnten (fast)
unendlich viele Fahrzeuge gebaut
werden. Allerdings benötigt dieser Plan
exakte Angaben zu den Details des
Fahrzeugs: Eigenschaften
So könnte ein Bauplan formuliert sein:
Zahlen und Texte als Informationen zu
den Eigenschaften des Fahrzeugs
Bei dieser Betrachtungsweise ist nun Folgendes zu beachten: Den Eigenschaften (man
spricht auch von Attributen) wie „Hubraum“, „Farbe“ usw. sind in der Schablone noch keine
Werte zugeordnet. Sie sind gleichsam Namen für „Platzhalter“ (Variablen) und lediglich
danach spezifiziert, welche „Sorte“ (= Typen) von Zeichen später bei den individuell
erzeugten Fahrzeugen hier stehen dürfen.
Zusammenfassung:
6
Es ist nun erforderlich, der Schablone „etwas mitzugeben“, was gestattet, die
Attributswerte der später erzeugten Fahrzeuge zu setzten, zu verändern und zu
lesen. Möglicherweise sollen auch sonstige Verarbeitungen mit diesen Werten
durchgeführt werden. Natürlich könnte man unabhängig von diesen Schablonen
einfach Befehle programmieren, welche eine Veränderung der Attributswerte im
Computer durchführt (so hat man das früher gemacht). Aber genau das will die
objektorientierte Programmierung verhindern. Dadurch, dass die Datenveränderung an die Schablone gleichsam gekoppelt wird, gewinnt man bei der
Modellierung einer Kfz -Verwaltung eine größere Nähe zum Objekt der realen
Welt. Alle erlaubten Operationen auf die Attribute einer speziellen Schablone
werden in dieser festgelegt und nicht irgendwie von außen beliebig zugelassen.
Man spricht hier von Geheimhaltungsprinzip bzw. Kapselung der Daten. Es
steht also nicht im Mittelpunkt der Betrachtungsweise: „Wie programmiere ich
eine Preiserhöhung mit Plausibilitätsprüfung?“ sondern die Frage: „Was lege ich
in meiner Schablone fest, was mit den Daten des individuellen Fahrzeugs später
möglich sein soll?“
Werden nun die möglichen Verarbeitungen, (= Methoden) hinsichtlich der
Attribute der Schablone hinzugefügt, so spricht man von einer Klasse.
Merke: Der Begriff "Schablone" ist umgangssprachlich gemeint und diente nur
der Verdeutlichung, während "Klasse" ein Fachbegriff der Informatik ist!
Zur Darstellung von Klassen wird häufig
UML (Unified Modelling Language)
benutzt.
„Die Unified Modelling Language ist eine
Sprache zur Spezifikation, Visualisierung, Konstruktion und Dokumentation
von Modellen für Softwaresysteme,
Geschäftsmodelle und andere NichtSoftwaresysteme. Sie bietet den Entwicklern die Möglichkeit, den Entwurf
und die Entwicklung von Softwaremodellen auf einheitlicher Basis zu diskutieren.“
Universität Magdeburg (UML-Tutorial)
Hinweis: Die Klammern hinter den Methodennamen haben (zunächst vereinfacht ausgedrückt) folgende Bedeutung: Unterhalb der Methodennamen stehen
später Programmzeilen, die genau bestimmen, wie was zu tun ist. Mit Hilfe der
Klammern hinter „Erfassen“ könnten der Methode dann spezielle Daten übermittelt werden, die für diese Verarbeitung wichtig sind (Schnittstelle).
7
Ein weiterer Hinweis: In manchen Fachdisziplinen werden Modelle dieser Art
als Symbolmodelle bezeichnet.
Die Namen dieser Methoden deuten inhaltlich darauf hin, dass es bei dieser
Modellierung offensichtlich nicht um das Bauen der Fahrzeuge geht (Produktion
am Fließband), sondern um ihre Verwaltung beim Autohändler. Die Preisangabe
z. B. spielt hinsichtlich der rein technischen Seite der Produktion keine Rolle.
Zusammenfassend: Das gleiche Objekt der realen Welt kann völlig unterschiedlich modelliert werden, es kommt darauf an, was man mit dem Modell
erreichen will. Hier: Werden Autos gebaut oder werden sie verkauft? Eine
Klasse modelliert also ein abstraktes Fahrzeug z. B. aus der rein technischen
Sicht oder aus der Sicht von Kaufleuten. Die Attribute und Methoden sind von
diesen Sichten abhängig!
Aufgabe 1:
Entwerfen Sie bitte eine Klasse „Kunde“ (bezogen auf das Autohaus). Legen
Sie bitte sinnvolle Attribute und Methoden fest.
8
1.3 Von der Klasse zum Objekt
Liegt die Klassenbeschreibung der Fahrzeuge vor, können nun (im Computer)
nach ihr alle individuellen Fahrzeuge "erzeugt" werden, welche das Autohaus zu
einem bestimmten Zeitpunkt anbietet. Entsprechend der Klassenbeschreibung
wird dann aus jedem realen Kfz ein Objekt im Computer. Diese Objekte (man
spricht hier auch von Instanzen einer Klasse) besitzen nun ihre individuellen
Eigenschaften (Kfz-Nummer, Typ, Leistung, Farbe usw.). Vorgänge mit den
realen Fahrzeugen wie "verkauft an Frau X" oder "verkauft von dem Mitarbeiter
Herr Y" oder "letzte Inspektion am ZZZZ" können im Computer erfasst und
verwaltet werden.
:Kfz bedeutet, dass es sich hier um Objekt vom "Typ" der Klasse Kfz handelt
(um ein Objekt "Art", wie es in der Klasse Kfz festgelegt wurde).
Die Attribute besitzen nun Attributswerte, da die Objekte ja reale Fahrzeuge
abbilden.
Zur Veranschaulichung eine Analogie:
„Rezept“ entspricht „Klasse“, ein bestimmter „Geburtstagskuchen“ für Simone,
sie hat am 10.11 Geburtstag, entspricht dem „Objekt“.
Mit einem Rezept lassen sich „unendlich“ viele Kuchen backen.
Merke: Nicht das Rezept wird gegessen, sondern der Kuchen!
Oder:
Die individuellen Eigenschaften eines Fahrzeugs werden nicht in der Klasse
gespeichert, sondern im Objekt!
9
Hat man die Eigenschaften und Funktionalitäten einer Windows-Maske in einer
Klasse festgelegt, lassen sich „unendlich viele“ Masken (quasi auf Knopfdruck)
hieraus erzeugen!
Eine weitere Veranschaulichung:
Hier zeigt jede Explorer-Instanz einen anderen Teil des Dateiverzeichnisses und
jede Ansicht kann durch einen Mausklick aktiviert werden. Die Attributwerte
der jeweiligen Instanz bleiben solange erhalten, bis sie durch Klick auf den
„Schließen-Button“ entfernt wird.
10
2 Implementierung in VBA
Nun ist es erforderlich, in die VBA - Programmierumgebung zu wechseln (hier
am Beispiel mit VBA unter EXCEL, mit WORD sind die Schritte analog):
Bevor nun das Kfz-Beispiel vorgestellt wird, erfolgt zunächst zur Darstellung
des Handlings dieser Programmierumgebung ein simples Programmbeispiel
ohne Klassen und Objekte:
Projektexplorer
Eigenschaften
der Dialogbox
bzw. der
Objekte auf ihr
1. Schritt: Excel aufrufen
2. Schritt: Mit <Alt> <F11> in die Programmierumgebung wechseln
3. Schritt: „Diese Arbeitsmappe“ anklicken (Das wird später anders gemacht!)
4. Schritt: Falls jetzt schon Programmcode erscheint, diesen löschen
5. Schritt: Obiges Programm eingeben
6. Schritt: Mit <F5> Programm starten
7. Schritt: Programm testen, gegebenenfalls korrigieren
8. Schritt: Mit <Alt><F11> zurück zu Excel
In Zukunft sollten alle Quelltexte in Textdateien abgespeichert werden (Pro-grammcode
markieren, kopieren, in ein Textverarbeitungsprogramm einfügen und Dokument
abspeichern).
Hinweis: Dieses Programm kommt ohne selbstdefinierte Klassen aus. Da diese Art der
Programmierung nicht das Ziel dieser Lernmaterialien ist, wird dieser Weg nicht weiter
beschritten. Allerdings ist es wichtig, dass die Eingabe und das Testen dieses Programms
auch wirklich funktionieren und nachvollziehbar sind. Andernfalls werden die weiteren
Übungen kaum zum Erfolg führen.
11
Und jetzt die Klasse:
Die Klasse besitzt drei Attribute und zwei
Methoden. Damit lässt sich in der Realität selbstverständlich kein Fahrzeug hinreichend modellieren – es geht jetzt zunächst darum, die Klasse und ein dazu
passendes Testprogramm in VBA zu implementieren.
Auf Folgendes ist zu achten:
Klassen werden in eigenen Quellcodebereichen erfasst: Jede Klasse steht in einem eigenen Klassenmodul. Das Programm, welches auf die Klassen zugreift (das „Hauptprogramm“), steht in dem
Quellcodebereich, der oben schon beschrieben wurde. Hier wird nun der ganze
Vorgang nicht in der EXCEL-VBA-Programmierumgebung vorgeführt, sondern
in WORD-VBA. Zunächst wird nicht erklärt, wie das Programm funktioniert,
sondern es wird eingetippt und getestet. Die Erklärungen erfolgen danach.
1. Schritt: Von WORD in VBA mit <ALT><F11>
Es ist nun sinnvoll, diesen Namen auf „Testprogramm“ (o. ä) umzubenennen.
Dies erfolgt in diesem Feld (mit der Maus in das Feld gehen, alten Namen
überschreiben).
12
2. Zunächst wird die Klasse erfasst:
Hier den Menüpunkt „Klassenmodul“ anwählen …
… und das neue Klassenmodul anlegen.
13
Doppelklick auf Klasse1…
…und den Namen ändern!
Änderung!
14
Die Klasse:
3. Das Testprogramm (auch: Standardmodul):
15
4. Programm starten: <F5>
Es ist sinnvoll, das Word-Dokument abzuspeichern, der Quellcode wird
„automatisch“ mit abgespeichert.
Und es funktioniert (falls kein Tippfehler vorliegt):
Andere Möglichkeit des Programmaufrufs:
16
5. Erklärung (Klasse):
Option Explicit
Das bedeutet, dass alle Variablen (Begriff wird später genauer erklärt)
ausdrücklich „angemeldet werden müssen.
Private Hersteller
Das Attribut „Hersteller“ darf nur von „Verarbeitungsschritten“ der
eigenen Klasse manipuliert werden (Kapselung). Das Gegenstück wäre
„Public“, wenn die Attribute allerdings dann „von überall“ verändert werden
können, ist das Einrichten einer Klasse eigentlich unsinnig.
Hier fällt noch etwas auf: Ein Datentyp muss hier nicht unbedingt angegeben
werden. VBA kennt einen „universellen Datentyp“ (wird später genauer erklärt).
Hinweis: Später werden Attribute und Methoden der Klassen auch als „Privat“
oder „Public“ gekennzeichnet.
Sub erfassen(her, ty, hub)
Sub kennzeichnet eine Methode der Klasse, in den Klammern stehen Platzhalter
(Variablen) für die Daten, die von außen (vom Testprogramm) dem Objekt
übermittelt werden. Die Verarbeitungsschritte stehen zwischen Sub und End
Sub.
Hersteller = her
Das Attribut „Hersteller“ erhält den Wert, der in Her von außen an das
Attribut übermittelt wurde. Beachte: Links steht der Empfangs-Platzhalter,
rechts der Sende-Platzhalter.
17
Function ErmittleTyp()
“Function” ist eine besondere Methode: Sie kann einen Wert an das Testprogramm
zurückliefern. Der Name der Funktion hat dann die Bedeutung eines Platzhalters. In den
Klammern könnte auch noch ein Platzhalter stehen, der einen Wert an diese Methode liefert.
Das ist hier aber nicht der Fall. (Das kommt später). Andere Programmiersprachen verlangen,
dass der Funktion selbst auch ein Datentyp (Typ des Rückgabewerts) zugeordnet werden
muss. . In VBA muss man das nicht machen, dies kann allerdings dann auch in speziellen
Fällen zu Fehlern führen. An späterer Stelle werden in diesen Unterlagen den Funktionen
auch Typen zugeordnet.
ErmittleTyp = Typ
Der im Objekt gespeicherte Wert für den Autotyp soll an das Testprogramm zurückgeliefert
werden. Wie oben: Links steht der Empfangsplatzhalter (hier der Name der Funktion), rechts
das Sendefeld (hier ein Attribut-Name).
6. Erklärung (Testprogramm):
Bemerkung: Das Testprogramm setzt hier die Werte der Attribute. In der Praxis wäre die
Quelle dieser Daten z. B. eine Datenbank. Ein Programm, welches die Daten zunächst setzt
und dann unmittelbar danach wieder abfragt, ist aus der Sicht der Praxis „unsinnig“. Es wäre
eher so, dass ein Programm für die Erfassung der Daten zuständig ist und ein anders für die
Weiterverarbeitung. Das wird auch später so in diesen Unterlagen vorgeführt – jetzt geht es
zunächst einmal nur darum, den „Mechanismus“ zu begreifen. Daher wurde auch die
Bezeichnung „Testprogramm“ gewählt!
18
Ein weiteres Beispiel:
Für den Autoteile-Zubehör-Shop ist eine ähnliche Klasse wie beim vorherigen
Beispiel festzulegen. Die Verkaufspreisberechnung funktioniert folgendermaßen: Der VK-Preis (netto) ergibt sich aus dem Einkaufspreis multipliziert mit
dem Kalkulationsfaktor (Prozentzahl).
Erklärungen:
Integer: Der Platzhalter „Artikelnummer“
(Variable) steht für eine Zahl ohne Nachkommastellen.
Double: Der Platzhalter „EK_PREIS“
(Variable) steht für eine Zahl mit Nachkommastellen.
Der Unterstreichungsstrich „_“ darf in einem
Namen für eine Variable oder eine Methode
benutzt werden
Das Testprogramm soll die Methoden der Klasse testen.
Die Klasse:
Option Explicit
Private Artikelnummer As Integer
Private Bezeichnung As String
Private EK_Preis As Double
Private K_Faktor As Double
Diese Typenangabe muss in VBA
nicht erfolgen.
Sub erfassen(EkP As Double)
Artikelnummer = 1234
Bezeichnung = "Sitzschoner"
K_Faktor = 50
EK_Preis = EkP
End Sub
Function Ausgeben_Bezeichnung()
Ausgeben_Bezeichnung = Bezeichnung
End Function
Function Ermitteln_VK_Preis() As Double
Ermitteln_VK_Preis = (EK_Preis * K_Faktor / 100) + EK_Preis
End Function
Hinweise: Gerechnet wird wie in der Mathematik, das Empfangsfeld steht
immer links. Aus Gründen der Vereinfachung wurden bis auf den EK_Preis alle
Daten in der Methode „erfassen“ direkt festgelegt.
19
Das Testprogramm:
Sub Testprg()
Dim Autoz As Kfz_Zubehoer
Dim bez As String
Dim EP As Double
Dim VkP As Double
Set Autoz = New Kfz_Zubehoer
EP = InputBox("Bitte Einkaufspreis eingeben: ")
Autoz.erfassen EP
MsgBox (Autoz.Ausgeben_Bezeichnung)
MsgBox (Autoz.Ermitteln_VK_Preis)
Set Auto1 = Nothing
End Sub
Hier wurde lediglich der EK_Preis an das Objekt übermittelt. Das ist natürlich
„willkürlich“ (s. die Bemerkungen zum ersten Testprogramm).
Zugriffe auf Eigenschaften
Die letzte Klassendefinition zeigt, dass es offensichtlich zwei „Sorten“ von
Methoden gibt. Die eine „Sorte“ ist letztlich nur dafür da, den Objekteigenschaften Werte zuzuweisen oder diese Werte abzurufen:
Sub erfassen(EkP As Double)
………………
Function Ausgeben_Bezeichnung() As Double
………………
Die zweite „Sorte“ führt kompliziertere Dinge durch, hier die Berechnung eines
neuen Wertes aus zwei Eigenschaften/Attributen der Klasse:
Function Ermitteln_VK_Preis()As Double
Ermitteln_VK_Preis = (EK_Preis * K_Faktor / 100) + EK_Preis
End Function
Es erscheint sicher sinnvoll, diesen Unterschied in der Implementierung zu
Ausdruck zu bringen. Dies erfolgt mit den Eigenschaftsprozeduren
Property Let
(Wert setzen)
Property Get
(Wert auslesen).
Hierbei handelt es sich um eine Alternative zu den bisherigen Möglichkeiten,
Attributwerte zu setzen oder zu lesen. Angesprochen ist also nur die erste
„Sorte“ Methoden (s. o.), für „Function Ermitteln_VK_Preis()“ bleibt alles
so, wie bisher.
20
Die neue Lösung:
Hinweis: Wie gleich erkennbar
ist, werden die Attribute auf eine
andere Art wie bei den vorherigen
Beispielen gesetzt bzw. gelesen.
Zur Kennzeichnung der Attributnamen einer Klasse steht hier nun
ein „m“ vor jedem Variablenamen (m: Member, Mitglied der
Klasse).
Option Explicit
Private mBezeichnung As String
Private mEK_Preis As Double
Private mK_Faktor As Double
Diese Prozedur schreibt den aus dem
Testprogramm übergebenen Wert des
Parameters in die links stehende Variable.
Public Property Let Artikelbezeichnung(Bez As String)
mBezeichnung = Bez
End Property
Public Property Let Einkaufspreis(EkP As Double)
mEK_Preis = EkP
End Property
Diese Prozedur gibt den Wert des Attributs
mBezeichnung unter dem Namen „ArtikelPublic Property Let K_Faktor(KF As Double)
bezeichnung“ an das Testprogramm
mK_Faktor = KF
zurück
End Property
Public Property Get Artikelbezeichnung() As String
Artikelbezeichnung = mBezeichnung
Diese Prozedur (genauer: Funktion)
End Property
berechnet etwas und gibt das Ergebnis unter
dem Funktionsnamen „Ermitteln_VK_Preis“
an das Testprogramm zurück
Double
zurück
Function Ermitteln_VK_Preis() As
Ermitteln_VK_Preis = (mEK_Preis * mK_Faktor / 100)+EK_Preis
End Function
Property bedeutet „Eigenschaft“. In der Klasse scheint sich kaum etwas geändert
zu haben, aus
Sub Erfassen(EKP as Double)
wurde
Public Property Let Einkaufspreis (EK As Double).
(Vor Sub hätte auch „Public“ stehen können, steht nichts da, ist die Prozedur/
Funktion automatisch public!)
21
Das Testprogramm:
Sub Testprg()
Dim Autoz As Kfz_Zubehoer
Dim Bez As String
Dim EP As Double
Dim VkP As Double
Neu!
Set Autoz = New Kfz_Zubehoer
Autoz.Artikelbezeichnung = "Sitzschoner"
Autoz.K_Faktor = 50
EP = InputBox("Bitte Einkaufspreis eingeben: ")
Autoz.Einkaufspreis = EP
MsgBox (Autoz.Artikelbezeichnung)
MsgBox (Autoz.Ermitteln_VK_Preis)
Set Auto1 = Nothing
End Sub
Hier könnte man den Eindruck haben, dass ein direkter Zugriff auf das Attribut
des Objektes möglich wäre. Das ist natürlich nicht der Fall! Das
Geheimhaltungsprinzip gilt immer noch, die Attribute sind gekapselt. Der
„echte“ Name des Attributs laute ja „mBezeichnung“ und nicht „Artikelbezeichnung“. Das Arbeiten mit Properties „vereinfacht“ das Setzen der
Attribute aus der Sicht des Testprogramms. Genau wie bei „normalen“
Methoden können in Property-Prozeduren noch weitere Programmzeilen stehen
(z. B. Plausibilitätsprüfungen hinsichtlich der übergebenen Werte).
Nun kann auf folgenden Unterschied hingewiesen werden: Objekte besitzen
zwei „Sorten“ von Attributen: Felder und Eigenschaften. Die intern vereinbarten
Attribute (z. B. mBezeichnung) sind Objektfelder. Eigenschaften sind das,
was die Objekte nach außen hin „preisgeben“ (z. B. Artikelbezeichnung).
Für das Testprogramm sieht es nun so aus, als ob es direkt auf die Objektfelder
zugreifen könnte: Autoz.K_Faktor = 50. In Wirklichkeit kapseln die
Objekteigenschaften aber nur die Zugriffe auf Felder. Die Objekteigenschaft
Artikelbezeichnung speichert selbst keinen Wert, sondern dient
gleichsam nur der Übergabe eines Wertes. Objektfelder hingegen belegen
„normale“ Speicherplätze.
22
3 Module, Klassenmodule und UserForms
Vor dem eigentlichen Einstieg in die Programmierung sind noch einige Aspekte
der Programmierumgebung zu klären.
Wie bereits oben gezeigt,
bietet das Menü „Einfügen“
mehrere Möglichkeiten an.
Die für uns
wichtigen
Bereiche!
1. Ab sofort werden Testprogramme und Programmmodule, die nicht direkt
objektorientiert vorliegen (also keine Klassen oder komplexere Dialogboxen beinhalten), im Bereich Module erfasst. Diese Art der Programmierung hat in diesen Unterlagen nur eine untergeordnete Bedeutung (z. B. Erstellung von Testprogrammen). Unter ThisDocument (s.
oben) gehören nur noch „Subs“, die einen direkten Bezug zum WordDokument (oder bei EXCEL entsprechend „Diese Arbeitsmappe“) haben.
Beispiel:
Anlegen eines neuen Moduls
und
Namen ändern!
23
2. Klassen werden (wie bereits beschrieben) als Klassenmodule erfasst (also
nicht Neues!).
3. Das Arbeiten mit MsgBox und InputBox ist nur in Ausnahmefällen
sinnvoll. „Normalerweise“ wird mit „echten“ Windows-Masken
gearbeitet, welche in VBA als UserForm(s) vorliegen. Bei UserForms
handelt es sich um Container-Objekte, welche andere Objekte (z. B.
TextBoxes oder Labels) enthalten.
Das Erstellen solcher Masken ist in modernen objektorientierten Umgebungen
äußerst einfach, da die internen Verarbeitungsschritte gleichsam gekapselt sind.
Wie auch in der Programmiersprache Delphi (o. a.), wird die Arbeit im
Wesentlichen von einer „Toolbox“ erledigt, Entwickler müssen lediglich einige
Mausklicks beherrschen. Dialogboxen bieten unzählige Möglichkeiten. Für den
Anfang reichen folgende Funktionalitäten:
Bildschirmmaske (User Form):
Hier wurden zwei Eingabefelder und
ein Ausgabefeld (Ergebnis der
Verarbeitung) festgelegt. Zwei
unterschiedliche Ereignisse können
ausgelöst werden: Klick auf Button
„Aktion 1“ und/oder auf Button
„Aktion 2“.
Die Erstellung dieser User Form wird nun vorgestellt. Damit aber auch ein
Programm „dahintersteht“, welches „etwas macht“, wird Folgendes vereinbart:
In die Eingabefelder 1 und 2 können kleine Texte (z. B. Vor- und Zuname)
eingegeben werden. Ein Klick auf „Aktion 1“ löst eine Ereignisprozedur aus,
welche diese beiden Texte aneinanderfügt und das Ergebnis im Ausgabefeld
anzeigt. Ein Klick auf Aktion 2 bewirkt, dass alle drei Felder wieder gelöscht
werden. Beendet wird das Programm, wie alle Windows-Programme beendet
werden können: Klick auf X.
24
User Form anlegen
Nach dem Klick auf <Einfügen><UserForm> erscheint eine „Werkzeugsammlung und eine leere Maske:
Klick auf das Zeichen A:
Labelfeld (Überschrift
oder Führungstext) auf der
Maske erzeugen
Ergebnis:
Caption ändern
Schriftgröße, -art usw. ändern
25
Die Eigenschaften wurden geändert, auch das ist oo Programmierung!
Nächster Schritt: Edit-Feld
(Textfeld) hinzufügen
Ein Eingabefeld ist nun auf der Maske platziert:
26
Die Vorgänge mehrmals wiederholen und die Objekte auf der Forms richtig
platzieren:
Doppelklick auf den
Button, dem Code zu
hinterlegen ist
Nun schaltet das System in den Quellcode-Editor um:
Automatisch wird nun der Rahmen für die Ereignisprozedur erstellt!
Quellcode:
Neu eingefügter Quellcode:
Zwei „Strings“ zusammenfügen (geht auch mit „+“)
27
Programmtest (F5):
Objektorientierung bis auf die „unterste Ebene“:
Für die User Form und alle ihre
Objekte (Buttons, Label usw.
existieren Eigenschaftstabellen!
28
Und zum Schluss: Eingabe von Zahlen, mit denen auch gerechnet wird:
Private Sub CommandButton1_Click()
Dim i As Double
Dim k As Double
i = TextBox1
k = TextBox1 + 1.89
TextBox2 = k
End Sub
Dieses Testprogramm zeigt, dass das Objekt TextBoxX auch in der Lage ist,
Zahlen entgegenzunehmen und mit ihnen zu rechnen, wenn die entsprechende
Variable als „Zahlentyp“ deklariert wurde. Das, was in TextBox1 eingegeben
wurde, muss dann zunächst dieser Variablen zugeordnet werden. Allerdings
erkennt diese Art der Zahleneingabe keine fehlerhaften Eingaben, auch die
Ausgabe ist nicht immer optimal.
Hinweis: Bisher wurden einige Grundlagen der VBA-Programmierung mit
Objekten vorgestellt, viele wichtige Aspekte fehlen (noch). Allerdings sollte es
nun möglich sein, prinzipielle Programmstrukturen mit VBA zu erstellen und zu
testen.
29
4 Die logischen Grundstrukturen
4.1
Algorithmus und Struktogramm
Bisher stand die Überlegung im Mittelpunkt, wie Objekte der realen Welt modelliert werden
können, damit die hieraus gewonnene Modellwelt hinsichtlich der Informationsverarbeitung
im Computer auch in diesem abgebildet werden kann. Die Modellierung von Klassen und die
Erzeugung von Objekten sind wichtige Ergebnisse. Mit Methoden erfolgt die Verarbeitung
der Daten. Die bisher vorgeführten Verarbeitungsschritte waren letztlich trivial und
selbsterklärend. Was aber, wenn komplexere Schritte erforderlich werden? Dies ist die
Thematik der nächsten Kapitel.
Zur Veranschaulichung der Verarbeitungsfolgen in einem Programm existieren verschiedene,
meist grafisch orientierte Darstellungsmittel, von denen das sogenannte Struktogramm eine
weite Verbreitung hat und in einer DIN-Vorschrift als Norm vorliegt. Das Struktogramm zeigt
die notwendigen Verarbeitungsschritte in der richtigen Reihenfolge, die erforderlich sind, um
z.B. Eingabedaten in Ausgabedaten zu überführen, also das, was die Aufgabe vieler
Methoden von Klassen darstellt.
Hinweis: Auch UML bietet in diesem Bereich Möglichkeiten an, allerdings sind
Struktogramme weiterhin relevante und einfach zu handhabende Darstellungsmöglichkeiten
der Ablauflogik. Es muss aber auch festgehalten werden, dass Struktogramme z. B. im
Bereich der Ereignissteuerung versagen.
Die Gesamtheit der Verarbeitungsschritte wird auch als Programmlogik oder Ablauflogik
bezeichnet. Diese Verarbeitungsschritte sind Arbeitsvorschriften (in Form einer
Anweisungsliste) an die verarbeitende Instanz. Diese muss nicht unbedingt ein Computer
sein; wenn z.B. eine Rechnung von Hand geschrieben wird, wäre ein Mensch derjenige, der
die Anweisungen ausführt. Ein sogenannter Algorithmus ist eine Anweisungsliste, die
folgende Kriterien erfüllt:
Die Anweisungen sind eindeutig und ausführbar, ihre Anzahl endlich und ihre
Befolgung liefert nach endlich vielen Schritten die Lösung eines Problems.
Eindeutigkeit: der nachfolgende Schritt wird nicht zufällig ausgewählt, sondern liegt (z. B.
aufgrund der aktuell vorhandenen Daten) eindeutig fest, der Algorithmus ist deterministisch.
Anders gesagt: Die Reihenfolge der Abarbeitung ist nicht willkürlich, und gleiche
Eingabewerte führen bei wiederholter Abarbeitung eines Algorithmus zu den gleichen
Ausgabewerten.
Ausführbarkeit: die einzelne Anweisung muss für den Ausführenden des Algorithmus (den
„Prozessor“) verständlich und ausführbar sein (die „Befehle“ sind dem Prozessor bekannt).
Ein ("funktionierendes") Computerprogramm ist demnach ein in einer Computersprache
formulierter Algorithmus. Der Algorithmus: gibt an, wie Eingabegrößen schrittweise in
Ausgabegrößen umgewandelt werden.
30
Beispiel für ein Struktogramm:
Aufgabe: Im Umfeld einer Fakturierung existiert eine Methode zur Berechnung
des Bruttopreises.
Prozedur: Brutto_berechnen
Berechne MWST_Betrag aus dem MWSTProzentsatz und dem Nettobetrag
Bruttobetrag =
Nettobetrag + MWST_Betrag)
(Beachte die unterschiedliche Formulierung der
beiden Verarbeitungsschritte! Wie diese Methode
mit Daten versorgt wird bzw.wie die Daten
weitergeleitet werden, ist im Moment unwichtig.)
Ein Struktogramm besitzt
einen Namen („Rechnungsfuß“) Anfang und Ende sind
durch das Rechteck festgelegt, verbale Bezeichnungen
wie „Anfang“ bzw. „Ende“
gibt es laut DIN nicht. Hinsichtlich der Formulierungen
in den einzelnen Verarbeitungsschritten gibt es keinen
Einschränkungen, sie müssen
natürlich verständlich sein.
In Struktogramm steht jeder Verarbeitungsschritt in einem Rechteck und ist so
formuliert, dass die Ablauflogik auch einem Personenkreis, der keine spezielle
Programmiersprache beherrscht, verständlich ist. U. U können auch mehrere
Schritte zu einem zusammengefasst werden. Die Überführung der Programmlogik in eine Computersprache (z.B. in VBA) wird als Codierung bezeichnet:
MWST_Betrag = (Netto * MWST_Proz) / 100
Bruttobetrag = MWST_Betrag + Netto
Beachte: Viele Wege führen zum Ziel, das „Problem“ könnte auch mit einer
einzigen Formel berechnet werden!
Modellierung des Systems
1. Grundsätzlich: Es erfolgt eine Trennung von GUI (Benutzeroberfläche,
und Fachkonzept (Berechnung), das (Fachkonzept-) Programm ist als
Klasse implementiert und kann mehrfach verwendet werden.
2. Der Mehrwertsteuersatz wird in der Klasse clsBrutto als Konstante
(19%) implementiert. (Dies ist eine Entscheidung, die unterschiedlich
bewertet werden kann!)
3. Die Klasse liefert sowohl der Brutto-Betrag als auch den Mwst-Betrag
zurück.
4. Auf Plausibilitätsprüfungen wird vorläufig verzichtet.
5. Die GUI hat zwei Schaltflächen: „Berechnen“ und „Felder leeren“.
6. Sie besitzt ein Eingabefeld und zwei Ausgabefelder (s. Punkt 3).
31
Klasse
Brutto-Betrag und Mwst-Betrag treten
hier nicht als Attribute auf. Es handelt
sich um Funktionsrückgabewerte; dies
wird später berücksichtigt (vgl. die
Modellierung der Klasse clsBrutto
einige Seiten weiter).
GUI
Struktogramm für die Berechnung: s. oben
Klassenmodul clsBrutto
Option Explicit
Private mNetto_Preis As Double
Public Property Let Nettopreis(NPr As Double)
mNetto_Preis = NPr
Hinweis: Dies wird später
End Property
noch „eleganter“ gelöst!
Public Function Ermitteln_Brutto()As Double
Dim Mwst_Betrag
Mwst_Betrag = (mNetto_Preis * 19 / 100)
Ermitteln_Brutto = mNetto_Preis + Mwst_Betrag
End Function
Public Function Ermitteln_Mwst()As Double
Ermitteln_Mwst = (mNetto_Preis * 19 / 100)
End Function
32
Quellcode User Form
Option Explicit
Dim oBrutto As clsBrutto
Dim net
As Double
Private Sub CommandButton1_Click()
Set oBrutto = New clsBrutto
net = TextBox1
oBrutto.Nettopreis = net
TextBox2 = oBrutto.Ermitteln_Brutto
TextBox3 = oBrutto.Ermitteln_Mwst
Set oBrutto = Nothing
End Sub
Private Sub CommandButton2_Click()
TextBox1.text = " "
TextBox2.text = " "
TextBox3.text = " "
End Sub
Programmtest:
Allerdings sollte hier klar sein, dass noch kein gesamtes Modell für diese Problemlösung vorliegt. Schwerpunkt der folgenden Betrachtung bleiben die
logischen Grundstrukturen, vier Aspekte hinsichtlich der Modellierung fehlen
noch:
 Modellierung der Ereignisbehandlung
 Modellierung der GUI
 Beziehungen zwischen den Klassen (GUI und Fachkonzept)
 Genaueres zur Datenmodellierung (Datentypen usw.)
33
4.2
Exkurs I: Botschaften und Ereignisse
„Botschaften senden“ ist eine zentrale Sichtweise der objektorientierten Programmierung. Es handelt sich dabei um eine Aufforderung eines „Senders“ (der
ein Objekt sein kann) an ein Objekt, eine seiner (public-) Methoden auszuführen.
Beispiel:
Benutzeraktion: Klick auf Button „Berechnen“
Windows (das OS) wertet dieses Ereignis aus und sendet eine Botschaft (z.B.
CommandButton2 gedrückt, siehe UserForm) an das Objekt, über dem sich der
Mauszeiger befindet. Diese Botschaft löst eine Ereignisbehandlungsroutine aus,
welche von Anwendungsentwicklern erstellt wurde:
Private Sub CommandButton2_Click()
TextBox1.text = " "
………….
End Sub
Die einzelnen Objekte (Buttons, Felder usw.) gehören jeweils zu einer UserForm (Dialogfenster) – Windows sendet letztlich die Botschaft an diese. Das
Dialogfenster „verarbeitet“ die Botschaft entsprechend dem Objekt, das betroffen ist. Der Button „liegt“ auf dem Fenster, die Ereignisbehandlung erfolgt
in der speziellen UserForm-Klasse.
Während der Ablauf in einer Methode (wie oben, z. B. MWST berechnen) nach
einem festgelegten Plan (Struktogramm) abläuft, ist dies für die gesamte
Programmsteuerung nicht so. Das Laufzeitsystem reagiert bei einem
ereignisgesteuerten Programm permanent auf Benutzereingaben – ein
Struktogramm kann dies nicht visualisieren. UML bietet hierzu professionelle
Möglichkeiten an, die allerdings an dieser Stelle etwas zu komplex wären. Eine
einfache Möglichkeit, welche die Modellierung kleinerer Problemstellungen
gestattet, ist die Ereignistabelle:
34
4.3
Exkurs II: Modellierung der Benutzeroberfläche
UserForm1
Label4
Label1
TextBox1
Label2
TextBox2
Label3
TextBox3
CommandButton1
CommandButton2
Sinnvoll ist es, die Bezeichner „UserForm1“, „Label1“ usw. umzubenennen:
UserForm1: Maske_MWST, Label1: N_Label usw.
Dies soll bei den folgenden Problemlösungen berücksichtigt werden.
35
4.4
Exkurs III: Beziehungen zwischen den Klassen
Wie ist nun der Zusammenhang von GUI und Fachkonzept zu modellieren? Die UserForm ist
zwar für die Ereignisbehandlung zuständig (s. Ereignistabelle), die eigentliche „fachliche“
Arbeit erledigt aber das Fachkonzept. Wie der Quellcode zeigt, erzeugt die GUI in unserem
Beispiel das Objekt des Fachkonzeptes:
Set oBrutto = New clsBrutto
Nun kann dieses Objekt benutzt werden, d. h. die Methoden, die es (öffentliche) zur Verfügung stellt, können aufgerufen werden. Vereinfacht ausgedrückt: Das Fensterobjekt ist mit
seinem Fachkonzept verbunden: Zwischen dem Dialogfenster und dem Fachkonzeptobjekt
besteht eine sogenannte Assoziation. Das Fensterobjekt kann Daten an das Fachkonzept
übergeben:
oBrutto.Nettopreis = net
und von diesem auch Daten empfangen:
TextBox2 = oBrutto.Ermitteln_Brutto
Modellierung der Assoziation:
oBrutto:clsBrutto
UserForm1:UserForm
oBrutto:
net
:
brut
:
mwst
:
clsBrutto
Double
Double
Double
Labels, Felder, Buttons: Object
mNetto : Double
benutzt
Click_Berechnen_
und_anzeigen()
Click_Felder_loe()
Netto_setzen(NPr:
double)
Brutto_ermitteln():
double
Mwst_Betrag_erm():
double
Durch Brutto_ermitteln(): double wird zum Ausdruck gebracht, dass ein Wert vom Typ
Double zurückgegeben wird. Damit ist klar, dass es sich bei dieser Methode um eine Funktion
handelt. Die UserForm1 kennt die Fachklasse, der Benutzer steuert die Fachklasse über die
GUI. Er gibt einen Nettopreis ein und klickt auf den Button „Berechnen“: Senden einer
Botschaft an die Fachklasse, welche den „Auftrag“ ausführt und Daten zurückliefert.
In der Ereignistabelle (letzte Spalte) ist erkennbar, dass die Methoden eines Objektes
aufgerufen werden und nicht lediglich Prozeduren der UserForm1. Die Klassen werden hier
ohne TextBox-Komponenten modelliert (dies erfolgte bereits in der Modellierung der
Benutzeroberfläche). Die Attribute brut und mwst entsprechen in der Userform den TextBoxKomponenten 2 und 3. Man könnte auch lokale Hilfsvariablen (net und brut) in der Userform
expliziet definieren (so wie es oben bei UserForm1 den Anschein hat) und diese den
TextBox-Komponenten zuweisen. Dieses Klassenmodell auf dieser Seite entspricht also nicht
100% dem zuvor dargestelltem Quellcode.
36
4.5
Exkurs IV: Genaueres zu Variablen, Konstanten und Datentypen
Das Programm "Bruttobetrag berechnen" kann zu jedem beliebigen Nettopreis
den Bruttopreis berechnen: der Nettopreis ist "variabel". In der Mathematik
werden beim Formelrechnen Platzhalter (= Variablen) verwendet: z. b.:
Z = K * P / 100
Bei einer konkreten Berechnung werden dann für die Platzhalter Zahlen
eingesetzt. Computer arbeiten ähnlich. Damit dies möglich ist, wird der Wert
unmittelbar nach seiner Eingabe zunächst im Speicher abgelegt. Für die sich
daran anschließende Berechnung werden die Werte dann aus diesem
abgerufen, die Berechnung ausgeführt und das Ergebnis wieder gespeichert,
bevor es dann ausgegeben wird. Der Computer hat intern seine Speicherzellen
durchnummeriert. In der Programmierung ist es aber sinnvoller, nicht mit
diesen "Hausnummern" zu arbeiten (was durchaus auch möglich ist!), sondern
mit sogenannten sprechenden Namen als Platzhalter/Variablen (z. B. "brut" für
Bruttobetrag). Bei der Programmausführung werden dann diese Platzhalter
durch die "echten" Speicheradressen ersetzt. Variablen haben also immer
einen Variablennamen und einen Inhalt (Wert). In der Zeile Dim net As
Double wird die Variable mit dem Namen "net" vereinbart. Der Zusatz "As
Double" sagt etwas über den Variablentyp aus; dies wird später erklärt. Das
Wort "Dim" bedeutet in etwa: Achtung, jetzt erfolgt eine Variablendeklaration
(Variablenvereinbarung).
Eine Programmmodifikation:
Option Explicit
Private mNetto_Preis As Double
Private Const mp = 19
……………………
Function Ermitteln_Brutto() As Double
Dim Mwst_Betrag
Mwst_Betrag = (mNetto_Preis * mp / 100)
……………………
Der Prozentwert für die Mehrwertsteuer (mp) wurde hier nicht als Variable,
sondern als sogenannte Konstante (Const) vereinbart. Konstanten können
während der Programmausführung ihren Wert nicht ändern. Sollte sich der
Mehrwertsteuersatz mal wieder ändern, müsste das Programm an dieser Stelle
geändert werden.
37
Zu der Zeile
Mwst_Betrag = (mNetto_Preis * mp / 100)
ist noch folgendes zu sagen: Hier werden eigentlich zwei Anweisungen
ausgeführt. Zunächst wird eine Berechnung durchgeführt (das was rechts vom
Gleichheitszeichen steht, dann erfolgt eine sogenannte Wertezuweisung, d. h.
das Ergebnis wird in den Speicherbereich mit dem Namen Mwst_Betrag
geschrieben. Das Gleichheitszeichen ist hier nicht im mathematischen Sinne zu
verstehen. So sind auch folgende Ausdrücke in der Programmierung sinnvoll:
X = X + 1. Im Sinne einer mathematischen Gleichung wäre diese
Formulierung unsinnig.
Eine Variable kann unterschiedliche "Sorten" von Daten aufnehmen, wie.
ganze Zahlen ohne Dezimalstelle (z. B. 23), Dezimalzahlen mit
unterschiedlicher Genauigkeit (z. B. 34.765), einzelne Buchstaben (z. B. "a")
oder Texte wie ganze Sätze "Hallo, wie geht es Dir?". In der Datenverarbeitung
spricht man vom Datentyp der Variablen. Der Datentyp einer Variablen ist die
dritte wichtige Eigenschaft neben dem Variablennamen und dem
Variableninhalt, durch die eine Variable gekennzeichnet ist. Prinzipiell wird
durch den Datentyp schon geklärt, was als Variableninhalt in Frage kommt. Oft
ist dem Inhalt aber nicht ohne weiteres der Typ anzusehen. So können z. B.
Variablen von dem Typ "Dezimalzahl" auch Zahlen ohne Dezimalstelle
aufnehmen.
Werden Variablen nicht deklariert, können sogar Text ohne feste Länge unter diesem
Variablennamen abgespeichert werden. (Typ: Variant, von dieser Möglichkeit sollte man
aber nur in Ausnahmefällen Gebrauch machen, die Programme werden u. U. langsamer, die
Codierung schwerer nachvollziehbar.). Wird der Rückgabetyp einer Funktion nicht
angegeben, wird ebenfalls automatisch der Typ Variant gesetzt. Bei der
Variablendeklaration wird der Variablentyp entweder durch die Typenbezeichnung (... As
Double) oder mit dem sogenannten Typenkennzeichen (z. B.: Dim rechbetrag#)
festgelegt. Die folgende Tabelle gibt eine Zusammenfassung der verschiedenen Datentypen:
Variablentyp
Boolean
Integer (Ganzzahl)
Long (Ganzzahl)
Single (Dez.-Zahl)
Typenkennzeichen
%
&
!
Double (Dez.-Zahl)
#
Currency (DezZahl, Währung)
Date (Datum)
String (Text)
Variant
@
$
Bereich
0 (False) und -1 (True)
-32768 bis +32767
-2147483648 bis +2147483647
-3,402823*10 hoch -38 bis
+3,402823*10 hoch 38
-1,797693*10 hoch -324 bis
+1,797693*10 hoch 324
-9,22*10 hoch 14
+9,22*10 hoch 14
1.1.1000 bis 31.12.9999
ca. 2 Milliarden
siehe oben
38
Speicherplatz
in Bytes
2
2
4
4
8
8
8
10 + Textlänge
22 + Textlänge
Hinweis: Bei den sogenannten. Literalen handelt es sich ebenfalls um
konstante Werte eines bestimmten Typs, die im Quelltext explizit (ohne Namen)
angegeben werden, z. B.:
c = 19 * p
19 ist dann ein Literal.
Ein weiteres Beispiel (hier: Erfassen als Standardmodul, nicht Klassenmodul
oder UserForm):
Sub test_var()
a = 29
test = 2
MsgBox (test)
test = 5.6
MsgBox (test)
test = "Hallo, wie geht es Dir?"
MsgBox (test)
End Sub
Beachten Sie bitte: Bei diesem Testprogramm wird absichtlich ohne
Variablendeklaration gearbeitet, da hier ein spezieller Sachverhalt vorgeführt
werden soll.
Aufgabe 2:
Testen Sie bitte dieses Programm (Standardmodul). Der Inhalt der Variablen
mit dem Namen test hat hier drei verschiedene Inhalte. Wodurch
unterscheiden sich diese (Länge, Wertebereich usw.)?
Arbeitshinweis: Erstellen Sie eine kleine Skizze, die den Hauptspeicher (stark
vereinfacht) darstellt und benennen sie einen Speicherbereich mit dem Namen
test!
Aufgabe 2a (Erweiterung von Aufgabe 2:
Entwerfen Sie bitte ein kleines Testprogramm, welches die möglichen
Zahlenformate veranschaulicht. Das Programm soll alle Variablen
deklarieren. Danach verlangt es für jede Zahl eine Eingabe und gibt
anschließend diese Zahl wieder aus. Was passiert bei der Eingabe von
falschen Zeichen? Testen Sie auch Beispiele aus dem Unterricht zum
kaufmännischen Rechnen!
39
Lineare Algorithmen
Algorithmen, bei denen alle Anweisungen ohne Ausnahme und genau einmal
durchlaufen werden, heißen lineare Algorithmen oder Reihung oder Sequenz.
Bisher haben wir lediglich diese einfache Form von Programmen kennen
gelernt. Die folgenden Aufgabenstellungen fassen das bisher Gelernte
zusammen:
Aufgabe 3:
Ein Unternehmen gewährt 5% Rabatt. Nach der Eingabe des Warenwertes wird der Nettoverkaufspreis berechnet, der Mehrwertsteuerbetrag auf den Nettoverkaufspreis addiert und
der Bruttopreis ausgegeben.
- Modellieren Sie eine geeignete GUI und das Fachkonzept (UML)
- Erstellen Sie ein Struktogramm!
- Codieren Sie das Programm in VBA!
Aufgabe 4:
Eine Pizzeria bietet zusätzlich zu dem „normalen“ Pizza-Angebot für jede Pizzasorte eine
Riesenpizza für sieben Personen an. Einzugeben ist der Preis für eine kleine Pizza der
gewünschten Pizzasorte; ausgegeben wird der Preis der Riesenpizza. Dieser Preis berechnet
sich aus dem Preis der kleinen Pizza multipliziert mit 7 minus einem Preisnachlass von 5,00
Euro. Erstellen Sie bitte das entsprechende Programm!
Aufgabe 5:
Erstellen Sie bitte ein Programm zur Zinsberechnung! Benutzen Sie folgende Formel:
Zinsen = Kapital * Zinssatz * Tage / 100 * 360
Aufgabe 6:
Ermitteln Sie mit Hilfe eines Programms den durchschnittlichen Benzinverbrauch eines
Wagens!
Aufgabe 7:
Ein gemeinnütziger Verein führt ein Sommerfest durch. Die Besucher können ähnlich wie
beim deutschen Lottosystem einen Lottoschein erwerben und auf diesem 10 Zahlen von 30
Zahlen ankreuzen. Ein Programm soll die Gewinnverteilung ermitteln: 1/3 der Gesamteinnahmen aus dem Lottoschein-Verkauf erhält der Verein. Vom Rest bekommt die erste
Gewinnposition die Hälfte und was dann übrig bleibt, wird an die zweite und dritte
Position zu gleichen Teilen verteilt. Die Gewinnposition richtet sich danach, wie viele
richtige Zahlen angekreuzt wurden. Für den Fall, dass mehrere Personen gleich viele
Zahlen richtig haben, ist ein Verfahren festgelegt, welches nicht Bestandteil dieser
Aufgabe ist. In diesem Programm sollen lediglich die Beträge für die Gewinnpositionen
ermittelt werden.
40
Verzweigte Algorithmen (Alternation, Auswahl)
In den meisten Fällen muss ein Programm flexibel auf eingegebene Daten
reagieren, d. h. je nach Eingabe sind unterschiedliche Verarbeitungsschritte
abzuarbeiten. Das bedeutet, dass bei einem Programmlauf nicht alle
Anweisungen durchlaufen werden, sondern nur die, die entsprechend der
Eingabedaten durch eine Fallunterscheidung in Frage kommen. Ein
Einführungsbeispiel möge den Fall verdeutlichen:
Beispiel: Falls der Nettobetrag einer Rechnung 99,99,- überschreitet, sollen 3%
Rabatt berücksichtigt werden.
Hier zunächst eine vereinfachte Lösung mit „InputBox“ (lediglich ein Modul,
kein Klassenmodul und keine UserForm):
Option Explicit
Sub rabatt_1()
Dim net As Double
Dim brut As Double
Const rab = 3
Const mwst = 19
net = InputBox("Nettobetrag: ")
If net > 99.99 Then net = net - (net * rab / 100)
brut = ((net * mwst) / 100) + net
MsgBox ("Rechnungsbetrag BRUTTO " & brut)
End Sub
(Hinweis: Auf die Ausgabe des Betrags für den Rabatt wurde hier aus Gründen der
Vereinfachung verzichtet.)
Die neue Anweisung für die Abfrage im Programm lautet: If ...Then....
Struktogramm:
Programm rabatt
Eingabe net
net > 99.99?
ja
net = nett (net * rab / 100)
nein
./.
Bruttobetrag berechnen und ausgeben
41
In diesem Fall steht unter dem Nein-Zweig "./.". Dies bedeutet, dass dann,
wenn der Netto-Betrag nicht größer als 99,99 ist, nichts gemacht wird. Nur im
ja-Fall soll ein Rabatt berechnet werden. Der Fachbergriff für diese spezielle
Situation lautet bedingte Anweisung (oder einseitige Auswahl). Die Abfrage
"net > 99.99" ist eine Bedingung, die entweder wahr oder falsch sein kann.
Aufgabe 8:
Modellieren Sie nun eine geeignete GUI und das separate Fachkonzept
(UML)! Entwickeln Sie dann die UserForm und das Klassenmodul! Codieren
Sie das Programm in VBA!
Mögliche Lösung (GUI und VBA):
UserForm
Option Explicit
Dim oBrutto As clsRabatt
Dim net
As Double
Private Sub CommandButton1_Click()
Set oBrutto = New clsRabatt
net = TextBox1
oBrutto.Nettopreis = net
Brutto_aus.Caption = _
Brutto.Ermitteln_Brutto
Set oBrutto = Nothing
End Sub
(Hinweis: das Ausgabefeld ist
hier als Label festgelegt!)
Fachkonzept (hier eine mögliche Lösung, Abfrage im Fachkonzept!):
Option Explicit
Private mNetto_Preis As Double
Private Const mRab = 3
Public Property Let Nettopreis(NPr As Double)
mNetto_Preis = NPr
End Property
Public Function Ermitteln_Brutto() As Double
Dim Mwst_Betrag As Double
If mNetto_Preis > 99.99 Then mNetto_Preis = _
mNetto_Preis - (mNetto_Preis * mRab / 100)
Mwst_Betrag = (mNetto_Preis * 19 / 100)
Ermitteln_Brutto = mNetto_Preis + Mwst_Betrag
End Function
42
Trennzeichen, wenn
eine Anweisung noch
nicht zu Ende ist und
in der nächsten Zeile
weitergeht:
Leerzeichen + „_“
Neue Objekte auf der GUI:
Soll eine Verkaufspauschale von 5 Euro berücksichtigt werden, ist der
entsprechende Optionsbutton anzuklicken.
Die Zusätze der GUI werden mit
diesen Steuerelementen (Objekten)
der Werkzeugsammlung erstellt
Aufgabe 9:
Erstellen Sie bitte diese erweiterte GUI!
VBA-Code: UserForm:
Option Explicit
Dim oBrutto As clsRabatt
Dim netto
As Double
Dim brutto As Double
Private Sub CommandButton1_Click()
Set oBrutto = New clsRabatt
netto = TextBox1
oBrutto.Nettopreis = netto
brutto = oBrutto.Ermitteln_Brutto
If OptionButton1.Value = True Then brutto = _
oBrutto.Ermittle_Br_Verpack_Pausch
Brutto_aus.Caption = brutto
Set oBrutto = Nothing
End Sub
43
VBA-Code: Fachkonzept:
Option Explicit
Private mNetto_Preis As Double
Private mBrutto_Preis As Double
Private Const mRab = 3
Public Property Let Nettopreis(NPr As Double)
mNetto_Preis = NPr
End Property
Public Function Ermitteln_Brutto() As Double
Dim Mwst_Betrag As Double
If mNetto_Preis > 99.99 Then mNetto_Preis = _
mNetto_Preis - (mNetto_Preis * mRab / 100)
Mwst_Betrag = (mNetto_Preis * 19 / 100)
mBrutto_Preis = mNetto_Preis + Mwst_Betrag
Ermitteln_Brutto = mBrutto_Preis
End Function
Public Function Ermittle_Br_Verpack_Pausch() As Double
Ermittle_Br_Verpack_Pausch = mBrutto_Preis + 5
End Function
Aufgabe 10:
Rekonstruieren Sie aus diesen Quellcodes die entsprechenden Klassen und
erstellen Sie bitte die Logik der Methoden als Struktogramme. Beachten Sie
bitte die Trennung zwischen GUI und Fachkonzept.
Hinweis: Wie bei jeder Lösung gibt es auch hier Alternativen. Sie sollten sich
für die Bearbeitung dieser Aufgabe genügend Zeit nehmen und mit der
Lösung experimentieren, indem Sie Lösungsalternativen auch tatsächlich
realisieren und testen. Für Ihre weiteren Fortschritte in der objektorientierten
Programmierung ist es wichtig, dass Sie diese Problemlösung verstehen und
durchschauen.
44
Alternative Anweisung (oder zweiseitige Auswahl): In vielen Fällen sind zwei
Möglichkeiten zu berücksichtigen.
Das Rabatt-Programm wird erweitert: Wenn der Netto-Preis über 99,99 € liegt,
beträgt der Rabattsatz 5%, andernfalls sind 3 % zu berücksichtigen.
Programm Rabatt_neu
Eingabe netto
netto > 99,99?
ja
rabatt = 5
nein
rabatt = 3
weitere Berechnungen….
In VBA wird diese alternative Anweisung folgendermaßen codiert:
If netto > 99.99 Then
rabatt = 5
Else
rabatt = 3
End If
Hinweis: Das Struktogramm skizziert nur die Lösung und ist unvollständig.
Hinweise zur Modellierung
Es sollen alle bisher behandelten Möglichkeiten der Zugriffe auf Methoden und Attribute
eines Objektes benutzt werden.
Die Bruttoberechnung wird als Funktion (Methode der Klasse) modelliert, die aus einem
Nettobetrag einen Bruttobetrag in Abhängigkeit eines ermittelten Rabatt-Satzes (3% oder 5%)
und einer gesetzten (Let) Mehrwertsteuer) berechnet und auf der GUI ausgibt. Der Rabattsatz
wird ausgelesen (Get) und auf der GUI ausgegeben.
45
Die Fachklasse:
Option Explicit
Private mNetto_Preis As Double
Private mBrutto_Preis As Double
Private mRabatt_st As Integer
Private mwst As Integer
Private Mwst_Betrag As Double
Public Property Let mwst_init(m As Integer)
mwst = m
End Property
Public Property Get Rab_aus() As Integer
Rab_aus = mRabatt_st
End Property
Public Function Ermitteln_Brutto(n As Double) As Double
mNetto_Preis = n
If mNetto_Preis > 99.99 Then
mRabatt_st = 5
Else
mRabatt_st = 3
End If
mNetto_Preis = mNetto_Preis - (mNetto_Preis * mRabatt_st / 100)
Mwst_Betrag = (mNetto_Preis * 19 / 100)
mBrutto_Preis = mNetto_Preis + Mwst_Betrag
Ermitteln_Brutto = mBrutto_Preis
End Function
Die GUI
Option Explicit
Dim oBrutto As clsRabatt
Dim netto
As Double
Dim brutto As Double
Dim mwst As Integer
Private Sub CommandButton1_Click()
Set oBrutto = New clsRabatt
mwst = 19
oBrutto.mwst_init = mwst
netto = TextBox1
brutto = oBrutto.Ermitteln_Brutto(netto)
Brutto_aus.Caption = brutto
Label4 = oBrutto.Rab_aus
Set oBrutto = Nothing
End Sub
Legen Sie die USER-Form an und testen Sie bitte das Programm.
46
Ein weiteres Beispiel: Eine Versicherung erstattet ihren Mitgliedern einen Teil
des Jahres-beitrags zurück: bei mehr als 5-jähriger Mitgliedschaft 9%,
andernfalls 4%.
Programm rueckerstattung
Eingabe beitrag_j, jahre
jahre > 5?
ja
rueck =
beitrag_j * 0,09
nein
rueck =
beitrag_j * 0,04
rueck ausgeben
If jahre > 5 Then
rueck = beitrag_j * 0.09
Else
rueck = beitrag_j * 0.04
End If
Beachten Sie bitte: Bei diesen komplexeren Formulierungen werden die
Bedingungen und die Anweisungen jeweils in separate Zeilen geschrieben!
Else ist der Zweig für die zweite Möglichkeit, mit End If wird die alternative
Anweisung abgeschlossen, damit die sich daran anschließenden Programmzeilen nicht mehr an die If-Else-Konstruktion gebunden sind.
Aufgabe 11:
Entwickeln Sie bitte das komplette Programm zu diesem Struktogramm!
(GUI und Fachkonzept getrennt!)
47
Unsere Aufgabe wird nun erweitert: die Versicherung erstattet ihren
Mitgliedern einen Teil des Jahresbeitrags zurück, bei mehr als 10-jähriger
Mitgliedschaft 14%, bei mehr als 5-jähriger Mitgliedschaft 9%, andernfalls 4%
(Mehrfachauswahl).
Programm rueckerstattung_neu
Eingabe beitrag_j, jahre
jahre > 10
ja
rueck =
beitrag_j * 0,14
nein
jahre > 5
ja
nein
rueck =
beitrag_j * 0,09
rueck =
beitrag_j * 0,04
Ausgabe: rueck
Codierung:
…………
If jahre > 10 Then
rueck = beitrag_j * 0.14
Else
If jahre > 5 Then
rueck = beitrag_j * 0.09
Else
rueck = beitrag_j * 0.04
End If
End If
…………
Aufgabe 12:
Auch für dieses Beispiel ist das komplette Programm zu entwickeln. (GUI
und Fachkonzept getrennt!)
48
Aufgabe 13:
Was passiert, wenn Sie die Abfragen jahre > 10 und jahre > 5 vertauschen?
Formulieren Sie bitte eine genaue Begründung!
Die Fallunterscheidung mit IF..ELSE.. IF..ELSE .. (auch mehrstufige Auswahl)
ist eine Erweiterung der alternativen Anweisung. Für die Bedingung kommen
nicht nur zwei Möglichkeiten (wahr/falsch) in Frage sondern mehr als zwei. Im
Struktogramm kann die Fallunterscheidung als Schachtelung alternativer
Anweisungen grafisch dargestellt werden. Eine andere Möglichkeit der
grafischen Darstellung der Fallunterscheidung zeigt folgendes Struktogramm
(Fallunterscheidung mit CASE, auch mehrseitige Auswahl):
Programm rueckerstattung_neu_case
Eingabe beitrag_j, jahre
>10
rück =
beitrag_j * 0,14
jahre?
>5
rück =
beitrag_j * 0,09
<= 5
rück =
beitrag_j * 0,04
Ausgabe: rueck
Für diese Struktur existiert in VBA eine spezielle Syntax:
…………
Select Case jahre
Case Is > 10
rueck = beitrag_j * 0.14
Case Is > 5
rueck = beitrag_j * 0.09
Case Else
rueck = beitrag_j * 0.04
End Select
…………
49
Beachten Sie: Die If-Else-Struktur verschachtelt nach innen und wird bei
steigender Anzahl der Möglichkeiten immer schwerer lesbarer, für die CaseStruktur gilt dies so nicht!
Weiterhin: Der Case – Else – Fall wird i. d. R. etwas anders dargestellt, als im
oben stehenden Struktogramm (bitte nachprüfen).
Hinweis: Die Begriffe „Fallunterscheidung“, „mehrseitige/-stufige Auswahl“
usw. werden in Lehrbüchern teilweise nicht einheitlich benutzt.
Aufgabe 14:
Auch für dieses Beispiel ist das komplette Programm zu entwickeln. (GUI und
Fachkonzept getrennt!)
Testen Sie bitte folgende Programmänderung:
Select Case jahre
Case Is > 5
rueck = beitrag_j * 0.09
Case Is > 10
rueck = beitrag_j * 0.14
Case Else
rueck = beitrag_j * 0.04
End Select
Aufgabe 15:
Beschreiben Sie die fehlerhafte Arbeitsweise des Programms! Worin
unterscheidet sich dieses Programm von dem auf der vorherigen Seite?
Versuchen Sie näher zu erklären, wie die Case-Struktur abgearbeitet wird!
Aufgabe 16:
Ein Weingut liefert an seine Kunden Wein frei Haus. Eine bestimmte Sorte
kostet in einem Sonderangebot 4,00 Euro. Wenn ein Auftrag unter 100 Euro
liegt, werden noch 8 Euro für die Verpackung verlangt. Ein Programm soll für
eine einzugebende Anzahl Flaschen (Sonderangebot) den Nettopreis berechnen.
Aufgabe 17:
Ein Programm soll die Lösungen einer quadratischen Gleichung berechnen bzw.
angeben, ob und wie viele Lösungen existieren. Einzugeben sind die
Koeffizienten.
Aufgabe 18:
Ein Programm berechnet das zu zahlende Porto für Briefe (s. Gebührenverordnung). (Hinweis: Einsatz von Optionsbuttons)
50
Schleifen im Programm: Iteration (Wiederholung)
Die Organisationsleitung einer Messe „Informationstechnologie für das Büro“
möchte wissen, wie viele Personen diese Messe pro Tag durchschnittlich
besuchten. Nach der Eingabe der Messedauer (Tage) werden die absoluten
Werte (Anzahl der Besucher) pro Tag eingegeben, der Durchschnitt berechnet
und das Ergebnis ausgegeben.
Programm: Messebesucher_Durchschnitt
Eingabe tage
z = 1, summe = 0
solange z <= tage
Eingabe anzahl
summe = summe + anzahl
z=z+1
schnitt = summe / tage
Ausgabe schnitt
Codierung (hier wieder nur als Modul):
Option Explicit
Sub durchschnitt_1()
Dim tage As Integer
Dim anzahl As Double
Dim summe As Double
Dim schnitt
Dim z As Integer
tage = InputBox("Anzahl Tage: ")
z = 1
summe = 0
Do While z <= tage
anzahl = InputBox("Anzahl Besucher: ", anzahl)
summe = anzahl + summe
z = z + 1
Loop
schnitt = summe / tage
MsgBox ("Durchschnitt: " & schnitt)
End Sub
51
Eine Wiederholungsstruktur ist durch folgende Eigenschaften gekennzeichnet:
- Es existiert eine Abbruchbedingung: Wann ist das, was wiederholt werden
soll, beendet?
- Die zu wiederholenden Anweisungen (= Schleifenkörper, Anweisungsblock
der Schleife) sind in irgendeiner Weise als zusammengehörend gekennzeichnet, z. B. durch Klammern (bei C++), begin … end (bei Delphi) oder
do … Loop (bei VB/VBA).
Im Struktogramm ist dies folgendermaßen realisiert:
Bedingung
Anweisung 1
Anweisung 2
Schleifenkörper, Block
Anweisung 3, 4 ,5 usw.
Die allgemeine Darstellung dieses Schleifentyps in VBA lautet:
Do While Bedingung
Anweisung 1
Anweisung 2
Anweisung 3, 4, 5 usw.
Loop
Bei diesem Schleifentyp, der Do-While-Schleife, wird zuerst abgefragt, ob der
logische Ausdruck in Bedingung wahr oder falsch ist, erst dann erfolgt die
Abarbeitung des Schleifenkörpers. Die Schleife wird also u. U. nicht ausgeführt, wenn die Anfangsbedingung nicht zutrifft („Überspringen“ der
Schleife). Beim Erreichen des Schlüsselwortes Loop kehrt das Programm
wieder an die Überprüfung der Bedingung zurück und führt den
Schleifenkörper gegebenenfalls nochmals aus.
Aufgabe 19:
Überführen Sie das Programm „Messebesucher“ in die objektorientierte Form
(Trennung GUI – Fachkonzept). Erstellen Sie bitte zunächst die Klassendiagramme.
52
Eine Programmänderung:
Do Until z > tage
anzahl = InputBox("Anzahl Besucher: ", anzahl)
summe = anzahl + summe
z = z + 1
Loop
Aufgabe 20:
Überprüfen Sie, ob das Programm mit dieser Änderung noch korrekt arbeitet.
Beschreiben Sie die Änderung! Wie sieht das Struktogramm zu dieser
Änderung aus?
Ein anderer Schleifentyp:
Bisher erfolgte die Schleifen-Ende-Abfrage immer vor der Ausführung des
Anweisungsblockes. Sie kann aber auch erst nach der Ausführung des
Schleifenkörpers erfolgen. das Struktogramm hat dann diese Form:
Programm: Messebesucher_Durchschnitt_neu
Eingabe tage
z = 1, summe = 0
Eingabe anzahl
summe = summe + anzahl
z=z+1
solange z <= tage
schnitt = summe / tage
Ausgabe schnitt
53
Codierung:
Option Explicit
Sub durchschnitt_1()
Dim tage As Integer
Dim anzahl As Double
Dim summe As Double
Dim schnitt As Double
Dim z As Integer
tage = InputBox("Anzahl Tage: ")
z = 1
summe = 0
Do
anzahl = InputBox("Anzahl Besucher: ", anzahl)
summe = anzahl + summe
z = z + 1
Loop While z <= tage
schnitt = summe / tage
MsgBox ("Durchschnitt: " & schnitt)
End Sub
Aufgabe 21:
Testen Sie das Programm und erklären Sie die Funktionsweise dieses
Schleifentyps! Wo sehen Sie Probleme, wann könnte das Programm etwas
„machen“, was nicht beabsichtigt ist?
Aufgabe 22:
Überführen Sie auch dieses Programm in die objektorientierte Form (Trennung
GUI – Fachkonzept). Erstellen Sie bitte zunächst die Klassendiagramme.
54
Unterscheiden Sie bitte:
Bedingung
Anweisung 1
Anweisung 2
Anweisung 3, 4 ,5 usw.
Schleifen von diesem Typ werden auch als „abweisende Schleife“ oder
„kopfgesteuerte Schleifen“ bezeichnet.
Anweisung 1
Anweisung 1
Anweisung 3, 4 ,5 usw.
Bedingung
Diese Schleifen heißen auch „nicht abweisende Schleife“ oder „fußgesteuerte
Schleife“.
Aufgabe 23:
Je nach Schleifentyp kann vermieden werden, dass die Schleife überhaupt
abgearbeitet wird: Eingabe Tage: 0. Trotzdem wird auch bei der vorliegenden
Lösung dann unsinnigerweise ein Durchschnitt berechnet, was dann zu einem
Laufzeitfehler (Division durch 0) führt. Erweitern Sie das Programm so, dass
dies abgefangen wird (auch Struktogrammerstellung)!
55
Vermutlich sind Sie zu einer ähnlichen Lösung wie diese gekommen:
Option Explicit
Sub durchschnitt_3()
Dim tage As Integer
Dim anzahl As Double
Dim summe As Double
Dim schnitt As Double
Dim z As Integer
tage = InputBox("Anzahl Tage: ")
z = 1
summe = 0
Do While z <= tage
anzahl = InputBox("Anzahl Besucher: ", anzahl)
summe = anzahl + summe
z = z + 1
Loop
If tage > 0 Then
schnitt = summe / tage
MsgBox ("Durchschnitt: " & schnitt)
End If
End Sub
Als vierte Möglichkeit der Schleifenprogrammierung wird nun die For-NextSchleife vorgeführt, die in ähnlicher Weise in praktisch in allen Programmiersprachen vorhanden ist:
......
tage = InputBox("Anzahl Tage: ")
summe = 0
For z = 1 To tage
anzahl = InputBox("Anzahl Besucher: ", anzahl)
summe = anzahl + summe
Next z
schnitt = summe / tage
MsgBox ("Durchschnitt: " & schnitt)
......
56
Die Variable z wird als Schleifenzähler benutzt und bei diesem Schleifentyp
automatisch hochgezählt. Für viele Aufgabenstellungen ist dies eine sehr
elegante und einfache Lösung. Allerdings gibt es Fälle, wo dieser Schleifentyp
nicht die bestmögliche Lösung darstellt, z. B. wenn die Anzahl der
Schleifendurchläufe bei Beginn der Abarbeitung unbekannt ist.
Eine mögliche Struktogrammdarstellung:
Eingabe: tage
summe = 0
AW = 1, EW = tage, LV = z
Eingabe anzahl
AW: Anfangswert
EW: Endwert
LV: Laufvariable
Manche Autoren benutzen folgende Formulierung der Bedingung:
„Für z = 1 bis …..“ („klingt“ sprachlich etwas merkwürdig, die AW-EW –
Formulierung erscheint dem Autor dieser Unterlagen sinnvoller).
Aufgabe 24:
Es ist ein Programm zu erstellen, welchen den Tilgungsplan eines Kredits
ausgibt. Nach der Eingabe der Kredithöhe, des Zinssatzes, der jährlichen
Rückzahlung und der Laufzeit soll eine Tabelle mit folgenden Angaben ausgegeben werden:
Jahr
Zins (in Euro)
Tilgung
Restkredit
Wird eine Laufzeit < 1 oder größer 20 eingegeben, wird standardmäßig eine
Laufzeit von 20 Jahren angenommen. Ihre erste Lösung sollte zunächst
lediglich als Modul getestet werden. Erstellen Sie hierzu ein Struktogramm.
Erst dann erarbeiten Sie die objektorientierte Lösung (s. nächste Aufgabe).
57
Lösung: Codierung:
Option Explicit
Sub tilgung()
Dim k As Double
Dim p As Double
Dim r As Double
Dim j As Integer
Dim z As Double
Dim t As Double
Dim i As Integer
Dim aus As String
aus = "Jahr
Zins
Tilgung"
aus = aus & "
Restkredit" & vbCrLf
k = InputBox("Kredit: ")
p = InputBox("Zinssatz: ")
r = InputBox("Jährl. Rückzahlung: ")
j = InputBox("Laufzeit :")
If j < 1 Or j > 20 Then j = 20
For i = 1 To j
z = (k * p) / 100
t = r - z
k = k - t
aus = aus & Format(i, "00
") & Format(z, "0000000.00 ") _
& Format(t, "0000000.00 ") & Format(k, "0000000.00") &
vbCrLf
Next i
MsgBox (aus)
End Sub
Hinweise:
Der String mit dem Variablenname "aus" beinhaltet die Ausgabezeilen und
wird in der Verarbeitungsschleife zusammengesetzt. Das "&" verkettet die
einzelnen Werte einer Zeile (die Berechnungen für ein Jahr); damit aber für
jedes Jahr mit einer neuen Zeile begonnen wird, muss der Zeilenvorschub
berücksichtigt werden (Code: vbCrLf). Die Formatangabe dient dazu, dass die
sich entsprechenden Werte genau untereinander stehen (sauberer
Tabellenaufbau); dass so allerdings führenden Nullen mit ausgegeben werden,
soll zunächst nicht stören.
Aufgabe 25:
Überführen Sie auch dieses Programm in die objektorientierte Form (Trennung
GUI – Fachkonzept). Erstellen Sie bitte zunächst die Klassendiagramme.
Informieren Sie sich bitte hinsichtlich folgender VBA – Möglichkeiten: Die
Tabelle soll in einem sogenannten Listfeld ausgegeben werden und die Zahlen
sind zu formatieren.
58
Hinweise zur Codierung mit Listfeldern:
Ist die ListBox zur
Aufnahme aller Daten
zu klein, wird
automatisch eine
Bildlaufleiste angelegt.
Tilgungsplan.ListBox1.Clear
While k > r
z = (k * p) / 100
t = r - z
k = k – t
Eine zusätzliche Möglichkeit zur Codierung einer kopfgesteuerten Schleife:
While … WEnd
…………
If z < 100 Then
a2 = "
00.00
Else
If z < 1000 Then
a2 = "
000.00
Else
If z < 10000 Then
a2 = "
0000.00
Else
If z < 100000 Then
a2 = " 00000.00
Else
If z < 1000000 Then
a2 = " 000000.00
Else
a2 = "0000000.00
End
End
End
End
End
If
If
If
If
If
"
"
"
"
"
"
Dies ist eine Möglichkeit der
Formatierung numerischer
Werte, wenn ein Unterdrückung führender Nullen
vorzunehmen ist, für den
Tabellenaufbau aber Leerstellen zu berücksichtigen
sind. Diese Prozedur wäre
für alle Ausgabefelder einer
Zeile anzuwenden, müsste
aber zwecks einer sinnvollen
Modellierung der
Programmstruktur
ausgelagert werden (z. B.
Definieren einer Klasse
„Ausgabenaufbereitung“.
ListBox
…………
Im Original: eine Zeile!
Tilgungsplan.ListBox1.AddItem Format(j, a1) &
Format(z, a2) & Format(t, a3) & Format(k, a4)
j = j + 1
Wend
59
Aufgabe 26:
Es ist ein Programm zu erstellen für den Druck einer Wertetabelle der Funktion
y=x². Einzugeben sind sowohl Unter- und Obergrenze der Wertetabelle als auch
die Schrittweite für die Berechnung der y-Werte. Welcher Schleifentyp erscheint
Ihnen als der sinnvollste Typ? Testen Sie bitte alle Schleifentypen
Programmerweiterung: Unsinnige Werte werden abgewiesen und eine
Neueingabe verlangt.
Aufgabe 27:
Office-Programme für Tabellenkalkulation haben die Funktionen MIN(),
MAX() und MITTELWERT(). Programmieren Sie diese Funktionen in
VBA. Die Anzahl der Eingabewerte ist beliebig. Programmerweiterung:
Bezüglich der Funktionen MIN() und MAX() wird auch noch ausgegeben,
um die wievielte der eingegebenen Zahl es sich handelt (Position der Zahl
auf der Eingabeliste).
60
Prozeduren und Funktionen (Ergänzungen)
Funktionen und Prozeduren sind ja bereits im Zusammenhang mit den
Methoden eines Objektes bekannt.
Beispiel (hier unabhängig von einer Klasse):
Sub funkt_test()
Dim a As Integer
Dim b As Integer
a = 3
a = a + 6
b = Sqr(a)
MsgBox ("Wurzel aus 9: " & b)
End Sub
Die Anweisungszeile
a = a + 6
wird vom Compiler in Maschinensprache übersetzt und kann dann ausgeführt
werden. Anders ist es bei der Zeile:
b = Sqr(a)
Das Berechnen der Quadratwurzel ist ein mathematisches Verfahren, welches
als fertiges Programm von VBA zur Verfügung gestellt wird und praktisch für
das vom Programmierer oder der Programmiererin erstellte Programm
unsichtbar "irgendwo im Hintergrund" abläuft, wenn es mit seinem Namen Sqr
aufgerufen wird. Solche Programme heißen Funktionen. Normalerweise gibt
man ihnen etwas mit: Übergabewerte, Schnittstelle, Funktionsargumente,
Parameter (hier die Variable a, aus der die Wurzel berechnet werden soll) und
sie liefern etwas zurück Rückgabewert, Return-Wert (hier den Wert der
Quadratwurzel aus a, der dann in der Variablen b gespeichert wird). Funktionen
werden aber nicht nur von VBA bereitgestellt, sie lassen sich auch selbst
programmieren (siehe z. B. die Methoden von Objekten). Ein Beispiel:
Sub
Dim
Dim
Dim
Dim
m_test()
a As Double
b As Double
c As Double
m As Double
a = 4.3
b = 5.5
c = 17.2
m = mit(a, b, c)
MsgBox ("Mittelwert: " & m)
End Sub
Function mit(x As Double, y As Double, z As Double) As Double
mit = (x + y + z) / 3
End Function
61
Erklärung:
Das Programm m_test ruft die Funktion auf und übergibt ihr Daten, die sie zur
Verarbeitung benötigt:
mit(a, b, c)
Die Festlegung der Schnittstelle und des Rückgabewertes wird folgendermaßen
vorgenommen:
Function mit(x As Double, y As Double, z As Double) As Double
Die Funktion mit dem Namen mit gibt
einen Wert vom Typ double zurück
Name der Funktion
Parameter, die bei dem Funktionsaufruf an die Funktion
übergeben werden, hier alle drei vom Typ double.
Das Programm, welches die Funktion aufruft erhält auf folgende Weise den
Rückgabewert:
mit = (x + y + z) / 3
(in der Funktion mit)
Das Programm kann den Wert dann selbst benutzen:
m = mit(a, b, c)
(im Programm m_test, welches die Funktion aufruft)
Aufgabe 28:
Testen Sie dieses Programm und erklären Sie wie es „funktioniert“!
Berücksichtigen Sie bitte insbesondere diese Anweisungszeile in der
Funktion: mit = (x + y + z).
Prozeduren
Prozeduren kennen Sie bereits, jedes Programm, welches Sie bisher geschrieben
haben, ist eine Prozedur (= Ansammlung von Anweisungen), welche mit Sub
eingeleitet wird und mit End Sub beendet wird. Im Prinzip ist die Arbeitsweise
und der Aufruf von Prozeduren und Funktionen gleich, der Unterschied besteht
darin, dass Prozeduren keinen Rückgabewert liefern.
62
Hier noch eine sehr nützlich Funktion, welche kaufmännisch rundet:
Sub r_test()
Dim a As Double
Dim c As Double
c = 17.2673
a = fRunden([c], 2)
MsgBox ("Gerundete Zahl: " & a)
End Sub
Function fRunden(Z, St) As Double
fRunden = Sgn(Z) * Int(Abs(Z) * (10 ^ St) + 0.5) / (10 ^ St)
End Function
63
5. Algorithmen mit strukturierten Datentypen
Neben den unstrukturierten Datentypen (Standard-Typen wie z. B. double) gibt
es die strukturierten (konstruierten) Typen wie Array, Record und File.
Arrays (Felder, Matrizen, Tabellen)
Beispiel einer Problembeschreibung: Für eine statistische Berechnung ist es
erforderlich, dass viele (z. B. 500) Zahlenwerte eingegeben werden und dass
diese Werte für eine nach der Eingabe erforderlichen Berechnung alle im
Hauptspeicher des Computers verfügbar ein müssen. Es ist einsichtig, dass eine
Deklaration eines jeden einzelnen Wertes sehr umständlich wäre, z. B.:
Dim
Dim
Dim
Dim
Dim
Dim
Z1
Z2
Z3
Z4
Z5
Z6
As
As
As
As
As
As
Double
Double
Double
Double
Double
Double
u.s.w
Dim Z500 As Double
Für Problemstellungen dieser Art existiert eine wesentlich komfortablere Art
der Datendefinition:
Dim Z(500) As Double
Gleiche Datentypen werden so zu sogenannten Datenfeldern (Arrays, Tabellen)
zusammengefasst. Die einzelnen Elemente eines Arrays haben alle den
gleichen Namen (hier: Z); unterscheiden lassen sie sich durch einen Index, der
hinter dem Datennamen in Klammern steht. Bei der Deklaration wird die
Anzahl der Datenelemente in der Klammer angegeben (in unserem Fall 500).
Bei manchen Programmiersprachen wird das erste Element mit dem Index 0
(hier also Z(0)) angesprochen, andere Sprachen (z. B. COBOL) beginnen mit
dem Index 1 für das erste Element, da dies etwas anschaulicher ist. VBA
gestattet beides; soll mit den Index 0 begonnen werden, wird nichts angegeben,
ansonsten erfolgt eine Option-Angabe:
Option Base 1
Dim Z(500) As Double
64
Die folgende Abbildung veranschaulicht die Speicherung eines Arrays im
Hauptspeicher:
3,4
12,7
1,67
78,41
1,44
45,0 usw
Z(1)
Z(2)
Z(3)
Z(4)
Z(5)
Z(6) usw
Element 1
Element 2
Element 3
Element 4
usw
Ein kleines Beispiel, hier aber mit String-Variablen als Basis-Datentyp, dient
der Einführung in die Array-Thematik:
Option Explicit
Option Base 1
Sub Woche()
Dim w_name(7) As String
Dim i As Integer
w_name(1) = "Montag"
w_name(2) = "Dienstag"
w_name(3) = "Mittwoch"
w_name(4) = "Donnerstag"
w_name(5) = "Freitag"
w_name(6) = "Samstag"
w_name(7) = "Sonntag"
i = InputBox("Eingabe Wochentag (1-7)")
MsgBox ("Tag: " & w_name(i))
End Sub
Aufgabe 29:
Testen Sie das Programm und erklären Sie bitte seine Funktionsweise! Was
passiert, wenn als Wochentag eine Zahl größer 7 oder kleiner 1 eingegeben
wird? Korrigieren Sie das Programm mit Hilfe einer geeigneten Abfrage und
der Ausgabe einer Fehlermeldung bei falscher Eingabe!
65
Übung
Finden Sie die Funktionalitäten des Programms mit der unten stehenden
Bildschirmmaske heraus. Hilfe: Analysieren Sie den Quelltext.
Option Explicit
Dim w_name(7) As String
Dim Umsatz(7) As Double
Dim i As Integer
Private Sub CommandButton1_Click()
w_name(1) = "Montag"
w_name(2) = "Dienstag"
w_name(3) = "Mittwoch"
w_name(4) = "Donnerstag"
w_name(5) = "Freitag"
w_name(6) = "Samstag"
w_name(7) = "Sonntag"
i = TextBox1
TextBox2 = w_name(i)
TextBox3 = Umsatz(i)
End Sub
Private Sub CommandButton2_Click()
i = TextBox1
Umsatz(i) = TextBox3
End Sub
Private Sub CommandButton3_Click()
TextBox1 = ""
TextBox2 = ""
TextBox3 = ""
End Sub
66
Sortierung von Zahlen (Selection Sort)
Problemstellung: Es werden Zahlen in beliebiger Reihenfolge eingegeben; die
Anzahl ist festgelegt (z. B. 10). Die Zahlen sollen der Größe nach aufsteigend
sortiert und dann ausgegeben werden. Hinweis: Die eingegebenen Zahlen (und
die danach sortierten Zahlen) stehen in einem Array.
Lösung: Es wird hier ein einfacher Sortieralgorithmus vorgestellt. Folgende
Überlegungen liegen diesem zugrunde:
1. Zunächst muss die kleinste Zahl gesucht und an die erste Stelle des Array
gebracht werden.
2. Das gleiche wird nun für die zweitkleinste Zahl und dann für die drittkleinste
Zahl usw. durchgeführt.
Der Überschaubarkeit halber wird hier nur von 4 Zahlen ausgegangen, die nach
der Eingabe im Array stehen:
8
3
5
1
0
Z(1)
Z(2)
Z(3)
Z(4)
H
Wenn zunächst die kleinste Zahl an den Anfang des Array geschoben werden
soll, müssen alle Zahlen miteinander verglichen werden. Das Schieben bewirkt
nun, dass das ursprüngliche Tabellenelement von einer anderen Zahl
überschrieben und damit gelöscht wird. Aus diesem Grund existiert noch eine
Variable H, eine Hilfsvariable, gleichsam ein Zwischenspeicher. Der Tausch
funktioniert nun folgendermaßen:
1. Schritt:
If Z(2) < Z(1) Then Z(2) und Z(1) vertauschen: Z(2)
H, Z(1)
Z(2), H
Z(1)
3
8
5
1
3
Z(1)
Z(2)
Z(3)
Z(4)
H
67
2. Schritt:
If Z(3) < Z(1) Then Z(3) und Z(1) vertauschen: Z(3)
H, Z(1)
Z(3), H
Z(1)
hier bleibt alles, wie es war, da die Bedingung nicht zutrifft:
3
8
5
1
3
Z(1)
Z(2)
Z(3)
Z(4)
H
3. Schritt:
If Z(4) < Z(1) Then Z(4) und Z(1) vertauschen: Z(4)
H, Z(1)
Z(4), H
Z(1)
1
8
5
3
1
Z(1)
Z(2)
Z(3)
Z(4)
H
Jetzt steht in der Tat die kleinste Zahl an erster Stelle des Arrays. Das gleiche
wird nun für die zweitkleinste Zahl durchgeführt.
4. Schritt:
If Z(3) < Z(2) Then Z(3) und Z(2) vertauschen: Z(3)
H, Z(2)
Z(3), H
Z(2)
1
5
8
3
5
Z(1)
Z(2)
Z(3)
Z(4)
H
5. Schritt:
If Z(4) < Z(2) Then Z(4) und Z(2) vertauschen: Z(4)
H, Z(2)
Z(4), H
Z(2)
1
3
8
5
3
Z(1)
Z(2)
Z(3)
Z(4)
H
Jetzt steht die zweitkleinste Zahl an zweiter Stelle des Arrays. Das gleiche wird
nun für die drittkleinste Zahl durchgeführt.
68
6. Schritt:
If Z(4) < Z(3) Then Z(4) und Z(3) vertauschen: Z(4)
H, Z(3)
Z(4), H
Z(3)
1
3
5
8
5
Z(1)
Z(2)
Z(3)
Z(4)
H
Nun steht die drittkleinste Zahl an der dritten Stelle des Arrays und die höchste
Zahl „automatisch“ an der letzten Stelle: das Array ist aufsteigend sortiert, das
Verfahren ist beendet.
selection_sort
I = 1, MAX ist die Anzahl der Tabellenelemente, wird hier festgelegt
solange bis I > MAX
Eingabe Z(I)
I=I+1
I=1
solange bis I > (MAX-1)
K=I+1
solange bis K > MAX
Z(K) < Z(I)?
ja
nein
H=Z(K)
Z(K)=Z(I)
Z(I)=H
./.
K=K+1
I=I+1
Ausgabe der Werte (Z(I))
Beachten Sie bitte: Hier ist eine innere Schleife (solange bis K > MAX) in eine
äußere Schleife (solange bis I > MAX-1) "verschachtelt".
69
Aufgabe 30:
Überprüfen Sie den Algorithmus anhand der Daten auf den vorherigen Seiten
in Form eines Schreibtischtests (Schritt 1 bis Schritt 6)! Legen Sie bitte die
zusätzlichen Variablen I und K an, MAX ist 4.
Codierung:
Option Explicit
Option Base 1
Sub sel_sort()
Dim Z(10) As Integer
Dim I As Integer
Dim K As Integer
Dim H As Integer
Dim aus As String
For I = 1 To 10
Z(I) = InputBox("Wert: ", I)
Next I
For I = 1 To 9
For K = I + 1 To 10
If Z(K) < Z(I) Then
H = Z(K)
Z(K) = Z(I)
Z(I) = H
End If
Next K
Next I
aus = "Sortierung: "
For I = 1 To 10
aus = aus & Z(I) & " "
Next I
MsgBox (aus)
End Sub
Aufgabe 31:
Erstellen Sie nun eine äquivalente Lösung dieses Problems mit einer DoWhile-Schleife!
70
Die Record-Struktur
Bei der Festlegung der Strukturart Array werden Daten vom gleichen Datentyp
zu einer größeren Einheit, dem Array (oder der Tabelle) zusammengefasst.
Weitaus häufiger liegt aber in der Datenverarbeitung der Fall vor, dass Daten
eine Einheit (einen Verbund) bilden, die nicht vom gleichen Datentyp sind.
Beispiele solcher Datenstrukturen sind die Informationen, die zur Beschreibung
von Kunden oder Artikeln benötigt werden:
Kunde
Kundennummer
Name
Straße
PLZ
Ort
Telefon
6 Stellen
25 Stellen 25 Stellen
5 St. 30 St. 14 Stellen
(alle vom Datentyp String, aber unterschiedlicher Länge)
oder:
Artikel
Artikelnummer
Bezeichnung
Preis (EK)
6 Stellen, String
30 Stellen, String Double
Preis (VK)
Mengeneinheit
Double
Integer (Code)
Wenn mit solchen sogenannten Record-Strukturen gearbeitet werden soll, wird
(in dem meisten Programmiersprachen) dem Computer zunächst mitgeteilt,
dass ein individueller (benutzerdefinierter) Datentyp mit einem komplexeren
Aufbau zu vereinbaren ist. Diesem neuen Datentyp wird dann auch ein Name
zugeordnet, den die Programmiererin oder der Programmierer selbst wählt.
Beispiel:
Type record_1
Anum As Integer
Abez As String
Apreis As Double
End Type
Der neu festgelegte Datentyp hat jetzt den Namen "record_1" (man hätte ihm
selbstverständlich einen anderen Namen geben könne, z. B. datensatz_artikel).
Damit wurde aber noch keine Variable deklariert (eben nur ein neuer Typ
vereinbart, vergleichbar mit Double, Integer usw.). Im Programm wird nun
eine Variable von diesem speziellen Datentyp deklariert.
Beachte: Ein RECORD ist gleichsam eine Klasse ohne Methoden.
71
Dim Artikelsatz As record_1
Der Variablename lautet nun "Artikelsatz"; auf die einzelnen Komponenten der
Variable (d.h. auf die einzelnen Daten) wird nun mit dem sogenannten PunktOperator zugegriffen:
Artikelsatz.Anum
Demo-Programm (Strukturart Record):
Option Explicit
Type record_1
Anum As Integer
Abez As String
Apreis As Double
End Type
Sub datensatz()
Dim Artikelsatz As record_1
Dim I As Integer
Dim aus As String
Artikelsatz.Anum = InputBox("Artikelnummer: ")
Artikelsatz.Abez = InputBox("Artikelbezeichnung: ")
Artikelsatz.Apreis = InputBox("Artikelpreis: ")
aus = "Artikelsatz: "
With Artikelsatz
aus = aus & .Anum & " " & .Abez & " " & .Apreis
End With
MsgBox (aus)
End Sub
Das Programm erfasst die einzelnen Daten zu dem Artikelsatz, baut
anschließend einen Ausgabestring zusammen und gibt diesen zur Kontrolle
aus. Mit der With-Anweisung wird der Punkt-Operator einschließlich des
Variablennamens des Artikel-Datensatzes eingespart. Ausformuliert (ohne
With...) lautet das Zusammensetzen des Ausgabestrings folgendermaßen:
aus = aus & Artikelsatz.Anum & " " & Artikelsatz.Abez & " " & ...
Aufgabe 32:
Vereinbaren Sie den Record-Typ für den (etwas ausführlich beschriebenen)
Artikel-Datensatz auf der vorherigen Seite! Deklarieren Sie eine Variable mit
dem Namen A_Satz von diesem Typ (Codierung als „Modul“!).
72
Die Strukturart „Record“ kann selbst andere, benutzerdefinierte Strukturen
beinhalten. Sie kann aber auch als Datenelement eines Arrays benutzt werden.
In diesem Fall können mehrere (viele) Datensätze als Tabelle verarbeitet
werden. Das folgende Beispiel verdeutlicht eine einfache Anwendung zu dieser
Thematik. Im Prinzip repräsentiert dies bereits eine Datei mit mehreren
Datensätzen. Erweitert um einen Abspeicherungsmechanismus und der Möglichkeit, die Datensätze wieder von der Festplatte zu laden, wäre das bereits ein
Beispiel für eine einfache Dateiverarbeitung (s. später). Das folgende Beispiel
demonstriert die Verbindung von Array und Record:
Option Explicit
Type record_1
Anum As Integer
Abez As String
Apreis As Double
End Type
Sub datensatz()
Dim Artikelsatz(3) As record_1
Dim I As Integer
Dim aus As String
For I = 1 To 3
Artikelsatz(I).Anum = InputBox("Artikelnummer: ")
Artikelsatz(I).Abez = InputBox("Artikelbezeichnung: ")
Artikelsatz(I).Apreis = InputBox("Artikelpreis: ")
Next I
For I = 1 To 3
aus = "Artikelsatz " & I & ": "
With Artikelsatz(I)
.Apreis = .Apreis * 0.95
aus = aus & .Anum & " " & .Abez & " " & .Apreis
End With
MsgBox (aus)
Next I
End Sub
Aufgabe 33:
Analysieren Sie dieses Programm! Erstellen Sie ein Struktogramm und
beschreiben Sie die Funktionsweise in Worten!
73
Dateiverarbeitung
Eingabe von drei Datensätzen und Ausgabe in eine Datei:
Option Explicit
Private Type record_Artikel
A_nummer As Integer
A_bezeichnung As String
A_preis As Double
End Type
Sub Dateiverarbeitung()
Dim Artikeltabelle(3) As record_Artikel
Dim I As Integer
For I = 1 To 3
Artikeltabelle(I).A_nummer = InputBox("Artikelnummer: ")
Artikeltabelle(I).A_bezeichnung =
InputBox("Artikelbezeichnung: ")
Artikeltabelle(I).A_preis = InputBox("Artikelpreis: ")
Next I
Open "Artikeldatei" For Output As #1
For I = 1 To 3
Write #1, Artikeltabelle(I).A_nummer,
Artikeltabelle(I).A_bezeichnung, Artikeltabelle(I).A_preis
Next I
Close #1
End Sub
Einlesen (Notwendige Zeilen von oben übernehmen):
Open "Artikeldatei" For Input As #1
For I = 1 To 3
Input #1, Artikeltabelle(I).A_nummer,
Artikeltabelle(I).A_bezeichnung, Artikeltabelle(I).A_preis
Next I
I = InputBox("Welcher Datensatz soll angezeigt werden?
Nummer:")
MsgBox (Artikeltabelle(I).A_nummer)
MsgBox (Artikeltabelle(I).A_bezeichnung)
MsgBox (Artikeltabelle(I).A_preis)
Close #1
74
Dateiverarbeitung im Dialog
Problem: Es sollen sich Daten zu verschiedenen Artikeln erfassen lassen, alle
Daten können auf die Festplatte als Datei abgespeichert werden. Es besteht die
Möglichkeit, die Datei wieder zu laden und die Artikeldaten in einem „BlätternModus“ anzuzeigen. Die Datensatzstruktur hat folgenden Aufbau:
- Artikelnummer: Integer
- Artikelbezeichnung: 20 Zeichen, String
- Artikelpreis: Double
Der Bildschirm ist folgendermaßen aufgebaut:
Hinweise zur Problemlösung: Bei der hier formulierten Artikelverwaltung
handelt es sich um die erste vereinfachte Version eines Programms, welches
später hinsichtlich des Datenmodells und der Funktionen verbessert bzw.
ausgebaut werden sollte.
Im Fachkonzept ist ein Array zu vereinbaren; die einzelnen Array-Elemente
bestehen aus Datensätzen (Datenstruktur RECORD). Maximal können (zunächst
zu Testzwecken) 10 Datensätze erfasst und gespeichert werden. Die Datensätze
werden durch Mausklick alle abgespeichert oder geladen, d.h. das ganze Array
wird komplett geladen oder abgespeichert.
Sämtliche Dateizugriffe erfolgen in der Fachkonzept - Klasse (hier. ZweiSchichten-Modell, sollte später zu dem 3-Schichten-Modell erweitert werden),
die GUI „weiß“ also nicht, wie die Datenspeicherung erfolgt: Absolute
Trennung zwischen Datenhaltung und GUI!
75
Aufgabe: Analysieren Sie bitte das vorliegende Programm vollständig! Zeichnen
Sie die Klassendiagramme für das Fachkonzept und die GUI! Erstellen Sie eine
Übersicht die darstellt, welche Funktionsblöcke/Moduln (hier: Prozeduren)
vorhanden sind und wie sie zusammenhängen und zeichnen Sie die
entsprechenden Struktogramme. Führen Sie ebenfalls eine Datenanalyse durch.
Es ist wichtig, dass Ihnen der Programmablauf und die Bedeutung der Daten
vollständig klar wird, damit in weiteren Arbeitsschritten dieses Programm
erweitert werden kann!
(Hinweis: Das Programm funktioniert fehlerfrei, es wurden allerdings nicht alle
Plausibilitäten bzw. die Möglichkeiten des falschen Programmhandlings durch den Benutzer
berücksichtigt!)
UserForm:
Option Explicit
Dim oArtDat As clsArtDat
Private Sub Aktualisieren_FeldEdit()
TextBox4 = oArtDat.sn
oArtDat.A_Nummer = TextBox1
oArtDat.A_Bezeichnung = TextBox2
oArtDat.A_Preis = TextBox3
End Sub
Private Sub
TextBox4
TextBox1
TextBox2
TextBox3
End Sub
Aktualisieren_EditFeld()
= oArtDat.sn
= oArtDat.A_Nummer
= oArtDat.A_Bezeichnung
= oArtDat.A_Preis
Private Sub CommandButton1_Click()
oArtDat.Dat_oeffnen
Aktualisieren_EditFeld
End Sub
Private Sub CommandButton2_Click()
Aktualisieren_FeldEdit
oArtDat.Dat_speichern
End Sub
Private Sub CommandButton3_Click()
Aktualisieren_FeldEdit
oArtDat.hole_Satz_prev
Aktualisieren_EditFeld
End Sub
76
Private Sub CommandButton4_Click()
Aktualisieren_FeldEdit
oArtDat.hole_Satz_next
Aktualisieren_EditFeld
End Sub
Private Sub CommandButton5_Click()
Set oArtDat = Nothing
End
End Sub
Private Sub UserForm_Initialize()
Set oArtDat = New clsArtDat
oArtDat.sn = 1
TextBox1 = 0
TextBox2 = " "
TextBox3 = 0#
End Sub
Klasse:
Option Explicit
Const max = 10
Private Type record_Artikel
mA_nummer As Integer
mA_bezeichnung As String
mA_preis As Double
End Type
Private Artikeltabelle(max) As record_Artikel
Private mI As Integer
Private z As Integer
Public Property Let A_Nummer(Num As Integer)
Artikeltabelle(mI).mA_nummer = Num
End Property
Public Property Let A_Bezeichnung(Bez As String)
Artikeltabelle(mI).mA_bezeichnung = Bez
End Property
Public Property Let A_Preis(Preis As Double)
Artikeltabelle(mI).mA_preis = Preis
End Property
Public Property Get A_Nummer() As Integer
A_Nummer = Artikeltabelle(mI).mA_nummer
End Property
Public Property Get A_Bezeichnung() As String
A_Bezeichnung = Artikeltabelle(mI).mA_bezeichnung
End Property
77
Public Property Get A_Preis() As Double
A_Preis = Artikeltabelle(mI).mA_preis
End Property
Public Property Let sn(n As Integer)
z = n
End Property
Public Property Get sn() As Integer
sn = z
If mI = 0 Then mI = 1
End Property
Public Sub hole_Satz_prev()
z = z - 1
If z < 1 Then z = 1
mI = z
End Sub
Public Sub hole_Satz_next()
If z = 0 Then z = 1
z = z + 1
If z > max Then z = max
mI = z
End Sub
Public Sub Dat_oeffnen()
Open "h:\Artikeldateir" For Input As #1
For mI = 1 To max
Input
#1,
Artikeltabelle(mI).mA_nummer,
Artikeltabelle(mI).mA_bezeichnung, Artikeltabelle(mI).mA_preis
Next mI
Close #1
mI = 1
z = 1
End Sub
Public Sub Dat_speichern()
Open "h:\Artikeldateir" For Output As #1
For mI = 1 To max
Write
#1,
Artikeltabelle(mI).mA_nummer,
Artikeltabelle(mI).mA_bezeichnung, Artikeltabelle(mI).mA_preis
Next mI
mI = 1
Close #1
End Sub
Hinweis: Bei der erstmaligen Anwendung Programm starten, auf „Speichern“ klicken (leere
Datei wird angelegt und Programm beenden. Dann erneut starten und Daten erfassen.
78
Exkurs: Änderungsdienst: ACCESS-Objekte
Grundidee: Die Datenhaltungsschicht ist für die Datenspeicherung, z. B. in einer
Datenbank oder in einer Datei verantwortlich. In dem vorliegenden Beispiel (2Schichten-Architektur) erledigt dies die Klasse „clsArtDat“. Das Programm ist
nun dergestalt zu verändern, dass das Konzept der Dateiverarbeitung durch eine
Access-Datenbank ausgetauscht wird. Die GUI-Schicht darf natürlich „davon
nichts merken“; wie die Daten abgespeichert werden, ist für sie „unsichtbar“.
Eine einfache Lösung, auf Access-Datenbanken zuzugreifen, ist die
Verwendung der DAO-Bibliothek (Objektbibliothek: Sammlung von Objekten
welche ermöglicht, auf eine Access-Datenbank zuzugreifen).
Achtung: Es gibt andere Möglichkeiten und die nun folgende Vorgehensweise
muss eventuell auf neue Access-Versionen angepasst werden!
Bekanntmachen der Bibliothek:
Zuerst:
dann:
79
Neue Klasse mit DB-Zugriff:
Option Explicit
Const max = 10
Private Type record_Artikel
mA_nummer As Integer
mA_bezeichnung As String
mA_preis As Double
End Type
Private
Private
Private
Private
Artikeltabelle(max) As record_Artikel
mI As Integer
z As Integer
SQL_Str As String
Public Property Let A_Nummer(Num As Integer)
Artikeltabelle(mI).mA_nummer = Num
End Property
Public Property Let A_Bezeichnung(Bez As String)
Artikeltabelle(mI).mA_bezeichnung = Bez
End Property
Public Property Let A_Preis(Preis As Double)
Artikeltabelle(mI).mA_preis = Preis
End Property
Public Property Get A_Nummer() As Integer
A_Nummer = Artikeltabelle(mI).mA_nummer
End Property
Public Property Get A_Bezeichnung() As String
A_Bezeichnung = Artikeltabelle(mI).mA_bezeichnung
End Property
Public Property Get A_Preis() As Double
A_Preis = Artikeltabelle(mI).mA_preis
End Property
Public Property Let sn(n As Integer)
z = n
If mI = 0 Then mI = 1
End Property
Public Property Get sn() As Integer
sn = z
End Property
Public Sub hole_Satz_prev()
z = z - 1
If z < 1 Then z = 1
mI = z
End Sub
Public Sub hole_Satz_next()
If z = 0 Then z = 1
z = z + 1
If z > max Then z = max
mI = z
End Sub
80
Public Sub Dat_oeffnen()
Dim docNew As Document
Dim dbWG As DAO.Database
Dim rdArtikel As Recordset
Dim intRecords As Integer
Set dbWG = OpenDatabase(Name:="C:\BBST.mdb")
Set rdArtikel = dbWG.OpenRecordset("Artikel", dbOpenDynaset)
mI = 1
Do While Not rdArtikel.EOF
Artikeltabelle(mI).mA_nummer = rdArtikel!ANummer
Artikeltabelle(mI).mA_bezeichnung = rdArtikel!Bezeichnung
Artikeltabelle(mI).mA_preis = rdArtikel!Preis
rdArtikel.MoveNext
mI = mI + 1
Loop
dbWG.Close
mI = 1
z = 1
End Sub
Public Sub Dat_speichern()
Dim docNew As Document
Dim dbWG As DAO.Database
Dim rdArtikel As Recordset
Dim intRecords As Integer
Set dbWG = OpenDatabase(Name:="C:\BBST.mdb")
Set rdArtikel = dbWG.OpenRecordset("Artikel", dbOpenDynaset)
mI = 1
For mI = 1 To max
SQL_Str = "INSERT INTO Artikel(ANummer, Bezeichnung, Preis)" _
& " Values(" & Artikeltabelle(mI).mA_nummer _
& ", '" & Artikeltabelle(mI).mA_bezeichnung _
& "', " & Artikeltabelle(mI).mA_preis & ")"
If Artikeltabelle(mI).mA_Nummer > 0 Then dbWG.Execute SQL_Str
Next mI
mI = 1
Close #1
End Sub
81
6 EXCEL - Objekte
In diesem Teil geht es nun darum, mit Hilfe von VBA-Programmen EXCELTabellenblätter, Arbeitsmappen, einzelne Zellen oder Zellbereiche zu verändern.
Dies bedeutet, dass Objekte manipuliert werden. Objekte (also z. B. eine
einzelne Zelle) besitzen Eigenschaften (z. B. Größe, Farbe usw.) und Methoden,
mit denen das Verhalten eines Objektes bestimmt wird (z. B. bewirkt die
Methode Close einer Arbeitsmappe, dass dieses Objekt geschlossen wird.
Wichtige Objekte:
Application (Das gesamte EXCEL-Fenster)
Workbook (eine Arbeitsmappe)
Worksheet (das einzelne Arbeitsblatt)
Range (Zellenbereich oder einzelne Zelle)
Soll jetzt ein Zellenbereich manipuliert werden, ist folgender Zugriff darauf
möglich:
Workbooks(„MappeX“).Worksheets(„TabelleY“).Range(„A1:C5“)
Wichtige Objekteigenschaften:
Caption (Beschriftung der Objekte)
Name
Selection (das markierte Objekt)
Value (Wert/Inhalt, z. B. einer Zelle)
Sub zelle_fuellen()
Workbooks(1).Worksheets(2).[B3].Value = "Hier bin ich!"
End Sub
Container-Objekt: Arbeitsmappe
Objekt im Containerobjekt: Tabelle 2
82
Wichtige Objektmethoden:
Activate (aktiviert ein Objekt, gleicher Effekt, wie das Anklicken mit der Maus)
Clear (löschen)
Cells (Zugriff auf spezielle Zellen, Cells erwartet eine Zeilen- und Spaltenindex)
Close (Applications-Objet oder Arbeitsmappe schließen)
Open (Arbeitsmappe öffnen)
Einfaches Beispiel: Einer Excel-Zelle mittels VBA einen Wert zuweisen:
Nach der Ausführung (F5):
Beachten Sie diese Angaben (s. Quellcode oben)!
83
Beispiel
1. Schritt: Anlegen der folgenden Tabelle:
Hinweis: „Tabelle1“ heißt nun Artikelliste.
2. Schritt: Geben Sie bitte folgenden Programmcode ein:
Sub Artikel_suchen()
ThisWorkbook.Sheets("Artikelliste").Activate
ActiveSheet.[A1].Select
Nummer_ein:
Nr = InputBox("Bitte eine Nummer eingeben")
If Not IsNumeric(Nr) Then
MsgBox "Bitte nur eine Zahl!"
GoTo Nummer_ein
End If
84
Nr = Val(Nr)
ActiveCell.Offset(0, 0).Select
While ActiveCell.Value <> ""
If ActiveCell.Value = Nr Then
ActiveCell.Offset(0, 1).Select
MsgBox "Der Artikel mit der Nummer " & _
Nr & " lautet " & ActiveCell.Value
Exit Sub
End If
ActiveCell.Offset(1, 0).Select
Wend
MsgBox "Die Nummer " & Nr & " wurde nicht gefunden!"
End Sub
3. Schritt: Starten Sie das Programm mit F5.
Geben Sie in der InputBox eine Artikelnummer ein. Ist der dazugehörende
Artikel vorhanden, müsste folgende Ausgabe erscheinen:
Select-Methode: markiert eine Zelle oder einen Zellbereich
Activate-Methode: macht eine einzelne Zelle zur aktiven Zelle
Offset: Bereich versetzen (s. Excel-Hilfe)
85
Übungen
Demoprogramm für verschiedene Möglichkeiten der Zellenbestimmung
1
2
3
4
5
6
7
8
9
10
11
Sub c()
Dim x As Integer
Dim y As Integer
x=3
y=4
ActiveCell.Value = "56"
Workbooks("Mappe1").Worksheets("Tabelle2").Range("C3").Value = 45
Workbooks("Mappe1").Worksheets("Tabelle3").Select
Cells(x, y).Select
ActiveCell.Value = "10120"
End Sub
Zeile 6: In der gerade aktivierten Tabelle wird in der markierten Zelle der Wert
56 eingetragen (könnte also an einer „zufälligen“ Zelle eingetragen
werden)
Zeile 7: Der „Zufall“ wird „ausgeschaltet“: Genau in Tabelle 2 in der Zelle C3
erscheint der Wert 45
Zeile 8: Tabelle 3 auswählen
Zeile 9: Die in den Zeilen 4 und 5 mit Werten versehenen Variablen dienen nun
zur Bestimmung der Zellen: x steht für die Zeile, Y für die Spalte
Zeile 10: Zuweisung des Wertes 10120 an die durch die Zeilen 4,5,8,9
bestimmte Zelle
86
Beispiel: Die Werte der Funktion y = x² von VBA nach Excel bringen
Option Explicit
Sub c()
Dim x As Integer
Dim i As Integer
x = 1
i = -5
Workbooks("Mappe1").Worksheets("Tabelle1").Select
Do While i < 6
Cells(x, 1).Select
ActiveCell.Value = i
Cells(x, 2).Select
ActiveCell.Value = i * i
x = x + 1
i = i + 1
Loop
End Sub
87
Aufgabe 34:
Erweitern Sie das Programm bitte um folgende Möglichkeiten:
1. Die Tabelle hat eine Beschriftung.
2. Über InputBox können die Anfangs- und Endewerte für x eingegeben
werden.
3. Es ist möglich, eine Schrittweite <> 1 zu wählen.
4. Unsinnige Eingabewerte werden abgefangen.
Alles soll von VBA aus realisiert werden.
Erstellen Sie mit dem Diagramm-Assistenten eine xy-Darstellung der Funktion!
Beachten Sie: Bei Änderung der Werte ändert sich der Funktionsgraph automatisch. Hinweis: Unter Extras/Makro ist das VBA-Programm unter dem
namen hinter Sub eingetragen, von hier aus kann es direkt (ohne <Alt> <F11>)
gestartet werden.
Das Arbeiten mit Dialogen und Formularen in EXCEL
88
Aufgabe 35:
Erstellen Sie ein Dialogfenster ähnlich wie das auf der vorherigen Seite!
Wenn Sie das Dialogfenster fertigerstellt haben, machen Sie bitte einen
Doppelklick auf den Button „Werte berechnen“. Sie gelangen dann in den
Quelltext Editor für dieses Dialogfenster. Ergänzen Sie bitte folgenden
Quellcode:
Private Sub CommandButton1_Click()
Dim x As Integer
Dim i As Integer
Dim k As Integer
Dim m As Integer
m = 0
x = 1
i = UserForm1.TextBox1.Value
k = UserForm1.TextBox2.Value + 1
If -(i) + k > 21 Then m = 99
If i > k Then m = 99
If m > 0 Then
MsgBox ("Werte ungültig")
Else
Workbooks("Mappe1").Worksheets("Tabelle1").Select
Do While i < k
Cells(x, 1).Select
ActiveCell.Value = i
Cells(x, 2).Select
ActiveCell.Value = i * i
x = x + 1
i = i + 1
Loop
End If
End Sub
89
Erstellen Sie bitte unter Einfügen/Modul ein Modul und fügen Sie folgenden
Quelltext dort ein:
Sub parabel()
UserForm1.Show
End Sub
Damit wird das Dialogfenster aktiviert, wenn Sie diese Sub unter Extras/Makro
aufrufen. Nun können Sie mit dem Dialog arbeiten.
Geben Sie bitte zuerst die Werte –10 und 10 ein. Damit legen Sie für das
Diagramm die maximale Anzahl der darzustellenden Werte fest. Erstellen Sie
nun das Diagramm (XY - Darstellung). Löschen Sie die Wertetabelle. Wenn Sie
nun die Sub unter Extras/Makro erneut aufrufen und andere Werte eingeben
werden Sie feststellen, dass sich der Funktionsgraph entsprechend ändert.
Aufgabe 36:
Modifizieren Sie bitte die vorliegende Lösung im Sinne der Trennung von GUI
und Fachkonzept!
Aufgabe 37:
„Verschönern“ Sie bitte die Darstellung (Überschriften usw.). Programmieren
Sie bitte das automatische Löschen der alten Funktionswerte, bevor die neuen
ausgegeben werden!
Aufgabe 38:
Entwickeln Sie bitte ähnliche Programme für andere Funktionen und Funktionsgraphen. Suchen Sie bitte aus den früheren Aufgaben dieser Unterlagen geeignete Aufgaben für die Programmierung mit Dialogfenstern heraus.
90
Herunterladen