jetzt lerne ich VBA mit Excel Unser Online-Tipp für noch mehr Wissen … ... aktuelles Fachwissen rund um die Uhr – zum Probelesen, Downloaden oder auch auf Papier. www.InformIT.de jetzt lerne ich VBA mit Excel Der einfache Einstieg in das Programmieren von Tabellen und Diagrammen BERND HELD Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.ddb.de> abrufbar. Die Informationen in diesem Produkt werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Software-Bezeichnungen, die in diesem Buch erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. 10 9 8 7 6 5 4 3 2 1 07 06 05 ISBN 3-8272-6938-5 © 2005 by Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Lektorat: Brigitte Alexandra Bauer-Schiewek, [email protected] Herstellung: Claudia Bäurle, [email protected] Korrektorat: Petra Kienle, Fürstenfeldbruck Coverkonzept: independent Medien-Design Coverlayout: adesso 21, Thomas Arlt Titelillustration: Karin Drexler Satz: text&form GbR, Fürstenfeldbruck Druck und Verarbeitung: Bosch-Druck, Ergolding Printed in Germany jetzt lerne ich Übersicht Liebe Leserin, lieber Leser! 1 Erste Schritte mit Excel-VBA 2 Die Sprachelemente von Excel-VBA 3 Zellen und Bereiche programmieren 4 Zeilen und Spalten programmieren 5 Tabellen und Diagramme programmieren 6 Die Programmierung von Arbeitsmappen 7 Eigene Funktionen schreiben 8 Ereignisse einsetzen 9 Dialoge und Steuerelemente programmieren Stichwortverzeichnis 13 15 61 93 127 159 189 211 241 273 303 5 jetzt lerne ich Inhaltsverzeichnis Liebe Leserin, lieber Leser! 13 1 1.1 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 15 Erste Schritte mit Excel-VBA Das Objektmodell von Excel Die Entwicklungsumgebung von Excel-VBA Das Code-Fenster Das Eigenschaftenfenster Das Direktfenster Das Überwachungsfenster Die Symbolleiste Bearbeiten Die Symbolleiste Debuggen Automatische Syntaxprüfung Den Code Schritt für Schritt durchlaufen Tastenkombinationen einsetzen Weitere Einstellungen Editor-Einstellungen Editorformat festlegen Allgemeine Einstellungen vornehmen Fenster verankern Der Makrorekorder Ein- und Ausschalten der Gitternetzlinien Die ersten Makros Ein mehrzeiliges Infofenster ausgeben Meldung mit Rückfrage erstellen Einen Eingabedialog aufrufen 16 18 19 20 21 21 25 29 30 31 31 33 33 34 35 37 37 38 40 40 41 43 7 Inhaltsverzeichnis jetzt lerne ich 8 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7 1.8 1.8.1 1.8.2 1.8.3 1.8.4 Variablen definieren und einsetzen Syntaxfestlegungen für Variablen Die Namenskonvention von Gregory Reddick Variablen deklarieren Statische Variablen Private Variablen Öffentliche Variablen Variablendeklarationen erzwingen Die wichtigsten Variablentypen Noch kürzere Deklaration von Variablen Die Verwendung von Konstanten Die wichtigsten Systemkonstanten Datums-Format-Konstanten Dir-Konstanten File Input-/Output-Konstanten Die Shell-Konstanten 44 45 45 46 46 47 47 48 48 50 50 51 51 55 57 59 2 2.1 2.1.1 2.2 2.2.1 2.2.2 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 2.4.4 Die Sprachelemente von Excel-VBA Die With-Anweisung Die aktive Zelle bearbeiten Die IF-Anweisung Datentyp einer Zelle prüfen Formelcheck durchführen Die Select Case-Anweisung Excel-Version feststellen Zahlenwerte prüfen Schleifen programmieren Die For...Next-Schleifen For Each...Next-Schleifen Die Schleife Do Until...Loop Die Schleife Do While...Loop 61 3 3.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.2 3.2.1 3.2.2 Zellen und Bereiche programmieren Zellen und Bereiche markieren Die übersichtlichere Mehrfachauswahl Die letzte benutzte Zelle einer Tabelle ansteuern Die letzte Zelle einer Spalte markieren Die letzte Zelle einer Zeile markieren Alle Formelzellen markieren Die umliegenden Zellen markieren Zellen und Bereiche formatieren Alle verbundenen Zellen kennzeichnen Die Schrift anpassen 93 61 62 64 65 66 67 68 69 70 71 79 87 89 93 94 95 97 98 98 100 101 101 102 Inhaltsverzeichnis jetzt lerne ich 3.2.3 3.2.4 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.4 3.4.1 3.4.2 3.4.3 3.4.4 3.5 3.5.1 3.5.2 Extremwerte kennzeichnen Bereiche einrahmen Zelleninhalte manipulieren Daten nach Datentransfer bereinigen Excel vorschreiben richtig zu rechnen Bestimmte Zeichen aus Zellen entfernen Namen drehen Kommentare aus Zellentexten generieren Formeln durch Festwerte ersetzen Bestimmte Zelleninhalte löschen Bezüge umsetzen Bereiche auswerten Einen Bereich summieren Einen Bereich bedingt summieren Numerische Werte zählen Eine bedingte Zählung durchführen Zellen suchen Suche in einem bestimmten Bereich durchführen Nach einem Datum suchen 104 106 107 107 108 109 113 114 115 116 117 118 118 120 121 122 123 123 124 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.15.1 4.15.2 4.15.3 4.15.4 4.16 Zeilen und Spalten programmieren Anzahl der verwendeten Zeilen ermitteln Anzahl der verwendeten Spalten ermitteln Zeilenhöhe und Spaltenbreite justieren Spaltenbreiten automatisch anpassen Zeilen bedingt ein- und ausblenden Spalten bedingt ein- und ausblenden »Leere Zeilen« bedingt löschen Wirklich nur komplett leere Zeilen löschen Doppelte Zeilen löschen Zeilen einfügen Zeilen einfügen und Summen bilden Spalten und Zeilen formatieren Zeilen sortieren Eine Unikatsliste erstellen Den AutoFilter bedienen AutoFilter einblenden Eine bestimmte Region filtern Den AutoFilter entfernen Die Top-Werte anzeigen Zeilen und Spalten gliedern 127 127 128 129 130 131 133 135 137 139 141 143 146 148 150 151 151 152 154 155 156 9 Inhaltsverzeichnis jetzt lerne ich 10 5 5.1 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.10 5.2 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 Tabellen und Diagramme programmieren Tabellen programmieren Tabellen ansprechen Tabellen einfügen Tabellen kopieren oder verschieben Tabellen löschen Tabellen drucken Tabellen gruppieren Tabellen listen und verlinken Tabellen schützen Tabellen ein- und ausblenden Tabellen sortieren Diagramme programmieren Ein Diagrammblatt einfügen Ein Diagrammobjekt einfügen Das Standarddiagramm setzen Diagramme exportieren Diagramm entfernen 159 6 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.2 6.2.1 6.2.2 6.3 6.4 6.4.1 6.4.2 6.4.3 6.5 6.6 6.7 6.8 6.8.1 6.8.2 Die Programmierung von Arbeitsmappen Arbeitsmappen öffnen Eine Mappe ohne Aktualisierung von Bezügen öffnen Arbeitsmappe(n) über einen Dialog öffnen Alle verknüpften Mappen öffnen Ist eine bestimmte Mappe bereits geöffnet? Arbeitsmappen speichern Mappe unter aktuellem Tagesdatum speichern Arbeitsmappe bedingt speichern Existiert die Mappe überhaupt? Arbeitsmappen schließen Arbeitsmappe schließen – Änderungen speichern Arbeitsmappe schließen – Änderungen verwerfen Mehrere Arbeitsmappen schießen Excel-Mappen listen und linken Arbeitsmappen zusammenführen Arbeitsmappen entfernen Mit Dokumenteigenschaften arbeiten Dokumenteigenschaften auslesen Dokumenteigenschaften setzen 189 7 7.1 7.1.1 Eigene Funktionen schreiben Eigene Tabellenfunktionen stricken Zellen mit roter, dicker Schriftfarbe summieren 211 159 160 162 166 167 168 169 171 172 176 177 179 179 181 184 184 186 189 191 192 195 195 196 197 198 199 200 200 200 201 202 204 206 206 207 208 212 212 Inhaltsverzeichnis 7.1.2 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.1.10 7.1.11 7.2 7.2.1 7.2.2 7.2.3 7.2.4 7.2.5 7.2.6 7.3 7.3.1 jetzt lerne ich 215 216 217 218 219 222 223 224 225 227 228 228 229 230 232 233 236 236 7.3.2 Formatierte Zellen zählen Die dynamische Farbwahl per Parameterübergabe Aktuelle Arbeitsmappe ermitteln Zelleninformationen abfragen Dokumenteigenschaften per Funktion abfragen Buchstaben aus Zeichenfolgen entfernen Zahlen aus Zeichenfolgen entfernen Das erste Auftreten einer Zahl ermitteln Zahlen als Text ausgeben Initialen bilden Modulare Funktionen programmieren Arbeitsmappen-Existenz prüfen Arbeitsmappen-Zustand prüfen Tabellen-Existenz prüfen Tabellenschutz ermitteln Eine umfangreiche Löschfunktion generieren Dateien in einem Verzeichnis zählen Funktionen dauerhaft verfügbar machen Speichern der Funktionen in der persönlichen Makroarbeitsmappe Speichern der Funktionen in einem Add-In 8 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.1.5 8.1.6 8.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.4 8.4.1 8.4.2 Ereignisse einsetzen Ereignisse auf Arbeitsmappenebene Das Ereignis Workbook_Open Das Ereignis Workbook_BeforeClose Das Ereignis Workbook_BeforeSave Das Ereignis Workbook_BeforePrint Das Ereignis Workbook_NewSheet Weitere Arbeitsmappenereignisse im Überblick Ereignisse auf Tabellenblattebene Das Ereignis Worksheet_Activate Das Ereignis Worksheet_Change Das Ereignis Worksheet_SelectionChange Das Ereignis Worksheet_BeforeRightClick Das Ereignis Worksheet_BeforeDoubleClick Weitere Tabellenereignisse im Überblick Excel über Tastenkombinationen bedienen Formeln und Verknüpfungen in Festwerte wandeln Excel zeitmäßig steuern Countdown in Excel Verarbeitung zu einer bestimmten Zeit beginnen 241 237 238 242 242 245 247 248 249 250 251 251 254 258 261 263 265 266 267 270 271 272 11 Inhaltsverzeichnis jetzt lerne ich 9 9.1 9.1.1 9.2 9.2.1 9.2.2 9.3 9.3.1 9.3.2 9.3.3 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.4.6 9.4.7 9.4.8 9.4.9 9.4.10 9.4.11 9.4.12 9.4.13 9.4.14 9.4.15 9.4.16 9.4.17 Dialoge und Steuerelemente programmieren Der Meldungen-Dialog MsgBox Löschrückfrage einholen Die Eingabemaske InputBox Die Mehrwertsteuer errechnen Bereich über eine InputBox markieren Integrierte Dialoge einsetzen Den Öffnen-Dialog aufrufen Den Dialog Drucken aufrufen Weitere integrierte Dialoge in Excel UserForms erstellen und automatisieren Die Anforderungen Die Datenmaske zeichnen und die ersten Eigenschaften einstellen Grafiken einstellen Default-Schaltfläche definieren und umbenennen Hintergrundfarbe und Schrift festlegen Accelerator definieren Spezialeffekte einstellen Steuerelemente anordnen Aktivierungsreihenfolge festlegen Aufgaben beim Start der UserForm ausführen Die Suche von Datensätzen Suchtreffer im Listenfeld anzeigen Die Neuanlage von Datensätzen Die Änderung von Datensätzen Die Löschung von Datensätzen UserForm starten UserForm schließen Stichwortverzeichnis 12 273 273 275 277 278 279 280 280 281 282 283 284 285 288 289 289 290 290 290 291 291 294 296 297 299 300 301 302 303 jetzt lerne ich Liebe Leserin, lieber Leser! Das Programm Excel ist technisch sehr ausgereift und Sie werden auf den ersten Blick kaum etwas vermissen, was für Ihre tägliche Arbeit benötigt wird. Mithilfe von VBA-Makros lassen sich aber gerade tägliche Routinearbeiten weitestgehend automatisieren. Sie haben zwar einmalig den Aufwand mit der Erstellung der dazu benötigten Makros. Später profitieren Sie jedoch mit jedem wiederholten Aufruf und haben dadurch mehr Zeit für andere Dinge zur Verfügung. Außerdem werden Sie zunehmend auf andere programmierte ExcelLösungen stoßen. Nur mit eigenen VBA-Kenntnissen, verstehen Sie diese Lösungen wirklich und können diese selbst auf eigene Bedürfnisse hin abändern, ohne auf externe Dienstleister zurückgreifen zu müssen. Dieses Buch ist in 9 Kapitel gegliedert, in denen die wichtigsten Objekte von Excel-VBA vorgestellt werden. Der Schwerpunkt lag darauf, übersichtlich die wichtigsten und für die Praxis interessantesten Lösungen in diesem Buch vorzustellen. Zu jedem Kapitel können Sie auf der mitgelieferten CD-ROM die entsprechende(n) Beispieldatei(en) öffnen, den Quellcode ansehen und testen. Sie brauchen daher nicht die einzelnen Listings abzutippen (wenngleich ich Ihnen das unbedingt empfehle, weil dann der Lerneffekt höher ist). Am Ende des Buches werden Sie in der Lage sein, effektiv mit VBAMakros umzugehen und eigene Lösungen zu entwickeln. 13 jetzt lerne ich Liebe Leserin, lieber Leser! Bei Nachfragen und allgemeinem Feedback zu meinem Buch erreichen Sie mich über meine Homepage http://held-Office.de oder über [email protected]. So erreichen Sie gleichzeitig auch den Verlag. Auf der Homepage von Markt + Technik finden Sie ein eigenes VBAForum, in dem Fragen zu VBA gestellt werden können. Gemeinsam mit meiner sehr geschätzten Kollegin Monika Weber, moderiere ich dieses Forum. Auch Sie sind natürlich herzlich eingeladen in diesem VBA-Forum mitzumachen. Möchten Sie in Ergänzung einen vertiefenden VBA-Kurs besuchen, so finden Sie auf meiner Homepage regelmäßig Schulungsangebote. Diese Angebote reichen von Einzelschulungen in eigenen Schulungsräumen bei Vaihingen-Enz/Roßwag, bis hin zu Gruppenschulungen auch in Hotel- oder Firmenräumen. Gerne komme ich auch direkt zu Ihnen in Ihre Firma, um Excel bzw. VBA zu schulen oder entwickle individuelle Lösungen zu komplexen Problemen in Excel. Nun aber viel Spaß beim Lesen und bei der Programmierung Ihrer Excel-Arbeitsmappen! – Bernd Held – MVP für Microsoft Excel 14 jetzt lerne ich KAPITEL 1 Erste Schritte mit Excel-VBA In Excel ist neben der allgemein bekannten Tabellenkalkulation eine Programmiersprache integriert, die sich VBA (Visual Basic for Application) nennt. Diese Sprache ist auch in allen anderen OfficeAnwendungen integriert. Somit besteht dadurch die Möglichkeit, Daten nicht nur in Excel komfortabel zu bearbeiten, sondern auch an die anderen Anwendungen wie Access, Word oder Outlook weiterzugeben. Dieses Buch beschäftigt sich damit, Ihnen die Möglichkeiten der Programmierung von Zellen, Zeilen und Spalten, Tabellen, Diagrammen und Arbeitsmappen näher zu bringen. Die Programmiersprache VBA hat vor allem dann einen hohen Nutzen, wenn tägliche Abläufe wie zum Beispiel Statistiken automatisiert werden sollen, und wenn Sie Excel um weitere eigene Funktionen anreichern möchten. Auch im Hinblick auf Arbeitssicherheit und Arbeitserleichterung besteht somit die Möglichkeit, gerade lästige Routinearbeiten mit VBA sicher und elegant auszuführen. Zusätzlich ergibt sich über den Einsatz der Programmiersprache eine erhöhte Arbeitsgeschwindigkeit. Sofern der Wunsch besteht eigene Anwendungen auf Basis von Excel zu entwickeln, führt die Realisierung mit VBA schnell zum Ziel. Sie finden alle Beispiele aus diesem Kapitel auf der diesem Buch beiliegenden CD-ROM im Verzeichnis Kap01 in der Datei Start.xls. 1 15 1 Erste Schritte mit Excel-VBA jetzt lerne ich 1.1 Das Objektmodell von Excel Um einen ersten Eindruck von den Objekten zu bekommen, die Ihnen in Excel-VBA zur Verfügung stehen, können Sie den Objektkatalog direkt in der Entwicklungsumgebung verwenden. Um den Objektkatalog von Excel aufzurufen, gehen Sie wie folgt vor: 1. Starten Sie Excel, legen eine neue Datenbank an oder laden eine bereits vorhandene und drücken danach die Tastenkombination Ç+Ó, um zur Entwicklungsumgebung zu gelangen. 2. In der Entwicklungsumgebung wählen Sie aus dem Menü ANSICHT den Befehl OBJEKTKATALOG. Alternativ dazu können Sie auch die Taste Ê drücken, um den Objektkatalog aufzurufen. 3. Wählen Sie im Dropdown-Feld PROJEKT/BIBLIOTHEK den Eintrag EXCEL aus. 4. Im Listenfeld KLASSEN aktivieren Sie beispielsweise den Eintrag APPLICATION. Bild 1.1: Der ObjektExplorer gibt Auskunft über die Objekte von Excel 16 Das Objektmodell von Excel jetzt lerne ich Im Objektkatalog werden nach Auswahl des Objekts (Klassen) in dem Listenfeld ELEMENTE die hier zur Verfügung stehenden Eigenschaften und Methoden des Objekts dargestellt. Markieren Sie die Methode bzw. Eigenschaft, zu der Sie mehr erfahren möchten, und klicken Sie auf das Fragezeichen-Symbol in der Symbolleiste. Daraufhin wird die Online-Hilfe aufgerufen. Dort befinden sich weiterführende Informationen und Beispielcodes, die Sie in ein eigenes Modul kopieren und weiterverwenden können. In Abbildung 1.1 ist beispielsweise das Objekt APPLICATION ausgewählt. Dabei handelt es sich um das hierarchisch am weitesten oben stehende Objekt. Dieses Objekt steht für die eigentliche Excel-Anwendung, zu der es diverse Methoden und Eigenschaften gibt. Zunächst einmal sollte geklärt werden, was man unter Objekten, Eigenschaften, Methoden und Ereignissen versteht. 쐽 Objekte Als Objekt bezeichnet man alle Teile, die sich in Excel einsehen lassen. Die wichtigsten Objekte sind Zellen, Zeilen, Spalten, Tabellen, Diagramme und Arbeitsmappen. 쐽 Eigenschaften Dahinter verbergen sich die Merkmale eines Objekts. So ist z. B. die Formatierung einer Zelle eine Eigenschaft des Objekts »Zelle«. 쐽 Methoden Wenn von Methoden die Rede ist, sollten Sie hinterfragen, was sich mit den einzelnen Objekten anstellen lässt. Angewandt auf eine Arbeitsmappe wären das zum Beispiel die Methoden zum Öffnen, Speichern und Schließen. 쐽 Ereignisse Ereignisse beschreibt man am besten als automatisierte Abläufe. Ein Beispiel hierfür wäre das Klicken auf eine Schaltfläche oder das Öffnen eines Dialogs. In beiden Fällen liegt ein Ereignis vor, auf dessen Basis nun bestimmt werden kann, welche weiteren Aktionen dabei stattfinden sollen. Alle in VBA zur Verfügung stehenden Objekte werden in Bibliotheken verwaltet. Standardmäßig ist im ersten Dropdown-Feld der Eintrag <ALLE BIBLIOTHEKEN> ausgewählt. Sofern die Anzeige etwas eingeschränkt werden soll, um die Inhalte einzelner Bibliotheken 17 1 Erste Schritte mit Excel-VBA jetzt lerne ich einzusehen, wählen Sie die gewünschte Bibliothek im DropdownFeld aus. So lassen sich z. B. in der Bibliothek VBA-Befehle ansehen, die nicht nur auf Excel beschränkt sind, sondern grundsätzlich im gesamten Office-Paket eingesetzt werden können. So finden Sie in dieser Bibliothek die Anweisungen ChDir und ChDrive zum Wechseln eines Verzeichnisses bzw. Laufwerks oder allgemeine Funktionen wie Date und Time, um den aktuellen Tag sowie die Uhrzeit aus dem System auszulesen. Klar, es würde keinen Sinn machen, diese Anweisungen ausschließlich nur in der Excel-Bibliothek zu speichern, da sie allgemein in allen Office-Anwendungen von Nutzen sind. 1.2 Die Entwicklungsumgebung von Excel-VBA Wie bereits erwähnt, können Sie über die Tastenkombination Ç+Ó in die Entwicklungsumgebung von Excel gelangen. Dort finden Sie folgendes Fenster vor: Bild 1.2: Die Entwicklungsumgebung von Excel-VBA 18 Die Entwicklungsumgebung von Excel-VBA 1.2.1 jetzt lerne ich Das Code-Fenster Zunächst besteht noch nicht die Möglichkeit, hier direkt Code (Programmierzeilen) einzufügen. Es muss vorher erst ein neues, noch leeres Modul angelegt werden. Dazu haben Sie zwei Möglichkeiten: 쐽 Klicken Sie im Projekt-Manager mit der rechten Maustaste auf die dort angezeigte Datenbank und wählen aus dem Kontextmenü den Befehl EINFÜGEN/MODUL. 쐽 Eine alternative Vorgehensweise, ohne vorher über die Tastenkombination Ç+Ó die Entwicklungsumgebung aufzurufen, ist, wenn Sie im Datenbankfenster in der linken Steuerungsleiste das Symbol MODULE anklicken und danach auf die Schaltfläche NEU klicken. Bei beiden Varianten wird ein neues Modul eingefügt, das auch gleich im Projekt-Explorer angezeigt wird. Sollten einzelne Fenster bei Ihnen nicht gleich angezeigt werden, dann können Sie diese über das Menü ANSICHT jederzeit einblenden. Bild 1.3: Ein neues, leeres Modul wird angezeigt 19 1 Erste Schritte mit Excel-VBA jetzt lerne ich Auf den ersten Blick erkennen Sie, dass sich oberhalb des Code-Bereichs zwei Dropdown-Felder befinden: 쐽 Im ersten Dropdown-Feld (ALLGEMEIN) werden alle Objekte aufgelistet, die sich in der Entwicklungsumgebung befinden. Das können beispielsweise Tabellen, Formulare und Berichte sein. 쐽 Im zweiten Dropdown-Feld (DEKLARATIONEN) sehen Sie alle Makros und Ereignisse, die für gewählte Objekte im ersten DropdownFeld angewendet werden können. 1.2.2 Das Eigenschaftenfenster Standardmäßig ist ein weiteres Fenster, das Eigenschaftenfenster, in der Entwicklungsumgebung von Excel nicht eingeblendet. Dieses Fenster lässt sich einblenden, indem Sie aus dem Menü ANSICHT den Befehl EIGENSCHAFTENFENSTER wählen oder alternativ die Taste Ì drücken. Das Eigenschaftenfenster lässt sich dazu benutzen, beispielsweise in einem Formular bestimmte Eigenschaften festzulegen, ohne dies im Einzelnen Zeile für Zeile programmieren zu müssen. Wenn Sie beispielsweise eine Tabelle im Projekt-Explorer markieren, dann werden die Eigenschaften in dem entsprechenden Fenster wie folgt dargestellt. Bild 1.4: Über das Eigenschaftenfenster Einstellungen für Tabellen definieren 20 Die Entwicklungsumgebung von Excel-VBA jetzt lerne ich Wenn Sie beispielsweise im EIGENSCHAFTENFENSTER auf die Registerkarte NACH KATEGORIEN wechseln, dann besteht die Möglichkeit, unter der Kategorie FORMAT bestimmte Einstellungen bezüglich der Größe, der Beschriftung sowie der Formatierung des Formulars einzustellen. 1.2.3 Das Direktfenster Das Direktfenster dient dazu, ein Makro zu testen. Dabei lassen sich beispielsweise bestimmte Inhalte von Variablen, die Sie im nächsten Kapitel kennen lernen werden, im Direktfenster ausgeben. So gehen Sie sicher, dass verwendete Variablen auch gefüllt bzw. weiterverwendet werden können. Das Direktfenster blenden Sie ein, indem Sie in der Entwicklungsumgebung die Tastenkombination Ÿ+G drücken. Einzelne Befehle lassen sich übrigens auch unmittelbar im Direktfenster testen. Geben Sie hierzu einmal die Zeile MsgBox Date ins Direktfenster ein und bestätigen Sie mit der Taste Æ. Als Ergebnis wird das aktuelle Datum am Bildschirm angezeigt. Soll das Ergebnis direkt im Direktfenster ausgegeben werden, dann schreiben Sie folgende Anweisung direkt ins Direktfenster und bestätigen mit Æ. Debug.Print Date Über diesen Befehl lässt sich auch mitten in einem Makro eine Variable bzw. ein Zwischenergebnis oder gar ein Text im Direktfenster der Entwicklungsumgebung anzeigen. Dieses Fenster sollte von Zeit zu Zeit selbst manuell gelöscht werden. 1.2.4 Das Überwachungsfenster Eine besonders wertvolle Funktion lässt sich nach Einblendung des Überwachungsfensters nutzen. Wählen Sie dazu aus dem Menü ANSICHT den Befehl ÜBERWACHUNGSFENSTER. Nun besteht die Möglichkeit, zu überprüfen, wann sich eine bestimmte Variable ändert. Genau dann soll der Makroablauf unterbrochen werden. Im folgenden Beispiel wird eine Schleife genau zehnmal durchlaufen. Bei jedem Schleifendurchlauf wird die Variable intz verändert. Die Aufgabe besteht nun darin, das Makro nach der ersten Änderung 21 jetzt lerne ich 1 Erste Schritte mit Excel-VBA der Variablen intz zu stoppen. Demnach müsste das folgende Makro nach dem ersten Schleifendurchlauf gestoppt werden. Sehen Sie sich zu diesem Zweck einmal die Prozedur in Listing 1.1 an. Mehr zum Thema »Schleifen & Co.« erfahren Sie in Kapitel 2 dieses Buches. Listing 1.1: Sub SchleifenMakro() Die Schleife Dim intz As Integer wird genau zehnmal For intz = 1 To 10 durchlaufen Debug.Print "Schleifendurchlauf: " & intz Next intz End Sub Um nun die Überwachung der Variablen intz einzustellen, befolgen Sie die nächsten Schritte: 1. Blenden Sie das Überwachungsfenster ein, indem Sie aus dem Menü ANSICHT den Befehl ÜBERWACHUNGSFENSTER auswählen. 2. Klicken Sie in diesem Fenster mit der rechten Maustaste und wählen den Befehl ÜBERWACHUNG HINZUFÜGEN aus dem Kontextmenü. Bild 1.5: Eine Überwachung hinzufügen 3. Geben Sie im Feld AUSDRUCK den Namen der Variablen an, die überwacht werden soll. 4. Die Namen der Prozedur sowie des Moduls werden automatisch eingestellt, sofern Sie vor dem Aufruf den Mauszeiger innerhalb des Makros positioniert haben. 22 Die Entwicklungsumgebung von Excel-VBA jetzt lerne ich 5. Aktivieren Sie die Option UNTERBRECHEN, WENN WERT GEÄNDERT WURDE. 6. Bestätigen Sie Ihre Einstellung mit OK. 7. Setzen Sie den Mauszeiger innerhalb der Prozedur und drücken Sie die Taste Í, um die Prozedur zu starten. Bild 1.6: Das Makro stoppt bereits beim ersten Schleifendurchlauf Da die Variable intz zu Beginn der Schleife auf den Wert 1 gesetzt wird, findet hier gleich die erste Änderung der Variable statt. Genau an diesem Punkt stoppt die Verarbeitung des Makros. Über den gelben Balken im Code-Fenster lässt sich die »Stopp-Stelle« direkt erkennen. Wenn Sie beispielsweise den Mauszeiger über die Variable intz im Code-Fenster bewegen, dann wird der momentane Inhalt dieser Variablen in einem kleinen Popup-Fenster angezeigt. Im Überwachungsfenster lässt sich der aktuelle Inhalt der Variablen ebenso anzeigen. Um die Prozedur weiterlaufen zu lassen, drücken Sie abermals die Taste Í. Das Makro stoppt nun bei jedem weiteren Schleifendurchlauf und zeigt den Inhalt der geänderten Variablen im Überwachungsfenster an. 23 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Das Überwachungsfenster wird selbstverständlich nur zum Testen von Makros eingesetzt. Wurde eine Prozedur ausgiebig getestet, wird der Überwachungsausdruck entfernt, indem Sie mit der rechten Maustaste im Überwachungsfenster klicken und aus dem Kontextmenü den Befehl ÜBERWACHUNG ENTFERNEN auswählen. Das gerade vorgestellte Beispiel stoppt bei der ersten Änderung der Variablen intz. Im folgenden Beispiel soll der erste Stopp-Punkt gesetzt werden, wenn die Variable intz den Wert 5 annimmt. Um diese Einstellung vorzunehmen, verfahren Sie wie folgt: 1. Klicken Sie im Überwachungsfenster mit der rechten Maustaste und wählen den Befehl ÜBERWACHUNGSAUSDRUCK HINZUFÜGEN. Bild 1.7: Makro stoppen bei Bedingung 2. Geben Sie im Feld AUSDRUCK die Formel INTZ = 5 ein. 3. Aktivieren Sie die Option UNTERBRECHEN, WENN DER WERT TRUE IST. 4. Bestätigen Sie mit OK. 5. Starten Sie das Makro mit Í und prüfen nach dem Stoppen des Makros den Inhalt des Überwachungsfensters. 24 Die Entwicklungsumgebung von Excel-VBA jetzt lerne ich Bild 1.8: Das Makro stoppt genau nach fünf Schleifendurchläufen 1.2.5 Die Symbolleiste Bearbeiten Diese Symbolleiste ist in der Entwicklungsumgebung standardmäßig nicht eingeblendet. Dies lässt sich ändern, indem Sie im Menü ANSICHT den Befehl SYMBOLLEISTEN/BEARBEITEN aufrufen. Bild 1.9: Die Symbolleiste Bearbeiten Auf die wichtigsten Funktionen dieser Symbolleiste soll im Folgenden kurz eingegangen werden: Einzug vergrößern bzw. verkleinern Mit der Funktion EINZUG VERGRÖSSERN lassen sich einzelne Zeilen oder auch mehrere Zeilen blockweise nach links einrücken. Dies macht den Programmcode leichter lesbar. Analog zur vorherigen Funktion können Sie mit der Funktion EINZUG VERKLEINERN eingerückte Programmteile wieder nach links rücken und pro Klick jeweils den markierten Text um einen Tabstopp versetzen. 25 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Haltepunkt ein/aus Wenn ein Makro gestartet wurde, das einen Haltepunkt aufweist, stoppt es genau an diesem Haltepunkt. Hiermit lassen sich Programm-Zwischenstände überprüfen. Block auskommentieren Hinterlegen Sie grundsätzlich ausreichend Kommentare in Ihren Makros. Es ist dadurch später leichter, die einzelnen Befehle und Funktionen nachzuvollziehen. Auch Änderungen am Makro selbst können auf diese Art und Weise festgehalten werden. Um einen Kommentar zu hinterlegen, gibt es mehrere Möglichkeiten: 쐽 Geben Sie ein einfaches Anführungszeichen ' (Hochkomma) vor dem eigentlichen Befehl oder Text ein. 쐽 Alternativ: Erfassen Sie etwas altertümlicher die Anweisung Rem, gefolgt von einem Leerzeichen und dem Befehl oder Text. Der Kommentar wird automatisch erkannt und nimmt standardmäßig die Schriftfarbe GRÜN an. Diese so kommentierten Zeilen werden beim Ablauf der Prozedur nicht ausgewertet. Es lassen sich ganze Kommentarzeilen anlegen oder auch innerhalb einer Zeile am Ende einen Kommentar anfügen. Möchten Sie innerhalb einer Zeile einen Kommentar im Anschluss an einen Befehl erfassen, fügen Sie nach dem eigentlichen Befehl ein einfaches Anführungszeichen (') ein und schreiben im Anschluss die Bemerkung. Eine der am häufigsten gebrauchten Funktionen ist jene zum schnellen Auskommentieren von Makrobefehlen. Wenn Sie im späteren Verlauf des Buches eigenständig programmieren, werden Sie mit Sicherheit auch mal etwas auf die Schnelle einfach probieren wollen. Dazu werden dann und wann einzelne oder auch mehrere Zeilen vorübergehend deaktiviert. Klar, die schnellste Methode besteht darin, die Zeilen zu löschen. Der Nachteil daran ist, dass diese Zeilen dann weg sind. Einfacher ist es, die momentan nicht benötigten Zeilen als Kommentar zu definieren. Dazu geben Sie am Anfang der Zeile ein einfaches Anführungszeichen mit der Tastenkombination Á+# ein. Damit wird die Zeile als Kommentar betrachtet und Excel ignoriert diese Zeile bei der Programmausführung. Wenn es sich dabei nur um einzelne Zeilen handelt, funktioniert diese Vorgehensweise. Umständlicher wird es aber, wenn Sie gleich blockweise 26 Die Entwicklungsumgebung von Excel-VBA jetzt lerne ich Zeilen auskommentieren möchten. Dazu markieren Sie den Bereich, der vorübergehend deaktiviert werden soll, und klicken auf das Symbol BLOCK AUSKOMMENTIEREN. Sollen hingegen einzelne Zeilen oder auch ein ganzer Block wieder aktiviert werden, markieren Sie die entsprechende(n) Zeile(n) und klicken auf das Symbol AUSKOMMENTIERUNG DES BLOCKS AUFHEBEN. Eigenschaften/Methoden anzeigen Möchten Sie kurzfristig die zur Verfügung stehenden Eigenschaften und Methoden einer Anweisung einsehen, markieren Sie den gewünschten Befehl im Code und klicken danach auf das Symbol EIGENSCHAFTEN/METHODEN ANZEIGEN. Alternativ lautet die Tastenkombination für das Aufrufen der zur Verfügung stehenden Methoden und Eigenschaften Ÿ+J. Parameterinfo Wenn Sie einen Befehl im Code-Bereich eingeben und danach die Taste þLeerÿ drücken, wird dynamisch ein QuickInfo-Fenster angezeigt, in dem die zur Verfügung stehenden Argumente abgelesen werden können. Die QuickInfo hilft Ihnen schnell weiter, die Befehle in der richtigen Syntax und mit den zur Verfügung stehenden Argumenten einzugeben. Möchten Sie bereits erfasste Befehle mit weiteren Argumenten bestücken, setzen Sie die Einfügemarke in die Anweisung (nicht auf den Befehl) und klicken in der Symbolleiste BEARBEITEN auf das Symbol PARAMETERINFO. Konstanten anzeigen Einige VBA-Befehle enthalten so genannte Konstanten. Solche Konstanten finden Sie beispielsweise beim Befehl MsgBox. Dieser Befehl zeigt ein normales Meldungsfenster mit einer OK-Schaltfläche an. Diesem Standarddialog können Sie weitere Schaltflächen bzw. Symbole hinzufügen. Genau diese sind als Konstanten hinterlegt. QuickInfo Wenn Sie die Einfügemarke in einen Befehl setzen und danach auf das Symbol QUICKINFO klicken, wird Ihnen die komplette Syntax angezeigt. 27 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Diese QuickInfo können Sie über die Tastenkombination Ÿ+I noch schneller anzeigen. 1 Sollten Sie die QuickInfos stören, lassen sich diese natürlich abschalten, indem Sie in der Entwicklungsumgebung im Menü EXTRAS den Befehl OPTIONEN wählen. Wechseln Sie danach zur Registerkarte EDITOR und deaktivieren Sie das Kontrollkästchen AUTOMATISCHE QUICKINFO. Lesezeichen setzen/zurücksetzen Bei sehr umfangreichen VBA-Prozeduren ist es in Bezug auf die Übersichtlichkeit besser, wenn Sie Lesezeichen in Ihrem Code setzen. Setzen Sie dazu die Einfügemarke auf die Stelle im Code, an der ein Lesezeichen eingefügt werden soll, und klicken Sie auf das Symbol LESEZEICHEN SETZEN/ZURÜCKSETZEN. Wie Sie jetzt sehen, wird am Beginn der Zeile ein hellblaues abgerundetes Vierecksymbol eingefügt. Betätigen Sie dieses Symbol erneut, wird das Lesezeichen wieder entfernt. Mit dem Einsatz von Lesezeichen lässt sich innerhalb des Quellcodes leichter navigieren bzw. schneller von einer Stelle an eine andere springen. Somit sind Sie auch in der Lage, bestimmte Codestücke miteinander zu vergleichen, ohne lange über die Bildlaufleisten die richtige Stelle im Code suchen zu müssen. Sobald Sie ein oder auch mehrere Lesezeichen in Ihrem Quellcode gesetzt haben, werden weitere Symbole in der Symbolleiste BEARBEITEN aktiviert. Damit können Sie zum nächsten bzw. vorherigen Lesezeichen springen. Nachdem die Programmierung abgeschlossen ist, lassen sich mit einem Klick alle gesetzten Lesezeichen wieder entfernen. 1 28 Eine sehr elegante Möglichkeit, um einzelne Prozeduren miteinander zu vergleichen, besteht darin, das Code-Fenster in zwei Bereiche zu teilen. Dazu wählen Sie aus dem Menü FENSTER den Befehl TEILEN. Dadurch wird der Code-Bereich genau in der Mitte horizontal geteilt. Es entstehen dabei zwei neue Fenster, die beide über eine eigene Steuerung verfügen. Über die vertikalen Bildlaufleisten lässt sich in den einzelnen Fenstern navigieren. Um diese Teilung der Fenster wieder rückgängig zu machen, wählen Sie noch einmal den Befehl TEILEN aus dem Menü FENSTER. Die Entwicklungsumgebung von Excel-VBA jetzt lerne ich Ganzes Wort Hinter diesem Symbol verbirgt sich eine Erleichterung bei der Eingabe von Befehlen. Geben Sie hierfür die ersten paar Buchstaben eines Befehls ein. Der VBA-Editor ergänzt dann automatisch die restlichen Buchstaben des Befehls, sofern er ihn erkennt. Geben Sie beispielsweise einmal die Buchstaben Ms ein und klicken danach auf das Symbol GANZES WORT. Der VBA-Editor schlägt daraufhin den Befehl MsgBox vor. Schneller geht es allerdings, wenn Sie die ersten Buchstaben eines Befehls eingeben und dann die Tastenkombination Ÿ+þLeerÿ drücken. 1.2.6 Die Symbolleiste Debuggen Die Symbolleiste DEBUGGEN stellt Ihnen Symbole zur Verfügung, die das schnelle Testen von Quellcode vereinfachen. Bild 1.10: Die Symbolleiste Debuggen Entnehmen Sie der folgenden Tabelle die Bedeutung der einzelnen Symbole: Symbol Bedeutung Aktiviert und deaktiviert den Entwurfsmodus. Führt die aktuelle Prozedur aus, falls sich der Cursor in einer Prozedur befindet; führt das UserForm-Formular aus, falls ein UserForm-Formular aktiv ist; führt ein Makro aus, falls weder ein Code-Fenster noch ein UserForm-Formular aktiv ist. Tabelle 1.1: Die Symbole der Symbolleiste Debuggen Beendet die Ausführung eines Programms und wechselt in den Haltemodus. Stattdessen können Sie auch die Taste È drücken, um den Ablauf des Makros zu stoppen. Löscht die Aufrufliste und die Variablen auf Modulebene und beendet das Projekt. 29 1 Erste Schritte mit Excel-VBA jetzt lerne ich Tabelle 1.1: Symbol Die Symbole der Symbolleiste Debuggen (Forts.) Bedeutung Setzt oder entfernt einen Haltepunkt in der aktuellen Zeile. Alternativ dazu genügt auch das Drücken der Taste Ñ, um einen Haltepunkt zu setzen bzw. zu entfernen. Führt jeweils genau eine Anweisung im Code aus. Alternativ lässt sich die Taste Ð einsetzen, um einen Code Zeile für Zeile zu durchlaufen. Führt im Code-Fenster jeweils eine Prozedur oder eine Anweisung im Code aus. Führt die restlichen Zeilen einer Prozedur aus, in der sich der aktuelle Ausführungspunkt befindet. Blendet das Lokal-Fenster ein. Blendet das Direktfenster ein. Alternativ dazu funktioniert auch die Tastenkombination Ÿ+G, um das Direktfenster einzublenden. Blendet das Überwachungsfenster ein. Zeigt das Dialogfeld AKTUELLEN WERT ANZEIGEN mit dem aktuellen Wert des ausgewählten Ausdrucks an. Zeigt das Dialogfeld AUFRUFLISTE an, in dem die derzeit aktiven Prozeduraufrufe (Prozeduren in der Anwendung, die gestartet, aber nicht abgeschlossen wurden) angezeigt werden. 1.2.7 Automatische Syntaxprüfung Der VBA-Editor von Excel unterstützt Sie bereits bei der Eingabe von Befehlen tatkräftig. Sehen Sie sich dazu einmal das nächste Beispiel an. Begonnen wird in der Prozedur MeldungAusgeben damit, das Objekt Application einzugeben. Sobald Sie den Punkt eintippen, bietet der VBA-Editor an, was er an Befehlen für genau dieses Objekt im Angebot hat. Unter anderem ist dies die Eigenschaft ActiveWorkbook, die den Namen der aktuellen Arbeitsmappe ermittelt. Sie brauchen nichts weiter zu tun, als die Eigenschaft aus dem Dropdown-Feld zu wählen. Mit diesem Automatismus stellt der VBA-Editor sicher, dass keine Eigenschaften oder Methoden verwendet werden, die den Objekten fremd sind. Mit der Taste Å wird der gewünschte Befehl aus dem Dropdown-Feld ausgewählt. Fügen Sie nun einen weiteren 30 Die Entwicklungsumgebung von Excel-VBA jetzt lerne ich Punkt ein, um das Kontextmenü für die Eigenschaft ActiveWorkbook auszuklappen. Wählen Sie aus dem Kontextmenü den Befehl Name. Bild 1.11: Alle Methoden und Eigenschaften des Objekts Application anzeigen 1.2.8 Den Code Schritt für Schritt durchlaufen Eine weitere Möglichkeit der Fehlersuche in Excel ist es, eine Prozedur Zeile für Zeile abzuarbeiten. Dazu setzen Sie die Einfügemarke in die erste Zeile der Prozedur und drücken die Taste Ð. Alternativ dazu können Sie ebenso den Menübefehl DEBUGGEN/EINZELSCHRITT wählen. Die Prozedur hält nach jedem Befehl an. Es lässt sich dann prüfen, ob die gewünschte Aktion ausgeführt wurde, indem Sie die Entwicklungsumgebung kurzfristig verlassen und in Ihrer Datenbanktabelle die Ergebnisse kontrollieren. Eine weitere Variante ist es, in der beschriebenen Prozedur die Einfügemarke in die Zeile zu setzen, bis zu der die Prozedur durchlaufen werden soll. Setzen Sie dazu beispielsweise die Einfügemarke in die Zeile, bis zu der Sie den Code durchlaufen möchten, und drücken Sie die Tastenkombination Ÿ+Ð. 1.2.9 Tastenkombinationen einsetzen Neben den beiden Tastenkombinationen Ÿ+C, um Codeteile zu kopieren, und Ÿ+V, um diese kopierten Codeteile an anderer Stelle des Moduls wieder einzufügen, gibt es eine ganze Reihe weiterer Tastenkombinationen, die Ihnen mehr Arbeitserleichterung 31 1 Erste Schritte mit Excel-VBA jetzt lerne ich und eine nicht zu unterschätzende Zeitersparnis beim Programmieren bringen. Entnehmen Sie der folgenden Tabelle einige der gängigsten Tastenkombinationen für das zügige Arbeiten in der Entwicklungsumgebung. Tabelle 1.2: Tastenkombination Die Tastenkombina- Ï tionen des Ê Entwicklers 32 Beschreibung Code-Fenster anzeigen Objektkatalog anzeigen Ÿ +F Suchen Ÿ +H Ersetzen Ë Weitersuchen Á+Ë Vorheriges suchen Ÿ +~ Nächste Prozedur Ÿ +| Vorherige Prozedur Á +Ê Definition anzeigen Ÿ +² Einen Bildschirm nach unten Ÿ +³ Einen Bildschirm nach oben Ÿ +Á +Ê Zur letzten Position wechseln Ÿ +£ Anfang des Moduls Ÿ +¤ Ende des Moduls Ÿ +} Ein Wort nach rechts Ÿ +{ Ein Wort nach links ¤ Zum Zeilenende wechseln £ Zum Zeilenanfang wechseln Ÿ +Z Letzten Befehl rückgängig machen Ÿ +C Code kopieren Ÿ +X Code ausschneiden Ÿ +V Code einfügen Ÿ +Y Aktuelle Zeile löschen Ÿ +® Bis zum Wortende löschen Å Einzug vergrößern Á +Å Einzug verkleinern Ÿ + Á +Ñ Alle Haltepunkte löschen Weitere Einstellungen Tastenkombination Beschreibung Á +Ò Kontextmenü anzeigen Ÿ +P Modul drucken Ÿ +E Modul/Formular exportieren Ÿ +S Modul speichern 1.3 jetzt lerne ich Tabelle 1.2: Die Tastenkombinationen des Entwicklers (Forts.) Weitere Einstellungen In der Entwicklungsumgebung von Excel besteht die Möglichkeit, den Visual Basic-Editor den eigenen Wünschen anzupassen. Dazu wählen Sie aus dem Menü EXTRAS den Befehl OPTIONEN. 1.3.1 Editor-Einstellungen Wechseln Sie auf die Registerkarte EDITOR. Dort lassen sich die Einstellungen für das Code- und das Projekt-Fenster festlegen. Bild 1.12: Editoreinstellungen vornehmen Im Gruppenfeld CODE-EINSTELLUNGEN finden Sie die folgenden Einstellungsmöglichkeiten: 쐽 AUTOMATISCHE SYNTAXÜBERPRÜFUNG: Mit dieser Einstellung unternimmt der Editor nach der Eingabe einer Codezeile automatisch eine Syntaxprüfung. 쐽 VARIABLENDEKLARATION ERFORDERLICH: Wenn Sie diese Option aktivieren, wird die Anweisung Option Explicit den allgemeinen Deklarationen in allen neuen Modulen hinzugefügt. Damit müssen alle im 33 1 Erste Schritte mit Excel-VBA jetzt lerne ich Code verwendeten Variablen zu Beginn eines Makros definiert werden. Wird dies vergessen, weist Excel den Programmierer automatisch darauf hin. Es wird auf jeden Fall kein Makro ausgeführt, in dem nicht alle verwendeten Variablen definiert sind. 쐽 ELEMENTE AUTOMATISCH AUFLISTEN: Zeigt eine Liste mit den Informationen an, um die Anweisung an der aktuellen Einfügemarke logisch zu vervollständigen. 쐽 AUTOMATISCHE QUICKINFO: Wird diese Option aktiviert, werden bei der Eingabe eines Befehls die dazugehörigen Funktionen bzw. Parameter angezeigt. 쐽 AUTOMATISCHE DATEN-TIPS: Diese Option ist lediglich im Haltemodus verfügbar und zeigt den Wert der Variablen an, auf der sich der Mauszeiger gerade befindet. 쐽 AUTOMATISCH EINZUG VERGRÖSSERN: Zur besseren Übersichtlichkeit ist es allgemein üblich den Quellcode einzurücken. Die dafür zur Verfügung gestellte Option ermöglicht es, für die erste Codezeile einen Tabulator festzulegen. Alle nachfolgenden Zeilen beginnen an der Tabulatorposition. 쐽 TAB-SCHRITTWEITE: In diesem Eingabefeld stellen Sie die TabulatorSchrittweite auf einen Wert zwischen 1 und 32 Leerzeichen ein. 쐽 Im Gruppenfeld FENSTEREINSTELLUNGEN können Sie unter anderem das Drag&Drop im Code-Fenster ausschalten, automatisch eine Trennlinie zwischen den einzelnen Prozeduren ziehen lassen und das Erscheinungsbild von neuen Modulen beeinflussen. 1.3.2 Editorformat festlegen Wenn Sie zur Registerkarte EDITORFORMAT wechseln, können Sie die Darstellung Ihres Quellcodes anpassen (vgl. Bild 1.2). Im Listenfeld werden die Textelemente angezeigt, bei denen die Farben angepasst werden können. Darunter befinden sich drei Dropdown-Felder, in denen das Format für den Vorder- bzw. Hintergrund der einzelnen Elemente sowie das Kennzeichen in der Kennzeichenleiste bestimmt werden kann. Darüber hinaus besteht die Möglichkeit, die Schriftart sowie deren Größe zu bestimmen. Die Kennzeichenleiste kommt dann zur Geltung, wenn Sie häufiger mit Haltepunkten oder Lesezeichen arbeiten. 34 Weitere Einstellungen jetzt lerne ich Bild 1.13: Das Editierformat anpassen 1.3.3 Allgemeine Einstellungen vornehmen Wechseln Sie nun zur Registerkarte ALLGEMEIN. Dort werden die Einstellungen, die Fehlerbehandlung und die Kompilierungseinstellungen für das aktuelle Visual Basic-Projekt festgelegt. Bild 1.14: Allgemeine Einstellungen vornehmen Im Gruppenfeld EINSTELLUNGEN FÜR FORMULAR-RASTER können Sie die Darstellungsart des Formulars beim Bearbeiten festlegen. Es lässt sich ein Raster anzeigen, die Rastereinheiten sowie die Rasterung selbst für das Formular festlegen. Außerdem lassen sich eingefügte Steuerelemente automatisch am Raster ausrichten. Die Einstellung QUICKINFO ANZEIGEN bezieht sich lediglich auf die QuickInfos für die Symbolschaltflächen und kann deaktiviert werden, wenn Sie etwas mehr Übung haben und die Symbole in den Symbolleisten kennen. 35 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Aktivieren Sie das Kontrollkästchen AUSBLENDEN DES PROJEKTS SCHLIESST FENSTER, wenn Projekt-, UserForm-, Objekt- oder Modulfenster automatisch geschlossen werden sollen, sobald ein Projekt im ProjektExplorer ausgeblendet wird. Im Gruppenfeld BEARBEITEN UND FORTFAHREN wird definiert, ob eine Benachrichtigung erfolgen soll, sofern durch eine angeforderte Aktion alle Variablen auf Modulebene für ein laufendes Projekt zurückgesetzt werden. Das Gruppenfeld UNTERBRECHEN BEI FEHLERN bestimmt, wie Fehler in der Visual Basic-Entwicklungsumgebung verarbeitet werden sollen. Das Einstellen dieser Option wirkt sich auf alle Instanzen von Visual Basic aus, die nach dem Ändern dieser Einstellung gestartet werden. Sie haben dabei folgende drei Möglichkeiten: 쐽 BEI JEDEM FEHLER: Bei jedem Fehler wird für das Projekt der Haltemodus aktiviert, unabhängig davon, ob eine Fehlerbehandlungsroutine aktiviert ist oder sich der Code in einem Klassenmodul befindet. Die fehlerhafte Zeile wird dann mit einer gelben Hintergrundfarbe hinterlegt. 쐽 IN KLASSENMODUL: Mit dieser Einstellung werden alle nicht verarbeiteten Fehler in einem Klassenmodul mit dem Haltemodus gestoppt. 쐽 BEI NICHT VERARBEITETEN FEHLERN: Wenn eine Fehlerbehandlungsroutine läuft, wird der Fehler behandelt, ohne den Haltemodus zu aktivieren. Sollte keine Fehlerbehandlungsroutine vorhanden sein, bewirkt der Fehler, dass der Haltemodus für das Projekt aktiviert wird. Im Gruppenfeld KOMPILIEREN wird definiert, ob ein Projekt vor dem Start vollständig kompiliert wird oder ob der Code bei Bedarf kompiliert wird, wodurch die Anwendung schneller gestartet werden kann. 36 Der Makrorekorder 1.3.4 jetzt lerne ich Fenster verankern Auf der Registerkarte VERANKERN legen Sie fest, welche Fenster verankerbar sein sollen. Bild 1.15: Fenster verankern Ein Fenster ist verankert, wenn es mit einer Kante eines anderen verankerbaren Fensters oder eines Anwendungsfensters verbunden ist. Es wird beim Verschieben automatisch ausgerichtet. Ein Fenster ist nicht verankerbar, wenn es an eine beliebige Position auf dem Bildschirm verschoben werden kann und diese Position beibehält. Wählen Sie die Fenster aus, die verankerbar sein sollen, und deaktivieren Sie die Kontrollkästchen für die anderen Fenster. 1.4 Der Makrorekorder Zu Beginn der Programmierung mit Excel-VBA wird es Ihnen vermutlich schwer fallen, sich die Syntax einiger Befehle anzueignen. Eine hervorragende Möglichkeit, sich schnell mit den einzelnen Befehlen vertraut zu machen, besteht darin, den Makrorekorder einzusetzen. Mithilfe des Makrorekorders lassen sich Aktionen, die sonst manuell in Excel vorgenommen werden, im Hintergrund aufzeichnen. Dabei wird jede einzelne Aktion mit den dafür notwendigen Befehlen direkt in das Code-Fenster geschrieben. Sie können sich diesen aufgezeichneten Quellcode danach ansehen und ihn noch weiter anpassen. Später lässt sich diese Sequenz innerhalb von Excel durch Aufruf des Makros beliebig oft erneut ausführen. Üben Sie 37 1 Erste Schritte mit Excel-VBA jetzt lerne ich sich im Gebrauch des Makrorekorders, indem Sie die folgenden Aufgaben durchführen: 1.4.1 Ein- und Ausschalten der Gitternetzlinien In der ersten Aufgabe werden die Gitternetzlinien für eine Tabelle aus- und wieder eingeschaltet. Setzen Sie den Makrorekorder ein, indem Sie die nächsten Arbeitsschritte ausführen: 1. Wählen Sie in Excel aus dem Menü EXTRAS den Befehl MAKRO/AUFZEICHNEN . Bild 1.16: Ein neues Makro aufzeichnen 2. Benennen Sie das Makro im Feld MAKRONAME mit einem zusammengeschriebenen Namen oder übernehmen Sie den von Excel vorgeschlagenen Namen. 3. Im Feld TASTENKOMBINATION können Sie dem Makro eine Tastenkombination zuweisen. Geben Sie in dieses Feld einmal den Buchstaben ü ein. 4. Im Dropdown-Feld MAKRO SPEICHERN IN haben Sie drei Auswahlmöglichkeiten: – DIESE ARBEITSMAPPE: Das Makro wird in der aktuellen Arbeitsmappe gespeichert. Es ist dann nur für diese Arbeitsmappe einsetzbar. – NEUE ARBEITSMAPPE: Das aufgezeichnete Makro wird in einer neuen Arbeitsmappe gespeichert. – PERSÖNLICHE MAKROARBEITSMAPPE: Das aufgezeichnete Makro wird in der zentralen Makroarbeitsmappe PERSONL.XLS abgelegt, die mit jedem Excel-Start geladen wird, aber im Hintergrund bleibt. Somit können Makros, die in dieser Mappe gespeichert werden, für alle anderen Arbeitsmappen eingesetzt werden. 38 Der Makrorekorder jetzt lerne ich Die Datei Personl.xls finden Sie übrigens im Office-Unterverzeichnis Office/XlStart. Standardmäßig ist diese Arbeitsmappe nach der Installation noch nicht angelegt. Die Mappe wird aber automatisch für Sie angelegt, wenn Sie ein Makro aufzeichnen und als Speicherort für das Makro die persönliche Makroarbeitsmappe auswählen. Entscheiden Sie sich hier für diese Variante. 5. Im Feld BESCHREIBUNG können Sie eine optionale Beschreibung für das Makro erfassen, die beispielsweise die Aufgabe, den Autor und das Erstellungsdatum beinhaltet. 6. Bestätigen Sie Ihre Eingaben mit OK. 7. Wählen Sie nun aus dem Menü EXTRAS den Befehl OPTIONEN. 8. Wechseln Sie im Dialogfeld OPTIONEN auf die Registerkarte ANSICHT. 9. Deaktivieren Sie das Kontrollkästchen GITTERNETZLINIEN. 10. Bestätigen Sie Ihre Aktion mit OK. 11. Beenden Sie die Aufzeichnung des Makrorekorders mit einem Klick auf das Symbol AUFZEICHNUNG BEENDEN in der angezeigten kleinen Symbolleiste. Kontrollieren Sie nun das Resultat der Aufzeichnung durch Wechseln in die Entwicklungsumgebung über die Tastenkombination Ç +Ó . Bild 1.17: Das erste aufgezeichnete Makro 39 1 Erste Schritte mit Excel-VBA jetzt lerne ich Für das Ausschalten der Gitternetzlinien ist lediglich eine Anweisung notwendig. Die benötigte Eigenschaft DisplayGridLines wird für diesen Zweck auf den Wert False gesetzt. Um die Gitternetzlinien wieder einzublenden, setzen Sie die Eigenschaft DisplayGridLines wieder auf den Wert True. 1.5 Die ersten Makros Am Ende des Kapitels schreiben Sie Ihre ersten Makros. Dazu wechseln Sie über die Tastenkombination Ç+Ó in die Entwicklungsumgebung und wählen aus dem Menü EINFÜGEN den Befehl MODUL. 1.5.1 Ein mehrzeiliges Infofenster ausgeben Erfassen Sie dazu die Prozedur aus Listing 1.2. Bild 1.18: Eine mehrzeilige Meldung wird am Bildschirm angezeigt Listing 1.2: Sub MehrzeiligeMeldungausgeben() Eine mehrzeilige Meldung MsgBox "Der angemeldete Anwender heißt: " & _ Environ("username") & vbLf & _ anzeigen "Heute ist " & Format(Date, "DDDD, ""der"" DD.MM.YYYY") & vbLf & _ "Aktuelle Uhrzeit: " & Time & " Uhr", vbInformation, _ "Aktuelle Ansage" End Sub Sollen mehrere Zeilen in einem Meldungsfenster ausgegeben werden, dann muss für jeden gewünschten Zeilenumbruch die Konstante vbLf (Visual Basic Line Feed = Zeilenumbruch) gesetzt werden. Der unter Windows angemeldete Anwender kann über die Anweisung Environ (Betriebssystem-Umgebung) abgerufen werden, der Sie die Konstante Username übergeben. Da in diesem Makro Textteile und Funktionen gemischt werden, müssen die einzelnen Teile durch das Zeichen & voneinander getrennt werden. Das aktuelle Systemdatum fragen Sie über die VBA-Funktion Date ab. Diese allgemeine VBA- 40 Die ersten Makros jetzt lerne ich Funktion ist übrigens in allen Office-Anwendungen einsetzbar und liefert das aktuelle Datum. Dabei orientiert sich diese Funktion an dem eingestellten Datum in der Systemsteuerung von Windows. Das zurückgelieferte Datum kann über die Funktion Format in das jeweils gewünschte Format gebracht werden. Die Formatierung erfolgt hierbei über Formatkürzel. So gelten folgende Definitionen: 쐽 DD zweistellige Tagesangabe (27) 쐽 DDD Tagesausgabe in der Kurzform (Mi) 쐽 DDDD Tagesausgabe in der Langform (Mittwoch) 쐽 MM zweistellige Monatsausgabe (04) 쐽 MMM Monatsausgabe in der Kurzform (Apr) 쐽 MMMM Monatsausgabe in der Langform (November) 쐽 YY zweistellige Jahresausgabe (05) 쐽 YYYY vierstellige Jahresausgabe (2005) Die aktuelle Uhrzeit wird über die VBA-Funktion Time abgefragt. Über die Konstante vbInformation können Sie dem Meldungsfenster noch ein Informations-Symbol hinzufügen. Weitere mögliche Symbole sind: 쐽 vbCritical Stopp-Symbol 쐽 vbExclamation Ausrufezeichen-Symbol 쐽 vbQuestion Fragezeichen-Symbol Ganz am Ende der Anweisung besteht noch die Möglichkeit dem Fenster einen Titel zuzuweisen. 1.5.2 Meldung mit Rückfrage erstellen Im folgenden Beispiel soll vor dem Start eines Vorgangs sicherheitshalber abgefragt werden, ob dieser wirklich durchgeführt werden soll. Diese Art der Abfrage finden Sie oft bei kritischen Vorgängen, wie dem Löschen oder Drucken von Daten. Gerade beim Löschen von Daten sollte eine Rückfrage eingesetzt werden, um sicherzustellen, dass nicht versehentlich wichtige Daten gelöscht werden. Auch für diese Aufgabe nutzen wir die Funktion MsgBox. Allerdings benötigen Sie bei der Meldung zwei zusätzliche Schaltflächen: JA 41 jetzt lerne ich 1 Erste Schritte mit Excel-VBA und NEIN. Erfassen Sie zunächst die vorläufige Prozedur aus Listing 1.3. Listing 1.3: Sub VorgangAbfragen() Der erste Dim intWahl As Integer Schritt zur Rückfrage intWahl = MsgBox("Wollen Sie den Vorgang wirklich fortsetzen?", _ vbYesNo + vbQuestion, "Rückfrage") Debug.Print intWahl End Sub Starten Sie diese Prozedur einmal, indem Sie den Mauszeiger in die Prozedur setzen und die Taste Í drücken. Bild 1.19: Ja oder Nein anklicken Bei der Programmierung von Schaltflächen verwendet VBA für jede Schaltfläche eine eindeutige Nummer. Wie können Sie diese Nummer aber herausfinden? 쐽 Setzen Sie dazu den Mauszeiger auf die Funktion MsgBox und rufen über die Taste É die Online-Hilfe zu diesem Befehl auf. 쐽 Eine andere Möglichkeit ist das Schreiben des Rückgabewerts der Funktion MsgBox über den Befehl Debug.Print in das Direktfenster der Entwicklungsumgebung. Blenden Sie das Direktfenster über die Tastenkombination Ÿ+G ein und lesen den Inhalt des Fensters ab. Sofern die Schaltfläche JA gedrückt wurde, ist der Rückgabewert im Direktfenster die Zahl 6. Beim Klick auf die Schaltfläche NEIN wird die Nummer 7 zurückgegeben. Arbeiten Sie diese Informationen in die Prozedur aus dem Listing 1.4 ein. 42 Die ersten Makros Sub VorgangAbfragen() Dim intWahl As Integer intWahl = MsgBox("Wollen Sie den Vorgang wirklich fortsetzen?", _ vbYesNo + vbQuestion, "Rückfrage") 'Debug.Print intWahl jetzt lerne ich Listing 1.4: Komplette Rückfrage, ob der Vorgang weiter durchgeführt werden soll If intWahl = 6 Then MsgBox "Sie haben Ja geklickt!" Else MsgBox "Sie haben Nein geklickt!" End If End Sub Lesen Sie in Kapitel 9 mehr über Dialoge. 1.5.3 Einen Eingabedialog aufrufen 1 Bei der nächsten Aufgabe soll ein Dialog aufgerufen werden, in dem der Anwender eine Eingabe vornehmen kann. Um diese Aufgabe zu lösen, setzen Sie die Funktion InputBox im Listing 1.5 ein. Bild 1.20: Das Geburtsdatum eingeben Sub EingabedialogAufrufen() Dim DatEingabe As String DatEingabe = InputBox("Geben Sie Ihr Geburtsdatum ein!", _ "Altersüberprüfung") Listing 1.5: Das Alter des Anwenders wird abgefragt If DatEingabe <> "" And IsDate(DatEingabe) Then MsgBox "Sie sind genau " & _ Format(Date - CDate(DatEingabe), "YY") & " Jahre alt!" End If End Sub 43 1 Erste Schritte mit Excel-VBA jetzt lerne ich Zunächst soll geprüft werden, ob überhaupt eine Eingabe erfolgt ist. Des Weiteren sollte geprüft werden, ob es sich bei dem eingegebenen Wert auch wirklich um ein gültiges Datum handelt. Die Überprüfung übernimmt die Funktion IsDate. Treffen beide Bedingungen zu, kann die Berechnung des Alters stattfinden. Dabei wird das aktuelle Tagesdatum vom Geburtsdatum subtrahiert. Diese Operation liefert standardmäßig die Anzahl der Tage zurück, die zwischen den beiden Datumsangaben liegen. Da wir aber die Differenz in Jahren anzeigen möchten, verwenden wir auch hier die Funktion Format, um das Ergebnis in das gewünschte Format zu bringen. 1.6 Variablen definieren und einsetzen Der folgende Abschnitt bildet die Voraussetzung für eine strukturierte Programmierung in Excel. Mit der Verwendung von Variablen werden Informationen dauerhaft während der Laufzeit einer Prozedur gespeichert. D. h. es können Variablen auch mehrmals in einer Prozedur als Datenpuffer genutzt werden, indem diese mit einem Wert gefüllt werden und dieser Wert zum Beispiel durch Hochzählen oder Subtrahieren verändert wird. Mit Konstanten werden Informationen festgehalten, die sich selten oder sogar nie ändern. Excel bietet für die Deklaration von Variablen und Konstanten eine ganze Auswahl an Datentypen an. Je nach Aufgabe setzten Sie dazu die vorgesehenen Datentypen ein. Sicher werden Sie sich fragen, warum Variablen in der Programmierung benötigt werden. Variablen werden unter anderem dazu benötigt, um Daten zwischenzuspeichern. Wenn Sie beispielsweise daran denken, Daten aus einer Tabelle zu lesen, um diese zu bearbeiten und dann wieder in eine andere Tabelle zurückzuschreiben, dann ist das ohne Variablen und nur über die Zwischenablage recht unsicher. Wenn es sich nur um eine einzige zu übertragende Information handelt, mag die Vorgehensweise ohne Variablen noch in Ordnung sein. Stellen Sie sich aber einmal vor, Sie müssten mehrere Informationen von einer Tabelle in eine andere übertragen und dabei die Daten noch abändern. Da kommen Sie um den Einsatz von Variablen nicht herum. Außerdem bietet die Zwischenablage nicht die Beständigkeit wie eine Variable. So ist die Zwischenablage beispielsweise leer, sobald Sie den Inhalt der Zwischenablage einmal in ein Feld einer Tabelle eingefügt haben. Außerdem haben noch 44 Variablen definieren und einsetzen jetzt lerne ich andere Anwendungen Zugriff auf die Zwischenablage. Mit Variablen können Sie in der Anwendung dauerhaft arbeiten, d. h. Sie können jederzeit darauf zugreifen, sie abfragen oder verändern und zum Schluss ausgeben. 1.6.1 Syntaxfestlegungen für Variablen Wenn Sie Variablen einsetzen, müssen Sie sich dabei an bestimmte Konventionen für deren Benennung halten: 쐽 Das erste Zeichen muss aus einem Buchstaben bestehen. Als folgende Zeichen können Buchstaben, Zahlen und einige Sonderzeichen verwendet werden. 쐽 Sie dürfen keine Leerzeichen in einem Variablennamen verwenden. Wenn einzelne Wörter getrennt werden sollen, verwenden Sie dazu den Unterstrich, wie z. B. Dim AktMiete_Januar as Currency. 쐽 Sonderzeichen wie #, %, &, ! oder ? sind nicht erlaubt. 1.6.2 Die Namenskonvention von Gregory Reddick Für die Deklaration von Variablen können Sie sich an die so genannte Notation von Gregory Reddick halten. Dabei wird dem Variablennamen ein Kürzel vorangesetzt, aus dem Sie den Datentyp der Variablen erkennen können. Dies erleichtert die Pflege von fremden Quellcodes erheblich. Folgende Kürzel wurden dabei von Herrn Reddick festgelegt: Kürzel Datentyp: bool Boolean byte Byte Cur Currency date Date dec Decimal dbl Double int Integer lng Long obj Object Tabelle 1.3: Die Namenskonvention von Gregory Reddick 45 1 Erste Schritte mit Excel-VBA jetzt lerne ich Tabelle 1.3: Die Namenskonvention von Gregory Reddick (Forts.) Kürzel Datentyp: sng Single str String var Variant 1.6.3 Variablen deklarieren Variablen werden immer zu Beginn einer Prozedur deklariert, also nach der Sub-Anweisung. Dabei spricht man von lokalen Variablen. Diese Variablen können nur in der Prozedur verwendet werden, in der sie deklariert wurden. Nachdem eine Prozedur durchgelaufen ist, wird diese Variable wieder aus dem Speicher gelöscht. Von globalen Variablen spricht man, wenn diese allgemein gültig, also in mehreren Prozeduren verwendet werden sollen. Hierfür muss die Variablendeklaration vor der Sub-Anweisung stattfinden. Globale Variablen können gleich für mehrere Prozeduren verwendet werden. Diese werden nach dem Ende einer Prozedur auch nicht gelöscht und behalten ihren aktuellen Wert bei. Es gibt Beispiele, in denen diese Vorgehensweise sinnvoll ist. In den meisten Fällen sollten globale Variablen aber weitestgehend vermieden werden, da sie wertvollen Speicherplatz auf dem Stapelspeicher belegen, was sich negativ auf das Laufzeitverhalten von Prozeduren auswirken kann. Eine Variablendeklaration beginnt immer mit der Anweisung Dim, gefolgt von einem Freizeichen und dem Variablennamen, der frei gewählt werden kann. Danach geben Sie mit dem Schlüsselwort As an, welchen Datentyp die Variable erhalten soll. 1.6.4 Statische Variablen Sie haben die Möglichkeit, Variablen so zu definieren, dass deren »Haltbarkeit« nach jedem Prozedurende erhalten bleibt. Sehen Sie sich dazu einmal die beiden folgenden Listings an. Listing 1.6: Der Inhalt der Variablen lngZaehler wird nach dem Makro gelöscht 46 Sub Variablen01() Dim lngZaehler As Long lngZaehler = lngZaehler + 1 MsgBox lngZaehler End Sub Variablen definieren und einsetzen jetzt lerne ich Im Listing 1.7 wird bei jedem Prozedurstart die Variable auf den Anfangswert 0 (ungesetzter Zustand) zurückgesetzt. Sub Variablen02() Static lngZaehler As Long lngZaehler = lngZaehler + 1 MsgBox lngZaehler End Sub Listing 1.7: Der Inhalt der Variablen lngZaehler bleibt nach Ablauf des Makros bestehen Wenn die Prozedur aus Listing 1.7 mehrmals hintereinander aufgerufen wird, wird deutlich, dass der Inhalt der Variablen lngZaehler auch nach jedem Durchlauf erhalten bleibt. 1.6.5 Private Variablen Als Nächstes ist die Anweisung Private zu nennen. Wird diese Anweisung bei der Deklaration einer Variablen eingesetzt, gilt deren Gültigkeit für alle im Modul befindlichen Prozeduren. Sehen Sie sich dazu die folgende Prozedur in Listing 1.8 an. Private strName As String Sub Variablen03() strName = Application.ActiveWorkbook.FullName MsgBox strName End Sub 1.6.6 Listing 1.8: Die Variable strName kann in allen Makros des Moduls eingesetzt werden Öffentliche Variablen Analog zu den privaten Variablen gibt es selbstverständlich auch öffentliche Variablen. Diese Variablen werden mit der Anweisung Public deklariert. Damit haben Sie die Möglichkeit, auf Variablen zuzugreifen, die in anderen Modulen untergebracht sind. Sehen Sie sich dazu einmal das Beispiel in Listing 1.9 an. Public sngMwst As Single Sub Variablen04() sngMwst = 1.16 MsgBox 100 * sngMwst End Sub Listing 1.9: Die Variable sngMwst kann in allen Makros des Projekts verwendet werden 47 1 Erste Schritte mit Excel-VBA jetzt lerne ich 1.6.7 Variablendeklarationen erzwingen Excel lässt sich so einstellen, dass jede Variable vor deren ersten Verwendung deklariert werden muss. Vorher kann keine einzige Prozedur gestartet werden, sofern sie mit Variablen arbeitet, die zuvor nicht deklariert wurden. Um diese wichtige Einstellung vorzunehmen, wechseln Sie in die Entwicklungsumgebung und rufen den Befehl EXTRAS/OPTIONEN auf. Wechseln Sie auf die Registerkarte EDITOR und aktivieren Sie das Kontrollkästchen VARIABLENDEKLARATION ERFORDERLICH . Was bewirkt diese Einstellung aber genau? Immer wenn Sie ein neues Modul einfügen, wird automatisch die Anweisung Option Explicit in die erste Zeile Ihres Modulblatts eingetragen. Diese Anweisung kann selbstverständlich auch manuell erfasst werden. Sie bedeutet nichts anderes, als dass verwendete Variablen im Code vor deren Aufruf deklariert werden müssen. Vorher läuft gar nichts! 1 Die Entwicklungsumgebung von Excel bietet Ihnen eine hilfreiche Möglichkeit, zu prüfen, wo verwendete Variablen definiert sind. Klicken Sie die zu überprüfende Variable mit der rechten Maustaste an und wählen Sie im Kontextmenü den Befehl DEFINITION aus. Der Mauszeiger springt danach direkt an die Stelle im Code, an der die Variable definiert wurde. 1.6.8 Die wichtigsten Variablentypen Die beiden wichtigsten Variablentypen sind zum einen die Variable vom Typ String und zum anderen die Integer-Variable. In einer Variablen vom Typ String kann beliebiger Text zwischengespeichert, manipuliert und ausgegeben werden. Mit einer Variablen vom Typ Integer werden ganze Zahlen gespeichert. Integer-Variablen werden oft als Zähler in Schleifen verwendet, die Sie im weiteren Verlauf des Buches noch kennen lernen werden, oder auch für allgemeine mathematische Berechnungen. Entnehmen Sie der nachfolgenden Tabelle die gängigsten Variablentypen und deren Speicherbedarf. 48 Variablen definieren und einsetzen Variablentyp Wertebereich/Speicherbedarf Byte Ganze Zahlen zwischen 0 und 255 (1 Byte) Boolean Wahrheitswert, entweder True oder False (2 Bytes) Currency Währungs-Datentyp: Festkommazahlen mit 15 Stellen vor und 4 Stellen nach dem Komma (8 Bytes) Date Datums- und Zeit-Datentyp (8 Bytes) Decimal Dezimalzahlen (14 Bytes) Double Fließkommazahlen mit einer Genauigkeit von 16 Stellen hinterm Komma (8 Bytes) Integer Ganze Zahlen zwischen –32.768 und +32.767 (2 Bytes) Long Ganze Zahlen im Wertebereich von –2.147.483.648 bis +2.147.483.647 (4 Byte) Object Datentyp gibt einen Verweis auf ein Objekt wieder (4 Bytes) Single Fließkommazahlen mit einer Genauigkeit von 8 Stellen hinterm Komma (4 Bytes) String Der Datentyp für alle Texte (10 Bytes) Variant Standarddatentyp, wird automatisch gewählt, wenn kein anderer Datentyp definiert ist (16 Bytes) jetzt lerne ich Tabelle 1.4: Die Datentypen für die Programmierung Oft werden Variablen in folgender Form deklariert: Dim lngZ1, lngZ2, lngZ3 As Long Hier ist anzumerken, dass lediglich die letzte Variable dem Typ Long zugeordnet wird. Alle anderen Variablen bekommen den Datentyp Variant. Richtig wäre hier: Dim lngZ1 As Long Dim lngZ2 As Long Dim lngZ3 As Long oder Dim lngZ1 As Long, lngZ2 As Long, lngZ3 As Long 49 1 Erste Schritte mit Excel-VBA jetzt lerne ich 1.6.9 Noch kürzere Deklaration von Variablen Wenn Sie nach und nach geübter in der Programmierung werden, möchten Sie möglicherweise die Variablennamen nicht mehr ganz so lang schreiben und auch bei der Datentyp-Anweisung weniger Schreibarbeit haben. Sehen Sie sich dazu einmal die folgende Tabelle an: Tabelle 1.5: Ausführlich Noch kürzere Datentyp- Dim intZähler as Integer Deklaration Dim lngZähler Groß as Long Kurzform Dim intZähler% Dim lngZählerGroß& Dim CurBetrag as Currency Dim CurBetrag@ Dim strMeldung as String Dim strMeldung$ Dim sngZahl as Single Dim sngZahl! Dim dblMaxZahl as Double Dim dblMaxZahl# Für jeden in der Tabelle 1.5 aufgeführten Datentyp gibt es ein Kurzzeichen, das Sie einsetzen können, um den Programmiercode zu verkürzen. 1.7 Die Verwendung von Konstanten Im Gegensatz zu den Variablen ändern die Konstanten ihre Werte nie und bleiben während der Programmausführung immer gleich. Auch hier wird zwischen lokalen und globalen Konstanten unterschieden. Globale Konstanten werden außerhalb der einzelnen Prozeduren definiert und sind damit für alle Prozeduren im Modul verwendbar. Lokale Konstanten hingegen gelten nur in der Prozedur, in der sie definiert wurden. Wie schon bei den Variablen sollten Sie darauf achten, nicht allzu viele globale Konstanten zu verwenden, da sich dies merklich auf Ihren Speicher auswirkt. Nachfolgend ein paar typische Deklarationen mit Konstanten: Const strMappe = "Mappe1.xls" Const DateStart = #1/1/2005# Const strFehlermeldung1 = _ "Fehler beim Drucken aufgetreten!" Const sngMWST = 1.16 50 Die wichtigsten Systemkonstanten jetzt lerne ich Was kann hier noch verbessert werden? Was für die Variablen gilt, hat auch bei den Konstanten Konsequenzen. In den vorigen Beispielen ist noch nicht erklärt worden, welche Datentypen verwendet werden sollen. Zum aktuellen Zeitpunkt wird in allen vier Beispielen der Datentyp Variant eingesetzt. Es geht auch etwas genauer und Speicher sparender: Const strMappe as String = "Mappe1.xls" Const DateStart As Date = #1/1/2005# Const strFehlermeldung1 as String = _ "Fehler beim Drucken!" Const sngMWST as Single = 1.16 1.8 Die wichtigsten Systemkonstanten Neben den selbst zu definierenden Konstanten gibt es in VBA eine ganze Reihe vorgefertigter Systemkonstanten, die Sie für Ihre Programmierung einsetzen können. Alle folgenden Prozeduren finden Sie auf der CD-ROM zum Buch im Ordner KAP01 unter dem Namen Start.xls. Öffnen Sie dazu im Visual Basic-Editor das Modul MDLSYSKONST. 1.8.1 / Datums-Format-Konstanten Für das Anzeigen von Datums- und Zeitangaben stehen fertige Systemkonstanten zur Verfügung, die eine Formatierung des Datums bzw. des Zeitwerts nach Bedarf übernehmen. Diese Datums-/Zeitkonstanten können im Zusammenspiel mit der Funktion FormatDatTime verwendet werden. Die Funktion FormatDateTime hat folgende Syntax: FormatDateTime(Datum[,BenanntesFormat]) Im Argument Datum übergeben Sie der Funktion einen Datumswert. Im Argument BenanntesFormat wird eine der folgenden Datums-/ Zeitkonstanten ausgewählt. 51 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Tabelle 1.6: Konstante Die Datumskonstanten vbGeneralDate vbLongDate Wert Beschreibung 0 Zeigt ein Datum und/oder eine Uhrzeit an. Wenn es ein Datum gibt, wird es in Kurzform angezeigt. Wenn es eine Uhrzeit gibt, wird sie im langen Format angezeigt. Falls vorhanden werden beide Teile angezeigt. 1 Zeigt ein Datum im langen Datumsformat an, gemäß der festgelegten Ländereinstellung des Computers. vbShortDate 2 Zeigt ein Datum im kurzen Datumsformat an, gemäß der festgelegten Ländereinstellung des Computers. vbLongTime 3 Zeigt eine Uhrzeit in dem Zeitformat der festgelegten Ländereinstellung des Computers an. vbShortTime 4 Zeigt eine Uhrzeit im 24-Stundenformat (hh:mm) an. Im Beispiel in Listing 1.10 wird das heutige Datum auf verschiedene Weise im Direktfenster angezeigt. Listing 1.10: Sub DatumsformateBearbeiten() DatAngabe = Now Das aktuelle Debug.Print FormatDateTime(DatAngabe, vbGeneralDate) Tagesdatum Debug.Print FormatDateTime(DatAngabe, vbLongDate) unterschiedDebug.Print FormatDateTime(DatAngabe, vbShortDate) lich darstellen Debug.Print FormatDateTime(DatAngabe, vbLongTime) Debug.Print FormatDateTime(DatAngabe, vbShortTime) End Sub Starten Sie die Prozedur aus Listing 1.10 und blenden in der Entwicklungsumgebung das Direktfenster ein. Bild 1.21: Datums- und Zeitangaben ausgeben Über weitere Datums-/Zeitkonstanten kann das Quartal bzw. der genaue Wochentag abgefragt werden. 52 Die wichtigsten Systemkonstanten jetzt lerne ich Über die Funktion DatePart kann ein bestimmter Teil des Datums extrahiert werden, indem Sie auf die Konstanten dieser Funktion zurückgreifen. Die Syntax dieser Funktion lautet: DatePart(interval, date[,firstdayofweek[, firstweekofyear]]) Im Argument Interval muss genau angegeben werden, welcher Teil des Datums extrahiert werden soll. Die einzelnen Möglichkeiten sehen Sie in der folgenden Tabelle 1.7. Einstellung Beschreibung yyyy Jahr q Quartal m Monat y Tag des Jahres d Tag w Wochentag ww Woche h Stunde n Minute s Sekunde Tabelle 1.7: Die IntervalKonstanten der Funktion DatePart Im Argument firstdayofweek wird der erste Tag der Woche angegeben. Denken Sie beispielsweise daran, dass der jüdische Kalender mit dem Sonntag als erstem Tag der Woche beginnt. Für unseren europäischen Bereich gilt der Wert 2 bzw. die Konstante vbMonday. Wenn dieses etwas variabler gehalten werden soll, dann setzen Sie die Konstante vbUseSystem ein. Damit wird die Einstellung des ersten Tags der Woche direkt aus den Einstellungen Ihrer Windows-Systemsteuerung herausgelesen. Nachfolgend finden Sie die einzelnen Belegungen der Konstanten in Tabelle 1.8. Konstante Wert Beschreibung vbUseSystem 0 Die NLS API-Einstellung wird verwendet. vbSunday 1 Sonntag (Voreinstellung) vbMonday 2 Montag vbTuesday 3 Dienstag vbWednesday 4 Mittwoch Tabelle 1.8: Die FirstDayOfWeekKonstanten der Funktion DatePart 53 jetzt lerne ich Tabelle 1.8: Die FirstDayOfWeekKonstanten der Funktion DatePart (Forts.) 1 Erste Schritte mit Excel-VBA Konstante Wert Beschreibung vbThursday 5 Donnerstag vbFriday 6 Freitag vbSaturday 7 Samstag Im letzten Argument firstweekofyear wird die erste Woche eines Jahres festgelegt. Danach richtet sich auch jeweils die Nummerierung der Kalenderwoche. Dabei können Sie folgende Einstellungen vornehmen: Tabelle 1.9: Konstante Die FirstWeekOfYear-Kon- vbUseSystem stanten der Funktion vbFirstJan1 DatePart vbFirstFourDays vbFirstFullWeek Wert Beschreibung 0 Die NLS API-Einstellung aus der Systemsteuerung von Windows wird verwendet. 1 Anfang in der Woche mit dem 1. Januar (Voreinstellung). 2 Anfang in der ersten Woche, die mindestens vier Tage im neuen Jahr enthält. 3 Anfang in der ersten vollen Woche des Jahres. Im folgenden Beispiel in Listing 1.11 wird zu einem gegebenen Tagesdatum das dazugehörige Quartal ausgegeben. Listing 1.11: Function Quartal(DatAngabe) Aus dem Quartal = DatePart("q", DatAngabe) Datum wird das dazugehörige Quartal End Function ermittelt Sub DatAbfrage() MsgBox " Das angegebene Datum liegt im " & Quartal("02.05.2005") & _ " .Quartal!" End Sub Eine weitere Funktion ist die Funktion WeekDayName. Mithilfe dieser Funktion können Sie auf ähnliche Konstanten wie gerade beschrieben zurückgreifen. Die Syntax dieser Funktion lautet: WeekDayName(Wochentag, abkürzen, ErsterWochentag) 54 Die wichtigsten Systemkonstanten jetzt lerne ich Das Argument Wochentag gibt eine numerische Bezeichnung des Wochentages wieder, die von der Wahl des Arguments ErsterWochentag abhängig ist. Das Argument abkürzen legt fest, ob der Name des Tages abgekürzt werden soll oder nicht. Setzen Sie dieses Argument auf den Wert True, wenn der ermittelte Wochentag abgekürzt werden soll. Setzen Sie hingegen dieses Argument auf den Wert False, um den Namen des ermittelten Tages auszuschreiben. Im Argument ErsterWochentag geben Sie den ersten Tag der Woche an, den Sie in Tabelle 1.8 ermitteln können. Im folgenden Beispiel in Listing 1.12 wird anhand eines Datums der dazugehörige Wochentag ausgegeben. Function Wochentag(DatAngabe) Listing 1.12: Wochentag = WeekdayName _ (Weekday(DatAngabe, vbUseSystemDayOfWeek), False) End Function Sub WochenTagAbfrage() MsgBox " Der angegebene Wochentag ist ein " & _ Wochentag("02.05.2005") End Sub 1.8.2 Dir-Konstanten Sicher kennen Sie noch den alten DOS-Befehl Dir, über den Sie sich damals (aber auch noch heute) den Inhalt Ihrer Festplatte anzeigen lassen konnten. Mit diesem Befehl können bestimmte Konstanten eingesetzt werden, die in der nachfolgenden Tabelle 1.10 beschrieben sind. Konstante Wert Beschreibung vbNormal 0 (Voreinstellung) Dateien ohne Attribute. vbReadOnly 1 Schreibgeschützte Dateien, zusätzlich zu Dateien ohne Attribute. Tabelle 1.10: Die Konstanten der Funktion Dir 55 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Tabelle 1.10: Konstante Die Konstanten der Funk- vbHidden tion Dir (Forts.) Wert Beschreibung 2 Versteckte Dateien, zusätzlich zu Dateien ohne Attribute. vbSystem 4 Systemdatei, zusätzlich zu Dateien ohne Attribute. Beim Macintosh nicht verfügbar. vbVolume 8 Datenträgerbezeichnung. Falls andere Attribute angegeben wurden, wird vbVolume ignoriert. Beim Macintosh nicht verfügbar. vbDirectory 16 Verzeichnis oder Ordner, zusätzlich zu Dateien ohne Attribute. Im folgenden Beispiel soll mithilfe der Funktion GetAttr und den DirKonstanten überprüft werden, ob eine bestimmte Datenbank in einem Verzeichnis existiert. Schreiben Sie dazu eine Funktion und eine aufzurufende Prozedur, gemäß dem folgenden Listing: Function DB_Ver(ByVal Pfad As String) As Boolean On Error Resume Next DB_Ver = (GetAttr(Pfad) And vbDirectory) = 0 End Function Sub DatDa() b = DB_Ver("C:\Mappe1.xls") If b = False Then MsgBox "Mappe konnte nicht gefunden werden!" Else MsgBox "Mappe wurde im angegebenen Pfad gefunden!" End If End Sub Übergeben Sie der Funktion DB_Ver den kompletten Pfad- und Dateinamen der gesuchten Mappe. Mit dem Schlüsselwort ByVal wird festgelegt, dass diese Variable als Wert übertragen wird. Das bedeutet, dass der aktuelle Wert der Variablen nicht von der Prozedur verändert werden kann, an die er übergeben wird. Über die Funktion GetAttr geben Sie einen Wert vom Typ Integer zurück, der die Attribute einer Datei, eines Verzeichnisses oder eines Ordners darstellt. 56 Die wichtigsten Systemkonstanten 1.8.3 jetzt lerne ich File Input-/Output-Konstanten Mithilfe dieser Konstanten kann der Zugriff auf eine Datei festgelegt werden. Zum Beispiel können Sie über das Leserecht eine Datei zwar öffnen, haben aber keine Chance diese Datei zu verändern. Eine weitere Möglichkeit ist es, eine Datei zu öffnen und dafür zu sorgen, dass diese nach einer Anpassung neu angelegt wird, sofern diese schon existiert. Die dritte Möglichkeit ist, in eine Datei hineinzuschreiben und dabei die bisherigen Eingaben beizubehalten, also den neuen Text einfach unten anzuhängen. Diese File Output-Konstanten werden bevorzugt in der Verarbeitung von Textdateien angewendet. Entnehmen Sie die einzelnen Möglichkeiten des Dateizugriffs aus der folgenden Tabelle 1.11. Konstante Wert Beschreibung ForReading 1 Öffnet eine Datei, die nur gelesen werden kann. Sie können nicht in diese Datei schreiben. ForWriting 2 Öffnet eine Datei zum Schreiben. Wenn es eine Datei mit dem gleichen Namen gibt, wird der frühere Inhalt überschrieben. ForAppending 8 Tabelle 1.11: Die Konstanten für den Dateizugriff bei Textdateien Öffnet eine Datei und schreibt an das Ende dieser Datei. Bei der nächsten Aufgabe greifen Sie auf den Windows Scripting Host von Microsoft zu. Um dafür den Zugriff auf die einzelnen Befehle zu erhalten, gehen Sie wie folgt vor: 1. Wechseln Sie in die Entwicklungsumgebung von Excel. 2. Wählen Sie aus dem Menü EXTRAS den Befehl VERWEISE. 3. Aktivieren Sie im Listenfeld VERFÜGBARE VERWEISE die Bibliothek MICROSOFT SCRIPTING RUNTIME. 4. Bestätigen Sie Ihre Einstellung mit OK. 5. Legen Sie im nächsten Schritt eine Textdatei an, geben einen Text ein und speichern diese Textdatei unter dem Namen Artikel.txt im Verzeichnis C:\Temp\. Erfassen Sie danach das folgende Makro. 57 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Listing 1.13: Function TextDat_Lesen(strFileIn As String) As Long Eine Textdatei zeilenweise Dim fso As Scripting.FileSystemObject einlesen Dim Puffer As Scripting.TextStream Dim strText As String Dim intZ As Long Set fso = New Scripting.FileSystemObject Set Puffer = _ fso.OpenTextFile(strFileIn, ForReading, False) Do While Puffer.AtEndOfStream <> True strText = Puffer.ReadLine intz = intz + 1 Debug.Print strText Loop Puffer.Close Set Puffer = Nothing Set fso = Nothing TextDat_Lesen = intz End Function Sub TextdateiLesen() TextDat_Lesen ("C:\Temp\Artikel.txt") End Sub Zu Beginn wird ein FileSystemObject erstellt. Danach wird die angegebene Textdatei in einen Datenpuffer eingelesen, unter Verwendung der Methode OpenTextFile, der Sie die Konstante ForReading übergeben. Die Eigenschaft AtEndOfStream liefert den Wert True, wenn Sie den letzten Satz des Datenpuffers gelesen haben. Und genau so bauen Sie Ihre Schleife auf, die so lange abgearbeitet wird, bis die letzte Zeile verarbeitet wurde. Mithilfe der Methode ReadLine wird der Datenpuffer zeilenweise ausgelesen und der String-Variable strText übergeben, die Sie dann auch im Direktbereich von Excel über die Anweisung Debug.Print ausgeben. Schließen Sie danach die geöffnete Textdatei über die Methode Close und geben den durch die Objekte reservierten Arbeitsspeicher über die Anweisung Set wieder frei, indem das Schlüsselwort die Zuweisung Nothing erhält. 58 Die wichtigsten Systemkonstanten jetzt lerne ich Bild 1.22: Eine Textdatei wurde in das Direktfenster der Entwicklungsumgebung gelesen 1.8.4 Die Shell-Konstanten Mithilfe der Funktion Shell kann jedes ausführbare Programm aufgerufen werden. Über die Shell-Konstanten legen Sie dabei fest, ob das Programm im Hintergrund bleiben bzw. minimiert oder maximiert angezeigt werden soll. Die Funktion Shell hat folgende Syntax: Shell(pathname[,windowstyle]) Im Argument pathname geben Sie den Pfad sowie den Dateinamen der ausführbaren Datei an, die gestartet werden soll. Das Argument WindowsStyle legt den Stil des Fensters fest, in dem das Programm ausgeführt werden soll. Dabei stehen Ihnen folgende Konstanten aus Tabelle 1.12 zur Verfügung. Konstante Wert Beschreibung vbHide 0 Das Fenster ist ausgeblendet, und das ausgeblendete Fenster erhält den Fokus. vbNormalFocus 1 Das Fenster hat den Fokus, und die ursprüngliche Größe und Position wird wiederhergestellt. vbMinimizedFocus 2 Das Fenster wird als Symbol mit Fokus angezeigt. vbMaximizedFocus 3 Das Fenster wird maximiert mit Fokus angezeigt. vbNormalNoFocus 4 Die zuletzt verwendete Größe und Position des Fensters wird wiederhergestellt. Das momentan aktive Fenster bleibt aktiv. vbMinimizedNoFocus 6 Das Fenster wird als Symbol angezeigt. Das momentan aktive Fenster bleibt aktiv. Tabelle 1.12: Die Konstanten der Funktion Shell 59 jetzt lerne ich 1 Erste Schritte mit Excel-VBA Wenden Sie jetzt die Funktion Shell und deren Konstanten in einem Beispiel an. So wird im nächsten Listing der Internet Explorer von Microsoft gestartet und eine bestimmte Webseite automatisch geladen. Listing 1.14: Sub InternetExplorerStarten() Den InternetExplorer Dim boolWebSeite As Boolean aufrufen Dim strWeb As String strWeb = "http://held-office.de" boolWebSeite = _ Shell("C:\Programme\Internet Explorer\IExplore.exe " & strWeb, 1) End Sub 60 jetzt lerne ich KAPITEL 2 Die Sprachelemente von Excel-VBA Das Wesentliche einer Programmiersprache sind ihre Sprachelemente. In diesem Kapitel erfahren Sie, wie mithilfe von Verzweigungen, Schleifen und anderen Anweisungen Programme flexibel gestaltet werden können. Solche Sprachelemente lassen sich leider nicht alle mit dem Makrorekorder aufzeichnen und müssen von selbst erstellt werden. Der richtige Einsatz der Sprachelemente macht letztendlich die Kunst der Programmierung aus. Alle hier vorgestellten Makros finden Sie auf der mitgelieferten CD-ROM im Verzeichnis Kap02 unter dem Namen Sprachelemente.xls. 2.1 1 Die With-Anweisung Die Anweisung With wird eingesetzt, um sich viel Schreibarbeit zu sparen und mehr Übersichtlichkeit in den Quellcode zu bringen. Dabei wird das Objekt, an dem mehrere Befehle angewendet werden sollen, einmalig definiert, ohne dieses Objekt für jeden Befehl zu wiederholen. 61 2 Die Sprachelemente von Excel-VBA jetzt lerne ich Die Syntax dieser Anweisung lautet: With Objekt [Anweisungen] End With Sehen Sie in Tabelle 2.1 die Syntax der Anweisung. Tabelle 2.1: Die Syntax der Anweisung With Teil Beschreibung Objekt Geben Sie den Namen eines Objekts an, den Sie ansprechen möchten. Anweisungen Erfassen Sie eine oder mehrere Anweisungen, die für das Objekt ausgeführt werden sollen. 2.1.1 Die aktive Zelle bearbeiten Sehen Sie sich dazu nun das folgende Beispiel in Listing 2.1 an. Dort wird in die aktive Zelle das aktuelle Systemdatum eingefügt und anschließend die Zellenschriftfarbe sowie der Rahmen definiert. Listing 2.1: Sub MehrSchreibarbeit() Bei diesem ActiveCell.Value = Date Beispiel ist ActiveCell.Font.ColorIndex = 4 ein Begriff ActiveCell.BorderAround LineStyle:=xlThin, ColorIndex:=3 redundant End Sub Beim Makro in Listing 2.1 wird die Eigenschaft ActiveCell gleich dreimal in Folge verwendet. Da immer dieselbe Zelle, nämlich die aktive Zelle gemeint ist, kann dieses Makro wie in Listing 2.2 gezeigt, über die With-Anweisung reduziert werden. Listing 2.2: Sub WenigerSchreibarbeit() Der Begriff With ActiveCell wird einmal .Value = Date angegeben .Font.ColorIndex = 3 und danach .BorderAround LineStyle:=xlThin, ColorIndex:=5 durch einen End With Punkt ersetzt End Sub 62 Die With-Anweisung jetzt lerne ich Zu Beginn des Makros in Listing 2.2 wird angegeben, welcher Begriff mehrfach verwendet wird. Danach folgt immer dann, wenn der Begriff eigentlich geschrieben werden müsste ein Punkt als »Ersatzzeichen«. Während des Makroverlaufs wird dann dieser Punkt intern quasi durch den Begriff ersetzt, der vorher bei With angegeben wurde. Vergessen Sie nicht, die Anweisung über End With wieder abzuschließen, wenn die Verkürzung nicht mehr benötigt wird. Noch ein paar Erläuterungen zu den beiden vorherigen Makros: Über die Eigenschaft Value wird einer Zelle ein Wert zugewiesen. In dem Beispiel wurde das aktuelle Systemdatum in die aktive Zelle eingefügt, indem die Funktion Date angesprochen wurde. Um die Schriftfarbe der Zelle anzupassen, greifen Sie das Objekt Font auf, das wiederum alle möglichen Schriftfarben beinhaltet. Über die Eigenschaft ColorIndex besteht die Möglichkeit 56 Standardfarben für die Schriftfarbe einer Zelle auszuwählen. Jede Farbe hat einen eindeutigen Farbindex. Dabei wird mit dem ColorIndex 3 die Farbe ROT identifiziert. Wie beispielsweise die Farbbelegung der Farben von 1-56 ausgelesen werden kann, erfahren Sie später in diesem Kapitel. Die Methode BorderAround sorgt dafür, dass die aktive Zelle mit einem Rahmen umgeben wird. Dabei werden in diesem Beispiel die beiden Argumente LineStyle und ColorIndex verwendet, um zum einen die Linienart und zum anderen die Linienfarbe festzulegen. Bild 2.1: Die aktive Zelle wird erfasst und formatiert 63 2 Die Sprachelemente von Excel-VBA jetzt lerne ich 2.2 Die IF-Anweisung Die Funktion der IF-Anweisung kennen Sie sicherlich bereits von der Standard-Arbeitsoberfläche von Excel. Dort wird die Tabellenfunktion WENN() eingesetzt, um entweder die eine oder die andere Aktion in Abhängigkeit von zum Beispiel einem Zellenwert einzuleiten. Da VBA nur in der englischen Sprache ausgeliefert wird, folgt hier anstelle von WENN eben die Anweisung IF. Wenn Sie also bereits mit Wenn-Tabellenfunktionen gearbeitet haben, dann dürften Ihnen auch die beiden nachfolgenden Syntaxen vertraut vorkommen. If Bedingung Then [Anweisung] [Else elseAnweisung] Alternativ können Sie die Block-Syntax verwenden: If Bedingung Then [Anweisung] [Anweisung] [Else] [elseAnweisung] [elseAnweisung] End If Unter dem Argument Bedingung geben Sie die Bedingung an, die erfüllt sein muss. Unter dem Argument Anweisung stehen die Anweisungen direkt im Anschluss an Then, die ausgeführt werden, wenn die Bedingung zutrifft. Im Argument elseAnweisung können eine oder auch mehrere Anweisungen durchgeführt werden, wenn die Bedingung nicht erfüllt wird. 0 1 64 Aufgrund der besseren Übersichtlichkeit sowie der später besseren Erweiterbarkeit, empfehle ich Ihnen, die Block-Syntax standardmäßig zu verwenden. Dabei muss die If-Anweisung am Ende durch End If abgeschlossen werden. Bei der ersten Syntaxform brauchen Sie keinen Abschluss zu machen, sofern der Befehl in eine Zeile passt, d. h. sobald Sie einen Zeilenumbruch ohne Zeilenfortsetzungszeichen eingeben, wird das End If dringend benötigt, da der VBA-Editor sonst einen Fehler moniert. Die IF-Anweisung 2.2.1 jetzt lerne ich Datentyp einer Zelle prüfen Im folgenden Beispiel in Listing 2.3 soll der Inhalt der momentan aktiven Zelle geprüft werden. Im ersten Schritt wird getestet, ob überhaupt etwas in der Zelle steht. Sub ZelleLeer() If ActiveCell.Value = "" Then MsgBox "Zelle ist leer", vbInformation Else MsgBox "Zelle ist gefüllt!", vbInformation End If Listing 2.3: Es wird geprüft, ob die aktive Zelle leer ist End Sub Zuerst wird überprüft, ob die aktive Zelle gefüllt ist. Alternativ zu der im Listing 2.3 aufgeführten Abfrage kann ebenso auch die Abfrage … If IsEmpty(ActiveCell.Value) Then … verwendet werden. Beide Bedingungen liefern das gewünschte Ergebnis. Für den Fall, dass die Zelle einen Inhalt enthält, wird der Then-Zweig ausgeführt, andernfalls der Else-Zweig. Im nächsten Schritt wird überprüft, ob der Zelleninhalt entweder numerisch oder alphanumerisch ist. Dazu wird die Verzweigung geschachtelt. Dies könnte dann wie in Listing 2.4 aussehen. Sub DatenTypInZelleFeststellen() If IsEmpty(ActiveCell.Value) Then MsgBox "Zelle ist leer", vbInformation Else If IsNumeric(ActiveCell) Then MsgBox "Zelle enthält eine Zahl", vbInformation Else MsgBox "Zelle enthält einen Text", vbInformation End If End If Listing 2.4: Der Datentyp einer Zelle wird überprüft End Sub In der ersten Verzweigung wird überprüft, ob die Zelle leer ist. Wenn ja, folgt eine entsprechende Meldung auf dem Bildschirm. Sofern nun die Zelle gefüllt ist, wird eine weitere Verzweigung eingebaut, um zu prüfen, ob es sich um einen numerischen oder alphanumerischen Zellenwert handelt. Mithilfe der Funktion IsNumeric wird ab- 65 2 Die Sprachelemente von Excel-VBA jetzt lerne ich gefragt, ob es sich um einen numerischen Wert handelt. Zum Ende der beiden Abfragen darf nicht vergessen werden die beiden Verzweigungen mit End If abzuschließen. Sie haben bereits die beiden Prüffunktionen IsEmpty und IsNumeric kennen gelernt, die häufig eingesetzt werden, um Eingaben bzw. Zelleninhalte zu überprüfen. In der folgenden Tabelle sind die gängigsten Prüffunktionen in VBA dargestellt. Tabelle 2.2: Funktion Die wichtigsten Prüffunkti- IsEmpty onen von VBA Beschreibung Gibt einen Wert vom Typ Boolean zurück, der angibt, ob eine Variable initialisiert wurde. IsArray Gibt einen Wert vom Typ Boolean zurück, der angibt, ob eine Variable ein Datenfeld ist. IsDate Gibt einen Wert vom Typ Boolean zurück, der angibt, ob ein Ausdruck in ein Datum umgewandelt werden kann. IsError Gibt einen Wert vom Typ Boolean zurück, der angibt, ob ein Ausdruck ein Fehlerwert ist. IsNull Gibt einen Wert vom Typ Boolean zurück, der angibt, ob ein Ausdruck keine gültigen Daten (Null) enthält. IsNumeric Gibt einen Wert vom Typ Boolean zurück, der angibt, ob ein Ausdruck als Zahl ausgewertet werden kann. IsObject Gibt einen Wert vom Typ Boolean zurück, der angibt, ob ein Bezeichner eine Objektvariable darstellt. 2.2.2 Formelcheck durchführen Bei den in der Tabelle 2.2 aufgeführten Funktionen könnten Sie eine weitere vermissen, die zum Beispiel prüft, ob eine Formel vorhanden ist. Interessanterweise gibt es leider die Funktion mit der Bezeichnung IsFormula nicht. Um festzustellen, ob in einer Zelle eine Formel enthalten ist, verwenden wir die Funktion HasFormula wie in Listing 2.5 gezeigt. Listing 2.5: Sub FormelCheck() Prüfung durchführen, If ActiveCell.HasFormula = True Then ob die aktive MsgBox "Die Zelle " & ActiveCell.Address & " enthält eine Formel!" Else Zelle eine Formel beinhaltet MsgBox "Die Zelle " & ActiveCell.Address & " enthält keine Formel!" End If End Sub 66 Die Select Case-Anweisung jetzt lerne ich Die erste Zeile im Makro aus Listing 2.5 kann noch wie folgt verkürzt werden: If ActiveCell.HasFormula Then Beide Varianten arbeiten einwandfrei. Mithilfe der Eigenschaft Address wird die exakte Zellenadresse der aktiven Zelle ausgelesen. Beachten Sie die Schreibweise bei der Funktion MsgBox. Immer wenn Texte und das Ergebnis einer Funktion (hier Activecell.Address) miteinander verknüpft werden, wird der so genannte Verkettungsoperator & eingesetzt. 2.3 Die Select Case-Anweisung Sofern mehrere Verzweigungen ineinander verschachtelt werden bzw. mehrere Abfragen hintereinander durchgeführt werden sollen, gibt es dafür eine bessere und übersichtlichere Lösung. Setzen Sie für solche Aufgaben die Anweisung Select Case ein. Die Syntax für Select Case lautet: Select Case Ausdruck [Case Ausdrucksliste-n [Anweisungen-n]] ... [Case Else [elseAnw]] End Select Unter dem Argument Ausdruck wird ein beliebiger numerischer Ausdruck oder Zeichenfolgenausdruck erfasst, der ausgewertet werden soll. Im Argument Ausdrucksliste-n werden die Abfrageoptionen näher spezifiziert. Dabei werden auch Vergleichsoperatoren wie To, Is oder Like eingesetzt. Unter dem Argument Anweisungen-n können eine oder mehrere Anweisungen angegeben werden, die ausgeführt werden sollen, wenn der abgefragte Ausdruck mit irgendeinem Element in Ausdruckslisten übereinstimmt. Das Argument elseAnw ist optional einsetzbar. Insbesondere dann, wenn der abgefragte Ausdruck mit keinem Element im Case-Abschnitt übereinstimmen sollte. Lernen Sie nun ganz konkret ein paar Beispiele kennen, wie Sie diese Anweisung in der Praxis einsetzen können. 67 2 Die Sprachelemente von Excel-VBA jetzt lerne ich 2.3.1 Excel-Version feststellen In der folgenden Aufgabe für dieses Sprachelement soll ermittelt werden, mit welcher Excel-Version Sie arbeiten. Für diese Aufgabe wird die Eigenschaft Version ausgewertet, die über einen numerischen Wert die aktuelle Excel-Installation identifiziert. Listing 2.6: Sub ExcelVersionFeststellen() Die Excel-Version ermitteln MsgBox Application.Version Select Case Left(Application.Version, 1) Case "5" MsgBox "Excel 5" Case "7" MsgBox "Excel 7/95" Case "8" MsgBox "Excel 8/97" Case "9" MsgBox "Excel 2000" Case "1" If Left(Application.Version, 2) = 10 Then MsgBox "Excel 2002" Else MsgBox "Excel 2003" End If Case Else MsgBox "Unbekannte Version von Excel" End Select End Sub Über die Funktion Left wird die erste Ziffer der Versionsnummer ausgewertet, die über die Eigenschaft Version abgefragt wurde. Innerhalb der Select Case-Anweisung wird nun die Versionsnummer überprüft. Trifft eine Bedingung zu, wird die entsprechende Meldung am Bildschirm ausgegeben, die angibt um welche Excel-Version es sich handelt. Da die beiden letzten aktuellen Excel-Versionen beide die Zahl 1 (Excel 2000 mit Versionsnummer 10 und Excel 2003 mit der Versionsnummer 11) enthalten, wird innerhalb der 68 Die Select Case-Anweisung jetzt lerne ich Case-Anweisung noch ein If-Abfrage eingebaut, um den Unterschied der Versionen anhand der Versionsnummer festzustellen. Bild 2.2: Die installierte Version wird ermittelt 2.3.2 Zahlenwerte prüfen Im nächsten Beispiel werden Eingaben geprüft. Dabei soll ermittelt werden, in welchem Wertebereich die Eingabe vorgenommen wurde. Sehen Sie sich dazu das folgende Makro in Listing 2.7 an. Sub ZahlAuswerten() Dim intEingabe As Integer intEingabe = InputBox("Geben Sie einen Wert ein!") Listing 2.7: Eingegebene Werte überprüfen Select Case intEingabe Case 1 To 5 MsgBox "Wert liegt zwischen 1 und 5" Case 6, 7, 8 MsgBox "Wert ist entweder 6, 7 oder 8" Case 9 To 15 MsgBox "Wert liegt zwischen 9 und 15" Case 16 To 50 MsgBox "Wert liegt zwischen 16 und 50" Case Is > 50 MsgBox "Wert liegt über 50" Case Else MsgBox "Es wurde kein gültiger Wert eingegeben!" End Select 69 2 Die Sprachelemente von Excel-VBA jetzt lerne ich Wenden Sie die Select Case-Anweisung an, um die eingegebenen Werte zu überprüfen. In der ersten Abfrage wird kontrolliert, ob der eingegebene Wert zwischen 1 und 5 liegt. Für die Prüfung eines Wertebereichs kann der Vergleichsoperator To eingesetzt werden. In der zweiten Abfrage werden einzelne Zahlenwerte durch Komma getrennt eingegeben. Wurde kein gültiger Zahlenwert eingegeben, kommt dann die Anweisung Case Else zum Tragen. Dieser Zweig würde beispielsweise dann angesteuert, wenn die eingegebene Zahl entweder 0 ist oder wenn es sich um eine negative Zahl handelt. 2 Die Reihenfolge, in der die einzelnen Case-Zweige angeordnet werden ist Ihnen frei überlassen. Dennoch macht es Sinn sofern beispielsweise verstärkt Werte größer als 50 eingegeben werden, dann kann der letzte Zweig aus Listing 2.7 auch als erste Abfrage gesetzt werden. Dadurch wird die Geschwindigkeit in der Abarbeitung der Abfragen deutlich erhöht, da Zweig für Zweig von oben nach unten abgearbeitet wird. Wird eine Entsprechung gefunden, dann wird sofort direkt ans Ende der Select Case-Anweisung gesprungen. Die folgende Tabelle enthält eine Liste der Vergleichsoperatoren und die Bedingungen, unter denen das Ergebnis True, False oder 0 wird: Tabelle 2.3: Vergleichsoperator Die Vergleichs- < operatoren <= in Excel Erklärung kleiner als kleiner oder gleich > größer als >= größer oder gleich = gleich <> ungleich 2.4 Schleifen programmieren Schleifen werden in Excel dazu verwendet, um Abläufe mehrmals hintereinander durchzuführen. Die Schleifen werden so lange durchlaufen, bis eine oder mehrere Bedingungen zutreffen, die dann einen Abbruch der Schleife bewirken. Je nach verwendeter Schleife 70 Schleifen programmieren jetzt lerne ich findet die Abbruchprüfung am Anfang bzw. am Ende der Schleife statt. Das war nun zugegeben etwas abstrakt: Stellen Sie sich vor, Sie müssten ein 600-Liter-Aquarium mit Wasser füllen. Ihnen steht dafür ein 10-Liter-Eimer zur Verfügung. Nun muss Eimer für Eimer mit Wasser gefüllt werden, um diese dann ins Aquarium zu kippen. Diesen Vorgang müssen Sie genau 60-mal wiederholen, um das Aquarium zu füllen. Zusätzlich soll noch dafür gesorgt werden, dass die Wassertemperatur konstant bleibt. Hier muss also eine entsprechende Prüfung erfolgen. Eine weitere Prüfung könnte sein, festzustellen, ob das Aquarium auch dicht ist. Diese Prüfung könnte bei jedem neuen Eimer, den Sie ins Aquarium schütten wiederholt werden. Dies ist ein typisches Beispiel für eine Schleife, die so lange durchlaufen wird, bis die Endbedingung eintrifft. Die Geschwindigkeit bei Excel-Schleifen ist natürlich um ein Tausendfaches schneller als bei dem Beispiel die Wassereimer zu füllen. Lernen Sie auf den nächsten Seiten die zur Verfügung stehenden Schleifen und einfache Beispiele für den Einsatz von Schleifen kennen. 2.4.1 Die For...Next-Schleifen Sie können die Schleife For...Next verwenden, um einen Block von Anweisungen in einer unbestimmten Anzahl von Wiederholungen auszuführen. For...Next-Schleifen verwenden eine Zählervariable, deren Wert mit jedem Schleifendurchlauf erhöht oder verringert wird. Es muss daher nicht daran gedacht werden, den Zähler selbst hoch- oder runterzusetzen. Die Syntax dieser Schleife lautet: For Zähler = Anfang To Ende [Step Schritt] [Anweisungen] [Exit For] [Anweisungen] Next [Zähler] Das Argument Zähler ist erforderlich und besteht aus einer numerischen Variablen, die als Schleifenzähler dient. Das Argument Anfang repräsentiert den Startwert des Zählers. 71 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Mit dem Argument Ende wird der Endwert des Zählers festgelegt. Das Argument Schritt ist optional. Hier können Sie den Wert bestimmen, um den der Zähler bei jedem Schleifendurchlauf verändert wird. Falls kein Wert angegeben wird, ist die Voreinstellung 1. Unter Anweisungen stehen eine oder mehrere Anweisungen zwischen For und Next, die so oft wie angegeben ausgeführt werden. Innerhalb einer Schleife kann eine beliebige Anzahl von Exit ForAnweisungen gesetzt werden, die eine alternative Möglichkeit darstellen die Schleife vorzeitig zu verlassen. Üben Sie diese Art von Schleife anhand der nächsten Aufgaben. Verfügbare Farben für Zellenhintergrund auslesen Im folgenden Beispiel wird eine neue Tabelle eingefügt. In dieser neuen Tabelle werden die verfügbaren Farben, die Excel für den Hintergrund einer Zelle zur Verfügung stellt, dargestellt. Listing 2.8: Sub FarbenErmitteln() Farben Dim intz As Integer auslesen Sheets.Add For intz = 1 To 56 With ActiveSheet .Cells(intz, 1).Value = intz .Cells(intz, 2).Interior.ColorIndex = intz End With Next intz End Sub Zunächst wird eine Zählvariable vom Typ Integer deklariert. Über die Methode Add wird nun eine neue, noch leere Tabelle eingefügt, die dadurch automatisch die aktive Tabelle ist. Danach setzen Sie eine Schleife auf, die genau 56 Mal durchlaufen wird, da es nur 56 Standardfarben für den Hintergrund einer Zelle gibt. Wir haben hier also eine vorher festgelegte Wiederholungszahl für die Schleife. Innerhalb der Schleife kann über die With-Anweisung ein wenig Schreibarbeit reduziert werden, da die Anweisungen für die aktive Tabelle gelten. 72 Schleifen programmieren jetzt lerne ich Über die Cells-Auflistung werden die Zellen gezielt angesteuert und von oben nach unten gefüllt. Diese Auflistung hat genau zwei Argumente. Das erste Argument gibt die Zeilennummer an, das zweite Argument enthält die Spaltennummer. In diesem Beispiel werden die Informationen zeilenweise in die Spalten A (=1) und B (=2) geschrieben. Die erste Spalte zeigt die eindeutige Farbnummer. Bei der Spalte B wird genau diese Farbnummer genutzt, um den Hintergrund der Zelle (Interior) über die Eigenschaft ColorIndex zu füllen. Wir haben im Beispiel in Listing 2.8 die Zählvariable doppelt verwendet. Zum einen wird dadurch die Zeilennummer verwaltet (von Zeile 1 bis Zeile 56), zum anderen werden die verfügbaren Farben (von 1 bis 56) den Zellen zugewiesen. 1 Bild 2.3: Alle 56 Standardfarben werden ausgelesen Zeilen abarbeiten Nach diesem Beispiel mit einem vorher bestimmten Ende (56 Durchläufe) soll nun eine Schleife programmiert werden, die eine dynamische Anzahl von Schleifendurchläufen aufweist. Im Makro in Listing 2.9 wird die TABELLE2 beginnend bei der ersten Zeile von oben nach unten abgearbeitet. Dabei wird der Wert jeder Zelle geprüft. In Abhängigkeit des Wertes wird dann der Hintergrund eingefärbt. Vergleichbar ist diese Lösung mit der bedingten Formatierung von Excel, bei der aber lediglich drei unterschiedliche Kriterien hinterlegt werden können. Bei der hier vorgestellten Lösung gilt diese Obergrenze nicht. 73 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Listing 2.9: Sub ZeilenAbarbeiten() Eine Tabelle Dim Zeile As Integer Zeile für Zeile Dim ZeileMax As Integer abarbeiten With Sheets("Tabelle2") ZeileMax = .Range("A65536").End(xlUp).Row For Zeile = 1 To ZeileMax Select Case .Cells(Zeile, 1).Value Case 0 To 3 .Cells(Zeile, 1).Interior.ColorIndex = 3 Case 4 To 7 .Cells(Zeile, 1).Interior.ColorIndex = 4 Case 8 To 12 .Cells(Zeile, 1).Interior.ColorIndex = 5 Case Is > 12 .Cells(Zeile, 1).Interior.ColorIndex = 6 Case Else .Cells(Zeile, 1).Interior.ColorIndex = xlColorIndexNone End Select Next Zeile End With End Sub Geben Sie zuerst über die Anweisung With an, dass die TABELLE2 verwendet wird. Danach wird die letzte verwendete Zelle in Spalte A ermittelt. Der Befehl .Range("A65536").End(xlUp).Row gibt die letzte verwendete Zelle als Nummer zurück und entspricht prinzipiell der Tastenkombination Ÿ+¤, die Sie in der Tabelle nutzen können, um zur letzten Zelle in Spalte A zu springen. Beginnend bei der ersten Zeile bis zur letzten Zeile, die in der Variablen ZeileMax gespeichert ist, wird nun die Schleife durchlaufen. Innerhalb der Schleife wenden Sie die Select Case-Anweisung an, um den Wert einer jeden Zelle zu prüfen. Die Farbbelegung können Sie dabei anhand der Abbildung 2.3 nachvollziehen. Sofern beispielsweise eine negative Zahl gefunden wurde, wird der Case Else-Zweig 74 Schleifen programmieren jetzt lerne ich angesteuert. In diesem Fall wird der Eigenschaft ColorIndex die Konstante xlColorIndexNone zugewiesen. Dies bewirkt, dass eine eventuell bereits angewendete Farbe in der jeweiligen Zelle entfernt wird. Bitte weisen Sie der Zelle nicht die Hintergrundfarbe WEIß zu, sondern verwenden eben diese Konstante, um die Zelle wieder zu »entfärben«. 1 Bild 2.4: Zellen je nach Wert einfärben Wenn Werte in der Tabelle geändert werden, dann müssen Sie das Makro aus Listing 2.9 erneut ausführen. Um dies zu erleichtern, kann eine Schaltfläche in der Tabelle integriert werden, über die das Programm gestartet wird. Verfahren Sie wie folgt: 1 1. Blenden Sie die Symbolleiste FORMULAR über den Menübefehl ANSICHT/SYMBOLLEISTEN/FORMULAR ein. 2. Klicken Sie auf das Symbol SCHALTFLÄCHE. 3. Ziehen Sie die Schaltfläche in der Tabelle in der gewünschten Größe auf. 4. Im Dialog MAKRO ZUWEISEN markieren Sie das Makro ZEILENABARBEITEN und bestätigen es mit OK. 5. Passen Sie die Beschriftung der Schaltfläche noch an und klicken danach auf eine beliebige Zelle, um die Schaltfläche »scharf« zu machen. 75 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Bild 2.5: Einer Schaltfläche ein Makro zuweisen 1 1 Lernen Sie im Kapitel 8 wie diese Aufgabe vollkommen automatisiert werden kann, sodass direkt bei einer Eingabe die Zellformatierung stattfindet. (Vergleichbar mit der bedingten Formatierung, nur besser!) Wollen Sie einer bereits eingefügten Schaltfläche nachträglich ein Makro zuweisen, dann klicken Sie die Schaltfläche mit der rechten Maustaste an und wählen den Befehl MAKRO ZUWEISEN aus dem Kontextmenü. Gültige Daten kennzeichnen Eine oft gebrauchte Lösung ist auch, einen Datenbestand zu durchforsten und gültige Datensätze zu kennzeichnen. Beim folgenden Beispiel wird die TABELLE4 Zeile für Zeile abgearbeitet. Dabei werden alle gültigen Zahlenwerte mit der Hintergrundfarbe ROT formatiert. 76 Schleifen programmieren Sub BestimmteZellenKennzeichnen() Dim Zeile As Integer Dim ZeileMax As Integer With Sheets("Tabelle4") ZeileMax = .Range("A65536").End(xlUp).Row jetzt lerne ich Listing 2.10: Alle alphanumerischen Zellen kennzeichnen For Zeile = 1 To ZeileMax If IsNumeric(.Cells(Zeile, 1).Value) = True And _ IsEmpty(.Cells(Zeile, 1).Value) = False Then .Cells(Zeile, 1).Interior.ColorIndex = 3 Else .Cells(Zeile, 1).Interior.ColorIndex = xlColorIndexNone End If Next Zeile End With End Sub Der Schleifenaufbau ist hier genau der gleiche wie beim vorherigen Beispiel in Listing 2.9. Innerhalb der Schleife wird überprüft, ob in der jeweiligen Zelle aus Spalte A ein numerischer Wert eingegeben wurde. Des Weiteren checken Sie mithilfe der Funktion IsEmpty, ob die jeweilige Zelle eventuell leer ist. Nur wenn numerische Eingaben vorgenommen wurden, wird die Zelle mit der Hintergrundfarbe ROT belegt. Bild 2.6: Es werden nur numerische Zellen gekennzeichnet 77 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Tabellennamen ermitteln Im nächsten Beispiel sollen die Namen der Tabellen ermittelt werden, die sich in der aktiven Arbeitsmappe befinden. Dies ist ein wichtiges Makro, um kennen zu lernen wie Sie die einzelnen Tabellen ansteuern. Das Makro für diese Aufgabe lautet: Listing 2.11: Sub TabellenErmitteln() Die Namen Dim intz As Integer der Tabellen Dim strTab As String auslesen For intz = 1 To ThisWorkbook.Worksheets.Count strTab = strTab & vbLf & Worksheets(intz).Name Next intz MsgBox "In dieser Mappe befinden sich folgende Tabellen: " & _ vbLf & strTab, vbInformation + vbOKOnly End Sub Die Schleife in Listing 2.11 ist dynamisch. Über die Anweisung ThisWorkbook.Worksheets.Count zählen Sie alle Tabellen, die sich in der Arbeitsmappe befinden. Diese Anzahl wird als Endkriterium in der Schleife eingesetzt. Innerhalb der Schleife werden die einzelnen Namen der Tabellen in einer String-Variablen gesammelt. Die Namen der einzelnen Tabellen werden über die Eigenschaft Name, des jeweiligen Tabellenblatts ermittelt. Über die Konstante vbLf kann jeweils eine neue Zeile definiert werden. Geben Sie am Ende den Inhalt der Variablen strTab am Bildschirm aus. Bild 2.7: Alle Tabellen der Arbeitsmappe werden gelistet 78 Schleifen programmieren 2.4.2 jetzt lerne ich For Each...Next-Schleifen Die Schleife For Each...Next wiederholt eine Gruppe von Anweisungen für jedes Element in einem Datenfeld oder einer Auflistung. Die Syntax dieser Schleife lautet: For Each Element In Gruppe [Anweisungen] [Exit For] [Anweisungen] Next [Element] Das Argument Element stellt die Variable zum Durchlauf durch die Elemente der Auflistung oder des Datenfeldes dar. Bei Auflistungen sind für Element nur eine Variable vom Typ Variant, eine allgemeine Objektvariable oder eine beliebige spezielle Objektvariable zulässig. Bei Datenfeldern ist für Element nur eine Variable vom Typ Variant zulässig. Das nächste Argument Gruppe steht für den Namen einer Objektauflistung oder eines Datenfeldes. Das letzte Argument Anweisungen ist optional und führt eine oder mehrere Anweisungen durch, die für jedes Element in der Gruppe ausgeführt werden sollen. Auch dieser wichtige Schleifentyp wird nun anhand praxisnaher Aufgaben geübt. Jede Zelle in der Markierung verarbeiten Beim ersten Beispiel für diese Art von Schleifen sollen alle Zellen, die momentan markiert sind, abgearbeitet werden. So schreibt das Makro in Listing 2.12 in alle Zellen der Markierung den Wert 0. Markieren Sie vor dem Start des Makros einige beliebige Zellen. Sub AlleZellenInMarkierungAbarbeiten() Dim Zelle As Range For Each Zelle In Selection Listing 2.12: Alle Zellen innerhalb einer Markierung werden gefüllt Zelle.Value = 0 Next Zelle End Sub 79 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Deklarieren Sie zu Beginn des Makros in Listing 2.12 eine Objektvariable vom Typ Range. Damit lassen sich alle Methoden und Eigenschaften für diese Variable einsetzen, die eben für Zellen (= Range) verfügbar sind. In einer anschließenden Schleife werden alle Zellen innerhalb der Markierung (= Selection) nacheinander abgearbeitet. Innerhalb der Schleife setzen Sie die Eigenschaft Value einer jeden Zelle auf den Wert 0. Preiserhöhung durchführen Im folgenden Beispiel werden alle Zellen in einem bestimmten Bereich um 10 % erhöht. Starten Sie dazu das Makro in Listing 2.13. Listing 2.13: Sub PreisAufschlag() Einen Preis- Dim Zelle As Range aufschlag Dim Bereich As Range durchführen Set Bereich = Sheets("Tabelle5").Range("B2:B8") For Each Zelle In Bereich Zelle.Offset(0, 1).Value = Zelle.Value * 1.1 Next Zelle End Sub Zu Beginn des Makros in Listing 2.13 wird der Bereich definiert, der Zelle für Zelle abgearbeitet werden soll. Danach steuert die For Each...Next -Schleife alle diese Zellen einzeln an und führt den Preisaufschlag durch. Das Ergebnis der Operation soll in die jeweilige Nebenspalte eingetragen werden. Dies wird über die Eigenschaft Offset erreicht. Diese Eigenschaft hat zwei Argumente: Im ersten Argument geben Sie die Zeilenverschiebung an. Da jedoch keine Zeilenverschiebung durchgeführt werden soll, steht an dieser Stelle der Wert 0. Im zweiten Argument wird die Spaltenverschiebung von der jeweiligen Zelle angegeben. Da der neue Wert in die Spalte B, also eine Spalte weiter rechts geschrieben werden soll, wird hier der Wert 1 angegeben. 80 Schleifen programmieren jetzt lerne ich Bild 2.8: Die Preiserhöhung wurde in der Nebenspalte durchgeführt Einheitliche Kopf- und Fußzeilen Im nächsten Beispiel optimieren wir das Layout der Datei durch eine einheitliche Gestaltung der Kopf- und Fußzeilen. Dabei werden alle Tabellen einer Arbeitsmappe einzeln abgearbeitet. Rufen Sie die Seitenansicht auf und stellen die gewünschten Kopf- und Fußzeilen ein. Dabei werden folgende Informationen hinterlegt: 쐽 Kopfzeile links: der Firmenname 쐽 Kopfzeile Mitte: der Name des Tabellenblatts 쐽 Kopfzeile rechts: das aktuelle Datum 쐽 Fußzeile links: der komplette Speicherpfad inkl. Dateinamen 쐽 Fußzeile Mitte: bleibt leer 쐽 Fußzeile rechts: Seitennummerierung Erfassen Sie nun das Makro in Listing 2.14: Sub EinheitlicheKopfUndFussZeilen() Dim Tabelle As Worksheet Application.ScreenUpdating = False Listing 2.14: Einheitliche Kopf- und Fußzeilen einstellen For Each Tabelle In ActiveWorkbook.Worksheets With Tabelle.PageSetup ..LeftHeader = _ ActiveWorkbook.BuiltinDocumentProperties("Company") .CenterHeader = Tabelle.Name 81 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA .RightHeader = Date .LeftFooter = ActiveWorkbook.FullName .CenterFooter = "" .RightFooter = "Seite &P von &N" End With Next Tabelle Application.ScreenUpdating = True End Sub Im ersten Schritt wird eine Objektvariable vom Typ Worksheet definiert. Nun wird die automatische Bildschirmaktualisierung durch die Anweisung Application.ScreenUpdating = False ausgeschaltet. Setzen Sie danach eine Schleife auf, die alle Tabellen der aktiven Arbeitsmappe durchläuft. Die Auflistung Worksheets enthält für diese Tabellen gleich ein Inhaltsverzeichnis, das Sie nun Tabelle für Tabelle auslesen. Über das Objekt PageSetup wird danach eine einheitliche Kopf- und Fußzeile eingestellt. Der Firmenname lässt sich direkt aus den Dokumenteigenschaften herauslesen. Der Name der Tabelle geht direkt aus der Eigenschaft Name hervor, die auf die Objektvariable Tabelle angewendet wird. Über die Funktion Date lässt sich das aktuelle Systemdatum abfragen. Den kompletten Pfadnamen fragen Sie über die Eigenschaft FullName ab. Bei der Seitennummerierung können Sie auf die Steuerzeichen &P (Seite) und &N (Seiten) zurückgreifen, die standardmäßig verwendet werden, wenn Sie auf herkömmliche Art und Weise die Kopf- und Fußzeilen über die Excel-Oberfläche einstellen. Bild 2.9: Die Kopfzeile mit Firmen-, Tabellenname und Datum 82 Schleifen programmieren jetzt lerne ich Bild 2.10: Die Fußzeile mit Pfad und Seitennummerierung Geöffnete Arbeitsmappen auslesen Im nächsten Beispiel werden die Namen aller momentan geöffneten Arbeitsmappen ermittelt und in einer Meldung am Bildschirm angezeigt. Auch für dieses Beispiel ist die For Each...Next-Schleife geradezu prädestiniert. Sub MappenListen() Dim Mappe As Workbook Dim strName As String For Each Mappe In Application.Workbooks Listing 2.15: Alle Namen der geöffneten Arbeitsmappen auslesen strName = strName & vbLf & Mappe.Name Next Mappe MsgBox "Derzeit sind folgende Mappe(n) geöffnet:" & _ vbLf & strName, vbInformation End Sub Deklarieren Sie im ersten Schritt des Makros in Listing 2.15 eine Objektvariable vom Typ Workbook. Danach werden in einer Schleife alle momentan geöffneten Arbeitsmappen überprüft. Diese sind automatisch in der Auflistung Workbooks verzeichnet. Über die Objektvariable können Sie jetzt Mappe für Mappe abarbeiten, die Namen aller geöffneten Mappen über die Eigenschaft Name abfragen und in einem extra Fenster darstellen. 83 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Bild 2.11: Die geöffneten Arbeitsmappen werden ermittelt Geschlossene Arbeitsmappen auslesen Im folgenden Beispiel zur For Each...Next-Schleife werden die Namen aller Excel-Arbeitsmappen eines Verzeichnisses und der darunter liegenden Verzeichnisse ermittelt und ausgegeben. Den Quellcode für diese Aufgabe können Sie in Listing 2.16 sehen. Listing 2.16: Alle Namen von geschlossenen Arbeitsmappen aus einem bestimmten Verzeichnis ermitteln Sub GeschlosseneMappenListen() Dim VarDat As Variant Dim strName As String Const verz = "C:\Temp\" On Error GoTo fehler With Application.FileSearch .NewSearch .LookIn = verz .Filename = "*.xls" .SearchSubFolders = True If .Execute() > 0 Then For Each VarDat In .FoundFiles strName = strName & vbLf & VarDat Next VarDat End If MsgBox "Die folgenden Mappen konnten ermittelt werden: " & _ vbLf & strName & vbLf & vbLf & "insgesamt wurden " & _ .FoundFiles.Count & " Mappen gezählt!", vbInformation End With Exit Sub fehler: MsgBox Err.Description End Sub 84 Schleifen programmieren jetzt lerne ich Zu Beginn des Makros aus Listing 2.16 wird das zu durchsuchende Verzeichnis in einer Konstanten bekannt gegeben. Danach starten Sie die Suche und verwenden dabei das Objekt FileSearch, um die einzelnen Dateien im Verzeichnis zu ermitteln. Auf dieses Objekt lassen sich einige nützliche Eigenschaften anwenden: Die Eigenschaft NewSearch setzt die Einstellungen aller Suchkriterien auf die Standardeinstellungen zurück. Mithilfe der Eigenschaft LookIn wird bekannt gegeben, in welchem Verzeichnis die Suche beginnen soll. Die Eigenschaft SearchSubFolders bestimmt, ob die Suche auch in Unterverzeichnissen fortgesetzt werden soll. In diesem Fall wird die Eigenschaft auf den Wert True gesetzt. Über die Eigenschaft Filename lässt sich festlegen, welche Dateien gesucht werden sollen. Die Methode Execute führt die eigentliche Suche aus. Danach stehen alle »Suchtreffer« im Objekt FoundFiles. Dieses Objekt können Sie jetzt über eine For...each Next-Schleife auslesen und die Namen der einzelnen Dateien in der Variablen StrName »zwischenparken«. Mithilfe der Anweisung FoundFiles.Count wird die Anzahl der gefundenen Dateien gezählt. Bild 2.12: Alle Mappen aus einem Verzeichnis auslesen Notizen auslesen Bei der folgenden Aufgabe fügen Sie zunächst in einer Tabelle ein paar Kommentare, so wie in Abbildung 2.13 gezeigt, ein. In der Abbildung wurde die Ansicht der Kommentare unter EXTRAS/ OPTIONEN auf der Registerkarte ANSICHT so eingestellt, dass sowohl das Kommentarfenster als auch der Kommentarindikator in der Tabelle angezeigt wird. Wenn diese Einstellung nicht vorgenommen ist, wird es schwierig, die einzelnen Kommentare anzusteuern. Die Aufgabe besteht nun darin, alle Kommentartexte auszulesen sowie die Zellenadressen der Kommentare zu ermitteln. Gerade auch für diese Aufgabe kommt die For Each...Next-Schleife wie gerufen. Sehen Sie sich dazu das Makro in Listing 2.17 an. 85 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA Bild 2.13: Es wurden wahllos einige Kommentare eingefügt Listing 2.17: Sub NotizenAuslesen() Alle Kommen- Dim Notiz As Comment tare einer Tabelle auslesen For Each Notiz In ActiveSheet.Comments Debug.Print Notiz.Text & vbLf & _ Notiz.Parent.Address & vbLf Next Notiz End Sub Zu Beginn des Makros in Listing 2.17 wird eine Objektvariable vom Typ Comment deklariert. Danach setzen Sie eine Schleife auf, die alle Kommentare in der aktiven Tabelle aufspürt und verarbeitet. In der Auflistung Comments sind automatisch alle Kommentare eingestellt. Nun kann festgelegt werden, was Sie mit diesen Kommentaren machen möchten. Über die Anweisung Debug.Print kann beispielsweise die Information in das Direktfenster der Entwicklungsumgebung geschrieben werden. Übernehmen Sie dort genau den Text (= Text) eines jeden einzelnen Kommentars sowie seine Zellenadresse (= Address). Die Eigenschaft Parent gibt laut Excel-Online-Hilfe das übergeordnete Objekt an. Aber was heißt das in diesem Fall? Nun es bedeutet, dass der eigentliche Kommentar eine Ebene unterhalb der Zelle sitzt, in der ein Kommentar erfasst wurde. Es handelt sich um ein 86 Schleifen programmieren jetzt lerne ich Kommentarfenster, das an eine Zelle angedockt wird. Um also eine Ebene höher zu kommen, wird die Eigenschaft Parent verwendet. Nach dem Starten des Makros in Listing 2.17 blenden Sie das Direktfenster in der Entwicklungsumgebung unter ANSICHT/DIREKTFENSTER ein. Bild 2.14: Alle Kommentare einer Tabelle wurden dokumentiert 2.4.3 Die Schleife Do Until...Loop Die Do Until...Loop-Schleife wiederholt einen Block mit Anweisungen, solange eine Bedingung den Wert True erhält. Die Bedingung wird jeweils am Ende der Schleife geprüft. Als Abbruchbedingung lassen sich unterschiedliche Bedingungen abfragen. So können Sie z. B. eine Abbruchbedingung festlegen, wenn ein bestimmter Wert erreicht ist oder eine Zelle einen bestimmten Text aufweist. Beispielsweise könnten Sie eine solche Schleife so lange wiederholen, wie die Zellenformatierung der Zellen sich nicht ändert. Die Syntax dieser Schleife sieht wie folgt aus: Do [{Until} Bedingung] [Anweisungen] [Exit Do] [Anweisungen] Loop Die Bedingung stellt einen numerischen Ausdruck oder Zeichenfolgenausdruck dar, der entweder erfüllt (True) oder nicht erfüllt (False) wird. Liefert die Bedingung den Wert 0, so wird die Bedingung als False interpretiert. Hinter den Anweisungen verbergen sich eine oder mehrere Anweisungen, die wiederholt werden, solange oder bis Bedingung durch True erfüllt ist. Innerhalb einer Do Until...Loop-Anweisung kann eine beliebige Anzahl von Exit Do-Anweisungen an beliebiger Stelle als Alternative zum Verlassen der Do Until...Loop-Anweisung verwendet werden. 87 2 Die Sprachelemente von Excel-VBA jetzt lerne ich Auch zu dieser Schleife, bei der Sie sich selber um den Zähler in der Schleife kümmern müssen, folgt nun ein Beispiel. Wochenenden kennzeichnen Bei der folgenden Aufgabe werden in eine Tabelle in der Spalte A einige Datumsangaben vorgenommen. Anhand eines Datums können Sie aber nicht erkennen, ob es sich um einen Wochentag oder um ein Wochenende handelt. Daher verwenden wir ein Makro, das eine »Wochenendprüfung« durchführt. Steht in einer Zelle der Spalte A ein Datum, das einem SAMSTAG oder SONNTAG entspricht, dann sollen diese Zellen mit dem Schriftschnitt FETT formatiert werden. Listing 2.18: Sub WochenendenFetten() Eine Wochen- Dim Zeile As Integer endprüfung durchführen Zeile = 1 With Sheets("Tabelle7") Do Until .Cells(Zeile, 1).Value = "" If Weekday(.Cells(Zeile, 1).Value) = 1 Or _ Weekday(.Cells(Zeile, 1).Value) = 7 Then .Cells(Zeile, 1).Font.Bold = True Else .Cells(Zeile, 1).Font.Bold = False End If Zeile = Zeile + 1 Loop End With End Sub Bei dieser Art von Schleife muss die Zählvariable vorbelegt werden. Setzen Sie daher die Variable Zeile auf den Wert 1. Sollte dies vergessen werden, ist schon direkt beim Schleifenbeginn ein Makroabsturz zu verzeichnen, da die Variable ohne Vorbelegung eine 0 aufweist. Excel versucht dann im Befehl Cells(Zeile,1) auf die Zeile 0 zuzugreifen, die es ja per Definition in einer Excel-Tabelle nicht gibt. 88 Schleifen programmieren jetzt lerne ich Das Schleifen-Ende wird dann erreicht, wenn die erste leere Zelle in Spalte A gefunden wurde. Innerhalb der Schleife prüfen Sie mithilfe der Funktion Weekday, ob es sich beim jeweiligen Datum um einen Wochentag bzw. um ein Wochenende handelt. Interessanterweise liefert diese Funktion für den Sonntag den Wert 1 und für den Samstag den Wert 7. Somit fängt die Woche in Excel mit dem Sonntag an! Bild 2.15: Die Wochenenden werden hervorgehoben 2.4.4 Die Schleife Do While...Loop Die Do While...Loop-Schleife wiederholt einen Block mit Anweisungen, solange eine Bedingung den Wert True erhält. Die Prüfung der angegebenen Bedingung erfolgt immer zu Beginn der Schleife. Als Abbruchbedingung können Sie z. B. festlegen, wenn ein bestimmter Wert erreicht ist oder eine Zelle einen bestimmten Text aufweist. Die Syntax dieser Schleife sieht wie folgt aus: Do [{While} Bedingung] [Anweisungen] [Exit Do] [Anweisungen] Loop Die Bedingung stellt einen numerischen Ausdruck oder Zeichenfolgenausdruck dar, der entweder erfüllt (True) oder nicht erfüllt (False) wird. Liefert die Bedingung den Wert 0, so wird die Bedingung als False interpretiert. Hinter den Anweisungen verbergen sich eine 89 2 Die Sprachelemente von Excel-VBA jetzt lerne ich oder mehrere Anweisungen, die wiederholt werden, solange oder bis die Bedingung True erfüllt ist. Innerhalb einer Do While...Loop-Anweisung kann eine beliebige Anzahl von Exit Do-Anweisungen an beliebiger Stelle als Alternative zum Verlassen der Do...Loop-Anweisung verwendet werden. Der Einsatz dieser Schleife wird an den folgenden Beispielen deutlich. Dateien in einem Verzeichnis zählen Beim folgenden Beispiel in Listing 2.19 sollen alle Dateien aus einem bestimmten Verzeichnis gezählt werden. Dazu setzen wir die Funktion Dir ein, die DOS-Anwender aus »alten« Tagen sicherlich noch kennen werden. Listing 2.19: Alle Dateien aus einem Verzeichnis werden gezählt Sub Dim Dim Dim DateienZaehlen() OrdnerName As String intz As Integer strName As String OrdnerName = "C:\Temp\" strName = Dir(OrdnerName & "*.*") Do While strName <> "" strName = Dir intz = intz + 1 Loop MsgBox "Anzahl der Dateien: " & intz End Sub Geben Sie zu Beginn des Makros in Listing 2.19 den Namen des Ordners an, in dem die darin enthaltenen Dateien gezählt werden sollen. Übergeben Sie diesen Ordner sowie den »Datei-Filter« an die Funktion Dir. Nun kommt die Do While-Schleife zum Einsatz. Innerhalb der Schleife wird wiederum die Funktion Dir angewendet, um die nächste Datei zu ermitteln. Erhöhen Sie dann jeweils den Zähler intz um den Wert 1. Die Ende-Bedingung für die Schleife wird dann erreicht, wenn keine weitere Datei mehr gefunden werden kann. In diesem Fall wird eine leere Zeichenfolge zurückgegeben. 90 Schleifen programmieren jetzt lerne ich Textdatei in Tabelle einlesen Beim folgenden Beispiel liegt eine Textdatei wie in Abbildung 2.16 gezeigt, vor. Diese Textdatei soll nun in eine Excel-Tabelle übertragen werden. Bild 2.16: Die Ausgangstabelle Starten Sie für diese Aufgabe das Makro in Listing 2.20. Sub TextdateiEinlesen() Dim Zeile As Integer Dim strInhalt As String Listing 2.20: Eine Textdatei einlesen Zeile = 1 With Sheets("Tabelle8") Open "c:\Temp\Artikel.txt" For Input As #1 Do While Not EOF(1) Line Input #1, strInhalt .Cells(Zeile, 1).Value = strInhalt Zeile = Zeile + 1 strInhalt = "" Loop Close #1 .Columns("A:A").TextToColumns Destination:=.Range("A1"), _ DataType:=xlDelimited, Semicolon:=True 91 jetzt lerne ich 2 Die Sprachelemente von Excel-VBA End With End Sub Mithilfe der Methode Open wird die Textdatei geöffnet. Danach arbeiten Sie diese über eine Do While-Schleife bis zum Textdateiende ab. Das Ende einer Textdatei lässt sich über die Funktion EOF (= End of file) feststellen. Innerhalb der Schleife »parken« Sie die jeweilige Zeile in einer Variablen vom Typ String. Danach wird der Inhalt dieser Variablen direkt Zeile für Zeile in die Tabelle geschrieben. Schließen Sie die Textdatei direkt nach Schleifen-Ende und führen die Methode TextToColumns durch, um die Daten, die momentan alle noch in Spalte A stehen, auf die daneben liegenden Spalten zu verteilen. Dabei wird in diesem Beispiel auf das Trennzeichen Semikolon zurückgegriffen, das bei dieser Methode als Argument angeben werden muss. Bild 2.17: Die Textdatei wurde eingelesen 1 92 Bei dieser Variante des Einlesens einer Textdatei besteht zusätzlich die Möglichkeit, auch nur bestimmte Sätze aus der Textdatei einzulesen, indem Sie innerhalb der Schleife eine zusätzliche IfAnweisung einbauen. jetzt lerne ich KAPITEL 3 Zellen und Bereiche programmieren Das wichtigste Objekt in Excel ist sicherlich die Zelle. Dort finden die wesentlichen Aktionen statt. In der Regel werden Zellen ausgewertet, gefüllt, formatiert und vieles mehr. In diesem Kapitel lernen Sie daher ganz konkret wie diese Zellen angesprochen und bearbeitet werden. Da Sie spezielle Aufgaben nicht immer nur für eine Zelle, sondern auch für ganze Bereiche durchführen, ist das vorherige Kapitel mit den Schleifen die Voraussetzung für dieses Kapitel. Das Range-Objekt repräsentiert eine Zelle oder gar mehrere Zellen. Des Weiteren kann ein Range-Objekt auch eine oder mehrere Zeilen bzw. Spalten darstellen. 1 Alle hier vorgestellten Makros finden Sie auf der mitgelieferten CD-ROM im Verzeichnis Kap03 unter dem Namen Zellen.xls. 1 3.1 Zellen und Bereiche markieren Das Markieren von Zellen und Bereichen ist bei der Programmierung im Prinzip gar nicht notwendig, da Zellen auch per Makro bearbeitet werden können, ohne »darauf zu sitzen«. Trotzdem ist es für bestimmte Aufgaben wichtig, Zellen- und Bereichsadressen auszulesen. Zellen bzw. Bereiche lassen sich mit der Methode Select markieren. 93 3 Zellen und Bereiche programmieren jetzt lerne ich Tabelle 3.1: Aktion Die Markierungsformen Markierung einzelner Zellen im Überblick Befehl Range("A1").Select oder Cells(1,1).Select Markierung eines Datenbereichs Range("A1:C10").Select Markierung nicht zusammenhängender Zellen Range("A1,A3,A5,A7").Select Markierung mehrerer Bereiche Range("A1:A10,C1:C10").Select Markieren aller Zellen einer Tabelle Cells.Select 3.1.1 Die übersichtlichere Mehrfachauswahl Sofern mehr als zwei Bereiche markiert werden sollen, wird die Schreibweise, wie in der Tabelle 3.1 beschrieben, ein wenig unübersichtlich. Hier hilft die Methode Union wie in dem folgenden Listing 3.1 beschrieben. Listing 3.1: Mehrere Bereiche definieren und zusammenführen Sub Dim Dim Dim MehrereBereicheMarkieren() Ber1 As Range, Ber2 As Range Ber3 As Range, Ber4 As Range Bereiche As Range With Sheets("Tabelle1") Set Set Set Set Set Ber1 = .Range("A1:A5") Ber2 = .Range("C1:C5") Ber3 = .Range("A10:A15") Ber4 = .Range("C10:C15") Bereiche = Union(Ber1, Ber2, Ber3, Ber4) Bereiche.Select End With End Sub Mit der Anweisung Set definieren Sie zuerst die einzelnen Zellbereiche Ber1-Ber4. Danach werden diese Einzelbereiche mithilfe der Methode Union in einem Block vereint, der den Namen Bereiche trägt. Dieser Block lässt sich nun individuell ansteuern und wie hier beschrieben über die Methode Select komplett markieren. 94 Zellen und Bereiche markieren jetzt lerne ich Bild 3.1: Mehrere Bereiche auf einmal markieren 3.1.2 Die letzte benutzte Zelle einer Tabelle ansteuern Wenn Sie mit Schleifen arbeiten und die Abbruchbedingung der Schleife beispielsweise von der letzten belegten Zelle auf dem Tabellenblatt abhängig machen möchten, dann wird Ihnen das Makro in Listing 3.2 helfen. Dort wird die SpecialCells-Methode verwendet, der Sie die Konstante xlCellTypeLastCell mitgeben. Diese Methode liefert Ihnen die Zellenadresse der letzten Zelle im verwendeten Bereich. Sub LetzteZelleImBenutztenBereichErmitteln() With Sheets("Tabelle2") .Activate .Cells.SpecialCells(xlCellTypeLastCell).Select Listing 3.2: Die letzte Zelle im benutzten Bereich einer Tabelle ansteuern End With MsgBox "Letzte Zelle im benutzten Bereich: " & ActiveCell.Address End Sub 95 jetzt lerne ich 3 Zellen und Bereiche programmieren Bild 3.2: Die letzte Zelle in der Tabelle wird markiert Weitere interessante Konstanten dieser Methode entnehmen Sie der Tabelle 3.2. Tabelle 3.2: Konstante Die möglichen Konstanten xlCellTypeAllFormatConditions der Methode xlCellTypeAllValidation SpecialCells 96 Beschreibung Markiert alle formatierten Zellen. Zellen mit Gültigkeitsregeln werden markiert. xlCellTypeBlanks Gibt alle leeren Zellen an. xlCellTypeComments Zellen mit Kommentaren werden markiert. xlCellTypeConstants Zellen mit Konstanten werden markiert. xlCellTypeFormulas Zellen mit Formeln werden markiert. xlCellTypeLastCell Letzte Zelle im benutzten Bereich wird angesteuert. xlCellTypeSameFormatConditions Zellen mit gleichem Format werden markiert. xlCellTypeSameValidation Zellen mit gleichen Gültigkeitskriterien werden markiert. xlCellTypeVisible Alle sichtbaren Zellen werden markiert. Zellen und Bereiche markieren 3.1.3 jetzt lerne ich Die letzte Zelle einer Spalte markieren Ähnlich wie beim vorherigen Makro wird nun wiederum eine letzte Zelle angesteuert. Im folgenden Beispiel in Listing 3.3 wird die letzte Zelle aus Spalte B markiert. Sub LetzteZelleAusSpalteErmitteln() With Sheets("Tabelle2") Listing 3.3: Die letzte Zelle einer Spalte markieren .Activate .Range("B65536").End(xlUp).Select End With MsgBox "Letzte Zelle in Spalte B: " & ActiveCell.Address End Sub Über die Eigenschaft End gelangen Sie an das Ende einer Spalte. Dazu übergeben Sie der Eigenschaft die Konstante xlUp. Intern führt Excel dann zunächst einen Sprung ans Ende der Spalte, also in die Zelle B65536, durch und springt danach nach oben bis zur letzten gefüllten Zelle der Spalte. Bild 3.3: Die letzte Zelle aus Spalte B wird ermittelt 97 3 Zellen und Bereiche programmieren jetzt lerne ich 3.1.4 Die letzte Zelle einer Zeile markieren Analog zum vorherigen Beispiel wird in dem Makro in Listing 3.4 die letzte Zelle der Zeile 5 angesteuert. Listing 3.4: Sub LetzteZelleAusZeileErmitteln() Die letzte Zelle einer Zeile With Sheets("Tabelle2") wird ermittelt .Activate .Range("B5").End(xlToLeft).Select End With MsgBox "Letzte Zelle in Zeile 5: " & ActiveCell.Address End Sub Über die Eigenschaft End gelangen Sie an das Ende einer Zeile. Dazu übergeben Sie der Eigenschaft die Konstante xlToLeft. Intern führt Excel dann zunächst einen Sprung ans Ende der Zeile, also in die Zelle IV5, durch und springt danach nach links bis zur letzten gefüllten Zelle der Zeile. Bild 3.4: Die letzte Zelle aus Zeile 5 wird ermittelt 3.1.5 Alle Formelzellen markieren Mithilfe der Methode SpecialCells lassen sich auch blitzschnell alle Zellen mit Formeln in einer Tabelle markieren. Das Makro für diese Aufgabe können Sie in Listing 3.5 nachsehen. 98 Zellen und Bereiche markieren Sub FormelzellenMarkieren() On Error GoTo fehler jetzt lerne ich Listing 3.5: Alle Zellen mit Formeln werden markiert With Sheets("Tabelle3") .Activate .Cells.SpecialCells(xlCellTypeFormulas).Select End With Exit Sub fehler: MsgBox Err.Description, vbCritical End Sub Übergeben Sie der Methode SpecialCells die Konstante xlCellTypeFormulas, um alle Formelzellen der Tabelle zu ermitteln. Mit der Methode Select werden anschließend diese Zellen markiert. Sollte die Tabelle überhaupt keine Formeln enthalten, würde das Makro ohne eine Fehlerbehandlung abstürzen. Daher verzweigen Sie im Fehlerfall über On Error GoTo direkt in den Paragrafen fehler. Dort wird auf das Objekt Err zurückgegriffen. In diesem Objekt werden im Fehlerfall automatisch alle Informationen über den Fehler zur Verfügung gestellt. Über die Eigenschaft Description lässt sich der genaue Wortlaut der Fehlermeldung darstellen. 1 Bild 3.5: Alle Formelzellen werden markiert 99 3 Zellen und Bereiche programmieren jetzt lerne ich 3.1.6 Die umliegenden Zellen markieren Über die Eigenschaft UsedRange lässt sich der verwendete Bereich Ihrer Tabelle ermitteln. Damit markieren Sie aber jeweils den kompletten verwendeten Bereich – möglicherweise möchten Sie aber nur einen Teilbereich davon adressieren. Mithilfe der Eigenschaft CurrentRegion lässt sich beispielsweise der umliegende Bereich einer Zelle ermitteln. Der ermittelte Bereich wird durch die erste Leerzeile bzw. Leerspalte begrenzt. Sehen Sie den Unterschied der beiden Eigenschaften in den folgenden Beispielen aus den Makros der Listings 3.6 und 3.7. Listing 3.6: Sub BenutzerBereichMarkieren() Der benutzte Sheets("Tabelle4").UsedRange.Select Bereich einer Tabelle wird markiert End Sub Die Eigenschaft UsedRange repräsentiert den verwendeten Bereich in der angegebenen Tabelle. Bild 3.6: Der benutzte Bereich der Tabelle wird komplett markiert Listing 3.7: Sub UmliegendenBereichMarkieren() Der umliegenSheets("Tabelle4").Range("A2").CurrentRegion.Select de Bereich einer Zelle wird markiert End Sub 100 Zellen und Bereiche formatieren jetzt lerne ich Mithilfe der Eigenschaft CurrentRegion wird, ausgehend von der Zelle A2, der umliegende Bereich dieser Zelle markiert und über die Methode Select ausgewählt. Bild 3.7: Den umliegenden Bereich von Zelle A2 markieren 3.2 Zellen und Bereiche formatieren Im folgenden Abschnitt lernen Sie einige Möglichkeiten kennen, wie Zellen und Bereiche formatiert werden können. Dabei reicht die Palette von Hintergrundfarben, Schriftfarben sowie Schriftschnitten bis hin zu Rahmen und Schattierungen. 3.2.1 Alle verbundenen Zellen kennzeichnen Nicht immer sind verbundene Zellen in einer Tabelle auf den ersten Blick sichtbar. Sollen alle verbundenen Zellen einer Tabelle optisch hervorgehoben werden, übernimmt das Makro in Listing 3.8 diese Aufgabe. Sub VerbundeneZellenFormatieren() Dim Zelle As Range For Each Zelle In Worksheets("Tabelle5").UsedRange Listing 3.8: Verbundene Zellen einfärben If Zelle.MergeCells = True Then Zelle.Interior.ColorIndex = 4 101 3 Zellen und Bereiche programmieren jetzt lerne ich Else Zelle.Interior.ColorIndex = xlColorIndexNone End If Next Zelle End Sub Über eine For Each...Next-Schleife wird in der TABELLE5 jede einzelne Zelle angesprochen, die aktuell verwendet wird. Hierzu wird die Eigenschaft UsedRange eingesetzt. In einer If-Abfrage erfolgt die Ermittlung, ob diese Zelle einem Zellenverbund angehört. Wenn ja, dann gibt die Eigenschaft MergeCells den Wert True zurück und die Zelle wird mit der Farbe GRÜN gefärbt. Bild 3.8: Die verbundenen Zellen aus Spalte B wurden eingefärbt 3.2.2 Die Schrift anpassen In der nächsten Aufgabe sollen innerhalb einer Markierung alle Zellen mit der Schriftart COURIER und dem Schriftgrad 12 formatiert werden. Das Makro für diese Aufgabe können Sie in Listing 3.9 finden. Markieren Sie vor dem Start des Makros ein paar beliebige Zellen, die bereits Texte oder Zahlen enthalten. Listing 3.9: Sub SchriftenFormatieren() Alle markier- Dim Zelle As Range ten Zellen formatieren For Each Zelle In Selection 102 Zellen und Bereiche formatieren jetzt lerne ich With Selection.Font .Name = "Courier" .Size = 12 .Strikethrough = False .Superscript = False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With Next Zelle End Sub Das Objekt Font hat eine ganze Reihe Eigenschaften, die angewendet werden können. Für die eben gestellte Aufgabe sind die beiden Eigenschaften Name und Size wichtig. Bei der Angabe der Schriftart ist die korrekte Schreibweise der gewünschten Schriftart wichtig. Bei der Eigenschaft Size wird die gewünschte Größe für die Schrift angegeben. Bild 3.9: Alle markierten Zellen wurden umformatiert Entnehmen Sie weitere wichtige Eigenschaften des Objekts Font aus der folgenden Tabelle. 103 3 Zellen und Bereiche programmieren jetzt lerne ich Tabelle 3.3: Eigenschaft Die wichtigsten Eigen- Bold schaften für die Schrift- ColorIndex gestaltung Beschreibung Diese Eigenschaft liefert den Wert True, wenn ein Text fett formatiert ist. Diese Eigenschaft gibt die Farbe des Rahmens, der Schriftart oder des Innenraums zurück. Es existieren in Excel genau 56 Farben. FontStyle Diese Eigenschaft sagt aus, welcher Schriftschnitt verwendet wird. Möglich sind u. a. Fett- und Kursivdruck. Italic Diese Eigenschaft liefert den Wert True, wenn ein Text kursiv formatiert ist. OutLineFont Diese Eigenschaft liefert den Wert True, wenn ein Text als Konturschriftart formatiert wird. Shadow Diese Eigenschaft liefert den Wert True, wenn ein Text als schattierte Schriftart formatiert wird. Strikethrough Diese Eigenschaft liefert den Wert True, wenn ein Text als horizontal durchgestrichen dargestellt wird. Subscript Diese Eigenschaft liefert den Wert True, wenn ein Text tiefergestellt formatiert wird. Superscript Diese Eigenschaft liefert den Wert True, wenn ein Text hochgestellt formatiert wird. Underline Diese Eigenschaft liefert den Wert True, wenn ein Text unterstrichen formatiert wird. Dabei können Sie u. a. Text einfach oder doppelt unterstreichen. 3.2.3 Extremwerte kennzeichnen Im nächsten Beispiel in Listing 3.10 sollen in einem Bereich alle Werte über 100 hervorgehoben werden. Diese Aufgabe lässt sich elegant über eine Schleife lösen, die alle Zellen des Bereichs kontrolliert und die »Ausreißer« farblich hervorhebt. Listing 3.10: Alle Werte größer oder gleich 100 werden optisch hervorgehoben Sub ExtremwerteHervorheben() Dim Zelle As Range Dim Bereich As Range Set Bereich = Sheets("Tabelle7").Range("A1:E12") For Each Zelle In Bereich If Zelle.Value >= 100 Then Zelle.Interior.ColorIndex = 4 104 Zellen und Bereiche formatieren jetzt lerne ich Else Zelle.Interior.ColorIndex = xlColorIndexNone End If Next Zelle End Sub Deklarieren Sie zunächst einmal zwei Objektvariablen vom Typ Range. Danach wird der Bereich, der abgearbeitet werden soll, mithilfe der Anweisung Set bekannt gegeben. Anschließend werden mit einer For Each...Next-Schleife alle Zellen innerhalb dieses Bereichs durchlaufen. In der Schleife selbst wird der Wert der Zellen überprüft. Liegt der Wert dabei über 100, wird der Hintergrund dieser Zelle über die Eigenschaft ColorIndex farblich angepasst. Vergessen Sie bei der If-Anweisung nicht den Else-Zweig, der eingesetzt wird, um Werte außerhalb der »Wertegrenze« wieder farblich zurückzusetzen. Es kann schließlich vorkommen, dass Werte im vorgegebenen Bereich geändert werden. Beispielsweise könnte in eine Zelle mit einem Wert über 100 ein Wert kleiner als 100 eingetragen werden. Ohne den Einsatz des Else-Zweiges würde der Farbindex dieser Zelle nicht zurückgesetzt werden und die Farbe bliebe bestehen. 1 Bild 3.10: Extremwerte über 100 werden mit der Hintergrundfarbe Grün hinterlegt 105 3 Zellen und Bereiche programmieren jetzt lerne ich 3.2.4 Bereiche einrahmen In dem folgenden Beispiel in Listing 3.11 werden die beiden Bereiche A2:E5 sowie A8:E11 mit einem Rahmen versehen. Listing 3.11: Mehrere Bereiche werden eingerahmt Sub Dim Dim Dim RahmenFestlegen() Bereich1 As Range Bereich2 As Range Gesamt As Range With Sheets("Tabelle8") Set Bereich1 = .Range("A2:E5") Set Bereich2 = .Range("A8:E11") Set Gesamt = Union(Bereich1, Bereich2) With Gesamt.Borders .ColorIndex = 3 .LineStyle = xlSlantDashDot End With End With End Sub Zu Beginn werden drei Objektvariablen vom Typ Range deklariert. Danach werden die zu umrahmenden Bereiche den ersten beiden Objektvariablen Bereich1 und Bereich2 mithilfe der Anweisung Set zugewiesen. Mit der Methode Union werden die beiden einzelnen Bereiche zu einem Gesamtbereich zusammengefasst und können nun unter dem Namen Gesamt als ein Bereich angesprochen werden. Bild 3.11: Eine individuelle Rahmung von Bereichen durchführen 106 Zelleninhalte manipulieren jetzt lerne ich Mit dem Objekt Borders wird nun die Umrahmung des Bereichs festgelegt. Dieses Objekt bietet Ihnen hierfür vielfältige Eigenschaften an. Unter anderem lässt sich über die Eigenschaft ColorIndex die Rahmenfarbe festlegen. Die Eigenschaft LineStyle definiert die Form des Rahmens. Sehen Sie in der nächsten Tabelle weitere Möglichkeiten, um die Form eines Rahmens zu definieren. Konstante Beschreibung xlContinuous durchgezogene Linie xlDash gestrichelte Linie xlDashDot Linie aus Strichen und Punkten xlDashDotDot Linie aus Strich-Punkt-Punkt xlDot gepunktete Linie xlDouble doppelte Linie xlSlantDashDot Linie aus Wellenzeichen und Punkt xlLineStyleNone keine Linie 3.3 Tabelle 3.4: Die weiteren Möglichkeiten der Rahmenformen Zelleninhalte manipulieren In diesem Abschnitt werden Zelleninhalte verändert. Dazu werden eine ganze Reihe praktischer Aufgaben vorgestellt. 3.3.1 Daten nach Datentransfer bereinigen Wenn Daten von anderen Systemen wie Großrechnern oder Datenbankservern eingelesen werden, haben Sie vielleicht schon einmal festgestellt, dass unerwünschte Zeichen mit übertragen wurden. Diese Zeichen nennt man »nicht druckbare Zeichen«. Auch kann es vorkommen, dass Excel Zahlenwerte nicht richtig erkennt und diese stattdessen als Text konvertiert. Auf den ersten Blick fällt das nicht immer gleich auf. Erst wenn Sie versuchen, die Daten weiter zu verarbeiten, zum Beispiel grafisch oder in Kalkulationen, entstehen Probleme. 107 3 Zellen und Bereiche programmieren jetzt lerne ich Im folgenden Beispiel in Listing 3.12 werden alle Zellen einer Markierung noch einmal geprüft und wo notwendig »geputzt«. Dabei werden Formelzellen von der Bereinigung ausgenommen. Listing 3.12: Sub ZellenBereinigen() Alle Zellen im Dim Zelle As Range benutzten Bereich werden For Each Zelle In ActiveSheet.UsedRange gesäubert With Zelle If .HasFormula = False Then .Value = Application.WorksheetFunction.Clean(.Value) End If End With Next Zelle End Sub Im benutzten Bereich der Tabelle wird die Säuberungsaktion nur bei Zellen durchgeführt, die keine Verknüpfungen und keine Formeln enthalten. Für diese Abfrage wird die Eigenschaft HasFormula verwendet. Gibt diese Eigenschaft den Wert True zurück, handelt es sich um eine Zelle, die eine Formel oder Verknüpfung enthält. Im anderen Fall gibt die Eigenschaft Hasformula den Wert False zurück. Danach entfernt die Funktion Clean alle nicht druckbaren Zeichen. 3.3.2 Excel vorschreiben richtig zu rechnen Im nächsten Beispiel wird Excel genötigt, importierte Zahlenwerte auch als solche zu erkennen. Am schnellsten kann geprüft werden, ob die Daten richtig nach Excel übertragen wurden, indem Sie versuchen eine Summe über die Zahlenwerte zu bilden. Meldet die Funktion den Wert 0, können Sie davon ausgehen, dass Excel die Zahlenwerte als Text interpretiert. Üblicherweise werden Sie im nächsten Schritt wahrscheinlich probieren, den Zellen noch einmal ein Zahlenformat über den Dialog ZELLEN FORMATIEREN zuzuweisen. Aber auch diese Aktion bringt nicht den gewünschten Erfolg. Wenn es sich nur um ein paar Werte handelt, die falsch wiedergegeben werden, lassen sich diese durch Markieren der Zelle und Drücken der Taste Ê und anschließend der Æ-Taste manuell umsetzen. 108 Zelleninhalte manipulieren jetzt lerne ich Damit wird Excel »gezwungen« neu zu rechnen. Bei größeren Datenmengen ist diese Vorgehensweise natürlich recht langwierig und nervig. Sie müssen daher eine Lösung finden, die Excel automatisch veranlasst die Daten zu korrigieren und dann neu zu rechnen. Dazu lässt sich zum Beispiel jeder Zellenwert mit der Zahl 1 multiplizieren. Damit wird der eigentliche Wert der Zelle nicht verändert und Sie gelangen zum gewünschten Ergebnis. Das Makro für diese Aufgabe ist in Listing 3.13 dargestellt. Sub ZahlenwerteRichtigErkennen() Dim Zelle As Range For Each Zelle In Selection If IsNumeric(Zelle.Value) = True And _ Zelle.HasFormula = False Then Listing 3.13: Excel dazu bewegen importierte Zahlenwerte auch richtig zu interpretieren Zelle.Value = Zelle.Value * 1 End If Next Zelle End Sub Zu Beginn wird eine Objektvariable vom Typ Range definiert. Danach werden mithilfe einer For Each...Next-Schleife alle markierten Zellen angesteuert. Innerhalb der Schleife erfolgt eine Prüfung, ob überhaupt ein numerischer Wert (IsNumeric) vorliegt oder ob sich in der jeweiligen Zelle eine Formel (HasFormula) befindet. Nur wenn die erste Prüfung True zurückgibt und die zweite den Wert False, wird eine Kalkulation durchgeführt und der Inhalt der jeweiligen Zelle neu beschrieben, indem der alte Wert mit der Zahl 1 multipliziert wird. 3.3.3 Bestimmte Zeichen aus Zellen entfernen Um bestimmte Zeichen aus Zellen zu eliminieren, was in der Fachsprache als »parsen« bezeichnet wird, lässt sich mit dem folgenden Makro viel mühevolle Handarbeit ersparen. Im folgenden Beispiel in Listing 3.14 werden alle Nullen, Minuszeichen und Punkte aus allen markierten Zellen entfernt. Sehen Sie sich jedoch zunächst die Abbildung 3.12 näher an. 109 3 Zellen und Bereiche programmieren jetzt lerne ich Bild 3.12: Die Ausgangsliste mit diversen Sonderzeichen Starten Sie jetzt das folgende Makro, um die gerade genannten Zeichen aus den Zellen zu entfernen. Listing 3.14: Definierte Zeichen werden aus allen markierten Zellen entfernt Sub Dim Dim Dim BestimmteZeichenEliminieren() Zelle As Range intz As Integer StrNeu As String For Each Zelle In Selection For intz = 1 To Len(Zelle) Select Case Mid(Zelle, intz, 1) Case 0, ".", "-" Case Else StrNeu = StrNeu & Mid(Zelle, intz, 1) End Select Next intz Zelle.Value = StrNeu StrNeu = "" Next Zelle End Sub In einer For Each...Next-Schleife werden alle markierten Zellen abgearbeitet. In der zweiten »verschachtelten« Schleife wird innerhalb einer Zelle Zeichen für Zeichen mithilfe der Funktion Mid zerlegt. 110 Zelleninhalte manipulieren jetzt lerne ich Diese Funktion hat drei Argumente. Im ersten Argument wird die Zelle angegeben, die zerlegt werden soll. Das zweite Argument gibt die jeweilige Startposition in dieser Zelle an. Das dritte Argument gibt die Länge an, d. h. wie viele Zeichen ausgewertet werden sollen. Da Zeichen für Zeichen ausgewertet wird, ist die dort zu verwendende Zahl die 1. Nun wird das jeweilige Zeichen über eine Select Case-Anweisung ausgewertet. Sofern die Zeichen nicht den im ersten Case-Zweig angegeben Zeichen entsprechen, werden diese einzeln in die Hilfsvariable strNeu übertragen. Wurden alle Zeichen einer Zelle abgearbeitet, wird diese mit dem neuen bereinigten Wert aus der Variablen strNeu überschrieben. Bild 3.13: Alle definierten Zeichen wurden entfernt Nach dem gleichen Strickmuster lassen sich beispielsweise auch numerische von alphanumerischen Zeichen trennen, wie im Makro in Listing 3.15 dargestellt. Sub Dim Dim Dim AlphaNumerischeZeichenEntfernen() Zelle As Range intz As Integer StrNeu As String For Each Zelle In Selection For intz = 1 To Len(Zelle) Listing 3.15: Alle alphanumerischen Zeichen aus den markierten Zellen entfernen Select Case Mid(Zelle, intz, 1) Case 0 To 9 StrNeu = StrNeu & Mid(Zelle, intz, 1) 111 jetzt lerne ich 3 Zellen und Bereiche programmieren Case Else End Select Next intz Zelle.Offset(0, 1).Value = StrNeu StrNeu = "" Next Zelle End Sub Das Makro in Listing 3.15 entspricht weitestgehend dem Makro in Listing 3.14. Jedoch wird der Zelleninhalt im ersten Case-Zweig nach den gültigen Zahlen 0 bis 9 untersucht. Entspricht das jeweilige Zeichen einer dort festgelegten Zahl, dann wird diese in der Hilfsvariablen strNeu Zeichen für Zeichen zusammengesetzt. Die Ausgabe des Ergebnisses erfolgt in diesem Beispiel nicht in der gleichen Zelle, sondern in der Zelle rechts neben der markierten Zelle. Um diesen »Versatz« hinzubekommen, wenden Sie die Eigenschaft Offset an, die zwei Argumente hat. Im ersten Argument lässt sich eine eventuelle Zeilenverschiebung angeben. Da Sie aber in der jeweiligen Zeile bleiben möchten, wird dort die Zahl 0 (= keine Verschiebung) angegeben. Im zweiten Argument wird die Spaltenverschiebung definiert. Da das Ergebnis genau eine Spalte weiter nach rechts dargestellt werden soll, tragen Sie in diesem Argument den Wert 1 ein. Bild 3.14: In Spalte B finden Sie nur noch numerische Werte 112 Zelleninhalte manipulieren 3.3.4 jetzt lerne ich Namen drehen Erhalten Sie Daten, die innerhalb der Zelle gedreht werden müssen (z. B. Vorname Name Name Vorname), dann hilft hierbei das folgende Makro in Listing 3.16: Sub NamenDrehen() Dim Zelle As Range For Each Zelle In Selection Listing 3.16: Der Vor- sowie Nachname wurde gedreht Zelle.Offset(0, 1).Value = _ Mid(Zelle.Value, InStr(Zelle.Value, " ") + 1) Zelle.Offset(0, 2).Value = _ Left(Zelle.Value, InStr(Zelle.Value, " ") - 1) Next Zelle End Sub Das Makro geht gegenüber der Aufgabenstellung sogar noch einen Schritt weiter, trennt Namen von Vornamen und schreibt diese in die Zellen nebenan. Hierbei wird die Funktion Mid eingesetzt, um den Nachnamen aus der Zelle in Spalte A zu extrahieren. Da zwischen Vor- und Nachname ein Leerzeichen liegt, lässt sich die exakte Position dieses Leerzeichens mithilfe der Funktion Instr ermitteln. Diese Position muss dann noch um den Wert 1 erhöht werden, da das Leerzeichen nicht übertragen werden soll. Bild 3.15: Eine Zelle zerlegen und wieder in anderer Form zusammensetzen 113 3 Zellen und Bereiche programmieren jetzt lerne ich Den Vornamen können Sie direkt über die Funktion Left aus der jeweiligen Zelle der Spalte A extrahieren. Der Vorname muss bis zu einem Zeichen vor dem ermittelten Leerzeichen übertragen werden. Auch zu diesem Zweck wird die Funktion Instr verwendet und von der gefundenen Position der Wert 1 subtrahiert. 3.3.5 Kommentare aus Zellentexten generieren Gerade haben Sie gelernt, wie Zellinhalte überprüft werden und ein Teil davon übersichtlich in einer Liste dargestellt werden kann. Stellen Sie sich aber jetzt einmal folgendes Szenario vor: Sie arbeiten an einer Liste und möchten bestimmte Zellen mit neuen Texten überschreiben. Die alten Texte sind aber durchaus noch von Interesse und sollten nicht gänzlich aus der Liste verschwinden. Wie wäre es, wenn diese alten Einträge als Kommentar gesichert werden würden? Damit sind die alten Einträge sogar noch der ursprünglichen Zelle zugeordnet und die Inhalte können nun jederzeit verändert werden. Für diese Aufgabe erstellen Sie das folgende Makro in Listing 3.17: Listing 3.17: Zelleninhalte als Kommentartext übernehmen Sub KommentareAusZellenInhaltBilden() Dim Kom As Comment Dim Zelle As Range For Each Zelle In Selection On Error Resume Next Set Kom = Zelle.AddComment Kom.Text Date & vbLf & Zelle.Value Next Zelle End Sub Das Makro in Listing 3.17 verschiebt innerhalb der Markierung den Inhalt der einzelnen Zellen jeweils in ein Kommentarfenster. Jeder Kommentar wird zusätzlich noch mit dem Datum der Verschiebung ausgestattet. 114 Zelleninhalte manipulieren jetzt lerne ich Bild 3.16: Aus den Zelleninhalten wurden Kommentare mit dem aktuellen Datum gebildet 3.3.6 Formeln durch Festwerte ersetzen Sofern alle Formeln, Funktionen und externe Verknüpfungen in einem Bereich durch Festwerte ersetzt werden sollen, damit beispielsweise keine Änderungen mehr stattfinden können, übernimmt das Makro in Listing 3.18 automatisch diese Aufgabe. Sub FormelnInTextUmsetzen() Dim Zelle As Range For Each Zelle In ActiveSheet.UsedRange Listing 3.18: Alle Formelzellen werden durch Festwerte ersetzt If Zelle.HasFormula = True Then Zelle.Formula = Zelle.Value End If Next Zelle End Sub Zur Lösung dieser Aufgabe durchläuft das Makro alle Zellen im benutzten Bereich mithilfe einer For Each...Next-Schleife. Innerhalb der Schleife erfolgt eine Prüfung mit der Funktion HasFormula, ob die jeweilige Zelle eine Formel enthält. Sofern dies zutrifft, wird der Zelle durch die Eigenschaft Value der Wert zugewiesen, den die Formel als Ergebnis aktuell darstellt. 115 3 Zellen und Bereiche programmieren jetzt lerne ich 3.3.7 Bestimmte Zelleninhalte löschen Bei der folgenden Aufgabe sollen alle negativen Werte aus einem Bereich gelöscht werden. Sehen Sie sich hierzu Abbildung 3.17 an. Bild 3.17: Die Ausgangstabelle mit negativen sowie positiven Werten Für den besseren Überblick wurden die Zellen, die negative Werte enthalten, vorab mit dem Schriftschnitt FETT formatiert. Die Aufgabe besteht jetzt darin, diese Zellen zu löschen. Starten Sie hierfür das Makro in Listing 3.19. Listing 3.19: Sub ZelleninhalteLöschenWennNegativ() Die Inhalte von Dim Zelle As Range negativen Zel- Dim Bereich As Range len entfernen Set Bereich = Sheets("Tabelle13").Range("A1:F10") For Each Zelle In Bereich If Zelle.Value < 0 Then Zelle.ClearContents End If Next Zelle End Sub Zunächst werden zwei Objektvariablen vom Typ Range deklariert. Danach wird mithilfe der Anweisung Set der Variablen Bereich bekannt gegeben, in welcher Tabelle sich der Bereich befindet, der korrigiert werden soll. Nun werden über eine Schleife alle Zellen dieses Bereichs abgearbeitet. Innerhalb der Schleife wird überprüft, ob der 116 Zelleninhalte manipulieren jetzt lerne ich Wert der jeweiligen Zelle kleiner als null ist. Sofern dies zutrifft wird über die Methode ClearContents der Inhalt aus der Zelle gelöscht. Die Methode ClearContents löscht lediglich den Inhalt einer Zelle. Sollen gleichzeitig der Wert und die Formate gelöscht werden, dann setzen Sie die Methode Clear ein. Diese Methode »putzt« die Zelle komplett. Wenn es darum geht, nur Formatierungen aus einer Zelle zu löschen, wird die Methode ClearFormats benötigt. 1 Bild 3.18: Die negativen Werte wurden entfernt 3.3.8 Bezüge umsetzen Wenn in einer Tabelle »relative« Zellenbezüge in »absolute« Bezüge umgewandelt werden sollen, dann ist das manuell eine mitunter langwierige Aufgabe. Diese Aufgabe übernimmt besser ein Makro, das alle relativen Zellenbezüge in absolute Bezüge umwandelt. Sub AbsoluteBezüge() Dim Zelle As Range Listing 3.20: Zellenbezüge umwandeln For Each Zelle In Selection If Zelle.HasFormula = True Then Zelle.Formula = Application.ConvertFormula _ (Zelle.Formula, xlA1, , xlAbsolute) End If Next Zelle End Sub 117 3 Zellen und Bereiche programmieren jetzt lerne ich In einer For Each...Next-Schleife werden alle Zellen innerhalb der vorgegebenen Markierung abgearbeitet. Mithilfe der Eigenschaft HasFormula wird in der Schleife zunächst geprüft, ob die jeweilige Zelle eine Formel enthält. Wenn ja, dann meldet diese Eigenschaft den Wert True. In diesem Fall werden mit der Methode ConvertFormula die relativen Bezüge in absolute Bezüge umgewandelt. Dieser Methode wird als Erstes die Zelle übergeben, die umgesetzt werden soll. Dann legen Sie über eine Konstante den Referenz-Stil fest und geben letztendlich wiederum über eine Konstante an, wie die Bezüge umgesetzt werden sollen (xlAbsolute bzw. XlRelativ). 3.4 Bereiche auswerten Standardmäßig werden Funktionen wie SUMME, SVERWEIS, ZÄHLENWENN usw. über die normale Oberfläche von Excel in die Tabellen eingetragen. Selbstverständlich besteht auch die Möglichkeit, diese Funktionen über VBA in die einzelnen Zellen zu schreiben. Dafür können ganze Bereiche diesen Funktionen übergeben werden, um das Ergebnis dieser Funktionen auf schnellste Art und Weise zu ermitteln. Lernen Sie auf den nächsten Seiten ein paar typische Praxisbeispiele kennen. 3.4.1 Einen Bereich summieren Im ersten Beispiel aus diesem Abschnitt soll ein Datenbereich aufsummiert werden. Dazu werden in einer Tabelle ein paar Umsätze in Spalte B erfasst. In Spalte A wird das dazugehörige Datum abgelegt. Ermitteln Sie jetzt die Summe aller Umsätze, die in der Spalte B stehen und setzen hierfür das Makro in Listing 3.21 ein. Listing 3.21: Sub SummeBilden() Alle Umsätze Dim Bereich As Range aus Spalte B summieren Set Bereich = Sheets("Tabelle14").Columns(2) MsgBox "Die Summe aller Beträge ergibt: " & _ Application.WorksheetFunction.Sum(Bereich), vbInformation End Sub 118 Bereiche auswerten jetzt lerne ich Deklarieren Sie im ersten Schritt des Makros in Listing 3.21 eine Objektvariable vom Typ Range und geben über die Anweisung Set bekannt, wo der Bereich liegt, der summiert werden soll. Danach wird die Tabellenfunktion SUMME durch Verwendung des Objekts WorksheetFunction aufgerufen. Dieses Objekt enthält nahezu alle Tabellenfunktionen, die standardmäßig in Excel eingesetzt werden können. Unter anderem auch die Funktion Sum, die den vorher definierten Bereich übergeben bekommt. Nun wird am Ende des Makros das Ergebnis der Formel am Bildschirm in einem extra Fenster dargestellt. Bild 3.19: Kontrollieren Sie die Summe in der Statusleiste Alle VBA-Tabellenfunktionen müssen in der englischen Syntax angegeben werden, was leicht verwirren kann, wenn Sie täglich mit den deutschen Tabellenfunktionen in der normalen Arbeitsoberfläche arbeiten. Microsoft bietet Ihnen aber eine Unterstützung durch die Auslieferung einer extra Tabelle an, in der eine Gegenüberstellung der deutschen und englischen Funktionen enthalten ist. Diese Arbeitsmappe heißt VBAListe.xls und befindet sich in einem Unterverzeichnis von Office. Suchen Sie diese Arbeitsmappe am besten mit der Windows-SUCHEN-Funktion. 1 119 3 Zellen und Bereiche programmieren jetzt lerne ich 3.4.2 Einen Bereich bedingt summieren Sollen aus einer Tabelle nur bestimmte Werte summiert werden, beispielsweise nur Umsätze, die einen Wert größer als 2.000 Euro aufweisen, dann kann diese Aufgabe über das folgende Makro in Listing 3.22 gelöst werden: Listing 3.22: Sub SummeBildenGrößer2000() Eine bedingte Dim Bereich As Range Summierung Set Bereich = Sheets("Tabelle14").Columns(2) durchführen MsgBox "Die Summe aller Beträge ergibt: " & _ Application.WorksheetFunction.SumIf(Bereich, ">2000"), _ vbInformation End Sub Die Funktion SumIf benötigt in diesem Beispiel zwei Argumente. Im ersten Argument geben Sie den Bereich an, in dem die Daten zu summieren sind. Im zweiten Argument wird die Bedingung für die Summierung angegeben. Bild 3.20: Es werden nur Umsätze summiert, die größer als 2.000 Euro sind 120 Bereiche auswerten 3.4.3 jetzt lerne ich Numerische Werte zählen Im folgenden Beispiel in Listing 3.23 sollen in einer Tabelle alle numerischen Werte gezählt werden. Sub ZählenNumerischeWerte() Dim intz As Integer Dim Bereich As Range Set Bereich = Sheets("Tabelle15").Range("A1:D10") Listing 3.23: Alle numerischen Zellen werden gezählt intz = Application.WorksheetFunction.Count(Bereich) MsgBox "Anzahl der numerischen Werte:" & _ vbLf & intz, vbInformation End Sub Mithilfe der Funktion Count (= ANZAHL) werden nur die numerischen Werte einer Liste gezählt. Der zu überprüfende Bereich, wird direkt im Anschluss an diese Tabellenfunktion in Klammern angegeben. Ist es egal, was in einer Zelle steht, sei es nun ein numerischer oder ein alphanumerischer Wert, dann muss zur Zählung dieser Zellen die Tabellenfunktion CountA (= ANZAHL2) verwendet werden. 1 Bild 3.21: Die Zellen mit numerischem Inhalt werden gezählt 121 3 Zellen und Bereiche programmieren jetzt lerne ich 3.4.4 Eine bedingte Zählung durchführen Beim nächsten Beispiel greifen Sie auf die TABELLE14 zu, in der vorher alle Umsätze summiert wurden, die größer als 2.000 Euro waren. Diese Umsätze sollen nun gezählt werden. Sehen Sie sich dazu das Makro in Listing 3.24 an. Listing 3.24: Sub AnzahlUmsätzeGrößer2000() Eine bedingte Dim Bereich As Range Zählung Set Bereich = Sheets("Tabelle14").Columns(2) durchführen MsgBox "Die Anzahl aller Beträge > 2000 lautet: " & _ Application.WorksheetFunction.CountIf(Bereich, ">2000"), _ vbInformation End Sub Zunächst wird der zu zählende Bereich, in dem die Anzahl der Umsätze ermittelt werden soll, die größer als 2.000 Euro sind, der Funktion CountIf übergeben. Die Bedingung >2000 formulieren Sie gleich im Anschluss daran. Bild 3.22: Alle Umsätze ab einem bestimmten Wertebereich werden gezählt 122 Zellen suchen 3.5 jetzt lerne ich Zellen suchen Das Aufspüren von bestimmten Daten in Tabellen kann entweder über die integrierte SUCHEN-Funktion von Excel oder alternativ über den Einsatz der bedingten Formatierung oder über das Programmieren eines Suchen- und Ersetzen-Makros durchgeführt werden. 3.5.1 Suche in einem bestimmten Bereich durchführen Im folgenden Beispiel in Listing 3.25 wird eine Suche durchgeführt, die sich auf einen bestimmten Bereich einer Tabelle beschränkt. Dabei soll eine eindeutige Nummer im Bereich A1:A10 gefunden werden. Sub Dim Dim Dim NummernSuche() zelle As Range Bereich As Range sBegriff As String Listing 3.25: Eine eindeutige Nummer in einem Bereich finden sBegriff = InputBox("Bitte Zahl eingeben:") If sBegriff = "" Then Exit Sub Set Bereich = Sheets("Tabelle16").Range("A1:A10") Set zelle = Bereich.Find(sBegriff, LookAt:=xlWhole, _ LookIn:=xlValues) If zelle Is Nothing Then MsgBox "Zahl wurde nicht gefunden!" Else MsgBox "Zahl befindet sich in Zelle " & _ zelle.Address End If End Sub Zunächst wird eine Objektvariable vom Typ Range deklariert und danach über die Anweisung Set definiert, wo sich der Bereich befindet, der durchsucht werden soll. Für die Suche wird die Methode Find angewendet. Im ersten Argument der Methode befindet sich der Suchbegriff, nach dem gesucht werden soll. Dieser wurde kurz vorher über eine Inputbox vom Anwender erfasst. Im Argument LookAt kann definiert werden, ob der identische Suchbegriff im Bereich gesucht werden soll oder ob es 123 3 Zellen und Bereiche programmieren jetzt lerne ich auch reicht, wenn der Suchbegriff zu Teilen im Bereich gefunden wird. Im Argument LookIn können Sie festlegen, ob nach Formeltext bzw. nach Werten gesucht werden soll. Damit die Suche nur im definierten Bereich durchgeführt wird, stellen Sie den definierten Bereich direkt vor die Methode. Das Ergebnis der Suche wird in der Objektvariablen Zelle gespeichert. Kann keine Zelle gefunden werden, die dem Suchkriterium entspricht, bleibt diese Variable leer. Über die Prüfung per Anweisung Is Nothing kann das diesbezügliche Suchergebnis angezeigt werden. Im anderen Fall lassen sich zum Beispiel die Zellenkoordinaten der Fundzelle über die Eigenschaft Address anzeigen. Bild 3.23: Die Fundstelle wurde ermittelt 3.5.2 Nach einem Datum suchen Im folgenden Beispiel sind in Spalte A Datumsangaben erfasst. Die Aufgabe besteht nun darin, die Zelle, die das aktuelle Tagesdatum enthält, aufzuspüren. Starten Sie zu diesem Zweck das Makro in Listing 3.26. Listing 3.26: Sub DatumSuche() Das aktuelle Dim zelle As Range Tagesdatum Dim Bereich As Range finden Set Bereich = Sheets("Tabelle17").Columns(1) Set zelle = Bereich.Find(Date, LookAt:=xlWhole, LookIn:=xlValues) 124 Zellen suchen jetzt lerne ich If zelle Is Nothing Then MsgBox "Das aktuelle Datum wurde nicht gefunden!" Else MsgBox "Das aktuelle Datum " & Date & " _ befindet sich in Zelle " & zelle.Address End If End Sub Übergeben Sie der Methode Find als Suchbegriff das aktuelle Tagesdatum, das mit der Funktion Date abgefragt werden kann. Die übrigen Beschreibungen entnehmen Sie bitte aus den Erläuterungen des Listings 3.25. Bild 3.24: Die Zellenadresse des aktuellen Tagesdatums finden 125 jetzt lerne ich KAPITEL 4 Zeilen und Spalten programmieren Wie schon im vorherigen Kapitel bei Zellen und Bereichen dargestellt, wird bei der Programmierung von Zeilen und Spalten ebenso das Objekt Range eingesetzt. Lernen Sie in diesem Kapitel anhand praktischer Beispiele, wie Sie Zeilen und Spalten ansprechen und programmieren können. Alle vorgestellten Makros finden Sie auf der mitgelieferten CDROM im Verzeichnis Kap04 unter dem Namen ZeilenSpalten.xls. 4.1 Anzahl der verwendeten Zeilen ermitteln / Die Anzahl der verwendeten Zeilen in einem Tabellenblatt lässt sich ermitteln, indem die Eigenschaft UsedRange verwendet wird. Diese ermittelt den verwendeten Bereich in dem Tabellenblatt. Mit der Eigenschaft Rows sowie der Funktion Count werden dann die Zeilen im verwendeten Bereich gezählt. Sub AnzahlVerwendeteZeilen() Dim lngZ As Long lngZ = ActiveSheet.UsedRange.Rows.Count MsgBox lngZ & " verwendete Zeilen in der aktiven Tabelle!" Listing 4.1: Die Anzahl der verwendeten Zeilen wird abgefragt End Sub 127 4 Zeilen und Spalten programmieren jetzt lerne ich 1 Achten Sie darauf, dass bei der Programmierung von Zeilen zur Sicherheit eine Variable vom Typ Long definiert ist, insbesondere wenn sehr viele Zeilen bearbeitet werden. Der Datentyp Integer kann nur Zahlenwerte bis 32.767 speichern. Würde in Listing 4.1 eine Integer-Variable eingesetzt und wäre die Anzahl der verwendeten Zellen größer als besagter Wert, käme es zu einem Überlauffehler. Bild 4.1: Die Anzahl der verwendeten Zeilen ermitteln 4.2 Anzahl der verwendeten Spalten ermitteln Soll die Anzahl der verwendeten Spalten einer Tabelle ermittelt werden, dann starten Sie das Makro in Listing 4.2. Listing 4.2: Sub AnzahlVerwendeteSpalten() Die Anzahl der Dim intz As Integer verwendeten Spalten wird intz = ActiveSheet.UsedRange.Columns.Count abgefragt MsgBox intz & " Spalten werden in der Tabelle verwendet!" End Sub Bei der Ermittlung der Anzahl der belegten Spalten brauchen Sie sich um die Variablendefinition keine Sorgen zu machen. Da in einem Excel-Tabellenblatt so oder so nur 256 Spalten vorhanden sind, reicht eine Variable vom Typ Integer bei weitem aus. 128 Zeilenhöhe und Spaltenbreite justieren jetzt lerne ich Bild 4.2: Die Anzahl der verwendeten Spalten ermitteln 4.3 Zeilenhöhe und Spaltenbreite justieren Bei der Einstellung für die richtige Spaltenbreite bzw. die korrekte Zeilenhöhe kann entschieden werden, ob die Einstellung für das ganze Tabellenblatt oder nur für bestimmte Spalten und Zeilen gelten soll. Im ersten Beispiel werden in dem Tabellenblatt TABELLE2 die Spalten A bis E sowie die Zeilen 1 bis 4 angepasst. Dazu werden zur Festlegung der Spaltenbreite die Eigenschaften EntireColumn und ColumnWidth eingesetzt. Um die Zeilenhöhe anzupassen, werden die Eigenschaften EntireRow und RowHeight auf das Objekt Range angewendet. Alternativ können Sie die Zeilen und Spalten auch über die Eigenschaften Columns und Rows direkt ansprechen. Sub SpaltenZeilenEinstellen() With Sheets("Tabelle2") .Range("A:E").EntireColumn.ColumnWidth = 15 .Range("1:4").EntireRow.RowHeight = 20 Listing 4.3: Zeilenhöhe und Spaltenbreite einstellen 'oder .Columns("A:E").ColumnWidth = 15 .Rows("1:4").RowHeight = 20 129 4 Zeilen und Spalten programmieren jetzt lerne ich End With End Sub Die Einheit für die Spaltenbreite bzw. die Zeilenhöhe entspricht der Breite eines Zeichens in der Formatvorlage STANDARD. Bei Proportionalschriftarten wird die Breite des Zeichens 0 (Null) verwendet. Bild 4.3: Spalten- und Zeileneinstellungen verändern 4.4 Spaltenbreiten automatisch anpassen Es ist möglich, dass Excel selbst die Spaltenbreiten automatisch einstellt. Dies geschieht in Abhängigkeit des Inhalts und unter Verwendung der Methode AutoFit, die die angegebenen Spalten automatisch in der richtigen Breite einstellt. Sicher kennen Sie die Reaktion von Excel, wenn eine Spalte zu klein ist und der eingegebene Zahlenwert nicht mehr angezeigt werden kann: Excel füllt die Zelle dann scheinbar mit dem Zeichen # auf. Erst durch manuelle Korrektur der Spaltenbreite oder Anpassung durch einen Doppelklick auf die Begrenzung des entsprechenden Spaltenkopfes, wird die Spalte so vergrößert, dass der komplette Zelleninhalt angezeigt werden kann. Dieser Vorgang kann auch ganz gezielt über ein Makro vorgenommen werden. 130 Zeilen bedingt ein- und ausblenden Sub SpaltenbreitenEinstellenAutomatisch() Sheets("Tabelle1").Columns("A:D").AutoFit End Sub 4.5 jetzt lerne ich Listing 4.4: Die Methode AutoFit passt Ihre Spalten nach dem Platzbedarf an Zeilen bedingt ein- und ausblenden Die folgende Aufgabe verwendet den Aufbau der Tabelle in Abbildung 4.4. Bild 4.4: Einige leere Zeilen »stören« Das Makro in Listing 4.5 entfernt alle Zeilen, die in Spalte A eine leere Zelle aufweisen. Sub AusblendenLeereZeilen() Dim Zeile As Integer Dim ZeileMax As Integer Listing 4.5: Zeilen werden ausgeblendet With Sheets("Tabelle3") ZeileMax = .Range("A65536").End(xlUp).Row For Zeile = 1 To ZeileMax 131 jetzt lerne ich 4 Zeilen und Spalten programmieren If .Cells(Zeile, 1).Value = "" Then .Rows(Zeile).Hidden = True End If Next Zeile End With End Sub Zunächst wird mithilfe der Eigenschaft End die letzte belegte Zelle in Spalte A ermittelt. Dabei wird dieser Eigenschaft die Richtungskonstante xlUp übergeben, ausgehend von der letzten Zelle der Tabelle aus der ersten Spalte, also A65536. Von dieser Zelle wird die zuletzt belegte Zelle in Spalte A ermittelt, indem Excel von ganz unten bis zu dieser Zelle nach oben »hüpft«. Da für die Schleife nicht die Adresse dieser Zelle benötigt wird, sondern eben die Zeilennummer, nutzen wir noch die Eigenschaft Row, die die Zeilennummer der letzten verwendeten Zelle aus Spalte A zurückgibt. Danach wird in dem Makro Zeile für Zeile in einer For...Next-Schleife abgearbeitet. Innerhalb der Schleife wird geprüft, ob die jeweilige Zelle in Spalte A leer ist. Wenn ja, dann wird die komplette Zeile adressiert durch Übergabe der Zeilennummer aus der Variablen Zeile an die Eigenschaft Rows. Über die Eigenschaft Hidden und die Zuweisung des Wertes True, wird nun diese Zeile ausgeblendet. Das gewünschte Ergebnis finden Sie in Abbildung 4.5. Bild 4.5: Alle »leeren« Zeilen sind jetzt ausgeblendet 132 Spalten bedingt ein- und ausblenden jetzt lerne ich Um die ausgeblendeten Zeilen wieder sichtbar zu machen, tauschen Sie im Makro in Listing 4.5 innerhalb der Schleife den Wert True gegen den Wert False aus. Noch schneller geht es mit dem folgenden »pfiffigen« Einzeiler im Listing 4.6. Sub EinblendenAlleZeilen() Sheets("Tabelle3").Rows.Hidden = False End Sub Listing 4.6: Alle versteckten Zeilen wieder einblenden Die Auflistung Rows enthält alle Zeilen einer Tabelle, sofern diese Auflistung keine Zeilennummer in Klammern enthält. Durch Setzen der Eigenschaft Hidden auf den Wert False, werden alle versteckten Zeilen in der Tabelle wieder eingeblendet. 4.6 Spalten bedingt ein- und ausblenden Im folgenden Beispiel in Listing 4.7 werden in der TABELLE4 alle Spalten, die ein Wochenende enthalten, ausgeblendet. Sehen Sie sich zunächst die Abbildung 4.6 an. Bild 4.6: Eine Datumsleiste mit Wochenenden und Arbeitstagen 133 jetzt lerne ich 4 Zeilen und Spalten programmieren Listing 4.7: Sub AusblendenWochenenden() Alle Wochen- Dim Spalte As Integer endspalten Dim SpalteMax As Integer werden ausgeblendet With Sheets("Tabelle4") SpalteMax = .Range("IV1").End(xlToLeft).Column For Spalte = 1 To SpalteMax If Weekday(.Cells(1, Spalte).Value) = 1 Or _ Weekday(.Cells(1, Spalte).Value) = 7 Then .Columns(Spalte).Hidden = True End If Next Spalte End With End Sub Zunächst wird ermittelt, wie viele Spalten in TABELLE4 verwendet werden. Dazu setzen Sie die Eigenschaft End ein, der die Richtungskonstante xlToLeft übergeben wird. Wichtig ist hierbei auch, dass die letzte Zelle der Tabelle aus der ersten Zeile, also IV1, vorangestellt wird. Von dieser Zelle aus soll nämlich die zuletzt belegte Zelle in Zeile 1 ermittelt werden. Es wird demnach von ganz rechts außen nach links »gehüpft«, bis die letzte Zelle in Zeile 1 ermittelt ist. Da wir aber für die Schleife nicht die Adresse dieser Zelle benötigen, sondern eben die Spaltennummer, wird noch die Eigenschaft Column angehängt, die die Spaltennummer der letzten Zelle aus Zeile 1 zurückgibt. Anschließend werden die einzelnen Spalten in der Tabelle mithilfe einer For...Next-Schleife nacheinander angesteuert. Innerhalb der Schleife wird überprüft, ob in der jeweiligen Zelle aus Zeile 1 ein Wochenenddatum steht. Wenn ja, dann meldet die Funktion Weekday den Rückgabewert 7 (für Samstag) bzw. den Wert 1 (für Sonntag). Die neue Woche beginnt also bei dieser Funktion mit dem Sonntag, was hier nicht bedeuten soll, dass der Sonntag ein neuer Arbeitstag wäre. Hierbei handelt es sich nur um eine Festlegung, die möglicherweise aus dem jüdischen Kalender übernommen wurde, bei dem die Woche jeweils am Sonntag beginnt. 134 »Leere Zeilen« bedingt löschen jetzt lerne ich Wenn also ein Wochenende ermittelt wurde, dann sprechen Sie die Spalte an, indem Sie der Eigenschaft Columns die Spaltennummer aus der Variablen Spalte übergeben. Über die Eigenschaft Hidden und die Zuweisung des Wertes True wird die betroffene Spalte ausgeblendet. Bild 4.7: Alle Wochenenden wurden ausgeblendet Um die ausgeblendeten Spalten wieder sichtbar zu machen, tauschen Sie im Makro in Listing 4.7 innerhalb der Schleife den Wert True gegen den Wert False aus. Schneller geht es noch mit dem folgenden Einzeiler in Listing 4.8. Sub EinblendenAlleSpalten() Sheets("Tabelle4").Columns.Hidden = False Listing 4.8: Alle Spalten wieder einblenden End Sub Die Auflistung Columns enthält alle Spalten einer Tabelle, sofern dieser Auflistung keine Spaltennummer in Klammern mitgegeben wurde. Durch Setzen der Eigenschaft Hidden auf den Wert False, werden alle Spalten wieder eingeblendet. 4.7 »Leere Zeilen« bedingt löschen Bei der nächsten Aufgabenstellung aus der Praxis sollen, einmal ganz allgemein gesehen, bestimmte Zeilen aus einer Tabelle gelöscht werden. In der TABELLE5 wurden in der Spalte A einmal einige numerische Daten sowie auch alphanumerische Daten erfasst. Die Aufgabe besteht jetzt darin, alle alphanumerischen Zellen aus Spalte A und somit eben die komplette Zeile zu löschen. 135 jetzt lerne ich 4 Zeilen und Spalten programmieren Bild 4.8: In Spalte A sind einige Eingaben vorgenommen worden Nun werden alle Zeilen mit »Texten« gelöscht, indem das Makro in Listing 4.9 gestartet wird. Listing 4.9: Die bedingte Löschung von Zeilen wird durchgeführt Sub AlphaNumerischeZeilenEntfernen() Dim Zeile As Integer Dim ZeileMax As Integer With Sheets("Tabelle5") ZeileMax = .Range("A65536").End(xlUp).Row For Zeile = ZeileMax To 2 Step -1 If IsNumeric(.Cells(Zeile, 1).Value) = True Then ' hier passiert nichts! Else .Rows(Zeile).Delete End If Next Zeile End With End Sub 136 Wirklich nur komplett leere Zeilen löschen jetzt lerne ich Ermitteln Sie im ersten Schritt die letzte verwendete Zelle aus Spalte A. In der Praxis hat sich gezeigt, dass Sie die Schleife besser von unten nach oben abarbeiten, indem Sie der Schleife als Startzeile zunächst die letzte Zeilennummer übergeben und sich dann Zeile für Zeile nach oben durcharbeiten. Da bei jedem Schleifendurchlauf eine Zeile weiter nach oben positioniert werden muss, wird der Schleifenstruktur die Schrittweite -1 übergeben. Innerhalb der Schleife wird mithilfe der Funktion IsNumeric überprüft, ob der Wert der jeweiligen Zelle aus Spalte A numerisch bzw. alphanumerisch ist. Trifft der zweite Fall zu, wird die ganze Zeile über die Methode Delete gelöscht. Damit Excel weiß, welche Zeile entfernt werden soll, wird der Rows-Auflistung die zu löschende Zeile durch die Variable Zeile bekannt gegeben. Bild 4.9: Alle »Textzeilen« wurden gelöscht 4.8 Wirklich nur komplett leere Zeilen löschen Beim vorherigen Beispiel wurden Zeilen komplett gelöscht, wenn in der jeweiligen Zelle aus Spalte A kein Eintrag verzeichnet war. Aber gerade bei größeren Tabellen kann es durchaus sein, dass beispielsweise in Spalte A tatsächlich nichts steht, jedoch in einer weiter rechts liegenden Spalte. Das folgende Makro in Listing 4.10 prüft vor der Löschung der kompletten Zeile, ob diese wirklich ohne Inhalt ist. Sehen Sie sich zum besseren Verständnis die Abbildung 4.10 an. 137 jetzt lerne ich 4 Zeilen und Spalten programmieren Bild 4.10: Nur die Zeilen 3 und 9 sind wirklich komplett leer Listing 4.10: Vor der Löschung erfolgt eine Prüfung, ob die Zeile wirklich komplett leer ist Sub LeerZeilenLöschen() Dim Zeile As Integer Dim ZeileMax As Integer With Tabelle7 ZeileMax = .Range("A65536").End(xlUp).Row For Zeile = ZeileMax To 1 Step -1 If Application.WorksheetFunction.CountA(Rows(Zeile)) = 0 Then .Rows(Zeile).Delete End If Next Zeile End With End Sub Über die Funktion CountA wird ermittelt, ob in der jeweiligen Zeile ein Eintrag vorgenommen wurde. Wenn ja, dann werden hier die Einträge gezählt. Ob es sich dabei um Zahlen oder Texte handelt, ist egal. Wird als Ergebnis dieser »Abfrage« der Wert 0 zurückgegeben, dann ist die Zeile wirklich komplett leer und kann über die Methode Delete entfernt werden. 138 Doppelte Zeilen löschen jetzt lerne ich Bild 4.11: Das Ergebnis – es wurden nur wirklich leere Zeilen gelöscht 4.9 Doppelte Zeilen löschen Wenn Daten in einer Liste aus Versehen doppelt erfasst werden, dann ist das für das Ergebnis einer darauf basierenden Auswertung sehr ungeschickt. Insbesondere dann, wenn durch den Fehler nun doppelte Kosten berechnet werden. Oder es entsteht der Eindruck, dass die eine oder andere Rechnung eventuell doppelt bezahlt wurde. Oder es passiert, dass der gleiche Artikel gleich mehrfach in Ihrem Datenbestand auftaucht. Im folgenden Beispiel wurden in der TABELLE6 einige Artikelnummern erfasst. Sehen Sie sich dazu einmal die Abbildung 4.12 an. Bild 4.12: Einige Artikelnummern sind doppelt erfasst 139 jetzt lerne ich 4 Zeilen und Spalten programmieren Die Artikelnummern 4711 und 4712 sind in der Liste mehrfach vorhanden. Entfernen Sie jetzt diese doppelten Zeilen, indem Sie das Makro in Listing 4.11 starten. Listing 4.11: Sub DoppelteZeilenEntfernen() Doppelte Dim Zeile As Integer Datensätze Dim ZeileMax As Integer entfernen With Sheets("Tabelle6") ZeileMax = .Range("A65536").End(xlUp).Row .Columns(1).Sort Key1:=Range("A1"), Order1:=xlAscending, Header:= _ xlGuess, OrderCustom:=1, MatchCase:=False, _ Orientation:=xlTopToBottom For Zeile = ZeileMax To 2 Step -1 If .Cells(Zeile, 1).Value = .Cells(Zeile - 1, 1).Value Then .Rows(Zeile).Delete End If Next Zeile End With End Sub Der Trick bei diesem Makro besteht darin, dass die Liste zunächst einmal sortiert wird. Danach wird die jeweils aktuell ausgewählte Zelle mit der eine Zeile weiter oben liegenden Zelle verglichen. Weisen beide Zellen den gleichen Inhalt auf, kann eine Zeile durch Anwendung der Methode Delete entfernt werden . 140 Zeilen einfügen jetzt lerne ich Bild 4.13: Alle doppelten Zeilen wurden entfernt 4.10 Zeilen einfügen Auch das automatische Einfügen von Zeilen in einer Tabelle kann oft nützlich sein. Beim folgenden Beispiel gehen wir von der folgenden Tabelle in der Abbildung 4.14 aus. In der darauf abgebildeten Tabelle sind einige Datumsangaben in der Spalte A eingegeben worden. Ihre Aufgabe besteht nun darin, immer dann, wenn sich ein Monatswechsel ergibt, eine Leerzeile einzufügen. Bild 4.14: Die Ausgangssituation – eine Tabelle mit Datumsangaben 141 jetzt lerne ich 4 Zeilen und Spalten programmieren Um nach jedem Monatswechsel eine Leerzeile einzufügen, starten Sie zu diesem Zweck das Makro in Listing 4.12. Listing 4.12: Beim »Gruppenwechsel« eine Leerzeile einfügen Sub ZeileEinfügen() Dim Zeile As Integer Dim ZeileMax As Integer With Sheets("Tabelle8") ZeileMax = .Range("A65536").End(xlUp).Row For Zeile = ZeileMax To 2 Step -1 If Month(.Cells(Zeile, 1).Value) _ <> Month(.Cells(Zeile - 1, 1).Value) Then .Cells(Zeile, 1).EntireRow.Insert End If Next Zeile End With End Sub Zunächst wird, wie in den vorangegangenen Aufgaben beschrieben, die letzte belegte Zelle in Spalte A ermittelt. Nun wird mit einer For...Next-Schleife die Tabelle Zeile für Zeile abgearbeitet, beginnend bei der letzten Zelle bis hoch zur Zelle A2. Innerhalb der Schleife wird das Datum in der aktuellen Zelle mit dem Datum in der vorhergehenden verglichen und geprüft, ob sich der Monat geändert hat. Der Monat wird über die Funktion Month abgefragt und liefert bei Überprüfung eines Datums einen Wert zwischen 1 und 12 zurück. Wird ein Monatswechsel festgestellt, dann wird mithilfe der Eigenschaft EntireRow und der Methode Insert eine neue Zeile eingefügt. 142 Zeilen einfügen und Summen bilden jetzt lerne ich Bild 4.15: Die leeren Zeilen wurden an der richtigen Stelle eingefügt 4.11 Zeilen einfügen und Summen bilden Gehen Sie nun noch einen Schritt weiter und bilden zusätzlich zum Einfügen von Zeilen auch noch Zwischensummen. Sehen Sie sich zunächst die Abbildung 4.16 an. Bild 4.16: Diese Liste soll ausgewertet werden 143 4 Zeilen und Spalten programmieren jetzt lerne ich Um die TABELLE9 mit variablen Summenzeilen getrennt nach Kostenstellen auszustatten, starten Sie das Makro in Listing 4.13. Listing 4.13: Sub SummenReinpacken() Dynamische Dim intz As Integer Summen Dim intBeginn As Integer bilden With Sheets("Tabelle9") intz = 2 intBeginn = 2 Do Until .Cells(intz, 1).Value = "" If .Cells(intz, 1).Value <> .Cells(intz + 1, 1).Value Then .Cells(intz + 1, 1).EntireRow.Insert .Cells(intz + 1, 1).Value = "Summe:" .Cells(intz + 1, 4).FormulaLocal = _ "=SUMME(D" & intBeginn & ":D" & intz & ")" .Cells(intz + 1, 5).FormulaLocal = _ "=SUMME(E" & intBeginn & ":E" & intz & ")" .Cells(intz + 1, 1).EntireRow.Font.Bold = True intz = intz + 1 intBeginn = intz + 1 End If intz = intz + 1 Loop End With End Sub In einer Schleife wird die TABELLE9 Zeile für Zeile durchlaufen und dabei wird verglichen, ob in Spalte A die Kostenstellennummer der aktuelle Zelle mit der darunter liegenden übereinstimmt. Fällt dieser Vergleich negativ aus, muss an dieser Stelle über die Methode Insert eine neue Zeile eingefügt werden. Es folgt die Beschriftung der noch leeren Zeile. In Spalte A wird hierbei das Wort SUMME über die Eigenschaft Value eingetragen. Mithilfe der Eigenschaft FormulaLocal wird nun die benötigte Summenzeile eingefügt. Dabei wird der Formel 144 Zeilen einfügen und Summen bilden jetzt lerne ich der Start- sowie der Endpunkt der jeweiligen Kostenstelle übergeben. Über die Eigenschaft Bold, wird dieser Summenzeile der Schriftschnitt FETT zugewiesen. Bild 4.17: Einfügen von Zeilen und Summen in einem Schritt Möchten Sie die Summenzeilen auf schnellstem Wege wieder aus der Tabelle entfernen und damit die vorherige Aktion wieder rückgängig machen, kann das folgende Makro in Listing 4.14 verwendet werden. Sub SummenRausNehmen() Dim intz As Integer intz = 2 With Sheets("Tabelle9") Listing 4.14: Alle Summenzeilen werden entfernt Do Until .Cells(intz, 1).Value = "" If .Cells(intz, 1).Value = "Summe:" Then .Cells(intz, 1).EntireRow.Delete intz = intz – 1 End If intz = intz + 1 145 4 Zeilen und Spalten programmieren jetzt lerne ich Loop End With End Sub In einer Do Until...Loop-Schleife werden alle Zeilen der TABELLE9 so lange angesteuert, bis in Spalte A kein Inhalt mehr gefunden wird. Innerhalb dieser Schleife erfolgt eine Prüfung der jeweiligen Zelle in Spalte A, ob dort der Text SUMME: auftaucht. Sofern dies zutrifft, wird die Methode Delete angewendet, um die komplette Zeile (=EntireRow) zu entfernen. 4.12 Spalten und Zeilen formatieren Kennen Sie vielleicht noch das Druckpapier, das meist in Rechenzentren für Ausdrucke verwendet wurde? Auf diesem Papier wurde jede zweite Zeile meist in der Farbe Grün dargestellt. Dies unterstützt die Lesbarkeit von großen Datentabellen und dieser Look kann auch für eigene Tabellen verwendet werden. Starten Sie dazu das Makro in Listing 4.15. Listing 4.15: Sub JedeZweiteZeileFärben() Jede zweite Dim intz As Long Zeile einfärben For intz = 1 To Selection.Rows.Count If intz Mod 2 = 1 Then Selection.Rows(intz).Interior.ColorIndex = 4 End If Next intz End Sub Über die Methode Count werden die Zeilen markiert. Der Operator Mod wird verwendet, um das Ergebnis bzw. den Rest der Division der beiden Zahlen intz und 2 zu ermitteln. Wird dabei der Wert 1 zurückgegeben, dann werden die in der Markierung befindlichen Zeilen mit der Hintergrundfarbe GRÜN eingefärbt. 146 Spalten und Zeilen formatieren jetzt lerne ich Bild 4.18: Jede zweite Zeile in der Markierung wird eingefärbt Selbstverständlich können Sie mit ein paar Handgriffen, diese Funktionalität auch für Spalten verfügbar machen. Starten Sie zu diesem Zweck das Makro in Listing 4.16. Sub JedeZweiteSpalteFärben() Dim intz As Integer For intz = 1 To Selection.Columns.Count Listing 4.16: Jede zweite Spalte einfärben If intz Mod 2 = 1 Then Selection.Columns(intz).Interior.ColorIndex = 4 End If Next intz End Sub Über die Methode Count werden die markierten Spalten gezählt. Wie im vorangegangenen Beispiel wird der Operator Mod verwendet, um den Rest der Division der beiden Zahlen intz und 2 zu ermitteln. Wird dabei der Wert 1 zurückgegeben, dann färben Sie die in der Markierung befindlichen Spalten mit der Hintergrundfarbe GRÜN. 147 jetzt lerne ich 4 Zeilen und Spalten programmieren Bild 4.19: Jede zweite Spalte in der Markierung wird eingefärbt 4.13 Zeilen sortieren Zur besseren Übersichtlichkeit lassen sich Zeilen nach maximal drei unterschiedlichen Kriterien, jeweils absteigend oder aufsteigend, sortieren. Im folgenden Beispiel ist in der Abbildung 4.20 eine Liste mit Umsätzen, Datumsangaben sowie Verkäufern dargestellt. Bild 4.20: Eine unsortierte Umsatzliste 148 Zeilen sortieren jetzt lerne ich Sortieren Sie jetzt diese Liste nach folgenden Kriterien: zuerst nach Datum, dann nach Verkäufer und zum Abschluss nach dem Umsatz. Sub DatenSortieren() With Sheets("Tabelle12") .UsedRange.Sort Key1:=.Range("A1"), Order1:=xlAscending, _ Key2:=.Range("C1"), Order2:=xlAscending, _ Key3:=.Range("B1"), Order3:=xlAscending, _ Header:=xlYes, MatchCase:=False, _ Orientation:=xlTopToBottom Listing 4.17: Zeilen nach mehreren Kriterien sortieren End With End Sub Für die Sortierung wird die Methode Sort angewendet. Die Methode kann maximal drei unterschiedliche Sortierfelder (Key1 bis Key3) verwenden. Das Argument Order bestimmt die Sortierreihenfolge. Es besteht dabei die Auswahl zwischen der Konstanten xlAscending, die das Sortierfeld (Key) in aufsteigender Reihenfolge sortiert, und der Konstanten xlDescending, die das Sortierfeld in absteigender Reihenfolge anordnet. Im Argument Header besteht die Möglichkeit festzulegen, ob der Bereich mit oder ohne Überschrift sortiert werden soll. Über das Argument MatchCase lässt sich bestimmen, ob die Sortierung Groß- und Kleinschreibung unterscheiden soll. Bild 4.21: Die Liste wurde entsprechend der Definition sortiert 149 jetzt lerne ich 4 Zeilen und Spalten programmieren 4.14 Eine Unikatsliste erstellen Bei der folgenden Aufgabe soll aus einer Liste, in der etliche Einträge doppelt vorhanden sind, eine so genannte Unikatsliste erstellt werden. In einer Unikatsliste wird jeder Wert nur einmalig aufgeführt. Sehen Sie sich zunächst einmal die Abbildung 4.22 an. Bild 4.22: In dieser Liste sind doppelte Konten erfasst Die Konten 5560 und 7689 tauchen mehrfach in der Liste auf. Erstellen Sie jetzt ab Zelle C1 eine Liste, in der jedes Konto nur einmal eingefügt wird. Eine solche eindeutige Liste lässt sich beispielsweise als Datenquelle für ein Kombinationsfeld oder Listenfeld nutzen. Listing 4.18: Sub UnikatslisteErstellen() Eine Unikatsliste per Makro With Sheets("Tabelle13") erstellen Range("A1:A" & .UsedRange.Rows.Count).AdvancedFilter _ Action:=xlFilterCopy, CopyToRange:=.Range("C1"), Unique:=True End With End Sub Übergeben Sie der Methode AdvancedFilter den Bereich, der die Daten enthält, für die Überprüfung. Die Angabe des Bereichs ist auf Basis der genutzten Zeilen in der Tabelle dynamisch und wird über die Anweisung UsedRange.Rows.Count ermittelt. 150 Den AutoFilter bedienen jetzt lerne ich Die Methode AdvancedFilter hat mehrere Argumente. Im ersten Argument Action wird über die Konstante xlFilterCopy festgelegt, dass die ursprüngliche Liste gefiltert wird. Dabei wird die Liste nicht überschrieben, sondern nur woanders hinkopiert. Die Einfügeposition für die kopierte Liste wird in dem Argument CopyToRange bekannt gegeben. Im letzten Argument Unique, das den Wert True zugewiesen bekommt, wird angegeben, dass nur »einmalige« Daten (jedes Konto nur einmal) in die neue Liste gefiltert werden. Bild 4.23: Ab Zelle C1 taucht jedes Konto nur einmal in der Liste auf 4.15 Den AutoFilter bedienen Ein AutoFilter lässt sich für eine Tabelle aktivieren, indem Sie aus dem Menü DATEN den Befehl FILTER/AUTOFILTER wählen. Danach blendet Excel für jede Spalte im benutzten Bereich einen AutoFilter ein. Zunächst befinden sich alle AutoFilter im Ruhezustand, d. h. es wird noch keine Filterung vorgenommen, was auch am schwarzen Pfeil der AutoFilter erkennbar ist. AutoFilter, bei denen schon Filterkriterien eingestellt sind, haben einen blauen Pfeil. 4.15.1 AutoFilter einblenden Beim folgenden Makro in Listing 4.19 wird der AutoFilter, sofern er noch nicht verfügbar ist, eingeblendet. 151 jetzt lerne ich 4 Zeilen und Spalten programmieren Listing 4.19: Sub AutoFilterEinschalten() Den AutoFilter bei Bedarf Sheets("Tabelle14").Activate einschalten If Not ActiveSheet.AutoFilterMode = True Then Range("A1").AutoFilter End If End Sub Die Eigenschaft AutoFilterMode liefert den Wert True, wenn die Dropdown-Pfeile für AutoFilter momentan in dem Tabellenblatt sichtbar sind. Liefert diese Eigenschaft den Wert False zurück, dann blenden Sie die AutoFilter mithilfe der Methode AutoFilter ein. Bild 4.24: Den AutoFilter einschalten 4.15.2 Eine bestimmte Region filtern Filtern Sie im folgenden Beispiel alle Zeilen, die der Region SÜD zugeordnet sind. Hierzu kann das Makro in Listing 4.20 gestartet werden. Listing 4.20: Sub RegionFiltern() Alle Daten der Region Süd With Sheets("Tabelle14") anzeigen If Not .AutoFilterMode = True Then .Range("A1").AutoFilter End If 152 Den AutoFilter bedienen jetzt lerne ich .Range("A1").AutoFilter Field:=1, Criteria1:="Süd", _ Operator:=xlAnd, , VisibleDropDown:=True End With End Sub Mit der AutoFilter-Methode wurde der Spalte A (Field:=1) das Anzeigekriterium für Zeilen bekannt gegeben (Criteria1:="Süd"). Bei dem Argument Operator gibt es eine größere Auswahl aus mehreren Konstanten, die Sie der folgenden Tabelle entnehmen können. Konstante Erklärung xlAnd Es müssen zwei Kriterien erfüllt sein (Criteria1 und Criteria2). xlOr Es muss entweder das eine oder das andere Kriterium erfüllt sein (Criteria1 oder Criteria2). xlTop10Items Die n-höchsten Einträge aus der Liste werden angezeigt (Absolutbetrachtung). xlTop10Percent Die n-höchsten Einträge aus der Liste werden angezeigt (prozentuale Betrachtung). xlBottom10Items Die n-niedrigsten Einträge aus der Liste werden angezeigt (Absolutbetrachtung). xlBottom10Percent Die n-niedrigsten Einträge aus der Liste werden angezeigt (prozentuale Betrachtung). Tabelle 4.1: Die OperatorKonstanten der Methode Auto-Filter Das Argument Criteria2 stellt ein mögliches zweites Kriterium dar. Es wird zusammen mit Criteria1 und dem Argument Operator zum Erstellen von zusammengesetzten Kriterien verwendet. Das letzte Argument VisibleDropDown ist standardmäßig mit dem Wert True voreingestellt, was bedeutet, dass die Dropdown-Pfeile für das gefilterte Feld angezeigt werden. Wenn das Argument auf den Wert False gesetzt wird, werden die Dropdown-Pfeile des AutoFilters für das gefilterte Feld ausgeblendet. 153 jetzt lerne ich 4 Zeilen und Spalten programmieren 4.15.3 Den AutoFilter entfernen Um wieder alle Zeilen anzuzeigen und den Datenfilter auszublenden, starten Sie das Makro in Listing 4.21. Listing 4.21: Sub FilterEntfernen() Der AutoFilter wird ausge- With Sheets("Tabelle14") blendet .AutoFilterMode = False End With End Sub Den AutoFilter schalten Sie aus, indem Sie die Eigenschaft AutoFilterMode auf den Wert False setzen. Dabei werden die Dropdown-Pfeile des AutoFilters entfernt sowie auch alle eingestellten Filterkriterien zurückgesetzt. Soll lediglich die Auswahl im Filter selbst wieder entfernt werden, dann kann das Makro in Listing 4.22 angewendet werden. Listing 4.22: Sub AuswahlImFilterZurücksetzen() Die Auswahl im Filter wird With Sheets("Tabelle14") zurückgesetzt If Not .AutoFilterMode = True Then .Range("A1").AutoFilter End If .Range("A1").AutoFilter Field:=1 End With End Sub Nach dem Einstellen des Filterkriteriums (ALLE) werden wieder alle Zeilen angezeigt, der Datenfilter bleibt aber weiterhin eingeblendet. Diese Einstellung wird dann automatisch verwendet, wenn das Argument Criteria für ein Feld nicht definiert wurde. 154 Den AutoFilter bedienen 4.15.4 jetzt lerne ich Die Top-Werte anzeigen Eine beliebte Methode des AutoFilters ist, sich die höchsten bzw. die niedrigsten Werte einer Liste anzeigen zu lassen. Dazu können Sie die so genannte Top10-Einstellung im Filter nutzen. Möchten Sie beispielsweise die höchsten drei Jahresumsätze ermitteln, dann starten Sie das Makro in Listing 4.23. Sub TopWerteAnzeigen() With Sheets("Tabelle14") Listing 4.23: Die größten Umsätze werden angezeigt If Not .AutoFilterMode = True Then .Range("A1").AutoFilter End If .Range("A1").AutoFilter Field:=3, Criteria1:="3", _ Operator:=xlTop10Items End With End Sub Um den AutoFilter mit der Top-Filterung zu beauftragen, wird bei der Methode AutoFilter im Argument Operator die Konstante xlTop10Items angegeben. Damit nur die drei höchsten Werte gefiltert werden, weisen Sie dem Argument Criteria1 die Zahl 3 zu. Bild 4.25: Die höchsten Umsätze aller Regionen werden angezeigt 155 jetzt lerne ich 1 4 Zeilen und Spalten programmieren Handelt es sich bei der Filterung um ein numerisches Feld, dann wird die Anzahl der gefilterten Zeilen in der Statusleiste angezeigt. 4.16 Zeilen und Spalten gliedern Neben dem AutoFilter gibt es in Excel die Möglichkeit, die Daten über Gliederungssymbole auszuwerten. Um in einer Tabelle eine Gliederung einfügen zu können, muss die Tabelle bereits in einem zu gliedernden Zustand vorliegen. Bevor die Gliederung angewendet werden kann, muss der verwendete Bereich ermittelt werden. Dabei kann auf den »Auto-Gliederer« von Excel zurückgegriffen werden. Sehen Sie sich zunächst die Abbildung 4.26 an. Bild 4.26: Die noch ungruppierte Liste Fügen Sie jetzt über das Makro in Listing 4.24 eine Autogliederung ein. Listing 4.24: Sub GliederungEinfügen() Excel nimmt eine Auto- With Sheets("Tabelle15") gliederung vor .UsedRange.AutoOutline End With End Sub 156 Zeilen und Spalten gliedern jetzt lerne ich Mithilfe der Methode AutoLine können Sie eine Gliederung für den benutzten Bereich einer Tabelle erstellen. Bild 4.27: Excel hat Gliederungssymbole zur Verfügung gestellt Soll die Gliederung wieder entfernt werden, wenden Sie die Methode ClearOutline, wie im Makro in Listing 4.25 gezeigt, an. Sub GliederungEntfernen() With Sheets("Tabelle15") Listing 4.25: Die Gliederung wieder entfernen .UsedRange.ClearOutline End With End Sub 157 jetzt lerne ich KAPITEL 5 Tabellen und Diagramme programmieren Lernen Sie in diesem Kapitel, wie Tabellen in Excel programmiert werden können. Die Palette reicht dabei von automatischer Erstellung und Löschung von Tabellen, über diverse Kopier- und Verschiebeaktionen, bis hin zum Schützen von Tabellen sowie weiteren nützlichen Funktionen. Des Weiteren bekommen Sie im zweiten Teil dieses Kapitels einen Einblick wie Diagramme in Excel erstellt und per Makros angepasst werden können. Alle hier vorgestellten Makros finden Sie auf der mitgelieferten CD-ROM im Verzeichnis Kap05 unter den Namen Tabellen.xls und Diagramme.xls. 5.1 1 Tabellen programmieren Im ersten Teil dieses Kapitels lernen Sie einige nützliche Makros kennen, die Tabellen teilweise automatisieren. Jede Tabelle hat eine durch Excel vorgegebene Kapazität von maximal 256 Spalten und maximal 65.536 Zeilen. Daran lässt sich nichts ändern. Die oft aufgestellte Behauptung, eine Mappe könne nur 256 Tabellen aufnehmen, stimmt nicht! Es können beliebig viele Tabellen in einer Arbeitsmappe aufgenommen werden – ob das jedoch allzu viel Sinn 159 5 Tabellen und Diagramme programmieren jetzt lerne ich macht, ist in Bezug auf die Übersichtlichkeit zu bezweifeln. Je größer eine Mappe, umso dramatischer ist ein potenzieller Datenverlust. 5.1.1 Tabellen ansprechen Bevor Sie beginnen, Tabellen zu programmieren, lernen Sie zunächst weitere Möglichkeiten kennen, wie Tabellen angesprochen werden können. In den bisherigen Beispielen in diesem Buch wurde die »Standardmethode« zum Ansprechen einer Tabelle verwendet. Im Makro in Listing 5.1 ist diese Methode noch einmal kurz dargestellt. Listing 5.1: Sub TabelleAnsprechen() Eine Tabelle ansprechen With Sheets("Blatt1") MsgBox .Name End With End Sub Bei diesem Verfahren wird der Name der Tabelle übernommen, der in Excel auf dem Tabellenreiter steht. Dabei handelt es sich bei der Auflistung Sheets um ein Objekt, in dem alle Blätter einer Arbeitsmappe automatisch verzeichnet sind. Mit dem Begriff »Blätter« können neben Standardtabellen auch Diagrammblätter und die etwas in die Jahre gekommenen Makro- und Dialogblätter aus den Excel-Versionen 4 bzw. 5 gemeint sein. Sofern ausschließlich nur Tabellen angesprochen werden sollen, verwenden Sie statt der Auflistung Sheets die Auflistung Worksheets. Trotz dieses feinen Unterschieds hat sich in der Praxis die »Kurzform« durchgesetzt. Neben dem Tabellennamen, der auf dem Tabellenreiter verzeichnet ist, gibt es den so genannten Codenamen einer Tabelle. In der Entwicklungsumgebung kann dieser Name im Projekt-Explorer an erster Stelle eingesehen werden. Der »normale« Tabellenname ist in Klammern aufgeführt. Da man diese beiden Namen gern verwechselt, können Sie sich als Gedankenstütze die beiden Klammern als »Tabellenreiterklappen« vorstellen. Wenn ein neues Tabellenblatt eingefügt wird, dann lauten der Codename sowie der »normale« Name der Tabelle immer gleich. Das ändert sich aber spätestens dann, wenn Anwender den Tabellennamen über einen Doppelklick 160 Tabellen programmieren jetzt lerne ich auf den Tabellenreiter ändern. Als Resultat ergibt sich dann eine wie in Abbildung 5.1 gezeigte Darstellung. Bild 5.1: Jede Tabelle hat zwei Namen Gerade in der Umbenennung einer Tabelle liegt auch eine Gefahr. Wird beispielsweise die Tabelle BLATT1 umbenannt, dann würde das Makro in Listing 5.1 unweigerlich abstürzen, da die Tabelle leider nicht mehr gefunden werden kann. Um dies zu verhindern, schreiben Sie das Makro in Listing 5.1 um und verwenden nun den Codenamen der Tabelle. Sub TabelleAnsprechenCodenamen() With Tabelle1 MsgBox .Name 'Standardname 'oder MsgBox .CodeName 'Codenamen einer Tabelle Listing 5.2: Der Unterschied zwischen »normalem Namen« und Codenamen End With End Sub Über die Eigenschaft Name wird der Tabellenname, der auf dem Tabellenreiter angegeben ist, ermittelt. Die Eigenschaft Codename liefert stattdessen den Codenamen einer Tabelle. Auch wenn die meisten gängigen Makros mit dem normalen Tabellennamen arbeiten, empfiehlt es sich, mit dem Codenamen zu arbeiten, da dieser nicht ganz so einfach zu ändern ist. 0 161 5 Tabellen und Diagramme programmieren jetzt lerne ich 5.1.2 Tabellen einfügen Im Menü EXTRAS finden Sie unter dem Befehl OPTIONEN auf der Registerkarte ALLGEMEIN eine Einstellung, über die festgelegt wird, wie viele Tabellen standardmäßig bei der Anlage einer neuen Arbeitsmappe zur Verfügung gestellt werden. Genau diese Anzahl lesen wir mit dem folgenden Makro in Listing 5.3 aus und setzen den Wert auf 12, um eine neue Arbeitsmappe mit 12 Tabellen anzulegen. Anschließend wird die Einstellung, die vor dem Makro gegolten hat, wieder auf den ursprünglichen Wert zurückgesetzt. Listing 5.3: Sub TabellenEinfügenUndBenennen() Neue Tabellen Dim intz As Integer einfügen Dim Mappe As Workbook Dim anzahlTab As Integer anzahlTab = Application.SheetsInNewWorkbook Application.SheetsInNewWorkbook = 12 Set Mappe = Workbooks.Add For intz = 1 To 12 Mappe.Sheets(intz).Name = "TAB" & intz Next intz Application.SheetsInNewWorkbook = anzahlTab End Sub Über die Methode Add der Auflistung Workbooks wird eine neue Arbeitsmappe angelegt. Diese Auflistung enthält standardmäßig alle momentan geöffneten Arbeitsmappen, denen nun eine weitere, noch leere Arbeitsmappe hinzugefügt wird. Damit diese neu angelegte Arbeitsmappe auch gleich richtig angesprochen werden kann, wird der Mappe ein emtsprechender Name über die Anweisung Set zugewiesen. Dieser wird im weiteren Verlauf des Makros verwendet. Nach der Anlage der neuen Arbeitsmappe wird eine For...NextSchleife verwendet, die genau zwölfmal durchlaufen wird. Innerhalb der Schleife werden die vorhandenen 12 Tabellen umbenannt. Jeder Tabelle wird über die Eigenschaft Name ein gewünschter Text, gefolgt von einer fortlaufenden Nummer, mitgegeben. 162 Tabellen programmieren jetzt lerne ich Am Ende des Makros wird die Voreinstellung für die Anzahl neuer Tabellen wiederhergestellt, indem Sie den Inhalt der Variablen anzahlTab der Eigenschaft SheetsInNewWorkbook übergeben. Bild 5.2: Es wurden 12 neue Tabellen eingefügt und benannt Eine etwas erweiterte Variante des vorherigen Beispiels ist das Einfügen und Benennen auf Basis von vorgegebenen Namen, die in einer Tabelle aufgeführt sind. Sehen Sie sich dazu die Abbildung 5.3 an. Bild 5.3: Die Tabellennamen als Vorlage Im nächsten Makro in Listing 5.4 werden zwölf neue Tabellen angelegt und entsprechend der Vorgabe aus dem Bereich A1:A12 der Tabelle BLATT1 benannt. 163 5 Tabellen und Diagramme programmieren jetzt lerne ich Listing 5.4: Neue Tabellen nach Vorgabe einfügen Sub Dim Dim Dim TabellenAnlegenUndBenennen() zeile As Integer zeileMax As Integer Blatt As Worksheet Set Blatt = Tabelle1 zeileMax = Blatt.UsedRange.Rows.Count For zeile = 1 To zeileMax Worksheets.Add after:=Worksheets(Worksheets.Count) ActiveSheet.Name = Blatt.Cells(zeile, 1).Value Next zeile End Sub Zu Beginn des Makros wird über die Anweisung Set bekannt gegeben, wie der Codename der Tabelle lautet, in der die gewünschten Namen für die neuen Tabellen verzeichnet sind. Danach wird ermittelt wie viele Zeilen in dieser Tabelle gefüllt sind. Dazu verwenden Sie die Eigenschaft UsedRange, die den verwendeten Bereich einer Tabelle repräsentiert. Die Anzahl der Zeilen wird über die Befehlskette Rows.Count ermittelt. Setzen Sie jetzt eine Schleife auf, die von der ersten bis zur letzten gefüllten Zeile der TABELLE1 alle Zellen einzeln abarbeitet. Innerhalb der Schleife wird über die Methode Add eine neue Tabelle eingefügt. Bei dieser Methode lässt sich die genaue Einfügeposition der jeweiligen Tabelle festlegen. Dabei stehen zwei Argumente zur Verfügung: die Argumente after und before. Um beispielsweise eine Tabelle am Ende einer Arbeitsmappe einzufügen, ermitteln Sie über den Befehl Worksheets.Count, wie viele Tabellen bereits in der Arbeitsmappe sind. Diese Anzahl wird an die Auflistung Worksheets übergeben. Sollen die Tabellen zu Beginn der Arbeitsmappe eingefügt werden, dann müssten Sie die Zeile wie folgt ändern: Aus Worksheets.Add after:=Worksheets(Worksheets.Count) wird Worksheets.Add after:=Worksheets(1) Im Anschluss wird der jeweils neuen Tabelle der entsprechende Name zugewiesen, den Sie aus der Tabelle BLATT1 beziehen. 164 Tabellen programmieren jetzt lerne ich Bild 5.4: Die neuen Tabellen wurden angelegt Sollen die Tabellen in einer neuen Arbeitsmappe angelegt werden, dann passen Sie das Makro in Listing 5.4 wie folgt an: Sub Dim Dim Dim Dim TabellenAnlegenUndBenennenNeueMappe() zeile As Integer zeileMax As Integer Blatt As Worksheet Mappe As Workbook Listing 5.5: Die Tabellen werden in einer neuen Arbeitsmappe angelegt Set Blatt = Tabelle1 Set Mappe = Workbooks.Add zeileMax = Blatt.UsedRange.Rows.Count For zeile = 1 To zeileMax Worksheets.Add after:=Mappe.Worksheets(Worksheets.Count) ActiveSheet.Name = Blatt.Cells(zeile, 1).Value Next zeile End Sub Wenn Sie die beiden Makros in Listing 5.4 und 5.5 vergleichen, werden Sie feststellen, dass die Änderungen nicht so tief greifend sind. Was wurde konkret angepasst? Zunächst wurde die Objektvariable Mappe vom Typ Workbook definiert. Damit können Sie zum einen auf alle Methoden und Eigenschaften, die für Mappen angeboten werden, zugreifen. Zum anderen lässt sich in Verbindung mit der Anweisung Set und der Befehlskette Work- 165 5 Tabellen und Diagramme programmieren jetzt lerne ich books.Add eine neue Mappe einfügen und gleichzeitig auch ansprechen. Beim Einfügen der neuen Tabellen wird mit dem Argument after diese neue Mappe als Zielort angegeben. Der Rest des Listings bleibt unverändert. 5.1.3 Tabellen kopieren oder verschieben Um Tabellen zu kopieren, wird die Methode Copy eingesetzt. Wenn es darum geht Tabellen zu verschieben, kommt die Methode Move zum Einsatz. Im folgenden Beispiel in Listing 5.6 wird die erste Tabelle einer Arbeitsmappe ganz ans Ende kopiert. Listing 5.6: Sub TabelleAnsEndeKopieren() Die erste TaWorksheets(1).Copy After:=Worksheets(Worksheets.Count) belle wird an das Ende der Mappe kopiert End Sub Wenn Sie die Auflistung Worksheets mit der Nummer 1 aufrufen, dann ist die Tabelle gemeint, die ganz links in einer Arbeitsmappe angeordnet ist. Über die Methode Copy können Sie diese Tabelle kopieren. Die genaue Einfügeposition legen Sie über das Argument After fest. Über die Befehlskette Worksheets.Count zählen Sie die bereits existierenden Tabellen einer Mappe. Die so ermittelte Anzahl übergeben Sie der Auflistung Worksheets. Bild 5.5: Die erste Tabelle wurde ans Ende der Mappe kopiert 166 Tabellen programmieren jetzt lerne ich Beim Kopieren einer Tabelle benutzt Excel für den Namen der Kopie den Originalnamen der Tabelle und hängt in Klammern eine fortlaufende Nummer an. Soll die erste Tabelle nicht kopiert, sondern ans Ende der Arbeitsmappe verschoben werden, dann starten Sie das Makro in Listing 5.7. Sub TabellenAnsEndeVerschieben() Worksheets(1).Move After:=Worksheets(Worksheets.Count) End Sub Listing 5.7: Die erste Tabelle wird ans Ende der Mappe verschoben Für die Methode Move gelten dieselben Argumente wie im vorherigen Makro in Listing 5.6. 5.1.4 Tabellen löschen Beim Löschen von Tabellen werden Sie standardmäßig von Excel aufgefordert, die Aktion noch einmal zu bestätigen. Diese Rückfrage ist im Rahmen einer bewussten Programmierung in den meisten Fällen gar nicht erwünscht. Glücklicherweise lässt sich die Rückfrage temporär ausschalten, wie Sie im Makro in Listing 5.8 sehen können. Sub TabelleLöschen() Application.DisplayAlerts = False Sheets("Tabelle2").Delete Application.DisplayAlerts = True Listing 5.8: Eine Tabelle ohne Rückfrage löschen End Sub Vor dem eigentlichen Löschen wird die Eigenschaft DisplayAlerts auf den Wert False gesetzt, um allgemein alle Standardmeldungen wie beispielsweise auch die Rückfrage beim Löschen von Tabellen auszuschalten. Wenden Sie danach die Methode Delete an, um die gewünschte Tabelle zu entfernen. Vergessen Sie nach diesem Vorgang grundsätzlich nicht, die Eigenschaft DisplayAlerts wieder auf den Wert True zu setzen! 167 5 Tabellen und Diagramme programmieren jetzt lerne ich 5.1.5 Tabellen drucken Drucken lassen sich ein oder mehrere Tabellenblätter, die ganze Arbeitsmappe, ein Druckbereich oder eine Markierung. Je nach Wunsch müssen dazu diverse Makros geschrieben werden. Mit dem Makro in Listing 5.9 wird die TABELLE2 gedruckt. Listing 5.9: Sub TabellenblattDrucken() Eine Tabelle Sheets("Tabelle2").PrintOut ausdrucken End Sub Übergeben Sie der Methode PrintOut den Namen der Tabelle, für die ein Ausdruck gewünscht wird. Diese Methode hat ein paar interessante Argumente, über die Sie den Druckauftrag näher spezifizieren können. Die Syntax lautet: PrintOut(From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName) 쐽 From: Gibt die Nummer der ersten Seite an, ab der gedruckt werden soll. Wenn dieses Argument nicht angeben ist, wird von der ersten Seite an gedruckt. 쐽 To: Gibt die Nummer der letzten Seite an, die gedruckt werden soll. Wenn dieses Argument nicht angegeben ist, wird bis zur letzten Seite gedruckt. 쐽 Copies: Die Anzahl von zu druckenden Kopien. Wenn dieses Argument nicht angeben ist, wird eine Kopie gedruckt. 쐽 Preview: Setzen Sie dieses Argument auf den Wert True, um vor einem Druck zunächst die Seitenansicht aufzurufen. Wenn das Argument den Wert False hat oder nichts angegeben wurde, wird das Objekt sofort gedruckt. 쐽 ActivePrinter: Hier können Sie den Namen des aktiven Druckers angeben. Wird dieses Argument nicht angegeben, wird auf dem Standarddrucker gedruckt. 쐽 PrintToFile: Wenn dieses Argument den Wert True hat, erfolgt die Ausgabe in eine Datei. Wenn PrToFileName nicht angegeben ist, fordert Microsoft Excel den Benutzer zur Eingabe des Namens der Ausgabedatei auf. 쐽 Collate: Setzen Sie dieses Argument auf den Wert True, um bei mehreren Kopien die Sortierung einzustellen. 168 Tabellen programmieren jetzt lerne ich 쐽 PrToFileName: Falls das Argument PrintToFile gesetzt ist, gibt dieses Argument den Namen der Datei an, in die gedruckt werden soll. Im folgenden Beispiel in Listing 5.10 wird die TABELLE2 mit zwei Kopien gedruckt und der Ausdruck danach sortiert. Sub TabellenblattDruckenMitKopie() Sheets("Tabelle2").PrintOut Copies:=2, Collate:=True End Sub Listing 5.10: Eine Tabelle inklusive Kopien drucken und sortieren Geben Sie bei der Methode PrintOut das Argument Copies mit der gewünschten Anzahl der Kopien ein. Sollen alle markierten Tabellen gedruckt werden, dann starten Sie das Makro in Listing 5.11. Sub SelektierteTabellenDrucken() ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True End Sub 5.1.6 Listing 5.11: Alle markierten Tabellen mit einer Kopie drucken Tabellen gruppieren In Excel besteht die Möglichkeit, Ihre Arbeit an einem Tabellenblatt automatisch auch für andere Tabellenblätter gültig zu machen. Dazu gruppieren Sie die einzelnen Tabellenblätter. Manuell klappt das, indem die Ÿ-Taste gedrückt wird und Sie dabei die einzelnen Tabellenregister mit der linken Maustaste anklicken. Das Ergebnis dieser Aktion lässt sich selbstverständlich auch mit VBA realisieren: Sub MehrereTabellenMarkieren() On Error GoTo fehler Sheets(Array("Tabelle2", "Tabelle3", "Tabelle1")).Select Exit Sub Listing 5.12: Mehrere Tabellen gruppieren fehler: If Err.Number = 9 Then MsgBox "Eine der angegebenen Tabellen existiert nicht!" End If End Sub 169 5 Tabellen und Diagramme programmieren jetzt lerne ich Die Funktion Array ermöglicht es, eine durch Kommas getrennte Liste von Werten (hier Tabellennamen) anzugeben. Wichtig ist auch hier wieder die On Error-Anweisung, um eine Fehlermeldung zu vermeiden, sofern eines der Tabellenblätter nicht vorhanden ist. Im Fehlerfall verzweigen Sie in den Paragrafen fehler. Dort wird der Fehler ausgewertet. Jeder Fehler hat in Excel eine eindeutige Nummer, die über die Eigenschaft Number abgefragt werden kann. Das Objekt Err liefert im Fehlerfall automatisch alle zu dem Fehler bekannten Informationen. Bild 5.6: Bestimmte Tabellen sind gruppiert Eine mehr dynamische Lösung bietet das Makro in Listing 5.13. In diesem Makro werden alle Tabellen einer Arbeitsmappe gruppiert. Dabei spielt der Name der einzelnen Tabellen keine Rolle. Listing 5.13: Alle Tabellen einer Mappe gruppieren Sub Dim Dim Dim MarkierenTabellen() intTabz As Long intTabMax As Long lArray() As Long intTabMax = ThisWorkbook.Worksheets.Count ReDim lArray(1 To intTabMax) For intTabz = 1 To intTabMax lArray(intTabz) = intTabz Next intTabz ThisWorkbook.Worksheets(lArray).Select End Sub 170 Tabellen programmieren jetzt lerne ich Im ersten Schritt wird die Anzahl der Tabellen ermittelt, die momentan in der Arbeitsmappe untergebracht sind. Dies geschieht über die bei der Auflistung Worksheets angewendete Funktion Count. In dieser Auflistung sind automatisch alle Tabellen der Arbeitsmappe, die dieses Makro anspricht (= ThisWorkbook) verzeichnet. Da zu Beginn des Makros noch nicht bekannt ist, wie viele Tabellen sich in der Arbeitsmappe befinden, wird diese Information jetzt über die Anweisung ReDim an das Datenfeld lArray übergeben. Danach wird eine dynamische Schleife aufgesetzt, die alle Tabellen der Mappe nacheinander abarbeitet und die Namen der Tabellen in das Datenfeld lArray schreibt. Am Ende werden die so »gesammelten« Tabellen über die Methode Select gruppiert. Bild 5.7: Alle Tabellen einer Mappe sind gruppiert 5.1.7 Tabellen listen und verlinken Gerade bei Arbeitsmappen mit sehr vielen Tabellen geht leicht einmal die Übersichtlichkeit verloren. Aus diesem Grund können Sie über eine Makrolösung eine Tabelle einfügen, die als Inhaltsverzeichnis dienen soll. In dieser Tabelle werden alle in der Arbeitsmappe enthaltenen Tabellen aufgelistet und mit einem Hyperlink abgelegt. So kann die gewünschte Tabelle mit einem Mausklick erreicht werden. Sub Dim Dim Dim TabellenVerzeichnisErstellenPlusHyperlinks() intTab As Integer Blatt As Worksheet intZeile As Integer Listing 5.14: Tabellen auflisten und verknüpfen Set Blatt = Worksheets.Add(before:=Worksheets(1)) intZeile = 1 171 5 Tabellen und Diagramme programmieren jetzt lerne ich For intTab = 2 To ActiveWorkbook.Worksheets.Count Blatt.Cells(intZeile, 1).Value = Worksheets(intTab).Name Blatt.Cells(intZeile, 1).Hyperlinks.Add _ Anchor:=Cells(intZeile, 1), Address:="", SubAddress:= _ Worksheets(intTab).Name & "!A1", _ ScreenTip:="Klicken Sie auf den Hyperlink", _ TextToDisplay:=Worksheets(intTab).Name intZeile = intZeile + 1 Next intTab End Sub Zu Beginn des Makros in Listing 5.14 wird eine neue Tabelle eingefügt. Der Zähler erhält den Wert 1. Mit einer For...Next-Schleife werden nun alle Tabellen der aktuellen Arbeitsmappe abgearbeitet. Innerhalb der Schleife wird der jeweilige Name der Tabelle über die Eigenschaft Name und die Auflistung Cells in die erste Spalte der neu angelegten Tabelle geschrieben. Nach dem Eintragen des Tabellennamens wird noch über die Methode Add ein Hyperlink eingefügt, der als »Sprungziel« den Inhalt der jeweiligen Zelle übernimmt. Bild 5.8: Ein automatisches Tabellenverzeichnis anlegen 5.1.8 Tabellen schützen Haben Sie wichtige Daten in einem Tabellenblatt erfasst und möchten Sie diese vor Veränderungen durch andere schützen, lässt sich die Tabelle mit einem Passwort belegen. 172 Tabellen programmieren jetzt lerne ich Eine Tabelle schützen Im Makro in Listing 5.15 wird die TABELLE2 mit einem Passwort belegt. Sub BlattschutzEinschalten() Sheets("Tabelle2").Protect Password:="test", _ DrawingObjects:=True, Contents:=True, Scenarios:=True, _ UserInterFaceOnly:=True Listing 5.15: Ein Passwort für den Tabellenschutz einstellen End Sub Wenden Sie die Methode Protect an, um eine Tabelle zu schützen. Im Argument Passwort wird eine Zeichenfolge angegeben, die das groß/kleinschreibungsabhängige Kennwort für das Blatt oder die Arbeitsmappe festlegt. Wenn Sie dieses Argument weglassen, kann der Schutz des Blatts oder der Arbeitsmappe ohne Angabe eines Kennworts aufgehoben werden. Mit dem Argument DrawingObjects lässt sich bestimmen, ob zusätzlich zu den Zellen auch noch Formen, wie z. B. Blockpfeile, Sterne oder Banner, geschützt werden sollen. Diese Formen werden standardmäßig nicht geschützt! Wenn nun also auch Formen geschützt werden sollen, wird das Argument auf den Wert True gesetzt. Bei dem Argument Contents, das standardmäßig auf True gesetzt ist, werden die Zellen eines Tabellenblatts geschützt. Das Argument Scenarios gilt nur für Arbeitsblätter und bedeutet, dass bestimmte Ansichten und Einstellungen, wie z. B. der eingestellte Zoom, geschützt werden. Die Standardeinstellung ist dabei ebenfalls True. Das letzte Argument UserInterFaceOnly nimmt den Wert True an. Damit wird die Benutzeroberfläche, jedoch keine Makros, geschützt. Ohne Angabe dieses Arguments gilt der Schutz für Makros und die Benutzeroberfläche. Den Tabellenschutz aufheben Um den Schutz einer Tabelle wieder zu entfernen, starten Sie das Makro in Listing 5.16. Sub BlattschutzEntfernen() Sheets("Tabelle2").Unprotect Password:="test" Listing 5.16: Den Tabellenschutz wieder aufheben End Sub Zum Deaktivieren des Tabellenschutzes reicht es, wenn bei der Methode Unprotect das Passwort angegeben wird. Sollte das Tabellen- 173 jetzt lerne ich 5 Tabellen und Diagramme programmieren blatt ohne Passwort geschützt worden sein, reicht allein der Befehl Sheets("Tabelle2").Unprotect. Neue Schutzeigenschaften ab Excel 2002 Eine sehr große Verbesserung gegenüber den Vorversionen lässt sich beim Schützen der Tabellen ab der Version Excel 2002 feststellen. Sie haben jetzt die Möglichkeit, einen Blattschutz einzustellen, aber einzelne Aktionen trotz eingestelltem Blattschutz freizuschalten. So können Sie zum Beispiel festlegen, dass ein Anwender in einer geschützten Tabelle die Filter verwenden, Formatierungen durchführen sowie ggf. Zeilen und Spalten einfügen darf. Diese und weitere Möglichkeiten können Sie einsehen, wenn Sie aus dem Menü EXTRAS den Befehl SCHUTZ/BLATT SCHÜTZEN wählen. Folgende zusätzliche Eigenschaften sind ab der Version Excel 2002 verfügbar: 쐽 AllowFormattingCells: Setzen Sie dieses Argument auf den Wert True, wenn die Formatierung in geschützten Zellen zugelassen werden soll. 쐽 AllowFormattingColumns: Bei dieser Einstellung darf der Benutzer Spalten formatieren, sofern dieses Argument auf den Wert True gesetzt wird. 쐽 AllowFormattingRows: Bei dieser Einstellung darf der Benutzer Zeilen formatieren, sofern dieses Argument auf den Wert True gesetzt wird. 쐽 AllowInsertingRows: Setzen Sie dieses Argument auf den Wert True, wenn Sie zulassen möchten, dass der Benutzer neue Zeilen in eine geschützte Tabelle einfügt. 쐽 AllowInsertingHyperlinks: Um das Einfügen von Hyperlinks in geschützten Tabellen zuzulassen, setzen Sie dieses Argument auf den Wert True. 쐽 AllowDeletingColumns: Möchten Sie zulassen, dass in einer geschützten Tabelle Spalten gelöscht werden, dann gilt für dieses Argument der Wert True. 쐽 AllowDeletingRows: Möchten Sie zulassen, dass in einer geschützten Tabelle Zeilen gelöscht werden, dann setzen Sie dieses Argument auf den Wert True. 174 Tabellen programmieren jetzt lerne ich 쐽 AllowSorting: Setzen Sie dieses Argument auf den Wert True, um eine Sortierung des geschützten Arbeitsblatts zu ermöglichen. Für jede Zelle im Sortierbereich muss die Sperre oder der Schutz aufgehoben werden. 쐽 AllowFiltering: Setzen Sie dieses Argument auf den Wert True, um zu ermöglichen, Filter für das geschützte Arbeitsblatt festzulegen. Die Benutzer können Filterkriterien ändern, jedoch keinen AutoFilter aktivieren oder deaktivieren. 쐽 AllowUsingPivotTables: Setzen Sie dieses Argument auf den Wert True, um es dem Benutzer zu ermöglichen, in einer geschützten Tabelle mit Pivot-Tabellen zu arbeiten. Bild 5.9: Die Schutzeinstellungen sind ab Excel 2002 stark erweitert worden Im folgenden Makro in Listing 5.17 wird die TABELLE2 geschützt. Dabei soll es trotz Blattschutz noch möglich sein, neue Zeilen und Spalten einzufügen. Sub TabelleSchützen() With Sheets("Tabelle2") .Protect Password:="test", DrawingObjects:=True, _ Contents:=True, Scenarios:=True, _ AllowInsertingColumns:=True, AllowInsertingRows:=True Listing 5.17: Bestimmte Aktionen trotz Blattschutz zulassen End With End Sub 175 5 Tabellen und Diagramme programmieren jetzt lerne ich Alle Tabellen einer Mappe schützen Müssen alle Tabellen einer Arbeitsmappe geschützt und mit einem Passwort belegt werden, dann ist dies manuell durchgeführt eine langwierige und nervende Angelegenheit. Schreiben Sie für diese Aufgabe lieber ein Makro, das diese Aufgabe in Sekunden automatisch erledigt. Listing 5.18: Sub TabellenSchützen() Tabellen Dim Blatt As Worksheet schneller schützen und For Each Blatt In ActiveWorkbook.Worksheets »entschützen« Blatt.Protect Password:="test" Next Blatt End Sub Sub TabellenEntSchützen() Dim Blatt As Worksheet For Each Blatt In ActiveWorkbook.Worksheets Blatt.Unprotect Password:="test" Next Blatt End Sub In einer For...Next-Schleife arbeiten Sie Tabelle für Tabelle einer Arbeitsmappe ab. Innerhalb der Schleife wird die Methode Protect bzw. Unprotect angewendet, um die jeweilige Tabelle zu schützen bzw. den Tabellenschutz aufzuheben. Dabei wird dem Argument Password das gewünschte Passwort für den Tabellenschutz übergeben. 5.1.9 Tabellen ein- und ausblenden Wenn bestimmte Tabellenblätter nicht mit einem Passwort geschützt werden, jedoch trotzdem ein gewisser Schutz der Daten erreicht werden soll, können Tabellenblätter auch ausgeblendet werden. Das Ein- und Ausblenden von Tabellenblättern erzielen Sie mit der Eigenschaft Visible. 176 Tabellen programmieren Sub TabelleAusblenden() Sheets("Tabelle2").Visible = False jetzt lerne ich Listing 5.19: Eine Tabelle ausblenden End Sub Nach der Ausführung des Makros TabelleAusblenden, wird die Tabelle in der Arbeitsmappe nicht mehr angezeigt. Der Anwender kann aber jederzeit über den Befehl BLATT/EINBLENDEN aus dem Menü FORMAT die ausgeblendeten Tabellenblätter wieder verfügbar machen. Um die Tabelle wieder einzublenden, benötigt die Eigenschaft Visible lediglich den Wert True. Möchten Sie verhindern, dass der Anwender Ihre ausgeblendeten Tabellenblätter über die Benutzeroberfläche wieder einblendet, müssen Sie bei der Eigenschaft Visible die Konstante xlVeryHidden verwenden. Sehen Sie sich dazu das Makro in Listing 5.20 an. Sub TabelleSicherAusblenden() Sheets("Tabelle2").Visible = xlVeryHidden Listing 5.20: Eine Tabelle sicher ausblenden End Sub 5.1.10 Tabellen sortieren In umfangreichen Excel-Arbeitsmappen geht leicht einmal der Überblick verloren. Aus diesem Grund ist es vorteilhaft, die Tabellen alphabetisch nach Tabellennamen sortiert in der Arbeitsmappe anzuordnen. Das Makro für die Sortierung der Tabellenblätter lautet: Sub Dim Dim Dim ArbeitsblätterSortieren() TabMax As Integer TabZ As Integer TabZ2 As Integer Listing 5.21: Die Tabellen werden nach Namen sortiert Application.ScreenUpdating = False TabMax = ActiveWorkbook.Worksheets.Count For TabZ = 1 To TabMax For TabZ2 = TabZ To TabMax 177 jetzt lerne ich 5 Tabellen und Diagramme programmieren If UCase(Worksheets(TabZ2).Name) _ < UCase(Worksheets(TabZ).Name) Then Worksheets(TabZ2).Move before:=Worksheets(TabZ) End If Next TabZ2 Next TabZ Application.ScreenUpdating = True End Sub Um das Sortieren von Arbeitsblättern durchzuführen, müssen zwei verschachtelte For...Next-Schleifen durchlaufen werden. Beide haben als Endbedingung immer die Anzahl der Tabellen, die in der Mappe enthalten sind. Innerhalb der zweiten Schleife werden die Namen der Tabellenblätter verglichen. Beim Vergleich der Tabellennamen werden diese erst einmal über die Funktion UCase in Großbuchstaben umgewandelt, um sicherzustellen, dass die Groß- und Kleinschreibung beim Sortiervorgang keine Rolle spielt. Je nach Vergleichsergebnis werden die einzelnen Tabellen dann innerhalb der Arbeitsmappe mithilfe der Methode Move verschoben oder an ihrer Stelle belassen. Bild 5.10: Die Tabellen liegen nun sortiert vor 178 Diagramme programmieren 5.2 jetzt lerne ich Diagramme programmieren Im zweiten Teil dieses Kapitels dreht sich alles um das Thema Diagramme. Sie lernen auf den nächsten Seiten, wie Diagramme eingefügt, formatiert, exportiert und gelöscht werden können. 5.2.1 Ein Diagrammblatt einfügen Bei der Erstellung von Diagrammen besteht die Auswahl aus mehreren Diagrammtypen. Für den richtigen Diagrammtyp ist die Eigenschaft ChartType verantwortlich. In der nachfolgenden Tabelle sehen Sie exemplarisch eine kleine Auswahl an möglichen Diagrammtypen, die über eine xlChartType-Konstante identifiziert werden. Diagrammtyp Konstante Säulendiagramm (gruppiert) xlColumnClustered Säulendiagramm (gestapelt) xlColumnStacked Säulendiagramm 3D-Darstellung xl3DColumn Balkendiagramm (gruppiert) xlBarClustered Balkendiagramm (gestapelt) xlBarStacked Liniendiagramm xlLine Kreisdiagramm xlPie Punktdiagramm xlXYScatter Blasendiagramm xlBubble Flächendiagramm xlArea Ringdiagramm xlDoughnut Netzdiagramm xlRadar Oberflächendiagramm xlSurface Kursdiagramm xlStockHLC Tabelle 5.1: Die wichtigsten Diagrammtypen Neben den in der Tabelle abgebildeten Diagrammtypen gibt es noch Zylinder-, Kegel- und Pyramidendiagramme sowie zu jedem Diagramm zahlreiche Untertypen. Eine komplette Liste der vorhandenen Diagramme in Excel erhalten Sie in der Online-Hilfe unter dem Stichwort CHARTTYPE. 179 jetzt lerne ich 5 Tabellen und Diagramme programmieren Beim folgenden Beispiel in Listing 5.22 soll ein Säulendiagramm auf Basis des Bereichs A2:G6 der TABELLE1 der Mappe Diagramme.xls erstellt werden. Bild 5.11: Die Ausgangstabelle für das zu erstellende Diagramm Listing 5.22: Sub DiagrammErstellen() Ein Säulen- Dim Bereich As Range diagramm Set Bereich = Sheets("Tabelle1").Range("A2:G6") erstellen Charts.Add With ActiveChart .ChartType = xlColumnClustered .SetSourceData Source:=Bereich, PlotBy:=xlRows .HasTitle = True .ChartTitle.Text = Sheets("Tabelle1").Range("B1").Value End With End Sub Im ersten Schritt wird der Bereich festgelegt, der die Datenbasis für das Diagramm enthält. Dazu wird die Adresse des Bereichs in der Range-Variablen Bereich gespeichert. Mit der Methode Add wird zunächst ein neues Diagrammblatt erstellt. Danach wird der Diagrammtyp mit der Eigenschaft ChartType bestimmt. Über die Methode SetSourceData geben Sie an, woher Excel die Daten für das Diagramm bekommt. Diese Methode benötigt zwei Argumente. Dem ersten Argument Source wird die Variable Bereich übergeben. Mit dem zweiten Argument PlotBy wird festgelegt, wie die Daten angezeigt werden sollen. Wählen Sie entweder die Konstante xlColumns oder xlRows. 180 Diagramme programmieren jetzt lerne ich Um das Diagramm mit einer Überschrift zu versehen, wird die Eigenschaft HasTitle auf den Wert True gesetzt. Die Überschrift des Diagramms erstellen Sie mithilfe der Eigenschaft ChartTitle und der Eigenschaft Text, die den Zelleninhalt der Zelle B1 der TABELLE1 übergeben bekommt. Bild 5.12: Ein Diagrammblatt wurde eingefügt 5.2.2 Ein Diagrammobjekt einfügen Neben der Möglichkeit ein Diagramm als separates Blatt einzufügen, lässt sich ein Diagrammobjekt ebenso in eine bereits bestehende Tabelle, wie in Abbildung 5.13 gezeigt, einfügen. Um ein Diagrammobjekt einzufügen, wenden Sie die Methode Add, wie im Makro in Listing 5.23 gezeigt, an. 181 jetzt lerne ich 5 Tabellen und Diagramme programmieren Bild 5.13: Ein Diagrammobjekt wurde eingefügt Listing 5.23: Ein Diagrammobjekt in einer Tabelle einfügen Sub DiagrammObjektEinfügen() Dim Dia As ChartObject Dim intZeilen As Integer With Sheets("Tabelle2") Set Dia = .ChartObjects.Add(150, 15, 350, 250) Dia.Name = "Laufende Umsätze" intZeilen = .Range("B1").End(xlDown).Row .Range("A2:B" & intZeilen).Copy .ChartObjects("Laufende Umsätze").Activate ActiveChart.SeriesCollection.Paste _ Rowcol:=xlColumns, SeriesLabels:=False, _ CategoryLabels:=True, Replace:=True, NewSeries:=True Application.CutCopyMode = False End With With ActiveChart .ChartType = xlLineMarkers .HasLegend = False .HasTitle = True .ChartTitle.Text = "Umsatzbericht" End With End Sub 182 Diagramme programmieren jetzt lerne ich Da ein eingebettetes Diagramm eingefügt werden soll, fügen Sie zunächst ein noch leeres Chart-Objekt mit der Methode Add in die Tabelle ein. Dabei lässt sich die genaue Position des Chart-Objekts festlegen. Die vier Zahlenwerte entsprechen den Angaben für den linken und den oberen Rand, die Breite sowie die Höhe. Die Angaben werden in Punkten angegeben und beziehen sich relativ zur oberen linken Ecke der Zelle A1 oder zur oberen linken Ecke des Diagramms. Geben Sie als Nächstes dem eingebetteten Diagramm einen Namen. Jetzt muss ermittelt werden, wie viele Tagesumsätze im Diagramm angezeigt werden sollen. Dazu wird die letzte belegte Zelle in der Spalte B ermittelt und die Zeilennummer in der Variablen intZeilen gespeichert. Markieren Sie den Bereich und kopieren ihn mit der Methode Copy. Nun wird das gerade eingefügte Diagramm markiert. Um die kopierten Daten einzufügen, verwenden Sie die Methode Paste der SeriesCollection-Auflistung. Die Methode Paste verwendet mehrere Argumente und hat die Syntax: Paste(Rowcol, SeriesLabels, CategoryLabels, Replace, _ NewSeries) Das erste Argument RowCol gibt Auskunft darüber, ob sich die Daten in Zeilen oder Spalten befinden. Zulässig sind hierbei die Konstanten xlColumns oder xlRows. Das Argument SeriesLabels bestimmt, woher Excel die Beschriftung für die Datenreihen nehmen soll. Wird der Wert auf True gesetzt, wird der Inhalt der Zelle in der ersten Spalte jeder Zeile (bzw. der ersten Zeile jeder Spalte) als Name für die Datenreihe in der betreffenden Zeile (bzw. Spalte) verwendet. Setzen Sie dieses Argument auf den Wert False, wenn der Inhalt der Zelle in der ersten Spalte jeder Zeile (bzw. der ersten Zeile jeder Spalte) als erster Datenpunkt der Datenreihe verwendet werden soll. Das nächste Argument CategoryLabels weist den Wert True auf, wenn der Inhalt der ersten Zeile (bzw. Spalte) als Rubrik des Diagramms verwendet wird. Setzen Sie das Argument auf den Wert False, wenn der Inhalt der ersten Zeile (bzw. Spalte) als erste Datenreihe im Diagramm verwendet werden soll. Das Argument Replace ist standardmäßig auf den Wert True gesetzt. Dabei werden beim Ersetzen vorhandener Rubriken durch Informationen aus dem kopierten Bereich wieder Rubriken erstellt. Das letzte Argument NewSeries hat dann den Wert True, wenn die Daten als eine neue Datenreihe eingefügt werden sollen. Setzen Sie das Argument auf den Wert False, wenn 183 5 Tabellen und Diagramme programmieren jetzt lerne ich die Daten als neue Datenpunkte in eine vorhandene Datenreihe eingefügt werden sollen. Nach der Kopier- und Einfügeaktion ist nach wie vor der Kopierrahmen aktiv. Mit der Eigenschaft CutCopyMode und dem Wert False wird der Ausschneide- bzw. Kopiermodus deaktiviert und dadurch der Laufrahmen entfernt. Als letzte Aufgabe wird dem Diagramm der richtige Diagrammtyp zugewiesen. Wir verzichten auf eine Legende, indem die Eigenschaft HasLegend auf den Wert False gesetzt wird, zeigen aber die Überschrift im Diagramm an. 5.2.3 Das Standarddiagramm setzen Wenn Sie einen Zellenbereich in einer Tabelle markieren und dann die Taste Ó drücken, wird ein Standarddiagramm als neues Blatt erstellt. Dabei wird standardmäßig immer ein Säulendiagramm erzeugt. Diese Standardeinstellung lässt sich ändern, indem das Makro in Listung 5.24 verwendet wird. Listing 5.24: Sub StandardDiagrammSetzen() Das Liniendiagramm wird Application.SetDefaultChart FormatName:=xlLineMarkers als Standarddiagramm End Sub definiert Mithilfe der Methode SetDefaultChart lässt sich festlegen, welches Di- agramm Excel zukünftig als Standarddiagramm einsetzen soll. Im Makro in Listing 5.24 wird beispielsweise das Liniendiagramm als Standarddiagramm festgelegt. 5.2.4 Diagramme exportieren In Excel lassen sich Diagramme über einen Grafikfilter umwandeln. Das bringt Vorteile, wenn Diagramme an Personen weitergegeben werden, die kein Excel installiert haben. Erstellen Sie aus den ExcelDiagrammen speicherschonende Grafikdateien im GIF-Format. Auch wenn Sie Diagramme in einer Textverarbeitung oder Präsentation verwenden möchten und dabei keine Excel-Diagramme verknüpfen wollen, ist das Einbinden von Diagrammgrafiken die bessere Methode. Einziger Nachteil ist, dass diese umgewandelten Diagramme dann allerdings nicht mehr aktualisiert werden. Das nachfolgende Makro in Listing 5.25 wandelt ein eingebettetes Diagramm in eine GIF-Datei um und speichert diese auf Ihrem lokalen Laufwerk C ab. 184 Diagramme programmieren Sub DiagrammAlsGrafikExportieren() Dim Dia As Chart With Sheets("Tabelle2") jetzt lerne ich Listing 5.25: Ein Diagrammobjekt als Grafikdatei exportieren Set Dia = .ChartObjects(1).Chart Dia.Export Filename:="c:\" & _ .ChartObjects(1).Name & ".gif", FilterName:="GIF" End With End Sub Über die Methode Export werden die Diagramme in ein Grafikformat exportiert. Dabei verwendet die Methode die Argumente FileName und FilterName. Im Argument FileName wird der Pfad sowie der Name der Grafikdatei angegeben. Dazu wenden Sie die Eigenschaft Name auf das Chart-Objekt an. Im Argument FilterName wird der Name des Grafikfilters angegeben, der verwendet werden soll. Bild 5.14: Das Diagramm liegt nun als Grafikdatei vor 185 5 Tabellen und Diagramme programmieren jetzt lerne ich 5.2.5 Diagramm entfernen Sollen nun Diagramme aus einer Arbeitsmappe entfernt werden, wenden Sie die Methode Delete an. Allerdings muss dabei unterschieden werden, ob Sie Diagrammblätter oder eingebettete Diagramme aus Ihrer Arbeitsmappe löschen möchten. Diagrammblätter löschen Um alle Diagrammblätter aus einer Arbeitsmappe zu löschen, setzen Sie folgendes Makro in Listing 5.26 ein. Listing 5.26: Sub AlleDiagrammeEntfernen() Alle DiaApplication.DisplayAlerts = False grammblätter On Error Resume Next einer ArbeitsActiveWorkbook.Charts.Delete mappe werApplication.DisplayAlerts = False den gelöscht End Sub Da die Eigenschaft DisplayAlerts auf den Wert False gesetzt wurde, müssen die einzelnen Löschungen nicht bestätigt werden. Die On Error-Anweisung sorgt dafür, dass die Verarbeitung sauber abgefangen wird, sofern überhaupt kein Diagrammblatt in der Arbeitsmappe enthalten ist. Die Eigenschaft Charts gibt eine Auflistung aller Diagrammblätter der aktiven Arbeitsmappe zurück, die Sie mithilfe der Methode Delete löschen. Diagrammobjekte löschen Um alle eingebetteten Diagramme aus einer Arbeitsmappe zu entfernen, wird ein Makro mit zwei Schleifen benötigt. Dies könnte so aussehen wie in Listing 5.27 gezeigt. Listing 5.27: Sub AlleEingebettetenDiagrammeLöschen() Alle eingebet- Dim TabZ As Integer teten Dia- Dim DiaZ As Integer grammobjekte einer Mappe For TabZ = 1 To Worksheets.Count löschen For DiaZ = 1 To ActiveSheet.ChartObjects.Count ActiveSheet.ChartObjects(DiaZ).Delete Next DiaZ 186 Diagramme programmieren jetzt lerne ich Next TabZ End Sub Das Makro in Listing 5.27 besteht aus einer äußeren Schleife, die dafür sorgt, dass Tabellenblatt für Tabellenblatt abgearbeitet wird. Die zweite Schleife kontrolliert, ob es auf einzelnen Tabellenblättern ein oder auch mehrere eingebettete Diagramme gibt. Sie markiert und löscht diese über die Methode Delete. 187 jetzt lerne ich KAPITEL 6 Die Programmierung von Arbeitsmappen Die Arbeitsmappe wird durch das Objekt Workbook angesprochen. Für dieses Objekt stehen die zu erwartenden Methoden, wie das Öffnen, Speichern, Schließen, Löschen und weitere, zur Verfügung. Lernen Sie nun anhand einiger Praxisaufgaben den Einsatz dieser Methoden kennen. Alle hier vorgestellten Makros finden Sie auf der mitgelieferten CD-ROM im Verzeichnis Kap06 unter dem Namen Mappen.xls. 6.1 Arbeitsmappen öffnen 1 Als allererstes Beispiel werden Sie erfahren, wie eine Arbeitsmappe geöffnet werden kann. Hierfür wird die Methode Open eingesetzt. Die komplette Syntax der Methode Open lautet: Workbooks.Open(FileName, UpdateLinks, ReadOnly, _ Format, Password, WriteResPassword,_ IgnoreReadOnlyRecommended, Origin, Delimiter, _ Editable, Notify, Converter, AddToMRU) Durch das Argument FileName wird der Name der gewünschten Arbeitsmappe angegeben, die geöffnet werden soll. 189 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Das Argument UpdateLinks legt fest, ob gegebenenfalls in der Arbeitsmappe enthaltene Verknüpfungen aktualisiert werden sollen oder nicht. Sicher haben Sie auch schon einmal beim Öffnen einer Arbeitsmappe die Meldung erhalten, ob die Verknüpfungen in der Arbeitsmappe aktualisiert werden sollen oder nicht. Diese Abfrage lässt sich unterdrücken, indem ein entsprechendes Argument (0-3) hinterlegt wird. Die Bedeutung der verschiedenen Werte entnehmen Sie der folgenden Tabelle: Tabelle 6.1: Konstante Die Konstanten für das 0 Argument 1 UpdateLinks Bedeutung Keine Aktualisierung von Bezügen. Aktualisierung von externen Bezügen, jedoch nicht von Fernbezügen. 2 Aktualisierung von Fernbezügen, jedoch nicht von externen Bezügen. 3 Aktualisierung von externen Bezügen und Fernbezügen. Setzen Sie das Argument ReadOnly auf den Wert True, wenn die Arbeitsmappe schreibgeschützt geöffnet werden soll. Der Anwender hat dann keine Chance, Änderungen an dieser Arbeitsmappe vorzunehmen. Das Argument Format kommt dann zum Einsatz, wenn eine Textdatei mit Daten importiert werden soll. Über dieses Argument wird das Trennzeichen angegeben, das in der Textdatei verwendet wird. Wenn dieses Argument nicht angegeben ist, wird das aktuelle Trennzeichen verwendet. Folgende Möglichkeiten stehen dabei zur Verfügung. Tabelle 6.2: Wert Die Konstanten für das 1 Argument 2 Format 190 Trennzeichen Tabstopps Kommas 3 Leerzeichen 4 Semikolons 5 Keine 6 Benutzerdefiniertes Trennzeichen Arbeitsmappen öffnen jetzt lerne ich Das Argument Password muss dann gesetzt werden, wenn versucht wird eine kennwortgeschützte Arbeitsmappe zu öffnen. In diesem Argument geben Sie das Passwort ein. Wird dieses Argument nicht angegeben, so erscheint beim Öffnen einer kennwortgeschützten Arbeitsmappe ein Dialog, in dem das Passwort eingegeben werden muss. Ohne Kenntnis dieses Passworts besteht keine Möglichkeit, die Arbeitsmappe zu öffnen. Beim Argument WriteResPassword ist eine Zeichenfolge gemeint, die das zum Schreiben in einer Arbeitsmappe mit Schreiberlaubnis erforderliche Kennwort enthält. Fehlt dieses Argument und ist ein Kennwort für die Arbeitsmappe erforderlich, wird der Benutzer beim Aufruf der Datei zur Kennworteingabe aufgefordert. Das Argument IgnoreReadOnlyRecommended wird auf den Wert True gesetzt, wenn Excel keine Meldung anzeigen soll, die den schreibgeschützten Zugriff empfiehlt (falls die Arbeitsmappe mit der Option SCHREIBSCHUTZ EMPFEHLEN gespeichert wurde). Wenn es sich um eine Textdatei handelt, wird mit dem Argument Origin der Dateiursprung angegeben. Dies kann eine der folgenden Xl-Plattform-Konstanten sein: xlMacintosh, xlWindows oder xlMSDOS. Wenn dieses Argument nicht angegeben ist, gilt das aktuelle Betriebssystem. Das Argument Delimiter wird nur gesetzt, wenn es sich um eine Textdatei handelt und das Argument Format den Wert 6 hat. Dabei gibt das Argument Delimiter die Zeichenfolge des zu verwendenden Trennzeichens an. Die restlichen Argumente der Methode Open sind in der Praxis eher weniger im Einsatz und können bei Bedarf in der Online-Hilfe nachgelesen werden. Üben Sie nun den Einsatz der Methode Open anhand einiger ausgesuchter Praxisbeispiele. 6.1.1 Eine Mappe ohne Aktualisierung von Bezügen öffnen In der folgenden Aufgabe soll eine Arbeitsmappe in einem bestimmten Verzeichnis geöffnet werden. Dabei sollen die in der Arbeitsmappe enthaltenen Verknüpfungen beim Öffnen nicht aktualisiert werden. Das Makro für diese Aufgabe sehen Sie in Listing 6.1: 191 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Listing 6.1: Sub ArbeitsmappeÖffnen() Eine Mappe ohne Aktuali- On Error GoTo fehler sierung von Workbooks.Open Filename:="c:\Mappe1.xls", UpdateLinks:=0 Bezügen Exit Sub öffnen fehler: MsgBox "Die angegebene Arbeitsmappe konnte nicht gefunden werden!" End Sub Um die Arbeitsmappe zu öffnen, wird die Methode Open angewendet. Im Argument UpdateLinks geben Sie den Wert 0 an, was bedeutet, dass die Verknüpfungen zu anderen Arbeitsmappen beim Öffnen nicht aktualisiert werden. Über die Anweisung On Error GoTo fehler wird sichergestellt, dass das Makro nicht abstürzt, sofern die angegebene Arbeitsmappe nicht im vorgegebenen Verzeichnis existiert. In diesem Fall stößt Excel auf einen Fehler, der abgefangen wird und direkt in den Paragrafen fehler verzweigt. Es wird eine eigene Meldung auf dem Bildschirm anzeigt. 6.1.2 Arbeitsmappe(n) über einen Dialog öffnen Möchten Sie in einem Dialog komfortabel die zu öffnende(n) Arbeitsmappe(n) auswählen, dann besteht die Möglichkeit, mithilfe der Methode GetOpenFileName den Dialog ÖFFNEN anzuzeigen und auszuwerten. Im folgenden Beispiel wird der Dialog ÖFFNEN angezeigt. Sie können nun eine Arbeitsmappe im Dialog auswählen und öffnen. Listing 6.2: Sub ArbeitsmappeÖffnenDialog() Den Öffnen- Dim DatOP As Variant Dialog anDatOP = Application.GetOpenFilename("Excel-Dateien(*.xls),*.xls") zeigen If DatOP = False Then Exit Sub Workbooks.Open Filename:=DatOP End Sub Geben Sie bei der Methode GetOpenFilename den Filter an, nach dem Dateien im Dialog ÖFFNEN angezeigt werden sollen. Da nur Excel-Da- 192 Arbeitsmappen öffnen jetzt lerne ich teien im Dialog angezeigt werden sollen, gilt als Filter die Endung .XLS. Nach dem Aufruf des Dialogs wird zunächst der Rückgabewert überprüft, ob der Dialog ÖFFNEN mit der Schaltfläche ABBRECHEN wieder verlassen wurde. In diesem Fall wird in der Variablen DatOP der Wert False zurückgegeben, was dann zu einem unmittelbaren Verlassen des Makros über die Anweisung Exit Sub führt. Im anderen Fall wird die ausgewählte Arbeitsmappe, die in der Variablen DatOP verzeichnet ist, mithilfe der Methode Open geöffnet. Bild 6.1: Der Dialog Öffnen wird angezeigt Über denselben Dialog besteht auch die Möglichkeit, mehrere ExcelArbeitsmappen gleichzeitig zu öffnen. Für diesen Zweck müssen Sie das Makro in Listing 6.2 ein wenig umschreiben. Sub ArbeitsmappenÖffnenDialog() Dim i As Integer Dim DatOP As Variant Listing 6.3: Mehrere Mappen per Dialog öffnen i = 0 DatOP = Application.GetOpenFilename("Excel-Dateien(*.xls),*.xls", _ MultiSelect:=True) If IsArray(DatOP) Then For i = LBound(DatOP) To UBound(DatOP) Workbooks.Open DatOP(i) Next i 193 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Else MsgBox "Sie haben keine Arbeitsmappe ausgewählt" End If End Sub Mit Einsatz der Methode GetOpenFileName wird der Dialog ÖFFNEN angezeigt. Damit die Möglichkeit besteht, mehrere Arbeitsmappen im Dialog über die Taste Ÿ zu markieren, muss hierbei das Argument MultiSelect auf den Wert True gesetzt werden. Im nächsten Schritt wird wie in dem vorherigen Makro wieder überprüft, ob überhaupt wenigstens eine Arbeitsmappe im Dialog ÖFFNEN markiert wurde. Wenn ja, dann meldet die Funktion IsArray den Wert True. In diesem Fall stehen die markierten Namen der Arbeitsmappen im Datenfeld DatOP. Dieses Datenfeld wird anschließend über den Einsatz einer Schleife abgearbeitet. Dabei repräsentiert die Funktion LBound den ersten Eintrag (die erste markierte Arbeitsmappe) und die Funktion UBound den letzten Eintrag (letzte markierte Arbeitsmappe) im Datenfeld DatOP. Innerhalb der Schleife werden durch die Methode Open und die Zählvariable i die markierten Arbeitsmappen nacheinander geöffnet. Bild 6.2: Auch mehrere Mappen können markiert und geöffnet werden 194 Arbeitsmappen öffnen 6.1.3 jetzt lerne ich Alle verknüpften Mappen öffnen Im folgenden Beispiel in Listing 6.4 werden alle verknüpften Mappen einer Arbeitsmappe geöffnet. Sub AlleVerknüpftenMappenÖffnen() Dim ArrLinks As Variant Dim intz As Integer Listing 6.4: Alle verknüpften Mappen öffnen ArrLinks = ActiveWorkbook.LinkSources(xlExcelLinks) If Not IsEmpty(ArrLinks) Then For intz = 1 To UBound(ArrLinks) Workbooks.Open ArrLinks(intz) Next intz End If End Sub Mithilfe der Methode LinkSources lassen sich alle verknüpften Mappen einer Arbeitsmappe ermitteln. Diese können Sie in einem Datenfeld zwischenspeichern. Danach wird überprüft, ob dieses Datenfeld überhaupt einen Eintrag aufweist. Wenn ja, dann wird es Eintrag für Eintrag abgearbeitet. In einer Schleife werden, beginnend beim ersten Eintrag bis zum letzten Eintrag (UBound), alle Mappen über die Methode Open geöffnet. 6.1.4 Ist eine bestimmte Mappe bereits geöffnet? Im folgenden Beispiel in Listing 6.5 wird überprüft, ob eine bestimmte Arbeitsmappe bereits geöffnet ist. Sub MappeOffen() Dim strName As String Dim Mappe As Workbook For Each Mappe In Application.Workbooks Listing 6.5: Es wird geprüft, ob eine bestimmte Mappe bereits geöffnet ist strName = Mappe.Name If strName Like "Mappe*" Then MsgBox "Die Datei " & strName & " ist geöffnet", vbInformation End If 195 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Next Mappe End Sub Deklarieren Sie zu Beginn des Makros eine Objektvariable vom Typ Workbook. Danach werden mithilfe einer For Each...Next-Schleife alle momentan geöffneten Arbeitsmappen abgearbeitet. Diese geöffneten Mappen stehen automatisch in der Auflistung Workbooks, die einem Inhaltsverzeichnis entspricht. Innerhalb der Schleife wird über den Operator Like geprüft, ob eine Datei, die mit der Zeichenfolge MAPPE beginnt, bereits geöffnet ist. Wenn ja, dann wird eine Meldung am Bildschirm ausgegeben. Wenn Sie ausschließlich nur eine bestimmte Mappe auf ihren Status hin überprüfen möchten, dann wird die Abfrage wie folgt geändert: If strName = "Mappen.xls" Then 6.2 Arbeitsmappen speichern Beim Speichern einer Arbeitsmappe sollte üblicherweise bestimmt werden, wo Sie die Mappe speichern möchten. Dazu wird über die ChDrive-Anweisung, das Laufwerk bestimmt, sowie per Anweisung ChDir in das gewünschte Verzeichnis gewechselt. Jetzt fehlt nur noch der Name der zu speichernden Mappe. Im folgenden Beispiel wird die aktive Arbeitsmappe in einem vorgegebenen Verzeichnis abgelegt: Listing 6.6: Eine Mappe in einem anderen Verzeichnis speichern Sub ArbeitsmappeSpeichern() Dim strName As String Const LW = "c:\" Const Pfad = "c:\Temp" strName = ActiveWorkbook.Name ChDrive LW ChDir Pfad ActiveWorkbook.SaveAs Filename:=strName, FileFormat:= _ xlNormal, Password:="", WriteResPassword:="", _ ReadOnlyRecommended:=False, CreateBackup:=True End Sub 196 Arbeitsmappen speichern jetzt lerne ich Die Speicherung der Arbeitsmappe erfolgt über die Methode SaveAs. Die Syntax der Methode SaveAs lautet: ActiveWorkbook.SaveAs(FileName, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AddToMru, TextCodePage, TextVisualLayout) Das Argument FileName haben Sie im Makro in Listing 6.6 in der Variablen strName über die Eigenschaft Name ermittelt. Beim Argument FileFormat lässt sich angeben, in welchem Format die Mappe gespeichert werden soll. Mit dem nächsten Argument Password lässt sich ein Passwort festlegen, das der Anwender beim Öffnen der Datei eingeben muss, um die Datei laden zu können. Im Beispiel in Listing 6.6 wurde eine Leerzeichenfolge übergeben, was bedeutet, dass kein Passwort beim Öffnen der Datei abgefragt wird. Das Argument WriteResPassword sorgt dafür, dass ein Kennwort für die Schreiberlaubnis der Datei eingegeben werden muss. Auch hier wurde eine Leerzeichenfolge übergeben, was bedeutet, dass beim Speichern der Arbeitsmappe kein Passwort eingegeben werden muss. Das Argument ReadOnlyRecommended setzen Sie auf True, wenn beim Öffnen der Datei in einer Meldung empfohlen werden soll, die Datei mit Nur-Lese-Zugriff zu öffnen. Bleibt das Argument auf dem Wert False, wird diese Meldung unterdrückt. Das Argument CreateBackup wird auf den Wert True gesetzt, um automatisch zu veranlassen, dass von der Mappe eine Sicherungskopie angelegt wird. Excel legt dann eine Sicherungskopie unter demselben Namen mit dem Zusatz Sicherungskopie von... und der Endung .wlk an. Die übrigen Argumente sind in der Praxis nicht so relevant und werden an dieser Stelle nicht weiter beschrieben. Eine Beschreibung lässt sich aber in der Online-Hilfe nachlesen. 6.2.1 Mappe unter aktuellem Tagesdatum speichern Beim folgenden Makro in Listing 6.7 wird eine Mappe unter dem aktuellen Tagesdatum gespeichert. Bedenken Sie hierbei, dass vorher die unerlaubten Punkte im Datum eliminiert werden müssen. 197 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Listing 6.7: Sub MappeUnterDatumSpeichern() Eine Mappe Dim Mappe As Workbook wird unter Set Mappe = Workbooks.Add dem aktuellen Tagesdatum Mappe.SaveAs (ThisWorkbook.Path & "\Mappe" & _ gespeichert Year(Date) & Format(Month(Date), "00") & Format(Day(Date), "00") _ & ".xls") Mappe.Close End Sub Deklarieren Sie zunächst eine Objektvariable vom Typ Workbook, um Zugriff auf alle für Mappen zur Verfügung stehenden Methoden und Eigenschaften zu bekommen. Danach wird durch die Methode Add eine neue, noch leere Arbeitsmappe erstellt. Diese wird mithilfe der Methode SaveAs im gleichen Verzeichnis wie die Arbeitsmappe (ThisWorkbook.Path) abgelegt. Beim Dateinamen wenden Sie die Funktionen Year (z. B. 2005), Month (z. B. 06) und Day (z. B. 21) an, um jeweils den Jahres-, Monats- sowie Tagesanteil aus dem aktuellen Datum zu extrahieren. Über die Funktion Format wird die Formatierung festgelegt, die bei der Monats- und Tagesangabe immer zweistellig sein soll. Ohne die Funktion Format würde Excel in der Monatsinformation beispielsweise für den Monat Juni die Zahl 6 ausgeben. Durch die Formatierung erhalten wir nun jedoch die Ausgabe 06. 6.2.2 Arbeitsmappe bedingt speichern Eine Arbeitsmappe sollte nur dann gespeichert werden, wenn Änderungen an ihr vorgenommen wurden. Wenn Sie wissen möchten, ob in der Arbeitsmappe seit dem letzten Öffnen Änderungen vorgenommen wurden, sei es durch Verknüpfungen oder Benutzereingaben, dann steht Ihnen hierfür eine Eigenschaft namens Saved zur Verfügung. Sehen Sie sich nun das Listing 6.8 an. Listing 6.8: Sub SpeichernArbeitsmappeBeiÄnderung() Die Mappe wird nur gesi- If ActiveWorkbook.Saved = False Then chert, wenn MsgBox "Die Mappe wurde geändert!" eine ÄndeActiveWorkbook.Save rung durchgeführt wurde Else 198 Existiert die Mappe überhaupt? jetzt lerne ich MsgBox "Arbeitsmappe ist unverändert!" End If End Sub Die Eigenschaft Saved liefert den Wert True, wenn die aktive Arbeitsmappe seit der letzten Speicherung nicht mehr geändert wurde. Gibt die Eigenschaft den Wert False zurück, wurden Änderungen an der Arbeitsmappe vorgenommen. 6.3 Existiert die Mappe überhaupt? Im folgenden Beispiel in Listing 6.9 wird überprüft, ob eine Arbeitsmappe überhaupt existiert. Sub DateiExistiert() Dim strName As String strName = Dir("C:\Mappe1.xls") Listing 6.9: Prüfung durchführen, ob eine Mappe existiert If strName <> "" Then MsgBox "Datei vorhanden!" Else MsgBox "Datei gibt es nicht!" End If End Sub Mithilfe der Funktion Dir lässt sich überprüfen, ob eine bestimmte Datei in einem vorgegebenen Verzeichnis vorhanden ist. Dazu werden der Funktion der Name der Mappe sowie der komplette Dateiname übergeben. Die Funktion gibt als Rückgabewert den Namen der gesuchten Datei zurück, wenn die Mappe im angegebenen Verzeichnis gefunden werden konnte. Im anderen Fall wird eine leere Zeichenfolge zurückgegeben. 199 6 Die Programmierung von Arbeitsmappen jetzt lerne ich 6.4 Arbeitsmappen schließen Für das Schließen einer Arbeitsmappe steht die Methode Close zur Verfügung. Wenn eine Arbeitsmappe wieder geschlossen werden soll, dann müssen Sie standardmäßig eine Meldung bestätigen, falls Änderungen an der Mappe vorgenommen wurden. Diese Meldung lässt sich aber unterdrücken, wenn Sie in der Methode Close ein zusätzliches Argument angeben. 6.4.1 Arbeitsmappe schließen – Änderungen speichern Im folgenden Beispiel in Listing 6.10 wird die aktive Arbeitsmappe ohne weitere Rückfrage geschlossen. Die Änderungen in der Mappe werden dabei mit gesichert. Listing 6.10: Sub ArbeitsmappeSchließenÄnderungenAnnehmen() Eine ArbeitsActiveWorkbook.Close SaveChanges:=True mappe schließen und Änderungen End Sub übernehmen Die Methode Close schließt die Arbeitsmappe. Wird das Argument SaveChanges auf den Wert True gesetzt, werden Änderungen an der Ar- beitsmappe gespeichert. 1 Der Vorteil beim Einsatz dieser Methode ist, dass Sie sich einen Befehl sparen. Sie brauchen nicht den Befehl Save anzuwenden, sondern wickeln das Speichern direkt beim Schließen-Vorgang ab. 6.4.2 Arbeitsmappe schließen – Änderungen verwerfen Demzufolge kann eine Arbeitsmappe geschlossen und die Änderungen an dieser Arbeitsmappe verworfen werden, indem Sie folgendes Makro in Listing 6.11 starten: 200 Arbeitsmappen schließen jetzt lerne ich Listing 6.11: Eine ArbeitsActiveWorkbook.Close SaveChanges:=False mappe schließen und ÄndeEnd Sub rungen Setzen Sie das Argument SaveChanges der Methode Close auf den Wert verwerfen Sub ArbeitsmappeSchließenÄnderungenVerwerfen() False, um Änderungen beim Schließen der Arbeitsmappe zu verwer- fen. 6.4.3 Mehrere Arbeitsmappen schießen Wenn mehrere Arbeitsmappen in Excel geöffnet wurden, lässt sich ganz schnell mit der Tastenkombination Ÿ+Î zwischen den einzelnen Arbeitsmappen hin- und herwechseln. Möchten Sie jetzt alle Arbeitsmappen, mit Ausnahme der Mappe, in der das Makro aus Listing 6.12 untergebracht ist, schließen, dann starten Sie das folgende Makro: Sub MehrereMappenSchließen() Dim Mappe As Workbook For Each Mappe In Application.Workbooks Listing 6.12: Alle Mappen außer der »Code-Mappe« schließen If Mappe.Name <> ThisWorkbook.Name Then Mappe.Close SaveChanges:=True End If Next Mappe End Sub Im Auflistungsobjekt Workbooks sind alle zurzeit geöffneten Arbeitsmappen verzeichnet. In einer For Each...Next-Schleife kann nun der Name der Arbeitsmappe, die den Code aus Listing 6.12 enthält, mit den Namen der anderen geöffneten Arbeitsmappen verglichen werden. Mit der Methode Close werden dann alle Arbeitsmappen geschlossen, bis auf die Arbeitsmappe, die das Listing 6.12 enthält. 201 6 Die Programmierung von Arbeitsmappen jetzt lerne ich 2 An dieser Stelle muss auf den Unterschied zwischen den Anweisungen ... ActiveWorkbook und ThisWorkbook ... hingewiesen werden. Die Arbeitsmappe, die mit der Eigenschaft ActiveWorkbook angesprochen wird, ist die Arbeitsmappe, die momentan aktiv ist, d. h., wenn Sie aus der Entwicklungsumgebung herausspringen und in die normale Arbeitsoberfläche von Excel wechseln. Mit der Eigenschaft ThisWorkbook ist die Arbeitsmappe gemeint, in der die Makros enthalten sind. Halten Sie diese beiden Eigenschaften auseinander und klären immer genau ab, was in welcher Arbeitsmappe vorgenommen werden soll. 6.5 Excel-Mappen listen und linken Ein übersichtliches Auskunftssystem lässt sich in einer Tabelle anlegen, indem Sie zum Beispiel Excel-Arbeitsmappen über einen Suchlauf in einem bestimmten Verzeichnis auslesen und deren Namen in eine Excel-Tabelle schreiben. Beim folgenden Makro aus Listing 6.13 wird davon ausgegangen, dass das Verzeichnis C:\Eigene Dateien auf Ihrer Festplatte bereits existiert. Passen Sie dieses Verzeichnis gegebenenfalls vorher an. Listing 6.13: Alle ExcelMappen ermitteln und auflisten Sub ExcelMappenAuflisten() Dim lngZaehler As Long Const Pfad = "C:\Eigene Dateien\" On Error GoTo fehler ChDir Pfad With Application.FileSearch .NewSearch .LookIn = Pfad .SearchSubFolders = False .FileType = msoFileTypeExcelWorkbooks .Execute For lngZaehler = 1 To .FoundFiles.Count Sheets(1).Cells(lngZaehler, 1).Value = .FoundFiles(lngZaehler) Next lngZaehler End With 202 Excel-Mappen listen und linken jetzt lerne ich Sheets(1).Columns("A").Columns.AutoFit Exit Sub fehler: MsgBox "Kein Verzeichnis mit dem Namen " & Pfad End Sub Zu Beginn des Makros wird das zu durchsuchende Verzeichnis in einer Konstanten angegeben und über die Anweisung ChDir dann direkt in dieses Verzeichnis gewechselt. Danach wird die Suche gestartet und mit dem Objekt FileSearch die einzelnen Dateien im Verzeichnis ermittelt. Auf dieses Objekt lassen sich einige Eigenschaften anwenden: Die Eigenschaft NewSearch setzt die Einstellungen aller Suchkriterien auf die Standardeinstellungen zurück. Mithilfe der Eigenschaft LookIn geben Sie bekannt, in welchem Verzeichnis die Suche beginnen soll. Die Eigenschaft SearchSubFolders bestimmt, ob die Suche auch in Unterverzeichnissen fortgesetzt werden soll. In diesem Fall muss diese Eigenschaft auf den Wert True gesetzt werden. Die Eigenschaft FileType gibt den Dateityp in einer Konstanten an, nach der gesucht werden soll. Über die Eigenschaft FoundFiles sowie den Index lngZaehler wird dann der Name der gefundenen Datei ermittelt und direkt in Ihre Excel-Tabelle geschrieben. Bild 6.3: Alle Mappen wurden in einer Tabelle verzeichnet Im nächsten Schritt werden die gerade eingefügten Namen der Excel-Dateien mit Hyperlinks im Makro aus Listing 6.14 ausgestattet. 203 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Listing 6.14: Sub HyperlinksErstellen() Hyperlinks Dim rngBereich As Range einfügen Dim rngZelle As Range Set rngBereich = Sheets(1).Range("A1").CurrentRegion For Each rngZelle In rngBereich rngZelle.Hyperlinks.Add rngZelle, rngZelle.Value Next rngZelle End Sub Über die Eigenschaft CurrentRegion ermitteln Sie den Bereich, der um die Zelle A1 mit Daten gefüllt ist. Innerhalb dieses Bereichs sollen alle Einträge in Hyperlinks umgesetzt werden. Dazu wird die Methode Add eingesetzt. Die Sprung-Adresse geht dabei direkt aus dem Zelleneintrag hervor. Bild 6.4: Alle ExcelMappen wurden verlinkt 6.6 Arbeitsmappen zusammenführen In der folgenden Aufgabe wird auf ein bestimmtes Verzeichnis zugegriffen und dann dort eine Arbeitsmappe nach der anderen geöffnet. Übertragen Sie dann die jeweils erste Tabelle in die aktuelle Arbeitsmappe. Das Makro zur Lösung dieser Aufgabenstellung können Sie im folgenden Listing 6.15 sehen: 204 Arbeitsmappen zusammenführen Sub Dim Dim Dim Dim TabellenInEineMappe() VerzVar As String Pfadname As String ZielMappe As Workbook QuellMappe As Workbook jetzt lerne ich Listing 6.15: Mehrere Mappen zusammenführen 'hier anpassen Pfadname = "c:\Eigene Dateien\" VerzVar = Dir(Pfadname & "*.xls") Set ZielMappe = ThisWorkbook Do While VerzVar <> "" UserFile = Pfadname & VerzVar Set QuellMappe = Workbooks.Open(Filename:=UserFile) QuellMappe.Sheets(1).Copy Before:=ThisWorkbook.Sheets(1) VerzVar = Dir() QuellMappe.Close savechanges:=False Loop End Sub Zunächst werden in dem Makro in Listing 6.15 einige Variablen deklariert. Die ersten beiden Variablen werden direkt im Anschluss mit dem gewünschten Pfad, in dem sich die Mappen befinden, sowie der Dateiendung dieser Mappen belegt. Übergeben Sie den zusammengesetzten Suchbegriff der Funktion Dir und starten damit die Suche. In einer Do While-Schleife werden nun die Mappen einzeln abgearbeitet. Innerhalb der Schleife kopieren Sie über die Methode Copy jeweils die erste Tabelle einer jeden Mappe und fügen diese immer zu Beginn Ihrer Quellarbeitsmappe ein. Anschließend wird über die Funktion Dir die nächste Mappe abgefragt. Jede verarbeitete Datei wird nach Verwendung mithilfe der Methode Close wieder geschlossen Da keine Veränderungen an diesen Dateien durchgeführt wurden, erhält das Argument SaveChanges dieser Methode den Wert False. 205 6 Die Programmierung von Arbeitsmappen jetzt lerne ich 6.7 Arbeitsmappen entfernen Wenn eine Arbeitsmappe gelöscht werden soll, ohne dazu den Datei-Explorer von Windows einzusetzen, wird hierfür die Anweisung Kill eingesetzt. Dabei darf die zu löschende Arbeitsmappe selbstverständlich nicht geöffnet sein! Im folgenden Beispiel in Listing 6.16 wird eine bestimmte Arbeitsmappe aus einem vorgegebenen Verzeichnis unwiderruflich entfernt. Listing 6.16: Sub ArbeitsmappeEntfernen() Eine Arbeits- Const Datei = "c:\Mappe1.xls" mappe löschen On Error GoTo fehler Kill Datei MsgBox "Arbeitsmappe " & Datei & " wurde gelöscht!" Exit Sub fehler: MsgBox "Es konnte keine Datei mit dem Namen " & _ Datei & " gefunden werden!" End Sub Beachten Sie hierbei die Fehlerbehandlung von Excel. Wenn Sie z. B. zweimal hintereinander versuchen, das Makro ArbeitsmappeEntfernen auszuführen, wird beim ersten Aufruf die Bestätigung angezeigt, dass die Datei gelöscht wurde. Bei einem weiteren Versuch, die nun nicht mehr vorhandene Arbeitsmappe zu löschen, liefert Excel Ihnen die Fehlermeldung, die unter der Zeilenmarke Fehler steht. 6.8 Mit Dokumenteigenschaften arbeiten Die Dokumenteigenschaften einer Arbeitsmappe lassen sich hinterlegen oder einsehen, indem Sie aus dem Menü DATEI den Befehl EIGENSCHAFTEN wählen. Wie in der Abbildung 6.5 dargestellt, sind die momentan verfügbaren Eigenschaften doch etwas rar gesät. Diese Dokumenteigenschaften können über den Einsatz von VBA sowohl gesetzt als auch abgefragt werden. 206 Mit Dokumenteigenschaften arbeiten jetzt lerne ich Bild 6.5: Die Dokumenteigenschaften einsehen 6.8.1 Dokumenteigenschaften auslesen Es existiert eine ganze Reihe von Dokumenteigenschaften für eine Arbeitsmappe. Wie aber lassen sich diese Dokumenteigenschaften ansprechen? Die Antwort auf diese Frage kann dem Makro in Listing 6.17 entnommen werden. Sub DokumentEigenschaftenAuslesen() Dim zeile As Integer Dim obj As Object zeile = 1 Listing 6.17: Alle Dokumenteigenschaften auslesen Sheets.Add before:=Worksheets(1) For Each obj In ActiveWorkbook.BuiltinDocumentProperties Cells(zeile, 1).Value = obj.Name On Error Resume Next Cells(zeile, 2).Value = obj.Value zeile = zeile + 1 Next obj End Sub Mit dem Befehl Sheets.Add wird gleich zu Beginn eine neue Tabelle in die aktuelle Arbeitsmappe eingefügt. Danach werden über eine 207 6 Die Programmierung von Arbeitsmappen jetzt lerne ich Schleife, nacheinander alle Dokumenteigenschaften der Arbeitsmappe ausgelesen und mit dem Namen sowie deren momentanen Inhalten in die Tabelle geschrieben. Hierfür wird noch die Eigenschaft BuiltInDocumentProperties benötigt, die eine Auflistung aller Dokumenteigenschaften ermöglicht. Bild 6.6: Alle verfügbaren Dokumenteigenschaften für eine Mappe 6.8.2 Dokumenteigenschaften setzen Nachdem Sie nun wissen wie die einzelnen Dokumenteigenschaften benannt sind, lassen sich für eine neue Arbeitsmappe die folgenden Dokumenteigenschaften relativ einfach hinterlegen: 쐽 Der Titel soll gesetzt werden (z. B. VBA-Demos). 쐽 Das Thema soll ebenfalls angegeben werden (z. B. Arbeitsmappenbeispiele). 쐽 Die Kategorie soll den Begriff »VBA« erhalten. 208 Mit Dokumenteigenschaften arbeiten jetzt lerne ich 쐽 Als Stichwörter sollen die Begriffe VBA, Makros und Programmierung aufgeführt werden. 쐽 Ebenso soll ein mehrzeiliger Kommentar als Dokumenteigenschaft gesetzt werden. Sub DokuEigenschaftenSetzen() Dim Mappe As Workbook Set Mappe = Workbooks.Add Listing 6.18: Mehrere Dokumenteigenschaften setzen With Mappe .BuiltinDocumentProperties("Title").Value = "VBA-Demos" .BuiltinDocumentProperties("Subject").Value = _ "Arbeitsmappenbeispiele" .BuiltinDocumentProperties("Category").Value = "VBA" .BuiltinDocumentProperties("Keywords").Value = _ "VBA, Makros, Programmierung" .BuiltinDocumentProperties("Comments").Value = _ "Beispiele zur Programmierung mit Excel-VBA " & vbLf & _ "Weitere Infos unter der URL: http://Held-office.de" End With End Sub Füllen Sie die einzelnen Dokumenteigenschaften, indem die Eigenschaft BuiltInDocumentProperties mit dem richtigen Namen angesprochen wird und dann den gewünschten Inhalt übergeben bekommt. Bild 6.7: Die Dokumenteigenschaften wurden gesetzt 209 jetzt lerne ich 6 Die Programmierung von Arbeitsmappen Das Ergebnis kann überprüft werden, indem Sie aus dem Menü DATEI den Befehl EIGENSCHAFTEN wählen und die Registerkarte ZUSAMMENFASSUNG aktivieren. 210 jetzt lerne ich KAPITEL 7 Eigene Funktionen schreiben In diesem Kapitel lernen Sie die Möglichkeiten kennen, wie sich Excel zusätzlich optimieren lässt, indem zusätzlich zu den bestehenden eigene Funktionen programmiert werden, und wie sich diese generell einbinden lassen. Sie finden alle Beispiele dieses Kapitels auf der diesem Buch beiliegenden CD-ROM im Verzeichnis Kap07 in der Datei Funktionen.xls. 1 Standardmäßig bietet Ihnen Excel sowie VBA einige hundert Funktionen an, die für die tägliche Arbeit genutzt werden können. Dabei müssen Sie zwischen den folgenden Funktionen unterscheiden: 쐽 Auf der einen Seite gibt es Funktionen, die in einer Tabelle direkt in eine Zelle eingegeben werden. Die populärste dieser Funktionen ist sicherlich die Funktion SUMME(), die einen angegebenen Zellenbereich summiert. Weitere Funktionen können über den Funktionsassistenten menügeführt in Tabellen eingefügt werden. 쐽 Es gibt spezielle VBA-Standardfunktionen, die in Makros eingesetzt werden können, um unterschiedliche Aufgaben zu erledigen. Ein Beispiel für eine solche Funktion stellt die Funktion Len dar, über die beispielsweise die Länge eines Textes festgestellt werden kann. Diese und weitere Funktionen können Sie in der 211 7 Eigene Funktionen schreiben jetzt lerne ich Online-Hilfe auf der Registerkarte INHALT unter der Rubrik FUNKTIONEN nachschlagen. In den meisten Fällen wird zu diesen Funktionen auch ein kleines Beispiel angeboten, das Sie kopieren und in eigenen Projekten mit einbauen können. 쐽 Des Weiteren gibt es Funktionen, die Sie selbst schreiben, um sich Schreibarbeit zu sparen und Redundanz von Quellcode zu vermeiden. Ein Beispiel für diese Art von Funktionen wäre eine, die überprüft, ob eine bestimmte Tabelle in einer Arbeitsmappe vorhanden ist. Da so eine Aufgabe in der Programmierung bestimmt sehr oft benötigt wird, empfiehlt es sich, eine solche Aufgabe in eine allgemeine Funktion zu packen und diese dann aus den verschiedenen Makros aufzurufen. Der Vorteil liegt auf der Hand: Wenn die Funktion geändert werden soll, dann muss dies nicht an zig Stellen im Quellcode gemacht werden, sondern eben nur in dieser einen Funktion. Jede Funktion beginnt mit dem Schlüsselwort Function, gefolgt vom Namen der Funktion, der nahezu beliebig gewählt werden kann. Nach dem Namen folgen in Klammern die Argumente, die der Funktion übergeben werden sollen. 7.1 Eigene Tabellenfunktionen stricken Sicher ist die Auswahl der standardmäßig angebotenen Tabellenfunktionen umfangreich und in den meisten Fällen auch ausreichend. Trotzdem gibt es hier und da noch Bedarf, eigene Tabellenfunktionen zu erstellen, um spezielle Aufgaben zu lösen. Die so erstellten neuen Tabellenfunktionen lassen sich ebenso über den Funktionsassistenten unter der Rubrik BENUTZERDEFINIERT einfügen. 7.1.1 Zellen mit roter, dicker Schriftfarbe summieren In der ersten Aufgabe liegt eine Tabelle mit Zahlenwerten vor. Die Aufgabe besteht nun darin, aus dieser Tabelle alle Zahlen zu summieren, deren Schriftfarbe ROT und deren Schriftschnitt FETT ist. Sehen Sie sich dazu einmal die Ausgangssituation in Abbildung 7.1 an. Die Zellen A2, A5 und A9 sind dabei mit der Schriftfarbe ROT und dem Schriftschnitt FETT formatiert. 212 Eigene Tabellenfunktionen stricken jetzt lerne ich Bild 7.1: Einige Zahlenwerte sind formatiert Erfassen Sie nun die Funktion, die ausschließlich die rot und fett formatierten Zellen summiert. Sehen Sie sich dazu das Makro in Listing 7.1 an. Function RUF(zelle As Range) Application.Volatile Listing 7.1: Formatierte Zellen summieren For Each zelle In zelle.Cells If IsNumeric(zelle) Then If zelle.Font.Bold = True And _ zelle.Font.ColorIndex = 3 Then RUF = RUF + zelle.Value End If End If Next zelle End Function Jede Funktion beginnt mit dem Schlüsselwort Function, gefolgt vom Namen der Funktion, der nahezu beliebig gewählt werden kann. Da der Name dieser Funktion später direkt in einer Tabellenzelle erfasst wird, empfiehlt es sich, möglichst kurze Funktionsnamen zu verwenden. Der hier gewählte Name RUF steht dabei abgekürzt für »Rot und Fett«. Nach dem Namen folgen in Klammern die Argumente, die der Funktion übergeben werden sollen. Da dieses Argument in un- 213 jetzt lerne ich 7 Eigene Funktionen schreiben serem Beispiel Zellen sein werden, übergeben wir der Funktion eine Objektvariable vom Typ Range. Der Aufruf der Funktion in einer beliebigen Zelle einer Tabelle lautet danach beispielsweise =RUF(A1:A10). Mit der Anweisung Application.Volatile wird dafür gesorgt, dass der Wert der Zelle neu berechnet wird, wenn ein neuer Wert in der Tabelle erfasst wird. Die Aktualisierung erfolgt nicht automatisch, wenn nur die Formatierung einer Zelle geändert wird! In einer anschließenden Schleife werden alle Zellen nacheinander abgearbeitet, die mit der Funktion übergeben wurden. Innerhalb dieser Schleife sollte sichergestellt werden, dass es sich wirklich um Zellen handelt, die Zahlenwerte enthalten. Wenn dem nicht so ist, meldet die VBA-Funktion IsNumeric den Wert False, was zur Folge hat, dass eine solche Zelle ignoriert wird. Neben dieser Prüfung folgt eine weitere, ob der Schriftschnitt FETT ist. Hierzu wird die Eigenschaft Bold des Font-Objekts abgefragt. Meldet diese Prüfung als Ergebnis den Wert True, dann ist die Zelle mit dem Schriftschnitt FETT formatiert. Als weitere Bedingung war noch vorgegeben, dass auch die richtige Farbe, nämlich ROT, vorliegt. Die Farbe der Schriftart lässt sich über die Eigenschaft ColorIndex feststellen, die für die Farbe ROT den Index 3 zurückmeldet. Nur wenn diese beiden Formatierungskriterien zutreffen, erfolgt eine Summierung. Achten Sie dabei darauf, dass die bereits ermittelten Werte nicht überschrieben werden. Für diesen Fall kann die Anweisung RUF = RUF + zelle.Value, verwendet werden, was bedeutet, dass der bisherige Wert der momentan in RUF steht, mit dem Wert addiert wird, der sich in der aktuell überprüften Zelle befindet. Testen Sie nun die Funktion, indem diese, gemäß der Abbildung 7.2, in eine beliebige Zelle der Tabelle eingegeben wird. 214 Eigene Tabellenfunktionen stricken jetzt lerne ich Bild 7.2: Die roten, fetten Zellen wurden summiert 7.1.2 Formatierte Zellen zählen Übrigens können Sie die Funktion in Listing 7.1 als Vorlage nutzen, wenn es darum geht, statt der Summierung eine einfache Zählung durchzuführen. In diesem Fall lautet die Funktion wie folgt: Function RUFZ(zelle As Range) Application.Volatile For Each zelle In zelle.Cells Listing 7.2: Die Zellen mit einem bestimmten Format zählen If IsNumeric(zelle) Then If zelle.Font.Bold = True _ And zelle.Font.ColorIndex = 3 Then RUFZ = RUFZ + 1 End If End If Next zelle End Function Addieren Sie innerhalb der zweiten Schleife bei jedem Vorkommen der abgefragten Formatierung den Wert 1. 215 7 Eigene Funktionen schreiben jetzt lerne ich 7.1.3 Die dynamische Farbwahl per Parameterübergabe Bei den beiden Funktionen in Listing 7.1 und Listing 7.2 wurde unter anderem die Farbe Rot als Bedingung vorgegeben, d. h. es ist mit diesen zwei Funktionen nur möglich rote und fett formatierte Einträge in einem Bereich zu summieren bzw. zu zählen. Wie könnte die Lösung aussehen, wenn nun nicht nur rote, sondern auch einmal blaue, grüne oder gelbe Einträge summiert bzw. gezählt werden sollen? Dazu lässt sich die Funktion in Listing 7.1 erweitern, indem Sie dort im Funktionskopf die gewünschte Farbe als Farbnummer mit übergeben. Listing 7.3: Function SumFarb(zelle As Range, FarbNr As Integer) Die dynamische Farb- Application.Volatile abfrage der Schriftart For Each zelle In zelle.Cells If IsNumeric(zelle) Then If zelle.Font.Bold = True And _ zelle.Font.ColorIndex = FarbNr Then SumFarb = SumFarb + zelle.Value End If End If Next zelle End Function Werten Sie innerhalb der Funktion SumFarb in der zweiten Schleife die Schriftfarbe der Zelle aus. Entspricht diese Farbe der übergebenen Farbnummer, dann wird der Eintrag der jeweiligen Zelle summiert. Der Aufruf der Funktion in einer beliebigen Zelle einer Tabelle lautet danach beispielsweise =SUMFARB(A1:A10;3). 216 Eigene Tabellenfunktionen stricken jetzt lerne ich Bild 7.3: Die Schriftfarben können dynamisch summiert werden 7.1.4 Aktuelle Arbeitsmappe ermitteln Um zu prüfen, welchen Namen die momentan aktive Arbeitsmappe hat, lässt sich eine benutzerdefinierte Funktion schreiben, die den Namen der Arbeitsmappe zunächst ermittelt und dann in eine Zelle schreibt. Die Funktion für diese Aufgabe ist so einfach wie in Listing 7.4 beschrieben: Function AktMap() AktMap = ActiveWorkbook.Name End Function Listing 7.4: Den Namen der aktiven Mappe in eine Zelle schreiben Über die Anweisung ActiveWorkbook.Name wird der Name der Arbeitsmappe ermittelt. Wenn Sie zusätzlich zum Namen auch noch den Speicherpfad ermitteln möchten, lässt sich die Funktion in Listing 7.4 wie folgt erweitern: Listing 7.5: Den Pfad und AktMapV = ActiveWorkbook.FullName den Dateinamen der aktiEnd Function ven Mappe in Über die Eigenschaft FullName wird der Name sowie der Pfad einer eine Zelle schreiben Function AktMapV() gespeicherten Arbeitsmappe ermittelt. Allerdings muss diese Arbeitsmappe vorher einmal gespeichert worden sein. 217 7 Eigene Funktionen schreiben jetzt lerne ich Bild 7.4: Der Pfad und der Dateiname wurde ermittelt 7.1.5 Zelleninformationen abfragen In der nächsten Aufgabe wird eine Zelle mithilfe einer Funktion überprüft. Je nach Funktionsaufruf sollen dabei folgende Informationen ermittelt werden: 쐽 die Zellenadresse, 쐽 der Zellenwert, 쐽 die Zellenformel. Alle diese Informationen lassen sich über die folgende Funktion in Listing 7.6 abfragen: Listing 7.6: Function INFOZ(zelle As Range, i As Integer) Einige ZellenSelect Case i informationen werden Case 1 abgefragt INFOZ = zelle.Address Case 2 INFOZ = zelle.Value Case 3 INFOZ = zelle.FormulaLocal Case Else INFOZ = "nicht vergeben" End Select End Function 218 Eigene Tabellenfunktionen stricken jetzt lerne ich Bei der Funktion in Listing 7.6 lassen sich je nach Bedarf sowohl die Zellenadresse als auch der Zellenwert und die Zellenformel abfragen. Um beispielsweise die Zellenadresse abzufragen, rufen Sie die Funktion in einer Tabelle wie folgt auf: =INFOZ(A5;1). Innerhalb dieser Funktion wird genau das zweite Argument ausgewertet. Um die Zellenadresse zurückzugeben, wird die Eigenschaft Address eingesetzt. Der Wert einer Zelle lässt sich über die Eigenschaft Value ermitteln und die Formel der Zelle erhalten Sie über die Eigenschaft FormulaLocal. Bild 7.5: Die Funktion infoz liefert Informationen über die Zelle 7.1.6 Dokumenteigenschaften per Funktion abfragen Das folgende Beispiel ähnelt der vorher beschriebenen Aufgabe. Auch in diesem Beispiel wird eine Funktion generiert, die mithilfe eines flexiblen Arguments unterschiedliche Ergebnisse zurückmeldet. So sollen unter anderem folgende Dokumenteigenschaften über eine Tabellenfunktion abgefragt werden: 쐽 Dateiname und Pfad, 쐽 nur Dateiname, 쐽 nur Pfad der Datei, 쐽 Dateityp, 쐽 Dateigröße, 쐽 Erstellungsdatum der Datei, 쐽 letzte Änderung an der Datei, 쐽 letzter Zugriff auf die Datei. 219 jetzt lerne ich 7 Eigene Funktionen schreiben Fassen Sie diese Informationen nun in einer Funktion zusammen, die in Listing 7.7 beschrieben ist: Listing 7.7: Dokumenteigenschaften über eine Funktion abfragen Function DokuEig(EigenschaftsNr As Integer) Dim fso As Object Dim tmp As String Set fso = CreateObject("Scripting.FileSystemObject") With fso.GetFile(ActiveWorkbook.FullName) Select Case EigenschaftsNr Case Is = 1 tmp = .Path Case Is = 2 tmp = Mid(.Path, 1,Len(.Path) - Len(.Name)) Case Is = 3 tmp = .Name Case Is = 4 tmp = .Type Case Is = 5 tmp = .Size Case Is = 6 tmp = .DateCreated Case Is = 7 tmp = .DateLastModified Case Is = 8 tmp = .DateLastAccessed Case Else tmp = "Ungültige EigenschaftsNr!" End Select End With DokuEig = tmp End Function 220 Eigene Tabellenfunktionen stricken jetzt lerne ich Als erster wesentlicher Schritt wird ein Verweis auf das FileSystemObject generiert, um damit die Informationen bezüglich der Arbeitsmappe zu ermitteln. Über die Methode GetFile teilen Sie Excel mit, welche Datei auszuwerten ist. Danach wird die übergebene Eigenschaften-Nummer in einer Select Case-Anweisung ausgewertet: 쐽 Mithilfe der Eigenschaft Path ermitteln Sie den Namen sowie den kompletten Speicherpfad der aktiven Arbeitsmappe. 쐽 Das Verzeichnis wird ermittelt, indem über die Funktion Mid ein Teil aus der kompletten Pfadangabe herausgeschnitten wird. Dabei subtrahieren Sie die Länge des Gesamttextes von der Anzahl der Zeichen des Dateinamens, der über die Eigenschaft Name ermittelt wurde. 쐽 Der Name der Datei wird direkt über die Eigenschaft Name ermittelt. 쐽 Die Eigenschaft Type meldet den Typ der Datei, d. h. Sie können diese Funktion auch mit Word-Dokumenten, Access-Datenbanken und allen anderen Dateitypen anwenden. 쐽 Die Eigenschaft Size gibt die Größe der Datei in Bytes an. 쐽 Mithilfe der Eigenschaft DateCreated können Sie das Erstellungsdatum einer Datei ermitteln. 쐽 Über die Eigenschaft DateLastModified gelangen Sie an das Datum inklusive der Uhrzeit der letzten Änderung der Datei. 쐽 Mit der Eigenschaft DateLastAccessed wird das letzte Zugangsdatum der Datei ermittelt, das bedeutet, wann die Datei das letzte Mal geöffnet wurde. Nach der Programmierung der Funktion im VBA- Editor, wechseln Sie in die Tabelle und tragen in Spalte A die Zahlen 1–8, wie in der Abbildung 7.6 dargestellt, ein. Nach der Markierung des Zellenbereichs B1:B8, wird die Formel =DOKUEIG(A1) eingegeben und die Eingabe über die Tastenkombination Ÿ+Æ bestätigt. 221 7 Eigene Funktionen schreiben jetzt lerne ich Bild 7.6: Auf die Schnelle wurde auf die Dokumenteigenschaften zugegriffen 7.1.7 Buchstaben aus Zeichenfolgen entfernen Mit der folgenden Funktion werden aus einer Zeichenfolge alle Buchstaben entfernt. Listing 7.8: Function BuchstabenRaus(Zelle As Range) Buchstaben Dim intz As Integer aus Zellen entfernen For intz = 1 To Len(Zelle) Select Case Mid(Zelle, intz, 1) Case 0 To 9 BuchstabenRaus = BuchstabenRaus & Mid(Zelle, intz, 1) Case Else End Select Next intz End Function Der Funktion BuchstabenRaus wird über einen Zellenbezug (z. B. A1) der Inhalt aus einer Zelle übergeben. In der Funktion angekommen wird über eine Schleife Zeichen für Zeichen abgearbeitet und nach Vorgabe überprüft. Entspricht das jeweilige Zeichen einer gültigen Zahl zwischen 0 und 9, wird dieses Zeichen zwischengespeichert. Übergeben Sie am Ende die bereinigte Zeichenfolge an die Zelle zurück, in der die Funktion aufgerufen wurde. 222 Eigene Tabellenfunktionen stricken jetzt lerne ich Bild 7.7: Alle Buchstaben wurden eliminiert 7.1.8 Zahlen aus Zeichenfolgen entfernen Das oben gezeigte Beispiel, nur mit umgekehrter Funktionsweise, sehen Sie in der Prozedur in Listing 7.9. Dabei werden aus einer Zeichenfolge alle numerischen Teile entfernt. Function ZahlenRaus(Zelle As Range) Dim intz As Integer For intz = 1 To Len(Zelle) Listing 7.9: Zahlen aus Zellen entfernen Select Case Mid(Zelle, intz, 1) Case 0 To 9 Case Else ZahlenRaus = ZahlenRaus & Mid(Zelle, intz, 1) End Select Next intz End Function In der Funktion ZahlenRaus wird der Inhalt der jeweiligen Zelle übergeben. In der Funktion angekommen wird über eine Schleife Zeichen für Zeichen überprüft. In dieser Funktion wird nun der Case Else-Zweig genutzt, um die Zahlen zu entfernen. Schreiben Sie am Ende die bereinigte Zeichenfolge in die jeweilige Zelle. 223 7 Eigene Funktionen schreiben jetzt lerne ich 7.1.9 Das erste Auftreten einer Zahl ermitteln Bei der nächsten Aufgabe soll die Position des ersten Auftretens einer Zahl in einer Zelle ermittelt und ausgegeben werden. Sehen Sie sich zu diesem Zweck die Funktion in Listing 7.10 an: Listing 7.10: Function PosErsteZahl(Zelle As Range) Die Position Dim i As Integer der ersten Zahl ermitteln Application.Volatile For i = 1 To Len(Zelle) Select Case Mid(Zelle, i, 1) Case 0 To 9 PosErsteZahl = i Exit Function End Select Next i PosErsteZahl = 0 End Function Im ersten Schritt wird die Länge der Zelle über die Funktion Len ermittelt. Danach extrahieren Sie mithilfe der Funktion Mid Zeichen für Zeichen aus der Zelle. Nun wird der Wertebereich 0 bis 9 innerhalb der Select Case-Anweisung ausgewertet. Wird das erste numerische Zeichen in der Zelle gefunden, wird mit der Anweisung Exit Function die Funktion verlassen. In der Variablen steht dann automatisch die richtige Position des Zeichens. Wurde kein numerisches Zeichen gefunden, meldet die Funktion den Wert 0 zurück. 224 Eigene Tabellenfunktionen stricken jetzt lerne ich Bild 7.8: Das erste Auftreten einer Zahl wird festgehalten 7.1.10 Zahlen als Text ausgeben Beim folgenden Beispiel wird eine Zahl als Text ausgegeben. So wird aus der Zahl 325 der Text dreihundertfünfundzwanzig. Function ZIT(Zahl As Integer) Dim Tausender As Single Dim Hunderter As Single Dim Zehner As Single Dim Einstellig As Variant Dim Zweistellig As Variant Dim zVar As Single Dim ZahlinText As String Listing 7.11: Zahlen als Text darstellen Einstellig = Array("", "Ein", "zwei", "drei", "vier", "fünf", _ "sechs", "sieben", "acht", "neun", "zehn", "elf", _ "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", _ "siebzehn", "achtzehn", "neunzehn") Zweistellig = Array("", "zehn", "zwanzig", "dreißig", "vierzig", _ "fünfzig", "sechzig", "siebzig", "achtzig", "neunzig") ZIT = "" If Zahl = 0 Then ZahlinText = "Null" End If Tausender = Zahl \ 1000 225 jetzt lerne ich 7 Eigene Funktionen schreiben If Tausender > 0 Then ZIT = Einstellig(Tausender) & "tausend" End If Zahl = Zahl - Tausender * 1000 Hunderter = Zahl \ 100 If Hunderter > 0 Then ZIT = ZIT & Einstellig(Hunderter) & "hundert" End If Zahl = Zahl - Hunderter * 100 If Zahl < 20 Then Zehner = Zahl ZIT = ZIT & Einstellig(Zehner) & " " Else Zehner = Zahl \ 10 zVar = Zahl - Zehner * 10 ZIT = ZIT & Einstellig(zVar) & "und" ZIT = ZIT & Zweistellig(Zehner) & " " End If End Function In der Funktion ZIT wird zunächst überprüft, ob eine Tausenderzahl vorliegt. Danach arbeiten Sie sich zu den Hundertern und Zehnern durch, greifen dabei immer wieder auf die beiden Datenfelder einstellig bzw. zweistellig zu und holen die entsprechenden »Zahlentexte«. Bild 7.9: Die Ausgabe von Zahlen in Textform 226 Eigene Tabellenfunktionen stricken 7.1.11 jetzt lerne ich Initialen bilden Im nächsten Beispiel werden mithilfe einer benutzerdefinierten Funktion aus Vor- und Nachnamen Initialen gebildet. So wird aus MICHAEL MÜLLER die Initiale MM. Function Initiale(str As String) As String Dim intz As Integer Listing 7.12: Aus Namen die Initialen bilden str = " " & Trim(str) For intz = 2 To Len(str) If Mid(str, intz - 1, 1) = " " Then Initiale = Initiale & Mid(str, intz, 1) End If Next intz End Function Bei der Funktion in Listing 7.12 wird jeweils das Zeichen vor dem Leerzeichen gespeichert. Dafür sorgt das zweite Argument bei der Funktion Mid, das die Position des zu übertragenden Zeichens angibt. Übergeben Sie am Ende die so ermittelten Anfangszeichen an die jeweilige Zelle. Bild 7.10: Es wird jeweils nur der erste Buchstabe übernommen 227 7 Eigene Funktionen schreiben jetzt lerne ich 7.2 Modulare Funktionen programmieren Nachdem Sie gelernt haben, wie benutzerdefinierte Tabellenfunktionen programmiert werden, kommen wir nun zu den modularen Funktionen. Unter einer modularen Funktion werden Arbeitsschritte zusammengefasst, die immer wieder in gleicher oder ähnlicher Form in Ihrem Quellcode genutzt werden. Anstatt diese Arbeitsschritte in Form von Anweisungen immer wieder neu zu erfassen, wird einmal eine Funktion definiert, die diese immer wieder an verschiedenen Stellen im Quellcode aufruft. Dies macht den Quellcode einfacher lesbar und Änderungen am Quellcode können so auch leichter durchgeführt werden. Lernen Sie in den folgenden Beispielen, wie Sie diese modularen Funktionen effizient bei Ihrer Arbeit einsetzen können. 7.2.1 Arbeitsmappen-Existenz prüfen Vor dem Öffnen einer bestimmten Arbeitsmappe über ein Makro, sollte sichergestellt sein, dass diese Arbeitsmappe überhaupt existiert. Damit werden unnötige Makroabstürze vermieden, weil solche Fehler abgefangen werden können. Erfassen Sie jetzt eine Funktion und übergeben dieser Funktion den Dateinamen mitsamt der Laufwerk- und Pfadangabe. Als Ergebnis dieser Funktion sollte dann eine Rückmeldung erfolgen, ob die angegebene Datei auch vorhanden ist. Listing 7.13: Function DateiExist(s As String) As Boolean Es wird geDateiExist = False prüft, ob eine If Len(s) > 0 Then DateiExist = (Dir(s) <> "") bestimmte Exit Function Mappe existiert End Function Wie schon erwähnt, erwartet die Funktion den Namen der Datei, deren Existenz geprüft werden soll. Die Prüfung, ob überhaupt eine Zeichenfolge an die Funktion übergeben wurde, erfolgt über die Funktion Len. Wird eine Länge von 0 gemeldet, wurde keine Zeichenfolge an die Funktion übergeben. Ansonsten entspricht diese in jedem Fall einer Größe >0. Die Funktion Dir versucht nun auf die Datei zuzugreifen. Ist die Datei nicht vorhanden, meldet diese eine 228 Modulare Funktionen programmieren jetzt lerne ich Leerfolge zurück. Damit wird der Datentyp Boolean mit dem Wert False an das aufrufende Makro zurückgemeldet. Im anderen Falle liefert die Funktion den Wert True zurück. Erfassen Sie jetzt das Makro, das die Funktion DateiExist aufruft und den Namen der zu überprüfenden Datei übergibt. Sub DateiÖffnen() Dim b As Boolean Const EDatei = "C:\Eigene Dateien\Mappe1.xls" b = DateiExist(EDatei) Listing 7.14: Vor dem Öffnen einer Mappe deren Existenz prüfen If b = True Then Workbooks.Open EDatei Else MsgBox "Die Datei " & EDatei & " ist nicht vorhanden!" End If End Sub Im Makro in Listing 7.14 wird der Name der zu öffnenden Datei in einer Konstanten zu Beginn des Makros festgelegt. Danach rufen Sie die Funktion DateiExist auf und übergeben dieser Funktion den Namen der zu prüfenden Datei. Das Ergebnis dieser Überprüfung durch die Funktion wird in der Variablen b abgelegt. Diese kann entweder False für den Fall, dass die Datei gar nicht existiert, oder True, sofern die Prüfung erfolgreich verlaufen ist, zurückgeben. In diesem Fall öffnen Sie die Datei mithilfe der Methode Open. 7.2.2 Arbeitsmappen-Zustand prüfen Manche Fehler treten auf, wenn versucht wird, über VBA Arbeitsmappen zu öffnen, die bereits geöffnet sind. Gerade wenn in einem größeren Projekt Dateien immer wieder geöffnet und geschlossen werden, kann es durchaus vorkommen, dass eine Arbeitsmappe doch bereits geöffnet ist. In der nächsten Funktion soll überprüft werden, ob eine bestimmte Arbeitsmappe bereits geöffnet wurde. Wenn ja, muss diese nicht noch einmal geöffnet, sondern nur aktiviert werden. Die Funktion zur Lösung dieser Aufgabenstellung können Sie in Listing 7.15 sehen. 229 7 Eigene Funktionen schreiben jetzt lerne ich Listing 7.15: Function MappeGeöffnet(strName As String) As Boolean On Error GoTo Fehler Es wird überMappeGeöffnet = True prüft, ob eine Windows(strName).Activate Mappe bereits Exit Function geöffnet ist Fehler: MappeGeöffnet = False End Function Sub MappeSchonGeöffnet() Dim B As Boolean B = MappeGeöffnet("Mappe1.xls") If B = True Then MsgBox "Mappe geöffnet!" Else MsgBox "Mappe geschlossen!" End If End Sub Die Funktion in Listing 7.15 erwartet als Argument den Namen der Datei, deren Status geprüft werden soll. Danach wird versucht, die entsprechende Datei zu aktivieren. Schlägt dies fehl, sorgt die On Error-Anweisung dafür, dass die Funktion nicht mit einer Fehlermeldung abbricht. In diesem Fall wird direkt zum Fehlerabschnitt fehler gesprungen. War die Aktion erfolgreich, wird die Funktion über die Anweisung Exit Function direkt verlassen. 7.2.3 Tabellen-Existenz prüfen Wenn versucht wird auf eine Tabelle zuzugreifen, die es in Ihrer Arbeitsmappe nicht gibt, folgt ein Absturz des Makros, sofern der Fehler nicht abgefangen wird. Fehler dieser Art, zum Beispiel verursacht durch führende oder nachfolgende Leerzeichen bei der Benennung von Tabellen, können schnell vorkommen und werden leicht übersehen. Die Groß- und Kleinschreibung spielt jedoch bei der Angabe des Tabellennamens keine Rolle. Im folgenden Beispiel in Listing 7.16 wird versucht auf die TABELLE3 der aktiven Arbeitsmappe zuzugreifen. Überprüfen Sie vor diesem 230 Modulare Funktionen programmieren jetzt lerne ich Zugriff über eine Funktion, ob diese Tabelle überhaupt in dieser Arbeitsmappe existiert. Function TabelleDa(s As String) As Boolean On Error GoTo fehler Sheets(s).Activate TabelleDa = True Exit Function Listing 7.16: Existiert eine bestimmte Tabelle? fehler: TabelleDa = False End Function Der Funktion TabelleDa wird der Name der Tabelle als String übergeben. Über die Methode Activate wird nun einfach einmal versucht, die angegebene Tabelle zu aktivieren. Schlägt dies fehl, meldet Excel einen Fehler, der sich abfangen lässt und über die Anweisung On Error ans Ende der Funktion verzweigt. Dort wird als Rückgabeargument an das aufrufende Makro der Wert False zurückgegeben. Sehen Sie sich nun das die Funktion aufrufende Makro in Listing 7.17 an: Sub TabelleAnspringen() Dim b As Boolean Const Tabelle = "Tabelle3" b = TabelleDa(Tabelle) Listing 7.17: Vor jedem Verwenden einer Tabelle wird deren Existenz überprüft If b = False Then MsgBox "Die Tabelle " & Tabelle & _ " konnte nicht gefunden werden!", vbCritical Else 'Tue nichts End If End Sub Der Name der zu aktivierenden Tabelle wird dem Makro in Listing 7.17 in einer Konstanten angegeben. Selbstverständlich lässt sich der Name der Tabelle auch direkt beim Funktionsaufruf angeben. b = TabelleDa("Tabelle3") 231 7 Eigene Funktionen schreiben jetzt lerne ich In beiden Fällen wird das Rückgabeergebnis der Funktion TabelleDa abgewartet und abhängig vom Wert True oder False reagiert. In dem Fall, dass die gewünschte Tabelle in der Arbeitsmappe vorhanden ist, müssen Sie nichts weiter unternehmen, da der Sprung in die Tabelle bereits in der Funktion TabelleDa durchgeführt wurde. Kann die Tabelle nicht gefunden werden, erfolgt eine Meldung auf dem Bildschirm. 7.2.4 Tabellenschutz ermitteln Im folgenden Beispiel in Listing 7.18 wird geprüft, ob in einer Tabelle ein Schreibschutz eingestellt wurde. Listing 7.18: Function TabProtect(s As String) As Boolean Tabelle geschützt oder On Error GoTo Fehler nicht? If Sheets(s).ProtectContents = True Then TabProtect = True Else End If Exit Function Fehler: TabProtect = False End Function Sub TabelleMitSchutz() Dim b As Boolean b = TabProtect("Tabelle1") If b = True Then MsgBox "Tabelle geschützt!" Else MsgBox "Tabelle ungeschützt!" End If End Sub Übergeben Sie der Funktion TabProtect den Namen der Tabelle, deren Schutzstatus abgefragt werden soll. Innerhalb der Funktion wird über die Eigenschaft ProtectContents abgefragt, ob die Tabelle geschützt ist. Wenn ja, dann gilt als Rückgabewert der Funktion an das aufrufende Makro der Wert True. 232 Modulare Funktionen programmieren 7.2.5 jetzt lerne ich Eine umfangreiche Löschfunktion generieren In dem nächsten Beispiel packen wir einige Unterfunktionen in eine einzelne Funktion hinein, um folgende Informationen aus einer Tabelle zu entfernen: 쐽 alle Inhalte, 쐽 alle Formatierungen, 쐽 alle Kommentare. 쐽 Formeln durch Festwerte ersetzen. 쐽 Hyperlinks löschen. Erfassen Sie jetzt die Funktion, die Sie in Listing 7.19 sehen können: Function LöschenWas(Nr As Integer) Dim zelle As Range Select Case Nr Case 1 Cells.Clear Listing 7.19: Diese Funktion löscht fast alles Case 2 Cells.ClearFormats Case 3 Cells.ClearComments Case 4 For Each zelle In ActiveSheet.UsedRange zelle.Value = zelle.Value Next zelle Case 5 For Each zelle In ActiveSheet.UsedRange With zelle If .Hyperlinks.Count > 0 Then .Hyperlinks.Delete With .Font .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With 233 jetzt lerne ich 7 Eigene Funktionen schreiben End If End With Next zelle Case Else MsgBox "Diese Nr ist nicht vergeben!" End Select End Function 쐽 Wird die Funktion LöschenWas mit dem Argument 1 aufgerufen, wenden Sie die Methode Clear an, um alle Zellen der Tabelle zu löschen. Im Auflistungsobjekt Cells sind alle Zellen der Tabelle enthalten. 쐽 Wird die Funktion LöschenWas mit dem Argument 2 aufgerufen, wenden Sie die Methode ClearFormats an, um alle Formatierungen in der Tabelle zu entfernen. Dazu zählen Formatierungen der Schrift, der Hintergrundfarbe, der Ausrichtung der Daten sowie alle möglichen Rahmen und sonstigen Formatierungsmöglichkeiten. 쐽 Wird die Funktion LöschenWas mit dem Argument 3 aufgerufen, wenden Sie die Methode ClearComments an, um alle in der Tabelle befindlichen Kommentare zu entfernen. 쐽 Wird die Funktion LöschenWas mit dem Argument 4 aufgerufen, sollen alle Formeln und Verknüpfungen in Festwerte umgewandelt werden. In diesem Fall ist es nicht sinnvoll, alle Zellen der Tabelle über das Auflistungsobjekt Cells abzuarbeiten. Schränken Sie die Bearbeitung auf die Zellen ein, die in der Tabelle verwendet werden. Dazu wird die Eigenschaft UsedRange auf die aktive Tabelle (ActiveSheet) angewendet. Innerhalb dieses verwendeten Bereichs wird jede Zelle angesteuert und eventuell vorhandene Formeln bzw. Verknüpfungen über die Eigenschaft Value durch den aktuellen Wert ersetzt. 쐽 Wird die Funktion LöschenWas mit dem Argument 5 aufgerufen, werden alle Hyperlinks in der Tabelle entfernt. Die Hyperlinktexte sollen aber erhalten bleiben. Auch für diesen Zweck sollen nicht alle Zellen der Tabellen über das Auflistungsobjekt Cells angesprochen werden. Stattdessen wird über die Anweisung Ac- 234 Modulare Funktionen programmieren jetzt lerne ich tiveSheet.UsedRange der verwendete Bereich der Tabelle ermittelt. In einer Schleife werden dann alle Zellen des Bereichs einzeln angesteuert und mithilfe der Eigenschaft Hyperlinks.Count geprüft, ob die jeweilige Zelle einen Hyperlink enthält. Wenn ja, meldet diese Eigenschaft den Wert 1 zurück und somit wird der Hyperlink mit der Methode Delete aus der Zelle entfernt. Da aber auch nach dem Entfernen des Hyperlinks die dafür typische Formatierung (blaue Schriftfarbe und Unterstreichung) erhalten bleibt, muss diese zusätzlich entfernt werden. Hierzu wird der Eigenschaft UnderLine die Konstante xlUnderlineStyleNone zugewiesen. Der Eigenschaft ColorIndex wird die Konstante xlAutomatic zugewiesen, um die aktuelle Standardfarbe in Excel zu verwenden. Rufen Sie jetzt beispielsweise die Funktion LöschenWas auf und übergeben der Funktion die Lösch-Nr. 5, um alle Hyperlinks aus der aktiven Tabelle zu entfernen. Sub Entfernen() Dim s As String s = InputBox _ ("Geben Sie eine Lösch-Nr zwischen 1 und 5 ein!", _ "Löschaktion durchführen", 1) Listing 7.20: Die Funktion LöchenWas wird aufgerufen If s <> "" Then LöschenWas (s) Else End If End Sub Über eine Eingabemaske kann festgelegt werden, welche Löschaktion durchgeführt werden soll. Die Funktion InputBox verwendet in diesem Beispiel drei Argumente. Im ersten Argument wird angegeben, welcher Text in der Eingabemaske angezeigt werden soll. Im zweiten Argument wird der Fenstertitel der Eingabemaske gesetzt. Mit dem dritten Argument besteht die Möglichkeit, das Eingabefeld bereits schon beim Aufruf der Maske vorzubelegen. Bild 7.11: Die Lösch-Nr. über eine Inputbox eingeben 235 7 Eigene Funktionen schreiben jetzt lerne ich 7.2.6 Dateien in einem Verzeichnis zählen Bei der folgenden Funktion werden alle Dateien eines Verzeichnisses gezählt. Listing 7.21: Function DateiZähler(VerzName) As Long Alle Dateien Dim strName As String eines Ver- Dim lngz As Long zeichnisses strName = Dir$(VerzName & "\*.*") werden gezählt Do While Len(strName) > 0 lngz = lngz + 1 strName = Dir$() Loop DateiZähler = lngz End Function Sub ZählenDateien() 'Achtung Pfad anpassen MsgBox DateiZähler("c:\Windows") End Sub Übergeben Sie der Funktion DateiZähler den Namen des Verzeichnisses, in dem die Anzahl der Dateien ermittelt werden soll. Innerhalb der Funktion setzen Sie eine Schleife auf, die alle Dateien des übergebenen Verzeichnisses zählt. Hierzu wird die Funktion Dir benötigt. 7.3 Funktionen dauerhaft verfügbar machen Bei den bisherigen Beispielen sind die Funktionen lediglich in der Arbeitsmappe verfügbar, die in der Entwicklungsumgebung ausgewählt wurde. Wenn Funktionen für alle Arbeitsmappen, ob neue oder alte, angewendet werden sollen, gibt es zwei Möglichkeiten: 쐽 Speichern in der persönlichen Arbeitsmappe Personl.xls oder 쐽 Erstellung eines ADD-INS und Aktivierung über den Add-Ins-Manager. 236 Funktionen dauerhaft verfügbar machen 7.3.1 jetzt lerne ich Speichern der Funktionen in der persönlichen Makroarbeitsmappe Um die Funktionen für alle Arbeitsmappen zur Verfügung zu haben, können Sie die Funktionen in Ihrer persönlichen Makroarbeitsmappe Personl.xls ablegen, die sich im Office-Verzeichnis XLSTART befindet. Sollte diese Arbeitsmappe noch nicht existieren, wird sie wie folgt beschrieben neu angelegt: 1. Wählen Sie in der Tabellenansicht den Menübefehl EXTRAS/MAKRO/ AUFZEICHNEN. 2. Wählen Sie im Dialogfeld MAKRO AUFZEICHNEN aus dem Kombinationsfeld den Eintrag PERSÖNLICHE MAKROARBEITSMAPPE. 3. Bestätigung durch OK. 4. Klicken Sie jetzt beispielsweise auf die Zelle A1. Der Makrorekorder wird die persönliche Arbeitsmappe erstellen und diesen Befehl aufzeichnen. Nun sind alle Voraussetzungen geschaffen worden, um eigene Funktionen in die persönliche Arbeitsmappe zu übertragen. 5. Beenden Sie die Makroaufzeichnung, indem Sie aus dem Menü EXTRAS den Befehl MAKRO/AUFZEICHNUNG BEENDEN auswählen. Übertragen Sie nun die Funktionen aus der Arbeitsmappe Funktionen.xls in die persönliche Arbeitsmappe Personl.xls. Dazu ist folgende Vorgehensweise notwendig: 1. Öffnen der Arbeitsmappe Funktionen.xls. 2. Wechseln Sie in die Entwicklungsumgebung. 3. Aktivieren Sie das MODUL1. 4. Markieren Sie alle Funktionen mit dem Menübefehl BEARBEITEN/ ALLES AUSWÄHLEN. 5. Drücken Sie die Tastenkombination Ÿ+C, um die Funktionen in die Zwischenablage zu kopieren. 6. Wählen Sie im Projekt-Explorer den Eintrag VBAPROJECT (PERSONAL .XLS) aus. 7. Aktivieren Sie in diesem Projekt das MODUL1. 237 7 Eigene Funktionen schreiben jetzt lerne ich 8. Fügen Sie Ihre Funktionen durch Positionierung des Mauszeigers im Code-Fenster ein und drücken Sie die Tastenkombination Ÿ+V. 9. Beenden Sie Excel und bestätigen beim Verlassen von Excel die Änderungsabfrage mit JA. Nun können nach erneutem Aufruf von Excel die benutzerdefinierten Tabellenfunktionen über den Funktionsassistenten in die Tabellen eingefügt werden. 7.3.2 Speichern der Funktionen in einem Add-In Die zweite Möglichkeit, um Funktionen allgemein verfügbar zu machen und auch noch an andere Anwender weiterzugeben, ist die Erstellung eines Add-Ins. Ein Add-In lässt sich direkt aus der Datei Funktionen.xls erstellen und bei Bedarf mit dem Add-Ins-Manager einbinden und wieder deaktivieren, wenn die Funktionen zeitweise nicht benötigt werden. Vor dem Erstellen eines Add-Ins sollten die Dokumenteigenschaften der Datei Funktionen.xls gepflegt werden. Diese Informationen sind später wichtig, um Zusatzinformationen zum Add-In zu hinterlegen. Geben Sie jetzt die Dokumenteigenschaften an, indem Sie die Datei Funktionen.xls öffnen und dann aus dem Menü DATEI den Befehl EIGENSCHAFTEN wählen. Bild 7.12: Die Dokumenteigenschaften pflegen 238 Funktionen dauerhaft verfügbar machen jetzt lerne ich Geben Sie einige zusätzliche Informationen zu dem zukünftigen Add-In an und bestätigen die Eingaben mit OK. Befolgen Sie jetzt die nachfolgenden Anweisungen: 1. Wählen Sie aus dem Menü DATEI den Befehl SPEICHERN UNTER. 2. Stellen Sie im Kombinationsfeld DATEITYP den Eintrag MICROSOFT EXCEL-ADD-IN ein. Nun wird automatisch das Add-In-Verzeichnis von Excel eingestellt. 3. Klicken Sie auf die Schaltfläche SPEICHERN. Das Add-In FUNKTIONEN.XLS wurde nun erstellt und kann wie folgt eingebunden werden: 1. Wählen Sie aus dem Menü EXTRAS den Befehl ADD-INS. Bild 7.13: Das Add-In einbinden 2. Aktivieren Sie das Add-In NÜTZLICHE FUNKTIONEN. Diese Information wurde vorher bei den Dokumenteigenschaften unter der Rubrik TITEL erfasst. 3. Bestätigen Sie Ihre Aktion durch OK. Nun können die benutzerdefinierten Tabellenfunktionen über den Funktionsassistenten in die Tabellen eingefügt werden. 239 Ereignisse einsetzen jetzt lerne ich KAPITEL 8 Die Programmierung von Ereignissen ist eines meiner Lieblingsthemen in der VBA-Programmierung, da Sie schon mit sehr wenigen Codezeilen gewaltige Effekte erzielen können. Was steckt hinter einem Ereignis? Nun, als Ereignis lassen sich alle möglichen Vorgänge in Excel bezeichnen, wie z. B. das Öffnen einer Arbeitsmappe, das Eingeben von Daten, das Drucken von Tabellen oder der Speichervorgang einer Mappe. Dies alles sind typische Vorgänge in Excel, die als Ereignisse bezeichnet werden. Es besteht die Möglichkeit, weitere Aktionen diesen Ereignissen anzuhängen, d. h. Sie können beispielsweise dafür sorgen, dass beim Ereignis ÖFFNEN einer Arbeitsmappe weitere VBA-Befehle ausgeführt werden sollen. Somit besteht die Möglichkeit, auf jedes Ereignis in Excel individuell zu reagieren. Einzelne Ereignisse lassen sich sogar abbrechen, wenn es beispielsweise darum geht, das Drucken einer Tabelle nur unter bestimmten Umständen zuzulassen. Bei den Ereignissen unterscheidet man in erster Linie zwischen Ereignissen, die für die gesamte Arbeitsmappe gelten, und Ereignissen, die nur für bestimmte Tabellenblätter Geltung haben. Ereignisse für eine Arbeitsmappe wären beispielsweise das Öffnen, Speichern, Drucken oder Schließen einer Arbeitsmappe. Ein Beispiel für ein Tabellenereignis wäre z. B. die Erfassung von Daten in einer Tabelle oder das Aktivieren bzw. Verlassen einer Tabelle. 241 8 Ereignisse einsetzen jetzt lerne ich Selbstverständlich gibt es noch viele weitere Ereignisse, wie z. B. Ereignisse bei UserForms (Dialogen) und Steuerelementen, die Sie im nächsten Kapitel kennen lernen werden. 1 Sie finden alle Beispiele dieses Kapitels auf der diesem Buch beiliegenden CD-ROM im Verzeichnis Kap08 in der Datei Ereignisse.xls. 8.1 Ereignisse auf Arbeitsmappenebene Wichtige Ereignisse, die für die Arbeitsmappe gelten, sind zum einen das Ereignis Workbook_Open, das eintritt sobald die Arbeitsmappe geöffnet wird, und zum anderen das Ereignis Workbook_BeforeClose, das automatisch ausgelöst wird, sobald die Arbeitsmappe geschlossen wird. 8.1.1 Das Ereignis Workbook_Open Das Ereignis Workbook_Open (beim Öffnen) wird in der Praxis meist eingesetzt, um Meldungen anzuzeigen, benutzerdefinierte Arbeitsumgebungen einzurichten, Sachverhalte zu prüfen oder auch verschiedene Aufgaben zu erledigen, die einen vorbereitenden Charakter haben. Bestimmte Tabelle aktivieren Im nächsten Beispiel in Listing 8.1 soll beim Öffnen einer Arbeitsmappe dafür gesorgt werden, dass eine bestimmte Tabelle aktiviert wird. Standardmäßig stellt Excel beim Öffnen einer Arbeitsmappe immer die Tabelle ein, die direkt vor der letzten Speicherung der Arbeitsmappe aktiviert war. Wenn Sie an das Beispiel aus Kapitel 5, Listing 5.14 denken, in dem eine Art Inhaltsverzeichnis für die Arbeitsmappe in TABELLE1 erstellt wurde, wäre es nun eine tolle Sache, diese Tabelle standardmäßig beim Öffnen der Arbeitsmappe einzustellen. Um das Ereignis Workbook_Open einzustellen, gehen Sie wie folgt vor: 1. Drücken Sie die Tastenkombination Ç+Ó, um in die Entwicklungsumgebung zu gelangen. 242 Ereignisse auf Arbeitsmappenebene jetzt lerne ich 2. Im Projekt-Explorer klicken Sie den Eintrag DIESEARBEITSMAPPE doppelt an. Bild 8.1: Ein Arbeitsmappenereignis einstellen 3. Klicken Sie im Code-Fenster auf den Pfeil des linken Kombinationsfeldes und wählen Sie den Eintrag WORKBOOK aus. Excel stellt Ihnen nun standardmäßig ein schon vorgefertigtes Ereignismakro zur Verfügung. 4. Mit einem Klick auf das zweite Kombinationsfeld bekommen Sie alle anderen verfügbaren Ereignisse angezeigt, die für die Arbeitsmappe einsetzbar sind. 5. Ergänzen Sie nun den eingestellten Rahmen des Ereignisses um folgende Zeilen: Private Sub Workbook_Open() On Error GoTo fehler Worksheets("Tabelle1").Activate Exit Sub Listing 8.1: Eine Tabelle beim Öffnen der Mappe voreinstellen fehler: MsgBox "Die Tabelle ist nicht vorhanden!" End Sub 243 jetzt lerne ich 8 Ereignisse einsetzen Bauen Sie sicherheitshalber eine Fehlerbehandlung in ein Ereignis ein, um zu verhindern, dass das Makro abstürzt, sofern das gewünschte Tabellenblatt umbenannt bzw. gelöscht wurde. 1 Möchten Sie eine Arbeitsmappe mit hinterlegten Ereignissen öffnen und dabei auf deren Ausführung verzichten, so halten Sie beim Öffnen der Datei die Taste Á gedrückt. Eine ScrollArea einstellen Ein weiteres Beispiel für Ereignisse liefert die Lösung in Listing 8.2. Dabei wird beim Öffnen der Arbeitsmappe eine so genannte »ScrollArea« eingestellt. Was ist eine ScrollArea konkret? Nun, damit wird ein zusammenhängender Zellenbereich bezeichnet, in dem dem Anwender vorgegeben wird, die Daten dort einzugeben. Damit können Sie also ganz bewusst festlegen, wo sich ein Anwender in einer Tabelle aufhalten darf und wo nicht. Beim folgenden Listing 8.2 wird das vorherige Listing 8.1 um die folgenden Zeilen ergänzt: Listing 8.2: Private Sub Workbook_Open() Beim Öffnen der Mappe ei- On Error GoTo fehler nen »Aufent- With Worksheets("Tabelle1") .Activate haltsbereich« .ScrollArea = "A1:D10" definieren End With Exit Sub fehler: MsgBox "Die Tabelle ist nicht vorhanden!" End Sub Übergeben Sie der Eigenschaft ScrollArea den Namen der Tabelle sowie die Zellenkoordinaten des Bereichs, der als zugänglicher Bereich definiert wird. Es ist nun nicht mehr möglich, außerhalb dieses Bereichs eine Zelle zu markieren. 244 Ereignisse auf Arbeitsmappenebene jetzt lerne ich Bild 8.2: Die Navigation ist nur im Bereich A1:D10 möglich Durch dieses Feature besteht die Möglichkeit, vor dem Einstellen des Ereignisses beispielsweise sensible Daten außerhalb der ScrollArea zu erfassen. Damit werden diese Daten zusätzlich geschützt, da sich diese bei eingestellter ScrollArea außerhalb des ansteuerbaren Bereichs befinden und somit auch nicht geändert werden können. Erst durch Deaktivierung des Ereignisses lassen sich die »versteckten« Daten erreichen. 8.1.2 1 Das Ereignis Workbook_BeforeClose Das Ereignis Workbook_BeforeClose (vor dem Schließen) tritt genau dann ein, wenn eine Arbeitsmappe geschlossen wird. Zugriffe dokumentieren Im folgenden Makro in Listing 8.3 wird jeder Zugriff auf eine Arbeitsmappe in einer separaten Tabelle verzeichnet, und zwar genau dann, wenn die Arbeitsmappe wieder geschlossen wird. Private Sub Workbook_BeforeClose(Cancel As Boolean) With Tabelle2 .Range("A65536").End(xlUp).Offset(1, 0).Value = Now .Range("A65536").End(xlUp).Offset(0, 1).Value = _ Environ("Username") ActiveWorkbook.Save End With Listing 8.3: Beim Schließen der Mappe wird eine Zugriffsdokumentation gepflegt End Sub 245 jetzt lerne ich 8 Ereignisse einsetzen Beim Schließen der Arbeitsmappe wird in der TABELLE2 die erste freie Zelle aus Spalte A ermittelt. In diese Zelle wird über die Funktion Now das aktuelle Tagesdatum sowie die Uhrzeit geschrieben. In die Nebenspalte wird nun noch der Name des Anwenders hinterlegt, der auf die Arbeitsmappe zugegriffen hat. Um den Namen des an Windows angemeldeten Anwenders auszulesen, wird die Funktion Environ verwendet, die als Konstante den Wert Username übergeben bekommt. Bild 8.3: Eine Zugriffsdokumentation wird mit ein paar Handgriffen eingestellt 1 Diese Tabelle lässt sich natürlich auch ausblenden. Schließen der Mappe verhindern Das Ereignis Workbook_BeforeClose kann aber auch so eingestellt werden, dass der Vorgang abgebrochen wird, d. h. über einen Trick lässt sich verhindern, dass eine Arbeitsmappe geschlossen wird. Es kann aber zusätzlich eine versteckte Möglichkeit eingerichtet werden, die es Ihnen dennoch erlaubt, die Arbeitsmappe zu schließen. Im folgenden Beispiel in Listing 8.4 kann eine Arbeitsmappe nur dann geschlossen werden, wenn in TABELLE1 in Zelle A1 der Text OK steht. Da jedes Arbeitsmappenereignis nur einmal für jede Mappe eingestellt werden darf, passen Sie das Listing 8.3 wie folgt an. 246 Ereignisse auf Arbeitsmappenebene Private Sub Workbook_BeforeClose(Cancel As Boolean) With Tabelle2 .Range("A65536").End(xlUp).Offset(1, 0).Value = Now .Range("A65536").End(xlUp).Offset(0, 1).Value = _ Environ("Username") End With jetzt lerne ich Listing 8.4: Die Mappe kann nur unter bestimmten Umständen geschlossen werden With Tabelle1 If .Range("A1").Value <> "OK" Then MsgBox "Mappe kann nicht geschlossen werden!" Cancel = True Else Cancel = False ThisWorkbook.Save End If End With End Sub Nur wenn in der Zelle A1 ein anderer Wert als OK steht, kann die Arbeitsmappe geschlossen werden. In diesem Fall wird das Argument Cancel auf den Wert False gesetzt, die Arbeitsmappe über die Methode Save gespeichert und geschlossen. Im andern Fall bleibt die Arbeitsmappe geöffnet. Das Speichern der Arbeitsmappe ist unabhängig davon weiterhin möglich! 8.1.3 Das Ereignis Workbook_BeforeSave Beim Ereignis Workbook_BeforeSave (vor dem Speichern) lässt sich gezielt darauf reagieren, wenn eine Arbeitsmappe gespeichert wird. Speichern einer Mappe unterbinden Im folgenden Beispiel wird verhindert, dass eine Arbeitsmappe gespeichert werden kann. Damit lassen sich Arbeitsmappen vor Veränderungen schützen, ohne für die Arbeitsmappe ein Kennwort zu hinterlegen. Die Speicherung soll aber in einem bestimmten Fall doch möglich sein, und zwar darf die Arbeitsmappe nur dann gespeichert werden, wenn das Datum in Zelle A1 der TABELLE3 dem aktuellen Datum entspricht. 247 8 Ereignisse einsetzen jetzt lerne ich Listing 8.5: Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, _ Cancel As Boolean) Das Speichern der Mappe ist nur unter be- If Worksheets("Tabelle3").Range("A1").Value <> Date Then MsgBox "Arbeitsmappe kann nicht gespeichert werden!" stimmten BeCancel = True dingungen Else möglich Cancel = False End If End Sub Nur wenn in der Zelle A1 ein Datumswert steht, der dem aktuellen Tagesdatum entspricht, kann die Arbeitsmappe gespeichert werden. In diesem Fall wird das Argument Cancel auf den Wert False gesetzt und die Arbeitsmappe gespeichert. 8.1.4 Das Ereignis Workbook_BeforePrint Das Ereignis Workbook_BeforePrint tritt unmittelbar dann auf, wenn Sie eine Tabelle bzw. alle Tabellen einer Mappe oder einen bestimmten Zellenbereich drucken möchten. Drucken verhindern Im folgenden Beispiel in Listing 8.6 wird die Drucken-Funktion für die komplette Arbeitsmappe gesperrt. Listing 8.6: Private Sub Workbook_BeforePrint(Cancel As Boolean) Es ist nicht Cancel = True möglich auch nur eine Seite auszudrucken End Sub Egal, wie Sie den Druckbefehl ausführen: sei es über das DRUCKENSymbol aus der Symbolleiste STANDARD oder über den Menübefehl DATEI/DRUCKEN, nicht einmal über die Tastenkombination Ÿ+P lässt sich der Druckvorgang anstoßen. Indem das Argument Cancel auf den Wert True gesetzt wurde, wird der Druckvorgang abgebrochen, noch ehe er begonnen hat. 248 Ereignisse auf Arbeitsmappenebene Selbstverständlich lässt sich wie schon im vorhergehenden Beispiel das Listing 8.6 anpassen, indem bestimmte Bedingungen formuliert werden, unter denen es doch möglich sein soll, einen Ausdruck vorzunehmen. Dies könnte in Abhängigkeit von bestimmten Anwendern, Uhrzeiten und diversen anderen Bedingungen »erlaubt« werden. 8.1.5 jetzt lerne ich 1 Das Ereignis Workbook_NewSheet Mit dem Ereignis Workbook_NewSheet (beim Einfügen einer neuen Tabelle), das erst ab der Excel-Version 2002 verfügbar ist, lässt sich auf das Einfügen neuer Tabellenblätter in eine Arbeitsmappe reagieren. Neuanlage von Tabellen unterbinden Ein Paradebeispiel für den Einsatz dieses Ereignisses ist es, eben keine Neuanlage von Tabellen zuzulassen. Leider besitzt dieses Ereignis standardmäßig kein Argument, über das dies möglich wäre. Aber auch hierfür haben wir eine Lösung. Wir reagieren direkt auf die Neuanlage, indem sofort danach die eingefügte Tabelle wieder gelöscht wird. Dies wird durch Excel so schnell umgesetzt, dass Sie kaum etwas davon mitbekommen. Sehen Sie sich dazu einmal das Ereignismakro in Listing 8.7 an. Private Sub Workbook_NewSheet(ByVal Sh As Object) Application.DisplayAlerts = False Sh.Delete Application.DisplayAlerts = True Listing 8.7: Eine neu eingefügte Tabelle wird sofort wieder entfernt End Sub Normalerweise wird eine Rückfrage angezeigt, sobald eine Tabelle aus der Arbeitsmappe entfernt wird. Diese Rückfrage ist für dieses Beispiel nicht gewünscht und wird aus diesem Grund einfach abgeschaltet. Dies erfolgt, indem Sie der Eigenschaft DisplayAlerts den Wert False zuweisen. Wenn nun versucht wird, eine neue Tabelle einzufügen, dann gelingt dies zunächst. Die Tabelle kann jetzt unter dem Argument Sh wie in der ersten Zeile des Ereignisses sichtbar identifiziert und angesprochen werden. Mithilfe der Methode Delete wird nun jedoch genau diese Tabelle wieder gelöscht. Vergessen Sie danach nicht die Eigenschaft DisplayAlerts wieder auf den Wert True 249 8 Ereignisse einsetzen jetzt lerne ich zu setzen, da die Systemmeldungen von Excel sonst ausgeschaltet bleiben würden. 8.1.6 Weitere Arbeitsmappenereignisse im Überblick Entnehmen Sie der Tabelle 8.1 alle möglichen Ereignisse, die für Arbeitsmappen angewendet werden können. Das eine oder andere Ereignis werden Sie im Laufe der nächsten Übungen wieder entdecken. Tabelle 8.1: Ereignis Alle Arbeitsmappenereig- Workbook_Activate nisse im Überblick Workbook_AddinInstall Beschreibung Tritt ein, sobald eine Arbeitsmappe aktiviert wird. Tritt ein, wenn ein Add-In eingebunden wird. Dies kann entweder durch direktes Öffnen des Add-Ins erfolgen oder auch durch das Einbinden im Add-Ins-Manager. Workbook_AddinUninstall Tritt ein, wenn ein Add-In aus dem AddIns-Manager deaktiviert wurde. Workbook_BeforePrint Tritt vor dem Druck einer Arbeitsmappe oder auch einer einzelnen Tabelle ein. Workbook_BeforeSave Tritt vor dem Speichervorgang ein. Dabei spielt es keine Rolle, ob Sie über Menübefehle, Symbolleiste oder Tastenkombination speichern. Workbook_Deactivate Tritt ein, wenn eine Arbeitsmappe deaktiviert wird. Beispielsweise wenn eine Arbeitsmappe minimiert wird. Workbook_NewSheet Tritt ein, wenn eine neue Tabelle in die Arbeitsmappe eingefügt wird. Workbook_SheetActivate Tritt ein, wenn ein beliebiges Tabellen- oder Diagrammblatt in der Arbeitsmappe aktiviert wird. Workbook_SheetBeforeDoubleClick Tritt ein, wenn an einer beliebigen Stelle der Arbeitsmappe ein Doppelklick mit der linken Maustaste durchgeführt wird. 250 Workbook_SheetBeforeRightClick Tritt ein, wenn an einer beliebigen Stelle der Arbeitsmappe ein Klick mit der rechten Maustaste durchgeführt wird. Workbook_SheetCalculate Tritt nach Neuberechnung jedes Tabellenblatts auf. Ereignisse auf Tabellenblattebene Ereignis Beschreibung Workbook_SheetChange Tritt ein, wenn sich in einem beliebigen Tabellenblatt etwas ändert, sei es durch eine Verknüpfung oder durch den Anwender. Workbook_SheetDeactivate Tritt ein, sobald ein beliebiges Tabellenblatt in der Arbeitsmappe verlassen wird. Workbook_SheetFollowHyperlink Tritt ein, wenn der Anwender auf einen Hyperlink in einer Tabelle klickt. Workbook_SheetSelectionChange Tritt ein, wenn sich die Markierung auf einem Tabellenblatt ändert. Workbook_WindowActivate Tritt ein, wenn ein Arbeitsmappenfenster aktiviert wird. Workbook_WindowDeactivate Tritt ein, wenn ein Arbeitsmappenfenster deaktiviert wird. Workbook_WindowResize Tritt ein, wenn eine Änderung an der Größe des Arbeitsmappenfensters durchgeführt wurde. 8.2 jetzt lerne ich Tabelle 8.1: Alle Arbeitsmappenereignisse im Überblick (Forts.) Ereignisse auf Tabellenblattebene Im Gegensatz zu Arbeitsmappenereignissen, die für alle Tabellen einer Arbeitsmappe gleichermaßen gelten, lassen sich über Tabellenereignisse ganz gezielt Ereignisse für bestimmte Tabellenblätter einstellen. Ein wichtiges Ereignis, das für das Tabellenblatt gilt, ist z. B. das Ereignis Worksheet_Activate. Mit diesem Ereignis wird bestimmt, was passieren soll, wenn ein bestimmtes Tabellenblatt aktiviert wird. Auch das Ereignis Worksheet_Change ist in der Praxis von großer Bedeutung. Mithilfe dieses Ereignisses lässt sich auf Änderungen in den Tabellen reagieren. Dabei besteht wiederum die Möglichkeit, Änderungen in der gesamten Tabelle oder ganz gezielt in einzelnen Zellen oder Bereichen zu überwachen. 8.2.1 Das Ereignis Worksheet_Activate Das Ereignis Worksheet_Activate tritt dann ein, wenn eine Tabelle aktiviert wird. Dabei ist es egal, ob die Tabelle über die Registerlaschen, über die Tastenkombination Ÿ+³ bzw. Ÿ+² oder gar über einen Fensterwechsel angesteuert wird. In allen Fäl- 251 jetzt lerne ich 8 Ereignisse einsetzen len wird dieses Ereignis ausgelöst, sofern es vorab in der Entwicklungsumgebung eingestellt wurde. Tabellenschutz dynamisch einstellen Im folgenden Beispiel in Listing 8.8 wird ein Tabellenschutz für eine Tabelle dynamisch eingestellt, sobald diese Tabelle aktiviert wird. Beim Verlassen der Tabelle wird dieser Schutz wieder entfernt. Setzen Sie für diese Aufgabe die beiden Ereignisse Worksheet_Activate bzw. Worksheet_Deactivate ein. Um die Ereignisse für diese Aufgabe festzulegen, verfahren Sie wie folgt: 1. Drücken Sie die Tastenkombination Ç+Ó, um in die Entwicklungsumgebung zu gelangen. 2. Im Projekt-Explorer klicken Sie die Tabelle doppelt an, der das Ereignis zugewiesen werden soll. In unserem Beispiel ist das die TABELLE3. Bild 8.4: Ein Tabellenereignis einstellen 3. Klicken Sie im Code-Fenster auf den Pfeil des linken Kombinationsfeldes und wählen Sie den Eintrag WORKSHEET aus. 4. Im zweiten Kombinationsfeld wählen Sie dann das Ereignis ACTIVATE und danach DEACTIVATE aus. 252 Ereignisse auf Tabellenblattebene jetzt lerne ich 5. Ergänzen Sie die beiden benötigten Ereignismakros wie folgt: Private Sub Worksheet_Activate() ActiveWorkbook.Protect Password:="Zauberschlüssel", _ Structure:=True Listing 8.8: Eine Tabelle beim Zugriff schützen End Sub Private Sub Worksheet_Deactivate() ActiveWorkbook.Unprotect Password:="Zauberschlüssel" End Sub Beim Aktivieren der TABELLE3 wird die Methode Protect eingesetzt, um die Tabelle zu schützen. Übergeben Sie im Argument Password einen Kennwortschutz Ihrer Wahl, z. B. Zauberschlüssel. Im Argument Structure, das den Wert True zugewiesen bekommt, wird festgelegt, dass die Struktur dieser Tabelle nicht verändert werden darf. Dabei ist das Löschen sowie das Verschieben der Tabelle mit eingeschlossen. Beim Verlassen der Tabelle wird die Methode Unprotect angegeben, um den Tabellenschutz wieder aufzuheben. Übergeben Sie hierbei das von Ihnen gewählte Kennwort im Argument Password. Diese Variante des Tabellenschutzes kann, wie schon vorher beschrieben, von bestimmten Kriterien abhängig gemacht werden. So kann beispielsweise einem bestimmten Anwender erlaubt werden, Änderungen an der Tabelle durchzuführen. Übernehmen Sie beim Aktivieren der Tabelle eine Abfrage wie in Listing 8.9 gezeigt. Private Sub Worksheet_Activate() If Environ("Username") <> "Bernd" Then ActiveWorkbook.Protect Password:="Password", _ Structure:=True End If End Sub 1 Listing 8.9: Die Tabelle nur schützen, wenn ein fremder Anwender Zugriff hat 253 8 Ereignisse einsetzen jetzt lerne ich Passwortabfrage bei Tabellenwechsel Beim nächsten Beispiel wird das Ereignis Worksheet_Actviate eingesetzt, das automatisch ausgeführt wird, wenn eine bestimmte Tabelle (TABELLE13) aktiviert wird. Dabei soll ein Passwortdialog eingeblendet werden, der erst nach Eingabe des richtigen Passwortes die Tabelle anzeigt. Das Ereignis für diese Aufgabe sieht wie folgt aus: Listing 8.10: Private Sub Worksheet_Activate() Beim Tabel- Dim s As String lenwechsel ein Passwort s = InputBox("Bitte Passwort eingaben!", "Passwortabfrage") abfragen If s <> "Test" Then Sheets(1).Activate End If End Sub Nur wenn das richtige Passwort über die Eingabebox eingegeben wird, kann der Anwender die Tabelle einsehen. Im anderen Fall wird automatisch die erste Tabelle der Arbeitsmappe angezeigt. 8.2.2 Das Ereignis Worksheet_Change Das wohl am häufigsten eingesetzte Ereignis lautet Worksheet_Change (bei Änderung) und kann eingesetzt werden, um auf Änderungen in der Tabelle zu reagieren. Es besteht dabei die Möglichkeit, die gesamte Tabelle, einen Teil davon oder einzelne Zellen auf Veränderungen hin zu überwachen. Alle Zellen überwachen Im folgenden Beispiel werden alle Änderungen der TABELLE4 sofort kenntlich gemacht, indem der Hintergrund dieser Zellen mit der Farbe GELB belegt wird. Wir gehen davon aus, dass es sich um eine Tabelle handelt die ab und an aktualisiert wird. Die Änderungen an dieser Liste, gegenüber dem ursprünglichen Zustand, sollen dadurch nachvollzogen werden können. Schauen Sie sich dazu einmal die Ausgangsliste in Abbildung 8.5 an. 254 Ereignisse auf Tabellenblattebene jetzt lerne ich Bild 8.5: Die Ausgangsliste mit den Schlüsseln Stellen Sie jetzt das Ereignis Worksheet_Change ein, indem Sie das Ereignis in Listing 8.11 direkt hinter die TABELLE4 legen. Listing 8.11: Jede ÄndeTarget.Interior.ColorIndex = 6 rung an einer Zelle wird mit End Sub einer FormaBei jeder Änderung in einer Zelle wird diese gelb eingefärbt. Hierfür tierung derselben quittiert Private Sub Worksheet_Change(ByVal Target As Range) wird die Eigenschaft ColorIndex des Objekts Interior (= Hintergrund der Zelle) benötigt, um das Objekt Target (= Zelle) mit dem Farbindex 6 (gelb) zu versehen. Wurden alle Änderungen nachvollzogen, lassen sich die Färbungen wieder »manuell« entfernen, ohne dass dadurch das Ereignis Change ausgelöst wird. Ereignisse reagieren allgemein nicht auf Formatänderungen. 1 Die Spaltenprüfung Im folgenden Beispiel in Listing 8.12 können Eingaben in der TABELLE5 in einer bestimmten Spalte nicht mehr geändert werden. Private Sub Worksheet_Change(ByVal Target As Excel.Range) If Target.Column <> 1 Then Exit Sub Application.EnableEvents = False Application.Undo Application.EnableEvents = True Listing 8.12: Änderungen in Spalte A können nicht vorgenommen werden End Sub 255 jetzt lerne ich 8 Ereignisse einsetzen Über die Eigenschaft Column lässt sich überprüfen, ob eine Änderung in Spalte A (= Spalte 1) vorgenommen wurde. Wenn nicht, dann wird das Ereignis ohne weitere Aktion beendet, indem die Anweisung Exit Sub ausgeführt wird. Im anderen Fall wird temporär die Ereignissteuerung über die Eigenschaft EnableEvents ausgeschaltet und dann die Methode Undo ausgeführt, um die Eingabe rückgängig zu machen. Schalten Sie danach die Ereignissteuerung wieder ein, indem Sie der Eigenschaft EnableEvents den Wert True zuweisen. Was wurde konkret gemacht? Nun, wir konnten eine Änderung auf den ersten Blick zwar nicht verhindern. Trotzdem besteht innerhalb von Excel immer die Möglichkeit, eine Aktion rückgängig zu machen. Dabei darf allerdings nicht vergessen werden, vorab die Ereignissteuerung kurz lahm zu legen, da sonst eine Endlosschleife die Folge wäre. Nachdem die Aktion rückgängig gemacht wurde, muss die Ereignissteuerung wieder eingeschaltet werden. Die Bereichsprüfung Im letzten Beispiel zu dem wichtigsten Ereignis Worksheet_Change wird ein bestimmter Bereich in einer Tabelle überwacht. Das Ereignis in TABELLE6 soll nur ausgelöst werden, wenn Änderungen in dem bestimmten Bereich B1:B4 durchgeführt werden. Listing 8.13: Private Sub Worksheet_Change(ByVal Target As Range) Alle Eingaben Dim Bereich As Range in einem bestimmten Be- Set Bereich = Range("B1:B4") reich werden in Großbuch- If Not Intersect(Target, Bereich) Is Nothing Then Target = UCase(Target) staben konEnd If vertiert End Sub Deklarieren Sie im ersten Schritt eine Objektvariable vom Typ Range und definieren Sie über die Anweisung Set, wo sich der zu überwachende Bereich in der Tabelle befinden soll. Über die Methode Intersect wird überprüft, ob die geänderte Zelle im definierten Zielbereich liegt. Wenn ja, wird die Funktion UCase eingesetzt, um die eingegebenen Buchstaben in Großbuchstaben umzuwandeln. 256 Ereignisse auf Tabellenblattebene Um Buchstaben in Kleinbuchstaben umzuwandeln, wird die Funktion LCase verwendet. jetzt lerne ich 1 Bild 8.6: Direkt nach der Eingabe werden Texte in Großbuchstaben konvertiert Die bedingte Formatierung erweitern Bei der bedingten Formatierung, die sich über das Menü FORMAT einstellen lässt, können insgesamt nur drei unterschiedliche Formatierungen eingerichtet werden. Über ein Ereignismakro lässt sich jedoch dieses Feature beliebig ausbauen. In TABELLE13 wird die Spalte A überwacht. Dabei sollen folgende Formatierungsregeln gelten: Formatierungskriterium Farbe des Hintergrunds Werte zwischen 1 und 5 Rot Werte zwischen 6 und 10 Orange Werte zwischen 11 und 15 Grün Werte zwischen 16 und 30 Blau Werte zwischen 31 und 40 Gelb Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 1 Then Select Case Target.Value Tabelle 8.2: Die Regeln für die bedingte Formatierung Listing 8.14: Die bedingte Formatierung wird um weitere Bedingungen erweitert Case 1 To 5 'ROT Target.Interior.ColorIndex = 3 Case 6 To 10 'ORANGE Target.Interior.ColorIndex = 46 257 8 Ereignisse einsetzen jetzt lerne ich Case 11 To 15 'GRÜN Target.Interior.ColorIndex = 4 Case 16 To 30 'BLAU Target.Interior.ColorIndex = 5 Case 31 To 40 'GELB Target.Interior.ColorIndex = 6 Case Else Target.Interior.ColorIndex = xlColorIndexNone End Select End If End Sub Über eine Select Case-Anweisung werden die Eingaben, die in Spalte A der TABELLE13 vorgenommen wurden, überprüft und je nach Wert entsprechend der Tabelle 8.2 formatiert. Bild 8.7: Die bedingte Formatierung reagiert auf jede Eingabe 8.2.3 Das Ereignis Worksheet_SelectionChange Das Ereignis Worksheet_SelectionChange reagiert auf jede Cursorbewegung, die in der Tabelle durchgeführt wird. Mit jeder Markierung einer Zelle wird dieses Ereignis ausgeführt. Dieses Ereignis, das im Prinzip laufend auftritt, wird selbstverständlich nur dann ausgeführt, wenn es eingestellt wurde. Es empfiehlt sich aus PerformanceGründen, dieses Ereignis nur sehr sparsam bzw. ganz gezielt einzu- 258 Ereignisse auf Tabellenblattebene jetzt lerne ich setzen. Lernen Sie drei Anwendungsmöglichkeiten für den Einsatz gerade dieses Ereignisses kennen. Ausschneiden verboten Mithilfe des Ereignisses Worksheet_SelectionChange lässt sich auf das Ausschneiden von Zellen reagieren. So können Sie diesen Vorgang beispielsweise ausschalten. Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range) If Application.CutCopyMode = xlCut Then MsgBox "Ausschneiden verboten!" Application.CutCopyMode = False End If Listing 8.15: Das Ausschneiden von Zellen wird verboten End Sub Über die Eigenschaft CutCopyMode wird überprüft, ob versucht wird, eine Zelle auszuschneiden. Wenn ja, dann wird dies durch die Konstante xlCut gemeldet. Setzen Sie in diesem Fall diese Eigenschaft auf den Wert False. Damit wird der Laufbalken einer ausgeschnittenen Zelle sowie der ganze Vorgang deaktiviert. Bild 8.8: Es ist nicht möglich, eine Zelle auszuschneiden Einen Zeilenzeiger programmieren Wenn Sie auf der Suche nach einer bestimmten Information in einer Tabelle sind und diese auch gefunden haben, interessiert manchmal nicht nur der Inhalt der gefundenen Zelle, sondern oft auch die Informationen, die in den übrigen Zellen der Zeile stecken. Aus diesem Grund können Sie das Ereignis Worksheet_SelectionChange (bei Aus- 259 jetzt lerne ich 8 Ereignisse einsetzen wahländerung) auch einsetzen, um die Markierung einer Zelle auf die Markierung der ganzen Zeile auszuweiten. Listing 8.16: Private Sub Worksheet_SelectionChange _ Einen Zeilen- (ByVal Target As Range) zeiger realiApplication.EnableEvents = False sieren Rows(Target.Row).Select Target.Activate Application.EnableEvents = True End Sub In Listing 8.16 müssen Sie die Ereignissteuerung kurzfristig ausschalten, um zu verhindern, dass eine Endlosschleife produziert wird. Dazu wird die Eigenschaft EnableEvents auf den Wert False gesetzt. Danach wird die komplette Zeile durch das Makro markiert und dafür gesorgt, dass der Mauszeiger trotzdem wieder auf der ursprünglich markierten Zelle positioniert wird. Setzen Sie daraufhin die Eigenschaft EnableEvent wieder auf den Wert True, um die Ereignissteuerung zuzulassen. Bild 8.9: Mehr Übersicht durch den Zeilenzeiger Zeilen vor Veränderungen schützen Ausgehend von der Tatsache, dass Sie keine Daten aus Zellen löschen können, sofern diese vorher nicht markiert wurden, wird folgende Lösung vorgestellt: Bei diesem Ansatz werden die ersten fünf Zeilen der TABELLE8 vor Veränderungen geschützt. Immer wenn versucht wird, eine Zelle in diesem Bereich zu markieren, wird automatisch ein Sprung in Zelle A6 durchgeführt. 260 Ereignisse auf Tabellenblattebene Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Row < 6 Then Range("A6").Select End If jetzt lerne ich Listing 8.17: Die ersten Zeilen einer Tabelle vor Veränderungen schützen End Sub Über die Eigenschaft Row lässt sich die Zeilennummer der aktuell markierten Zelle ermitteln. Ist diese Zeilennummer kleiner als der Wert 6, dann wird über die Methode Select die Zelle A6 angesteuert. Bild 8.10: Die ersten fünf Zeilen sind tabu 8.2.4 Das Ereignis Worksheet_BeforeRightClick Standardmäßig wird in Excel beim Drücken der rechten Maustaste ein Kontextmenü aufgerufen. Beispielsweise wird das Zellenkontextmenü aktiviert, wenn mit der rechten Maustaste auf eine beliebige Zelle geklickt wurde. Dieses Standardverhalten kann auch deaktiviert und durch eine andere, eigene Funktion ersetzt werden. Das Kontextmenü deaktivieren Im folgenden Beispiel in Listing 8.18 wird das Herunterklappen des Kontextmenüs unterbunden, sobald Sie eine beliebige Zelle einer bestimmten Tabelle mit der rechten Maustaste anklicken. Private Sub Worksheet_BeforeRightClick _ (ByVal Target As Range, Cancel As Boolean) Cancel = True End Sub Listing 8.18: Das Herunterklappen des Zellenkontextmenüs verhindern 261 jetzt lerne ich 8 Ereignisse einsetzen Das Ereignis Worksheet_BeforeRightClick hat zwei Argumente: Im Argument Target wird die Überwachung der rechten Maustaste auf einen bestimmten Bereich der Tabelle beschränkt. Im Argument Cancel besteht nun die Möglichkeit, die Standardfunktion, das Herunterklappen des Kontextmenüs, zu unterbinden, indem dieses Argument auf den Wert True gesetzt wird. Das Kontextmenü für bestimmte Bereiche deaktivieren Um die Überwachung der rechten Maustaste nur in einem bestimmten Bereich der Tabelle zuzulassen, wird wie bereits erwähnt das Argument Target eingesetzt. Im folgenden Makro in Listing 8.19 wird das Kontextmenü für den Zellenbereich A1:D10 in der TABELLE10 ausgeschaltet. Listing 8.19: Private Sub Worksheet_BeforeRightClick _ Das Deakti- (ByVal Target As Range, Cancel As Boolean) vieren des Kontextmenüs Dim Bereich As Range für einen bestimmten Set Bereich = Range("A1:D10") Bereich If Intersect(Target, Bereich) Is Nothing Then Exit Sub Cancel = True End Sub Deklarieren Sie im ersten Schritt eine Objektvariable vom Typ Range. Danach wird dieser Objektvariablen über die Anweisung Set bekannt gegeben, welcher Bereich der Tabelle überwacht werden soll. Mithilfe der Methode Intersect lässt sich überprüfen, ob die angeklickte Zelle (Target) sich im definierten Bereich (Bereich) befindet. Wenn nicht, dann wird über die Anweisung Exit Sub direkt aus dem Makro herausgesprungen. Im anderen Fall wird das Argument Cancel auf den Wert True gesetzt, um die rechte Maustaste zu deaktivieren und damit das Zellenkontextmenü nicht darzustellen. 262 Ereignisse auf Tabellenblattebene jetzt lerne ich Bild 8.11: Die Standardfunktion der rechten Maustaste wird unterbunden 8.2.5 Das Ereignis Worksheet_BeforeDoubleClick Nachdem Sie erfahren haben, wie die rechte Maustaste abgefragt bzw. programmiert wird, lernen Sie nun, wie die linke Maustaste abgefragt wird. Standardmäßig ist dem linken Doppelklick auf eine Zelle die Funktion DIREKTE ZELLENBEARBEITUNG zugeordnet, d. h. der Textcursor springt genau in die Zelle hinein. Sie haben dann die Möglichkeit, Zeichen einzugeben bzw. bereits gemachte Eingaben zu korrigieren. Zum Abfangen von Doppelklicks mit der linken Maustaste steht das eigene Ereignis Worksheet_BeforeDoubleClick zur Verfügung. Wie schon bei der rechten Maustaste beschrieben, besteht auch bei diesem Ereignis die Möglichkeit, die standardmäßig zugewiesene Funktion zu deaktivieren, indem das Argument Cancel dieses Ereignisses den Wert True zugewiesen bekommt. Einfärben per Doppelklick Im folgenden Beispiel in Listing 8.20 liegt eine Liste, bestehend aus drei Spalten und etlichen Zeilen, vor. Die Aufgabe besteht nun darin, per Doppelklick jeweils alle Zellen der angeklickten Zeile mit der Hintergrundfarbe GELB zu formatieren. Bei erneutem Doppelklick auf eine Zelle soll diese wieder entfärbt werden. 263 jetzt lerne ich 8 Ereignisse einsetzen Listing 8.20: Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, _ Zeilen per Cancel As Boolean) Doppelklick If Target.Interior.ColorIndex = 6 Then färben bzw. wieder entRange(Cells(Target.Row, 1), _ färben Cells(Target.Row, 3)).Interior.ColorIndex = xlColorIndexNone Else Range(Cells(Target.Row, 1), _ Cells(Target.Row, 3)).Interior.ColorIndex = 6 End If Cancel = True End Sub Zunächst wird bei einem Doppelklick auf eine Zelle geprüft, ob diese bereits die Hintergrundfarbe 6 (= Gelb) enthält. Wenn dies zutrifft, dann werden die farbigen Zellen entfärbt, indem Sie der Eigenschaft ColorIndex die Konstante xlColorIndexNone zuweisen. Da nicht die komplette Zeile gefärbt werden soll, sondern nur die ersten drei Spalten, wird mithilfe der Eigenschaft Range und der Cells-Auflistung ein dynamischer Bereich definiert, der die ersten drei Spalten der jeweiligen Zeile enthält. Bild 8.12: Mit einem Doppelklick auf eine Zelle werden die dazugehörigen Daten gelb formatiert 264 Ereignisse auf Tabellenblattebene jetzt lerne ich Werte addieren per Doppelklick In der nächsten Praxisaufgabe in Listing 8.21 soll der Wert einer bestimmten Zelle in TABELLE12 bei jedem Doppelklick auf diese Zelle um den Wert 1 erhöht werden. Private Sub Worksheet_BeforeDoubleClick _ (ByVal Target As Excel.Range, Cancel As Boolean) If Target.Address = "$A$1" Then Target.Value = Target.Value + 1 Cancel = True End If Listing 8.21: Einen Zellenwert bei jedem Doppelklick um den Wert 1 erhöhen End Sub Mithilfe der Eigenschaft Address lässt sich die genaue Zellenadresse der doppelt angeklickten Zelle abfragen. Entspricht diese Adresse der Zelle A1, dann wird der momentane Wert der Zelle mit dem Wert 1 addiert. Setzen Sie danach das Argument Cancel auf den Wert True, um die direkte Zellenbearbeitung für diese Zelle zu deaktivieren. Bild 8.13: Ein Feature, das mit normalen Mitteln in Excel nicht zu realisieren wäre 8.2.6 Weitere Tabellenereignisse im Überblick Entnehmen Sie der folgenden Tabelle alle Ereignisse, die Sie auf Tabellenebene einsetzen können. Ereignis Beschreibung Worksheet_Activate Tritt ein, wenn ein Tabellenblatt aktiviert wird. Worksheet_Change Tritt ein, wenn sich der Wert in einer Zelle ändert. Tabelle 8.3: Alle Tabellenereignisse im Überblick 265 8 Ereignisse einsetzen jetzt lerne ich Tabelle 8.3: Ereignis Alle Tabellenereignisse Worksheet_Calculate im Überblick (Forts.) Worksheet_Deactivate Beschreibung Tritt ein, wenn eine Tabelle neu berechnet wird. Tritt ein, wenn ein Tabellenblatt deaktiviert wird. Beispielsweise wenn ein Tabellenblatt verlassen wird. Worksheet_FollowHyperlink Tritt ein, wenn der Anwender auf einen Hyperlink in einer Tabelle klickt. Worksheet_SelectionChange Tritt ein, wenn sich die Markierung in einem Tabellenblatt ändert. BeforeDoubleClick Tritt ein, wenn an einer beliebigen Stelle der Tabelle ein Doppelklick mit der linken Maustaste durchgeführt wird. BeforeRightClick Tritt ein, wenn an einer beliebigen Stelle der Tabelle ein Klick mit der rechten Maustaste durchgeführt wird. Calculate Tritt nach Neuberechnung eines Tabellenblatts auf. PivotTableUpdate Tritt auf, wenn Sie eine Pivot-Tabelle aktualisieren. 8.3 Excel über Tastenkombinationen bedienen Viele Standardfunktionen in Excel lassen sich über Tastenkombinationen bzw. Funktionstasten abrufen. In einem vorangegangenem Beispiel haben Sie gelernt, dass über die Taste Ó ein Standarddiagramm in Excel eingefügt werden kann. Auch die Tastenkombinationen Ÿ+C und Ÿ+V, um Daten zu kopieren bzw. einzufügen, gehören zum Standard von Excel. Darüber hinaus besteht die Möglichkeit, eigene Tastenkombinationen zu definieren, mit denen dann ein eigenes Makro gestartet wird. Sie können somit Ihre Arbeit in Excel optimieren und Arbeiten noch schneller erledigen, um dadurch gegebenenfalls früher Feierabend zu haben! 266 Excel über Tastenkombinationen bedienen 8.3.1 jetzt lerne ich Formeln und Verknüpfungen in Festwerte wandeln Im ersten Beispiel werden über eine vorher definierte Tastenkombination alle Formeln, Funktionen oder Verknüpfungen im markierten Bereich durch Festwerte ersetzt. Dies stellt eine nützliche Funktion dar, da dies der schnellste Weg ist Formeln in Festwerte umzusetzen. Stellen Sie sich beispielsweise vor, Sie müssten eine Tabelle, die Verknüpfungen zu anderen Tabellen oder Arbeitsmappen enthält, an einen Kollegen per E-Mail schicken. In diesem Fall ist es besser, alle Verknüpfungen aus der Arbeitsmappe zu entfernen, um nicht alle verknüpften Arbeitsmappen mit ausliefern zu müssen. Damit wird auch die zu versendende Datengröße auf ein notwendiges Minimum beschränkt. Eine weiteres Anwendungsbeispiel für die Praxis stellt folgendes Szenario dar: Es wurden einige Berechnungen über Funktionen und Formeln in Excel durchgeführt und prinzipiell ist damit die Arbeit soweit beendet. Nun möchten Sie sicherheitshalber eine Kopie der Arbeitsmappe ohne Formeln abspeichern. Sie können somit sicherstellen, dass diese Arbeitsmappe nicht mehr durch Formeln oder Funktionen verändert werden kann, da die Mappe nur noch Festwerte enthält. Formeln durch Festwerte ersetzen Im ersten Schritt erfassen Sie das Makro, das die Formelzellen in Festwertzellen umsetzt. Danach wird dem Makro eine Tastenkombination zugewiesen, mit der es direkt aufgerufen wird. Das Makro für die Umsetzung lautet: Sub FormelnFest() Dim Zelle As Range For Each Zelle In Selection Zelle.Value = Zelle.Value Next Zelle End Sub Listing 8.22: Die Formeln in allen markierten Zellen werden durch Festwerte ersetzt Im ersten Schritt wird eine Objektvariable vom Typ Range definiert. Danach werden in einer Schleife alle Zellen durchlaufen, die in der Markierung enthalten sind. Über das Auflistungsobjekt Selection 267 jetzt lerne ich 8 Ereignisse einsetzen (= Auswahl) erhalten Sie Zugriff auf genau diese markierten Zellen und überschreiben den Inhalt mit dem aktuellen Wert der Zelle. Für den Fall, dass es sich hierbei um eine Formelzelle handelt, wird die Formel durch den Festwert ersetzt. Tastenkombination zuweisen Nun soll das Starten des Makros über eine Tastenkombination durchgeführt werden. Das Zuweisen einer Tastenkombination in Excel sollte dynamisch erfolgen. Dabei bietet sich das Öffnen einer Arbeitsmappe geradezu an. Die so definierte Tastenkombination ist dann nutzbar und der Anwender kann das der Tastenkombination zugewiesene Makro starten. Für das Ersetzen von Formelzellen durch Festwerte soll beim Öffnen der Arbeitsmappe Ereignisse.xls die Tastenkombination Ÿ+Ü definiert werden. Um diese Aufgabe umzusetzen, befolgen Sie die nächsten Arbeitsschritte: 1. Wechseln Sie in die Entwicklungsumgebung von Excel. 2. Führen Sie im Projekt-Explorer einen Doppelklick auf den Eintrag DIESEARBEITSMAPPE durch. 3. Wählen Sie oben im Codebereich aus dem ersten Dropdown-Feld den Eintrag WORKBOOK aus. 4. Ergänzen Sie das WORKBOOK_OPEN-Ereignis wie folgt: Listing 8.23: Private Sub Workbook_Open() Eine TastenApplication.OnKey "^ü", "FormelnFest" kombination beim Öffnen der Mappe End Sub zuweisen Mit dem Einsatz der Methode OnKey wird die angegebene Prozedur ausgeführt, wenn eine bestimmte Taste oder Tastenkombination gedrückt wird. Die Syntax der Methode lautet: Application.OnKey(Key, Procedure) Das Argument Key entspricht der Tastenkombination, die gedrückt wird. Das Argument Procedure entspricht dem Makro, das der Tastenkombination zugewiesen werden kann. Bleibt dieses Argument leer (""), dann hat das Drücken der Taste keine Wirkung. 268 Excel über Tastenkombinationen bedienen jetzt lerne ich Entnehmen Sie der Tabelle 8.4 alle möglichen Tasten und deren Codebelegung, die für die Programmierung verwendet werden können. Taste Codebelegung à {BACKSPACE} oder {BS} þPauseÿ {BREAK}  {CAPSLOCK} ® {CLEAR} ® {DELETE} oder {DEL} ~ {DOWN} ¤ {END} Æ Zehnertastatur {ENTER} ~ ~ (Tilde) È {ESCAPE} oder {ESC} þHilfeÿ {HELP} £ {HOME} - {INSERT} { {LEFT} ´ {NUMLOCK} ² {PGDN} ³ {PGUP} Æ {RETURN} } {RIGHT} þRollenÿ {SCROLLOCK} Å {TAB} | {UP} É bis þF15ÿ {F1} bis {F15} Tabelle 8.4: Die verfügbaren Tasten in Excel-VBA In jeder Anwendung von Windows können die Tasten in Tabelle 8.4 auch mit den Tasten Ç, Ÿ oder Á kombiniert werden. Entnehmen Sie der nachfolgenden Tabelle 8.5 die Kodierung dieser Zusatztasten. 269 8 Ereignisse einsetzen jetzt lerne ich Tabelle 8.5: Zusatztaste Die Zusatztasten Á Vorangestelltes Zeichen + (Pluszeichen) Ÿ ^ (Caret-Zeichen) Ç % (Prozentzeichen) þBefehlstasteÿ * (Sternchen) Nachdem Sie die Tastenkombination Ÿ+Ü dem Makro FORMELNFEST zugewiesen haben, sollte beim Schließen der Arbeitsmappe Ereignisse.xls dafür gesorgt werden, dass diese Tastenkombination wieder aufgehoben wird. Dabei verfahren Sie wie folgt: 1. Wechseln Sie in die Entwicklungsumgebung von Excel. 2. Führen Sie im Projekt-Explorer einen Doppelklick auf den Eintrag DIESEARBEITSMAPPE durch. 3. Wählen Sie oben im Codebereich aus dem ersten Dropdown-Feld den Eintrag WORKBOOK aus. 4. Im zweiten Dropdown-Feld wählen Sie den Eintrag BEFORECLOSE aus und ergänzen das Ereignis wie folgt: Listing 8.24: Die Tasten- Private Sub Workbook_BeforeClose(Cancel As Boolean) kombination Application.OnKey "^ü" wird beim Schließen der Mappe wieder End Sub aufgehoben 8.4 Excel zeitmäßig steuern Mit Excel besteht die Möglichkeit, Makros zu einem bestimmten Zeitpunkt zu starten. Des Weiteren lassen sich Makros auch in bestimmten Intervallen wiederholt ausführen. Für diese Aufgabe wird die Methode OnTime verwendet. Die Syntax der Methode lautet: OnTime(EarliestTime, Procedure, LatestTime, Schedule) Das Argument EarliestTime gibt den Zeitpunkt an, an dem eine Prozedur ausgeführt werden soll. Das Argument Procedure beinhaltet den Namen der auszuführenden Prozedur. 270 Excel zeitmäßig steuern jetzt lerne ich Das Argument LatestTime ist optional einsetzbar und gibt den letzten Zeitpunkt an, zu dem die Prozedur ausgeführt werden kann. Das letzte Argument Schedule ist optional einsetzbar und führt eine neue OnTime-Prozedur aus, sofern dieses Argument auf den Wert True gesetzt ist. Indem Sie das Argument auf den Wert False setzen, wird eine vorher eingestellte Prozedur gelöscht. Die Möglichkeiten, die Sie mit dieser Zeitsteuerung haben, werden in den nächsten Praxisaufgaben näher erläutert. 8.4.1 Countdown in Excel Sofern benötigt, lässt sich mit Excel auch ein Countdown realisieren, um eine bestimmte Aufgabe auszuführen. So lässt sich beispielsweise dafür sorgen, dass genau 60 Sekunden nach dem Start eines Makros alle offenen Arbeitsmappen geschlossen werden und Excel beendet wird. Erfassen Sie zu diesem Zweck zuerst einmal die Zeitsteuerung, die Sie in Listing 8.25 finden können. Sub CountdownEinstellen() Application.OnTime _ Now + TimeValue("00:00:60"), "ExcelEnde" Listing 8.25: Die Schaltuhr wird gesetzt End Sub Mit der Funktion Now ermitteln Sie sowohl das aktuelle Tagesdatum als auch die aktuelle Uhrzeit. Zur Uhrzeit werden mithilfe der Funktion TimeValue 60 Sekunden addiert. Damit vergehen genau 60 Sekunden bis zum Start des Makros EXCELENDE, das Sie in Listing 8.26 sehen. Sub ExcelEnde() Dim Mappe As Workbook Application.DisplayAlerts = False For Each Mappe In Workbooks Mappe.Save Next Mappe Listing 8.26: Alle Mappen werden gesichert und Excel wird beendet Application.DisplayAlerts = True Application.Quit End Sub 271 8 Ereignisse einsetzen jetzt lerne ich Indem die Eigenschaft DisplayAlerts auf den Wert False gesetzt wird, erfolgt keine Rückfrage vor dem Beenden von Excel. In einer vorherigen Schleife wird sichergestellt, dass alle aktuell geöffneten Arbeitsmappen gespeichert werden. Dabei wenden Sie innerhalb der Schleife die Methode Save an. Anschließend wird über die Methode Quit Excel geschlossen. 8.4.2 Verarbeitung zu einer bestimmten Zeit beginnen Im letzten Beispiel zur Zeitsteuerung mit Excel wird ein Makro zu einer ganz bestimmten Uhrzeit gestartet. Erfassen Sie zu diesem Zweck das Makro in Listing 8.27: Listing 8.27: Sub ZeitSteuerung() Das Makro startet um Application.OnTime TimeValue("16:00:00"), "Verarbeitung" 16:00 End Sub Um das Makro in Listing 8.27 korrekt ablaufen zu lassen, sollte die Uhreinstellung in der Systemsteuerung von Windows überprüft werden. Und generell sollte sichergestellt sein, dass sowohl Excel als auch die Arbeitsmappe, die diese Lösung enthält, geöffnet sind. Im oben dargestellten Makro ZEITSTEUERUNG wird um 16:00 Uhr das unten beschriebene Makro VERARBEITUNG aufgerufen. Listing 8.28: Sub Verarbeitung() Dieses Makro wird genau um 'beliebige Aufgaben durchführen... MsgBox "Jetzt ist genau " & Time & " Uhr!" 16:00 gestartet End Sub 272 jetzt lerne ich KAPITEL 9 Dialoge und Steuerelemente programmieren In diesem Kapitel lernen Sie, wie Dialoge in der Programmierung eingesetzt werden können, um anwenderfreundliche Anwendungen zu erstellen. Dabei haben Sie die Möglichkeit, schon bestehende Dialoge in Excel zu nutzen oder eigene Dialoge (UserForms) zu erstellen. Sie finden alle Beispiele dieses Kapitels auf der diesem Buch beiliegenden CD-ROM im Verzeichnis Kap09 in den Dateien Dialoge.xls und Datenmaske.xls. 9.1 1 Der Meldungen-Dialog MsgBox In den vorherigen Kapiteln wurde die Funktion MsgBox schon öfter eingesetzt. Diese Funktion wird z. B. dazu verwendet, um den Anwender über ein Ergebnis eines Makros zu informieren oder um eine Warnmeldung auf dem Bildschirm anzuzeigen. Dabei können Sie das Aussehen dieser Maske selbst bestimmen. Im folgenden Makro in Listing 9.1 wird die eingesetzte Excel-Version ermittelt und am Bildschirm angezeigt. 273 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren Listing 9.1: Sub MsgboxEinfach() Eine einfache MsgBox "Sie haben die Excel Version " & _ Meldung am Application.Version & " im Einsatz!", vbInformation Bildschirm ausgeben End Sub Bild 9.1: Eine einfache Meldung am Bildschirm ausgeben Um eine Meldung auf dem Bildschirm anzuzeigen, verwenden Sie die Funktion MsgBox, die folgende Syntax hat: =MsgBox(prompt[, buttons] [, title] [, helpfile, context]) Das erste Argument prompt muss angegeben werden. Es besteht aus einem Text, der als Meldung im Dialogfeld erscheinen soll. Das nächste Argument buttons bestimmt, welche Schaltflächen der Meldung mit angezeigt werden sollen. Diese Einstellung lässt sich entweder durch eine Konstante oder einen eindeutigen Index ansprechen. Entnehmen Sie dazu der folgenden Tabelle 9.1 die möglichen Varianten: Tabelle 9.1: Konstante oder Wert Die zur Verfügung stehen- 1. Gruppe den Schalt- vbOKOnly oder 0 flächen Beschreibung Zeigt nur die Schaltfläche OK an. vbOKCancel oder 1 Zeigt die Schaltflächen OK und ABBRECHEN an. vbAbortRetryIgnore oder 2 Zeigt die Schaltflächen ABBRUCH, WIEDERHOLEN und IGNORIEREN an. vbYesNoCancel oder 2 Zeigt die Schaltflächen JA, NEIN und ABBRECHEN an. vbYesNo oder 4 Zeigt die Schaltflächen JA und NEIN an. vbRetryCancel oder 5 Zeigt die Schaltflächen WIEDERHOLEN und ABBRECHEN an. 2. Gruppe 274 vbCritical oder 16 Zeigt Meldung mit STOP-Symbol an. vbQuestion oder 32 Zeigt Meldung mit FRAGEZEICHEN-Symbol an. vbExclamation oder 48 Zeigt Meldung mit AUSRUFEZEICHEN-Symbol an. vbInformation oder 64 Zeigt Meldung mit INFO-Symbol an. Der Meldungen-Dialog MsgBox Konstante oder Wert Beschreibung 3. Gruppe vbDefaultButton1 oder 0 Erste Schaltfläche ist Standardschaltfläche. vbDefaultButton2 oder 256 Zweite Schaltfläche ist Standardschaltfläche. vbDefaultButton3 oder 512 Dritte Schaltfläche ist Standardschaltfläche. vbDefaultButton4 oder 768 Vierte Schaltfläche ist Standardschaltfläche. vbApplicationModal oder 0 Der Anwender muss zuerst auf das Meldungsfeld reagieren, bevor er seine Arbeit mit der aktuellen Anwendung fortsetzen kann. vbSystemModal oder 4096 Alle Anwendungen werden unterbrochen, bis der Benutzer auf das Meldungsfeld reagiert. vbMsgBoxHelpButton oder 16384 Fügt dem Meldungsfenster eine Hilfeschaltfläche hinzu. jetzt lerne ich Tabelle 9.1: Die zur Verfügung stehenden Schaltflächen (Forts.) Die Anzahl und der Typ der im Dialogfeld angezeigten Schaltflächen werden in der ersten Gruppe beschrieben. Die zweite Gruppe beschreibt die Symbolart. Die dritte Gruppe legt die Standardschaltfläche fest. Je Gruppe kann jeweils nur ein Wert angegeben werden. Im nächsten Argument Title legen Sie einen Text fest, der im Fenstertitel angezeigt werden soll. Die letzten beiden Argumente helpfile und context werden dann verwendet, wenn Sie auf einen Hilfetext im Meldungsfenster verweisen möchten. Die maximale Länge ist je nach Breite der verwendeten Zeichen auf ca. 1.024 Zeichen beschränkt. Gerade haben Sie erfahren, wie sich zusätzliche Schaltflächen in eine Meldung integrieren lassen. Wie aber lässt sich ermitteln, welche Schaltfläche der Anwender letztendlich anklickt? 9.1.1 Löschrückfrage einholen Stellen Sie sich vor, es wurde eine Zelle oder ein Zellenbereich markiert, um diese/n mit einem Makro zu löschen. Vorher soll aber noch eine Meldung auf dem Bildschirm angezeigt werden, mit der eine Abfrage erstellt wird, ob der markierte Bereich wirklich gelöscht werden darf. 275 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren Listing 9.2: Sub LöschenMarkierterBereich() Eine Rückfra- Dim i As Integer ge auswerten i = MsgBox _ ("Wollen Sie den markierten Bereich löschen?", _ 1 + vbQuestion, "Löschenabfrage") If i = 2 Then Exit Sub Else Selection.Clear End If End Sub Um zu ermitteln, welche Schaltfläche der Anwender anwählt, wird die Variable i abgefragt. Klickt der Anwender auf die Schaltfläche ABBRECHEN, meldet die Variable den Wert 2, was ein sofortiges Beenden des Makros zur Folge hat. Im andern Fall werden über die Methode Clear die Daten innerhalb der Markierung gelöscht. Bild 9.2: Eine Rückfrage programmieren Weitere mögliche Rückgaben, je nach eingesetzter Schaltfläche, können Sie in Tabelle 9.2 nachsehen. Tabelle 9.2: Konstante oder Wert Die RückgabeNummern der vbOK oder 1 Schaltflächen vbCancel oder 2 276 Beschreibung Die Schaltfläche OK wurde angeklickt. Die Schaltfläche ABBRECHEN wurde angeklickt. vbAbort oder 3 Die Schaltfläche ABBRUCH wurde angeklickt. vbRetry oder 4 Die Schaltfläche WIEDERHOLEN wurde angeklickt. vbIgnore oder 5 Die Schaltfläche IGNORIEREN wurde angeklickt. vbYes oder 6 Die Schaltfläche JA wurde angeklickt. vbNo oder 7 Die Schaltfläche NEIN wurde angeklickt. Die Eingabemaske InputBox 9.2 jetzt lerne ich Die Eingabemaske InputBox Mithilfe der Methode InputBox kann der Anwender einzelne Eingaben in einer Maske vornehmen. Diese Funktion eignet sich hervorragend für kleinere Aufgaben, und auch hier können Sie Aussehen und Funktion des Dialogs selbst bestimmen. Die Syntax dieser Funktion sieht wie folgt aus: InputBox(prompt, title, default, Left, Top, helpFile, helpContext, type) Das erste Argument prompt muss angegeben werden. Es besteht aus einem Text, der als Meldung im Dialogfeld erscheinen soll. Im nächsten Argument title wird ein Text festgelegt, der im Fenstertitel angezeigt werden soll. Im Argument default lässt sich eine Vorbelegung definieren, die im Textfeld angezeigt wird, wenn das Dialogfeld aufgerufen wird. Wenn das Argument weggelassen wird, erscheint ein leeres Textfeld. Mit den nächsten beiden Argumenten left und top lässt sich die Position auf dem Bildschirm festlegen, wo die InputBox angezeigt werden soll. So wird beim Argument left der horizontale Abstand des linken Rands des Dialogfeldes vom linken Rand des Bildschirms festgelegt. Beim Argument top wird der vertikale Abstand des oberen Rands des Dialogfeldes vom oberen Rand des Bildschirms festgelegt. Die beiden Argumente helpfile und context werden dann eingesetzt, wenn Sie auf einen Hilfetext im Meldungsfenster verweisen möchten. Das letzte Argument type legt den Datentyp des Rückgabewertes fest. Ohne Angabe dieses Arguments gibt das Dialogfeld den Datentyp Text zurück. Entnehmen Sie die zulässigen Rückgabewerte der Tabelle 9.3. Wert Beschreibung 0 Formel 1 Zahl 2 Text 4 logischer Wert (True oder False) Tabelle 9.3: Die möglichen Typen der Methode InputBox 277 9 Dialoge und Steuerelemente programmieren jetzt lerne ich Tabelle 9.3: Wert Die möglichen Typen der Me- 8 thode InputBox 16 (Forts.) Beschreibung Zellenbezug Fehlerwert Wertematrix 64 9.2.1 Die Mehrwertsteuer errechnen Dem Anwender soll nach der Eingabe eines Nettobetrags automatisch die Mehrwertsteuer angezeigt werden. Dazu erfassen Sie das Makro in Listing 9.3. Listing 9.3: Die Mehrwertsteuer aus einem Betrag ausrechnen Sub MwstErrechnen() Dim Betrag As Currency Dim Gesamt As Currency Const mwst = "1,16" Betrag = Application.InputBox _ ("Mehrwertsteuer errechnen", "Bitte Betrag eingeben") If Betrag = 0 Then Exit Sub Gesamt = Betrag * mwst MsgBox "Die Mehrwertsteuer ist: " & _ Gesamt - Betrag & " Euro" End Sub Legen Sie zuerst in einer Konstanten den derzeitigen Mehrwertsteuersatz fest. Danach wird die Methode InputBox aufgerufen, damit der Anwender einen Nettobetrag eingeben kann. Sollte der Anwender die Schaltfläche ABBRECHEN angeklickt haben, wird das Programm durch die Anweisung Exit Sub sofort verlassen. Im andern Fall wird zuerst der Gesamtbetrag aus dem Nettobetrag und dem Prozentsatz der Mehrwertsteuer errechnet. Danach wird der Mehrwertsteuerbetrag ermittelt und in einem Meldungsfenster ausgegeben. Bild 9.3: Eingabe des Bruttobetrags 278 Die Eingabemaske InputBox 9.2.2 Bereich über eine InputBox markieren jetzt lerne ich Bild 9.4: Das Ergebnis ist die Mehrwertsteuer (derzeit noch 16 %) Dass einzelne Daten über eine InputBox erfasst werden können, haben Sie in den letzten Beispielen gelernt. Haben Sie aber gewusst, dass mit der gleichen Methode auch Bereiche angegeben werden können, um diese später zu markieren? Sehen Sie sich dazu das folgende Makro in Listing 9.4 an. Sub BereicheMarkieren() Dim Bereich As Range On Error Resume Next Set Bereich = Application.InputBox(prompt:="Bereich markieren", _ Type:=8) Listing 9.4: Einen Bereich über eine InputBox markieren If Bereich Is Nothing Then MsgBox "Sie haben keinen Bereich ausgewählt", _ vbExclamation Else Bereich.Select End If End Sub Zuerst muss eine Range-Variable deklariert werden, die den auszuwählenden Bereich aufnehmen soll. Um einen Bereich mit der InputBox zu markieren, muss diese vom Typ 8 sein. Wird kein Bereich ausgewählt, erscheint eine Meldung auf dem Bildschirm, im andern Fall wird der Bereich in dem Tabellenblatt markiert. Selbstverständlich lassen sich auch mehrere Bereiche nacheinander markieren. Halten Sie hierbei die Taste Ÿ gedrückt. Excel übernimmt automatisch die Zellenkoordination in dem Textfeld der InputBox. 1 279 9 Dialoge und Steuerelemente programmieren jetzt lerne ich Bild 9.5: Ein Bereich wird über eine InputBox markiert 9.3 Integrierte Dialoge einsetzen Bei der Programmierung mit Dialogen müssen nicht unbedingt eigene Dialoge erstellt werden. Oft reicht es auch aus, bereits vorhandene Dialoge in Excel für eigene Projekte zu nutzen. Ein weiterer Vorteil ist, dass ein Anwender diese bereits kennt und sich nicht mehr in fremde Dialoge einarbeiten muss. Alle integrierten Dialoge von Excel können über die Methode Show aufgerufen werden. 9.3.1 Den Öffnen-Dialog aufrufen Normalerweise lassen sich Excel-Arbeitsmappen auch direkt mit einem Makro öffnen, ohne den ÖFFNEN-Dialog einzusetzen. Stehen jedoch mehrere Arbeitsmappen zur Auswahl, zwischen denen sich der Anwender entscheiden muss, verwenden Sie den integrierten ÖFFNEN-Dialog und lassen den Anwender die gewünschte Arbeitsmappe auswählen. Der Vorteil liegt auf der Hand: Sie brauchen sich um bestimmte Dinge, wie das Anzeigen der Arbeitsmappen im Dialog oder auch das Markieren und Öffnen der Mappen, nicht selbst zu kümmern. Die gesamte benötigte Funktionalität ist schon vorhanden. Wie der ÖFFNEN-Dialog aufgerufen werden kann ist im Folgenden dargestellt: 280 Integrierte Dialoge einsetzen Sub DialogÖffnen() Dim b As Boolean b = Application.Dialogs(xlDialogFindFile).Show MsgBox b jetzt lerne ich Listing 9.5: Den Standarddialog Öffnen anzeigen End Sub Definieren Sie zuerst einmal eine Variable vom Typ Boolean, um zu ermitteln, ob eine Datei geöffnet worden ist oder nicht. Wurde über den ÖFFNEN-Dialog eine Datei geöffnet, steht in der Variablen b der Wert WAHR. Wurde dagegen im Dialog ÖFFNEN auf die Schaltfläche ABBRECHEN geklickt, meldet die Variable b den Wert FALSCH. Bild 9.6: Einen integrierten ExcelDialog anzeigen 9.3.2 Den Dialog Drucken aufrufen Um ein oder mehrere Tabellenblätter zu drucken, wird üblicherweise der Dialog DRUCKEN aufgerufen. In manchen Fällen ist es aber wichtig, vorher bestimmte Einstellungen für den Druck vorzunehmen, die durch den Anwender selbst bestimmt werden können. Im folgenden Beispiel wird der DRUCKEN-Dialog aufgerufen und dabei werden automatisch bestimmte Informationen, wie die Anzahl der Kopien bzw. die zu druckenden Seiten, eingestellt. 281 9 Dialoge und Steuerelemente programmieren jetzt lerne ich Listing 9.6: Den Standarddialog Drucken aufrufen und nutzen Sub DialogDrucken() Const SeiteVon = 1 Const SeiteBis = 4 Const Kopien = 2 Application.Dialogs(xlDialogPrint).Show arg1:=2, _ arg2:=SeiteVon, arg3:=SeiteBis, arg4:=Kopien End Sub Wenn Sie beim Definieren der Druckeinstellungen mit Konstanten arbeiten und diese zu Beginn des Makros definieren, lassen sich diese Einstellungen jederzeit leicht ändern. Bild 9.7: Im DruckenDialog sind einige Einstellungen vorab vorgenommen worden 9.3.3 Weitere integrierte Dialoge in Excel Möchten Sie eine Übersicht darüber erhalten, welche integrierten Dialoge es in Excel gibt und vor allem, wie diese heißen? Dann rufen Sie in der Entwicklungsumgebung den Objektkatalog über die Taste Ê auf und schauen in der Rubrik XLBUILTINDIALOG nach. 282 UserForms erstellen und automatisieren jetzt lerne ich Bild 9.8: Alle verfügbaren Dialoge von Excel in der Kurzübersicht 9.4 UserForms erstellen und automatisieren Sollen individuelle oder auch komplexere Aufgaben über Dialoge abgewickelt werden? Und kommen Sie mit den standardmäßig angebotenen Elementen, Eingabemasken, Meldungen sowie integrierten Dialogen nicht mehr aus? Dann besteht die Möglichkeit, eigene Dialoge zu »zeichnen« und danach mit Makros zu automatisieren. Diese Dialoge nennen sich in Excel UserForms. Vielleicht haben Sie auch schon einmal mit der Datenmaske aus dem Menü DATEN gearbeitet. Diese Maske bietet zwar die wichtigsten Funktionen zum Suchen, Löschen, Ändern und zur Neuanlage von Daten an, jedoch fehlt es dort erheblich an Bedienerfreundlichkeit und optimalem Handling. Wenn Sie beispielsweise versuchen, mithilfe dieser Datenmaske nach einem bestimmten Suchbegriff, der mehrfach in der Datenbasis vorkommt, zu suchen, dann lässt sich darin jeweils nur ein Satz nach dem anderen ansehen. Dabei geht die Übersichtlichkeit verloren und meistens werden Sie aus diesem Grund auf dieses Feature auch generell verzichten. 283 9 Dialoge und Steuerelemente programmieren jetzt lerne ich In diesem Abschnitt wird Ihnen eine allgemein gültige und stark erweiterte Datenmaske präsentiert, mit der sich Daten anlegen, ändern und löschen lassen. Folgen Sie den nachfolgenden Beispielen und nutzen die dadurch entstehenden neuen Möglichkeiten für die tägliche Arbeit. 1 Die Beispieldatei Datenmaske.xls finden Sie auf der CD-ROM im Verzeichnis Kap09. Bild 9.9: Die herkömmliche Datenmaske 9.4.1 Die Anforderungen In diesem Abschnitt wird Ihnen eine universal einsetzbare Datenmaske vorgestellt, über die der Anwender in einer datenbankähnlichen Liste schnell und übersichtlich suchen, ändern, löschen oder gar ganz neue Sätze anlegen kann. Dabei kann für die Suche über ein Textfeld ein Suchbegriff eingegeben werden, nach dem in der Liste gesucht werden soll. Excel arbeitet danach die Datenliste Satz für Satz ab und stellt alle Suchergebnisse in einem mehrspaltigen Listenfeld dar. Mit einem Klick auf den gewünschten Satz können dann folgende Aktionen durchgeführt werden: 쐽 Datensatz anzeigen 쐽 Datensatz erfassen 쐽 Datensatz ändern 쐽 Datensatz löschen 284 UserForms erstellen und automatisieren jetzt lerne ich Bild 9.10: Das Ziel – die fertige erweiterte Datenmaske Mit dieser flexiblen Lösung können individuelle Eingabemasken relativ einfach erstellt und auch leicht nachträglich für unterschiedliche Aufgaben angepasst werden. Folgen Sie der nachfolgend beschriebenen Realisierung Schritt für Schritt und testen am besten am eigenen Computer, wie schnell Sie zum gleichen Ergebnis gelangen. 9.4.2 Die Datenmaske zeichnen und die ersten Eigenschaften einstellen Als erste Aufgabe muss die Datenmaske gezeichnet werden. Dazu fügen Sie eine leere UserForm in der Entwicklungsumgebung ein und entwerfen mithilfe der Symbolleiste WERKZEUGSAMMLUNG eine Datenmaske nach dem Vorbild in Abbildung 9.11. Sobald Sie Ihre erste UserForm eingefügt haben, wird automatisch die Symbolleiste WERKZEUGSAMMLUNG mit eingeblendet. Diese Werkzeugsammlung nutzen Sie, um den noch leeren Dialog mit Elementen zu bestücken. 285 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren Bild 9.11: Der Rohbau der Datenmaske Entnehmen Sie der folgenden Tabelle die wichtigsten Steuerelemente der Symbolleiste WERKZEUGSAMMLUNG. Tabelle 9.4: Symbol Die wichtigsten Steuerelemente für UserForms Funktionsbeschreibung Markiert das entsprechende Element in der UserForm. Damit lassen sich Texte in der UserForm hinterlegen, meist im Zusammenspiel mit Eingabefeldern, um diese zu bezeichnen. Die Bezeichnungsfelder werden in der UserForm mit grauem Hintergrund hinterlegt. Damit sind Eingabefelder gemeint, mit denen der Anwender Texte oder Zahlen erfassen kann. Ein Kombinationsfeld besteht streng genommen aus einem Eingabefeld, das mit einem Listenfeld gekoppelt ist. Kombinationsfelder erkennen Sie daran, dass sich rechts neben dem Eingabefeld ein kleiner Pfeil nach unten befindet. Mit einem Klick darauf werden Ihnen weitere Auswahlmöglichkeiten angeboten. In einem Kombinationsfeld kann immer nur ein Eintrag gewählt werden. 286 UserForms erstellen und automatisieren Symbol Funktionsbeschreibung Verwandt mit dem Kombinationsfeld ist auch das Listenfeld. Das Listenfeld benötigt jedoch mehr Platz, weil mehrere Einträge gleichzeitig angezeigt werden. Ein Listenfeld kann so eingestellt werden, dass mehrere Einträge ausgewählt werden können. jetzt lerne ich Tabelle 9.4: Die wichtigsten Steuerelemente für UserForms (Forts.) Das Rahmen-Steuerelement lässt sich verwenden, um einzelne Elemente in einer Gruppe zu umrahmen bzw. zusammenzufassen. Wichtig bei der Erstellung eines Rahmens ist, dass dieser vor den einzelnen Steuerelementen, die darin platziert werden sollen, eingefügt wird. Das Steuerelement RAHMEN besticht ferner durch seine räumliche Darstellung und kann auch eingesetzt werden, um die UserForm optisch aufzupeppen. Das Kontrollkästchen kann als Voreinstellung entweder aktiviert oder nicht aktiviert sein. Bei aktiviertem Zustand erscheint im Kästchen ein Häkchen. Wenn Sie Kontrollkästchen in einer Gruppe verwenden, können ein oder mehrere Kontrollkästchen aktiviert sein. Das Optionsfeld, auch bekannt als Radiobutton, kann als Voreinstellung aktiviert oder nicht aktiviert sein. Bei aktiviertem Zustand ist das Optionsfeld mit einem schwarzen Punkt ausgefüllt. Wenn Sie mehrere Optionsfelder innerhalb einer Gruppe verwenden, kann immer nur eine Option aktiviert sein. Das Umschaltfeld können Sie mit einem Lichtschalter vergleichen. Es hat genau zwei Zustände: Ein und Aus, die sich optisch leicht voneinander abheben. Hinter Befehlsschaltflächen legen Sie Makros, um bestimmte Aktionen durch einen Mausklick mit der UserForm auszuführen. Sofern notwendig, lässt sich aber auch eine Schaltfläche über eine Tastenkombination bedienen. Dazu schreiben Sie in der Caption-Eigenschaft das Zeichen & vor den gewünschten Buchstaben. Dieser Buchstabe in Verbindung mit der Taste Ç bildet dann die Tastenkombination für diese Schaltfläche. Wenn in einer UserForm mehrere Register verwendet werden sollen, lässt sich dies mit dem dargestellten Element realisieren. Verwandt mit dem letzten Steuerelement ist auch das Steuerelement MULTISEITEN. Auch bei diesem Element besteht die Möglichkeit, Informationen übersichtlich auf mehrere Seiten zu verteilen. 287 9 Dialoge und Steuerelemente programmieren jetzt lerne ich Tabelle 9.4: Symbol Die wichtigsten Steuerelemente für UserForms (Forts.) Funktionsbeschreibung Dieses Steuerelement wird bei umfangreichen UserForms verwendet, wenn horizontal oder auch vertikal gescrollt werden muss, um bestimmte Elemente anzuzeigen. Das Drehfeld lässt sich ideal dazu verwenden, um z. B. einen Wert schrittweise hochzuzählen. Das Steuerelement wird meist in Verbindung mit einem Textfeld verwendet. Mithilfe dieses Elements lassen sich Grafiken in eine UserForm einfügen. Mit dem REFEDIT-Element können Sie über ein Eingabefeld einen Bereich markieren bzw. auch Texte eingeben. 1 Weitere Steuerelemente lassen sich jederzeit einblenden, indem Sie mit der rechten Maustaste auf die Symbolleiste klicken und aus dem Kontextmenü den Befehl ZUSÄTZLICHE STEUERELEMENTE auswählen. Im Listenfeld VERFÜGBARE STEUERELEMENTE lassen sich dann per Mausklick zusätzliche Steuerelemente zu Ihrer Symbolleiste hinzufügen. 9.4.3 Grafiken einstellen Das Suchen-Symbol »Fernglas« links oben in der Datenmaske wurde vorher aus einer Windows-Applikation abfotografiert und als Grafik auf der Festplatte gespeichert. Dann wurde zunächst eine normale Schaltfläche über das Steuerelement BEFEHLSSCHALTFLÄCHE in die UserForm eingefügt und über das Eigenschaften-Fenster die Eigenschaft Picture eingesetzt, um das Bild als Schaltflächengrafik einzufügen. Die ursprünglichen Eigenschaften einer Befehlsschaltfläche bleiben erhalten und die gewünschte Funktionalität kann grafisch mit eigenen Symbolen logisch angedeutet werden. Die vorher auf der Festplatte gespeicherte Grafikdatei wird zukünftig nicht mehr benötigt. Nach dem Einfügen ist diese in den Quellcode eingebunden. Wenn Sie also die Lösung an andere Anwender weitergeben möchten, muss die Grafikdatei nicht einzeln mitgeliefert werden. 288 UserForms erstellen und automatisieren 9.4.4 jetzt lerne ich Default-Schaltfläche definieren und umbenennen Nachdem Sie diese Schaltfläche im Projekt-Explorer in der UserForm markiert haben, wird nun noch eine weitere Eigenschaft über das Eigenschaften-Fenster eingerichtet. So setzen Sie beispielsweise die Eigenschaft Default auf den Wert True. Damit wird das Ereignismakro, das dieser Schaltfläche zugewiesen wird, standardmäßig ausgeführt, wenn die Taste Æ gedrückt wird. Benennen Sie unter der Eigenschaft Caption gleich noch die Bezeichnung COMMANDBUTTON1 in die etwas sprechendere Syntax cmdSuchen um und bestätigen diese Aktion mit der Taste Å. Bild 9.12: Die Farbpalette zum Einstellen des Hintergrunds 9.4.5 Hintergrundfarbe und Schrift festlegen Für das Listenfeld lässt sich die Größe der Schrift, die Schriftfarbe sowie die Farbe des Hintergrunds über das Eigenschaften-Fenster leicht anpassen. Stellen Sie gemäß Abbildung 9.10 zum Beispiel eine blaue Schrift auf hellgelben Hintergrund ein. Dazu markieren Sie das Listenfeld und klicken im Eigenschaften-Fenster bei der Eigenschaft ForeColor auf das Pfeilsymbol am rechten Rand des Eigenschaften-Fensters. Wechseln Sie dann auf die Registerkarte PALETTE. Wählen Sie dort die gewünschte Farbe aus. 289 9 Dialoge und Steuerelemente programmieren jetzt lerne ich Die Hintergrundfarbe für das Listenfeld lässt sich über die Eigenschaft BackColor einstellen. Soll die Schriftart geändert werden, ist dies über die Eigenschaft Font möglich. Dazu klicken Sie am rechten Rand dieser Eigenschaft auf das Symbol mit den drei Punkten und stellen im Dialog SCHRIFTART die gewünschte Schriftart, Schriftgröße oder den gewünschten Schriftschnitt ein. 9.4.6 Accelerator definieren Um Schaltflächen nicht nur mit der Maus zu bedienen, gibt es die Möglichkeit pro Schaltfläche über die Eigenschaft Accelerator festzulegen, welcher Buchstabe auf der Schaltfläche unterstrichen werden soll. Neben der Unterstreichung wird über diese Eigenschaft festgelegt, dass in Verbindung mit der Taste Ç der unterstrichene Buchstabe gedrückt werden kann, um das jeweilige Klick-Ereignismakro der Schaltfläche automatisch zu starten, ohne direkt mit der Maus auf die Schaltfläche zu klicken. In unserem Beispiel werden über die Tastenkombination Ç+E alle Textfelder der UserForm gelöscht. 9.4.7 Spezialeffekte einstellen Für die bessere Optik wurde in der Mitte der UserForm ein Rahmen eingefügt, in dem dann danach das Listenfeld integriert wurde, um dort die Suchergebnisse darzustellen. Über die Eigenschaft SpecialEffect wird festgelegt, wie das Rahmenfeld in der UserForm aussehen soll. Der Effekt 1 – fmSpecialEffectRaised bewirkt, dass das Rahmenfeld optisch hervorgehoben wird und einen 3D-Effekt erhält. 9.4.8 Steuerelemente anordnen Beim Einfügen der Textfelder sowie der Beschriftungsfelder kommt es leicht vor, dass die einzelnen Felder nicht genau untereinander angeordnet werden und unterschiedliche Größen haben. Um dies zu korrigieren und einheitlich anzupassen, markieren Sie die Felder, indem die Taste Ÿ gedrückt wird und dabei die Elemente nacheinander angeklickt werden, die angeglichen werden sollen. Danach können Sie in der Entwicklungsumgebung mit dem Menü FORMAT die Abstände zwischen den einzelnen Steuerelementen anpassen bzw. die einzelnen Elemente ausrichten. 290 UserForms erstellen und automatisieren 9.4.9 jetzt lerne ich Aktivierungsreihenfolge festlegen Die Aktivierungsreihenfolge der einzelnen Textfelder, also die Reihenfolge der Textfelder, die in der UserForm über die Taste Å angesteuert werden, kann leicht durcheinander geraten, gerade wenn Textfelder verschoben, gelöscht oder neue Textfelder hinzugefügt wurden. Die Ordnung wird wieder hergestellt, indem aus dem Menü ANSICHT der Befehl AKTIVIERREIHENFOLGE gewählt wird. Über die Schaltflächen NACH OBEN beziehungsweise NACH UNTEN wird die Aktivierungsreihenfolge festgelegt, mit der die einzelnen Textfelder nacheinander angesteuert werden. Bild 9.13: Die Aktivierungsreihenfolge anpassen Markieren Sie vor Aufruf des Dialogs AKTIVIERREIHENFOLGE eine Textbox. Damit wird sichergestellt, dass auch alle anderen Textboxen im Dialog AKTIVIERREIHENFOLGE angezeigt werden. Testen können Sie die Aktivierungsreihenfolge direkt im Anschluss, indem die UserForm in der Entwicklungsumgebung angeklickt und danach die Taste Í gedrückt wird. Mit der Taste Å springen Sie nun von Feld zu Feld. Ein Sprung rückwärts lässt sich über die Tastenkombination Á+Å durchführen. 9.4.10 1 Aufgaben beim Start der UserForm ausführen Bestimmte Aufgaben sollten bereits beim Starten der UserForm ausgeführt werden. Dazu wird das Ereignis UserForm_Initialize eingesetzt, das durch den Start der UserForm automatisch ausgeführt wird. Dies ist der ideale Zeitpunkt, um zum Beispiel die folgenden Aufgaben durchzuführen: 쐽 Festlegung des Dialogtitels: Der Titel für die UserForm lässt sich beispielsweise aus einem Zelleninhalt einer bestimmten Zelle ableiten. In diesem Beispiel wird der Inhalt der Zelle A1 der Tabelle DATEN als Überschrift für die UserForm verwendet. Durch Än- 291 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren derung des Textes, erfolgt automatisch auch eine Anpassung des Titels der UserForm. 쐽 Dynamische Zuweisung der Beschriftungsfelder: Die Texte der Beschriftungsfelder für die UserForm werden aus der Zeile 2 der Tabelle DATEN entnommen. Das bedeutet, dass sich Änderungen in dieser Überschriftenzeile flexibel vornehmen lassen. Ändern Sie beispielsweise einen Feldnamen in Zeile 2 der Tabelle, dann werden die Beschriftungsfelder in der UserForm automatisch mit angepasst. 쐽 Mehrspaltendefinition und Festlegung der Spaltenbreite des Listenfeldes: Um ein mehrspaltiges Listenfeld zu programmieren, muss vorher festgelegt werden, wie viele Spalten im Listenfeld verwendet werden sollen. Des Weiteren können Sie exakt festlegen, wie breit die einzelnen Spalten im Listenfeld werden sollen. 쐽 Festlegen des Textfeldes, das vorab aktiviert werden soll: Beim Aufruf einer UserForm können Sie den Mauszeiger schon vorab in einem bestimmten Textfeld positionieren. Im Beispiel ist dies die TEXTBOX1, weil aufgrund der dortigen Eingabe die anschließende Suche durchgeführt wird. Bild 9.14: Die Beschriftung der UserForm wird aus der Tabelle übernommen Alle diese Aufgaben werden über das Initialize-Ereignis der UserForm ausgeführt. Um dieses Ereignis zu definieren, klicken Sie in der Entwicklungsumgebung die UserForm an einer freien Stelle doppelt an und wählen danach im Code-Fenster aus der Kombinationsfeld- 292 UserForms erstellen und automatisieren jetzt lerne ich liste ganz rechts den Befehl Initialize. Ergänzen Sie danach den noch leeren Ereignisrahmen wie in Listing 9.7 gezeigt. Private Sub UserForm_Initialize() Dim tblDaten As Worksheet Set tblDaten = Worksheets("DATEN") 'Titel der UserForm festlegen UserForm3.Caption = Sheets("Daten").Cells(1, 1).Value 'Beschriftungen für die Bezeichnungsfelder aus Tabelle holen Listing 9.7: Standardaufgaben beim Starten der UserForm ausführen With UserForm3 .Label1.Caption = tblDaten.Cells(2, 1).Value .Label2.Caption = tblDaten.Cells(2, 2).Value .Label3.Caption = tblDaten.Cells(2, 3).Value .Label4.Caption = tblDaten.Cells(2, 4).Value .Label5.Caption = tblDaten.Cells(2, 5).Value .Label6.Caption = tblDaten.Cells(2, 6).Value .Label7.Caption = tblDaten.Cells(2, 7).Value .Label8.Caption = tblDaten.Cells(2, 8).Value .Label9.Caption = tblDaten.Cells(2, 9).Value .Label10.Caption = tblDaten.Cells(2, 10).Value .ListBox1.ColumnCount = 6 .ListBox1.ColumnWidths = "70;70;100;70;150;50" .TextBox1.SetFocus End With End Sub Zu Beginn des Listings wird eine Objektvariable vom Typ Worksheet deklariert. Danach folgt die Benennung der Tabelle über die Anweisung Set. Dadurch kann nun statt des vollen Namens der Tabelle der unter Set angegebene Name genutzt werden. Sie haben damit auch Zugriff auf alle Methoden und Eigenschaften, die für das WorksheetObjekt in Excel zur Verfügung stehen. Der Titel der UserForm wird über die Eigenschaft Caption festgelegt. Mithilfe der Auflistung Cells (1,1) wird ganz gezielt auf eine bestimmte Zelle zugegriffen. Der Inhalt dieser Zelle (A1) wird über die Eigenschaft Value ausgelesen und dann als Titel für die UserForm verwendet. Danach werden die Beschriftungen für die Bezeichnungsfelder aus der Zeile 2 der Tabelle DATEN entnommen und auf diese dynamische Art und Weise über die Eigenschaft Caption den jeweiligen Labels als Beschriftung zugewiesen. Über die Anweisung With wird, einerseits viel Schreibarbeit ein- 293 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren gespart und andererseits der Code übersichtlich strukturiert. Der Name der UserForm3 wurde dabei in der Anweisung With einmalig angegeben. Wenn nun innerhalb der With-Anweisung auf ein Steuerelement dieser UserForm zugegriffen werden soll, reicht als Platzhalter ein Punkt. Der Editor verwendet dann zur Laufzeit automatisch den vorher definierten Namen der UserForm. Mithilfe der Listbox-Eigenschaft ColumnCount wird die Anzahl der gewünschten Spalten im Listenfeld festgelegt. Über die Listbox-Eigenschaft ColumnsWidths wird, jeweils durch ein Semikolon getrennt, die Breite der Spalten in Punkten angegeben. Die Methode SetFocus bestimmt, welche Textbox in der UserForm nach dem Laden der Maske direkt angesteuert werden soll. Dort blinkt dann der Cursor und steht hiermit zur Eingabe bereit. 9.4.11 Die Suche von Datensätzen Um nun die SUCHEN-Schaltfläche mit der gewünschten Funktionalität zu versehen, wechseln Sie in die Entwicklungsumgebung. Per Doppelklick auf die SUCHEN-Schaltfläche öffnet sich ein Fenster mit einer entsprechenden Prozedur und dem Klick-Ereignis. Hinterlegen Sie innerhalb der Prozedur den Namen für ein Modul, das die eigentliche Funktionalität beinhaltet und dann durch einen Klick auf die Schaltfläche ausgeführt wird. Der Hauptgrund die Funktionalität in einem Modul auszulagern ist, dass dieses dadurch auch für andere Aufrufe allgemeingültig nutzbar ist. Listing 9.8: Private Sub cmdSuchen_Click() Die Datensuche umsetzen Suchen End Sub Sub Suchen() Dim lng As Long Dim i As Integer Application.ScreenUpdating = False With UserForm3 .ListBox1.Clear Sheets("DATEN").Activate i = 0 294 UserForms erstellen und automatisieren jetzt lerne ich For lng = 3 To ActiveSheet.UsedRange.Rows.Count If InStr(LCase(Cells(lng, 1).Value), _ LCase(.TextBox1.Value)) > 0 Then .ListBox1.AddItem Cells(lng, 1).Value .ListBox1.Column(1, i) = Cells(lng, 2).Value .ListBox1.Column(2, i) = Cells(lng, 3).Value .ListBox1.Column(3, i) = Cells(lng, 4).Value .ListBox1.Column(4, i) = Cells(lng, 5).Value .ListBox1.Column(5, i) = Cells(lng, 6).Row i = i + 1 Else End If Next lng End With Application.ScreenUpdating = True End Sub Deklarieren Sie zu Beginn zwei Variablen. Die Variable lng repräsentiert die Zeilen, die in der Tabelle DATEN abgearbeitet werden müssen. Da eine Excel-Tabelle insgesamt 65.536 Zeilen maximal umfassen kann und eine Integer-Variable zu klein für diese maximale Zeilenanzahl ist, wählen Sie hier den Datentyp Long. Über die Integer-Variable i werden die Sätze, die in das Listenfeld eingefügt werden, gesteuert. In diesem Fall reicht die Integer-Variable aus, da im Listenfeld nur die Ergebnisse der Suche angezeigt werden sollen. Damit die Suche schneller abläuft, wird zu Beginn des Makros die Bildschirmaktualisierung abgeschaltet, indem die Eigenschaft ScreenUpdating auf den Wert False gesetzt wird. Danach wechseln Sie über die Methode Activate einmalig in die Tabelle DATEN. Dieser Befehl stellt sicher, dass die Suche wirklich in der Tabelle DATEN durchgeführt wird. Setzen Sie die Integer-Variable auf den Wert 0. Damit kann später der erste Suchtreffer ins Listenfeld eingefügt werden. Merken Sie sich hier, dass die erste Zeile eines Listenfeldes über den Index 0 angesprochen wird. Zum Suchen wird eine Schleife verwendet, die ab Zeile 3 beginnt, da ab dort die relevanten Daten beginnen, die für die Suche einbezogen werden sollen. Den letzten Eintrag der Tabelle wird über die Anweisung ActiveSheet.UsedRange.Rows.Count ermittelt. Dabei werden die verwendeten Zeilen der aktiven Tabelle über die Methode Count 295 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren gezählt. Innerhalb der Schleife erfolgt eine Prüfung, ob der Inhalt des ersten Textfeldes der UserForm der Zelle aus Spalte A der Tabelle DATEN entspricht. Wenn ja, dann gibt die Funktion Instr einen Wert >1 zurück. Damit die Groß- und Kleinschreibung bei der Suche keine Rolle spielt, wandeln Sie den Suchbegriff sowie den Text aus der Zelle in Spalte A temporär in Kleinbuchstaben um, egal wie der Suchbegriff beziehungsweise die Texte in der Tabelle DATEN vorliegen. Über diesen Trick werden weder die Daten in der Tabelle noch die Daten im Textfeld geändert, sondern diese werden nur im Code selbst angeglichen. Konnte eine Übereinstimmung zwischen dem eingegebenen Suchbegriff und der Zelle aus Spalte A ermittelt werden, dann wenden Sie die Methode AddItem für das Listenfeld an, um die erste Spalte des Listenfeldes zu füllen. Über die Listbox-Eigenschaft Columns füllen sich danach die anderen Spalten des Listenfeldes, indem diese Spalten die Informationen aus der Tabelle DATEN mithilfe der Cells-Auflistung zugewiesen bekommen. In der letzten Spalte des Listenfeldes soll nun noch die Adresse der Zeile, in der die Übereinstimmung gefunden wurde, dargestellt werden. Damit ist es später leichter, die Fundstelle in der Tabelle DATEN über das Listenfeld direkt wieder zu finden, ohne erneut eine Suche durchzuführen. Mit der Schleife werden nun Zeile für Zeile die Inhalte überprüft, bis am Ende alle Suchergebnisse im Listenfeld dargestellt sind. 1 Wird übrigens kein Suchbegriff eingegeben und stattdessen gleich nach dem Laden der UserForm die Taste Æ gedrückt beziehungsweise das Symbol SUCHEN angeklickt, dann werden alle Datensätze der Tabelle im Listenfeld eingefügt. 9.4.12 Suchtreffer im Listenfeld anzeigen Nachdem die gefundenen Sätze (es können mehrere sein) im Listenfeld angezeigt wurden, soll der Anwender die Möglichkeit erhalten, einen gewünschten Satz zu markieren und ihn in den darüber liegenden Textfeldern angezeigt zu bekommen. Wird ein anderer Datensatz im Listenfeld markiert, soll sofort eine Aktualisierung der darüber liegenden Textfelder erfolgen. Um dieses Klick-Ereignis für das Listenfeld einzustellen, klicken Sie das Listenfeld doppelt an und ergänzen den leeren Ereignisrahmen wie in Listing 9.9 gezeigt. 296 UserForms erstellen und automatisieren Private Sub ListBox1_Click() Dim lng As Integer Sheets("DATEN").Activate jetzt lerne ich Listing 9.9: Die Ergebnisse der Suche im Listenfeld anzeigen lng = UserForm3.ListBox1.Column(5) With UserForm3 TextBox1.Value = Cells(lng, 1).Value TextBox2.Value = Cells(lng, 2).Value TextBox3.Value = Cells(lng, 3).Value TextBox4.Value = Cells(lng, 4).Value TextBox5.Value = Cells(lng, 5).Value TextBox6.Value = Cells(lng, 6).Value TextBox7.Value = Cells(lng, 7).Value TextBox8.Value = Cells(lng, 8).Value TextBox9.Value = Cells(lng, 9).Value TextBox10.Value = Cells(lng, 10).Value End With End Sub In Listing 9.9 wird zu Beginn die Variable lng deklariert. Danach wird aus dem Listenfeld, die bei der Suche ermittelte Zeilennummer in der Variablen lng gespeichert. Mit dieser Information ist klar, welcher Datensatz in der Tabelle angezeigt werden soll. Es werden den einzelnen Textfeldern die Inhalte der jeweiligen Zeile über die Auflistung Cells bekannt gegeben. Dabei wird im ersten Argument der Cells-Auflistung die ermittelte Zeilennummer übergeben. Im zweiten Argument, dem Argument für die Spalte der Tabelle, wird die Spaltennummer dargestellt. Dabei entspricht der Wert 1 der Spalte A, der Wert 2 der Spalte B und so weiter. 9.4.13 Die Neuanlage von Datensätzen Bei der Neuanlage eines Datensatzes kann zunächst so vorgegangen werden, dass zuerst ein ähnlicher Satz gesucht wird, der Satz dann im Listenfeld markiert und in den Textfeldern angepasst wird. Mit einem Klick auf die Schaltfläche DATENSATZ ERFASSEN wird der neue Satz dann am Ende der Datenliste angehängt. Um diese Funktion zu integrieren, klicken Sie in der Entwicklungsumgebung die Schaltfläche DATENSATZ ERFASSEN doppelt an und ergänzen den leeren Ereignisrahmen des Klick-Ereignisses wie in Listing 9.10 gezeigt. 297 jetzt lerne ich Listing 9.10: Einen neuen Datensatz anlegen 9 Dialoge und Steuerelemente programmieren Private Sub cmdNeu_Click() 'Datensatz anlegen Dim Dia As UserForm Dim lng As Long On Error Resume Next Set Dia = UserForm3 Worksheets("DATEN").Activate lng = Range("A65536").End(xlUp).Offset(1, 0).Row With Dia Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, 1).Value = "'" & .TextBox1.Value 2).Value = .TextBox2.Value 3).Value = .TextBox3.Value 4).Value = .TextBox4.Value 5).Value = .TextBox5.Value 6).Value = .TextBox6.Value 7).Value = .TextBox7.Value 8).Value = .TextBox8.Value 9).Value = .TextBox9.Value 10).Value = .TextBox10.Value End With End Sub Deklarieren Sie zu Beginn des Makros in Listing 9.10 eine Objektvariable vom Typ UserForm. Die Long-Variable lng wird auch bei diesem Makro wieder dazu verwendet, die Zeilen der Tabelle DATEN anzusprechen. Geben Sie danach über die Anweisung Set bekannt, wie die UserForm in diesem Makro heißen und wie sie angesprochen werden soll. Nun wird die erste freie Zelle in Spalte A ermittelt und diese Information in der Variablen lng gespeichert. Die erste freie Zelle aus Spalte A ergibt sich durch die zuletzt verwendete Zeile, die um den Wert 1 erhöht wird. Hinterlegen Sie danach die neue Zeile mit Inhalten, indem die Inhalte der Textboxen aus der UserForm direkt über die Cells-Auflistung in die Tabelle geschrieben werden. Da es sich beim ersten Textfeld in diesem Beispiel um eine Information handelt, die eins zu eins in die Tabelle geschrieben werden muss, sorgen Sie mithilfe eines Apostrophs dafür, dass führende Nullen beispielsweise nicht plötzlich nach dem Übertrag in die Tabelle verschwinden. In Excel werden üblicherweise führende Nullen unterdrückt. Im Falle einer Personalnummer hätte dies möglicherweise schwer wiegende Folgen. 298 UserForms erstellen und automatisieren 9.4.14 jetzt lerne ich Die Änderung von Datensätzen Auch bei der Änderung eines Datensatzes muss dieser vorher gefunden und im Listenfeld angezeigt sowie markiert werden. Danach erfolgt die Anpassung der einzelnen Textfelder. Mit einem Klick auf die Schaltfläche DATENSATZ ÄNDERN wird die Änderung in der Tabelle vorgenommen. Um diese Funktion einzufügen, klicken Sie in der Entwicklungsumgebung die Schaltfläche DATENSATZ ÄNDERN doppelt an und ergänzen den leeren Ereignisrahmen des Klick-Ereignisses wie in Listing 9.11 gezeigt. Private Sub cmdÄndern_Click() 'Datensatz ändern Dim lng As Long Dim i As Integer Listing 9.11: Einen Datensatz ändern On Error Resume Next lng = UserForm3.ListBox1.Column(5) Sheets("DATEN").Activate With UserForm3 Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, Cells(lng, 1).Value = .TextBox1.Value 2).Value = .TextBox2.Value 3).Value = .TextBox3.Value 4).Value = .TextBox4.Value 5).Value = .TextBox5.Value 6).Value = .TextBox6.Value 7).Value = .TextBox7.Value 8).Value = .TextBox8.Value 9).Value = .TextBox9.Value 10).Value = .TextBox10.Value 'Listbox aktualisieren i = .ListBox1.ListIndex .ListBox1.Column(0, i) .ListBox1.Column(1, i) .ListBox1.Column(2, i) .ListBox1.Column(3, i) .ListBox1.Column(4, i) = = = = = .TextBox1.Value .TextBox2.Value .TextBox3.Value .TextBox4.Value .TextBox5.Value End With End Sub 299 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren Zu Beginn werden die beiden bereits bekannten Variablen deklariert. Danach wird direkt aus dem Listenfeld die Zeilennummer entnommen, mit der die Zeilennummer des zu ändernden Datensatzes in der Tabelle ermittelt werden kann. Über die Cells-Auflistung lassen sich die in den Textfeldern der UserForm geänderten Daten direkt in die Tabelle zurück schreiben. Anschließend müssen die Änderungen natürlich auch im Listenfeld aktualisiert werden. Dazu werden die Inhalte der Textfelder an die entsprechenden Spalten des Listenfeldes übertragen. Über die Eigenschaft Columns können die einzelnen Spalten im Listenfeld direkt angesprochen und über die Eigenschaft Value befüllt werden. 9.4.15 Die Löschung von Datensätzen Auch beim Löschen von Datensätzen wird so vorgegangen, dass der zu löschende Satz zunächst gesucht und im Listenfeld markiert wird. Danach erfolgt die Löschung des Satzes über einen Klick auf die Schaltfläche DATENSATZ LÖSCHEN. Integrieren Sie diese Funktionalität, indem Sie in der Entwicklungsumgebung die Schaltfläche DATENSATZ LÖSCHEN doppelt anklicken und den leeren Ereignisrahmen des KlickEreignisses wie in Listing 9.12 gezeigt ergänzen. Listing 9.12: Private Sub cmdLöschen_Click() Einen Daten- 'Datensatz löschen satz löschen Dim lng As Long On Error Resume Next Sheets("DATEN").Activate lng = UserForm3.ListBox1.Column(5) Sheets("DATEN").Cells _ (UserForm3.ListBox1.Column(5), 1).EntireRow.Delete FelderLöschen End Sub Nachdem der gewünschte Datensatz im Listenfeld markiert wurde, kann auf die in Spalte 5 gespeicherte Zeilennummer des Datensatzes zugegriffen werden. Mithilfe dieser Zeilennummer wird der entsprechende Datensatz in der Tabelle DATEN direkt identifiziert. Über die Methode Delete, die für die komplette Zeile (EntireRow) gilt, wird im Anschluss daran die entsprechende Zeile komplett aus der Tabelle entfernt. 300 UserForms erstellen und automatisieren jetzt lerne ich Nach dieser Löschung der Zeile aus dem Datenbestand, wird das Listenfeld entleert sowie alle Textfelder initialisiert. Diese Aufgabe lässt sich mit dem Makro in Listing 9.13 lösen. Sub FelderLöschen() Dim tb As Object Listing 9.13: Textfelder initialisieren With UserForm3 .ListBox1.Clear For Each tb In .Controls If TypeName(tb) = "TextBox" Then tb.Text = "" Next tb End With End Sub Über die Methode Clear wird das angesprochene Listenfeld komplett geleert. Im Anschluss daran werden in einer For Each...Next-Schleife alle Steuerelemente der UserForm angesteuert und über die Funktion TypeName geprüft, ob es sich bei dem jeweiligen Steuerelement tatsächlich um ein Textfeld handelt. Beachten Sie dabei die Schreibweise von TextBox. Denn TextBox ist nicht gleich TEXTbox. Ein kleiner Unterschied in der Groß- und Kleinschreibung bewirkt, dass bei der zweiten Schreibweise überhaupt kein Textfeld identifiziert werden kann. Stimmt die Schreibweise, dann wird über die Eigenschaft Text der Inhalt der Textfelder mit einem Leerstring belegt. 9.4.16 UserForm starten Das Makro für den Aufruf der UserForm geben Sie in einem Standardmodul, beispielsweise MODUL1, wie folgt ein. Sub Dia() UserForm3.Show Listing 9.14: Die UserForm aufrufen End Sub Mithilfe der Methode Show wird die UserForm aufgerufen. Es besteht ab der Version Excel 2000 die Möglichkeit, eine UserForm gebunden oder ungebunden aufzurufen. Mit dieser Variante können Sie, selbst 301 jetzt lerne ich 9 Dialoge und Steuerelemente programmieren bei aufgerufener UserForm, im Hintergrund Zellen editieren und in andere Tabellen wechseln. Da dies bei diesem Beispiel aber eher nachteilig ist, wird bewusst auf diese Methode verzichtet. 9.4.17 UserForm schließen Den Code für das Schließen der UserForm, wird idealerweise genau hinter die Schaltfläche ABBRECHEN gelegt. Ergänzen Sie den leeren Klick-Ereignisrahmen durch die Anweisung Unload Me. Soll die UserForm ausschließlich über die Schaltfläche ABBRECHEN beendet werden, muss das Kreuzsymbol in der oberen, rechten Ecke sowie die Taste È deaktiviert werden. Hierfür benötigen wir das UserForm-Ereignis QueryClose: Listing 9.15: Private Sub UserForm_QueryClose _ Das Schließen (Cancel As Integer, CloseMode As Integer) einer UserForm ist nur If CloseMode = vbFormControlMenu Then MsgBox _ über die Schaltfläche "Schließen Sie die Userform über die Schaltfläche Abbrechen!", _ vbInformation möglich Cancel = True End If End Sub Über die Konstante vbFormControlMenu kann der Versuch verhindert werden, die UserForm über das Kreuzsymbol in der rechten, oberen Ecke zu schließen. Wenn das Ereignis zutrifft, dann wird eine Meldung auf dem Bildschirm ausgegeben und das Argument Cancel auf den Wert True gesetzt, um das Schließen der UserForm zu verhindern. 302 A abgeschaltet 295 Accelerator 290 Activate 295 ActiveCell 62 ActiveSheet 295 ActiveWorkbook 30, 202 Add 72, 162, 180, 198, 204 Add-In – erstellen 238 AddItem 296 Address 124, 219, 265 AdvancedFilter 150 Aktivierungsreihenfolge – anpassen 291 Aktuellen Wert – anzeigen 30 AllowDeletingColumns 174 AllowDeletingRows 174 AllowFiltering 175 AllowFormattingCells 174 AllowFormattingColumns 174 AllowFormattingRows 174 AllowInsertingHyperlinks 174 AllowInsertingRows 174 AllowSorting 175 AllowUsingPivotTables 175 Application 30 Arbeitsmappe – schließen 200 jetzt lerne ich Stichwortverzeichnis Arbeitsmappen – auslesen 83 – entfernen 206 – öffnen 189 – programmieren 189 – schließen 200 – speichern 196 – verknüpfen 202 – zusammenführen 204 Arbeitsmappen-Existenz – prüfen 228 Arbeitsmappen-Zustand – prüfen 229 Array 170 AtEndOfStream 58 Aufrufliste – anzeigen 30 – löschen 29 – zurücksetzen 29 Auskommentierung – aufheben 27 Ausschneiden – verboten 259 AutoFilter – bedienen 151 – einblenden 151 – entfernen 154 AutoFilterMode 152, 154 AutoFit 130 AutoLine 157 303 jetzt lerne ich Stichwortverzeichnis B BackColor 290 Bedingte Formatierung – erweitern 257 Bedingte Summierung – durchführen 120 Befehle – vervollständigen 29 BeforeDoubleClick 266 BeforeRightClick 266 Bereich – durchsuchen 123 – summieren 118 – umliegend 100 – verwendet 100 Bereiche – auswerten 118 – einrahmen 106 Bereichsprüfung – durchführen 256 Beschriftung – festlegen 289 Bezeichnung – festlegen 289 Bezüge – umsetzen 117 Bibliothek – auswählen 16 Bildschirmaktualisierung – ausschalten 82 Block – auskommentieren 26, 27 Bold 104, 145 Boolean 49 BorderAround 63 Borders 107 Buchstabe – unterstreichen 290 Buchstaben – entfernen 222 BuiltInDocumentProperties 208, 209 Byte 49 ByVal 56 C Calculate 266 Caption 289, 293 Cells 73, 172, 264, 293, 296, 300 Chart 183 ChartTitle 181 ChartType 179 ChDir 18, 196, 203 ChDrive 18, 196 304 Clear 117, 234, 276, 301 ClearComments 234 ClearContents 117 ClearFormats 117, 234 ClearOutline 157 Close 58, 200, 205 Code-Fenster – aufrufen 19 Codename 161 Codenamen – verwenden 161 ColorIndex 63, 75, 104, 105, 264 Column 134, 256 ColumnCount 294 Columns 129, 135, 296, 300 ColumnWidth 129 Comment 86 Comments 86 ConvertFormula 118 Copy 166, 183, 205 Count 121, 127, 146, 295 CountA 121, 138 CountIf 122 Currency 49 CurrentRegion 100, 204 CutCopyMode 259 D Date 18, 49, 125 DateCreated 221 Dateien – zählen 90 Dateityp – festlegen 85 DateLastAccessed 221 DateLastModified 221 Daten – bereinigen 107 – kennzeichnen 76 Datenmaske – aufrufen 283 Datensatz – ändern 299 – einfügen 297 – löschen 300 Datensätze – suchen 294 Datentipps – anzeigen 34 Datentyp – prüfen 65 DatePart 53 Datums-Format-Konstanten Stichwortverzeichnis – einsetzen 51 Datumssuche – durchführen 124 Debug.Print 86 Debuggen 29 Debuggen/Einzelschritt 31 Default 289 Default-Schaltfläche – festlegen 289 Definition – ActiveWorkbook 202 – Eigenschaften 17 – Ereignisse 17 – Methoden 17 – Objekte 17 – Sheets 160 – ThisWorkbook 202 – Worksheets 160 Delete 137, 138, 140, 146, 186, 235, 300 Description 99 Diagrammblatt – einfügen 179 Diagramme – exportieren 184 – löschen 186 – programmieren 179 Diagrammobjekt – einfügen 181 Diagrammobjekte – löschen 186 Diagrammquelle – angeben 180 Diagrammtyp – festlegen 179 Dir 55, 56, 90, 199, 205, 228, 236 – Konstanten 55 Direktfenster – aufrufen 21 – ausblenden 30 – einblenden 30 – füllen 86 DisplayAlerts 167, 186 DisplayGridLines 40 Do Until...Loop 87, 146 Do While...Loop 89 Dokumenteigenschaften – abfragen 219 – auslesen 206 – setzen 208 Doppelte Zeilen – löschen 139 Double 49 jetzt lerne ich Drucken – verhindern 248 E Editor-Einstellungen – ändern 33 Editorformat – festlegen 34 Eigenschaften – anzeigen 27 Eigenschaftenfenster – aufrufen 20 Einfügemarke – setzen 31 Einträge – zählen 121 Einzug – vergrößern 25, 34 – verkleinern 25 Elemente – auflisten 34 EnableEvents 256 End 74, 97, 132, 134 End With 63 EntireColumn 129 EntireRow 129, 300 Entwicklungsumgebung – anpassen 33 – aufrufen 16, 18 – einstellen 33 Entwurfsmodus – aktivieren 29 – deaktivieren 29 EOF 92 Ereignis – Workbook_BeforeClose 245 – Workbook_BeforePrint 248 – Workbook_BeforeSave 247 – Workbook_NewSheet 249 – Workbook_Open 242 – Worksheet_Activate 251 – Worksheet_BeforeDoubleClick 263 – Worksheet_BeforeRightClick 261 – Worksheet_Change 254 – Worksheet_SelectionChange 258 Ereignisse – einsetzen 241 Err 99, 170 Excel-Version – feststellen 68 Execute 85 Exit Function 224 305 jetzt lerne ich Stichwortverzeichnis Exit Sub 193, 256 Export 185 Extremwerte – kennzeichnen 104 F Fehler – abfangen 192 Fehlernummer – abfragen 170 Fehlerobjekt – abfragen 99 Fenster – teilen 28 – verankern 37 File Input-/Output – Konstanten 57 Filename 85 FileSearch 85, 203 FileSystemObject 58, 221 FileType 203 Find 123, 125 firstdayofweek 53 Font 103, 290 FontStyle 104 For Each...Next 79, 196 For Each_Next 109, 110 For...Next 71, 132 For_Next 134, 172 ForAppending 57 ForeColor 289 Format 198 FormatDateTime 51 Formatierungen – löschen 117 Formelcheck – durchführen 66 Formeln – ersetzen 115, 267 Formelzellen – markieren 98 FormulaLocal 144 Formular-Raster – definieren 35 ForReading 57 ForWriting 57 FoundFiles 85, 203 FullName 82, 217 Function 213 G GetAttr 56 GetOpenFileName 192 306 Gitternetzlinien – anzeigen 38 – ausblenden 38 Grafik – einfügen 288 H Haltemodus – aktivieren 29 – einstellen 29 Haltepunkt – ausschalten 26 – einschalten 26 – setzen 30 HasFormula 108, 109, 115, 118 HasTitle 181 Hidden 132, 135 Hintergrund – einstellen 289 – festlegen 289 I IF 64 Initialen – bilden 227 Initialize 292 InputBox 235, 277 Insert 142, 144 Instr 113, 296 Integer 49 Integrierte Dialoge – einsetzen 280 Interior 73 Intersect 262 Interval 53 IsArray 66 IsDate 66 IsEmpty 66, 77 IsError 66 IsNull 66 IsNumeric 66, 109, 137 IsObject 66 Italic 104 K kann 297 Kill 206 Kommentare – anfügen 26 – auslesen 85 – einfügen 114 Kommentierung – aufheben 26 Stichwortverzeichnis Kompilierungseinstellungen – festlegen 35 Konstanten – anzeigen 27 – einsetzen 50 Kontextmenü – deaktivieren 261 Kopf- und Fußzeilen – gestalten 81 L LBound 194 LCase 257 Leere Zeilen – löschen 135 Leerzeichen – finden 113 Left 68, 114 Len 224 Lesezeichen – setzen 28 – zurücksetzen 28 Like 196 LineStyle 63, 107 Linienart – bestimmen 63 LinkSources 195 Listenfeld – füllen 296 Long 49, 295 LookIn 85, 203 Löschfunktion – erstellen 233 Löschrückfrage – einholen 275 M Makro – aufzeichnen 38 – debuggen 31 – speichern 38 – zuweisen 75, 268 Makrorekorder – einsetzen 37 Markierung – abarbeiten 79 Mehrfachauswahl – vornehmen 94 Mehrwertsteuer – errechnen 278 MergeCells 102 Methoden – anzeigen 27 jetzt lerne ich Mid 110, 113, 224 Mod 146 Month 142 Move 167, 178 MsgBox 273 N Name 82, 103, 161, 172, 221 Namen – drehen 113 Neuanlage – unterbinden 249 NewSearch 85, 203 Notizen – auslesen 85 Now 271 Number 170 O Object 49 Objektkatalog – aufrufen 16 Objektvariable – definieren 298 – deklarieren 82, 106 Offset 80, 112 On Error 186, 192 OnTime 270 Open 192, 194, 195 OpenTextFile 58 OutLineFont 104 P PageSetup 82 Parameterinfo – anzeigen 27 Passwortabfrage – einholen 254 Paste 183 Path 221 pathname 59 Picture 288 PivotTableUpdate 266 Preiserhöhung – durchführen 80 PrintOut 168 Projekt – ausblenden 36 – kompilieren 36 Protect 173 Prozedur – ausführen 29 – starten 29 307 jetzt lerne ich Stichwortverzeichnis Q QueryClose 302 QuickInfo – anzeigen 27, 35 Quit 272 R Rahmenart – festlegen 107 Rahmenfarbe – festlegen 107 Range 109, 116, 129 ReadLine 58 ReDim 171 Rem 26 Row 261 RowHeight 129 Rows 127, 129, 132, 295 S SaveAs 197 Saved 198 Schaltfläche – einfügen 75 Schleifen – programmieren 70 Schriftart – festlegen 103 Schriftfarbe – abfragen 63 Schriftgestaltung – durchführen 102 Schriftgröße – festlegen 103 Schriftschnitt – festlegen 290 ScreenUpdating 295 ScrollArea – einstellen 244 SearchSubFolders 85, 203 Select 94, 171, 261 Select Case 67, 74, 111 Selection 80 Set 58, 94, 106, 123, 162, 298 SetDefaultChart 184 SetFocus 294 SetSourceData 180 Shadow 104 Sheets 160 SheetsInNewWorkbook 163 Shell 59, 60 Show 301 Single 49 308 Size 103, 221 Sort 149 Spalten – ausblenden 133 – einblenden 133 – formatieren 146 – gliedern 156 – programmieren 127 Spaltenbreite – einstellen 129 Spaltenprüfung – durchführen 255 Spaltenverschiebung – angeben 80 SpecialCells 95, 98 SpecialEffect 290 Spezialeffekte – einstellen 290 Standarddiagramm – festlegen 184 Standardmeldungen – ausschalten 167 – einschalten 167 Steuerelemente – anordnen 290 Strikethrough 104 String 49 Subscript 104 Suche – ausführen 85 Suchergebnisse – verwalten 85 Suchkriterien – zurücksetzen 85 SumIf 120 Superscript 104 Syntax – Do Until...Loop 87 – Do While_Loop 89 – For Each...Next 79 – For...Next 71 – IF 64 – Select Case 67 – With 62 Syntaxprüfung – durchführen 33 Systemdatum – abfragen 63 Systemkonstanten – einsetzen 51 T Tabelle Stichwortverzeichnis – einfügen 72 – Prüffunktionen 66 Tabellen – aktivieren 295 – ansprechen 160 – ausblenden 176 – drucken 168 – einblenden 176 – einfügen 162 – gruppieren 169 – kopieren 166 – programmieren 159 – schützen 172 – sortieren 177 – verknüpfen 171 – verlinken 171 – verschieben 166 Tabellen-Existenz – prüfen 230 Tabellenfunktionen – aufrufen 119 – einsetzen 119 Tabellennamen – ermitteln 78 Tabellenschutz – aufheben 173 – einstellen 252 – prüfen 232 Tab-Schrittweite – festlegen 34 Tastenkombination – zuweisen 268 Tastenkombinationen – einsetzen 32 Teilung – aufheben 28 Text 301 Textdatei – einlesen 91 TextToColumns 92 ThisWorkbook 202 Time 18 TimeValue 271 To 70 Top-Werte – ermitteln 155 Type 221 TypeName 301 U Überwachung – hinzufügen 22 Überwachungsausdruck jetzt lerne ich – entfernen 24 Überwachungsfenster – aufrufen 21 – ausblenden 30 – einblenden 30 UBound 194, 195 UCase 178, 256 Underline 104 Unikatsliste – erstellen 150 Union 106 Unload Me 302 Unprotect 173 Unterbrechen – bei Fehler 36 Unterverzeichnisse – durchsuchen 85 UsedRange 100, 127, 164, 295 UserForm – entwerfen 285 – schließen 302 – starten 301 UserForm_Initialize 291 V Value 63, 293, 300 Variablen – deklarieren 44 – öffentliche 47 – private 47 – statische 46 Variablendeklaration – erzwingen 33, 48 Variablentypen – einsetzen 48 Variant 49 vbAbort 276 vbAbortRetryIgnore 274 vbApplicationModal 275 vbCancel 276 vbCritical 274 vbDefaultButton1 275 vbDefaultButton2 275 vbDefaultButton3 275 vbDefaultButton4 275 vbDirectory 56 vbExclamation 274 vbFirstFourDays 54 vbFirstFullWeek 54 vbFirstJan1 54 vbFormControlMenu 302 vbFriday 54 vbGeneralDate 52 309 jetzt lerne ich Stichwortverzeichnis vbHidden 56 vbHide 59 vbIgnore 276 vbInformation 274 vbLongDate 52 vbLongTime 52 vbMaximizedFocus 59 vbMinimizedFocus 59 vbMinimizedNoFocus 59 vbMonday 53 vbMsgBoxHelpButton 275 vbNo 276 vbNormal 55 vbNormalFocus 59 vbNormalNoFocus 59 vbOK 276 vbOKCancel 274 vbOKOnly 274 vbQuestion 274 vbReadOnly 55 vbRetry 276 vbRetryCancel 274 vbSaturday 54 vbShortDate 52 vbShortTime 52 vbSunday 53 vbSystem 56 vbSystemModal 275 vbThursday 54 vbTuesday 53 vbUseSystem 53, 54 vbVolume 56 vbWednesday 53 vbYes 276 vbYesNo 274 vbYesNoCancel 274 Verfügbare Farben – einlesen 72 Vergleichsoperatoren – einsetzen 70 Version 68 Verwendete Spalten – ermitteln 128 Volatile 214 W Weekday 89, 134 WeekDayName 54 Werkzeugsammlung – einblenden 285 Werte – addieren 265 – zählen 121 310 WindowsStyle 59 With 61, 293 Wochenenden – kennzeichnen 88 Workbook 83, 165 Workbook_Activate 250 Workbook_AddinInstall 250 Workbook_AddinUninstall 250 Workbook_BeforePrint 250 Workbook_BeforeSave 250 Workbook_Deactivate 250 Workbook_NewSheet 250 Workbook_SheetActivate 250 Workbook_SheetBeforeDoubleClick 250 Workbook_SheetBeforeRightClick 250 Workbook_SheetCalculate 250 Workbook_SheetChange 251 Workbook_SheetDeactivate 251 Workbook_SheetFollowHyperlink 251 Workbook_SheetSelectionChange 251 Workbook_WindowActivate 251 Workbook_WindowDeactivate 251 Workbook_WindowResize 251 Workbooks 83, 166, 196 Worksheet 293 Worksheet_Activate 265 Worksheet_Calculate 266 Worksheet_Change 265 Worksheet_Deactivate 266 Worksheet_FollowHyperlink 266 WorkSheet_SelectionChange 266 WorksheetFunction 119 Worksheets 82, 160 X xlContinuous 107 xlDash 107 xlDashDot 107 xlDashDotDot 107 xlDot 107 xlDouble 107 xlLineStyleNone 107 xlSlantDashDot 107 Z Zahlenwerte – prüfen 69 Zeichen – entfernen 109 Stichwortverzeichnis jetzt lerne ich – extrahieren 114 Zeilen – abarbeiten 73 – ausblenden 131 – einblenden 131 – einfügen 141, 143 – formatieren 146 – gliedern 156 – programmieren 127 – schützen 260 – sortieren 148 Zeilenhöhe – einstellen 129 Zeilenverschiebung – angeben 80 Zeilenzeiger – programmieren 259 Zellen – formatieren 101 – markieren 93 – suchen 123 – überwachen 254 – zählen 215 Zelleninformationen – abfragen 218 Zelleninhalte – löschen 116 – manipulieren 107 Zellenkoordinaten – ausgeben 124 Zellenverbund – prüfen 102 Zugriffe – dokumentieren 245 311 Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen eBook-Zusatzdaten sind urheberrechtlich geschützt. Dieses eBook stellen wir lediglich als persönliche Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses eBooks oder zugehöriger Materialien und Informationen, einschliesslich • der Reproduktion, • der Weitergabe, • des Weitervertriebs, • der Platzierung im Internet, in Intranets, in Extranets, • der Veränderung, • des Weiterverkaufs • und der Veröffentlichung bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder Änderung des vom Verlag vergebenen Passwortschutzes ausdrücklich untersagt! Bei Fragen zu diesem Thema wenden Sie sich bitte an: [email protected] Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen. Hinweis Dieses und viele weitere eBooks können Sie rund um die Uhr und legal auf unserer Website http://www.informit.de herunterladen
© Copyright 2024