Einstieg in VBA mit Excel: Für Excel 2016 bis 2021 und Microsoft 365 9783836290616

Sie möchten Berechnungen automatisieren, eigene Dialogfelder erstellen und ganz einfach Excel in jeder Hinsicht an Ihre

116 54 11MB

German Pages 463 [961] Year 2022

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Einstieg in VBA mit Excel: Für Excel 2016 bis 2021 und Microsoft 365
 9783836290616

Table of contents :
Aus dem Lektorat
Inhaltsverzeichnis
Materialien zum Buch
Geleitwort des Fachgutachters
1 Einführung
1.1 Was wird besser durch Makros und VBA?
1.2 Mit Makros arbeiten
1.2.1 Makro aufzeichnen
1.2.2 Makro ausführen
1.2.3 Makro ansehen
1.2.4 Makro speichern
1.2.5 Makrosicherheit ändern
1.2.6 Registerkarte »Entwicklertools«
1.2.7 Makrosicherheit dauerhaft ändern
1.3 Visual Basic Editor
1.3.1 Menüleiste und Symbolleiste
1.3.2 Projekt-Explorer und Fenster »Eigenschaften«
1.3.3 Codefenster
1.4 Makrocode verstehen und ändern
1.5 Makro per Schaltfläche ausführen
1.6 Relative Verweise verwenden
1.7 Persönliche Makroarbeitsmappe
1.8 Code schreiben für einfache Ausgaben
1.8.1 Eigene Sub-Prozedur
1.8.2 Ausgabe in Zelle
1.8.3 Ausgabe in Nachrichtenbox
1.8.4 Ausgabe im Direktfenster des VBE
1.9 Microsoft 365
1.10 Web-Apps
2 Grundlagen von Objekten und Ereignissen
2.1 Objekthierarchie und Auflistungen
2.2 Arbeitsmappen bearbeiten
2.2.1 Anzahl der Arbeitsmappen ermitteln
2.2.2 Neue Arbeitsmappe erzeugen
2.2.3 Vorhandene Arbeitsmappe öffnen
2.2.4 Alle Arbeitsmappen schließen
2.2.5 Name einer Arbeitsmappe ermitteln
2.2.6 Aktive Arbeitsmappe ermitteln
2.2.7 Arbeitsmappe aktivieren
2.2.8 Arbeitsmappe speichern
2.2.9 Arbeitsmappe über Index oder Namen auswählen
2.2.10 Pfad einer Arbeitsmappe ermitteln
2.3 Tabellenblätter bearbeiten
2.3.1 Tabellenblatt erzeugen
2.3.2 Tabellenblatt kopieren
2.3.3 Tabellenblatt verschieben
2.3.4 Tabellenblatt löschen
2.3.5 Tabellenblatt aktivieren
2.3.6 Tabellenblatt formatieren
2.3.7 Gitternetz, Zeilen- und Spaltenüberschriften
2.3.8 Seite einrichten
2.4 Auf Zellen und Zellbereiche zugreifen
2.4.1 Zellen über das »Range«-Objekt auswählen
2.4.2 Zellen über das »Cells«-Objekt auswählen
2.4.3 Zellinhalte verschieben oder kopieren
2.4.4 Teile von Zellinhalten kopieren
2.4.5 Zellinhalte löschen
2.4.6 Werte und Formeln eintragen
2.4.7 Zahlenformate anwenden
2.4.8 Zellen ausrichten
2.4.9 Schrifteigenschaften bestimmen
2.4.10 Einzelne Zeichen formatieren
2.4.11 Zellbereiche einrahmen
2.4.12 Hintergrundmuster von Zellen gestalten
2.4.13 Zellen einfügen
2.4.14 Zellen löschen
2.4.15 Zeilenhöhe und Spaltenbreite
2.4.16 Benutzten Zellbereich erkennen
2.4.17 Spezielle Zellen erkennen
2.4.18 Versatz mit Offset vornehmen
2.4.19 Zellbereich sortieren
2.4.20 Mehr als drei Sortierschlüssel
2.5 Ereignisprozeduren schreiben
2.5.1 Arbeitsmappe wird geöffnet
2.5.2 Arbeitsmappe wird geschlossen
2.5.3 Tabellenblatt wird aktiviert
2.5.4 Zellbereich wird ausgewählt
2.5.5 Zelle wird doppelt angeklickt
2.5.6 Tabellenblatt wird neu berechnet
3 Grundlagen der Programmierung mit VBA
3.1 Allgemeines
3.1.1 Codeblöcke auskommentieren
3.1.2 Zeilen zerlegen
3.2 Variablen und Datentypen
3.2.1 Namen, Werte
3.2.2 Deklarationen
3.2.3 Datentypen
3.2.4 Funktion »TypeName()«
3.2.5 Konstanten
3.2.6 Enumerationen
3.3 Operatoren
3.3.1 Arithmetische Operatoren
3.3.2 Vergleichsoperatoren
3.3.3 Logische Operatoren
3.3.4 Verkettungsoperator
3.3.5 Rangfolge der Operatoren
3.4 Verzweigungen
3.4.1 Einzeiliges »If … Then … Else«
3.4.2 If-Then-Else-Block
3.4.3 Select Case
3.5 Schleifen
3.5.1 Schleife mit »For … Next«
3.5.2 Schleife mit »Do … Loop«
4 Fehlerbehandlung
4.1 Eine Anwendung entwickeln
4.2 Syntaxfehler
4.3 Laufzeitfehler
4.3.1 Programm mit Laufzeitfehlern
4.3.2 Laufzeitfehler abfangen: »On Error«
4.4 Logische Fehler und Debugging
4.4.1 Einzelschrittverfahren
4.4.2 Haltepunkte
5 Mehr über die Programmierung mit VBA
5.1 Gültigkeitsbereiche
5.2 Datenfelder
5.2.1 Eindimensionale Datenfelder
5.2.2 Datenfeld sortieren
5.2.3 Mehrdimensionale Datenfelder
5.2.4 Dynamische Datenfelder
5.2.5 VBA-Funktion »Array()«
5.2.6 Datenfelder löschen oder freigeben
5.3 Prozeduren und Funktionen
5.3.1 Prozeduren
5.3.2 Parameter übergeben
5.3.3 Funktionen
5.3.4 Beispiel »Der letzte Tag im Monat«
5.3.5 Optionale Parameter
5.3.6 Benannte Parameter
5.3.7 Beliebig viele Parameter
5.3.8 Datenfelder als Parameter
5.3.9 Rekursive Prozeduren und Funktionen
5.4 Benutzerdefinierter Datentyp
5.5 Modular programmieren
5.5.1 Code in der gleichen Datei
5.5.2 Code in einer anderen Datei
5.6 Module exportieren und importieren
5.6.1 Ein Modul exportieren
5.6.2 Ein Modul importieren
6 Mehr über Objekte
6.1 Objektkatalog
6.2 Objekte referenzieren
6.2.1 Beispiel »Zellen verschieben«
6.3 Mit »With« auf Objekte zugreifen
6.4 Mit Objektvariablen arbeiten
6.4.1 Objektvariablen hierarchisch zuweisen
6.4.2 Neue Objekte erzeugen
6.4.3 Objekttyp ermitteln
6.5 For-Each-Schleife
6.6 Collections
6.7 Hauptobjekt »Application«
6.7.1 Anwendungspfad ausgeben
6.7.2 Prozedur zeitverzögert aufrufen
6.7.3 Excel-Anwendung schließen
6.8 Filtern
7 Diagramme und Grafiken
7.1 Diagramm erstellen
7.1.1 Diagrammblatt erstellen
7.1.2 Eingebettetes Diagramm erstellen
7.2 Diagramm ändern
7.2.1 Diagrammblatt ändern
7.2.2 Eingebettetes Diagramm ändern
7.3 Diagramm verwalten
7.3.1 Diagrammblatt verwalten
7.3.2 Eingebettetes Diagramm verwalten
7.4 Beispiel: Formatiertes Kreisdiagramm
7.5 Shapes
7.5.1 Rechteck
7.5.2 Oval
7.5.3 Linie
7.5.4 Verbinder
7.5.5 Geschlossene Freiform
7.5.6 Offene Freiform
7.5.7 Alle Formen
7.6 WordArt
7.7 Bedingte Formatierungen
7.7.1 Datenbalken
7.7.2 Zweifarbige Farbskala
7.7.3 Dreifarbige Farbskala
7.7.4 Symbolsatz
7.8 Sparklines
7.8.1 Linie
7.8.2 Spalte
7.8.3 Gewinn/Verlust
7.8.4 Formatierung
7.8.5 Alle Farben
7.9 SmartArt
7.10 Grafiken aus Bilddateien
7.10.1 Grafik einfügen
7.10.2 Grafik abschneiden
8 VBA- und Worksheet-Funktionen
8.1 Formeln zuweisen und lesen
8.1.1 Formeln zuweisen
8.1.2 Formeln lesen
8.2 Benutzereingaben
8.2.1 Funktion »InputBox()«
8.2.2 Methode »Application.InputBox()«
8.3 Einfacher Dialog mit dem Benutzer
8.3.1 Schaltfläche »OK«
8.3.2 Schaltflächen – eine Übersicht
8.3.3 Zeichen »Information«
8.3.4 Systemmodal
8.3.5 Schaltflächen »Ja« und »Nein«
8.3.6 Drei Schaltflächen einschließlich Default-Schaltfläche
8.3.7 Schaltflächen »Wiederholen« und »Abbrechen«
8.3.8 Schaltflächen »Abbrechen«, »Wiederholen« und »Ignorieren«
8.4 Zeichenketten
8.4.1 Zeichenketten umwandeln
8.4.2 Ausgabeformatierung
8.4.3 Datensätze zusammenfügen
8.4.4 Datensätze zerlegen
8.5 Datum und Uhrzeit
8.5.1 Rechnen mit Zeitangaben
8.5.2 Datumsangaben erstellen und Wochentage markieren
8.5.3 Jahreskalender
8.5.4 ISO-Kalenderwoche berechnen
8.5.5 Arbeitstage berechnen
8.6 Weitere Funktionen
8.6.1 Anwendung unterbrechen
8.6.2 Einheiten umrechnen
8.6.3 Zwischen Zahlensystemen umrechnen
8.6.4 Zellen zählen
8.6.5 Größte und kleinste Werte finden
8.6.6 Zahlen runden
8.6.7 Römische und arabische Zahlen umwandeln
9 Externe Daten
9.1 Ein Überblick
9.2 Einfache Textdateien
9.2.1 Einfache Textdateien schreiben
9.2.2 Einfache Textdateien lesen
9.3 CSV-Dateien
9.3.1 CSV-Dateien schreiben
9.3.2 CSV-Dateien lesen
9.4 Dateien mit wahlfreiem Zugriff
9.4.1 Benutzerdefinierten Datentyp erstellen
9.4.2 Datei mit allen Datensätzen erstellen
9.4.3 An beliebiger Stelle lesen
9.4.4 An beliebiger Stelle schreiben
9.5 Mit Dateien arbeiten
9.5.1 Dateien suchen und auflisten
9.5.2 Informationen über Dateien ermitteln
9.5.3 Operationen mit Dateien durchführen
9.5.4 Operationen mit Verzeichnissen ausführen
9.6 Daten mit MS Word austauschen
9.6.1 Objektmodell von Word
9.6.2 Word-Absätze schreiben
9.6.3 Word-Absätze lesen
9.6.4 Word-Tabelle schreiben
9.6.5 Word-Tabelle lesen
9.6.6 Internetseite lesen
9.7 Daten mit MS Outlook austauschen
9.7.1 Objektmodell von Outlook
9.7.2 Eine Arbeitsmappe als Anlage versenden
9.7.3 Integriertes E-Mail-Dialogfeld nutzen
9.7.4 Eine E-Mail zusammensetzen
9.7.5 Eine Serien-E-Mail erstellen
9.7.6 Bestimmten Zellbereich in E-Mail versenden
9.7.7 Auf Outlook-Verzeichnis zugreifen
9.7.8 Auf E-Mail-Anhänge zugreifen
9.7.9 Kontakt erzeugen
9.7.10 Auf Kontakte zugreifen
9.7.11 Termin erzeugen
9.7.12 Terminserie erzeugen
9.7.13 Auf Termine und Terminserien zugreifen
9.8 Daten mit MS Access austauschen
9.8.1 Beispieldatenbank: Aufbau
9.8.2 Beispieldatenbank: Verbindung herstellen
9.8.3 SQL-Befehle
9.8.4 Auswahlabfrage
9.8.5 Beispieldatenbank: Aktionsabfrage
9.8.6 Auswahl von Feldern und Datensätzen
9.8.7 Operatoren
9.8.8 Ergebnis sortieren
9.8.9 Ergebnis nach Eingabe
9.8.10 Ändern mit »UPDATE«
9.8.11 Einfügen mit »INSERT«
9.8.12 Löschen mit »DELETE«
9.9 Export in PDF-Dateien
9.9.1 Export einer Word-Datei
9.9.2 Export von Word-Dateien in einem Verzeichnis
9.9.3 Export einer Excel-Datei
9.9.4 Export von Excel-Dateien in einem Verzeichnis
9.9.5 Export von Dateien in einer Hierarchie
10 Dialogfelder
10.1 Integrierte Dialogfelder
10.1.1 Datei öffnen
10.1.2 Datei speichern unter
10.1.3 Hintergrundmuster für Zellbereich auswählen
10.1.4 Schriftformatierung für Zellbereich auswählen
10.2 Eigene Dialogfelder
10.2.1 Gestaltung des Dialogfelds
10.2.2 Code des Dialogfelds
10.2.3 Aufruf des Dialogfelds
10.2.4 Dialogfelder exportieren und importieren
10.3 Mit Steuerelementen arbeiten
10.3.1 Textfeld und Beschriftungsfeld
10.3.2 Optionsfeld und Kontrollkästchen
10.3.3 Liste, Bildlaufleiste und Drehfeld
10.3.4 Ausgabeformatierung
10.3.5 RefEdit und Umschaltfeld
11 Funktionen aus Excel 2021
11.1 Gleichmäßige Abfolge von Werten
11.2 Bereich mit zufälligen Werten
11.3 Alle unterschiedlichen Werte
11.4 Zellbereich filtern
11.5 Zellbereich sortieren
12 Beispielprojekte
12.1 Memory
12.1.1 Spielablauf
12.1.2 Aufbau des Spielfelds
12.1.3 Spiel starten
12.1.4 Spiel bedienen
12.2 Snake
12.2.1 Spielablauf
12.2.2 Aufbau des Spielfelds
12.2.3 Spiel starten
12.2.4 Spiel bedienen
12.3 Vokabeln
12.3.1 Programmablauf
12.3.2 Aufbau der Vokabelsammlung
12.3.3 Spiel starten
12.4 Puzzle
12.4.1 Ablauf des Puzzle-Spiels
12.4.2 Alle Bilder löschen
12.4.3 Schaltflächen für die Benutzer
12.4.4 Modulweite Variablen
12.4.5 Puzzle anzeigen und mischen
12.4.6 Benutzerin wählt ein Puzzle-Teil aus
12.4.7 Zwei Puzzle-Teile werden getauscht
12.4.8 Prüfen der Positionen
12.4.9 Zum nächsten Spiel
A Lösungen der Übungsaufgaben
Stichwortverzeichnis
Rechtliche Hinweise
Über den Autor

Citation preview

Thomas Theis

Einstieg in VBA mit Excel Für Excel 2016 bis 2021 und Microsoft 365 6., aktualisierte Auflage 2022, 1. Nachdruck 2023

Impressum Dieses E-Book ist ein Verlagsprodukt, an dem viele mitgewirkt haben, insbesondere: Lektorat   Anne Scheibe, Patricia Zündorf

Fachgutachten   Alois Eckl

Korrektorat   Petra Biedermann, Reken

Covergestaltung   Mai Loan Nguyen Duy

Herstellung E-Book   Norbert Englert

Satz E-Book   SatzPro, Krefeld

Bibliografische Information der Deutschen Nationalbibliothek:

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.dnb.de abrufbar. ISBN 978-3-8362-9061-6 6., aktualisierte Auflage 2022, 1. Nachdruck 2023

© Rheinwerk Verlag GmbH, Bonn 2022

Liebe Leserin, lieber Leser, Microsoft Excel bietet Ihnen viele fertige Funktionen für die tägliche Arbeit an, und dennoch stoßen Sie damit oft an Grenzen: Nicht jede gewünschte Funktion ist vorhanden und manche Arbeitsabläufe könnten deutlich schneller gehen. Und genau das können Sie mit Visual Basic for Applications, kurz VBA genannt, erreichen. Vielleicht haben Sie bislang den Aufwand gescheut, sich mit VBA auseinanderzusetzen. Wenn das so ist, liegen Sie mit diesem Buch goldrichtig. Es wurde für alle diejenigen geschrieben, die sich schnell in VBA einarbeiten wollen und bislang keine Erfahrung im Programmieren haben. Schritt für Schritt zeigt Ihnen unser Autor Thomas Theis, wie Sie eigene VBA-Skripte entwickeln. Die Theorie ist dabei auf das absolut Notwendige reduziert – im Zentrum stehen die vielen Praxisbeispiele, an denen Sie den Stoff leicht nachvollziehen können. Ihre neu gewonnenen Kenntnisse können Sie an Übungsaufgaben austesten, bevor Sie an Ihre eigenen Dateien gehen. Schon bald sind Sie in der Lage, Excel ganz an Ihre Bedürfnisse anzupassen. Dieses Buch wurde mit großer Sorgfalt geschrieben, geprüft und produziert. Sollte dennoch einmal etwas nicht so funktionieren, wie Sie es erwarten, freue ich mich, wenn Sie sich mit mir in Verbindung setzen. Ihre Kritik und konstruktiven Anregungen sind uns jederzeit herzlich willkommen!

Doch nun viel Spaß bei der Lektüre und viel Erfolg mit VBA wünscht Ihnen Ihre Anne Scheibe

Lektorat Rheinwerk Computing [email protected]

www.rheinwerk-verlag.de

Rheinwerk Verlag • Rheinwerkallee 4 • 53227 Bonn

Inhaltsverzeichnis Aus dem Lektorat Inhaltsverzeichnis

Materialien zum Buch Geleitwort des Fachgutachters

1   Einführung 1.1   Was wird besser durch Makros und VBA? 1.2   Mit Makros arbeiten 1.2.1   Makro aufzeichnen 1.2.2   Makro ausführen 1.2.3   Makro ansehen 1.2.4   Makro speichern 1.2.5   Makrosicherheit ändern 1.2.6   Registerkarte »Entwicklertools« 1.2.7   Makrosicherheit dauerhaft ändern

1.3   Visual Basic Editor 1.3.1   Menüleiste und Symbolleiste 1.3.2   Projekt-Explorer und Fenster »Eigenschaften«

1.3.3   Codefenster

1.4   Makrocode verstehen und ändern 1.5   Makro per Schaltfläche ausführen 1.6   Relative Verweise verwenden 1.7   Persönliche Makroarbeitsmappe 1.8   Code schreiben für einfache Ausgaben 1.8.1   Eigene Sub-Prozedur 1.8.2   Ausgabe in Zelle 1.8.3   Ausgabe in Nachrichtenbox 1.8.4   Ausgabe im Direktfenster des VBE

1.9   Microsoft 365 1.10   Web-Apps

2   Grundlagen von Objekten und Ereignissen 2.1   Objekthierarchie und Auflistungen 2.2   Arbeitsmappen bearbeiten 2.2.1   Anzahl der Arbeitsmappen ermitteln 2.2.2   Neue Arbeitsmappe erzeugen 2.2.3   Vorhandene Arbeitsmappe öffnen 2.2.4   Alle Arbeitsmappen schließen 2.2.5   Name einer Arbeitsmappe ermitteln 2.2.6   Aktive Arbeitsmappe ermitteln 2.2.7   Arbeitsmappe aktivieren

2.2.8   Arbeitsmappe speichern 2.2.9   Arbeitsmappe über Index oder Namen auswählen 2.2.10   Pfad einer Arbeitsmappe ermitteln

2.3   Tabellenblätter bearbeiten 2.3.1   Tabellenblatt erzeugen 2.3.2   Tabellenblatt kopieren 2.3.3   Tabellenblatt verschieben 2.3.4   Tabellenblatt löschen 2.3.5   Tabellenblatt aktivieren 2.3.6   Tabellenblatt formatieren 2.3.7   Gitternetz, Zeilen- und Spaltenüberschriften 2.3.8   Seite einrichten

2.4   Auf Zellen und Zellbereiche zugreifen 2.4.1   Zellen über das »Range«-Objekt auswählen 2.4.2   Zellen über das »Cells«-Objekt auswählen 2.4.3   Zellinhalte verschieben oder kopieren 2.4.4   Teile von Zellinhalten kopieren 2.4.5   Zellinhalte löschen 2.4.6   Werte und Formeln eintragen 2.4.7   Zahlenformate anwenden 2.4.8   Zellen ausrichten 2.4.9   Schrifteigenschaften bestimmen 2.4.10   Einzelne Zeichen formatieren 2.4.11   Zellbereiche einrahmen 2.4.12   Hintergrundmuster von Zellen gestalten 2.4.13   Zellen einfügen 2.4.14   Zellen löschen 2.4.15   Zeilenhöhe und Spaltenbreite

2.4.16   Benutzten Zellbereich erkennen 2.4.17   Spezielle Zellen erkennen 2.4.18   Versatz mit Offset vornehmen 2.4.19   Zellbereich sortieren 2.4.20   Mehr als drei Sortierschlüssel

2.5   Ereignisprozeduren schreiben 2.5.1   Arbeitsmappe wird geöffnet 2.5.2   Arbeitsmappe wird geschlossen 2.5.3   Tabellenblatt wird aktiviert 2.5.4   Zellbereich wird ausgewählt 2.5.5   Zelle wird doppelt angeklickt 2.5.6   Tabellenblatt wird neu berechnet

3   Grundlagen der Programmierung mit VBA 3.1   Allgemeines 3.1.1   Codeblöcke auskommentieren 3.1.2   Zeilen zerlegen

3.2   Variablen und Datentypen 3.2.1   Namen, Werte 3.2.2   Deklarationen 3.2.3   Datentypen 3.2.4   Funktion »TypeName()« 3.2.5   Konstanten 3.2.6   Enumerationen

3.3   Operatoren 3.3.1   Arithmetische Operatoren 3.3.2   Vergleichsoperatoren 3.3.3   Logische Operatoren 3.3.4   Verkettungsoperator 3.3.5   Rangfolge der Operatoren

3.4   Verzweigungen 3.4.1   Einzeiliges »If … Then … Else« 3.4.2   If-Then-Else-Block 3.4.3   Select Case

3.5   Schleifen 3.5.1   Schleife mit »For … Next« 3.5.2   Schleife mit »Do … Loop«

4   Fehlerbehandlung 4.1   Eine Anwendung entwickeln 4.2   Syntaxfehler 4.3   Laufzeitfehler 4.3.1   Programm mit Laufzeitfehlern 4.3.2   Laufzeitfehler abfangen: »On Error«

4.4   Logische Fehler und Debugging 4.4.1   Einzelschrittverfahren 4.4.2   Haltepunkte

5   Mehr über die Programmierung mit VBA 5.1   Gültigkeitsbereiche 5.2   Datenfelder 5.2.1   Eindimensionale Datenfelder 5.2.2   Datenfeld sortieren 5.2.3   Mehrdimensionale Datenfelder 5.2.4   Dynamische Datenfelder 5.2.5   VBA-Funktion »Array()« 5.2.6   Datenfelder löschen oder freigeben

5.3   Prozeduren und Funktionen 5.3.1   Prozeduren 5.3.2   Parameter übergeben 5.3.3   Funktionen 5.3.4   Beispiel »Der letzte Tag im Monat« 5.3.5   Optionale Parameter 5.3.6   Benannte Parameter 5.3.7   Beliebig viele Parameter 5.3.8   Datenfelder als Parameter 5.3.9   Rekursive Prozeduren und Funktionen

5.4   Benutzerdefinierter Datentyp 5.5   Modular programmieren 5.5.1   Code in der gleichen Datei 5.5.2   Code in einer anderen Datei

5.6   Module exportieren und importieren 5.6.1   Ein Modul exportieren 5.6.2   Ein Modul importieren

6   Mehr über Objekte 6.1   Objektkatalog 6.2   Objekte referenzieren 6.2.1   Beispiel »Zellen verschieben«

6.3   Mit »With« auf Objekte zugreifen 6.4   Mit Objektvariablen arbeiten 6.4.1   Objektvariablen hierarchisch zuweisen 6.4.2   Neue Objekte erzeugen 6.4.3   Objekttyp ermitteln

6.5   For-Each-Schleife 6.6   Collections 6.7   Hauptobjekt »Application« 6.7.1   Anwendungspfad ausgeben 6.7.2   Prozedur zeitverzögert aufrufen 6.7.3   Excel-Anwendung schließen

6.8   Filtern

7   Diagramme und Grafiken

7.1   Diagramm erstellen 7.1.1   Diagrammblatt erstellen 7.1.2   Eingebettetes Diagramm erstellen

7.2   Diagramm ändern 7.2.1   Diagrammblatt ändern 7.2.2   Eingebettetes Diagramm ändern

7.3   Diagramm verwalten 7.3.1   Diagrammblatt verwalten 7.3.2   Eingebettetes Diagramm verwalten

7.4   Beispiel: Formatiertes Kreisdiagramm 7.5   Shapes 7.5.1   Rechteck 7.5.2   Oval 7.5.3   Linie 7.5.4   Verbinder 7.5.5   Geschlossene Freiform 7.5.6   Offene Freiform 7.5.7   Alle Formen

7.6   WordArt 7.7   Bedingte Formatierungen 7.7.1   Datenbalken 7.7.2   Zweifarbige Farbskala 7.7.3   Dreifarbige Farbskala 7.7.4   Symbolsatz

7.8   Sparklines 7.8.1   Linie 7.8.2   Spalte

7.8.3   Gewinn/Verlust 7.8.4   Formatierung 7.8.5   Alle Farben

7.9   SmartArt 7.10   Grafiken aus Bilddateien 7.10.1   Grafik einfügen 7.10.2   Grafik abschneiden

8   VBA- und WorksheetFunktionen 8.1   Formeln zuweisen und lesen 8.1.1   Formeln zuweisen 8.1.2   Formeln lesen

8.2   Benutzereingaben 8.2.1   Funktion »InputBox()« 8.2.2   Methode »Application.InputBox()«

8.3   Einfacher Dialog mit dem Benutzer 8.3.1   Schaltfläche »OK« 8.3.2   Schaltflächen – eine Übersicht 8.3.3   Zeichen »Information« 8.3.4   Systemmodal 8.3.5   Schaltflächen »Ja« und »Nein« 8.3.6   Drei Schaltflächen einschließlich DefaultSchaltfläche

8.3.7   Schaltflächen »Wiederholen« und »Abbrechen« 8.3.8   Schaltflächen »Abbrechen«, »Wiederholen« und »Ignorieren«

8.4   Zeichenketten 8.4.1   Zeichenketten umwandeln 8.4.2   Ausgabeformatierung 8.4.3   Datensätze zusammenfügen 8.4.4   Datensätze zerlegen

8.5   Datum und Uhrzeit 8.5.1   Rechnen mit Zeitangaben 8.5.2   Datumsangaben erstellen und Wochentage markieren 8.5.3   Jahreskalender 8.5.4   ISO-Kalenderwoche berechnen 8.5.5   Arbeitstage berechnen

8.6   Weitere Funktionen 8.6.1   Anwendung unterbrechen 8.6.2   Einheiten umrechnen 8.6.3   Zwischen Zahlensystemen umrechnen 8.6.4   Zellen zählen 8.6.5   Größte und kleinste Werte finden 8.6.6   Zahlen runden 8.6.7   Römische und arabische Zahlen umwandeln

9   Externe Daten

9.1   Ein Überblick 9.2   Einfache Textdateien 9.2.1   Einfache Textdateien schreiben 9.2.2   Einfache Textdateien lesen

9.3   CSV-Dateien 9.3.1   CSV-Dateien schreiben 9.3.2   CSV-Dateien lesen

9.4   Dateien mit wahlfreiem Zugriff 9.4.1   Benutzerdefinierten Datentyp erstellen 9.4.2   Datei mit allen Datensätzen erstellen 9.4.3   An beliebiger Stelle lesen 9.4.4   An beliebiger Stelle schreiben

9.5   Mit Dateien arbeiten 9.5.1   Dateien suchen und auflisten 9.5.2   Informationen über Dateien ermitteln 9.5.3   Operationen mit Dateien durchführen 9.5.4   Operationen mit Verzeichnissen ausführen

9.6   Daten mit MS Word austauschen 9.6.1   Objektmodell von Word 9.6.2   Word-Absätze schreiben 9.6.3   Word-Absätze lesen 9.6.4   Word-Tabelle schreiben 9.6.5   Word-Tabelle lesen 9.6.6   Internetseite lesen

9.7   Daten mit MS Outlook austauschen 9.7.1   Objektmodell von Outlook 9.7.2   Eine Arbeitsmappe als Anlage versenden

9.7.3   Integriertes E-Mail-Dialogfeld nutzen 9.7.4   Eine E-Mail zusammensetzen 9.7.5   Eine Serien-E-Mail erstellen 9.7.6   Bestimmten Zellbereich in E-Mail versenden 9.7.7   Auf Outlook-Verzeichnis zugreifen 9.7.8   Auf E-Mail-Anhänge zugreifen 9.7.9   Kontakt erzeugen 9.7.10   Auf Kontakte zugreifen 9.7.11   Termin erzeugen 9.7.12   Terminserie erzeugen 9.7.13   Auf Termine und Terminserien zugreifen

9.8   Daten mit MS Access austauschen 9.8.1   Beispieldatenbank: Aufbau 9.8.2   Beispieldatenbank: Verbindung herstellen 9.8.3   SQL-Befehle 9.8.4   Auswahlabfrage 9.8.5   Beispieldatenbank: Aktionsabfrage 9.8.6   Auswahl von Feldern und Datensätzen 9.8.7   Operatoren 9.8.8   Ergebnis sortieren 9.8.9   Ergebnis nach Eingabe 9.8.10   Ändern mit »UPDATE« 9.8.11   Einfügen mit »INSERT« 9.8.12   Löschen mit »DELETE«

9.9   Export in PDF-Dateien 9.9.1   Export einer Word-Datei 9.9.2   Export von Word-Dateien in einem Verzeichnis 9.9.3   Export einer Excel-Datei

9.9.4   Export von Excel-Dateien in einem Verzeichnis 9.9.5   Export von Dateien in einer Hierarchie

10   Dialogfelder 10.1   Integrierte Dialogfelder 10.1.1   Datei öffnen 10.1.2   Datei speichern unter 10.1.3   Hintergrundmuster für Zellbereich auswählen 10.1.4   Schriftformatierung für Zellbereich auswählen

10.2   Eigene Dialogfelder 10.2.1   Gestaltung des Dialogfelds 10.2.2   Code des Dialogfelds 10.2.3   Aufruf des Dialogfelds 10.2.4   Dialogfelder exportieren und importieren

10.3   Mit Steuerelementen arbeiten 10.3.1   Textfeld und Beschriftungsfeld 10.3.2   Optionsfeld und Kontrollkästchen 10.3.3   Liste, Bildlaufleiste und Drehfeld 10.3.4   Ausgabeformatierung 10.3.5   RefEdit und Umschaltfeld

11   Funktionen aus Excel 2021 11.1   Gleichmäßige Abfolge von Werten

11.2   Bereich mit zufälligen Werten 11.3   Alle unterschiedlichen Werte 11.4   Zellbereich filtern 11.5   Zellbereich sortieren

12   Beispielprojekte 12.1   Memory 12.1.1   Spielablauf 12.1.2   Aufbau des Spielfelds 12.1.3   Spiel starten 12.1.4   Spiel bedienen

12.2   Snake 12.2.1   Spielablauf 12.2.2   Aufbau des Spielfelds 12.2.3   Spiel starten 12.2.4   Spiel bedienen

12.3   Vokabeln 12.3.1   Programmablauf 12.3.2   Aufbau der Vokabelsammlung 12.3.3   Spiel starten

12.4   Puzzle 12.4.1   Ablauf des Puzzle-Spiels 12.4.2   Alle Bilder löschen 12.4.3   Schaltflächen für die Benutzer 12.4.4   Modulweite Variablen

12.4.5   Puzzle anzeigen und mischen 12.4.6   Benutzerin wählt ein Puzzle-Teil aus 12.4.7   Zwei Puzzle-Teile werden getauscht 12.4.8   Prüfen der Positionen 12.4.9   Zum nächsten Spiel

A   Lösungen der Übungsaufgaben Stichwortverzeichnis Rechtliche Hinweise Über den Autor

Materialien zum Buch Auf der Webseite zu diesem Buch stehen folgende Materialien für Sie zum Download bereit: alle Beispielprogramme Lösungen der Übungsaufgaben Gehen Sie auf www.rheinwerk-verlag.de/5546. Klicken Sie auf den Reiter Materialien. Sie sehen die herunterladbaren Dateien samt einer Kurzbeschreibung des Dateiinhalts. Klicken Sie auf den Button Herunterladen, um den Download zu starten. Je nach Größe der Datei (und Geschwindigkeit Ihrer Internetverbindung) kann es einige Zeit dauern, bis der Download abgeschlossen ist.

Geleitwort des Fachgutachters Seit der Version 95, die im August 1995 erschien, bietet Microsoft Excel-Anwendern die Möglichkeit, in VBA (Visual Basic for Applications) zu programmieren und das Programm auf diese Weise ihren Bedürfnissen anzupassen. Um die ersten wichtigen Schritte beruhigt gehen zu können, ist eine gute Wegbegleitung unverzichtbar. Die VBA-gestützte Steuerung und Erweiterung gewährleistet größtmögliche Flexibilität und optimale Anpassungsfähigkeit. Durch die Verwendung von Visual Basic for Applications neben den bereits in Excel integrierten Funktionen erschließen sich völlig neue Anwendungsbereiche und Möglichkeiten. Excel-Tabellen lassen sich dynamisieren und automatisieren, eigene Funktionen können erstellt werden und stehen damit uneingeschränkt zur Verfügung. Die Liste der Möglichkeiten könnte an dieser Stelle beliebig weitergeführt werden. Zum Einstieg in VBA bietet Excel den sogenannten Makrorekorder, mit dessen Hilfe sich schnell und fast ohne jegliche Programmierkenntnisse schon respektable Ergebnisse erzielen lassen. Wenn es allerdings darum geht, eigene benutzerdefinierte Eingabemöglichkeiten wie die einfache Abfrage eines Wertes oder gar eigene Dialogfenster mit mehreren Eingabe- und Auswahlmöglichkeiten zu erstellen, dann kommen Sie ohne VBA und entsprechend tiefgreifende Programmierkenntnisse nicht weiter. Wichtig in diesem Zusammenhang ist ein umfangreiches

Wissen über das Objektmodell von Excel und über grundlegende Programmierlogiken wie beispielsweise If-Abfragen, Programmverzweigungen und Schleifen. Darüber hinaus muss der VBA-Programmierer überblicken, welchen Befehlssatz Microsoft Office und insbesondere Microsoft Excel zur Verfügung stellt und wie dieser angesprochen werden kann. Genau hier setzt nun das vorliegende Buch von Thomas Theis an, indem es ganz speziell auf die Bedürfnisse von VBA-Einsteigern eingeht. Es führt Sie Schritt für Schritt an die VBA-Programmierung heran. Beginnend mit grundlegenden Themen wie dem Umgang mit dem VBA-Editor bis hin zur Programmierung von eigenen Dialogfenstern werden die Möglichkeiten von VBA sehr klar und übersichtlich dargestellt. In diesem Buch ist der schwierige Spagat zwischen verständlicher Schreibweise, klarer Themenstruktur und detaillierter Erläuterung sehr gut gelungen. Darüber hinaus wird Gelerntes in Übungsaufgaben vertieft und damit gefestigt. Aber auch fortgeschrittene Anwender und VBA-Entwicklerinnen können von diesem Werk profitieren. Durch den konsequent objektorientierten Aufbau des Buches lässt sich dieses auch sehr gut als Praxis-Nachschlagewerk verwenden. An diesem Buch gefällt mir besonders gut, dass sich mithilfe der beschriebenen Programmierbeispiele die Theorie schnell und verständlich in die Praxis umsetzen lässt. Neben der verständlichen Darstellung von theoretischen Zusammenhängen geht Thomas Theis den Weg, anhand von einzelnen kleineren Praxisbeispielen alle relevanten VBA-Befehle zu erklären und deren Funktionsweise zu erläutern. So lernt die Einsteigerin nicht nur Step by Step die Möglichkeiten von VBA kennen, sondern übt sich zugleich darin, sie auch anzuwenden.

Zu guter Letzt bleibt mir nur zu sagen, dass ich dieses Buch als ein rundum gelungenes Werk all denen empfehlen kann, die sich näher mit der Thematik VBA rund um Microsoft Excel auseinandersetzen möchten und schnell und unkompliziert in diese Materie eintauchen wollen.

Alois Eckl

Eckl-IT-Consulting

Controller, Consultant und VBA-Entwickler

1    Einführung In diesem Kapitel lernen Sie erste VBA-Makros kennen. Sie erfahren, wie sie aufgebaut sind und wie Sie sie verändern. Außerdem werde ich die VBA-Entwicklungsumgebung erläutern. Die Abkürzung VBA steht für Visual Basic for Applications. Es handelt sich dabei um die Programmiersprache Visual Basic mit passenden Ergänzungen für die verschiedenen Anwendungen in Microsoft Office. Mit Microsoft Excel werden viele alltägliche Aufgaben im beruflichen und privaten Bereich bereits hervorragend bewältigt. Durch eine zusätzliche Programmierung mit VBA geht das bedeutend schneller. Zudem werden viele Aufgaben erst dank VBA gelöst. Sie erlernen anhand von leicht verständlichen, schrittweise aufgebauten Beispielen, wie Sie VBA als Ergänzung zu Excel sinnvoll einsetzen. Eigene Übungen (mit Lösungen im Anhang) unterstützen Sie bei der Überprüfung Ihres Wissensstands. Für die Hilfe bei der Erstellung dieses Buches bedanke ich mich beim ganzen Team des Rheinwerk Verlags, ganz besonders bei Anne Scheibe.

1.1    Was wird besser durch Makros und VBA? Ein Makro besteht aus einer Reihe von Anweisungen, die nacheinander ausgeführt werden. Durch jede dieser Anweisungen wird in Excel ein bestimmter Vorgang ausgeführt, z. B. eine Zahl in eine Tabellenzelle geschrieben oder die Farbe eines Diagrammbalkens geändert. Die Anweisungen sind in der Sprache VBA geschrieben. VBAProgramme gehen über solch einfache Makros weit hinaus und steuern komplexe Abläufe. In der alltäglichen Arbeit wird Excel von zwei Gruppen genutzt: von Excel-Benutzern, die sich mit einfachen Themen wie z. B. der Dateneingabe und dem Aufruf von Excel-Anwendungen befassen von erfahrenen Excel-Programmiererinnen, die sich mit der Entwicklung von Excel-Anwendungen zur Unterstützung der Excel-Benutzer befassen Die Entwicklung der Excel-Anwendungen kann im selben Unternehmen stattfinden. Es kann sich aber auch um eingekaufte Excel-Anwendungen handeln. Es folgen einige typische Szenarien, die die Nutzung und die Vorteile von VBA zeigen: Es werden große Mengen an Daten aus einer Textdatei eingelesen. Nur der Aufbau der Daten ist bekannt, nicht aber die Menge. Außerdem werden, abhängig vom aktuellen Inhalt der Textdatei, nur bestimmte Daten gelesen. Nach dem Einlesen werden die Daten verarbeitet, formatiert, zusammengefasst und zur Verdeutlichung grafisch dargestellt. Es wird ein Diagramm aus einer Tabelle erstellt. Die jeweilige Größe und der Inhalt der Tabelle bestimmen die Art des

Diagramms und seine Darstellung. Benutzer haben nach dem Aufrufen der Excel-Anwendung ein Dialogfeld vor sich. Darin nehmen sie, abhängig von der jeweiligen Situation, bestimmte Einstellungen vor, treffen die gewünschte Auswahl der Daten und starten dann deren weitere Verarbeitung. In regelmäßigen Zeitabständen ergeben sich Daten, die auf eine ähnliche, aber nicht identische, Art und Weise weiterverarbeitet werden. Die Verarbeitung bestimmter Daten ist komplex und erfolgt in mehreren Schritten. Mit VBA vereinfachen Sie die Koordination und die Durchführung der einzelnen Schritte. Benutzerinnen steht nach dem Aufruf von Excel nur eine bestimmte Funktionalität zur Verfügung. Excel kann durch VBA gleichzeitig: eingeschränkt werden, wodurch weniger Fehler gemacht werden; erweitert werden, wodurch besondere Funktionen und Abläufe zur Verfügung stehen, die über Excel hinausgehen. Zur Bewältigung der laufenden Geschäftsprozesse werden bereits Excel-Anwendungen eingesetzt. Nach einer Änderung der Prozesse werden die Excel-Anwendungen entsprechend angepasst und gegebenenfalls erweitert. In diesem Buch werde ich verschiedene Möglichkeiten zur Problemlösung mit VBA anhand von Beispielen aus der Praxis zeigen. Dabei werden wir mit einer umfangreichen Auswahl aus der Sprache VBA und der zugrundeliegenden Excel-Objektbibliothek

arbeiten. Das ermöglicht Ihnen, selbständig mit Excel und VBA zu arbeiten, ohne den Überblick zu verlieren.

1.2    Mit Makros arbeiten Zu Beginn erstellen wir ein einfaches Makro, das anschließend ausgeführt wird. Hinterher werfen wir einen ersten Blick auf den VBA-Code. Das Thema Makrosicherheit, also die Sicherheit vor fremden Makros, die schädlichen Code enthalten können, spielt eine große Rolle. Diese Thematik werde ich in Abschnitt 1.2.5, »Makrosicherheit ändern«, erläutern. Excel-Dateien können sowohl mit als auch ohne Makros gespeichert werden. Darauf werde ich in Abschnitt 1.2.4, »Makro speichern«, eingehen. Die in diesem Kapitel erläuterte Bedienung gilt für Excel 2016 bis Excel 2021. Die weitaus meisten Beispiele in diesem Buch laufen auch unter noch älteren Versionen. Sämtliche Beispiele finden Sie in den Materialien, die Sie über www.rheinwerk-verlag.de/5546 erreichen.

1.2.1    Makro aufzeichnen Mithilfe der folgenden Beschreibung erstellen Sie ein einfaches Makro zur Verschiebung des Inhalts von Zelle A1 in Zelle C1. Das Beispiel dient einer ersten Verdeutlichung der Abläufe, noch ohne VBA: 1. Starten Sie Excel. 2. Sie haben eine leere Arbeitsmappe vor sich. Tragen Sie in Zelle A1 einen beliebigen Inhalt (Zahl oder Text) ein (siehe

Abbildung 1.1).

Abbildung 1.1     Zelle, deren Inhalt verschoben wird

3. Betätigen Sie auf der Registerkarte Ansicht den unteren Teil der Schaltfläche Makros, der mit einem Pfeil gekennzeichnet ist. Es klappt ein kleines Untermenü auf, siehe Abbildung 1.2.

Abbildung 1.2     Menü »Ansicht • Makros«, Untermenü

4. Wählen Sie den Menüpunkt Makro aufzeichnen. Es erscheint das Dialogfeld Makro aufzeichnen (siehe Abbildung 1.3). Wählen Sie in der Liste Makro speichern in: den Eintrag Diese Arbeitsmappe, falls diese Option noch nicht eingestellt ist.

Abbildung 1.3     Makro mit dem Namen »Makro1«

5. Der vorgeschlagene Makroname lautet Makro1. Diesen können Sie beibehalten. 6. Betätigen Sie die Schaltfläche OK. Ab jetzt werden alle Aktionen, die Sie ausführen, aufgezeichnet. 7. Wählen Sie Zelle A1 aus. 8. Schneiden Sie den Inhalt von Zelle A1 aus, zum Beispiel mit (Strg)+(X). 9. Wählen Sie Zelle C1 aus. 10. Fügen Sie den Inhalt von Zelle A1 ein, zum Beispiel mit (Strg)+ (V). 11. Damit wurde der Inhalt von Zelle A1 in Zelle C1 verschoben (siehe Abbildung 1.4). 12. Klappen Sie in der Registerkarte Ansicht wiederum über den Pfeil auf der Schaltfläche Makros das Menü auf.

13. Wählen Sie den Menüpunkt Aufzeichnung beenden. Damit wird die Aufzeichnung Ihrer Aktionen beendet. 14. Sie haben damit soeben Ihr erstes Makro erfolgreich erstellt. Speichern Sie die Datei an dieser Stelle noch nicht.

Abbildung 1.4     Zellen nach der Verschiebung

Das Aufzeichnen geht etwas schneller, wenn Sie auf der ExcelOberfläche das entsprechende Symbol in der Statusleiste betätigen (siehe Abbildung 1.5).

Abbildung 1.5     Symbol zum Starten einer Makroaufzeichnung

Nach Beginn der Aufzeichnung erscheint an der gleichen Stelle das Symbol zum Beenden der Aufzeichnung (siehe Abbildung 1.6).

Abbildung 1.6     Symbol zum Beenden einer Makroaufzeichnung

Übung »Makro aufzeichnen« Tragen Sie eine Zahl oder einen Text in Zelle E3 ein. Zeichnen Sie ein Makro auf, das den Inhalt von Zelle E3 in Zelle E5 kopiert. Nennen Sie das Makro KopieE3E5.

1.2.2    Makro ausführen Das soeben erstellte Makro Makro1 wird nun ausgeführt. Gehen Sie dazu wie folgt vor: 1. Tragen Sie in Zelle A1 einen beliebigen Inhalt ein (Zahl oder Text). Wählen Sie anschließend Zelle A1 aus. 2. Klappen Sie auf der Registerkarte Ansicht über den Pfeil unten auf der Schaltfläche Makros das Menü auf. 3. Wählen Sie den Menüpunkt Makros anzeigen. 4. Es erscheint das Dialogfeld Makro mit einer Liste der bisher erstellten Makros. Wählen Sie in der Liste das Makro Makro1 aus. 5. Betätigen Sie die Schaltfläche Ausführen. 6. Der Inhalt von Zelle A1 wird wiederum in Zelle C1 verschoben. Damit haben Sie Ihr erstes Makro erfolgreich ausgeführt. Übung »Makro ausführen«

Tragen Sie einen neuen Inhalt in Zelle E3 ein. Wählen Sie anschließend Zelle E3 aus. Führen Sie das Makro KopieE3E5 aus, und überprüfen Sie anhand des Ergebnisses die korrekte Umsetzung.

[»]  Hinweis Geben Sie einem Makro einen möglichst sprechenden Namen, der etwas über seine Arbeitsweise aussagt. Sie finden es dann leichter in der Liste der Makros.

1.2.3    Makro ansehen Sehen wir uns den VBA-Code des soeben erstellten Makros an, um einen ersten Eindruck von der Sprache zu erhalten. Dazu gehen Sie wie folgt vor: 1. Klappen Sie in der Registerkarte Ansicht über den Pfeil auf der Schaltfläche Makros das Menü auf. 2. Wählen Sie den Menüpunkt Makros anzeigen. 3. Es erscheint das Dialogfeld Makro mit einer Liste der bisher erstellten Makros. Wählen Sie in der Liste das Makro Makro1 aus. 4. Betätigen Sie die Schaltfläche Bearbeiten. Es erscheint der Visual Basic Editor (kurz: VBE), die eigentliche Entwicklungsumgebung. Auf seine einzelnen Elemente werde ich in Abschnitt 1.3, »Visual Basic Editor«, eingehen. Zunächst ist im rechten Fenster der Code der ausgewählten Makros zu sehen (siehe Abbildung 1.7).

Abbildung 1.7     VBA-Code des Makros »Makro1«

Es folgt eine kurze Erläuterung der einzelnen Zeilen. Es macht nichts, falls Sie noch nicht alles genau verstehen. Die einzelnen Codeelemente werde ich später ausführlicher erklären. Der Code des Makros Makro1 ist in einer Sub-Prozedur zwischen Sub und End Sub notiert. Nach dem Namen eines Makros bzw. einer SubProzedur werden Klammern gesetzt, die zunächst leer sind. Das Hochkomma dient dazu, eine ganze Zeile bzw. den Rest einer Zeile zu einem Kommentar zu machen. Der Text hinter einem Hochkomma dient der Erläuterung des VBA-Codes. Er wird nicht ausgeführt. Die Anweisung Range("A1").Select bedeutet: Es wird Zelle A1 ausgewählt. Dank der Anweisung Selection.Cut wird der Inhalt der aktuellen Auswahl, also der Inhalt von Zelle A1, ausgeschnitten und befindet sich anschließend in der Zwischenablage. Die Anweisung Range("C1").Select bedeutet: Zelle C1 wird ausgewählt. Dank der Anweisung ActiveSheet.Paste wird der Inhalt der Zwischenablage in das aktuell aktive Tabellenblatt eingefügt.

Durch diesen Ablauf wird der Inhalt von Zelle A1 in Zelle C1 verschoben. Schließen Sie den VBE über das Menü Datei • Schließen und zurück zu Microsoft Excel. Es erscheint wieder die Excel-Oberfläche. Übung »Makro ansehen« Interpretieren Sie den VBA-Code des Makros KopieE3E5: Sub KopieE3E5()

Range("E3").Select

Selection.Copy

Range("E5").Select

ActiveSheet.Paste

End Sub

1.2.4    Makro speichern Excel-Dateien können sowohl mit Makros als auch ohne Makros gespeichert werden. Zum Speichern rufen Sie das Menü Datei auf und darin den Menüpunkt Speichern. Auf der rechten Seite wählen Sie die Schaltfläche Durchsuchen. Es erscheint das Dialogfeld Speichern unter. Als Dateityp ist im Dialogfeld Speichern unter angegeben: ExcelArbeitsmappe mit der Dateiendung .xlsx (siehe Abbildung 1.8).

Abbildung 1.8     Als Arbeitsmappe ohne Makros speichern

Betätigen Sie nun die Schaltfläche Speichern, erscheint der Hinweis, dass die Makros in dieser Datei bei diesem Dateityp nicht mitgespeichert würden (siehe Abbildung 1.9) und daher verloren gehen würden.

Abbildung 1.9     Warnung, dass Makros nicht mitgespeichert werden

Daher betätigen Sie zunächst die Schaltfläche Nein. Wählen Sie im Dialogfeld Speichern unter als Dateityp die Option Excel-Arbeitsmappe mit Makros (mit der Dateiendung .xlsm) aus, und speichern Sie die Datei unter dem gewählten Namen im gewünschten Verzeichnis, z. B. C:\Temp\Mappe1.xlsm (siehe Abbildung 1.10).

Abbildung 1.10     Als Arbeitsmappe mit Makros speichern

Nachdem die Datei erfolgreich mit Makros gespeichert wurde, schließen Sie Excel.

1.2.5    Makrosicherheit ändern Starten Sie Excel erneut. Beim Öffnen der soeben gespeicherten Datei stoßen Sie unweigerlich auf das Thema Makrosicherheit. Was bedeutet das?

Excel möchte Sie davor bewahren, möglicherweise schädlichen VBACode auszuführen. Unterhalb der Multifunktionsleiste erscheint daher ein Sicherheitshinweis, dass die in dieser Datei enthaltenen Makros deaktiviert wurden (siehe Abbildung 1.11).

Abbildung 1.11     Sicherheitswarnung »Makros wurden deaktiviert.«

Diese Reaktion erfolgt aufgrund der folgenden Standardeinstellung für die Makrosicherheit in Excel: Alle Makros mit Benachrichtigung deaktivieren. Versuchen Sie, ein Makro auszuführen, erscheint die Information, dass dies nicht möglich ist (siehe Abbildung 1.12).

Abbildung 1.12     Hinweis, dass die Makroausführung nicht möglich ist

Sie haben die Möglichkeit, die in dieser Datei enthaltenen Makros zu aktivieren. Schließen Sie dazu die Datei, und öffnen Sie sie erneut. Betätigen Sie die Schaltfläche Inhalt aktivieren neben der Sicherheitswarnung (siehe Abbildung 1.11). Die Sicherheitswarnung verschwindet, und Sie können die Makros in dieser Datei ausführen.

Die Datei wurde in die Liste der »vertrauenswürdigen Dokumente« aufgenommen. Sie können auch alle Excel-Dateien in einem Verzeichnis für vertrauenswürdig erklären, siehe Abschnitt 1.2.7, »Makrosicherheit dauerhaft ändern«.

1.2.6    Registerkarte »Entwicklertools« Die Registerkarte Entwicklertools bietet weitergehende Möglichkeiten zur Erstellung und Verwaltung von Makros. Daher wird sie am besten dauerhaft in Excel eingeblendet. Rufen Sie dazu das Menü Datei auf und betätigen die Schaltfläche Optionen. Im Dialogfeld Excel-Optionen klicken Sie auf die Schaltfläche Menüband anpassen. Auf der rechten Seite markieren Sie die Hauptregisterkarte Entwicklertools (siehe Abbildung 1.13) und betätigen die Schaltfläche OK.

Abbildung 1.13     Registerkarte »Entwicklertools« einblenden

Anschließend ist die Registerkarte dauerhaft aktiviert (siehe Abbildung 1.14).

Abbildung 1.14     Registerkarte »Entwicklertools«

1.2.7    Makrosicherheit dauerhaft ändern Klicken Sie auf der Registerkarte Entwicklertools die Schaltfläche Makrosicherheit an (siehe Abbildung 1.15).

Abbildung 1.15     Schaltfläche »Makrosicherheit«

Anschließend öffnet sich das Dialogfeld Trust Center. Nach Auswahl der Kategorie Makroeinstellungen sehen Sie die Standardeinstellung Deaktivieren von VBA-Makros mit Benachrichtigung (siehe Abbildung 1.16). Außerdem sehen Sie die verschiedenen Einstellmöglichkeiten.

Abbildung 1.16     Trust Center

Ich empfehle Ihnen, die Makroeinstellungen nicht zu ändern. Stattdessen sollten Sie Ihre Excel-Dateien mit Makros in einem bestimmten Verzeichnis speichern und dieses Verzeichnis zu der Kategorie Vertrauenswürdige Speicherorte hinzufügen. Die Makros in den Verzeichnissen dieser Kategorie können immer ausgeführt werden. Wählen Sie zum Hinzufügen eines Verzeichnisses die Kategorie Vertrauenswürdige Speicherorte aus. Es wird eine Liste von Verzeichnissen angezeigt. Betätigen Sie die Schaltfläche Neuen Speicherort hinzufügen. Es erscheint ein Dialogfeld, in dem Sie Ihr Verzeichnis eintragen (siehe Abbildung 1.17).

Abbildung 1.17     Vertrauenswürdiges Verzeichnis

Anschließend ist die Liste der Verzeichnisse um dieses Element ergänzt (siehe Abbildung 1.18).

Abbildung 1.18     Liste der vertrauenswürdigen Verzeichnisse

Sind Sie nicht mehr sicher, welche einzelnen Dokumente Sie bereits außerhalb der vertrauenswürdigen Verzeichnisse als vertrauenswürdig erklärt haben, betätigen Sie nach der Auswahl der Kategorie Vertrauenswürdige Dokumente die Schaltfläche Löschen. Damit wird die gesamte Liste der vertrauenswürdigen Dokumente gelöscht. Anschließend erklären Sie Ihre Dokumente jeweils beim Öffnen wieder einzeln als vertrauenswürdig.

1.3    Visual Basic Editor Bei dem Visual Basic Editor (VBE) handelt es sich um die Entwicklungsumgebung, in der Sie den VBA-Code schreiben. Zum Aufruf des VBE betätigen Sie die Schaltfläche Visual Basic auf der Registerkarte Entwicklertools. Alternativ rufen Sie den VBE von der Excel-Oberfläche aus mit der Tastenkombination (Alt)+(F11) auf. Mit der gleichen Tastenkombination wechseln Sie auch wieder vom VBE zur ExcelOberfläche zurück. Dies ist in der Praxis der gängigste Weg.

1.3.1    Menüleiste und Symbolleiste Im oberen Teil des VBE befinden sich eine Menüleiste und die Symbolleiste Voreinstellung. Sehr nützlich für die Programmierung ist auch die Symbolleiste Bearbeiten, die Sie über das Menü Ansicht • Symbolleisten einblenden. Beide Symbolleisten sehen Sie in Abbildung 1.19.

Abbildung 1.19     Symbolleisten »Voreinstellung« und »Bearbeiten«

Nehmen Sie zu Beginn eine wichtige Voreinstellung vor: Im Menü Extras • Optionen • Registerkarte Editor setzen Sie ein Häkchen bei Variablendeklaration erforderlich (siehe Abbildung 1.20) und betätigen die Schaltfläche OK.

Abbildung 1.20     Einstellung »Variablendeklaration erforderlich«

Dies sorgt ab dem nächsten Öffnen von Excel dafür, dass in jedem Modul oberhalb des VBA-Codes die Zeile Option Explicit steht und alle Variablen deklariert werden müssen. Damit wird in Ihrem VBA-Code automatisch darauf geachtet, dass Sie alle Variablen explizit deklarieren. Dies trägt zur Verminderung von Fehlern und zur Verbesserung der Performance Ihrer Programme bei. Variablen dienen der Speicherung von Zahlen, Daten und Texten, die in einem Programm benötigt werden. Dazu mehr in Kapitel 3, »Grundlagen der Programmierung mit VBA«.

1.3.2    Projekt-Explorer und Fenster »Eigenschaften« Auf der linken Seite des VBE befinden sich der Projekt-Explorer und das Fenster Eigenschaften (siehe Abbildung 1.21).

Abbildung 1.21     Projekt-Explorer und Fenster »Eigenschaften«

Im Projekt-Explorer werden die Elemente der aktuell geöffneten Dateien angezeigt, in denen Sie aktuell mit VBA arbeiten können: Es gibt eigene Codemodule, wie z. B. das Modul1, das durch die Aufzeichnung eines Makros automatisch erzeugt wurde. Ein eigenes, leeres Modul wird zudem über das Menü Einfügen • Modul erzeugt. Zudem gibt es vorhandene Klassenmodule, wie DieseArbeitsmappe oder Tabelle1, also Module für die gesamte Arbeitsmappe oder für die aktuell vorhandenen Tabellen. Hier wird VBA-Code notiert, der beim Eintreten eines Ereignisses automatisch ausgeführt wird, das mit einem dieser Objekte zusammenhängt, wie zum Beispiel das Öffnen einer Arbeitsmappe. Sie können eigene Klassenmodule zur objektorientierten Programmierung erzeugen, und zwar über das Menü Einfügen •

Klassenmodul. Sie können auch UserForms, also eigene Dialogfelder zur komfortablen Programmsteuerung, über das Menü Einfügen • UserForm erzeugen. Wir arbeiten zunächst mit eigenen Codemodulen. Die VBA-Beispiele in diesem Buch werden in Codemodulen (Modul1, Modul2 …) gespeichert, falls kein anderslautender Hinweis erfolgt. Wird Code in UserForms oder in eigenen Klassenmodulen gespeichert, so wird dies explizit erwähnt. Per Doppelklick auf ein Element im ProjektExplorer wird der VBA-Code des betreffenden Moduls eingeblendet. Übung »Code einblenden« Blenden Sie den VBA-Code der verschiedenen Elemente ein.

Im Fenster Eigenschaften werden die Eigenschaften des aktuell ausgewählten Moduls bzw. die Eigenschaften des ausgewählten Steuerelements eines eigenen Dialogfelds aufgelistet. Die Werte dieser Eigenschaften lassen sich ändern. Ein Modul wird durch einen einfachen Klick im Projekt-Explorer ausgewählt. Das Fenster Eigenschaften wird für uns erst später wichtig.

1.3.3    Codefenster Auf der rechten Seite des VBE befindet sich das Codefenster mit dem VBA-Code. Zur direkten Ausführung eines der Makros setzen Sie den Cursor in die betreffende Prozedur, und führen Sie Folgendes aus: Rufen Sie im Menü Ausführen den Menüpunkt Sub/UserForm ausführen auf, oder betätigen Sie die Taste (F5), oder

betätigen Sie in der Symbolleiste Voreinstellung das Symbol mit dem grünen Pfeil, der nach rechts weist (siehe Abbildung 1.22).

Abbildung 1.22     Symbol »Sub/UserForm ausführen« (Taste »F5«)

Übung »Code starten« Rufen Sie die beiden vorhandenen Makros mit den beschriebenen Methoden auf. Das Ergebnis sehen Sie jeweils auf der Excel-Oberfläche. Sie müssen daher zwischen ExcelOberfläche und VBE hin- und herwechseln, z. B. mithilfe der Tastenkombination (Alt)+(F11). Übung »Code kommentieren« Fügen Sie Ihren beiden Makros jeweils eine Kommentarzeile hinzu mit dem Text Dieses Makro wurde von [Ihr Name] erstellt. Zur Erinnerung: Ein Hochkomma im VBA-Code dient dazu, eine ganze Zeile bzw. den Rest einer Zeile hinter dem Hochkomma zu einem Kommentar zu machen. Rufen Sie Ihre Makros erneut auf.

1.4    Makrocode verstehen und ändern Im nächsten Schritt verändern Sie Ihre eigenen Makros. Dazu betrachten wir den Code etwas näher, zunächst am Beispiel des Makros Makro1: Sub Makro1()

Range("A1").Select

Selection.Cut

Range("C1").Select

ActiveSheet.Paste

End Sub

Listing 1.1     Sub »Makro1()« in Mappe1.xlsm, Modul 1

Der Code der Makros wird jeweils innerhalb einer Sub-Prozedur zwischen Sub und End Sub notiert. Die einzelnen Zeilen werden der Reihe nach durchlaufen und ausgeführt. Die Anweisung Range("A1").Select bedeutet: Für einen Zellbereich (Bereich: engl. range) wird etwas durchgeführt. In diesem Fall wird der Zellbereich ausgewählt (engl. select). Der Zellbereich umfasst hier nur Zelle A1. Er kann auch mehrere Zellen umfassen. Dank der Anweisung Selection.Cut wird für die vorher getroffene Auswahl (engl. selection) etwas durchgeführt. In diesem Fall wird die Auswahl ausgeschnitten (engl. cut), hier der Inhalt von Zelle A1. Dieser Inhalt befindet sich nun in der Zwischenablage. In dem Makro KopieE3E5 aus der Übung »Makro aufzeichnen« wird auf ähnliche Art und Weise mit Selection.Copy die vorher getroffene Auswahl in die Zwischenablage kopiert. Die Anweisung Range("C1").Select erklärt sich nun von selbst.

Die Anweisung ActiveSheet.Paste bedeutet: Für das aktuell aktive Tabellenblatt (engl. sheet) wird etwas durchgeführt. In diesem Fall wird der Inhalt der Zwischenablage eingefügt (engl. paste). Dies wird an der vorher ausgewählten Stelle (Zelle C1) vorgenommen. [»]  Hinweis Das Präfix Active bezeichnet immer das aktuell aktive Element, wie z. B. ActiveCell (Zelle), ActiveSheet (Tabellenblatt) oder ActiveWorkbook (Arbeitsmappe).

Ändern Sie den Code durch den Eintrag von D1 statt C1 als Zielzelle. Damit wird durch Ausführung des Makros der Inhalt von Zelle A1 in Zelle D1 verschoben. Übung »Makro ändern« Verändern Sie das Makro KopieE3E5 aus der Übung »Makro aufzeichnen« (siehe Abschnitt 1.2.1, »Makro aufzeichnen«). Der Inhalt der Zellen E3 bis G3 wird sowohl in die Zellen E5 bis G5 als auch in die Zellen E10 bis G10 kopiert. Nennen Sie das geänderte Makro KopieE3E5Neu. Hinweise dazu: Ein Zellbereich aus mehreren Zellen wird genau wie in Excel notiert, also z. B. E3:G3. Für eine Zielangabe reicht die Angabe einer einzelnen Zelle aus. Die weiteren Zellen des kopierten Bereichs werden, wie aus Excel gewohnt, in die Nachbarzellen eingefügt. Aus der Zwischenablage können beliebig viele Kopien eingefügt werden.

[»]  Hinweis In den genannten Beispielen werden Quellbereiche selektiert und Zielbereiche aktiviert. Dadurch erhält man als VBA-Neuling einen leicht verständlichen Einstieg, weil der Code die gleichen Schritte ausführt wie der Benutzer auf der Excel-Oberfläche. Es wird aber mehr Code als notwendig erzeugt. Die Wartung eines solchen Codes dauert länger, und die Ausführung ist langsamer. Im weiteren Verlauf dieses Buches werden Sie lernen, wie Sie besseren Code erstellen.

1.5    Makro per Schaltfläche ausführen Stellen Sie der Benutzerin eine Schaltfläche (engl. button) zum Starten eines Makros zur Verfügung. Das trägt dazu bei, Benutzern eine übersichtliche Benutzeroberfläche mit Daten, Formeln und Programmen zu bieten. Zur Erzeugung einer Schaltfläche gehen Sie wie folgt vor: 1. Auf der Excel-Oberfläche betätigen Sie den Pfeil unterhalb der Schaltfläche Einfügen auf der Registerkarte Entwicklertools. 2. Es erscheint eine Sammlung von Steuerelementen. Daraus wählen Sie das Symbol links oben: Schaltfläche (Formularsteuerelement). 3. Platzieren Sie den Mauszeiger an der gewünschten Stelle auf dem Tabellenblatt. Es erscheint ein kleines Kreuz. Drücken Sie die linke Maustaste, halten Sie sie gedrückt, und ziehen Sie die Schaltfläche in der gewünschten Größe auf. 4. Das Dialogfeld Makro zuweisen (siehe Abbildung 1.23) öffnet sich. Suchen Sie das gewünschte Makro heraus, und bestätigen Sie mit OK.

Abbildung 1.23     Makro einer Schaltfläche zuordnen

Anschließend erscheint die Schaltfläche im Bearbeitungsmodus. Klicken Sie einmal neben die Schaltfläche, damit der Bearbeitungsmodus der Schaltfläche endet. Anschließend können Sie das ausgewählte Makro durch einen Klick auf die Schaltfläche ausführen (siehe Abbildung 1.24).

Abbildung 1.24     Neu eingefügte Schaltfläche

[»]  Hinweis Sie können eine Schaltfläche nachträglich bearbeiten. Dazu klicken Sie mit der rechten Maustaste auf die Schaltfläche, dann sind Sie wieder im Bearbeitungsmodus. Nun lassen sich die Größe und die Position der Schaltfläche beeinflussen. Über das Kontextmenü (wiederum erreichbar per Rechtsklick) weisen Sie der Schaltfläche ein anderes Makro zu oder ändern den Text auf der Schaltfläche. Sie können sie gegebenenfalls durch Betätigung der Taste (Entf) löschen.

1.6    Relative Verweise verwenden Beim Aufzeichnen der Makros ist Ihnen sicherlich schon die Schaltfläche Relative Verweise verwenden aufgefallen. Dabei handelt es sich um eine Schaltfläche, die Sie an zwei Stellen betätigen können: in dem Menü, das über die Schaltfläche Makros auf der Registerkarte Ansicht erreicht wird auf der Registerkarte Entwicklertools Ist dieser Schalter eingeschaltet, also optisch hervorgehoben, werden die nachfolgenden Makros relativ aufgezeichnet. Bei den bisher erstellten Makros war dieser Schalter nicht eingeschaltet. Diese Makros wurden daher absolut aufgezeichnet: Absolute Aufzeichnung bedeutet, dass im Makrocode absolute Zellangaben stehen (Beispiel: A1, C1). Bei der Ausführung eines solchen Makros ist es egal, welche Zelle in Excel aktiv ist, denn es wird immer mit den Zellen A1 und C1 gearbeitet. Relative Aufzeichnung bedeutet, dass im Makrocode relative Zellangaben stehen. Bei der Ausführung eines solchen Makros werden die Aktionen relativ zu der Zelle ausgeführt, die in Excel aktiv ist. Zur Verdeutlichung wird ein Makro aufgezeichnet, in dem das Gleiche gemacht wird wie im ersten Beispielmakro: Der Inhalt von Zelle A1 wird nach C1 verschoben. Allerdings wird das Makro relativ aufgezeichnet. Führen Sie folgende Schritte durch: 1. Aktivieren Sie den Schalter Relative Verweise verwenden. 2. Tragen Sie in Zelle A1 einen beliebigen Inhalt ein (Zahl oder Text).

3. Wählen Sie Zelle A1 aus. 4. Beginnen Sie mit der Aufzeichnung des Makros (Name Makro2). 5. Schneiden Sie den Inhalt von Zelle A1 aus. 6. Fügen Sie den Inhalt der Zwischenablage in Zelle C1 ein. Der Inhalt von Zelle A1 wurde in Zelle C1 verschoben. 7. Beenden Sie die Makroaufzeichnung. Bis hierhin ist noch kein sichtbarer Unterschied aufgetreten. Führen Sie allerdings das Makro aus, wird jeweils der Inhalt der aktuell ausgewählten Zelle um zwei Zellen nach rechts verschoben, zum Beispiel von Zelle D10 in Zelle F10. Die aktive Zelle ist nun der Ausgangspunkt. Der Code des neuen Makros: Sub Makro2()

Selection.Cut

ActiveCell.Offset(0, 2).Range("A1").Select

ActiveSheet.Paste

End Sub

Listing 1.2     Sub »Makro2()« in Mappe1.xlsm, Modul 1

Betrachten wir den Code: Selection.Cut: Es geschieht das Gleiche wie bei der absoluten

Aufzeichnung: Der Inhalt der aktiven Zelle wird ausgeschnitten. Er liegt nun in der Zwischenablage. ActiveCell.Offset(0,2).Range("A1").Select: Ausgehend von der

aktiven Zelle wird ein Offset (also ein Versatz) ausgewählt. Die Angaben in Klammern stehen für Zeile und Spalte des Versatzes. Es wird daher eine Zelle in der gleichen Zeile (Offset-Zeile 0) und zwei Spalten weiter rechts (Offset-Spalte 2) ausgewählt. Ist die aktive Zelle D10, wird demnach Zelle F10 ausgewählt.

Zu diesem Versatz wird der Zellbereich A1 ausgewählt. Dies ist nicht die absolute Zelle A1 des Tabellenblatts, sondern die oberste linke Zelle des Versatzes. Diese Zelle (in der gleichen Zeile, zwei Zellen weiter rechts) wird ausgewählt. ActiveSheet.Paste: Es geschieht das Gleiche wie bei der absoluten

Aufzeichnung: Der Inhalt der Zwischenablage wird eingefügt. Dieses Makro verhält sich anders als das Makro, das absolut aufgezeichnet wurde. Beide Aufzeichnungsarten haben ihre Vorteile, je nach Situation. [»]  Hinweis Nach dem Schließen und erneuten Öffnen von Excel steht der Schalter immer auf »absolute Aufzeichnung«. Während einer Aufzeichnung wechseln Sie bei Bedarf über den Schalter zwischen relativer und absoluter Aufzeichnung. Übung »Relative Verweise«

Erstellen Sie ein Makro, das den Inhalt von drei nebeneinanderliegenden, markierten Zellen um zwei Zeilen bzw. um sieben Zeilen nach unten kopiert. Es entspricht dem Makro aus der Übung »Makro ändern« (siehe Abschnitt 1.4, »Makrocode verstehen und ändern«), allerdings mit relativer Aufzeichnung. Nennen Sie das Makro RelKopie. Testen Sie es, und interpretieren Sie den VBA-Code.

1.7    Persönliche Makroarbeitsmappe Die bisher aufgezeichneten Makros wurden in der aktuell aktiven Arbeitsmappe gespeichert. Daher stehen sie nur dort zur Verfügung. Möchten Sie bestimmte Makros jederzeit zur Verfügung haben, speichern Sie sie in der Mappe Persönliche Makroarbeitsmappe. Diese Arbeitsmappe wird immer zusammen mit Excel geöffnet, sobald sie existiert. Zum Speichern eines Makros in der Mappe Persönliche Makroarbeitsmappe wird im Dialogfeld Makro aufzeichnen der entsprechende Eintrag in der Liste Makro speichern in: ausgewählt (siehe Abbildung 1.25).

Abbildung 1.25     In der Mappe »Persönliche Makroarbeitsmappe« speichern

Nach der Aufzeichnung erscheint ein weiterer Eintrag im ProjektExplorer des VBE: die Datei personal.xlsb (siehe Abbildung 1.26).

Abbildung 1.26     »Persönliche Makroarbeitsmappe« im Projekt-Explorer

Wurde diese Datei verändert, indem z. B. ein Makro hinzugefügt oder geändert wurde, werden Sie bei jedem Schließen von Excel gefragt, ob Sie diese Änderungen speichern möchten. Übung »Persönliche Makroarbeitsmappe« Erstellen Sie noch einmal das Makro aus der Übung »Relative Verweise«. Speichern Sie es diesmal in der Mappe Persönliche Makroarbeitsmappe. Schließen Sie Excel. Testen Sie das Makro nach dem erneuten Öffnen von Excel in einer beliebigen Arbeitsmappe.

1.8    Code schreiben für einfache Ausgaben In diesem Abschnitt wird erstmalig VBA-Code nicht durch eine Makroaufzeichnung, sondern durch Schreiben des Codes in einer eigenen Sub-Prozedur erstellt. Damit entsteht das erste richtige VBA-Programm. ich werde drei Möglichkeiten zur Ausgabe von Ergebnissen oder Kontrollwerten erläutern, die häufig in der VBAProgrammierung eingesetzt werden: in einer Zelle in einer Nachrichtenbox im Direktfenster des VBE

1.8.1    Eigene Sub-Prozedur Zunächst erstellen Sie eine eigene Sub-Prozedur. Wechseln Sie dazu mit der Tastenkombination (Alt)+(F11) zum VBE. Schreiben Sie unterhalb des letzten Makros die folgende Zeile: Sub AusgabeZelle

Sobald Sie mit der Taste (¢) die Zeile wechseln, stellen Sie fest, dass der Editor Sie bei der VBA-Programmierung unterstützt (siehe Abbildung 1.27): Am Ende der Zeile werden Klammern angefügt. Es wird die Zeile mit End Sub erzeugt. Der Cursor steht in der Zeile dazwischen – bereit zur Eingabe Ihres VBA-Codes. Es wird eine Trennzeile zwischen den einzelnen Makros erzeugt.

Abbildung 1.27     Neue eigene Sub-Prozedur

Nach dem Namen einer Sub-Prozedur (oder kurz Prozedur) folgen immer Klammern, wie bei Ihren bisherigen Makros. Diese Klammern sind zunächst leer. Später lernen Sie, innerhalb der Klammern Aufrufparameter zu notieren, die eine Prozedur flexibler machen.

1.8.2    Ausgabe in Zelle Geben Sie in der Prozedur AusgabeZelle() folgende Codezeile ein: Range("A1").Value = "Hallo"

Damit sieht Ihre Prozedur wie folgt aus: Sub AusgabeZelle()

Range("A1").Value = "Hallo"

End Sub

Listing 1.3     Sub »AusgabeZelle()« in Mappe1.xlsm, Modul 1

Beim Ausführen dieser Prozedur, z. B. mithilfe der Taste (F5), wird der Text »Hallo« in Zelle A1 ausgegeben (siehe Abbildung 1.28).

Abbildung 1.28     Ergebnis der eigenen Sub-Prozedur

Auf einen Zellbereich, der eine oder mehrere Zellen umfasst, wird über Range zugegriffen. Der Eigenschaft Value dieses Bereichs wird

ein Wert zugewiesen, der Text »Hallo«. Damit erhält die Zelle einen Inhalt. [»]  Hinweis Geben Sie einer Prozedur einen eindeutigen und sprechenden Namen, der etwas über ihre Arbeitsweise aussagt.

1.8.3    Ausgabe in Nachrichtenbox Schreiben Sie eine weitere Prozedur mit folgendem Code: Sub AusgabeBox()

MsgBox "Hallo"

End Sub

Listing 1.4     Sub »AusgabeBox()« in Mappe1.xlsm, Modul 1

Nach dem Aufruf der Prozedur erscheint eine kleine Nachrichtenbox mit dem Text »Hallo« (siehe Abbildung 1.29). Das Programm hält an. Nach dem Betätigen der Schaltfläche OK wird die Nachrichtenbox geschlossen, und das Programm läuft weiter. Zeigt der VBE einmal unerwartet keinerlei Reaktion, wechseln Sie mit der Tastenkombination (Alt)+(F11) zum Excel-Tabellenblatt: Möglicherweise wartet dort eine Nachricht auf Ihre Reaktion.

Abbildung 1.29     In Nachrichtenbox ausgeben

Eine solche Nachrichtenbox benutzen Sie u. a. zur: Kontrollausgabe während der Programmierung Information der Benutzerin bei einem Fehler Information des Benutzers am Ende eines Programms Bei MsgBox() handelt es sich um eine vorgefertigte Funktion, bei der Sie eine Zeichenkette als Aufrufparameter notieren müssen. Die Funktion MsgBox() bietet allerdings wesentlich mehr, wie Sie in Abschnitt 8.3, »Einfacher Dialog mit dem Benutzer«, sehen werden. Bei längeren Ausgaben wird häufig ein Zeilenumbruch benötigt. Dieser wird über die Konstante vbCrLf bereitgestellt. Ein Beispiel: Sub AusgabeBoxZeilenumbruch()

MsgBox "Hallo" & vbCrLf & "Welt"

End Sub

Listing 1.5     Sub »AusgabeBoxZeilenumbruch()« in Mappe1.xlsm, Modul 1

Die Ausgabe sehen Sie in Abbildung 1.30.

Abbildung 1.30     Mit Zeilenumbruch ausgeben

Bei dem Namen dieser Konstanten handelt es sich um ein Relikt aus der Urzeit: In vbCrLf steht das Cr für Carriage Return, den Wagenrücklauf der Schreibmaschine zum Zeilenanfang. Das Lf steht für Line Feed, den Zeilenvorschub.

[»]  Hinweis Der Operator & dient der Verkettung von Zeichenfolgen. Er wird häufig benötigt, um die Ergebnisse eines Programms zusammen mit Text auszugeben. Dabei werden Zahlen vor der Verkettung automatisch in Text umgewandelt.

1.8.4    Ausgabe im Direktfenster des VBE Schreiben Sie eine weitere Prozedur mit folgendem Code: Sub AusgabeKontrolle()

Debug.Print "Hallo"

End Sub

Listing 1.6     Sub »AusgabeKontrolle()« in Mappe1.xlsm, Modul 1

Nach dem Aufruf erscheint zunächst gar nichts, da das Direktfenster des VBE standardmäßig nicht eingeblendet ist. Lassen Sie es über das Menü Ansicht • Direktfenster im VBE anzeigen. Anschließend sehen Sie die soeben erzeugte Ausgabe (siehe Abbildung 1.31). Das Direktfenster (= Direktbereich) nutzen Sie ebenfalls zur Kontrollausgabe während der Programmierung.

Abbildung 1.31     Im Direktfenster ausgeben

1.9    Microsoft 365 Bei Microsoft 365 handelt es sich um ein Software-Abonnement, das u. a. zur Nutzung von Excel dient. Funktionen in neuen ExcelVersionen, wie zum Beispiel die Überlauf-Funktionen für Excel 2021 (siehe Kapitel 11, »Funktionen aus Excel 2021«), stehen auch in Microsoft 365 zur Verfügung. Zudem haben Sie Zugang zu folgenden Möglichkeiten: Microsoft OneDrive: ein Dateispeicherdienst zum Speichern Ihrer Excel-Dateien in der Microsoft Cloud Microsoft Office Online: eine Online-Anwendung zum Bearbeiten Ihrer Excel-Dateien in einem Browser Ihren Zugang erhalten Sie mit Ihren persönlichen Anmeldedaten zu Microsoft über die Adresse https://onedrive.live.com/. Sie speichern Excel-Dateien mit Makros, die Sie mit der DesktopAnwendung auf Ihrem PC erstellt haben, entweder auf Ihrem PC oder in der Microsoft Cloud. Im letztgenannten Fall werden die Dateien zum Beispiel unter der folgenden Adresse gespeichert: https://d.docs.live.net//xxx/Documents/Mappe1.xlsm Die Zeichenfolge xxx steht hier für Ihren persönlichen Zugang bei Microsoft. Dateien, die Sie mithilfe von Microsoft OneDrive in der Microsoft Cloud gespeichert haben, können Sie auch wieder auf Ihren PC laden. Öffnen Sie eine Excel-Datei, die VBA-Code enthält und in der Microsoft Cloud gespeichert ist, müssen Sie die Makros zunächst aktivieren, siehe auch Abschnitt 1.2.5, »Makrosicherheit ändern«. Anschließend haben Sie die Möglichkeit, diese Datei zu einem

vertrauenswürdigen Dokument zu erklären, siehe Abbildung 1.32. Entscheiden Sie sich für diese Möglichkeit, werden Sie beim nächsten Öffnen der Datei nicht mehr gefragt.

Abbildung 1.32     Datei mit Netzwerkadresse

Die Online-Anwendung von Excel in Microsoft Office Online hat gegenüber der Desktop-Anwendung einen reduzierten Funktionsumfang. Die Ausführung von Makros beziehungsweise VBA-Code ist nicht möglich. Steuerelemente, zum Beispiel Schaltflächen, werden in der Online-Anwendung nicht angezeigt. Diese Makros und Steuerelemente werden aber nicht gelöscht. Nach dem Öffnen der betreffenden Excel-Datei in der DesktopAnwendung auf Ihrem PC können Sie sie wieder nutzen.

1.10    Web-Apps MS Office-Dateien können mit Web-Apps aus dem Office Store erweitert werden. Diese Web-Apps haben Zugriff auf die Daten in einer Office-Datei. Entwickler können diese Web-Apps mithilfe von Webtechniken (HTML, JavaScript, jQuery, CSS …) programmieren und im Office Store anbieten. In diesem Buch wird nur die Entwicklung von Anwendungen mithilfe von VBA beschrieben.

2    Grundlagen von Objekten und Ereignissen In diesem Kapitel lernen Sie die Objekte »Arbeitsmappe«, »Tabellenblatt« und »Zellbereich« mit ihren jeweiligen Eigenschaften, Methoden und Ereignissen kennen. VBA ist eine objektorientierte Sprache, d. h., es wird mit Objekten gearbeitet. Objekte verfügen über Eigenschaften, Methoden und Ereignisse: Eigenschaften (Attribute) bestimmen das Aussehen eines Objekts. Ein Tabellenblatt verfügt z. B. über die Eigenschaft Name. Der Wert dieser Eigenschaft ist die Bezeichnung des Tabellenblatts (z. B. Tabelle1). Methoden bestimmen die Fähigkeiten eines Objekts. Ein Tabellenblatt verfügt z. B. über die Methode Copy(), d. h., es kann kopiert werden. Ereignisse bestimmen, was mit dem Objekt passiert. Bei einem Tabellenblatt findet z. B. Ereignis »Aktivieren« (sprich: Öffnen) durch den Benutzer statt. Ereignisse können mit VBA-Code verbunden werden, so dass automatisch weitere Aktionen folgen. In diesem Kapitel werde ich Ihnen zahlreiche direkt ausführbare Möglichkeiten von VBA vorstellen, ohne dass Sie in die reine Programmierung mit Variablen, Datentypen, Verzweigungen und Schleifen einsteigen müssen. In Kapitel 3, »Grundlagen der

Programmierung mit VBA«, werde ich dann diese wichtigen Elemente der Programmierung erläutern, die die automatisierte Bearbeitung von Excel erheblich verbessern.

2.1    Objekthierarchie und Auflistungen Objekte verfügen über Eigenschaften. Eine Eigenschaft eines Objekts kann wiederum ein Unterobjekt sein – mit eigenen Eigenschaften, Methoden und Ereignissen. Setzen Sie diese Überlegung weiter fort, so erhalten Sie eine Hierarchie von Objekten, ausgehend von einem Hauptobjekt. Das Hauptobjekt bei Office-Anwendungen ist Application (engl. für Anwendung). Damit wird das Programm Excel selbst bezeichnet: Eine Eigenschaft des Objekts Application ist die Auflistung Workbooks. Darin befinden sich alle geöffneten Arbeitsmappen, also Excel-Dateien. Eine Eigenschaft einer einzelnen Arbeitsmappe ist die Auflistung Worksheets. Darin befinden sich alle Tabellenblätter einer Arbeitsmappe. Eine Eigenschaft eines einzelnen Tabellenblatts ist das Objekt Range. Darin befinden sich Zellen und Zellbereiche eines Tabellenblatts. In Excel wird häufig mit Auflistungen gearbeitet, wie z. B. Workbooks oder Worksheets. Dabei handelt es sich um Sammlungen gleichartiger Objekte. Sie sind an der Mehrzahlschreibweise (mit einem »s« am Ende) erkennbar.

2.2    Arbeitsmappen bearbeiten Das Objekt Workbooks ist eine Auflistung, die alle geöffneten Arbeitsmappen enthält. Das Objekt Workbook (ohne ein »s« am Ende) steht für eine einzelne Arbeitsmappe. Zur Bearbeitung einer bestimmten Arbeitsmappe gibt es verschiedene Möglichkeiten: ThisWorkbook: die Arbeitsmappe, die den aktuell ausgeführten

VBA-Code enthält. Sie wird auch als diese Arbeitsmappe bezeichnet.

ActiveWorkbook: die aktive Arbeitsmappe, die vom aktuell

ausgeführten VBA-Code bearbeitet wird. Dies muss nicht diese Arbeitsmappe sein. Workbooks(Index): Index ist die laufende Nummer der

Arbeitsmappe in der Workbooks-Auflistung. Die laufende Nummer einer Auflistung startet immer bei 1 und geht bis zur Nummer des letzten Elements in der Auflistung. Diese letzte Nummer entspricht der Anzahl der Elemente, die Sie bei allen Auflistungen über die Eigenschaft Count ermitteln. Workbooks("Name"): Gibt den Namen der Arbeitsmappe als

Zeichenkette an, also den Namen der Excel-Datei (in doppelten Anführungszeichen). In diesem Abschnitt wird davon ausgegangen, dass sich die genutzten Dateien im Verzeichnis C:\Temp befinden bzw. darin erzeugt werden.

2.2.1    Anzahl der Arbeitsmappen ermitteln

Mit folgender Prozedur wird die Anzahl der geöffneten Arbeitsmappen ermittelt: Sub MappenZaehlen()

MsgBox "Anzahl der Arbeitsmappen: " & Workbooks.Count

End Sub

Listing 2.1     Sub »MappenZaehlen()« in Mappe2.xlsm, Modul 1

Es wird der Wert der Eigenschaft Count des Objekts Workbooks ermittelt und mithilfe der Funktion MsgBox() ausgegeben (siehe Abbildung 2.1). Zu beachten ist, dass dabei die Persönliche Makroarbeitsmappe mitgezählt wird, sofern vorhanden. Sie können sie im VBE sehen.

Abbildung 2.1     Eigenschaft »Count«

[»]  Hinweis Die Überschrift der Nachrichtenbox und die Schaltfläche OK werden ab dieser Abbildung im Buch nicht mehr dargestellt.

2.2.2    Neue Arbeitsmappe erzeugen Mit folgender Prozedur wird eine neue Mappe erzeugt und geöffnet. Zur Kontrolle wird die Anzahl der geöffneten Mappen vor und nach dem Erzeugen ausgegeben: Sub NeueMappe()

MsgBox "Vorher: " & Workbooks.Count & " Mappe(n)"

Workbooks.Add

MsgBox "Nachher: " & Workbooks.Count & " Mappe(n)"

End Sub

Listing 2.2     Sub »NeueMappe()« in Mappe2.xlsm, Modul 1

Die Methode Add() des Workbooks-Objekts wird aufgerufen. Dadurch wird eine neue, leere Arbeitsmappe in Excel geöffnet. Diese ist dann die aktive Arbeitsmappe. Gleichzeitig wird der Auflistung Workbooks ein weiteres Element hinzugefügt, wie Sie an den beiden Ausgaben der Eigenschaft Count (vorher/nachher) erkennen.

2.2.3    Vorhandene Arbeitsmappe öffnen Mit folgender Prozedur wird eine vorhandene Mappe geöffnet: Sub VorhandeneMappe()

Workbooks.Open "C:\Temp\Mappe1.xlsm"

End Sub

Listing 2.3     Sub »VorhandeneMappe()« in Mappe2.xlsm, Modul 1

Die Methode Open() des Workbooks-Objekts wird aufgerufen. Dadurch wird die Arbeitsmappe mit dem angegebenen Namen im genannten Verzeichnis geöffnet. Diese ist dann die aktive Arbeitsmappe. Der Auflistung Workbooks wird ein weiteres Element hinzugefügt. Im Beispiel wurde eine Datei über eine absolute Pfadangabe erreicht. Dateien lassen sich auch mit relativen Pfadangaben oder ohne Pfadangabe erreichen, siehe Abschnitt 2.2.10, »Pfad einer Arbeitsmappe ermitteln«. Existiert die Arbeitsmappe (= Datei) nicht, wird das Programm mit einer Fehlermeldung abgebrochen (siehe Abbildung 2.2). Es kommt zu einem sogenannten Laufzeitfehler. In Kapitel 4, »Fehlerbehandlung«, werden Sie lernen, wie Sie solche Abbrüche vermeiden.

Abbildung 2.2     Programmabbruch durch Laufzeitfehler

2.2.4    Alle Arbeitsmappen schließen Mit folgender Prozedur werden alle geöffneten Arbeitsmappen geschlossen: Sub AlleMappenSchliessen()

Workbooks.Close

End Sub

Listing 2.4     Sub »AlleMappenSchliessen()« in Mappe2.xlsm, Modul 1

Die Methode Close() des Objekts Workbooks wird aufgerufen. Sie schließt alle geöffneten Arbeitsmappen, aber nicht den VBE oder die Excel-Hilfe. Die Anwendung Excel bleibt weiterhin geöffnet. Hat ein Benutzer Änderungen in einer Arbeitsmappe vorgenommen, wird er gefragt, ob er sie speichern möchte (siehe Abbildung 2.3).

Abbildung 2.3     Nachfrage im Anschluss an Dateiänderung

2.2.5    Name einer Arbeitsmappe ermitteln

Mit folgender Prozedur wird der Name einer Arbeitsmappe auf zwei Arten ermittelt: Sub MappenName()

MsgBox "Name: " & ThisWorkbook.Name

MsgBox "Name mit Pfad: " & ThisWorkbook.FullName

End Sub

Listing 2.5     Sub »MappenName()« in Mappe2.xlsm, Modul 1

Die Bezeichnung ThisWorkbook verweist immer auf die Arbeitsmappe, in der diese Prozedur steht. Es wird der Wert der Eigenschaft Name ermittelt und ausgegeben. Dies ist der Dateiname der Arbeitsmappe (siehe Abbildung 2.4).

Abbildung 2.4     Eigenschaft »Name«

Zusätzlich wird der Wert der Eigenschaft FullName ermittelt und ausgegeben. Dies ist der Dateiname der Arbeitsmappe inklusive vollständiger Pfadangabe (siehe Abbildung 2.5).

Abbildung 2.5     Eigenschaft »FullName«

2.2.6    Aktive Arbeitsmappe ermitteln Mit folgender Prozedur wird in zwei verschiedenen Situationen der Name der aktiven Arbeitsmappe ermittelt: Sub AktiveMappe()

Workbooks.Open "C:\Temp\Mappe1.xlsm"

MsgBox "Aktiv nach dem Öffnen: " & ActiveWorkbook.Name

ActiveWorkbook.Close

MsgBox "Aktiv nach dem Schließen: " & ActiveWorkbook.Name

End Sub

Listing 2.6     Sub »AktiveMappe()« in Mappe2.xlsm, Modul 1

Zunächst wird eine weitere vorhandene Arbeitsmappe geöffnet. ActiveWorkbook verweist immer auf die aktuell aktive Arbeitsmappe.

Eine Arbeitsmappe ist immer dann aktiv, nachdem die Benutzerin sie ausgewählt oder der Entwickler sie per Programm aktiviert hat. Eine Arbeitsmappe, die soeben geöffnet wurde, ist automatisch aktiv. Zur Kontrolle wird der Name der aktiven Arbeitsmappe ausgegeben (siehe Abbildung 2.6).

Abbildung 2.6     Aktive Arbeitsmappe nach dem Öffnen

Die Methode Close() des Objekts Workbook wird aufgerufen. Dadurch wird eine einzelne Arbeitsmappe, in diesem Fall die aktive Arbeitsmappe, geschlossen. Danach ist wieder die Arbeitsmappe aktiv, die vor dem Öffnen der gerade geschlossenen Arbeitsmappe aktiv war. Möchten Sie eine bestimmte Arbeitsmappe schließen, die Sie über ihren Namen ansprechen, lautet die Anweisung für das vorliegende Beispiel Workbooks("Mappe1.xlsm").Close. Dabei wird kein Pfadname angegeben, siehe auch Abschnitt 2.2.9, »Arbeitsmappe über Index oder Namen auswählen«. Zur Kontrolle wird wiederum der Name der nun aktiven Arbeitsmappe ausgegeben (siehe Abbildung 2.7).

Abbildung 2.7     Wieder aktive Arbeitsmappe nach dem Schließen

2.2.7    Arbeitsmappe aktivieren Mit folgender Prozedur wird eine bereits geöffnete Arbeitsmappe aktiviert. Dies benötigen Sie, um eine bestimmte Arbeitsmappe unter mehreren geöffneten Arbeitsmappen für die weitere Bearbeitung auszuwählen. Sub MappeAktivieren()

ThisWorkbook.Activate

MsgBox ActiveWorkbook.Name

End Sub

Listing 2.7     Sub »MappeAktivieren()« in Mappe2.xlsm, Modul 1

Es wird die Methode Activate() des Objekts Workbook aufgerufen. Dadurch wird die angesprochene Arbeitsmappe, in diesem Fall diese Arbeitsmappe, aktiviert. Zur Kontrolle wird der Name der aktiven Arbeitsmappe ausgegeben.

2.2.8    Arbeitsmappe speichern Mit folgender Prozedur wird diese Arbeitsmappe auf zwei verschiedene Arten gespeichert: Sub MappeSichern()

ThisWorkbook.Save

ThisWorkbook.SaveAs "C:\Temp\Mappe2.xlsm"

MsgBox "Gesichert: " & ThisWorkbook.Saved

End Sub

Listing 2.8     Sub »MappeSichern()« in Mappe2.xlsm, Modul 1

Die Methode Save() des Objekts Workbook wird aufgerufen. Dadurch wird diese Arbeitsmappe gespeichert.

Zusätzlich wird die Methode SaveAs() des Objekts Workbook aufgerufen. Dadurch wird diese Arbeitsmappe noch einmal gespeichert, und zwar im Verzeichnis C:\Temp unter dem Namen Mappe2.xlsm. Anschließend arbeiten Sie in der soeben angelegten Kopie der Mappe (!). Zur Kontrolle wird der Wert der Eigenschaft Saved ermittelt und ausgegeben. Dabei handelt es sich um einen sogenannten Wahrheitswert: False (falsch) oder True (wahr). Da die Arbeitsmappe soeben gespeichert wurde, ist der Wert aktuell True (siehe Abbildung 2.8). Nach einer Änderung in der Arbeitsmappe hätte die Eigenschaft den Wert False.

Abbildung 2.8     Eigenschaft »Saved«

[»]  Hinweis Sie können den Wert der Eigenschaft Saved in einer Verzweigung (siehe Abschnitt 3.4, »Verzweigungen«) nutzen. Je nach Wert der Eigenschaft (True oder False) wird gespeichert.

2.2.9    Arbeitsmappe über Index oder Namen auswählen Mit folgender Prozedur werden Arbeitsmappen, die bereits geöffnet sind, nacheinander mit zwei verschiedenen Techniken aktiviert: Sub MappeAusListe()

Workbooks(1).Activate

MsgBox ActiveWorkbook.Name

Workbooks("Mappe2.xlsm").Activate

MsgBox ActiveWorkbook.Name

End Sub

Listing 2.9     Sub »MappeAusListe()« in Mappe2.xlsm, Modul 1

Zunächst wird eine geöffnete Arbeitsmappe über den Index ausgewählt. Der Index ist die laufende Nummer der Arbeitsmappe in der Workbooks-Auflistung, von 1 bis zur Nummer des letzten Elements, die der Anzahl der Elemente der Auflistung entspricht (Eigenschaft Count). Sind zwei Arbeitsmappen geöffnet, können Sie nur die Indizes 1 oder 2 nutzen. Wählen Sie einen anderen Index aus, erfolgt ein Abbruch mit einer Fehlermeldung. Wie erwähnt, werden Sie in Kapitel 4, »Fehlerbehandlung«, lernen, wie Sie solche Abbrüche vermeiden. Es ist nicht immer leicht, festzustellen, welches gerade die Arbeitsmappe Nummer 1, 2 usw. ist. Daher ist die nachfolgende Methode vorzuziehen. Eine bereits geöffnete Arbeitsmappe wird über ihren Namen (in doppelten Anführungszeichen) ausgewählt. Dabei handelt es sich um den reinen Dateinamen, ohne Pfad. Sie können in Excel nicht gleichzeitig zwei Dateien mit dem gleichen Namen öffnen, selbst wenn sie in unterschiedlichen Verzeichnissen stehen. Daher ist der ausgewählte Dateiname eindeutig.

2.2.10    Pfad einer Arbeitsmappe ermitteln Häufig ist der Zugriff auf Arbeitsmappen im selben Verzeichnis oder in einem Unterverzeichnis erforderlich. Dazu wird zunächst der Pfad dieser Arbeitsmappe (die den VBA-Code enthält) oder der Pfad der aktuellen Arbeitsmappe ermittelt. Ein Beispiel, in dem der Pfad von drei verschiedenen Arbeitsmappen ermittelt wird: Sub PfadErmitteln()

Workbooks.Open "C:\Temp\Mappe1.xlsm"

MsgBox "Die Mappe Mappe1 ist in: " & ActiveWorkbook.Path

ActiveWorkbook.Close

MsgBox "Diese Mappe ist in: " & ThisWorkbook.Path

Workbooks.Open ThisWorkbook.Path & "\Zusatz\Test.xlsx"

MsgBox "Die Mappe Test ist in: " & ActiveWorkbook.Path

ActiveWorkbook.Close

End Sub

Listing 2.10     Sub »PfadErmitteln()« in Mappe2.xlsm, Modul 1

Zunächst wird die Arbeitsmappe C:\Temp\Mappe1.xlsm geöffnet. Dies ist jetzt die aktive Arbeitsmappe. Ihr Name wird ausgegeben, außerdem der Pfad zu ihrem Verzeichnis mithilfe der Eigenschaft Path (siehe Abbildung 2.9). Dann wird sie wieder geschlossen.

Abbildung 2.9     Pfad der Mappe »Mappe1«

Anschließend wird der Pfad zu dieser Arbeitsmappe ausgegeben, in der sich die oben angegebene Prozedur PfadErmitteln() befindet (siehe Abbildung 2.10).

Abbildung 2.10     Pfad »dieser« Mappe

Es wird erneut die Arbeitsmappe Mappe1.xlsm geöffnet. Diese steht im selben Verzeichnis wie diese Arbeitsmappe, in der sich die oben angegebene Prozedur PfadErmitteln() befindet. Diese Methode wird häufig benötigt, um sicherzugehen, dass eine Datei geöffnet wird, die im selben Verzeichnis steht. Die Arbeitsmappe Mappe1.xlsm wird wieder geschlossen. Zuletzt wird die Arbeitsmappe Test.xlsx geöffnet. Diese steht im Unterverzeichnis Zusatz des Verzeichnisses dieser Arbeitsmappe

(siehe Abbildung 2.11). Ihr Name und ihr Pfad werden ausgegeben, anschließend wird sie wieder geschlossen.

Abbildung 2.11     Pfad der Mappe »Test«

2.3    Tabellenblätter bearbeiten Das Objekt Worksheets ist eine Auflistung, in der sich alle Tabellenblätter einer Arbeitsmappe befinden. Für den Zugriff auf ein einzelnes Tabellenblatt gibt es verschiedene Möglichkeiten: Sie arbeiten mit ActiveSheet. Damit wird das aktuell aktive Arbeitsblatt bezeichnet. Sie verwenden Worksheets(Index). Mit Index ist die laufende Nummer des Tabellenblatts in der Worksheets-Auflistung gemeint, von 1 bis zur Nummer des letzten Elements, die der Anzahl der Elemente entspricht (Count). Sie nutzen Worksheets("Name"). Bei Name wird der Name des Tabellenblatts als Zeichenkette (in doppelten Anführungszeichen) angegeben. [»]  Hinweis In den folgenden Beispielen für den Einsatz von Worksheets wird jeweils vorher diese Arbeitsmappe aktiviert. Dies dient der eindeutigen Zuordnung für den Fall, dass mehrere Arbeitsmappen geöffnet sind. Möchten Sie die Beispiele und ihre Ergebnisse nachvollziehen, stellen Sie sicher, dass Ihre Arbeitsmappe zumindest die drei Tabellen mit den Namen Tabelle1, Tabelle2 und Tabelle3 enthält.

2.3.1    Tabellenblatt erzeugen

Mit folgender Prozedur wird in dieser Arbeitsmappe ein neues Tabellenblatt erzeugt: Sub NeuesBlatt()

ThisWorkbook.Activate

MsgBox Worksheets.Count

Worksheets.Add

ActiveSheet.Name = "Neu"

MsgBox Worksheets.Count

End Sub

Listing 2.11     Sub »NeuesBlatt()« in Mappe2.xlsm, Modul 2

Zunächst wird zur Kontrolle die Anzahl der Tabellenblätter dieser Arbeitsmappe (der Wert der Eigenschaft Count des Objekts Worksheets) ermittelt und ausgegeben. Die Methode Add() des Objekts Worksheets wird aufgerufen. Damit wird ein neues Tabellenblatt erzeugt (siehe Abbildung 2.12). Es wird dann automatisch zum aktiven Tabellenblatt. Durch die Angabe von Parametern bestimmen Sie, an welcher Stelle das neue Tabellenblatt eingefügt wird, siehe Abschnitt 2.3.2, »Tabellenblatt kopieren«. Die Bezeichnung ActiveSheet bezeichnet das aktuell aktive Tabellenblatt. Der Name eines Tabellenblatts kann ermittelt bzw. geändert werden. Zur Kontrolle wird wiederum die Anzahl der Tabellenblätter ausgegeben. Sie hat sich erwartungsgemäß um 1 erhöht.

Abbildung 2.12     Neu erzeugtes Tabellenblatt

[»]  Hinweis Führen Sie die Sub-Prozedur NeuesBlatt() ein zweites Mal aus, kommt es zu einer Fehlermeldung. Es wird zwar ein weiteres Tabellenblatt erzeugt, dieses kann jedoch nicht in »Neu« umbenannt werden, weil bereits ein Tabellenblatt mit diesem Namen existiert.

2.3.2    Tabellenblatt kopieren Mit folgender Prozedur wird ein Tabellenblatt dieser Arbeitsmappe kopiert: Sub BlattKopieren()

ThisWorkbook.Activate

Worksheets("Tabelle1").Copy After:=Worksheets("Tabelle1")

ActiveSheet.Name = "Tab1Kopie"

End Sub

Listing 2.12     Sub »BlattKopieren()« in Mappe2.xlsm, Modul 2

Die Methode Copy() des Objekts Worksheets wird aufgerufen. Dadurch wird ein Tabellenblatt kopiert. Es wird hinter einem Tabellenblatt in der gleichen Arbeitsmappe eingefügt, und es wird zum aktiven Tabellenblatt (siehe Abbildung 2.13). Auf beide Tabellenblätter wird über ihren Namen zugegriffen.

Abbildung 2.13     Kopiertes Tabellenblatt

Bei After handelt es sich um einen benannten Parameter. Solche Parameter werden mithilfe des Operators := (Doppelpunkt und

Gleichheitszeichen) angegeben. Statt After ist auch Before möglich. Dann wird das Tabellenblatt vor einem anderen Tabellenblatt in der gleichen Arbeitsmappe eingefügt. Wird kein Parameter angegeben, wird eine neue Arbeitsmappe erzeugt, die die Kopie enthält. Zum Abschluss wird der Name des Tabellenblatts geändert. [»]  Hinweis Hat eine Methode mehrere Parameter, werden sie häufig als benannte Parameter aufgerufen, siehe Abschnitt 5.3.6, »Benannte Parameter«. Das bietet folgende Vorteile: Der Parameter wird eindeutig angesprochen. Nicht alle Parameter, die möglich sind, müssen genannt werden. Das Programm wird lesbarer.

2.3.3    Tabellenblatt verschieben Mit folgender Prozedur wird ein Tabellenblatt dieser Arbeitsmappe verschoben. Die zugehörige Methode Move() arbeitet sehr ähnlich wie die Methode Copy(): Sub BlattVerschieben()

ThisWorkbook.Activate

Worksheets("Tab1Kopie").Move Before:=Worksheets("Tabelle1")

End Sub

Listing 2.13     Sub »BlattVerschieben()« in Mappe2.xlsm, Modul 2

Die Methode Move() des Objekts Worksheets wird aufgerufen. Das Tabellenblatt Tab1Kopie wird innerhalb derselben Arbeitsmappe verschoben, und es wird zum aktiven Tabellenblatt (siehe Abbildung 2.14).

Abbildung 2.14     Verschobenes Tabellenblatt

Statt mit Before können Sie auch mit After oder ganz ohne Parameter arbeiten, wie bei Copy().

2.3.4    Tabellenblatt löschen Mit folgender Prozedur werden zwei Tabellenblätter dieser Arbeitsmappe gelöscht: Sub BlattLoeschen()

ThisWorkbook.Activate

Worksheets("Neu").Delete

Worksheets("Tab1Kopie").Delete

End Sub

Listing 2.14     Sub »BlattLoeschen()« in Mappe2.xlsm, Modul 2

Es wird die Methode Delete() des Objekts Worksheets zum Löschen eines Tabellenblatts aufgerufen. Auf beide Tabellenblätter wird über ihren Namen zugegriffen. Es erfolgt jeweils eine Rückfrage.

2.3.5    Tabellenblatt aktivieren Mit folgender Prozedur werden nacheinander zwei Tabellenblätter dieser Arbeitsmappe aktiviert:

Sub BlattAktivieren()

ThisWorkbook.Activate

Worksheets("Tabelle3").Activate

MsgBox ActiveSheet.Name

Worksheets("Tabelle1").Activate

MsgBox ActiveSheet.Name

End Sub

Listing 2.15     Sub »BlattAktivieren()« in Mappe2.xlsm, Modul 2

Es wird die Methode Activate() des Objekts Worksheets zum Aktivieren eines Tabellenblatts aufgerufen. Das benötigen Sie, um ein bestimmtes Tabellenblatt aus mehreren offenen Tabellenblättern zur Weiterarbeit auszuwählen. Aktionen in Zellen oder Bereichen beziehen sich anschließend auf das ausgewählte Tabellenblatt. Zur Kontrolle wird in der Prozedur der Name des jeweils aktiven Tabellenblatts ausgegeben. Stellen Sie vor der Ausführung der Prozedur sicher, dass die genannten Tabellenblätter in der Mappe existieren.

2.3.6    Tabellenblatt formatieren Die Eigenschaft Cells eines Tabellenblatts bietet die Möglichkeit, alle Zellen eines Tabellenblatts zu formatieren. Die Formatierung lässt sich auch auf einzelne Zellen oder Zellbereiche begrenzen – dazu mehr ab Abschnitt 2.4.7, »Zahlenformate anwenden«. Nachfolgend werden alle Zellen des Tabellenblatts Tabelle3 mit der Schriftart Arial und der Schriftgröße 10 formatiert. Sub BlattFormatieren()

ThisWorkbook.Activate

Worksheets("Tabelle3").Cells.Font.Name = "Arial"

Worksheets("Tabelle3").Cells.Font.Size = 10

End Sub

Listing 2.16     Sub »BlattFormatieren()« in Mappe2.xlsm, Modul 2

Die Eigenschaft Cells bietet Zugriff auf alle Zellen eines Tabellenblatts. Die Eigenschaft Font einer Zelle bestimmt die Schriftarteigenschaften. Die Untereigenschaften Name und Size dienen der Festlegung des Namens der Schriftart und der Größe der Schrift. Weitere Formatierungsmöglichkeiten folgen in Abschnitt 2.4.9, »Schrifteigenschaften bestimmen«. An dieser Stelle lässt sich wiederum gut die Objekthierarchie erkennen. Es wird die Untereigenschaft Name der Untereigenschaft Font der Eigenschaft Cells des Tabellenblatts geändert.

2.3.7    Gitternetz, Zeilen- und Spaltenüberschriften Sowohl die feinen Gitternetzlinien der einzelnen Zellen als auch Zeilen- und Spaltenüberschriften lassen sich ein- oder ausblenden. Dies sind eigentlich Eigenschaften des aktiven Fensters und nicht des Tabellenblatts. Sie werden an dieser Stelle aufgeführt, da sie thematisch hierhergehören. Eine Prozedur zum Ausblenden der genannten Objekte: Sub BlattGitternetz()

ThisWorkbook.Activate

Worksheets("Tabelle3").Activate

ActiveWindow.DisplayGridlines = False

ActiveWindow.DisplayHeadings = False

End Sub

Listing 2.17     Sub »BlattGitternetz()« in Mappe2.xlsm, Modul 2

Zunächst wird das gewünschte Tabellenblatt aktiviert. Anschließend greifen Sie mit ActiveWindow auf dieses Tabellenblatt zu. Die Eigenschaft DisplayGridlines bestimmt den Zustand der Gitternetzlinien (ein/aus). Die Eigenschaft DisplayHeadings bestimmt den Zustand der Zeilen- und Spaltenüberschriften

(ein/aus). In Abbildung 2.15 sehen Sie ein Tabellenblatt ohne Gitternetz und Überschriften.

Abbildung 2.15     Tabellenblatt ohne Gitternetz und Überschriften

Möchten Sie die ausgeblendeten Elemente wieder einblenden, tragen Sie in der Prozedur jeweils True statt False ein.

2.3.8    Seite einrichten Vorbereitungen für einen Ausdruck treffen Sie in der Seiteneinrichtung. Zur Automatisierung dieses Vorgangs mithilfe von VBA nutzen Sie die Eigenschaft PageSetup. In der folgenden Prozedur wird aus den zahlreichen Möglichkeiten eine kleine Auswahl getroffen. [»]  Hinweis Einige Anweisungszeilen dieser Prozedur sind sehr lang. Zur besseren Übersicht lassen sie sich mithilfe des Zeichens _ (Unterstrich) in mehrere, übersichtliche Zeilen zerlegen, siehe Abschnitt 3.1.2, »Zeilen zerlegen«.

Sub BlattSeiteneinrichtung()

ThisWorkbook.Activate

Worksheets("Tabelle3").PageSetup.Orientation = xlLandscape

Worksheets("Tabelle3").PageSetup.PrintGridlines = True

Worksheets("Tabelle3").PageSetup.PrintHeadings = True

Worksheets("Tabelle3").PageSetup.Zoom = False

Worksheets("Tabelle3").PageSetup.FitToPagesWide = 1

Worksheets("Tabelle3").PageSetup.FitToPagesTall = 99

Worksheets("Tabelle3").PageSetup.CenterHorizontally = True

Worksheets("Tabelle3").PageSetup.LeftHeader = "Das ist die Kopfzeile"

Worksheets("Tabelle3").PageSetup.CenterFooter = "Seite &P von &N"

End Sub

Listing 2.18     Sub »BlattSeiteneinrichtung()« in Mappe2.xlsm, Modul 2

Die Eigenschaft Orientation bestimmt das Druckformat. Es gibt die Möglichkeiten xlLandscape (Querformat) und xlPortrait (Hochformat). Ähnlich wie beim Einrichten des Anzeigefensters wird mit den Eigenschaften PrintGridlines und PrintHeadings festgelegt, ob die Gitternetzlinien und die Zeilen- und Spaltenüberschriften ausgedruckt werden oder nicht (True oder False). Mit der Eigenschaft Zoom bestimmen Sie den Prozentsatz der Vergrößerung oder Verkleinerung des Tabellenblatts für den Ausdruck. Eine Zahl über 100 sorgt für einen vergrößerten, eine Zahl unter 100 für einen verkleinerten Ausdruck. Der Wert False dient als Vorbereitung für eine Skalierung, die abhängig von der Seitenzahl ist. Ist die Skalierung abhängig von der Seitenzahl, wird mit den Eigenschaften FitToPagesWide und FitToPagesTall jeweils eine Seitenanzahl festgelegt. Damit wird angegeben, auf wie vielen Seiten das Tabellenblatt in der Breite (Wide) und in der Höhe (Tall) ausgedruckt wird. Das Arbeitsblatt kann für den Ausdruck horizontal zentriert (CenterHorizontally = True) oder auch vertikal zentriert

(CenterVertically = True) werden. Den Text und die Anordnung von Kopf- und Fußzeile bestimmen die Eigenschaften …Header und …Footer. Es gibt jeweils die Präfixe Left…, Right… und Center… für die verschiedenen Bereiche. Im vorliegenden Beispiel wurde eine Kopfzeile links und eine Fußzeile zentriert angeordnet. In dem Text, der als Zeichenkette zugewiesen wird, können bestimmte Variablen verwendet werden: Seitennummer: &P Seitenanzahl: &N Druckdatum: &D Druckuhrzeit: &T Pfad zum Verzeichnis der Datei: &Z Dateiname: &F Tabellenblattname: &A

2.4    Auf Zellen und Zellbereiche zugreifen Mithilfe der Objekte Range bzw. Cells haben Sie zahlreiche Möglichkeiten, auf einzelne Zellen oder ganze Zellbereiche eines Tabellenblatts zuzugreifen. Die aktuell aktive Zelle zur Bearbeitung wird mit ActiveCell bezeichnet. [»]  Hinweis In den folgenden Beispielen für den Einsatz von Range und Cells wird jeweils ein bestimmtes Tabellenblatt in dieser Arbeitsmappe aktiviert. Dies dient der eindeutigen Zuordnung für den Fall, dass vorher eine andere Arbeitsmappe oder ein anderes Tabellenblatt aktiviert war.

2.4.1    Zellen über das »Range«-Objekt auswählen Mithilfe des Objekts Range werden sowohl zusammenhängende als auch nicht zusammenhängende Zellbereiche für den weiteren Zugriff ausgewählt. Dabei wird ein Buchstabe für die Spalte und eine Nummer für die Zeile angegeben. Einige Möglichkeiten zur Auswahl sehen Sie in Tabelle 2.1. Range

Beschreibung

Range("A3").Select

einzelne Zelle

Range("A3:F7").Select

zusammenhängender Zellbereich

Range("A3, C5,

mehrere nicht zusammenhängende Zellen

E2").Select

Range

Beschreibung

Range("A8, B2:C4,

mehrere nicht zusammenhängende Zellen bzw. Zellbereiche

E2").Select

Tabelle 2.1     Range-Zellbereiche

Bei den Zellbereichen kann es sich aber auch um ganze Spalten oder Zeilen handeln, wie Tabelle 2.2 zeigt. Range

Beschreibung

Range("A:A").Select

ganze Spalte

Range("C:E").Select

mehrere zusammenhängende Spalten

Range("B:D, F:F, H:I").Select

mehrere nicht zusammenhängende Spalten

Range("3:3").Select

ganze Zeile

Range("3:5").Select

mehrere zusammenhängende Zeilen

Range("3:5, 8:9,

mehrere nicht zusammenhängende Zeilen

12:12").Select Range("A2:B4, 7:8, D:E, G2:H4").Select

eine Mischung aus mehreren Möglichkeiten, siehe Abbildung 2.16

Tabelle 2.2     Range – ganze Spalten, ganze Zeilen

Beachten Sie, dass alle Ausdrücke mit Range jeweils in eine Zeile gehören. Im letzten Beispiel (siehe Abbildung 2.16) wurden insgesamt vier nicht zusammenhängende Bereiche ausgewählt: zwei rechteckige Bereiche (A2:B4 und G2:H4), zwei ganze Spalten (D und E) und zwei

ganze Zeilen (7 und 8). Die aktive Zelle (erkennbar am Rahmen) ist die erste ausgewählte Zelle (A2).

Abbildung 2.16     Range("A2:B4, 7:8, D:E, G2:H4").Select

Mit folgender Prozedur werden Zellbereiche eines ausgewählten Tabellenblatts selektiert. Anschließend wird jeweils die Adresse der aktiven Zelle ausgegeben: Sub ZellenMitRange()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A2").Select

MsgBox ActiveCell.Address

Range("C4:G7").Select

MsgBox ActiveCell.Address

Range("A5, C3:G7").Select

MsgBox ActiveCell.Address

Range("C3:G7, A5").Select

MsgBox ActiveCell.Address

Range("C:D").Select

MsgBox ActiveCell.Address

End Sub

Listing 2.19     Sub »ZellenMitRange()« in Mappe2.xlsm, Modul 3

Das Tabellenblatt Tabelle1 dieser Arbeitsmappe wird aktiviert. Aktionen in Zellen oder Bereichen beziehen sich anschließend auf dieses Tabellenblatt. Die Methode Select() des Objekts Range wird mehrmals zum Auswählen von Zellen aufgerufen. Werden mehrere Zellen ausgewählt, ist die obere linke Zelle des ersten angegebenen Bereichs aktiv. Sie wird über ActiveCell erreicht.

Die Eigenschaft Address enthält die Adresse eines Zellbereichs aus einer oder mehreren Zellen, hier der aktiven Zelle. Nacheinander werden ausgegeben: $A$2, $C$4, $A$5, $C$3 und $C$1. Beachten Sie, dass im dritten und vierten Schritt die gleichen Zellen ausgewählt sind, sich aber die aktive Zelle aufgrund der Reihenfolge unterscheidet.

2.4.2    Zellen über das »Cells«-Objekt auswählen Ein Zugriff auf einzelne Zellen oder ganze Zellbereiche ist auch mithilfe des Objekts Cells möglich. Dabei wird eine Nummer für die Zeile und eine Nummer für die Spalte angegeben. Der Vorteil gegenüber dem Zugriff mit Range: Diese Nummern können leichter mithilfe von Berechnungen in VBA ermittelt werden. Mit der folgenden Prozedur erhalten bestimmte Zellbereiche eines ausgewählten Tabellenblatts einen Wert (siehe Abbildung 2.17): Sub ZellenMitCells()

ThisWorkbook.Worksheets("Tabelle1").Activate

Cells(1, 5).Value = "abc"

Range(Cells(3, 5), Cells(4, 7)).Value = "xyz"

End Sub

Listing 2.20     Sub »ZellenMitCells()« in Mappe2.xlsm, Modul 3

Abbildung 2.17     Mit dem Objekt »Cells« arbeiten

Die Zelle 1, 5 erhält mithilfe der Eigenschaft Value den Wert »abc«. Sie steht in Zeile 1 und Spalte 5, ist also Zelle E1. In Verbindung mit

dem Objekt Range können auch Zellbereiche ausgewählt werden, hier der Zellbereich von Zelle 3, 5 (= Zelle E3) bis Zelle 4, 7 (= Zelle G4).

2.4.3    Zellinhalte verschieben oder kopieren Mit folgender Prozedur werden in einem ausgewählten Tabellenblatt die Inhalte von Zellbereichen verschoben bzw. kopiert. Beides haben Sie bereits in Kapitel 1, »Einführung«, mit Makros durchgeführt, die mehrere Einzelschritte enthalten. Hier wird der Vorgang jeweils in einem Schritt durchgeführt. Das bedeutet: weniger Codezeilen, ein schneller Ablauf und eine bessere Wartbarkeit des Codes: Sub ZellinhalteVerschiebenKopieren()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A1:A2").Cut Destination:=Range("C1")

Range("A5:A6").Copy Destination:=Range("C5")

End Sub

Listing 2.21     Sub »ZellinhalteVerschiebenKopieren()« in Mappe2.xlsm, Modul 3

Die Methode Cut() des Objekts Range wird zum Ausschneiden von Zellen aufgerufen. Ist dabei ein Ziel mit dem optionalen Parameter Destination angegeben, werden die Zellen dorthin verschoben. Ist kein Ziel angegeben, werden die Zellen in die Zwischenablage verschoben und können an anderer Stelle wieder eingefügt werden. Die Methode Copy() des Objekts Range wird zum Kopieren von Zellen aufgerufen. Wie bei der Methode Cut() kann ein Ziel angegeben werden. Ansonsten liegt die Kopie in der Zwischenablage und kann an anderer Stelle wieder eingefügt werden. Den Tabelleninhalt vor Ablauf der Prozedur sehen Sie in Abbildung 2.18.

Abbildung 2.18     Originalinhalte

Den Tabelleninhalt nach Ablauf der Prozedur sehen Sie in Abbildung 2.19.

Abbildung 2.19     Inhalte nach dem Verschieben und Kopieren

2.4.4    Teile von Zellinhalten kopieren Nach der Übernahme eines Zellinhalts in die Zwischenablage haben Sie die Möglichkeit, nur Teile des Inhalts in das Tabellenblatt zu übernehmen, zum Beispiel nur die Werte oder nur die Formate. Ein Beispiel: Sub TeileKopieren()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A1:A2").Copy

Range("C1").PasteSpecial xlPasteValues

Range("A5:A6").Copy

Range("C5").PasteSpecial xlPasteFormats

End Sub

Listing 2.22     Sub »TeileKopieren()« in Mappe2.xlsm, Modul 3

Es wird zweimal die Methode Copy() zum Kopieren eines Bereichs in die Zwischenablage aufgerufen. Anschließend wird jeweils die Methode PasteSpecial() zum Einfügen aufgerufen. Beim ersten Mal werden nur die Werte eingefügt, beim zweiten Mal nur die Formate. Den Tabelleninhalt vor Ablauf der Prozedur sehen Sie in Abbildung 2.20.

Abbildung 2.20     Originalinhalte und -formate

Den Tabelleninhalt nach Ablauf der Prozedur sehen Sie in Abbildung 2.21.

Abbildung 2.21     Inhalte nach dem Kopieren von Werten bzw. Formaten

2.4.5    Zellinhalte löschen Mit folgender Prozedur werden Zellinhalte bzw. Teile davon gelöscht:

Sub ZellinhaltLoeschen()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A1:A2").Clear

Range("A3:A4").ClearContents

Range("A5:A6").ClearFormats

End Sub

Listing 2.23     Sub »ZellinhaltLoeschen()« in Mappe2.xlsm, Modul 3

Die Methode Clear() des Objekts Range dient dem Löschen von Zellinhalten, inklusive Formatierung und Kommentaren. Mithilfe der Methode ClearContents() werden nur die Inhalte gelöscht. Dabei bleiben Formate und Kommentare erhalten. Die Methode ClearFormats() wird zum Löschen der Formate genutzt. Dabei bleiben Inhalte und Kommentare erhalten. Den Tabelleninhalt vor Ablauf der Prozedur sehen Sie in Abbildung 2.22.

Abbildung 2.22     Originalinhalte und -formate

Den Tabelleninhalt nach Ablauf der Prozedur sehen Sie in Abbildung 2.23.

Abbildung 2.23     Inhalte nach dem Löschen von Werten und Formaten

2.4.6    Werte und Formeln eintragen Mit der nachfolgenden Prozedur werden Zahlen, Datumsangaben, Prozentzahlen und Formeln in die betreffenden Zellen des Tabellenblatts Tabelle2 eingetragen. Abhängig von Ihrer ExcelVersion kann es sein, dass es dieses Tabellenblatt noch nicht gibt. Legen Sie es bei Bedarf zunächst an. Sub WerteFormeln()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("A1").Value = 5.8

Range("A2").Value = 1629.9

Range("A3").FormulaLocal = "=SUMME(A1:A2)"

Range("A4").Value = "2023/03/31"

Range("A5").Value = "2022/11/10"

Range("A6").FormulaLocal = "=A4-A5"

Range("A7").Value = 0.125

End Sub

Listing 2.24     Sub »WerteFormeln()« in Mappe2.xlsm, Modul 3

Abbildung 2.24 zeigt das Ergebnis.

Abbildung 2.24     Werte und Formeln eintragen

Mithilfe der Eigenschaft Value wird den Zellen A1, A2 und A7 jeweils ein Zahlenwert zugewiesen. Bei Zahlen mit Nachkommastellen ist ein Punkt statt eines Kommas einzutragen.

Die Formel =SUMME(A1:A2) wird als Wert der Eigenschaft FormulaLocal in der von Excel gewohnten Form (in Deutsch) eingetragen. In der Bearbeitungszeile ist erkennbar, dass der Inhalt von Zelle A3 nach wie vor eine Formel ist. Mehr zu den Formula-Eigenschaften sehen Sie in Abschnitt 8.1, »Formeln zuweisen und lesen«. Bei Datumsangaben dürfen die doppelten Anführungszeichen nicht fehlen. Es empfiehlt sich, die amerikanische Schreibweise zu benutzen. Dann werden die Werte direkt als Datumsangaben erkannt und formatiert. Die Formel =A4-A5 berechnet die Tagesdifferenz zwischen den beiden Datumsangaben.

2.4.7    Zahlenformate anwenden Mit folgender Prozedur werden die Formate für Zahlen, Datumsangaben und Prozentzahlen in Zellen festgelegt: Sub ZellformatZahlen()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("A1:A3").NumberFormatLocal = "#.##0,00 €"

Range("A4:A5").NumberFormatLocal = "TTTT, ""den"" TT. MMMM JJ"

Range("A6").NumberFormatLocal = "0 ""Tage"""

Range("A7").NumberFormatLocal = "0,00 %"

End Sub

Listing 2.25     Sub »ZellformatZahlen()« in Mappe2.xlsm, Modul 3

Das Ergebnis sehen Sie in Abbildung 2.25.

Abbildung 2.25     Zahlenformate anwenden

Mithilfe der Eigenschaft NumberFormatLocal werden Formate in der von Excel gewohnten Form (in Deutsch) eingetragen. Bei Zahlen, Währungs- oder Prozentangaben werden im Beispiel die folgenden Zeichen verwendet: #: Ziffer nur anzeigen, falls vorhanden 0: Ziffer immer anzeigen , (Komma): Nachkommastelle abtrennen . (Punkt): Tausenderpunkt setzen € (Euro): Währungszeichen verwenden % (Prozent): Multiplikation mit 100 und Darstellung mit

Prozentzeichen

Bei Datumsangaben werden im Beispiel die folgenden Zeichen verwendet: TTTT: Name des Wochentags in Deutsch ausschreiben TT: zwei Ziffern für den Tag im Monat anzeigen MMMM: Monatsname in Deutsch ausschreiben JJ: zwei Ziffern für das Jahr anzeigen

Beachten Sie: Wird ein Text in das Format integriert, muss er in Excel in doppelten Anführungszeichen stehen. So entsteht kein Konflikt mit den standardmäßigen Formatangaben. Da aber der Wert der Eigenschaft NumberFormatLocal bereits in doppelten Anführungszeichen steht, muss der integrierte Text in zweifachen doppelten Anführungszeichen stehen.

2.4.8    Zellen ausrichten

Mit folgender Prozedur werden Zellen auf verschiedene Art und Weise ausgerichtet: Sub ZellformatAusrichtung()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("C1").Value = "Hallo"

Range("C1").HorizontalAlignment = xlCenter

Range("C1").VerticalAlignment = xlTop

Range("C2").Value = "Das ist ein längerer Text"

Range("C2").WrapText = True

Range("C3").Value = "Hallo"

Range("C3:C7").MergeCells = True

Range("C3:C7").Orientation = xlVertical

Range("C8").Value = "Hallo"

Range("C8").Orientation = 45

End Sub

Listing 2.26     Sub »ZellformatAusrichtung()« in Mappe2.xlsm, Modul 3

Das Ergebnis ist in Abbildung 2.26 dargestellt.

Abbildung 2.26     Zellen ausrichten

Die horizontale Ausrichtung von Text wird mithilfe der Eigenschaft HorizontalAlignment durchgeführt. Zulässige Konstanten sind

xlLeft (linksbündig), xlRight (rechtsbündig), xlCenter (zentriert)

und xlJustify (Blocksatz).

Die Eigenschaft VerticalAlignment dient zur vertikalen Ausrichtung von Text. Zulässige Konstanten sind xlBottom (am unteren Rand), xlCenter (vertikal zentriert) und xlTop (am oberen Rand). Mehr zum Thema Konstanten finden Sie in Abschnitt 3.2.5, »Konstanten«. Die Eigenschaft WrapText bestimmt die Anordnung längerer Texte. Hat sie den Wert True, wird der Text in der Zelle über mehrere Zeilen verteilt. Hat sie den Wert False, wird der Text in einer einzelnen Zeile geschrieben, die gegebenenfalls über den rechten Rand der Zelle hinausgeht. Mit der Eigenschaft MergeCells wird festgelegt, ob Zellen miteinander verbunden werden. Hat sie den Wert True, werden die Zellen des genannten Bereichs miteinander verbunden. Hat sie den Wert False, werden die Zellen des genannten Bereichs einzeln dargestellt. Die einzelnen Zeichen eines Zellinhalts können mithilfe der Eigenschaft Orientation auf unterschiedliche Art geschrieben werden, zum Beispiel übereinander mit dem Wert xlVertical oder in einem schrägen Winkel mit einem Zahlenwert zwischen – 90 Grad und +90 Grad. Der Normalwert ist 0 Grad.

2.4.9    Schrifteigenschaften bestimmen Mit folgender Prozedur werden die Schrifteigenschaften von Zellen bestimmt: Sub ZellformatSchrift()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("C1").Font.Name = "Tahoma"

Range("C1").Font.Bold = True

Range("C1").Font.Italic = True

Range("C1").Font.Underline = True

Range("C1").Font.Size = 20

Range("C1").Font.Color = vbRed

End Sub

Listing 2.27     Sub »ZellformatSchrift()« in Mappe2.xlsm, Modul 3

Das Ergebnis sehen Sie in Abbildung 2.27.

Abbildung 2.27     Zellenschrift gestalten

Die Eigenschaft Font steht für die Formatierung der Schriftart in der Zelle. Sie hat zahlreiche Untereigenschaften, z. B.: Name für den Namen der Schriftart Bold für das Format »fett« (True oder False) Italic für das Format »kursiv« (True oder False) Underline für das Attribut »unterstrichen« (True oder False) Size für die Größe der Schrift Color für die Farbe der Schrift

Die Grundfarben können vereinfacht mithilfe von Farbkonstanten angegeben werden, hier mit vbRed für Rot. Mehr zu Konstanten sehen Sie in Abschnitt 3.2.5, »Konstanten«. Es gibt folgende Farbkonstanten: vbBlack: Schwarz vbRed: Rot vbGreen: Grün vbYellow: Gelb

vbBlue: Blau vbMagenta: Magenta vbCyan: Cyan vbWhite: Weiß

Zudem steht die Funktion RGB() zur Verfügung. Sie hat drei Parameter, die für die Rot-, Grün- und Blauwerte der Farbe stehen, die jeweils zwischen 0 und 255 liegen. Im Beispiel hätte die folgende Anweisung dasselbe bewirkt: Range("C1").Font.Color = RGB(255, 0, 0).

2.4.10    Einzelne Zeichen formatieren Mit folgender Prozedur werden einzelne Zeichen innerhalb von Zeichenketten formatiert: Sub EinzelneZeichen()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("E2").Value = "x2"

Range("E3").Value = "x3"

Range("E2:E3").Characters(2, 1).Font.Superscript = True

Range("E4:E6").Value = "a38 + a39"

Range("E4:E6").Characters(2, 2).Font.Subscript = True Range("E4:E6").Characters(8, 2).Font.Subscript = True End Sub

Listing 2.28     Sub »EinzelneZeichen()« in Mappe2.xlsm, Modul 3

Das Ergebnis sehen Sie in Abbildung 2.28.

Abbildung 2.28     Einzelne Zeichen formatieren

Die Eigenschaft Characters liefert Teile einer Zeichenfolge. Diese können anschließend formatiert werden. Es müssen zwei Werte festgelegt werden: Die erste Ziffer bestimmt die Stelle, an der die Teilzeichenfolge beginnt. Das erste Zeichen einer Zeichenfolge hat die Nummer 1. Die zweite Ziffer bestimmt die Länge der Teilzeichenfolge. Im ersten Beispiel wird für zwei Zellen die Teilzeichenfolge hinter dem Zeichen x geliefert. Mithilfe der Untereigenschaft Superscript der Font-Eigenschaft des Textes wird dieses Zeichen hochgestellt. Im zweiten Beispiel wird für drei Zellen die Teilzeichenfolge hinter dem Zeichen a geliefert. Mithilfe der Untereigenschaft Subscript der Font-Eigenschaft des Textes werden diese Zeichen tiefgestellt.

2.4.11    Zellbereiche einrahmen Mit folgender Prozedur werden verschiedene Zellbereiche ganz oder teilweise eingerahmt: Sub ZellformatRahmen()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("E2:E3").Borders.LineStyle = xlDouble

Range("E2:E3").Borders.Weight = xlThick

Range("E2:E3").Borders.Color = vbGreen

Range("E4:E6").Borders(xlEdgeLeft).Weight = xlThin

Range("E4:E6").Borders(xlEdgeRight).Weight = xlThin

Range("E4:E6").Borders(xlInsideHorizontal).Weight = xlHairline

End Sub

Listing 2.29     Sub »ZellformatRahmen()« in Mappe2.xlsm, Modul 3

Das Ergebnis sehen Sie in Abbildung 2.29.

Abbildung 2.29     Zellbereiche einrahmen

Die Eigenschaft Borders dient der Bearbeitung des Rahmens: Folgt nach Borders keine weitere Angabe in Klammern, werden die Eigenschaften für alle Rahmenlinien eingestellt, innen wie außen. Zur Bestimmung von Eigenschaften einzelner Rahmenlinien verwenden Sie Konstanten, wie z. B. xlEdgeLeft (linker Rahmen), xlEdgeRight (rechter Rahmen), xlEdgeTop (oberer Rahmen), xlEdgeBottom (unterer Rahmen), xlInsideHorizontal (innere horizontale Zwischenlinien) und xlInsideVertical (innere vertikale Zwischenlinien). Mit der Eigenschaft LineStyle wird die Linienart für den Rahmen festgelegt. Zulässige Konstanten sind z. B. xlContinuous (durchgehende Linie), xlDot (gepunktete Linie) und xlDouble (doppelte Linie). Die Eigenschaft Weight bestimmt die Stärke des Rahmens. Zulässige Konstanten aus der Enumeration xlBorderWeight sind xlHairline (ganz feine Linie), xlThin (feine Linie), xlMedium (mittelstarke Linie) und xlThick (starke Linie). Mehr zu diesem Thema finden Sie in Abschnitt 3.2.5, »Konstanten«.

Durch die Eigenschaft Color wird die Rahmenfarbe bestimmt. Auch hier können Sie mit den Farbkonstanten oder mit der Funktion RGB() arbeiten.

2.4.12    Hintergrundmuster von Zellen gestalten Mit folgender Prozedur wird das Hintergrundmuster der zwei Zellen E3 und E6 gestaltet: Sub ZellformatMuster()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("E2, E6").Interior.Color = vbYellow

End Sub

Listing 2.30     Sub »ZellformatMuster()« in Mappe2.xlsm, Modul 3

Das Ergebnis sehen Sie in Abbildung 2.30.

Abbildung 2.30     Hintergrundmuster von Zellen gestalten

Die Eigenschaft Interior dient der Bearbeitung des Innenbereichs einer Zelle. Sie hat verschiedene Untereigenschaften, u. a. Color für die Innenfarbe.

2.4.13    Zellen einfügen

Mit folgender Prozedur werden Zellbereiche in einem ausgewählten Tabellenblatt eingefügt: Sub ZelleEinfuegen()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A2:A3").Insert Shift:=xlShiftDown

Range("6:7").Insert

End Sub

Listing 2.31     Sub »ZelleEinfuegen()« in Mappe2.xlsm, Modul 3

Es wird die Methode Insert() des Objekts Range zum Einfügen von Zellen aufgerufen. Mithilfe des optionalen Parameters Shift legen Sie fest, was mit den Nachbarzellen passiert. Wird dieser Parameter weggelassen, entscheidet Excel anhand der Bereichsform. Im ersten Fall werden die unteren Nachbarzellen nach unten verschoben. Dazu dient die Konstante xlShiftDown. Die Konstante xlShiftToRight hätte die rechten Nachbarzellen nach rechts verschoben. Im zweiten Fall sind ganze Zeilen ausgewählt. Es kann nur eine Verschiebung nach unten stattfinden. Daher wird der Parameter Shift nicht benötigt. Den Tabelleninhalt vor Ablauf der Prozedur sehen Sie in Abbildung 2.31.

Abbildung 2.31     Originalstruktur der Tabelle

Den Tabelleninhalt nach Ablauf der Prozedur sehen Sie in Abbildung 2.32. [»]  Hinweis Die Anweisung Range("A2:A3").EntireRow.Insert würde zwei neue Zeilen vor den Zeilen 2 und 3 einfügen, da sich der gewählte Zellbereich über Zellen aus zwei Zeilen erstreckt. Die Anweisung Range("A2:A3").EntireColumn.Insert würde eine neue Spalte vor Spalte A einfügen, da sich der gewählte Zellbereich nur über Zellen aus einer Spalte erstreckt.

Abbildung 2.32     Struktur nach dem Einfügen von Zellen und Zeilen

2.4.14    Zellen löschen Mit folgender Prozedur werden Zellbereiche eines ausgewählten Tabellenblatts gelöscht: Sub ZelleLoeschen()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("6:7").Delete

Range("A2:A3").Delete Shift:=xlShiftUp

End Sub

Listing 2.32     Sub »ZelleLoeschen()« in Mappe2.xlsm, Modul 3

Es wird die Methode Delete() des Objekts Range zum Löschen von Zellen aufgerufen. Auch hier gibt es einen optionalen Parameter Shift, mit dem Sie festlegen, was mit den Nachbarzellen passiert. Wird dieser Parameter weggelassen, entscheidet Excel wiederum aufgrund der Bereichsform. Im ersten Fall sind ganze Zeilen ausgewählt. Es kann nur eine Verschiebung (aller Zeilen darunter) nach oben stattfinden. Daher wird auch hier der Parameter Shift nicht benötigt. Im zweiten Fall werden die unteren Nachbarzellen nach oben verschoben. Dazu dient die Konstante xlShiftUp. Die Konstante xlShiftToLeft hätte die rechten Nachbarzellen nach links verschoben. Im vorliegenden Beispiel wird durch das Löschen von Zellen und Zeilen das vorherige Einfügen von Zellen und Zeilen rückgängig gemacht. [»]  Hinweis Die Anweisung Range("A2:A3").EntireRow.Delete würde die Zeilen 2 und 3 löschen. Die Anweisung Range("A2:A3").EntireColumn.Delete würde die gesamte Spalte A löschen.

2.4.15    Zeilenhöhe und Spaltenbreite Mit folgender Prozedur stellen Sie die Höhe bestimmter Zeilen und die Breite bestimmter Spalten ein:

Sub HoeheBreite()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("1:2").RowHeight = 55

Range("B:B,D:D").ColumnWidth = 3

End Sub

Listing 2.33     Sub »HoeheBreite()« in Mappe2.xlsm, Modul 3

Das Ergebnis ist in Abbildung 2.33 dargestellt.

Abbildung 2.33     Zeilenhöhe und Spaltenbreite einstellen

Als Zellbereich werden die Zeilen 1 und 2 sowie die Spalten B und D ausgewählt. Die Eigenschaft RowHeight verändert die Zeilenhöhe. Die Eigenschaft ColumnWidth bestimmt die Spaltenbreite. [»]  Hinweis Die optimale Einstellung der Zeilenhöhe und der Spaltenbreite lässt sich über die Methode AutoFit() des Unterobjekts Columns bzw. Rows erreichen. Zwei Beispiele: Range("G:G").Columns.AutoFit würde die Breite von Spalte G optimal einstellen, Range("1:2").Rows.AutoFit die Höhe der Zeilen 1 und 2.

2.4.16    Benutzten Zellbereich erkennen

Eine nützliche Eigenschaft eines Tabellenblatts ist UsedRange. Dabei handelt es sich um ein Range-Objekt, das den benutzten Zellbereich angibt. Damit ist der kleinste zusammenhängende rechteckige Zellbereich gemeint, der alle nicht leeren Zellen umfasst. Das Problem: Sie sehen nicht immer alle Inhalte einer Zelle. So ist zum Beispiel die Formatierung einer Zelle ohne Inhalt nicht sichtbar. Wird ein Datum in eine Zelle geschrieben und anschließend wieder gelöscht, ist die Zelle nach wie vor mit dem Datumsformat formatiert. Somit wird sie in den UsedRange einbezogen. Um hier sicherzugehen, könnten Sie vor dem Einfügen neuer Daten alle Zellen der Tabelle löschen (mit Cells.Delete). Mit folgender Prozedur werden alle Zellen des benutzten Bereichs durch einen Rahmen und eine Hintergrundfarbe hervorgehoben und gezählt: Sub BenutzterBereich()

ThisWorkbook.Worksheets("Tabelle1").Activate

ActiveSheet.UsedRange.Borders.Color = vbRed

ActiveSheet.UsedRange.Interior.Color = vbYellow

MsgBox "Anzahl: " & ActiveSheet.UsedRange.Count

End Sub

Listing 2.34     Sub »BenutzterBereich()« in Mappe2.xlsm, Modul 3

Nehmen wir an, es wurden die Zellen in Abbildung 2.34 benutzt.

Abbildung 2.34     Zellen mit Inhalt

Der benutzte Zellbereich ergibt sich dann wie in Abbildung 2.35. Mit ActiveSheet.UsedRange werden alle benutzten Zellen des aktiven Tabellenblatts erfasst. Die Eigenschaft Count liefert die Anzahl der Zellen eines Range-Objekts.

Abbildung 2.35     Benutzter Zellbereich

2.4.17    Spezielle Zellen erkennen Die Methode SpecialCells() ist in der Lage, spezielle Zellen zu erkennen. Im folgenden Beispiel werden damit bestimmte Zellen farblich hervorgehoben bzw. gezählt: alle Zellen eines Bereichs, die eine Formel enthalten alle Zellen eines Bereichs, die leer sind die letzte Zelle eines Bereichs, in diesem Fall des benutzten Bereichs Sub SpezielleZellen()

ThisWorkbook.Worksheets("Tabelle2").Activate

' Zellen mit Formeln

Range("A1:A8").SpecialCells(xlCellTypeFormulas). _

Interior.Color = vbYellow

MsgBox "Formeln: " & Range("A1:A9"). _

SpecialCells(xlCellTypeFormulas).Count

' Leere Zellen

Range("A1:A8").SpecialCells(xlCellTypeBlanks). _

Interior.Color = vbCyan

MsgBox "Leer: " & Range("A1:A8"). _

SpecialCells(xlCellTypeBlanks).Count

' Letzte benutzte Zelle

ActiveSheet.UsedRange. _

SpecialCells(xlCellTypeLastCell).Interior.Color = vbGreen

MsgBox "Letzte Zeile: " & ActiveSheet.UsedRange. _

SpecialCells(xlCellTypeLastCell).Row

MsgBox "Letzte Spalte: " & ActiveSheet.UsedRange. _

SpecialCells(xlCellTypeLastCell).Column

End Sub

Listing 2.35     Sub »SpezielleZellen()« in Mappe2.xlsm, Modul 3

Abbildung 2.36 zeigt das Ergebnis. Mithilfe verschiedener Konstanten liefert die Methode SpecialCells() unterschiedliche Bereiche von Zellen zurück: Der Typ xlCellTypeFormulas liefert Zellen, die Formeln enthalten. Hier sind dies die Zellen A3 und A6. Der Typ xlCellTypeBlanks liefert Zellen, die leer sind, hier Zelle A8. Der Typ xlCellTypeLastCell liefert die letzte Zelle eines Bereichs. In diesem Fall ist es der benutzte Zellbereich (UsedRange). Es handelt sich um Zelle E8. Mithilfe der Eigenschaften Row und Column werden die Zeilennummer und die Spaltennummer einer Zelle angegeben, hier der letzten Zelle des benutzten Bereichs.

Abbildung 2.36     Spezielle Zellen

[»]  Hinweis Für ein Range-Objekt wird mit den Eigenschaften Row bzw. Column die Nummer der Zeile bzw. der Spalte der aktiven Zelle des Bereichs ausgegeben. Ein Beispiel: Range("A3:B5").Row ergibt 3 und Range("A3:B5").Column ergibt 1.

2.4.18    Versatz mit Offset vornehmen Mit dem Offset für einen Zellbereich bezeichnen Sie einen zweiten Zellbereich, der gegenüber dem Ursprungsbereich versetzt ist. Dieser Zellbereich ist wiederum ein Range-Objekt. Dieser Versatz kann sowohl in Bezug auf einzelne Zellen als auch in Bezug auf zusammenhängende oder nicht zusammenhängende Zellbereiche angewendet werden. Es folgt ein Beispiel mit Zellbereichen im Tabellenblatt Tabelle3. Stellen Sie vorher sicher, dass es existiert.

Sub ZellOffset()

ThisWorkbook.Worksheets("Tabelle3").Activate

' Offset berechnen

Cells(4, 3).Value = "Ber 1"

Cells(4, 3).Offset(0, 2).Value = "Off(0,2)"

Cells(4, 3).Offset(-3, 1).Value = "Off(-3,1)"

Cells(4, 3).Offset(-2, -1).Value = "Off(-2,-1)"

' Offset eines Bereichs

Range("C6:D8,E9").Value = "Ber 2"

Range("C6:D8,E9").Offset(4, 0).Value = "Off(4,0)"

' Offset-relative Zellen

Cells(4, 3).Offset(0, 2).Range("A2").Value = "A2"

Cells(4, 3).Offset(0, 2).Range("A3").Value = "A3"

Cells(4, 3).Offset(0, 2).Range("B1").Value = "B1"

Cells(4, 3).Offset(0, 2).Range("B2").Value = "B2"

Cells(4, 3).Offset(0, 2).Range("B3").Value = "B3"

End Sub

Listing 2.36     Sub »ZellOffset()« in Mappe2.xlsm, Modul 3

Im Beispiel wird der Offset von der Zelle 4,3 aus berechnet, also von Zelle C4 aus. Zuerst wird der Versatz für die Zeile, dann für die Spalte angegeben. Ist der Ursprungsbereich mithilfe des Cells-Objekts angegeben, ist der versetzte Zellbereich leicht zu ermitteln: Addieren Sie jeweils die Zahlen für die Zeile und die Spalte. Ist ein Offset-Wert positiv, handelt es sich um Zeilen unterhalb oder um Spalten rechts des Ursprungsbereichs. Ist ein Offset-Wert negativ, handelt es sich um Zeilen oberhalb oder um Spalten links des Ursprungsbereichs. Die drei Offset-Angaben für den ersten Zellbereich ergeben: Zelle 4,3 + Offset 0,2 = Zelle 4,5 = Zelle E4 Zelle 4,3 + Offset 3,1 = Zelle 1,4 = Zelle D1 Zelle 4,3 + Offset 2,1 = Zelle 2,2 = Zelle B2 Das Ergebnis für den ersten Zellbereich sehen Sie in Abbildung 2.37.

Abbildung 2.37     Offset berechnen

Ein Beispiel für den Offset eines Bereichs sehen Sie in Abbildung 2.38. Die Offset-Angabe für den nicht zusammenhängenden Zellbereich C6:D8,E9 ergibt einen gleichartigen Zellbereich. Er ist wegen der Angabe Offset(4,0) um vier Zeilen nach unten verschoben.

Abbildung 2.38     Offset eines Bereichs

Ein Beispiel für Offset-relative Zellen sehen Sie ebenfalls in Abbildung 2.38. Die erste Zelle eines Offsets, egal ob einzelne Zelle oder Zellbereich, wird relativ mit A1 bezeichnet. So können Sie auf jede Zelle im Offset eindeutig zugreifen. Hier werden die Zellen A2, A3, B1, B2 und B3 des Offsets hervorgehoben.

2.4.19    Zellbereich sortieren

Die Methode Sort() des Range-Objekts bietet zahlreiche Möglichkeiten, Zellbereiche zu sortieren. Ausgangspunkt ist die Tabelle im Tabellenblatt Tabelle4, die Sie in Abbildung 2.39 sehen.

Abbildung 2.39     Tabelle, die sortiert wird

Diese Tabelle wird zunächst nach der Nummer sortiert. Die oberste Zeile wird als Überschrift erkannt und daher nicht einsortiert: Sub SortierenNummer()

ThisWorkbook.Worksheets("Tabelle4").Activate

Range("A1:C4").Sort Key1:=Range("C1:C4"), Header:=xlYes

End Sub

Listing 2.37     Sub »SortierenNummer()« in Mappe2.xlsm, Modul 4

Das Ergebnis sehen Sie in Abbildung 2.40.

Abbildung 2.40     Sortierung nach der Nummer

Der Zellbereich A1:C4 wird sortiert. Die Methode Sort() hat zahlreiche Parameter. Daher wird mit benannten Parametern gearbeitet: Der Parameter Key1 gibt den Zellbereich an, in dem der Sortierschlüssel steht. Hier ist dies die Spalte mit der Überschrift »Nummer«, also C1:C4.

Standardmäßig wird aufsteigend sortiert. Mithilfe des Parameters Order1 würden Sie festlegen, dass absteigend (xlDescending) sortiert wird. Über den Parameter Header legen Sie fest, ob die oberste Zeile des Bereichs als Überschrift erkannt wird. Der Standard ist xlNo. Hier wird xlYes angegeben. Wird der Wert xlGuess angegeben, entscheidet Excel, ob eine Überschrift vorhanden ist, und reagiert entsprechend. Es folgt die Prozedur für eine Sortierung nach dem Nachnamen und dem Vornamen: Sub SortierenName()

ThisWorkbook.Worksheets("Tabelle4").Activate

Range("A1:C4").Sort Key1:=Range("A1:A4"), _

Key2:=Range("B1:B4"), Header:=xlYes

End Sub

Listing 2.38     Sub »SortierenName()« in Mappe2.xlsm, Modul 4

Abbildung 2.41 zeigt das Ergebnis.

Abbildung 2.41     Sortierung nach dem Nachnamen und dem Vornamen

Der Parameter Key2 gibt den Zellbereich an, in dem der zweite Sortierschlüssel steht. Es wird zunächst nach der ersten Spalte mit den Nachnamen sortiert und bei gleichem Nachnamen nach der zweiten Spalte mit den Vornamen. Es können bis zu drei Sortierschlüssel (Key1 bis Key3) angegeben werden. Eine auf- bzw. absteigende Sortierung wird über die

Parameter Order1 bis Order3 bestimmt.

2.4.20    Mehr als drei Sortierschlüssel Benötigen Sie mehr als drei Sortierschlüssel, nutzen Sie das Objekt Sort des Tabellenblatts. Im nachfolgenden Beispiel im Tabellenblatt Tabelle5 werden insgesamt fünf Sortierschlüssel eingesetzt. Der gewünschte Zellbereich wird zunächst nach dem ersten Schlüssel sortiert. Liegen dabei gleiche Einträge vor, wird nach dem zweiten Schlüssel sortiert usw. Sub SortierenVieleSchluessel()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.Sort.SortFields.Clear

ActiveSheet.Sort.SortFields.Add Range("A1:A6")

ActiveSheet.Sort.SortFields.Add Range("B1:B6")

ActiveSheet.Sort.SortFields.Add Range("C1:C6")

ActiveSheet.Sort.SortFields.Add Range("D1:D6")

ActiveSheet.Sort.SortFields.Add Range("E1:E6")

ActiveSheet.Sort.SetRange Range("A1:E6")

ActiveSheet.Sort.Apply

End Sub

Listing 2.39     Sub »SortierenVieleSchluessel()« in Mappe2.xlsm, Modul 4

Mithilfe der Methode Clear() werden vorhandene alte Sortiereinstellungen aus der Auflistung SortFields der Sortierschlüssel entfernt. Die Methode Add() dient dem Hinzufügen der Bereiche, in denen die Sortierschlüssel stehen, zu der Auflistung SortFields. Im vorliegenden Beispiel wird zunächst nach den Einträgen im Zellbereich A1 bis A6 sortiert. Gibt es Daten, die in diesem Zellbereich übereinstimmen, werden sie nach den Einträgen im Zellbereich B1 bis B6 sortiert usw. Mithilfe der Methode SetRange() wird der Zellbereich festgelegt, der sortiert wird. Die Methode Apply() dient der Ausführung der

Sortierung.

2.5    Ereignisprozeduren schreiben Ereignisse sagen etwas darüber aus, was aktuell mit einem Objekt passiert. Es finden Ereignisse bezüglich Arbeitsmappen, Tabellenblättern oder Zellbereichen statt. Diese Ereignisse können mit VBA-Code verbunden werden, so dass automatisch weitere Aktionen folgen. Der VBA-Code von Ereignissen wird in Klassenmodulen eingetragen. Nach Erstellung einer neuen Arbeitsmappe stehen automatisch die Klassenmodule DieseArbeitsmappe und Tabelle1 zur Verfügung. Ein Doppelklick auf ein Klassenmodul im Projekt-Explorer führt dazu, dass das zugehörige Codefenster angezeigt wird. Oberhalb des Codefensters wählen Sie in der linken Liste das Objekt (Workbook oder Worksheet) und anschließend in der rechten Liste das Ereignis aus. Es wird ein leerer Prozedurrahmen angezeigt, in dem der Code der Ereignisprozedur notiert wird. Noch umfangreicher sind die Möglichkeiten der Ereignisprogrammierung bei eigenen Dialogfeldern. Diese werde ich in Kapitel 10, »Dialogfelder«, beschreiben.

2.5.1    Arbeitsmappe wird geöffnet Mit folgender Prozedur wird beim Öffnen der Arbeitsmappe gleichzeitig eine zweite Arbeitsmappe geöffnet: Private Sub Workbook_Open()

MsgBox ActiveWorkbook.Name

Workbooks.Open "C:\Temp\Mappe1.xlsm"

End Sub

Listing 2.40     Sub »Workbook_Open()« in Mappe2.xlsm,

Klassenmodul »DieseArbeitsmappe«

In der Ereignisprozedur Workbook_Open() wird nach einer Kontrollausgabe eine zweite Arbeitsmappe geöffnet. Testen Sie die Prozedur, indem Sie Excel vollständig schließen und dann die Arbeitsmappe Mappe2.xlsm öffnen, die die oben angegebene Prozedur enthält.

2.5.2    Arbeitsmappe wird geschlossen Mit folgender Prozedur im Klassenmodul DieseArbeitsmappe wird eine Arbeitsmappe vor dem Schließen ohne weitere Nachfrage automatisch gespeichert: Private Sub Workbook_BeforeClose(Cancel As Boolean)

ThisWorkbook.Save

End Sub

Listing 2.41     Sub »Workbook_BeforeClose()« in Mappe2.xlsm,

Klassenmodul »DieseArbeitsmappe«

In der Ereignisprozedur Workbook_BeforeClose() wird die Arbeitsmappe mithilfe der Methode Save() gespeichert. Wie sähe es ohne diese Prozedur aus? Hat der Benutzer die Arbeitsmappe geändert, wird er beim Schließen gefragt, ob er speichern möchte. Diese Prozedur umgeht das, da das Ereignis BeforeClose vor der Nachfrage auftritt. Testen Sie die Prozedur, indem Sie eine Änderung vornehmen und die Arbeitsmappe schließen.

2.5.3    Tabellenblatt wird aktiviert

Mit folgender Prozedur in einem Klassenmodul wird nach dem Aktivieren eines Tabellenblatts eine Zelle ausgewählt. Das gilt unabhängig davon, ob die Aktivierung durch die Benutzerin oder durch VBA-Code erfolgt: Private Sub Worksheet_Activate()

MsgBox ActiveSheet.Name

Range("C5").Select

End Sub

Listing 2.42     Sub »Worksheet_Activate()« in Mappe2.xlsm,

Klassenmodul »Tabelle1«

In der Ereignisprozedur Worksheet_Activate() wird nach einer Kontrollausgabe eine Zelle ausgewählt. Das zugehörige Ereignis tritt bei einer Aktivierung desjenigen Tabellenblatts ein, in dessen Codefenster diese Prozedur steht. Testen Sie die Prozedur, indem Sie auf der Excel-Oberfläche zwischen verschiedenen Tabellenblättern der Arbeitsmappe wechseln.

2.5.4    Zellbereich wird ausgewählt Mit folgender Prozedur in einem Klassenmodul wird nach der Auswahl eines Zellbereichs in der betreffenden Tabelle die Adresse des Zellbereichs ausgegeben: Private Sub Worksheet_SelectionChange(ByVal Target As Range)

MsgBox Target.Address

End Sub

Listing 2.43     Sub »Worksheet_SelectionChange()« in Mappe2.xlsm,

Klassenmodul »Tabelle1«

Ein neu ausgewählter Zellbereich steht über die Objektvariable Target zur Verfügung. Diese Variable verweist auf ein Range-Objekt. Dessen Adresse wird in der Ereignisprozedur

Worksheet_SelectionChange() ermittelt und ausgegeben. Mehr zu

Objektvariablen lesen Sie in Abschnitt 6.4, »Mit Objektvariablen arbeiten«.

Testen Sie die Prozedur, indem Sie verschiedene zusammenhängende bzw. nicht zusammenhängende Zellbereiche (mithilfe der Taste (Strg)) auswählen.

2.5.5    Zelle wird doppelt angeklickt Mit folgender Prozedur in einem Klassenmodul wird bei einem Doppelklick auf eine Zelle die betreffende Zelle formatiert: Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, _

Cancel As Boolean)

Target.Interior.Color = vbGreen

Target.Borders.LineStyle = xlContinuous

Target.Borders.Weight = xlThick

Cancel = True

End Sub

Listing 2.44     Sub »Worksheet_BeforeDoubleClick()« in Mappe2.xlsm,

Klassenmodul »Tabelle1«

Die Ereignisprozedur Worksheet_BeforeDoubleClick() zu einem Tabellenblatt wird durchlaufen. Mit Target wird auf diejenige Zelle verwiesen, auf der der Mauszeiger beim Doppelklick steht. Das Hintergrundmuster und der Rahmen der Zelle werden eingestellt. Über die logische Variable Cancel bestimmen Sie, ob das eigentliche Ereignis, hier der Doppelklick, stattfindet: Mit Cancel = True wird die weitere Verarbeitung abgebrochen. Es findet nur die Formatierung statt. Mit Cancel = False oder ohne diese Anweisung wird fortgefahren, also der Cursor zur Bearbeitung in die Zelle gesetzt. Logische

Variablen werde ich in Abschnitt 3.2.3, »Datentypen«, noch genauer erklären.

2.5.6    Tabellenblatt wird neu berechnet Mit folgender Prozedur in einem Klassenmodul wird eine Spaltenbreite optimal eingestellt, falls an einer beliebigen Stelle im Tabellenblatt eine Neuberechnung stattfand: Private Sub Worksheet_Calculate()

Range("G:G").Columns.AutoFit

End Sub

Listing 2.45     Sub »Worksheet_Calculate()« in Mappe2.xlsm,

Klassenmodul »Tabelle1«

In der Ereignisprozedur Worksheet_Calculate() zu einem Tabellenblatt wird die Breite von Spalte G optimal auf die aktuellen Werte eingestellt. Das Ereignis tritt ein, falls z. B. eine Zelle einen neuen Wert erhalten hat, die in der Berechnungsformel für den Wert einer anderen Zelle vorkommt. Beispiel: In Zelle G3 steht die Formel =G1+G2. Sobald sich G1 oder G2 ändert, tritt das Ereignis Calculate ein.

3    Grundlagen der Programmierung mit VBA Inhalte dieses Kapitels sind Variablen, Datentypen, Operatoren und Kontrollstrukturen im Zusammenspiel mit Excel und seinen Objekten. Im Folgenden lernen Sie die wichtigsten grundlegenden Elemente und Techniken kennen, die Sie zum Schreiben von VBAProgrammen benötigen.

3.1    Allgemeines Vor der Programmierung folgen noch einige allgemeine Tipps. Eine Entwicklerin, ob in VBA oder in einer anderen Programmiersprache, sollte sich um einen guten Programmierstil bemühen. Sie erleichtert sich und anderen damit die Arbeit. Durch eine übersichtliche Schreibweise und eine ausreichende Kommentierung ist der Code von ihr und von anderen besser lesbar und wartbar. Zu einer übersichtlichen Schreibweise gehören z. B. Einrückungen und Leerzeilen. Die Entwicklungsumgebung VBE unterstützt Sie als Entwicklerin mit zahlreichen Hilfestellungen. Einige dieser Hilfestellungen kennen Sie vermutlich schon:

Markieren Sie den Namen eines Objekts oder einer Eigenschaft und betätigen Sie anschließend die Taste (F1), wird die zugehörige Erläuterung eingeblendet. Kann der Begriff nicht eindeutig zugeordnet werden, wird eine Liste mit den möglichen Zuordnungen angezeigt, aus der Sie auswählen. Werden Sie nicht zur richtigen Seite der VBA-Hilfe geleitet oder finden Sie keinen passenden Hinweis für den Weg dorthin, geben Sie einfach den Begriff »VBA« und den Suchbegriff in einer Suchmaschine ein. Meist landen Sie dann schnell auf der richtigen Seite des Microsoft Developer Network (MSDN) für VBA. Sobald Sie eine Zeile beendet haben und zur nächsten Zeile wechseln, werden Korrekturen vorgenommen. Ein Beispiel: Sie schreiben »msgbox activesheet.name«, eventuell sogar mit mehreren unnötigen Leerzeichen hinter msgbox. Im Editor wird dies beim Zeilenwechsel geändert in MsgBox ActiveSheet.Name. Alle Leerzeichenfolgen werden außerdem reduziert zu einem Leerzeichen. Bei einem Wechsel von einer eingerückten Zeile zur nächsten Zeile bleibt die Einrückung erhalten. Dadurch sind Programmstrukturen, wie Prozeduren, Verzweigungen und Schleifen, leichter erkennbar. Sie rücken mehrere Zeilen auf einmal ein, indem Sie sie vollständig markieren und dann die Taste (ê) betätigen. Mit der Tastenkombination (ª)+(ê) machen Sie Einrückungen wieder rückgängig. Sobald Sie einen Punkt hinter den Namen eines Objekts gesetzt haben, erscheint eine Liste der Eigenschaften und Methoden dieses Objekts zur Auswahl. Geben Sie einen oder mehrere Anfangsbuchstaben ein, wird das passende Element in der Liste

ausgewählt. Mit der Taste (ê) fügen Sie das betreffende Listenelement in den Code ein.

3.1.1    Codeblöcke auskommentieren Sie können ganze Codeblöcke als Kommentar setzen, damit der betreffende Code kurzfristig nicht durchlaufen wird. Dies können z. B. Zeilen mit Kontrollausgaben (MsgBox, Debug.Print) sein, die in der Endfassung des Programms nicht mehr benötigt werden. Zur Auskommentierung markieren Sie die betreffenden Zeilen. Anschließend betätigen Sie das Symbol Block auskommentieren in der Symbolleiste Bearbeiten (siehe Abbildung 3.1). Rechts daneben steht das Symbol Auskommentierung des Blocks aufheben, mit dem Sie den VBA-Code wieder aktivieren. Die Symbolleiste Bearbeiten lässt sich über das Menü Ansicht • Symbolleisten einblenden.

Abbildung 3.1     Block auskommentieren und Auskommentierung wieder aufheben

Übung »Code auskommentieren« Verändern Sie das Makro KopieE3E5Neu aus der Übung »Makro ändern«, siehe Abschnitt 1.4, »Makrocode verstehen und ändern«. Kommentieren Sie einzelne Zeilen aus, so dass die drei Zellen E3 bis G3 nur noch in die Zellen E10 bis G10 kopiert werden, aber nicht mehr in die Zellen E5 bis G5. Geben Sie am Ende den Text »Fertig« in einer Nachrichtenbox aus. Testen Sie das veränderte Makro.

3.1.2    Zeilen zerlegen

Lange Programmzeilen lassen sich mithilfe des Zeichens _ (Unterstrich) in mehrere, kürzere Programmzeilen zerlegen. Dies wird hier zum Kopieren eines Tabellenblatts durchgeführt (siehe Abschnitt 2.3.2, »Tabellenblatt kopieren«) – zugegeben in etwas übertriebener Form: Sub BlattKopieren()

ThisWorkbook.Activate

Worksheets _

("Tabelle1"). _

Copy _

After:=Worksheets("Tabelle1")

ActiveSheet.Name = "Tab1Kopie"

End Sub

Listing 3.1     Sub »BlattKopieren()« in Mappe2.xlsm, Modul 2 (geändert)

Am Ende einiger Zeilen steht ein Unterstrich. Dies bedeutet, dass die Anweisung in der nächsten Zeile fortgesetzt wird. Eine übliche Trennstelle ist z. B. ein Leerzeichen, wie hier zwischen Copy und After. Eine Trennstelle darf nicht innerhalb eines Worts oder innerhalb einer Zeichenkette liegen. Hier werden als weitere Trennstellen das Ende des Worts Worksheets und der Punkt vor Copy genutzt. In VBA kommen bei der Referenzierung von Objekten (siehe Abschnitt 6.2) bisweilen sehr lange Objektnamen vor. Das Beispiel zeigt, wie ein solcher Name zerlegt wird.

3.2    Variablen und Datentypen Variablen dienen der vorübergehenden Speicherung von Daten, die sich zur Laufzeit eines Programms ändern können.

3.2.1    Namen, Werte Eine Variable besitzt einen eindeutigen Namen, unter dem sie angesprochen wird. Für diese Namen gelten in VBA die folgenden Regeln: Sie beginnen mit einem Buchstaben. Sie bestehen nur aus Buchstaben, Zahlen und einigen wenigen Sonderzeichen (z. B. dem Unterstrich _). Sie enthalten keine deutschen Umlaute (ä, ö, ü) oder das Eszett (ß). In einem Gültigkeitsbereich darf es keine zwei Variablen mit dem gleichen Namen geben (siehe Abschnitt 5.1, »Gültigkeitsbereiche«). Gültige Namen sind demnach Temperatur, Summe_Werte oder X12. Ungültige Namen sind z. B. 5Tage oder Tag#12. Variablen erhalten ihre Werte durch Zuweisung per Gleichheitszeichen. Einer Variablen sollte vor ihrer ersten Benutzung ein Wert zugewiesen werden, z. B. Temperatur = 25. Dadurch werden Programme lesbarer und fehlerfreier.

3.2.2    Deklarationen

Variablen sollten in Visual Basic immer deklariert werden. Dies beugt Fehlern und unnötig hohem Speicherbedarf vor. Bei einer Deklaration geben Sie den Namen und den Datentyp einer Variablen an. Der Datentyp einer Variablen bestimmt die Art der gespeicherten Information. Der Entwickler wählt den Datentyp danach aus, ob er Text, Zahlen ohne Nachkommastellen, Zahlen mit Nachkommastellen oder z. B. Datumsangaben speichern möchte. Außerdem macht er sich Gedanken über die Größe des Zahlenbereichs, in dem eine Zahl liegt, und verwendet anschließend den Datentyp mit dem geringsten Speicherbedarf. In Abschnitt 3.2.3, »Datentypen«, finden Sie eine Liste der Datentypen mit ihrem Namen, ihrem Speicherbedarf und ihrem Wertebereich. In Kapitel 1, »Einführung«, haben Sie eine Voreinstellung vorgenommen, die für die VBA-Programmierung wichtig ist: Im Menü Extras • Optionen haben Sie auf der Registerkarte Editor ein Häkchen bei Variablendeklaration erforderlich gesetzt. Dies sorgt ab dem nächsten Öffnen von Excel dafür, dass oberhalb des VBA-Codes die Zeile Option Explicit steht und alle Variablen deklariert werden müssen.

3.2.3    Datentypen Tabelle 3.1 enthält die wichtigsten von VBA unterstützten Datentypen sowie deren Speicherbedarf und Wertebereich: Datentyp Speicherbedarf Wertebereich, Bedeutung Boolean

2 Byte

True

oder False (wahr oder falsch)

Byte

1 Byte

ganze Zahl von 0 bis 255

Datentyp Speicherbedarf Wertebereich, Bedeutung Integer

2 Byte

ganze Zahl von –32.768 bis +32.767

Long

4 Byte

lange ganze Zahl von –2,1 × 109 bis +2,1 × 109

Single

4 Byte

Gleitkommazahl mit einfacher Genauigkeit: von ca. –3,4 × 10+38 bis ca. –1,4 × 10–45 für negative Werte und von ca. +1,4 × 10–45 bis ca. +3,4 × 10+38 für positive Werte

Double

8 Byte

Gleitkommazahl mit doppelter Genauigkeit: von ca. –1,8 × 10+308 bis ca. –4,9 × 10–324 für negative Werte und von ca. +4,9 × 10–324 bis +1,9 × 10+308 für positive Werte

Date

8 Byte

Datum vom 1. Januar 100 bis zum 31. Dezember 9999

Object

4 Byte

Verweis auf ein Objekt, siehe Abschnitt 6.4, »Mit Objektvariablen arbeiten«

String

10 Byte (+)

10 Byte plus die Zeichenfolgenlänge, d. h. Zeichenkette mit variabler Länge

Variant

>= 16 Byte

Datentyp nicht explizit festgelegt

(nicht zu empfehlen)

Tabelle 3.1     Datentypen

Mit folgender Prozedur werden Variablen einiger der oben genannten Typen deklariert, mit Werten versehen und in Zellen angezeigt: Sub Variablen()

Dim By As Byte

Dim Bo As Boolean

Dim It As Integer, Lg As Long

Dim Sg As Single, Db As Double

Dim Dt As Date

Dim St As String

By = 200

Bo = True

It = 20000

Lg = 200000

Sg = 0.1 / 7

Db = 0.1 / 7

Dt = "15.08.2022"

St = "Zeichenkette"

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A1").Value = By

Range("A2").Value = Bo

Range("A3").Value = It

Range("A4").Value = Lg

Range("A5").Value = Sg

Range("A6").Value = Db

Range("A5:A6").NumberFormatLocal = "0,00000000000000000000"

Range("A7").Value = Dt

Range("A8").Value = St

Range("A:A").Columns.AutoFit

End Sub

Listing 3.2     Sub »Variablen()« in Mappe3.xlsm, Modul 1

Abbildung 3.2 zeigt das Ergebnis.

Abbildung 3.2     Verschiedene Datentypen

Variablen werden mit Dim deklariert. Mit As wird ihnen ein definierter Datentyp zugewiesen. Es können auch mehrere Variablen in einer Zeile deklariert werden. Beachten Sie dabei: Mit Dim a, b As Integer wird aus a eine Variable vom Datentyp Variant! Richtig heißt es: Dim a As Integer, b As Integer. Logische Variablen des Datentyps Boolean können nur einen der beiden Wahrheitswerte True (wahr) oder False (falsch) annehmen. Bei den Datentypen für Zahlen führt eine Über- oder Unterschreitung des Wertebereichs zu einem Abbruch. Ganze Zahlen werden in Variablen der Datentypen Byte, Integer oder Long mathematisch genau abgespeichert. Zahlen mit Nachkommastellen werden in Variablen der Datentypen Single oder Double mit begrenzter Genauigkeit abgespeichert. Die Zahl 18,55 kann z. B. als 18,549999 abgespeichert werden. In vielen Berechnungen ist diese kleine Ungenauigkeit nicht von Belang. Behalten Sie sie aber im Hinterkopf. Werte für Zahlen mit Nachkommastellen werden im VBA-Code mit einem Dezimalpunkt eingegeben. Die Datentypen Single und Double für solche Zahlen unterscheiden sich in ihrer Genauigkeit. Im Beispiel wurde die Anzahl der in den Zellen angezeigten

Nachkommastellen mithilfe der Eigenschaft NumberFormatLocal auf den Wert 20 gestellt. Der Wert einer Double-Variablen ist mathematisch genauer als der Wert der Single-Variablen. [»]  Hinweis Wird einer Variablen kein definierter Datentyp (mit As) zugewiesen, hat diese Variable den Typ Variant. Verwenden Sie diesen Datentyp möglichst selten, da Variablen dieses Datentyps einen höheren Speicherbedarf haben, langsamer zu verarbeiten und schwerer zu kontrollieren sind. Markieren Sie den Namen einer Variablen. Mit (ª)+(F2) gelangen Sie jetzt zu der Stelle, an der die Variable deklariert wurde. Mit (Strg)+(ª)+(F2) kommen Sie wieder zurück in die Zeile, in der die Variable genutzt wird.

Bei der Eingabe von sehr großen oder sehr kleinen Werten können Sie mit Exponentialzahlen arbeiten. Zwei Beispiele: Die Eingabe 1.5e6 entspricht mathematisch dem Wert 1,5 × 106 und wird vom Editor in den Wert 1500000 umgewandelt. Die Eingabe 1.5e–6 entspricht mathematisch dem Wert 1,5 × 10–6 und wird vom Editor in den Wert 0.0000015 umgewandelt. Werte für Zeichenketten und Datumsangaben werden in doppelten Anführungszeichen angegeben. Bei Datumsangaben ist die Schreibweise TT.MM.JJJJ zu bevorzugen. Zeilenhöhe und Spaltenbreite lassen sich über die Methode AutoFit() des Objekts Columns bzw. Rows optimal einstellen, siehe auch Abschnitt 2.4.15, »Zeilenhöhe und Spaltenbreite«.

Den selten genutzten Datentyp für Zeichenketten mit fester Länge werde ich in Abschnitt 9.4, »Dateien mit wahlfreiem Zugriff«, an einem passenden Beispiel erläutern. Übung »Variablen und Datentypen« Schreiben Sie die Prozedur UebungVariablen(), in der Ihr Nachname, Ihr Vorname, Ihre Adresse, Ihr Geburtsdatum und Ihr Alter jeweils in Variablen eines geeigneten Datentyps gespeichert und anschließend wie in Abbildung 3.3 ausgegeben werden.

Abbildung 3.3     Ausgabe zu Übung »Variablen und Datentypen«

3.2.4    Funktion »TypeName()« Die Funktion TypeName() liefert den Datentyp einer Variablen, eines Zellinhalts oder eines Objekts als Zeichenkette. Ein Beispiel: Sub TypErkennen()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("B2").Value = TypeName(Range("A2").Value)

Range("B3").Value = TypeName(Range("A3").Value)

Range("B4").Value = TypeName(Range("A4").Value)

Range("B5").Value = TypeName(Range("A5").Value)

Range("B6").Value = TypeName(Range("A6").Value)

Range("B7").Value = TypeName(Range("A7").Value)

Range("B8").Value = TypeName(Range("A8").Value)

End Sub

Listing 3.3     Sub »TypErkennen()« in Mappe3.xlsm, Modul 1

In den Zellen B1 bis B8 wird jeweils der Datentyp der linken Nachbarzelle ausgegeben, also der Zellen A1 bis A8. Das Ergebnis sehen Sie in Abbildung 3.4.

Abbildung 3.4     Datentypen

Die Zahlen in den Zellen einer Tabelle werden, ob mit oder ohne Nachkommastellen, als Werte vom Datentyp Double erkannt. Ein Beispiel dazu: Die Zahl in Zelle A5 »weiß nicht mehr«, dass sie ursprünglich einmal eine Single-Variable in einem VBA-Programm war. Es könnte ebenso eine Zahl sein, die der Benutzer von Hand in die Zelle eingetragen hat. Die Funktion TypeName() des VBAProgramms »sieht« nur, dass es sich um eine Zahl handelt, und liefert den Datentyp mit der höchsten Genauigkeit für Zahlen, also Double.

3.2.5    Konstanten Konstanten kommen seltener zum Einsatz als Variablen. Bei Konstanten handelt es sich um vordefinierte Werte verschiedener Datentypen, die während der Laufzeit nicht verändert werden können. Man gibt Konstanten im Allgemeinen aussagekräftige

Namen. Dadurch sind sie leichter zu behalten als die Werte, die sie repräsentieren. Das Programm greift schneller auf Konstanten als auf Variablen zu. Daher sollten Sie Konstanten verwenden, falls der Wert feststeht und sich während des Programmablaufs niemals ändert. Es gibt: Eigene Konstanten: Sie werden von der Entwicklerin an einer zentralen Stelle definiert und an verschiedenen Stellen des Programms genutzt. Der Gültigkeitsbereich von Konstanten ist analog zum Gültigkeitsbereich von Variablen (siehe Abschnitt 5.1, »Gültigkeitsbereiche«). Integrierte Konstanten: Sie sind vordefiniert und können vom Entwickler nicht verändert werden: Beim Einfügen von Zellen verwenden Sie die integrierten Konstanten xlShiftDown und xlShiftToRight. Sie repräsentieren die Zahlen 4.121 bzw. 4.161. Eine andere häufig genutzte Konstante ist vbCrLf für den Zeilenumbruch in einer Nachrichtenbox (MsgBox). Im folgenden Beispiel werden Konstanten und Variablen genutzt: Sub Konstanten()

Const MaxWert As Integer = 55

Dim MinWert As Integer

MinWert = 15

MsgBox MaxWert - MinWert

MinWert = 35

MsgBox MaxWert - MinWert

End Sub

Listing 3.4     Sub »Konstanten()« in Mappe3.xlsm, Modul 1

Die Konstante MaxWert mit dem Datentyp Integer wird festgelegt. Sie kann nicht mehr verändert werden. Dagegen kann die Variable MinWert mit dem Datentyp Integer in der Prozedur ihren Wert verändern.

3.2.6    Enumerationen Enumerationen sind Sammlungen von zusammengehörigen, ganzzahligen Konstanten, die ebenfalls aussagekräftige Namen haben. Als Entwickler können Sie sowohl eigene Enumerationen definieren als auch vordefinierte Enumerationen einsetzen. Im folgenden Beispiel wird eine eigene Enumeration definiert und genutzt. Enum Farbe

Rot

Gelb

Blau

Schwarz = 5

Orange

End Enum

Sub Enumeration()

Dim F As Farbe

F = Orange

MsgBox F

End Sub

Listing 3.5     Definition und Sub-Prozedur in Mappe3.xlsm, Modul 1

Enumerationen werden innerhalb eines Blocks zwischen Enum und End Enum definiert, und zwar außerhalb von Sub-Prozeduren, im Kopf des Moduls direkt unterhalb von Option Explicit. Im Beispiel sehen Sie die Enumeration Farbe mit fünf Elementen: Werden bei der Definition keine Werte zugewiesen, repräsentiert das erste Element den Wert 0, die anschließenden Elemente repräsentieren die nachfolgenden Zahlen: 1, 2, 3 … Wird bei der Definition ein Wert zugewiesen, repräsentiert das betreffende Element diesen Wert (hier: 5), die anschließenden Elemente repräsentieren die nachfolgenden Zahlen (hier: 6, 7, 8 …).

In der Prozedur Enumeration() wird eine Variable des Enumerationstyps Farbe deklariert. Bei der Zuweisung eines Wertes erscheint nach Eingabe des Gleichheitszeichens als Hilfestellung eine Liste der Enumerationswerte. Es dürfen zwar auch andere Werte zugewiesen werden, dies würde aber dem Sinn einer Enumeration widersprechen. Als Ausgabe erscheint der Zahlenwert, den das Element der Enumeration repräsentiert (hier: 6). Es gibt viele vordefinierte Enumerationen. Ein Beispiel aus Abschnitt 2.4.8, »Zellen ausrichten«: Die Eigenschaft Weight bestimmt die Stärke des Rahmens eines Zellbereichs. Zulässige Konstanten aus der Enumeration xlBorderWeight sind xlHairline (ganz feine Linie), xlThin (feine Linie), xlMedium (mittelstarke Linie) und xlThick (starke Linie).

3.3    Operatoren Zum Zusammensetzen von Ausdrücken werden sowohl in den Zellen der Excel-Tabellenblätter als auch in VBA Operatoren verwendet. Sie haben schon den Operator = für die Zuweisung von Werten kennengelernt. Es gibt verschiedene Kategorien von Operatoren. Manche Operatoren arbeiten anders als in Excel. Werden mehrere Operatoren in einem Ausdruck verwendet, bestimmt die Rangfolge der Operatoren (Priorität) die Reihenfolge bei der Bearbeitung. Diese Rangfolge finden Sie in Abschnitt 3.3.5, »Rangfolge der Operatoren«. Sind Sie sich bei der Verwendung dieser Regeln nicht sicher, können Sie die Reihenfolge der Bearbeitung durch Klammern festlegen.

3.3.1    Arithmetische Operatoren Mit arithmetischen Operatoren werden Berechnungen durchgeführt. Tabelle 3.2 listet die arithmetischen Operatoren auf. Operator Beschreibung +

Addition

-

Subtraktion oder Negation

*

Multiplikation

/

Division

\

Ganzzahldivision

Mod

Modulo

Operator Beschreibung ^

Potenzierung

Tabelle 3.2     Arithmetische Operatoren

Division

Beachten Sie bei der mathematischen Division mit dem Operator / den Datentyp der Variablen, in der das Ergebnis gespeichert wird. In den beiden nachfolgenden Prozeduren wird zunächst auf der rechten Seite des Gleichheitszeichens der mathematische Wert 2,6 berechnet. Dieser Wert wird in der ersten Prozedur einer DoubleVariablen zugewiesen, die anschließend den Wert 2,6 besitzt.. Erstes Beispiel: Sub DivisionOhneRunden()

Dim x As Double

x = 13 / 5

MsgBox x

End Sub

Listing 3.6     Sub »DivisionOhneRunden()« in Mappe3.xlsm, Modul 1

In der nachfolgenden zweiten Prozedur wird der Wert 2,6 einer Integer-Variablen zugewiesen, die anschließend den Wert 3 besitzt. Zweites Beispiel: Sub DivisionMitRunden()

Dim x As Integer

x = 13 / 5

MsgBox x

End Sub

Listing 3.7     Sub »DivisionMitRunden()« in Mappe3.xlsm, Modul 1

Ganzzahldivision

Die Ganzzahldivision wird in zwei Schritten durchgeführt. Im ersten Schritt werden Dividend und Divisor einzeln gerundet. Im zweiten Schritt werden die beiden verbliebenen ganzen Zahlen geteilt. Anschließend werden die Ziffern nach dem Komma abgeschnitten. Tabelle 3.3 zeigt einige Beispiele. Ausdruck Ergebnis 19 / 4

4,75

19 \ 4

4

19 \ 4.6

3

19.5 \ 4.2

5

Tabelle 3.3     Ganzzahldivision

Modulo-Operator

Der Modulo-Operator Modberechnet den Rest einer Division. Diese Berechnung wird ebenfalls in zwei Schritten durchgeführt. Im ersten Schritt werden Dividend und Divisor einzeln gerundet. Im zweiten Schritt wird der Rest der Ganzzahldivision ermittelt. Einige Beispiele sehen Sie in Tabelle 3.4. Ausdruck

Ergebnis

19 Mod 4

3

19.5 Mod 3.2

2

Tabelle 3.4     Modulo-Operator

In Excel gibt es die Funktion REST(). Sie berechnet den Rest, ohne vorher zu runden. Die Berechnung des zweiten Beispiels aus

Tabelle 3.4 mit REST(19,5; 3,2) ergibt damit 0,3 statt 2. Potenzierung

Der Potenzierung einer Zahl dient in Excel der Operator ^ (hoch). Diesen Operator gibt es ebenso in VBA. Außerdem gibt es die Funktion POTENZ(). Mit beiden werden dieselben Ergebnisse wie mit dem VBA-Operator ^ ermittelt (Beispiele siehe Tabelle 3.5). Ausdruck Ergebnis 2^5

32

3^2^3

729

2 ^ 5.4

42,2242531447326

-2 ^ 5

–32

Tabelle 3.5     Operator ^ (hoch)

Eine Beispielprozedur, in der eine Reihe von arithmetischen Operatoren eingesetzt wird: Sub ArithmetischeOperatoren()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("C1").Value = 5 * 3 - 6 / 3

Range("C2").Value = 5 * (3 - 6) / 3

Range("C4").Value = 19 / 4

Range("C5").Value = 19 \ 4

Range("C6").Value = 19 \ 4.6

Range("C7").Value = 19.5 \ 4.2

Range("D1").Value = 19 Mod 4

Range("D2").Value = 19.5 Mod 3.2

Range("D4").Value = 2 ^ 5

Range("D5").Value = 3 ^ 2 ^ 3

Range("D6").Value = 2 ^ 5.4

Range("D7").Value = -2 ^ 5

End Sub

Listing 3.8     Sub »ArithmetischeOperatoren()« in Mappe3.xlsm, Modul 1

Das Ergebnis der Berechnungen sehen Sie in Abbildung 3.5.

Abbildung 3.5     Ergebnis der Berechnungen

Multiplikation und Division sind innerhalb eines Ausdrucks gleichrangig und werden von links nach rechts in der Reihenfolge ihres Auftretens ausgewertet. Dasselbe gilt für Addition und Subtraktion innerhalb eines Ausdrucks. Mit Klammern wird diese Rangfolge außer Kraft gesetzt. Operationen in Klammern haben grundsätzlich Vorrang.

3.3.2    Vergleichsoperatoren Vergleichsoperatoren werden in Bedingungen benötigt. Diese wiederum nutzen Sie für Verzweigungen und Schleifen, die der Ablaufsteuerung von Programmen dienen. Verzweigungen arbeiten nach dem gleichen Prinzip wie die Funktion WENN() in Excel. Das Ergebnis einer Bedingung ist einer der beiden Werte, die für eine Variable des Typs Boolean verwendet werden dürfen: True

(wahr) oder False (falsch). Tabelle 3.6 führt die Vergleichsoperatoren auf. Operator Beschreibung
=

größer als oder gleich

=

gleich

ungleich

Tabelle 3.6     Vergleichsoperatoren

Einige Beispiele sehen Sie in Tabelle 3.7. Ausdruck

Ergebnis

5>3

wahr

3 = 3.2

falsch

5 + 3 * 2 >= 12

falsch

Tabelle 3.7     Ausdrücke mit Vergleichsoperatoren

Darüber hinaus gibt es den Operator Like, der dem Mustervergleich dient. Dabei setzen Sie u. a. die Platzhalter * (Stern) für eines oder mehrere Zeichen und ? (Fragezeichen) für genau ein Zeichen ein. Tabelle 3.8 zeigt einige Beispiele. Ausdruck

Ergebnis

Ausdruck

Ergebnis

"abxba" Like "a*a"

wahr

"abxba" Like "a?a"

falsch

"aba" Like "a?a"

wahr

"asdlfigc" Like "a?d?f*c"

wahr

Tabelle 3.8     Operator »Like«

Mithilfe von Like können Sie noch wesentlich komplexere Mustervergleiche durchführen als in den hier genannten Beispielen. Eine Beispielprozedur: Sub VergleichsOperatoren()

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("E1").Value = (5 > 3)

Range("E2").Value = (3 = 3.2)

Range("E3").Value = (5 + 3 * 2 >= 12)

Range("F1").Value = ("abxba" Like "a*a")

Range("F2").Value = ("abxba" Like "a?a")

Range("F3").Value = ("aba" Like "a?a")

Range("F4").Value = ("asdlfigc" Like "a?d?f*c")

End Sub

Listing 3.9     Sub »VergleichsOperatoren()« in Mappe3.xlsm, Modul 1

[»]  Hinweis Die Klammern um die Ausdrücke mit den Vergleichsoperatoren sind für die richtige Auswertung nicht notwendig. Sie dienen der besseren Lesbarkeit.

Das Ergebnis der Vergleiche sehen Sie in Abbildung 3.6.

Abbildung 3.6     Ergebnis der Vergleiche

Übung »Vergleichsoperatoren« Schreiben Sie die Prozedur UebungVergleich(). Ermitteln Sie darin das Ergebnis der beiden folgenden Ausdrücke, speichern Sie es in einer Variablen eines geeigneten Datentyps, und zeigen Sie es an: 12 – 3 >= 4 * 2.5 "Maier" Like "M??er"

3.3.3    Logische Operatoren Logische Operatoren dienen dazu, mehrere Bedingungen zusammenzufassen. Sie werden in Tabelle 3.9 aufgelistet. Operator Beschreibung

Das Ergebnis ist wahr, wenn …

Not

Nicht

… der Ausdruck falsch ist.

And

Und

… beide Ausdrücke wahr sind.

Or

inklusives Oder

… mindestens ein Ausdruck wahr ist.

Xor

exklusives Oder … genau ein Ausdruck wahr ist.

Tabelle 3.9     Logische Operatoren

In Tabelle 3.10 sehen Sie einige Beispiele. Es gilt a = 1, b = 3 und c = 5. Ausdruck

Ergebnis

Not (a < b)

falsch

(b > a) And (c > b)

wahr

(b < a) Or (c < b)

falsch

(b < a) Xor (c > b)

wahr

Tabelle 3.10     Ausdrücke mit logischen Operatoren

Die Funktionsweise der logischen Operatoren entnehmen Sie Tabelle 3.11. Ausdruck 1

Ausdruck 2

Not (Ausdruck 1)

And

Or

Xor

wahr

wahr

falsch

wahr

wahr

falsch

wahr

falsch

falsch

falsch wahr

wahr

falsch

wahr

wahr

falsch wahr

wahr

falsch

falsch

wahr

falsch falsch falsch

Tabelle 3.11     Funktionsweise logischer Operatoren

Eine Beispielprozedur: Sub LogischeOperatoren()

Dim a As Integer, b As Integer, c As Integer

a = 1

b = 3

c = 5

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("G1").Value = Not (a < b)

Range("G2").Value = (b > a) And (c > b)

Range("G3").Value = (b < a) Or (c < b)

Range("G4").Value = (b < a) Xor (c > b)

End Sub

Listing 3.10     Sub »LogischeOperatoren()« in Mappe3.xlsm, Modul 1

Das Ergebnis der Vergleiche sehen Sie in Abbildung 3.7.

Abbildung 3.7     Ergebnis der Vergleiche mit logischen Operatoren

Übung »Logische Operatoren« Schreiben Sie die Prozedur UebungLogisch(). Ermitteln Sie darin das Ergebnis der beiden folgenden Ausdrücke, speichern Sie es in einer Variablen eines geeigneten Datentyps, und zeigen Sie es an: 4 > 3 And –4 > –3 4 > 3 Or –4 > –3

3.3.4    Verkettungsoperator Der Operator & dient der Verkettung von Zeichenketten. Er wird häufig benötigt, um Ergebnisse anschaulich zusammen mit Text darzustellen. Ist einer der Ausdrücke keine Zeichenfolge, sondern eine Zahl oder Datumsangabe, wird er in eine Zeichenfolge verwandelt. Das Gesamtergebnis ist dann wiederum eine Zeichenfolge. Ein Beispiel: Sub VerkettungsOperator()

Dim a As String

Dim s As Single

Dim d As Date

d = "15.08.2022"

s = 4.6

a = "Temperatur: " & s & " Grad am " & d

MsgBox a

End Sub

Listing 3.11     Sub »VerkettungsOperator()« in Mappe3.xlsm, Modul 1

Das Ergebnis der Verkettung sehen Sie in Abbildung 3.8.

Abbildung 3.8     Verkettung unterschiedlicher Daten

3.3.5    Rangfolge der Operatoren Enthält ein Ausdruck mehrere Operatoren, werden die einzelnen Teilausdrücke gemäß der Rangfolge bzw. Priorität der Operatoren ausgewertet (siehe Tabelle 3.12). Rang Operator Beschreibung 1

^

Potenzierung (Exponentialoperator)

2

-

negatives Vorzeichen

3

*

4

\

Ganzzahldivision

5

Mod

Modulo

6

+

7

&

und /

und -

Multiplikation und Division

Addition und Subtraktion Verkettung

Rang Operator Beschreibung 8

=, , ,

Vergleichsoperatoren (das Zeichen = steht für den Vergleich, nicht für die Zuweisung)

=

und Like 9

Not

logisches Nicht

10

And

logisches Und

11

Or

logisches Oder

12

Xor

logisches Oder (exklusiv)

Tabelle 3.12     Rangfolge der Operatoren

Ausdrücke mit Operatoren der gleichen Priorität werden von links nach rechts ausgewertet. Mit Klammern wird die Rangfolge außer Kraft gesetzt. Operationen in Klammern haben grundsätzlich Vorrang. Übung »Rangfolge der Operatoren« Sind die Bedingungen in Tabelle 3.13 wahr oder falsch? Lösen Sie die Aufgabe möglichst auf dem Papier, ohne VBA. Zum Vergleich finden Sie eine Lösung in der Prozedur UebungRangfolge() in Mappe3.xlsm, Modul 2. Nr. Werte

Bedingung

1

a=5 b=10

a>0 And b10

2

a=5 b=10

a>0 Or b10

Nr. Werte

Bedingung

3

z=10 w=100

z0 Or z>w Or w-z=90

4

z=10 w=100

z=11 And z>w Or w-z=90

5

x=1.0 y=5.7 x>=.9 And y=.9 And Not(y0 And n2>0 Or n1>n2 And n217

8

n1=1 n2=17

n1>0 And (n2>0 Or n1>n2) And n217

Tabelle 3.13     Angaben zu Übung »Rangfolge der Operatoren«

3.4    Verzweigungen Der Programmcode wurde bisher sequenziell bearbeitet, d. h. eine Anweisung nach der anderen. Kontrollstrukturen ermöglichen eine Steuerung der Bearbeitung. Sie unterteilen sich in Verzweigungen und Schleifen. Verzweigungen gestatten dem Programm, unterschiedliche Anweisungsblöcke auszuführen. Es gibt die beiden Verzweigungsstrukturen If … Then … Else und Select Case … Dabei wird die Programmausführung aufgrund von Bedingungen an einen bestimmten Anweisungsblock übergeben. Bedingungen werden mithilfe von Vergleichsoperatoren erstellt. Verzweigungen arbeiten nach dem gleichen Prinzip wie die Funktion WENN() in Excel. Gibt es mehr als zwei Möglichkeiten, kann diese Funktion verschachtelt werden. Dies trifft auf die Verzweigungen in VBA ebenfalls zu.

3.4.1    Einzeiliges »If … Then … Else« Das einzeilige If … Then … Else hat folgenden Aufbau: If Bedingung Then Anweisungen1 [ Else Anweisungen2 ]

Bedingungen werden ausgewertet und ergeben entweder wahr oder falsch. Ist das Ergebnis wahr, wird der Then-Teil mit den Anweisungen1 ausgeführt. Ist das Ergebnis falsch und gibt es einen Else-Teil, wird der Else-Teil mit den Anweisungen2 ausgeführt. In der folgenden Prozedur wird das einzeilige If in zwei verschiedenen Beispielen genutzt:

Sub EinzeilenIf()

ThisWorkbook.Worksheets("Tabelle1").Activate

If Range("A1").Value > 100 Then MsgBox "Groß"

If Range("A1").Value < 10 Then MsgBox "Klein" Else MsgBox "Nicht klein"

End Sub

Listing 3.12     Sub »EinzeilenIf()« in Mappe3.xlsm, Modul 1

Für das erste Beispiel gilt: Ist der Wert in der Zelle größer als 100, erfolgt eine Ausgabe, anderenfalls passiert nichts. Beim zweiten Beispiel wird in jedem Fall etwas ausgegeben.

3.4.2    If-Then-Else-Block Für die Ausführung von einzelnen Anweisungen ist das einzeilige If geeignet. Sind mehrere Anweisungen auszuführen, wird der Programmcode schnell unübersichtlich. Dann ist ein If-Then-ElseBlock besser geeignet. Er hat folgenden Aufbau: If Bedingung1 Then

Anweisungen1

[ ElseIf Bedingung2

Anweisungen2 ] ...

[ Else

AnweisungenX ]

End If

Zunächst wird die erste Bedingung geprüft. Trifft sie nicht zu, wird die zweite Bedingung geprüft usw. Das Programm verzweigt zu den Anweisungen hinter der ersten zutreffenden Bedingung. Trifft keine der Bedingungen zu, werden die Anweisungen hinter dem Else ausgeführt, sofern es diesen Else-Zweig gibt. Anderenfalls wird keine Anweisung durchgeführt. Ein If-Then-Else-Block endet immer mit einem End If. In der folgenden Prozedur werden mithilfe von zwei Bedingungen drei verschiedene Fälle unterschieden:

Sub BlockIf()

ThisWorkbook.Worksheets("Tabelle1").Activate

If Range("C1").Value > 100 Then

Range("C1").Font.Size = 14

Range("C1").Font.Italic = True

Range("C1").Font.Underline = True

ElseIf Range("C1").Value < 10 Then

Range("C1").Font.Size = 11

Range("C1").Font.Italic = False

Range("C1").Font.Underline = False

Else

Range("C1").Font.Size = 17

Range("C1").Font.Italic = False

Range("C1").Font.Underline = True

End If

End Sub

Listing 3.13     Sub »BlockIf()« in Mappe3.xlsm, Modul 1

Das Ergebnis der Verzweigung sehen Sie in Abbildung 3.9.

Abbildung 3.9     Der dritte Fall trifft zu.

Je nach Wert der Zelle werden die Schrifteigenschaften »Größe«, »kursiv« und »unterstrichen« eingestellt. Hier ist der Wert weder größer als 100 noch kleiner als 10. Daher trifft der dritte Fall zu. Übung »Verzweigung mit If« Schreiben Sie in der Prozedur UebungIf() ein stark vereinfachtes Programm zur Berechnung der Steuer. Zu einem Gehaltsbetrag, der in Zelle A10 steht, wird der Steuerbetrag berechnet und in der Zelle darunter ausgegeben. Formatieren Sie beide Zellen wie in Abbildung 3.10 gezeigt.

Abbildung 3.10     Beispielwert einschließlich Ergebnis

In Tabelle 3.14 werden die Steuersätze für die jeweiligen Gehälter genannt. Verwenden Sie für die Verzweigung einen IfThen-Else-Block. Gehalt

Steuersatz

bis einschließlich 12.000 €

12 %

größer als 12.000 bis einschließlich 20.000 € 15 % größer als 20.000 bis einschließlich 30.000 € 20 % größer als 30.000 €

25 %

Tabelle 3.14     Angaben zu Übung »Verzweigung mit If«

3.4.3    Select Case Die Anweisung Select Case ... dient als Alternative zum If-ThenElse-Block. Sie ermöglicht die übersichtlichere Gestaltung einer Mehrfachauswahl und ist wie folgt aufgebaut: Select Case Testausdruck

[ Case Ausdrucksliste1

Anweisungen1 ]

[ Case Ausdrucksliste2

Anweisungen2 ] ...

[ Case Else

AnweisungenX ]

End Select

Die Anweisung Select Case ... verwendet einen Testausdruck, der am Beginn der Struktur ausgewertet wird. Sein Wert wird

anschließend der Reihe nach mit den Werten der Ausdruckslisten verglichen. Eine Ausdrucksliste kann aus mehreren Ausdrücken oder einer Bereichsangabe mit dem Schlüsselwort To bestehen. Ein Ausdruck kann aus einem Wert oder einer Bedingung mit dem Schlüsselwort Is bestehen. Bei der ersten Übereinstimmung wird der zugehörige Anweisungsblock ausgeführt und dann mit der nächsten Anweisung hinter dem End Select fortgefahren. Wird keine Übereinstimmung gefunden, wird der optionale Anweisungsblock hinter dem Case Else ausgeführt. In der folgenden Prozedur werden verschiedene Fälle geprüft. Trifft keiner dieser Fälle zu, wird der Case-Else-Zweig ausgeführt: Sub SelectCase()

ThisWorkbook.Worksheets("Tabelle1").Activate

Select Case Range("C1").Value

Case 20, 30, 40 Range("C1").Interior.Color = vbRed

Case Is < 10, Is > 100

Range("C1").Interior.Color = vbGreen

Case 12 To 17

Range("C1").Interior.Color = vbCyan

Case Else

Range("C1").Interior.Color = vbYellow

End Select

End Sub

Listing 3.14     Sub »SelectCase()« in Mappe3.xlsm, Modul 1

Das Ergebnis der Mehrfachauswahl sehen Sie in Abbildung 3.11.

Abbildung 3.11     Der dritte Fall trifft zu.

Der Ausdruck Case 20, 30, 40 bedeutet: »Ist der Wert 20, 30 oder 40 …« Als Nächstes folgt die Ausdrucksliste Case Is < 10, Is > 100. Sie bedeutet: »Ist der Wert kleiner als 10 oder größer als 100 …« Der Ausdruck Case 12 To 17 bedeutet: »Ist der Wert größer als oder gleich 12 und kleiner als oder gleich 17 …«, was hier zutrifft. Der Ausdruck Case Else steht für die restlichen Fälle. Übung »Verzweigung mit Select« Schreiben Sie in der Prozedur UebungSelect() das Programm aus der vorherigen Übung »Verzweigung mit If«. Benutzen Sie hierfür die Verzweigung Select Case.

3.5    Schleifen Schleifen ermöglichen den mehrfachen Durchlauf von Anweisungen. Darin liegt eine besondere Stärke der Programmierung allgemein: die schnelle wiederholte Bearbeitung ähnlicher Vorgänge. Es gibt die folgenden Schleifenstrukturen: Do ... Loop For ... Next For Each ... In ... Next

Mithilfe der ersten beiden Strukturen steuern Sie die Wiederholungen eines Anweisungsblocks, also die Durchläufe der Schleife. Dabei wird der Wahrheitswert eines logischen Ausdrucks (der Schleifenbedingung) oder der Wert eines numerischen Ausdrucks (der Schleifenvariablen) benötigt. Eine Schleife mit For Each ... In ... Next wird im Zusammenhang mit Auflistungen oder Feldern eingesetzt. Mehr dazu in Abschnitt 6.5, »For-Each-Schleife«.

3.5.1    Schleife mit »For … Next« Ist die Anzahl der Schleifendurchläufe bekannt oder vor Beginn der Schleife berechenbar, wird eine Schleife mit For ... Next verwendet. Ihr Aufbau sieht wie folgt aus: For Zahl = Anfang To Ende [ Step = Schritt ]

[ Anweisungen ]

[ Exit For ]

[ Anweisungen ]

Next [ Zahl ]

Die Schleifenvariable Zahl wird zunächst auf den Wert von Anfang gesetzt. Nach jedem Durchlauf wird sie um den Wert von Schritt verändert, also vergrößert oder verkleinert. Wird Step = Schritt nicht angegeben, wird die Variable um 1 vergrößert. Der neue Wert von Zahl wird mit dem Wert von Ende verglichen: Ist die Schrittweite positiv und der Wert von Zahl größer als der Wert von Ende, wird die Schleife beendet, ansonsten nochmals durchlaufen. Ist die Schrittweite negativ und der Wert von Zahl kleiner als der Wert von Ende, wird die Schleife auch beendet, ansonsten ebenso nochmals durchlaufen. Die Anweisung Exit For wird eingesetzt, um die Schleife aufgrund einer besonderen Bedingung unmittelbar zu verlassen. In den folgenden Prozeduren werden drei unterschiedliche Schleifen durchlaufen. Die Ausgaben erfolgen im Tabellenblatt Tabelle2. Stellen Sie vor der Ausführung sicher, dass es existiert. Das erste Beispiel: Sub ForNext1()

Dim i As Integer

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("B1:B10").Clear

For i = 3 To 7

Cells(i, 2).Value = Cells(i, 1).Value * 2

Next i

End Sub

Listing 3.15     Sub »ForNext1()« in Mappe3.xlsm, Modul 1

Abbildung 3.12 zeigt das Ergebnis.

Abbildung 3.12     Schleife mit »i« von 3 bis 7, Schrittweite 1

Die Zahlen 1 bis 10 in Spalte A sind bereits vorhanden. Der Zielbereich wird vorher mit der Methode Clear() gelöscht, da auch die nachfolgenden Ergebnisse hier notiert werden. Als Schleifenvariable dient i. Die Schleife wird erstmalig mit i = 3 und letztmalig mit i = 7 durchlaufen. Es ist keine Schrittweite angegeben, daher beträgt sie 1. Ein weiteres Beispiel: Sub ForNext2()

Dim i As Integer

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("B1:B10").Clear

For i = 3 To 7 Step 2

Cells(i, 2).Value = Cells(i, 1).Value * 2

Next i

End Sub

Listing 3.16     Sub »ForNext2()« in Mappe3.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 3.13.

Abbildung 3.13     Schleife mit »i« von 3 bis 7, Schrittweite 2

Aufgrund der Schrittweite von 2 wird nur jede zweite Zelle bearbeitet. Ein letztes Beispiel: Sub ForNext3()

Dim i As Integer

Dim Ergebnis As Integer

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("B1:B10").Clear

For i = 9 To 2 Step -2

Ergebnis = Cells(i, 1).Value * 2

If Ergebnis < 10 Then Exit For

Cells(i, 2).Value = Ergebnis

Next i

End Sub

Listing 3.17     Sub »ForNext3()« in Mappe3.xlsm, Modul 1

Das Ergebnis ist in Abbildung 3.14 dargestellt. Die Schleife wird, beginnend mit dem größten Wert, mit negativer Schrittweite durchlaufen. Das Rechenergebnis wird zur Verdeutlichung in der Variablen Ergebnis zwischengespeichert. Ist die besondere Bedingung Ergebnis < 10 erfüllt, wird die Schleife mit Exit For vorzeitig verlassen.

Abbildung 3.14     Schleife mit »i« von 9 bis 2, Schrittweite –2, mit »Exit For«

Die Schleifen lassen sich auch mithilfe des Range-Objekts bilden. Nachfolgend eine Alternative für die Prozedur ForNext1(): Sub ForNext4()

Dim i As Integer

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("B1:B10").Clear

For i = 3 To 7

Range("B" & i).Value = Range("A" & i).Value * 2

Next i

End Sub

Listing 3.18     Sub »ForNext4()« in Mappe3.xlsm, Modul 1

Die Zellbezeichnungen von B3 bis B7 bzw. von A3 bis A7 werden mithilfe einer Verkettung gebildet. Mithilfe der nachfolgenden Prozedur wird eine Schleife über mehrere Spalten gebildet: Sub ForNext5()

Dim i As Integer

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("A20:E20").Clear

For i = 1 To 5

Range(Chr(i + 64) & "20").Value = i

Next i

End Sub

Listing 3.19     Sub »ForNext5()« in Mappe3.xlsm, Modul 1

Zur Erzeugung der Buchstaben für die Bezeichnung der Spalte wird die VBA-Funktion Chr() genutzt. Sie liefert zu einer Codenummer aus dem ASCII-Code das zugehörige Zeichen. Die Großbuchstaben von A bis Z haben die Codenummern 65 bis 90. Übung »Schleife mit For« Programmieren Sie in der Prozedur UebungFor() eine Schleife, mit der die in Abbildung 3.15 gezeigten Zahlen in den Zellen D1 bis D7 ausgegeben werden.

Abbildung 3.15     Ergebnis zu Übung »Schleife mit For«

3.5.2    Schleife mit »Do … Loop« Ist die Anzahl der Schleifendurchläufe nicht bekannt bzw. vor Beginn der Schleife nicht berechenbar, wird die Schleife mit Do ... Loop verwendet. Es gibt fünf verschiedene Typen, und zwar mit: Do While ... Loop: Die Bedingung zum Durchlauf der Schleife wird

am Anfang geprüft.

Do ... Loop While: Die Bedingung zum Durchlauf der Schleife wird

am Ende geprüft.

Do Until ... Loop: Die Bedingung zum Abbruch der Schleife wird

am Anfang geprüft.

Do ... Loop Until: Die Bedingung zum Abbruch der Schleife wird

am Ende geprüft.

Do ... Loop: Es gibt keine Bedingung zum Durchlauf oder

Abbruch der Schleife. Zur Beendigung der Schleife sind eine Verzweigung in der Schleife und ein Exit Do notwendig. Ansonsten würde die Schleife endlos weiterlaufen. Die Schleifen mit Do ... Loop While und Do ... Loop Until nennt man auch fußgesteuert: Die Bedingung wird erst am Fuß der Schleife geprüft. Eine solche Schleife wird mindestens einmal durchlaufen. Im Gegensatz dazu gibt es die kopfgesteuerten Schleifen mit Do While ... Loop und Do Until ... Loop: Die Bedingung wird bereits im Kopf der Schleife geprüft. Dabei kann es vorkommen, dass diese Schleife niemals durchlaufen wird. Der allgemeine Aufbau sieht wie folgt aus: Do { [ [ [ Loop

While | Until } Bedingung

Anweisungen ]

Exit Do ]

Anweisungen ]

oder Do

[ [ [ Loop

Anweisungen ]

Exit Do ]

Anweisungen ]

{ While | Until } Bedingung

In den folgenden Prozeduren werden drei der fünf Möglichkeiten genutzt. Es werden jeweils so lange Zahlen addiert, bis die Summe der Zahlen 5 erreicht. Da die Zahlen durch einen

Zufallszahlengenerator erzeugt werden, ist die Anzahl der Schleifendurchläufe nicht vorhersagbar. [»]  Hinweis Der Zufallszahlengenerator wird mithilfe der Funktion Rnd() realisiert. Diese liefert zufällige Zahlen mit einem Wert, der größer als oder gleich 0 und kleiner als 1 ist. Beim Aufruf der Funktion Rnd() fallen die Klammern weg, da sie keine Parameter besitzt. Der Zufallszahlengenerator sollte vor der ersten Benutzung mithilfe der Anweisung Randomize initialisiert werden. Ansonsten werden immer wieder die gleichen Zahlenfolgen geliefert, die dann eben nicht mehr zufällig sind.

Das erste Beispiel: Sub DoLoop1()

Dim i As Integer

Dim Summe As Single

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("C1:C20").Clear

Randomize

i = 1

Summe = 0

Do

Summe = Summe + Rnd

Cells(i, 3).NumberFormatLocal = "0,000"

Cells(i, 3).Value = Summe

i = i + 1

Loop While Summe < 5

Cells(i, 3).Value = "Fertig"

End Sub

Listing 3.20     Sub »DoLoop1()« in Mappe3.xlsm, Modul 1

Der Zielbereich wird zu Beginn mit der Methode Clear() gelöscht, da die Ergebnisse aller drei Beispiele hier erscheinen. Der

Zufallszahlengenerator wird initialisiert. Vor der Schleife wird die Variable i für die Zeilennummer der Ausgabezelle auf 1 gesetzt. Die Variable Summe wird mit dem Wert 0 initialisiert. Dies ist nicht notwendig, gehört aber zum guten Programmierstil. Damit verdeutlichen Sie den Startwert der Summe. In der Schleife wird der Wert der Variablen Summe um eine Zufallszahl zwischen 0 und 1 erhöht. Die Summe wird ausgegeben. Die Variable i für die Zeilennummer der Ausgabezelle wird um 1 erhöht, damit der nächste Wert von Summe in der nächsten Zeile ausgegeben wird. Am Ende der Schleife wird mithilfe von While geprüft, ob die Summe kleiner als 5 ist. Trifft dies zu, läuft die Schleife weiter, andernfalls wird sie beendet. Am Ende der Prozedur wird die Ausgabe »Fertig« erzeugt, siehe Abbildung 3.16.

Abbildung 3.16     Addition zufälliger Zahlen bis zur Grenzsumme 5

Das zweite Beispiel: Sub DoLoop2()

.....

Do

Summe = Summe + Rnd

Cells(i, 3).NumberFormatLocal = "0,000"

Cells(i, 3).Value = Summe

i = i + 1

Loop Until Summe >= 5

Cells(i, 3).Value = "Fertig"

End Sub

Listing 3.21     Sub »DoLoop2()« in Mappe3.xlsm, Modul 1

Der Anfang dieser Prozedur entspricht dem Anfang der vorherigen Prozedur. Am Ende der Schleife wird mithilfe von Until geprüft, ob die Summe größer als oder gleich 5 ist. Trifft dies zu, wird die Schleife beendet, andernfalls läuft sie weiter. Das dritte und letzte Beispiel: Sub DoLoop3()

.....

Do

Summe = Summe + Int(Rnd * 6 + 1)

Cells(i, 3).Value = Summe

i = i + 1

If Summe >= 30 Then Exit Do

Loop

Cells(i, 3).Value = "Fertig"

End Sub

Listing 3.22     Sub »DoLoop3()« in Mappe3.xlsm, Modul 1

Der Anfang dieser Prozedur ist wieder gleich geblieben. In der Schleife wird mithilfe einer Verzweigung geprüft, ob die Summe größer als oder gleich 30 ist. Trifft dies zu, wird die Schleife mit Exit Do abgebrochen, andernfalls läuft sie weiter. In diesem dritten Beispiel wird mit zufälligen ganzen Zahlen gearbeitet. Die Funktion Rnd() liefert Zahlen mit einem Wert, der größer als oder gleich 0 und kleiner als 1 ist. Nach der Multiplikation mit 6 sind diese Werte größer als oder gleich 0 und kleiner als 6. Nach der Addition von 1 sind diese Werte größer als oder gleich 1

und kleiner als 7. Die Funktion Int() schneidet die Nachkommastellen ab. Es ergeben sich zufällige ganze Zahlen von 1 bis 6, also die Zahlen eines Würfels. Übung »Schleife mit Do« Schreiben Sie die Prozedur UebungDo(), mit deren Hilfe eine Zahl, die in der obersten Zelle einer Spalte steht, wiederholt halbiert wird. Alle Zahlen werden, wie in Abbildung 3.17 dargestellt, nacheinander unter der ursprünglichen Zahl ausgegeben. Ist das Ergebnis der Halbierung kleiner als 0,001, wird die Prozedur beendet.

Abbildung 3.17     Ergebnis zu Übung »Schleife mit Do«

Übung »Steuertabelle« In der Übung »Verzweigung mit If« (siehe Abschnitt 3.4.2, »IfThen-Else-Block«) haben Sie ein stark vereinfachtes Programm zur Berechnung der Steuer geschrieben. Erweitern Sie die Lösung, indem Sie in der Prozedur UebungTabelle() zu einer Reihe von Gehältern u. a. den Steuerbetrag berechnen und ausgeben.

In Tabelle 3.15 sind die Steuersätze angegeben. Gehalt

Steuersatz

bis einschließlich 12.000 €

12 %

größer als 12.000 bis einschließlich 20.000 € 15 % größer als 20.000 bis einschließlich 30.000 € 20 % größer als 30.000 €

25 %

Tabelle 3.15     Angaben zu Übung »Steuertabelle«

Es werden für jedes Gehalt von 9.000 € bis 33.000 € in Schritten von 3.000 € folgende vier Werte ausgegeben: das Gehalt, der Steuersatz, der Steuerbetrag und das Gehalt abzüglich des Steuerbetrags. Jedes Gehalt wird mit den zugehörigen Werten in einer Zeile ausgegeben, siehe Abbildung 3.18.

Abbildung 3.18     Ergebnis zu Übung »Steuertabelle«

Übung »Kopfrechnen mit Verzweigung«

Schreiben Sie ein Programm, mit dessen Hilfe die Benutzerin das Kopfrechnen trainiert. Nach dem Betätigen der Schaltfläche Aufgabe stellen (siehe Abbildung 3.19) wird die Prozedur UebungKopfVerzweigung_Aufgabe() aufgerufen. Mit ihrer Hilfe erscheint in den Zellen A1 bis D1 eine Aufgabenstellung. Außerdem wird das richtige Ergebnis berechnet und in Zelle Z1 geschrieben, außerhalb des Sichtbereichs der Benutzerin. Das dient zum späteren Vergleich mit seiner Eingabe. Die Benutzerin addiert die beiden angezeigten Zahlen im Kopf und gibt das Ergebnis in Zelle E1 ein. Nach dem Betätigen der Schaltfläche Eingabe prüfen wird die Prozedur UebungKopfVerzweigung_Pruefen() aufgerufen. Mit ihrer Hilfe wird die Benutzereingabe mit dem richtigen Ergebnis verglichen. Es erscheint eine Nachrichtenbox, entweder mit dem Text »Richtig« oder mit dem Text »Falsch« und dem richtigen Ergebnis, siehe Abbildung 3.20.

Abbildung 3.19     Aufgabenstellung

Abbildung 3.20     Reaktion auf eingetragenes Ergebnis

Die beiden Zahlen sind zufällige ganze Zahlen aus dem Bereich von 1 bis 20. In Abschnitt 1.5, »Makro per Schaltfläche ausführen«, habe ich beschrieben, wie Sie eine Prozedur mithilfe einer Schaltfläche starten.

Übung »Kopfrechnen mit Schleife« Erweitern Sie das Programm aus der Übung »Kopfrechnen mit Verzweigung«. Nach dem Betätigen der Schaltfläche Aufgaben stellen wird die Prozedur UebungKopfSchleife_Aufgabe() aufgerufen. Mit ihrer Hilfe erscheinen in den Zellen A1 bis D5 fünf verschiedene Aufgabenstellungen, siehe Abbildung 3.21. Außerdem werden die richtigen Ergebnisse berechnet und in die Zellen Z1 bis Z5 geschrieben.

Abbildung 3.21     Fünf Aufgabenstellungen

Der Benutzer führt die fünf Additionen im Kopf durch und trägt die Ergebnisse in den Zellen E1 bis E5 ein. Nach dem Betätigen der Schaltfläche Eingaben prüfen wird die Prozedur UebungKopfSchleife_Pruefen() aufgerufen. Mit ihrer Hilfe erscheint eine Nachrichtenbox mit dem Text »Richtig:« und der Anzahl der richtig gelösten Aufgaben, siehe Abbildung 3.22.

Abbildung 3.22     Reaktion auf eingetragene Ergebnisse

4    Fehlerbehandlung Wer programmiert, macht Fehler. In diesem Kapitel lernen Sie, wie Sie Programmierfehler erkennen und wie Sie mit ihnen umgehen. Während der Entwicklung eines Programms treten Fehler auf. Sie lassen sich in drei Gruppen unterteilen: Syntaxfehler, Laufzeitfehler und logische Fehler. Syntaxfehler können mithilfe des Editors vermieden werden. Laufzeitfehler treten zur Laufzeit eines Programms auf. Sie können einen Programmabsturz zur Folge haben, können aber mit der OnError-Anweisung behandelt werden. Logische Fehler sind erfahrungsgemäß am schwersten zu finden. Hier bietet das Debugging eine gute Hilfestellung. Doch zunächst zur wichtigsten Methode zur Vermeidung von Fehlern: der wohlüberlegten und schrittweisen Entwicklung einer Anwendung.

4.1    Eine Anwendung entwickeln Bei der Entwicklung Ihrer eigenen Anwendungen mit VBA und Excel gehen Sie Schritt für Schritt vor. Stellen Sie zuerst einige Überlegungen an, wie die gesamte Anwendung aufgebaut ist, und zwar auf Papier. Aus welchen Teilen besteht sie nacheinander?

Versuchen Sie dann nicht, die gesamte Anwendung mit all ihren komplexen Bestandteilen auf einmal (!) zu schreiben. Dies ist der größte Fehler, den Einsteiger (und manchmal auch Fortgeschrittene) machen können. Schreiben Sie zunächst eine einfache Version des ersten Teils der Anwendung. Anschließend testen Sie diese. Erst nach einem erfolgreichen Test fügen Sie den nächsten Teil hinzu. Nach jeder Änderung testen Sie wiederum. Zeigt sich ein Fehler, so wissen Sie, dass er aufgrund der letzten Änderung aufgetreten ist. Nach dem letzten Hinzufügen haben Sie eine einfache Version Ihrer gesamten Anwendung. Nun ändern Sie einen Teil Ihrer Anwendung in eine komplexere Version ab. Auf diese Weise machen Sie Ihre Anwendung Schritt für Schritt komplexer, bis Sie schließlich die gesamte Anwendung so erstellt haben, wie sie Ihren anfänglichen Überlegungen auf Papier entspricht. Manchmal ergibt sich während der praktischen Programmierung noch die eine oder andere Änderung gegenüber Ihrem Entwurf. Das ist kein Problem, solange sich nicht der gesamte Aufbau ändert. Ist dies allerdings der Fall, kehren Sie noch einmal kurz zum Papier zurück und überdenken den Aufbau. Das bedeutet nicht, dass Sie die bisherigen Teile Ihrer Anwendung löschen müssen, sondern möglicherweise nur ein wenig ändern und anders anordnen. Schreiben Sie Ihre Anwendungen übersichtlich. Falls Sie gerade überlegen, wie Sie drei, vier bestimmte Schritte in Ihrer Anwendung auf einmal machen können: Machen Sie daraus einzelne Anweisungen, die der Reihe nach ausgeführt werden. Dies vereinfacht eine eventuelle Fehlersuche. Möchten Sie (oder andere Personen) Ihre Anwendung später einmal ändern oder erweitern,

gelingt der Einstieg in den Aufbau der Anwendung wesentlich schneller. Sie können die Funktion MsgBox() zur Kontrolle von Werten und zur Suche von logischen Fehlern einsetzen. Zusätzlich können Sie einzelne Teile einer Anwendung, in der Fehler auftreten, als Kommentar kennzeichnen. Damit stellen Sie fest, welcher Teil einer Anwendung fehlerfrei läuft und welcher andere Teil demnach fehlerbehaftet ist. Weitere Methoden zur Fehlersuche erläutere ich in den folgenden Abschnitten.

4.2    Syntaxfehler Syntaxfehler treten in der Entwicklungsphase des Programms auf und haben ihre Ursache in falsch oder unvollständig geschriebenem Programmcode. Bereits beim Schreiben des Codes, spätestens aber beim Starten einer Prozedur, macht VBA auf Syntaxfehler aufmerksam. Der Programmierer erhält eine Warnmeldung und gegebenenfalls einen Hinweis auf die richtige Vorgehensweise. Wird der Fehler nicht behoben, wird eine Ausführung des Programms abgelehnt. Der Editor bietet einige Hilfestellungen zur Vermeidung von Fehlern, die ich in Abschnitt 3.1, »Allgemeines«, erläutert habe. Abbildung 4.1 zeigt ein Beispiel für einen Syntaxfehler. Der Fehler wird während des Schreibens, genauer gesagt beim Zeilenwechsel, bemerkt. Die Fehlerstelle wird markiert, und es wird ein Hinweis auf die richtige Schreibweise gegeben.

Abbildung 4.1     Syntaxfehler

4.3    Laufzeitfehler Die Anweisung On Error dient dem Abfangen von Laufzeitfehlern. Diese treten bei einer unzulässigen Operation auf, z. B. bei einer Division durch 0 oder beim Öffnen einer nicht vorhandenen Datei. Es ist besser, Laufzeitfehler von Anfang an zu unterbinden. Allerdings gibt es Vorgänge, auf die die Entwicklerin keinen Einfluss hat, z. B. eine fehlerhafte Benutzereingabe.

4.3.1    Programm mit Laufzeitfehlern In der folgenden Prozedur wird ein Laufzeitfehler hervorgerufen. Der Inhalt von Zelle A1 wird durch den Inhalt von Zelle A2 geteilt. Das Ergebnis der Division wird in Zelle A3 ausgegeben: Sub LaufzeitFehler()

Dim x As Integer, y As Integer, z As Integer

ThisWorkbook.Worksheets("Tabelle1").Activate

x = Range("A1").Value

y = Range("A2").Value

z = x / y

Range("A3").Value = z

Range("A4").Value = "Fertig"

End Sub

Listing 4.1     Sub »LaufzeitFehler()« in Mappe4.xlsm, Modul 2

Stehen in den beiden Zellen die Zahlen 12 und 3, sieht das Ergebnis erwartungsgemäß wie in Abbildung 4.2 aus.

Abbildung 4.2     Berechnung ohne Laufzeitfehler

Stehen jedoch die Zahlen 12 und 0 in den beiden Zellen, bricht das Programm mit einem Laufzeitfehler ab. Es werden weder ein Ergebnis noch der Text »Fertig« in den Zellen ausgegeben. Stattdessen erscheint ein Dialogfeld mit einer Fehlermeldung (siehe Abbildung 4.3).

Abbildung 4.3     Mathematisch nicht erlaubt

Sie betätigen nun entweder die Schaltfläche Beenden oder die Schaltfläche Debuggen. Im letzteren Fall wird die Zeile, die den Laufzeitfehler erzeugt hat, gelb markiert (siehe Abbildung 4.4).

Abbildung 4.4     Programmzeile mit Division

Das ist in diesem Fall die Zeile z = x / y, da die Division in dieser Zeile vorgenommen wird. Damit erhalten Sie einen weiteren Hinweis zur Fehlerbehebung. Stehen die Zahl »12« und der Text »abc« in den beiden Zellen, bricht das Programm mit einer anderen Fehlermeldung ab, siehe Abbildung 4.5.

Abbildung 4.5     Falscher Datentyp

Betätigen Sie die Schaltfläche Debuggen: In der gelb markierten Zeile (siehe Abbildung 4.6) wird versucht, den Text »abc« einer IntegerVariablen zuzuweisen. Das erzeugt einen Laufzeitfehler.

Abbildung 4.6     Programmzeile mit Zuweisung

Beenden Sie das Debugging nach der Fehleranalyse eines Laufzeitfehlers. Ansonsten stehen Ihnen einige Möglichkeiten und Informationen nicht zur Verfügung, und es ist auch kein Neustart des Programms möglich. Sie beenden das Debugging über den Menüpunkt Ausführen • Zurücksetzen oder über das entsprechende Symbol in der Symbolleiste.

4.3.2    Laufzeitfehler abfangen: »On Error« Die Prozedur OnErrorAnweisung() stellt eine verbesserte Version der Prozedur Laufzeitfehler() dar: Sub OnErrorAnweisung()

Dim x As Integer, y As Integer, z As Integer

ThisWorkbook.Worksheets("Tabelle1").Activate

On Error GoTo Fehler

x = Range("A1").Value

y = Range("A2").Value

z = x / y

Range("A3").Value = z

Range("A4").Value = "Fertig"

Exit Sub

Fehler:

MsgBox Err.Description

Resume Next

End Sub

Listing 4.2     Sub »OnErrorAnweisung()« in Mappe4.xlsm, Modul 1

Das Programm bricht trotz der Werte 12 und 0 in den beiden Zellen nicht ab, sondern zeigt den Fehler wie in Abbildung 4.7 an.

Abbildung 4.7     Fehler wird angezeigt.

Die Anweisung On Error GoTo Fehler bedeutet, dass im Falle eines Laufzeitfehlers in dieser Prozedur zu der Zeile mit der Zeilenmarke Fehler gesprungen wird. Die Zeilenmarke wird gesetzt mit Fehler:, also mit dem Namen der Zeilenmarke und einem Doppelpunkt. Beim Auftreten eines Laufzeitfehlers wird das Fehlerobjekt Err mit Daten versorgt. Sie können z. B. den Wert der Eigenschaft Description ausgeben und erhalten die Beschreibung des Fehlers.

Das Programm läuft bis zum Ende, siehe Abbildung 4.8.

Abbildung 4.8     Es gibt keinen Programmabbruch.

Mit Exit Sub wird eine Prozedur vorzeitig verlassen. Mehr dazu lesen Sie in Abschnitt 5.3.1, »Prozeduren«. Würde diese Anweisung in der vorliegenden Prozedur weggelassen, würden die Anweisungen nach der Zeilenmarke Fehler in jedem Fall durchlaufen, selbst wenn die Zahlen in den Zellen korrekt sind. Die Anweisung Resume Next bedeutet, dass der Programmlauf mit der Anweisung fortsetzt, die der Anweisung mit dem Laufzeitfehler folgt. Steht in Zelle A2 der Text »abc«, erscheint zunächst die Fehlermeldung »Typen unverträglich«, weil dieser Wert der IntegerVariablen y nicht zugewiesen werden kann. Das Programm läuft wegen der Anweisung Resume Next mit der nächsten Anweisung weiter. Da die Variable y nach wie vor den Standardwert 0 hat, erscheint als Nächstes die Fehlermeldung »Division durch Null«.

4.4    Logische Fehler und Debugging Läuft eine Anwendung ohne Syntaxfehler und ohne Laufzeitfehler, liefert aber das falsche Ergebnis, liegt ein logischer Fehler vor. Die Suche nach der Ursache logischer Fehler erfordert häufig intensives Testen und Analysieren der Abläufe und Ergebnisse. VBA stellt mit dem Debugging eine wertvolle Hilfe zur Verfügung.

4.4.1    Einzelschrittverfahren Beim Debuggen lassen Sie ein Programm im Einzelschrittverfahren ablaufen. Bei jedem einzelnen Schritt prüfen Sie die aktuellen Inhalte der Variablen. Als Beispiel dient die Prozedur OnErrorAnweisung(). Für den ersten Durchlauf in Einzelschritten stehen die Zahlen 12 und 3 in den Zellen. Sie beginnen im VBE mit dem Menüpunkt Debuggen • Einzelschritt (Taste (F8)). Ein gelber Pfeil vor einer gelb markierten Zeile kennzeichnet den Punkt, an dem die Prozedur gerade angehalten wurde und auf die Reaktion des Entwicklers wartet. Nach einigen weiteren Einzelschritten (wiederum Taste (F8)) stehen Sie in derjenigen Zeile, die in Abbildung 4.9 mit einem Pfeil hervorgehoben wird.

Abbildung 4.9     Markierte Zeile nach einigen Einzelschritten

Platzieren Sie nun den Cursor über einer der Variablen, sehen Sie ihren aktuellen Wert, z. B. den Wert 12 für x. Sie erkennen auch, dass die Variable z den Wert 0 hat, da die markierte Anweisung noch nicht ausgeführt wurde. Nach dem nächsten Einzelschritt hat die Variable z den Wert 4 erhalten. Die aktuellen Variablenwerte können Sie auch im Direktfenster prüfen. Sie erreichen es über das Menü Ansicht • Direktfenster. Nach der Eingabe von ? im Direktbereich erscheint der jeweilige Wert, siehe Abbildung 4.10. Parallel zu den Variablen können Sie nach jedem Einzelschritt die Inhalte der Zellen des Tabellenblatts betrachten. Diese verändern sich erst, nachdem die entsprechende Prozedurzeile durchlaufen wurde. Mit dem Einzelschrittverfahren verfolgen Sie den Ablauf eines Programms stückweise und lokalisieren den Ursprung eines logischen Fehlers.

Abbildung 4.10     Variablenwerte im Direktfenster

Für den zweiten Durchlauf in Einzelschritten stehen die Zahl 12 und der Text »abc« in den Zellen. Während des Ablaufs sehen Sie zweimal den Sprung zur Fehlermarke (siehe Abbildung 4.11) und die Fortsetzung der Prozedur: bei der Zuweisung des Textes »abc« an die Zahlenvariable y bei der Durchführung der Division

Abbildung 4.11     Sprung zur Fehlermarke

4.4.2    Haltepunkte Dauert Ihnen das Einzelschrittverfahren bei einem umfangreichen Programm zu lange, können Sie mit Haltepunkten (engl. breakpoints) arbeiten. Das Programm durchläuft alle Anweisungen bis zu einem solchen Haltepunkt ohne Unterbrechung. Setzen Sie einen Haltepunkt in eine Zeile kurz vor die Stelle, an der Sie den Ursprung eines Fehlers vermuten: Setzen Sie den Cursor in die gewünschte Zeile, und führen Sie den Menüpunkt Debuggen • Haltepunkt setzen (Taste (F9)) aus. Im Beispiel bietet sich die Zeile an, in der z = x / y berechnet wird (siehe Abbildung 4.12). Das Programm wird über die Taste (F5) gestartet und hält vor Ausführung der Zeile mit dem Haltepunkt an. Ab dieser Zeile können Sie das Programm in Einzelschritten ablaufen lassen und die Werte der Variablen prüfen.

Abbildung 4.12     Gesetzter Haltepunkt

Ein Haltepunkt wird entfernt, indem Sie den Cursor in die betreffende Zeile setzen und wiederum die Taste (F9) betätigen. Eine weitere Möglichkeit zum Setzen oder Entfernen eines

Haltepunkts: Klicken Sie in den grauen Bereich vor der betreffenden Zeile. Es können mehrere Haltepunkte gesetzt werden. Über den Menüpunkt Debuggen • Alle Haltepunkte löschen lassen sich alle Haltepunkte auf einmal entfernen.

5    Mehr über die Programmierung mit VBA In diesem Kapitel erfahren Sie etwas über Datenfelder, die Gültigkeitsbereiche von Variablen und über die Modularisierung von Programmen mit Prozeduren und Funktionen. In Kapitel 3, »Grundlagen der Programmierung mit VBA«, haben Sie die Grundlagen der VBA-Programmierung kennengelernt. Im Folgenden werde ich Sie mit weiteren Elementen und Techniken vertraut machen.

5.1    Gültigkeitsbereiche Gültigkeitsbereiche definieren den Bereich, in dem Variablen gültig sind. Nach ihrer Gültigkeit werden Variablen wie folgt bezeichnet: Lokale Variablen: Sie werden in einer Prozedur mit Dim deklariert. Sie sind nur in der Prozedur gültig und auch nur während des aktuellen Ablaufs der Prozedur. Außerhalb der Prozedur sind sie unbekannt. Beim nächsten Aufruf der Prozedur werden sie neu deklariert und erhalten neue Werte. Die Nutzung lokaler Variablen macht Ihre Anwendung leichter wartbar. Statische Variablen: Sie werden in einer Prozedur mit Static statt mit Dim deklariert. Sie sind ebenfalls nur in der Prozedur gültig,

behalten aber ihren Wert über mehrere Aufrufe der Prozedur hinweg. Ihr aktueller Wert hängt u. a. von der Anzahl der Aufrufe der Prozedur ab. Modulweite Variablen: Sie werden im Deklarationsteil eines Moduls (oberhalb der ersten Prozedur) mit Dim deklariert. In jeder Prozedur dieses Moduls kann auf sie zugegriffen werden. Ihr Wert bleibt während der Laufzeit des Projekts erhalten. Projektweite oder öffentliche Variablen: Sie werden im Deklarationsteil eines Moduls mit Public statt mit Dim deklariert. In jeder Prozedur aller Module des Projekts kann auf sie zugegriffen werden. Ihr Wert bleibt während der Laufzeit des Projekts erhalten. Gibt es mehrere Variablen mit demselben Namen, gelten folgende Regeln: Lokale oder statische Variablen mit demselben Namen in derselben Prozedur sind nicht zulässig. Modulweite Variablen werden in einer Prozedur von lokalen Variablen mit demselben Namen ausgeblendet. Projektweite Variablen werden in einem Modul von modulweiten oder lokalen Variablen mit demselben Namen ausgeblendet. Im folgenden Beispiel werden lokale, statische, modulweite und projektweite Variablen deklariert, in verschiedenen Prozeduren verändert und ausgegeben. Zunächst der Inhalt von Modul1: Option Explicit

Public Px As Integer

Dim Mx As Integer

Sub Gueltigkeit1()

Static Sx As Integer

Dim Lx As Integer

Px = Px + 10

Mx = Mx + 10

Sx = Sx + 10

Lx = Lx + 10

MsgBox "Projektweit Px = " & Px & vbCrLf & _

"Modulweit Mx = " & Mx & vbCrLf & _

"Statisch Sx = " & Sx & vbCrLf & _

"Lokal Lx = " & Lx

End Sub

Sub Gueltigkeit2()

Px = Px + 1

Mx = Mx + 1

MsgBox "Projektweit Px = " & Px & vbCrLf & _

"Modulweit Mx = " & Mx

End Sub

Sub Gueltigkeit3()

Dim Mx As Integer

Mx = Mx + 1

MsgBox "Lokal Mx = " & Mx

End Sub

Listing 5.1     Variablen und drei Sub-Prozeduren in Mappe5.xlsm, Modul 1

Es folgt der Inhalt von Modul2: Sub Gueltigkeit4()

Px = Px + 5

MsgBox "Projektweit Px = " & Px

End Sub

Listing 5.2     Sub »Gueltigkeit4()« in Mappe5.xlsm, Modul 2

Die Variable Px ist projektweit gültig. Sie wird in mehreren Prozeduren, die in verschiedenen Modulen stehen, verändert und ausgegeben. Ihr Wert hängt von der Anzahl und der Reihenfolge der Aufrufe der Prozeduren ab. Die modulweite Variable Mx wird in mehreren Prozeduren, die in Modul 1 stehen, verändert und ausgegeben. Ihr Wert hängt von der Anzahl und der Reihenfolge der Aufrufe der Prozeduren ab. In Modul 2 ist sie unbekannt. Sie wird in der Prozedur Gueltigkeit3() von einer lokalen Variablen mit demselben Namen ausgeblendet.

Die lokale Variable Lx wird in der Prozedur Gueltigkeit1() bei jedem Aufruf neu erzeugt, erhält jedes Mal den Wert 10 und wird ausgegeben. Außerhalb dieser Prozedur ist sie unbekannt. Die statische Variable Sx wird in der Prozedur Gueltigkeit1() verändert und ausgegeben. Ihr Wert hängt von der Anzahl der Aufrufe der Prozedur ab. Außerhalb dieser Prozedur ist sie unbekannt. Die genannten Regeln für die Gültigkeitsbereiche von Variablen gelten ebenso für Konstanten und Enumerationen. Mit Public Const legen Sie eine projektweit bekannte Konstante fest, mit Public Enum definieren Sie eine projektweit bekannte Enumeration.

5.2    Datenfelder Sie verwenden Datenfelder, um auf eine größere Menge zusammengehöriger Daten desselben Datentyps unter einem Namen zuzugreifen. Es gibt ein- und mehrdimensionale Datenfelder. Statische Datenfelder haben eine festgelegte Größe, dynamische eine variable Größe. Große Mengen von Daten werden in einem Datenfeld schneller bearbeitet als in den Zellen eines Tabellenblatts. Schleifen ermöglichen den Zugriff auf alle Elemente eines Datenfelds.

5.2.1    Eindimensionale Datenfelder In der folgenden Prozedur werden sieben Werte aus einer Reihe von Temperaturmessungen in einem eindimensionalen, statischen Datenfeld des Typs Integer gespeichert. Zur Verdeutlichung werden sie anschließend in Zellen ausgegeben: Sub DatenfeldEindimensional()

Dim T(1 To 7) As Integer

Dim i As Integer

ThisWorkbook.Worksheets("Tabelle1").Activate

Randomize

For i = 1 To 7

T(i) = Rnd * 10 + 20

Cells(i, 1).Value = T(i)

Next i

End Sub

Listing 5.3     Sub »DatenfeldEindimensional()« in Mappe5.xlsm, Modul 1

Abbildung 5.1 zeigt ein mögliches Ergebnis.

Abbildung 5.1     Datenfeld mit sieben Elementen

Die Werte werden per Zufallszahlengenerator ermittelt, der zunächst mit der Anweisung Randomize initialisiert wird. Mit der Anweisung Dim T(1 To 7) As Integer wird ein eindimensionales Feld mit sieben Elementen deklariert. Jedes Element entspricht einer einzelnen Integer-Variablen. Sie können Felder aller Datentypen deklarieren. Die Elemente werden durch eine laufende Nummer, den sogenannten Index, voneinander unterschieden. Der Index beginnt für dieses Feld bei 1 und geht bis 7. Das erste Element des Felds hat die Bezeichnung T(1), das nächste T(2) usw. bis T(7). In einer Schleife wird jedem Element des Felds ein zufälliger Wert zwischen 20 und 30 zugewiesen. Beim Durchlauf der Schleife wird auf das aktuelle Element mit T(i) zugegriffen. Die Schleifenvariable i nimmt nacheinander die Werte von 1 bis 7 an, die als Index benötigt werden. Die Elemente des Datenfelds werden in den Zellen untereinander angezeigt. [»]  Hinweis

Die Anweisung Dim T(7) As Integer hätte ein eindimensionales Feld mit acht (!) Elementen deklariert. Die Elemente hätten die Bezeichnungen T(0) bis T(7). Für die Darstellung in den Zellen eines Tabellenblatts bietet es sich allerdings an, den Index bei 1 beginnen zu lassen. Fügen Sie auf Modulebene, also oberhalb der ersten Prozedur eines Moduls, die Anweisung Option Base 1 ein, gilt der Wert 1 (statt des Werts 0) automatisch als Untergrenze der Felder in dem betreffenden Modul. In diesem Fall würde die Anweisung Dim T(7) As Integer ein eindimensionales Feld mit sieben Elementen deklarieren.

Übung »Eindimensionale Datenfelder« Schreiben Sie die Prozedur UebungEindimensional(), in der den Elementen eines eindimensionalen Felds, das zehn IntegerWerte enthält, zufällige Werte zwischen 30 und 35 zugewiesen werden. Anschließend werden alle Zellen, die den kleinsten Wert des Felds enthalten, wie in Abbildung 5.2 besonders hervorgehoben.

Abbildung 5.2     Kleinster Wert ist durch Rahmen hervorgehoben.

Übung »Kopfrechnen mit Datenfeld« Erweitern Sie das Programm aus der Übung »Kopfrechnen mit Schleife«. Die fünf richtigen Ergebnisse werden diesmal nicht in die Zellen Z1 bis Z5 geschrieben, sondern in einem eindimensionalen Datenfeld des passenden Datentyps gespeichert. Es wird modulweit deklariert, damit die Prozeduren UebungKopfFeld_Aufgabe() und UebungKopfFeld_Pruefen() darauf Zugriff haben. Die Ausgaben des Programms sehen aus wie in Abbildung 3.21 und Abbildung 3.22.

Übung »Kopfrechnen mit mehreren Operatoren« Erweitern Sie das Programm aus der Übung »Kopfrechnen mit Datenfeld«. Die Benutzerin trainiert nicht nur die Addition, sondern auch die Subtraktion, die Multiplikation und die Division. Es gibt unterschiedliche Aufgaben für die vier Grundrechenarten: Bei der Addition und der Subtraktion wird mit zufälligen ganzen Zahlen aus dem Bereich von 1 bis 20 gerechnet, bei der Multiplikation und der Division mit zufälligen ganzen Zahlen aus dem Bereich von 1 bis 10. Das Programm enthält die beiden Prozeduren UebungKopfOperator_Aufgabe() und UebungKopfOperator_Pruefen(). Legen Sie los … oder lesen Sie erst die folgende Hilfestellung: Die vier Operatorenzeichen +, -, * und / werden in einem weiteren eindimensionalen Datenfeld des passenden Datentyps gespeichert. Per Zufallsgenerator wird eine ganze Zahl aus dem Bereich von 1 (für die Addition) bis 4 (für die Division) ermittelt. In den Zellen B1 bis B5 wird der zugehörige Operator abgebildet.

Mithilfe einer mehrfachen Verzweigung werden in Abhängigkeit vom Operator unterschiedliche Aufgaben erstellt. Noch ein Tipp: Bei der Division ergibt sich ein weiteres Problem. Es werden nur Aufgaben gestellt, bei denen das Ergebnis eine ganze Zahl ist. Das wird mithilfe eines Umwegs über eine Multiplikation gelöst. Nehmen wir an, die Aufgabe lautet: A / B = Ergebnis. Ermitteln Sie zwei zufällige ganze Zahlen aus dem genannten Bereich für Ergebnis und für B. Berechnen Sie anschließend A = B * Ergebnis.

5.2.2    Datenfeld sortieren In der folgenden Prozedur wird ein eindimensionales, statisches Datenfeld des Typs Integer mit Werten gefüllt. Dann wird es mithilfe des schnellen Bubble-Sort-Verfahrens sortiert und anschließend ausgegeben: Sub DatenfeldSortieren()

Dim T(1 To 7) As Integer

Dim i As Integer

Dim Getauscht As Boolean

Dim Temp As Integer

ThisWorkbook.Worksheets("Tabelle1").Activate

Randomize

For i = 1 To 7

T(i) = Rnd * 10 + 20

Next i

Do

Getauscht = False

For i = 1 To 6 If T(i) > T(i + 1) Then

Temp = T(i)

T(i) = T(i + 1)

T(i + 1) = Temp

Getauscht = True

End If

Next i

Loop While Getauscht



For i = 1 To 7

Cells(i, 1).Value = T(i)

Next i

End Sub

Listing 5.4     Sub »DatenfeldSortieren()« in Mappe5.xlsm, Modul 1

Abbildung 5.3 zeigt ein mögliches Ergebnis.

Abbildung 5.3     Sortiertes Datenfeld

Beim Bubble-Sort-Verfahren wird das Datenfeld mehrmals nacheinander vom ersten bis zum vorletzten Element durchlaufen. Jedes Element wird mit seinem Nachfolger verglichen. Stehen die beiden Elemente nicht in der richtigen Reihenfolge, werden sie mithilfe einer dritten Variablen vertauscht. Auf diese Weise wandern einzelne Elemente innerhalb des Datenfelds nach oben. Sie steigen wie (Luft-)Blasen (engl. bubbles) im Wasser auf – daher der Name des Verfahrens. Im vorliegenden Fall wird aufsteigend sortiert. Möchten Sie absteigend sortieren, ändern Sie die Bedingung der Verzweigung: T(i) < T(i + 1). Nach einer Reihe von Durchläufen gibt es einen Durchlauf durch das Datenfeld, bei dem kein Tauschvorgang mehr stattfindet. Die boolesche Variable Getauscht behält ihren Wert False. Dann endet die Sortierung.

5.2.3    Mehrdimensionale Datenfelder Wurden die sieben Temperaturwerte jeweils an drei verschiedenen Orten aufgenommen, bietet sich zur Speicherung ein zweidimensionales Feld an. Die Elemente eines solchen Felds werden über zwei Indizes angesprochen. Der erste Index steht hier für die laufende Nummer der Messung, der zweite Index für den Ort, an dem die Messung durchgeführt wurde. Die folgende Prozedur, bei der die Werte eines Ortes jeweils in einer Spalte angezeigt werden, veranschaulicht dies: Sub DatenfeldMehrdimensional()

Dim T(1 To 7, 1 To 3) As Integer

Dim i As Integer, k As Integer

ThisWorkbook.Worksheets("Tabelle1").Activate

Randomize

For i = 1 To 7

For k = 1 To 3 T(i, k) = Rnd * 10 + 20

Cells(i, k).Value = T(i, k)

Next k

Next i

End Sub

Listing 5.5     Sub »DatenfeldMehrdimensional()« in Mappe5.xlsm, Modul 1

Ein mögliches Ergebnis sehen Sie in Abbildung 5.4. Mit Dim T(1 To 7, 1 To 3) wird ein zweidimensionales Feld der Größe sieben mal drei Elemente vom Datentyp Integer deklariert. Der Index beginnt in jeder Dimension bei 1.

Abbildung 5.4     Datenfeld mit sieben mal drei Elementen

Es folgen zwei geschachtelte Schleifen, eine äußere und eine innere Schleife. Die äußere Schleife besitzt die Schleifenvariable i, die zunächst den Wert 1 erhält. Dann erhält die Schleifenvariable k in der inneren Schleife nacheinander die Werte von 1 bis 3. Anschließend erhält i den Wert 2, und k durchläuft wieder die Werte von 1 bis 3 usw. Auf diese Weise wird auf alle 21 Elemente des zweidimensionalen Felds zugegriffen. Das jeweils aktuelle Element T(i,k) erhält seinen Wert über den Zufallsgenerator. Das zweidimensionale Feld wird vollständig gefüllt. Die Ausgabe in den Zellen erfolgt parallel, also zunächst in den drei Zellen von Zeile 1, anschließend in den drei Zellen von Zeile 2 usw. Das gesamte Feld wird im Tabellenblatt ausgegeben. Mehr als zwei Dimensionen

Ein zweidimensionales Feld lässt sich in einem Tabellenblatt darstellen. Datenfelder können aber auch mehr als zwei Dimensionen haben: Haben wir nicht nur sieben Messungen pro Tag an drei verschiedenen Orten, sondern diese auch noch über einen

ganzen Monat an 31 Tagen, benötigen wir eine dritte Dimension. Es empfiehlt sich der Datentyp Single, damit auch die Nachkommastellen gespeichert werden. Die Deklaration sieht dann wie folgt aus: Dim T(1 To 7, 1 To 3, 1 To 31) As Single. Das Datenfeld enthält 7 × 3 × 31 = 651 Elemente. Dieses Beispiel lässt sich erweitern: Wie bisher haben wir sieben Messungen an drei Orten an 31 Tagen. Neben der Temperatur werden auch die Windrichtung, die Windgeschwindigkeit und die Luftfeuchtigkeit gemessen. Dazu benötigen wir ein vierdimensionales Feld, das wir wie folgt deklarieren: Dim T(1 To 7, 1 To 3, 1 To 31, 1 To 4) As Single. Es enthält 7 × 3 × 31 × 4= 2.604 Elemente. Datenfelder bieten umfangreiche Möglichkeiten zur Speicherung und Verarbeitung größerer Datenmengen. Der Begriff Speicherung ist hier temporär zu verstehen, d. h. für die Speicherung während der Verarbeitung. Für eine dauerhafte Speicherung auf der Festplatte benötigen Sie Dateien (siehe Abschnitt 9.2, »Einfache Textdateien«) oder besser noch Datenbanken (siehe Abschnitt 9.8). Übung »Mehrdimensionale Datenfelder« Schreiben Sie die Prozedur UebungMehrdimensional(), in der den Elementen eines zweidimensionalen Felds, das 10 × 2 IntegerWerte enthält, zufällige Werte zwischen 130 und 135 zugewiesen werden. Anschließend werden alle Zellen, die den kleinsten Wert des Felds enthalten, wie in Abbildung 5.5 besonders hervorgehoben.

Abbildung 5.5     Kleinster Wert ist durch Rahmen hervorgehoben.

5.2.4    Dynamische Datenfelder Steht zum Zeitpunkt des Programmstarts noch nicht fest, wie viele Variablen in einem Feld gespeichert werden, arbeiten Sie mit dynamischen Feldern. Die Größe eines solchen Felds lässt sich zur Laufzeit mithilfe des Schlüsselworts ReDim mehrmals verändern. Bei Bedarf stellen Sie mithilfe des Schlüsselworts Preserve sicher, dass vorhandene Werte erhalten bleiben. Ein möglicher Anwendungsfall: Es wird eine größere, unbekannte Menge an Daten aus einer Textdatei eingelesen und verarbeitet. Anschließend werden die Ergebnisse in einem Tabellenblatt dargestellt. Im folgenden Beispiel wird ein dynamisches Datenfeld deklariert. Seine Größe wird dreimal unterschiedlich festgelegt – mit bzw. ohne Preserve: Sub DatenfeldDynamisch()

Dim T() As Integer Dim i As Integer

ThisWorkbook.Worksheets("Tabelle1").Activate

Randomize



ReDim T(1 To 3)

For i = 1 To 3

T(i) = Rnd * 10 + 20

Cells(i, 5).Value = T(i)

Next i

ReDim Preserve T(1 To 6)

For i = 4 To 6

T(i) = Rnd * 10 + 20

Next i

For i = 1 To 6

Cells(i, 6).Value = T(i)

Next i

ReDim T(1 To 9)

For i = 7 To 9

T(i) = Rnd * 10 + 20

Next i

For i = 1 To 9

Cells(i, 7).Value = T(i)

Next i

End Sub

Listing 5.6     Sub »DatenfeldDynamisch()« in Mappe5.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 5.6.

Abbildung 5.6     Dynamisches Datenfeld (zweimal verändert)

Das Feld T wird zunächst ohne Größenangabe deklariert. Mit ReDim wird festgelegt, dass es die Größe 3 besitzt, mit den Indizes 1, 2 und 3. Die drei Elemente werden mit zufälligen Werten gefüllt und ausgegeben.

Anschließend wird das Feld auf die Größe 6 vergrößert – mit Preserve. Die neuen Elemente 4 bis 6 werden mit zufälligen Werten gefüllt. Das gesamte Feld wird ausgegeben. Die Elemente 1 bis 3 haben ihren Wert behalten. Zuletzt wird das Feld auf die Größe 9 vergrößert – ohne Preserve. Die neuen Elemente 7 bis 9 werden ebenso mit zufälligen Werten gefüllt. Das gesamte Feld wird ausgegeben. Die Elemente 1 bis 6 haben ihren Wert verloren und besitzen wieder den Standardwert 0.

5.2.5    VBA-Funktion »Array()« Mithilfe der Funktion Array() können Werte beliebiger Datentypen zusammen mit beliebigen Objekten in einem eindimensionalen Datenfeld des Typs Variant zusammengefasst werden. In der nachfolgenden Prozedur wird ein Datenfeld mit zwei Ganzzahlen, einer Zahl mit Nachkommastellen, einer Zeichenkette und einem Objekt des Typs Range erzeugt. Es wird 3.5 ausgegeben, der Wert des dritten Feldelements: Sub FunktionArray()

Dim T() As Variant T = Array(2, -14, 3.5, "abc", Range("A2"))

MsgBox T(2)

End Sub

Listing 5.7     Sub »FunktionArray()« in Mappe5.xlsm, Modul 1

Das Feld T wird ohne Größenangabe deklariert. Die Indizes beginnen bei 0. An dieser Stelle muss der Datentyp Variant verwendet werden, der ansonsten wegen seiner verminderten Kontrollmöglichkeiten und seiner Speichergröße nicht zu empfehlen ist.

5.2.6    Datenfelder löschen oder freigeben Das Schlüsselwort Erase dient folgendem Zweck: Bei einem statischen Datenfeld dem Zurücksetzen aller Inhalte. Das Datenfeld selbst ist dann noch vorhanden und beansprucht Speicherplatz. Bei einem dynamischen Datenfeld der Freigabe des gesamten Speicherplatzes. Dieser Speicherplatz steht anschließend wieder anderen Variablen oder Datenfeldern zur Verfügung. Ein Beispiel mit einem statischen Datenfeld: Sub DatenfeldZuruecksetzen()

Dim T(1 To 5) As Integer

T(1) = 10

MsgBox T(1)

Erase T

MsgBox T(1)

End Sub

Listing 5.8     Sub »DatenfeldZuruecksetzen()« in Mappe5.xlsm, Modul 1

Das statische Datenfeld T hat fünf Elemente. Das erste Element wird gefüllt und ausgegeben. Nach dem Zurücksetzen des Felds wird das erste Element erneut ausgegeben. Es hat wieder den Startwert 0. [»]  Hinweis Die Elemente von Feldern von Zeichenketten werden auf den Wert "" (= leere Zeichenkette) gesetzt.

Ein Beispiel mit einem dynamischen Datenfeld: Sub DatenfeldFreigeben()

Dim T() As Integer On Error GoTo Fehler

ReDim T(1 To 5)

T(1) = 10

MsgBox T(1)

Erase T

MsgBox T(1)

ReDim T(1 To 5)

T(1) = 10

MsgBox T(1)

Exit Sub

Fehler:

MsgBox Err.Description

Resume Next

End Sub

Listing 5.9     Sub »DatenfeldFreigeben()« in Mappe5.xlsm, Modul 1

Das dynamische Datenfeld T wird deklariert und mithilfe von ReDim auf die Größe 5 gesetzt. Das erste Element wird gefüllt und ausgegeben. Nach dem Freigeben des Speicherplatzes mit der Anweisung Erase wird das Element erneut ausgegeben. Es tritt ein Laufzeitfehler auf (der abgefangen wird), da das Element nicht mehr existiert. Im weiteren Verlauf der Prozedur wird das Datenfeld erneut mit ReDim auf eine gewünschte Größe gesetzt und verwendet.

5.3    Prozeduren und Funktionen In Excel verwenden Sie integrierte Funktionen, wie zum Beispiel SUMME(), WENN() oder VERWEIS(). In einer solchen Funktion werden Daten aus einem Tabellenblatt verwendet. Es wird ein Ergebnis ermittelt und in der Zelle, in der die Funktion aufgerufen wird, ausgegeben. Eigene VBA-Funktionen arbeiten ähnlich, bieten aber weitergehende Möglichkeiten. Wie Prozeduren enthalten sie Anweisungen, ermitteln darüber hinaus ein Ergebnis und liefern es zurück. Prozeduren und eigene VBA-Funktionen haben folgende Vorteile: Gleiche oder ähnliche Vorgänge werden einmal definiert und sind beliebig oft aufrufbar. Umfangreiche Programme werden modularisiert, d. h. in kleinere Bestandteile zerlegt, die übersichtlicher und besser wartbar sind. Eigene VBA-Funktionen können wie integrierte Funktionen in Tabellenblättern verwendet werden. An eine Prozedur oder an eine Funktion können Parameter übergeben werden. Dadurch werden sie flexibler. [»]  Hinweis Methoden sind Funktionen, die sich auf ein bestimmtes ExcelObjekt beziehen. Ein Beispiel: Für das Workbooks-Objekt werden die Methoden Add(), Open() oder Close() aufgerufen.

5.3.1    Prozeduren In einer Prozedur werden Anweisungen zusammengefasst, die gemeinsam ausgeführt werden. Die Definition einer Prozedur hat folgenden Aufbau: Sub Prozedurname (Parameterliste)

[ Anweisungsblock ]

[ Exit Sub ]

[ Anweisungsblock ]

End Sub

Nach dem Schlüsselwort Sub und dem Namen der Prozedur folgt in runden Klammern eine Parameterliste. Die Elemente der Liste werden durch Kommata getrennt. Die Definition der Prozedur endet mit End Sub. Die Anweisung Exit Sub wird verwendet, um eine Prozedur aufgrund einer besonderen Bedingung unmittelbar zu verlassen. Beim Aufruf einer Prozedur entfallen die Klammern um die Parameterliste. Im nachfolgenden Beispiel wird die Prozedur ZeigeMaximum() von zwei verschiedenen Stellen aus aufgerufen. Sie berechnet jeweils das Maximum der beiden übergebenen Parameter und gibt es aus: Sub Prozedur1()

Dim a As Double, b As Double a = 4.5

b = 7.2

ZeigeMaximum a, b

End Sub

Sub Prozedur2()

Dim c As Double

c = 23.9

ZeigeMaximum c, 5.6

End Sub

Sub ZeigeMaximum(x As Double, y As Double)

If x > y Then

MsgBox "Maximum: " & x

Else

MsgBox "Maximum: " & y

End If

End Sub

Listing 5.10     Drei Sub-Prozeduren in Mappe5.xlsm, Modul 1

Das Ergebnis von Prozedur2() zeigt Abbildung 5.7.

Abbildung 5.7     Ausgabe der Sub »Prozedur2()«

Die Prozedur ZeigeMaximum() hat zwei Parameter: die beiden DoubleVariablen x und y. Folglich muss die Prozedur mit zwei Werten oder Variablen des Datentyps Double aufgerufen werden. Die Prozedur kann auch mit Werten eines anderen Datentyps aufgerufen werden, zum Beispiel Single oder Integer, falls sich diese Werte automatisch in Double-Werte umwandeln lassen. In der Prozedur Prozedur1() wird die Prozedur ZeigeMaximum() mit den Variablen a und b, in Prozedur2() mit der Variablen c und dem Wert 5.6 aufgerufen. In der Prozedur ZeigeMaximum() werden die Variablen bzw. Werte in der gegebenen Reihenfolge an die beiden Variablen x und y übergeben. Das Maximum dieser beiden Werte wird ermittelt und ausgegeben. Die Prozedur endet, und der Programmablauf kehrt zur aufrufenden Stelle zurück. Wird eine Variable an eine Prozedur übergeben, muss sie nicht den gleichen Namen haben wie die Variable in der Prozedur. Prozeduren werden von verschiedenen Stellen des Programms aus mit unterschiedlichen Parametern aufgerufen. Anzahl, Reihenfolge und Datentyp der Parameter müssen übereinstimmen.

Die beiden lokalen Variablen a und b sind nur in der Prozedur Prozedur1() bekannt und gültig. Bezogen auf die Prozedur Prozedur2() trifft dies für die lokale Variable c zu. Ebenso gilt dies für die beiden Parameter x und y, bezogen auf die Prozedur ZeigeMaximum(). Kommt ein Variablenname in mehreren Prozeduren vor, ist die Eindeutigkeit aufgrund des Gültigkeitsbereichs gegeben. [»]  Hinweis Markieren Sie den Namen einer Prozedur oder einer Funktion. Mit (ª)+(F2) springen Sie zu der Stelle, an der die Prozedur oder die Funktion definiert wurde. Mit (Strg)+(ª)+(F2) kommen Sie wieder zurück. Zur Erinnerung: Mit (ª)+(F2) auf dem Namen einer Variablen springen Sie zu der Stelle, an der die Variable deklariert wurde. Übung »Prozedur« Schreiben Sie die Prozedur UebungProzedur(), in der zwei Double-Variablen beliebige Werte zugewiesen werden. Anschließend wird die Prozedur PMittelwert() aufgerufen, der genau zwei Variablen übergeben werden. In der Prozedur PMittelwert() wird der Mittelwert der beiden Zahlen berechnet und wie in Abbildung 5.8 dargestellt ausgegeben.

Abbildung 5.8     Ergebnis zu Übung »Prozedur«

5.3.2    Parameter übergeben Parameter werden in VBA per Referenz übergeben. Dies bedeutet, dass eine Veränderung der Parameter in der Prozedur bzw. Funktion eine Rückwirkung auf die Originalvariable hat. Zur Vermeidung einer solchen Rückwirkung müssen Sie vor der betreffenden Variablen das Schlüsselwort ByVal einfügen. Dies bedeutet, dass die Variable per Kopie an die Prozedur oder an die Funktion übergeben wird. Eine Veränderung der Kopie hat keine Auswirkung auf die Originalvariable. Das folgende Programm veranschaulicht beide Möglichkeiten: Sub Uebergabe()

Dim x As Integer, y As Integer

ThisWorkbook.Worksheets("Tabelle2").Activate

x = 5

y = 12

Cells(1, 1).Value = x

Cells(1, 2).Value = y

TauscheKopie x, y

Cells(2, 1).Value = x

Cells(2, 2).Value = y

TauscheReferenz x, y

Cells(3, 1).Value = x

Cells(3, 2).Value = y

End Sub

Sub TauscheKopie(ByVal a As Integer, ByVal b As Integer)

Dim c As Integer

c = a

a = b

b = c

End Sub

Sub TauscheReferenz(ByRef a As Integer, ByRef b As Integer)

Dim c As Integer

c = a

a = b

b = c

End Sub

Listing 5.11     Drei Sub-Prozeduren in Mappe5.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 5.9.

Abbildung 5.9     Übergabe per Kopie und Übergabe per Referenz

In der Prozedur Uebergabe() werden zwei Integer-Variablen mit Startwerten belegt. Anschließend werden die Prozeduren TauscheKopie() und TauscheReferenz() aufgerufen. Die Werte der beiden Variablen werden zu Beginn und nach jedem Prozeduraufruf ausgegeben. In den beiden aufgerufenen Prozeduren werden die beiden übergebenen Variablen mithilfe einer dritten Variablen getauscht (Ringtausch). Im Fall der Prozedur TauscheKopie() wird ByVal verwendet. In der Ausgabe zeigt sich keine Änderung, da der Tausch nur in der Prozedur TauscheKopie() stattfindet und keine Wirkung nach außen besitzt. In der Prozedur TauscheReferenz() wird ByRef verwendet. Da die Variablen per Referenz übergeben werden, zeigt die Ausgabe eine Änderung. Die Übergabe per Referenz ist der Standard, daher kann das Schlüsselwort ByRef weggelassen werden.

5.3.3    Funktionen Die Definition einer Funktion hat den folgenden Aufbau: Function Funktionsname (Parameterliste) As Typ

[ Anweisungsblock ]

[ Exit Function ]

[ Anweisungsblock ]

End Function

Nach dem Schlüsselwort Function und dem Namen der Funktion folgt wie bei Prozeduren eine Parameterliste in runden Klammern. Eine Funktion hat (wie eine Variable) einen Datentyp, der nach As notiert wird. Die Definition endet mit End Function. Die Anweisung Exit Function wird eingesetzt, um die Funktion aufgrund einer besonderen Bedingung unmittelbar zu verlassen. Eine Funktion ermittelt ein Ergebnis, das dem Funktionsnamen zugewiesen wird. Damit besitzt die Funktion einen Rückgabewert, der an der aufrufenden Stelle gespeichert oder ausgegeben wird. Wird beim Aufruf einer Funktion der Rückgabewert genutzt, werden Klammern um die Parameterliste gesetzt, also: Variable = Funktionsname(Parameterliste)

Wird beim Aufruf einer Funktion der Rückgabewert nicht genutzt, werden keine Klammern um die Parameterliste gesetzt, also: Funktionsname Parameterliste

[»]  Hinweis Eigene Funktionen können Sie sowohl in VBA-Anwendungen als auch auf dem Tabellenblatt mithilfe von =FUNKTIONSNAME() nutzen. Sie stehen in der jeweiligen Excel-Datei in der Kategorie Benutzerdefiniert zur Verfügung.

Im folgenden Beispiel wird die Funktion MaxWert() aufgerufen. Mit ihr wird das Maximum der beiden übergebenen Parameter berechnet und an die aufrufende Stelle zurückgegeben: Sub Funktionen()

Dim a As Integer, b As Integer, c As Integer

a = 12

b = 17

c = MaxWert(a, b)

MsgBox "Maximum: " & c

End Sub

Function MaxWert(x As Integer, y As Integer) As Integer

If x > y Then

MaxWert = x

Else

MaxWert = y

End If

End Function

Listing 5.12     Sub-Prozedur und Funktion in Mappe5.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 5.10.

Abbildung 5.10     »Funktionen()« erhält ein Ergebnis zurück.

Durch die Anweisung c = MaxWert(a, b) passiert nacheinander Folgendes: Die Funktion MaxWert() wird aufgerufen. Dabei werden zwei Zahlenwerte an die Funktion übergeben. In der Funktion wird das Maximum dieser beiden Zahlen ermittelt und als Rückgabewert der Funktion gespeichert. Nach dem Durchlauf der Funktion kehrt das Programm zu der Aufrufstelle zurück. Dort wird der Rückgabewert an die Variable c übergeben, die anschließend ausgegeben wird. Hätte die Anweisung nur MaxWert(a, b) gelautet, hätten alle diese Schritte stattgefunden – außer der Übergabe an c. Der Funktionsaufruf wäre in diesem Fall vergeblich gewesen – ein häufiger Fehler bei Programmiereinsteigern.

Die Funktion MaxWert() kann in dieser Arbeitsmappe auch im Tabellenblatt benutzt werden. Geben Sie z. B. =MaxWert(A1;B1) in einer Zelle ein, erscheint das erwartete Ergebnis. Übung »Funktion« Schreiben Sie die Prozedur UebungFunktion(), in der Sie zwei Double-Variablen beliebige Werte zuweisen. Anschließend wird die Funktion FMittelwert() aufgerufen, der genau zwei Variablen übergeben werden. In der Funktion FMittelwert() wird der Mittelwert der beiden Zahlen berechnet und als Ergebnis an die Prozedur UebungFunktion() zurückgegeben. Die Ausgabe erfolgt in der Prozedur UebungFunktion().

5.3.4    Beispiel »Der letzte Tag im Monat« Es folgt ein weiteres Beispiel zur Arbeit mit Funktionen, Parametern und Rückgabewerten. Gleichzeitig werde ich die Rangfolge der Operatoren – siehe Abschnitt 3.3.5 – noch einmal verdeutlichen. In der nachfolgenden Funktion LetzterTagImMonat() wird der letzte Tag des Monats eines bestimmten Jahres berechnet. Dabei ergibt sich je nach Monat der Wert 30 oder 31 und für den Monat Februar in Schaltjahren der Wert 29, ansonsten der Wert 28. Zunächst eine Testprozedur, mit der die Funktion LetzterTagImMonat() aufgerufen wird: Sub LetzterTagImMonatTesten()

ThisWorkbook.Worksheets("Tabelle2").Activate

Range("D3").Value = LetzterTagImMonat _

(Range("D1").Value, Range("D2").Value)

End Sub

Listing 5.13     Sub »LetzterTagImMonatTesten()« in Mappe5.xlsm, Modul 1

Die Funktion LetzterTagImMonat() wird mit zwei Parametern aufgerufen. Dabei handelt es sich hier um den Inhalt von zwei Zellen, in denen das gewünschte Jahr und der gewünschte Monat stehen. Es folgt die Funktion LetzterTagImMonat(): Function LetzterTagImMonat(J As Integer, M As Integer) As Integer

If M = 2 Then

If J Mod 4 = 0 And J Mod 100 0 Or J Mod 400 = 0 Then

LetzterTagImMonat = 29

Else

LetzterTagImMonat = 28

End If

ElseIf M = 4 Or M = 6 Or M = 9 Or M = 11 Then

LetzterTagImMonat = 30

Else

LetzterTagImMonat = 31

End If

End Function

Listing 5.14     Funktion »LetzterTagImMonat()« in Mappe5.xlsm, Modul 1

Die beiden Werte für Jahr und Monat werden beim Aufruf der Funktion an die Parameter J und M übergeben. Handelt es sich bei dem Monat um den Februar, wird mithilfe des Operators Mod untersucht, ob das Jahr ein Schaltjahr ist. Das trifft zu, falls sich die Jahreszahl durch 4, aber nicht durch 100 ohne Rest teilen lässt oder sich die Jahreszahl durch 400 ohne Rest teilen lässt. Bei den anderen Monaten ergibt sich der Wert 30 oder 31 – je nach Monat. In dem Ausdruck J Mod 4 = 0 And J Mod 100 0 Or J Mod 400 = 0 müssen keine Klammern gesetzt werden. Es gilt die folgende Rangfolge der Operatoren, beginnend mit der höchsten Priorität: arithmetischer Operator Mod Vergleichsoperatoren = bzw.

logischer Operator And logischer Operator Or In Abbildung 5.11 sehen Sie, wie die Funktion LetzterTagImMonat() im Tabellenblatt genutzt wird. Nach der Eingabe der ersten Zeichen wird mithilfe der Pfeiltasten der zugehörige Eintrag in der Liste markiert. Anschließend wird er mithilfe der Taste (ê) ausgewählt. Der Beginn des Funktionsaufrufs erscheint im Bearbeitungsfeld (siehe Abbildung 5.12) und kann vervollständigt werden (siehe Abbildung 5.13). Nach Betätigung der Taste (¢) erscheint das Ergebnis.

Abbildung 5.11     Nach Eingabe der ersten Zeichen

Abbildung 5.12     Nach Auswahl der Funktion

Abbildung 5.13     Nach Vervollständigung des Funktionsaufrufs

5.3.5    Optionale Parameter Anzahl und Reihenfolge der Parameter müssen beim Aufruf und bei der Definition einer Prozedur bzw. Funktion übereinstimmen. Sie können aber auch mit optionalen Parametern arbeiten. Diese müssen beim Aufruf nicht angegeben werden. Sie werden mit dem Schlüsselwort Optional gekennzeichnet, stehen immer am Ende der Parameterliste und sollten mit einem Standardwert initialisiert werden. Im folgenden Beispiel wird die Funktion Addiere() insgesamt dreimal aufgerufen, einmal mit zwei Parametern, einmal mit drei Parametern und einmal mit vier Parametern. Die Funktion berechnet die Summe der übergebenen Parameter und liefert diese zurück. Sub OptionaleParameter()

Dim a As Double, b As Double, c As Double, d As Double

a = 4

b = 7.5

c = 10.5

d = 9

MsgBox "Addition von vier Werten: " & Addiere(a, b, c, d)

MsgBox "Addition von drei Werten: " & Addiere(a, b, c)

MsgBox "Addition von zwei Werten: " & Addiere(a, b)

' MsgBox "'Addition' von einem Wert: " & Addiere(a)

End Sub

Function Addiere(x As Double, y As Double, Optional z As _

Double = 0, Optional q As Double = 0) As Double

Addiere = x + y + z + q

End Function

Listing 5.15     Sub-Prozedur und Funktion in Mappe5.xlsm, Modul 1

Das Ergebnis der ersten Addition sehen Sie in Abbildung 5.14.

Abbildung 5.14     Addition (31 = 4 + 7,5 + 10,5 + 9)

Das zweite Ergebnis sehen Sie in Abbildung 5.15.

Abbildung 5.15     Addition (22 = 4 + 7,5 + 10,5)

Das dritte Ergebnis sehen Sie in Abbildung 5.16.

Abbildung 5.16     Addition (11,5 = 4 + 7,5)

Die Funktion Addiere() erwartet insgesamt vier Parameter des Datentyps Double. Die beiden letzten Parameter sind optional und besitzen den Standardwert 0. In der Funktion findet eine Addition der vier Parameter statt. Daher ist 0 der geeignete Standardwert, der das Ergebnis der Funktion nicht verfälscht. Bei Prozeduren oder Funktionen, die andere Aufgaben zu erfüllen haben, können andere Standardwerte zur Initialisierung sinnvoll sein. In der Prozedur OptionaleParameter() wird die Funktion Addiere() mit vier, drei oder zwei Parametern aufgerufen. Das führt jeweils zur

Addition und Ausgabe der Werte. Da der Parameter y nicht optional ist, führt ein Aufruf mit einem Parameter zu einer Fehlermeldung, siehe Abbildung 5.17. Geben Sie beim Aufruf von integrierten VBA-Funktionen nicht genügend Parameter an, begegnet Ihnen dieselbe Fehlermeldung.

Abbildung 5.17     Mindestens zwei Parameter sind erforderlich.

5.3.6    Benannte Parameter Viele integrierte Prozeduren, Funktionen oder Objektmethoden besitzen umfangreiche Parameterlisten. Zur besseren Lesbarkeit können sie mithilfe von benannten Parametern aufgerufen werden. Dabei wird der Name des Parameters angegeben. In diesem Abschnitt wird die Definition der eigenen Prozedur Adresse() erläutert, die mit optionalen Parametern arbeitet. Sie wird auf unterschiedliche Weise mit benannten Parametern aufgerufen, setzt daraus einen Text zusammen und gibt ihn aus: Sub BenannteParameter()

Adresse "Maier", Ort:="Hamburg"

Adresse "Maier", Ort:="Hamburg", PLZ:="80445"

Adresse "Maier", Vorname:="Ernst", Ort:="Hamburg", PLZ:="80445"

Adresse Name:="Maier", PLZ:="80445", Vorname:="Ernst"

Adresse "Maier"

End Sub

Sub Adresse(Name As String, Optional Vorname As String, _ Optional PLZ As String, Optional Ort As String)

Dim Ausgabe As String

If Vorname "" Then

Ausgabe = Name & ", " & Vorname

Else

Ausgabe = Name

End If

If PLZ "" Then

If Ort "" Then

Ausgabe = Ausgabe & vbCrLf & PLZ & " " & Ort

Else

Ausgabe = Ausgabe & vbCrLf & PLZ

End If

Else

If Ort "" Then

Ausgabe = Ausgabe & vbCrLf & Ort

End If

End If

MsgBox Ausgabe

End Sub

Listing 5.16     Zwei Sub-Prozeduren in Mappe5.xlsm, Modul 1

Das Ergebnis des dritten Aufrufs der Prozedur Adresse() sehen Sie in Abbildung 5.18.

Abbildung 5.18     Ergebnis mit allen optionalen Parametern

Die Prozedur Adresse() erwartet insgesamt vier Parameter des Datentyps String. Die drei letzten Parameter sind optional und können mithilfe ihres Namens in beliebiger Reihenfolge angegeben werden. Die Werte werden dabei mithilfe des Operators := zugewiesen. Die einzelnen Parameter eines Aufrufs werden geprüft. Wird ein Parameter nicht oder ohne Inhalt geliefert, erfolgt keine Ausgabe. Zur Verbesserung der Lesbarkeit können auch Pflichtparameter mithilfe von benannten Parametern übergeben werden, wie am vierten Aufruf zu sehen ist.

5.3.7    Beliebig viele Parameter Mithilfe des Schlüsselworts ParamArray definieren Sie eine Prozedur bzw. Funktion, an die beliebig viele Parameter übergeben werden können. ParamArray verträgt sich nicht mit Optional. Sie müssen sich daher für eine der beiden Lösungen entscheiden. Im folgenden Beispiel wird die Funktion Mittelwert() insgesamt dreimal aufgerufen, einmal ohne Parameter, einmal mit zwei Parametern und einmal mit vier Parametern. Sie berechnet jeweils den (arithmetischen) Mittelwert der übergebenen Parameter und liefert ihn zurück: Sub BeliebigVieleParameter()

Dim a As Double, b As Double, c As Double, d As Double

a = 4

b = 7.5

c = 10.5

d = 9

MsgBox "Mittelwert: " & Mittelwert()

MsgBox "Mittelwert: " & Mittelwert(a, b)

MsgBox "Mittelwert: " & Mittelwert(a, b, c, d)

End Sub

Function Mittelwert(ParamArray x() As Variant) As Double

Dim i As Integer

Dim Summe As Double

Dim Anzahl As Integer

Summe = 0

For i = 0 To UBound(x)

Summe = Summe + x(i)

Next

Anzahl = UBound(x) + 1

If Anzahl > 0 Then

Mittelwert = Summe / Anzahl

Else

Mittelwert = 0

End If

End Function

Listing 5.17     Sub-Prozedur und Funktion in Mappe5.xlsm, Modul 1

Abbildung 5.19 zeigt das Ergebnis des letzten Aufrufs.

Abbildung 5.19     Aufruf mit Datenfeld mit vier Elementen

Die Funktion Mittelwert() wird dreimal aufgerufen, jeweils mit einer unterschiedlichen Anzahl an Parametern (0, 2 und 4). Zur Aufnahme der Parameter steht das Parameterdatenfeld (ParamArray x) zur Verfügung. Dabei handelt es sich um ein Datenfeld, dessen Größe nicht festgelegt ist. Wie bei der Funktion Array() (siehe Abschnitt 5.2.4, »Dynamische Datenfelder«) muss hier als Datentyp Variant verwendet werden, der ansonsten wegen seiner verminderten Kontrollmöglichkeiten und seiner Speichergröße nicht zu empfehlen ist. In der Funktion werden die Parameter mithilfe einer Schleife summiert. Die Obergrenze für die Schleife (und damit der höchste Wert für den Index) wird über die Funktion UBound() ermittelt. Die Anzahl der Elemente des Datenfelds wird ermittelt. Sie wird für die Berechnung des Mittelwerts benötigt. Wird die Funktion ohne Parameter aufgerufen, ergibt UBound() den Wert –1. Der Wert von Anzahl ist dann 0, d. h., es würde eine Division durch 0 durchgeführt werden. Dies gilt es zu vermeiden. Konnte in einer Funktion, die einen Zahlenwert liefert, kein Wert für die Funktion ermittelt werden, ist dieser wie bei Variablen 0. Im Sinne eines sauberen Programmierstils geben Sie sowohl Variablen als auch Funktionen immer einen Wert, wie dies in der Funktion Mittelwert() geschehen ist. [»]  Hinweis

Mit der Funktion LBound() ermitteln Sie den niedrigsten Wert für den Index eines Felds. Mithilfe eines optionalen zweiten Parameters sind die Funktionen LBound() und UBound() in der Lage, diese Indizes für alle Dimensionen eines ein- oder mehrdimensionalen Datenfelds zu ermitteln.

5.3.8    Datenfelder als Parameter Sie können ein Datenfeld als Parameter an eine Prozedur bzw. Funktion übergeben. Dabei wird weder die Anzahl noch die Größe der Dimensionen angegeben. Damit ist die Prozedur bzw. Funktion flexibler und verarbeitet unterschiedliche Felder. Das folgende Beispiel veranschaulicht eine solche Übergabe: Sub DatenfeldUebergeben()

Dim x(1 To 5, 1 To 3) As Integer

DatenfeldFuellen x()

DatenfeldAusgeben x()

End Sub

Sub DatenfeldFuellen(z() As Integer)

Dim i As Integer, k As Integer

For i = LBound(z, 1) To UBound(z, 1)

For k = LBound(z, 2) To UBound(z, 2)

z(i, k) = i * k

Next k

Next i

End Sub

Sub DatenfeldAusgeben(z() As Integer)

Dim i As Integer, k As Integer

ThisWorkbook.Worksheets("Tabelle3").Activate

For i = LBound(z, 1) To UBound(z, 1)

For k = LBound(z, 2) To UBound(z, 2)

Cells(i, k).Value = z(i, k)

Next k

Next i

End Sub

Listing 5.18     Drei Sub-Prozeduren in Mappe5.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 5.20.

Abbildung 5.20     Übergabe eines zweidimensionalen Felds

In der Prozedur DatenfeldUebergeben() wird ein Feld mit fünf mal drei Elementen deklariert. Das leere Feld wird an die Prozedur DatenfeldFuellen() übergeben. In dieser Prozedur wird es mit Werten gefüllt. Da die Übergabe per Referenz erfolgt, bleiben die Werte erhalten. Das gefüllte Feld wird an die Prozedur DatenfeldAusgeben() übergeben. In dieser Prozedur werden die Werte in einem Tabellenblatt ausgegeben. In beiden Prozeduren werden mit den Funktionen LBound() und UBound() jeweils die Unter- und Obergrenzen der beiden Dimensionen ermittelt. Dadurch ist gewährleistet, dass alle Feldelemente erreicht werden.

5.3.9    Rekursive Prozeduren und Funktionen Funktionen oder Prozeduren können jederzeit andere Funktionen oder Prozeduren aufrufen. Man spricht hier von verschachtelten Aufrufen. Das Programm kehrt jeweils – aus einer beliebigen Schachtelungstiefe – zur ursprünglich aufrufenden Stelle zurück.

Funktionen oder Prozeduren können sich auch selbst aufrufen. Dieser Vorgang wird als Rekursion bezeichnet. Eine Rekursion muss eine Bedingung enthalten, die die Rekursion wieder beendet, da es sonst zu einer endlosen Kette von Selbstaufrufen kommt. Bestimmte Problemstellungen lösen Sie programmiertechnisch am elegantesten durch eine Rekursion. Im nachfolgenden Beispiel sehen Sie das Grundprinzip der Rekursion anhand einer rekursiven Prozedur. Diese rekursive Prozedur wird von einer startenden Prozedur mit einem Startwert aufgerufen. Anschließend ruft sie sich mehrmals selbst auf, bis das Ende der Rekursion erreicht ist. Danach findet die Rückkehr zur startenden Prozedur statt. Sub RekursionStart()

Dim Zahl As Double

Zahl = 3.5

MsgBox Zahl

RekursionLauf Zahl

MsgBox "Ende"

End Sub

Sub RekursionLauf(Zahl As Double)

Zahl = Zahl / 2

MsgBox Zahl

If Zahl > 0.5 Then RekursionLauf Zahl

End Sub

Listing 5.19     Rekursive Prozedur in Mappe5.xlsm, Modul 1

Mithilfe der vorliegenden Rekursion wird eine Zahl (hier 3,5) so lange halbiert, bis sie den Wert 0,5 erreicht oder unterschritten hat. In der Prozedur RekursionStart() wird der Wert der Variablen Zahl auf den Startwert 3.5 gesetzt und ausgegeben. Es wird erstmals die Prozedur RekursionLauf() aufgerufen. Dabei wird der Wert von Zahl übergeben. In der Prozedur RekursionLauf() wird der Wert halbiert und wiederum ausgegeben.

Solange der Wert größer als 0,5 ist, ruft sich die Prozedur RekursionLauf() selbst wieder auf. Das wiederholt sich mehrmals. Wäre dieser Aufruf nicht an eine Bedingung geknüpft, würde sich der Vorgang endlos wiederholen. Nachdem Zahl den Wert 0,5 erreicht oder unterschritten hat, wird die Prozedur RekursionLauf() erstmals beendet. Das geschieht mehrmals nacheinander. Danach wird das Ende der Prozedur RekursionStart() erreicht und das Wort »Ende« ausgegeben.

5.4    Benutzerdefinierter Datentyp Ein benutzerdefinierter Datentyp dient der Verbindung von zusammengehörigen Daten unterschiedlichen Datentyps. Die Entwicklerin verdeutlicht damit den thematischen Zusammenhang zwischen bestimmten Daten. In der objektorientierten Programmierung wird dieser Gedanke mithilfe von Klassen weitergeführt. Die einzelnen Komponenten des neuen Datentyps sind einzelne Variablen oder Datenfelder von Variablen. Sie können einzelne Variablen oder Datenfelder von Variablen des neuen Datentyps sowohl deklarieren als auch an Prozeduren oder Funktionen übergeben. Ein Beispiel: Option Explicit

Type Person

Name As String

PNummer As Integer

Telefon() As String

Telefax(1 To 2) As String

Gehalt As Single

End Type

Sub Benutzerdefiniert()

Dim S As Person

Dim T(1 To 5) As Person

S.Name = "Maier"

S.PNummer = 17

S.Telefax(1) = "0965-347767"

S.Telefax(2) = "0975-227134"

S.Gehalt = 2652.5

ReDim S.Telefon(1 To 3)

S.Telefon(1) = "0965-347766"

S.Telefon(2) = "0189-938439"

S.Telefon(3) = "0975-227133"

T(5) = S

' MsgBox T(5)

MsgBox T(5).Name & ": " & _

T(5).Telefon(3) & " und " & T(5).Telefax(2)

BDTypAusgabe T(5)

' MsgBox T(1).Name

' MsgBox T(1).Telefon(1)

End Sub

Sub BDTypAusgabe(x As Person)

MsgBox x.Name & ": " & x.Telefon(3) & " und " & x.Telefax(2)

End Sub

Listing 5.20     Typdefinition und zwei Sub-Prozeduren in Mappe5.xlsm, Modul 1

Abbildung 5.21 zeigt die Ausgabe, die insgesamt zweimal erscheint.

Abbildung 5.21     Ausgabe einer Variablen des Datentyps »Person«

Benutzerdefinierte Datentypen werden zwischen Type und End Type definiert. Dies muss auf Modulebene durchgeführt werden, nicht innerhalb von Prozeduren oder Funktionen, am besten ganz oben unter Option Explicit. Der Datentyp Person hat fünf Komponenten: eine Zeichenkette eine ganze Zahl ein Datenfeld variabler Größe mit Zeichenketten ein Datenfeld fester Größe mit zwei Zeichenketten eine Zahl mit Nachkommastellen In der Prozedur Benutzerdefiniert() werden eine einzelne Variable und ein Datenfeld des neuen Datentyps definiert. Der Editor bietet dabei Unterstützung: Nach der Eingabe von As erscheint der Name des neuen Datentyps in der Liste der möglichen Typen.

Den Komponenten der einzelnen Variablen werden Werte zugewiesen. Nach Eingabe des Punktes hinter dem Variablennamen erscheint eine Liste der Komponenten als Hilfestellung. Die Komponente Telefon ist ein Datenfeld variabler Größe. Diesem Datenfeld muss eine Größe gegeben werden, bevor seinen Elementen Werte zugewiesen werden können. Für eine Variable eines benutzerdefinierten Datentyps gilt Folgendes: Sie kann einer anderen Variablen (oder dem Element eines Datenfelds) des gleichen Datentyps zugewiesen werden. Dabei werden automatisch alle Werte der einzelnen Komponenten zugewiesen. Handelt es sich bei einer Komponente um ein Datenfeld variabler Größe, wird dieses unmittelbar passend dimensioniert. Sie kann nicht als Ganzes ausgegeben werden. Stattdessen werden die Komponenten bzw. ihre Elemente einzeln angegeben. Sie kann an eine Prozedur bzw. Funktion übergeben werden. In der Parameterliste dieser Prozedur muss eine Variable des entsprechenden Datentyps deklariert werden. [»]  Hinweis Ein benutzerdefinierter Datentyp hat ohne weitere Angaben einen projektweiten Gültigkeitsbereich (Public Type ...). Er ist daher nicht nur in dem Modul bekannt, in dem er definiert wurde. Sie können die Gültigkeit durch die Angabe von Private Type ... einschränken, so dass der Datentyp nur in demjenigen Modul bekannt ist, in dem er definiert wurde.

Wird eine Komponente ausgegeben, der noch kein Wert zugewiesen wurde, hat sie den Wert 0 oder "" (leere Zeichenkette). Handelt es sich bei der Komponente um ein Datenfeld variabler Größe, muss dieses zunächst dimensioniert werden, da ansonsten ein Fehler auftritt.

5.5    Modular programmieren Prozeduren und Funktionen bieten die Möglichkeit zur modularen Programmierung. Dabei werden Programme in kleinere Bestandteile zerlegt, die übersichtlicher und besser wartbar sind. Häufig vorkommende Abläufe werden einmal definiert und beliebig oft aufgerufen. Bisher wurden Prozeduren und Funktionen aufgerufen, die sich im gleichen Modul befinden. Wie sieht es aus, falls sie sich in anderen Modulen, in Klassenmodulen oder in anderen Dateien befinden? Dazu sehen Sie in diesem Abschnitt unterschiedliche Konstellationen. In den Beispielen werden jeweils definiert und aufgerufen: eine Prozedur, die als Parameter zwei ganze Zahlen erwartet, die Summe berechnet und ausgibt eine Funktion, die ebenfalls als Parameter zwei ganze Zahlen erwartet, die Summe berechnet und an die aufrufende Stelle zurückliefert

5.5.1    Code in der gleichen Datei Zunächst ein Beispiel für Prozeduren und Funktionen in der gleichen Datei. Der Code im Codemodul Modul1: Sub ModularGleicheDatei()

Summe1 3, 5

MsgBox "Summe 2: " & Summe2(3, 5)

Tabelle1.Summe3 3, 5

MsgBox "Summe 4: " & Tabelle1.Summe4(3, 5)

End Sub

Listing 5.21     Sub »ModularGleicheDatei()« in Mappe5.xlsm, Modul 1

Es folgt der Code im Codemodul Modul2: Sub Summe1(a As Integer, b As Integer)

MsgBox "Summe 1: " & (a + b)

End Sub

Function Summe2(a As Integer, b As Integer) As Integer

Summe2 = a + b

End Function

Listing 5.22     Sub-Prozedur und Funktion in Mappe5.xlsm, Modul 1

Zuletzt der Code im Klassenmodul zum Objekt Tabelle1: Sub Summe3(a As Integer, b As Integer)

MsgBox "Summe 3: " & (a + b)

End Sub

Function Summe4(a As Integer, b As Integer) As Integer

Summe4 = a + b

End Function

Listing 5.23     Sub-Prozedur und Funktion in Mappe5.xlsm, Klassenmodul »Tabelle1«

Werden Prozeduren und Funktionen in Codemodulen nicht explizit mithilfe des Schlüsselworts Private definiert, haben sie die Sichtbarkeit Public. Daher können Sie die Prozedur Summe1() und die Funktion Summe2() aus Modul2 direkt aufrufen. Beim Aufruf von Prozeduren und Funktionen in Klassenmodulen, wie zum Beispiel bei der Prozedur Summe3() oder der Funktion Summe4() aus dem Klassenmodul zum Objekt Tabelle1, muss der Name des Klassenmoduls angegeben werden, also ..

5.5.2    Code in einer anderen Datei

Es folgt ein Beispiel für Prozeduren und Funktionen, die in einer anderen Datei definiert werden. Die andere Datei muss in Excel geöffnet sein, damit der Code genutzt werden kann. Zunächst der Code im Codemodul Modul1 der aufrufenden Datei: Sub ModularAndereDatei()

Workbooks.Open ThisWorkbook.Path & "\Mappe5Mod.xlsm"

Application.Run "Mappe5Mod.xlsm!Modul1.Summe5", 3, 5

MsgBox "Summe 6: " & Application.Run _

("Mappe5Mod.xlsm!Modul1.Summe6", 3, 5)

Application.Run "Mappe5Mod.xlsm!Tabelle1.Summe7", 3, 5

MsgBox "Summe 8: " & Application.Run _

("Mappe5Mod.xlsm!Tabelle1.Summe8", 3, 5)

Workbooks("Mappe5Mod.xlsm").Close

End Sub

Listing 5.24     Sub »ModularAndereDatei()« in Mappe5.xlsm, Modul 1

Es folgt der Code im Codemodul Modul1 der anderen Datei Mappe5Mod.xlsm: Sub Summe5(a As Integer, b As Integer)

MsgBox "Summe 5: " & (a + b)

End Sub

Function Summe6(a As Integer, b As Integer) As Integer

Summe6 = a + b

End Function

Listing 5.25     Sub-Prozedur und Funktion in Mappe5Mod.xlsm, Modul 1

Zuletzt der Code im Klassenmodul zum Objekt Tabelle1 der anderen Datei Mappe5Mod.xlsm: Sub Summe7(a As Integer, b As Integer)

MsgBox "Summe 7: " & (a + b)

End Sub

Function Summe8(a As Integer, b As Integer) As Integer

Summe8 = a + b

End Function

Listing 5.26     Sub-Prozedur und Funktion in Mappe5Mod.xlsm, Klassenmodul »Tabelle1«

Prozeduren und Funktionen in Modulen anderer Dateien können nur aufgerufen werden, falls die betreffende Datei in Excel geöffnet ist. Daher wird diese Datei zunächst geöffnet und am Ende wieder geschlossen. Im vorliegenden Beispiel wird angenommen, dass die andere Datei im selben Verzeichnis liegt. Daher wird das Verzeichnis der aufrufenden Datei ermittelt und zum Vervollständigen des Namens der anderen Datei genutzt. Die Methode Run() des Application-Objekts wird benötigt, um Prozeduren und Funktionen in anderen Dateien aufzurufen. Als ersten Parameter erhält sie eine Zeichenkette. Darin stehen nacheinander: der Name der Datei ein Ausrufezeichen der Name des Moduls ein Punkt der Name der Prozedur bzw. Funktion Anschließend folgen die weiteren Parameter. Der Aufruf einer Prozedur sieht daher wie folgt aus: Application.Run "!.", _

Parameter1, Parameter2, ...

Es folgt der Aufruf einer Funktion: Ergebnis = Application.Run("!. _

", Parameter1, Parameter2, ...)

Von einer Funktion in einem Klassenmodul einer anderen Datei, wie hier der Funktion Summe8(), kann nichts zurückgeliefert werden.

5.6    Module exportieren und importieren Möchten Sie Prozeduren und Funktionen in anderen Arbeitsmappen einsetzen, haben Sie mehrere Möglichkeiten: Sie kopieren oder verschieben den Code im VBE entweder in ein Modul der gewünschten Arbeitsmappe, damit er Ihnen in dieser Arbeitsmappe zur Verfügung steht, oder in die Persönliche Makroarbeitsmappe, damit er Ihnen jederzeit zur Verfügung steht. Sie exportieren ein ganzes Modul. Anschließend importieren Sie es in eine andere Arbeitsmappe oder in die Persönliche Makroarbeitsmappe. Dieser Vorgang werde ich nachfolgend erläutern.

5.6.1    Ein Modul exportieren Sie wählen das gewünschte Modul im Projekt-Explorer aus. Anschließend wählen Sie im Menü Datei den Menüpunkt Datei exportieren. Es erscheint das gleichnamige Dialogfeld. Sie erreichen es auch über das Kontextmenü, indem Sie mit der rechten Maustaste im Projekt-Explorer auf das zu exportierende Modul klicken. Wählen Sie den Speicherort aus. Die Dateiendung für Codemodule lautet .bas (siehe Abbildung 5.22). Sie können auch UserForm-Module exportieren, siehe Abschnitt 10.2, »Eigene Dialogfelder«. In diesem Fall lautet die Dateiendung .frm, und es wird zusätzlich eine weitere Datei mit der Dateiendung .frx gespeichert.

Abbildung 5.22     Datei mit VBA-Code exportieren

Möchten Sie ein Modul löschen, finden Sie im Kontextmenü den Menüpunkt Entfernen von. Zum Schutz vor einem unbeabsichtigten Löschen werden Sie gefragt, ob Sie das Modul vorher exportieren wollen. Stimmen Sie zu, landen Sie ebenfalls im Dialogfeld Datei exportieren.

5.6.2    Ein Modul importieren Zum Importieren markieren Sie zunächst im Projekt-Explorer diejenige Arbeitsmappe, in die ein Modul importiert wird. Anschließend wählen Sie im Menü Datei den Menüpunkt Datei importieren. Es erscheint das gleichnamige Dialogfeld, siehe Abbildung 5.23. Sie erreichen es auch über das Kontextmenü, indem Sie mit der rechten Maustaste im Projekt-Explorer auf die Arbeitsmappe klicken, in die importiert wird.

Abbildung 5.23     Datei mit VBA-Code importieren

Wählen Sie das Verzeichnis und das zu importierende Modul aus. Codemodule erkennen Sie an der Dateiendung .bas, UserFormModule an der Dateiendung .frm.

6    Mehr über Objekte In diesem Kapitel erfahren Sie mehr über den Umgang mit Objekten. Das Verständnis von Objekten hilft Ihnen beim Erstellen effektiverer Programme. Die Grundlagen von Objekten haben Sie in Kapitel 2, »Grundlagen von Objekten und Ereignissen«, kennengelernt. Im Folgenden erhalten Sie weiterführende Informationen zu diesem Thema.

6.1    Objektkatalog Im VBE blenden Sie mit der Taste (F2) den Objektkatalog ein. Wählen Sie darin eine der Klassen aus (siehe Abbildung 6.1), erscheint rechts eine Liste der zugehörigen Eigenschaften, Methoden und Ereignisse.

Abbildung 6.1     Objektkatalog

Eine weitere Hilfestellung wird über das Menü ? im VBE, Menüpunkt Microsoft Visual Basic for Applications-Hilfe, angeboten. Nach dem Aufruf wird die Online-Hilfe von Microsoft angezeigt, u. a. mit der VBA-Referenz für Excel, siehe Abbildung 6.2.

Abbildung 6.2     VBA-Referenz

6.2    Objekte referenzieren In vielen VBA-Anwendungen wird wie folgt auf Objekte zugegriffen: Eine Arbeitsmappe wird aktiviert. Ein Tabellenblatt wird aktiviert. Ein Zellbereich wird selektiert. Eigenschaften des selektierten Zellbereichs werden verändert, bzw. es werden Methoden auf den selektierten Zellbereich angewandt. Diese Vorgehensweise des Aktivierens und Selektierens ist zwar leicht verständlich, aber langsam und fehlerträchtig. Nachfolgend ein Beispiel: Sub AktivierenUndSelektieren()

ThisWorkbook.Activate

Worksheets("Tabelle1").Activate

Range("A7:A9").Select

Selection.Interior.Color = vbYellow

End Sub

Listing 6.1     Sub »AktivierenUndSelektieren()« in Mappe6.xlsm, Modul 1

Besser ist es, unmittelbar auf die Objekte zuzugreifen, und zwar mithilfe der Referenzierung. Damit laufen Ihre Anwendungen schneller und sind besser wartbar. Nachfolgend das obige Beispiel in verbesserter Form: Sub Referenzieren()

ThisWorkbook.Worksheets("Tabelle1"). _

Range("A10:A12").Interior.Color = vbYellow

End Sub

Listing 6.2     Sub »Referenzieren()« in Mappe6.xlsm, Modul 1

Der Zugriff orientiert sich an der Objekthierarchie: Arbeitsmappe, Tabellenblatt, Zellbereich, Eigenschaft, gegebenenfalls Untereigenschaft. Längere Anweisungen können über mehrere Zeilen verteilt werden.

6.2.1    Beispiel »Zellen verschieben« Mithilfe des ersten aufgezeichneten Makros in diesem Buch wurde der Inhalt einer Zelle in eine andere Zelle verschoben: Sub Makro1()

Range("A1").Select

Selection.Cut

Range("C1").Select

ActiveSheet.Paste

End Sub

Listing 6.3     Sub »Makro1()« in Mappe1.xlsm, Modul 1

Mit der Referenzierung lösen Sie das eindeutig und schneller: Sub Verschieben()

ThisWorkbook.Worksheets("Tabelle1").Range("A7:A9").Cut _

Destination:=ThisWorkbook.Worksheets("Tabelle1").Range("B7")

End Sub

Listing 6.4     Sub »Verschieben()« in Mappe6.xlsm, Modul 1

6.3    Mit »With« auf Objekte zugreifen Mithilfe von With stellen Sie einen Bezug zu einem Objekt her. Diesen Bezug können Sie anschließend mehrfach verwenden, um eine Reihe von Anweisungen für das betreffende Objekt in übersichtlicher Form durchzuführen. Der Aufbau sieht wie folgt aus: With Objekt

[ Anweisungen ]

End With

Nachfolgend ein Beispiel: Sub WithAnweisung()

With ThisWorkbook.Worksheets("Tabelle1").Range("A1:A3")

.Value = 12.8

.NumberFormatLocal = "0,000"

.Font.Size = 24

.Borders.Weight = xlThick

End With

End Sub

Listing 6.5     Sub »WithAnweisung()« in Mappe6.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 6.3.

Abbildung 6.3     Objektzugriff mit »With«

Mithilfe von With werden die Eigenschaften des Zellbereichs A1:A3 geändert. Nacheinander werden Werte für den Inhalt, das

Zahlenformat, die Schriftgröße und die Rahmenstärke zugewiesen. Zu Beginn der jeweiligen Anweisung wird ein Punkt notiert. Da sich die Anweisungen im With-Block befinden, ist damit der Bezug zum Objekt gegeben. Mit With können auch geschachtelte Bezüge erzeugt werden. Zur Verdeutlichung wurde das Beispiel mit den fünf Sortierschlüsseln aus Abschnitt 2.4.19, »Zellbereich sortieren«, umgeschrieben: Sub WithGeschachtelt()

ThisWorkbook.Worksheets("Tabelle4").Activate

With ActiveSheet.Sort

With .SortFields

.Clear

.Add Range("A1:A5")

.Add Range("B1:B5")

.Add Range("C1:C5")

.Add Range("D1:D5")

.Add Range("E1:E5")

End With

.SetRange Range("A1:E6")

.Apply

End With

End Sub

Listing 6.6     Sub »WithGeschachtelt()« in Mappe6.xlsm, Modul 1

Der äußere With-Block bezieht sich auf das Objekt Sort des aktiven Tabellenblatts. Für dieses Objekt werden die Methoden SetRange() und Apply() aufgerufen. Zudem wird auf die Auflistung SortFields des Objekts zugegriffen. Der innere With-Block bezieht sich auf die Auflistung SortFields des Objekts Sort des aktiven Tabellenblatts. Für diese Auflistung werden die Methoden Clear() und Add() aufgerufen.

6.4    Mit Objektvariablen arbeiten Sie kennen Variablen der elementaren Datentypen wie Integer, Double usw. zur Speicherung von Zahlen und Texten. Im Gegensatz dazu speichert eine Objektvariable einen Verweis auf ein Objekt. Dabei kann es sich um einen Verweis auf ein existierendes Objekt handeln, auf das Sie mit einem kürzeren Namen zugreifen möchten. Es kann sich aber auch um einen Verweis auf ein neu erzeugtes Objekt handeln. Nachfolgend ein erstes Beispiel: Sub ObjektVariable()

Dim Rg1 As Range

Dim Rg2 As Range

Set Rg1 = ThisWorkbook.Worksheets("Tabelle1").Range("B1:B3")

Set Rg2 = Rg1

Rg1.Value = 18.2

Rg1.NumberFormatLocal = "0,000"

Rg2.Font.Size = 24

Einrahmen Rg2

Set Rg1 = Nothing

Set Rg2 = Nothing

End Sub

Sub Einrahmen(x As Range)

x.Borders.Weight = xlThick

End Sub

Listing 6.7     Zwei Sub-Prozeduren in Mappe6.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 6.4.

Abbildung 6.4     Mit Objektvariablen arbeiten

Die Objektvariablen Rg1 und Rg2 werden mithilfe von As als Verweise auf Objekte des Typs Range deklariert. Eine Objektvariable erhält ihren Wert mithilfe von Set. Hier wird der Variablen Rg1 ein Zellbereich zugewiesen. Damit ist es möglich, mithilfe von Rg1 auf diesen Zellbereich zuzugreifen. Der Objektvariablen Rg2 wird der Wert der Objektvariablen Rg1 zugewiesen. Anschließend verweisen beide Objektvariablen auf denselben Zellbereich und bieten die Möglichkeit, auf diesen Zellbereich zuzugreifen. Im vorliegenden Beispiel werden der Inhalt, das Zahlenformat und die Schriftgröße des Zellbereichs geändert. Eine Objektvariable kann an eine Prozedur bzw. Funktion übergeben werden. Hier wird in der aufgerufenen Prozedur Einrahmen() die Rahmenstärke gesetzt. Der Parameter der Prozedur hat den Typ Range. Zur Fehlervermeidung sollten Sie einer Objektvariablen nach ihrer Verwendung den Wert Nothing zuweisen. Damit geht der Bezug zum Objekt verloren und es kann kein versehentlicher Zugriff mehr stattfinden.

[»]  Hinweis Nach der Zuweisung für Rg1 erleichtert die Entwicklungsumgebung dem Entwickler die Arbeit: Sobald er den Punkt hinter Rg1 eingibt, erscheint eine Liste der Eigenschaften und Methoden des betreffenden Objekts. Dies ist nach der Eingabe des Punktes hinter Range("B1:B3") nicht der Fall. Mit der Taste (F1) wird automatisch die Hilfe für die Eigenschaft oder Methode des passenden Objekttyps aufgerufen.

6.4.1    Objektvariablen hierarchisch zuweisen Sie können Objektvariablen ihren Wert auch stufenweise (über die Objekthierarchie) zuweisen. Wird auf mehrere Objekte in unterschiedlichen Ebenen der Hierarchie zugegriffen, macht das den Code übersichtlicher. Ein Beispiel: Sub ObjektVariableHierarchisch()

Dim WS As Worksheet

Dim Rg1 As Range, Rg2 As Range

Set WS = ThisWorkbook.Worksheets("Tabelle1")

Set Rg1 = WS.Range("C1:C2")

Set Rg2 = WS.Range("D1:D2")

Rg1.Value = 1.7

Rg2.Value = 3.4

Set Rg1 = Nothing

Set Rg2 = Nothing

Set WS = Nothing

End Sub

Listing 6.8     Sub »ObjektVariableHierarchisch()« in Mappe6.xlsm, Modul 1

Das Ergebnis sehen Sie in Abbildung 6.5.

Abbildung 6.5     Über die Hierarchie ausgewählte Bereiche

Zunächst wird WS als Verweis auf das Tabellenblatt Tabelle1 genutzt. Anschließend werden Rg1 und Rg2 als Verweise auf verschiedene Bereiche dieses Tabellenblatts eingesetzt.

6.4.2    Neue Objekte erzeugen Viele Objekte in VBA-Anwendungen existieren bereits in Excel. Es handelt sich um Objekte, die Sie »sehen« (Range, Worksheet usw.). Es gibt aber auch »unsichtbare« Hilfsobjekte, die Sie erst im Verlauf Ihres VBA-Programms erzeugen. Dies kann z. B. eine Verbindung zu einer Datenbank (siehe Abschnitt 9.8.2, »Beispieldatenbank: Verbindung herstellen«) oder eine Auflistung (siehe Abschnitt 6.6, »Collections«) sein. Solche Objekte werden mithilfe des Schlüsselworts New erzeugt. Anschließend kann ein Verweis auf das Objekt eingerichtet werden. Es folgt ein Beispiel mit einem Objekt des Typs Collection: Sub NeuesObjekt()

Dim C1 As New Collection

Dim C2 As Collection

Set C2 = New Collection

Set C1 = Nothing

Set C2 = Nothing

End Sub

Listing 6.9     Sub »NeuesObjekt()« in Mappe6.xlsm, Modul 1

In der ersten Anweisung wird mit New Collection eine neue Auflistung erstellt. Gleichzeitig wird die Objektvariable C1 deklariert und als Verweis auf diese Auflistung eingerichtet. Die Objektvariable C2 verweist zunächst auf kein Objekt. Das Objekt wird erst in der nächsten Anweisung mit New Collection erzeugt. Mit Set wird C2 als Verweis auf diese neue Auflistung eingerichtet. Durch die Zuweisung von Nothing wird auch hier die Verbindung zwischen Verweis und Objekt wieder gelöst. Gibt es auf ein selbst erzeugtes Objekt keinen Verweis mehr, ist ein Zugriff auf dieses Objekt nicht mehr möglich. Der benötigte Speicherplatz wird vom System freigegeben und steht Ihrer Anwendung anschließend wieder zur Verfügung.

6.4.3    Objekttyp ermitteln Eine Objektvariable sollte mit dem passenden Typ deklariert werden. Bei vielen Objekten ist der Typ allerdings nicht unmittelbar erkennbar. Die Funktion TypeName() ist in der Lage, den Typ einer Variablen, eines Datenfelds oder eines Objekts zu erkennen. Hat das geprüfte Objekt den Datentyp Variant, wird Empty zurückgeliefert. Nachfolgend ein Beispiel mit einer Reihe von Variablen und Objekten: Sub ObjektTyp()

Dim i As Integer

Dim a(1 To 5) As Double

Dim b

Dim c As Variant

Dim Ws1 As Worksheet

Set Ws1 = ThisWorkbook.Worksheets("Tabelle1")

ThisWorkbook.Worksheets("Tabelle2").Activate



Range("A1").Value = TypeName(i)

Range("A2").Value = TypeName(a)

Range("A3").Value = TypeName(b)

Range("A4").Value = TypeName(c)

Range("A5").Value = TypeName(ThisWorkbook)

Range("A6").Value = TypeName(ThisWorkbook.Name)

Range("A7").Value = TypeName(Ws1)

Range("A8").Value = TypeName(Ws1.Range("A1:A5"))

Range("A9").Value = TypeName(Ws1.Range("A1:A5").Borders)

Range("A10").Value = TypeName(Ws1.Range("A1:A5").Font)

Range("A11").Value = TypeName(Nothing)

Set Ws1 = Nothing

End Sub

Listing 6.10     Sub »ObjektTyp()« in Mappe6.xlsm, Modul 1

Die Typen der einzelnen Variablen i und des Datenfelds a werden erkannt, ebenso wie der Typ der Arbeitsmappe, des Tabellenblatts und des Zellbereichs. Eine Variable, die ohne Datentyp deklariert wird, besitzt automatisch den Datentyp Variant. Die Eigenschaft Name hat den Datentyp String. Die Untereigenschaften Borders und Font haben den Typ Borders bzw. Font. Der Wert Nothing hat den eigenen Typ Nothing. Das Ergebnis sehen Sie in Abbildung 6.6.

Abbildung 6.6     Ergebnis der Funktion »TypeName()«

6.5    For-Each-Schleife Die Schleife mit »For Each ... In ... Next« wird bei Auflistungen oder Datenfeldern eingesetzt. In der Objekthierarchie von Excel gibt es zahlreiche Auflistungen, z. B. Workbooks und Worksheets. Nachfolgend ein Beispiel mit der Auflistung Workbooks, also der Liste aller geöffneten Excel-Dateien: Sub ForEachWorkbook()

Dim WB As Workbook

Dim Ausgabe As String

Ausgabe = "Workbooks: "

For Each WB In Workbooks

Ausgabe = Ausgabe & WB.Name & " "

Next WB

MsgBox Ausgabe

Set WB = Nothing

End Sub

Listing 6.11     Sub »ForEachWorkbook()« in Mappe6.xlsm, Modul 1

Ein mögliches Ergebnis sehen Sie in Abbildung 6.7.

Abbildung 6.7     Liste der geöffneten Workbooks

Die Variable WB wird als Verweis auf ein Objekt des Typs Workbook deklariert. Mithilfe der Schleife wird jedes Element der Auflistung Workbooks durchlaufen. Das jeweils aktuelle Element wird automatisch mit WB bezeichnet. Es ist keine Zuweisung mithilfe von Set erforderlich. Hier wird der Name des jeweils aktuellen Elements einer Ausgabeliste hinzugefügt. Zur Verdeutlichung des Elements in der

Schleife wird nach Next wiederum WB notiert. Ein weiteres Beispiel mit der Liste der Tabellenblätter: Sub ForEachWorksheet()

Dim WS As Worksheet

Dim Ausgabe As String

Ausgabe = "Worksheets: "

For Each WS In ThisWorkbook.Worksheets

Ausgabe = Ausgabe & WS.Name & " "

Next WS

MsgBox Ausgabe

Set WS = Nothing

End Sub

Listing 6.12     Sub »ForEachWorksheet()« in Mappe6.xlsm, Modul 1

Ein mögliches Ergebnis sehen Sie in Abbildung 6.8.

Abbildung 6.8     Liste der Worksheets

Die Variable WS wird als Verweis auf ein Objekt des Typs Worksheet deklariert. In der Schleife verweist WS auf das jeweils aktuelle Element.

6.6    Collections Zusätzlich zu den vordefinierten Auflistungen, z. B. Worksheets oder Workbooks, können Sie eigene Auflistungen erschaffen. Damit wird aus zusammengehörigen Elementen eine Sammlung erstellt. Die Elemente einer eigenen Auflistung können leichter hinzugefügt oder entfernt werden als die Elemente eines Datenfelds. Allerdings haben alle Elemente einer Auflistung den Datentyp Variant. Zur Erstellung einer eigenen Auflistung wird der Datentyp Collection verwendet. Objekte dieses Typs haben folgende Eigenschaften und Methoden: Methode Add(): Element hinzufügen Eigenschaft Count: Anzahl der Elemente angeben Methode Remove(): Element löschen Auf die Elemente einer Auflistung wird mithilfe einer For-EachSchleife oder eines Index zugegriffen. Im folgenden Beispiel wird eine Auflistung von Zahlen erstellt: Sub CollectionListe()

Dim Auflistung As New Collection

Auflistung.Add 5.2

Auflistung.Add 9.6

Auflistung.Add -3.8

Auflistung.Add 12.2

ListeAusgabe Auflistung

If Auflistung.Count >= 2 Then Auflistung.Remove 2

ListeAusgabe Auflistung

Set Auflistung = Nothing

End Sub

Sub ListeAusgabe(X As Collection)

Dim i As Integer

Dim Ausgabe As String

Dim Element As Variant

Ausgabe = "Index: "

For i = 1 To X.Count

Ausgabe = Ausgabe & i & ": " & X(i) & " "

Next i

MsgBox Ausgabe

Ausgabe = "For Each: "

For Each Element In X

Ausgabe = Ausgabe & Element & " "

Next Element

MsgBox Ausgabe

End Sub

Listing 6.13     Zwei Sub-Prozeduren in Mappe6.xlsm, Modul 1

In der Prozedur CollectionListe() wird mit New Collection ein neues Collection-Objekt erzeugt und mit Dim der Verweis Auflistung auf das Objekt eingerichtet. Mithilfe der Methode Add() werden dieser eigenen Auflistung einige Zahlen hinzugefügt. Die Auflistung wird zur Ausgabe an die Prozedur ListeAusgabe() übergeben. Das zweite Element der Auflistung wird mithilfe der Methode Remove() entfernt. Anschließend erfolgt wiederum eine Ausgabe. In der Prozedur ListeAusgabe() stellt der Parameter X einen Verweis auf ein Collection-Objekt dar. Die Eigenschaft Count wird für den Aufbau der For-Next-Schleife genutzt, in der die Elemente der Auflistung über den Index erreicht werden. Alternativ werden die Elemente der Auflistung mithilfe einer For-Each-Schleife ausgegeben. Dabei wird eine Variable des Datentyps Variant benötigt.

6.7    Hauptobjekt »Application« Das Objekt Application ist das Hauptobjekt. Es steht am oberen Ende der Objekthierarchie und repräsentiert die Anwendung Excel selbst. Einige seiner Eigenschaften und Methoden werde ich nachfolgend erläutern.

6.7.1    Anwendungspfad ausgeben Mit folgender Prozedur wird der Pfad ausgegeben, in dem Excel installiert ist: Sub AnwendungsPfad()

MsgBox Application.Path

End Sub

Listing 6.14     Sub »AnwendungsPfad()« in Mappe6.xlsm, Modul 1

Die Eigenschaft Path des Application-Objekts enthält den Namen des Verzeichnisses auf dem PC, in dem die Anwendung Excel installiert wurde. Die Ausgabe bei einer Standardinstallation sehen Sie in Abbildung 6.9.

Abbildung 6.9     Eigenschaft »Application.Path«

6.7.2    Prozedur zeitverzögert aufrufen Der zeitverzögerte Aufruf einer Prozedur wird wie folgt durchgeführt:

Sub AufrufInZukunft()

Application.OnTime Now + TimeValue("00:00:05"), "AnwendungsPfad"

End Sub

Listing 6.15     Sub »AufrufInZukunft()« in Mappe6.xlsm, Modul 1

Die Methode OnTime() des Application-Objekts dient dazu, eine Prozedur in der Zukunft auszuführen. Die Methode hat zwei Parameter: eine Zeitangabe und den Namen der auszuführenden Prozedur, und zwar in doppelten Anführungszeichen. Die Zeitangabe ist entweder absolut (z. B. um 17:35:30 Uhr) oder relativ (z. B. wie hier: in 5 Sekunden). Ist sie relativ, wird zunächst die aktuelle Uhrzeit mit der vordefinierten Funktion Now() ermittelt. Zu dieser Uhrzeit wird eine Zeitdifferenz addiert, die mithilfe der vordefinierten Funktion TimeValue() erstellt wird.

6.7.3    Excel-Anwendung schließen Mit folgender Prozedur wird die gesamte Anwendung Excel geschlossen: Sub AnwendungSchliessen()

Application.Quit

End Sub

Listing 6.16     Sub »AnwendungSchliessen()« in Mappe6.xlsm, Modul 1

Die Methode Quit() des Objekts Application schließt Excel einschließlich aller geöffneten Arbeitsmappen, des VBE und der Excel-Hilfe. Für jede geänderte Arbeitsmappe wird der Benutzer gefragt, ob er sie speichern möchte, siehe Abbildung 6.10.

Abbildung 6.10     »Application.Quit()« – Frage zur Speicherung

6.8    Filtern Größere Datenmengen untersuchen Sie in Excel mithilfe von Filtern. Dabei legen Sie fest, welcher Teil der Daten angezeigt wird. Dies lässt sich in VBA mithilfe der Methode AutoFilter() auch automatisieren. Als anschauliche Basis für den Einsatz von Filtern wird die Tabelle der Artikel aus der Datenbank Nordwind verwendet. Diese Beispieldatenbank wurde in früheren Versionen von MS Office zusammen mit MS Access ausgeliefert. Die Tabelle umfasst 77 Datensätze mit jeweils sechs Spalten. Zur Verdeutlichung eines Datumsfilters wird noch eine siebte Spalte mit Datumsangaben hinzugefügt. Die zufälligen Werte für diese Spalte werden mithilfe der nachfolgenden Prozedur erzeugt: Sub SpalteDatum()

Dim i As Integer

Randomize

ThisWorkbook.Worksheets("Tabelle5").Activate

For i = 2 To 78

Cells(i, 7).Value = Int(Rnd * 30) + 43900

Next i

Range("G2:G78").NumberFormatLocal = "TT.MM.JJJJ"

End Sub

Listing 6.17     Sub »SpalteDatum()« in Mappe6.xlsm, Modul 2

Mithilfe des Zufallsgenerators werden zufällige ganze Zahlen von 44.700 bis 44.729 ermittelt. Passend formatiert ergeben sich daraus Datumsangaben vom 19.05.2022 bis zum 17.06.2022. Es folgen einige kurze Prozeduren, in denen die Methode AutoFilter() angewandt wird. Zunächst ein einfacher Zahlenfilter:

Sub ZahlenfilterGleich()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 6, "0"

End Sub

Listing 6.18     Sub »ZahlenfilterGleich()« in Mappe6.xlsm, Modul 2

Der Aufruf der Methode AutoFilter() ohne Parameter löscht den bisher geltenden Filter. Anschließend werden die Daten vollständig und ungefiltert dargestellt. Standardmäßig wird die Methode AutoFilter() mit mindestens zwei Parametern aufgerufen: Der erste Parameter entspricht der gefilterten Spalte, der zweite Parameter dem Filterkriterium. Der Aufruf mit den Parametern 6 und "0" führt dazu, dass Spalte 6 für den Lagerbestand gefiltert wird. Es werden nur noch diejenigen Datensätze angezeigt, deren Wert in dieser Spalte gleich 0 ist. Es folgt ein Filter mit einem Vergleichsoperator: Sub ZahlenfilterVergleich()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 5, ">20"

End Sub

Listing 6.19     Sub »ZahlenfilterVergleich()« in Mappe6.xlsm, Modul 2

Nun werden nur noch diejenigen Datensätze angezeigt, deren Wert in Spalte 5 für den Einzelpreis größer als 20 ist. Es gibt die Vergleichsoperatoren , = und . Der Operator = entspricht in seiner Wirkung dem Filter aus dem vorherigen Beispiel. Es folgt ein Filter mit zwei Bedingungen (bezüglich einer Spalte), die miteinander verknüpft sind: Sub ZahlenfilterZwischen()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 6, ">20", xlAnd, "20"

ActiveSheet.UsedRange.AutoFilter 6, ">40"

End Sub

Listing 6.21     Sub »DoppelFilter()« in Mappe6.xlsm, Modul 2

Nun werden nur noch diejenigen Datensätze angezeigt, deren Wert in Spalte 5 für den Einzelpreis größer als 20 ist und deren Wert in Spalte 6 für den Lagerbestand größer als 40 ist. Der zweite Filter verstärkt die Wirkung des ersten Filters. Mithilfe von Textfiltern werden Spalten mit textlichen Inhalten gefiltert. Zunächst ein einfaches Beispiel: Sub TextfilterGleich()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 3, "Getränke"

End Sub

Listing 6.22     Sub »TextfilterGleich()« in Mappe6.xlsm, Modul 2

Nun werden nur noch die Datensätze aus der Kategorie "Getränke" angezeigt. Möchten Sie die Artikel aus mehreren Kategorien sehen, geht das folgendermaßen: Sub TextfilterMehrereGleich()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 3, "Getränke", xlOr, "Gewürze"

End Sub

Listing 6.23     Sub »TextfilterMehrereGleich()« in Mappe6.xlsm, Modul 2

Die integrierte Konstante xlOr legt fest, dass nur eines der beiden Kriterien benötigt wird. Bei Textfiltern können Sie auch Platzhalter nutzen: Sub TextfilterBeginntMit()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 2, "M*"

End Sub

Listing 6.24     Sub »TextfilterBeginntMit()« in Mappe6.xlsm, Modul 2

Nun werden nur noch die Datensätze angezeigt, deren Wert in Spalte 2 mit »M« beginnt. Der Platzhalter kann auch mehrfach angewandt werden: Sub TextfilterEnthaelt()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 2, "*ed*"

End Sub

Listing 6.25     Sub »TextfilterEnthaelt()« in Mappe6.xlsm, Modul 2

Nun werden nur noch die Datensätze angezeigt, deren Wert in Spalte 2 die Zeichenfolge »ed« an beliebiger Stelle enthält. Für den nachfolgenden Datumsfilter nutzen Sie die amerikanische Schreibweise (JJJJ/M/T): Sub Datumsfilter()

ThisWorkbook.Worksheets("Tabelle5").Activate

ActiveSheet.UsedRange.AutoFilter

ActiveSheet.UsedRange.AutoFilter 7, ">=2022/5/30", xlAnd, " 3600"

In der WHERE-Klausel geben Sie Bedingungen an, ähnlich wie bei einer Verzweigung. Das Ergebnis enthält nur die Datensätze, die dieser Bedingung genügen – in diesem Fall die Datensätze, bei denen der Wert im Feld gehalt größer als 3600 ist, siehe Abbildung 9.47.

Abbildung 9.47     Nur bestimmte Datensätze auswählen

[»]  Hinweis Diese und die nachfolgenden Ausgaben beziehen sich auf die Originalwerte der Tabelle, bevor sie um 5 % erhöht wurden. SQLCommand = "SELECT * FROM personen WHERE name = 'Schmitz'"

Wird ein Vergleich mit dem Wert einer Zeichenkette oder eines Datums vorgenommen, muss dieser Wert in einfache Hochkommata (') gesetzt werden (Abbildung 9.48).

Abbildung 9.48     Über eine Zeichenkette auswählen

9.8.7    Operatoren Sie können die Vergleichsoperatoren aus Tabelle 9.1 verwenden. Operator Erläuterung

Operator Erläuterung =

gleich

ungleich

>

größer als

>=

größer als oder gleich


Ausgabe.Cells( _

z + 1, SortierSpalte).Value Then Tauschen = True

End If

If Tauschen Then

For s = 1 To Ausgabe.Columns.Count

Temp = Ausgabe.Cells(z, s).Value

Ausgabe.Cells(z, s).Value = Ausgabe.Cells(z + 1, s).Value

Ausgabe.Cells(z + 1, s).Value = Temp

Next s

End If

Next z

Loop While Tauschen

End Sub

Listing 11.10     Sub »PSortieren()« in Mappe11.xlsm

Zunächst wird der untersuchte Zellbereich mithilfe der Funktion Copy() vollständig in den Ausgabebereich kopiert. Die Sortierung erfolgt mithilfe des Bubble-Sort-Verfahrens, siehe Abschnitt 5.2.2, »Datenfeld sortieren«. Für alle Werte aus der Sortierspalte des untersuchten Zellbereichs wird in einer inneren For-Next-Schleife geprüft, ob sie bezüglich des nachfolgenden Werts in der richtigen Reihenfolge stehen. Trifft das nicht zu, wird die boolesche Variable Tauschen, die vor Beginn der For-Next-Schleife auf False gesetzt wurde, auf True gesetzt. In diesem Fall werden die zugehörigen Zeilen des Zellbereichs miteinander getauscht. Bei dem Tausch wird eine temporäre Hilfsvariable benötigt. Mithilfe der booleschen Variablen Absteigend wird zwischen aufund absteigender Sortierung unterschieden. Diese Prüfung in der inneren For-Next-Schleife wird innerhalb einer äußeren Do-Loop-Schleife wiederholt, solange in der inneren For-

Next-Schleife mindestens ein Tausch stattgefunden hat.

12    Beispielprojekte In den Beispielprojekten werden Zusammenhänge zwischen den verschiedenen VBA-Themen verdeutlicht. In diesem Kapitel werden wichtige Themen in VBA auf spielerische Art und Weise miteinander verbunden. Als Beispiel dienen das Memory-Spiel, eine Variation des Snake-Spiels, ein VokabelLernprogramm und ein Puzzle. Das Zusammenspiel zwischen Codemodulen und Ereignisprozeduren in Klassenmodulen wird verdeutlicht. Wir werden mit Variablen unterschiedlicher Gültigkeitsbereiche arbeiten. Ein Zufallsgenerator und zeitlich parallele Abläufe kommen zum Einsatz – wie bei vielen Spielen und Lernprogrammen.

12.1    Memory Zunächst werde ich den Ablauf des Spiels beschreiben, das Sie in der Datei Memory.xlsm finden.

12.1.1    Spielablauf Nach dem Öffnen der Datei erscheint ein leeres Spielfeld mit insgesamt 36 eingerahmten Zellen. Rechts daneben sieht die

Benutzerin zwei grau eingefärbte Zellbereiche, die als Schaltflächen dienen, siehe Abbildung 12.1. Nach der Betätigung der Schaltfläche Starten werden den 36 Zellen 18 Paare von Zeichen zufällig zugeordnet. Die Zeichen sind zunächst nicht zu sehen. Stattdessen werden die Zellen grau eingefärbt, siehe Abbildung 12.2. Nach dem Anklicken einer ersten Zelle ist das Zeichen aus dieser Zelle sichtbar. Nach dem Anklicken einer zweiten Zelle ist das Zeichen darin ebenfalls sichtbar, siehe Abbildung 12.3.

Abbildung 12.1     Ansicht nach dem Öffnen der Datei

Abbildung 12.2     Ansicht nach dem Start

Abbildung 12.3     Anzeige von zwei Zeichen

Eine Sekunde nach der Anzeige des zweiten Zeichens werden beide Zeichen wieder verdeckt. Hat die Benutzerin zwei Zellen mit demselben Zeichen angeklickt, werden diese Zellen ohne Hintergrundfarbe angezeigt. Dies ist in Abbildung 12.3 bereits für zwei Zeichenpaare geschehen. Nach dem Aufdecken des 18. Zeichenpaars ist das Spiel beendet. Das Betätigen der Schaltfläche Info zeigt die Spielbeschreibung an, siehe Abbildung 12.4.

Abbildung 12.4     Beschreibung des Spiels

12.1.2    Aufbau des Spielfelds Im Klassenmodul DieseArbeitsmappe steht die Prozedur Workbook_Open() zum Aufbau des Spielfelds nach dem Öffnen der Datei: Private Sub Workbook_Open()

' Zellen löschen und in quadratische Form bringen

ThisWorkbook.Worksheets("Tabelle1").Activate

Cells.Delete

Cells.RowHeight = 20

Cells.ColumnWidth = 3.5

' Rahmen für Spielfeld mit Zellen versehen

With Range("B2:G7")

.Borders.Weight = xlMedium

.HorizontalAlignment = xlCenter

.VerticalAlignment = xlCenter

.Font.Size = 14

End With

' Startzelle

Range("I2").Value = "Starten"

With Range("I2:K2")

.Interior.Color = RGB(192, 192, 192)

.MergeCells = True

.HorizontalAlignment = xlCenter

.VerticalAlignment = xlCenter

End With

' Infozelle

Range("I7").Value = "Info"

With Range("I7:K7")

.Interior.Color = RGB(192, 192, 192)

.MergeCells = True

.HorizontalAlignment = xlCenter

.VerticalAlignment = xlCenter

End With

End Sub

Listing 12.1     Sub »Workbook_Open()« in Memory.xlsm,

Klassenmodul »DieseArbeitsmappe«

Nach der Aktivierung des Tabellenblatts Tabelle1 werden mithilfe der Methode Delete() des Cells-Objekts alle Zellen gelöscht. Den beiden Eigenschaften RowHeight und ColumnWidth werden passende Werte zugewiesen, damit die Zellen eine quadratische Form erhalten. Alle Zellen des Spielfelds (im Zellbereich B2:G7) erhalten einen Rahmen. Ihr Inhalt wird horizontal und vertikal zentriert und erhält die Schriftgröße 14. Die drei Zellen für die Schaltfläche Starten (im Zellbereich I2:K2) werden mithilfe der Eigenschaft MergeCells miteinander verbunden,

erhalten einen grauen Hintergrund sowie einen horizontal und vertikal zentriert dargestellten Text. Das Gleiche geschieht für die Schaltfläche Info (im Zellbereich I7:K7).

12.1.3    Spiel starten Im Modul Modul1 stehen einige Variablen bzw. ein Feld mit dateiweitem Gültigkeitsbereich und die Prozedur Starten(). Sie dienen der Initialisierung des Spiels und der Kontrolle des Spielzustands. Zunächst die Variablen: Public Public Public Public

Zeichen(2 To 7, 2 To 7) As String

Gestartet As Boolean

ErstesZeichenSichtbar As Boolean

Gefunden As Integer

Listing 12.2     Variablen und Feld in Memory.xlsm, Modul 1

Die Variablen und das Feld werden an unterschiedlichen Stellen der Anwendung benötigt. Das zweidimensionale Feld Zeichen hat sechs mal sechs Elemente. Darin stehen die 18 zufällig verteilten Zeichenpaare. Die boolesche Variable Gestartet verhindert das erneute Starten des Spiels, falls es bereits gestartet wurde. Nach dem Anklicken einer Zelle muss das Programm wissen, ob es sich um die erste oder die zweite Zelle handelt. Das wird mithilfe der booleschen Variablen ErstesZeichenSichtbar ermittelt. Die Integer-Variable Gefunden enthält die Anzahl der bisher gefundenen Paare. Nach dem Erreichen des Wertes 18 ist das Spiel beendet. Es folgt die Prozedur Starten(): Sub Starten()

Dim z As Integer, s As Integer

Dim i As Integer

' Zum Mischen

Dim z1 As Integer, s1 As Integer

Dim z2 As Integer, s2 As Integer

Dim Tausch As String

' Nicht zweimal starten

If Gestartet Then Exit Sub

Gestartet = True

' Feld füllen

z = 2

s = 2

For i = 1 To 18

Zeichen(z, s) = Chr(i + 64)

Zeichen(z, s + 1) = Chr(i + 64)

s = s + 2

If s > 7 Then

z = z + 1

s = 2

End If

Next i

' Zufallsgenerator initialisieren

Randomize

' Feld mischen. Im For i = 1 To 180

z1 = Int(Rnd * s1 = Int(Rnd * z2 = Int(Rnd * s2 = Int(Rnd *

Schnitt wird jede Zelle fünfmal getauscht.

6 6 6 6

+ + + +

2)

2)

2)

2)



Tausch = Zeichen(z1, s1)

Zeichen(z1, s1) = Zeichen(z2, s2)

Zeichen(z2, s2) = Tausch

Next i

' Zellen verdecken

For z = 2 To 7

For s = 2 To 7 Cells(z, s).Value = ""

Cells(z, s).Interior.Color = RGB(192, 192, 192)

Next s

Next z

' Anfangswerte setzen

ErstesZeichenSichtbar = False

Gefunden = 0

End Sub

Listing 12.3     Sub »Starten()« in Memory.xlsm, Modul 1

Die drei Integer-Variablen z, s und i werden für die Belegung des zweidimensionalen Felds verwendet. Die vier Integer-Variablen z1, z2, s1 und s2 sowie die String-Variable Tausch dienen zum Mischen der Zeichen. Steht die boolesche Variable Gestartet auf True, wird das Spiel nicht erneut gestartet. Handelt es sich um den ersten Start, wird sie auf True gesetzt. Das zweidimensionale Feld wird zeilenweise gefüllt, zunächst zwei Elemente mit dem Zeichen A, dann zwei Elemente mit dem Zeichen B usw. Nach dem Füllen der ersten Zeile folgt das Füllen der zweiten Zeile usw. Die Anweisung Randomize initialisiert den Zufallsgenerator für das nachfolgende Mischen der Zeichen innerhalb des Felds. Der Mischvorgang: Insgesamt 180-mal werden jeweils zwei Elemente des Felds mithilfe von Rnd() zufällig ermittelt und miteinander getauscht. Auf diese Weise erhält jedes Feldelement im Durchschnitt zehnmal einen neuen Inhalt. Alle Zellen des Spielfelds werden geleert und grau eingefärbt. Es werden zwei Anfangswerte gesetzt: Das erste Zeichen ist nicht sichtbar, und es wurden bisher 0 Zeichenpaare gefunden.

12.1.4    Spiel bedienen Die Prozedur Worksheet_SelectionChange() im Klassenmodul zum Objekt Tabelle1 wird für die Bedienung des Spiels benötigt. Zudem gibt es zwei Variablen mit modulweitem Gültigkeitsbereich: Dim z1 As Integer, s1 As Integer



Private Sub Worksheet_SelectionChange(ByVal Target As Range)

Dim z As Integer, s As Integer

Dim Startzeit As Single

' Starten und Info

If Target.Address = "$I$2:$K$2" Then

Starten

ElseIf Target.Address = "$I$7:$K$7" Then

MsgBox "Finden Sie 18 Paare von Zeichen." & vbCrLf & _

"Wählen Sie nacheinander zwei Zellen aus." & vbCrLf & _

"Sie sehen dann jeweils das Zeichen in der Zelle." & _

vbCrLf & "Eine Sekunde nach Auswahl der 2. Zelle " & _

"werden beide Zeichen verdeckt.", , "Spielbeschreibung"

' Memory-Zellen

Else

' Welche Zelle?

z = CInt(Mid(Target.Address, 4, 1))

s = Asc(Mid(Target.Address, 2, 1)) - 64

' Zelle außerhalb?

If z < 2 Or z > 7 Or s < 2 Or s > 7 Then Exit Sub

' Zeichen mittlerweile aus dem Spiel?

If Zeichen(z, s) = "" Then Exit Sub

' Zweites Zeichen anzeigen, warten, beide Zeichen verdecken

If ErstesZeichenSichtbar Then

ErstesZeichenSichtbar = False

' Zeichen anzeigen

Cells(z, s).Value = Zeichen(z, s)

Cells(z, s).Interior.Color = xlNone

' Warten

Startzeit = Timer

Do While Timer < Startzeit + 1

Loop

' Beide Zellen leeren

Cells(z, s).Value = ""

Cells(z1, s1).Value = ""

' Falls Paar gefunden: beide Zeichen aus dem Spiel

If Zeichen(z, s) = Zeichen(z1, s1) Then

Cells(z, s).Interior.Color = xlNone

Cells(z1, s1).Interior.Color = xlNone

Zeichen(z, s) = ""

Zeichen(z1, s1) = ""

' Zählen

Gefunden = Gefunden + 1

If Gefunden = 18 Then

Gestartet = False

MsgBox "Ende des Spiels", , "Ende"

End If

' Falls kein Paar gefunden: beide Zeichen verdecken

Else

Cells(z, s).Interior.Color = RGB(192, 192, 192)

Cells(z1, s1).Interior.Color = RGB(192, 192, 192)

End If

' Erstes Zeichen anzeigen und Zelle speichern

Else

ErstesZeichenSichtbar = True

Cells(z, s).Value = Zeichen(z, s)

Cells(z, s).Interior.Color = xlNone

z1 = z

s1 = s

End If

End If

End Sub

Listing 12.4     Variablen und Sub-Prozedur in Memory.xlsm, Klassenmodul »Tabelle1«

In den beiden modulweiten Variablen z1 und s1 werden die Nummern der Zeile und der Spalte der jeweils ersten angeklickten Zelle gespeichert. Die Prozedur Worksheet_SelectionChange() wird durch das Anklicken einer neuen Zelle ausgelöst. Die beiden Variablen z und s werden zur Speicherung der Nummer der Zeile und der Spalte dieser Zelle genutzt. Die Variable Startzeit wird für die Steuerung eines zeitlich parallelen Ablaufs benötigt. Es wird die Zeit gespeichert, zu der dieser Ablauf startet. Der ausgewählte Zellbereich wird als Range über die Objektvariable Target ermittelt. Die Eigenschaft Address des Target-Objekts enthält die Adresse der angeklickten Zelle als Zeichenkette. Klickt der Benutzer eine von mehreren miteinander verbundenen Zellen an,

wird die Adresse des gesamten Zellbereichs geliefert, nicht die Adresse einer einzelnen Zelle. Handelt es sich um die Adresse der Schaltfläche Starten, wird die gleichnamige Prozedur in Modul1 gestartet. Handelt es sich um die Adresse der Schaltfläche Info, wird eine Nachrichtenbox mit der Spielbeschreibung ausgegeben. Handelt es sich um die Adresse einer beliebigen anderen Zelle, werden mithilfe der Funktionen Mid(), CInt() und Asc() die Nummer der Zeile und die Nummer der Spalte aus der Zeichenkette ermittelt: Die Funktion Mid() liefert eine Teilzeichenkette. Im ersten Parameter steht die Zeichenkette, aus der ein Teil ermittelt wird. Der zweite und der dritte Parameter geben Beginn und Länge der Teilzeichenkette an. Wird bei der Umwandlung einer Zeichenkette eine ganze Zahl erwartet, können Sie die Funktion CInt() verwenden. Die Funktion Asc() liefert die Codenummer eines Zeichens. Die Codenummern von 65 bis 90 gelten für die Großbuchstaben von A bis Z. Zieht man von der Codenummer den Wert 64 ab, ergeben sich Zahlen von 1 bis 26. Für Spalte A ergibt sich der Wert 1, für B der Wert 2 usw. Handelt es sich um eine Adresse außerhalb des Spielfelds, wird die Prozedur unmittelbar verlassen. Nachfolgend wird davon ausgegangen, dass es sich um eine Adresse innerhalb des Spielfelds handelt. Handelt es sich um eine Zelle, deren Inhalt bereits aufgedeckt wurde, ist das zugehörige Element des zweidimensionalen Felds leer. Die Prozedur wird unmittelbar verlassen. An dieser Stelle sehen

Sie, dass das Feld der Zeichen und das Spielfeld mit den Zellen immer synchron gehalten werden müssen. Nun wird mithilfe der booleschen Variablen ErstesZeichenSichtbar ermittelt, ob es sich bei der Zelle um die erste oder die zweite Zelle handelt, die der Benutzer angeklickt hat. Ist es die zweite Zelle, startet der nachfolgende Ablauf: Das zweite Zeichen aus dem Feld wird in der zugehörigen Zelle angezeigt. Die Zelle wird ohne Hintergrundfarbe dargestellt. Es wird eine Sekunde gewartet. Dies geschieht mithilfe einer DoLoop-Schleife. Diese läuft, solange der Zeitpunkt Startzeit + 1 Sekunde noch nicht erreicht wurde. Dabei wird mehrmals die Anzahl der Sekunden seit Mitternacht mithilfe der Funktion Timer() ermittelt. Nach Ablauf der Sekunde werden beide Zellen geleert. Hat in beiden Zellen dasselbe Zeichen gestanden, passiert Folgendes: Die graue Einfärbung beider Zellen wird entfernt. Beide zugehörigen Elemente des Felds werden geleert. Die Anzahl der gefundenen Zeichenpaare wird um 1 erhöht. Hat die Anzahl der gefundenen Zeichenpaare den Wert 18 erreicht, wird das Spielende angezeigt. Die boolesche Variable Gestartet wird wieder zurückgesetzt, so dass der Benutzer das nächste Spiel starten kann. Hat in beiden Zellen nicht dasselbe Zeichen gestanden, werden beide Zellen wieder grau eingefärbt. Hat der Benutzer die erste Zelle angeklickt, wird das zugehörige Zeichen aus dem Feld angezeigt. Die Nummer der Zeile und die

Nummer der Spalte dieser ersten Zelle werden gespeichert, um sie später mit der Nummer der Zeile und der Nummer der Spalte der zweiten Zelle zu vergleichen. Viel Spaß beim Spielen, beim Erforschen des Codes und beim Codieren eigener Erweiterungen! Statt 18 Zeichenpaaren in Zellen ohne Hintergrundfarbe könnten z. B. sechs Zeichenpaare mit drei unterschiedlichen Hintergrundfarben genutzt werden. Der Benutzer müsste sich dann nicht nur merken, dass das Zeichen »C« auf einer bestimmten Position stand, sondern auch, ob es sich um das Zeichen »C« auf rotem, gelbem oder grünem Hintergrund handelte.

12.2    Snake Sie finden das Snake-Spiel in der Datei Snake.xlsm. Zunächst beschreibe ich den Ablauf des Spiels und anschließend den Aufbau des Programms.

12.2.1    Spielablauf Nach dem Öffnen der Datei erscheint ein leeres Spielfeld mit zehn mal zehn Zellen. Rechts daneben sieht die Benutzerin insgesamt drei Gruppen von grau eingefärbten Zellen, die wie Schaltflächen bedient werden. Außerdem wird ihm in einer gelb eingefärbten Zelle ein Zähler angezeigt, der zu Beginn auf 0 steht, siehe Abbildung 12.5.

Abbildung 12.5     Ansicht nach dem Öffnen der Datei

Nach der Betätigung der Schaltfläche Starten wird eine Zelle dunkelrot eingefärbt. Das ist die Beute, also die Zelle, die »gefressen« wird. Außerdem erscheint eine hellgrün eingefärbte

Zelle. Das ist die Schlange, die die Beute »frisst«, siehe Abbildung 12.6.

Abbildung 12.6     »Schlange« und »Beute«

Die Schlange »bewegt sich« selbständig, sie wechselt also ihre Position. Dies wird erreicht, indem nach kurzer Zeit die nächste Zelle grün eingefärbt wird, die in der Bewegungsrichtung der Schlange liegt. Die bisher grün eingefärbte Zelle wird dann ohne Hintergrundfarbe dargestellt. Die Benutzerin ändert die Bewegungsrichtung der Schlange, indem sie eine der vier Zellen anklickt, die auf der rechten Seite wie in einem Fadenkreuz angeordnet sind. Sie achtet darauf, dass die Schlange nicht auf den Rand des Spielfelds trifft. Dies würde das Spiel beenden. Es ist nicht möglich, die Bewegungsrichtung direkt umzukehren. Bewegt sich die Schlange z. B. nach oben, kann die Bewegungsrichtung daher in »rechts« oder »links«, aber nicht in »unten« geändert werden. Trifft die Schlange auf die Beute, wird der Zählerstand um 1 erhöht. Die Beute wird anschließend an einer neuen, zufälligen Position

angezeigt. Die Benutzerin muss die Schlange zu dieser neuen Position bewegen. Allerdings geschieht der Wechsel von Zelle zu Zelle in kürzerer Zeit. Die Schlange wird daher nach jedem Fressvorgang schneller. Das Betätigen der Schaltfläche Info zeigt die Spielbeschreibung an, siehe Abbildung 12.7.

Abbildung 12.7     Beschreibung des Spiels

12.2.2    Aufbau des Spielfelds Die Prozedur Workbook_Open() im Klassenmodul DieseArbeitsmappe dient dem Aufbau des Spielfelds nach dem Öffnen der Datei. Private Sub Workbook_Open()

ThisWorkbook.Worksheets("Tabelle1").Activate

Cells.Delete

Cells.RowHeight = 20

Cells.ColumnWidth = 3.5

' Rahmen für Spielfeld

Range("B2:K2").Borders(xlEdgeTop).Weight = xlThick

Range("B11:K11").Borders(xlEdgeBottom).Weight = xlThick

Range("B2:B11").Borders(xlEdgeLeft).Weight = xlThick

Range("K2:K11").Borders(xlEdgeRight).Weight = xlThick

' Startzelle

Range("M2").Value = "Starten"

With Range("M2:O2")

.Interior.Color = RGB(192, 192, 192)

.MergeCells = True

.HorizontalAlignment = xlCenter

.VerticalAlignment = xlCenter

End With

' Richtungszellen mit neutraler Zelle in der Mitte

Range("N4, M5, O5, N6").Interior.Color = RGB(192, 192, 192)

Range("N5").Activate



' Zählerstandszelle

Range("N8").Value = 0

With Range("N8")

.Interior.Color = vbYellow

.HorizontalAlignment = xlCenter

.VerticalAlignment = xlCenter

End With

' Infozelle

Range("M11").Value = "Info"

With Range("M11:O11")

.Interior.Color = RGB(192, 192, 192)

.MergeCells = True

.HorizontalAlignment = xlCenter

.VerticalAlignment = xlCenter

End With

End Sub

Listing 12.5     Sub »Workbook_Open()« in Snake.xlsm, Klassenmodul »DieseArbeitsmappe«

Nach der Aktivierung des Tabellenblatts Tabelle1 werden mithilfe der Methode Delete() und der beiden Eigenschaften RowHeight und ColumnWidth des Cells-Objekts alle Zellen gelöscht und in eine quadratische Form gebracht. Das Spielfeld (im Zellbereich B2:K11) wird mit einem Rahmen versehen. Dies ist der Spielfeldrand, mit dem die Schlange nicht kollidieren darf. Die drei Zellen für die Schaltfläche Starten (im Zellbereich I2:K2) werden mithilfe der Eigenschaft MergeCells miteinander zu einer Zelle verbunden, grau eingefärbt und mit einem horizontal und vertikal zentrierten Text gefüllt. Das Gleiche geschieht für die Schaltfläche Info (im Zellbereich I7:K7). Die vier Zellen, die der Benutzer zur Änderung der Bewegungsrichtung anklickt (N4, M5, O5 und N6), werden grau eingefärbt. Zelle N5 im Zentrum dieser vier Zellen wird aktiviert.

Die Zelle für den Zählerstand erhält den Anfangswert 0 und wird gelb eingefärbt. Der Inhalt wird horizontal und vertikal zentriert.

12.2.3    Spiel starten Im Modul Modul1 finden Sie zwei Variablen mit dateiweitem Gültigkeitsbereich und die Prozedur Starten(). Sie dienen der Initialisierung des Spiels und der Kontrolle des Spielzustands. Zunächst die Variablen: Public Richtung As Integer

Dim Gestartet As Boolean

Listing 12.6     Variablen in Snake.xlsm, Modul 1

In der Variablen Richtung wird die aktuelle Bewegungsrichtung der Schlange als Integer-Wert gespeichert. Sie wird mit dateiweitem Gültigkeitsbereich deklariert, da sie von mehreren Prozeduren in unterschiedlichen Modulen benötigt wird. Die boolesche Variable Gestartet verhindert das erneute Starten des Spiels, falls es bereits gestartet wurde. Sie wird im gesamten Modul benötigt. Es folgt die Prozedur Starten(): Sub Starten()

Dim Startzeit As Single

Dim Wartezeit As Single

Dim Z As Integer, S As Integer ' Snake

Dim ZB As Integer, SB As Integer ' Beute

Dim Ende As Boolean

' Nicht zweimal starten

If Gestartet Then Exit Sub

Gestartet = True

Range("B2:K11").Interior.Color = xlNone ' Spielfeld leer

Range("N8").Value = 0 ' Zählerstand

Wartezeit = 0.5 Ende = False

' Anfangswert für Wartezeit

' Ende noch nicht erreicht



' Startpunkt und Startrichtung für die grüne Schlange

Z = 10

S = 6

Cells(Z, S).Interior.Color = vbGreen

Richtung = 0

' Startpunkt für die rote Beute

ZB = 3

SB = 9

Cells(ZB, SB).Interior.Color = vbRed

' Zufallsgenerator initialisieren

Randomize

' Schleife bis Kollision

Do While Not Ende

' Timer starten

Startzeit = Timer

Do While Timer < Startzeit + Wartezeit

DoEvents

Loop

' Alte Zelle leeren

Cells(Z, S).Interior.Color = xlNone

' In aktueller Richtung bewegen

If Richtung = 0 Then

If Z >= 3 Then Z = Z - 1 Else Ende = True

ElseIf Richtung = 1 Then

If S = 1 And Kombination = Sh2.Left Then

AllesRichtig = False

Exit For

End If

Next k

If Not AllesRichtig Then Exit For

Next i

If Not AllesRichtig Then Exit Sub

For i = 1 To 4

For k = 1 To 5 Name1 = "P" & i & k

Name2 = "P" & (i + 1) & k

Set Sh1 = ActiveSheet.Shapes(Name1)

Set Sh2 = ActiveSheet.Shapes(Name2)

If Sh1.Top >= Sh2.Top Then

AllesRichtig = False

Exit For

End If

Next k

If Not AllesRichtig Then Exit For

Next i

If Not AllesRichtig Then Exit Sub

SpielAktiv = False

Application.OnTime Now + TimeValue("00:00:01"), "FrageNeuesSpiel"

Set Sh1 = Nothing

Set Sh2 = Nothing

End Sub

Listing 12.22     Sub »Pruefen()« in Puzzle.xlsm, Modul 1

Zunächst wird davon ausgegangen, dass alle Puzzle-Teile richtig angeordnet sind (AllesRichtig steht auf True). In der ersten doppelten For-Schleife wird jeweils der Abstand von zwei Puzzle-Teilen vom linken Rand untersucht. Mithilfe des Werts der Eigenschaft Left wird geprüft, ob sich P11 links von P12 befindet, P12 links von P13 und so weiter. Sobald die Prüfung einen Fehler ergibt, wird die Prozedur vorzeitig verlassen. In der zweiten doppelten For-Schleife wird jeweils der Abstand von zwei Puzzle-Teilen vom oberen Rand untersucht. Mithilfe des Werts der Eigenschaft Top wird geprüft, ob sich P11 oberhalb von P21 befindet, P21 oberhalb von P31 und so weiter. Sobald die Prüfung einen Fehler ergibt, wird auch hier die Prozedur vorzeitig verlassen. Wurde die Prozedur nicht vorzeitig verlassen, wird das Spiel beendet (SpielAktiv auf True). Eine Sekunde später wird die Prozedur FrageNeuesSpiel() aufgerufen, siehe folgenden Abschnitt. Die kleine Zeitverzögerung ist notwendig, damit Tauschvorgang und Prüfung zuvor sicher beendet wurden.

12.4.9    Zum nächsten Spiel Nach dem erfolgreichen Lösen des Puzzle-Spiels wird der Benutzerin die Frage gestellt, ob sie ein neues Spiel beginnen möchte. Bejaht sie diese Frage, wird die Prozedur Starten() aufgerufen, ansonsten die Prozedur Loeschen():

Sub FrageNeuesSpiel()

If MsgBox("Geschafft! Neues Spiel?", vbYesNo, "Neues Spiel?") = vbYes Then

Starten

Else

Loeschen

End If

End Sub

Listing 12.23     Sub »FrageNeuesSpiel()« in Puzzle.xlsm, Modul 1

Viel Spaß beim Spielen, beim Erforschen des Codes und beim Codieren eigener Erweiterungen! Sie könnten z. B. verschiedene Bilder zur Verfügung stellen, von denen eines per Zufallsgenerator ausgewählt wird. Auch die Anzahl der Puzzle-Teile könnten Sie verändern, um den Schwierigkeitsgrad zu beeinflussen.

A    Lösungen der Übungsaufgaben Die Lösungen zu den nachfolgenden Übungsaufgaben finden Sie in den hier angegebenen Arbeitsmappen bzw. Modulen in den Materialien zum Buch, die Sie über www.rheinwerk-verlag.de/5546 erreichen: Lösung zu Übung »Makro aufzeichnen« Sub KopieE3E5()

Range("E3").Select

Selection.Copy

Range("E5").Select

ActiveSheet.Paste

End Sub

Listing A.1     Sub »KopieE3E5()« in Mappe1.xlsm, Modul 1

Lösung zu Übung »Makro ändern« Sub KopieE3E5Neu()

Range("E3:G3").Select

Selection.Copy

Range("E5").Select

ActiveSheet.Paste

Range("E10").Select

ActiveSheet.Paste

End Sub

Listing A.2     Sub »KopieE3E5Neu()« in Mappe1.xlsm, Modul 1

Lösung zu Übung »Relative Verweise«

Sub RelKopie()

Selection.Copy

ActiveCell.Offset(2, 0).Range("A1:C1").Select

ActiveSheet.Paste

ActiveCell.Offset(5, 0).Range("A1:C1").Select

ActiveSheet.Paste

End Sub

Listing A.3     Sub »RelKopie()« in Mappe1.xlsm, Modul 1

Lösung zu Übung »Code auskommentieren« Sub KopieE3E5Neu()

Range("E3:G3").Select

Selection.Copy

' Range("E5").Select

' ActiveSheet.Paste

Range("E10").Select

ActiveSheet.Paste

MsgBox "Fertig"

End Sub

Listing A.4     Sub »KopieE3E5Neu()« in Mappe3.xlsm, Modul 2

Lösung zu Übung »Variablen und Datentypen« Sub UebungVariablen()

Dim Nachname As String

Dim Vorname As String

Dim Adresse As String

Dim Geburtsdatum As Date

Dim Alter As Integer

Nachname = "Mustermann"

Vorname = "Max"

Adresse = "Holzweg 7, 53776 Rheinhausen"

Geburtsdatum = "20.07.1978"

Alter = 44

MsgBox Vorname & " " & Nachname & vbCrLf & Adresse & vbCrLf _

& "geb.: " & Geburtsdatum & vbCrLf & "Alter: " & Alter

End Sub

Listing A.5     Sub »UebungVariablen()« in Mappe3.xlsm, Modul 2

Lösung zu Übung »Vergleichsoperatoren« Sub UebungVergleich()

Dim Ergebnis As Boolean

Ergebnis = (12 - 3 >= 4 * 2.5)

MsgBox Ergebnis

Ergebnis = ("Maier" Like "M??er")

MsgBox Ergebnis

End Sub

Listing A.6     Sub »UebungVergleich()« in Mappe3.xlsm, Modul 2

Lösung zu Übung »Logische Operatoren« Sub UebungLogisch()

Dim Ergebnis As Boolean

Ergebnis = (4 > 3 And -4 > -3)

MsgBox Ergebnis

Ergebnis = (4 > 3 Or -4 > -3)

MsgBox Ergebnis

End Sub

Listing A.7     Sub »UebungLogisch()« in Mappe3.xlsm, Modul 2

Lösung zu Übung »Rangfolge der Operatoren« Nr. Werte

Bedingung

Lösung

1

a=5 b=10

a>0 And b10

falsch

2

a=5 b=10

a>0 Or b10

wahr

3

z=10 w=100

z0 Or z>w Or w-z=90

wahr

4

z=10 w=100

z=11 And z>w Or w-z=90

wahr

5

x=1.0 y=5.7 x>=.9 And y=.9 And Not(y0 And n2>0 Or n1>n2 And n217

Nr. Werte

Bedingung

Lösung

8

n1>0 And (n2>0 Or n1>n2) And n217

falsch

n1=1 n2=17

Tabelle A.1     Lösung zu Übung »Rangfolge der Operatoren«

Lösung zu Übung »Verzweigung mit If« Sub UebungIf()

Dim Gehalt As Single

Dim Steuerbetrag As Single

ThisWorkbook.Worksheets("Tabelle1").Activate

Range("A10:A11").NumberFormatLocal = "#.##0,00 €"

Gehalt = Range("A10").Value

If Gehalt