Das Excel-VBA Premium Codebook
 3827324718, 9783827324719 [PDF]

  • Commentary
  • no
  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

MELANIE BREDEN MICHAEL SCHWIMMER

Das Excel-VBA Codebook

2471_Excel-VBA.book Seite 1 Dienstag, 4. Dezember 2007 1:42 13

Das Excel-VBA Codebook

2471_Excel-VBA.book Seite 2 Dienstag, 4. Dezember 2007 1:42 13

2471_Excel-VBA.book Seite 3 Dienstag, 4. Dezember 2007 1:42 13

Melanie Breden, Michael Schwimmer

Das Excel-VBA Codebook

2471_Excel-VBA.book Seite 4 Dienstag, 4. Dezember 2007 1:42 13

Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über 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 Softwarebezeichnungen und weitere Stichworte und sonstige Angaben, die in diesem Buch verwendet werden, sind als eingetragene Marken geschützt. Da es nicht möglich ist, in allen Fällen zeitnah zu ermitteln, ob ein Markenschutz besteht, wird das ®-Symbol in diesem Buch nicht verwendet. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie – zum Schutz vor Verschmutzung – ist aus umweltverträglichem und recyclingfähigem PE-Material.

10 9 8 7 6 5 4 3 2 1 10 09 08 ISBN 978-3-8273-2471-9

© 2008 by Addison-Wesley Verlag,

ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Korrektorat: Simone Meißner Lektorat: Brigitte Bauer-Schiewek, [email protected] Fachlektorat: Michael Powell Herstellung: Elisabeth Prümm, [email protected] Satz: Kösel, Krugzell (www.KoeselBuch.de) Umschlaggestaltung: Marco Lindenbeck, webwo GmbH ([email protected]) Druck und Verarbeitung: Kösel, Krugzell (www.KoeselBuch.de) Printed in Germany

19

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

19 19 21 23 23 24 24 25 25 26 26 27 30 33 34 38 40 41 44 48 51 55 58 63

Einführung Namenskonventionen für Variablen und Objekte Variablendeklaration Vollständige Referenzierung Referenzierung und Objektvariable DoEvents Benutzerdefinierte Tabellenfunktionen Berechnungen ausschalten Bildschirmaktualisierung ausschalten Select vermeiden Durchlaufen von Auflistungen Farbindex RGB-Farben Farbanteile aus dem RGB-Wert extrahieren RGB-Dialog RGB in den ColorIndex umwandeln ColorIndex in RGB-Wert umwandeln Zufallszahlen erzeugen Sortieren mit Quicksort Mischen Beschreibung für eigene Funktionen Kommentare hinzufügen Kommentare als Bildcontainer Systeminformationen mit WMI

Allgemein

67

25 26 27 28 29 30 31 32 33 34 35 36 37 38

67 70 71 74 76 79 81 82 83 84 89 90 91 92

Formeln mit Zirkelbezügen berechnen VBA-Addition mit eigenem Zellenwert Zellenwert kumulieren Welche Zellen sind gesperrt? Gesperrte Zellen einfärben Formelzellen schützen Autofilter trotz Blattschutz Gliederung trotz Blattschutz Sortierung trotz Blattschutz Schutzoptionen auslesen Schutzoptionen einstellen Nicht gesperrte Zellen markieren und formatieren Nicht gesperrte Zellen formatieren (ab Excel 2002) Nicht gesperrte Zellen formatieren (alle Excel-Versionen)

Inhaltsverzeichnis

Einstieg

Inhaltsverzeichnis

17

Inhaltsverzeichnis

Teil I Rezepte

Inhaltsverzeichnis

15

Inhaltsverzeichnis

Vorwort

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 5 Dienstag, 4. Dezember 2007 1:42 13

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 6 Dienstag, 4. Dezember 2007 1:42 13

6

>> Inhaltsverzeichnis

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

Schutzoptionen ändern Benutzerberechtigte Bereiche hinzufügen Benutzerberechtigte Bereiche löschen Benutzerberechtigte Bereiche entschützen Benutzerberechtigte Bereiche schützen Benutzerberechtigte Bereiche – Passwort ändern Benutzerberechtigte Bereiche – Titel ändern Benutzerberechtigte Bereiche – Bereich ändern Ausgewählte Bereiche freigeben Löschen von Blättern verhindern Schreibgeschützte Datei ohne Speichern-Rückfrage schließen Entfernen des Schreibschutzes ignorieren Benutzerdefinierte Ansichten schützen Informationen des Betriebssystems auslesen Zwei Benutzernamen auslesen Persönliche Informationen aus Dateieigenschaften entfernen Mit Dokumentinspektor Daten und Informationen entfernen

93 96 98 99 100 101 102 105 109 113 115 117 118 122 124 125 128

Datum/Zeit

131

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

131 136 137 138 139 142 144 145 147 151 152 153 155 158 160 161 162 164 165 166 171 176 176 178 179 182 183 184 187 188

Datum und Zeitformat anpassen Wochentag des Geburtstages ermitteln Anzeigen des Systemdatums Schaltjahre bestimmen Dateizugriffe dokumentieren Bestandsveränderungen dokumentieren Vereinfachte Datumseingabe Uhrzeiten mit Autokorrektur Uhrzeiten ohne Doppelpunkt eingeben Aktuelles Datum finden Beliebiges Datum finden Arbeitsstunden in Meldungsfenster anzeigen Arbeitszeiten summieren Kalenderwoche nach DIN 1355 berechnen Anzahl Kalenderwochen bestimmen Feiertage mit Formeln berechnen Formeln in Tabelle anzeigen Funktion zur Formelanzeige Feiertage mit VBA berechnen Tageskalender erstellen 100-jähriger Kalender und Arbeitszeittabelle Lohn berechnen Minuszeiten berechnen Negative Zeitberechnung mit Funktion 1904-Datumswerte für Minuszeiten Anzeige des eingestellten Datumssystems in Statuszeile Eingabe von Minuszeiten 1904-Datumswerte mit VBA kopieren Datumswerte aus anderem Datumssystem importieren Datumsfunktionen bei 1904-Datumswerten

209 209 211 213 217 221 227 245 251 253 256 265 268 270 274

Einleitung Doppelte Datensätze mit Excel 2007 löschen Doppelte Datensätze vor Excel 2007 löschen Tabellenblätter vergleichen (Ausgabe in einem separaten Tabellenblatt) Mehrfach vorkommende Zellinhalte markieren Formeln eines Tabellenblattes ausgeben Bedingte Formatierung Autofilter Filtern nach Datum Filtern nach Farben Eine Pivot-Tabelle erzeugen Eine bestehende Pivot-Tabelle formatieren Pivot-Formatvorlagen Pivot-Verbindung zu fremder Datenbank mit ADO Pivot-Auswertung fremder Datenbanken über eine Datenverbindung

Steuerelemente

281

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

281 282 285 286 287 288 292 294 294 295 295 296 298 299 300 301 303 306 307 311 313

Einführung Formular-Steuerelemente Formular-Schaltfläche erstellen Formular-Schaltfläche löschen Makro an Formular-Schaltfläche zuweisen Steuerelement-Toolbox Steuerelemente erstellen Steuerelemente löschen Alle Steuerelemente löschen Steuerelemente eines Typs löschen Fokus der Steuerelemente verwalten Wert in Kontrollkästchen (CheckBox) ändern Kontrollkästchen (CheckBox)-Wert auslesen Wahrheitswert eines Kontrollkästchens übertragen Steuerelement-Eigenschaften ändern Mit Umschaltfläche Steuerelement steuern Gruppen von Steuerelementen erstellen Optionsfelder auswerten Optionsfelder und Kontrollkästchen zurücksetzen Arbeitsblätter über Listenfeld auswählen Listenfeld durch Mausbewegung füllen

Inhaltsverzeichnis

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

Inhaltsverzeichnis

209

Inhaltsverzeichnis

Auswertungen

Inhaltsverzeichnis

190 192 195 199 201 204 205 206 206

Inhaltsverzeichnis

Berechnung von Datumsdifferenzen Zeitdifferenzen mit VBA DateDiff VBA-Funktion für die DateDif-Tabellenfunktion Funktion um Lebensalter zu berechnen Stoppuhr mit Excel Excel kann warten Signaltöne erzeugen Töne bei aktuellem Datum ausgeben Meldung zeitbegrenzt anzeigen

Inhaltsverzeichnis

86 87 88 89 90 91 92 93 94

7

Inhaltsverzeichnis

>> Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 7 Dienstag, 4. Dezember 2007 1:42 13

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 8 Dienstag, 4. Dezember 2007 1:42 13

8

>> Inhaltsverzeichnis

131 132 133 134 135 136 137 138 139 140 141

Monate in Listenfeld auflisten Listenfeldeinträge bei Auswahl ändern Mehrspaltiges Listenfeld füllen Kombinationsfeld nach Auswahl füllen Passworteingabe durch Platzhalterzeichen ersetzen Textfeld-Werte umwandeln Zeilenumbruch in Textfeld (TextBox) per Code einfügen Mit Drehfeld (SpinButton) Monatswerte verändern Mit Bildlaufleiste (ScrollBar) zu Datum wechseln Steuerelemente mit Tastatur aktivieren Tabellenblatt-Zugriffe mit Steuerelementen verwalten

314 316 318 321 323 325 327 328 331 334 337

Befehlsleisten

347

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

347 349 351 353 357 358 361 364 366 367 369 372 373 374 376 379 385 387 390 392 397 401 403 411 416 419 421 426

Einführung Integrierte Befehlsleisten ermitteln Kontextmenüs ermitteln Kontextmenüs deaktivieren Kontextmenüs zurücksetzen Menüs und Steuerelemente ermitteln Benutzerdefinierte Menübefehle hinzufügen Benutzerdefinierte Menübefehle löschen Gruppe Menübefehle löschen Schaltflächen in integrierten Symbolleisten Benutzerdefinierte Symbolleisten erstellen Benutzerdefinierte Symbolleisten löschen Gruppen in Add-Ins Registerkarte löschen Befehlsleistendatei finden Kontextmenü mit Datum und Zeit erstellen DropDown-Menü erzeugen Steuerelement aufrufen Steuerelemente kopieren Original Symbolleisten aus Excel 2003 erstellen Kontextmenü als Symbolleiste verwenden Menüpunkte mit Hyperlinks Schaltfläche einem Menü hinzufügen Blattregisterfarben über DropDownfeld auswählen Zellenschutz im Kontextmenü anzeigen und ändern Kontextmenü durch Kaskaden-Menü ersetzen Welches Kontextmenü wurde aufgerufen? Symbole über Kontextmenü einfügen Alle FaceID's auf einen Blick

Objekte

427

170 171 172 173 174 175

427 427 430 435 440 446

Einführung Einen Bereich in eine Grafik umwandeln Bereich als Grafik exportieren Bereich als Hintergrund eines Steuerelementes Iconpicker Karte

479 486 498 503 508 512 517 520 535 537 541 551 558

Einführung Diagramm programmgesteuert erzeugen Diagrammtitel Legende Datentabelle formatieren Datenreihen Datenpunkte Achsen, Gitternetzlinien Marker Datenbeschriftungen Trendlinien Hintergrund Diagramm- und Zeichnungsfläche Wände, Böden und Perspektive von 3-D-Diagrammen

Ereignisse

565

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

565 567 568 573 576 578 579 590 591 595 601 602 605 605 608 609 609 611 612 614 616 618 622 625 627 628 629

Allgemeine Prozeduren Ereignis-Prozeduren Workbook-Ereignisse Aktuelles Monatsblatt anzeigen Ereignisse ignorieren Ereignisse aus- und einschalten Excel-Datei ohne Makros unbrauchbar Datei nur mit Makrounterstützung anzeigen Registerreiter neu nummerieren Neues Blatt beschriften Diagramm nach Ansicht löschen Tabellenblatt-Ereignisse (Worksheet) Zellenkontextmenü verhindern Auf den Spuren von Target Bereichsauswahl verhindern Cursorbewegungen protokollieren Markierten Zellenbereich vergrößern Cursor in eine Eieruhr verwandeln Formeln in Kommentaren anzeigen Bei Blattwechsel Monatsspalten anzeigen Blattschutz ohne Blattschutz Ereignisbedingte Formatierung Ereignisbedingte Formatierung durch Formelbezüge Makro aus Hyperlink aufrufen Adresse zu Hyperlink ermitteln Autoprozeduren Datei öffnen und Auto_Open-Prozedur aufrufen

Inhaltsverzeichnis

181 182 183 184 185 186 187 188 189 190 191 192 193

Inhaltsverzeichnis

479

Inhaltsverzeichnis

Diagramme

Inhaltsverzeichnis

455 460 466 469 471

Inhaltsverzeichnis

Koordinaten umrechnen Assistent MSAgent Animierte Grafik Video-/Audiodateien abspielen Control-Icons extrahieren

Inhaltsverzeichnis

176 177 178 179 180

9

Inhaltsverzeichnis

>> Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 9 Dienstag, 4. Dezember 2007 1:42 13

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 10 Dienstag, 4. Dezember 2007 1:42 13

10

>> Inhaltsverzeichnis

221 222 223 224 225 226 227 228 229 230 231 232

Datei schließen und Auto_Close-Prozedur aufrufen Begrüßung nach der Tageszeit Zoomfaktor über Bildschirmauflösung einstellen Zoomfaktor mit Workbook_Open Zeitgesteuerte Makros Uhrzeit in Statuszeile zeitbegrenzt anzeigen Uhrzeit in Statuszeile steuern Uhrzeitmeldung nach Zeitplan ausführen Tastenkombinationen erstellen Navigation mit Fadenkreuz Makro rückgängig machen Befehl »Wiederholen« aktivieren

630 631 632 634 636 638 640 642 643 647 651 653

UserForm

655

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254

655 659 662 663 667 668 671 674 678 687 696 701 706 710 713 717 719 724 728 731 732 735

Einstieg UserForm anzeigen UserForm-Ereignisse Befehlsschaltflächen (CommandButton) Bezeichnungsfeld (Label) Textfelder (Textbox) Rahmen (Frame) Einspaltige Listenfelder (ListBox) Mehrspaltige Listenfelder (ListBox) Kombinationsfelder (ComboBox) Optionsfelder (OptionButton) Kontrollkästchen (CheckBox) Referenz (RefEdit) Register (TabStrip) Multiseiten (Multipage) Anzeigesteuerelement (Image) Bildlaufleiste (Scrollbar) Drehfeld (SpinButton) Umschaltfeld (ToggleButton) Kalendersteuerelement (Calendar) Einer UserForm Min, Max, Resize beibringen Steuerelemente dynamisch anlegen

Web/Mail

741

255 256 257 258 259 260 261 262 263 264 265

741 741 743 750 758 762 765 768 771 773 775

Einführung Dialog zum Versenden Arbeitsblätter und Bereiche versenden Eine E-Mail mit Dateianhang versenden Interne Hyperlinks Hyperlink auf Datei Hyperlink auf Webseite Hyperlink auf E-Mail-Adresse Liste aller Hyperlinks XML-Kalkulationstabellen 2003 XML-Datei mit Bordmitteln erzeugen

815 815 816 817 818 819 821 823 825 828 831 836 837 839 841 847 849 851 857 858 860 862 864 868 872 876 879 881

Einführung Explorer mit bestimmtem Anfangspfad starten VBA-Befehle Dateisystem Verzeichnis anlegen Verzeichnis mit der API anlegen Datei anlegen Dateien öffnen Dateien löschen Verzeichnis löschen Datei oder Verzeichnis kopieren/verschieben Dateiliste FileSearch-Objekt OLE FileSystemObject Mit dem FSO eine Dateiliste erzeugen Laufwerksliste Dateizeiten auslesen Dateizeiten ändern GetAttr/SetAttr Outlook Verfügbare Ordner aus Outlook auslesen Eigenschaftsnamen eines Outlook-Elementes auslesen Alle Eigenschaften aller Elemente eines Ordners ausgeben Datenbankabfrage Query ACCDB Datenbanken mit ADO auslesen MDB Datenbank erzeugen CSV-Dateien erzeugen CSV mit ADO

VBE-Programmierung

885

299 300 301 302 303 304 305 306 307 308 309 310

885 887 889 890 891 892 893 894 897 897 899 900

VBE-Entwicklungsumgebung Verweise auslesen Verweise aktivieren Verweise deaktivieren VBA-Projekteigenschaften auslesen Projektname auslesen und ändern Ist Projekt-Ansicht gesperrt? Mit VBA Projektschutz aufheben Entwicklungsumgebung ein- und ausblenden Codemodul-Fenster auflisten Codemodul-Fenster anzeigen Text in Direktbereich löschen

Inhaltsverzeichnis

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298

Inhaltsverzeichnis

815

Inhaltsverzeichnis

Extern

Inhaltsverzeichnis

780 783 786 793 800

Inhaltsverzeichnis

XML-Datei mit DOM erzeugen Internetbrowser einbinden Eine Webabfrage (Query) erstellen Eine Webabfrage mit dem Internetbrowser Smart Tags erzeugen

Inhaltsverzeichnis

266 267 268 269 270

11

Inhaltsverzeichnis

>> Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 11 Dienstag, 4. Dezember 2007 1:42 13

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 12 Dienstag, 4. Dezember 2007 1:42 13

12

>> Inhaltsverzeichnis

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340

Alle Projekte auslesen Module und Prozeduren des aktiven VBAProjektes auslesen Code einer Prozedur auslesen Blatt- und Codenamen einer Tabelle auslesen Codenamen einer Tabelle ändern Codenamen nach Tabellennamen benennen Modul erstellen Modul mit Namensvergabe erstellen Modul löschen Vorhandene Module überprüfen Vorhandene Prozeduren überprüfen Prozedur in ein Modul schreiben und aufrufen Prozedur in eigenes Modul schreiben und aufrufen Ereignisprozedur erstellen Prozeduren löschen Code eines Moduls löschen Menü in VBE-Menüleiste erstellen Ereignisprozeduren für integrierte Ereignisse erstellen Meldungen über alle Zellpositions-Änderungen Add-Ins Add-Ins hinzufügen und installieren Add-In von Speichermedium auf Festplatte kopieren Add-Ins auflisten Add-Ins über Explorer installieren Add-In deinstallieren und aus Liste entfernen Titel und Beschreibung einem Add-In hinzufügen Code-Änderungen in Add-In speichern Funktionen in Add-In einbinden Makros aus Add-In aufrufen Makros aus Add-In über Schaltfläche aufrufen

Specials

965

341 342 343 344 345 346 347 348 349 350 351 352 353

965 965 973 985 994 1000 1008 1011 1014 1019 1026 1028 1034

Einführung Ein Zusammensetzspiel (Puzzle) Sudokufelder erzeugen Sudoku lösen Einen Lottoschein ausfüllen (Array) Routenplaner mit Virtual Earth Zahlen in Wörter umwandeln Schriftarten auflisten Sprachtrainer Tabellenblatt-Übersicht in Menüleiste Präsentation in Excel Menüeinträge mit Fenster-Optionen Eine Summe in Einzelbeträge aufteilen

RibbonX Inhaltsverzeichnis

901 903 906 908 910 914 914 916 916 917 918 919 920 921 924 925 925 931 938 941 944 946 947 948 951 953 954 955 957 958

354 355

Einführung Ribbon aus- und einblenden (VBA)

1041 1041 1046

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

Die englischen Funktionsnamen der deutschen Tabellenblattfunktionen MsgBox-Konstanten Application.InputBox-Methode Vergleichs-Operatoren Arithmetische Operatoren Verkettungs-Operatoren SpecialCells-Methode RGB-Funktion ColorIndex-Eigenschaft ColorFormat-Objekt (Fülleffekte) FormatCondition-Objekt (Bedingte Formatierung) Formatcodes für Kopf- und Fußzeilen Datentypen Typ-Umwandlungsfunktionen Benutzerdefinierte Datums- und Zeitformate (Format-Funktion) DateDiff-Funktion OnKey-Methode Attributes-Eigenschaft Verschiedene Konstanten ClipboardFormats-Eigenschaft Spezifikationen und Einschränkungen von Excel Übersicht über Ribbon-XML-Elemente und Attribute

Stichwortverzeichnis

1103 1103 1106 1108 1109 1110 1112 1113 1114 1115 1115 1116 1118 1120 1121 1122 1124 1126 1127 1128 1128 1129 1133

1143

Inhaltsverzeichnis Inhaltsverzeichnis Inhaltsverzeichnis

Anhang

1101

Inhaltsverzeichnis

Teil II Anhang

1047 1049 1051 1053 1053 1055 1056 1057 1060 1062 1063 1065 1068 1071 1077 1084 1088 1090 1092 1094

Inhaltsverzeichnis

Einen Befehl aus Multifunktionsleiste aufrufen Excel-Benutzeroberfläche ausblenden Eine Registerkarte ausblenden Eine Gruppe ausblenden Eine kontextbezogene Registerkarte ausblenden Gruppe einer Kontext-Registerkarte ausblenden Einen integrierten Befehl deaktivieren Zuweisung eines Befehls an integrierte Schaltfläche Eine Registerkarte erstellen Eine integrierte Gruppe erstellen Eine integrierte Gruppe anpassen Anpassen des Office-Menüs Verwendung von integrierten und eigenen Symbolen Makros mit Callback-Handler aufrufen Symbole zur Laufzeit ändern Eine Schaltfläche auf der Schnellzugriffleiste einfügen Registerkarten zur Laufzeit aus- und einblenden Ein statisches Kombinationsfeld erstellen Ein dynamisches Kombinationsfeld erstellen Tabellenblätter durch DropDown wechseln

Inhaltsverzeichnis

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

13

Inhaltsverzeichnis

>> Inhaltsverzeichnis

Inhaltsverzeichnis

2471_Excel-VBA.book Seite 13 Dienstag, 4. Dezember 2007 1:42 13

2471_Excel-VBA.book Seite 14 Dienstag, 4. Dezember 2007 1:42 13

2471_Excel-VBA.book Seite 15 Dienstag, 4. Dezember 2007 1:42 13

Vorwort Mit der Einführung von Office 2007 hat sich Grundlegendes am Aussehen und im Umgang mit Excel verändert, es fehlen beispielsweise die gewohnten Menüs, stattdessen gibt es die RIBBON-Leiste. Auch sonst ist alles andere etwas bunter, intuitiver und userfreundlicher geworden. Microsoft hat zudem vielen Anwenderwünschen entsprochen und beispielsweise die BEDINGTE FORMATIERUNG erheblich ausgeweitet. Auch der Autofilter ist aufgebohrt worden, man kann nun zum Beispiel auch nach Formaten filtern, sogar nach solchen, die über die BEDINGTE FORMATIERUNG gesetzt worden sind. Die Beschränkungen der bisher verwendeten BIFF-Dateistruktur (Binary Interchange File Format), wie zum Beispiel die auf 256 Spalten und 65536 Zeilen, oder die begrenzte Anzahl der Farben gelten nun nicht mehr. So können Sie jetzt ohne weiteres alle Tage eines Jahres nebeneinander auf einem Tabellenblatt darstellen und große Datenmengen mit mehr als 65536 Datensätzen importieren. Man kann auch beliebige RGB-Farben in Zellen benutzen und dauerhaft speichern. Die Dateien, die von Excel 2007 erzeugt werden, sind nun in Wirklichkeit ZIPArchive. In diesem komprimierten, Ordner befinden sich eine Reihe von XMLDateien, die als Datenspeicher verwendet werden und die man sich ohne Probleme mit einem Editor anschauen kann. Lediglich einige Daten, wie beispielsweise der VBA-Code, stecken in einer nicht im Klartext lesbaren binären Datei. Das kann man sich zunutze machen, um beispielsweise neue Registerkarten mit eigenen Symbolgruppen und Steuerelementen zu erzeugen. Über die Manipulation dieser XMLDateien ist es nun auch möglich, die Funktionalität vorhandener Symbole außer Kraft zu setzen und einen Klick darauf auf selbst definierte Prozeduren umzuleiten. Wenn auch im Vorfeld immer wieder Gerüchte aufgekommen sind, dass VBA mit Office 2007 stirbt und Dotnet triumphalen Einzug hält, hat sich im Bereich der Programmierung aber nicht allzu viel getan. VBA gibt es immer noch und selbst die Syntax ist vollkommen gleich geblieben. Für Umsteiger von früheren Versionen ist das sicherlich ein nicht zu unterschätzender Vorteil. Für Profis mit Dotnet-Ambitionen bleiben immer noch die VISUAL STUDIO TOOLS FÜR OFFICE (VSTO). Auch in der integrierten VBA-Entwicklungsumgebung findet sich der gemeine VBA-Programmierer sofort zurecht, Microsoft hat konsequenterweise den Editor genauso gelassen, wie er war. Einige Objekte, wie beispielsweise das FileSearch-Objekt, sind aber jetzt nicht mehr vorhanden, dafür sind neue Excel-Objekte hinzugekommen. Besonders zum Formatieren stehen neue Objektklassen wie die ChartFormat-Klasse zur Verfügung, welche Formate zulässt, die unter den Vorgängerversionen noch gar nicht möglich waren, trotzdem können die meisten traditionellen Eigenschaften weiterbenutzt werden. All dem haben wir in dieser Neuauflage Rechnung getragen und dieses Buch vollkommen neu überarbeitet. Alle Rezepte des sehr erfolgreichen Vorgängers wurden

2471_Excel-VBA.book Seite 16 Dienstag, 4. Dezember 2007 1:42 13

16

>> Vorwort

umfassend getestet, den neuen Gegebenheiten angepasst, Überholtes über Bord geschmissen und neues hinzugefügt. Man muss dazu auch anmerken, dass in der neuen Auflage wiederum ein Autorenwechsel stattgefunden hat, zum Teil wurden deshalb auch die Prioritäten anders gesetzt. Man möchte als neuer Autor zwar gerne alle bewährten Rezepte übernehmen, aber wir haben den neuen Möglichkeiten von Excel 2007 konsequent Rechnung getragen und daher eine gründliche Überarbeitung vorgezogen. Als Zielgruppe für dieses Buch wurde hauptsächlich der fortgeschrittene bis hin zum Profi-Anwender von Excel 2007 gewählt. Das Buch ist kein reines Lehrbuch, sondern eine Art Lexikon. Es soll Ihnen als Nachschlagewerk dienen. Sie finden hier eine sehr umfangreiche Auswahl an Code-Elementen, die sich nach Belieben zusammenfügen lassen. Wir haben zudem Wert darauf gelegt, neben umfangreichen Codes auch kürzere Beispiele zu erstellen, so dass es auch einem Einsteiger möglich ist, sich besser mit dieser Programmiersprache vertraut zu machen. Für die erfahrenen VBA-Anwender sind viele komplexe Beispiele enthalten.

2471_Excel-VBA.book Seite 17 Dienstag, 4. Dezember 2007 1:42 13

Einstieg Allgemein

Datum/Zeit

Teil I Rezepte

Auswertungen

Steuerelemente Befehlsleisten

Objekte Diagramme

Ereignisse UserForm

Web/Mail Extern

VBE-Programmierung Specials

RibbonX

2471_Excel-VBA.book Seite 18 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

2471_Excel-VBA.book Seite 19 Dienstag, 4. Dezember 2007 1:42 13

Einstieg In diesem Kapitel werden zuerst allgemeine VBA-Themen behandelt, wie etwa Namenskonventionen oder die Deklaration von Variablen. Danach geht es weiter mit der Optimierung von VBA-Code, anschließend werden einige Rezepte vorgestellt, die etwas mit den in Excel verwendeten Farben zu tun haben. Weiterhin wird gezeigt, wie Sie Zufallszahlen erzeugen, Zahlen sortieren und auch wieder mischen können. Ein weiteres Rezept beschreibt, wie Sie für benutzerdefinierte Funktionen eine Beschreibung der Funktion selbst und deren Parameter hinbekommen. Kommentare sind ein weiteres Thema, damit ist es sogar möglich, eine kleine Bilderschau zu realisieren.

Einstieg

Einführung

Einstieg

1

Beim Programmieren sollte man eine Notation verwenden, mit der man auf Anhieb den Daten- bzw. den Objekttyp und die Gültigkeit von Variablen erkennen kann. Um das zu erreichen, werden Präfixe, also Vorsilben benutzt. Nachfolgend ein Vorschlag, welche Präfixe man verwenden sollte. Diese Liste ist zwar kein absolutes Muss, die Namenskonventionen haben sich aber im Laufe der Zeit international eingebürgert. Das Präfix für die Gültigkeit oder der Sichtbarkeit (Tabelle 1) einer Variablen kommt an die erste Position. Gültigkeit

Präfix

Global

g

Modulweit

m

Prozedurweit

Kein Präfix

Einstieg

Namenskonventionen für Variablen und Objekte

Einstieg

2

Einstieg

Benötigt man Systeminformationen, kann man das letzte Rezept in diesem Abschnitt verwenden. Mit Hilfe von WMI lassen sich nahezu alle Informationen über die verwendete Hardware auslesen.

Einstieg

Auf die Gültigkeit folgt die Information, ob es sich bei der Variablen um ein Array handelt. Ist das der Fall, wird der Buchstabe a benutzt. Anschließend folgt die Kennung des Datentyps (Tabelle 2).

Einstieg

Tabelle 1: Präfixe der Gültigkeit

2471_Excel-VBA.book Seite 20 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

Einstieg

20

>> Namenskonventionen für Variablen und Objekte

Variablentyp

Präfix

Boolean

bln

Byte

byt

Collection

col

Currency

cur

Date

dtm

Double

dbl

Error

err

Integer

int

Long

lng

Object

obj

Single

sng

String

str

Benutzerdefinierter Typ

udt

Variant

var

Tabelle 2: Präfixe der Datentypen

Einstieg

Einstieg

Einstieg

Objektvariablen und Steuerelemente sollte man mit Präfixen versehen, welche die Art des Objekts (Tabelle 3) beschreiben. Objekttyp

Präfix

Object

obj

Klasse

cls

Modul

mdl

ADO Data

ado

Befehlsschaltfläche (CommandButton)

cmd

Bezeichnungsfeld (Label)

lbl

Bild (Picture)

pic

Bildlaufleiste Horizontal (HScrollBar)

hsb

Bildlaufleiste Vertikal (VScrollBar)

vsb

Diagramm (Graph)

gra

Drehfeld (SpinButton)

spn

Figur (Shape)

shp

Formular

frm

Kombinationsfeld, Dropdown-Listenfeld (ComboBox)

cbo

Einstieg

Tabelle 3: Präfixe der Objekte und Steuerelemente

2471_Excel-VBA.book Seite 21 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg Präfix

Kontrollkästchen (CheckBox)

chk

Listenfeld (ListBox)

lsb

Optionsfeld

opt

Rahmen (Frame)

fra

Register (TabStrip)

tab

Textfeld (TextBox)

txt

Einstieg

Objekttyp

Einstieg

21

Die Präfixe werden generell kleingeschrieben, der erste Buchstabe danach groß. Bei zusammengesetzten Namen sollte auch der erste Buchstabe des zweiten Wortes großgeschrieben werden.

Einstieg

Tabelle 3: Präfixe der Objekte und Steuerelemente (Forts.)

3

Variablendeklaration

Einstieg

Ein mappenweit (g) gültiges Array (a) vom Datentyp Long (lng), welches verschiedene Zeilennummern aufnehmen soll, bekäme nach dieser Notation den Namen galngVerschiedeneZeilennummern.

Glücklicherweise ist in Excel 2007, anders als in den Vorgängerversionen, standardmäßig vorgegeben, dass eine Variablendeklaration erforderlich ist. Das ist daran zu erkennen, dass in jedem neu hinzugefügten Modul an erster Stelle die zwei Schlüsselwörter Option Explicit stehen, die man auch tunlichst nicht löschen sollte. Verwendet man in diesem Modul eine nicht deklarierte Variable, wird eine Fehlermeldung ausgegeben.

Einstieg

Falsch eingegebene Variablennamen verhalten sich beim Programmieren und während der Laufzeit unauffällig. Erst wenn man den Wert einer Variablen weiterverarbeiten will und stattdessen den Wert einer neuen, leeren Variablen benutzt, weil es beispielsweise beim Eingeben des Namens zu einem Buchstabendreher gekommen ist, bekommt man ein fehlerhaftes Ergebnis. Ein Laufzeitfehler, der auf einen falschen Namen hinweisen würde, wird in solch einem Fall leider nicht ausgelöst.

Einstieg

Der Typ einer Variablen, die man ohne eine Deklaration erzeugt hat, ist generell ein Variant. Dieser Datentyp kann nahezu alle Daten mit Ausnahme von benutzerdefinierten Typen und Strings fester Länge aufnehmen. Diese Flexibilität erfordert aber auch einen größeren Verwaltungsaufwand, der sich durch einen höheren Speicherbedarf und eine geringere Verarbeitungsgeschwindigkeit negativ bemerkbar macht.

Einstieg

VBA lässt grundsätzlich die Freiheit, Variablen zu deklarieren oder diese einfach durch die Benutzung eines beliebigen Variablennamens zu erzeugen.

Einstieg

Eingestellt wird das unter dem Menüpunkt der Entwicklungsumgebung von Excel (VBE) EXTRAS | OPTIONEN | EDITOR, indem unter dem Menüpunkt VARIABLENDEKLARATION ERFORDERLICH (Abbildung 1) ein Haken gesetzt wird.

2471_Excel-VBA.book Seite 22 Dienstag, 4. Dezember 2007 1:42 13

>> Variablendeklaration

Einstieg

Einstieg

Einstieg

Einstieg

22

Einstieg

Abbildung 1: Variablendeklaration erforderlich

Bei der Deklaration von Variablen sollte man immer auch den Datentyp mit angeben. Ohne diese Angabe hat man es automatisch mit dem Datentyp Variant zu tun, wie die folgende Codezeile zeigt:

Einstieg

Dim varVariable1, strVariable2 As String

Anders als bei anderen Programmiersprachen, wie beispielsweise bei VB.Net, wird bei dieser Deklaration nur strVariable2 als String deklariert, die andere ist automatisch eine Variantvariable, weil bei ihr der As-Abschnitt fehlt. Nachfolgend die korrekte Deklaration: Dim varVariable1 As String Dim varVariable2 As String

Einstieg

Einstieg

Nun die gleichwertige Deklaration in einer Codezeile: Dim varVariable1 As String, varVariable2 As String

2471_Excel-VBA.book Seite 23 Dienstag, 4. Dezember 2007 1:42 13

4

23

Vollständige Referenzierung

Einstieg

>> Einstieg

Immer wieder sieht man Codezeilen wie die folgende:

Sie sollten sich angewöhnen, vollständig zu referenzieren. Das heißt, man gibt auch das übergeordnete Objekt mit an. Handelt es sich dabei um das Arbeitsblatt mit dem Namen »Tabelle1«, müsste der Code folgendermaßen angepasst werden.

Einstieg

Damit soll die Hintergrundfarbe der Zelle A1 gesetzt werden. Das Problem dabei ist, dass nicht mit angegeben wurde, in welchem Arbeitsblatt und in welcher Arbeitsmappe sich die Zielzelle A1 befindet. Befindet sich die Codezeile in einem normalen Modul, wird ohne die explizite Angabe des Arbeitsblattes das gerade aktive Blatt als das Objekt angenommen, auf das sich die Angabe des Bereichs bezieht. Befindet sich der Code in dem Klassenmodul eines Arbeitsblattes, gilt dieses als das Standardobjekt, auf das sich der Range bezieht.

Einstieg

Range("A1").Interior.Color = 65535

Die Arbeitsmappe, in welcher der Code gerade läuft, kann über das Objekt ThisWorkbook, die gerade aktive Arbeitsmappe über das Objekt ActiveWorkbook angegeben werden. ThisWorkbook.Worksheets("Tabelle1").Range("A1").Interior.Color=255

Einstieg

Worksheets("Tabelle1").Range("A1").Interior.Color=255

ActiveWorkbook.Worksheets("Tabelle1").Range("A1").Interior.Color=255

Referenzierung und Objektvariable

Bei einer vollständigen Referenzierung wie beispielsweise in der Zeile ActiveWorkbook.Worksheets(1).Range("A1").Value="2"

Einstieg

5

muss man bei der Ausführung auf die Objekte aller Verschachtelungsebenen zugreifen, während man bei einer gleichwertigen Objektvariablen, in diesem Fall Dim rngDestination As Range Set rngDestination = ActiveWorkbook.Worksheets(1).Range("A1") rngDestination.Value = "2"

Einstieg

rngDestination

Verwendet man die With-Anweisung mit einer vollständigen Referenzierung, verschenkt man aber erhebliche Zeit gegenüber der Benutzung eines gleichwertigen Objektes. Erstellt man vorher ein Objekt und benutzt mit diesem die With-Anweisung, ist die Ausführung weit mehr als doppelt so schnell.

Einstieg

Mit der With-Anweisung kann man eine Reihe von Anweisungen, die zwischen den Schlüsselwörtern With und End With stehen, für ein bestimmtes Objekt ausführen, ohne jedes Mal das Objekt angeben zu müssen. Das, was auf einen vorangestellten Punkt folgt, bezieht sich dann auf dieses Objekt.

Einstieg

direkt auf das Zielobjekt zugreift. Das spart bei häufigen Zugriffen auf das gleiche Objekt einiges an Zeit.

2471_Excel-VBA.book Seite 24 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

24

>> DoEvents

Die Ausführung ab der Codezeile With ActiveWorkbook.Worksheets(1).Range("A1")

Einstieg

ist also langsamer als nach der folgenden With-Anweisung: Dim rngDestination As Range Set rngDestination = ActiveWorkbook.Worksheets(1).Range("A1") With rngDestination

DoEvents

Um eine Schleife durch eine Aktion von außen zu verlassen, muss auch ein Ereignis, beispielsweise das Klickereignis einer Befehlsschaltfläche ausgeführt werden. Während des Programmablaufs wird aber solch ein Ereignis unterdrückt.

Um einen Schleifenabbruch durch ein Ereignis zu realisieren, benötigt man eine Variable, die sowohl in der abzubrechenden Prozedur als auch in der entsprechenden Ereignisprozedur gültig ist. Den Wert dieser Variablen fragt man nach jedem Aufruf von DoEvents in der Schleife ab. Ist dieser zwischenzeitig geändert worden, bricht man an dieser Stelle ab.

7

Einstieg

Einstieg

Einstieg

Um dem abzuhelfen, kommt die Anweisung DoEvents zum Einsatz. Damit wird der Anwendung, in diesem Fall Excel, die Möglichkeit gegeben, anstehende Ereignisse abzuarbeiten und auch sonstige Aktualisierungen durchzuführen. Der Programmablauf in der aufrufenden Prozedur wird in dieser Zeit gestoppt, man sollte es also mit dem Einsatz von DoEvents nicht übertreiben.

Einstieg

Einstieg

6

Benutzerdefinierte Tabellenfunktionen

Immer wieder ein Grund zur Irritation ist die Tatsache, dass die in einer Zelle verwendeten benutzerdefinierten Tabellenfunktionen keine Aktionen ausführen können, die ein Ereignis auslösen. Das könnte sonst zum Auslösen von immer neuen Ereignissen führen, welche schlussendlich ein völliges Blockieren der Anwendung als Ergebnis hätten. Testet man solch eine Funktion dagegen aus dem Direktbereich oder durch einen Aufruf aus einer Prozedur, kann man ohne Probleme Zellen ändern und beliebige Aktionen ausführen. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_01_Function.xlsm ' Tabelle Tabellenfunktion ' Modul mdl_01_07_Function '===================================================================

Einstieg

Listing 1

2471_Excel-VBA.book Seite 25 Dienstag, 4. Dezember 2007 1:42 13

25

Public Function ChangeCell(rngCell As Range) As String

Einstieg

>> Einstieg

rngCell.Interior.Color = vbRed End Function

Einstieg

ChangeCell = "Zelle " & rngCell.Address & _ " Hintergrundfarbe ändern"

Wird diese Funktion beispielsweise in der Zelle A1 mit der Formel =CHANGECELL(B1) verwendet, steht anschließend in dieser Zelle die Fehlermeldung »#WERT«. Die Hintergrundfarbe der Zelle B1 selbst wurde nicht geändert. In den Vorgängerversionen wurde in dieser Konstellation noch das Funktionsergebnis zurückgegeben, konsequenterweise wurde in der aktuellen Version darauf verzichtet.

Ändert man mit VBA die Zellen von Tabellenblättern, auf die sich Tabellenfunktionen anderer Zellen beziehen, wird eine Neuberechnung angestoßen. Je nach Funktion und Anzahl der Berechnungen kann das bis fast zum völligen Stillstand der Anwendung führen. Zwar arbeitet Excel unablässig an der Neuberechnung, die Abarbeitung des Programmcodes wird aber ausgebremst, da mit dem Programmablauf erst fortgefahren wird, wenn die Berechnung abgeschlossen ist. Um das zu vermeiden wird die automatische Berechnung mit folgender Programmzeile ausgeschaltet:

Einstieg

Berechnungen ausschalten

Einstieg

8

Einstieg

Listing 1 (Forts.)

Application.Calculation = xlCalculationManual

Application.Calculation = xlCalculationAutomatic

ausführt. Anschließend sollte man mit der Methode

Einstieg

Nachdem alle Zellen geändert sind, muss man die automatische Berechnung wieder aktivieren, indem man vor dem Beenden der Prozedur die Codezeile

Application.Calculate

9

Bildschirmaktualisierung ausschalten

Mit der VBA-Zeile

Einstieg

eine komplette Neuberechnung durchführen.

Application.ScreenUpdating=False

Einstieg

wird die Bildschirmaktualisierung deaktiviert. Damit kann man die Laufzeit eines Programms erheblich verkürzen.

2471_Excel-VBA.book Seite 26 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

26

>> Select vermeiden

Bei Manipulationen des sichtbaren Bereiches sind damit durchaus Geschwindigkeitssteigerungen bis zum Vierfachen möglich. Man darf aber nicht vergessen, die Bildschirmaktualisierung am Ende auch wieder freizugeben.

Einstieg

Zum Einschalten der Bildschirmaktualisierung brauchen Sie einfach nur die Codezeile Application.ScreenUpdating=True

auszuführen.

Einstieg

10

Select vermeiden

Viele Objekte in Excel, wie zum Beispiel Zellen (Bereiche), Spalten oder Zeilen, besitzen die Methode Select. Mit dieser Methode kann man aber recht schnell die Performance eines selbst geschriebenen Programms auf den Nullpunkt bringen, selbst wenn man sorgfältig den Code auf Geschwindigkeit getrimmt hat. Hat man die Auslösung von Ereignissen nicht durch

Einstieg

Einstieg

Einstieg

Application.EnableEvents = False

ausgeschaltet, wird bei jedem Select das Ereignis Worksheet_SelectionChange ausgelöst. Existiert eine solche Ereignisprozedur, wird diese jedes Mal abgearbeitet, wenn man vom Programmcode aus eine Zelle selektiert. Der Programmablauf in der aufrufenden Prozedur stoppt dann so lange, bis der Code in dieser Ereignisprozedur fertig ausgeführt ist. Aber auch ohne Ereignisprozeduren kostet das Selektieren viel Zeit und lässt den Bildschirm durch das Hin- und Herhüpfen der Markierung und möglicherweise sogar noch durch das dauernde Anzeigen eines anderen Bereiches unruhig erscheinen. Ein Select ist dabei aber wirklich nur in den allerwenigsten Fällen notwendig. Anstatt erst eine Zelle zu selektieren und dann beispielsweise mittels Selection.Value den Zellinhalt zu verändern, sollte man direkt referenzieren. Anstatt Folgendes einzusetzen, Worksheets("Tabelle1").Range("A1").Select Selection.Value=22

verwendet man besser diese Zeile:

Einstieg

Einstieg

Worksheets("Tabelle1").Range("A1").Value = 22

11

Durchlaufen von Auflistungen

Auflistungen sind Gruppen gleichartiger Objekte wie zum Beispiel Tabellenblätter, Zellen, Arbeitsmappen oder auch selbst angelegte Collections. Erkennbar sind vorhandene Auflistungen meistens schon an ihren Namen. Sie besitzen ein Plural-s am Ende (Workbooks, Worksheets, Cells …), welches an den Namen der in ihnen enthaltenen Objekte gehängt ist.

2471_Excel-VBA.book Seite 27 Dienstag, 4. Dezember 2007 1:42 13

For Each Element In Gruppe ' Schleifenkörper Next [Element] Element ist dabei die Variable, die nacheinander eine Referenz oder den Wert jedes

einzelnen Elementes der Auflistung erhält. Beim Iterieren durch Datenfelder kann als Variablentyp nur Variant gewählt, bei Auflistungen gleichartiger Objekte kann Variant, Object oder der spezielle Objekttyp der Auflistung verwendet werden.

Wird eine Variantvariable für Element verwendet, bekommt man die Inhalte der Elemente als Wert (ByVal) zurückgeliefert. Wird bei Auflistungen eine Objektvariable des Typs der Objekte in dieser Auflistung eingesetzt, erhält man eine Referenz auf das Element, das heißt, man bekommt direkten Zugriff auf das Originalobjekt.

Farbindex

In Excel stehen standardmäßig 56 Farben zur Verfügung, die in einer Palette zusammengefasst sind. Die Farben dieser Palette können geändert und auch zusammen mit der Arbeitsmappe abgespeichert werden.

Einstieg

12

Einstieg

Schleifen mit der For Each...Next-Anweisung sind dafür gemacht, nacheinander alle Elemente einer Auflistung oder eines Datenfeldes zurückzugeben. Der Aufbau solch einer Schleife ist folgender:

Einstieg

Jedes Element in einer solchen Auflistung ist unter einem eindeutigen numerischen Index ansprechbar. Dazu wird die Standardeigenschaft Item der Auflistungen benutzt. Da sich bei jeder Änderung der Auflistung die Reihenfolge und somit auch der Index eines bestimmten Elementes ändern kann, ist es keine gute Idee, sich den numerischen Index eines bestimmten Elements zu merken, um später darüber auf das Element zuzugreifen.

Einstieg

27

Einstieg

>> Einstieg

Mit folgendem Codefragment startet man den Dialog (Abbildung 2) zum Ändern der Palettenfarben:

Abbildung 2: Dialog Palettenfarben

Einstieg

Einstieg

Einstieg

Application.Dialogs(xlDialogColorPalette).Show

2471_Excel-VBA.book Seite 28 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

28

>> Farbindex

In der Regel werden dabei die einzelnen Farben in VBA über die Eigenschaft Color-

Index angesprochen.

Acht fest definierte RGB-Farben stehen aber auch in Form von Konstanten (Tabelle 4) mit sprechenden Namen zur Verfügung, die aber nicht in Verbindung mit der ColorIndex-Eigenschaft benutzt werden können. Den entsprechenden Farbindex kann man der folgenden Tabelle entnehmen. Farbe

Farbindex

Farbkonstante

Schwarz

0

vbBlack

Weiß

2

vbWhite

Rot

3

vbRed

Grün

4

vbGreen

Blau

5

vbBlue

Gelb

6

vbYellow

Magenta

7

vbMagenta

Cyan

8

vbCyan

Tabelle 4: Verfügbare Farbkonstanten

Mit dem nachfolgenden Code können Sie die 56 zur Verfügung stehenden Farben einer Arbeitsmappe auf einem Tabellenblatt ausgeben. Dabei werden die einzelnen Farben in 8 Reihen mit je 7 Farben dargestellt, wobei jeweils zwei Zellen nebeneinander zu einer Farbe gehören. Die etwas kompliziert anmutenden Berechnungen für die aktuelle Zeile und Spalte sollen noch etwas näher erläutert werden. Die Laufvariable i wird bei jedem Schleifendurchlauf um 1 erhöht und nimmt nacheinander die Werte von 1 bis 56 an. Für die Berechnung der Zeile wird der Variablenwert i um 1 vermindert und mit einer Ganzzahlendivision, erkennbar an dem umgekehrten Divisionszeichen \, durch 7 geteilt. Werte von 1 bis 7 ergeben bei dieser Division die Ganzzahl 0, von 8 bis 14 die Ganzzahl 1, usw. Zu diesem Divisionsergebnis wird noch 1 hinzugezählt, da es eine Zeile Null nicht gibt. Zur Berechnung der Spalte wird der Mod-Operator benutzt, der den Rest einer ganzzahligen Division zweier Zahlen zurückgibt. Der Variablenwert i wird dabei erst um 1 vermindert und die Modulo-Operation mit den Operanden i und 7 durchgeführt. Als Ergebnis erhält man nacheinander immer Werte zwischen 0 und 7, die anschließend mit 2 multipliziert werden, da für jeden Wert zwei Zellen vorgesehen sind. Da es eine Spalte Null nicht gibt, wird zur Darstellung des Wertes eine 1 und zum Anzeigen der Farbe eine 2 hinzugezählt.

2471_Excel-VBA.book Seite 29 Dienstag, 4. Dezember 2007 1:42 13

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle Farbindex ' Modul mdl_01_12_ColorIndex '=================================================================== Public Sub ShowColorIndex() Dim i As Long

Einstieg

29

Einstieg

>> Einstieg

With Worksheets("Farbindex")

.Cells(((i - 1) \ 7) + 1, _ 2 * ((i - 1) Mod 7) + 2 _ ).Interior.ColorIndex = i

Einstieg

' Ausgabe Farbindex und Zellfarbe .Cells(((i - 1) \ 7) + 1, _ 2 * ((i - 1) Mod 7) + 1 _ ).Value = "Colorindex = " & i

Einstieg

For i = 1 To 56 ' Nacheinander jeden Farbindex ansprechen

Next

End With End Sub

Einstieg

.Cells.Columns.AutoFit 'Spaltenbreite automatisch anpassen

Listing 2

Einstieg

Einstieg

Folgendermaßen (Abbildung 3) sieht das Ergebnis aus:

Um eine Prozedur wie die vorliegende ShowColorIndex auszuführen, kann man die Tastenkombination (Alt)+(F8) benutzen oder auf der Registerkarte ENTWICKLERTOOLS

Einstieg

Abbildung 3: Farbpalette

2471_Excel-VBA.book Seite 30 Dienstag, 4. Dezember 2007 1:42 13

>> RGB-Farben

die Schaltfläche MAKROS anklicken. In beiden Fällen öffnet sich ein Dialog, in dem man aus einer Liste das gewünschte Makro auswählen und ausführen kann.

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

30

Abbildung 4: Makro ausführen

RGB-Farben

Während in Excel-Versionen vor Excel 2007 lediglich die angesprochenen 56 Farben dargestellt werden konnten, ist es in der neuesten Version möglich, den kompletten RGB-Farbraum abzubilden. Hi n we is

Einstieg

Einstieg

13

Im RGB-Modell wird für jeden Bildpunkt der Rot-, Grün- und Blauwert angegeben, das Mischungsverhältnis der drei Farben beschreibt den Farbwert inklusive der Helligkeit. Bei einer heute üblichen Bittiefe von 24 Bit stehen für jede Farbe eines Bildpunktes 8 Bit zur Verfügung. Das heißt, jede der drei Farben eines Bildpunktes kann einen Wert von 0 bis 255 annehmen.

Einstieg

Null bedeutet, dass diese Farbe überhaupt nicht, das Maximum 255, dass dieser Farbanteil voll vorhanden ist. RGB(0, 0, 0) ist beispielsweise schwarz, RGB(255, 255, 255) weiß, RGB(255, 0, 0) rot, RGB(0, 255, 0) grün und RGB(0, 0, 255) blau.

2471_Excel-VBA.book Seite 31 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg

Folgender Code, eingefügt in das Klassenmodul eines Tabellenblattes, läuft unter allen Excel-Versionen seit Excel 97: '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle RGB ' Modul Tabelle RGB '=================================================================== Private Sub cmdRGB_Click() Dim strColor Dim bytR Dim bytG Dim bytB

As As As As

String Byte Byte Byte

Einstieg Einstieg

Das heißt, wurde beispielsweise der Color-Eigenschaft eines Zellhintergrundes eine RGB-Farbe zugewiesen, entsprach sie nach dem Auslesen nicht mehr dem Originalwert, sondern dem RGB-Wert der Palettenfarbe.

Einstieg

In den Versionen vor Excel 2007 konnten zwar auch RGB-Farben zum Setzen einer Farbe benutzt werden. Bedingt durch die eingeschränkte BIFF 8-Struktur (BINARY INTERCHANGE FILE FORMAT) der Excel-Dateien wurden aber ausschließlich Palettenfarben dargestellt und gespeichert, benutzt wurde dazu die ähnlichste Palettenfarbe.

Einstieg

Gespeichert wird der RGB-Wert im Allgemeinen in einer Long-Variablen, die 32 Bit groß ist. Da zur Speicherung nur 24 Bit benötigt werden, bleiben die 8 Höchstwertigen Bits (24–31) unbenutzt. Bit 0–7 nehmen den Rot-, Bit 8–15 den Grün- und Bit 16–23 den Blauwert auf.

Einstieg

31

' Die einzelnen Farbanteile extrahieren bytR = CByte("&H" & Right(strColor, 2)) bytG = CByte("&H" & Mid(strColor, 3, 2)) bytB = CByte("&H" & Left(strColor, 2))

Einstieg

strColor = "FF8080"

Listing 3

Einstieg

' RGB-Wert ausgeben, Zellhintergrund setzen Me.Range("A8") = "RGB-Wert = _ (" & strColor & ") " & &HFF8080 Me.Range("B8").Interior.Color = &HFF8080 Me.Range("C8") = "Ausgelesener Color-Wert B8= " & _

Einstieg

' Die einzelnen Farbanteile ausgeben Me.Range("A5") = "Rotanteil = " & bytR Me.Range("A6") = "Grünanteil = " & bytG Me.Range("A7") = "Blauanteil = " & bytB

2471_Excel-VBA.book Seite 32 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

32

>> RGB-Farben Me.Range("B8").Interior.Color

Einstieg

' Palettenfarbe ausgeben, Zellhintergrund setzen und Color' Eigenschaft auslesen Me.Range("A9") = "Palettenfarbe B8 = " & _ Me.Range("B8").Interior.ColorIndex Me.Range("B9").Interior.ColorIndex = _ Me.Range("B8").Interior.ColorIndex Me.Range("C9") = "Ausgelesener Color-Wert B9= " & _ Me.Range("B9").Interior.Color

Einstieg

Einstieg

Einstieg

Einstieg

Listing 3 (Forts.)

In der Ereignisprozedur cmdRGB_Click, die durch einen Klick auf die Befehlsschaltfläche cmdRGB ausgeführt wird, wird zu Beginn eine RGB-Farbe definiert. Die Variable strColor nimmt diesen Wert als Text in Form von 6 Zeichen auf. Eine solche Darstellung wird Hexadezimaldarstellung genannt. Hinweis

Einstieg

Einstieg

End Sub

In der Hexadezimaldarstellung repräsentieren jeweils zwei Zeichen den Wert eines Bytes und werden Nibbles genannt. Jedes dieser zwei Zeichen steht für die Kombination von 4 gesetzten oder nicht gesetzten Bits. Dabei werden die Ziffern 0–9 und die Zeichen A–F benutzt, das heißt, jedes dieser 16 Zeichen steht für einen Wert von 0–15. Die zwei äußerst rechts stehenden Zeichen stellen das niederwertigste Byte dar, stehen also für die Bits 0–7. Die zwei Zeichen links daneben stehen für die Bits 8–15, die nächsten zwei repräsentieren die Bits 16–23 und links daneben folgen die Bits 24–31. Im Programmcode kann man die Hexadezimaldarstellung eines Wertes einsetzen, indem man die zwei Zeichen »&H« vor den eigentlichen Hexadezimalwert setzt. Die Codezeile lngWert = 255 ist also gleichwertig mit der Zeile lngWert = &HFF.

Die darauf folgenden Zeilen extrahieren aus den 6 Zeichen die Anteile der Farben, wobei die zwei äußerst rechts stehenden Zeichen den Rotwert, die zwei links daneben den Grünwert und die links stehenden den Blauwert angeben. Die einzelnen Anteile werden auf einem Tabellenblatt ausgegeben. Anschließend wird ein Zellhintergrund auf diesen Wert gesetzt, der ColorIndex dieser Zelle ausgelesen und zusammen mit dem ursprünglich gesetzten RGB-Wert ausgegeben. Ein anderer Zellhintergrund wird auf den ausgelesenen ColorIndex-Wert gesetzt, die Color-Eigenschaft ausgelesen und zusammen mit dem gesetzten ColorIndex-Wert ausgegeben. Folgendermaßen (Abbildung 5) sieht das Ergebnis unter Excel 2007 aus:

2471_Excel-VBA.book Seite 33 Dienstag, 4. Dezember 2007 1:42 13

33

Einstieg

Einstieg

>> Einstieg

Einstieg

Die gleiche Ausgabe unter den Vorgängerversionen (Abbildung 6):

Einstieg

Abbildung 5: Colorindex unter Excel 2007

Wie man unschwer erkennen kann, ist der gesetzte (16744567) und gleich danach wieder ausgelesene (16751001) Farbwert vor Excel 2007 unterschiedlich. Das liegt daran, dass die gesetzte Farbe sofort in die ähnlichste Palettenfarbe umgewandelt wurde, in diesem Fall in die Palettenfarbe 17 mit dem Farbwert 16751001.

Farbanteile aus dem RGB-Wert extrahieren

Nachfolgend eine Funktion, die als Funktionsergebnis einen gewünschten Farbanteil aus einer RGB-Farbe zurückliefert. Dabei wird als Funktionsargument eine RGB-Farbe und optional ein Wert übergeben, der angibt, welcher Farbanteil zurückgeliefert werden soll.

Einstieg

14

Einstieg

Abbildung 6: Colorindex vor Excel 2007

Den zwei ausgewählten Zeichen wird das Präfix »&H« vorangestellt, anschließend mit der Funktion CLng in einen Longwert umgewandelt und als Funktionsergebnis zurückgegeben.

Einstieg

Der übergebene RGB-Longwert wird in der Funktion GetColorPart in eine Zeichenfolge in Hexadezimaldarstellung umgewandelt. Die zwei Zeichen ganz rechts beschreiben den Rot-, die zwei links daneben den Grün- und die zwei Zeichen ganz links den Blauwert.

Einstieg

Wird eine 1 oder gar nichts als zweites Argument übergeben, wird der Rotwert, bei einer 2 der Grünwert und bei einer 3 der Blauwert zurückgeliefert.

2471_Excel-VBA.book Seite 34 Dienstag, 4. Dezember 2007 1:42 13

>> RGB-Dialog

Einstieg

Einstieg

34

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Modul mdl_01_14_ConvertColor '=================================================================== Public Sub TestColorPart() Dim lngRGB As Long

Einstieg

lngRGB = RGB(12, 20, 30) MsgBox "RGB-Wert= " & lngRGB & vbCrLf & _ "Rotwert= " & GetColorPart(lngRGB, 1) & vbCrLf & _ "Grünwert= " & GetColorPart(lngRGB, 2) & vbCrLf & _ "Blauwert= " & GetColorPart(lngRGB, 3) End Sub

Einstieg

Public Function GetColorPart( _ lngRGB As Long, Optional lngColor As Long = 1) As Long Dim strColor

As String

Einstieg

Einstieg

If lngColor < 1 Or lngColor > 3 Then Exit Function ' In einen Hexstring mit den letzten 6 Stellen umwandeln strColor = String(6 - Len(Hex(lngRGB)), _ Asc("0")) & Hex(lngRGB) Select Case lngColor Case 1 ' Rotanteil GetColorPart = CLng("&H" & Right(strColor, 2)) Case 2 ' Grünanteil GetColorPart = CLng("&H" & Mid(strColor, 3, 2)) Case 3 ' Blauanteil GetColorPart = CLng("&H" & Left(strColor, 2)) End Select End Function

Einstieg

Listing 4

15

RGB-Dialog

Einstieg

Möchte man eine benutzerdefinierte Farbe einsetzen, bietet Excel 2007 situationsabhängige Dialoge an. Für den Zellhintergrund gibt es beispielsweise den folgenden Dialog (Abbildung 7):

2471_Excel-VBA.book Seite 35 Dienstag, 4. Dezember 2007 1:42 13

35

Einstieg

Einstieg

Einstieg

Einstieg

>> Einstieg

Einstieg

Einstieg

Um aber per VBA einen RGB-Wert ohne den Umweg über das Setzen und Auslesen eines Formates zu bekommen, ist dieser Dialog ungeeignet. Dafür bietet das Windows-Betriebssystem einen Standarddialog (Abbildung 8) an, den man dafür sehr gut verwenden kann.

Einstieg

Abbildung 7: Excel-Dialog Farbauswahl

Einstieg

Abbildung 8: Standarddialog Farbe

2471_Excel-VBA.book Seite 36 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

36

>> RGB-Dialog

Die Prozedur TestChooseColor dient dazu, die eigentliche Funktion ColorDialog aufzurufen, den von dieser zurückgelieferten RGB-Wert in seine Farbanteile zu zerlegen und das Ergebnis in einer Meldungsbox auszugeben. Die Funktion ColorDialog erledigt die eigentliche Arbeit. Die dort eingesetzte APIFunktion CHOOSEMYCOLOR erwartet als Argument eine Variable vom Typ CHOOSECOLOR, welche Voreinstellungen aufnimmt und auch das Ergebnis zurückliefert. Es können 16 benutzerdefinierte Farben definiert werden, die anschließend im Dialog zusätzlich zur Auswahl stehen. Die 16 RGB-Werte dieser Farben werden im Array alngCustomColors vom Datentyp Long definiert und der Variablenzeiger des ersten Elements des Arrays als Wert an das Element lpCustColors der Struktur udtChoosecolor übergeben. Das Element lStructSize der Struktur udtChoosecolor wird anschließend auf die Größe der Struktur in Bytes gesetzt und die API-Funktion mit der Struktur udtChoosecolor als Argument aufgerufen. Liefert die API-Funktion einen Wert ungleich Null zurück, wurde eine Farbe gewählt. Das Element rgbResult der Struktur udtChoosecolor enthält dann den RGB-Wert, der als Funktionsergebnis zurückgegeben wird. Wurde keine Farbe gewählt, gibt man als Funktionsergebnis den Fehlerwert

&HFFFFFFFF (–1) zurück.

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle RGB-Dialog ' Modul mdl_01_15_GetColor '=================================================================== Private Type CHOOSECOLOR lStructSize As Long hwndOwner As Long hInstance As Long rgbResult As Long lpCustColors As Long flags As Long lCustData As Long lpfnHook As Long lpTemplateName As String End Type Declare Function CHOOSEMYCOLOR _ Lib "comdlg32.dll" Alias "ChooseColorA" ( _ pChoosecolor As CHOOSECOLOR _ ) As Long Listing 5

2471_Excel-VBA.book Seite 37 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg

String Long Byte Byte Byte

lngRGB = ColorDialog()

Einstieg

As As As As As

Einstieg

Sub TestChooseColor() Dim strColor Dim lngRGB Dim bytR Dim bytG Dim bytB

37

' Die einzelnen Farbanteile extrahieren bytR = CByte("&H" & Right(strColor, 2)) bytG = CByte("&H" & Mid(strColor, 3, 2)) bytB = CByte("&H" & Left(strColor, 2)) MsgBox "RGB-Farbe = " & lngRGB & " (" & strColor & ")" & _ vbCrLf & "Rotanteil = " & bytR & _ vbCrLf & "Grünanteil = " & bytG & _ vbCrLf & "Blauanteil = " & bytB

Einstieg

' In einen Hexstring mit den letzten 6 Stellen umwandeln strColor = String(6 - Len(Hex(lngRGB)), _ Asc("0")) & Hex(lngRGB)

Einstieg

If lngRGB = &HFFFFFFFF Then Exit Sub

Public Function ColorDialog() As Long Dim udtChoosecolor As CHOOSECOLOR Dim alngCustomColors(1 To 16) As Long

Einstieg

End Sub

Listing 5 (Forts.)

Einstieg Einstieg

'Die benutzerdefinierten Farben vorbelegen alngCustomColors(1) = RGB(255, 0, 0) 'Rot alngCustomColors(2) = RGB(0, 255, 0) 'Grün alngCustomColors(3) = RGB(0, 0, 255) 'Blau alngCustomColors(4) = RGB(255, 255, 255) 'Weiß alngCustomColors(5) = RGB(0, 0, 0) 'Schwarz alngCustomColors(6) = RGB(255, 0, 0) 'Rot alngCustomColors(7) = RGB(0, 255, 0) 'Grün alngCustomColors(8) = RGB(0, 0, 255) 'Blau alngCustomColors(9) = RGB(255, 255, 255) 'Weiß alngCustomColors(10) = RGB(0, 0, 0) 'Schwarz alngCustomColors(11) = RGB(255, 0, 0) 'Rot alngCustomColors(12) = RGB(0, 255, 0) 'Grün

Einstieg

' Funktion mit Fehlerwert vorbelegen ColorDialog = &HFFFFFFFF

2471_Excel-VBA.book Seite 38 Dienstag, 4. Dezember 2007 1:42 13

>> RGB in den ColorIndex umwandeln

Einstieg

Einstieg

Einstieg

38

alngCustomColors(13) alngCustomColors(14) alngCustomColors(15) alngCustomColors(16)

= = = =

RGB(0, 0, 255) 'Blau RGB(255, 255, 255) 'Weiß RGB(0, 0, 0) 'Schwarz RGB(255, 0, 0) 'Rot

' Zeiger als Wert auf die benutzerdefinierten Farben udtChoosecolor.lpCustColors = VarPtr(alngCustomColors(1)) ' Größe der Struktur in Bytes udtChoosecolor.lStructSize = Len(udtChoosecolor) 'Den Dialog aufrufen If CHOOSEMYCOLOR(udtChoosecolor) 0 Then ' Farbe wurde gewählt ' Den gewählten RGB Wert zurückgeben ColorDialog = udtChoosecolor.rgbResult

Einstieg

End If End Function Listing 5 (Forts.)

Einstieg

Einstieg

Einstieg

16

RGB in den ColorIndex umwandeln

Eine Möglichkeit, einen RGB-Wert in den entsprechenden ColorIndex-Wert umzuwandeln, besteht darin, einem Zellhintergrund oder einem Zeichen über die Color-Eigenschaft eine RGB-Farbe zuzuweisen und anschließend die ColorIndex-Eigenschaft auszulesen. Man muss dabei aber sicherstellen, dass die ursprünglichen Werte zurückgesetzt werden und diese Aktion unsichtbar ist, was aber nicht immer ganz einfach ist. Die folgende Funktion kommt ohne solch ein Vorgehen aus. Man vergleicht dabei die einzelnen Farbanteile eines übergebenen RGB-Wertes nacheinander mit den entsprechenden Farbanteilen aller 56 Excel-Farben und bildet daraus einen Wert, der umso geringer ist, je ähnlicher sich die einzelnen Farbanteile sind. Der Farbindex mit der geringsten Abweichung wird anschließend als Funktionsergebnis zurückgegeben. Da man leider nicht erkennen kann, nach welchen Kriterien Excel den Farbindex tatsächlich auswählt, kann nicht garantiert werden, dass der zurückgelieferte Index immer mit der Excel-Wahl übereinstimmt, zumal auch standardmäßig verschiedene Farben doppelt vorkommen.

Einstieg

Die Funktion kann auch als benutzerdefinierte Tabellenfunktion in einer Zelle eingesetzt werden. Die folgende Formel liefert den Colorindex der RGB-Farbe, welche sich aus den Rot-, Grün- und Blauanteilen der Zellen B1, B2 und B3 zusammensetzt:

2471_Excel-VBA.book Seite 39 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg

=ConvertRgbToColorIndex(HEXINDEZ(DEZINHEX(B1;2)&DEZINHEX(B2;2)&DEZINHEX(B3;2))) Listing 6

Einstieg

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle Umwandlungsfunktionen '===================================================================

Einstieg

39

Function ConvertRgbToColorIndex(RgbColor As Long) As Long i As Long r As Long g As Long b As Long strBuiltColor As String strSearchColor As String lngRGB As Long lngMin As Long lngIndex As Long lngAbweichung As Long

Einstieg

Public Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim

Einstieg

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle Umwandlungsfunktionen ' Modul mdl_01_14_ConvertColor '===================================================================

Einstieg

Nachfolgend die Funktion ConvertRgbToColorIndex:

' In einen Hexstring mit den letzten 6 Stellen umwandeln strBuiltColor = String(6 - Len(Hex(lngRGB)), _ Asc("0")) & Hex(lngRGB) ' r g b

Die einzelnen = CLng("&H" & = CLng("&H" & = CLng("&H" &

Farbanteile extrahieren Right(strBuiltColor, 2)) Mid(strBuiltColor, 3, 2)) Left(strBuiltColor, 2))

Einstieg

lngRGB = ActiveWorkbook.Colors(i)

Einstieg

lngMin = 1000 For i = 1 To 56

Listing 7

Einstieg

' In einen Hexstring mit den letzten 6 Stellen umwandeln strSearchColor = String(6 - Len(Hex(RgbColor)), _

2471_Excel-VBA.book Seite 40 Dienstag, 4. Dezember 2007 1:42 13

>> ColorIndex in RGB-Wert umwandeln

Einstieg

40

Asc("0")) & Hex(RgbColor)

Einstieg

'Die absoluten Abweichungen ermitteln lngAbweichung = _ Abs(CLng("&H" & Right(strSearchColor, 2)) - r) + _ Abs(CLng("&H" & Mid(strSearchColor, 3, 2)) - g) + _ Abs(CLng("&H" & Left(strSearchColor, 2)) - b) If lngAbweichung < lngMin Then

Einstieg

' Index zurückgeben ConvertRgbToColorIndex = i ' Min-Abweichung anpassen lngMin = lngAbweichung End If

Einstieg

Next End Function Listing 7 (Forts.)

Einstieg

17

ColorIndex in RGB-Wert umwandeln

Die Funktion ConvertColorIndexToRGB ermittelt den RGB-Wert einer der 56 Excel-Farben. Dabei wird lediglich die Color-Eigenschaft der Farbe mit dem übergebenen Index zurückgegeben.

Einstieg

Die Funktion kann auch als benutzerdefinierte Tabellenfunktion in einer Zelle eingesetzt werden. Die folgende Formel liefert den RGB-Wert des Colorindex, welcher sich in der Zelle B6 befindet: '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle Umwandlungsfunktionen '===================================================================

Einstieg

Einstieg

=ConvertColorIndexToRGB(B6) Listing 8

2471_Excel-VBA.book Seite 41 Dienstag, 4. Dezember 2007 1:42 13

Nachfolgend die Funktion ConvertColorIndexToRGB: '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_02_Farben.xlsm ' Tabelle Umwandlungsfunktionen ' Modul mdl_01_14_ConvertColor '===================================================================

Einstieg

41

Einstieg

>> Einstieg

' Überprüfen, ob Index zwischen 1 und 56 ist If lngIndex > 56 Then lngIndex = 56 If lngIndex < 1 Then lngIndex = 1 ' RGB ermitteln ConvertColorIndexToRGB = ActiveWorkbook.Colors(lngIndex)

Einstieg

Public Function ConvertColorIndexToRGB(lngIndex As Long) As Long

Häufig werden Zufallszahlen eines bestimmten Zahlenbereichs benötigt, die aber nicht doppelt vorkommen dürfen. Die Ziehung von Zahlen beim Zahlenlotto oder Bingo wären solch ein Einsatzgebiet. Nun könnte man ganz einfach so lange Zufallszahlen erzeugen und nachschauen, ob diese bereits gezogen sind, bis man die gewünschte Anzahl einmaliger Zahlen beisammen hat. Bei einigen wenigen Zahlen aus einem großen Bereich sicherlich auch einigermaßen schnell, bei größeren Zahlenmengen aus einem engen Bereich steigt der Zeitbedarf aber enorm an. Besser ist es sicherlich, sich einen Pool mit den verfügbaren Zahlen anzulegen und die daraus bereits gezogenen zu entfernen. Die Prozedur TestGetRandomNumbers ruft die Funktion GetRandomNumbers auf, zurückgeliefert wird ein Array mit 10 Zahlen aus dem Zahlenbereich von 11 bis 20. Anschließend wird eine Zeichenkette, die aus allen gezogenen Zahlen besteht, in einer Meldungsbox ausgegeben. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_03_RndShuffleSort.xlsm ' Modul mdl_01_18_Random '===================================================================

Einstieg

Zufallszahlen erzeugen

Einstieg

18

Einstieg

Listing 9

Einstieg

End Function

Einstieg

Listing 10

2471_Excel-VBA.book Seite 42 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

42

>> Zufallszahlen erzeugen

Sub TestGetRandomNumbers() Dim varNumbers As Variant Dim strAusgabe As String Dim i As Long ' 10 Zahlen aus dem Bereich von 11 bis 20 erzeugen varNumbers = GetRandomNumbers(11, 20, 10) ' Die Zahlen zu einem String zusammenzusetzen For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next ' In einer Meldungsbox ausgeben MsgBox Left(strAusgabe, Len(strAusgabe) - 1) End Sub

Einstieg

Einstieg

Listing 10 (Forts.)

Die Funktion GetRandomNumbers übernimmt als Argument den Beginn und das Ende des Zahlenbereichs, aus dem die als weiteres Argument übergebene Anzahl Zahlen gezogen und als Array zurückgegeben werden. Dazu wird das Datenfeld alngSource mit allen verfügbaren Zahlen angelegt und in einer Schleife in jedem Durchlauf ein Element daraus ausgewählt. Dieses wird im Datenfeld alngResult gespeichert und anschließend aus dem Bereich der aktuell verfügbaren Zahlen im Array alngSource geschoben. Eine noch nicht gezogene Zahl am Ende des verfügbaren Bereichs nimmt dann den Platz dort ein. Danach wird die Anzahl der verfügbaren Zahlen im Array um 1 vermindert und die Schleife so lange fortgesetzt, bis die gewünschte Anzahl Zahlen gezogen wurden.

Einstieg

Einstieg

Einstieg

Am Ende gibt man das Datenfeld alngResult als Funktionsergebnis zurück. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_03_RndShuffleSort.xlsm ' Modul mdl_01_18_Random '=================================================================== Public Function GetRandomNumbers( _ NumberFrom As Long, _ NumberTo As Long, _ NumberCount As Long _ ) As Variant Dim alngSource() As Long Dim alngResult() As Long Listing 11

2471_Excel-VBA.book Seite 43 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg

If NumberFrom > NumberTo Then Exit Function If NumberCount < 1 Then Exit Function ' Zufallsgenerator initialisieren Randomize

Einstieg

As Long As Long As Long

Einstieg

Dim lngItems Dim i Dim k

43

' Datenfeld mit allen verfügbaren Zahlen füllen For i = 1 To lngItems alngSource(i) = NumberFrom + i - 1 Next ' Schleife durchlaufen. 1 bis Anzahl der gewünschten Zahlen For i = 1 To NumberCount

Einstieg

' Datenfeld in der gewünschten Größe anlegen ReDim alngSource(1 To lngItems) ReDim alngResult(1 To NumberCount)

Einstieg

lngItems = NumberTo - NumberFrom + 1 If NumberCount > lngItems Then NumberCount = lngItems

' Das Element mit dem zufällig gewählten Index auswählen alngResult(i) = alngSource(k)

Einstieg

' Zufallszahl erzeugen k = Int((lngItems) * Rnd) + 1

' Menge der verfügbaren Zahlen anpassen lngItems = lngItems - 1

Einstieg

' Das letzte nicht gewählte Element an die Stelle ' des gewählten verschieben If lngItems > 0 Then alngSource(k) = alngSource(lngItems)

' Array zurückgeben GetRandomNumbers = alngResult End Function

Einstieg

Next

Einstieg

Listing 11 (Forts.)

2471_Excel-VBA.book Seite 44 Dienstag, 4. Dezember 2007 1:42 13

>> Sortieren mit Quicksort

Einstieg

Der Quicksort Algorithmus wurde um 1960 von C. Antony R. Hoare entwickelt, ist seitdem mehrfach verbessert worden und hat sich zum Sortieren größerer Datenmengen bestens bewährt. In der Praxis ist er recht schnell und durch den Einsatz von Rekursionen ist der Programmcode dennoch recht kurz. Da während der Programmausführung lediglich die vorhandenen Elemente untereinander vertauscht werden, hält sich der benötigte Speicherbedarf dennoch in Grenzen.

Einstieg

Einstieg

19

Einstieg

44

Sortieren mit Quicksort

Die Prozedur TestQuicksort legt zu Beginn ein Array mit 10 unsortierten Zahlen an und übergibt es als Argument an die Prozedur QuicksortArray. Da das Array als Referenz übergeben wird, und in der aufgerufenen Prozedur dieses Array sortiert wird, enthält das Array anschließend auch in der aufrufenden Prozedur die Elemente in sortierter Reichenfolge. Zusammen mit dem Originalarray wird das sortierte Array als Zeichenkette in einer Meldungsbox ausgegeben. Das gleiche wird anschließend noch einmal gemacht, das zu sortierende Array enthält aber dabei Text statt Zahlen. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_03_RndShuffleSort.xlsm ' Modul mdl_01_19_Quicksort '===================================================================

Einstieg

Einstieg

Sub TestQuicksort() Dim varNumbers As Variant Dim strAusgabe As String Dim i As Long ' Array anlegen varNumbers = Array( _ 12, 11, 19, 18, 13, 15, 14, 16, 17, 20) ' Originalarray in eine Stringvariable strAusgabe = "" For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next strAusgabe = Left(strAusgabe, Len(strAusgabe) - 1) & vbCrLf

Einstieg

' Mit der Funktion QuickSortArr Array sortieren QuickSortArr varNumbers ' Ergebnis in eine Stringvariable For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next

Einstieg

Listing 12

2471_Excel-VBA.book Seite 45 Dienstag, 4. Dezember 2007 1:42 13

' Array anlegen varNumbers = Array( _ "Mercedes", "Fiat", "Ford", "Jaguar", "Subaru", _ "Opel", "Audi", "Toyota", "BMW", "Alfa Romeo") ' Originalarray in eine Stringvariable strAusgabe = "" For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next strAusgabe = Left(strAusgabe, Len(strAusgabe) - 1) & vbCrLf

Einstieg

' Ausgeben MsgBox Left(strAusgabe, Len(strAusgabe) - 1)

Einstieg

45

Einstieg

>> Einstieg

' Ergebnis in eine Stringvariable For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next

Einstieg

' Array sortieren QuickSortArr varNumbers

Das Grundprinzip von QUICKSORT beruht darauf, den Sortierungsprozess in immer kleinere Häppchen aufzuteilen, die wiederum durch den gleichen Sortieralgorithmus sortiert werden. Die nachfolgenden Erläuterungen gehen von einer Sortierrichtung aus, die von unten nach oben erfolgt. Die gesamte Datenmenge wird dabei durch ein Schnittelement, auch das PIVOTELEMENT genannt, in zwei Teile zerlegt. Als Pivot-Element wird bei dieser Implementierung das Element benutzt, das sich etwa in der Mitte befindet. Die Variable varElement ist in diesem Rezept das angesprochene Pivot-Element. Danach werden nacheinander beide Teile durchlaufen und zwar einmal vom Anfang und zum anderen vom Ende in Richtung des Pivot-Elements. Das aktuelle Element wird dann

Einstieg Einstieg

Die nachfolgende Prozedur QuickSortArr übernimmt als erstes Argument das zu sortierende Array als Referenz. Optional werden die aktuellen Grenzen des Arrays übergeben, die aber lediglich zwischen den rekursiven Aufrufen benötigt werden. Als letztes Argument kann ein Wahrheitswert übergeben werden, der angibt, ob absteigend sortiert werden soll. Wird nichts, oder der Wahrheitswert Falsch übergeben, wird aufsteigend sortiert, ansonsten absteigend.

Einstieg

Listing 12 (Forts.)

Einstieg

' Ausgeben MsgBox Left(strAusgabe, Len(strAusgabe) - 1) End Sub

2471_Excel-VBA.book Seite 46 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

46

>> Sortieren mit Quicksort

jeweils mit dem Pivot-Element verglichen. Die Elemente links von diesem Element sollen am Ende einer Prozedur alle kleiner, die rechts davon größer sein. Ist im Programmverlauf irgendwann ein von links kommendes Element größer, beginnt man die Elemente von rechts kommend, mit dem Pivot-Element zu vergleichen, bis das aktuelle Element auf der rechten Seite kleiner als das Pivot-Element ist. Wenn noch die linke Position kleiner als die rechte ist, werden die zwei Elemente getauscht. Das wird so lange fortgesetzt, bis die aktuelle rechte Position kleiner als die linke Position ist. Anschließend befinden sich im linken Teilbereich nur noch Elemente, die kleiner, und im rechten nur noch Elemente, die größer als das PivotElement sind. Beide Bereiche werden dann jeweils mit dem gleichen, vorher vorgestellten Verfahren bearbeitet. Dazu ruft sich die Prozedur selbst auf und übergibt dabei noch die Grenzen des Teilbereiches, der in der aufgerufenen Prozedur weiter sortiert werden sollen. In der aufgerufenen Prozedur wird wiederum ein Pivot-Element festgelegt, von beiden Seiten kommend werden die Elemente durchlaufen und bei Bedarf getauscht, bis die linke Position größer als die rechte ist. Die zwei entstehenden Teilbereiche werden anschließend wiederum rekursiv mit der gleichen Prozedur bearbeitet. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_03_RndShuffleSort.xlsm ' Modul mdl_01_19_Quicksort '=================================================================== Public Sub QuickSortArr(varArray As Variant, _ Optional ByVal lngLow As Long, _ Optional ByVal lngUp As Long, _ Optional SortDescending As Boolean) ' VarArray wird als Referenz übergeben, deshalb ' wird Originalarray geändert Dim lngLowIndex As Long Dim lngUpIndex As Long Dim varElement As Variant Dim strSort As String Dim varBuffer As Variant

Einstieg

Einstieg

If Not IsArray(varArray) Then Exit Function If lngUp + lngLow = 0 Then ' Grenzen des Arrays bestimmen lngLow = LBound(varArray) lngUp = UBound(varArray) End If Listing 13

2471_Excel-VBA.book Seite 47 Dienstag, 4. Dezember 2007 1:42 13

lngLowIndex = lngLow lngUpIndex = lngUp

47 Einstieg

>> Einstieg

Do If SortDescending Then

Einstieg

' Ein Vergleichselement aus der Mitte der verbleibenden holen varElement = varArray((lngLowIndex + lngUpIndex) / 2)

Do While varArray(lngUpIndex) < varElement lngUpIndex = lngUpIndex - 1 Loop

Einstieg

' Absteigend sortieren Do While varArray(lngLowIndex) > varElement lngLowIndex = lngLowIndex + 1 Loop

Do While varArray(lngUpIndex) > varElement lngUpIndex = lngUpIndex - 1 Loop End If

Einstieg

' Aufsteigend sortieren Do While varArray(lngLowIndex) < varElement lngLowIndex = lngLowIndex + 1 Loop

Einstieg

Else

' Jeweils auf die nächsten Elemente zeigen ' Einmal von unten auf das nächste lngLowIndex = lngLowIndex + 1 ' Von oben auf das nächste lngUpIndex = lngUpIndex - 1

Einstieg

'Die zwei gefundenen Elemente tauschen varBuffer = varArray(lngLowIndex) varArray(lngLowIndex) = varArray(lngUpIndex) varArray(lngUpIndex) = varBuffer

Einstieg

If lngLowIndex > Mischen

Einstieg

48

' So lange, wie der untere Index kleiner ' oder gleich dem oberen ist Loop Until (lngLowIndex > lngUpIndex)

Einstieg

If lngLow < lngUpIndex Then ' Die Prozedur rekursiv aufrufen, mit angepasster ' oberer Grenze. QuickSortArr varArray, lngLow, lngUpIndex, SortDescending End If

Einstieg

If lngLowIndex < lngUp Then ' Die Prozedur rekursiv aufrufen, mit angepasster ' unterer Grenze. QuickSortArr varArray, lngLowIndex, lngUp, SortDescending End If End Function

Einstieg

Hinweis

Einstieg

Listing 13 (Forts.)

20

Wenn mit VBA ein Vergleich von Elementen durchgeführt wird, ist die dabei verwendete Vergleichsmethode wichtig. Beim Sortieren von Text sollte man daher auf Modulebene das Vergleichsverfahren festlegen, beispielsweise mit der Zeile Option Compare Text, die einen Vergleich ohne Berücksichtigung von Groß- bzw. Kleinschreibung vornimmt, oder Option Compare Binary unter Berücksichtigung der Schreibweise.

Mischen

Einstieg

Einstieg

Um aus einem geordneten ein zufällig zusammengewürfeltes Datenfeld zu machen, ist die Funktion Shuffle zum Mischen hervorragend geeignet. Die Prozedur TestShuffle legt zu Beginn ein Array mit 10 sortierten Zahlen an und übergibt es als Argument an die Funktion Shuffle. Zurückgegeben wird ein Array mit den Elementen in sortierter Reihenfolge. Zusammen mit dem Originalarray wird das sortierte Array als Zeichenkette in einer Meldungsbox ausgegeben. Das Gleiche wird anschließend noch einmal gemacht, das zu mischende Array enthält aber dabei sortierten Text statt Zahlen. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_03_RndShuffleSort.xlsm ' Modul mdl_01_20_Shuffle '===================================================================

Einstieg

Listing 14

2471_Excel-VBA.book Seite 49 Dienstag, 4. Dezember 2007 1:42 13

' Array anlegen varNumbers = Array( _ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) ' Originalarray in eine Stringvariable strAusgabe = "" For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next strAusgabe = Left(strAusgabe, Len(strAusgabe) - 1) & vbCrLf

Einstieg Einstieg

Sub TestShuffle() Dim varNumbers As Variant Dim strAusgabe As String Dim i As Long

49

Einstieg

>> Einstieg

' Ergebnis in eine Stringvariable For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next

Einstieg

' Array mit Hilfe der Funktion Shuffle mischen varNumbers = Shuffle(varNumbers)

' Array mit Hilfe der Funktion Shuffle mischen varNumbers = Shuffle(varNumbers)

Einstieg

' Originalarray in eine Stringvariable strAusgabe = "" For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & "," Next strAusgabe = Left(strAusgabe, Len(strAusgabe) - 1) & vbCrLf

Einstieg

' Array anlegen varNumbers = Array( _ "Alfa Romeo", "Audi", "BMW", "Fiat", "Ford", _ "Jaguar", "Mercedes", "Opel", "Subaru", _ "Toyota")

Einstieg

' Ausgeben MsgBox Left(strAusgabe, Len(strAusgabe) - 1)

Listing 14 (Forts.)

Einstieg

' Ergebnis in eine Stringvariable For i = LBound(varNumbers) To UBound(varNumbers) strAusgabe = strAusgabe & varNumbers(i) & ","

2471_Excel-VBA.book Seite 50 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

50

>> Mischen Next

Einstieg

' Ausgeben MsgBox Left(strAusgabe, Len(strAusgabe) - 1) End Sub Listing 14 (Forts.)

Einstieg

Einstieg

Einstieg

Einstieg

In der nachfolgenden Funktion Shuffle durchläuft man nacheinander alle Elemente des übergebenen Datenfeldes, das jeweils aktuelle Element wird anschließend mit einem anderen, zufällig ausgewählten Element vertauscht. VBA bietet, nachdem der Zufallsgenerator mit Randomize initialisiert worden ist, mit der Rnd-Funktion die Möglichkeit, eine zufällige Zahl zwischen Null und eins zu erzeugen. Mit der Anzahl der zu mischenden Elemente multipliziert und abgerundet, bekommt man eine Ganzzahl zwischen 0 und der Anzahl der Elemente minus 1, also wird noch die Zahl 1 hinzugezählt. Das ergibt dann das Element, welches mit dem aktuellen getauscht wird. Als Funktionsergebnis wird das gemischte Array zurückgegeben. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_03_RndShuffleSort.xlsm ' Modul mdl_01_20_Shuffle '=================================================================== Public Dim Dim Dim Dim Dim

Function Shuffle(ByVal varArray As Variant) As Variant i As Long k As Long lngHigh As Long lngLow As Long varDummy As Variant

If Not IsArray(varArray) Then Exit Function On Error Resume Next

Einstieg

' Zufallsgenerator initialisieren Randomize 'Grenzen ermitteln lngHigh = UBound(varArray) lngLow = LBound(varArray)

Einstieg

For i = lngLow To lngHigh Listing 15

2471_Excel-VBA.book Seite 51 Dienstag, 4. Dezember 2007 1:42 13

' Zufallszahl erzeugen k = Int((lngHigh - 1) * Rnd) + lngLow ' Das zufällig gewählte mit dem ' nächsten Element des Bereichs vertauschen varDummy = varArray(k) varArray(k) = varArray(i) varArray(i) = varDummy

Einstieg

51

Einstieg

>> Einstieg

Next

End Function Listing 15 (Forts.)

Einstieg

In den Versionen vor Excel 2007 konnte man damit noch eine eigene Kategorie definieren, ab der aktuellen Version sind alle selbst definierten Funktionen in der Kategorie NEUER EINTRAG eingeordnet. Wird die benutzerdefinierte Funktion als Public deklariert, erscheint sie im Assistenten danach doppelt, einmal als Funktion ohne Beschreibung und einmal mit der selbst angelegten.

Einstieg

Die Funktion Register diente in früheren Versionen (EXCEL 4) einmal dazu, fremde Coderessourcen verfügbar zu machen, deshalb wird diese auch mit der Funktion Application.ExecuteExcel4Macro aufgerufen. Diese Funktion benötigt als Argument eine Zeichenkette, weshalb der größte Teil des Makros sich damit beschäftigt, diesen String zu erzeugen.

Einstieg

Um Funktionsbeschreibungen für benutzerdefinierte Funktionen zu realisieren, gibt es nicht sehr viele Möglichkeiten. In diesem Rezept wird eine Funktion benutzt, die es vor der Zeit von VBA gab und die auch in der aktuellen Version noch funktioniert.

Einstieg

Beschreibung für eigene Funktionen

Einstieg

21

Einstieg

Shuffle = varArray

2471_Excel-VBA.book Seite 52 Dienstag, 4. Dezember 2007 1:42 13

>> Beschreibung für eigene Funktionen

Einstieg

Einstieg

Einstieg

Einstieg

52

Einstieg

Einstieg

Einstieg

Einstieg

Abbildung 9: Funktionsbeschreibung

Man kann die Funktion aber ohne Probleme in einem Modul als Private deklarieren und dann mit dem Excel 4 Makro registrieren. Wird die Mappe unter Excel anschließend geöffnet, sollte man in der Workbook_Open-Prozedur eine erneute Registrierung durchführen, sonst wird bei einer Neuberechnung die Fehlermeldung »#WERT!« angezeigt. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_04_FunctionCategory.xlsm ' Modul DieseArbeitsmappe '=================================================================== ' Im Klassenmodul DieseArbeitsmappe Private Sub Workbook_Open() Call Funktionsbeschreibung_Functionstest End Sub Listing 16

Ohne Registrierung zeigt eine Selektierung der betroffenen Zelle und das anschließende Aufrufen des Funktionsassistenten zwar das korrekte Funktionsergebnis an, die Funktion erscheint aber im Assistenten nicht. Die Zeichenkette, die an die

2471_Excel-VBA.book Seite 53 Dienstag, 4. Dezember 2007 1:42 13

Nachfolgend der Code dazu: '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_04_FunctionCategory.xlsm ' Modul DieseArbeitsmappe '=================================================================== Private Function Functionstest(a, b, c) As String 'Dummy-Funktion, um das Prinzip zu zeigen Functionstest = "Argument 1 =" & a & _ ", Argument 2 =" & b & ", Argument 3 =" & c End Function Listing 17

Einstieg Einstieg Einstieg

REGISTER( ArbeitsblattMitDenTexten!R1C1, ArbeitsblattMitDenTexten!R2C1, "", ArbeitsblattMitDenTexten!R3C1, ArbeitsblattMitDenTexten!R4C1, "1", ArbeitsblattMitDenTexten!R5C1,,, "Funktionsbeschreibung", "Parameterbeschreibung 1", "Parameterbeschreibung 2", "Parameterbeschreibung 3.", "etc. ")

Einstieg

Problematisch ist dabei lediglich eine Begrenzung der Zeichenlänge auf 255 Zeichen. Dem kann aber abgeholfen werden, wenn die einzelnen Parameter nicht im Klartext, sondern als Bezug (in R1C1-Schreibweise) stehen. Als Ziel kann ja ein ausgeblendetes Arbeitsblatt dienen.

Einstieg

REGISTER( "Vorhandene dll", "Vorhandene Funktion in dieser dll", "", "Name der zu beschreibenden Funktion", "Parametername 1,Parametername 2,Parametername 3, etc.", "1", "Neuer/Vorhandener Kategoriename",,, "Funktionsbeschreibung", "Parameterbeschreibung 1", "Parameterbeschreibung 2", "Parameterbeschreibung 3", "etc. ")

Einstieg

EXCEL 4-Funktion zum Registrieren übergeben wird, muss folgendermaßen aufgebaut sein:

Einstieg

53

Einstieg

>> Einstieg

2471_Excel-VBA.book Seite 54 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

Einstieg

54

>> Beschreibung für eigene Funktionen

Public Sub Funktionsbeschreibung_Functionstest() ' Für jede Beschreibung muss eine andere ' API-Funktion benutzt werden. Die Beschreibungen ' gehen beim Beenden verloren. Daher beim Öffnen ' der Mappe automatisch starten lassen. Dim strName As String Dim strParameter As String Dim strDummy As String Dim strCategory As String Dim strDescription As String Dim strArgsDescr(1 To 3) As String Dim strXL4Macro As String Const X1 As String = """" Const X2 As String = "," ' Jede beliebige API-Funktion ' kann benutzt werden. Sie muss nur ' in der entsprechenden .dll vorhanden ' sein. Groß- und Kleinschreibung beachten. strDummy = "kernel32" & X1 & "," & X1 & "GetACP" ' Der Name der zu beschreibenden Funktion strName = "Functionstest"

Einstieg

' Die zukünftigen Parameternamen strParameter = "Variant1,Variant2,Variant3" ' Die Kategorie strCategory = "Neuer Eintrag"

Einstieg

Einstieg

Einstieg

' Hier kommt die allgemeine Beschreibung hin strDescription = "In Schwimmers Funktion werden" & _ " die Parameter angezeigt" ' Die Beschreibung der strArgsDescr(1) = "Der strArgsDescr(2) = "Der strArgsDescr(3) = "Der

einzelnen Parameter erste Parameter " zweite Parameter " dritte Parameter "

' Der String für das Excel4 strXL4Macro = strXL4Macro & strXL4Macro = strXL4Macro & strXL4Macro = strXL4Macro & strXL4Macro = strXL4Macro & strXL4Macro = strXL4Macro & strXL4Macro = strXL4Macro & strXL4Macro = strXL4Macro & Listing 17 (Forts.)

Makro wird erstellt X2 & X1 & X1 X2 & X1 & strName & X1 X2 & X1 & strParameter & X1 X2 & X1 & "1" & X1 X2 & X1 & "" & strCategory & X1 X2 & X2 X2 & X1 & strDescription & X1

2471_Excel-VBA.book Seite 55 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg strXL4Macro strXL4Macro strXL4Macro strXL4Macro

& & & &

X2 & X1 & strArgsDescr(1) & X1 X2 & X1 & strArgsDescr(2) & X1 X2 & X1 & strArgsDescr(3) & ". " & X1 ")"

strXL4Macro = "REGISTER(" & X1 & strDummy & X1 & strXL4Macro ' Das Excel4 Makro wird gestartet Application.ExecuteExcel4Macro strXL4Macro

Einstieg

= = = =

Einstieg

strXL4Macro strXL4Macro strXL4Macro strXL4Macro

55

strName = "Functionstest" strXL4Macro strXL4Macro strXL4Macro strXL4Macro

= = = =

"REGISTER(" strXL4Macro strXL4Macro strXL4Macro

& & & &

X1 X2 X2 X2

& & & &

strDummy & X1 X1 & X1 X1 & strName & X1 X2 & "0)"

Application.ExecuteExcel4Macro strXL4Macro

Einstieg

strDummy = "kernel32" & X1 & "," & _ X1 & "GetACP"

Einstieg

Public Sub UnregisterFunctionsbeschreibung_Functionstest() Dim strName As String Dim strXL4Macro As String Dim strDummy As String Const X1 As String = """" Const X2 As String = ","

Einstieg

End Sub

strXL4Macro = "UNREGISTER(" & strName & ")"

Einstieg

Application.ExecuteExcel4Macro strXL4Macro End Sub Listing 17 (Forts.)

Kommentare sind hervorragend dazu geeignet, Zusatzinformationen bereitzustellen, beispielsweise um einem Benutzer das Ausfüllen eines Formulars zu erleichtern. Kommentare sind kleine Textfenster, die beliebig formatiert und sogar mit Bildern bestückt werden können. Um in einer Zelle manuell einen Kommentar einzufügen, klickt man die entsprechende Zelle mit der rechten Maustaste an. In dem sich öffnenden Kontextmenü wird

Einstieg

Kommentare hinzufügen

Einstieg

22

2471_Excel-VBA.book Seite 56 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

56

>> Kommentare hinzufügen

anschließend der Eintrag NEUER KOMMENTAR gewählt und man kann sofort Text eingeben.

Einstieg

Einstieg

Nach einem weiteren Rechtsklick auf den markierten Textrahmen oder die markierten Buchstaben können Sie in dem sich öffnenden Kontextmenü der Eintrag KOMMENTAR FORMATIEREN wählen und das Aussehen auf vielfältige Weise anpassen. Leider funktioniert das Aufzeichnen von Kommentarformatierungen mit dem Makrorecorder nicht bei Formatierungen, die man auf den Textrahmen (TextFrame) anwendet, während Formatierungen, die sich auf das Shape-Objekt beziehen, ohne Probleme aufgezeichnet werden. In diesem TextFrame, einem Bestandteil des Shape-Objektes, können einzelne Buchstaben unterschiedlich formatiert werden, während die Textformatierungen, die auf das übergeordnete Objekt Shape angewendet werden, für den komplett enthaltenen Text gelten. Die Funktion Characters liefert ein Objekt, welches einzelne oder Gruppen von Buchstaben repräsentiert. Function Characters([Start], [Length]) As Characters

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Dieses Objekt besitzt die Eigenschaft Font, welche die Schriftart mit allen Eigenschaften wie Farbe oder Aussehen festlegt oder zurückgibt. Im folgenden Bild (Abbildung 10) ist ein mittels VBA erzeugter und formatierter Kommentar zu sehen.

Abbildung 10: Kommentar

Zu Beginn werden in der Prozedur FormatComments alle Kommentare eingeblendet. Um Fehlermeldungen zu vermeiden, wird mit Is Nothing daraufhin geprüft, ob in der Zielzelle bereits ein Kommentar existiert. Ist das nicht der Fall, fügt man einen neuen mit dem Text »Hello World« hinzu. Anschließend wird das Shape-Objekt formatiert: Sie setzen dabei die Transparenz und die Vordergrundfarbe des Kommentars. Dazu wird die Eigenschaft Fill des ShapeObjektes modifiziert, gesetzt werden dabei die zwei Eigenschaften Transparency und ForeColor, die in der Klasse FillFormat definiert sind. Nun können Sie daran gehen, die Texteigenschaften anzupassen. Dazu bedienen Sie sich der Eigenschaften des Textrahmens (TextFrame) und modifizieren die einzelnen Zeichen. Man hat aber bei der vorliegenden Officeversion mit dem Problem zu kämpfen, dass bei einem Text mit unterschiedlichen Schriftgraden ein Fehler ausgelöst wird, sobald man Zeichen formatieren will. Möglicherweise werden die Probleme bei späteren Updates gefixt, momentan muss man aber leider damit leben.

2471_Excel-VBA.book Seite 57 Dienstag, 4. Dezember 2007 1:42 13

>> Einstieg

Sub FormatComments() With Worksheets("Kommentare").Range("A1") ' Kommentare einblenden Application.DisplayCommentIndicator = _ xlCommentAndIndicator ' Ist kein Kommentar vorhanden, einen neuen ' hinzufügen If .Comment Is Nothing Then _ .AddComment Text:="Hello World" With .Comment.Shape ' Transparenz einstellen .Fill.Transparency = 0.5

Einstieg Einstieg

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_05_Comments.xlsm ' Tabelle Kommentare ' Modul mdl_01_22_CommentFormat '===================================================================

Einstieg

Anschließend wird das Shape-Objekt formatiert, und zwar werden die Transparenz und die Vordergrundfarbe des Kommentars gesetzt. Dazu wird die Eigenschaft Fill des Shape-Objektes modifiziert, gesetzt werden dabei die zwei Eigenschaften Transparency und ForeColor, die in der Klasse FillFormat definiert sind.

Einstieg

Bei der Textfarbe funktioniert lediglich der COLORINDEX, das Setzen der Color-Eigenschaft führt zwar zu keiner Fehlermeldung, bringt aber auch nicht den gewünschten Erfolg. Mit Hilfe der Funktion ConvertRgbToColorIndex aus dem Rezept 16 kann man einen RGB-Wert in den ähnlichsten aktuell gültigen Colorindex umwandeln.

Einstieg

Die Fehlermeldungen kann man nur umgehen, indem man den Schriftgrad vorher einheitlich macht. Anschließend formatiert man die gewünschten Zeichen, wobei die Änderung des Schriftgrades zuletzt erfolgen sollte, um die schon angesprochene Fehlermeldung zu vermeiden.

Einstieg

57

With .TextFrame ' Bei unterschiedlichen Schriftgraden ' gibt es Probleme. Vorher zurücksetzen .Characters.Font.Size = 8

Einstieg

' Die Farbe der Kommentarbox auf rot verändern .Fill.ForeColor.RGB = RGB(255, 0, 0)

Einstieg

Listing 18

2471_Excel-VBA.book Seite 58 Dienstag, 4. Dezember 2007 1:42 13

>> Kommentare als Bildcontainer

Einstieg

58

' .Characters.Font.ColorIndex = _ xlColorIndexAutomatic

Einstieg

' Buchstaben 1-5 rot .Characters(1, 5).Font.ColorIndex = 8 ' Buchstaben 1-2 kursiv .Characters(1, 2).Font.Italic = True

Einstieg

' Buchstaben 10-11 weiß .Characters(10, 2).Font.ColorIndex = _ ConvertRgbToColorIndex(vbWhite) ' Buchstaben 7-9 grün .Characters(7, 3).Font.ColorIndex = _ ConvertRgbToColorIndex(RGB(0, 255, 0))

Einstieg

' Buchstaben 3-5 Schriftgröße 15 .Characters(3, 3).Font.Size = 15 End With ' .TextFrame... End With ' .Comment.Shape End With ' ...Range("A1")

Einstieg

End Sub Listing 18 (Forts.)

Einstieg

Einstieg

Einstieg

23

Kommentare als Bildcontainer

Kommentare können neben der Darstellung reiner Textinformationen auch als Container für Bilder dienen, die wie normale Kommentare durch das Überfahren mit dem Mauszeiger angezeigt werden. Diese Funktionalität ist seit Excel 97 verfügbar, aber leider etwas versteckt untergebracht. Am besten ist der Dialog über das Kontextmenü KOMMENTAR BEARBEITEN erreichbar, der sich nach einem Rechtsklick auf die Zelle mit dem Kommentar öffnet. Anschließend klickt man auf den Rahmen des Kommentarfeldes und wählt KOMMENTAR FORMATIEREN. Auf der Registerkarte FARBEN UND LINIEN des sich öffnenden Dialogs klickt man auf das Dropdownfeld AUSFÜLLEN/FARBE und dort auf FÜLLEFFEKTE. Im nächsten Dialog hat man nun die Möglichkeit, eine Grafik als Hintergrund zu wählen.

2471_Excel-VBA.book Seite 59 Dienstag, 4. Dezember 2007 1:42 13

59

Der Kommentar wurde auf der Registerkarte ÜBERPRÜFEN in der Gruppe KOMMENTARE über das Icon ALLE KOMMENTARE ANZEIGEN (Abbildung 12) dauerhaft eingeblendet. Das dauerhafte Anzeigen lässt sich auch mit folgenden beiden Codezeilen aus- bzw. einschalten. Application.DisplayCommentIndicator = xlCommentIndicatorOnly Application.DisplayCommentIndicator = xlCommentAndIndicator

Einstieg Einstieg

In diesem Rezept wird eine ausgewählte Bilddatei als Hintergrundbild eines Kommentars in eine Zelle eingefügt. Zusätzlich wird in diese Zelle ein Hyperlink eingesetzt, der auf die Datei verweist. Benutzt wird dafür eine Datei, welche im Programmverzeichnis von Windows zu finden sein dürfte, nämlich Angler.bmp. Ist diese Datei auf dem Zielsystem, sprich dem Rechner des Anwenders nicht vorhanden oder existiert der Pfad dorthin nicht, funktioniert der Link natürlich nicht. Das Bild ist aber unabhängig davon dennoch zu sehen, da es intern in der Mappe gespeichert wird.

Einstieg

Abbildung 11: Grafik als Hintergrund einfügen

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

>> Einstieg

2471_Excel-VBA.book Seite 60 Dienstag, 4. Dezember 2007 1:42 13

>> Kommentare als Bildcontainer

Einstieg

Anschließend legt man in der Zelle, die den Kommentar enthält, einen Hyperlink an, der auf die Zieldatei verweist. Über die DisplayCommentIndicator-Eigenschaft werden dann noch alle eventuell sichtbaren Kommentare ausgeblendet.

Einstieg

Einstieg

Abbildung 12: Kommentare als Bildcontainer

Einstieg

Einstieg

Einstieg

Einstieg

60

In der Prozedur TestAddPicture wird mit Hilfe der GetOpenFilename-Methode eine Datei ausgewählt und der Name inklusive dem Pfad zurückgeliefert. Dieser Pfad wird zusammen mit der Zielzelle, dem anzuzeigenden Kommentar und der Bildhöhe an die Prozedur AddPictureAsComment übergeben.

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_06_PictureShow.xlsm ' Tabelle Grafik als Kommentar ' Modul mdl_01_23_CommentPicture '=================================================================== Public Dim Dim Dim

Sub TestAddPicture() strFilename As Variant strFilter As String rngDest As Range

' Ziel des Kommentars festlegen Set rngDest = Worksheets("Grafik als Kommentar").Range("A1")

Einstieg

Listing 19

2471_Excel-VBA.book Seite 61 Dienstag, 4. Dezember 2007 1:42 13

' Filter zur Dateiauswahl strFilter = "Bitmaps (*.bmp), *.bmp" _ & ",Gif Files (*.gif),*.gif" _ & ",JPG Files (*.jpg),*.jpg" _ & ",JPEG Files (*.jpeg),*.jpeg" _ & ",WMF Files (*.wmf),*.wmf" ' Dialog Dateiauswahl starten strFilename = Application.GetOpenFilename(strFilter)

Einstieg

61

Einstieg

>> Einstieg

AddPictureAsComment rngDest, CStr(strFilename), _ CStr(strFilename), 200

Einstieg

' Abbrechen, wenn nichts gewählt If strFilename = False Then Exit Sub

Application.DisplayCommentIndicator = xlCommentIndicatorOnly ' Application.DisplayCommentIndicator = xlCommentAndIndicator End Sub

Einstieg

rngDest.Worksheet.Hyperlinks.Add rngDest, CStr(strFilename), _ , , Dir(strFilename)

Das zu Beginn mit der LoadPicture-Methode in den Speicher geladene Bild liefert die Höhe und Breite in der Einheit Himetric, das sind 1/1000 cm. Teilt man diesen Wert durch 1000, erhält man die Angabe in cm, teilt man durch 2540, bekommt man die Abmessungen in Zoll. Für das Kommentarfeld werden Angaben aber in Punkt benötigt, wobei 1 Punkt 1/72 Zoll groß ist. Indem man also die Himetric-Angabe durch 2540 teilt und mit 72 malnimmt, erhält man die Abmessung in Punkt. Mit Hilfe des errechneten Skalierungsfaktors kann man nun die gewünschte Breite und Höhe des Kommentarfeldes berechnen und es entsprechend anpassen.

Einstieg

Zu Beginn wird mit der LoadPicture-Methode versucht, das Bild in den Speicher zu laden, existiert es nicht, wird die Funktion verlassen. Anschließend wird in der Zielzelle ein eventuell vorhandener Kommentar gelöscht und danach ein neuer hinzugefügt. Wurde an die Funktion eine Kommentarhöhe übergeben, was man daran erkennt, dass der Parameter PicHeight größer als Null ist, wird das Verhältnis von gewünschter zu vorhandener Höhe berechnet und in der Variablen dblScale gespeichert. Anschließend wird mit der UserPicture-Methode das Bild als Füllung des Kommentarfeldes geladen.

Einstieg

Mit Hilfe der Prozedur AddPictureAsComment wird das ausgewählte Bild in das Kommentarfeld gebracht.

Einstieg

Listing 19 (Forts.)

Einstieg

Die als Parameter strComment übergebene Stringvariable liefert den Text, der im Kommentarfeld angezeigt wird.

2471_Excel-VBA.book Seite 62 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

62

>> Kommentare als Bildcontainer

'=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_06_PictureShow.xlsm ' Tabelle Grafik als Kommentar ' Modul mdl_01_23_CommentPicture '=================================================================== Public Sub AddPictureAsComment(Dest As Range, _ Source As String, Optional strComment As String, _ Optional PicHeight As Double = 0) Dim objPic As IPictureDisp Dim objComment As Comment Dim dblScale As Double On Error Resume Next

Einstieg

' Bild wegen Abfrage der Größe laden Set objPic = LoadPicture(Source) ' Abbrechen, wenn kein Bild If objPic Is Nothing Then Exit Sub ' Kommentar in Zielzelle löschen Dest.ClearComments

Einstieg

Einstieg

Einstieg

' Kommentar in Zielzelle hinzufügen Set objComment = Dest.AddComment ' Skalierung berechnen If PicHeight > 0 Then dblScale = PicHeight / (objPic.Height * 72 / 2540) Else dblScale = 1 End If ' Kommentar mit Bildhintergrund und Text füllen With objComment .Shape.Fill.UserPicture Source .Shape.Height = (objPic.Height * 72 / 2540) * dblScale .Shape.Width = (objPic.Width * 72 / 2540) * dblScale .Text Text:=strComment End With End Sub

Einstieg

Listing 20

2471_Excel-VBA.book Seite 63 Dienstag, 4. Dezember 2007 1:42 13

WMI (WINDOWS MANAGEMENT INSTRUMENTATION) ist eine API (APPLICATION PROGRAMMING INTERFACE), welche standardisierte Schnittstellen zum Auslesen und Bearbeiten der unterschiedlichsten Windows-Funktionen und Datenlieferanten bereitstellt. WMI steht standardmäßig unter Windows XP, 2000 und Me zur Verfügung. Für andere Versionen, beispielsweise Windows NT oder Windows 9x, kann es nachinstalliert werden.

WMI verwendet die Sprache WMI QUERY LANGUAGE (WQL), die STRUCTURED QUERY LANGUAGE (SQL) ähnelt. Damit ist es möglich, gezielt Informationen auszulesen. Wer

Einstieg

Zu Beginn verschafft man sich ein NAMESPACE-Objekt (GetObject("winmgmts:\\" & strComputer & "\" & strNameSpace)). Die Variable strComputer enthält dabei den Computernamen, welcher angesprochen werden soll, ein einfacher Punkt steht für den aktuellen Computer. Die Variable strNameSpace enthält den NAMESPACE, in unserem Rezept ist das \root\cimv2. Man kann es sich so vorstellen, dass ein NAMESPACE ein Container wie ein Verzeichnis ist und die Klassen darin Objekte mit Eigenschaften und Methoden sind. Die Klassen, welche in diesem Rezept benutzt werden, stecken im NAMESPACE root\cimv2.

Einstieg

Abbildung 13: Auslesen von Informationen

Einstieg

Einstieg

Einstieg

Damit können sich Administratoren beliebige Informationen über Rechner verschaffen, welche über das Netzwerk verfügbar sind und über die der Administrator die notwendigen Rechte für die Operation besitzt. Es besteht mit WMI sogar die Möglichkeit, Änderungen vorzunehmen. Sie können damit zwar keinen Prozessor oder die Hauptplatine wechseln, aber beispielsweise Dienste starten oder stoppen.

Einstieg

Systeminformationen mit WMI

Einstieg

24

63

Einstieg

>> Einstieg

2471_Excel-VBA.book Seite 64 Dienstag, 4. Dezember 2007 1:42 13

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

Einstieg

64

>> Systeminformationen mit WMI

sich mit Datenbanken auskennt, sollte damit keine Probleme haben. Mit der Methode ExecQuery wird die WQL-Anweisung übergeben, im einfachsten Fall besteht die Anweisung aus dem Text »SELECT PROPERTY FROM KLASSE«, wobei PROPERTY für die Eigenschaft und KLASSE für den Klassennamen steht. Als PROPERTY kann auch der Stern benutzt werden, in diesem Fall werden alle Eigenschaften zurückgeliefert. In einer For ... Each-Schleife werden erst alle untergeordneten Objekte des von der Methode ExecQuery zurückgelieferten Objektes angesprochen, in einer weiteren Schleife alle Eigenschaften dieser Objekte ausgelesen und auf dem Tabellenblatt mit Namen und Wert ausgegeben. Das Ignorieren von Fehlern durch die On Error Resume Next-Anweisung wurde deshalb eingebaut, weil sich manche Eigenschaftswerte nicht ohne weiteres in eine Zeichenkette umwandeln lassen, beispielsweise dann, wenn es sich um ein Array handelt. '=================================================================== ' Auf CD Buchdaten\Beispiele\01_Einstieg\ ' Dateiname 01_07_WMI.xlsm ' Tabelle Infos ' Modul Tabelle Infos '=================================================================== Private Sub cmdInfos_Click() Const strComputer As String = "." Dim varClass As Variant Dim objItem As Object Dim objProperties As Object Dim strClass As String Dim i As Long On Error Resume Next ' Klassennamen auslesen strClass = Me.Range("A2") ' Ausgabebereich löschen Me.Range("C2:D100000").Clear

Einstieg

Einstieg

i = 2 ' Alle verfügbaren Eigenschaften der gewählten Klasse im ' Namespace /root/cimv2 auslesen. VarClass enthält als ' Collection alle Objekte mit Eigenschaften Set varClass = GetObject("winmgmts://" _ & strComputer _ & "/root/cimv2").ExecQuery( _ Listing 21

2471_Excel-VBA.book Seite 65 Dienstag, 4. Dezember 2007 1:42 13

"SELECT * FROM " _ & strClass)

65 Einstieg

>> Einstieg

With objProperties Me.Cells(i, 3) = .Name Me.Cells(i, 4) = .Value i = i + 1 DoEvents End With

Einstieg

For Each objProperties In objItem.Properties_ ' Jede Eigenschaft ansprechen, Name und Wert ausgeben

Einstieg

For Each objItem In varClass ' Jedes Objekt ansprechen

Next objProperties

Einstieg Einstieg Einstieg

Listing 21 (Forts.)

Einstieg

End Sub

Einstieg

Next objItem

2471_Excel-VBA.book Seite 66 Dienstag, 4. Dezember 2007 1:42 13

Allgemein Eine Formel kann Werte oder Zellbezüge zu anderen Zellen enthalten, die nach Berechnung der Formel als Ergebnis in der Formelzelle angezeigt werden. Das folgende Beispiel können Sie in der Beispieldatei im Tabellenblatt ZIRKELBEZUG austesten.

Allgemein

Abbildung 14: Formel mit Werten

Allgemein

Formeln mit Zirkelbezügen berechnen

Allgemein

25

Allgemein

2471_Excel-VBA.book Seite 67 Dienstag, 4. Dezember 2007 1:42 13

Dies wird als Zirkelbezug bezeichnet und es wird ein Meldungsfenster mit dem Hinweis eingeblendet, dass ein Zirkelbezug vorliegt. Nachdem Sie die Schaltfläche OK gedrückt haben, wird ein Hilfefenster mit weiteren Informationen zum Thema eingeblendet.

Abbildung 16: Warnhinweis bei Zirkelbezügen

Allgemein

B2=A2+B2

Allgemein

Problematisch wird es, wenn sich eine Formel direkt oder indirekt auf ihre eigene Zelle bezieht.

Allgemein

Abbildung 15: Formel mit Zellbezügen

Allgemein

Die Statusleiste zeigt anschließend das Wort ZIRKELBEZÜGE an, gefolgt von einem Bezug auf eine der Zellen, die im Zirkelbezug enthalten sind. Wenn das Wort ZIRKEL-

2471_Excel-VBA.book Seite 68 Dienstag, 4. Dezember 2007 1:42 13

>> Formeln mit Zirkelbezügen berechnen

ohne Angabe eines Zellbezugs angezeigt wird, ist der Zirkelbezug nicht im aktiven Arbeitsblatt aufgetreten.

BEZÜGE

Wenn in einer beliebigen geöffneten Arbeitsmappe der Excel-Instanz ein oder mehrere Zirkelbezüge vorliegen, ist die Schaltfläche ZIRKELVERWEISE im Register START | FORMELÜBERWACHUNG | FEHLERÜBERPRÜFUNG aktivierbar. Mit einem Klick auf diese Schaltfläche wird eine Liste mit den genauen Bezügen angezeigt. Befinden sich die Zirkelbezüge auf einem anderen Tabellenblatt als dem gerade aktiven oder in einer anderen Arbeitsmappe, wird die genaue Referenzierung angezeigt. Über die Optionen SPUR ZUM VORGÄNGER und SPUR ZUM NACHFOLGER in der Gruppe FORMELÜBERWACHUNG werden durch Pfeilmarkierungen die betroffenen Bezüge auf dem Tabellenblatt dargestellt.

Allgemein

Allgemein

Allgemein

Allgemein

68

Um einen Zirkelbezug dennoch zu berechnen, klicken Sie auf die OFFICE-Schaltfläche gefolgt von einem Klick auf die Schaltfläche EXCEL-OPTIONEN und aktivieren in der Kategorie FORMELN im Abschnitt BERECHNUNGSOPTIONEN das Kontrollkästchen ITERATIVE BERECHNUNG AKTIVIEREN. Stellen Sie den Wert MAXIMALE ITERATIONSZAHL auf den Wert 1. Der Zirkelbezug wird durch diese Einstellungen aufgehoben und die Berechnung der Formel durchgeführt. Bei jeder Neuberechnung der Arbeitsmappe wird ebenfalls eine Neuberechnung der Formel mit dem Zirkelbezug vorgenommen, was zu falschen Ergebnissen führt. Deaktivieren Sie deshalb die automatische Neuberechnung, indem Sie die Option MANUELL aktivieren, und entfernen Sie den Haken vor VOR DEM SPEICHERN NEU BERECHNEN. Eine Neuberechnung der gesamten Arbeitsmappe erreichen Sie dann über die Taste (F9).

Allgemein

Allgemein

Allgemein

Allgemein

Abbildung 17: Überprüfung von Zirkelbezügen

Abbildung 18: Einstellungen zur Zirkelberechnung

2471_Excel-VBA.book Seite 69 Dienstag, 4. Dezember 2007 1:42 13

69

Allgemein

Nachdem die Einstellungen laut Abbildung 18 vorgenommen wurden, verschwindet der Zirkelbezug-Hinweis in der Statuszeile und die Formel wird berechnet.

Allgemein

>> Allgemein

Public Sub IterationOn() With Application .Iteration = True .Calculation = xlCalculationManual .CalculateBeforeSave = False .MaxIterations = 1 .MaxChange = 0.001 End With End Sub Public Sub IterationOff() With Application .Iteration = False .Calculation = xlAutomatic End With End Sub

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_01_SumMyself.xlsm ' Tabelle Zirkelbezug ' Modul mdl_01_Iteration ‘==============================================================

Allgemein

Im Tabellenblatt ZIRKELBEZUG werden über zwei Schaltflächen die Makros IterationOn zur Aktivierung und IterationOff zur Deaktivierung der Iteration ausgeführt.

Allgemein

Mit VBA können Sie ebenfalls die ITERATION einstellen. Bei den folgenden Prozeduren ist es wichtig, die Reihenfolge der Befehle einzuhalten, da das Ergebnis der Formel sonst durch Mehrfachberechnungen verfälscht würde.

Allgemein

Geben Sie jetzt in die Zelle A2 eine neue Zahl ein, so wird die Formel in Zelle B2 erst durch eine manuelle Neuberechnung (F9) aktualisiert. Jede weitere Neuberechnung addiert den Wert der Zelle A2 zu dem aktuellen Wert in B2.

Allgemein

Abbildung 19: Formelberechnung mit Zirkelbezug

Allgemein

Listing 22

2471_Excel-VBA.book Seite 70 Dienstag, 4. Dezember 2007 1:42 13

>> VBA-Addition mit eigenem Zellenwert

Allgemein

Allgemein

Allgemein

Allgemein

70

26

VBA-Addition mit eigenem Zellenwert

Dass Excel nicht dafür konzipiert ist, mit Zirkelbezügen zu arbeiten, haben Sie in dem vorherigen Beispiel an den vielen Einstellungen, die vorgenommen werden müssen, gesehen. Ebenso sind die weiteren Nachteile, wie manuelle Neuberechnung, oft nicht erwünscht. Mit VBA ist es ohne weiteres möglich, eine Berechnung, welche sich direkt oder indirekt auf ihre eigene Zelle bezieht, ohne die Verwendung der Iteration vorzunehmen. Zum direkten Vergleich verwenden wir das Formelbeispiel aus Rezept 25. Dieses Beispiel befindet sich im Tabellenblatt ZIRKELBEZUG der Beispieldatei. Bei einer Änderung der Eingabezelle E2 soll der Wert der Zelle F2 zu dem neuen Wert aus E2 addiert werden. Dazu setzen wir das Worksheet_Change-Ereignis der Tabelle ein. Da die Prozedur nur ausgeführt werden soll wenn sich der Wert der Zelle E2 ändert, wird zu Beginn der Prozedur ermittelt, ob das Ereignis durch eine Änderung des Wertes in Zelle E2 ausgelöst wurde. Die Ereignis-Prozedur wird beendet, wenn ein anderer Zellbezug der Auslöser für das Aufrufen des Ereignisses war. In der Prozedur sollen Zahlenwerte berechnet werden. Bei Texteingaben in Zelle E2 würde Excel versuchen einen Zahlenwert mit einem Textwert zu berechnen, was zu einer Fehlermeldung führen würde. Mit der IsNumeric-Funktion wird überprüft, ob es sich bei der Eingabe um eine Zahl oder Text handelt. Bei einem Textwert erfolgt ein Meldungsfenster und die Eingabezelle wird daraufhin wieder markiert und die Prozedur verlassen.

Allgemein

Ist die Eingabe wie erwartet ein Zahlenwert, wird der Wert der Zelle E2 zu dem Wert der Zelle F2 hinzuaddiert und in die Zelle F2 geschrieben. Schalten Sie vor dem Schreiben des Wertes in Zelle F2 alle Ereignisse mit der EnableEvents-Eigenschaft aus, damit das Worksheet_Change-Ereignis nicht nochmals ausgelöst und der Zellenwert aus E2 erneut zu F2 addiert wird. Anschließend muss die

EnableEvents-Eigenschaft unbedingt wieder eingeschalten werden, da sonst in der

Allgemein

Allgemein

gesamten Excel-Anwendung alle Ereignis-Prozeduren bis auf Widerruf oder ExcelNeustart deaktiviert bleiben. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_01_SumMyself.xlsm ' Tabelle Zirkelbezug ' Ereignis Klassenmodul Zirkelbezug ‘============================================================== Private Sub Worksheet_Change(ByVal Target As Range) ' Geänderte Zelle überprüfen If Target.Address "$E$2" Then Exit Sub

Allgemein

' Prüfung, ob Eingabe eine Zahl ist If Not IsNumeric(Target.Value) Then MsgBox "Eingabe muss eine Zahl sein", _ Listing 23

2471_Excel-VBA.book Seite 71 Dienstag, 4. Dezember 2007 1:42 13

Listing 23 (Forts.)

27

Zellenwert kumulieren

Im Listing 23 haben wir Ihnen gezeigt, dass es mit der Funktion ITERATION möglich ist, Formeln zu erstellen, welche zusätzlich zu Werten aus Bezügen ihren eigenen Zellenwert mit berechnen können. Das geht mit einer einzigen Zelle allerdings nicht. Sie können in eine Zelle entweder einen Wert bzw. Text oder eine Formel eingeben. Angenommen, Sie haben in Zelle A1 den Wert 20 stehen und wollen zu diesem Wert die Zahl 10 addieren. Entweder rechnen Sie das Ergebnis im Kopf oder mit einem Taschenrechner aus und ersetzen in A1 den Wert 20 durch 30, oder Sie verwenden in Zelle A1 die Formel =20+10. Mit Hilfe einiger VBA-Befehle kann man ganz bequem Zahlen nacheinander in eine Zelle eingeben, welche dann mit dem vorherigen Wert in dieser Zelle verrechnet werden. Im Tabellenblatt KUMULIEREN der Beispieldatei werden alle Werte, die in die Zelle F13 eingegeben werden, addiert. Enthält die Zelle F13 den Wert 20 und Sie überschreiben diesen Zellenwert durch den Wert 10, wird in Zelle F13 der berechnete Wert 30 angezeigt. Ebenso werden negative Eingaben vom Vorwert abgezogen. Das Wichtigste ist hierbei, dass Excel sich den vorherigen Wert merken muss, um ihn mit dem neuen Wert verrechnen zu können. Dazu wird der Wert der Zelle F13 zunächst beim Öffnen der Datei an die öffentliche Variable gdblRemember übergeben.

Allgemein Allgemein

' Ereignisse aktivieren Application.EnableEvents = True End Sub

Allgemein

' Eingabewert zu Gesamtwert addieren With Range("F2") .Value = .Value + Target.Value End With

Allgemein

' Ereignisse deaktivieren Application.EnableEvents = False

Allgemein

Target.Select Exit Sub End If

Allgemein

vbCritical, _ "Eingabefehler"

Allgemein

71

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 72 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

72

>> Zellenwert kumulieren

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_01_SumMyself.xlsm ' Ereignis DieseArbeitsmappe ‘============================================================== Private Sub Workbook_Open() gdblRemember = Worksheets("Kumulieren").Range("F13").Value End Sub

Allgemein

Allgemein

Listing 24

Die Deklarierung dieser öffentlichen Variablen wird in einem allgemeinen Modul hinterlegt, damit alle Prozeduren dieser Arbeitsmappe auf die Variable gdblRemember und deren Wert Zugriff haben. Der jeweilige Wert bleibt auch nach Beendigung der Prozeduren im Speicher erhalten. '============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_01_SumMyself.xlsm ' Ereignis mdl_02_Deklare '============================================================== Public gdblRemember As Double

Allgemein

Allgemein

Allgemein

Allgemein

Listing 25

Bei jeder Zelländerung im Tabellenblatt KUMULIEREN wird das Worksheet_ChangeEreignis ausgelöst. Hier wird mittels Target.Address geprüft, ob die Zelle F13 geändert wurde, da nur die Werte dieser Zelle kumuliert werden sollen. Die Prozedur wird beendet, wenn eine andere Zelle der Auslöser für das Ereignis war. Bevor wir zum eigentlichen Rechenvorgang kommen, müssen noch mögliche Fehlerquellen, wie zum Beispiel Texteingaben oder das Löschen des Zellenwertes, abgefangen werden. Target.Value enthält den Wert der Zelle F13 und wird im Code dazu verwendet, die gemachte Eingabe auszuwerten. Wurde der Zellinhalt gelöscht, enthält Target.Value einen Leerstring (""). Die Variable gdblRemember erhält infolgedessen den Wert 0 und die Prozedur wird verlassen. Ist die Eingabe keine Zahl, wird mit der Undo-Methode die letzte Benutzeraktion vor der Ausführung des Makros, also die Eingabe in Zelle F13, rückgängig gemacht und anschließend die Prozedur verlassen. Der Wert der Variablen gdblRemember bleibt dabei unverändert. Die Undo-Methode muss im Makro aufgerufen werden, bevor durch das Makro Änderungen im Tabellenblatt vorgenommen werden. Visual Basic-Befehle können mit dieser Methode nicht rückgängig gemacht werden.

2471_Excel-VBA.book Seite 73 Dienstag, 4. Dezember 2007 1:42 13

Private Sub Worksheet_Change(ByVal Target As Range) With Target ' Geänderte Zelle überprüfen If .Address "$F$13" Then Exit Sub ' Überprüfung, ob Eingabe leer ist If .Value = "" Then gdblRemember = 0 Exit Sub End If ' Überprüfung, ob Eingabe eine Zahl ist If Not IsNumeric(Target.Value) Then With Application .EnableEvents = False .Undo .EnableEvents = True End With

Allgemein Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_01_SumMyself.xlsm ' Ereignis Klassenmodul Kumulieren ‘==============================================================

Allgemein

Ist die Eingabe eine Zahl gewesen, dann wird zu dem Eingabewert der Wert der Variablen gdblRemember addiert und in die Zelle F13 geschrieben. Dieser neue Wert wird für die nächste Berechnung an der Variable gdblRemember übergeben. Um fortlaufend Eingaben in die Zelle F13 machen zu können wird als letzter Befehl in der Prozedur diese Zelle wieder selektiert.

Allgemein

Um Visual Basic-Befehle rückgängig zu machen verwendet man die OnUndoMethode Weitere Informationen und Beispiele zu dieser Methode finden Sie in der Kategorie »Ereignisse«.

Allgemein

73

Allgemein

Hinwei s

>> Allgemein

' Eingabewert zu vorherigem Wert addieren .Value = .Value + gdblRemember Listing 26

Allgemein

' Ereignisse deaktivieren Application.EnableEvents = False

Allgemein

Exit Sub End If

2471_Excel-VBA.book Seite 74 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

74

>> Welche Zellen sind gesperrt? ' Ereignisse aktivieren Application.EnableEvents = True

Allgemein

' Aktuellen Wert in globaler Variablen speichern gdblRemember = .Value ' Eingabezelle aktivieren .Select End With End Sub

28

Welche Zellen sind gesperrt?

Standardmäßig sind alle Zellen eines Tabellenblattes gesperrt und die Option AUSGEBLENDET ist deaktiviert. Diese Einstellungen können Sie im Dialog ZELLEN FORMATIEREN einsehen und einstellen. Sie zeigen diesen Dialog an über den Register START in der Gruppe ZELLEN | FORMAT | ZELLEN FORMATIEREN auf der Registerkarte SCHUTZ oder im KONTEXTMENÜ der Zelle über ZELLE FORMATIEREN oder über die Tastenkombination (Strg) (1).

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Listing 26 (Forts.)

Abbildung 20: Standardeinstellung des Zellenschutzes

Die Option GESPERRT verhindert, dass markierte Zellen geändert, verschoben, in ihrer Größe verändert oder gelöscht werden. Die Option AUSGEBLENDET blendet die Formel in einer Zelle aus, so dass diese beim Markieren der Zelle nicht in der Bearbeitungszeile angezeigt wird.

2471_Excel-VBA.book Seite 75 Dienstag, 4. Dezember 2007 1:42 13

Das Sperren und Ausblenden von Zellen ist nur bei geschützten Blättern wirksam. Um ein Tabellenblatt zu schützen, aktivieren Sie unter START | ZELLEN | FORMAT | SCHUTZ | BLATT SCHÜTZEN das Kontrollkästchen ARBEITSBLATT UND INHALT GESPERRTER ZELLEN SCHÜTZEN und vergeben bei Bedarf ein Kennwort zum Aufheben des Blattschutzes. Standardmäßig ist es in Excel nicht möglich den Sperrstatus einer Zelle per Formel ausgeben zu lassen. Aber mit Hilfe eines Excel4-Makros oder einer benutzerdefinierten VBA-Funktion können Sie dies erreichen. Für die Excel4-Makro-Lösung definieren Sie im NAMENS-MANAGER über START | DEFINAMEN | NAMENS-MANAGER einen neuen Namen Zelle_gesperrt und schreiben in die Zeile BEZIEHT SICH AUF folgende Formel:

Allgemein

75

Allgemein

>> Allgemein

Alleine durch die Änderung der Zellensperre wird jedoch noch kein Ereignis ausgelöst, das die Neuberechnung der Formel auslösen würde. Aktualisieren Sie die Formelergebnisse dieser Funktion, indem Sie die Tastenkombination (F9) drücken. Dadurch erfolgt eine Neuberechnung des Tabellenblattes. Der in der Formel =IsLocked(A10) angegebene Bezug wird über die Variable rngCell an die Funktion übergeben. Der Ausdruck rngCell.Locked liefert den Sperr-Zustand WAHR oder FALSCH der Zelle A10. Das Ergebnis vom Datentyp Boolean wird an die Funktion IsLocked übergeben, welche dementsprechend als Ergebnis WAHR oder FALSCH zurückgibt.

Allgemein Allgemein

Durch die Volatile-Methode wird die Funktion als flüchtig gekennzeichnet. Solche Funktionen werden immer neu berechnet, wenn in einer beliebigen Zelle des Tabellenblattes eine Berechnung durchgeführt wird. Nicht flüchtige Funktionen werden nur dann neu berechnet, wenn sich die Eingabevariablen ändern. Diese Methode wird in der Regel in einer benutzerdefinierten Funktion zur Berechnung einer Tabellenzelle verwendet, andernfalls hat sie keine Auswirkung.

Allgemein

Um das gleiche Ergebnis über eine benutzerdefinierte Funktion zu erhalten, schreiben Sie die Funktion IsLocked in ein Standardmodul. Den Sperr-Status der Zelle A10 ermitteln Sie, indem Sie in eine Zelle die Formel =IsLocked(A10) eingeben.

Allgemein

Tragen Sie die Formel =Zelle_gesperrt in eine Zelle ein, um den Sperr-Status der links neben der Formelzelle liegenden Zelle als Ergebnis der Formel ausgeben zu lassen. Die Formel liefert den Wert WAHR, wenn die Zelle gesperrt ist, FALSCH, wenn sie nicht gesperrt ist.

Allgemein

=ZELLE.ZUORDNEN(14;INDIREKT("ZS(-1)";FALSCH))

Allgemein

NIERTE

2471_Excel-VBA.book Seite 76 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

76

>> Gesperrte Zellen einfärben

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_02_CellProtection.xlsm ' Modul mdl_01_IsLocked ‘============================================================== Public Function IsLocked(ByRef rngCell As Range) As Boolean Application.Volatile IsLocked = rngCell.Locked End Function

29

Gesperrte Zellen einfärben

Über die IsLocked-Funktion aus dem vorherigen Beispiel und der bedingten Formatierung können Sie geschützte Zellen farblich hervorheben. Markieren Sie einen Bereich, welchen Sie auf den Zellschutz überprüfen wollen, und rufen Sie den Dialog BEDINGTE FORMATIERUNG über die Registerkarte START | BEDINGTE FORMATIERUNG | REGELN VERWALTEN auf. Klicken Sie im MANAGER FÜR REGELN ZUR BEDINGTEN FORMATIERUNG auf die Schaltfläche NEUE REGEL und im darauf folgenden Dialogfeld auf FORMELN ZUR ERMITTLUNG DER ZU FORMATIERENDEN ZELLEN VERWENDEN. Geben Sie die Formel mit Bezug auf die erste Zelle des markierten Bereichs ein. Wählen Sie anschließend ein Format und bestätigen Sie Ihre Eingaben mit OK. Wollen Sie alle nicht gesperrten Zellen markieren, lautet die Formel:

=IsLocked(A10)=FALSCH

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Listing 27

Abbildung 21: Gesperrte Zellen farblich markieren

Allgemein

Im Tabellenblatt ISLOCKED der Beispieldatei haben wir zu der bedingten Formatierung eine Tabelle erstellt.

2471_Excel-VBA.book Seite 77 Dienstag, 4. Dezember 2007 1:42 13

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_02_CellProtection.xlsm ' Tabelle Show Locked Cells ' Modul mdl_02_ShowLockedCells ‘============================================================== Public Sub ShowLockedCells() Dim rngCell As Range For Each rngCell In Selection If rngCell.Locked Then rngCell.Interior.ColorIndex = 45 Else rngCell.Interior.ColorIndex = 0 End If Next rngCell

Allgemein Allgemein

In der Prozedur wird über eine For Each...Next-Anweisung jede Zelle eines markierten Bereichs angesprochen. In einer If...Then...Else-Anweisung wird der Sperrstatus der jeweiligen Zelle über die Locked-Eigenschaft abgefragt. Ist die Zelle gesperrt, beträgt der Wert True und die Zelle erhält die im Code angegebene Hintergrundfarbe 45. Die Else-Anweisung wird nur durchlaufen, wenn die Zelle nicht gesperrt ist, also den Wert False zurückgibt. In dem Fall wird der Zelle die Hintergrundfarbe 0 zugewiesen. Eine eventuell vorhandene Farbe wird dadurch entfernt.

Allgemein

Neben der bedingten Formatierung ist es mit einer VBA-Prozedur ebenfalls möglich, alle gesperrten Zellen farblich hervorzuheben. Um den nachfolgenden Code zu testen, markieren Sie im Tabellenblatt ShowLockedCells der Beispieldatei einen Bereich, bevor Sie das Makro ShowLockedCells über die Schaltfläche auf dem Tabellenblatt starten.

Allgemein

77

Allgemein

>> Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_02_CellProtection.xlsm ' Tabelle Show Locked Cells ' Modul mdl_02_ShowLockedCells ‘============================================================== Listing 29

Allgemein

Da bekanntlich viele Wege nach Rom führen, kann man obigen Code auch anders aufbauen. Anstelle der If...Then...Else-Anweisung verwenden wir im nachfolgenden Code die IIf-Funktion für die Farbzuweisung der Zelle. Beide Prozeduren führen zu dem gleichen Ergebnis. Hier kann jeder Programmierer seinen persönlichen Stil einbringen.

Allgemein

Listing 28

Allgemein

End Sub

2471_Excel-VBA.book Seite 78 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

78

>> Gesperrte Zellen einfärben

Public Sub ShowLockedCells2() Dim rngCell As Range For Each rngCell In Selection rngCell.Interior.ColorIndex = _ IIf(rngCell.Locked = True, 45, 0) End Sub

Next rngCell

Allgemein

Allgemein

Allgemein

Listing 29 (Forts.)

Um die Hintergrundfarben aller Zellen zu löschen, markieren Sie durch Drücken der Tastenkombination (Strg) (A) das gesamte Tabellenblatt, klicken im Register START in der Gruppe SCHRIFTART auf den Pfeil des FÜLLEIMER-Symbols und wählen die Option KEINE FÜLLUNG. Im Tabellenblatt ShowLockedCells befindet sich eine zweite Schaltfläche um die Hintergrundfarben der Tabelle zu entfernen. Dieser haben wir das Makro ClearColors zugewiesen. Es ist nicht notwendig, das gesamte Tabellenblatt vor dem Aufruf der Prozedur manuell zu markieren, da die Prozedur alle Zellen des aktiven Tabellenblattes bearbeitet. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_02_CellProtection.xlsm ' Tabelle Show Locked Cells ' Modul mdl_02_ShowLockedCells ‘============================================================== Public Sub ClearColors() ActiveSheet.Cells.Interior.ColorIndex = 0 End Sub

Tipp

Allgemein

Listing 30

Zellenformate können auch mit der Option FORMATE LÖSCHEN über die Registerkarte START, Gruppe BEARBEITEN, Auswahlfeld LÖSCHEN (Radiergummi-Symbol) gelöscht werden. Der entsprechende VBA-Befehl lautet:

Allgemein

Allgemein

Selection.ClearFormats

Dabei werden alle Formate der markierten Zellen auf die Standard-Einstellungen zurückgesetzt. Ebenfalls zu den Standard-Einstellungen gehört, dass Zellen als gesperrt formatiert sind. Bedenken Sie diese Auswirkung, bevor Sie alle Formate einer Zelle löschen.

2471_Excel-VBA.book Seite 79 Dienstag, 4. Dezember 2007 1:42 13

In der folgenden Prozedur LockedFormulas1 werden alle Formelzellen des aktiven Tabellenblattes über das Type-Argument xlCellTypeFormulas der SpecialCellsMethode als eigenständiger Bereich einer Range-Variablen zugewiesen. Da dieser Befehl nicht für ein geschütztes Blatt verwendet werden kann, muss zuvor der Blattschutz aufgehoben werden. Diese Methode liefert allerdings einen Fehler, wenn sich im angegebenen Bereich keine Formelzellen befinden. Um eine mögliche Fehlermeldung zu verhindern wird die On Error Resume Next

Fehlerbehandlung vorangestellt und im Anschluss an die Range Zuweisung mit

Allgemein

Standardmäßig sind alle Zellen eines neuen Tabellenblatts gesperrt und die Option AUSGEBLENDET ist deaktiviert. Diese Einstellungen wirken sich erst bei eingeschaltetem Blattschutz aus. Oftmals sollen in einem Tabellenblatt lediglich die Zellen geschützt werden, welche Formeln enthalten. Dazu müssen Sie in allen Zellen des Tabellenblattes die Sperroption der Zellen ohne Formeln aufheben, um diese zur Bearbeitung freizugeben. Auf dem Tabellenblatt sehen Sie normalerweise nur Zahlen oder Text in den einzelnen Zellen. Ob diese Werte über eine Formel berechnet wurden, erkennen Sie an dem Inhalt der Bearbeitungszeile. Zur Überprüfung müsste jede Zelle einzeln markiert werden.

Allgemein

Formelzellen schützen

Allgemein

30

79

Allgemein

>> Allgemein

If rngFormulas Is Nothing Then Exit Sub

Anschließend werden alle Zellen im benutzten Bereich des Tabellenblattes entsperrt und die Formeln in der Bearbeitungszeile eingeblendet. Da sich alle Formelzellen des benutzten Bereichs in der Variablen rngFormulas befinden, wird dieser Bereich gesperrt und die Formeln in der Bearbeitungszeile ausgeblendet.

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_02_CellProtection.xlsm ' Tabelle Locked Formula Cells ' Modul mdl_03_LockedFormulas ‘==============================================================

Allgemein

Listing 31

Allgemein

In dem Tabellenblatt wurden Formeln der Funktion ISLOCKED () aus dem Beispiel 29 hinterlegt. Diese Formeln werden erst durch eine Neuberechnung des Tabellenblattes aktualisiert. Über die Calculate-Methode wird nur der in der With-Anweisung angesprochene Formel-Bereich rngFormulas neu berechnet. Damit die festgelegten SchutzEinstellungen wirksam werden, wird das Tabellenblatt über die Protect-Methode geschützt. Hier vergeben wir das Passwort Codebook.

Allgemein

wieder aufgehoben. Um zu prüfen, ob die Range-Variable initialisiert wurde, also einen Bereich enthält, verwendet man das Schlüsselwort Is Nothing:

Allgemein

On Error GoTo 0

2471_Excel-VBA.book Seite 80 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

80

>> Formelzellen schützen

Public Sub LockedFormulas1() Dim rngFormulas As Range With ActiveSheet ' Blattschutz aufheben .Unprotect "Codebook" ' Fehlerbehandlung einschalten On Error Resume Next

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

' Verweis auf Formelzellen Set rngFormulas = .UsedRange.SpecialCells(xlCellTypeFormulas) ' Fehlerbehandlung zurücksetzen On Error GoTo 0 ' Überprüfung, ob Tabellenblatt Formelzellen enthält If rngFormulas Is Nothing Then ' Blattschutz setzen .Protect "Codebook" ' Prozedur verlassen, wenn keine Formelzellen gefunden ' wurden Exit Sub End If ' Alle Zellen entsperren und Formeln einblenden With .UsedRange.Cells .Locked = False .FormulaHidden = False End With ' Alle Formelzellen sperren und Formeln ausblenden With rngFormulas .Locked = True .FormulaHidden = True ' Formelbereich neu berechnen .Calculate End With .Protect "Codebook" End With End Sub Listing 31 (Forts.)

Allgemein

In der vorherigen Prozedur LockedFormulas1 werden zunächst alle Zellen entsperrt und anschließend nur die Formelzellen in einem Durchgang gesperrt.

2471_Excel-VBA.book Seite 81 Dienstag, 4. Dezember 2007 1:42 13

Public Sub LockedFormulas2() Dim rngCell As Range With ActiveSheet .Unprotect "Codebook" For Each rngCell In .UsedRange With rngCell .Locked = .HasFormula .FormulaHidden = .HasFormula End With Next .Calculate .Protect "Codebook" End With End Sub Listing 32

Die benutzerdefinierten Schutz-Einstellungen, die Sie ab Excel 2002 bis Excel 2007 vorgenommen haben, werden in der Arbeitsmappe nicht unterstützt, wenn Sie diese in älteren Excel-Versionen öffnen.

Bei eingestelltem Blattschutz ist es bis einschließlich Excel 2000 standardmäßig nicht möglich den Autofilter anzuwenden. Wenn der AUTOFILTER im Tabellenblatt eingestellt ist, können Sie die AutoFilter-Pfeile mit der EnableAutoFilter-Eigenschaft aktivieren. Setzen Sie dazu deren Eigenschaft auf True. Anschließend schützen Sie das Tabellenblatt und schalten Sie zusätzlich den Schutz Nur-Benutzerschnittstelle

Allgemein Allgemein

Achtung

Ab Excel 2002 wird die Nutzung des Autofilters über die AllowFiltering–Eigenschaft des Protection-Objektes aktiviert (siehe Rezepte 34 und 35).

Allgemein

Autofilter trotz Blattschutz

Allgemein

31

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_02_CellProtection.xlsm ' Tabelle Locked Formula Cells ' Modul mdl_03_LockedFormulas ‘==============================================================

Allgemein

Es ist ebenso möglich, über die HasFormula-Eigenschaft der Zellen die Schutzeinstellungen vorzunehmen. Der HasFormula-Rückgabewert True oder False wird auf die Locked-Eigenschaft einer einzelnen Zelle übertragen. Diese Methode empfiehlt sich nur bei kleinen Tabellenbereichen, da in einer For Each...Next-Anweisung jede Zelle einzeln abgearbeitet werden muss.

Allgemein

81

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 82 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

Allgemein

82

über die UserInterfaceOnly-Eigenschaft ein. Dadurch wird nur die Benutzeroberfläche, jedoch kein VBA-Befehl geschützt. Diese Eigenschaft muss für jedes Arbeitsblatt eingestellt werden und wird nicht mit dem Arbeitsblatt oder der Sitzung gespeichert. Im folgenden Beispiel werden die AUTOFILTER-Pfeile im geschützten Arbeitsblatt aktiviert. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_03_WorksheetProtectTools.xlsm ' Tabelle AutoFilter ' Modul mdl_01_AutoFilter ‘============================================================== Public Sub AutoFilter() With ActiveSheet .EnableAutoFilter = True .Protect UserInterfaceOnly:=True End With End Sub Listing 33

Allgemein

Allgemein

Allgemein

32

Allgemein

>> Gliederung trotz Blattschutz

Gliederung trotz Blattschutz

Für die Gliederungsfunktion gelten die gleichen Voraussetzungen wie für die Autofilter-Funktion. Bei eingeschaltetem Blattschutz können die Gliederungssymbole bis zur Excel-Version 2000 nur aktiviert werden, wenn die Outlining-Eigenschaft auf True gesetzt wird. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_03_WorksheetProtectTools.xlsm ' Tabelle Gliederung_Outlining ' Modul mdl_02_Outlining ‘============================================================== Public Sub Outlining() With ActiveSheet .EnableOutlining = True .Protect UserInterfaceOnly:=True End With End Sub Listing 34

2471_Excel-VBA.book Seite 83 Dienstag, 4. Dezember 2007 1:42 13

Im Gegensatz zu den vorherigen Funktionen AUTOFILTER und GLIEDERUNG gibt es bis Excel 2000 für die Sortierung von Tabellen keine Eigenschaft diese bei eingeschaltetem Blattschutz zuzulassen. Ab Excel 2002 steht zur Sortierung von Daten in einem Tabellenblatt die AllowSorting-Eigenschaft des Protection-Objektes zur Verfügung. Bei der AllowSortingEigenschaft ergibt sich allerdings ein großer Nachteil: In dem zu sortierenden Bereich eines geschützten Tabellenblattes (inkl. Überschrift) dürfen keine Zellen gesperrt sein. Sobald auch nur eine Zelle im zu sortierenden Bereich gesperrt ist, kann keine Sortierung von Daten vorgenommen werden. Excel gibt die Fehlermeldung aus, dass vor der Sortierung der Blattschutz aufgehoben werden muss.

Allgemein

Allgemein

Allgemein

Allgemein

Um eine individuelle Sortierung in allen Excel-Versionen durch den Anwender zuzulassen bedienen wir uns einer kleinen Prozedur. Nachdem der Blattschutz aufgehoben wurde, wird der SORTIEREN-Dialog angezeigt. Der Anwender kann nun nach Belieben sortieren, solange das Dialogfenster angezeigt wird. Es ist aber weiterhin nicht möglich, Änderungen im Tabellenblatt vorzunehmen.

Allgemein

Sortierung trotz Blattschutz

Allgemein

33

83

Allgemein

>> Allgemein

Um eine Tabelle zu sortieren, können Sie den Bereich Ihrer Tabelle markieren, welcher sortiert werden soll. Markieren Sie eine einzelne Zelle innerhalb eines

Allgemein

Abbildung 22: Sortieren bei eingeschaltetem Blattschutz

2471_Excel-VBA.book Seite 84 Dienstag, 4. Dezember 2007 1:42 13

>> Schutzoptionen auslesen

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

84

zusammenhängenden Bereichs, wird dieser zusammengehörende Bereich ohne ausdrückliche Markierung sortiert. Damit die Prozedur SortBySheetProtection den Sortierbereich erkennt, müssen Sie entweder eine Zelle innerhalb des Datenbereichs oder den gesamten Sortierbereich markieren. Wir markieren den benutzten Bereich UsedRange des Tabellenblattes. Die vor Makroaufruf aktive Zelle wird in der Variablen rngCell gespeichert, damit diese Zelle nach der Sortierung wieder markiert werden kann. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_03_WorksheetProtectTools.xlsm ' Tabelle Sort ' Modul mdl_03_Sort ‘============================================================== Public Sub SortBySheetProtection() Dim rngCell As Range ' aktuelle Zellmarkierung merken Set rngCell = ActiveCell With ActiveSheet ' Blattschutz aufheben .Unprotect "Codebook" ' verwendeten Bereich markieren .UsedRange.Activate ' Dialog >>Sortieren> Allgemein

Schutzeinstellungen

Bedeutung

Konstante

Wert

[x] GESPERRTE ZELLEN AUSWÄHLEN [x] NICHT GESPERRTE ZELLEN AUSWÄHLEN

keine Einschränkung der Markierung

xlNoRestrictions

0

[ ] GESPERRTE ZELLEN AUSWÄHLEN [x] NICHT GESPERRTE ZELLEN AUSWÄHLEN

Markierung nicht gesperrter Zellen

xlUnlockedCells

1

[ ] GESPERRTE ZELLEN AUSWÄHLEN [ ] NICHT GESPERRTE ZELLEN AUSWÄHLEN

keine Markierung möglich

xlNoSelection

4142

Allgemein

Die ersten zwei Optionen GESPERRTE ZELLEN AUSWÄHLEN und NICHT GESPERRTE ZELLEN AUSWÄHLEN (siehe Abbildung 23) geben an, welche Elemente vom Benutzer auf dem Blatt markiert werden können. Es ist nicht möglich, diese beiden Schutzoptionen einzeln auszulesen. Verwenden Sie die EnableSelection-Eigenschaft um die Kombination dieser beiden Optionen zu ermitteln.

Allgemein

Einstellungen der Schutzoptionen, die in Excel 2002 bis 2007 gemacht wurden, werden in älteren Versionen nicht berücksichtigt.

Allgemein

Hi n we is

Abbildung 23: Standardeinstellungen beim Blattschutz

Allgemein

Allgemein

Allgemein

85

Allgemein

In Excel 2002 ist das Protection-Objekt mit zwölf Elementen neu hinzugekommen. Es stellt die verschiedenen Arten von Schutzoptionen dar, die für ein Arbeitsblatt zur Verfügung stehen. Elf dieser Elemente sind im Dialog BLATT SCHÜTZEN aufgeführt. Das zwölfte Element AllowEditRange gibt eine Auflistung der benutzerberechtigten Bereiche zurück.

Allgemein

Tabelle 5: Konstanten der EnableSelection-Eigenschaft

2471_Excel-VBA.book Seite 86 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

86

>> Schutzoptionen auslesen

Schutzoption

Protection-Eigenschaft

Zellen formatieren

AllowFormattingCells

Spalten formatieren

AllowFormattingColumns

Zeilen formatieren

AllowFormattingRows

Spalten einfügen

AllowInsertingColumns

Zeilen einfügen

AllowInsertingRows

Hyperlinks einfügen

AllowInsertingHyperlinks

Spalten löschen

AllowDeletingColumns

Zeilen löschen

AllowDeletingRows

Sortieren

AllowSorting

Autofilter

AllowFiltering

Pivot Table-Berichte

AllowUsingPivotTables

Benutzerberechtigte Bereiche

AllowEditRanges

Mit VBA können Sie die gegenwärtigen Schutzoptionen für die Anwendung auslesen und einstellen. Es ist nicht möglich, die Werte aller Optionen in einer Schleife abzufragen. Diese müssen einzeln aufgeführt und ausgelesen werden. Der Objektvariablen wks wird das aktive Tabellenblatt zugewiesen. Das hat den Vorteil, dass die IntelliSense bei der Auswahl der Protection-Elemente angesprochen wird. Des Weiteren können in einer With-Anweisung eine Reihe von Anweisungen für ein einzelnes Objekt zusammengefasst werden.

Abbildung 24: IntelliSense-Auflistung des Protection-Objektes

Allgemein

Tipp

Allgemein

Allgemein

Allgemein

Allgemein

Tabelle 6: Übersicht der Protection-Elemente

Nähere Informationen zur IntelliSense finden Sie in der Kategorie »Einführung«.

2471_Excel-VBA.book Seite 87 Dienstag, 4. Dezember 2007 1:42 13

>> Allgemein

Sub ReadProtection() wks As Worksheet rngArea As Range intI As Integer

Set wks = ActiveSheet With wks Debug.Print "Blattschutz .ProtectContents Debug.Print "Zellmarkierung .EnableSelection

--> "; _

Allgemein Allgemein

Public Dim Dim Dim

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_04_Protection.xlsm ' Tabelle ReadProtection ' Modul mdl_01_ReadProtection ‘==============================================================

Allgemein

Das Protection-Objekt wird in früheren Excel-Versionen nicht unterstützt. Verwenden Sie Makros mit diesem Objekt, kommt es in den Versionen bis Excel 2000 zu Fehlermeldungen.

--> "; _

Debug.Print "Zellen formatieren --> "; _ .Protection.AllowFormattingCells

Allgemein

Achtung

In nachfolgender Prozedur werden alle Schutzoptionen mit ihrem Wert im Direktfenster ausgegeben. In einer For...Next-Anweisung wird über die Count-Eigenschaft des AllowEditRanges-Objektes die Anzahl an Benutzerberechtigungen zurückgegeben. Sind im aktiven Blatt Benutzerberechtigungen zum Bearbeiten von Bereichen vorhanden, dann werden zu jedem Bereich die Bereichs-Nummer, der -Name sowie -Bezug ausgegeben. Wenn das Direktfenster im VBA-Editor nicht sichtbar ist, zeigen Sie es über den Menüpunkt ANSICHT | DIREKTFENSTER oder die Tastenkombination (Strg) (G) an.

Allgemein

87

Debug.Print "Zeilen formatieren --> "; _ .Protection.AllowFormattingRows

Allgemein

Debug.Print "Spalten formatieren --> "; _ .Protection.AllowFormattingColumns

Listing 36

Allgemein

Debug.Print "Spalten einfügen --> "; _ .Protection.AllowInsertingColumns

2471_Excel-VBA.book Seite 88 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

88

>> Schutzoptionen auslesen Debug.Print "Zeilen einfügen --> "; _ .Protection.AllowInsertingRows

Allgemein

Debug.Print "Hyperlinks einfügen --> "; _ .Protection.AllowInsertingHyperlinks Debug.Print "Spalten löschen --> "; _ .Protection.AllowDeletingColumns

Allgemein

Allgemein

Debug.Print "Zeilen löschen --> "; _ .Protection.AllowDeletingRows Debug.Print "Sortieren --> "; _ .Protection.AllowSorting Debug.Print "Autofilter --> "; _ .Protection.AllowFiltering Debug.Print "Pivot Table-Berichte --> "; _ .Protection.AllowUsingPivotTables Debug.Print "Objekte --> "; _ .ProtectDrawingObjects

Allgemein

Allgemein

Allgemein

Debug.Print "Szenarios bearbeiten .ProtectScenarios

Debug.Print Chr(10); "Anzahl Benutzerberechtigte"; _ Chr(10); _ "Bereiche --> "; _ .Protection.AllowEditRanges.Count ' Auflistung Benutzerberechtigte Bereiche For intI = 1 To .Protection.AllowEditRanges.Count With .Protection.AllowEditRanges.Item(intI) Debug.Print "" Debug.Print "Bereichs Nummer --> "; _ intI Debug.Print "Bereichs Titel --> "; _ .Title Debug.Print "Bereichs Adresse --> "; _ .Range.Address End With Next End With End Sub

Allgemein

--> "; _

Listing 36 (Forts.)

2471_Excel-VBA.book Seite 89 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Abbildung 25: Ausgegraute Formatierungsfunktionen

Allgemein

Allgemein

Allgemein

Das Tabellenblatt SETPROTECTION der Beispieldatei ist geschützt. Änderungen an den Zelleninhalten sind nur in den nicht gesperrten Zellen zulässig. Die Prozeduren ProtectTrue und ProtectFalse haben wir jeweils einer Schaltfläche zugewiesen. Über diese Schaltflächen wird die Schutzoption ZELLEN FORMATIEREN aktiviert, bzw. deaktiviert. Nur wenn die Schutzoption ZELLEN FORMATIEREN aktiviert ist, können sowohl die gesperrten als auch die nicht gesperrten Zellen formatiert werden. Bei einer Deaktivierung der Option sind keine Zellen des Tabellenblattes formatierbar. Die Deaktivierung erkennen Sie am leichtesten an der Verfügbarkeit von Formatfunktionen im Register START. Alle Formatierungssymbole und die Farbpaletten der FÜLLFARBE und SCHRIFTFARBE sind ausgegraut, also nicht anwählbar. Weiterhin wird die MINISYMBOLLEISTE über dem Zellen-Kontextmenü nach einem Rechtsklick nicht angezeigt und der Kontexteintrag ZELLEN FORMATIEREN ist ebenfalls deaktiviert.

Allgemein

Über das Protection-Objekt können Sie die Schutzeinstellungen eines Tabellenblattes per VBA vorgeben. Am Beispiel der Schutzoption ZELLEN FORMATIEREN zeigen wir Ihnen die Befehle zur Aktivierung, bzw. Deaktivierung der Optionen. Bis auf die AllowEditRanges-Eigenschaft können Sie alle anderen Eigenschaften des ProtectionObjektes nach dem gleichen Muster einstellen. Eine Übersicht aller Eigenschaften finden Sie im Rezept 34.

Allgemein

Schutzoptionen einstellen

Allgemein

35

89

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 90 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

Achtung

Allgemein

90

Das Protection-Objekt wird in früheren Excel-Versionen nicht unterstützt. Verwenden Sie Makros mit diesem Objekt, kommt es in den Versionen bis Excel 2000 zu Fehlermeldungen.

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_04_Protection.xlsm ' Tabelle SetProtection ' Modul mdl_02_SetProtection ‘============================================================== Public Sub ProtectTrue() ActiveSheet.Protect AllowFormattingCells:=True End Sub Public Sub ProtectFalse() ActiveSheet.Protect AllowFormattingCells:=False End Sub Listing 37

36

Nicht gesperrte Zellen markieren und formatieren

In unserem vorherigen Beispiel ist es bei eingestelltem Blattschutz und Aktivierung der Option ZELLEN FORMATIEREN möglich, auch die gesperrten Zellen zu formatieren. Damit nur die nicht gesperrten Zellen formatiert werden können, verhindern Sie einfach die Markierung der gesperrten Zellen durch den Benutzer. Aktivieren Sie dazu unbedingt die Option NICHT GESPERRTE ZELLEN AUSWÄHLEN, da sonst keine Zellen des Tabellenblattes markiert werden können. In Abbildung 26 sehen Sie die entsprechenden Einstellungen.

Allgemein

Allgemein

Allgemein

Allgemein

>> Nicht gesperrte Zellen markieren und formatieren

Abbildung 26: Alle nicht gesperrten Zellen sind formatierbar.

2471_Excel-VBA.book Seite 91 Dienstag, 4. Dezember 2007 1:42 13

Public Sub ProtectLockedCellsTrue() ActiveSheet.EnableSelection = xlUnlockedCells ActiveSheet.Protect AllowFormattingCells:=True End Sub Public Sub ProtectLockedCellsFalse() ActiveSheet.EnableSelection = xlNoRestrictions ActiveSheet.Protect AllowFormattingCells:=True End Sub Listing 38

Angenommen, Sie wollen in einem geschützten Tabellenblatt lediglich die Formatierung von gesperrten Zellen verhindern, eine Markierung der nicht gesperrten Zellen soll aber nach wie vor möglich sein. Diese Kombination lässt sich nicht alleine über den Dialog BLATT SCHÜTZEN einstellen. Nehmen Sie dazu das Worksheet_SelectionChange-Ereignis des Tabellenblattes zu Hilfe. In der Ereignis-Prozedur verwenden Sie eine For Each...Next-Anweisung. Diese ermöglicht es, sowohl eine einzelne markierte Zelle als auch einen Bereich von mehreren markierten Zellen auf ihre jeweilige Locked-Eigenschaften zu überprüfen. Sobald auch nur eine Zelle dieses markierten Bereichs gesperrt ist, wird die Schutzoption ZELLEN FORMATIEREN deaktiviert und die Prozedur verlassen. Mit dem Schlüsselwort Me wird das Tabellenblatt angesprochen, in welchem die Ereignisprozedur hinterlegt ist. Nur wenn keine Zelle des markierten Bereichs Target gesperrt ist, wird eine Formatierung der Zellen ermöglicht.

Allgemein Allgemein

Nicht gesperrte Zellen formatieren (ab Excel 2002)

Allgemein

37

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_04_Protection.xlsm ' Tabelle FormatUnlockedCells ' Modul mdl_03_ProtectLockedCells ‘==============================================================

Allgemein

Ersetzen Sie die AllowFormattingCell-Eigenschaft durch eine andere Protection-Eigenschaft aus der Tabelle 6. Bis auf die AllowEditRanges-Eigenschaft können Sie alle anderen Elemente des Protection-Objektes nach dem gleichen Muster wie in den folgenden Prozeduren einstellen. Zum Thema »Benutzerberechtigte Bereiche einstellen« zeigen wir in Ihnen im Rezept 40 ein Beispiel.

Allgemein

Tipp

In VBA nehmen Sie die Einstellungen der Zellenmarkierung über die SelectionEnable-Eigenschaft vor. Um nur die Markierung nicht gesperrter Zellen zu erlauben, wird die EnableSelection-Konstante xlUnlockedCells verwendet.

Allgemein

91

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 92 Dienstag, 4. Dezember 2007 1:42 13

>> Nicht gesperrte Zellen formatieren (alle Excel-Versionen)

Allgemein

Allgemein

Allgemein

Das Protection-Objekt wird in früheren Excel-Versionen nicht unterstützt. Verwenden Sie Makros mit diesem Objekt, kommt es in den Versionen bis Excel 2000 zu Fehlermeldungen.

Achtung

Allgemein

92

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_04_Protection.xlsm ' Tabelle FormatUnlockedCells_Change ' Ereignis Klassenmodul FormatUnlockedCells_Change ‘============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim rngCell As Range For Each rngCell In Target If rngCell.Locked = True Then Me.Protect AllowFormattingCells:=False Exit Sub End If Next rngCell

Allgemein

Allgemein

Allgemein

Allgemein

Me.Protect AllowFormattingCells:=True End Sub Listing 39

38

Nicht gesperrte Zellen formatieren (alle Excel-Versionen)

Wenn Sie Excel-Arbeitsmappen in verschiedenen Excel-Versionen bearbeiten müssen, kann es Probleme bei der Verwendung des Protection-Objektes geben, weil dieses Objekt erst in Excel 2002 in die Objektbibliothek aufgenommen wurde. Der Versuch, VBA Code mit unbekannten Objekten auszuführen, wird mit einem Laufzeitfehler '1004' Anwendungs- oder objektdefinierter Fehler quittiert. Um dieses Problem zu umgehen, verwenden Sie einen kleinen Workaround mit Hilfe des Worksheet_SelectionChange-Ereignisses, um Formatierungen in nicht gesperrten Zellen zu ermöglichen. Das Tabellenblatt der Beispieldatei ist dabei mit dem Passwort »Codebook« geschützt. Wird eine nicht gesperrte Zelle markiert, wird der Blattschutz aufgehoben, bei gesperrten Zellen wird er wieder gesetzt. Wird ein Bereich aus mehreren Zellen markiert, welche einen unterschiedlichen GESPERRT-Status haben, kann Excel sich nicht entscheiden, ob die Syntax Target.Locked den Wert True oder False hat, und gibt den Wert NULL zurück. Dementsprechend wurde die Prozedur so programmiert, dass der Blattschutz nur dann

2471_Excel-VBA.book Seite 93 Dienstag, 4. Dezember 2007 1:42 13

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_04a_FormatLockedCells_Excel2000.xlsm ' Ereignis Klassenmodul FormatCells ‘============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Locked = False Then Me.Unprotect "Codebook" Else Me.Protect "Codebook" End If End Sub

Allgemein

aufgehoben wird, wenn Target.Locked den Wert False zurückgibt. Dies ist nur dann der Fall, wenn alle Zellen im markierten Bereich nicht gesperrt sind.

Allgemein

93

Allgemein

>> Allgemein

In der Prozedur ChangeProtection wird zunächst die Einstellung der Schutzoption SPALTEN EINFÜGEN ausgelesen und an die Variable blnOption übergeben. Im weiteren Verlauf der Prozedur kann über diese Variable jederzeit auf die anfängliche SchutzEinstellung zurückgegriffen werden. Die Variable blnOption hat den Wert True, wenn die Schutzoption aktiviert ist, False wenn deaktiviert. Diese Information wird in einer If...Then...Else-Anweisung in einen sprechenden Text umgewandelt. Die Variable strResult erhält für den Wahr-Wert den Text »zugelassen«, für den Falsch-Wert »untersagt«. Anschließend wird in einem Meldungsfenster die anfänglich ermittelte Einstellung bekannt gegeben. Das Meldungsfenster weist mittels der Konstante vbYesNo eine JA- und eine NEIN-Schaltfläche auf. Klicken Sie auf JA, um die aktuelle Einstellung der Schutzoption zu ändern. Bei NEIN werden Sie in einem weiteren Meldungsfenster darüber informiert, dass die Einstellung nicht geändert wurde.

Allgemein

Eine neu eingefügte Spalte übernimmt standardmäßig die Formatierung der Spalte, die links von ihr steht. Das bedeutet, dass diese möglicherweise über gesperrte Zellen verfügt und die Benutzer vielleicht nicht in der Lage sind, die von ihnen eingefügten Spalten wieder zu löschen.

Allgemein

Hinweis

In unserem nächsten Beispiel verwenden wir die Schutzoption SPALTEN EINFÜGEN. Anstelle der entsprechenden Protection-Eigenschaft AllowInsertingColumns können Sie auch ein anderes Element aus der Tabelle 6. einsetzen. Lediglich die AllowEditRanges-Eigenschaft benötigt zusätzliche Argumente. Dazu zeigen wir in Ihnen im Rezept 40 ein Beispiel.

Allgemein

Schutzoptionen ändern

Allgemein

39

Allgemein

Listing 40

2471_Excel-VBA.book Seite 94 Dienstag, 4. Dezember 2007 1:42 13

>> Schutzoptionen ändern

Allgemein

Allgemein

Allgemein

94

Wollen Sie die Einstellung der Schutzoption SPALTEN EINFÜGEN ändern, klicken Sie im Meldungsfenster SCHUTZOPTION EINSTELLEN auf JA. In einer weiteren If... Then...Else-Anweisung wird anhand des Wertes der Variablen blnOption die Schutzeinstellung umgedreht. Aus False wird True, aus True False. Der Blattschutz wurde mit dem Passwort Codebook versehen. Bei Änderung der Schutz-Einstellungen muss dieses im Code mit angegeben werden. Geben Sie das Passwort nicht in der Prozedur an, wird das vergebene Passwort zurückgesetzt. Der Dialog BLATT SCHÜTZEN ist damit für den Anwender ohne Eingabe eines Passwortes zugänglich. Für die Schlussmeldung erhält die Variable strResult den umgekehrten Wert.

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Abbildung 27: Es wurden keine Änderungen vorgenommen.

Abbildung 28: Änderungen wurden vorgenommen.

2471_Excel-VBA.book Seite 95 Dienstag, 4. Dezember 2007 1:42 13

bytQuestion = _ MsgBox("Die Option ""Spalten einfügen"" ist " & _ strResult & "." & _ vbNewLine & vbNewLine & _ "Wollen Sie die Einstellung ändern?" _ , vbYesNo + vbQuestion, _ "Schutzoption einstellen") If bytQuestion = vbYes Then ' Einstellung soll geändert werden If blnOption = True Then ' Schutz ist WAHR gewesen ActiveSheet.Protect _ Password:="Codebook", _ AllowInsertingColumns:=False strResult = "untersagt" Else ' Schutz ist FALSCH gewesen ActiveSheet.Protect _ Password:="Codebook", _ AllowInsertingColumns:=True strResult = "zugelassen" End If MsgBox "Die Option ""Spalten einfügen"" ist jetzt " & _ strResult & ".", _ vbOKOnly + vbInformation, _ Listing 41

Allgemein Allgemein Allgemein

If blnOption = True Then strResult = "zugelassen" Else strResult = "untersagt" End If

Allgemein

' Schutzzustand auslesen blnOption = ActiveSheet.Protection.AllowInsertingColumns

Allgemein

Sub ChangeProtection() blnOption As Boolean strResult As String bytQuestion As Byte

Allgemein

Public Dim Dim Dim

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_04_Protection.xlsm ' Tabelle ChangeProtection ' Modul mdl_04_ChangeProtection ‘==============================================================

95

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 96 Dienstag, 4. Dezember 2007 1:42 13

>> Benutzerberechtigte Bereiche hinzufügen

Allgemein

Allgemein

96

"Schutzoption wurde geändert" ' Einstellung soll nicht ' geändert werden MsgBox "Die Option ""Spalten einfügen""ist immer noch " &_ strResult & ".", _ vbOKOnly + vbInformation, _ "Schutzoption wurde nicht geändert" End If End Sub Else

40

Benutzerberechtigte Bereiche hinzufügen

Ab der Version Excel 2002 ist es möglich, Benutzerberechtigungen für ausgewählte Bereiche zu erteilen. Diese Einstellung können Sie in Excel 2007 unter ÜBERPRÜFEN | ÄNDERUNGEN | BENUTZER DÜRFEN BEREICHE BEARBEITEN vornehmen. Diese Option ermöglicht es, definierte Zellen oder Bereiche in einem geschützten Arbeitsblatt zur Bearbeitung freizugeben. Benutzerberechtigte Bereiche gelten je Tabellenblatt. Der gleiche Bereichsname kann mit den gleichen oder verschiedenen Bezugsangaben in anderen Tabellenblättern erstellt werden. Zur Identifizierung muss in VBA jeweils das Tabellenblatt mit angegeben werden.

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Listing 41 (Forts.)

Abbildung 29: Benutzerberechtigungen definieren

Die Einstellungen der Bereiche werden in VBA über das AllowEditRange-Objekt vorgenommen. Dieses Objekt ist eine der Eigenschaften des Protection-Objektes (siehe Tabelle 6). In der Prozedur AddAllowEditRange soll im aktiven Tabellenblatt der benutzerberechtigte Bereich Data neu erstellt werden. Existiert der Titel des neu einzufügenden Bereichs bereits, erhalten Sie eine Fehlermeldung. Dieser Fehler würde durch die vorangestellte On Error GoTo-Anweisung zur Sprungmarke Errorhandler verzweigen. Hier wird ein Meldungsfenster mit dem Fehlerhinweis ausgegeben. Anstelle der MsgBox können auch andere oder gar keine Befehle angegeben werden.

2471_Excel-VBA.book Seite 97 Dienstag, 4. Dezember 2007 1:42 13

Achtung

Zur besseren Orientierung schreiben wir die Einstellungen des neu erstellten Bereichs Data in die Zellen C17:C19 des Tabellenblattes ADD_DELETE_AER. Der TITEL sowie BEREICH wird über das Protection-Objekt ausgelesen. Die Passwörter des Tabellenund Bereich-Schutzes können nicht ermittelt werden. Diese Angaben geben wir im Code vor. Im Anschluss daran erfolgt ein Meldungsfenster, dass ein benutzerberechtigter Bereich erstellt wurde. Das AllowEditRange-Objekt ist in der Excel-Version 2002 neu hinzugekommen. Es wird in früheren Excel-Versionen nicht unterstützt. Verwenden Sie Makros mit diesem Objekt, kommt es in den Versionen bis einschließlich Excel 2000 zu Fehlermeldungen.

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle Add_Delete_AER ' Modul mdl_01_Add_AER ‘==============================================================

Allgemein Allgemein Allgemein

In unserem Beispiel wurde das Tabellenblatt ADD_DELETE_AER mit dem Passwort VBA geschützt. Um einen neuen benutzerberechtigten Bereich zu erstellen, muss der Blattschutz aufgehoben werden. Anschließend erstellen Sie einen neuen benutzerberechtigten Bereich über die Add-Methode des AllowEditRange-Objektes. Es ist zwingend erforderlich, den Bereichsnamen Title sowie den Bereich Range, der bearbeitet werden darf, anzugeben. Die Angabe eines Kennwortes ist optional. Für den Bereich Data vergeben wir das Passwort Codebook. Der Bereichsschutz für den hinzugefügten Bereich wird erst dann wirksam, wenn das Tabellenblatt geschützt wird. Hier verwenden wir, wie bereits erwähnt, das Passwort VBA.

Allgemein

Die Anweisung With ActiveSheet ermöglicht es, eine Reihe von Anweisungen für das aktive Tabellenblatt zusammenzufassen. Dadurch muss der Name ActiveSheet nicht vor jeder Anweisung angeben werden. Vor einem Befehl für ActiveSheet muss lediglich ein Punkt geschrieben werden. Dieser ersetzt den Namen des Objektes ActiveSheet.

Allgemein

97

Allgemein

>> Allgemein

With ActiveSheet ' Blattschutz aufheben .Unprotect "VBA"

Allgemein

Public Sub AddAllowEditRange() On Error GoTo Errorhandler

Listing 42

Allgemein

' Neuer benutzerberechtigter Bereich .Protection.AllowEditRanges.Add _ Title:="Data", _

2471_Excel-VBA.book Seite 98 Dienstag, 4. Dezember 2007 1:42 13

>> Benutzerberechtigte Bereiche löschen

Allgemein

98

Range:=Range("A1:A10"), _ Password:="Codebook"

Allgemein

' Auflistung im Tabellenblatt .Range("C17").Value = .Protection.AllowEditRanges("Data") _ .Title .Range("C18").Value = .Protection.AllowEditRanges("Data") _ .Range.Address .Range("C19").Value = "Codebook" ' Bereichs Passwort

Allgemein

' Blattschutz setzen

MsgBox _ "Der benutzerberechtigte Bereich " & Range("C17").Value & _ " wurde erstellt.", vbInformation Exit Sub

Allgemein

.Protect "VBA"

Errorhandler: MsgBox _ "Der benutzerberechtigte Bereich " & Range("C17").Value & _ " existiert bereits.", vbExclamation .Protect "VBA" End With

Allgemein

Allgemein

Allgemein

Allgemein

End Sub Listing 42 (Forts.)

41

Benutzerberechtigte Bereiche löschen

Bevor ein benutzerberechtigter Bereich gelöscht werden kann, muss ein eventuell vorhandener Blattschutz aufgehoben werden. Bei bestehendem Blattschutz würde der Debugger sonst eine Fehlermeldung ausgeben. Wenn Sie versuchen, einen nicht vorhandenen Bereich zu löschen, würde ebenfalls eine Fehlermeldung ausgegeben. Diese wird wie in dem vorherigen Beispiel durch eine On Error GoTo-Anweisung verhindert. Nachdem der Bereich Data gelöscht wurde, wird das Tabellenblatt wieder geschützt. Der Bereich C17:C19, welcher die Einstellungen des Bereichs Data enthält, wird nach dem Löschvorgang des Bereichs Data ebenfalls gelöscht. Am Ende der Prozedur werden Sie über ein Meldungsfenster darüber informiert, ob der Löschvorgang des benutzerberechtigten Bereichs Data erfolgreich war.

2471_Excel-VBA.book Seite 99 Dienstag, 4. Dezember 2007 1:42 13

With ActiveSheet .Unprotect "VBA" .Protection.AllowEditRanges("Data").Delete .Range("C17:C19").ClearContents .Protect "VBA" MsgBox _ "Der benutzerberechtigte Bereich ""Data""" & _ "wurde gelöscht.", vbInformation Exit Sub

Allgemein

Errorhandler: MsgBox _ "Der benutzerberechtigte Bereich ""Data""" & _ "existiert nicht!", vbExclamation .Protect "VBA" End With

Allgemein

Public Sub DeleteAllowEditRange() On Error GoTo Errorhandler

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle Add_Delete_AER ' Modul mdl_02_Delete_AER ‘==============================================================

Allgemein

99

Allgemein

>> Allgemein

End Sub

Sie können mit VBA den Schutz benutzerberechtigter Bereiche aufheben. Dazu steht Ihnen in der Objektbibliothek die Unprotect-Methode des AllowEditRange-Objektes zur Verfügung. In unserem Beispiel soll der Schutz des Bereichs DATA aufgehoben werden. Excel würde eine Fehlermeldung ausgeben, wenn der Bereich nicht existiert. Durch die vorangestellte On Error GoTo-Anweisung wird diese Fehlermeldung übergangen. Nachdem ein Fehler aufgetreten ist, wird die Prozedur zur Sprungmarke Errorhandler verzweigt. Hier erfolgt in unserer Prozedur ein Meldungsfenster. Wurde der Bereichsschutz aufgehoben, kann anschließend der Bereich oder können einzelne Zellen bearbeitet werden. In unserem Beispiel erhalten die erste und letzte Zelle des Bereichs einen Textwert.

Allgemein

Benutzerberechtigte Bereiche entschützen

Allgemein

42

Allgemein

Listing 43

2471_Excel-VBA.book Seite 100 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

100 >> Benutzerberechtigte Bereiche schützen ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle Add_Delete_AER ' Modul mdl_03_Unprotect_AER ‘============================================================== Public Sub UnprotectAllowEditRange() Dim rngData As Range On Error GoTo Errorhandler ActiveSheet.Protection.AllowEditRanges("Data"). _ Unprotect "Codebook" Set rngData = _ ActiveSheet.Protection.AllowEditRanges("Data").Range

Allgemein

Allgemein

Allgemein

' erste Zelle im Bereich Data beschreiben rngData(1, 1).Value = "erste Zeile" ' letzte Zelle im Bereich Data beschreiben rngData.Cells(rngData.Rows.Count, rngData.Columns.Count) _ .Value = "letzte Zeile" MsgBox _ "Der benutzerberechtigte Bereich ""Data"" ist nicht " & _ " geschützt.", vbInformation Exit Sub Errorhandler: MsgBox _ "Der benutzerberechtigte Bereich" & " ""Data"" " & _ "existiert nicht", vbCritical End Sub Listing 44

Allgemein

Allgemein

43

Benutzerberechtigte Bereiche schützen

Wurde der Schutz eines benutzerberechtigten Bereichs einmal aufgehoben, lässt er sich nicht ohne weiteres wieder einschalten. In der Objektbibliothek steht zu der Unprotect-Methode des AllowEditRange-Objektes kein Gegenstück Protect zur Verfügung. Um einen Bereich dennoch erneut zu schützen, muss zunächst der Blattschutz aufgehoben und anschließend gleich wieder eingeschaltet werden. Geben Sie bei diesen Befehlen ein vorhandenes Passwort zum Blattschutz im Code mit an. Ein Kennwort des Bereichsschutzes muss nicht angegeben werden. Wird die Arbeitsmappe mit aufgehobenem Bereichsschutz geschlossen, dann wird der Schutz nach erneutem Öffnen automatisch wieder hergestellt.

2471_Excel-VBA.book Seite 101 Dienstag, 4. Dezember 2007 1:42 13

With ActiveSheet ' Blattschutz aufheben .Unprotect cstrPassword ' Blattschutz setzen .Protect cstrPassword End With MsgBox _ "Der benutzerberechtigte Bereich ""Data"" ist geschützt.", _ vbInformation End Sub

Allgemein

Public Sub ReProtectAllowEditRange() ' Konstante für Kennwort deklarieren Const cstrPassword As String = "VBA"

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle Add_Delete_AER ' Modul mdl_04_ReProtect_AER ‘==============================================================

Allgemein

101

Allgemein

>> Allgemein

Mit VBA greifen Sie für die Änderung des Passwortes eines benutzerdefinierten Bereichs auf die ChangePassword-Methode des AllowEditRange-Objektes zu. In der Prozedur ChangePasswordAER verzweigt die anfängliche On Error GoTo-Anweisung zur Sprungmarke Errorhandler, falls der Bereich Data nicht existiert. Vergessen Sie nicht, vor der Passwort-Änderung den Blattschutz des Tabellenblattes aufzuheben. Das ursprüngliche Passwort Codebook des benutzerberechtigten Bereichs Data wird in neues Passwort geändert. Anschließend wird der Blattschutz wieder eingestellt. Hier vergeben wir ebenfalls ein neues Kennwort, indem wir das neue Passwort Excel hinter der Protect Eigenschaft aufführen. In unserem Beispiel werden die neuen Kennwörter zur Orientierung in die Zellen C16 und C19 der Tabelle geschrieben.

Allgemein

Um das Kennwort für den Zugriff auf einen benutzerberechtigten Bereich zu ändern, heben Sie den Blattschutz auf und zeigen den Dialog BEREICH BEARBEITEN über die Registerkarte ÜBERPRÜFEN | ÄNDERUNGEN | BENUTZER DÜRFEN BEREICHE BEARBEITEN Schaltfläche ÄNDERN an. Klicken Sie auf die Schaltfläche KENNWORT um im darauf folgenden Dialogfeld das Bereichskennwort zu ändern.

Allgemein

Benutzerberechtigte Bereiche – Passwort ändern

Allgemein

44

Allgemein

Listing 45

2471_Excel-VBA.book Seite 102 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

102 >> Benutzerberechtigte Bereiche – Titel ändern ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle ChangePassword_AER ' Modul mdl_05_ChangePasswordAER ‘============================================================== Public Sub ChangePasswordAER() On Error GoTo Errorhandler With ActiveSheet .Unprotect "VBA" .Protection.AllowEditRanges("Data"). _ ChangePassword "neues Passwort" .Protect "Excel"

Allgemein

Allgemein

.Range("C16") = "Excel" .Range("C19") = "neues Passwort" End With Exit Sub

Errorhandler: MsgBox _ "Der benutzerberechtigte Bereich ""Data""" & _ " existiert nicht!", vbCritical End Sub Listing 46

45

Benutzerberechtigte Bereiche – Titel ändern

Ab Excel 2007 können Sie manuell über die Benutzeroberfläche über die Registerkarte ÜBERPRÜFEN | BENUTZER DÜRFEN BEREICHE BEARBEITEN | ÄNDERN den TITEL, BEZUG und das KENNWORT eines benutzerberechtigten Bereichs ändern.

Allgemein

Allgemein

' Blattschutz ' Bereichsschutz

Allgemein

Abbildung 30: Ändern eines benutzerberechtigten Bereichs

2471_Excel-VBA.book Seite 103 Dienstag, 4. Dezember 2007 1:42 13

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle ChangeTitle_AER ' Modul mdl_06_ChangeTitelAER ‘============================================================== Public Function AERChangeTitle(strOldTitle As String, _ strNewTitle As String, _ Optional strSheetPassword As String) _ As Boolean Dim AER As AllowEditRange

Allgemein Allgemein Allgemein

Der Wahrheitswert der Funktion ergibt sich daraus, ob der Titel eines übergebenen Bereichs erfolgreich geändert wurde. In einer For Each...Next-Schleife wird jeder Benutzerberechtigte Bereich des aktiven Tabellenblattes durchlaufen. In einer If...Then...Else-Anweisung wird der gerade durchlaufene Bereichstitel mit der Variablen strOldTitle verglichen. Diese Variable enthält den Namen des Bereichs, dessen Titel geändert werden soll. Wird der alte Bereichstitel in der Auflistung aller benutzerberechtigten Bereiche gefunden, erfolgt die Umbenennung. Dazu muss vorab der Blattschutz aufgehoben und anschließend wieder gesetzt werden. War die Umbenennung erfolgreich, wird der Rückgabewert der Funktion auf True gesetzt und die Funktion mit Exit Function verlassen. Wird der übergebene Bereich in der For Each...Next-Anweisung nicht gefunden oder hat die Angabe eines falschen Passwortes zu einem Fehler geführt, wird die Schleife verlassen und zu der Sprungmarke ERRORHANDLER verwiesen. Der Rückgabewert der Funktion AERChangeTitle bleibt in diesen Fällen unverändert auf dem Standardwert False.

Allgemein

Beim Aufruf der Funktion müssen als Argumente der alte Titel strOldTitle, sowie der neue Bereichstitel strNewTitle an die Funktion übergeben werden. Die Angabe eines Passwortes strSheetPassword ist optional. Das bedeutet, dass eine Angabe nur erforderlich ist, wenn das Tabellenblatt mit einem Kennwort geschützt ist. Bei Angabe eines Passwortes wird das Tabellenblatt durch die Funktion mit diesem Kennwort geschützt. Dies geschieht unabhängig davon, ob das Tabellenblatt vorher geschützt war oder nicht.

Allgemein

Mit VBA können Sie standardmäßig lediglich das Passwort eines benutzerdefinierten Bereichs ändern (siehe Rezept 44). Zur Änderung des Titels und Bezugs steht im Objektkatalog keine Methode zur Verfügung. Auch in der Liste der integrierten Dialogfenster fehlt der Dialog BEREICH BEARBEITEN (Abbildung 30). Um dennoch den Titel eines benutzerberechtigten Bereichs zu ändern haben wir die benutzerdefinierte Funktion AERChangeTitle programmiert. Die Funktion ist vom Datentyp Boolean und liefert als Rückgabewert einen Wahrheitswert True oder False.

Allgemein

103

Allgemein

>> Allgemein

Listing 47

Allgemein

On Error GoTo Errorhandler

2471_Excel-VBA.book Seite 104 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

104 >> Benutzerberechtigte Bereiche – Titel ändern With ActiveSheet For Each AER In .Protection.AllowEditRanges If AER.Title = strOldTitle Then .Unprotect strSheetPassword AER.Title = strNewTitle .Protect strSheetPassword ' Funktionswert auf True setzen AERChangeTitle = True Exit Function End If Next End With Errorhandler:

Listing 47 (Forts.)

Um einen Bereichstitel über die AERChangeTitle-Funktion zu ändern, rufen Sie die Funktion in einem Makro auf und übergeben die benötigten Argumente. Beim Schreiben der Argumente hilft Ihnen die Quick- bzw. Parameterinfo bei der Zuweisung der Argumente. Die Prozedur in Abbildung 31 ändert den Bereichstitel Data in MyData über die aufgerufene Prozedur AERChangeTitle. Wenn der Bereich Data nicht im aktiven Tabellenblatt existiert oder das Passwort falsch eingegeben wurde, erfolgt keine Fehlermeldung, weil die Funktion stattdessen den Wert False liefert.

Allgemein

Allgemein

Allgemein

End Function

Allgemein

Abbildung 31: Parameterinfo der Funktionsargumente

In der folgenden Prozedur ChangeDataTitle wird die AERChangeTitle-Funktion in einer If...Then...Else-Anweisung aufgerufen. Es wird überprüft, ob der Rückgabewert der Funktion mit den angegebenen Parametern False ist, also die Ausführung der Funktion fehlerhaft war.

Allgemein

Ebenso können Sie den Funktionswert False über den Not-Operator überprüfen:

2471_Excel-VBA.book Seite 105 Dienstag, 4. Dezember 2007 1:42 13

105

' erwartet False If Not AERChangeTitle("Data", "Daten", "VBA") Then

Allgemein

>> Allgemein

Den Rückgabewert True ermitteln Sie mit:

Public Sub ChangeDataTitle() If AERChangeTitle("Data", "MyData", "VBA") = False Then MsgBox _ "Der benutzerberechtigte Bereich ""Data"" " & _ "existiert nicht," & _ vbNewLine & _ "oder das Passwort des Blattschutzes ist falsch!", _ vbCritical, "Fehlermeldung" Else With ActiveSheet .Range("C17").Value = _ .Protection.AllowEditRanges(1).Title End With End If End Sub

Allgemein Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle ChangeTitle_AER ' Modul mdl_06_ChangeTitleAER ‘==============================================================

Allgemein

Im Anschluss an den Funktionsaufruf erfolgt eine Meldung, ob die Umbenennung erfolgreich war. Zur Orientierung wird der neue Titel des Benutzerberechtigten Bereichs in die Zelle C17 geschrieben.

Allgemein

If AERChangeTitle("Data", "Daten", "VBA") Then

Allgemein

' erwartet True

Benutzerberechtigte Bereiche – Bereich ändern

Für die Änderung des Zellenbereichs eines Benutzerberechtigten Bereichs sieht das AllowEditRange-Objekt keine Methode vor. Wie schon für den Bereichstitel haben wir deshalb für die Änderung des Zellenbereichs die benutzerdefinierte Funktion AERChangeRange programmiert. Diese ermöglicht es, die Bereichsangaben eines Benutzerberechtigten Bereichs zu ändern.

Allgemein

46

Allgemein

Listing 48

2471_Excel-VBA.book Seite 106 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

106 >> Benutzerberechtigte Bereiche – Bereich ändern

Der Aufbau der Funktion AERChangeRange ähnelt der Funktion AERchangeTitle zur Änderung des Bereichstitels aus dem Rezept 45. Zur Identifizierung des Benutzerberechtigten Bereichs muss strTitle als erstes Argument beim Aufruf an die Funktion übergeben werden. Das zweite Argument rngNewRange enthält den neuen Zellenbereich. Hier können entweder ein zusammenhängender Zellbereich oder mehrere Bereiche, durch Semikolons voneinander getrennt, angegeben werden. Die Angabe eines Kennwortes ist optional und richtet sich danach, ob das Tabellenblatt mit einem Passwort geschützt ist.

Allgemein

Die Argumenten-Bezeichnungen werden jedoch nicht in der INTELLISENSE aufgeführt. Die Groß-/Kleinschreibung spielt bei der Angabe von benannten Argumenten im Code keine Rolle. Eine andere Groß-/Kleinschreibung als in der Funktionsdeklarierung beeinträchtigt nicht die Codeausführung. Ebenso werden tatsächliche Rechtschreibfehler von benannten Argumenten beim Kompilieren des VBA Codes vom Interpreter noch nicht erkannt. Erst wenn die Befehlszeile zur Laufzeit erreicht wird, meldet der VBA Interpreter einen Kompilierungsfehler, wenn ein benanntes Argument aufgrund einer falschen Schreibweise nicht gefunden wurde.

Allgemein

Allgemein

Die Abbildung 32 zeigt den Aufruf der Funktion über ein Makro. Die Parameterinfo leistet wiederum Hilfe bei der Angabe der Argumente. Beim Aufruf ist die Angabe der Parameterbezeichnung als »Benannte Argumente« nicht zwingend erforderlich, erleichtert aber bei späteren Codeüberarbeitungen oder fremden Programmierern die Übersichtlichkeit und Verständigung, welche Parameter verwendet und welche Werte dabei jeweils übergeben werden.

Allgemein

Sowohl benutzerdefinierte Funktionen als auch die Prozeduren zum Aufruf der Funktion werden in Standardmodulen hinterlegt. Es ist nicht erforderlich, dass das Aufrufmakro und die Funktion in dem gleichen Modul gespeichert sind.

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle ChangeRange_AER ' Modul mdl_07_ChangeRangeAER ‘==============================================================

Allgemein

Abbildung 32: Benannte Argumente bei Funktionsaufruf

Listing 49

2471_Excel-VBA.book Seite 107 Dienstag, 4. Dezember 2007 1:42 13

Public Function AERChangeRange(strTitle As String, _ rngNewRange As Range, _ Optional strSheetPassword As String) _ As Boolean Dim rngAER As AllowEditRange On Error GoTo Errorhandler

Allgemein

107

Allgemein

>> Allgemein

With ActiveSheet

If rngAER.Title = strTitle Then .Unprotect strSheetPassword

Allgemein

For Each rngAER In .Protection.AllowEditRanges

' Funktionswert auf True setzen AERChangeRange = True Exit Function End If

Allgemein

Set rngAER.Range = rngNewRange .Protect strSheetPassword

End With Errorhandler:

Allgemein

Next

Vor dem Aufruf der InputBox haben wir die Anweisung On Error Resume Next geschrieben. Diese Anweisung ist notwendig, falls der Anwender in der InputBox die Schaltfläche ABBRECHEN klickt. Dadurch kann der Variablen rngInputBox kein

Allgemein

In der folgenden Prozedur soll der benutzerdefinierte Bereich Data geändert werden. Zunächst wird der aktuelle Bereich im Tabellenblatt markiert, anschließend ein Eingabedialog InputBox aufgerufen. Als Default-Wert werden die Bereiche "A1:A5;I25;K25" angegeben. Diese Zellbereiche werden beim Aufruf der InputBox durch Strichumrandungen der Zellen und Bereiche angezeigt. Das Argument Type wird auf 8 gesetzt, damit die InputBox ein Range-Objekt zurückgibt. Mit Hilfe der SetAnweisung weisen wir das Ergebnis dem Range-Objekt rngInputBox zu. Wenn Sie keine Set-Anweisung verwenden, wird die Variable auf den Wert im angegebenen Bereich statt auf das Range-Objekt gesetzt.

Allgemein

Listing 49 (Forts.)

Allgemein

End Function

2471_Excel-VBA.book Seite 108 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

108 >> Benutzerberechtigte Bereiche – Bereich ändern

Wert zugewiesen werden. Das wiederum würde zu einer Fehlermeldung führen. Im Anschluss an die InputBox wird über eine If...Then...Else-Anweisung überprüft, ob rngInputBox einen Wert oder Nothing enthält. Über eine weitere If...Then...Else-Anweisung wird die Funktion AERChangeRange aufgerufen. Dabei werden folgende benannte Argumente übergeben: 왘 der Bereichstitel Data 왘 der neue Bereich mittels der Variablen rngInputBox

Allgemein

Allgemein

왘 das Passwort VBA des Tabellenblattes CHANGERANGE_AER Die Funktion AERChangeRange gibt den Wert False zurück, wenn bei deren Abarbeitung ein Fehler aufgetreten ist. Demzufolge wird ein Meldungsfenster angezeigt. War die Änderung des Bereichs erfolgreich, wird die neue Bereichsadresse zur Orientierung in die Zelle C18 der Tabelle geschrieben. Zum Abschluss wird der neue Bereich im Tabellenblatt markiert. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_05_AllowEditRange.xlsm ' Tabelle ChangeTitle_AER ' Modul mdl_07_ChangeRangeAER ‘==============================================================

Allgemein

Allgemein

Allgemein

Public Sub ChangeDataRange() Dim rngInputBox As Range ' Aktuellen »Data«-Bereich markieren ActiveSheet.Protection.AllowEditRanges("Data").Range.Select On Error Resume Next ' Neuen Bereich über InputBox wählen Set rngInputBox = Application.InputBox _ ("Markieren Sie den neuen Zellbereich mit der Maus." & _ vbNewLine & _ "Trennen Sie nicht zusammenhängende Bereiche mit einem " & _ "Semikolon.", _ "Bereich für ""Data"" ändern", _ Default:="A1:A5;I25;K25", _ Type:=8) If rngInputBox Is Nothing Then Exit Sub If AERChangeRange("Data", rngInputBox, "VBA") = False Then

Allgemein

MsgBox _ "Der benutzerberechtigte Bereich ""Data"" " & _ Listing 50

2471_Excel-VBA.book Seite 109 Dienstag, 4. Dezember 2007 1:42 13

"existiert nicht," & _ vbNewLine & _ "oder das Passwort des Blattschutzes ist falsch!", _ vbCritical, "Fehlermeldung" Else With ActiveSheet .Range("C18").Value = _ .Protection.AllowEditRanges(1).Range.Address

Allgemein

109

Allgemein

>> Allgemein

End If End Sub

Allgemein

' Neuen »Data«-Bereich markieren .Protection.AllowEditRanges("Data").Range.Select End With

Zunächst müssen die freizugebenden Bereiche je Benutzer festgelegt werden. Hierzu verwenden Sie BENANNTE BEREICHE. Markieren Sie, während Sie die STRG-Taste gedrückt halten, nacheinander alle Zellen bzw. Zeilen/Spalten, welche durch einen Benutzer geändert werden dürfen. Schreiben Sie anschließend in das Namensfeld (links neben der Bearbeitungszeile) den Usernamen (Netzwerkanmeldung unter Windows) und bestätigen die Eingabe mit der RETURN-Taste. Bereichsnamen dürfen keine Leerzeichen enthalten. Wenn in einem Anmeldenamen Leerschritte enthalten sind, müssen diese bei der Vergabe eines Bereichsnamens durch Unterstriche ersetzt werden (»Melanie Breden« als »Melanie_Breden«). Wiederholen Sie diese Schritte für weitere Benutzer. Soll es möglich sein, dass mehrere User den gleichen Bereich bearbeiten können, also eine Zuweisung von mehreren Namen an einen Bereich notwendig ist, dann wählen Sie im Namensfeld einen bereits vorhandenen Bereichsnamen aus. Der entsprechende Bereich wird daraufhin markiert. Schreiben Sie jetzt einen anderen Namen in das

Allgemein

In einem Tabellenblatt (die Mappe liegt auf dem Server und wird von mehreren Usern genutzt) sollen bestimmte Zellen bzw. Zeilen/Spalten geschützt werden, so dass diese nur gelesen und nicht geändert werden können. In Abhängigkeit des Benutzernamens (Netzwerkanmeldung unter Windows) sollen bestimmte Zellen bzw. Spalten automatisch beim Öffnen freigegeben werden.

Allgemein

Die Funktion BENUTZERBERECHTIGUNGEN ZUM BEARBEITEN VON BEREICHEN ist erst seit Excel 2002 als feste Funktion in Excel integriert. Das bedeutet aber nicht, dass Sie in den vorherigen Excel-Versionen auf diese Möglichkeit verzichten müssen. Die Freigabe definierter Bereiche können Sie ebenso über eine VBA-Prozedur steuern. Das nachfolgende Beispiel ist für alle Excel-Versionen von Excel 97 bis Excel 2007 geeignet.

Allgemein

Ausgewählte Bereiche freigeben

Allgemein

47

Allgemein

Listing 50 (Forts.)

2471_Excel-VBA.book Seite 110 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

110 >> Ausgewählte Bereiche freigeben

Namensfeld und bestätigen Sie Ihre Eingabe wieder mit der (Enter)-Taste. Beide Namen verweisen jetzt auf den identischen Bereich. Die Vergabe eines Bereichsnamens können Sie ebenso über VBA vornehmen.

Allgemein

Dim rngMyRange As Range Set rngMyRange = Range("A1:B20,D6,D9,D13") ActiveWorkbook.Names.Add Name:="Melanie_Breden", _ RefersTo:=rngMyRange

Allgemein

Noch einfacher ist die Namensvergabe über das Direktfenster:

T ipp

Beim Öffnen der Excel-Arbeitsmappe wird das Workbook_Open-Ereignis ausgelöst. In dieser Prozedur wird zunächst das betreffende Tabellenblatt an die Variable wks übergeben. Anschließend wird der unter Windows angemeldete Benutzername über die Environ-Funktion ausgelesen und in der Variablen strName gespeichert.

Allgemein

Weitere Informationen zu der Environ-Funktion erhalten Sie in Rezept 50 dieses Kapitels und im Kapitel »Einstieg«.

Um bei der Suche nach dem dazugehörigen Bereichsnamen Fehlermeldungen zu vermeiden, werden über die Funktion Wechseln, mögliche Leerzeichen im Benutzernamen durch Unterstriche ersetzt. Tabellenblattfunktionen müssen im VBA-Code mit ihren englischen Bezeichnungen aufgerufen werden. strName = Application.WorksheetFunction.Substitute _ (Environ("UserName"), " ", "_")

T ipp

Allgemein

Allgemein

Allgemein

Abbildung 33: Schnelle Namensvergabe im Direktbereich

Eine Übersicht mit Übersetzung der meisten Funktionen und Schlüsselwörter ist in der Datei VBALISTE.XLS aufgeführt. Bei einer vollständig installierten Excel-Anwendung befindet sich diese Datei auf Ihrem Rechner in dem Installationsordner. Der Standardpfad lautet unter Windows XP: C:\Programme\Microsoft Office\Office\1031\VBALISTE.XLS In Windows Vista wird die Datei standardmäßig in folgendem Pfad gespeichert:

Allgemein

C:\Program Files\Microsoft Office\Office12\1031\VBALISTE.XLS

2471_Excel-VBA.book Seite 111 Dienstag, 4. Dezember 2007 1:42 13

In Tabellenblatt SHEETNAMEDRANGE wird der Blattschutz aufgehoben und anschließend alle Zellen gesperrt. Danach wird der definierte Bereich des Benutzernamens, welcher in der Variablen strName enthalten ist, entsperrt. Über die EnableSelectionEigenschaft wird festgelegt, welche Zellen im Tabellenblatt markiert werden können. Diese Eigenschaft ist nur wirksam, wenn das Arbeitsblatt geschützt ist. Infolgedessen wird das Tabellenblatt geschützt und das Passwort Codebook vergeben. Um anzuzeigen, welche Zellen im Tabellenblatt freigegeben wurden, werden diese über die GoToMethode markiert.

Allgemein

111

Allgemein

>> Allgemein

Wird die Datei durch einen Benutzer geöffnet, für den kein Bereich definiert wurde, würde das Makro bei dem Versuch, den nach ihm benannten Bereich freizugeben, eine Fehlermeldung ausgeben. Mit der On Error Resume Next-Anweisung wird sichergestellt, dass der Code dennoch weiter ausgeführt wird, damit das Tabellenblatt nach einem eventuell auftretenden Fehler wieder geschützt wird. Vor Beendigung der Prozedur wird über die Number-Eigenschaft des Err-Objektes geprüft, ob innerhalb der Prozedur ein Fehler aufgetreten ist. In dem Fall wird eine Meldung ausgegeben, dass für den Benutzer der Datei kein freigegebener Bereich festgelegt ist.

Allgemein

Wenn der freigegebene Bereich nicht markiert werden soll, können Sie diesen Befehl auch auskommentieren oder löschen. Er beeinflusst nicht die Funktionalität des Beispiels.

Allgemein

Application.GoTo Reference:=(strName)

Wenn Sie dieses Beispiel in reellen Excel-Dateien verwenden möchten, benötigen Sie keinen definierten Bereich namens NamedRange und löschen obige Codezeilen aus der Prozedur. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_06_UserEditRange.xlsm ' Ereignis DieseArbeitsmappe ‘==============================================================

Allgemein

ActiveWorkbook.Names.Add Name:=strName, _ RefersTo:=Range("NamedRange")

Allgemein

Natürlich möchten wir Ihnen dieses Beispiel in einer Excel-Datei demonstrieren. Da wir aber Ihren Anmeldenamen nicht kennen, würde es zu einer Fehlermeldung kommen, wenn der freizugebende Bereich nach dem Autor des Beispiels benannt wäre. In der Beispieldatei wurde deshalb ein Bereich mit dem Namen NamedRange definiert. Zu Beginn der Prozedur wird der Beispieldatei ein benannter Bereich hinzugefügt. Mittels der Environ-Funktion wird Ihr Benutzername ausgelesen und über die Variable strname als Bereichsname vergeben. Als Bezug für den nach Ihnen benannten Bereich wird der bereits vorhandene Bereichsname NamedRange angegeben.

Allgemein

If Err.Number > 0 Then MsgBox "Es ist kein Bereich freigegeben"

Allgemein

Listing 51

2471_Excel-VBA.book Seite 112 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

Allgemein

112 >> Ausgewählte Bereiche freigeben Private Sub Workbook_Open() Dim wks As Worksheet Dim strName As String ' Tabellenblattname anpassen Set wks = Worksheets("SheetNamedRange") ' Windows-Anmeldenamen in Variable speichern ' mögliche Leerschritte werden durch Unterstriche ersetzt strName = Application.WorksheetFunction.Substitute _ (Environ("UserName"), " ", "_") On Error Resume Next '############################################################ ' Um dieses Beispiel zu testen wird dem unter Windows ' angemeldeten Benutzer ein vorhandener benannter Bereich ' zugewiesen. ' Wenn Sie dieses Beispiel in reellen Excel-Dateien verwenden ' möchten, löschen Sie folgende Codezeilen aus der Prozedur. ActiveWorkbook.Names.Add Name:=strName, _ RefersTo:=Range("NamedRange")

Allgemein

Allgemein

Allgemein

'############################################################ With wks ' Blattschutz aufheben .Unprotect "Codebook" ' alle Zellen sperren .Cells.Locked = True ' Bereich nach Username entsperren .Range(strName).Locked = False ' alle gesperrten Zellen nicht selektierbar .EnableSelection = xlUnlockedCells ' Blattschutz setzen .Protect "Codebook" End With ' Freigegebenen Bereich des Benutzers selektieren Application.GoTo Reference:=(strName) ' Meldung, wenn kein Bereich zu Username definiert wurde If Err.Number > 0 Then MsgBox "Es ist kein Bereich freigegeben" End Sub

Allgemein

Listing 51 (Forts.)

2471_Excel-VBA.book Seite 113 Dienstag, 4. Dezember 2007 1:42 13

Löschen von Blättern verhindern

Allgemein

Allgemein

In Excel ist es möglich die gesamte Arbeitsmappe vor Veränderungen an der Struktur zu schützen. Zeigen Sie dazu im Register ÜBERPRÜFEN in der Gruppe ÄNDERUNGEN, Schaltfläche STRUKTUR UND WINDOWS SCHÜTZEN das Dialogfeld STRUKTUR UND FENSTER SCHÜTZEN an. Aktivieren Sie das Kontrollkästchen STRUKTUR, und vergeben Sie optional ein Kennwort. Nachdem Sie das Dialogfeld mit Klick auf OK beendet haben, werden im Kontextmenü der Registerreiter wie auch in den Menüoptionen alle Funktionen, welche die Arbeitsmappenstruktur verändern können, deaktiviert (Abbildung 34).

Allgemein

48

113

Allgemein

>> Allgemein

Wenn der Arbeitsmappenschutz aktiv ist, sind folgende Funktionen weder in Excel noch mit VBA ausführbar: 왘 Blätter einfügen/löschen 왘 Blätter umbenennen

Allgemein

Abbildung 34: Deaktivierte Optionen beim Arbeitsmappenschutz

왘 Blätter verschieben/kopieren 왘 Registerfarben ändern 왘 Veränderungen in den Eigenschaften der Arbeitsmappe

Allgemein

왘 Blätter ausblenden/einblenden

Allgemein

Einzelne Blätter einer Arbeitsmappe lassen sich nur aus VBA heraus vor dem Umbenennen, Löschen etc. schützen. Dazu wird bei einem Blattwechsel im Workbook_SheetActivate-Ereignis anhand des Blattnamens überprüft, welches Blatt aktiviert wurde. Die Namen der zu schützenden Blätter sind in einer Select CaseAnweisung hinterlegt. Wenn das aktivierte Blatt aufgeführt ist, wird für die gesamte Arbeitsmappe der Strukturschutz aktiviert. Damit der Anwender nicht die Möglichkeit hat, zu experimentieren, wie er diesen Schutz umgehen kann, blenden wir zusätzlich das Kontextmenü der Registerreiter Ply aus.

Allgemein

Der Arbeitsmappenschutz gilt mappenweit, also für alle vorhandenen Arbeitsblätter. Er ist unabhängig vom Blattschutz einsetzbar.

2471_Excel-VBA.book Seite 114 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

114 >> Löschen von Blättern verhindern

Wenn Sie ein Arbeitsblatt aktivieren, welches nicht im Code aufgeführt ist, wird der Blattschutz und damit gleichzeitig der Strukturschutz aufgehoben. Bei unseren Tests hat sich herausgestellt, dass es mit etwas Geschick und Schnelligkeit möglich ist, gesicherte Blätter zu verschieben. Um dies zu erreichen, halten Sie beim Wechsel von einem ungeschützten zu einem geschützten Blatt die linke Maustaste gedrückt. Ziehen Sie dann den Registerreiter schnell an eine andere Position. Ansonsten haben wir keine weiteren Sicherheitslücken feststellen können. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_07_WorkbookProtection.xlsm ' Ereignis DieseArbeitsmappe ‘============================================================== Private Sub Workbook_SheetActivate(ByVal Sh As Object)

Allgemein

With ThisWorkbook Select Case Sh.Name Case "Tabelle1", "Tabelle3" .Protect Password:=("Codebook"), Structure:=True Application.CommandBars("Ply").Enabled = False

Allgemein

Case Else .Unprotect Password:=("Codebook") Application.CommandBars("Ply").Enabled = True End Select

Allgemein

Allgemein

End With End Sub Listing 52

Beim Wechsel in eine andere Arbeitsmappe muss sichergestellt werden, dass das Kontextmenü der Registerreiter wieder eingeblendet wird. Einen Mappenwechsel überwachen wir mit dem Workbook_Deactivate-Ereignis. Sobald dieses Ereignis eintritt, wird die Anweisung zur Aktivierung des Registerreiter-Kontextmenüs ausgeführt. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_07_WorkbookProtection.xlsm ' Ereignis DieseArbeitsmappe ‘==============================================================

Allgemein

Listing 53

2471_Excel-VBA.book Seite 115 Dienstag, 4. Dezember 2007 1:42 13

115

Private Sub Workbook_Deactivate() Application.CommandBars("Ply").Enabled = True End Sub

Allgemein

>> Allgemein

49

Schreibgeschützte Datei ohne Speichern-Rückfrage schließen

Allgemein

Listing 53 (Forts.)

Allgemein

Allgemein

Allgemein

Allgemein

Den Schreibschutz-Status einer Excel-Arbeitsmappe können Sie im Windows-Explorer über das Eigenschaftsfenster der Datei vornehmen (siehe Abbildung 35).

Folgende Prozedur gibt beim Öffnen der Arbeitsmappe die Meldung aus, ob das Attribut SCHREIBGESCHÜTZT aktiviert ist. Der Wahrheitswert dieser Option wird in der IIF-Funktion ausgelesen und der entsprechende Rückgabewert an die Funktion zurückgegeben.

Allgemein

Ob eine Excel-Arbeitsmappe schreibgeschützt ist, können Sie mit VBA ermitteln und entsprechend auf deren Einstellung reagieren.

Allgemein

Abbildung 35: Schreibschutz einstellen

2471_Excel-VBA.book Seite 116 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

116 >> Schreibgeschützte Datei ohne Speichern-Rückfrage schließen ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_08_ReadOnly.xlsm ' Ereignis DieseArbeitsmappe ‘============================================================== Private Sub Workbook_Open() MsgBox _ "Die Datei """ & ThisWorkbook.Name & """ ist " & _ vbNewLine & vbNewLine & _ IIf(ThisWorkbook.ReadOnly, _ "schreibgeschützt", _ "nicht schreibgeschützt") End Sub Listing 54

In einer schreibgeschützten Datei können Sie Veränderungen vornehmen, oder die Datei kann durch Verknüpfungen aktualisiert werden. Nach jeglichen Änderungen fragt Excel standardmäßig beim Schließen der Datei, ob die Änderungen gespeichert werden sollen. Solange die Datei als schreibgeschützt geöffnet wurde, kann auf diese Meldung eigentlich verzichtet werden. Für die Umsetzung verwenden wir das Workbook_BeforeClose-Ereignis, welches in das Codeblatt von DIESEARBEITSMAPPE geschrieben wird. Die Speicher-Abfrage richtet sich danach, welchen Wahrheitswert die Saved-Eigenschaft des Workbook-Objektes enthält. Wurden Änderungen in der Datei vorgenommen, ist dessen Wert False und Excel fragt, ob Sie die Datei speichern möchten. Demzufolge übergeben wir den Wahrheitswert der ReadOnly-Eigenschaft an die Saved-Eigenschaft. Ist der ReadOnly-Wert True, dann ist die Saved-Eigenschaft ebenfalls True. Die Speicher-Abfrage vor dem Schließen der Datei fällt dann aus. Umgekehrt wird bei einer nicht schreibgeschützten Datei der Saved-Wert auf False gesetzt und Sie werden nach einer Speicherung gefragt. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_08_ReadOnly.xlsm ' Ereignis DieseArbeitsmappe ‘============================================================== Private Sub Workbook_BeforeClose(Cancel As Boolean) ThisWorkbook.Saved = ThisWorkbook.ReadOnly End Sub Listing 55

2471_Excel-VBA.book Seite 117 Dienstag, 4. Dezember 2007 1:42 13

Private Sub Workbook_Open() MyReadOnly End Sub Listing 56

Wird der Schreibschutz für eine Datei aktiviert, die bereits schreibgeschützt ist, würde Excel eine Fehlermeldung ausgeben. Bevor in der Prozedur MyReadOnly der Schreibschutz aktiviert werden kann, muss deshalb über die ReadOnly-Eigenschaft der eingestellte Schreibschutz-Status ausgelesen werden. Wenn die Datei nicht schreibgeschützt ist, wird über die ChangeFileAccess-Methode die Zugriffsberechtigung zu der Arbeitsmappe Schreibgeschützt auf xlReadOnly eingestellt. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_09_ProtectReadOnly.xlsm ' Modul mdl_01_ReadOnly ‘============================================================== Public Sub MyReadOnly() If ThisWorkbook.ReadOnly = False Then ThisWorkbook.ChangeFileAccess _ Mode:=xlReadOnly End If End Sub Listing 57

Die Prozedur MyReadWrite hebt den Schreibschutz wieder auf. Auf dem Tabellenblatt der Beispieldatei wurden zwei Schaltflächen zum Aktivieren und Deaktivieren des Schreibschutzes erstellt. Diesen sind die beiden Prozeduren zugewiesen.

Allgemein Allgemein Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_09_ProtectReadOnly.xlsm ' Ereignis DieseArbeitsmappe ‘==============================================================

Allgemein

In folgender Prozedur wird beim Öffnen der Beispieldatei die Prozedur MyReadOnly aufgerufen.

Allgemein

Im Windows-Explorer kann über das Eigenschaften-Fenster einer Excel-Arbeitsmappe (siehe Abbildung 35) der Schreibschutz einer Datei aufgehoben werden. Dadurch kann die Datei geöffnet, Änderungen vorgenommen und die Datei gespeichert werden. Unabhängig von der Schreibschutz-Einstellung im Eigenschaftsfenster einer Datei ist es mit VBA auf einfache Weise möglich, eine Excel-Datei nur im schreibgeschützten Modus zu öffnen.

Allgemein

Entfernen des Schreibschutzes ignorieren

Allgemein

50

117

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 118 Dienstag, 4. Dezember 2007 1:42 13

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_09_ProtectReadOnly.xlsm ' Modul mdl_01_ReadOnly ‘============================================================== Public Sub MyReadWrite() If ThisWorkbook.ReadOnly = True Then ThisWorkbook.ChangeFileAccess _ Mode:=xlReadWrite End If End Sub Listing 58

51

Benutzerdefinierte Ansichten schützen

In Excel können Sie in einer Arbeitsmappe verschiedene Ansichten in einer ExcelDatei speichern. Um eine benutzerdefinierte Ansicht zu erstellen, blenden Sie die gewünschten Zeilen, Spalten und Blätter ein oder aus. Auch die Druck- und Filtereinstellungen sowie das aktive Tabellenblatt und die aktuelle Zellposition können in der Ansicht hinterlegt werden. Klicken Sie im Register ANSICHT in der Gruppe ARBEITSMAPPENANSICHTEN auf die Schaltfläche BENUTZERDEF. ANSICHTEN, klicken Sie dann auf die Schaltfläche HINZUFÜGEN und geben Sie einen Namen für die aktuelle Ansicht ein.

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

118 >> Benutzerdefinierte Ansichten schützen

Abbildung 36: Aktuelle Ansicht speichern

Mit VBA vergeben Sie mit folgender Syntax für die aktuelle Ansicht den Namen »UserA«. Die Optionen DRUCKEINSTELLUNGEN und AUSGEBLENDETE ZEILEN werden aktiviert. ActiveWorkbook.CustomViews.Add _ ViewName:="UserA", _ PrintSettings:=True, _

Allgemein

RowColSettings:=True

Um eine benutzerdefinierte Ansicht anzuzeigen wählen Sie im Register ANSICHT | BENUTZERDEF. ANSICHTEN eine Ansicht aus (siehe Abbildung 37) und klicken auf Anzeigen. Das Tabellenblatt darf bei dieser Funktion nicht geschützt sein.

2471_Excel-VBA.book Seite 119 Dienstag, 4. Dezember 2007 1:42 13

119

Allgemein

Allgemein

>> Allgemein

Um zur Ansicht Normal zu wechseln, geben Sie in der ersten InputBox das Wort »Normal« ein. Der Eingabewert wird in der Variablen mstrUser gespeichert. Wurde in der ersten InputBox auf ABBRECHEN geklickt, oder enthält diese keine Eingabe, wird die Prozedur in der ersten If...Then...Else-Anweisung beendet. In der folgenden Select Case-Anweisung wird überprüft, ob der eingegebene Wert einer definierten Ansicht entspricht. Geben Sie anschließend in der zweiten InputBox das hinterlegte Passwort zu der Ansicht ein. Für die Normal-Ansicht den Buchstaben »N«. Diese Eingabe wird zur späteren Überprüfung in der Variablen mstrPw hinterlegt. Zum Schluss der Prozedur wird in einer Select Case-Anweisung der Name der Ansicht über die Konstante cstrUser ausgewertet. In einzelnen Case-Abschnitten werden die vier gespeicherten Ansichten abgefragt. Trifft ein Ansichtsname auf den Textausdruck mstrUser zu, wird die Prozedur zur Überprüfung des Passwortes aufgerufen. Dabei wird über die Variable mstrPw das eingegebene Passwort an die aufgerufene Prozedur übergeben.

Allgemein Allgemein

Die Prozedur zum Wechsel einer benutzerdefinierten Ansicht haben wir in der Beispieldatei einer Schaltfläche zugewiesen. Oberhalb der Prozedur sind für jede Ansicht zwei Konstanten deklariert worden. Diese enthalten den Namen der Ansicht sowie das Passwort. Die Werte können in den Deklarierungszeilen beliebig geändert werden und erfordern keine weiteren Korrekturen in der Prozedur. Achten Sie jedoch darauf, dass die angegebenen Ansichtsnamen in der Arbeitsmappe vorhanden sind.

Allgemein

In unserem Beispiel wurden in der Beispieldatei vier Ansichten gespeichert. Die NORMAL-Ansicht zeigt alle Spalten des Tabellenblattes an. In den drei weiteren Ansichten wurden einzelne Spalten aus- oder eingeblendet. Die drei Ansichten sind für verschiedene Benutzer (UserA, UserB und UserC) vorgesehen und tragen die entsprechenden Namen der Anwender. Jeder dieser Benutzer soll seine Ansicht nur mit der Eingabe eines Passwortes aufrufen können.

Allgemein

ActiveWorkbook.CustomViews("UserA").Show

Allgemein

Mit VBA zeigen Sie eine benutzerdefinierte Ansicht mit folgender Syntax an:

Allgemein

Abbildung 37: Gespeicherte Ansichten anzeigen

2471_Excel-VBA.book Seite 120 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

120 >> Benutzerdefinierte Ansichten schützen ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_10_CustomViewsWithPassword.xlsm ' Modul mdl_01_MyCustomViews ‘============================================================== Private mstrUser Private mstrPw

As String As String

Const cstrNormal Const cstrPwN

As String = "Normal" As String = "N"

Const cstrUserA Const cstrPwA

As String = "UserA" As String = "A"

Const cstrUserB Const cstrPwB

As String = "UserB" As String = "B"

Const cstrUserC Const cstrPwC

As String = "UserC" As String = "C"

Public Sub MyCustomViews() mstrUser = Application.InputBox( _ "Geben Sie einen Ansichtsnamen ein:" & _ vbNewLine & _ cstrNormal & vbNewLine & _ cstrUserA & vbNewLine & _ cstrUserB & vbNewLine & _ cstrUserC, _ "Ansichten", "User", Type:=2)

Allgemein

Allgemein

Allgemein

If mstrUser = "Falsch" Or mstrUser = "" Then Exit Sub Select Case mstrUser Case cstrNormal, cstrUserA, cstrUserB, cstrUserC ' keine Anweisungen Case Else ' Fehlermeldung snzeigen MsgBox "Für " & mstrUser & " liegt keine Ansicht vor.", _ vbOKOnly & vbExclamation Exit Sub End Select mstrPw = Application.InputBox( _ mstrUser & ", geben Sie Ihr Passwort ein:", _ "Passwortabfrage", "Passwort", Type:=2) Listing 59

2471_Excel-VBA.book Seite 121 Dienstag, 4. Dezember 2007 1:42 13

Folgende Prozedur CheckPassword überprüft den Wert der Variablen mstrPw, also die Passworteingabe aus der zweiten InputBox. Man könnte diese Prozedur auch in jedem der Case-Abschnitte schreiben. Dadurch würde die erste Prozedur aber zu unübersichtlich und vier Mal den gleichen Code enthalten. Die beim Aufruf der Prozedur übergebene Zeichenkette wird in der Variablen strP gespeichert. Ist das eingegebene Passwort gleich dem hinterlegten Passwort aus der Konstantendeklarierung, wird in einer With-Anweisung zunächst der Blattschutz aufgehoben. Anschließend wird die benutzerdefinierte Ansicht aus der Eingabe der ersten InputBox angezeigt und das Tabellenblatt mit dem Passwort »Codebook« wieder geschützt. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_10_CustomViewsWithPassword.xlsm ' Modul mdl_01_MyCustomViews ‘============================================================== Public Sub CheckPassword(strP As String) If strPw strP Then MsgBox strUser & ", das Passwort ist falsch!", _ vbExclamation Exit Sub Else With ActiveSheet .Unprotect "Codebook"

Allgemein Allgemein Allgemein

Listing 59 (Forts.)

Allgemein

Select Case mstrUser Case cstrNormal CheckPassword cstrPwN Case cstrUserA CheckPassword cstrPwA Case cstrUserB CheckPassword cstrPwB Case cstrUserC CheckPassword cstrPwC End Select End Sub

Allgemein

If mstrPw = "Falsch" Or mstrUser = "" Then Exit Sub

Allgemein

121

Allgemein

>> Allgemein

' benutzerdefinierte Ansichten wurden nach Benutzernamen ‘ benannt Allgemein

Listing 60

2471_Excel-VBA.book Seite 122 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

Allgemein

122 >> Informationen des Betriebssystems auslesen ActiveWorkbook.CustomViews(strUser).Show .Protect "Codebook" End With End If End Sub Listing 60 (Forts.)

Allgemein

Allgemein

Allgemein

Allgemein

52

Informationen des Betriebssystems auslesen

Die Environ-Funktion gibt über einen Zeichenfolgen- oder numerischen Ausdruck Informationen des Betriebssystems zurück. Abhängig vom Betriebssystem wird eine unterschiedliche Anzahl von Umgebungsvariablen zur Verfügung gestellt. Die folgende Prozedur listet alle verfügbaren Umgebungsvariablen Ihres Rechners in einem neuen Tabellenblatt auf. Der Blattname wird nach dem ausgelesenen Computernamen benannt. ‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_11_OSInfo.xlsm ' Tabelle Environ-Funktion ' Modul mdl_01_OSInfo ‘============================================================== Public Sub OSInfo() Dim lngItem As Long ' Bildschirmaktualisierung ausschalten Application.ScreenUpdating = False With ThisWorkbook ' Blatt löschen, wenn das Makro schon gelaufen ist For lngItem = 1 To .Worksheets.Count If .Worksheets(lngItem).Name = Environ("ComputerName") Then ' Warnhinweise abschalten Application.DisplayAlerts = False

Allgemein

' Tabellenblatt löschen .Worksheets(lngItem).Delete ' Warnhinweise einschalten Application.DisplayAlerts = True

Allgemein

Listing 61

2471_Excel-VBA.book Seite 123 Dienstag, 4. Dezember 2007 1:42 13

' Tabellenblatt einfügen .Worksheets.Add After:=ActiveSheet End With

Allgemein

' Schleife verlassen Exit For End If Next lngItem

123

Allgemein

>> Allgemein

' Zeichenfolge von Ausgabeinformation trennen .Range("B2:B100").TextToColumns _ Destination:=.Range("B2"), _ DataType:=xlDelimited, _ Other:=True, OtherChar:="=" With .Columns("A:C") ' Spaltenbreite anpassen .AutoFit ' Zellenausrichtung links .HorizontalAlignment = xlLeft End With Listing 61 (Forts.)

Allgemein Allgemein Allgemein

lngItem = 1 Do ' numerischer Ausdruck .Cells(lngItem + 1, 1).Value = lngItem ' Zeichenfolge zu numerischem Ausdruck ' und Informationsausgabe .Cells(lngItem + 1, 2).Value = Environ(lngItem) lngItem = lngItem + 1 Loop Until Environ(lngItem) = ""

Allgemein

' Überschriften formatieren With .Range("A1:C1").Font .Bold = True .Size = 12 End With

Allgemein

' Tabellenüberschriften .Range("A1") = "Nr." .Range("B1") = "Zeichenfolge" .Range("C1") = "Ausgabe"

Allgemein

With ActiveSheet ' Blattname nach Computername benennen .Name = Environ("ComputerName")

2471_Excel-VBA.book Seite 124 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

124 >> Zwei Benutzernamen auslesen End With

Allgemein

' Bildschirmaktualisierung einschalten Application.ScreenUpdating = True End Sub Listing 61 (Forts.)

Die Information zu einer Umgebungsvariablen erhalten Sie im VBA Code mit der Syntax:

Allgemein

Environ("Zeichenfolge")

Zum Beispiel liefert Environ("OS") den Namen des Betriebssystems und Environ("Username") den unter Windows angemeldeten Benutzernamen.

Allgemein

53

Zwei Benutzernamen auslesen

Neben dem unter Windows angemeldeten Benutzernamen verwaltet Excel einen eigenständigen Benutzernamen. Diesen können Sie in Excel über die OFFICE-SCHALTFLÄCHE | EXCEL-OPTIONEN | HÄUFIG VERWENDET | BENUTZERNAME festlegen, ändern oder löschen. Im VBA-Code wird dieser mit der Syntax Application.UserName ermittelt. Ebenso können Sie den Namen des aktuellen Excel-Benutzers mit VBA ändern: Mit folgender Anweisung wird der unter Windows angemeldete Benutzername als Excel-Benutzername eingesetzt: Application.UserName=Environ("UserName")

Achtung

Allgemein

Allgemein

Application.UserName="Codebook-Leser"

Umgekehrt ist das Ändern des Windows-Benutzernamens unter VBA nicht möglich. Dieser ist Teil der Betriebssystem-Ebene und kann nur über die Verwaltung der Systemsteuerung geändert werden.

Allgemein

Allgemein

Folgendes Makro zeigt beide Benutzernamen in einem Meldungsfenster an.

Abbildung 38: Windows- und Excel-Benutzernamen anzeigen

2471_Excel-VBA.book Seite 125 Dienstag, 4. Dezember 2007 1:42 13

Public Sub ShowUserNames() MsgBox _ "Windows-Benutzername:" & vbTab & Environ("UserName") & _ vbNewLine & _ "Excel-Benutzername: " & vbTab & Application.UserName, _ Buttons:=vbInformation, _ Title:="Benutzernamen auslesen" End Sub

Allgemein

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_11_OSInfo.xlsm ' Tabelle ShowUserNames ' Modul mdl_02_ShowUserNames ‘==============================================================

Allgemein

125

Allgemein

>> Allgemein

Persönliche Informationen aus Dateieigenschaften entfernen

Seit Excel 2003 können Sie über eine Einstellung persönliche und ausgeblendete Informationen aus Excel Arbeitsmappen entfernen. Dies empfiehlt sich oftmals, wenn Sie eine Datei an andere Personen ohne persönliche Informationen weitergeben wollen. In Excel 2003 zeigen Sie die Option über den Menüpunkt EXTRAS | OPTIONEN auf der Registerkarte SICHERHEIT an. Aktivieren Sie das Kontrollkästchen BEIM SPEICHERN PERSÖNLICHE DATEN AUS DATEIEIGENSCHAFTEN ENTFERNEN.

Abbildung 39: Entfernen persönlicher Informationen aus Dateieigenschaften

Allgemein

Allgemein

Allgemein

Diese Option wird mit der Arbeitsmappe gespeichert und gilt nicht für alle alten oder neuen Excel Arbeitsmappen.

Allgemein

54

Allgemein

Listing 62

2471_Excel-VBA.book Seite 126 Dienstag, 4. Dezember 2007 1:42 13

Allgemein

126 >> Persönliche Informationen aus Dateieigenschaften entfernen

Bei jedem Speichervorgang einer Arbeitsmappe mit aktivierter Option werden die folgenden persönlichen Informationen aus dem Dokument entfernt:

Allgemein

왘 Dateieigenschaften: Autor, Manager, Firma, Zuletzt gespeichert von. 왘 Namen im Zusammenhang mit Kommentaren oder Überarbeitungen: Die Namen werden zu Autor geändert. 왘 Verteiler: Der Verteiler wird entfernt. 왘 Der Nachrichtenkopf von E-Mail-Nachrichten, der über die Schaltfläche E-MAIL generiert wird, wird entfernt.

Allgemein Allgemein

Achtung

Allgemein

Mit VBA kann man diese Funktion auch dazu verwenden, jeweils bei Bedarf die persönlichen Informationen aus einer Arbeitsmappe zu entfernen, ohne dafür die Funktion dauerhaft zu aktivieren. Folgende Prozedur schaltet zunächst mittels der DisplayAlerts-Eigenschaft alle Warnhinweise aus. Anschließend wird die Option zur Entfernung persönlicher Informationen auf True gesetzt und die Datei gespeichert. Wenn Sie ausschließen wollen, dass die Option dauerhaft mit der Arbeitsmappe gespeichert wird, muss die Option anschließend wieder auf den Standardwert False zurückgesetzt und die Datei nochmals gespeichert werden.

Allgemein

Persönliche Informationen, die möglicherweise in vorhandenen Makros, ActiveXSteuerelementen, XML-Erweiterungspaketinformationen oder Webkomponenten enthalten sind, können nicht entfernt werden. Vor dem Speichervorgang weist Excel mit einer Sicherheitswarnung, die mit OK bestätigt werden muss, nochmals darauf hin.

Allgemein

왘 Version: Der Name unter »Gespeichert von« wird zu Autor geändert.

In der Objektbibliothek findet sich neben der vorgestellten Eigenschaft keine Methode, die das Entfernen persönlicher Informationen direkt ausführt.

‘============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_12_RemovePersonalInformation.xlsm ' Tabelle RemovePersonalInformation ' Modul mdl_01_RemovePersonalInf ‘============================================================== Public Sub MyRemovePersonalInformation() ' Warnhinweise deaktivieren Application.DisplayAlerts = False

Allgemein

With ActiveWorkbook ' Eigenschaft aktivieren .RemovePersonalInformation = True Listing 63

2471_Excel-VBA.book Seite 127 Dienstag, 4. Dezember 2007 1:42 13

' Warnhinweise aktivieren Application.DisplayAlerts = True End Sub Listing 63 (Forts.)

In Excel 2007 wurde die Funktion ENTFERNEN PERSÖNLICHER INFORMATIONEN AUS DATEIEIGENSCHAFTEN aus der Oberfläche von Excel verbannt, steht aber weiterhin in der Objektbibliothek zur Verfügung. Das bedeutet, dass in Dateien mit aktivierter Einstellung auch in Excel 2007 beim Speichern persönliche Einstellungen entfernt werden. Ebenso wird möglicher vorhandener Code aus älteren Excel-Versionen mit dieser Eigenschaft ohne Fehlermeldungen in Excel 2007 ausgeführt.

Abbildung 40: Aktivierung zum Entfernen persönlicher Informationen

Allgemein Allgemein

Allgemein

Allgemein

Sowohl in Excel 2007 als auch in früheren Excel-Versionen können Sie die RemovePersonalInformation-Eigenschaft direkt im Eigenschaftenfenster der Arbeitsmappe einstellen. Aktivieren Sie dazu im VBA Projektexplorer das Klassenmodul DIESEARBEITSMAPPE des VBA Projektes und stellen Sie dann im Eigenschaftenfenster die RemovePersonalInformation-Eigenschaft auf True.

Allgemein

' Eigenschaft deaktivieren .RemovePersonalInformation = False ' Datei erneut speichern .Save End With

Allgemein

' Beim Speichervorgang werden persönliche Informationen ' aus Dateieigenschaften und Namen in Kommentaren entfernt .Save

Allgemein

127

Allgemein

>> Allgemein

2471_Excel-VBA.book Seite 128 Dienstag, 4. Dezember 2007 1:42 13

Achtung

Wenn Sie die RemovePersonalInformation in einer Datei manuell auf True setzen, um bei jedem Speichervorgang die persönlichen Informationen zu entfernen, sollte die Datei in dem für Makros erlaubten Dateityp *.XLSM gespeichert werden. Wird die Datei im normalen Excelformat *XLSX, also ohne Makros gespeichert, erfolgt bei jedem Speichervorgang ein Hinweisfenster. Selbst wenn eine Datei keinen VBA Code oder Module enthält, reicht die auf True eingestellte RemovePersonalInformation-Eigenschaft aus, um eine Makromeldung hervorzurufen.

55

Mit Dokumentinspektor Daten und Informationen entfernen

In Office 2007 wurde das Entfernen persönlicher Informationen durch den Dokumentinspektor erweitert. Zeigen Sie den Dokumentinspektor (siehe Abbildung 41) mit Klick auf die OFFICE-SCHALTFLÄCHE | VORBEREITEN | DOKUMENT PRÜFEN an.

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

128 >> Mit Dokumentinspektor Daten und Informationen entfernen

Abbildung 41: Prüfen von Arbeitsmappen auf ausgeblendete Daten und persönliche Informationen

In der VBA Objektbibliothek wird der Dokumentinspektor über die Workbook.RemoveDocumentInformation-Methode angesprochen. Die Syntax lautet:

Allgemein

Workbook.RemoveDocumentInformation(RemoveDocInfoType)

Der Methode stehen folgende Konstanten, die namentlich für sich selbst sprechen, zur Verfügung:

2471_Excel-VBA.book Seite 129 Dienstag, 4. Dezember 2007 1:42 13

129

XlRemoveDocInfoType-Konstanten

Allgemein

>> Allgemein

xlRDIAll xlRDIComment

xlRDIDefinedNameComments xlRDIDocumentManagementPolicy xlRDIDocumentProperties

Allgemein

xlRDIContentType

xlRDIDocumentServerProperties

xlRDIEmailHeader xlRDIInactiveDataConnections xlRDIInkAnnotations

Allgemein

xlRDIDocumentWorkspace

xlRDIlPublishInfo xlRDIRemovePersonalInformation

Im Gegensatz zu der RemovePersonalInformation-Eigenschaft aus Rezept 54, der man einen booleschen Wert zuweisen muss, führt die RemoveDocumentInformation-Methode einen Befehlsaufruf zur Laufzeit des Codes aus. Folgende Prozedur entfernt in der aktiven Arbeitsmappe sämtliche Dateieigenschaften. Im Vergleich dazu entfernt die RemovePersonalInformation-Eigenschaft aus dem vorherigen Rezept aus den Dateieigenschaften nur den Autor, Manager, Firma und das Datum, wann die Datei zuletzt gespeichert wurde. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\02_Allgemein\ ' Dateiname 02_12_RemovePersonalInformation.xlsm ' Tabelle RemoveDocumentInformation ' Modul mdl_02_RemoveDocumentInf ‘=============================================================== Public Sub MyRemoveDocumentInformation() ActiveWorkbook.RemoveDocumentInformation (xlRDIDocumentProperties) End Sub

Allgemein

Tabelle 7: Arten von ausgeblendeten Daten und persönlichen Informationen

Allgemein

xlRDISendForReview

Allgemein

xlRDIScenarioComments

Allgemein

xlRDIRoutingSlip

Wollen Sie anstelle der Dokumenteneigenschaften andere ausgeblendete Daten oder persönliche Informationen aus einer Arbeitsmappe entfernen, dann wählen Sie

Allgemein

Listing 64

2471_Excel-VBA.book Seite 130 Dienstag, 4. Dezember 2007 1:42 13

anstelle der xlRDIDocumentProperties eine andere Konstante, die beim Schreiben des Befehls in der Intellisense-Auflistung angezeigt wird (siehe Abbildung 42).

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

Allgemein

130 >> Mit Dokumentinspektor Daten und Informationen entfernen

Abbildung 42: Intellisense mit Konstanten der RemoveDocumentInformationMethode

Datum/Zeit

2471_Excel-VBA.book Seite 131 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit Microsoft Excel speichert Datumsangaben intern als fortlaufende Zahlen, um sie in Berechnungen verwenden zu können. Die Zahl 1 entspricht standardmäßig dem 1. Januar 1900, die Zahl 39083 ist gleich dem 01. Januar 2007, da er genau 39083 Tage nach dem 1. Januar 1900 liegt. Zeitangaben werden intern als Bruchteile eines ganzen Tages gespeichert, da die Uhrzeit als Untermenge des Tages betrachtet wird. 1 Tag = 1 1 Stunde = 1/24

Datum/Zeit

Datum und Zeitformat anpassen

Datum/Zeit

56

1 Minute = 1/1440 (24*60)

Anzeige

Monat

Anzeige

Jahr

Anzeige

T

1

M

1

J

7

TT

01

MM

01

JJ

07

TTT

Mi

MMM

Jan

JJJJ

2007

TTTT

Mittwoch

MMMM

Januar

Tabelle 8: Datumsformatierungen

Je nach Kombination der Buchstaben erzeugen Sie individuelle Datumsformate, die durch zusätzliche Textangaben ergänzt werden können. Der definierte Text muss dabei zwischen Anführungszeichen gesetzt werden.

Datum/Zeit Datum/Zeit

Tag

Datum/Zeit

Die Formatierung der Tage, Monate und Jahre werden durch Angabe von Buchstaben dargestellt. Für die Anzeige der Tage verwenden Sie den Buchstaben T. Die Monatsanzeige geben Sie über den Buchstaben M, die Jahreszahl über den Buchstaben J an. Je nachdem wie oft Sie den Buchstaben eingeben, ändert sich die Anzeige in der Zelle. Am besten lässt sich dies an einem Beispiel veranschaulichen. Der Tag des Datums 01.01.2007 lässt sich auf vier verschiedene Arten anzeigen.

Datum/Zeit

Über das Zellenformat kann eine Zahl in einem beliebigen Datum- oder Zeit-Format dargestellt werden. Öffnen Sie den Dialog ZELLEN FORMATIEREN über die Registerkarte START in der Gruppe ZAHL oder drücken Sie die Tastenkombination (Strg) (1) um die selektierten Zellen zu formatieren. Auf der Registerkarte Zahlen des Dialogfeldes können Sie in der Kategorie BENUTZERDEFINIERT eigene Zahlenformate definieren. Siehe dazu auch Abbildung 43.

Datum/Zeit

1 Sekunde = 1/86400 (24*60*60)

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 132 Dienstag, 4. Dezember 2007 1:42 13

132 >> Datum und Zeitformat anpassen Darstellung in Zelle

Kategorie

Zellenformat

39083

Standard

01.01.2007

Datum

TT.MM.JJJJ

So, 01.01.2007

Benutzerdefiniert

TTT, TT.MM.JJJJ

Mittwoch, der 01.01.2007

Benutzerdefiniert

TTTT, "der" TT.MM.JJJJ

München, den 1. Jan 2007

Benutzerdefiniert

"München, den" T. MMM JJJJ

Datum/Zeit

Datum/Zeit

Datum/Zeit

Tabelle 9: Datumsformate

Uhrzeiten können standardmäßig in Stunden, Minuten und Sekunden angezeigt werden. Für die Formatierung werden wieder Buchstaben verwendet. Der Buchstabe h steht für Stunden, m für Minuten und s für Sekunden. Da der Buchstabe M sowohl für den Monat im Datumsformat als auch für die Minutenanzeige im Uhrzeitformat verwendet wird, werden die Schriftzeichen des Uhrzeitformats in Kleinbuchstaben angegeben. Am Beispiel der Uhrzeit 08:05:09 kann man die Auswirkung der einzelnen Buchstaben gut erkennen: Format

Darstellung

h

8

hh

08

m

5

mm

05

s

9

ss

09

Tabelle 10: Uhrzeitformate

Datum/Zeit

Datum/Zeit

Auch beim Uhrzeitformat gibt es benutzerdefinierte Formatierungsmöglichkeiten. Darstellung in Zelle

Kategorie

0,5200833

Standard

12:30:00

Uhrzeit

hh:mm:ss

12

Benutzerdefiniert

[hh]

750

Benutzerdefiniert

[mm]

45000

Benutzerdefiniert

[ss]

12 Uhr 30 Minuten

Benutzerdefiniert

hh "Uhr" mm "Minuten"

Datum/Zeit

Tabelle 11: Zeitformate

Zellenformat

133

Die Anzeige und Berechnung von Hundertstelsekunden erreichen Sie in Excel über das benutzerdefinierte Zahlenformat hh:mm:ss,000.

Tipp

Im Tabellenblatt DATEFORMAT der Beispieldatei wird das Zellenformat eines Datums über ein Kombinationsfeld aus der STEUERELEMENT-TOOLBOX-Symbolleiste geändert. Hierzu verwenden wir das Change-Ereignis der ComboBox, welches bei jeder Änderung des Kombinationsfeldes ausgelöst wird. Der zu der Auswahl gehörende Formattyp steht im Tabellenblatt in dem benannten Bereich CellFormat und wird in der Prozedur ausgelesen. Ausführliche Informationen zu Steuerelementen und deren Ereignisse finden Sie im Kapitel »Steuerelemente«.

Datum/Zeit

Das Zellenformat lässt sich sowohl über das Dialogfeld ZELLEN FORMATIEREN laut Abbildung 43 als auch per VBA Code bestimmen.

Datum/Zeit

Im Dialogfenster ZELLEN FORMATIEREN in den Kategorien DATUM und UHRZEIT, Listenfeld TYP können Sie ein vordefiniertes Format auswählen. Die Standardeinstellung der Systemsteuerung erkennen Sie an dem jeweils vorangestellten Sternchen (*).

Datum/Zeit

Abbildung 43: Standardeinstellung der Systemsteuerung

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Hinwei s

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 133 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 134 Dienstag, 4. Dezember 2007 1:42 13

134 >> Datum und Zeitformat anpassen '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Tabelle DateFormat ' Ereignis Tabelle2 (DateFormat) '=================================================================== Private Sub ComboBox1_Change() Dim strFormat As String ' Datumsformat aus Liste ermitteln strFormat = Cells(ComboBox1.ListIndex + 2, [CellFormat].Column) ' Format an Zelle zuweisen Range("B6").NumberFormat = strFormat End Sub

Datum/Zeit

Listing 65

Analog dazu wird im Tabellenblatt TIMEFORMAT ein Zeitwert in unterschiedlichen Formatierungen in einer Zelle angezeigt. Der Code ist fast identisch zum vorhergehenden, geändert haben sich lediglich der Name des Steuerelementes und der Bereichsname.

Datum/Zeit

Abbildung 44: Zeiten formatieren

Wie Sie einen bereits vorhandenen Zellinhalt über das Zellformat im Dialog ZELLEN FORMATIEREN formatieren können, wissen Sie jetzt. Mit VBA ist es mit der FormatFunktion möglich, in eine Zelle einen formatierten Textwert hineinzuschreiben, dies geschieht unabhängig vom vorhandenen Zellenformat. Range("A1")=Format(Date,"MMMM") ' liefert den Monat der Systemzeit ' im Textformat

Achtung

Datum/Zeit

Datum/Zeit

Datum/Zeit

strFormat = Cells(ComboBox2.ListIndex + 2, [CellFormatTime].Column)

Wenn Sie einer im Format Text formatierten Zelle mit VBA ein Datum beliebigen Formates zuweisen, wird Excel dieses Datum korrekt anzeigen. Im Hintergrund bleibt diese Zelle allerdings weiterhin im Textformat bestehen, was zu Problemen bei weiteren Berechnungen führen kann.

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Tabelle VBA_Format ' Modul mdl_01_DateFormat '=================================================================== Public Sub DateToday () ' liefert das aktuelle Datum im Format »dd.mm.yyyy« MsgBox Date End Sub Listing 66

Über die Format-Funktion weisen Sie einer Zelle oder Variablen neben einem Wert zugleich ein Format zu. Der zugewiesene Wert wird in dem angegebenen Formatausdruck dargestellt. Beachten Sie, dass die Format-Funktion einen Wert im Textformat zurückgibt. Das erkennen Sie daran, dass ein über die Format-Funktion gesetztes Datum in einer Zelle links ausgerichtet ist. Die Syntax dazu lautet:

Datum/Zeit

Werden Datums- oder Zeitangaben in der Entwicklungsumgebung vorgenommen, dann wird ohne spezifische Formatanweisung das kurze Datums- oder Zeitformat aus den aktuellen Systemeinstellungen zur Darstellung verwendet.

Datum/Zeit

135

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 135 Dienstag, 4. Dezember 2007 1:42 13

Geben Sie zusätzlich zu dem Datumsformat einen Text in dem Formatausdruck mit an, dann muss der Text zusätzlich in doppelte Anführungszeichen gesetzt werden. Daraus resultieren die vielen Anführungszeichen in dem nachfolgenden BeispielCode. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Tabelle VBA_Format ' Modul mdl_01_DateFormat '=================================================================== Public Sub DateAndPlace() MsgBox Format(Date, """München, den"" dd.mmmm yyyy") End Sub

Datum/Zeit

Format(Date, "DD. MMMM YYYY")

Datum/Zeit

Die Angabe des Formates wird in einem String dargestellt, welcher jeweils mit Anführungszeichen beginnt und endet.

Datum/Zeit

Format(Ausdruck, Format)

Datum/Zeit

Listing 67

136 >> Wochentag des Geburtstages ermitteln

57

Wochentag des Geburtstages ermitteln

Um herauszufinden, an welchem Wochentag Sie geboren sind, brauchen Sie nicht einmal VBA oder eine Formel für die Berechnung einzusetzen. Wie eingangs erwähnt, steht in einer Zelle lediglich eine Zahl. Das Erscheinungsbild dieser Zahl wird jedoch durch die Formatierung der Zelle bestimmt. Geben Sie in eine Zelle Ihr Geburtsdatum, zum Beispiel 03.12.1966, ein und formatieren Sie diese Zelle im benutzerdefinierten Zahlenformat TTTT. An dem Inhalt der Bearbeitungszeile sehen Sie, dass in der Zelle immer noch das eingegebene Datum 03.12.1966 steht. Die Zelle selbst aber stellt den Wochentag Samstag dar.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 136 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 45: Wochentag eines Datums

In VBA wird der Wochentag eines Datums am einfachsten mit der Format-Funktion ermittelt. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Tabelle DateFormat ' Modul mdl_01_DateFormat '===================================================================

Datum/Zeit

Listing 68

Private Sub CommandButton1_Click() ' Wochentag des aktuellen Tages ermitteln MsgBox "Heute ist " & Format(Date, "DDDD") End Sub Listing 68 (Forts.)

58

Anzeigen des Systemdatums

In der VBA-Umgebung wird das aktuelle Datum mit der Date-Funktion ermittelt. Hierbei wird, ebenso wie über die Tastenkombination (Strg) (.) oder die Tabellenfunktionen =HEUTE(), das eingestellte Datum der Systemsteuerung abgerufen und im kurzen Datumsformat in die aktive Zelle geschrieben. Die Time-Funktion gibt die aktuelle Uhrzeit zurück und die Funktion Now liefert das aktuelle Datum und die Uhrzeit.

Datum/Zeit

137

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 137 Dienstag, 4. Dezember 2007 1:42 13

ActiveCell = Date

Date = "24.12.2030"

Abbildung 46: Datumsumstellung der Systemzeit

Datum/Zeit

Durch Zuweisung eines Werts an die Date-Funktion kann das Systemdatum geändert werden, was jedoch zu unerwünschten Nebeneffekten führen kann und deshalb mit Vorsicht zu gebrauchen ist. Die gesamte Windows-Umgebung ist von dieser Einstellung betroffen. Das zugewiesene Datum wird als aktuelles Datum eingestellt und täglich um einen Tag erhöht.

Datum/Zeit

Achtung

Dim Date1 As Date Date1 = Date MsgBox Date1

Datum/Zeit

Selbstverständlich sind diese Funktionen nicht nur darauf beschränkt, Werte in Zellen zu schreiben. Sie können auch einer Variablen das aktuelle Systemdatum oder die aktuelle Zeit zuweisen um die Werte im weiteren Code zu verwenden:

Datum/Zeit

ActiveCell = Now

Datum/Zeit

ActiveCell = Time

Datum/Zeit

Datum/Zeit

138 >> Schaltjahre bestimmen

Hinwei s

Datum/Zeit

2471_Excel-VBA.book Seite 138 Dienstag, 4. Dezember 2007 1:42 13

59

Unter Windows Vista kann das Einstellen der Systemzeit mit VBA zu einem Fehler führen, wenn die Benutzerkontensteuerung (UAC User Account Control) aktiviert ist. Nicht autorisierte Änderungen (dazu gehört das Einstellen der Systemzeit) sollen dadurch verhindert werden und zum Schutz des Computers beitragen.

Schaltjahre bestimmen

Nach dem Gregorianischen Kalender, der heute weltweit verbreitet ist, haben Gemeinjahre 365 Tage, Schaltjahre 366 Tage. Nach der genauen wahren Dauer des Umlaufs der Erde um die Sonne hat ein Jahr allerdings 365,25 Tage. Um diese Ungenauigkeit auszugleichen, wurde als Schalttag der 29. Februar eingeführt. Letztendlich wurden im Oktober 1582 von Papst Gregor XIII folgende Regeln aufgestellt. Diese definieren, welches Jahr ein Schaltjahr ist. 왘 Glatt durch 4 teilbare Jahre sind Schaltjahre

Datum/Zeit

왘 Glatt durch 400 teilbare Jahre sind aber wieder Schaltjahre So sind z. B. die Jahre 1800, 1900 und 2100 keine Schaltjahre. Die Jahre 2000, 2400 dagegen sind Schaltjahre. In den Schaltjahren hat ein Jahr also 366 Tage, da der 29. Februar enthalten ist. Damit dauert das Gregorianische Jahr 365,2425 Tage. Für Jahreszahlen ab 1901 liefert folgende Tabellenformel das Ergebnis WAHR für ein Schaltjahr und FALSCH für kein Schaltjahr. In der Zelle A1 wird eine Jahreszahl erwartet. =TAG(DATUM(A1;2;29))=29

Bei der Schaltjahrberechnung macht Excel im Jahr 1900 allerdings einen Fehler. Hier zeigt Excel nach dem 28.02. den 29.02. an und nicht den 01.03.1900. Um für alle Jahre ein Schaltjahr korrekt zu definieren, verwenden Sie folgende Formel, die diesen Makel ausgleicht. =N(TAG(("3/"&A1+(2000*(A1> Dateizugriffe dokumentieren .Cells(LastRow, 2).Value = Application.UserName End With ' Fehlerbehandlung, falls Datei von nicht ' beschreibbarer CD geöffnet wird On Error Resume Next ThisWorkbook.Save End Sub

Datum/Zeit

Datum/Zeit

Listing 70 (Forts.)

Um dieses Blatt vor anderen Benutzern unsichtbar zu machen, können Sie das Tabellenblatt über den Menüpunkt FORMAT | BLATT aus- und einblenden. Im VBA-Code verwenden Sie dazu folgende Befehle: Worksheets("Logbook ").Visible = xlSheetHidden Worksheets("Logbook ").Visible = xlSheetVisible

' ausblenden ' einblenden

Im Eigenschaftsfenster des Tabellenblattes bzw. mit VBA ist es möglich, Tabellenblätter so auszublenden, dass diese nur im VBA Editor oder via VBA Code eingeblendet werden können. Klicken Sie dazu im Projektexplorer des VBA Editors auf das Tabellenblatt und setzen Sie im dazugehörigen Eigenschaftsfenster die Visible-Eigenschaft des Tabellenblattes auf xlSheetVeryHidden.

Datum/Zeit

' verstecken

Die VBA Befehle zum Ein- und Ausblenden des Tabellenblattes LOGBOOK haben wir im Tabellenblatt DATEFORMAT der Beispieldatei einer Umschaltfläche zugewiesen. Je nach Wert der Umschaltfläche wird das Tabellenblatt ein- oder ausgeblendet. Den Code dazu können Sie zum Beispiel in einer If...Then...Else-Anweisung einarbeiten: If ToggleButton1.Value = True Then Worksheets("Logbook").Visible = xlSheetVeryHidden Else Worksheets("Logbook").Visible = xlSheetVisible End If

Anstelle der If...Then...Else-Anweisung können Sie bei diesem Beispiel ebenso die IIF-Funktion verwenden. Die IIF-Funktion wertet einen vorgegebenen Ausdruck als WAHR oder FALSCH aus und gibt den definierten Rückgabewert aus. Die Syntax der IIF-Funktion lautet: IIf(expr, truepart, falsepart).

Achtung

Datum/Zeit

Datum/Zeit

Datum/Zeit

Worksheets("Logbook ").Visible = xlSheetVeryHidden

Die IIf-Funktion wertet immer sowohl den Teil truepart als auch den Teil falsepart aus, auch dann, wenn nur einer von beiden Teilen zurückgegeben wird. Aus diesem Grund kann es zu unerwünschten Nebeneffekten kommen. Wenn z. B. die Auswertung von falsepart zu einem Fehler aufgrund einer Division durch Null führt, tritt ein Fehler auch dann auf, wenn expr den Wert True hat.

>> Datum/Zeit

141

Wir wollen also der Visible-Eigenschaft des Tabellenblattes einen Wert zuweisen: Worksheets("Logbook").Visible = ..._ ' Wahrheitswert

Datum/Zeit

2471_Excel-VBA.book Seite 141 Dienstag, 4. Dezember 2007 1:42 13

Dieser Wert wird über die IIF-Funktion ermittelt: Ist der Ausdruck ToggleButton1.Value = True WAHR, dann gibt die IIF-Funktion den hinterlegten Wahrheitswert xlSheetVeryHidden

Datum/Zeit

IIf(ToggleButton1.Value = True, xlSheetVeryHidden, xlSheetVisible)

Worksheets("Logbook").Visible = xlSheetVeryHidden

Ist der Ausdruck jedoch FALSCH, dann gibt die IIF-Funktion den Parameter falsepart zurück. In unserem Beispiel haben wir diesem Parameter den Wert xlSheetVisible übergeben, wodurch das Tabellenblatt LOGBOOK eingeblendet wird. Das würde folgender Schreibweise entsprechen:

Datum/Zeit

zurück und das Tabellenblatt LOGBOOK wird versteckt. Das entspricht der Schreibweise:

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Tabelle DateFormat ' Ereignis Tabelle2 (DateFormat) '===================================================================

Datum/Zeit

Die Beschriftung der Umschaltfläche über die Caption-Eigenschaft und die Zuweisung der Visible-Eigenschaft werden in je einer IIF-Funktion in einer Prozedur abgearbeitet.

Datum/Zeit

Worksheets("Logbook ").Visible = xlSheetVisible

Application.ScreenUpdating = True End Sub Listing 71

Datum/Zeit

' Tabellenblatt nach Wert der Umschaltfläche ein-/ausblenden Worksheets("Logbook").Visible = _ IIf(ToggleButton1.Value = True, _ xlSheetVeryHidden, xlSheetVisible)

Datum/Zeit

' Beschriftung auf Umschaltfläche zuweisen Me.ToggleButton1.Caption = _ IIf(ToggleButton1.Value = True, _ "Logbook einblenden", "Logbook ausblenden")

Datum/Zeit

Private Sub ToggleButton1_Click() Application.ScreenUpdating = False

142 >> Bestandsveränderungen dokumentieren

61

Bestandsveränderungen dokumentieren

Nachfolgend zeigen wir Ihnen ein kleines Beispiel, welches nicht nur das Thema Datum/Zeit und die dazugehörige Formatierung betrifft, sondern zugleich das Ereignis Worksheet_Change nutzt und die sinnvolle Verwendung eines benannten Bereichs aufzeigt. In der verwendeten Warenbestandstabelle werden zu verschiedenen Artikeln die entsprechenden Stückzahlen in Zellen eingetragen. Die Eingabe der Stückzahl erfolgt im Bereich D2:D18. Diesem Bereich wurde über die Registerkarte FORMELN | DEFINIERTE NAMEN | NAMEN DEFINIEREN der Name Number zugewiesen.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 142 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 47: Benannter Bereich

Der Vorteil dieser Namensvergabe liegt klar auf der Hand. Angenommen, Sie wollen für die Zeitdokumentation nicht zwei Spalten »Datum und Uhrzeit« wie in unserem Beispiel verwenden, sondern halten lediglich das »Datum« oder »Datum und Zeit« in einer Spalte fest. Dann können Sie die überflüssige Spalte aus der Tabelle löschen. Der vorherige Bezug zwischen dem Namen Number und dem Bereich D2:D18 wird auf den neuen Bereich C2:C18 angeglichen. Würden Sie sich im Code auf einen absoluten Bereich Range("D2:D18") festlegen, müssten Sie das Makro an die neue Tabellenstruktur anpassen und den Wirkungsbereich des Makros in Range("C2:C18") ändern. Mit der Verwendung eines benutzerdefinierten Namens halten Sie Ihre Tabellenstruktur variabel und vermeiden Fehlerquellen.

In unserer Beispieltabelle werden drei verschiedene Formate zugewiesen. Sie sehen, dass das Format Short Date das gleiche Ergebnis zeigt wie die benutzerdefinierte Datumsformatierung DD.MM.YYYY, da Short Date das kurze Datumsformat aus den Einstellungen der Systemsteuerung verwendet. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Tabelle shortDate ' Ereignis Tabelle4(shortDate) '================================================================== Private Sub Worksheet_Change(ByVal Target As Range) ' Überprüfung auf Änderungen in benanntem Bereich If Application.Intersect(Target, [Number]) Is Nothing _ Then Exit Sub

Listing 72

_

Datum/Zeit

_

_

_

Datum/Zeit

_

_ Datum/Zeit

' Überprüfung der geänderten Zeile Select Case (Target.Row) Case Is > 13 Cells(Target.Row, Range("Date1").Column) = Format(Date, "DDDD DD.MM.YYYY") Cells(Target.Row, Range("Time1").Column) = Format(Time, "hh:mm:ss") Case Is > 7 Cells(Target.Row, Range("Date1").Column) = Format(Date, "DD.MM.YYYY") Cells(Target.Row, Range("Time1").Column) = Format(Time, "hh:mm") Case Is > 1 Cells(Target.Row, Range("Date1").Column) = Format(Date, "Short Date") Cells(Target.Row, Range("Time1").Column) = Format(Time, "Short Time")

Datum/Zeit

' Ereignisse deaktivieren Application.EnableEvents = False On Error Resume Next

Datum/Zeit

Nachdem in dem Tabellenblatt SHORTDATE ein Zellwert geändert wurde, überprüft die Intersect-Methode im Worksheet_Change-Ereignis des Tabellenblattes, ob die Eingabezelle im Bereich Number erfolgt ist. Liegt keine Übereinstimmung der Schnittmenge zwischen Eingabezelle und dem definierten Bereich vor, wird die Prozedur mit der Anweisung Exit Sub beendet. Befindet sich die Eingabezelle Target im angegebenen Range, geht das Makro zur Select Case-Anweisung weiter. Hier wird überprüft, in welcher Zeile die Änderung gemacht wurde, damit das jeweilige Format für die Eingabezelle aus der Zelle ausgelesen wird.

Datum/Zeit

143

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 143 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

2471_Excel-VBA.book Seite 144 Dienstag, 4. Dezember 2007 1:42 13

144 >> Vereinfachte Datumseingabe End Select

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

' Ereignisse deaktivieren Application.EnableEvents = True End Sub Listing 72 (Forts.)

Nachfolgend sehen Sie eine Auflistung der in Excel zur Verfügung stehenden benannten Datums- und Zeitformate und deren Bedeutung. Format

Beschreibung

General Date

Zeigt ein Datum und/oder eine Zeit an. Bei reellen Zahlen werden Datum und Uhrzeit angezeigt (zum Beispiel 4.3.93 05:34). Werden keine Nachkommastellen angegeben, so wird nur ein Datum (zum Beispiel 4.3.93) angezeigt. Enthält der Wert ausschließlich Nachkommastellen, so wird nur eine Uhrzeit ausgegeben (zum Beispiel 05:34). Die Anzeige von Datum und Zeit wird durch die Systemeinstellungen festgelegt.

Long Date

Zeigt ein Datum im langen Datumsformat entsprechend den Systemeinstellungen an.

Medium Date

Zeigt ein Datum im mittleren Datumsformat an, das von der Sprachversion der Host-Anwendung bestimmt wird.

Short Date

Zeigt ein Datum im kurzen Datumsformat entsprechend den Systemeinstellungen an.

Long Time

Zeigt eine Zeit entsprechend der Einstellung für das lange Zeitformat an, einschließlich Stunden, Minuten und Sekunden.

Medium Time

Zeigt eine Zeit im 12-Stunden-Format mit Stunden, Minuten und einer AM/PM-Kennung an.

Short Time

Zeigt eine Zeit im 24-Stunden-Format an (zum Beispiel 17:45).

Tabelle 12: Benannte Datums- und Zeitformate

62

Vereinfachte Datumseingabe

Datum/Zeit

Datum/Zeit

Die schnellste Art, das aktuelle Datum in der selektierten Zelle auszugeben, ist über die Tastenkombination (Strg) (.). Um die aktuelle Uhrzeit einzufügen drücken Sie (Strg) (:). Für das Datum gilt in Deutschland der Punkt als Trennzeichen zwischen Tag, Monat und Jahr. Die Datumseingabe können Sie sich vereinfachen, indem Sie statt des Punktes das Minuszeichen auf der Nummerntastatur eingeben. Dadurch ersparen Sie sich den Wechsel zwischen der Nummer- und Schreibtastatur.

Abbildung 48: Vereinfachte Datumseingabe

Ein Datum des aktuellen Jahres können Sie auch noch schneller eingeben. Tippen Sie auf der Nummerntastatur zuerst die Tageszahl gefolgt von dem Divisionszeichen und der Monatszahl. Für den 1. Januar schreiben Sie (1) (/) (1). Nachdem Sie die Eingabezelle verlassen haben, generiert Excel daraus den ersten Januar des derzeitigen Jahres.

Datum/Zeit

145

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 145 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Eine einfache Möglichkeit, sich diese Arbeit zu erleichtern, erhalten Sie durch die Autokorrektur. Klicken Sie auf die OFFICE-SCHALTFLÄCHE und anschließend auf EXCELOPTIONEN. Wählen Sie auf der linken Seite den Eintrag DOKUMENTENPRÜFUNG und klicken Sie auf die Schaltfläche AUTOKORREKTUR-OPTIONEN. Aktivieren Sie den Register AUTOKORREKTUR und geben Sie im Eingabefeld ERSETZEN zwei Pluszeichen (+) (+), im Eingabefeld DURCH einen Doppelpunkt (:) ein, klicken Sie auf HINZUFÜGEN und schließen Sie den AUTOKORREKTUR-Dialog wieder.

Datum/Zeit

Oft muss man in einer Tabelle sehr viele Uhrzeiten eintippen, zum Beispiel in einer Arbeitszeittabelle. Damit Excel die Eingabe als Uhrzeit erkennt, ist es erforderlich die Stunden durch einen Doppelpunkt von den Minuten zu trennen. Für die Uhrzeit 12:49 geben Sie über den Nummernblock der Tastatur die Zahlen 1 und 2 ein, müssen dann auf die Schreibtastatur wechseln um mit (Shift) (.) einen (:) zu erzeugen, und wieder zurück auf den Nummernblock um die Minuten einzutippen.

Datum/Zeit

Uhrzeiten mit Autokorrektur

Datum/Zeit

63

Datum/Zeit

Abbildung 49: Schnelles Datum des aktuellen Jahres

146 >> Uhrzeiten mit Autokorrektur

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 146 Dienstag, 4. Dezember 2007 1:42 13

Sobald Sie in einer Zelle zwei Zahlen, gefolgt von zwei Plus-Zeichen und wieder zwei Zahlen hintereinander eingeben, ersetzt Excel diese zwei Plus-Zeichen durch einen Doppelpunkt und es entsteht eine für Excel zulässige Uhrzeit. Selbstverständlich funktioniert das auch mit anderen Zeichen-Kombinationen.

Abbildung 51: Schnelle Uhrzeiteingabe durch AutoKorrektur

Hinweis

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Abbildung 50: Autokorrektur Doppelpunkt

Einstellungen der AutoKorrektur wirken sich auf die gesamte Excel-Anwendung aus und nicht nur auf die Datei, die gerade aktiv war, als die Einstellungen geändert wurden.

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_01_DateAndTimeFormat.xlsm ' Modul mdl_02_Replacement '=================================================================== Public Sub MyAddReplacement() ' Autokorrektur von zwei Pluszeichen zu einem Doppelpunkt Application.AutoCorrect.AddReplacement _ What:="++", Replacement:=":" End Sub Public Sub MyDeleteReplacement() ' Autokorrektur-Eintrag löschen Application.AutoCorrect.DeleteReplacement _ What:="++" End Sub Listing 73

64

Uhrzeiten ohne Doppelpunkt eingeben

Datum/Zeit

Die Einstellung der Autokorrektur lässt sich auch mit VBA einstellen.

Datum/Zeit

147

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 147 Dienstag, 4. Dezember 2007 1:42 13

Eingabe

Ergebnis

1

00:01

10

00:10

100

01:00

1000

10:00

Datum/Zeit

Viel einfacher wäre es doch, Sie tippen lediglich die vier Zahlen ein, welche eine Uhrzeit erfordert, und Excel setzt diese Eingabe in ein von Ihnen gewünschtes Format um. Selbstverständlich muss das Weiterrechnen mit diesem Zellinhalt auch dann noch gewährleistet sein.

Datum/Zeit

Die Eingabe von Uhrzeiten über die Autokorrektur ist schon eine große Erleichterung, aber geht das nicht noch ein bisschen bequemer?

Datum/Zeit

Nach Eingabe eines Wertes in eine Zelle wird das Worksheet_Change-Ereignis ausgelöst (Näheres zu Ereignis-Prozeduren erfahren Sie in der entsprechenden Kategorie). Dieses Ereignis nutzen Sie, um eine laufende Umwandlung der Eingaben in das Uhrzeitformat durchzuführen. Die Prozedur wird in den Codebereich des Tabellenblattes geschrieben, in welchem die Umwandlung in das Uhrzeitformat ausgeführt werden soll. Es ist erforderlich den Zellbereich, welcher in das Uhrzeitformat umgewandelt werden soll, im Code zu definieren. Ansonsten würde der Code in jeder Zelle in der

Datum/Zeit

Tabelle 13: Uhrzeitergebnisse durch Zahleneingaben

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

148 >> Uhrzeiten ohne Doppelpunkt eingeben

Tabelle die eingegebenen Zahlen in Uhrzeiten umwandeln. Das ist meistens nicht erwünscht. In unserem Beispiel werden die Uhrzeiten im Bereich B2:C32 eingetragen. Mit der Intersect-Methode wird der Variablen rngArea die Schnittmenge des Eingabe- und Gültigkeitsbereichs übergeben. Set rngArea = Application.Intersect(Target, Range("B2:C32"))

Befindet sich keine geänderte Zelle im Bereich B2:C32, wird die Prozedur mit der Exit-Anweisung vorzeitig beendet. Um die Geschwindigkeit des Makros zu erhöhen und die einzelnen Schritte des Makros am Bildschirm unsichtbar zu machen, wird die Bildschirmaktualisierung über die ScreenUpdating-Eigenschaft deaktiviert. Wird durch den Code der Inhalt der Zelle verändert (dazu gehört auch das Rückgängigmachen der letzten Benutzeraktion), würde das Worksheet_Change-Ereignis erneut ausgelöst werden und die Prozedur in einer Endlosschleife enden. Um dies zu verhindern werden alle Ereignisse mit der EnableEventsEigenschaft ausgeschaltet. Da sich diese beiden Befehle auf die Application-Eigenschaft beziehen, können sie in einer With-Anweisung zusammengefasst werden. Die Eingabe kann in einer einzelnen Zelle oder in einem markierten Bereich erfolgen, indem Sie mehrere Zellen markieren, die Zahl 1249 eintippen und mit (Strg) (Enter) die Eingabe beenden. Alle Zellen in dem markierten Bereich erhalten so die Zahl 1249. Achtung

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 148 Dienstag, 4. Dezember 2007 1:42 13

Mit Target sprechen Sie die gesamte Markierung in Ihrem Tabellenblatt an. Ob der markierte Bereich aus nur einer einzelnen Zelle oder einem Bereich mit mehreren Zellen besteht, spielt hier keine Rolle.

Damit es bei einem Eingabebereich von mehr als einer Zelle nicht zu einer Fehlermeldung kommt, benötigt das Makro eine For Each...Next-Anweisung. In dieser Schleife werden mittels der Variablen rngCell alle Zellen des markierten Bereichs Target angesprochen. Anschließend wird geprüft, ob sich jede Zelle innerhalb der definierten Schnittmenge rngArea befindet. Wenn diese Prüfung nicht stattfindet, würde eine Umwandlung der Eingabe auch in dem nicht vorgesehenen Bereich erfolgen. Liegt eine Zelle außerhalb des definierten Bereichs B2:C32, wird die letzte Benutzeraktion, also die Eingabe eines Wertes, über die Undo-Methode rückgängig gemacht. Nachdem die erste Zelle des Bereichs mit Target(1, 1).Select markiert wurde, wird das Makro über die GoTo-Anweisung zur Zeilenmarke Errorhandler verzweigt. Befindet sich der Eingabebereich im vorgesehenen Bereich, wird in der nächsten For Each...Next-Anweisung überprüft, welche Eingabe gemacht wurde. Entspricht die Eingabe nicht einer für Excel umwandlungsfähigen Uhrzeit, wird die Prozedur vorzeitig beendet. Es würde sonst zu einer Fehlermeldung führen. Entfernen Sie zum Beispiel einen vorhandenen Zellinhalt oder verlassen eine Zelle ohne Eingabe eines Wertes, würde die Zelle 00:00 anzeigen. Damit diese leere Zelle ("") auch tatsächlich leer bleibt, darf das Makro nicht durchlaufen werden. Verwenden Sie für diese Abfrage die Syntax If rngZelle = "".

Die Zahl 1249 ist in der Variablen rngCell enthalten und wird in Stunden und Minuten umgerechnet. Die Variable intHour erhält den Wert 12 für die Stunden, intMinute 49 für die Minuten. Die gefüllten Variablen werden an die Parameter der TimeSerialFunktion übergeben und das Format der Zelle bestimmt. Falls ein größerer Bereich mit mehreren Zahlen durch Copy und Paste eingefügt wird, kann es sich um verschiedene Werte handeln. Aus diesem Grund wird jede Zelle des markierten Bereichs einzeln berechnet und der ermittelte Uhrzeitwert in die jeweilige Zelle geschrieben.

Achtung

Vor Beendigung der Prozedur muss die Bildschirmaktualisierung wieder eingeschaltet werden. Vergessen Sie nicht, alle Ereignis-Prozeduren wieder zu aktivieren, sonst würde bei der nächsten Eingabe in eine Zelle dieses Makro nicht mehr aufgerufen.

Der gesamte Code sieht folgendermaßen aus: '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_02_TimeWithoutDoublepoint.xlsm ' Ereignis Tabelle1(Calendar) '=================================================================== Private Sub Worksheet_Change(ByVal Target As Range) Dim rngCell As Range Dim rngArea As Range Dim intHour As Integer Dim intMinute As Integer Listing 74

Datum/Zeit Datum/Zeit

If rngCell = "" Or Not IsNumeric(rngCell) Or Len(rngCell) > 4 _ Then GoTo Errorhandler

Datum/Zeit

Diese drei Abfragen lassen sich in einer Zeile im VBA Code darstellen:

Datum/Zeit

Die nächste Fehlerquelle liegt in der Anzahl der eingegebenen Zahlen. Der Code kann maximal vierstellige Zahlen in Uhrzeiten umwandeln. Überprüfen Sie deshalb mit der Len-Funktion, ob die eingegebene Zahlenlänge über vier liegt (zwei Zahlen für die Stunden, zwei für die Minuten). Wenn dies zutrifft, dann wird das Makro vorzeitig beendet, um eine Fehlermeldung zu verhindern. Eingaben von Zahlenwerten unter vier Zahlen werden fehlerfrei umgesetzt.

Datum/Zeit

Geben Sie Text in eine Zelle ein, dann wird Excel versuchen, diesen in ein Uhrzeitformat umzuwandeln, was zu einer Fehlermeldung führen würde. Kontrollieren Sie deshalb mit Hilfe der IsNumeric-Funktion, ob es sich bei der Eingabe um eine Zahl handelt. Wenn nicht, wird die Prozedur ebenfalls vorzeitig verlassen.

Datum/Zeit

149

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 149 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 150 Dienstag, 4. Dezember 2007 1:42 13

150 >> Uhrzeiten ohne Doppelpunkt eingeben

' hier Umwandlungsbereich definieren ' Schnittmenge des Eingabe- und Gültigkeitsbereichs Set rngArea = _ Application.Intersect(Target, Range("B2:C32")) ' Wenn Änderung nicht in angegebenem Bereich, verlasse Prozedur If rngArea Is Nothing Then Exit Sub End If ' Bildschirmaktualisierung und Ereignisse ausschalten With Application .ScreenUpdating = False .EnableEvents = False End With For Each rngCell In Target If Intersect(rngCell, rngArea) Is Nothing Then ' Eingaben innerhalb >>und> Datum/Zeit

153

' Variable erwartet booleschen Wert oder Zahlenwert Dim AnyDay As Variant

Datum/Zeit

2471_Excel-VBA.book Seite 153 Dienstag, 4. Dezember 2007 1:42 13

' Eingabedialog anzeigen AnyDay = Application.InputBox _ ("Geben Sie eine Tageszahl des aktuellen Monats ein.", _ "Searching Date", 1, , , , , 1)

Datum/Zeit

Do

' Nebenzelle der Fundzelle markieren rngDate.Offset(0, 1).Select End Sub Listing 76 (Forts.)

Aus den vorherigen Beispielen wissen Sie nun, wie über die Find-Methode die Adresse einer Datumszelle gefunden wird. Im folgenden Beispiel sollen anhand der Beispieldatei die geleisteten Arbeitsstunden vom 01.06.2007 angezeigt werden. Im Bereich A2:A32 stehen alle Datumswerte des aktuellen Monats. Mit der DateSerialFunktion wird der erste Tag des derzeitigen Monats und Jahres ermittelt. Dieses Datum wird über die Find-Methode im Datenbereich gesucht. Mittels der OffsetEigenschaft Offset(0, 3).Value wird der Wert, der sich null Zeilen und drei Spalten gegenüber dem gefundenen Bereich versetzt befindet, zurückgegeben.

Datum/Zeit

Arbeitsstunden in Meldungsfenster anzeigen

Datum/Zeit

67

Datum/Zeit

' Variable zurücksetzen AnyDay = 0 Else ' Verweis auf gesuchte Zelle setzen Set rngDate = _ Range("A2:A32").Find _ (What:=DateSerial(Year(Date), Month(Date), AnyDay), _ LookIn:=xlValues) End If Loop Until AnyDay > 0

Datum/Zeit

MsgBox "Ihre Eingabe ist kein gültiger Tag des Monats " & _ Format(Date, "mmmm"), _ vbCritical, "Input Error"

Datum/Zeit

' Prüfung, ob Eingabewert größer als letzter ' Tag des Monats ist If AnyDay > _ Day(DateSerial(Year(Date), Month(Date) + 1, -1)) Then

Datum/Zeit

'Abbrechen wurde geklickt If AnyDay = False Then Exit Sub

154 >> Arbeitsstunden in Meldungsfenster anzeigen

In der gesuchten Zelle D2 wird die per Formel errechnete Arbeitszeit über das Uhrzeitformat hh:mm als 09:00 angezeigt. Excel speichert diesen Wert intern jedoch als Dezimalwert mit 0,375. In der Prozedur wird mit der Value-Eigenschaft lediglich der Zellenwert ohne jegliche Formatierungsangaben angefordert. Aus diesem Grund erfolgt in dem Meldungsfenster die Ausgabe der Stunden als Dezimalzahl.

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 154 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Abbildung 52: Uhrzeitausgabe dezimal '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_02_TimeWithoutDoublepoint.xlsm ' Modul mdl_02_FindTime '=================================================================== Public Sub FindDecimalTime() MsgBox _ "Am " & Range("A2").Value & " haben Sie " & _ vbCr & _ Range("A2:A32").Find _ (What:=DateSerial(Year(Date), Month(Date), 1), _ LookIn:=xlValues).Offset(0, 3).Value & _ " Stunden gearbeitet" End Sub Listing 77

In der Zelle wird der Wert über das Uhrzeitformat hh:mm als 09:00 angezeigt. Geben Sie in der Format-Funktion das Format hh:mm an. Dadurch wird der gefundene Wert im Meldungsfenster im Uhrzeitformat angezeigt. Eine weitere Möglichkeit, den angezeigten Wert der Zelle zu ermitteln, bietet die

Text-Eigenschaft des Range-Objektes.

155

Public Sub FindTime() MsgBox _ "Am " & Range("A2").Value & " haben Sie " & _ vbCr & _ Range("A2:A32").Find _ (What:=DateSerial(Year(Date), Month(Date), 1), _ LookIn:=xlValues).Offset(0, 3).Text & _ " Stunden gearbeitet" End Sub

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_02_TimeWithoutDoublepoint.xlsm ' Modul mdl_02_FindTime '===================================================================

Datum/Zeit

Abbildung 53: Uhrzeitausgabe im Stundenformat

Datum/Zeit

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 155 Dienstag, 4. Dezember 2007 1:42 13

Arbeitszeiten summieren

Die Arbeitszeit eines Tages lässt sich noch einfach in der Tabelle nachlesen. Für den Zeitraum vom 01.06. bis 05.06.2007 benötigen Sie die Summenformel =SUMME(D2:D6) und formatieren die Ausgabezelle im Uhrzeitformat. Als Ergebnis erhalten Sie 29:20. Um den zu summierenden Zeitraum variabel zu halten, verwenden Sie nachfolgende Prozedur. Geben Sie den Beginn und das Ende des zu berechnenden Zeitraums jeweils in einer InputBox als Tageszahl ein. Geben Sie z. B. für den Start die Zahl 1 und das Ende die Zahl 5 ein. Excel gibt die gewünschte Information anschließend in einem Meldungsfenster aus.

Datum/Zeit

68

Datum/Zeit

Listing 78

Über die zwei Eingabedialoge ermitteln Sie im Code die gesuchten Zelladressen und setzen daraus einen Range zusammen. Die Variablen rngFirstDay, rngLastDay und

Datum/Zeit

Nun, wie kommen wir dahin?

Datum/Zeit

2471_Excel-VBA.book Seite 156 Dienstag, 4. Dezember 2007 1:42 13

156 >> Arbeitszeiten summieren rngMyRange werden als Range deklariert und enthalten die gefundenen Zelladressen

der eingegebenen Daten.

Datum/Zeit

Set rngMyRange = Worksheets(1).Range(rngFirstDay, rngLastDay)

Analog zu der Tabellenblattfunktion Summe verwenden Sie in VBA das WorksheetFunction-Objekt. Es wird als Container für Arbeitsblattfunktionen von Microsoft Excel verwendet, die aus Visual Basic aufgerufen werden können. In VBA müssen die englischen Funktionsnamen verwendet werden. Weisen Sie deshalb diesem Objekt die Eigenschaft SUM zu. Die Variable dblToTalSum erhält das Ergebnis aus der Summenberechnung.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

dblTotalSum = Application.WorksheetFunction.Sum(rngSum)

Bei der Berechnung der Uhrzeiten erhalten Sie in unserem Beispiel einen Wert über 24 Stunden. Um Zeiten über 24 Stunden anzuzeigen wird dafür im Tabellenblatt das Format [hh]:mm angewandt. Leider kennt die Format-Funktion in VBA die []-Klammern nicht als Formatierung an. Dementsprechend kann die Format-Funktion nicht zur Anzeige der errechneten Stunden verwendet werden. Um dennoch in VBA eine Ausgabe über die MsgBox im Uhrzeitformat zu erzielen setzen Sie die Uhrzeit in der Prozedur selbst zusammen und integrieren diese im Meldungsfenster. Im Makro wird dafür die Variable strTime reserviert. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_02_TimeWithoutDoublepoint.xlsm ' Modul mdl_03_WorkingHours '=================================================================== Public Dim Dim Dim Dim Dim Dim Dim

Sub WorkingHours() varDay1 As Variant varDay2 As Variant rngFirstDay As Range rngLastDay As Range rngSum As Range rngTotalSum As Double strTime As String

varDay1 = Application.InputBox _ (Prompt:="Ab welchem Tag wollen Sie die Stunden summieren?", _ Title:="Begin Day", _ Default:=1, _ Type:=1) ' Abbrechen wurde geklickt If varDay1 = False Then Exit Sub

Datum/Zeit

varDay2 = Application.InputBox _ Listing 79

' Startrange ermitteln Set rngFirstDay = Range("A2:A32").Find _ (What:=DateSerial(Year(Date), Month(Date), varDay1), _ LookIn:=xlValues).Offset(0, 3) ' Endrange ermitteln Set rngLastDay = Range("A2:A32").Find _ (What:=DateSerial(Year(Date), Month(Date), varDay2), _ LookIn:=xlValues).Offset(0, 3)

Datum/Zeit

(Prompt:="Bis zu welchem Tag wollen Sie die Stunden summieren?", _ Title:="End Day", _ Default:=5, _ Type:=1) If varDay2 = False Then Exit Sub

157

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 157 Dienstag, 4. Dezember 2007 1:42 13

Listing 79 (Forts.)

Datum/Zeit Datum/Zeit

MsgBox "Im Zeitraum vom " & varDay1 & ". bis " & varDay2 & ". " _ & Format(Date, "mmmm") & vbCrLf _ & "ergeben sich " _ & strTime & " Stunden" _ , vbInformation + vbOKOnly _ , "WorkingHours" End Sub

Datum/Zeit

' Uhrzeit über 24h berechnen strTime = Format(Int(rngTotalSum * 24), "00") & ":" & _ Format(Int(((rngTotalSum * 24) - _ Int(rngTotalSum * 24)) * 60), "00")

Datum/Zeit

' Summe berechnen rngTotalSum = Application.WorksheetFunction.Sum(rngSum)

Datum/Zeit

' Bereich aus beiden Ranges zusammensetzen Set rngSum = Range(rngFirstDay, rngLastDay)

158 >> Kalenderwoche nach DIN 1355 berechnen

69

Kalenderwoche nach DIN 1355 berechnen

Die in Excel integrierte Funktion KALENDERWOCHE aus dem Add-In Analyse-Funktionen.xla liefert eine Zahl, die angibt, in welche Woche des dazugehörigen Jahres das angegebene Datum fällt.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 158 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Abbildung 54: Integrierte Funktion »Kalenderwoche« aus Analyse-Add-In

Einige Excel-Spezialisten bemühen sich seit Jahren darum, komplizierte Formeln und benutzerdefinierte Funktionen zu Berechnung der Kalenderwoche zu erstellen. »Warum?«, werden Sie fragen, wenn diese Funktion doch bereits in Excel mitgeliefert wird. Die Funktion KALENDERWOCHE() rechnet falsch, oder sagen wir besser, nach amerikanischem Standard. Der 01.01.2000 z. B. ist laut DIN in der 52. Kalenderwoche des Jahres 1999. In den USA ist dieses Datum in der ersten Kalenderwoche des Jahres 2000. In Deutschland wurde 1976 der Wochenbeginn auf »Montag« festgelegt. Die erste Woche des Jahres ist definiert als die Woche, in die mindestens 4 Tage des neuen Jahres fallen. Beides nach DIN 1355 aus dem Jahr 1974. Diese Definition entspricht der internationalen Norm ISO 8601 (1988); übernommen von der EU als EN 28601 (1992) und in Deutschland als DIN EN 28601 (1993) umgesetzt. Anders gesagt; die Woche, deren erster Donnerstag im neuen Jahr liegt, ist KW 1. Für einzelne Daten innerhalb von Jahrzehnten mag man mit falschen Kalenderwochen-Angaben leben können. Da die in Excel integrierte Funktion KALENDERWOCHE() nachweislich für die kompletten Jahre 2005, 2006, 2010–2012 und weitere Jahre falsche Werte liefert, ist eine benutzerdefinierte Formel oder Funktion unerlässlich.

>> Datum/Zeit

159

Die folgende Tabellen-Funktion berechnet anhand eines Datums in Zelle A1 die korrekte deutsche Kalenderwoche nach der aktuellen DIN 1355 Norm:

Datum/Zeit

2471_Excel-VBA.book Seite 159 Dienstag, 4. Dezember 2007 1:42 13

In der Beispieldatei wurden verschiedene Möglichkeiten zur Berechnung der Kalenderwoche gegenübergestellt. Ausgangsdatum sind die Daten in Spalte A, hier wurden nur einige Daten aufgenommen. Die interne Excel-Funktion KALENDERWOCHE(), nach amerikanischem Standard, liefert weitaus mehr Fehlberechnungen.

In Spalte D wird über die benutzerdefinierte Funktion WeekNumberDIN() die exakte Kalenderwoche des Datums in Spalte A berechnet. Die Formel in D2 lautet =WeekNumberDIN(A2).

Hinwei s

Folgende benutzerdefinierte Funktion muss für die Berechnung im Tabellenblatt in einem Standardmodul des VBA Projektes zur Verfügung gestellt werden. Ausführliche Informationen zu benutzerdefinierten Funktionen finden Sie im Kapitel »Einstieg«.

Datum/Zeit

Die korrekten Werte in Spalte C wurden mit obiger Formel errechnet.

Datum/Zeit

Abbildung 55: Berechnung Kalenderwoche

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Zur Kontrolle wurden das Datum und die Kalenderwoche des ersten Donnerstag des angegebenen Jahres mit in die Tabelle aufgenommen.

Datum/Zeit

=KÜRZEN((A1-DATUM(JAHR(A1-REST(A1-2;7)+3);1;REST(A1-2;7)-9))/7)

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 160 Dienstag, 4. Dezember 2007 1:42 13

160 >> Anzahl Kalenderwochen bestimmen '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_03_WeeknumberDIN.xlsm ' Modul mdl_01_WeekNumberDIN '=================================================================== Function WeekNumberDIN(MyDate As Date) As Integer Dim datDate As Date

Datum/Zeit

datDate = 4 + MyDate - Weekday(MyDate, 2) WeekNumberDIN = (datDate - DateSerial(Year(datDate), 1, -6)) \ 7 End Function Listing 80

Datum/Zeit

Datum/Zeit

Datum/Zeit

70

Anzahl Kalenderwochen bestimmen

Nach der in Deutschland gültigen DIN1355-Norm für Wochenzählungen kann ein Jahr 52 oder 53 Wochen enthalten. Ein Jahr hat 53 Wochen, wenn der 01.01. und/ oder 31.12. des Jahres ein Donnerstag ist. In der benutzerdefinierten Funktion CountGermanWeeks wird eine Jahreszahl an die Variable intYear übergeben. Über die DatePart-Funktion werden die Wochentage des 01.01. und 31.12. des Jahres intYear ermittelt. Die Funktion DatePart gibt je nach Wochentag eine Zahl von 1 bis 7 zurück. Die Ergebnisse werden in den Variablen bytDay1 und bytDay2 gespeichert. In der If...Then..Else-Anweisung erfolgt anschließend die Überprüfung des Wochentags und Zuweisung der Anzahl Kalenderwochen an die CountGermanWeeks-Funktion. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_03_WeeknumberDIN.xlsm ' Tabelle CountGermanWeeks ' Modul mdl_02_CountGermanWeeks '===================================================================

Datum/Zeit

Function CountGermanWeeks(lngYear As Integer) As Long Dim lngDay1 As Long Dim lngDay2 As Long ' Wochentag des 1. Januar lngDay1 = DatePart("w", DateSerial(lngYear, 1, 1), vbMonday)

Datum/Zeit

' Wochentag des 31. Dezember lngDay2 = DatePart("w", DateSerial(lngYear, 12, 31), vbMonday) Listing 81

161

' Prüfung, ob erster oder letzter Tag des Jahres ein ' Donnerstag ist If lngDay1 = 4 Or lngDay2 = 4 Then CountGermanWeeks = 53 Else CountGermanWeeks = 52 End If End Function

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 161 Dienstag, 4. Dezember 2007 1:42 13

Gesetzliche Feiertage, wie der 01. Januar, 01. Mai, 03. Oktober etc., lassen sich ohne Probleme formulieren, wenn das entsprechende Jahr bekannt ist. Für nachfolgende Formeln steht das Jahr 2007 als Ganzzahl in der Zelle A1. =DATUM(A1;12;24)

' liefert 24.12.2007

Die kirchlichen Feiertage richten sich nach dem Ostersonntag des entsprechenden Jahres aus. Die derzeit kürzeste Osterformel stammt von Norbert Hetterich und erwartet für nachstehende Formel in der Zelle A1 eine Jahreszahl: =DM((TAG(MINUTE(A1/38)/2+55)&".4."&A1)/7;)*7-6 ' liefert 08.04.2007

Beachten Sie bitte, dass diese Formel nur im 1900-Datumssystem das korrekte Datum des Ostersonntags liefert. Die kürzeste Formel, die sowohl im 1900- als auch im 1904-Datumssystem funktioniert, wurde von unserem US-MVP-Kollegen Stephen Bullen entwickelt: =DATUM(A1;3;28)+REST(24-REST(A1;19)*10,63;29)-REST(KÜRZEN(A1*5/4)+REST(24REST(A1;19)*10,63;29)+1;7)

In unserer Beispieldatei finden Sie in dem Tabellenblatt FEIERTAGE_FORMELN eine Übersichtstafel der Jahre 2003 bis 2010 mit den geläufigsten deutschen Feiertagen und anderen wichtigen Ereignissen, wie zum Beispiel »Muttertag« oder »Rosenmontag«. Durch Änderung der Jahreszahlen in den Spaltenüberschriften in Zeile 3 werden die Daten der Feiertage neu berechnet.

Datum/Zeit Datum/Zeit

Ein Kalender ohne Kennzeichnung der Feiertage wäre kein richtiger Kalender. Aus diesem Grund helfen wir Excel ein bisschen auf die Sprünge.

Datum/Zeit

In Abbildung 54 sehen Sie das Dialogfenster FUNKTION EINFÜGEN. Die Kategorie DATUM & ZEIT enthält etliche Funktionen, aber leider fehlt hier die oft nachgefragte Funktion, um Feiertage berechnen zu können. Das mag daran liegen, dass es nicht nur unterschiedliche Feiertage in den einzelnen Ländern gibt, sondern sogar innerhalb Deutschlands die Feiertage in den einzelnen Bundesländern nicht einheitlich sind. Wer zum Beispiel in Nordrhein-Westfahlen wohnt, darf in seinem Kalender den 1. November als Feiertag markieren. In Hessen gilt der 1. November, »Allerheiligen«, dagegen als gewöhnlicher Tag.

Datum/Zeit

Feiertage mit Formeln berechnen

Datum/Zeit

71

Datum/Zeit

Listing 81 (Forts.)

162 >> Formeln in Tabelle anzeigen

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 162 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 56: Feiertagsberechnung mit Formeln

72

Formeln in Tabelle anzeigen

Wir könnten die Formeln zu obiger Beispieltabelle mühselig aus den einzelnen Zellen kopieren und in einer Tabelle auflisten um sie hier darzustellen. Einfacher ist es, sich die Formeln statt der Werte direkt in der Tabelle anzeigen zu lassen. Klicken Sie dazu nacheinander auf die OFFICE-SCHALTFLÄCHE | EXCEL-OPTIONEN | ERWEITERT und aktivieren Sie im Abschnitt OPTIONEN FÜR DIESES ARBEITSBLATT ANZEIGEN das Kontrollkästchen vor ANSTELLE DER BERECHNETEN WERTE FORMELN IN ZELLEN ANZEIGEN. Dadurch werden in der Tabelle, anstelle der durch Formeln erzeugten Werte, die Formeln angezeigt. Diese Einstellung gilt nicht für die gesamte Mappe, sondern kann für jedes Tabellenblatt einzeln aktiviert/deaktiviert werden. Alternativ verwenden Sie die Tastenkombination (Strg) (#). Hierbei wird bei jedem Drücken der Tastenkombination der Anzeigemodus zwischen WERTE und FORMELN gewechselt. Innerhalb eines Tabellenblattes ist es standardmäßig leider nicht möglich, einen Bereich als Formeln und gleichzeitig einen anderen Bereich als Werte darzustellen. Aber hier gibt es eine wesentliche Vereinfachung noch aus den alten Excel4-MakroZeiten, die wir Ihnen nicht vorenthalten möchten. Sie finden die dazugehörige Tabelle im Tabellenblatt FEIERTAGE_FORMELN_SICHTBAR der Beispieldatei. Zunächst fügen Sie neben Spalte C eine Hilfsspalte ein, indem Sie den Spaltenkopf C anklicken, so dass die ganze Spalte markiert ist. Mit Rechtsklick innerhalb der Markierung erhalten Sie ein Kontextmenü, wählen Sie daraus den Eintrag ZELLEN EINFÜGEN.

163

Die nächste Überlegung ist, welche Formel in welcher Zelle angezeigt werden soll. Wir möchten die Ausgabe einer Formel in der jeweils rechts neben der Formelzelle liegenden Zelle erreichen. Die Formel aus Zelle C4 soll also in D4 angezeigt werden. Dementsprechend markieren Sie nun die Zelle D4, klicken nacheinander auf den Register FORMELN | DEFINIERTE NAMEN | NAMEN DEFINIEREN und schreiben in das Eingabefeld NAME das Wort »Formel«. Wählen Sie im Auswahlfeld BEREICH, ob sich der neue Name auf ein einzelnes Tabellenblatt oder die gesamte Arbeitsmappe beziehen soll. In die Eingabezeile BEZIEHT SICH AUF wird das Excel4-Makro eingetragen. Für die Formelanzeige lautet die Syntax:

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 163 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

Ersetzen Sie entsprechend unserem Beispiel das Wort Bezug durch C4 und klicken Sie dann auf HINZUFÜGEN. Excel vervollständigt den genauen Bezug automatisch. Schließen Sie den Dialog mit einem Klick auf die Schaltfläche OK.

Datum/Zeit

=ZELLE.ZUORDNEN(6;Bezug)

Datum/Zeit

Schreiben Sie in die Zelle D4 die Formel =Formel und kopieren Sie diese bis an das Tabellenende. Das Resultat sehen Sie in Abbildung 58. Die Formel der jeweils linken Nebenzelle wird als Ergebnis angezeigt. Falls beim Öffnen der Datei diese Formeln den Fehlerwert #NAME? Anzeigen, müssen sie eventuell neu berechnet werden. Markieren Sie den Zellbereich und drücken Sie für jede Zelle die (F2)-Taste gefolgt von der (Enter)-Taste.

Datum/Zeit

Abbildung 57: Formelanzeige über definierten Namen

164 >> Funktion zur Formelanzeige

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 164 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

73

Funktion zur Formelanzeige

Für die Anzeige von Formeln können Sie anstelle eines definierten Namens mit Excel4-Makro auch eine benutzerdefinierte Funktion verwenden. Hinweis

Datum/Zeit

Datum/Zeit

Abbildung 58: Formelanzeige über Excel4-Makro in definierten Namen

Ausführliche Informationen und Beispiele zu Funktionen finden Sie in Kapitel »Einstieg«.

Die nachfolgende Funktion ShowFormula wird in allen Excel-Versionen ab Excel 97 unterstützt. Damit die Formel im Tabellenblatt berechnet werden kann, speichern Sie diese in einem Standardmodul. Die Formel =ShowFormula(A1) liefert als Ergebnis die Formel der Zelle A1 des aktiven Tabellenblattes im Textformat. Im Tabellenblatt FUNCTION_SHOWFORMULA der Beispieldatei werden die Formeln der Nebenzelle über die ShowFormula-Funktion angezeigt.

165

Datum/Zeit

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 165 Dienstag, 4. Dezember 2007 1:42 13

Public Function ShowFormula(rngCell As Range) As String ShowFormula = rngCell.FormulaLocal End Function

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_04_HolidaysFormula.xlsm ' Tabelle Function_ShowFormula ' Modul mdl_01_ShowFormula '===================================================================

Datum/Zeit

Abbildung 59: Formelanzeige in Excel2007

Zur Berechnung des Ostersonntags und der daraus resultierenden kirchlichen Feiertage gibt es neben der bereits erwähnten Formel auch eine benutzerdefinierte Funktion EASTER. Dadurch wird die lange »Hetterich-Formel« durch nachfolgende benutzerdefinierte Tabellenblatt-Funktion ersetzt. Voraussetzung ist wieder eine Jahreszahl als Ganzzahl in der Zelle A1. =Easter(A1)

' liefert im Jahr 2007 den 08.04.2007

Datum/Zeit

Feiertage mit VBA berechnen

Datum/Zeit

74

Datum/Zeit

Listing 82

166 >> Tageskalender erstellen '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_05_HolidaysVBA.xlsm ' Tabelle Feiertage_VBA ' Modul mdl_01_FunctionEaster '=================================================================== Public Function EASTER(intYear As Integer) As Date Dim intDummy As Integer intDummy = (((255 - 11 * (intYear Mod 19)) - 21) Mod 30) + 21 EASTER = DateSerial(intYear, 3, 1) + intDummy + (intDummy > 48) _ + 6 - ((intYear + intYear \ 4 + intDummy _ + (intDummy > 48) + 1) Mod 7) End Function Listing 83

75

Tageskalender erstellen

Für unser nächstes Beispiel haben wir uns eine kleine Spielerei ausgedacht. Sicherlich kennen Sie die kleinen Abreißkalender, die für jeden Tag des Jahres ein separates Blatt beinhalten. Dort zeigt das oberste Blatt den aktuellen Tag an.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 166 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Abbildung 60: Tageskalender

In der Beispieldatei, Tabelle DAILY, sehen Sie die Einzelheiten dazu. Das Kalenderblatt in Abbildung 60 besteht aus vier Zellen, die teilweise aus mehreren Zellen verbunden sind. Diese sind unterschiedlich formatiert und orientieren sich alle an dem Inhalt der Zelle E4, die das Datum enthält.

167

Die Funktionalität des Drehfeldes erreichen Sie wieder durch Deaktivierung des Entwurfsmodus. Im Eigenschaften-Fenster dieses Drehfeldes wurde der LINKEDCELL-Eigenschaft der Zellbezug E4 zugewiesen. Dadurch wird der Wert des Drehfeldes in die Zelle E4 geschrieben und umgekehrt wird bei Eingabe in Zelle E4 der Wert Value des Drehfeldes angeglichen.

Datum/Zeit

Aktivieren Sie den ENTWURFSMODUS im Register ENTWICKLERTOOLS in der Gruppe STEUERELEMENTE, wählen Sie ein bereits eingefügtes Steuerelement durch Anklicken aus und klicken Sie auf die Schaltfläche EIGENSCHAFTEN. Dadurch wird das Eigenschaften-Fenster mit allen Optionen des aktiven Objektes angezeigt.

Datum/Zeit

Eigenschaften von Steuerelementen lassen sich nur im Entwurfsmodus einstellen.

Datum/Zeit

Hinweis

Das Datum verändern Sie durch eine Datumseingabe in E4 oder durch Anklicken des Drehfeldes. Dadurch springt das Datum jeweils einen Tag vor oder zurück. Das Drehfeld SpinButton wurde aus der Symbolleiste STEUERELEMENT-TOOLBOX eingefügt.

Datum/Zeit

Abbildung 61: Tageskalender mit unformatierten Werten und Formeln

Datum/Zeit

Datum/Zeit

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 167 Dienstag, 4. Dezember 2007 1:42 13

168 >> Tageskalender erstellen

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 168 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 62: Eigenschaftsfenster eines Drehfeldes

Die Eigenschaft Min enthält den Wert 39083, was dem 01.01.2007 entspricht. Max beträgt 75971, entsprechend dem 31.12.2107. Diese beiden Werte bestimmen die Unter- und Obergrenze des Drehfeldes. Über die weiteren Eigenschaften können Sie die Farben, Größe, Name etc. festlegen. Hier sind Ihrer Kreativität kaum Grenzen gesetzt. In der untersten Zelle des Tagesblattes werden die per Code hinterlegten Feiertage über die Holiday-Funktion ausgegeben. Beim Funktionsaufruf wird der Bezug $E$4 inklusive dem enthaltenen Datum aus Zelle E4 von der Formel an die Funktion übergeben. Die Variable dDate enthält dadurch das Datum der Zelle E4 und wird in der folgenden Select Case-Anweisung mit vorgegebenen Daten verglichen. Mit den Codezeilen Case Is = DateAdd("D", 1, datEastern) Holiday = "Ostermontag"

wird ein Datumswert mit dem Inhalt der Variablen dDate verglichen. Bei Übereinstimmung wird ein definierter Text an die Funktion übergeben und die Anweisung verlassen. Dieser Text wird nach Beendigung der Funktion in der aufrufenden Zelle als Ergebnis der Holiday-Funktion angezeigt.

Public Function Holiday(dDate As Date) As String Dim intYear As Integer Dim datEastern As Date ' Jahr aus übergebenem Datum berechnen intYear = Year(dDate) ' Ostern Berechnung datEastern = EASTER(intYear) Select Case dDate Case Is = DateSerial(intYear, 1, 1) Holiday = "NeuJahr" Case Is = DateSerial(intYear, 1, 6) Holiday = "Dreikönig" Case Is = DateAdd("D", -48, datEastern) Holiday = "Rosenmontag" Case Is = DateSerial(intYear, 4, 0) - _ (Weekday(DateSerial(intYear, 4, 0), 2) Mod 7) Holiday = "Beginn Sommerzeit" Case Is = DateAdd("D", -2, datEastern) Holiday = "Karfreitag" Case Is = datEastern Holiday = "Ostersonntag" Case Is = DateAdd("D", 1, datEastern) Holiday = "Ostermontag" Listing 84

Datum/Zeit Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_05_HolidaysVBA.xlsm ' Tabelle Daily ' Tabelle Today ' Modul mdl_02_FunctionHoliday '===================================================================

Datum/Zeit

Der nachfolgende Code befindet sich in einem Standardmodul der angegebenen Beispieldatei. In dem Tabellenblatt TODAY wird der jeweils aktuelle Tag auf einem Tageskalender angezeigt. Hierbei wird ebenfalls die Holiday-Funktion über den nachstehenden Code angewandt.

Datum/Zeit

Case Is = DateSerial(intYear, 12, 3) Holiday = "Geburtstag"

Datum/Zeit

Sie können beliebig viele solcher Case-Blöcke innerhalb der Select Case-Anweisungen angeben. In unserem Beispiel haben wir unter anderem die Tage der Zeitumstellung (Sommerzeit) und das Datum des Muttertages aufgenommen. Ebenso können Sie auch individuelle Anlässe wie Geburtstage angeben. Der folgende Case-Block gibt am 03.12. eines Jahres den Hinweistext »Geburtstag« zurück.

Datum/Zeit

169

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 169 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 170 Dienstag, 4. Dezember 2007 1:42 13

170 >> Tageskalender erstellen Case Is = DateSerial(intYear, 5, 1) Holiday = "Tag der Arbeit" Case Is = IIf(DateSerial(intYear, 5, 15) - _ (Weekday(DateSerial(intYear, 5, 1), 2) Mod 7) = datEastern + 49, DateSerial(intYear, 5, 15) - _ (Weekday(DateSerial(intYear, 5, 1), 2) Mod 7) 7, DateSerial(intYear, 5, 15) - _ (Weekday(DateSerial(intYear, 5, 1), 2) Mod 7)) Holiday = "Muttertag" Case Is = DateAdd("D", 39, datEastern) Holiday = "Christi Himmelfahrt" Case Is = DateAdd("D", 49, datEastern) Holiday = "Pfingstsonntag" Case Is = DateAdd("D", 50, datEastern) Holiday = "Pfingstmontag" Case Is = DateAdd("D", 60, datEastern) Holiday = "Fronleichnam" Case Is = DateSerial(intYear, 8, 15) Holiday = "Maria Himmelfahrt" Case Is = DateSerial(intYear, 10, 3) Holiday = "Deutsche Einheit" Case Is = DateSerial(intYear, 11, 0) - (Weekday( _ DateSerial(intYear, 11, 0), 2) Mod 7) Holiday = "Ende Sommerzeit" Case Is = DateSerial(intYear, 10, 31) Holiday = "Reformationstag" Case Is = DateSerial(intYear, 11, 1) Holiday = "Allerheiligen" Case Is = DateSerial(intYear, 12, 3) Holiday = "Geburtstag" Case Is = DateSerial(intYear, 12, 24) - _ (Weekday(DateSerial(intYear, 12, 24), 2) Mod 7) Holiday = "1. Advent" Case Is = DateSerial(intYear, 12, 24) - _ (Weekday(DateSerial(intYear, 12, 24), 2) Mod 7) Holiday = "2. Advent" Case Is = DateSerial(intYear, 12, 24) - _ (Weekday(DateSerial(intYear, 12, 24), 2) Mod 7) Holiday = "3. Advent" Case Is = DateSerial(intYear, 12, 24) - _ (Weekday(DateSerial(intYear, 12, 24), 2) Mod 7) Holiday = "4. Advent" Case Is = DateSerial(intYear, 12, 24) Holiday = "Heilig Abend" Case Is = DateSerial(intYear, 12, 25) Holiday = "erster Weihnachtstag" Listing 84 (Forts.)

_ _

- 21

- 14

- 7

171

Case Is = DateSerial(intYear, 12, 26) Holiday = "zweiter Weihnachtstag" Case Is = DateSerial(intYear, 12, 31) Holiday = "Silvester" Case Else Holiday = "" End Select End Function

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 171 Dienstag, 4. Dezember 2007 1:42 13

76

100-jähriger Kalender und Arbeitszeittabelle

In der angegebenen Beispieldatei haben wir einen 100-jährigen Kalender erstellt. Durch Auswahl eines Monats und Jahres über zwei Drehfelder werden die Tage eines Monats mitsamt den dazugehörigen Kalenderwochen und Feiertagen dargestellt.

Datum/Zeit

Listing 84 (Forts.)

Private Sub SpinButton1_Change() Sheetname End Sub

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_06_Calendar.xlsm ' Ereignis Tabelle2(Monat Jahr) '===================================================================

Datum/Zeit

Über das Change-Ereignis der Drehfelder wird die Prozedur Sheetname aufgerufen. Die SpinButton_Change-Ereignisse werden im Codebereich des Tabellenblattes gespeichert.

Für diesen Fall wird die Fehlermeldung mit einer On Error GoTo-Anweisung abgefangen und das Tabellenblatt zusätzlich mit seiner Indexnummerierung benannt.

Datum/Zeit

Diese Prozeduren rufen das Makro Sheetname zur Beschriftung des Tabellenregisters auf, welches in einem Standardmodul hinterlegt ist. Wenn Sie in einem weiteren Blatt das gleiche Datum wie in einem vorherigen Tabellenblatt auswählen, würde die Prozedur versuchen einen bereits verwendeten Namen diesem Tabellenblatt zuzuweisen, was zu einer Fehlermeldung führt.

Datum/Zeit

Listing 85

Datum/Zeit

Private Sub SpinButton2_Change() Sheetname End Sub

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 172 Dienstag, 4. Dezember 2007 1:42 13

172 >> 100-jähriger Kalender und Arbeitszeittabelle '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_06_Calendar.xlsm ' Modul mdl_01_Sheetname '=================================================================== Public Sub Sheetname() On Error GoTo Errorhandler

Datum/Zeit

Datum/Zeit

' Tabellenblatt nach ausgewähltem Monat/Jahr benennen ActiveSheet.Name = Format(Range("C5"), "MMMM YY") ' Prozedur verlassen, wenn kein Fehler aufgetreten ist Exit Sub ' Fehlerbehandlung wird nur bei auftretendem Fehler durchlaufen Errorhandler: ' Tabellenblatt wegen doppelter Namensvergabe mit Index benennen ActiveSheet.Name = _ Format(Range("C5"), "MMMM YY") & "_" & ActiveSheet.Index End Sub Listing 86

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Über die bedingte Formatierung werden Feiertage in Spalte A sowie Sonntage in Spalte C hervorgehoben.

Abbildung 63: Feiertage und Sonntage mit bedingter Formatierung hervorheben

Auf der Basis dieses Kalenders lässt sich leicht eine Arbeitszeittabelle erstellen, wie in unserem Beispiel.

173

Bei einer Arbeitszeit von mehr als 24 Stunden soll ein entsprechender Spesensatz gewährt werden. Dies erreichen Sie, indem Sie als Arbeitsbeginn zum Beispiel 8:00 und -ende 7:59 ohne Pause eingeben. Da dies eine große Fehlerquelle darstellt, wurde über DATEN | DATENTOOLS | DATENÜBERPRÜFUNG eine benutzerdefinierte Gültigkeitsprüfung mit der Formel =$D5$F5 eingegeben, so dass der Beginn und Ende der Arbeitszeit nicht identisch sein dürfen.

Datum/Zeit

In der Tabelle werden nur der Arbeitsbeginn, das Arbeitsende sowie die Pausen eingetragen. Die Ergebnisse werden über Formeln berechnet, die in den Zellen der Spalten G bis K hinterlegt sind.

Datum/Zeit

Abbildung 64: Arbeitszeittabelle mit Feiertagsberechnung

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 173 Dienstag, 4. Dezember 2007 1:42 13

Hinwei s

174 >> 100-jähriger Kalender und Arbeitszeittabelle

Weitere Informationen zum Thema Datenüberprüfung und Gültigkeit finden Sie in der Kategorie »Auswertungen«.

Im Tabellenblatt VORGABEN der Beispieldatei hinterlegen Sie alle veränderbaren Angaben für eine individuelle Berechnung. Unter Zuhilfenahme der Easter-Funktion aus Rezept 74, die im Modul mdl_02_Easter hinterlegt ist, erstellen Sie eine Liste der Feiertage entsprechend Ihres Bundeslandes. Die Nachtstunden werden anhand einer vorgegebenen Anfangs- und Endzeit berechnet. Ebenso die Höhe der Spesen, des Lohnes und der Zuschläge. Die hinterlegten Werte werden in den Formeln eingelesen. Die Nachtzeit zum Beispiel wird nur für die Zeit berechnet, die zwischen den vorgegebenen Uhrzeiten liegt. In unserem Beispiel also zwischen 20:00 Uhr und 06:00 Uhr.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 174 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 65: Vorgaben für Arbeitszeittabelle

Für die Feiertagsliste und die in den Formeln verwendeten Werte wurden in dieser Tabelle den jeweiligen Zellen und Bereichen Namen zugewiesen, um bei der Formelerstellung einen guten Überblick zu behalten. Eine Gesamtübersicht aller im Tabellenblatt vorhandenen Namen erhalten Sie über den Register FORMELN | DEFINIERTE NAMEN | IN FORMEL VERWENDEN | NAMEN EINFÜGEN | LISTE EINFÜGEN. Im Tabellenblatt wird diese Auflistung ab der aktuellen Zellposition ausgegeben:

Name

Bezug

Druckbereich

=Datenbank!$B$1:$E$23

Feiertage

=Datenbank!$B$5:$C$23

Feiertagszuschlag

=Datenbank!$E$9

Jahr

='Januar 03'!$G$2

Monat

='Januar 03'!$D$3

Nacht_Beginn

=Datenbank!$E$14

Nacht_Ende

=Datenbank!$E$15

Nachtzuschlag

=Datenbank!$E$7

Sonntagszuschlag

=Datenbank!$E$8

Spesen

=Datenbank!$D$20:$E$23

Stundenlohn

=Datenbank!$E$6

Datum/Zeit

175

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 175 Dienstag, 4. Dezember 2007 1:42 13

Formel

A

Feiertag

=WENN(ISTFEHLER(SVERWEIS(C5;Feiertage;2;0));""; SVERWEIS(C5;Feiertage;2;0))

B

KW

=WENN(ISTFEHLER(WeekNumberDIN(C5));""; WeekNumberDIN(C5))

C5

Datum

=DATUM(Jahr;Monat;1)

C6 – C35

Datum

=WENN($C5="";"";WENN(MONAT($C$5)=MONAT($C5+1); $C5+1;""))

G

Gesamt Std.

=WENN(ODER(D5="";F5="");""; WENN(REST(F5-D5;1)-E5 Lohn berechnen

Diese Beispieldatei ist nur für ein Kalenderjahr konzipiert, da für die Berechnung der Feiertage im Tabellenblatt DATENBANK das ausgewählte Jahr des CALENDAR-Blattes herangezogen wird. Sie können aber innerhalb der Datei das CALENDAR-Blatt kopieren und in der Kopie einen anderen Monat auswählen.

77

Lohn berechnen

In der Beispieldatei wird unterhalb der Arbeitszeittabelle der Lohn der einzelnen Spalten sowie der Gesamtlohn berechnet.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 176 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 66: Lohnberechnung

Die Zelle, welche den Stundensatz enthält, wurde mit dem Namen STUNDENLOHN benannt. Für die Lohnberechnung in Zelle G38 werden die errechneten Gesamtstunden aus G36 mit dem hinterlegten Stundensatz und der Zahl 24 multipliziert.

Datum/Zeit

=G36*Stundenlohn*24

' liefert 419,83 €

Diese Formel entspricht den Werten: 41:59*10*24. Die Ergebniszellen der Lohnberechnungen sind mit dem Währungsformat formatiert. Bei der Zuschlagsberechnung für die Nacht-, Sonntags- und Feiertagsstunden wird zusätzlich der angegebene Prozentsatz aus der DATENBANK berücksichtigt. Am Beispiel der Nachtstunden wird folgende Formel angewandt.

Datum/Zeit

=H36*Stundenlohn*24*Nachtzuschlag

Zur Verdeutlichung stellen wir die dazugehörigen Werte noch einmal dar: 16:00*10*24*25%

78 Datum/Zeit

' liefert 40,00 €

Minuszeiten berechnen

Wenn es um die Berechnung von Uhrzeiten geht, sorgt Excel für einige Verwirrung, wenn die Zeitdifferenz einen Minuswert ergibt. Subtrahiert man eine größere Uhrzeit

>> Datum/Zeit

177

Public Sub MinusTime() ' Berechnung und Ausgabe in Meldungsfenster MsgBox "B2-A2=" & _ vbNewLine & _ Format(Range("B2") - Range("A2"), "- hh:mm") ' Ausgabe der Berechnung in Zelle Range("G2").Value = Format(Range("B2").Value _ - Range("A2").Value, "- hh:mm") End Sub Listing 87

Hier sehen Sie die richtige Ausgabe der Zeitdifferenz im Meldungsfenster und im Textformat in der Zelle G2. Ein Weiterrechnen ist mit diesem Textwert allerdings nicht ohne weiteres möglich.

Datum/Zeit Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle Function_NegativeTime ' Modul mdl_01_MinusTime '===================================================================

Datum/Zeit

Bei der Zeitberechnung und deren Darstellung kann man mit VBA durch Vorgabe des Formates eine korrekte Ausgabe der Zeitdifferenz im Textformat erzielen.

Datum/Zeit

Excel hat lediglich bei der Darstellung negativer Uhrzeiten im UHRZEITFORMAT Defizite und nicht mit der Berechnung von negativen Uhrzeiten.

Datum/Zeit

Achtung

Abbildung 67: Minuszeiten berechnen

Datum/Zeit

Datum/Zeit

von einer niedrigeren, dann erscheinen als Ergebnis standardmäßig Rauten (#), auch Gitterzäune genannt, in der Zelle. Die Ursache liegt entweder darin, dass Excel das bereits verwendete Format der Quellzellen hh:mm übernimmt oder der Anwender dieses Format angibt um einen Uhrzeitwert zu erhalten. Ändert man das Format auf STANDARD oder ZAHL, wird der errechnete Wert korrekt als Dezimalzahl angezeigt.

Datum/Zeit

2471_Excel-VBA.book Seite 177 Dienstag, 4. Dezember 2007 1:42 13

178 >> Negative Zeitberechnung mit Funktion

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 178 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 68: Negative Zeitberechnung mit VBA

Mit einigen verschachtelten Tabellenfunktionen erzielen Sie das gleiche Ergebnis: eine negative Zeitdarstellung im Textformat. Da dieses Ergebnis im Textformat vorliegt, kann man damit nicht ohne weiteres weiterrechnen.

Datum/Zeit

="-"&TEXT(STUNDE((B2-A2)*-1);"00")&":"&TEXT(MINUTE((B2-A2)*-1);"00")

oder =TEXT(ABS(B2-A2);"- hh:mm")

Aufgrund der obigen Feststellung, dass VBA negative Zeiten berechnen und im Uhrzeitformat darstellen kann, verwenden wir zur Berechnung im Tabellenblatt eine benutzerdefinierte Funktion. Diese erspart Ihnen die komplizierte Eingabe der oben gezeigten Formellösungen. Die Zeitdifferenz zwischen B2 und A2 wird nicht mehr mit einer Formel, sondern mit der Funktion =NegativeTime(B2;A2) berechnet. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle Function_NegativeTime ' Modul mdl_02_Function_NegativeTime '===================================================================

Datum/Zeit

Datum/Zeit

Datum/Zeit

Negative Zeitberechnung mit Funktion

Datum/Zeit

79

Public Function NegativeTime(rng1 As Range, rng2 As Range) ' Prüfung, ob Ergebnis negativ oder positiv ist If rng1 < rng2 Then ' negatives Ergebnis NegativeTime = Format(rng1 - rng2, "- hh:mm") Else ' positives Ergebnis Listing 88

>> Datum/Zeit

179

NegativeTime = Format(rng1 - rng2, "hh:mm") End If End Function

Datum/Zeit

2471_Excel-VBA.book Seite 179 Dienstag, 4. Dezember 2007 1:42 13

1904-Datumswerte für Minuszeiten

Abbildung 69: Umstellen der 1904-Datumswerte

Datum/Zeit Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Die einfachste Möglichkeit für die richtige negative Zeitberechnung und Darstellung ist die Umstellung der 1904-DATUMSWERTE über die OFFICE-SCHALTFLÄCHE | EXCELOPTIONEN | ERWEITERT. Aktivieren Sie im Abschnitt BEIM BERECHNEN DIESER ARBEITSMAPPE die Option 1904-DATUMSWERTE VERWENDEN, damit Excel Minuszeiten anzeigen und berechnen kann. Diese Einstellung gilt für die gesamte Arbeitsmappe und behält auch bei erneutem Öffnen die gewählte Einstellung.

Datum/Zeit

80

Diese Funktion liefert in einer Zelle das korrekte Ergebnis einer negativen Zeitdifferenz im Textformat. Das bedeutet, dass mit diesem Ergebnis keine weiteren Berechnungen durchgeführt werden können. Ist die Endzeit größer als die Anfangszeit, so gibt die Funktion das positive Ergebnis ebenfalls im Textformat aus.

Datum/Zeit

A c ht u n g

Listing 88 (Forts.)

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 180 Dienstag, 4. Dezember 2007 1:42 13

180 >> 1904-Datumswerte für Minuszeiten

Diese Methode ist zwar einfach, birgt allerdings dann ihre Tücken, wenn sich in der aktiven Arbeitsmappe außer Zeiten bereits Datumswerte befinden oder die Zelleingaben via VBA manipuliert werden. Die vorhandenen Datumswerte werden bei der Umstellung um vier Jahre und einen Tag hochgezählt. Wert

1900-Datumswerte

1904-Datumswerte

-3

##############

-04.01.1904

-2

##############

-03.01.1904

-1

##############

-02.01.1904

0

00.01.1900

01.01.1904

1

01.01.1900

02.01.1904

2

02.01.1900

03.01.1904

3

03.01.1900

04.01.1904

39114

01.02.2007

02.02.2011

Bei normaler Datumsberechnung im 1900-Datumssystem wird die Anzahl der seit dem 31.12.1899 vergangenen Tage gezählt, bei der 1904-Datumsberechnung die Tage, die ab dem 01.01.1904 vergangen sind. In der Beispieldatei haben wir im Tabellenblatt 1904-DATUMSWERTE einige Testdaten bereitgestellt. Über eine Umschaltfläche ToggleButton wird das Datumssystem gewechselt. So haben Sie einen direkten Vergleich zwischen den beiden Datumssystemen. Als Besonderheit des Makros zur Umstellung des Datumssystems wird über die IIfFunktion die Beschriftung Caption der Umschaltfläche entsprechend dem eingestellten Datumssystem geändert. Das aktivierte Datumssystem wird zudem in der Statuszeile bekannt gegeben.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Tabelle 16: Datumswerte bei verschiedenen Datumssystemen

Datum/Zeit

Abbildung 70: Deaktivierte 1904-Datumswerte

181

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 181 Dienstag, 4. Dezember 2007 1:42 13

' Beschriftung der Umschaltfläche einstellen ToggleButton1.Caption = _ "1904-Datumswerte" & vbCr & _ IIf(Application.ActiveWorkbook.Date1904, _ "deaktivieren", "aktivieren")

Datum/Zeit

Private Sub ToggleButton1_Click() ' Einstellung des Datumssystems umkehren ActiveWorkbook.Date1904 = Not ActiveWorkbook.Date1904

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle 1904_Datumswerte ' Ereignis Tabelle2(1904_Datumswerte) '===================================================================

Datum/Zeit

Abbildung 71: Aktivierte 1904-Datumswerte

Listing 89

Die Syntax zur Aktivierung des 1904-Datumssystems lautet:

Datum/Zeit

' Prozeduraufruf zur Einstellung der Statuszeile InfoDateSystem End Sub

Datum/Zeit

Verwenden Sie die Eigenschaft False für die Deaktivierung des 1904-Datumssystems, also die Einstellung des 1900-Datumssystems.

Datum/Zeit

ActiveWorkbook.Date1904 = True

182 >> Anzeige des eingestellten Datumssystems in Statuszeile

81

Anzeige des eingestellten Datumssystems in Statuszeile

Woran erkennen Sie nun, nach welchem Datumssystem Excel die aktive Arbeitsmappe berechnet? Entweder subtrahieren Sie zwei Uhrzeiten und erkennen an den Gitterzäunen bzw. an der korrekten Ausgabe der negativen Zeitdifferenz die aktuelle Einstellung, oder Sie klicken sich wieder durch die EXCEL-OPTIONEN und schauen nach, ob in dem Kontrollkästchen 1904-DATUMSWERTE ein Häkchen steht oder nicht. Eine elegantere Möglichkeit bietet die Anzeige des Datumssystems in der STATUSZEILE von Excel. Üblicherweise wird diese von Excel verwaltet um Informationen anzuzeigen. Der Standardtext lautet BEREIT.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 182 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 72: Standardtext der Statuszeile

In der Beispieldatei zeigen wir Ihnen das jeweils eingestellte Datumssystem als Hinweistext in der Statuszeile an. Das Auslesen der Einstellung sowie das Schreiben in die Statuszeile erfolgt über die Prozedur InfoDateSystem. Wenn die Statusleiste wieder von Microsoft Excel gesteuert werden soll, setzen Sie die StatusBar-Eigenschaft mit der Prozedur StatusBarReset wieder zurück. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle 1904_Datumswerte ' Modul mdl_03_StatusBar '=================================================================== Public Sub InfoDateSystem() ' aktiviertes Datumssystem in Statusleiste anzeigen Application.StatusBar = _ IIf(Application.ActiveWorkbook.Date1904 = True, _ "1904", "1900") & "-Datumssystem" End Sub Public Sub StatusBarReset() ' Statusleiste zurücksetzen Application.StatusBar = False End Sub Listing 90

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Activate() ' Datumssystem in Statuszeile anzeigen InfoDateSystem End Sub Private Sub Workbook_Deactivate() ' Statuszeile zurücksetzen StatusBarReset End Sub Private Sub Workbook_SheetSelectionChange _ (ByVal Sh As Object, ByVal Target As Range) ' Datumssystem in Statuszeile anzeigen InfoDateSystem End Sub Listing 91

Eingabe von Minuszeiten

Die Eingabe einer negativen Uhrzeit erreichen Sie in beiden Datumssystemen durch den Zelleneintrag ="-10:00"

Datum/Zeit

82

Datum/Zeit

Die Umstellung des Datumssystems selber löst kein Ereignis aus. Um dennoch jederzeit das eingestellte Datumssystem in der Statuszeile ausgeben zu können verwenden wir das Workbook_SheetSelectionChange-Ereignis. Jede Änderung der Zellmarkierung auf jedem Tabellenblatt der Datei löst dieses Ereignis aus. Dadurch wird sichergestellt, dass die ordnungsgemäße Anzeige des Datumssystems zeitnah nach der Umstellung erfolgt.

Datum/Zeit

Dazu verwenden Sie einige der Workbook-Ereignis-Prozeduren, die in Kapitel »Ereignisse« noch genauer beschrieben werden. Tritt eines der Ereignisse ein, wird die jeweils angegebene Prozedur aufgerufen und ausgeführt.

Datum/Zeit

Die Anzeige des Datumssystems soll nur in dieser Beispieldatei geschehen. Daraus folgt, dass Sie Excel mitteilen müssen, wann die gewünschte Information in der Statuszeile angezeigt werden soll und wann Excel wieder die Kontrolle übernimmt.

Datum/Zeit

183

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 183 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Folgende Prozedur schreibt eine negative Zeit im Textformat in die Zelle E10.

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 184 Dienstag, 4. Dezember 2007 1:42 13

184 >> 1904-Datumswerte mit VBA kopieren '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle Function_NegativeTime ' Modul mdl_04_WriteMinusTime '=================================================================== Public Sub WriteMinusTime() Range("E10").Value = "-10:00" End Sub

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Achtung

Datum/Zeit

Listing 92

83

Beachten Sie, dass es sich bei diesem Zellwert um einen Wert im Textformat handelt. Eine Berechnung ist mit diesem Zellinhalt nicht möglich. Diese Möglichkeit der negativen Zeiteingabe in eine Zelle ist nur dafür gedacht, Minuszeiten in einer Zelle anzuzeigen.

1904-Datumswerte mit VBA kopieren

In der Zelle A12 der Beispieldatei in Tabelle 1904_DATUMSWERTE steht das Datum 01.01.2007. Dieses Datum wird bei der Umstellung auf das 1904-Datumssystem auf den 02.01.2011 geändert, was exakt 1462 Tagen entspricht. Angenommen, die 1904-DATUMSWERTE sind aktiviert und Sie wollen das Datum aus A12 mit einem einfachen Befehl in eine weitere Zelle A13 schreiben. Dazu können Sie folgende Anweisung geben, im Glauben, dass Excel den korrekten Datumwert kopiert: Range("A13") = Range("A12")

In der folgenden Prozedur stellen wir zunächst die 1904-Datumswerte ein und ändern passend dazu die Beschriftung der Umschaltfläche, zur Umstellung des Datumssystems. Im Anschluss daran wird der Zelle A13 der Wert der Zelle A12 zugewiesen. Das Ergebnis sehen Sie anschließend im Tabellenblatt und in einem Meldungsfenster: '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle 1904_Datumswerte ' Modul mdl_05_CopyDate '=================================================================== Public Sub CopyDateFalse() ' 1904-Datumssystem einstellen ActiveWorkbook.Date1904 = True Listing 93

' Beschriftung Umschaltfläche ActiveSheet.ToggleButton1.Caption = _ "1904-Datumswerte" & vbCr & "deaktivieren" ' Wert aus A12 in A13 kopieren Range("A13") = Range("A12") ' Meldungsfenster mit Werten MsgBox "A12= " & Range("A12") & _ vbCr & _ "A13= " & Range("A13") _ , , "CopyDateFalse" End Sub

Datum/Zeit

Datum/Zeit

Listing 93 (Forts.)

Datum/Zeit

185

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 185 Dienstag, 4. Dezember 2007 1:42 13

Wie kann das passieren? Ist das ein bereits mehrfach beschriebener Bug? Nein, es ist kein Bug, die Erklärung dazu ist einfach: Die Default-Einstellung des Range-Objektes ist Value. Wird einem Range-Objekt keine Eigenschaft zugewiesen gibt es den Wert des angegebenen Bezugs zurück. Leider rechnet Excel in unserem Fall dem gefundenen Wert aufgrund der aktivierten 1904-Datumswerte vier Jahre und einen Tag hinzu. Die Lösung des Problems liegt auf der Hand: schreiben Sie obige Prozedur mit expliziter Zuweisung der gewünschten Value-Eigenschaft für das Range-Objekt.

Datum/Zeit

Sie sehen, dass Excel nicht das Datum der Zelle A12 eins zu eins nach A13 transferiert hat, sondern entsprechend der aktivierten 1904-Datumswerte vier Jahre und einen Tag dazu addiert hat.

Datum/Zeit

Abbildung 73: Falscher Datentransfer

Datum/Zeit

Range("A13").Value = Range("A12").Value

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 186 Dienstag, 4. Dezember 2007 1:42 13

186 >> 1904-Datumswerte mit VBA kopieren

Dadurch wird der tatsächliche Wert des Bezugs richtig von der Zelle A12 in die Zelle A13 transferiert: '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle 1904_Datumswerte ' Modul mdl_05_CopyDate '===================================================================

Datum/Zeit

Datum/Zeit

Public Sub CopyDateTrue() ActiveWorkbook.Date1904 = True ActiveSheet.ToggleButton1.Caption = _ "1904-Datumswerte" & vbCr & "deaktivieren" Range("A13").Value = Range("A12").Value MsgBox "A12= " & Range("A12").Value & _ vbCr & _ "A13= " & Range("A13").Value _ , , "CopyDateTrue" End Sub

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Listing 94

Abbildung 74: Richtiger Datentransfer

Haben Sie bereits einen umfangreichen Bestand an Datumswerten in Ihrer Tabelle und ändern dann das Datumssystem auf 1904-Datumswerte, können Sie mit der ersten Prozedur ConvertInto1904 alle vorhandenen Daten wieder berichtigen, also um vier Jahre und einen Tag zurückrechnen. Dieser Zeitraum entspricht einem Zahlenwert von 1462. Durch Verwendung der SpecialCells-Methode werden dabei nur reine Zahlenwerte neu berechnet. Ergebnisse, welche aus Formeln resultieren, bleiben dabei unberücksichtigt. Die Prozedur ConvertFrom1904 zählt zu jedem Datumswert im benutzten Bereich 1462 Tage hinzu, um die entstandene Differenz durch die Umstellung des Datumssystems auszugleichen. Die folgenden Prozeduren erledigen im benutzten Bereich des aktiven Tabellenblattes die Konvertierungsarbeit. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle Date_Convert ' Modul mdl_06_DateConvert '=================================================================== ' Feste Datumswerte konvertieren _ von normalem Datumssystem zu 1904-Datumswerten

Datum/Zeit

Für den Fall, dass Sie Daten aus anderen Arbeitsmappen importiert haben, welche in einem anderen als dem aktuellen Datumssystem gespeichert waren, konvertieren Sie die Datumswerte entweder von den 1900- zu den 1904-Datumswerten oder umgekehrt.

Datum/Zeit

Datumswerte aus anderem Datumssystem importieren

Datum/Zeit

84

187

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 187 Dienstag, 4. Dezember 2007 1:42 13

' Fehlerroutine zurücksetzen On Error GoTo 0

Datum/Zeit

On Error Resume Next ' Verweis auf Zahlenzellen im aktiven Tabellenblatt Set rngArea = ActiveSheet.UsedRange _ .SpecialCells(xlCellTypeConstants, xlNumbers) ' Verlasse Prozedur, wenn keine Zahlenzellen vorhanden sind If Err.Number > 0 Then Exit Sub

Datum/Zeit

Public Sub ConvertInto1904() Dim rngArea As Range Dim rngCell As Range

Listing 95

Datum/Zeit

' Ereignisse deaktivieren Application.EnableEvents = False

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 188 Dienstag, 4. Dezember 2007 1:42 13

188 >> Datumsfunktionen bei 1904-Datumswerten For Each rngCell In rngArea If IsDate(rngCell.Value) Then ' Datumswerte zurückrechnen rngCell.Value = rngCell.Value - 1462 End If Next ' Ereignisse aktivieren Application.EnableEvents = True End Sub ' Feste Datumswerte konvertieren _ von 1904-Datumswerten zu normalem Datumssystem Public Sub ConvertFrom1904() Dim rngArea As Range Dim rngCell As Range On Error Resume Next Set rngArea = ActiveSheet.UsedRange _ .SpecialCells(xlCellTypeConstants, xlNumbers) If Err.Number > 0 Then Exit Sub On Error GoTo 0 Application.EnableEvents = False For Each rngCell In rngArea If IsDate(rngCell.Value) Then rngCell.Value = rngCell.Value + 1462 End If Next Application.EnableEvents = True End Sub Listing 95 (Forts.)

85

Datumsfunktionen bei 1904-Datumswerten

Formeln mit Datumsberechnungen reagieren anders als fixe Datumsangaben bei der Umstellung des Datumssystems. Die Formel =HEUTE() liefert in beiden Systemen den gleichen Wert: das Datum der Systemeinstellung. Dieses Verhalten betrifft auch weitere Funktionen der Kategorie DATUM & ZEIT im Funktions-Assistenten, wie zum Beispiel die Jetzt()- und die Datum()-Funktion. Wurde das Datumssystem auf 1904-Datumswerte oder umgekehrt umgestellt, gleichen die folgenden Prozeduren die Zeitdifferenz wieder aus.

On Error Resume Next ' Verweis auf Formelzellen im aktiven Tabellenblatt Set rngArea = ActiveSheet.UsedRange _ .SpecialCells(xlCellTypeFormulas, 23) If Err.Number > 0 Then Exit Sub On Error GoTo 0 Application.EnableEvents = False For Each rngCell In rngArea If IsDate(rngCell.Value) And _ Right(rngCell.Formula, 5) = "+1462" Then rngCell.Formula = _ Left(rngCell.Formula, Len(rngCell.Formula) - 5) End If Next Application.EnableEvents = True End Sub ' Formel-Datumswerte konvertieren _ von 1904-Datumswerten zu normalem Datumssystem Public Sub ConvertDateFormularFrom1904() Dim rngArea As Range Dim rngCell As Range On Error Resume Next ' Verweis auf Formelzellen im aktiven Tabellenblatt Set rngArea = ActiveSheet.UsedRange _ .SpecialCells(xlCellTypeFormulas, 23) If Err.Number > 0 Then Exit Sub

Datum/Zeit Datum/Zeit

Public Sub ConvertDateFormularInto1904() Dim rngArea As Range Dim rngCell As Range

Datum/Zeit

' Formel-Datumswerte konvertieren _ von normalem Datumssystem zu 1904-Datumswerten

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_07_MinusTime.xlsm ' Tabelle Date_Convert ' Modul mdl_06_DateConvert '===================================================================

Datum/Zeit

189

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 189 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Listing 96

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 190 Dienstag, 4. Dezember 2007 1:42 13

190 >> Berechnung von Datumsdifferenzen On Error GoTo 0 Application.EnableEvents = False For Each rngCell In rngArea If IsDate(rngCell.Value) Then rngCell.Formula = rngCell.Formula & "+1462" End If Next Application.EnableEvents = True End Sub

Datum/Zeit

Datum/Zeit

Listing 96 (Forts.)

86

Berechnung von Datumsdifferenzen

Wenn Sie die Anzahl der Tage, Monate oder Jahre zwischen zwei Datumsangaben berechnen möchten, können Sie die Tabellen-Funktion DATEDIF verwenden. Diese Funktion liefert die Anzahl der Tage, Monate oder Jahre zwischen einem Ausgangsund einen Enddatum. Obwohl diese Funktion aus Kompatibilitätsgründen mit Lotus 1-2-3 seit einigen Jahren in Microsoft Excel zur Verfügung gestellt wird, wurde sie erstmals in der in Excel integrierten Online-Hilfe, Version Excel 2000, beschrieben. Ab Excel 2002 wird diese Funktion wiederum nicht mehr dokumentiert. Aus diesem Grund geben wir hier noch einmal eine genauere Beschreibung.

Datum/Zeit

=DATEDIF(Ausgangsdatum;Enddatum;Einheit)

Datum/Zeit

Die DATEDIF-Funktion hat die folgende Syntax:

Datumsangaben können als Textzeichenfolgen in Anführungszeichen, als fortlaufende Zahlen oder als Ergebnis anderer Formeln oder Funktionen eingegeben werden.

Der dritte Parameter der Funktion ist der Informationstyp, welcher die Einheit angibt, die zurückgegeben werden soll. Diese Einheit wird über die englische Kurzschreibweise vorgenommen. Die Online-Hilfe in Excel 2000 nennt hier fälschlicherweise die deutschen Abkürzungen. Zum Beispiel wird dort J für Jahre angegeben, richtig ist aber Y für Year.

Ausgangsdatum ist das erste Datum oder Startdatum des Zeitraums. Datum/Zeit

Enddatum ist ein Datum, welches das letzte Datum oder Enddatum des Zeitraums

angibt.

Die folgenden Einheiten stehen Ihnen dabei zur Verfügung. Die Ergebnisse wurden mit nachstehender Formel berechnet:

Datum/Zeit

=DATEDIF("15.06.2007";"01.02.2010";"Einheit")

Einheit

Ergebnis

Rückgabewert

"Y"

2

Die Anzahl der vollständigen Jahre im Zeitraum

"M"

31

Die Anzahl der vollständigen Monate im Zeitraum

"D"

961

Die Anzahl der Tage im Zeitraum

"MD"

17

Die Differenz zwischen den Tagen in Anfangsdatum und Enddatum Die Monate und Jahre der Datumsangaben werden ignoriert

"YM"

7

Die Differenz zwischen den Monaten in Anfangsdatum und Enddatum Die Tage und Jahre der Datumsangaben werden ignoriert

"YD"

231

Die Differenz zwischen den Tagen in Anfangsdatum und Enddatum Die Jahre der Datumsangaben werden ignoriert

Tabelle 17: Informationstypen der DATEDIF-Tabellenfunktion

Datum/Zeit

191

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 191 Dienstag, 4. Dezember 2007 1:42 13

=DATEDIF("15.01.2007";"15.02.2007";"M") ' ergibt 1 Monat Ausgangsdatum

Enddatum

Einheit

Differenz

15.01.2007

14.01.2008

Y

0 Jahre

15.01.2007

15.01.2008

Y

1 Jahr

15.01.2007

14.02.2007

YM

0 Monate

15.01.2007

15.02.2007

YM

1 Monat

15.01.2007

14.01.2007

D

#ZAHL!

15.01.2007

15.01.2007

D

0 Tage

15.01.2007

16.01.2007

D

1 Tag

Datum/Zeit

Bei der Berechnung mit der DATEDIF-Funktion werden nur ganze Jahre bzw. Monate berücksichtigt. Der Zeitraum zwischen dem 15.01.2007 und 14.02.2007 ergibt 0 Monate. Erst wenn der Tag des Ausgangsdatums erreicht oder überschritten wird, zählt die DATEDIF-Funktion einen Monat weiter.

Datum/Zeit

ergibt 2 Jahre und 7 Monate und 14 Tage.

Datum/Zeit

=DATEDIF("15.06.2007";"01.02.2010";"Y") & " Jahre und " & DATEDIF("15.06.2007";"01.02.2010";"YM") & " Monate" & " und "& DATEDIF("15.06.2007";"01.02.2010";"MD") & " Tage"

Datum/Zeit

Es sind auch Kombinationen der DATEDIF-Funktion innerhalb einer Formel möglich:

In der Tabelle 18 wird ersichtlich, dass das Enddatum größer als das Ausgangsdatum sein muss, da die Formel ansonsten die Fehlermeldung #ZAHL! als Ergebnis liefert.

Datum/Zeit

Tabelle 18: DATEDIF-Berechnungen

Datum/Zeit

2471_Excel-VBA.book Seite 192 Dienstag, 4. Dezember 2007 1:42 13

192 >> Zeitdifferenzen mit VBA DateDiff

87

Zeitdifferenzen mit VBA DateDiff

Mit der DateDiff-Funktion die in VBA zur Verfügung steht, können Sie ermitteln, wie viele Zeitintervalle sich zwischen zwei Daten oder Zeiten befinden.

Datum/Zeit

Datum/Zeit

Die Syntax dieser Funktion lautet: DateDiff(interval, date1, date2[, firstdayofweek _ [, firstweekofyear]])

Die ersten drei Parameter interval, date1 und date2 sind vergleichbar mit den Parametern der bereits genannten DATEDIF-Tabellenfunktion. Der vierte Parameter firstdayofweek ist optional und erwartet als Argument eine Zahl, die den ersten Tag der Woche angibt. Ist dieser Wert nicht angegeben, so wird Sonntag angenommen. Der letzte Parameter firstweekofyear ist ebenfalls optional und erwartet eine Zahl, welche die erste Woche des Jahres angibt. Ist dieser Wert nicht angegeben, wird die Woche mit dem 1. Januar als die erste Woche angenommen.

Datum/Zeit

Datum/Zeit

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 19: Interval-Argumente der DateDiff-Funktion

Achtung

Datum/Zeit

Datum/Zeit

Datum/Zeit

Folgende Einstellungen sind für das Argument interval möglich:

Die Annahme, dass die DateDiff-Funktion in der VBA Programmierung das Gegenstück zu der Tabellenfunktion DATEDIF darstellt, ist falsch.

Mit der VBA-Funktion DateDiff wird ermittelt, wie viele Zeitintervalle sich zwischen zwei Daten befinden. Die Zeitdifferenz zwischen dem 31.01. zum 01.02. gilt deswegen als ganzer Monat, während die viel längere Zeitdifferenz vom 1.1. zum 31.1. keinen ganzen Monat ergibt.

durch Vergleich der Monatszahlen, wobei ergänzend der Tag hinzuzunehmen ist.

Vergleichen wir die Ergebnisse der beiden Funktionen DATEDIF und DateDiff, wird deutlich, dass diese beiden Funktionen sich nicht nur durch ein f mehr oder weniger unterscheiden, sondern auch unterschiedlich rechnen. In der Beispieldatei finden Sie die Testdaten und Ergebnisse unserer Berechnungen. Ausgangssituation sind zwei Datumswerte in A2 und B2 der Tabelle DATEDIFCONTRADATEDIFF. In der Zelle A2 steht das Datum 15.06.2007, in B2 der 01.01.2010. Die Ergebnisse der Excel Funktion wurden mit oben bereits erwähnten Formeln berechnet. Die Werte der VBA-Funktion haben wir mit dem nachstehenden Makro in die einzelnen Zellen geschrieben. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_08_DATEDIFandDateDiff.xlsm ' Tabelle DATEDIFcontraDateDiff ' Modul mdl_01_VBADateDiff '=================================================================== Public Dim Dim Dim Dim

Sub VBADateDiff() DateBegin As Date DateEnd As Date intI As Integer varInterval As Variant

Datum/Zeit

DateDiff bestimmt die Monatsdifferenz nicht im Sinne einer Tagezählung, sondern

Datum/Zeit

193

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 193 Dienstag, 4. Dezember 2007 1:42 13

Listing 97

Datum/Zeit

' Zeitinterval in Zelle schreiben Cells(intI + 2, "F") = varInterval(intI) Next End Sub

Datum/Zeit

' Elemente des Datenfeldes durchlaufen For intI = 0 To 2 ' Funktionsergebnis in Zelle schreiben Cells(intI + 2, "E") = _ DateDiff(varInterval(intI), DateBegin, DateEnd)

Datum/Zeit

' Datenfeld mit Zeitintervallen varInterval = Array("yyyy", "m", "d")

Datum/Zeit

DateBegin = Range("A2").Value DateEnd = Range("B2").Value

194 >> Zeitdifferenzen mit VBA DateDiff

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 194 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 75: Vergleichsergebnisse DATEDIF / DateDiff

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Per Makro sieht ein Vergleich der beiden Funktionen, die sich von der Schreibweise her nur durch ein zusätzliches f unterscheiden, folgendermaßen aus: '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_08_DATEDIFandDateDiff.xlsm ' Tabelle DATEDIFcontraDateDiff ' Modul mdl_02_DateSpanYear '=================================================================== Public Sub DateSpanYear() Dim intExcel As Integer Dim intVBA As Integer ' Ergebnis aus Formelberechnung an Variable übergeben intExcel = Evaluate("=DateDif(A2,B2,""Y"")") ' Ergebnis aus VBA-Funktion an Variable übergeben intVBA = DateDiff( _ interval:="yyyy", _ Date1:=Range("A2").Value, _ date2:=Range("B2").Value) MsgBox "Im Zeitraum vom " & Range("A2").Value & _ " bis " & Range("B2").Value _ & " liegen" & _ vbNewLine & _ "Excel: " & intExcel & " Jahre" & _ vbNewLine & _ "VBA: " & intVBA & " Jahre", , _ "DATEDIF contra DateDiff" End Sub Listing 98

88

VBA-Funktion für die DateDif-Tabellenfunktion

Die ausgegebene Meldung laut Abbildung 76 hat uns überzeugt, eine Ersatzlösung für die VBA-Funktion DateDiff zu finden, um auch unter VBA das gleiche Ergebnis wie das der Tabellenfunktion DATEDIF zu erhalten. Eine einfache Möglichkeit, Tabellenfunktionen unter VBA zu verwenden, besteht über das Application.WorksheetFunction-Objekt. Folgende Syntax wird für die Tabellenfunktion =SUMME("A1:A5") unter VBA angewandt. Range("D2") = Application.WorksheetFunction.Sum(Range("A1:A5"))

Abbildung 77: Methoden des Application.WorksheetFunction-Objektes über die Intellisense-Auflistung

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Genauso wie die Tabellenfunktion DATEDIF nicht in der Hilfe dokumentiert wird, erscheint sie auch in Excel 2007 nicht in der INTELLISENSE-Liste des Application.WorksheetFunction-Objektes (siehe Abbildung 77) und steht somit unter VBA nicht direkt zur Verfügung.

Datum/Zeit

Abbildung 76: Vergleichsberechnung

Datum/Zeit

195

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 195 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

2471_Excel-VBA.book Seite 196 Dienstag, 4. Dezember 2007 1:42 13

196 >> VBA-Funktion für die DateDif-Tabellenfunktion

Da die Tabellenfunktion DATEDIF in VBA nicht zur Verfügung steht, kann sie mit der Evaluate-Methode in VBA berechnet werden.

Datum/Zeit

Will man die Tabellenfunktion mit VBA in eine Zelle schreiben, wird folgende Syntax verwendet: Range("D2").Formula = "=DateDif(A2,B2,""Y"")"

Bei der Auswertung in VBA gibt man in der Evaluate-Methode die gleiche Zeichenkette wie in der Formel an. Die dabei angegebenen Bezüge beziehen sich ohne vorangestelltes Worksheet-Objekt jeweils auf das gerade aktive Tabellenblatt. Das Ergebnis der Evaluate-Berechnung kann man entweder direkt in eine Zelle schreiben,

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Range("D2").Value = Evaluate("=DateDif(A2,B2,""Y"")")

oder einer Variablen zur weiteren Verwendung im laufenden Code zuweisen. lngYear = Evaluate("=DateDif(A2,B2,""Y"")")

Um sicherzustellen, dass sich die Berechnung und Ausgabe des Ergebnisses auf ein bestimmtes Tabellenblatt der aktiven Arbeitsmappe bezieht, wird das gewünschte Worksheet-Objekt in die Syntax eingebunden: Worksheets("Tabelle1").Range("D2").Value = _ Evaluate("=DateDif(' Tabelle1'!A2, _ ' Tabelle1'!B2,""Y"")")

Eine 100%-ige Referenzierung beinhaltet zusätzlich die Angabe des WorkbookObjektes: Workbooks("Mappe.xlsm").Worksheets("Tabelle1") _ .Range("D2").Value = _ Evaluate("=DATEDIF('[Mappe.xlsm]Tabelle1'!$A$2," & _ "'[Mappe.xlsm]Tabelle1'!$B$2,""Y"")")

Um die Benutzung der Datedif-Tabellenfunktion in VBA variabel zu halten, empfiehlt sich eine benutzerdefinierte Funktion, die als Ergebnis einen Long-Wert liefert. Als Variablen werden das Anfangs-, das Enddatum sowie der Zeitinterval festgelegt. Beim Aufruf der Funktion müssen die Argumente mit übergeben werden. In der Funktion muss nicht berücksichtigt werden, in welcher Arbeitsmappe oder Tabellenblatt die Berechnung ausgeführt werden soll, weil nur feste Werte oder genaue Bezüge zu den gewünschten Werten an die Funktion übergeben werden.

Datum/Zeit

Datum/Zeit

In der Datedif-Tabellenfunktion werden die Datumswerte als Long-Werte erwartet. Aus diesem Grund werden die übergebenen Datumswerte mit der CLng-Umwandlungsfunktion zur weiteren Berechnung direkt in der Evaluate-Methode umgewandelt. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_08_DATEDIFandDateDiff.xlsm ' Tabelle Function DATEDIF ' Modul mdl_03_Function_DATEDIF '=================================================================== Listing 99

Public Function Excel_DateDif(date1 As Date, date2 As Date, _ strInterval As String) As Long ' Funktion berechnet Zeitdifferenzen nach der Excel ' DateDif-Tabellenfunktion ' ' ' '

date1 = Anfangsdatum date2 = Enddatum strInterval muss eine der folgenden Einheiten sein: "Y","M","D","MD","YM","YD"

Excel_DateDif = Evaluate("=DateDif(" & _ CLng(date1) & "," & _ CLng(date2) & ",""" & strInterval & """)") End Function

Datum/Zeit

197

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 197 Dienstag, 4. Dezember 2007 1:42 13

Beim Aufruf der benutzerdefinierten Funktion kann den einzelnen Argumenten der Parametername vorangestellt werden. Dies erleichtert die bessere Lesbarkeit des Codes zu einem späteren Zeitpunkt. Im Gegensatz zur integrierten VBA Funktionen müssen in benutzerdefinierten Funktionen entweder alle Parameternamen oder gar keine angegeben werden.

Public Sub MonthSpan() ' keine Benennung der Parameter Range("D3").Value = _ Excel_DateDif(Range("A2").Value, _ Range("B2").Value, _ "M")

Datum/Zeit

Listing 100

Datum/Zeit

Public Sub YearSpan() ' Anfangsdatum in A2 ' Enddatum in B2 ' mit Benennung der Parameter Range("D2").Value = _ Excel_DateDif(date1:=Range("A2").Value, _ date2:=Range("B2").Value, _ strInterval:="Y") End Sub

Datum/Zeit

Der Prozeduraufruf erfolgt über Schaltflächen im Tabellenblatt. Dadurch kann auf die genaue Referenzierung des Tabellenblattes sowie der Arbeitsmappe verzichtet werden.

Datum/Zeit

In der Tabelle FUNCTION DATEDIF der Beispieldatei wurden die nachfolgend aufgeführten Prozeduren angewandt, die jeweils über die Excel_DateDif-Funktion die Berechnung von Zeitintervallen direkt in Zellen des Tabellenblattes schreiben.

Datum/Zeit

Listing 99 (Forts.)

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 198 Dienstag, 4. Dezember 2007 1:42 13

198 >> VBA-Funktion für die DateDif-Tabellenfunktion End Sub Public Sub DaySpan() Range("D4").Value = _ Excel_DateDif(Range("A2").Value, _ Range("B2").Value, _ "D") End Sub Public Sub MonthDaySpan() Range("D5").Value = _ Excel_DateDif(Range("A2").Value, _ Range("B2").Value, _ "MD") End Sub Public Sub YearMonthSpan() Range("D6").Value = _ Excel_DateDif(Range("A2").Value, _ Range("B2").Value, _ "YM") End Sub Public Sub YearDaySpan() Range("D7").Value = _ Excel_DateDif(Range("A2").Value, _ Range("B2").Value, _ "YD") End Sub

Datum/Zeit

Datum/Zeit

Datum/Zeit

Listing 100 (Forts.)

Es ist ebenso möglich, ohne die DATEDIF-Funktion eine Zeitdifferenz zu berechnen. Das folgende Makro zeigt dies am Beispiel einer Monatsdifferenz. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_08_DATEDIFandDateDiff.xlsm ' Tabelle Function DATEDIF ' Modul mdl_04_MonthDifference '=================================================================== Public Dim Dim Dim Dim

Sub MonthDifference() datDate1 As Date datDate2 As Date bytTemp As Byte intDiffMonth As Integer

Listing 101

>> Datum/Zeit

199

datDate1 = Worksheets("AWF.DATEDIF").Range("A2").Value datDate2 = Worksheets("AWF.DATEDIF").Range("B2").Value

Datum/Zeit

2471_Excel-VBA.book Seite 199 Dienstag, 4. Dezember 2007 1:42 13

MsgBox "Zwischen dem " & Range("A2").Value & _ " und dem " & Range("B2").Value & _ vbNewLine & _ "liegen " & intDiffMonth & " Monate.", , _ "Monatsberechnung ohne DATEDIF-Funktion" End Sub Listing 101 (Forts.)

=Age(C8;DATWERT("01.01.2007"))

Ist der Parameter Birthday leer oder enthält keinen gültigen Datumswert, dann wird die Funktion beendet. Als Ergebnis der Age-Funktion wird dann der Wert 0 geliefert, weil die Funktion als Long deklariert wurde. Mit der IsMissing-Funktion wird in der Prozedur überprüft, ob der optionale Parameter Deadline in der Formel angegeben wurde. Fehlt dieses Argument, wird das aktuelle Datum aus der Systemeinstellung als Enddatum zur Berechnung herangezogen. Um die IsMissing-Funktion zu verwenden, darf der zu überprüfende optionale Parameter nicht mit einem festen Datentyp deklariert sein, da sonst der typabhängige Standardwert einen Wert vortäuscht. Wird der Parameter z. B. als Date deklariert, weist der Parameter, ohne dass ein Datum übergeben wurde, den Wert "00:00:00"

Datum/Zeit

Interessant an der Funktion ist der zweite optionale Parameter Deadline, den Sie auf Wunsch verwenden können, aber nicht müssen. Standardmäßig wird das Alter auf Basis des aktuellen Datums berechnet. Über den Parameter Deadline können Sie auch ein bestimmtes Enddatum angeben. Folgende Formel liefert das Alter der Person am 01.01.2007 (Geburtsdatum in Zelle C8):

Datum/Zeit

Schreiben Sie die Funktion im VBA-Editor in ein Modul. In der Funktion wird berücksichtigt, ob der Geburtstag im aktuellen Jahr bereits stattgefunden hat oder nicht. In der Beispieldatei Tabelle FUNCTION_AGE wird in Zelle C8 das Geburtsdatum eingegeben. Der Aufruf in einer Zelle erfolgt über die Tabellen-Formeln =Age(Bezug) oder =Age(Bezug; [Deadline]).

Datum/Zeit

Im Zusammenhang mit der Datediff-Funktion möchten wir Ihnen noch eine benutzerdefinierte Funktion vorstellen, die Ihnen bei der Altersberechnung behilflich sein kann.

Datum/Zeit

Funktion um Lebensalter zu berechnen

Datum/Zeit

89

Datum/Zeit

intDiffMonth = (Year(datDate2) - Year(datDate1)) * 12 _ + Month(datDate2) - Month(datDate1) - bytTemp

Datum/Zeit

If Day(datDate2) < Day(datDate1) Then bytTemp = 1

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 200 Dienstag, 4. Dezember 2007 1:42 13

200 >> Funktion um Lebensalter zu berechnen

auf. Dieser Wert lässt die IsMissing-Funktion fehlschlagen und das Ergebnis der Funktion wird verfälscht. Die Berechnung des Lebensalters soll taggenau erfolgen. Unter Berücksichtigung des Jahres der Endzeit wird kontrolliert, ob das Startdatum größer oder kleiner als das Enddatum ist. Dazu verwenden wir die DateSerial-Funktion. In dieser Funktion wird aus dem Tag und Monat des Startdatums und dem Jahr des Enddatums ein Vergleichsdatum erzeugt: DateSerial(Year(Deadline), Month(Birthday), Day(Birthday))

Mit diesem Vergleichsdatum lässt sich nun überprüfen, ob der angegebene Geburtstag in dem Jahr des Enddatums schon war oder ob er noch vor dem Enddatum liegt. Ist das Vergleichsdatum größer als das Enddatum, dann liegt der Geburtstag noch vor uns. Dementsprechend wird von dem Ergebnis der Datediff-Funktion ein Jahr abgezogen. Wenn das Vergleichsdatum kleiner als das Enddatum ist, wurde der Geburtstag in dem Jahr schon gefeiert. In diesem Fall stimmt die Berechnung der VBAFunktion Datediff. In der Beispieldatei wird die Age-Funktion in der Zelle C12 über die Formel =Age(C8) aufgerufen. Sobald Sie ein Datum in die Zelle C8 eingeben, erfolgt die erneute Berechnung mit anschließender Ausgabe des Ergebnisses in der Zelle C12. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_08_DATEDIFandDateDiff.xlsm ' Tabelle Function_Age ' Modul mdl_05_FunctionAge '=================================================================== Public Function Age(Birthday As Variant, _ Optional Deadline As Variant) As Long ' Prüfung, ob Startdatum übergeben wurde If IsEmpty(Birthday) Or Not IsDate(Birthday) Then ' Rückgabewert ist durch Deklarierung der Funktion ' als Long automatisch 0 Exit Function End If ' bei fehlendem Argument wird aktuelles Datum als ' Enddatum angenommen If IsMissing(Deadline) Then Deadline = Date ' Prüfung, ob Geburtstag im angegebenen Endjahr ' schon vergangen ist If DateSerial(Year(Deadline), Month(Birthday), _ Day(Birthday)) > Deadline Then Listing 102

Age = DateDiff("yyyy", Birthday, Deadline) - 1 Else Age = DateDiff("yyyy", Birthday, Deadline) End If End Function Listing 102 (Forts.)

90

Stoppuhr mit Excel

Abbildung 78: Stoppuhr

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_09_StopWatch.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Listing 103

Datum/Zeit

Die Darstellung der Zeit erfolgt hier nicht in einer Zelle, sondern wird in einem Bezeichnungsfeld LABEL angezeigt. In der Beispieldatei haben wir noch einige kleinere Spielereien integriert. Über das Workbook_Open-Ereignis sowie bei Aktivierung der START/STOP-Schaltfläche werden die verwendeten Steuerelemente unterschiedlich formatiert und beschriftet.

Datum/Zeit

Eine ausführliche Beschreibung mit anschaulichen Beispielen zu der OnTimeMethode finden Sie in der Kategorie »Ereignisse«.

Datum/Zeit

Hinweis

In dem Code zu obigen Beispiel bedienen wir uns der OnTime-Methode.

Datum/Zeit

Datum/Zeit

In diesem Rezept zeigen wir Ihnen, wie man in Excel eine Stoppuhr erstellt. Bei Klick auf die Schaltfläche START wird in einem Feld die abgelaufene Zeit im Sekundentakt bis zum nächsten Klicken auf die Schaltfläche STOP mitgeschnitten.

Datum/Zeit

201

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 201 Dienstag, 4. Dezember 2007 1:42 13

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 202 Dienstag, 4. Dezember 2007 1:42 13

202 >> Stoppuhr mit Excel

Private Sub Workbook_Open() ' Fenstergröße festlegen With ActiveWindow .WindowState = xlNormal .Width = 195 .Height = 197 End With With Worksheets(1) ' Zeitfenster ausblenden .Label1.Visible = False ' Schaltflächen Beschriftung .CmbStartStop.Caption = "K l i c k m i c h" ' Hintergrundfarbe .CmbStartStop.BackColor = &HC000& End With ' Bei eingestelltem Blattschutz kann im Tabellenblatt ' nichts markiert werden Worksheets(1).EnableSelection = xlNoSelection End Sub Listing 103 (Forts.)

Für den START bzw. STOP der Zeitmessung verwenden wir für beide Funktionen eine Befehlsschaltfläche COMMANDBUTTON. Beide Elemente, LABEL und COMMANDBUTTON, wurden aus der STEUERELEMENT-TOOLBOX-Symbolleiste eingefügt. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_09_StopWatch.xlsm ' Ereignis Tabelle1(StopWatch) '=================================================================== Private Sub CmbStartStop_Click() With CmbStartStop ' Prüfung Schaltflächen Beschriftung If .Caption = "S t a r t" Or _ .Caption = "K l i c k m i c h" Then ' Zeit Übernahme datTimeNow = Time ' Beschriftung ändern .Caption = "S t o p" ' Hintergrundfarbe ändern .BackColor = &H80FF& Listing 104

' Zeitfenster anzeigen Label1.Visible = True ' Aufruf des Makros zur Zeitanzeige ShowTime Else Label1.Caption = Format(Time - datTimeNow, "hh:mm:ss") .Caption = "S t a r t" .BackColor = &HC000& ' Aufruf des Makros um die Zeitanzeige zu beenden StopTime End If End With End Sub

Datum/Zeit

203

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 203 Dienstag, 4. Dezember 2007 1:42 13

Public Sub ShowTime() ' Vergangene Zeit anzeigen ThisWorkbook.Sheets(1).Label1.Caption = _ Format(Time - datTimeNow, "hh:mm:ss") ' nächsten Prozeduraufruf berechnen varET = Now + TimeValue("00:00:01") ' Zeitversetzter Prozeduraufruf Application.OnTime varET, "ShowTime" End Sub Listing 105

Datum/Zeit

Public datTimeNow As Date Public varET As Variant

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_09_StopWatch.xlsm ' Modul mdl_01_StopWatch '===================================================================

Datum/Zeit

Über die OnTime-Methode wird die Prozedur ShowTime im Sekundentakt erneut aufgerufen, um die angezeigte Zeit im Bezeichnungsfeld Label1 um eine Sekunde zu erhöhen.

Datum/Zeit

Listing 104 (Forts.)

Datum/Zeit

Im folgenden Makro wird die OnTime-Einstellung aus der vorherigen Prozedur gelöscht.

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 204 Dienstag, 4. Dezember 2007 1:42 13

204 >> Excel kann warten Public Sub StopTime() ' Zeitversetzten Prozeduraufruf löschen On Error Resume Next Application.OnTime EarliestTime:=ET, Procedure:="ShowTime", _ Schedule:=False End Sub

Beim Beenden der Beispieldatei wird die Prozedur StopTime im Workbook_BeforeCloseEreignis aufgerufen. Sie setzt die Aktualisierung der Zeitanzeige zurück. Die SavedEigenschaft wird auf True gesetzt. Dadurch wird die Datei, ohne sie zu speichern und ohne den Anwender zum Speichern aufzufordern, geschlossen. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_09_StopWatch.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_BeforeClose(Cancel As Boolean) StopTime ThisWorkbook.Saved = True End Sub Listing 106

Datum/Zeit

91

Excel kann warten

Bei der Verarbeitung eines aufgerufenen Makros werden die einzelnen Codezeilen einer Prozedur schrittweise, Zeile für Zeile, abgearbeitet. Mit der Wait-Methode wird das aktuell ausgeführte Makro bis zu einem angegebenen Zeitpunkt angehalten.

Datum/Zeit

Datum/Zeit

In folgendem Listing wird über die Wait-Methode der Zeitpunkt festgelegt, zu dem das Makro fortgesetzt und dann das Meldungsfenster angezeigt wird. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_10_Wait.xlsm ' Modul mdl_01_Wait '=================================================================== Public Sub MessageIn10Seconds() If Application.Wait(Now + TimeValue("0:00:10")) Then MsgBox "10 Sekunden sind abgelaufen" End If End Sub

Datum/Zeit

Listing 107

Im nächsten Beispiel wollen wir mit der Beep-Anweisung fünf aufeinander folgende Signaltöne über den Lautsprecher des Computers abspielen. Mit folgendem Code werden zwar in einer For...Next-Anweisung fünf Signaltöne erzeugt, aber beim Makrodurchlauf ist nur ein Ton zu hören. Die Begründung liegt darin, dass der Schleifendurchlauf zu schnell ist, um fünf getrennte Töne hörbar wahrzunehmen. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_10_Wait.xls ' Modul mdl_01_Wait '=================================================================== Public Sub OneBeep() Dim bytCounter As Byte For bytCounter = 1 To 5 Beep Next bytCounter End Sub

Datum/Zeit

Signaltöne erzeugen

Datum/Zeit

92

205

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 205 Dienstag, 4. Dezember 2007 1:42 13

For bytCounter = 1 To 5 Beep Application.Wait (Now + TimeValue("0:00:01")) Next bytCounter End Sub Listing 109

Datum/Zeit

Public Sub FiveBeeps() Dim bytCounter As Byte

Datum/Zeit

'=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_10_Wait.xlsm ' Modul mdl_01_Wait '===================================================================

Datum/Zeit

Lassen Sie Excel jeweils nach jeder Tonausgabe eine Sekunde lang warten, bevor die Schleife erneut durchlaufen wird. Dadurch werden fünf einzelne Signaltöne hörbar erzeugt.

Datum/Zeit

Listing 108

Datum/Zeit

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 206 Dienstag, 4. Dezember 2007 1:42 13

206 >> Töne bei aktuellem Datum ausgeben

93

Töne bei aktuellem Datum ausgeben

Im folgenden Beispiel wird die aktive Zelle auf das heutige Datum überprüft. Bei Übereinstimmung werden drei Signaltöne ausgegeben. Hat die aktive Zelle nicht den heutigen Datumswert, erfolgt eine Fehlermeldung. Es kann vorkommen, dass Excel zu Beginn der Schleife zeitlich ins Stolpern gerät und die Tonausgabe ungleichmäßig erfolgt. Diesen Effekt haben Sie eventuell im vorherigen Beispiel feststellen können. Aus diesem Grund halten wir das Makro eine Sekunde lang an, bevor die Schleife begonnen wird. Dadurch sind die drei angeforderten Töne in gleichmäßigen Abständen zu hören. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_10_Wait.xlsm ' Modul mdl_01_Wait '===================================================================

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Datum/Zeit

Public Sub BeepMsgBox() Dim bytCounter As Byte If ActiveCell.Value = Date Then Application.Wait (Now + TimeValue("0:00:01")) For bytCounter = 1 To 3 Beep Application.Wait (Now + TimeValue("0:00:01")) Next bytCounter Else MsgBox "Die ausgewählte Zelle enthält nicht den " & Date End If End Sub Listing 110

94

Meldung zeitbegrenzt anzeigen

Im folgenden Beispiel wird ein Text für eine definierte Zeitspanne in einer UserForm angezeigt. In unserem Beispiel enthält das Formular keine Schaltflächen. Die UserForm zeigt nur einen Text sowie die verbleibende Zeit bis zur selbstständigen Schließung der Meldung an. Die UserForm wird nach zehn Sekunden automatisch geschlossen.

Abbildung 79: Selbstschließende Meldung

Der Aufruf der UserForm erfolgt über eine Schaltfläche auf dem Tabellenblatt. '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_10_Wait.xlsm ' Modul mdl_02_CallInfo '===================================================================

Datum/Zeit

207

Datum/Zeit

>> Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 207 Dienstag, 4. Dezember 2007 1:42 13

Durch Verwendung der DoEvents-Funktion wird die Steuerung an das Betriebssystem übergeben, damit andere Ereignisse verarbeitet werden können. Durch die DoEvents-Funktion wird sichergestellt, dass die Aufschrift des Bezeichnungsfeldes lbl_Counter bei jedem Schleifendurchlauf aktualisiert wird. Für die Zeitanzeige im Tabellenblatt verwenden wir ein BEZEICHNUNGSFELD aus der Formular-WERKZEUGSAMMLUNG. In dessen Caption-Eigenschaft wird bei jedem Schleifendurchlauf die verbleibende Restlaufzeit der Schleife geschrieben. Direkt im Anschluss an die Schleife wird das Formular wieder geschlossen.

Datum/Zeit Datum/Zeit

Die Wait-Methode unterbricht alle Aktivitäten von Microsoft Excel und verhindert unter Umständen auch das Ausführen sonstiger Vorgänge auf dem Computer. Hintergrundprozesse, wie Drucken und Neuberechnung, werden jedoch fortgesetzt.

Datum/Zeit

Achtung

Beim Aufruf der UserForm wird im UserForm_Activate-Ereignis über die Wait-Methode innerhalb einer For...Next-Anweisung die Zeit bis zur Schließung der Form abgearbeitet. Da die Schleife zehn Mal durchlaufen wird, beträgt die Anzeigendauer dementsprechend zehn Sekunden.

Datum/Zeit

Listing 111

Datum/Zeit

Public Sub CallInfo() frm_01_Info.Show End Sub

Datum/Zeit

Datum/Zeit

2471_Excel-VBA.book Seite 208 Dienstag, 4. Dezember 2007 1:42 13

208 >> Meldung zeitbegrenzt anzeigen '=================================================================== ' Auf CD Buchdaten\Beispiele\03_Datum_Zeit\ ' Dateiname 03_10_Wait.xlsm ' Formular frm_01_Info '=================================================================== Private Sub UserForm_Activate() Dim intI As Integer

Datum/Zeit

For intI = 1 To 10 ' Ereignisse des Betriebssystems ausführen DoEvents ' Zähler aktualisieren lbl_Counter.Caption = 11 - intI

Datum/Zeit

' Wartezeit bis zum nächsten Schleifendurchlauf Application.Wait Now + TimeValue("00:00:01") Next ' Userform beenden Unload Me End Sub

Datum/Zeit

Datum/Zeit

Datum/Zeit

Hinweis

Datum/Zeit

Listing 112

Nähere Informationen und Beispiele zu den Steuerelementen des Formulars finden Sie in Kapitel »UserForm«.

In der Praxis wird das Tabellenkalkulationsprogramm Excel auch als Datenbank eingesetzt. Für solche Aufgaben ist aber eine Tabellenkalkulation wie Excel nur bedingt geeignet, denn grundlegende Funktionen, die in einem Datenbankprogramm Standard sind, fehlen gänzlich und müssen, wenn überhaupt möglich, mühsam nachgebaut werden. Zudem muss das verwendete Format jeder Zelle einer Spalte übereinstimmen, was in einer echten Datenbank durch das Feldformat eindeutig und unerbittlich festgelegt ist. Verwendet man unter Excel beispielsweise in einer Zelle das Format Text und in einer anderen der gleichen Spalte das Format Datum, stimmen beide Inhalte trotz gleich angezeigter Werte möglicherweise nicht mehr überein. Zu einer in einer echten Datenbank grundlegend implementierten Funktion gehört unter anderem, dass durch verschiedene Mechanismen, wie beispielsweise das Verwenden von Primärschlüsseln, doppelt angelegte Datensätze verhindert werden sollen. Excel interessiert es aber überhaupt nicht, ob in einer anderen Zeile gleiche Werte vorkommen, und gibt deshalb auch keinen Hinweis darauf aus, wenn ein solcher Datensatz angelegt wird. Um solche unabsichtlich angelegten redundanten Datensätze zu löschen, könnte man den Spezialfilter einsetzen, an anderer Stelle filtern und dabei die Option KEINE DUPLIKATE einsetzen. Excel 2007 bietet aber eine neue eigene Funktion (REGISTER DATEN | ICON DUPLIKATE ENTFERNEN) an (Abbildung 80), mit der sich diese Aufgabe hervorragend erledigen lässt.

Auswertungen Auswertungen

Doppelte Datensätze mit Excel 2007 löschen

Auswertungen

96

Auswertungen

In dieser Kategorie finden Sie Beispiele, die Ihnen zeigen, wie Sie VBA anwenden können, um Ihre Daten auszuwerten. Sie werden erfahren, wie Sie Bezüge speichern können, wie Sie Tabellenblätter vergleichen und wie Formeln ermittelt werden können. Es werden zudem die Themen Autofilter, Sortieren und Pivot-Tabellen behandelt.

Auswertungen

Einleitung

Auswertungen

95

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 209 Dienstag, 4. Dezember 2007 1:42 13

210 >> Doppelte Datensätze mit Excel 2007 löschen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 210 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 80: Duplikate entfernen

Um das Gleiche mit VBA unter Excel 2007 zu erledigen, wird eine Zelle des relevanten Bereichs selektiert und die folgende Prozedur ausgeführt. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_01_Vergleichen.xlsm ' Tabelle Duplikate ' Modul mdl_04_01_RemoveDuplicates '=================================================================== Public Sub RemoveMyDuplicates() Selection.CurrentRegion.RemoveDuplicates Header:=xlNo End Sub Listing 113

Auswertungen

Enthält der Bereich Überschriften, wird statt Header:=xlNo einfach Header:=xlYes eingesetzt.

Damit man nicht jeden einzelnen Datensatz (Zeile) immer wieder mit jedem anderen Satz vergleichen muss, was bei größeren Datenmengen extrem zeitaufwendig wäre, wird hier ein Umweg über eine Collection gegangen. Die Elemente einer Collection verfügen über einen eindeutigen Schlüssel, der beim Hinzufügen des Elements zu der Collection selbst festgelegt werden kann. Dieser Schlüssel ist eine beliebige Zeichenkette, die aber in der Collection nur einmal vorkommen darf. Versucht man, ein Element hinzuzufügen, und verwendet einen schon vorhandenen Schlüssel, wird der Fehler mit der Nummer 457 ausgeben. Jeder Datensatz, das heißt die Inhalte aller relevanten Zellen einer Zeile, wird zu diesem Zweck in eine Zeichenkette umgewandelt, zusammengeführt und das Ergebnis schließlich als Schlüssel verwendet. Tritt ein Fehler 457 beim Hinzufügen eines neuen Elementes zur Collection auf, ist dieser Datensatz bereits vorhanden und kann gelöscht werden. Ein Problem bei dieser Vorgehensweise gibt es aber. Durchläuft man mit einer Zählvariablen (For i = 1 To 6 ... Next) nacheinander jede Zeile eines Bereiches und löscht dann die aktuelle Zeile, wird ohne Anpassung der Zählvariablen eine Zeile übersprungen. Es ist die, die nach dem Löschen die aktuelle Position eingenommen hat. Um das zu umgehen, durchlaufen Sie einfach den Bereich von hinten nach vorne, ein Löschen der aktuellen Zeile erfordert dann nämlich kein Anpassen der Zählvariablen. Ein kleiner Nachteil einer Collection ist, dass der Schlüssel nicht zwischen Groß- und Kleinschreibung unterscheidet, was man aber sicherlich in den meisten Fällen verschmerzen kann. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_01_Vergleichen.xlsm ' Tabelle Duplikate ' Modul mdl_04_03_KillDoubleRecords '===================================================================

Auswertungen Auswertungen

In diesem Rezept werden doppelt vorhandene Datensätze direkt aus dem markierten Bereich entfernt. An die Funktion KillDoubleRecords wird der zu überprüfende Bereich als Funktionsargument übergeben. Zurückgeliefert wird zum Schluss die Anzahl der tatsächlich gelöschten Datensätze.

Auswertungen

Die Vorgängerversionen von Excel 2007 bieten außer dem Spezialfilter keine einfache Lösung, um Duplikate zu löschen. Der Spezialfilter setzt für diesen Zweck aber eine Speicherung an eine andere Stelle voraus, was aber in den meisten Fällen nicht gewünscht ist.

Auswertungen

Doppelte Datensätze vor Excel 2007 löschen

Auswertungen

97

211

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 211 Dienstag, 4. Dezember 2007 1:42 13

Auswertungen

Listing 114

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 212 Dienstag, 4. Dezember 2007 1:42 13

212 >> Doppelte Datensätze vor Excel 2007 löschen Public Sub TestKillDoubleRecords() MsgBox KillDoubleRecords( _ Worksheets("Tabelle1").Range("A1:D10000") _ ), , "Gelöschte Datensätze" End Sub Public Dim Dim Dim Dim Dim

Function KillDoubleRecords(Range1 As Range) As Long rngField As Range lngCount As Long strKey As String myCol As New Collection i As Long

On Error Resume Next For i = Range1.Rows.Count To 1 Step -1 ' Alle Reihen des Bereiches nacheinander ' von unten nach oben durchlaufen strKey = "" For Each rngField In Range1.Rows(i).Cells ' Alle Zellen dieser Reihe nacheinander durchlaufen With rngField If .Value "" Then ' Eindeutigen Schlüssel aus allen Infos ' einer Zeile generieren strKey = strKey & CStr(.Value) End If End With Next rngField If strKey "" Then Err.Clear ' Fehlerspeicher löschen ' Element zur Collection hinzufügen myCol.Add strKey, "X" & strKey If Err.Number = 457 Then ' Wenn Fehler 457 auftritt, ist Datensatz bereits ' vorhanden. Da der Vergleich nur wie LIKE ' funktioniert (Groß-/Kleinschreibung wird ' nicht beachtet), noch mal kontrollieren. ' Option Compare auf Modulebene wird jetzt beachtet Listing 114 (Forts.)

98

Tabellenblätter vergleichen (Ausgabe in einem separaten Tabellenblatt)

Wird ein Datenbestand von mehreren Personen auf verschiedenen Rechnern bearbeitet und ist die Datenquelle, also hier die Excelmappe, auf jedem dieser Rechner eine Kopie des Originals, enthalten diese nach einer Bearbeitung unterschiedliche Datensätze. Sollen diese als Tabellenblätter vorliegenden Datenbanken anschließend zusammengeführt werden, muss irgendjemand letztendlich entscheiden, welche Datensätze verworfen und welche davon behalten werden. Dazu muss man aber erst einmal erkennen, welche Datensätze überhaupt verändert wurden. Ein einfacher 1-zu-1-Vergleich jeder Zeile des einen Blattes mit der gleichen der anderen ist dabei aber auch nicht besonders ratsam, da bereits das Löschen oder Einfügen einer Zeile in einem dieser Blätter heilloses Durcheinander bringen würde. In diesem Rezept wird die Position der abweichenden, also einmalig vorkommenden Datensätze in einem gesonderten Blatt (AUSGABE) ausgegeben, wobei aber unterschiedliche Positionen (Zeilennummer) in beiden Quelltabellen keine Rolle spielen. Gleiche Datensätze an unterschiedlichen Positionen werden also ohne Probleme erkannt. Die Zelladressen werden in der Ausgabetabelle zudem mit Hyperlinks versehen, so dass bequem per Mausklick in die jeweilige Zeile gesprungen werden kann.

Auswertungen Auswertungen Auswertungen

Listing 114 (Forts.)

Auswertungen

Next i KillDoubleRecords = lngCount ' Anzahl gelöschte zurückgeben End Function

Auswertungen

If strKey = myCol("X" & strKey) Then ' Aktuelle Zeile des Bereichs löschen Range1.Rows(i).Delete Shift:=xlUp ' Gelöschte Zeilen zählen lngCount = lngCount + 1 End If ElseIf Err.Number 0 Then MsgBox Err.Description End If End If

Auswertungen

213

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 213 Dienstag, 4. Dezember 2007 1:42 13

214 >> Tabellenblätter vergleichen (Ausgabe in einem separaten Tabellenblatt)

Abbildung 81: Unikate ausgeben

In der Prozedur TestCompare wird die Funktion FindUnique aufgerufen, welche die Collection mit den einmaligen Datensätzen als Funktionsergebnis zurückliefert. Als Funktionsargument übergibt man die zu vergleichenden Bereiche und das Zielblatt.

Auswertungen

Anschließend werden die Zellinhalte im Zielblatt gelöscht und jedes Element der zurückgelieferten Collection nacheinander durchlaufen. Jedes Element der Collection besteht aus einem Array mit zwei Elementen, welche wiederum die Zelladresse und den Datensatz als zusammengesetzte Zeichenkette enthalten. Beides wird zum Schluss im Zielblatt ausgegeben, die Adresse zusätzlich dazu benutzt, einen Hyperlink darauf zu erzeugen. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_01_Vergleichen.xlsm ' Tabelle Ausgabe ' Modul mdl_04_04_FindUni '===================================================================

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 214 Dienstag, 4. Dezember 2007 1:42 13

Listing 115

Sub TestCompare() rngSource1 As Range rngSource2 As Range wsDestSheet As Worksheet colResult As Collection varItem As Variant i As Long

' Bereich 1, der mit Bereich 2 verglichen werden soll Set rngSource1 = Worksheets("Duplikate").Range("A1:D10000") ' Bereich 2, der mit Bereich 1 verglichen werden soll Set rngSource2 = Worksheets("Orginale").Range("A1:D10000") ' Zielbereich (Ausgabe) Set wsDestSheet = Worksheets("Doppelte")

Auswertungen

Public Dim Dim Dim Dim Dim Dim

215

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 215 Dienstag, 4. Dezember 2007 1:42 13

' Hyperlink auf Datensatz erzeugen .Hyperlinks.Add _ Anchor:=.Cells(i, 1), _ Address:="", _ SubAddress:=varItem(1), _ TextToDisplay:=varItem(1) Next End With End Sub Listing 115 (Forts.)

In der Funktion FindUnique wird wie schon im vorherigen Rezept zum Vergleich der Datensätze eine Collection zweckentfremdet. In diesem Fall wird aber bei einem auftretenden Fehler 457 kein Datensatz gelöscht, sondern das Element mit dem entsprechenden Schlüssel wieder aus der Collection entfernt. Am Ende bleiben in der Collection also nur einmalig vorkommende Datensätze übrig.

Auswertungen Auswertungen

For Each varItem In colResult i = i + 1 .Cells(i, 1) = varItem(1) ' Ausgabe Adresse .Cells(i, 2) = varItem(2) ' Ausgabe Satzinhalt

Auswertungen

' Zielblatt säubern .Cells.Clear

Auswertungen

' Ausgeben ins Zielblatt With wsDestSheet

Auswertungen

' Ungleiche Datensätze ermitteln Set colResult = FindUnique(rngSource1, rngSource2)

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 216 Dienstag, 4. Dezember 2007 1:42 13

216 >> Tabellenblätter vergleichen (Ausgabe in einem separaten Tabellenblatt)

Wichtig ist aber, dass Duplikate in der gleichen Tabelle vorher entfernt werden (Rezept 96, 97). Würde man das nicht machen, wird beim zweiten Auftreten im gleichen Tabellenblatt das Element bereits aus der Collection entfernt und somit der gleiche Datensatz in der anderen Tabelle als Unikat erkannt. Beim Hinzufügen eines Elementes zur Collection wird als Elementinhalt ein Array mit der aktuellen Adresse und dem Datensatzinhalt hinterlegt. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_01_Vergleichen.xlsm ' Tabelle Ausgabe ' Modul mdl_04_04_FindUni '=================================================================== Private Function FindUnique(Range1 As Range, Range2 As Range) _ As Collection Dim rngRow As Range Dim rngField As Range Dim rngSource As Range Dim strKey As String Dim strAddress As String Dim myCol As New Collection Dim x(1 To 2) As String Dim i As Long On Error Resume Next For i = 1 To 2 ' Beide Bereiche durchlaufen If i = 1 Then Set rngSource = Range1 Else Set rngSource = Range2 End If For Each rngRow In rngSource.Rows ' Alle Reihen der Bereiche nacheinander strKey = "" strAddress = "" With rngRow.Cells(1) ' Adresse der ersten Zelle dieser Reihe ' extrahieren strAddress = .Worksheet.Name & "!" & .Address End With Listing 116

x(1) = strAddress x(2) = strKey ' Element zur Collection hinzufügen myCol.Add x, "X" & strKey If Err.Number = 457 Then ' Wenn Fehler 457 auftritt, ist Datensatz bereits ' vorhanden. Da der Vergleich nur wie LIKE ' funktioniert (Groß-/Kleinschreibung wird ' nicht beachtet), noch mal kontrollieren. ' Option Compare auf Modulebene wird jetzt beachtet If strKey = myCol("X" & strKey)(2) Then myCol.Remove "X" & strKey End If ElseIf Err.Number 0 Then MsgBox Err.Description End If End If Next rngRow Next i Set FindUnique = myCol End Function

Auswertungen Auswertungen

If strKey "" Then Err.Clear ' Fehlerspeicher löschen

Auswertungen

For Each rngField In rngRow.Cells ' Alle Zellen dieser Reihe nacheinander durchlaufen With rngField If .Value "" Then ' Eindeutigen Schlüssel aus allen Infos ' einer Zeile generieren strKey = strKey & CStr(.Value) End If End With Next rngField

Auswertungen

217

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 217 Dienstag, 4. Dezember 2007 1:42 13

Mehrfach vorkommende Zellinhalte markieren

In diesem Rezept wird gezeigt, wie man mehrfach vorkommende Zellinhalte eines Bereiches findet und diese Zellen mit einer ovalen Form hervorhebt. Gleichzeitig wird in die doppelte Zelle ein Kommentar hinzugefügt, der auf die erstmals vorkommende Zelle hinweist (Abbildung 82).

Auswertungen

99

Auswertungen

Listing 116 (Forts.)

218 >> Mehrfach vorkommende Zellinhalte markieren

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 218 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 82: Doppelt vorkommende Zellinhalte markieren

In der Prozedur MarcDoubleCells werden zu Beginn alle Formen (Shapes) des Tabellenblattes daraufhin untersucht, ob es sich dabei um den Typ msoShapeOval handelt. Ist das der Fall, wird diese Form gelöscht. Danach werden alle Kommentare des Tabellenblattes entfernt, die in den ersten 16 Zeichen die Zeichenkette »Erstes Vorkommen« enthalten. Dazu werden alle Zellen, die Kommentare enthalten, nacheinander durchlaufen. Das Codefragment Selection.SpecialCells(xlCellTypeComments)

liefert dabei einen Range des selektierten Bereiches, der ausschließlich die Zellen des entsprechenden Typs, in diesem Fall Zellen, mit Kommentaren enthält. Nachdem also die eventuell vorkommenden Rahmen und Kommentare einer vorherigen Duplikatsuche entfernt wurden, wird jede Zelle des selektierten Bereiches nacheinander durchlaufen. Jeder Zellinhalt wird in eine Zeichenkette umgewandelt und das Ergebnis als Schlüssel für das Einfügen in eine Collection verwendet. Als Elementinhalt wird die Adresse der aktuellen Zelle verwendet. Tritt ein Fehler 457 beim Hinzufügen auf, ist dieser Schlüssel bereits vorhanden. In diesem Fall wird die aktuelle Zelle markiert, indem ein rotes, ovales Shape erzeugt, in der Größe angepasst und so platziert wird, dass es genau in die Zelle passt. Anschließend wird nachgeschaut, ob sich vor der in diesem Element hinterlegten Adresse das Zeichen »–« befindet. Ist das nicht der Fall, wurde die Zelle, in der dieser Wert zum ersten Mal vorkam, noch nicht markiert. Nun wird an die in der Collection hinterlegte Zellposition ein blaues, ovales Shape gesetzt. Um beim nächsten Vorkommen nicht noch einmal die erste Zelle zu markieren, wird das Element aus der Collection gelöscht und ein neues mit dem gleichen Schlüssel hinzugefügt. Bei Collections ist ein nachträgliches Ändern der Werte leider nicht möglich. Vor die eigentliche Adresse wird zur Unterscheidung als Elementinhalt aber dieses Mal das Zeichen »–« gesetzt. Wird beim Überprüfen der Adresse an der ersten Position das Zeichen »–« entdeckt, muss dieses zum Bestimmen der tatsächlichen Adresse aus der Zeichenkette entfernt werden. Die Codezeile strAddress = Mid(strAddress, 2)

Public Sub MarcDoubleCells() Dim colX As New Collection Dim rngX As Range Dim wsSheet As Worksheet Dim objShape As Shape Dim strAddress As String On Error Resume Next ' Objektvariable des selektierten Bereiches erzeugen Set wsSheet = Selection.Cells(1).Worksheet For Each objShape In wsSheet.Shapes ' Alle Shapes des Tabellenblattes durchlaufen If objShape.AutoShapeType = msoShapeOval Then ' Shapes vom Typ msoShapeOval löschen objShape.Delete End If Next objShape For Each rngX In Selection.SpecialCells(xlCellTypeComments) ' Alle Zellen mit Kommentaren durchlaufen If Left(rngX.Comment.Text, 16) = "Erstes Vorkommen" Then ' Kommentar löschen rngX.Comment.Delete End If Next

Auswertungen Auswertungen

'=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_01_Vergleichen.xlsm ' Tabelle Duplikate ' Modul mdl_04_05_Marc '===================================================================

Auswertungen

erledigt diese Aufgabe, das heißt, die Variable strAddress enthält danach die Adresse der Zelle, an der dieser Wert zum ersten Mal auftrat. In die gerade aktuelle Zelle wird nun noch ein Kommentar eingefügt, der auf die Zelladresse des ersten Vorkommens hinweist.

Auswertungen

219

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 219 Dienstag, 4. Dezember 2007 1:42 13

If rngX.Value "" Then Err.Clear ' Fehlerspeicher löschen

Auswertungen

For Each rngX In Selection

Listing 117

Auswertungen

' Überprüfen, ob sich Zellinhalt als Schlüssel ' in die Collection einfügen lässt

220 >> Mehrfach vorkommende Zellinhalte markieren colX.Add rngX.Address(0, 0), "X" & rngX.Value If Err.Number = 457 Then ' Wenn Fehler 457 auftritt, ist Zellinhalt bereits ' vorhanden. Da der Vergleich nur wie LIKE funktioniert, ' wird z.B. Groß-/Kleinschreibung nicht beachtet With wsSheet ' Ovalen Kringel hinzufügen With .Shapes.AddShape(msoShapeOval, _ rngX.Left, _ rngX.Top, _ rngX.Width, _ rngX.Height) .Fill.Visible = msoFalse .Line.ForeColor.SchemeColor = 10 End With ' Adresse auslesen strAddress = colX("X" & rngX.Value) If Left(strAddress, 1) "-" Then ' Ovalen Kringel zum ersten Vorkommen hinzufügen With .Shapes.AddShape(msoShapeOval, _ .Range(strAddress).Left, _ .Range(strAddress).Top, _ .Range(strAddress).Width, _ .Range(strAddress).Height) .Fill.Visible = msoFalse .Line.ForeColor.SchemeColor = 12 End With

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 220 Dienstag, 4. Dezember 2007 1:42 13

' Item mit Adresse löschen colX.Remove "X" & rngX.Value ' Ein "-" vor die Adresse, damit beim nochmaligen ' Vorkommen erkannt wird, dass in erster Zelle ' bereits ein Shape eingefügt wurde colX.Add "-" & strAddress, "X" & rngX.Value Else ' "-" aus der Adresse entfernen strAddress = Mid(strAddress, 2) Listing 117 (Forts.)

221

End If ' Kommentar mit Hinweis auf erstes Vorkommen rngX.AddComment "Erstes Vorkommen" & vbLf & _ "Zelle : " & strAddress End With ' wsSheet End If ' Err.Number = 457

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 221 Dienstag, 4. Dezember 2007 1:42 13

Next rngX End Sub

Auswertungen

End If ' rngX.Value ""

100 Formeln eines Tabellenblattes ausgeben

Auswertungen

Auswertungen

Auswertungen

Die Formeln eines Tabellenblattes lassen sich mit der Tastenfolge (Strg) + (#) sichtbar machen und mit derselben Tastenfolge auch wieder ausblenden. Das Gleiche erreicht man, indem man auf der Registerkarte FORMELN das Icon mit der Bezeichnung FORMELN ANZEIGEN anklickt (Abbildung 83).

Auswertungen

Listing 117 (Forts.)

Wenn ein Tabellenblatt viele Formeln enthält, kann das Ganze aber sehr leicht unübersichtlich werden, erschwerend kommt noch hinzu, dass man nicht gleichzeitig

Auswertungen

Abbildung 83: Formeln ein-/ausblenden

222 >> Formeln eines Tabellenblattes ausgeben

den berechneten Wert und die Formeln sehen kann. Möchte man außerdem noch die direkten Vorgängerzellen anzeigen, erkennt man durch die eingeblendeten Pfeile noch weniger. Es ist daher hilfreich, wenn man die in einem solchen Tabellenblatt enthaltenen Formeln in einem separaten Tabellenblatt ausgeben kann. In diesem Rezept wird vorgestellt, wie die in einem Blatt enthaltenen Formeln ausgelesen und die direkten Vorgängerzellen ermittelt werden. Die Ergebnisse werden anschließend im Blatt FORMELAUSGABE ausgegeben (Abbildung 84).

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 222 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 84: Ausgabe der Formeln auf einem gesonderten Blatt

Die Prozedur FindFormulars ist dafür da, die Formelzellen eines Blattes nacheinander zu durchlaufen, mittels der benutzerdefinierten Funktion GetDirectPrecedents die direkten Vorgängerzellen zu ermitteln und das Ergebnis im Blatt FORMELAUSGABE auszugeben. Die SpecialCells-Methode liefert zusammen mit der als ersten Parameter übergebenen vordefinierten Konstante xlCellTypeFormulas einen Bereich, der ausschließlich Formelzellen enthält und der der Variablen rngFormulars zugewiesen wird. Danach wird das Zielblatt leer gemacht und es werden die Spaltenüberschriften eingetragen. Besitzt das auszuwertende Blatt keine Formelzellen, wird die Prozedur an dieser Stelle verlassen. Anschließend werden in der For Each ... Next-Schleife nacheinander alle Formelzellen angesprochen. Die Adresse der aktuellen Formelzelle, welche als Range in der Variablen rngCell steckt, wird zusammen mit einem Hyperlink in die Spalte A eingetragen. In Spalte B kommt die Formel als Text und in Spalte C der berechnete Wert dieser Formel.

'=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_02_GetFormulas.xlsm ' Tabelle Formelausgabe ' Modul mdl_04_06_Formulars '=================================================================== Public Dim Dim Dim Dim Dim Dim

Sub FindFormulars() rngFormulars As rngCell As varErg As strHyperlink As i As k As

Range Range Variant String Long Long

On Error Resume Next

Auswertungen

223

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 223 Dienstag, 4. Dezember 2007 1:42 13

' Ausgabe Zellüberschriften .Cells.Clear i = 1 .Rows(i).Font.Bold = True .Cells(i, 1).Value = "Zelladresse" .Cells(i, 2).Value = "Formeltext" .Cells(i, 3).Value = "Formelwert" .Cells(i, 4).Value = "Vorgängerzellen"

Auswertungen

With Worksheets("Formelausgabe") ' Ausgabetabelle

Auswertungen

Set rngFormulars = Worksheets("Tabelle1").Cells.SpecialCells( _ xlCellTypeFormulas)

' Adresse der Formel eintragen .Cells(i, 1).Value = strHyperlink ' Hyperlink auf Formelzelle erzeugen .Hyperlinks.Add _ Anchor:=.Cells(i, 1), _ Listing 118

Auswertungen

i = i + 1 strHyperlink = rngCell.Worksheet.Name & "!" & _ rngCell.Address(0, 0)

Auswertungen

For Each rngCell In rngFormulars ' Alle Zellen mit Formel durchlaufen

Auswertungen

' Keine Formeln, beenden If rngFormulars.Count = 0 Then Exit Sub

Auswertungen

2471_Excel-VBA.book Seite 224 Dienstag, 4. Dezember 2007 1:42 13

224 >> Formeln eines Tabellenblattes ausgeben Address:="", _ SubAddress:=strHyperlink

Auswertungen

' Formel ausgeben .Cells(i, 2).Value = "'" & rngCell.FormulaLocal ' Formelwert ausgeben .Cells(i, 3).Value = rngCell.Value

Auswertungen

' Vorgänger extrahieren varErg = GetDirectPrecedents(rngCell) If IsArray(varErg) Then ' Vorgänger existieren For k = LBound(varErg) To UBound(varErg) ' Alle Vorgänger durchlaufen

Auswertungen

'Vorgängeradresse ausgeben .Cells(i, k + 3).Value = varErg(k)

Auswertungen

' Hyperlink auf Vorgänger erzeugen .Hyperlinks.Add _ Anchor:=.Cells(i, k + 3), _ Address:="", _ SubAddress:=varErg(k), _ TextToDisplay:=varErg(k) Next k End If

Auswertungen

Next rngCell End With End Sub

Auswertungen

Auswertungen

Listing 118 (Forts.)

Die Funktion GetDirectPrecedents liefert danach die Adressen der Vorgängerzellen als Array. Ihr wird dazu als Funktionsargument die aktuelle Formelzelle übergeben. Die Elemente dieses zurückgelieferten Arrays werden ausgelesen und ab Spalte D in das Zielblatt eingetragen. Zusätzlich werden die Einträge noch mit einem Hyperlink versehen. Alle Werte einer Zeile gehören dabei zu der Formel, deren Adresse in Spalte A steht. Innerhalb der Funktion GetDirectPrecedents wird erst einmal nachgeschaut, ob die Formel ein Ausrufezeichen enthält. Ist das der Fall, besteht die Möglichkeit, dass sich

Die zwei Bedingungen, das Anführungs- und das Ausrufezeichen, werden benötigt, um zu vermeiden, dass ein Ausrufezeichen in einer Zeichenfolge fälschlicherweise als Zellbezug gehalten wird. Danach kann man die Eigenschaft DirectPrecedents der Zelle benutzen, um die direkten Vorgängerzellen auf dem gleichen Blatt zu bekommen. Die Adressen dieser Zellen werden mit dem Tabellenblattnamen zu einem vollständigen Bezug zusammengesetzt, also Blattname, das Ausrufezeichen und die Adresse. Dieser Bezug wird wiederum in dem Array varErg als Element gespeichert Schließlich wird das Array varErg als Funktionsergebnis zurückgegeben. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_02_GetFormulas.xlsm ' Tabelle Formelausgabe ' Modul mdl_04_06_Formulars '=================================================================== Function GetDirectPrecedents(rngFormula As Range) As Variant Dim varDummy As Variant Dim avarReplace As Variant Dim varErg As Variant Dim strErg As String Dim strWSName As String Dim i As Long Dim k As Long Dim rngX As Range Dim rngY As Range

Auswertungen Auswertungen

Anschließend wird mit der Split-Funktion die Zeichenkette in ein eindimensionales Array umgewandelt, wobei als DELIMITER (Zeichenfolge, welche die Trennstellen angibt) die fünf Pluszeichen dienen. Das Element dieses Arrays, welches kein Anführungszeichen und zusätzlich ein Ausrufezeichen enthält, wird als Zellbezug auf ein anderes Blatt interpretiert und in dem Array varErg als Element gespeichert.

Auswertungen

Um dennoch an solch eine Adresse zu kommen, muss man etwas mehr Aufwand betreiben. Erst einmal werden die vorhandenen Operatoren im Formeltext durch eine möglichst eindeutige Zeichenfolge ersetzt. Hier wurden fünf Pluszeichen verwendet, normalerweise dürfte diese Zeichenfolge außer in Zeichenketten im Formeltext nicht mehr vorkommen.

Auswertungen

eine direkte Vorgängerzelle auf ein anderes Blatt bezieht. Die Eigenschaft DirectPrecedents einer Zelle liefert diese Vorgängerzelle aber leider nicht, da die DirectPrecedents-Eigenschaft nur für das gleiche Blatt funktioniert und keine REMOTEVerweise nachverfolgen kann.

Auswertungen

225

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 225 Dienstag, 4. Dezember 2007 1:42 13

Listing 119

Auswertungen

On Error Resume Next

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 226 Dienstag, 4. Dezember 2007 1:42 13

226 >> Formeln eines Tabellenblattes ausgeben With rngFormula strErg = .Formula strWSName = .Worksheet.Name If InStr(strErg, "!") Then ' Zellbezug auf andere Tabelle möglich ' Alle Operatoren durch Zeichenfolge "+++++" ersetzen avarReplace = Array("+", "-", "*", "/", "%", "&", _ "^", "", ">=", "", " 0 Then

Auswertungen

If Err.Number = 0 Then

Listing 122 (Forts.)

Auswertungen

objDestSheet.Cells(m, 3) = "'" & True

Auswertungen

2471_Excel-VBA.book Seite 238 Dienstag, 4. Dezember 2007 1:42 13

238 >> Bedingte Formatierung End If End If

Auswertungen

End If Case xlUniqueValues ' Unikate oder Duplikate

Auswertungen

Err.Clear ' Bezieht sich auf Set rngList = .AppliesTo If Err.Number = 0 Then

Auswertungen

' Berechnen, wie oft der Wert im ' Bereich vorkommt Select Case WorksheetFunction.CountIf( _ rngList, varValue) Case 1 ' Einmaliges Vorkommen If .DupeUnique = xlUnique Then objDestSheet.Cells(m, 3) = "'" & True objDestSheet.Cells(m,34) = "'" & True End If

Auswertungen

Case Is > 1 ' Mehrmaliges Vorkommen If .DupeUnique = xlDuplicate Then objDestSheet.Cells(m, 3) = "'" & True objDestSheet.Cells(m, 35)= "'" & True End If End Select

Auswertungen

End If Case xlTextString objDestSheet.Cells(m, 3) = "'" & _ Evaluate(strDummy)

Auswertungen

Auswertungen

Case xlColorScale ' Eigenschaften Farbskala objDestSheet.Cells(m, 37) = "'" & True ' Array mit den Eigenschaften holen varColorScale = GetColorScaleInformation( _ objCondition) Listing 122 (Forts.)

239 objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m,

38) 39) 40) 41) 42) 43) 44) 45) 46)

= = = = = = = = =

varColorScale(1, varColorScale(2, varColorScale(3, varColorScale(4, varColorScale(5, varColorScale(6, varColorScale(7, varColorScale(8, varColorScale(9,

= = = = = =

"'" & True .BarColor.Color .MaxPoint.Value .MinPoint.Value .PercentMax .PercentMin

2) 2) 2) 2) 2) 2) 2) 2) 2)

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 239 Dienstag, 4. Dezember 2007 1:42 13

Case xlTop10 ' Top Ten objDestSheet.Cells(m, 53) = "'" & True objDestSheet.Cells(m, 54) = .Rank ' Den Typ in den Konstantennamen übersetzen objDestSheet.Cells(m, 55) = _ GetTopBottomTypeString(.TopBottom) objDestSheet.Cells(m, 56) = .Percent Case xlIconSets 'Icons

Auswertungen

47) 48) 49) 50) 51) 52)

Auswertungen

objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m,

Auswertungen

Case xlDatabar ' Datenbalken

objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m, objDestSheet.Cells(m,

65) 66) 67) 68)

= = = =

.IconSet.Count .ShowIconOnly .ReverseOrder .IconCriteria.Count

For k = 0 To .IconCriteria.Count - 1

Auswertungen

' Die ID in den Konstantennamen übersetzen objDestSheet.Cells(m, 64) = _ GetIconSetIDString(.IconSet.ID)

Auswertungen

objDestSheet.Cells(m, 63) = "'" & True

Listing 122 (Forts.)

Auswertungen

'Die Typ-ID in den Konstantennamen übersetzen

240 >> Bedingte Formatierung objDestSheet.Cells(m, 69 + k * 3) = _ GetIconSetTypeString( _ .IconCriteria(k + 1).Type) ' Operator übersetzen objDestSheet.Cells(m, 70 + k * 3) = _ GetOperatorTypeString( _ .IconCriteria(k + 1).Operator)

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 240 Dienstag, 4. Dezember 2007 1:42 13

Auswertungen

objDestSheet.Cells(m, 71 + k * 3) = _ .IconCriteria(k + 1).Value Next Case xlBlanksCondition ' Leere Zellen

Auswertungen

objDestSheet.Cells(m, 57) = "'" & True objDestSheet.Cells(m, 3) = "'" & _ Evaluate(strDummy) Case xlNoBlanksCondition ' Nichtleere Zellen objDestSheet.Cells(m, 58) = "'" & True objDestSheet.Cells(m, 3) = "'" & _ Evaluate(strDummy)

Auswertungen

Case xlTimePeriod ' Zeitbereich objDestSheet.Cells(m, 3) = "'" & _ Evaluate(strDummy) Case xlErrorsCondition ' Fehlerwerte

Auswertungen

objDestSheet.Cells(m, 59) = "'" & True objDestSheet.Cells(m, 3) = "'" & _ Evaluate(strDummy) Case xlNoErrorsCondition ' Keine Fehlerwerte

Auswertungen

objDestSheet.Cells(m, 60) = "'" & True objDestSheet.Cells(m, 3) = "'" & _ Evaluate(strDummy) Case xlAboveAverageCondition ' Durchschnitt

Auswertungen

objDestSheet.Cells(m, 61) = "'" & True objDestSheet.Cells(m, 62) = _ Listing 122 (Forts.)

>> Auswertungen

241 GetAboveBelowTypeString(.AboveBelow)

End Select

Auswertungen

2471_Excel-VBA.book Seite 241 Dienstag, 4. Dezember 2007 1:42 13

Next objCondition End With

Auswertungen

End With

Zuerst wird ein Variantarray angelegt, welches die Informationen einer Dreifarbenskala aufnehmen kann. Zu speichern sind zwei mal neun Werte und hinzu kommt noch der Beschreibungstext. Für jede Farbe werden drei Informationen ausgelesen. Wie viel Farben überhaupt gesetzt wurden, kann man dabei der Eigenschaft ColorScaleCriteria.Count entnehmen. Die möglichen Informationen für das erste Farbkriterium sind der Minimumwert, die zugehörige Farbe und der zugehörige Typ. Beim zweiten Farbkriterium und einer Zweifarbenskala sind es der Maximalwert, die zugehörige Farbe und der Typ, bei einer Dreifarbenskala der mittlere Wert mit den entsprechenden Farb- und Typinformationen. Das dritte Kriterium bleibt bei einer Zweifarbenskala leer, bei einer Dreifarbenskala werden die Informationen für das Maximum darin gespeichert. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_03_FormatConditions.xlsm ' Tabelle Ausgabe ' Modul mdl_04_07_FormatCondition '=================================================================== Private Function GetColorScaleInformation( _ objCondition As Object _ ) As Variant Dim lngCount As Long Listing 123

Auswertungen

Die Funktion GetColorScaleInformation liest die Farbskaleninformationen aus und gibt ein Array mit den einzelnen Informationen zurück.

Auswertungen

Listing 122 (Forts.)

Auswertungen

End Sub

Auswertungen

MsgBox "Alle bedingten Formatierungen ausgelesen"

Auswertungen

Application.ScreenUpdating = True

Auswertungen

Next rngCell

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 242 Dienstag, 4. Dezember 2007 1:42 13

242 >> Bedingte Formatierung Dim avarInfo Dim varCriteria

As Variant As Object

' Liest die Farbskaleninformationen aus ReDim avarInfo(1 To 9, 1 To 2) With objCondition lngCount = .ColorScaleCriteria.Count For Each varCriteria In .ColorScaleCriteria ' Alle Kriterien der Farbskala durchlaufen With varCriteria If .Index = 1 Then avarInfo(1, 1) = "Farbtabelle Min Farbe" avarInfo(1, 2) = .FormatColor.Color avarInfo(2, 1) = "Farbtabelle Min Wert" avarInfo(2, 2) = .Value avarInfo(3, 1) = "Farbtabelle Min Typ" avarInfo(3, 2) = GetColorScaleTypeString(.Type) End If If lngCount = 2 And .Index = 2 Then ' Zweifarbenskala avarInfo(7, 1) = "Farbtabelle Max Farbe" avarInfo(7, 2) = .FormatColor.Color avarInfo(8, 1) = "Farbtabelle Max Wert" avarInfo(8, 2) = .Value avarInfo(9, 1) = "Farbtabelle Max Typ" avarInfo(9, 2) = GetColorScaleTypeString(.Type) End If If lngCount = 3 And .Index = 2 Then ' Dreifarbenskala avarInfo(4, 1) = "Farbtabelle Mid Farbe" avarInfo(4, 2) = .FormatColor.Color avarInfo(5, 1) = "Farbtabelle Mid Wert" avarInfo(5, 2) = .Value avarInfo(6, 1) = "Farbtabelle Mid Typ" avarInfo(6, 2) = GetColorScaleTypeString(.Type) End If If lngCount = 3 And .Index = 3 Then ' Dreifarbenskala avarInfo(7, 1) = "Farbtabelle Max Farbe" avarInfo(7, 2) = .FormatColor.Color avarInfo(8, 1) = "Farbtabelle Max Wert" avarInfo(8, 2) = .Value avarInfo(9, 1) = "Farbtabelle Max Typ" avarInfo(9, 2) = GetColorScaleTypeString(.Type) End If Listing 123 (Forts.)

Listing 123 (Forts.)

Die Funktion IsCellValueTrue ermittelt den Wahrheitswert der übergebenen Regel. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_03_FormatConditions.xlsm ' Tabelle Ausgabe ' Modul mdl_04_07_FormatCondition '=================================================================== Private Function IsCellValueTrue( _ objCondition As Object _ ) As Boolean Dim varFormula1 As Variant Dim varFormula2 As Variant Dim varValue As Variant

Auswertungen

End With Next End With GetColorScaleInformation = avarInfo End Function

Auswertungen

243

Auswertungen

>> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 243 Dienstag, 4. Dezember 2007 1:42 13

Err.Clear ' Wert 1 der Bedingung auslesen varFormula1 = Range(.Formula1).Value ' Kein Bezug, die Formel selbst ist der Wert If Err.Number 0 Then varFormula1 = .Formula1 varFormula1 = CDbl(varFormula1) Err.Clear ' Wert 2 der Bedingung auslesen varFormula2 = Range(.Formula2).Value ' Kein Bezug, die Formel selbst ist der Wert If Err.Number 0 Then varFormula2 = .Formula2 varFormula2 = CDbl(varFormula2)

Auswertungen

' Zellwert auslesen varValue = .Parent.Value

Auswertungen

With objCondition ' aktuelle Bedingung

Auswertungen

On Error Resume Next

Listing 124

Auswertungen

varFormula1 = Replace(varFormula1, "=", "") varFormula2 = Replace(varFormula2, "=", "")

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 244 Dienstag, 4. Dezember 2007 1:42 13

244 >> Bedingte Formatierung varFormula1 varFormula2 varFormula1 varFormula2

Replace(varFormula1, """", "") Replace(varFormula2, """", "") CDbl(varFormula1) CDbl(varFormula2)

Select Case .Operator Case xlBetween ' Zwischen zwei Werten If (varValue >= varFormula1) And _ (varValue varFormula1 Then _ IsCellValueTrue = True Case xlLess ' Kleiner If varValue < varFormula1 Then _ IsCellValueTrue = True Case xlGreaterEqual ' Größer oder gleich If varValue >= varFormula1 Then _ IsCellValueTrue = True Case xlLessEqual ' Kleiner oder gleich If varValue > Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 245 Dienstag, 4. Dezember 2007 1:42 13

246 >> Autofilter

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 246 Dienstag, 4. Dezember 2007 1:42 13

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Abbildung 87: Filtermöglichkeiten

Unter VBA können verschiedene vordefinierte Operatoren eingesetzt werden, wie beispielsweise die oberen und unteren 10 Werte/Prozent der Werte, oder man kann Vergleichsoperatoren im Kriteriumstext direkt verwenden. Für jede Spalte kann man zwei Kriterien logisch miteinander verknüpfen. Nachfolgend einige Operatoren, die direkt zur Filterung oder zur Verknüpfung zweier Kriterien herangezogen werden können. Konstante

Index

Beschreibung

xlAnd

1

Und

xlOr

2

Oder

xlTop10Items

3

Die obersten x Elemente

xlTop10Percent

5

Die untersten x Prozent

xlBottom10Items

4

Die untersten x Elemente

xlBottom10Percent

6

Die untersten x Prozent

xlFilterCellColor

8

Hintergrundfarbe der Zelle

xlFilterFontColor

9

Textfarbe

xlFilterAutomaticFontColor

13

Textfarbe »Automatisch«

xlFilterAboveAverage

33

Werte über dem Mittelwert

xlFilterBelowAverage

34

Werte unter dem Mittelwert

xlFilterDynamic

11

Dynamisch in Verbindung mit anderen Kriterien

Tabelle 20: Konstanten für den Operator des Autofilters



entspricht nicht

>

ist größer als

>=

ist größer oder gleich


Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 247 Dienstag, 4. Dezember 2007 1:42 13

Auswertungen

Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 248 Dienstag, 4. Dezember 2007 1:42 13

248 >> Autofilter Private Sub myFilter End Sub Private Sub myFilter End Sub Private Sub myFilter End Sub Private Sub myFilter End Sub

Opt1_Click()

opt2_Click()

opt3_Click()

opt4_Click()

Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address(0, 0) = "B2" Then chkAutofilter_Click End Sub

Auswertungen

Auswertungen

Auswertungen

Listing 125 (Forts.)

Wird die Ereignisprozedur chkAutofilter_Click aufgerufen oder ausgelöst, ermittelt man, ob der Autofilter gesetzt oder nicht gesetzt ist. Die AutoFilter-Eigenschaft des Tabellenblattes liefert bei gesetztem Autofilter ein Objekt, ansonsten wird ein Fehler ausgelöst, der aber durch die Fehlerbehandlung ignoriert wird. Je nachdem, ob das Kontrollkästchen gesetzt oder nicht gesetzt ist, blendet man den Autofilter ein oder aus. '=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_04_Filter.xlsm ' Tabelle Autofilter ' Modul Klassenmodul Autofilter '=================================================================== Private Sub chkAutofilter_Click() Dim objFilter As Object On Error Resume Next

Auswertungen

Set objFilter = Me.AutoFilter If chbAutofilter.Value Then If objFilter Is Nothing Then Me.Range("A7").AutoFilter myFilter

Auswertungen

Else Listing 126

>> Auswertungen

249

If Not (objFilter Is Nothing) Then Me.Range("A7").AutoFilter

Auswertungen

2471_Excel-VBA.book Seite 249 Dienstag, 4. Dezember 2007 1:42 13

Private Sub myFilter() Dim strFrom As String Dim strTo As String Dim strYear As String Dim strResult As String Dim rngTotal As Range On Error Resume Next If chkAutofilter.Value = False Then Exit Sub Set rngTotal = Me.Range("F8:F1000") strYear = CStr(Me.Range("B2")) If Opt1 Then strFrom = ">=01/01/" & strYear strTo = "=04/01/" & strYear Listing 127

Auswertungen Auswertungen

'=================================================================== ' Auf CD Buchdaten\Beispiele\04_Auswertung\ ' Dateiname 04_04_Filter.xlsm ' Tabelle Autofilter ' Modul Klassenmodul Autofilter '===================================================================

Auswertungen

Anschließend werden die beiden Kriterien mir dem logischen Operator xlAnd verknüpft und auf das erste Feld des Autofilters angewendet. Schließlich wird noch die Tabellenfunktion Teilergebnis verwendet, um einige Werte der Tabelle wie die Summe, den Min- und Maxwert, die Anzahl und den Mittelwert der verbleibenden Datensätze zu ermitteln und in einer Meldungsbox auszugeben.

Auswertungen

Innerhalb der Prozedur myFilter ermittelt man, ob das Kontrollkästchen gesetzt ist, ist das nicht der Fall, wird die Prozedur umgehend verlassen. Im weiteren Verlauf werden mit Hilfe des Zellinhaltes von B2 und dem aktuell gesetzten Optionsschaltfeld die Variablen strFrom und strTo mit dem Anfangs- und Enddatum in englischer Notation gefüllt. Zusätzlich werden noch die Operatoren GrößerGleich (>=) und KleinerGleich (> Autofilter strTo = "=07/01/" strTo = "=10/01/" strTo = "> Auswertungen

Auswertungen

2471_Excel-VBA.book Seite 279 Dienstag, 4. Dezember 2007 1:42 13

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Auswertungen

Listing 139 (Forts.)

2471_Excel-VBA.book Seite 280 Dienstag, 4. Dezember 2007 1:42 13

Die Steuerelemente aus der Werkzeugsammlung der Formulare werden im Kapitel »UserForm« anhand von einzelnen Rezepten ausführlich beschrieben.

Die Objekte der Steuerelemente können aus Textfeldern, Listenfeldern, Optionsfeldern, Befehlsschaltflächen und anderen Elementen bestehen. Steuerelemente stellen Benutzern Optionen, Auswahllisten oder Schaltflächen, auf die geklickt werden kann, zur Verfügung. Eine Übersicht aller Steuerelemente finden Sie in Tabelle 24 und Tabelle 25. Bis Excel 2003 befinden sich in der Liste der integrierten Symbolleisten im Menü ANSICHT | SYMBOLLEISTEN zwei Leisten mit Steuerelementen: 왘 Formular-Symbolleiste 왘 Steuerelement-Toolbox-Symbolleiste

FORMULAR-Steuerelemente sind kompatibel mit früheren Versionen von Excel (ab Excel Version 5.0) und können neben Tabellenblättern auch auf XLM-MAKROBLÄTTERN und DIAGRAMMBLÄTTERN verwendet werden. FORMULAR-Steuerelemente verfügen

Steuerelemente

In der heutigen VBA-Programmierung verwendet man meist die ACTIVEX-Steuerelemente. Sie können ActiveX-Steuerelemente verwenden, wenn Sie verschiedene Ereignisse steuern müssen, die eintreten, wenn das Steuerelement verwendet wird. Beispielsweise können Sie einem Arbeitsblatt ein LISTENFELD-Steuerelement hinzufügen und anschließend ein Makro für andere Vorgänge erstellen, in Abhängigkeit davon, welche Option der Benutzer aus der Liste auswählt.

Steuerelemente

Abbildung 100: Formular- und ActiveX-Steuerelemente in Excel 2007 verwalten

Steuerelemente

Steuerelemente

In Excel 2007 werden die FORMULAR- und ACTIVEX-Steuerelemente in der Gruppe STEUERELEMENTE auf der Registerkarte ENTWICKLERTOOLS verwaltet.

Steuerelemente

T ipp

Steuerelemente sind Grafikobjekte, die auf einem Excel-Arbeitsblatt oder einem Formular UserForm platziert werden können.

Steuerelemente

110 Einführung

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 281 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

282 >> Formular-Steuerelemente

nur über das Click-Ereignis, welches bei Klick darauf das zugewiesene Makro ausführt. Achtung

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 282 Dienstag, 4. Dezember 2007 1:42 13

In Diagrammblättern ist es nicht möglich, ACTIVEX-Steuerelemente aus der STEUERELEMENT-TOOLBOX-Symbolleiste anzuwenden. Verwenden Sie auf Diagrammblättern die Steuerelemente der FORMULAR-Symbolleiste.

Beide Arten von Steuerelementen werden auf die gleiche Weise in ein Tabellenblatt eingefügt. Klicken Sie mit der linken Maustaste in einer der beiden Leisten auf ein Steuerelement-Symbol und anschließend auf das Tabellenblatt. Excel erstellt daraufhin das Element an der markierten Zellposition in seiner Standardgröße. Wenn Sie einen Doppelklick auf ein Steuerelement in einer Symbolleiste ausführen, können mehrere gleiche Elemente nacheinander auf dem Tabellenblatt eingefügt werden, ohne das Symbol des einzufügenden Steuerelementes jedes Mal drücken zu müssen. Durch nochmaliges Klicken auf das Symbol oder Drücken der (Esc)-Taste wird der Einfügemodus wieder aufgehoben. Sie können aber auch nach der Auswahl auf der Symbolleiste das gewählte Element auf dem Tabellenblatt »aufziehen«, indem Sie die linke Maustaste gedrückt halten und durch die Mausbewegung einen Rahmen für die gewünschte Größe ziehen. Wenn Sie beim Aufziehen eines Steuerelementes die (Alt)-Taste gedrückt halten, wird das Objekt an den nächstliegenden Zellen ausgerichtet. Um zu ermitteln, ob ein Steuerelement ein ACTIVEX- oder ein FORMULAR-Steuerelement ist, klicken Sie mit der rechten Maustaste auf das Steuerelement. Wenn kein Kontextmenü angezeigt wird oder das Kontextmenü den Befehl EIGENSCHAFTEN enthält, dann handelt es sich um ein ACTIVEX-Steuerelement. Wenn das Kontextmenü den Befehl MAKRO ZUWEISEN enthält, handelt es sich um ein Steuerelement der Formularsymbolleiste.

111 Formular-Steuerelemente Sie können ein FORMULAR-Steuerelement verwenden, wenn Sie alle Makros für ein Formular aufzeichnen möchten, jedoch keinen Makrocode in VBA schreiben oder ändern möchten. FORMULAR-Steuerelemente lassen sich auch auf Diagrammblättern anwenden. Im Gegensatz zu den ACTIVEX-Steuerelementen verfügen diese nur über ein Ereignis. Bis einschließlich Excel 2003 lautete das Klick-Ereignis BeiKlick. In Excel 2007 wurde dieser Name in KlickenSieAuf geändert. Der Prozedurname eines Klick-Ereignisses für FORMULAR-Steuerelemente setzt sich aus dem Namen der Schaltfläche und dem Ereignisnamen zusammen. In Excel 2007 z. B. Sub Schaltfläche1_KlickenSieAuf()

FORMULAR-Steuerelemente können nicht zur Steuerung von anderen Ereignissen verwendet werden, wie sie bei ACTIVEX-Elementen zur Verfügung stehen. Darüber hi-

Icon

Name

Typ

Beschreibung

Schaltfläche

Buttons

Führt ein Makro aus, wenn daraufgeklickt wird

Kombinations- DropDowns feld KontrollCheckBoxes kästchen Drehfeld

Spinners

Listenfeld

ListBoxes

Optionsfeld

OptionButtons

Gruppenfeld

GroupBoxes

Bezeichnung

Labels

Bildlaufleiste

ScrollBars

Ein Dropdown-Listenfeld. Das im Listenfeld ausgewählte Element wird im Textfeld angezeigt. Aktiviert oder deaktiviert eine Option. Sie können mehrere Kontrollkästchen auf einem Blatt oder in einer Gruppe gleichzeitig aktivieren. Erhöht oder verringert einen Wert. Um den Wert zu erhöhen, klicken Sie auf den Aufwärtspfeil. Um den Wert zu verringern, klicken Sie auf den Abwärtspfeil. Zeigt eine Liste mit Elementen an Wählt eine Option aus einer Gruppe von Optionen aus, die in einem Gruppenfeld enthalten sind. Verwenden Sie Optionsfelder, um nur eine von verschiedenen Möglichkeiten zuzulassen. Fasst zusammengehörende Steuerelemente zusammen, wie z. B. Optionsfelder oder Kontrollkästchen Text, der Informationen zu einem Steuerelement, zum Arbeitsblatt oder zum Formular liefert Blättert durch einen Wertebereich, wenn Sie auf die Bildlaufpfeile klicken oder wenn Sie das Bildlauffeld ziehen. Sie können durch eine Seite mit Werten blättern, indem Sie auf eine Stelle zwischen dem Bildlauffeld und einem Bildlaufpfeil klicken.

Tabelle 24: Symbole und Funktionen der Formular-Steuerelemente

Steuerelemente Steuerelemente

Mit dem GRUPPENFELD gibt es auch eine interessante Funktion in dieser Gruppe, die sich nicht unter den ACTIVEX-Steuerelementen befindet. Nachfolgend ist eine Übersicht aller Symbole und Funktionen der FORMULAR-Symbolleiste aufgeführt.

Steuerelemente

Abbildung 101: Formular-Steuerelemente

Steuerelemente

In der Gruppe der FORMULAR-Steuerelemente befinden sich einige Schaltflächen, welche nicht in den neueren Excel-Versionen zur Verfügung stehen und entsprechend ausgegraut sind (siehe Abbildung 101).

Steuerelemente

naus können FORMULAR-Steuerelemente nicht verwendet werden, um Webskripts auf Webseiten auszuführen.

Steuerelemente

283

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 283 Dienstag, 4. Dezember 2007 1:42 13

284 >> Formular-Steuerelemente Icon

Name Textfeld

Kombinationsliste DropdownKombinationsfeld

Typ

Beschreibung Steht in Microsoft Excel-Arbeitsmappen nicht zur Verfügung. Dieses Steuerelement wird bereitgestellt, um es Ihnen zu ermöglichen, mit Dialogblättern zu arbeiten, die mit Excel Version 5.0 erstellt wurden. Steht in Microsoft Excel-Arbeitsmappen nicht zur Verfügung Steht in Microsoft Excel-Arbeitsmappen nicht zur Verfügung

Tabelle 24: Symbole und Funktionen der Formular-Steuerelemente (Forts.)

Sie können an ein FORMULAR-Steuerelement ein vorhandenes Makro über das Kontextmenü des Elementes mit dem Befehl MAKRO ZUWEISEN anbinden. Wenn ein Benutzer des Formulars auf das Steuerelement klickt, führt dieses das Makro aus. In vielen Rezepten dieses Buches werden Schaltflächen der FORMULAR-Steuerelemente verwendet, weil man diesen leicht eine bestehende Prozedur zuweisen kann und sie keine zusätzliche Ereignisprozedur im Tabellenblatt aufweisen müssen. Nachdem Sie ein neues FORMULAR-Steuerelement erstellt haben, wird anschließend automatisch der Dialog MAKRO ZUWEISEN angezeigt (siehe Abbildung 102). Hier können Sie entweder dem Objekt ein bestehendes Makro zuweisen oder über die Schaltfläche AUFZEICHNEN ein neues Makro erstellen.

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 284 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 102: Einer Schaltfläche ein Makro zuweisen

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_01_FormularControls.xlsm ' Tabelle Tabelle1 ' Modul mdl_01_AddFormularButton '=================================================================== Public Sub AddFormularButton() Dim objButton As Object With Range("G10:F11") Set objButton = ActiveSheet.Buttons.Add( _ Left:=.Left, Top:=.Top, _ Width:=.Width, Height:=.Height) End With With objButton .Name = "MyButton" Listing 140

Steuerelemente Steuerelemente

Die folgende Prozedur erstellt auf dem aktiven Tabellenblatt genau über dem Zellenbereich G10:F11 eine Schaltfläche. Um ein Steuerelement an einer festen Position auf dem Tabellenblatt zu erstellen, übergeben Sie den Left-, Top-, Width- und HeightEigenschaften feste Pixelwerte. Der Reihe nach legen diese Eigenschaften die Pixelwerte vom oberen und linken Bildschirmrand sowie die Breite und Höhe des Steuerelementes fest. Über die OnAction-Eigenschaft bestimmen Sie die Prozedur MyMacro, die ausgeführt wird, wenn der Anwender auf die Schaltfläche MyButton klickt. Wenn Sie die Prozedur mehrmals ausführen, wird jeweils die gleiche Schaltfläche mit gleich lautender Bezeichnung erstellt. Um andere Steuerelement-Typen der FORMULAR-Symbolleiste mit VBA zu erstellen, verwenden Sie den jeweiligen Typ aus der Übersichtstabelle Tabelle 24.

Steuerelemente

112 Formular-Schaltfläche erstellen

Steuerelemente

Die ActiveX-Steuerelemente der STEUERELEMENT-TOOLBOX-Symbolleiste – mit ihren programmierbaren Ereignissen und verbesserten Eigenschaften – haben in der heutigen VBA-Programmierung eine höhere Priorität als die FORMULARSteuerelemente. Deswegen beschränken wir uns bei den FORMULAR-Controls auf einige kurze Beispiele.

Steuerelemente

Hinweis

Die meisten Steuerelemente besitzen Eigenschaften, die Sie ändern können; Sie können bei Befehlsschaltflächen jedoch nur die Formatierungseigenschaften der Schaltfläche selbst und die Beschriftung ändern. Klicken Sie dazu das Steuerelement mit der rechten Maustaste an und wählen Sie im Kontextmenü den Eintrag STEUERELEMENT FORMATIEREN.

Steuerelemente

285

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 285 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 286 Dienstag, 4. Dezember 2007 1:42 13

286 >> Formular-Schaltfläche löschen .OnAction = "MyMacro" .Characters.Text = "Macro ausführen" .Characters.Font.Name = "Arial" .Characters.Font.Size = 12 End With End Sub Listing 140 (Forts.) '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_01_FormularControls.xlsm ' Modul mdl_01_AddFormularButton '=================================================================== Public Sub MyMacro() MsgBox "Hallo " & Application.UserName End Sub Listing 141

113 Formular-Schaltfläche löschen Um ein Steuerelement der FORMULAR-Symbolleiste zu löschen, verwenden Sie den Namen der Schaltfläche. Existiert die Schaltfläche im angegebenen Tabellenblatt nicht, gibt Excel eine Fehlermeldung aus. Dies könnten Sie mit einer vorangestellten Fehlerroutine verhindern. On Error Resume Next ActiveSheet.Shapes("MyButton").Delete

In der folgenden Prozedur werden alle Objekte mittels einer For Each...Next-Anweisung durchlaufen. Wenn ein Objekt den im Code angegebenen Namen aufweist, wird es gelöscht und die Schleife verlassen. Dadurch erübrigt sich eine vorgeschaltete Fehlerroutine. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_01_FormularControls.xlsm ' Modul mdl_02_DeleteFormularButton '=================================================================== Public Sub DeleteFormularButton() Dim shButton As Shape ' Alle Zeichnungsobjekte im aktiven Tabellenblatt durchlaufen For Each shButton In ActiveSheet.Shapes Listing 142

287

' Vergleich über Objektnamen If shButton.Name = "MyButton" Then ' Objekt löschen shButton.Delete ' Prozedur verlassen Exit For End If

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 287 Dienstag, 4. Dezember 2007 1:42 13

End Sub Listing 142 (Forts.)

Steuerelemente

Next shButton

' Meldung, ob Schaltfläche vorhanden und Befehl ausgeführt If Err.Number 0 Then ' Makrozuweisung hat Fehler hervorgerufen MsgBox "Die Schaltfläche 'MyButton' ist nicht vorhanden.", _ vbExclamation Else ' Makrozuweisung war erfolgreich MsgBox "Der Schaltfläche 'MyButton' wurde ein neues Makro zugewiesen.", _ vbInformation

Steuerelemente

Public Sub NewOnAction() ' Errorhandler, wenn Schaltfläche nicht vorhanden On Error Resume Next ActiveSheet.Shapes("MyButton").OnAction = "MyNewMacro"

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_01_FormularControls.xlsm ' Modul mdl_02_NewOnAction '===================================================================

Steuerelemente

Mit VBA können Sie einer bestehenden Schaltfläche leicht eine neue Prozedur zuweisen. In dem folgenden Beispiel wird der neu erstellten Schaltfläche MyButton im aktiven Tabellenblatt die Prozedur MyNewMacro zugewiesen. Diese wird anstelle der vorher zugewiesenen Prozedur MyMacro bei Klick auf die Schaltfläche ausgeführt.

Steuerelemente

114 Makro an Formular-Schaltfläche zuweisen

Listing 143

Steuerelemente

End If End Sub

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 288 Dienstag, 4. Dezember 2007 1:42 13

288 >> Steuerelement-Toolbox Public Sub MyNewMacro() MsgBox "Hallo Welt" End Sub Listing 143 (Forts.)

115 Steuerelement-Toolbox Bis einschließlich Excel 2003 ist die STEUERELEMENT-TOOLBOX eine Symbolleiste, die ACTIVEX-Steuerelemente zur Verfügung stellt.

Abbildung 103: Steuerelement-Toolbox-Symbolleiste in Excel 2003

In Excel 2007 werden die ACTIVEX-Steuerelemente in der Gruppe STEUERELEMENTE/ EINFÜGEN auf der Registerkarte ENTWICKLERTOOLS verwaltet.

Abbildung 104: ActiveX-Steuerelemente und Funktionen

ACTIVEX-Steuerelemente sind mit Steuerelementen vergleichbar, die in Programmiersprachen (z. B. Microsoft Visual Basic) verwendet werden. Hierbei handelt es sich um dieselben Steuerelemente, die Sie benutzerdefinierten Formularen im Visual Basic Editor hinzufügen können. Wenn Sie einem Arbeitsblatt ein ACTIVEX-Steuerelement hinzufügen, schreiben Sie Makrocode, der sich auf die ID-Nummer des Steuerelementes bezieht, und weisen nicht ein Makro zu, das ausgeführt werden soll, wenn auf das Steuerelement geklickt wird. Wenn ein Benutzer des Formulars das Steuerelement verwendet, wird der von Ihnen angegebene Code ausgeführt, um auftretende Ereignisse zu verarbeiten. Einige dieser Steuerelemente sind den Steuerelementen auf der FORMULAR-Symbolleiste ähnlich. Andere dagegen, wie beispielsweise Umschaltflächen und Bild-Steuerelemente, sind auf der FORMULAR-Symbolleiste nicht verfügbar. Die STEUERELEMENTTOOLBOX enthält zusätzlich angepasste ActiveX-Steuerelemente, die von anderen Programmen installiert werden, z. B. den Microsoft Webbrowser, der von Microsoft Internet Explorer installiert wird. Mit diesem Steuerelement können Sie zum Beispiel Webseiten, animierte *.gif-Dateien oder Excel Tabellenblätter anzeigen.

>> Steuerelemente

289

Nachfolgend eine Übersicht aller Symbole und Funktionen für ACTIVEX-Steuerelemente.

Eigenschaften

Zeigt das Eigenschaftsfenster des markierten Steuerelementes im Tabellenblatt an. Ändern der Eigenschaften der Websteuerelemente.

Code anzeigen

Zeigt das Codeblatt des aktiven Tabellenblattes im Visual-Basic-Editor an.

Befehlsschaltfläche

Forms.Command- Eine Schaltfläche, die eine Aktion initialisiert, Button.1 wenn darauf geklickt wird

Kombinationsfeld

Forms.ComboBox.1

Ein Textfeld mit einem DropDown-Listenfeld. Sie können in dem Feld entweder eine Auswahl in der Liste treffen oder Ihren eigenen Eintrag eingeben.

Kontrollkästchen

Forms.CheckBox.1

Eine Option, die Sie einschalten oder ausschalten können, indem Sie sie aktivieren oder deaktivieren. In einem Blatt können mehrere Kontrollfelder gleichzeitig aktiviert sein.

Listenfeld

Forms.ListBox.1

Ein Feld, das eine Liste mit Elementen enthält

Textfeld

Forms.TextBox.1

Ein Feld, in dem Text eingegeben werden kann

Bildlaufleiste

Forms.ScrollBar.1 Ein Steuerelement, das durch einen Wertebereich blättert, wenn Sie auf die Bildlaufpfeile klicken oder wenn Sie das Bildlauffeld ziehen. Sie können durch eine Seite mit Werten blättern, indem Sie auf eine Stelle zwischen dem Bildlauffeld und einem Bildlaufpfeil klicken.

Drehfeld

Forms.SpinButton.1

Eine Schaltfläche, die einer Zelle oder einem Textfeld zugeordnet werden kann. Um einen Wert zu erhöhen, klicken Sie auf den Aufwärtspfeil; um einen Wert zu verringern, klicken Sie auf den Abwärtspfeil.

Optionsfeld

Forms.OptionButton.1

Eine Schaltfläche, die zum Auswählen einer Option – aus einer Gruppe von Optionen gleichen GroupNamens – verwendet wird

Steuerelemente

Wechselt zwischen Formularentwurfsmodus, in dem Steuerelemente erstellt und bearbeitet werden können, und dem Anwendermodus.

Steuerelemente

Entwurfsmodus

Steuerelemente

Beschreibung

Steuerelemente

Typ / progID

Steuerelemente

Name

Steuerelemente

Icon

Steuerelemente

2471_Excel-VBA.book Seite 289 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Tabelle 25: Symbole und Funktionen der ActiveX-Steuerelemente

290 >> Steuerelement-Toolbox Icon

Name

Typ / progID

Beschreibung

Bezeichnung

Forms.Label.1

Text, der einem Arbeitsblatt oder Formular hinzugefügt wurde und Informationen zu einem Steuerelement oder zu dem Arbeitsblatt bzw. Formular enthält

Bild

Forms.Image.1

Ein Steuerelement, das ein Bild in einem Formular einbettet

Umschaltfläche

Forms.ToggleButton.1

Eine Schaltfläche, die nach dem Klicken darauf niedergedrückt bleibt und nach einem erneuten Klicken darauf wieder herausspringt

Weitere Steuerelemente

Eine Liste weiterer ACTIVEX-Steuerelemente

Tabelle 25: Symbole und Funktionen der ActiveX-Steuerelemente (Forts.)

ACTIVEX-Steuerelemente verfügen über Eigenschaften, die Sie im Eigenschaftsfenster des markierten Steuerelementes anpassen können (siehe Abbildung 105). Beispielsweise können Sie die Hintergrundfarbe des Elementes ändern oder die Darstellung des Mauszeigers festlegen, wenn ein Benutzer auf das Steuerelement zeigt.

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 290 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 105: Eigenschaftsfenster des aktiven Objektes

291

Klicken Sie im Eigenschaftsfenster auf der linken Seite eine Eigenschaft an und drücken Sie dann die Taste (F1). Daraufhin wird die Online-Hilfe zum markierten Thema angezeigt.

Wechseln Sie in der Excel-Umgebung im Tabellenblatt in den Entwurfsmodus und führen Sie einen Doppelklick auf ein Steuerelement aus. Daraufhin wird das Codeblatt der Tabelle mit dem Click-Ereignis des Steuerelementes angezeigt. Wenn noch kein Ereignis für dieses Steuerelement vorhanden war, wird die entsprechende Codeschablone erstellt.

Steuerelemente

Tip p

Abbildung 107: Ereignisprozeduren des ausgewählten Objektes

Steuerelemente

Steuerelemente

Nachdem Sie ein Objekt aus der Liste ausgewählt haben, stehen im rechten DropDown-Feld PROZEDUREN (siehe Abbildung 107) alle für dieses Objekt verfügbaren Ereignisprozeduren zur Auswahl. Klicken Sie auf einen Eintrag, damit die Codeschablone des Ereignisses mit allen benötigten Parametern im Codeblatt erstellt wird.

Steuerelemente

Abbildung 106: Objekte eines Tabellenblattes

Steuerelemente

Steuerelemente

Sie können Makros schreiben, die auf Ereignisse reagieren, die mit ACTIVEX-Steuerelementen verknüpft sind. Im Codeblatt der Tabelle, in welcher die Steuerelemente platziert sind, werden alle eingefügten Steuerelemente im linken DropDown-Feld OBJEKT (siehe Abbildung 106) angezeigt.

Steuerelemente

Tipp

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 291 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 292 Dienstag, 4. Dezember 2007 1:42 13

292 >> Steuerelemente erstellen

Der Unterschied zwischen einem CommandButton aus der STEUERELEMENT-TOOLBOX und einer BEFEHLSSCHALTFLÄCHE der FORMULAR-Symbolleiste liegt in erster Linie darin, dass Sie dem CommandButton direkt in den Ereignisprozeduren Code zuweisen können. Dieser wird bei verschiedenen auftretenden Ereignissen ausgeführt. Befehlsschaltflächen können nur Makros zugewiesen werden, die bei Klick auf die Schaltfläche aufgerufen werden. Zudem können CommandButtons aus der STEUERELEMENT-TOOLBOX mit farbiger Hintergrund-Fläche dargestellt werden, was bei den Formular-Befehlsschaltflächen nicht möglich ist.

Steuerelemente

ActiveSheet.OLEObjects.Add "Forms.ToggleButton.1"

Steuerelemente

Steuerelemente

Steuerelemente

Um auf einem Tabellenblatt ein ACTIVEX-Steuerelement zu erstellen, müssen Sie den programmtechnischen Bezeichner des Objekts, welcher über die ProgId-Eigenschaft festgelegt ist, an die Add-Methode des OLEObjects-Auflistungsobjekt übergeben. Folgende einfache Syntax erstellt im aktiven Tabellenblatt an der aktiven Zellposition eine Umschaltfläche. Die Bezeichner ProgId der weiteren Steuerelemente können Sie der Tabelle 25 entnehmen.

Steuerelemente

116 Steuerelemente erstellen

Viel übersichtlicher ist es, wenn Sie für die programmtechnischen Bezeichner als Konstanten am Anfang des Moduls (vor der ersten Prozedur) deklarieren. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle1 (AddControls) '=================================================================== Const Const Const Const Const Const Const Const Const Const Const

CHECKBOX COMBOBOX COMMANDBUTTON IMAGE LABEL LISTBOX OPTIONBUTTON SCROLLBAR SPINBUTTON TEXTBOX TOGGLEBUTTON

As As As As As As As As As As As

String String String String String String String String String String String

= = = = = = = = = = =

"Forms.CheckBox.1" "Forms.ComboBox.1" "Forms.CommandButton.1" "Forms.Image.1" "Forms.Label.1" "Forms.ListBox.1" "Forms.OptionButton.1" "Forms.ScrollBar.1" "Forms.SpinButton.1" "Forms.TextBox.1" "Forms.ToggleButton.1"

Listing 144

Diese Konstanten können Sie in dem Modul, in dem sie erstellt wurden, in allen Prozeduren in Vertretung der progID verwenden.

Steuerelemente

ActiveSheet.OLEObjects.Add TOGGLEBUTTON

Um in allen Modulen des VBA-Projektes auf diese Konstanten zuzugreifen, stellen Sie zusätzlich die Public-Anweisung vor die jeweilige Deklarierung.

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle1 (AddControls) '=================================================================== Private Sub CommandButton1_Click() Const cstrRange As String = "G3" Dim obj As OLEObject Dim objForm As MSForms.CHECKBOX With ActiveSheet Set obj = .OLEObjects.Add( _ ClassType:=CHECKBOX, _ Left:=Range(cstrRange).Left, _ Top:=Range(cstrRange).Top, _ Width:=Range(cstrRange).Width, _ Height:=Range(cstrRange).Height) Set objForm = obj.Object With objForm .Name = "TestCheckBox" & ActiveSheet.OLEObjects.Count .Caption = "MyCheckBox" .Enabled = True .GroupName = "MyGroup" .LinkedCell = Range(cstrRange).Offset(0, -1).Address .Value = True End With End With End Sub Listing 145

Steuerelemente Steuerelemente

Wenn Sie versuchen ein Steuerelement gleichen Namens zu erstellen, gibt Excel eine Fehlermeldung aus. Dies verhindern wir, indem wir über die Count-Eigenschaft die Anzahl der bereits vorhandenen Controls an den Namen des neu eingefügten Steuerelementes anhängen.

Steuerelemente

In dem folgenden With-Block werden verschiedene Eigenschaften der neuen CheckBox wie Name, Beschriftungstext etc. festgelegt.

Steuerelemente

In der folgenden Prozedur wird ein Kontrollkästchen im aktiven Tabellenblatt eingefügt und an die Zellposition der Zelle G3 angepasst. Dies erreichen Sie über die Left-, Top-, Width- und Height-Eigenschaften der Zelle G3, die auf das einzufügende Objekt übertragen wird. Anstelle der progID für Kontrollkästchen Forms.CheckBox.1 verwenden Sie die deklarierte Konstante CHECKBOX.

Steuerelemente

Public Const TOGGLEBUTTON = "Forms.ToggleButton.1"

Steuerelemente

293

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 293 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 294 Dienstag, 4. Dezember 2007 1:42 13

294 >> Steuerelemente löschen

117 Steuerelemente löschen Um ein bestimmtes Steuerelement Ihrer Tabelle zu löschen, verwenden Sie den Namen des zu löschenden Objektes. Für den Fall, dass das genannte Element nicht existiert, haben wir vor dem Löschvorgang die Fehlerroutine On Error Resume Next gesetzt. Es ist ebenso möglich, alle Steuerelemente in einer For Each...NextAnweisung zu durchlaufen und dabei die Namen der Elemente zu überprüfen. Eine Beispielprozedur dazu finden Sie in Rezept 118. Dadurch würde sich unsere vorangestellte Fehlerroutine erübrigen. Der Schaltfläche haben wir den Namen CmdCheckBox1Delete zugewiesen. Wenn Sie diese Schaltfläche anklicken, wird das hinterlegte gleichnamige Click-Ereignis aufgerufen. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle2 (DeleteControls) '=================================================================== Private Sub CmdCheckBox1Delete_Click() On Error Resume Next ActiveSheet.OLEObjects("CheckBox1").Delete End Sub Listing 146

118 Alle Steuerelemente löschen Mit einer einzigen Zeile ist es möglich alle Grafikobjekte, zu welchen auch die ACTIVEX-Steuerelemente zählen, zu löschen: ActiveSheet.DrawingObjects.Delete

Wenn Sie allerdings diesen Befehl über eine Schaltfläche auf dem Tabellenblatt ausführen, wird die aufrufende Schaltfläche ebenfalls gelöscht. Nachfolgende Prozedur löscht nur die Objekte, welche nicht vom Typ CommandButton sind. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle2 (DeleteControls) '=================================================================== Private Sub CmdDeleteAllControls_Click() Dim obj As OLEObject For Each obj In ActiveSheet.OLEObjects ' Controls löschen, die keine CommandButton sind Listing 147

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle2 (DeleteControls) '=================================================================== Private Sub CmdDeleteCheckBoxes_Click() Dim obj As OLEObject For Each obj In ActiveSheet.OLEObjects If obj.progID = " Forms.CheckBox.1" Then obj.Delete End If Next obj End Sub Listing 148

120 Fokus der Steuerelemente verwalten In der Microsoft Windows-Umgebung kann zu einem Zeitpunkt nur ein Objekt den Fokus besitzen. Zum Beispiel: 왘 ein einziges Fenster 왘 ein einziges Formular 왘 ein einziges Steuerelement 왘 eine Zelle/Zellenbereich Nur das Objekt, welches den Fokus besitzt, kann Mausklicks oder Tastatureingaben empfangen. Das aktive Objekt wird normalerweise durch eine hervorgehobene Überschrift oder Titelleiste angezeigt. Der Fokus kann vom Benutzer oder von der Anwendung gesetzt werden.

Steuerelemente Steuerelemente

Genauso, wie Sie beim Löschen von Steuerelementen einen Typ ausschließen, können Sie auch nur die Elemente eines bestimmten Typs löschen. Folgende Prozedur löscht im aktiven Tabellenblatt alle Steuerelemente vom Typ CheckBox.

Steuerelemente

119 Steuerelemente eines Typs löschen

Steuerelemente

Listing 147 (Forts.)

Steuerelemente

If obj.progID "Forms.CommandButton.1" Then obj.Delete End If Next obj End Sub

Steuerelemente

295

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 295 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

296 >> Wert in Kontrollkästchen (CheckBox) ändern

Wenn Sie auf ein Steuerelement klicken, erhält dieses standardmäßig den Fokus, bis Sie mit der Maus ein anderes Objekt oder Zelle anklicken. Dies erkennen Sie auch daran, dass es nicht möglich ist, sich mit der Tabulator- oder den Pfeiltasten auf dem Tabellenblatt von Zelle zu Zelle zu bewegen, wenn ein Objekt markiert ist. Auch die sonst übliche Adressanzeige im Namensfeld bleibt leer. Solange ein Steuerelement den Fokus hat, sind einige Menübefehle in Excel deaktiviert und können nicht angewählt werden. Ab Excel 2000 ist es aber möglich, mit VBA-Code dennoch Befehle auszuführen, welche über die Excel-Oberfläche nicht ausgeführt werden können. Der CommandButton der STEUERELEMENT-TOOLBOX besitzt als einziges Element die TakeFocusOnClick-Eigenschaft. Setzen Sie diese Eigenschaft auf False, damit nach dem Ausführen des hinterlegten Codes das vorher aktive Objekt wieder den Fokus erhält. Dies kann entweder eine Zelle oder ein anderes Steuerelement sein. Um bei den anderen Steuerelementen den Fokus nach Beendigung der aufgerufenen Ereignis-Prozedur an die Tabelle zurückzugeben, selektieren Sie die vorher aktive Zelle, bzw. Markierung. Die Activate- und Select-Methode sind dabei gleichwertig. Am Beispiel eines Kontrollkästchens verwenden Sie folgenden Code: '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle3 (TakeFocusOnClick) '=================================================================== Private Sub CheckBox2_Click() Selection.Activate End Sub Listing 149

H i n we i s

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 296 Dienstag, 4. Dezember 2007 1:42 13

Unter Excel 97 erhalten Sie einen Laufzeitfehler, wenn Sie versuchen auf deaktivierte Befehle zuzugreifen, wenn eine Befehlsschaltfläche den Fokus hat. Setzen Sie die TakeFocusOnClick-Eigenschaft des CommandButtons auf False, damit der Fehler abgefangen und der Befehl ausgeführt wird.

121 Wert in Kontrollkästchen (CheckBox) ändern Ein Kontrollkästchen CheckBox dient dazu, eine angegebene Option als aktiviert, bzw. deaktiviert zu kennzeichnen. Bei jedem Klick auf das Kontrollkästchen wird der Status zwischen aktiviert und deaktiviert gewechselt; indem das Kontrollkästchen einen Haken, bzw. keinen Haken aufweist. Die LinkedCell-Eigenschaft legt die verknüpfte Zelle des Steuerelementes fest. Der aktuelle Zustand der CheckBox wird in der angegebenen verknüpften Zelle als boolescher Wert in Form von Wahr oder Falsch angezeigt. Umgekehrt können Sie in der verknüpften Zelle den Wert ändern, um die Anzeige in

Tipp

der CheckBox zu ändern. Geben Sie in der verknüpften Zelle für eine aktivierte CheckBox den Wert Wahr bzw. die Zahl 1 ein. False, bzw. 0 bewirkt einen deaktivierten Status des Kontrollkästchens. Den Wert eines Kontrollkästchens können Sie auch über die Leertaste Ihrer Tastatur ändern. Jedes Drücken der (Leertaste) bewirkt einen Wechsel zwischen Wahr und Falsch. Dies wird optisch durch einen Haken für ein aktiviertes, bzw. keinen Haken für ein deaktiviertes Steuerelement angezeigt.

Hinwei s

Standardmäßig ist die TripleState-Eigenschaft auf False eingestellt. Über VBA, bzw. Entfernen des Wertes der verknüpften Zelle können Sie aber dennoch einen NULL-Zustand des Kontrollkästchens erzielen. Um einen NULLZustand per Klick auf das Steuerelement zu bewirken, muss allerdings die TripleState-Eigenschaft auf True gesetzt werden.

Steuerelemente

Bei OptionsButton kann ein Null-Zustand nur über VBA, oder das Entfernen des Wertes der verknüpften Zelle, aber nicht über das Anklicken der Optionsfelder erzeugt werden. Zu den Optionsfeldern finden Sie in diesem Kapitel einige Rezepte.

Steuerelemente

Neben dem Kontrollkästchen weisen die Umschaltfläche und das Optionsfeld ebenfalls die TripleState-Eigenschaft auf. Das Handling der Umschaltfläche ToggleButton ist identisch mit dem der CheckBox.

Steuerelemente

Abbildung 108: Status von Kontrollkästchen ändern

Steuerelemente

Steuerelemente

Wenn Sie den Wert der verknüpften Zelle entfernen, wird das Kontrollkästchen in einen neutralen Zustand NULL versetzt und es erscheint abgedunkelt mit hellgrauem Hintergrund. (siehe Abbildung 108). Diesen Zustand können Sie auch über das Anklicken des Kontrollkästchens erzielen. Dazu muss die TripleState-Eigenschaft auf True gesetzt werden. Jeder Klick auf die CheckBox wechselt dann zwischen Wahr, Falsch und Null. In der verknüpften Zelle wird der Null-Wert als Fehlermeldung #NV angezeigt.

Steuerelemente

297

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 297 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 298 Dienstag, 4. Dezember 2007 1:42 13

298 >> Kontrollkästchen (CheckBox)-Wert auslesen

Nachfolgende Prozeduren ändern den Aktivierungs-Status der CheckBox1. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '=================================================================== Private Sub CmdCheckBoxActivate_Click() ActiveSheet.CheckBox1.Value = True End Sub Private Sub CmdCheckBoxDeactivate_Click() ActiveSheet.CheckBox1.Value = False End Sub Private Sub CmdCheckBoxNULL_Click() ActiveSheet.CheckBox1.Value = Null End Sub Listing 150

122 Kontrollkästchen (CheckBox)-Wert auslesen Die Abfrage nach dem Wert eines Kontrollkästchens kann drei verschiedene Ergebnisse liefern. Zwei der Werte (Wahr und Falsch) sind vom Datentyp Boolean. Wenn die CheckBox einen Zwischenstand aufweist, also mit sichtbarem Häkchen abgedunkelt dargestellt wird, liefert die Value-Eigenschaft den Wert Null vom Datentyp Variant. Null darf nicht mit dem Zahlenwert 0 verwechselt werden. Es ist nicht möglich, ein Kontrollkästchen direkt auf einen Null-Wert in der Form If CheckBox1.Value = Null zu überprüfen. Der Wert Null ist nur mit der IsNull-Funktion vom Datentyp Boolean nachweisbar. If IsNull(CheckBox1.Value) Then

Neben unserer nachfolgend vorgestellten Prozedur CmdReadValue_Click können Sie lediglich noch über den Case Else-Abschnitt der Select Case-Anweisung einen NullZustand genau ermitteln. Select Case ActiveSheet.CheckBox1.Value Case True MsgBox "Wahr" Case False MsgBox "Falsch" Case Else MsgBox "Null" End Select

If varValue = True Then MsgBox "Kontrollkästchen ist aktiviert" ElseIf varValue = False Then MsgBox "Kontrollkästchen ist deaktiviert" ElseIf IsNull(varValue) Then MsgBox "Kontrollkästchen ist im Null-Zustand" End If End Sub Listing 151

123 Wahrheitswert eines Kontrollkästchens übertragen

Achtung

Wenn Sie sicher sind, dass ein Kontrollkästchen nur den Wert True oder False für aktiviert/deaktiviert haben kann, reicht es, wenn Sie den booleschen Wert des Kontrollkästchens nutzen, um Einstellungen, welche ebenfalls einen booleschen Wert erwarten, zu ändern. Um zum Beispiel die Gitternetzlinien des Tabellenblattes einoder auszublenden, verwenden Sie das Change-Ereignis einer CheckBox. Jedes Mal, wenn der Anwender den Status des Kontrollkästchens durch Anklicken ändert, wird die Anzeige der Gitternetzlinien über die folgende Ereignisprozedur gewechselt. Wenn das Kontrollkästchen einen Zwischenzustand Null aufweist, liefert folgende Prozedur einen Fehler. Gitternetzlinien können nur ein- oder ausgeblendet werden, weisen aber keinen Zustand Null auf. Wenn Sie die TripleStateEigenschaft auf False gesetzt und keine verknüpfte Zelle festgelegt haben oder diese für den Anwender nicht zugänglich machen, kann aber kein Fehler passieren.

Steuerelemente Steuerelemente

varValue = ActiveSheet.CheckBox1.Value

Steuerelemente

Private Sub CmdReadValue_Click() Dim varValue As Variant

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '===================================================================

Steuerelemente

Klicken Sie in der Beispieldatei auf die Schaltfläche CHECKBOX-WERT AUSLESEN um das hinterlegte Click-Ereignis auszulösen.

Steuerelemente

299

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 299 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 300 Dienstag, 4. Dezember 2007 1:42 13

300 >> Steuerelement-Eigenschaften ändern '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '=================================================================== Private Sub CheckBox2_Change() ActiveWindow.DisplayGridlines = CheckBox2.Value End Sub

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Listing 152

124 Steuerelement-Eigenschaften ändern Die Eigenschaften eines Steuerelementes ändern Sie, indem Sie in der VBA-Codezeile nach dem Objekt eine Eigenschaft, gefolgt von einem Wert angeben. Verwenden Sie folgende Prozedur, um den Beschriftungstext eines Kontrollkästchens über die Caption-Eigenschaft zu ändern. Sie können auf diese Art eine beliebige Eigenschaft oder Methode des genannten Objektes angeben und einstellen. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '=================================================================== Private Sub CmdCheckBoxCaption_Click() ActiveSheet.CheckBox1.Caption = "My CheckBox" End Sub Listing 153

Wenn Sie nicht alle Eigenschaften, welche für ein Steuerelement zur Verfügung stehen, auswendig im Kopf haben, lassen Sie sich alle verwendbaren Eigenschaften in der INTELLISENSE-Liste anzeigen. Damit Excel erkennen kann, um welches Objekt es sich handelt, bedarf es allerdings vorab einer genauen Zuweisung des Objektes. Da es sich bei dem zu bearbeitenden Steuerelement um eine CheckBox der STEUERELEMENT-TOOLBOX handelt, deklarieren Sie die Variable objForm vom Datentyp MSForms.CHECKBOX. Innerhalb einer With-Anweisung können alle Eigenschaften und Methoden des angegebenen Objektes objForm untereinander angegeben werden. Geben Sie innerhalb des With-Blocks einen Punkt (.) ein, damit automatisch die INTELLISENSE mit allen für dieses Objekt verfügbaren Eigenschaften angezeigt wird. Ohne Verwendung der With-Anweisung wird die INTELLISENSE-Liste im Anschluss an den Variablennamen, gefolgt von einem Punkt (.) angezeigt objForm..

301

Set objForm = ActiveSheet.CheckBox1 With objForm .BackColor = RGB(0, 255, 0) ' . weitere Eigenschaft End With End Sub Listing 154

125 Mit Umschaltfläche Steuerelement steuern Die Umschaltfläche ToggleButton verhält sich ähnlich wie eine CheckBox. Anstelle eines Häkchens wird diese Schaltfläche als gedrückt, bzw. nicht gedrückt dargestellt. Wenn die Umschaltfläche gedrückt dargestellt wird, liefert deren Visible-Eigenschaft den Wert True, nicht gedrückt gibt False zurück. Wenn die TripleState-Eigenschaft auf True eingestellt ist, ergibt der Zwischenstand der Umschaltfläche den Wert Null.

Steuerelemente Steuerelemente

Private Sub CmdCheckBoxProperties_Click() Dim objForm As MSForms.CHECKBOX

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '===================================================================

Steuerelemente

Folgende Prozedur ändert im aktiven Tabellenblatt die Hintergrundfarbe der CheckBox1.

Steuerelemente

Abbildung 109: CheckBox-Eigenschaften in Intellisense-Liste anzeigen

Steuerelemente

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 301 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

302 >> Mit Umschaltfläche Steuerelement steuern

H i n we i s

Um den Aktivierungswechsel beim Anklicken auf die Umschaltfläche abzufangen, können Sie sich des Change-Ereignisses des ToggleButtons bedienen. Nachfolgende Prozedur ermittelt über eine If...Then...Else-Anweisung den booleschen Wert der Umschaltfläche und blendet ein Kontrollkästchen entsprechend diesem Wert ein oder aus. Die ToggleButton-Beschriftung Caption wird ebenfalls in Abhängigkeit der Value-Eigenschaft geändert. Die If...Then...Else-Anweisung überprüft nur den Wert True. Das heißt, nur wenn die Umschaltfläche gedrückt ist, wird die CheckBox eingeblendet. Es wird kein Zwischenstand berücksichtigt. Wenn die TripleState-Eigenschaft auf True eingestellt ist, bewirkt ein Wert Null wie beim Wert False das Ausblenden des angegebenen Steuerelementes.

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '=================================================================== Private Sub TglCheckBoxVisible_Click() If TglCheckBoxVisible.Value = True Then ActiveSheet.CheckBox1.Visible = True TglCheckBoxVisible.Caption = "CheckBox ausblenden" Else ActiveSheet.CheckBox1.Visible = False TglCheckBoxVisible.Caption = "CheckBox einblenden" End If End Sub Listing 155

Ein Klick auf eine Umschaltfläche löst zuerst das Change-Ereignis des Steuerelementes aus. Anschließend wird aber auch ein hinterlegtes Click-Ereignis aufgerufen. Es ist also mit beiden Ereignissen möglich auf einen Wechsel des Aktivierungs-Status zu reagieren. H i nwe i s

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 302 Dienstag, 4. Dezember 2007 1:42 13

Wenn die TripleState-Eigenschaft der Umschaltfläche auf True eingestellt ist, wird beim Anklicken des ToggleButtons zum Null-Zustand nur das ChangeEreignis, jedoch nicht das Click-Ereignis ausgelöst.

In folgender Prozedur wird der boolesche Wert der Enabled-Eigenschaft, also das mögliche Anwählen der CheckBox1, über den booleschen Wert der Umschaltfläche gesteuert. Der Beschriftungstext wird über die IIf-Funktion dirigiert, welche sich ebenfalls nach der Value-Eigenschaft der Umschaltfläche richtet.

126 Gruppen von Steuerelementen erstellen Das aus den FORMULAR-Steuerelementen bekannte GRUPPENFELD ist unter den ACTIVEXSteuerelementen nicht verfügbar. Um eine Anzahl an ACTIVEX-Steuerelementen optisch zusammenzufassen, verwenden Sie das Gruppenfeld der FORMULAR-Steuerelemente. Oft ist es erwünscht, Kontrollkästchen oder Optionsfelder lediglich als optische Gruppe darzustellen. Ziehen Sie dazu einfach um mehrere Steuerelemente einen Rahmen der Formular-Symbolleiste.

Hinwei s

Abbildung 110: Optische Gruppe von ActiveX-Steuerelementen mit Gruppenfeld aus Formular-Steuerelementen

Beachten Sie, dass ACTIVEX-Steuerelemente in einem Gruppenfeld der FORMULAR-Symbolleiste nicht als eigenständige funktionelle Gruppe erkannt werden. Gruppen von Steuerelementen müssen über die GROUPNAME-Eigenschaft der Steuerelemente entsprechend definiert werden.

Als funktionelle Gruppe bezeichnet man Steuerelemente, die inhaltlich und logisch miteinander verbunden sind. Steuerelemente, die logisch miteinander verbunden sind, beeinflussen sich gegenseitig. Wenn Sie auf einem Tabellenblatt mehrere Opti-

Steuerelemente Steuerelemente

Listing 156

Steuerelemente

With TglCheckBoxEnabled .Caption = "CheckBox " & _ IIf(.Value, "deaktivieren", "aktivieren") End With End Sub

Steuerelemente

Private Sub TglCheckBoxEnabled_Click() ActiveSheet.CheckBox1.Enabled = TglCheckBoxEnabled.Value

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle4 (CheckBox) '===================================================================

Steuerelemente

303

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 303 Dienstag, 4. Dezember 2007 1:42 13

304 >> Gruppen von Steuerelementen erstellen

onsfelder aufziehen und der Wert eines Optionsfeldes auf True gesetzt wird, werden die Werte aller anderen Optionsfelder auf False gesetzt.

Hinweis

Oftmals sollen einzelne Gruppen von Optionsfeldern auf einem Tabellenblatt sich aber nicht gegenseitig beeinflussen und nur innerhalb der Gruppe logisch miteinander verbunden sein. Um eine Gruppe von Optionsfeldern von anderen Steuerelementen getrennt zu verwalten, müssen Sie allen Elementen der Gruppe über die GroupName-Eigenschaft den gleichen Gruppennamen zuweisen, damit diese als eigenständige Gruppe erkannt werden. Um mehrere Steuerelemente als eine Gruppe zu definieren, können Sie die Elemente mit gedrückter (Strg)-Taste nacheinander markieren, und im Eigenschaftsfenster in der Zeile GroupName einen Namen, zum Beispiel GRUPPE1 für diese Gruppe, vergeben (siehe Abbildung 111).

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 304 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Abbildung 111: Optionsfelder als funktionelle Gruppe definieren

Im Tabellenblatt OPTIONBUTTON der Beispieldatei sollen drei Bereiche aus mehreren Zellen unabhängig voneinander über Optionsfelder eingefärbt werden. Die einzufärbenden Bereiche werden im Codeblatt der Tabelle vor der ersten Prozedur über deklarierte Konstanten definiert. Dadurch können die Zellenbereiche in den verwendeten Prozeduren direkt über die Variablen angesprochen werden. Änderungen an der Tabellenstruktur müssen dann nur noch in der Konstanten-Deklarierung und nicht in den einzelnen Prozeduren geändert werden. Die Konstanten wurden ohne

' Gruppe 1 Private Sub OptBtnRed_Click() Range(strColorRange1).Interior.ColorIndex = 3 End Sub Private Sub OptBtnGreen_Click() Range(strColorRange1).Interior.ColorIndex = 10 End Sub Private Sub OptBtnBlue_Click() Range(strColorRange1).Interior.ColorIndex = 5 End Sub ' Gruppe 2 Private Sub OptBtnYellow_Click() Range(strColorRange2).Interior.ColorIndex = 6 End Sub Private Sub OptBtnGrey_Click() Range(strColorRange2).Interior.ColorIndex = 15 End Sub Private Sub OptBtnOrange_Click() Range(strColorRange2).Interior.ColorIndex = 45 End Sub ' Gruppe 3 Private Sub OptBtnTurkey_Click() Range(strColorRange3).Interior.ColorIndex = 8 End Sub Listing 157

Steuerelemente Steuerelemente

Const strColorRange1 As String = "B4:C10" Const strColorRange2 As String = "F4:G10" Const strColorRange3 As String = "J4:K10"

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle5 (OptionButton) '===================================================================

Steuerelemente

Wenn Sie einen OptionButton aus einer der drei Gruppen anklicken, wird das hinterlegte Click-Ereignis aufgerufen und der angegebene Zellenbereich entsprechend dem genannten Farbindex eingefärbt.

Steuerelemente

vorangestellte Public-Anweisung deklariert. Dadurch stehen sie nur in dem Modul, in dem sie deklariert wurden, zur Verfügung.

Steuerelemente

305

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 305 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 306 Dienstag, 4. Dezember 2007 1:42 13

306 >> Optionsfelder auswerten Private Sub OptBtnOliv_Click() Range(strColorRange3).Interior.ColorIndex = 12 End Sub Private Sub OptBtnPink_Click() Range(strColorRange3).Interior.ColorIndex = 7 End Sub Listing 157 (Forts.)

127 Optionsfelder auswerten Innerhalb einer Gruppe von Optionsfeldern kann immer nur ein Element aktiviert sein. In der VBA-Programmierung gibt die Value-Eigenschaft den Wert True für das aktive Element einer Gruppe zurück. Alle anderen Elemente der Gruppe haben entweder den Wert False für nicht aktiviert, oder Null für einen Zwischenstand. Um zu ermitteln, welches Element der Gruppe aktiv ist, müssen alle OptionButton dieser Gruppe überprüft werden. Sobald eines dieser Elemente den Wert True aufweist, wird die Beschriftung über die Caption-Eigenschaft als Ergebnis der Auswertung ausgelesen. Zur Auswertung einer Optionsfelder- oder Kontrollkästchen-Gruppe stellen wir Ihnen in diesem Beispiel die benutzerdefinierte Funktion ResultControls mit folgenden zwei Parametern vor:

Steuerelemente

ResultControls(strWks, strGroup)

Diese Funktion ist in einem Standardmodul hinterlegt und erwartet als erstes Argument den Namen des Tabellenblattes, in dem sich die zu überprüfende Gruppe befindet. Als zweites Argument muss der Gruppenname übergeben werden. Über das Schlüsselwort Me wird das Tabellenblatt angesprochen, in dessen Codemodul sich die aufgerufene Ereignis-Prozedur befindet.

Steuerelemente

Steuerelemente

Steuerelemente

Der Aufruf der Funktion erfolgt über eine Befehlsschaltfläche. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle5 (OptionButton) '=================================================================== Private Sub CmdBtnResultGr4_Click() MsgBox ResultControls(Me.Name, "Gruppe4") End Sub Listing 158

Um eine Gruppe von Optionsfeldern zu überprüfen, müssen in einer For Each...NextAnweisung alle Steuerelemente des angegebenen Tabellenblattes durchlaufen werden. Über die progID-Eigenschaft wird der programmtechnische Bezeichner zurück-

For Each objCtrl In Sheets(strWks).OLEObjects If objCtrl.progID = "Forms.OptionButton.1" Then If objCtrl.Object.GroupName = strGroup Then ' Wenn Elementwert auf True, Beschriftungstext als ' Funktionsergebnis festlegen If objCtrl.Object.Value Then ResultControls = objCtrl.Object.Caption Exit Function End If End If End If Next objCtrl End Function Listing 159

128 Optionsfelder und Kontrollkästchen zurücksetzen Um Kontrollkästchen zurückzusetzen, klicken Sie diese im Tabellenblatt an, so dass der Haken entfernt ist. Bei Optionsfeldern ist diese manuelle Verfahrensweise leider nicht mit der Maustaste möglich, da über die Excel-Anwendung immer ein Optionsfeld einer Gruppe von Optionsfeldern den Wert Wahr aufweist. Sie können im Tabellenblatt lediglich die Inhalte der verknüpften Zellen von Optionsfeldern ändern, um diese zurückzusetzen. Um Optionsfeldern eine verknüpfte Zelle zuzuweisen, verwenden Sie deren LinkedCell-Eigenschaft. In der angegebenen Zelle wird der Wert des verknüpften Elementes angezeigt. Sie können die LinkedCellEigenschaft entweder im Eigenschaften-Fenster des Steuerelementes oder über VBACode festlegen. Schreiben Sie in die verknüpften Zellen den Wert Falsch oder 0 um das verknüpfte Optionsfeld zurückzusetzen, also zu deaktivieren. Im Eigenschaften-Fenster selbst können Sie den Wert eines Optionsfeldes ändern, indem Sie der Value-Eigenschaft den Wert True oder False zuweisen. Geben Sie keine

Steuerelemente Steuerelemente

Dim objCtrl As OLEObject

Steuerelemente

Public Function ResultControls(strWks As String, _ strGroup As String) As String

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Modul mdl_01_FunctionResultControls '===================================================================

Steuerelemente

gegeben. Wenn das überprüfte Element der Schleife vom Bezeichner Forms. OptionButton.1 ist, den angegebenen Gruppennamen strGroup und den Wert True aufweist, wird der Beschriftungstext Caption als Ergebnis der Funktion festgelegt und die Funktion verlassen.

Steuerelemente

307

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 307 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 308 Dienstag, 4. Dezember 2007 1:42 13

308 >> Optionsfelder und Kontrollkästchen zurücksetzen Value-Eigenschaft an oder löschen einen vorhandenen Wert, wird das Optionsfeld in den Null-Zustand versetzt.

In diesem Beispiel stellen wir Ihnen die Prozedur ResetControls vor. Sie ist in der Lage, sowohl Kontrollkästchen als auch Optionsfelder einer Gruppe zurückzusetzen. Ebenso ist es möglich, allen Elementen der angegebenen Gruppe den Zustand Null zuzuweisen. Alle Kontrollkästchen einer Gruppe können zudem auf True gesetzt werden. Der Aufruf der Prozedur ResetControls erfolgt über eine Befehlsschaltfläche, wobei die erforderlichen Argumente beim Aufruf übergeben werden. ResetControls(strWks, strForm, strGroup, [strValue = "False"]) Parameter

Beschreibung

strWks As String

Name des Tabellenblattes, auf dem sich die Elemente befinden.

strForm As String

Objektangabe: 왘 OptionButton 왘 CheckBox

strGroup As String

Gruppenname

[strValue As String = "False"])

Optionaler Wert, kann True, False oder Null sein. Standardwert ist False. Eine Gruppe von Optionsfeldern kann nicht auf True gesetzt werden.

Tabelle 26: Parameter der ResetControls-Prozedur '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Tabelle OptionButton ' Modul mdl_02_ResetControls '=================================================================== Public Sub ResetControls(strWks As String, _ strForm As String, _ strGroup As String, _ Optional strValue As String = "False") Dim objCtrl As OLEObject ' Umwandeln der Objektangabe in progID strForm = IIf(strForm = "OptionButton", _ "Forms.OptionButton.1", _ "Forms.CheckBox.1") Listing 160

End Sub Listing 160 (Forts.)

Wenn Sie im Tabellenblatt OPTIONBUTTON auf die Schaltfläche ZURÜCKSETZEN der GRUPPE4 klicken, wird das hinterlegte Click-Ereignis ausgelöst. Über die aufgerufene Prozedur ResetControls werden alle Optionsfelder der GRUPPE4 zurückgesetzt. Dem optionalen Parameter strValue wird der Wert False zugewiesen. Dies ist der Standardwert von strValue und muss nicht unbedingt angegeben werden. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle5 (OptionButton) '=================================================================== Private Sub CmdBtnResetGr4_Click()

Steuerelemente

For Each objCtrl In Sheets(strWks).OLEObjects If objCtrl.progID = strForm Then If objCtrl.Object.GroupName = strGroup Then objCtrl.Object.Value = strValue End If End If Next objCtrl

Steuerelemente

' alle Optionsfelder einer Gruppe können nicht den ' Wert True erhalten If strForm = "Forms.OptionButton.1" And _ strValue = "True" Then Exit Sub

Steuerelemente

309

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 309 Dienstag, 4. Dezember 2007 1:42 13

In GRUPPE5 werden wiederum alle OptionButton dieser Gruppe zurückgesetzt. Der folgende Aufruf verdeutlicht, dass bei fehlender Angabe des strValue-Parameters diesem in der Prozedur automatisch der Wert False zugewiesen wird.

Steuerelemente

Listing 161

Steuerelemente

ResetControls Me.Name, _ "OptionButton", _ "Gruppe4", _ "False" End Sub

Steuerelemente

' ResetControls(strWks, strForm, strGroup, [strValue = "False"])

310 >> Optionsfelder und Kontrollkästchen zurücksetzen '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle5 (OptionButton) '=================================================================== Private Sub CmdBtnResetGr5_Click() ResetControls Me.Name, _ "OptionButton", _ "Gruppe5" End Sub

Hinweis

Listing 162

Obwohl Optionsfelder die TripleState-Eigenschaft aufweisen, ist es manuell über die Excel-Anwendung nur über die verknüpfte Zelle möglich einen NullZustand zu erreichen. Wenn Sie über VBA einen Zwischenstand zuweisen, ist es unerheblich, ob die Eigenschaft auf False oder True gesetzt wird. In beiden Fällen wird der Befehl ausgeführt und die Elemente zurück, bzw. auf Null gesetzt.

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 310 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 112: Alle Optionsfelder einer Gruppe auf Null setzen

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle5 (OptionButton) '=================================================================== Private Sub CmdBtnNULLGr5_Click() ResetControls Me.Name, _ "OptionButton", _ "Gruppe5", _ "NULL" End Sub Listing 163

129 Arbeitsblätter über Listenfeld auswählen

Beim Öffnen der Datei wird das Listenfeld ListBox1 im Workbook_Open-Ereignis gefüllt.

Steuerelemente

Abbildung 113: Tabellenblattauswahl über Listenfeld

Steuerelemente

Steuerelemente

Steuerelemente

Für dieses Beispiel wurde im Tabellenblatt ein Listenfeld der ACTIVEX-Steuerelemente aufgezogen (siehe Abbildung 113). Die Größe des Listenfeldes Listbox wurde so bemessen, dass immer drei Einträge (Namen von vorhandenen Arbeitsblättern der Excel-Arbeitsmappe) sichtbar sind. Weitere Tabellen- und Diagrammblätter der Arbeitsmappe werden durch Klicken auf die Pfeile in der ListBox angezeigt.

Steuerelemente

Die folgende Prozedur weist allen Optionsfeldern der GRUPPE5 des aktiven Tabellenblattes einen Null-Wert zu (siehe Abbildung 112).

Steuerelemente

311

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 311 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 312 Dienstag, 4. Dezember 2007 1:42 13

312 >> Arbeitsblätter über Listenfeld auswählen '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Open() Dim sh As Object For Each sh In ActiveWorkbook.Sheets Sheets("ListBox").ListBox1.AddItem sh.Name Next sh End Sub Listing 164

Immer wenn das Listenfeld ausgewählt wird, also den Fokus erhält, wird das GotFocus-Ereignis der Listbox1 ausgelöst. Dieses Ereignis wird verwendet, um über die Clear-Methode bereits vorhandene Einträge aus vorherigen Auflistungen zu entfernen. In der anschließenden For Each...Next-Anweisung werden dem Listenfeld über die AddItem-Methode alle Tabellenblatt-Bezeichnungen der aktiven Datei hinzugefügt. Durch die Verwendung des Sheets-Auflistungsobjektes werden sowohl Tabellen- als auch Diagrammblätter der aktiven Arbeitsmappe aufgeführt. Dadurch wird sichergestellt, dass immer alle aktuellen Arbeitsblätter in dem Listenfeld angezeigt werden. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '=================================================================== Private Sub ListBox1_GotFocus() Dim sh As Object ListBox1.Clear For Each sh In ActiveWorkbook.Sheets ListBox1.AddItem sh.Name Next sh End Sub Listing 165

Sobald Sie einen Eintrag im Listenfeld anklicken, wird über das hinterlegte ClickEreignis das ausgewählte Arbeitsblatt angezeigt.

313

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '=================================================================== Private Sub ListBox1_Click() Sheets(ListBox1.Text).Activate End Sub

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 313 Dienstag, 4. Dezember 2007 1:42 13

Bei mehrmaligem Kontakt mit dem Steuerelement würden die Wochentage durch das ausgelöste MouseMove-Ereignis wiederholt in die ListBox2 geschrieben. Um das zu verhindern, könnten Sie vor dem Befüllen der ListBox2 alle vorhandenen Einträge mit der Clear-Methode löschen. Da sich aber die Werte der ListBox2 nicht ändern, wird mittels der ListCount-Eigenschaft überprüft, ob das Listenfeld bereits gefüllt ist,

Steuerelemente

Abbildung 114: Listenfeld als Gruppe von Optionsfeldern anzeigen

Steuerelemente

Steuerelemente

In diesem Beispiel wird das Steuerelement ListBox2 mit den sieben Wochentagen gefüllt (siehe Abbildung 114). Dazu verwenden wir die WeekdayName-Funktion. Bei jedem Durchlauf der For Each...Next-Anweisung wird durch den Schleifenzähler intI der Wert des Wochentages hochgezählt und über die AddItem-Methode der ListBox2 hinzugefügt. Die ListStyle-Eigenschaft ist auf fmListStyleOption eingestellt. Dadurch werden die Listeneinträge als Optionsfelder dargestellt.

Steuerelemente

Wenn Sie einem Listen- oder Kombinationsfeld Einträge über eine Schleife zuordnen, ist das Steuerelement beim Öffnen der Excel-Datei zunächst leer. Das Hinzufügen von Einträgen können Sie, wie im vorherigen Beispiel, im Workbook_Open-Ereignis ausführen lassen. Eine weitere Möglichkeit bietet das MouseMove-Ereignis. Dieses wird ausgelöst, sobald der Maus-Cursor das Steuerelement »berührt«.

Steuerelemente

130 Listenfeld durch Mausbewegung füllen

Steuerelemente

Listing 166

314 >> Monate in Listenfeld auflisten

und die Prozedur in diesem Fall vorzeitig verlassen. Der durch Mausklick ausgewählte Wert wird in die angegebene Zelle der LinkedCell-Eigenschaft geschrieben. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '=================================================================== Private Sub ListBox2_MouseMove(ByVal Button As Integer, _ ByVal Shift As Integer, _ ByVal X As Single, ByVal Y As Single) Dim intI As Integer If ListBox2.ListCount > 0 Then Exit Sub For intI = 1 To 7 ListBox2.AddItem WeekdayName(intI) Next intI End Sub Listing 167

131 Monate in Listenfeld auflisten Ein Listenfeld lässt sich nicht wie ein Kombinationsfeld als DropDown-Feld anzeigen. Wenn Sie ein Listenfeld auf die Höhe eines Eintrages beschränken, ist immer nur ein Eintrag sichtbar. Durch Klick auf die Pfeile am Steuerelement wird der vorherige bzw. nachfolgende Wert der Liste angezeigt (siehe Abbildung 115). Ein Klick auf die Auswahl schreibt den Wert in die verknüpfte Zelle LinkedCell.

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 314 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 115: Listenfeld mit Monatsauswahl

Die Darstellungsart des Listenfeldes können Sie über die SpecialEffect-Eigenschaft festlegen. In unserem Beispiel wurde die Konstante fmSpecialEffectBump ausgewählt. Dadurch ist das Objekt am unteren und rechten Rand hervorgehoben und erscheint

>> Steuerelemente

315

Experimentieren Sie ein wenig mit den verschiedenen Einstellungen der SpecialEffect-Eigenschaft und finden Sie dabei Ihre bevorzugte Darstellung der Steuerelemente.

Die ListBox3 wird wieder im Workbook_Open-Ereignis der Beispiel-Datei gefüllt. Dabei wird die MonthName-Funktion angewandt, welche eine Zeichenfolge zurückgibt, die den festgelegten Monat angibt. Die Syntax lautet:

Steuerelemente

Abbildung 116: Darstellung eines Objekts festlegen

Steuerelemente

Steuerelemente

am oberen und linken Rand flach. Diese Einstellung ist für Kontrollkästchen und Optionsfelder nicht gültig.

Steuerelemente

2471_Excel-VBA.book Seite 315 Dienstag, 4. Dezember 2007 1:42 13

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Open() Dim intI As Integer For intI = 1 To 12 Sheets("ListBox").ListBox3.AddItem MonthName(intI) Next intI

Steuerelemente

ListBox3.AddItem MonthName(IntI, True) ' liefert bei 3 den Wert Mrz

Steuerelemente

Um die Monatsnamen in abgekürzter Schreibweise darzustellen, geben Sie in der MonthName-Funktion für den zweiten Parameter abkürzen den Wert True an:

Steuerelemente

H i n we i s

MonthName(Monat[, abkürzen])

Listing 168

Steuerelemente

End Sub

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 316 Dienstag, 4. Dezember 2007 1:42 13

316 >> Listenfeldeinträge bei Auswahl ändern

132 Listenfeldeinträge bei Auswahl ändern In diesem Beispiel wird der ListBox4 im Workbook_Open-Ereignis der Eintrag Jahreszeiten als einziges Element zugeordnet. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Open() Sheets("ListBox").ListBox4.AddItem "Jahreszeiten" End Sub Listing 169

Wenn Sie mit der Maus das Listenfeld ListBox4 anklicken, sollen anstelle der Überschrift Jahreszeiten die vier Jahreszeiten zur Auswahl angezeigt werden (siehe Abbildung 117).

Abbildung 117: GotFocus-Ereignis ändert Listenfeld-Einträge und -Größe

Sobald das Listenfeld ListBox4 den Fokus erhält, wird das hinterlegte GotFocus-Ereignis ausgelöst. An die Variant-Variable Season wird ein Array mit den einzufügenden Einträgen übergeben. Im folgenden With-Block wird zunächst der Eintrag »Jahreszeiten« durch die RemoveItem-Methode gelöscht. Der Wert 0 repräsentiert dabei den ersten Eintrag im Listenfeld. Über die List-Eigenschaft wird das komplette Datenfeld Season mit seinen Werten in das Steuerelement kopiert. Dadurch ersparen Sie sich die bereits bekannte Verfahrensweise über eine For Each...Next-Anweisung in Kombination mit der AddMethode. Jetzt muss nur noch die Höhe Height des Listenfeldes angepasst werden, so dass alle Einträge vollständig angezeigt werden. Davon ausgehend, dass ein Listenfeldeintrag eine Höhe von 13 Punkt benötigt, wird diese Höhe mit der Anzahl der Array-Werte multipliziert. Diese wird über die UBound-Funktion ermittelt, welche die Obergrenze einer Datenfeld-Dimension zurückgibt. Da ein Datenfeld mit dem Wert 0 beginnt, wird zu dem ermittelten Wert die Zahl 1 addiert.

Wenn Sie mit der Standardeinstellung 0 arbeiten wollen, ersetzen Sie die Zahl 1 durch 0 oder lassen die Anweisung ganz einfach weg. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '=================================================================== Private Sub ListBox4_GotFocus() Dim intI As Integer Dim Season As Variant Season = Array("Frühling", "Sommer", "Herbst", "Winter") With ListBox4 .RemoveItem (0) .List = Season ' Größe des Listenfeldes anpassen .Height = 13 * (UBound(Season) + 1) End With End Sub

Steuerelemente

Option Base 1

Steuerelemente

Damit der Index der Untergrenze eines Datenfeldes nicht bei 0, sondern bei 1 beginnt, setzen Sie die Option Base-Anweisung ein. Diese muss zu Beginn des Moduls vor allen Prozeduren und Deklarationen von Datenfeldern stehen, die Dimensionen enthalten. Folgende Anweisung besagt, dass die Untergrenze aller Datenfelder im verwendeten Modul mit dem Index 1 beginnt:

Steuerelemente

317

Steuerelemente

Hinwei s

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 317 Dienstag, 4. Dezember 2007 1:42 13

Listing 171

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '===================================================================

Steuerelemente

Durch einen Doppelklick auf einen Eintrag in der ListBox4 wird das hinterlegte ListBox4_DblClick-Ereignis ausgelöst. Der ausgewählte Wert wird in die Zelle E23 geschrieben. Anschließend wird die aktive Zelle im Tabellenblatt aktiviert. Das ist erforderlich, damit das Listenfeld ListBox4 den Fokus wieder an die aktive Zelle des Tabellenblattes übergibt. Dabei wird zugleich das ListBox4_LostFocus-Ereignis aus gelöst.

Steuerelemente

Listing 170

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 318 Dienstag, 4. Dezember 2007 1:42 13

318 >> Mehrspaltiges Listenfeld füllen Private Sub ListBox4_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Range("E23").Value = ListBox4.Text ' löst LostFocus-Ereignis aus ActiveCell.Activate End Sub Listing 171 (Forts.)

Nachdem das Listenfeld verlassen wurde, soll der Ausgangszustand der ListBox4 mit der Themenüberschrift »Jahreszeiten« wieder hergestellt werden. Dazu wird die Höhe des Listenfeldes angepasst, alle vorhandenen Einträge mit der Clear-Methode gelöscht und die gewünschte Zeichenkette wieder mit der AddItem-Methode dem Listenfeld hinzugefügt. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '=================================================================== Private Sub ListBox4_LostFocus() With ListBox4 .Height = 15 .Clear .AddItem "Jahreszeiten" End With End Sub Listing 172

133 Mehrspaltiges Listenfeld füllen Über die ListFillRange-Eigenschaft eines Listenfeldes oder Kombinationsfeldes können Sie einen Zellenbereich auf einem Tabellenblatt einem Steuerelement zuweisen. Die Werte im angegebenen Bezug werden im genannten Objekt angezeigt. Worksheets("Tabelle1").ListBox1.ListFillRange = "Tabelle1!A1:A12"

Wenn Sie diese Methode verwenden, können Sie keine einzelnen Einträge im Steuerelement löschen. Um die gesamte Liste zu entfernen, weisen Sie der ListFillRangeEigenschaft einen Leerstring zu. Worksheets("Tabelle1").ListBox1.ListFillRange = ""

Um einen Bereich aus mehreren Spalten in einem Listenfeld anzuzeigen, reicht es nicht aus, diesen Bereich der ListFillRange-Eigenschaft zuzuweisen. Zusätzlich muss die Anzahl der Spalten an die ColumnsCount-Eigenschaft übergeben und die jeweilige Spaltenbreite in ColumnWidths hinterlegt werden (siehe Abbildung 118). Spaltenbreiten werden in Punkten gemessen. Sie können die Angaben aber auch in Zentimeter-

Wenn ColumnWidths keinen Wert aufweist, wird die Spaltenbreite automatisch berechnet, indem die Breite des Steuerelements gleichmäßig auf alle Spalten der Liste aufgeteilt wird. Überschreitet die Summe der angegebenen Spaltenbreiten die Gesamtbreite des Steuerelements, wird die Liste innerhalb des Steuerelements linksbündig angeordnet und eine oder mehrere der ganz rechts befindlichen Spalten werden nicht angezeigt. Der Benutzer kann dann mit Hilfe der horizontalen Bildlaufleiste durch die Liste blättern und die ganz rechts befindlichen Spalten anzeigen lassen.

Es ist nicht möglich, über die ListFillRange-Eigenschaft einen Bereich aus nicht zusammenhängenden Zellen in einem Listenfeld anzuzeigen. Dazu müssen die einzelnen Bereiche dem Listenfeld über eine For...Next-Anweisung hinzugefügt werden.

Steuerelemente

Abbildung 118: Mehrspaltiges Listenfeld mit Spaltenüberschriften

Steuerelemente

Steuerelemente

Steuerelemente

Wenn die ColumnHeads-Eigenschaft auf True gesetzt ist, wird die Zeile oberhalb der ListFillRange-Angabe als Überschriftenzeile angenommen. Wenn ListFillRange bei Zeile 1 beginnt, werden die Spaltenbezeichnungen der Excel-Tabelle selbst (SPALTE H, SPALTE I usw.) als Spaltenüberschriften verwendet.

Steuerelemente

H i n we i s

Einheiten (zum Beispiel 2,5 cm) im Eigenschaftsfenster angeben. Sobald Sie die Zeile verlassen, rechnet Excel die verwendete Einheit in Punkte um. Die ColumnWidthsEigenschaft kann für einzelne oder alle Spalten leer sein. Wenn Sie gar keine Spaltenbreite bestimmen wollen, lassen Sie die Zeile der ColumnWidths-Eigenschaft leer. Wenn für einzelne Spalten keine bestimmte Größe festgelegt werden soll, schreiben Sie ein Semikolon (;) ohne voranstehenden Wert an die Position der betreffenden Spalte.

Steuerelemente

319

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 319 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

320 >> Mehrspaltiges Listenfeld füllen

Die ListBox6 soll in diesem Beispiel mit den Spalten H und L der Tabelle aus Abbildung 118 gefüllt werden. Die erste Spalte eines Listenfeldes wird einfach mit der Add-Methode gefüllt. Weitere Spalten werden über die List-Eigenschaft angesprochen. Dabei werden zuerst der Zeilen- und dann der Spaltenindex angegeben. Beide Index-Werte beginnen bei 0. List(0, 1)

Achtung

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 320 Dienstag, 4. Dezember 2007 1:42 13

' Listenfeld(Zeile 1, Spalte 2)

Bevor Sie in einem Listenfeld einem Feld einer Spalte einen Wert hinzufügen können, müssen die vorangegangenen Spaltenfelder derselben Zeilenhöhe gefüllt sein.

Bei jedem Schleifendurchlauf wird die zu füllende Listenzeile um eine Zeile hochgezählt und mit dem fortlaufenden Zellenwert aus den angegebenen Bereichen rngA und rngB gefüllt. Die ListBox6 wird durch einen Klick auf eine Befehlsschaltfläche gefüllt. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle6 (ListBox) '=================================================================== Private Sub Dim rngA Dim rngB Dim intI

CommandButton1_Click() As Range As Range As Integer

Set rngA = Me.Range("H1:H5") Set rngB = Me.Range("L1:L5") With ListBox6 .Clear .ColumnCount = 2 For intI = 0 To rngA.Cells.Count – 1 ' erste Spalte füllen .AddItem rngA.Cells(intI + 1).Value ' zweite Spalte füllen .List(intI, 1) = rngB.Cells(intI + 1).Value Next intI End With End Sub Listing 173

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle7 (ComboBoxBox) '=================================================================== Private Sub CommandButton1_Click() With ComboBox1 .Clear .AddItem "Deutsch" .AddItem "Englisch" ' Anzeige bei Start des Programms: "Deutsch" .ListIndex = 0 End With End Sub Listing 174

Abbildung 119: Kombinationsfeld nach Auswahl füllen

Steuerelemente

Steuerelemente

Wenn der Anwender auf einen Eintrag im Kombinationsfeld klickt, wird das hinterlegte ComboBox1_Change-Ereignis ausgelöst. Zu Beginn der Prozedur werden zwei Array-Datenfelder an die Variablen varGerman und varEnglish übergeben. Über eine Select Case-Anweisung wird der ausgewählte Wert überprüft und der List-Eigenschaft das dazugehörige Datenfeld übergeben. Die ComboBox2 weist nach einem Pfeilklick eine Auflistung mit einer deutschen bzw. englischen CountDown-Liste auf.

Steuerelemente

In diesem Beispiel wird die ComboBox1 per Klick auf eine Befehlsschaltfläche CommandButton1 mit den Werten Deutsch und Englisch gefüllt. Die ListIndex-Eigenschaft erhält den Wert 0. Dadurch wird der erste Wert der Liste Deutsch im Steuerelement angezeigt.

Steuerelemente

Die Handhabung von Kombinationsfeldern ComboBox ist ähnlich der von Listenfeldern. Kombinationsfelder lassen sich nicht als aufgeklappte Listen anzeigen, sie funktionieren wie ein DropDown-Feld. Wenn Sie auf den Pfeil eines Kombinationsfeldes klicken, klappt die Liste mit den vorhandenen Einträgen auf. Durch Klick auf einen Eintrag wird dieser in das Sichtfenster des Steuerelementes kopiert und die Liste wieder zugeklappt.

Steuerelemente

134 Kombinationsfeld nach Auswahl füllen

Steuerelemente

321

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 321 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 322 Dienstag, 4. Dezember 2007 1:42 13

322 >> Kombinationsfeld nach Auswahl füllen

Das ComboBox-Steuerelement verfügt nicht über die TakeFocusOnClick-Eigenschaft. Dadurch behält es standardmäßig weiterhin den Fokus, nachdem eine Auswahl getroffen wurde. Der Fokus wird an das Tabellenblatt zurückgegeben, indem der aktive Zellbereich aktiviert wird. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle7 (ComboBox) '=================================================================== Private Sub ComboBox1_Change() Dim varGerman As Variant Dim varEnglish As Variant varGerman = _ Array("Fünf", "Vier", "Drei", "Zwei", "Eins", "Null") varEnglish = _ Array("Five", "Four", "Three", "Two", "One", "Zero") With ComboBox2 Select Case ComboBox1.Value Case "Deutsch" .List = varGerman Case "Englisch" .List = varEnglish Case Else .Clear End Select ' bei Start ersten Wert der Liste anzeigen If .ListCount > 0 Then .ListIndex = 0 End With ' Fokus an Tabellenblatt zurückgeben Selection.Activate End Sub Listing 175

Wenn der Anwender einen Eintrag aus der ComboBox2 wählt, wird deren DropDownListe zugeklappt und die Auswahl erscheint im Steuerelement. Im ausgelösten ComboBox2_Change-Ereignis wird der Fokus anschließend an das Tabellenblatt zurückgegeben.

Private Sub ComboBox2_Change() ' Fokus an Tabellenblatt zurückgeben Selection.Activate End Sub Listing 176

135 Passworteingabe durch Platzhalterzeichen ersetzen Sie können ein Textfeld der ACTIVEX-Steuerelemente verwenden, um wichtige Informationen, z. B. Kennwörter oder Sicherheitscodes, während der Eingabe zu schützen, indem die eingegebenen Zeichen durch so genannte »Platzhalterzeichen« ersetzt werden. Verwenden Sie dazu die PasswordChar-Eigenschaft des TextBox-Objektes.

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '=================================================================== Listing 177

Steuerelemente

Über eine Befehlschaltfläche im Tabellenblatt wird ein Meldungsfenster MsgBox mit dem enthaltenen Text des Textfeldes angezeigt.

Steuerelemente

Abbildung 120: Text mit Platzhalterzeichen anzeigen

Steuerelemente

Steuerelemente

Geben Sie auf Ihrer Tastatur ein beliebiges einzelnes Zeichen für die PasswordCharEigenschaft ein, damit dieses Zeichen anstelle des Zeichens angezeigt wird, das der Benutzer tatsächlich eingibt.

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle7 (ComboBoxBox) '===================================================================

Steuerelemente

323

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 323 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 324 Dienstag, 4. Dezember 2007 1:42 13

324 >> Passworteingabe durch Platzhalterzeichen ersetzen Private Sub CommandButton1_Click() MsgBox "Der eingegebene Text lautet:" & _ vbNewLine & vbNewLine & _ TextBox1.Text End Sub Listing 177 (Forts.)

Mit einer If...Then...Else-Anweisung ist es auf diese Weise möglich ein vorgegebenes Passwort zu überprüfen, um zum Beispiel ein bestimmtes Tabellenblatt anzuzeigen oder sonstige Befehle auszuführen. Wenn das eingegebene Passwort nicht mit dem im Code hinterlegten Passwort der Variablen strPassword übereinstimmt, wird die TextBox1 aktiviert und der enthaltene Text durch einen Leerstring ersetzt. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '=================================================================== Private Sub CommandButton2_Click() Dim strPassword As String strPassword = "Codebook" If TextBox1.Text = strPassword Then MsgBox "Das Paßwort '" & TextBox1.Text & "' ist richtig!" Else MsgBox "Das Paßwort '" & TextBox1.Text & "' ist falsch!" With TextBox1 .Activate .Text = "" End With End If End Sub

Steuerelemente

Steuerelemente

Listing 178

Wenn Sie kein Zeichen für die PasswordChar-Eigenschaft angeben, zeigt das Steuerelement die Zeichen an, die der Benutzer eingibt. Wenn Sie einen Leerschritt eingeben, wird der eingegebene Text nicht angezeigt, ist aber dennoch im Textfeld vorhanden. In unserer Beispieldatei wird bei einem Klick auf die Schaltfläche PLATZHALTERZEICHEN ein Eingabefenster InputBox angezeigt. Geben Sie ein einzelnes Zeichen oder einen Leerschritt ein, um den Text der TextBox1 entsprechend anzuzeigen. Wenn Sie die Eingabezeile leer lassen, wird der Text in den verwendeten Zeichen dargestellt.

Private Sub CommandButton3_Click() Dim strChar As String strChar = InputBox( _ "Wählen Sie ein einzelnes Zeichen auf Ihrer Tastatur aus.", _ "Platzhalterzeichen", "*") If Len(strChar) > 1 Then Exit Sub With TextBox1 .PasswordChar = strChar End With End Sub Listing 179

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '===================================================================

Steuerelemente

325

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 325 Dienstag, 4. Dezember 2007 1:42 13

Private Sub CommandButton4_Click() ' Text zurückgeben Range("H16").Value = TextBox2.Text End Sub Listing 180

Steuerelemente Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '===================================================================

Steuerelemente

Wie aus dem Namen »Textfeld« schon herauszuhören ist, wird in diesem Steuerelement Text verwaltet. Die im Eigenschaften-Fenster in LinkedCell angegebene Zelle zeigt alle Werte (Text-, Zahlen-, Datums- oder Währungswerte) des verknüpften Textfeldes linksbündig im Textformat an. Den Inhalt eines Textfeldes ermitteln Sie entweder über die Text- oder die Value-Eigenschaft. Beide Eigenschaften sind gleichwertig. Wenn Sie den Wert eines Textfeldes in eine Zelle schreiben oder innerhalb des Codes weiterverwenden, bzw. einer Variablen übergeben, wird er weiterhin als Text vom Datentyp String verarbeitet.

Steuerelemente

136 Textfeld-Werte umwandeln

Steuerelemente

Steuerelemente

326 >> Textfeld-Werte umwandeln

Um die Werte aus einer TextBox typengerecht auszugeben, wenden Sie die gewünschten Typ-Umwandlungsfunktionen an. Nachfolgende Tabelle informiert Sie über die gängigsten Umwandlungsfunktionen in Bezug auf Textfelder: Funktion

Rückgabetyp Bereich des Arguments Ausdruck

CCur

Currency

Ein Datentyp mit einem Wertebereich von -922.337.203.685.477,5808 bis 922.337.203.685.477,5807. Verwenden Sie diesen Datentyp für Berechnungen von Währungen und für Berechnungen mit festgelegten Nachkommastellen, bei denen es besonders auf Genauigkeit ankommt.

CDate

Date

Ein Datentyp, der Datums- und Zeitangaben als reelle Zahlen speichert. Datumsvariablen werden als 64-Bit-Zahlen (8 Bytes) gespeichert. Der Wert links vom Dezimalzeichen steht für ein Datum, der Wert rechts vom Dezimalzeichen für eine Uhrzeit.

CDbl

Double

Ein Datentyp, der Fließkommazahlen mit doppelter Genauigkeit als 64-Bit-Zahlen im Wertebereich von -1.79769313486231E308 bis -4,94065645841247E-324 für negative Werte und von 4,94065645841247E-324 bis 1,79769313486232E308 für positive Werte enthält.

CInt

Integer

Ein Datentyp, der ganzzahlige Variablen enthält und diese als ganze Zahlen mit 2 Byte im Wertebereich von -32.768 bis 32.767 speichert. Nachkommastellen werden gerundet. Der Datentyp Integer wird auch verwendet, um Aufzählungswerte darzustellen.

Cvar

Variant

Numerische Werte im Bereich des Typs Double. Nichtnumerische Werte im Bereich des Typs String.

Tabelle 27: Typ-Umwandlungsfunktionen

Bevor Sie einen TextBox-Wert als Zahl weiterverwenden, bzw. in eine Zelle schreiben, wandeln Sie ihn über die CDbl-Funktion in einen Wert vom Datentyp Double um. Hinweis

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 326 Dienstag, 4. Dezember 2007 1:42 13

Wenn Sie versuchen, Text, der nicht in Zahlen konvertiert werden kann, mit der CDbl-Funktion umzuwandeln, wird ein Fehler verursacht. Um dies zu verhindern, wird vorab über die IsNumeric-Funktion in einer If...Then...ElseAnweisung überprüft, ob es sich bei dem Wert um eine Zahl handelt.

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '=================================================================== Listing 181

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '=================================================================== Private Sub CommandButton6_Click() ' Datum zurückgeben With Range("H22") If IsDate(TextBox2.Text) Then .Value = CDate(TextBox2.Text) Else .Value = TextBox2.Text End If End With End Sub Listing 182

137 Zeilenumbruch in Textfeld (TextBox) per Code einfügen Immer wieder taucht die Frage auf, wie man in einer Textbox einen Zeilenwechsel per Code realisieren kann. In einem Word-Dokument oder Text Editor genügt es die EINGABE- oder ENTER-Taste zu drücken, und schon hat man einen Zeilenwechsel. Mit einem Textfeld funktioniert dies standardmäßig nicht. Wenn Sie die MultiLine-Eigenschaft auf True setzen, wird der eingegebene Text automatisch bei Erreichen des Textfeldrandes umgebrochen und in der nächsten Zeile fortgeführt. Einen manuellen Zeilenumbruch erzeugen Sie bei aktivierter MultiLine-Eigenschaft mit der Tastenkombination (Strg) (Enter).

Steuerelemente Steuerelemente Steuerelemente

Im folgenden Beispiel wird bei einem Klick auf die Befehlsschaltfläche Datum in Zelle schreiben ein eingegebenes Datum von der TextBox2 in die Zelle H22 im Datumsformat geschrieben.

Steuerelemente

Listing 181 (Forts.)

Steuerelemente

Private Sub CommandButton5_Click() ' Zahl zurückgeben With Range("H19") If IsNumeric(TextBox2.Text) Then .Value = CDbl(TextBox2.Text) Else .Value = TextBox2.Text End If End With End Sub

Steuerelemente

327

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 327 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 328 Dienstag, 4. Dezember 2007 1:42 13

328 >> Mit Drehfeld (SpinButton) Monatswerte verändern

Stellen Sie zusätzlich zur MultiLine- die EnterKeyBehavior-Eigenschaft auf True, um in einem Textfeld einen Zeilenumbruch mit der (Enter)-Taste auszuführen. Die Eigenschaften EnterKeyBehavior und MultiLine sind eng miteinander verbunden. Die weiter oben beschriebenen Werte können nur angewendet werden, wenn MultiLine den Wert True hat. Wenn MultiLine den Wert False hat, wird durch Drücken der (Enter)-Taste immer der Fokus zum nächsten Steuerelement in der Aktivierreihenfolge bewegt, unabhängig vom Wert von EnterKeyBehavior. Mit VBA können die Tastendrücke des Benutzers überwacht werden. Setzen Sie dazu das KeyDown-Ereignis des TextBox-Objektes ein. Bei jedem Tastendruck innerhalb des angegebenen Steuerelementes wird das Ereignis ausgelöst und überprüft das eingegebene Zeichen bzw. Taste über den KeyCode-Parameter. Wurde die (Enter)-Taste gedrückt, wird über die vbNewLine-Konstante ein Zeilenumbruchzeichen an das Textende hinzugefügt. Damit das Textfeld den Zeilenumbruch anzeigen kann, muss die MultiLine-Eigenschaft auch bei dieser VBA-Methode auf True eingestellt sein. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle8 (TextBox) '=================================================================== Private Sub TextBox3_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) ' Prüfung Eingabetaste If KeyCode = vbKeyReturn Then With TextBox3 .Text = .Text & vbNewLine .MultiLine = True End With End If End Sub Listing 183

138 Mit Drehfeld (SpinButton) Monatswerte verändern Mit einem Drehfeld SpinButton kann ein Zahlenwert innerhalb eines vorgegebenen Bereichs eingestellt werden. Über die Eigenschaften Min und Max werden die Unterund Obergrenze eines Drehfeld-Steuerelements vorgegeben. Durch das Klicken auf ein Drehfeld-Steuerelement wird die Value-Eigenschaft des Steuerelements verändert. In diesem Beispiel wurde die Min- und Max-Eigenschaft des SpinButton1 entsprechend der Anzahl Monate auf 1 und 12 festgesetzt. Jeder Wert des Drehfeldes stellt dadurch einen Monatswert dar. Durch das Klicken auf die Pfeile des Drehfeldes wird der Zäh-

329

Private Sub Worksheet_Activate() Dim intI As Integer If ComboBox1.ListCount > 0 Then Exit Sub For intI = 1 To 12 ComboBox1.AddItem MonthName(intI) Next intI End Sub Listing 184

Steuerelemente Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle9 (SpinButton) '===================================================================

Steuerelemente

Um das Kombinationsfeld zu Beginn mit den 12 Monatsnamen zu füllen, wird das Worksheet_Activate-Ereignis eingesetzt. Wenn das Tabellenblatt SPINBUTTON aktiviert wird, löst das Ereignis aus und die ComboBox1 wird in einer For...Next-Anweisung über die MonthName-Funktion mit den Monatsnamen gefüllt. Damit die ComboBox1 nicht bei jedem Aktivieren des Tabellenblattes erneut gefüllt wird, werden eventuell vorhandene Einträge vorab mit der ListCount-Eigenschaft überprüft. Die Prozedur wird beendet, wenn bereits Einträge vorhanden sind.

Steuerelemente

Abbildung 121: Voneinander abhängige Steuerelemente

Steuerelemente

Steuerelemente

ler um eine Zahl nach oben oder unten verändert. Die Einstellungen am Drehfeld wirken sich in diesem Beispiel sowohl auf den Wert in der TextBox1 als auch auf die ComboBox1 aus. Umgekehrt verändert sich der Wert des Drehfeldes, wenn der TextBoxoder der Kombinationfeld-Wert geändert wird. Alle drei Steuerelemente leben sozusagen in Abhängigkeit voneinander (siehe Abbildung 121).

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 329 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 330 Dienstag, 4. Dezember 2007 1:42 13

330 >> Mit Drehfeld (SpinButton) Monatswerte verändern

Durch das Klicken auf einen der beiden Pfeile des Drehfeldes wird das hinterlegte Change-Ereignis ausgelöst. In der Prozedur wird der neue Zahlenwert des SpinButton1 an die TextBox1 weitergegeben. Die MonthName-Funktion wandelt den Zahlenwert des SpinButton1 in den entsprechenden Monatsnamen um und wird dann in der ComboBox1 als Monatsname angezeigt. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle9 (SpinButton) '=================================================================== Private Sub SpinButton1_Change() TextBox1.Value = SpinButton1.Value ' Monatszahl in Monatsnamen umwandeln ComboBox1.Value = MonthName(SpinButton1.Value) End Sub

Steuerelemente

Steuerelemente

Listing 185

Wenn Sie durch eine Eingabe im Textfeld den Wert der TextBox1 verändern, wird das hinterlegte Change-Ereignis der TextBox1 ausgelöst. Bevor die Werte des SpinButtonund ComboBox-Steuerelementes nach dessen Wert eingestellt werden können, muss überprüft werden, ob es sich bei der Eingabe um einen gültigen Zahlenwert im Bereich von 1 bis 12 für einen Monat handelt. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle9 (SpinButton) '===================================================================

Steuerelemente

Steuerelemente

Steuerelemente

Private Sub TextBox1_Change() With TextBox1 If Not IsNumeric(.Value) Or .Value < 1 Or .Value > 12 Then ' TextBox-Eingabe durch Wertabgleich aus SpinButton ' rückgängig machen .Value = SpinButton1.Value Else SpinButton1.Value = .Value ' Monatszahl in Monatsnamen umwandeln ComboBox1.Value = MonthName(.Value) End If End With End Sub Listing 186

Listing 187

139 Mit Bildlaufleiste (ScrollBar) zu Datum wechseln Ebenso wie das Drehfeld vermindert oder erhöht die Bildlaufleiste den Wert einer Zahl. Ein Bildlaufleisten-Steuerelement ScrollBar ist ein eigenständiges Steuerelement. Es sieht genauso aus wie die Bildlaufleiste in bestimmten Objekten, z. B. in einem Listenfeld, oder wie der DropDown-Bereich eines Kombinationsfeldes. Im Gegensatz zu diesen Elementen ist das eigenständige Bildlaufleisten-Steuerelement jedoch kein integraler Bestandteil irgendeines anderen Steuerelements. Sie können ein horizontales oder vertikales Bildlaufleisten-Steuerelement erstellen, indem Sie die Ziehpunkte zur Größenänderung in horizontaler oder vertikaler Richtung ziehen. In diesem Beispiel haben wir in Spalte A alle Datumswerte des aktuellen Jahres untereinander dargestellt. Die Zelle A10 weist durch die Formel =DATUM(JAHR(HEUTE ());1;1) den 01. Januar des heutiges Jahres auf. Darunter liegende Zellen zählen zu ihrer Vorgängerzelle jeweils einen Tag hinzu =A10+1. Die Bildlaufleiste soll nun die Datumswerte des aktuellen Jahres repräsentieren. Bei Veränderung ihres Wertes soll die Zelle mit dem entsprechenden Datum markiert und an oberster Stelle der Datumsreihe angezeigt werden (siehe Abbildung 122). Der Beschriftungstext des Bezeichnungsfeldes Label1 weist ebenfalls den Wert der ScrollBar1 im Datumsformat auf. Die TextBox1 dient dazu, ein Datum einzutragen, zu dem über den CommandButton2 gewechselt wird.

Steuerelemente Steuerelemente

Private Sub ComboBox1_Change() ' Datum in Monatszahl umwandeln SpinButton1.Value = Month("1." & ComboBox1.Value) TextBox1.Value = Month("1." & ComboBox1.Value) End Sub

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle9 (SpinButton) '===================================================================

Steuerelemente

Um den ausgeschriebenen Monatsnamen aus dem Kombinationsfeld in eine Zahl umzuwandeln, wenden wir die Month-Funktion an. Sie gibt einen Wert vom Typ Integer zurück, der den Monat als ganze Zahl im Bereich von 1 bis 12 angibt. Diese ermittelte Monatszahl wird an die Value-Eigenschaften des SpinButton1 und TextBox1-Objektes übergeben.

Steuerelemente

Damit auch das Dreh- und Textfeld entsprechend der Auswahl im Kombinationsfeld eingestellt wird, verwenden wir das Change-Ereignis der ComboBox1.

Steuerelemente

331

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 331 Dienstag, 4. Dezember 2007 1:42 13

332 >> Mit Bildlaufleiste (ScrollBar) zu Datum wechseln

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 332 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 122: Bildlaufleiste mit Datumswerten des derzeitigen Jahres

Da Excel Datumswerte intern als fortlaufende Zahlen verwaltet, wird der Min-Eigenschaft des ScrollBar1-Steuerelementes der 01. Januar des aktuellen Jahres als Ganzzahl zugewiesen. Dazu wird der Datumswert mit der CLng-Funktion in eine Zahl vom Datentyp Long umgewandelt. ScrollBar1.Min = CLng(DateSerial(Year(Date), 1, 1))

Diese Berechnung liefert im Jahr 2007 die Zahl 39083. Der maximale Wert der Bildlaufleiste wird auf die gleiche Weise berechnet. Die ermittelte Zahl 39447, welche den 31.12.2007 darstellt, wird an die Max-Eigenschaft zugewiesen. Diese Einstellungen werden beim Aktivieren des Tabellenblattes SCROLLBAR der Beispieldatei im Worksheet_Activate-Ereignis vorgenommen. Zusätzlich wird der aktuelle Tag an die Value-Eigenschaft zugewiesen. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle10 (ScrollBar) '=================================================================== Private Sub Worksheet_Activate() With ScrollBar1 .Min = CLng(DateSerial(Year(Date), 1, 1)) .Max = CLng(DateSerial(Year(Date), 12, 31)) .Value = CLng(Date) End With End Sub Listing 188

Wenn Sie den Wert der Bildlaufleiste durch Klicken auf einen der äußeren Pfeile oder Verschieben des Bildlauffeldes verändern, wird das hinterlegte Change-Ereignis ausgelöst. Das Bezeichnungsfeld Label1 erhält über die Caption-Eigenschaft den neuen Wert der ScrollBar1 im Datumsformat.

Application.Goto _ Cells(ScrollBar1.Value - ScrollBar1.Min + 10, "A"), True End Sub Listing 189

Über den CommandButton1 mit der Beschriftung HEUTE wird der Wert der ScrollBar1 auf den aktuellen Tag eingestellt. Diese Veränderung löst wiederum das Change-Ereignis aus, wodurch das eingestellte Datum der Systemsteuerung markiert wird. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle10 (ScrollBar) '=================================================================== Private Sub CommandButton1_Click() ScrollBar1.Value = CLng(Date) End Sub Listing 190

Geben Sie im Tabellenblatt SCROLLBAR in der TEXTBOX1 ein Datum des aktuellen Jahres ein. Die Eingabe eines Datums kann, wie in einer Zelle, auf verschiedene Arten erfolgen. Nachfolgende Schreibweisen repräsentieren den 01.01. des aktuellen Jahres: 왘 01.01.2007

Steuerelemente Steuerelemente

Private Sub ScrollBar1_Change() Label1.Caption = Format(ScrollBar1.Value, "DDDD DD.MMMM YYYY")

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle10 (ScrollBar) '===================================================================

Steuerelemente

Über die Goto-Methode wird die Datumszelle des eingestellten Wertes markiert. Gleichzeitig werden die nötigen Bildläufe durchgeführt, damit die Zelle als obere linke Zelle des Fensters bzw. der eingestellten Fenster-Fixierung erscheint. Die Berechnung der Datumszeile wird im ersten Parameter der Cells-Eigenschaft durchgeführt. Im zweiten Parameter, welcher die Spalte angibt, wird der Spaltenbuchstabe A angegeben. Sie können stattdessen auch die entsprechende Spaltenzahl 1 für die Spalte A angeben.

Steuerelemente

333

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 333 Dienstag, 4. Dezember 2007 1:42 13

왘 1.1.7 왘 1-1-7

Steuerelemente

왘 01.01.07

334 >> Steuerelemente mit Tastatur aktivieren

왘 1-1 왘 1/1 Klicken Sie auf die Schaltfläche GEHE ZU DATUM um das hinterlegte Click-Ereignis aufzurufen und den Wert des ScrollBar1-Steuerelementes auf dieses Datum einzustellen. Um sicherzustellen, dass es sich bei der Datumseingabe um ein gültiges Datum im derzeitigen Jahr handelt, müssen einige Abfragen erfolgen. Excel gibt eine Fehlermeldung aus, wenn Sie versuchen Text in ein Datum oder eine Zahl umzuwandeln, oder wenn ein Wert außerhalb der Min- und Max-Eigenschaft an das ScrollBarElement zugewiesen werden soll. Bevor das Datum der TextBox1 an die Value-Eigenschaft der ScrollBar1 übergeben werden kann, wird es mit der CDate-Funktion vom Text- in das Datums-Format umgewandelt. Die CLng-Funktion wandelt dieses Datum in eine Zahl um und weist diese als neuen Wert an die ScrollBar1. Dieser Vorgang löst wiederum das ScrollBar1_Change-Ereignis aus und das Datum des Textfeldes wird im Bezeichnungsfeld Label1 angezeigt und die entsprechende Datumszelle markiert. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_02_ActiveXControls.xlsm ' Ereignis Tabelle10 (ScrollBar) '=================================================================== Private Sub CommandButton2_Click() If Not IsDate(TextBox1.Text) Then MsgBox "Eingabe ist kein gültiger Datumswert!" Exit Sub End If

MsgBox "Das eingegebene Datum liegt nicht im Jahr " _ & Year(Date) Else ScrollBar1.Value = CLng(CDate(TextBox1.Text)) End If End Sub Listing 191

Steuerelemente

Steuerelemente

If CLng(CDate(TextBox1.Text)) < ScrollBar1.Min Or _ CLng(CDate(TextBox1.Text)) > ScrollBar1.Max Then

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 334 Dienstag, 4. Dezember 2007 1:42 13

140 Steuerelemente mit Tastatur aktivieren In einem Formular UserForm können Sie die Aktivierreihenfolge der Steuerelemente vorgeben. Mit der (Tab)-Taste wird das nächste, mit (Shift) (Tab) das vorherige Steuerelement aktiviert. Auf einem Tabellenblatt mit ACTIVEX-Steuerelementen ist diese Aktivierung mittels Tastaturanschlägen standardmäßig nicht vorgesehen. Um

Die gedrückten Tasten werden in Form einer KeyCode-Konstante an den Parameter KeyCode übergeben. Nachfolgende Übersicht zeigt die Konstanten, welche die einzelnen Tasten auf Ihrer Tastatur darstellen. Konstante

Beschreibung

Konstante

Beschreibung

vbKeyBack

RÜCK-Taste

vbKeyLeft

NACH-LINKS-Taste

vbKeyTab

TAB-Taste

vbKeyUp

NACH-OBEN-Taste

vbKeyClear

ENTF-Taste

vbKeyRight

NACH-RECHTS-Taste

vbKeyReturn

EINGABE-Taste

vbKeyDown

NACH-UNTEN-Taste

vbKeyShift

UMSCHALT-Taste

vbKeySelect

AUSWAHL-Taste

vbKeyControl

STRG-Taste

vbKeyPrint

DRUCK-Taste

vbKeyMenu

MENÜ-Taste

vbKeyExecute

AUSFÜHREN-Taste

vbKeyPause

PAUSE-Taste

vbKeySnapshot

SNAPSHOT-Taste

vbKeyCapital

FESTSTELL-Taste

vbKeyInsert

EINFG-Taste

vbKeyEscape

ESC-Taste

vbKeyDelete

LÖSCHEN-Taste

vbKeySpace

LEER-Taste

vbKeyHelp

HILFE-Taste

vbKeyPageUp

BILD-AUF-Taste

vbKeyNumlock

NUM-Taste

vbKeyPageDown

BILD-AB-Taste

VbKeyA – VbKeyZ

A-Taste – Z-Taste

vbKeyEnd

ENDE-Taste

vbKey0 – vbKey9

0-Taste – 9-Taste

vbKeyHome

POS1-Taste

vbKeyF1 - vbKeyF12

F1-Taste – F12-Taste

Tabelle 28: Tasten-Code-Konstanten

Steuerelemente Steuerelemente

Private Sub ComboBox1_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer)

Steuerelemente

Beim Aufruf des KeyDown-Ereignisses werden die gedrückten Tasten an die Parameter KeyCode und Shift der Prozedur übergeben. Excel stellt die benötigten Parameter in der Codeschablone selbstständig zur Verfügung. Am Beispiel einer COMBOBOX lautet die Aufrufzeile wie folgt:

Steuerelemente

Wenn Sie eine beliebige Taste auf Ihrer Tastatur drücken, wird zunächst das KeyDown-, danach das KeyPress und abschließend das KeyUp-Ereignis des aktiven Steuerelementes ausgelöst. Da das KeyPress-Ereignis nur auf alphanumerische Tasten sowie RETURN, ESC und STRG-Kombinationen reagiert, ist es für eine allgemeingültige Tastaturverwaltung nicht ausreichend. Die KeyDown- und KeyUp-Ereignisse sind gleichwertig und überwachen jegliche Tastenanschläge.

Steuerelemente

von einem zum anderen Element zu wechseln, müssen Sie die Elemente mit der linken Maustaste anklicken.

Steuerelemente

335

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 335 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 336 Dienstag, 4. Dezember 2007 1:42 13

336 >> Steuerelemente mit Tastatur aktivieren

Die folgenden Konstanten repräsentieren die Zahlen auf der Zehnertastatur: Konstante

Beschreibung

Konstante

Beschreibung

vbKeyNumpad0

0-Taste

vbKeyNumpad8

8-Taste

vbKeyNumpad1

1-Taste

vbKeyNumpad9

9-Taste

vbKeyNumpad2

2-Taste

vbKeyMultiply

MULTIPLIKATIONSZEICHEN-Taste (*)

VbKeyNumpad3

3-Taste

vbKeyAdd

PLUSZEICHEN-Taste (+)

VbKeyNumpad4

4-Taste

vbKeyReturn

EINGABE-Taste

VbKeyNumpad5

5-Taste

vbKeySubtract

MINUSZEICHEN-Taste (–)

vbKeyNumpad6

6-Taste

vbKeyDecimal

DEZIMALPUNKT-Taste

vbKeyNumpad7

7-Taste

vbKeyDivide

DIVISIONSZEICHEN-Taste

Tabelle 29: Tasten-Code-Konstanten auf der Zehnertastatur

Der Parameter Shift gibt eine Zahl zurück, welche die Zusatztasten SHIFT, STRG und ALT repräsentieren. Rückgabewert

Zusatztaste

0

Keine Zusatztaste

1

(Shift)

2

(Strg) oder (AltGr)

4

(Alt)

Tabelle 30: Rückgabewerte des Shift-Parameters

In der KeyDown-Ereignisprozedur werden die Variablen KeyCode und Shift über eine If...Then...Else- oder Select Case-Anweisung auf ihren Wert überprüft. Entsprechend dieser Auswertung wird ein anderes Steuerelement aktiviert oder ein anderer Befehl oder Makro ausgeführt. Folgende Anweisung aktiviert die TextBox1, wenn die TABULATOR-Taste gedrückt wurde. If KeyCode = vbKeyTab Then TextBox1.Activate

Sie müssen für jedes Steuerelement auf einem Tabellenblatt ein eigenständiges KeyDown-Ereignis definieren, um einen kontinuierlichen Wechsel zwischen den Steuerelementen zu ermöglichen. Im nachfolgenden Rezept verdeutlichen wir Ihnen, dass es möglich ist, eine Menüführung nur mit der Tastatur auszuführen (siehe Abbildung 123).

337

141 Tabellenblatt-Zugriffe mit Steuerelementen verwalten

Steuerelemente

Diese Liste der verfügbaren Benutzerkonten und Passwörter ist im Tabellenblatt ADMIN hinterlegt. Der Bereich A2:A5 wurde der ListFillRange-Eigenschaft der ComboBox1 zugewiesen.

Steuerelemente

Abbildung 123: Formular-Maske auf einem Tabellenblatt

Steuerelemente

Steuerelemente

Steuerelemente

Die Beispieldatei zu diesem Rezept enthält ein Tabellenblatt START mit verschiedenen Steuerelementen (siehe Abbildung 123). Weiter stehen mehrere Tabellenblätter für verschiedene Benutzer zur Verfügung. Beim Öffnen der Datei oder Aktivierung des Start-Blattes ist nur das Start-Blatt sichtbar. Über ein Kombinationsfeld wird eine Liste der vorhandenen, aber ausgeblendeten Blätter angezeigt. Wenn Sie das Benutzerkonto ADMIN auswählen und das richtige Passwort eingeben, werden alle Blätter der Beispieldatei angezeigt. Die anderen Benutzer erhalten jeweils nur das Tabellenblatt entsprechend ihrem Namen.

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 337 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Abbildung 124: Benutzerkonten mit Passwort festlegen

338 >> Tabellenblatt-Zugriffe mit Steuerelementen verwalten

Wenn die Datei geöffnet wird, setzen wir im Workbook_Open-Ereignis die EnableSelection-Eigenschaft auf xlNoSelection. Da das Tabellenblatt START geschützt und alle Zellen im Tabellenblatt gesperrt sind, kann dadurch keine Zelle markiert werden. Es ist also nur möglich, die vorhandenen Steuerelemente zu bedienen. Den Fokus übergeben wir an die ComboBox1, indem dieses Element aktiviert wird.

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_XControlsKeyCode.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Open() With Worksheets("Start") .EnableSelection = xlNoSelection .ComboBox1.Activate End With End Sub

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 338 Dienstag, 4. Dezember 2007 1:42 13

Listing 192

Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '===================================================================

Steuerelemente

Steuerelemente

In der äußeren If...Then...Else-Anweisung wird die gedrückte Taste überprüft. Entspricht diese der angegebenen Konstante vbKeyTab, steht fest, dass die (Tab)-Taste gedrückt wurde. Jetzt muss noch ermittelt werden, ob der Benutzer zusätzlich die (Shift)-Taste betätigt hat, da mit dieser Kombination ein Rückwärtsspringen zu Steuerelementen gängig ist. Die Variable Shift weist den Wert 1 auf, wenn die SHIFTTaste gedrückt wurde. Demzufolge wird das vorherige Steuerelement CommandButton1 aktiviert. Andernfalls wird die nachfolgende TextBox1 aktiviert.

Steuerelemente

Nachdem Sie im Kombinationsfeld ComboBox1 einen Benutzer ausgewählt haben, können Sie mit der TABULATOR-Taste zum nächsten Steuerelement TextBox1 wechseln. Dies wird durch die hinterlegte ComboBox1_KeyDown-Ereignisprozedur ermöglicht.

Private Sub ComboBox1_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) If KeyCode = vbKeyTab Then If Shift = 1 Then ' Rückwärts springen CommandButton1.Activate Listing 193

Private Sub TextBox1_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) If KeyCode = vbKeyTab Then If Shift = 1 Then ' Rückwärts springen ComboBox1.Activate Else ' Vorwärts springen ToggleButton1.Activate End If End If End Sub Listing 194

Wenn das Textfeld aktiviert wird, also den Fokus erhält, soll ein evtl. noch vorhandener Text entfernt werden. Dieser Vorgang wird im TextBox1_GotFocus-Ereignis vorgenommen. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '=================================================================== Private Sub TextBox1_GotFocus() TextBox1.Text = "" End Sub Listing 195

Steuerelemente Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '===================================================================

Steuerelemente

Die gleiche Vorgehensweise gilt für das Textfeld. Mit (Tab), bzw. (Shift) (Tab) wechseln Sie zum nachfolgenden, bzw. vorherigen Steuerelement.

Steuerelemente

Listing 193 (Forts.)

Steuerelemente

Else ' Vorwärts springen TextBox1.Activate End If End If End Sub

Steuerelemente

339

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 339 Dienstag, 4. Dezember 2007 1:42 13

340 >> Tabellenblatt-Zugriffe mit Steuerelementen verwalten

Bei der verwendeten Umschaltfläche ToggleButton HELP und Befehlsschaltfläche LOGIN wird neben dem KeyDown-Ereignis auch das Click-Ereignis eingesetzt. Dieses wird normalerweise ausgeführt, wenn der Benutzer mit der Maustaste draufklickt. Ein Klick auf die Umschaltfläche HELP zeigt ein Bezeichnungsfeld mit Informationen der verwendeten Passwörter an, bzw. blendet es aus (siehe Abbildung 125).

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 340 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 125: Bezeichnungsfeld über Umschaltfläche anzeigen

Nachdem die Visible-Eigenschaft des Label1 nach dem Wert des ToggleButton1 eingestellt wurde, wird der Beschriftungstext der Umschaltfläche über die IIf-Funktion festgelegt. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_XControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '=================================================================== Private Sub ToggleButton1_Click() Label1.Visible = ToggleButton1.Value ToggleButton1.Caption = _ IIf(ToggleButton1.Value, "Close HELP", "H E L P") End Sub

Steuerelemente

Listing 196

Public Sub LabelText() Worksheets("Start").Label1.Caption = _ "Blattschutz" & vbTab & "Codebook" & Chr(10) & _ "----------------------------------" & Chr(10) & _ "Name" & vbTab & vbTab & "Passwort" & Chr(10) & _ "-------" & vbTab & vbTab & "-----------" & Chr(10) & _ "Admin" & vbTab & vbTab & "Admin" & Chr(10) & _ "Melanie" & vbTab & "MB" & Chr(10) & _ "Michael" & vbTab & "MS" & Chr(10) & _ "Brigitte" & vbTab & "BB" End Sub Listing 197

Wenn Sie bei aktivierter Umschaltfläche die TABULATOR-Taste drücken, soll wie bei den bereits genannten Steuerelementen das nachfolgende, bzw. vorherige Element aktiviert werden. Diese Prüfung wird in der folgenden ToggleButton1_KeyDown-Prozedur in einer Select Case-Anweisung vorgenommen. Ein Druck auf die (Enter)-Taste soll bei aktivierter Umschaltfläche den Wert des ToggleButon1 umkehren und dadurch das Bezeichnungsfeld ein- oder ausblenden. Die (Enter)-Taste hat also die gleiche Auswirkung auf das Steuerelement wie ein Mausklick. Durch den Not-Operator wird eine logische Umkehrung der Value-Eigenschaft des ToggleButton1 erzielt. Durch die Umkehrung, also Änderung des ToggleButtons1-Wertes, wird das Change-Ereignis dieses Elementes ausgelöst. Damit es bei der weiteren Verarbeitung von Code nicht zu Fehlern kommt, wird die Variable KEYCODE auf 0 zurückgesetzt.

Steuerelemente Steuerelemente Steuerelemente

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Modul mdl_01_LabelText '===================================================================

Steuerelemente

Die Gestaltung und Formatierung des Textes eines Bezeichnungsfeldes gestaltet sich über die Eingabezeile im Eigenschaften-Fenster sehr schwierig. Umfangreicher Text muss in der Caption-Eigenschaft in eine Zeile geschrieben werden. Im Eigenschaftenfenster können keine manuellen Zeilenumbrüche oder Ausrichtungen innerhalb des Textes vorgenommen werden. In unserem Beispiel wurde deshalb der Beschriftungstext über die Prozedur LabelText an das Bezeichnungsfeld zugewiesen. Durch die vbTab-Konstante wird ein Tabulatorzeichen erzeugt, welches die linksbündige Ausrichtung in der rechten Hälfte des Labels ermöglicht. Mit vbCrLf wird eine Kombination aus Wagenrücklauf und Zeilenvorschub bewirkt. Das Ergebnis zeigt Ihnen die Abbildung 125.

Steuerelemente

In realen Projekten ist es natürlich nicht ratsam, die geheimen Passwörter gleich mitzuliefern. Sie können dem Anwender aber andere wichtige Informationen über das Bezeichnungsfeld mitteilen.

Steuerelemente

341

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 341 Dienstag, 4. Dezember 2007 1:42 13

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 342 Dienstag, 4. Dezember 2007 1:42 13

342 >> Tabellenblatt-Zugriffe mit Steuerelementen verwalten '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '=================================================================== Private Sub ToggleButton1_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) Select Case KeyCode Case vbKeyTab If Shift = 1 Then ' Rückwärts springen TextBox1.Activate Else ' Vorwärts springen CommandButton1.Activate End If Case vbKeyReturn ' ToggleButton-Wert umkehren ToggleButton1.Value = Not ToggleButton1.Value KeyCode = 0 End Select End Sub Listing 198

Bei einem Klick auf die Befehlsschaltfläche LOGIN wird zunächst geprüft, ob ein Benutzerkonto ausgewählt und ein Passwort in das Textfeld eingegeben wurde. Anschließend wird das hinterlegte Passwort des ausgewählten Benutzers im Tabellenblatt ADMIN ausgelesen und an die Variable strPassword übergeben. Je nach ausgewähltem Benutzerkonto werden entweder alle Tabellenblätter der Beispieldatei oder nur jenes des ausgewählten Benutzers angezeigt und aktiviert. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '=================================================================== Private Sub CommandButton1_Click() Dim strPassword As String Dim wks As Worksheet

Steuerelemente

' ComboBox1 überprüfen If ComboBox1.Value = "" Then Listing 199

' Passwort aus Sheet "Admin" auslesen strPassword = Worksheets("Admin").Columns("A") _ .Find(ComboBox1.Value, , xlValues) _ .Offset(0, 1).Value ' Bei falscher Passworteingabe verlasse Prozedur If TextBox1.Text strPassword Then MsgBox "Das Passwort ist falsch!", vbCritical With TextBox1 .Text = "" .Activate End With Exit Sub End If

Steuerelemente Steuerelemente

' TextBox1 überprüfen If TextBox1.Text = "" Then MsgBox "Geben Sie ein Passwort ein.", _ vbOKOnly + vbInformation TextBox1.Activate Exit Sub End If

Steuerelemente

MsgBox "Wählen Sie ein Benutzerkonto.", _ vbOKOnly + vbInformation ComboBox1.Activate Exit Sub End If

343

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 343 Dienstag, 4. Dezember 2007 1:42 13

If ComboBox1.Value = "Admin" Then ' Alle Blätter einblenden For Each wks In ThisWorkbook.Worksheets wks.Visible = xlSheetVisible Next wks

Steuerelemente

Application.ScreenUpdating = False

Listing 199 (Forts.)

Steuerelemente

' Alle Blätter bis auf Start-Blatt ausblenden For Each wks In ThisWorkbook.Worksheets If wks.Name "Start" Then _ wks.Visible = xlSheetVeryHidden Next wks

Steuerelemente

Else

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 344 Dienstag, 4. Dezember 2007 1:42 13

344 >> Tabellenblatt-Zugriffe mit Steuerelementen verwalten End If ' Tabellenblatt des Anmelders anzeigen With Worksheets(ComboBox1.Value) .Visible = xlSheetVisible .Activate End With Application.ScreenUpdating = True End Sub Listing 199 (Forts.)

Das Click-Ereignis des CommandButton1 können Sie auch auslösen, indem Sie bei aktiviertem Element die (Enter)- oder (Return)-Taste drücken. Wenn in der Select CaseAnweisung die Konstante vbKeyReturn für die Eingabe-Taste ermittelt wird, bewirkt die Aufrufzeile des CommandButton1_Click-Ereignisses den Start desselben. Vergessen Sie nicht die Variable KeyCode auf 0 zurückzusetzen. Bei der weiteren Verarbeitung von Code kann es unter Umständen sonst zu Fehlermeldungen kommen. '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '=================================================================== Private Sub CommandButton1_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) Select Case KeyCode Case vbKeyTab If Shift = 1 Then ' Rückwärts springen ToggleButton1.Activate Else ' Vorwärts springen ComboBox1.Activate End If Case vbKeyReturn ' Schaltfläche-Ereignis aufrufen CommandButton1_Click KeyCode = 0 End Select End Sub Listing 200

'=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Modul mdl_02_HideSheets '=================================================================== Public Sub HideSheets() Dim wks As Worksheet Application.ScreenUpdating = False ' Alle Blätter bis auf Start-Blatt ausblenden For Each wks In ThisWorkbook.Worksheets If wks.Name "Start" Then wks.Visible = xlSheetVeryHidden End If Next wks

Steuerelemente

Um den Ausgangszustand, also nur das Start-Blatt anzuzeigen, verwenden wir die Prozedur HideSheets. Nachdem die Benutzerblätter ausgeblendet wurden, wird das Tabellenblatt START geschützt und die Steuerelemente auf ihren Ausgangszustand zurückgesetzt. Abschließend wird die Datei gespeichert, damit sie beim nächsten Öffnen in diesem Zustand angezeigt wird.

Steuerelemente

345

Steuerelemente

>> Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 345 Dienstag, 4. Dezember 2007 1:42 13

Die Prozedur HideSheets wird beim Schließen der Datei und Aktivierung des Tabellenblattes START von den entsprechenden Ereignissen Workbook_BeforeClose und Worksheet_Activate aufgerufen.

Steuerelemente

Listing 201

Steuerelemente

' Datei speichern ThisWorkbook.Save End Sub

Steuerelemente

With Worksheets("Start") .Protect "Codebook" .ComboBox1.Value = "" .TextBox1.Text = "" .ToggleButton1.Value = False End With

Steuerelemente

Application.ScreenUpdating = True

Steuerelemente

Steuerelemente

2471_Excel-VBA.book Seite 346 Dienstag, 4. Dezember 2007 1:42 13

346 >> Tabellenblatt-Zugriffe mit Steuerelementen verwalten '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_BeforeClose(Cancel As Boolean) HideSheets End Sub

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Steuerelemente

Listing 202 '=================================================================== ' Auf CD Buchdaten\Beispiele\05_Steuerelemente\ ' Dateiname 05_03_ControlsKeyCode.xlsm ' Ereignis Tabelle1 (Start) '=================================================================== Private Sub Worksheet_Activate() HideSheets End Sub Listing 203

In früheren Versionen von Microsoft Office haben Entwickler das COMMANDBARSObjektmodell zur Entwicklung des Visual Basic-Codes verwendet, mit dem die Benutzeroberfläche angepasst werden konnte. In Excel 2007 lässt sich dieser ältere Code meist ohne Änderungen weiter verwenden. Neue Befehle auf Symbolleisten werden in Excel 2007 jedoch in Gruppen auf der Registerkarte Add-Ins angezeigt. Die Art der angezeigten Anpassung hängt vom ursprünglichen Design des Add-Ins ab. So erstellt Excel beispielsweise eine Gruppe MENÜBEFEHLE, in der die in der früheren Menüstruktur (Menü DATEI, Menü EINFÜGEN, Menü EXTRAS usw.) hinzugefügten Elemente enthalten sind. In der Gruppe SYMBOLLEISTENBEFEHLE werden Elemente angezeigt, die in den früheren integrierten Symbolleisten (Symbolleiste STANDARD, Symbolleiste FORMAT, Symbolleiste GRAFIK usw.) hinzugefügt wurden. Alle selbst definierten benutzerdefinierten Symbolleisten werden in der Gruppe BENUTZERDEFINIERTE SYMBOLLEISTEN auf der Registerkarte ADD-INS angezeigt. Das komplette Objektmodell der COMMANDBARS und CONTROLS ist jedoch weiterhin in Office 2007 enthalten. Wenn Sie ältere Excel-Anwendungen in Excel 2007 öffnen, werden die meisten Prozeduren mit Zugriff auf Befehlsleisten ohne Modifikation einwandfrei funktionieren.

Befehlsleisten Befehlsleisten Befehlsleisten

Eine ausführliche Beschreibung und Beispiele im Umgang mit der RibbonBenutzerschnittstelle finden Sie in Kapitel »RibbonX«.

Befehlsleisten

Hinweis

Mit Excel 2007 hat sich die Oberfläche und Struktur der Menüs und Befehlsaufrufe grundlegend verändert. Bis auf wenige Ausnahmen sind die Symbolleisten durch Ribbons (zu Deutsch Multifunktionsleisten) ersetzt worden.

Befehlsleisten

Alle älteren Versionen von Microsoft Excel bis einschließlich Excel 2003 enthalten zwei verschiedene Menüleisten (Arbeitsblatt- und Diagrammmenüleiste) sowie dutzende von integrierten Befehlsleisten und Kontextmenüs und können um beliebig viele benutzerdefinierte Symbolleisten erweitert werden.

Befehlsleisten

142 Einführung

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 347 Dienstag, 4. Dezember 2007 1:42 13

Achtung

348 >> Einführung

VBA Code, der Schaltflächen und Elemente über ihre ID-Eigenschaft auf einer Symbolleiste erstellt hat, wird in Excel 2007 nicht mehr ausgeführt. Ebenso versagt die COPY-Methode, welche einen integrierten Befehl von einer Symbolleiste auf eine benutzerdefinierte Symbolleiste kopiert hat, wenn der zu kopierende Befehl in Excel 2007 nicht mehr zur Verfügung steht. Da in beiden Fällen keine Fehlermeldung auf die fehlenden Elemente aufmerksam macht, ist jede Anwendung bei Verwendung in Excel 2007 zu überprüfen und fehlende Funktionen gegebenenfalls durch eigene Prozeduren zu ersetzen.

Alle Prozeduren, die wir Ihnen in dieser Kategorie vorstellen, wurden von Excel 2000 bis Excel 2007 getestet. Teilweise werden einige Befehle nur noch bis Excel 2003 ausgeführt, verursachen aber bei der Verwendung unter Excel 2007 keinen Fehler. Bis Excel 2003 war es möglich integrierte Befehle auf einer beliebigen Symbolleiste hinzuzufügen, oder eigene benutzerdefinierte Symbolleisten zu definieren. In Office 2007 ist die Schnellzugriffleiste (QAT = Quick ACCESS Toolbar) als einzige von den Symbolleisten früherer Versionen übrig geblieben.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 348 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Abbildung 126: Schnellzugriffleiste in Excel 2007

Diese Schnellzugriffleiste ist die einzige Leiste, die Veränderungen durch den Benutzer direkt zulässt und die angepasst werden kann. Anpassungen sind entweder manuell vom Benutzer möglich oder mit Hilfe der Ribbon-Benutzerschnittstelle. Es gibt in der Excel Bibliothek unter VBA kein Objekt um auf die Schnellzugriffleiste Einfluss zu nehmen. Änderungen an der Schnellzugriffleiste werden in der Datei Excel.qat gespeichert, die im Ordner C:\Dokumente und Einstellungen\Benutzername\Lokale Einstellungen\Anwendungsdaten\Microsoft\Office hinterlegt ist. Die Datei Excel.qat ist nur dann im angegebenen Ordner verfügbar, wenn Änderungen an der Schnellzugriffleiste vorgenommen wurden. Anpassungen

Sicherlich werden Sie jetzt fragen, wofür man die Symbolleisten denn in Excel 2007 noch verwenden kann. Nun, das liegt auf der Hand. Wenn Sie Excel-Anwendungen in einer früheren Excel-Version erstellt haben, würde Excel 2007 ohne Kenntnis dieser Objekte beim Zugriff auf diese Objekte einen Fehler ausgeben. Die Prozedur zu dem unten angegebenen Beispiel listet alle integrierten und benutzerdefinierten Befehlsleisten im Tabellenblatt MYCOMMANDBARS der Beispieldatei auf. In einer For...Each-Schleife wird jede Befehlsleiste durchlaufen. Über die TypeEigenschaft wird anschließend in einer Select Case-Anweisung der Typ der Befehlleiste ermittelt und an die Variable strType übergeben. Konstante

Wert

Befehlsleiste

msoBarTypeMenuBar

1

Menüleiste

msoBarTypeNormal

0

Symbolleiste

msoBarTypePopup

2

Kontextmenü

Tabelle 31: Konstanten des CommandBar-Objektes

Klicken Sie in der nachfolgend genannten Beispieldatei in dem Tabellenblatt START auf die Schaltfläche BEFEHLSLEISTEN AUFLISTEN. Die hinterlegte Prozedur ListCommandBars wird gestartet und gibt im Tabellenblatt MYCOMMANDBARS zu jeder Leiste zeilenweise Informationen aus. Über die Index-Eigenschaft erfahren Sie die Indexnummer. strType gibt den ermittelten Leistentyp zurück. Excel kennt zu jeder Befehlsleiste zwei Namen. Bei einer integrierten Befehlsleiste gibt die Name-Eigenschaft den US-englischen Namen der Befehlsleiste zurück. Mit der NameLocal-Eigenschaft erhalten Sie den übersetzten Namen. Der lokale Name einer Befehlsleiste wird in der Quickinfo eines jeden Schaltflächenelementes vor dem Prozedurnamen ausgegeben. Die BuiltIn-Eigenschaft gibt einen booleschen Wert zurück, der besagt, ob die Befehlsleiste integriert oder benutzerdefiniert ist. True steht dabei für integriert. False für benutzerdefiniert.

Befehlsleisten Befehlsleisten

Bis auf die in Excel integrierten Kontextmenüs ist es jedoch nicht möglich die alten Menü- oder Symbolleisten in Excel 2007 anzuzeigen. Eine Überprüfung mittels der Visible- oder Enabled-Eigenschaft wird zwar bei diesen Leisten jeweils mit True oder False angegeben. Jedoch bleibt jeder Versuch, eine der integrierten Befehlsleisten anzuzeigen, erfolglos.

Befehlsleisten

Obwohl in Office 2007 standardmäßig keine Symbolleisten mehr zur Benutzung angeboten werden, führt die neueste Excel-Version noch sämtliche integrierte Menü-, Symbolleisten und Kontextmenüs aus Excel 2003 im Hintergrund mit sich mit.

Befehlsleisten

143 Integrierte Befehlsleisten ermitteln

Befehlsleisten

werden just in time in der Datei aktualisiert und nicht wie bei der Symbolleistendatei *.xlb erst bei Beendigung der Excel-Anwendung.

Befehlsleisten

349

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 349 Dienstag, 4. Dezember 2007 1:42 13

350 >> Integrierte Befehlsleisten ermitteln

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 350 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 127: Auflistung aller Befehlsleisten '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Start ' Modul mdl_01_ListCommandBars '=================================================================== Public Dim Dim Dim

Sub ListCommandBars() cmb As CommandBar lngRow As Long strType As String

Application.ScreenUpdating = False lngRow = 1 With Worksheets("MyCommandBars") .Cells.ClearContents .Range("A1").Value = "Index" .Range("B1").Value = "Typ" .Range("C1").Value = "Name" .Range("D1").Value = "Lokaler Name" .Range("E1").Value = "Integriert" .Range("A1:E1").Font.Bold = True

Befehlsleisten

For Each cmb In Application.CommandBars Select Case cmb.Type Listing 204

Case msoBarTypeMenuBar strType = "Menüleiste" Case msoBarTypeNormal strType = "Symbolleiste" Case msoBarTypePopup strType = "Kontextmenü" End Select lngRow = lngRow + .Cells(lngRow, 1) .Cells(lngRow, 2) .Cells(lngRow, 3) .Cells(lngRow, 4) .Cells(lngRow, 5) Next cmb End With

1 = = = = =

cmb.Index strType cmb.Name cmb.NameLocal cmb.BuiltIn

Befehlsleisten

351

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 351 Dienstag, 4. Dezember 2007 1:42 13

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '=================================================================== Public Sub GetPopups() Dim cmb As CommandBar Dim lngRow As Long Listing 205

Befehlsleisten

Um eine Übersicht aller Kontextmenüs zu erhalten, kann das Konzept aus dem vorherigen Beispiel verwendet werden. Hier werden innerhalb der For...Each-Schleife in einer If-Abfrage die CommandBars-Auflistung auf Kontextmenüs überprüft und die Ergebnisse im Tabellenblatt aufgelistet.

Befehlsleisten

Wie bereits angesprochen, ist es in Excel 2007 nicht mehr möglich integrierte Symbolleisten zu verändern. Was geblieben ist, sind die Kontextmenüs, die nach einem Klick mit der rechten Maustaste ein Menü aus Befehlen zur Verfügung stellen. Die Auswahl der Befehle richtet sich danach, welches Objekt zum Zeitpunkt des Aufrufs aktiv ist.

Befehlsleisten

144 Kontextmenüs ermitteln

Befehlsleisten

Listing 204 (Forts.)

Befehlsleisten

Application.ScreenUpdating = True End Sub

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 352 Dienstag, 4. Dezember 2007 1:42 13

352 >> Kontextmenüs ermitteln Application.ScreenUpdating = False lngRow = 1 With Worksheets("ShowPopUp") ' alte Werte löschen .Columns("A:E").ClearContents ' Überschriftenzeile aufbereiten .Range("A1:E1").Value = Array("Index", "ID", "Name", _ "Lokaler Name", "Integriert") For Each cmb In Application.CommandBars If cmb.Type = msoBarTypePopup Then ' Prüfung, ob Befehlsleiste ein Kontextmenü ist lngRow = lngRow + 1 .Cells(lngRow, 1) = cmb.Index .Cells(lngRow, 2) = cmb.ID .Cells(lngRow, 3) = cmb.Name .Cells(lngRow, 4) = cmb.NameLocal .Cells(lngRow, 5) = cmb.BuiltIn .Cells(lngRow, 5) = cmb.BuiltIn End If Next cmb End With

Listing 205 (Forts.)

Befehlsleisten

Befehlsleisten

Befehlsleisten

Application.ScreenUpdating = True End Sub

Befehlsleisten

Abbildung 128: Liste der Kontextmenüs in Excel 2007

Public Sub DisablePopUps() ' Alle Kontextmenüs deaktivieren ChangePopUpStatus False End Sub Public Sub EnablePopUps() ' Alle Kontextmenüs aktivieren ChangePopUpStatus True End Sub Public Sub ChangePopUpStatus(blnEnabled As Boolean) Dim cmb As CommandBar For Each cmb In Application.CommandBars ' Prüfung, ob Befehlsleiste ein Kontextmenü ist If cmb.Type = msoBarTypePopup Then ' Kontextmenü nach Übergabeparameter einstellen cmb.Enabled = blnEnabled End If Next cmb End Sub

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '===================================================================

Befehlsleisten

Über die Enabled-Eigenschaft können Sie die Anzeige und den Zugriff auf Kontextmenüs unterbinden. Folgende Prozedur de- bzw. aktiviert alle Kontextmenüs der Excel-Anwendung. Beim Aufruf der Prozedur ChangePopUpStatus wird ein boolescher Wert (True oder False) erwartet, der angibt, ob die Kontextmenüs de- oder aktiviert werden. Hierzu wurde in der Argumentenliste der Prozedur der Parameter blnEnabled definiert.

Befehlsleisten

145 Kontextmenüs deaktivieren

Befehlsleisten

353

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 353 Dienstag, 4. Dezember 2007 1:42 13

Kontextmenü

Beschreibung

Cell

Kontextmenü der Zellen

Column

Kontextmenü der Spaltenköpfe

Tabelle 32: Die meistgenutzten Kontextmenüs

Befehlsleisten

Um gezielt ein spezielles Kontextmenü zu deaktivieren sind in der nachfolgenden Tabelle die gängigsten Kontextmenüs aufgeführt.

Befehlsleisten

Listing 206

354 >> Kontextmenüs deaktivieren Kontextmenü

Beschreibung

Row

Kontextmenü der Zeilenköpfe

Ply

Kontextmenü der Blattregisterkarten

Workbook Tabs

Kontextmenü der Arbeitsmappen-Registerkarte (Auflistung aller Tabellen- und Diagrammblätter der aktiven Arbeitsmappe)

Tabelle 32: Die meistgenutzten Kontextmenüs (Forts.)

Hinweis

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 354 Dienstag, 4. Dezember 2007 1:42 13

Eine Übersicht aller Kontextmenüs finden Sie in der Beispieldatei aus Rezept 144.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Folgende Prozeduren de- bzw. aktivieren das Kontextmenü der Blattregisterkarten. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '=================================================================== Public Sub DisablePlyCmb() ' Kontextmenü der Blattregisterkarten deaktivieren Application.CommandBars("Ply").Enabled = False End Sub Public Sub EnablePlyCmb() ' Kontextmenü der Blattregisterkarten aktivieren Application.CommandBars("Ply").Enabled = True End Sub Listing 207

In der Liste der integrierten Kontextmenüs werden einige Befehlsleisten doppelt aufgeführt (siehe Abbildung 128). 왘 Cell (Zelle) 왘 Column (Spalte) 왘 Row (Zeile) Der Grund liegt darin, dass sowohl für die Ansichten Normal und Seitenlayout als auch für die Seitenumbruchvorschau jeweils ein eigenes Kontextmenü zur Verfügung gestellt wird. Für welche Ansicht welches Kontextmenü gültig ist, lässt sich nur anhand der ID feststellen.

355

Name

Lokaler Name

ID

Ansicht

Cell

Zelle

424

Normal/Seitenlayout

Row

Zeile

425

Normal/Seitenlayout

Column

Spalte

426

Normal/Seitenlayout

Cell

Zelle

427

Seitenumbruchvorschau

Row

Zeile

428

Seitenumbruchvorschau

Column

Spalte

429

Seitenumbruchvorschau

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 355 Dienstag, 4. Dezember 2007 1:42 13

Erfolgt die Referenzierung über den Namen, dann wird bei gleichnamigen Elementen die erste Befehlsleiste mit dem angegebenen Namen aus der Auflistung angenommen. Eine eindeutige Referenzierung gleichnamiger Befehlsleisten ist demnach nur über den Index der CommandBars-Auflistung möglich. Aus diesem Grund ist die Ermittlung der Indexe zur eindeutigen Identifizierung in jeder Excel-Applikation unerlässlich. Entsprechend unserer CommandBars-Auflistung aus Listing 144 haben die Cell-Kontextmenüs die Indexe 36 und 39. Mit der ShowPopUp-Methode können sie direkt angezeigt werden: Application.CommandBars(36).ShowPopup ' Zelle - Normalansicht

Abbildung 129: Zellen-Kontextmenüs der Excel-Applikation

Befehlsleisten Befehlsleisten

Befehlsleisten

Befehlsleisten

Application.CommandBars(39).ShowPopup ' Zelle - Seitenumbruchvorschau

Befehlsleisten

Um ein Kontextmenü zu bearbeiten oder anzuzeigen, muss entweder dessen Name oder der Index aus der CommandBars-Auflistung angegeben werden, ein Zugriff über die ID ist nicht möglich.

Befehlsleisten

Achtung

Tabelle 33: Gleichnamige Kontextmenüs

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 356 Dienstag, 4. Dezember 2007 1:42 13

356 >> Kontextmenüs deaktivieren

Um zum Beispiel das Zellen-Kontextmenü in allen Ansichten zu bearbeiten oder zu deaktivieren, müssen beide CELL-Symbolleisten im VBA Code über deren Index referenziert werden. Der Index des ersten Zellen-Kontextmenüs lässt sich einfach über die Name-Eigenschaft ermitteln: lngIndex = Application.CommandBars(strPopUp).Index

Um den Index des Zellen-Kontextmenüs der Seitenumbruchvorschau zu ermitteln, wird zunächst der Index des ersten Zellen-Kontextmenüs aus der Normalansicht ermittelt. Laut der Tabelle 33 befinden sich die entsprechenden gleichnamigen Befehlsleisten in der CommandBars-Auflistung genau 3 Indexe weiter. Über diese Berechnung können Kontextmenüs mit gleicher Bezeichnung in einer Prozedur deoder aktiviert werden. In der Beispielprozedur werden in der Argumentenliste die Parameter strPopup und blnEnabled deklariert. Beim Aufruf der Prozedur muss der Name der Befehlsleiste

angegeben werden, gefolgt von einem booleschen Wert, der angibt, ob die genannte Befehlsleiste de- oder aktiviert wird.

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '=================================================================== Public Sub CallSetPopUp() ' beide Zellen-Kontextmenüs deaktivieren SetPopup "Cell", False End Sub Public Sub SetPopup(strPopUp As String, blnEnabled As Boolean) ' strPopUp erwartet Cell, Row oder Column ' blnEnabled = True -> Kontextmenü aktivieren ' blnEnabled = False -> Kontextmenü deaktivieren Dim lngIndex As Long ' Index des Kontextmenüs der Normalansicht lngIndex = Application.CommandBars(strPopUp).Index Application.CommandBars(lngIndex).Enabled = blnEnabled ' Index des Kontextmenüs der Seitenumbruchvorschau lngIndex = lngIndex + 3 Application.CommandBars(lngIndex).Enabled = blnEnabled End Sub

Befehlsleisten

Listing 208

357

Änderungen an den Kontextmenüs wirken sich auf alle geöffneten Arbeitsmappen der Excel Instanz aus und nicht nur auf die Arbeitsmappe, aus welcher der Code aufgerufen wurde. Wie in Excel 2003 und in älteren Versionen bleiben deaktivierte Kontextmenüs beim Beenden und Neustart von Excel 2007 weiterhin deaktiviert. Achten Sie also darauf, beim Verlassen Ihrer Excel-Datei alle Symbolleisten wieder in den Normalzustand zu versetzen und für andere Anwendungen zu aktivieren.

Befehlsleisten

Tipp

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 357 Dienstag, 4. Dezember 2007 1:42 13

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '=================================================================== Public Sub ResetPopUps() Dim cmb As CommandBar For Each cmb In Application.CommandBars ' Prüfung, ob Befehlsleiste ein Kontextmenü ist If cmb.Type = msoBarTypePopup Then ' Prüfung, ob Kontextmenü integriert ist If cmb.BuiltIn = True Then ' integriertes Kontextmenü zurücksetzen cmb.Reset Listing 210

Befehlsleisten Befehlsleisten

Listing 209

Befehlsleisten

Private Sub Workbook_Deactivate() ' Alle Kontextmenüs zurücksetzen ResetPopUps End Sub

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Modul DieseArbeitsmappe '===================================================================

Befehlsleisten

Wenn Änderungen an Kontextmenüs nur in einer Datei verfügbar sein sollen, müssen alle betroffenen Kontextmenüs beim Wechseln zu anderen Arbeitsmappen zurückgesetzt werden. Hierzu eignet sich das Workbook_Deactivate-Ereignis im Klassenmodul DieseArbeitsmappe, welches den hinterlegten Code automatisch ausführt, wenn eine andere Arbeitsmappe aktiviert wird.

Befehlsleisten

146 Kontextmenüs zurücksetzen

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 358 Dienstag, 4. Dezember 2007 1:42 13

358 >> Menüs und Steuerelemente ermitteln ' benutzerdefiniertes Kontextmenü aktivieren cmb.Enabled = True End If End If Next cmb End Sub Listing 210 (Forts.)

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

147 Menüs und Steuerelemente ermitteln Auf jeder Befehlsleiste können sich beliebig viele Steuerelemente, so genannte Controls, befinden. In diesem Beispiel wird aufgezeigt, wie man alle Controls einer Symbolleiste auslesen kann. Dabei ist es unerheblich, von welchem Typ die Symbolleiste ist, oder ob sie integriert oder benutzerdefiniert ist. Im Tabellenblatt START der Beispieldatei wurde der Zelle F12 ein Auswahlfeld über die Funktion DATENPRÜFUNG hinterlegt. Diese Funktion war bereits in älteren ExcelVersionen unter dem Begriff GÜLTIGKEITSPRÜFUNG verfügbar. Das Dialogfeld DATENPRÜFUNG wird in Excel 2007 über den Menüpunkt DATEN | DATENTOOLS | DATENÜBERPRÜFUNG aufgerufen. Im Register EINSTELLUNGEN wurde als Gültigkeitskriterium eine LISTE, bestehend aus dem benannten Bereich LokalerName zugewiesen. Dieser enthält den Bereich der Spalte D des Tabellenblattes MYCOMMANDBARS mit den lokalen Namen der Befehlsleisten. Durch Auswahl einer Befehlsleiste aus dem Auswahlfeld der DATENÜBERPRÜFUNG wird in Zelle G12 über eine verschachtelte Tabellenfunktion der entsprechende englische Befehlsleistenname ausgegeben. Bei Klick auf die Schaltfläche SCHALTFLÄCHEN AUFLISTEN wird die Prozedur ListControls aufgerufen. An die Variable strcmb wird ein Verweis auf die ausgewählte Befehlsleiste (aus Zelle G12) übergeben. In der Zelle G12 muss entweder die Indexnummer der Leiste oder der englische Name zur Identifizierung angegeben werden. Im Tabellenblatt wird die Zelle G12 durch Auswahl der Nebenzelle (F12) ausgefüllt.

Über die Add-Methode wird an die letzte Stelle der Tabellenregister ein neues Tabellenblatt in die Arbeitsmappe eingefügt. Zu Beginn der With-Anweisung werden die Überschriften für das neue Tabellenblatt aufbereitet. Diese werden in den Bereich A1:D2 geschrieben. In der darauf folgenden For Each...Next-Anweisung wird jedes Steuerelement der Befehlsleiste durchlaufen. Über die Type-Eigenschaft wird anschließend ermittelt, ob es sich bei dem jeweiligen Befehlsleisten-Steuerelement um eine Schaltfläche vom Typ msoControlButton handelt. Ist dies der Fall, wird über die CopyFace-Methode das Symbol des angegebenen Schaltflächensteuerelements in die Zwischenablage kopiert. Mit der Paste-Methode wird das Symbol der Schaltfläche, auch FaceId genannt, als eigenständige Grafik im Tabellenblatt eingefügt. Da die Grafik durch den Kopier-Prozess bereits markiert ist, kann mit der Top- und Left-Eigenschaft des ShapeRange-

359

Objektes die Grafik in die gewünschte Zelle platziert werden. In die jeweilige Zeile des Steuerelementes wird noch die Index-Nummer, die ID für ein integriertes Befehlsleisten-Steuerelement und die Beschriftung des Elementes ausgegeben.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Da das letzte eingefügte Grafiksymbol markiert ist, wird die Markierung mit der GotoMethode in die Zelle A1 des aktiven Tabellenblattes gesetzt. Das Scroll-Argument wird dabei auf True gesetzt, um Bildläufe im Zielfenster durchzuführen.

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 359 Dienstag, 4. Dezember 2007 1:42 13

Sub ListControls() cmb As CommandBar ctl As CommandBarControl strcmb As String lngRow As Long

Listing 211

Befehlsleisten

Public Dim Dim Dim Dim

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Start ' Modul mdl_02_ListControls '===================================================================

Befehlsleisten

Abbildung 130: Schaltflächen und Befehle der Standard-Symbolleiste aus Excel 2003

360 >> Menüs und Steuerelemente ermitteln

' Prüfung, ob Verweis einen Fehler ausgelöst hat If Err.Number 0 Then MsgBox "Wählen Sie eine Symbolleiste aus dem Auswahlfeld aus." _ , vbInformation Exit Sub End If ' Fehlerhandler zurücksetzen On Error GoTo 0

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

lngRow = 2 On Error Resume Next strcmb = Range("G12").Value Set cmb = Application.CommandBars(strcmb)

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 360 Dienstag, 4. Dezember 2007 1:42 13

Worksheets.Add After:=Worksheets(Worksheets.Count) With ActiveSheet .Name = cmb.NameLocal .Range("A1").Value = cmb.Name .Range("A2").Value = "Index" .Range("B2").Value = "Symbol" .Range("C2").Value = "ID" .Range("D2").Value = "Name" .Range("A1:D2").Font.Bold = True For Each ctl In cmb.Controls lngRow = lngRow + 1 If ctl.Type = msoControlButton Then ctl.CopyFace ActiveSheet.Paste Selection.ShapeRange.Top = Cells(lngRow, 2).Top Selection.ShapeRange.Left = Cells(lngRow, 2).Left + 13 End If Cells(lngRow, 1) = ctl.Index Cells(lngRow, 3) = ctl.ID Cells(lngRow, 4) = ctl.Caption Next ctl End With Application.Goto Range("A1"), Scroll:= True End Sub Listing 211 (Forts.)

148 Benutzerdefinierte Menübefehle hinzufügen In vielen Excel-Anwendungen bis Excel 2003 wurden die Menü- oder andere Symbolleisten mittels VBA Code verändert. Es wurden neue Menübefehle hinzugefügt oder Standardmenüs deaktiviert oder ausgeblendet. Excel 2007 versucht nach Möglichkeit jeden Code mit Zugriff auf das COMMANDBARS Objektmodell auszuführen. Dabei ist es jedoch nicht möglich, Menübefehle aus älteren Excel-Versionen zu deaktivieren oder auszublenden. Da diese in Excel 2007 über die RIBBON-Benutzerschnittstelle dargestellt werden, können sie auch nur über dieses Objekt bearbeitet werden.

Application.CommandBars.ActiveMenuBar

Beim Erzeugen einer neuen Schaltfläche sollte der Wert des optionalen TemporaryArgumentes auf True gesetzt werden, um das neue Steuerelement vorübergehend zu erstellen. Bis einschließlich Excel 2007 werden temporäre Steuerelemente beim

Befehlsleisten

In Excel 2007 gibt es keine Menüleisten im eigentlichen Sinne mehr. Alle Befehle, die auf verschiedenen Menüleisten erstellt werden, werden in der gleichen Gruppe MENÜBEFEHLE angeordnet. Beim Löschen einzelner Befehle müssen die exakten Referenzierungen bei Erstellung der einzelnen Controls genau eingehalten werden. Um dabei mögliche Fehler auszuschließen, ist es ratsam keine spezielle Menüleiste anzugeben, sondern sich sowohl beim Erstellen als auch beim Löschen auf die aktive Menüleiste zu beziehen.

Befehlsleisten

Neben bereits bestehenden Anwendungen aus früheren Excel-Versionen ist es in Excel 2007 immer noch möglich über das COMMANDBAR-Objekt dem Anwender benutzerdefinierte Befehle zur Verfügung zu stellen. Diese Methode setzt lediglich voraus, dass die Datei in einem für Makros erlaubten Dateiformat (Excel 97-2003 Dateiformate oder *.xlsm, *xlsb, *xltm, *xlam) gespeichert wird, da der Code weiterhin mit der Arbeitsmappe mitgeführt wird.

Befehlsleisten

Abbildung 131: Menübefehle in Excel 2007

Befehlsleisten

Befehlsleisten

Wann immer mittels Code auf einer Menüleiste ein Steuerelement hinzugefügt wird, wird der Register ADD-INS sichtbar und der neue Befehl in der Gruppe MENÜBEFEHLE angezeigt (siehe Abbildung 131). Es spielt dabei keine Rolle, an welcher Stelle der Befehl in älteren Excel-Versionen platziert wurde. Alle hinzugefügten Befehle werden in der Reihenfolge ihrer Erstellung von oben nach unten und von links nach rechts angezeigt.

Befehlsleisten

361

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 361 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 362 Dienstag, 4. Dezember 2007 1:42 13

362 >> Benutzerdefinierte Menübefehle hinzufügen

Schließen der Excel-Anwendung automatisch gelöscht. Nicht temporäre Steuerelemente werden auch nach Neustart der Excel-Anwendung so lange angezeigt, bis sie manuell oder mittels Code gelöscht werden. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_04_AddMenuCommand '=================================================================== Public Dim Dim Dim

Sub AddMenuCommand() cmdBar As CommandBar ctl As CommandBarButton strCaption As String

' Aktive Menüleiste Set cmdBar = Application.CommandBars.ActiveMenuBar ' Schaltflächen Name und Bezeichnung zusammensetzen strCaption = "Button on the " & cmdBar.Name ' Evtl. bereits vorhandenes gleichnamiges Element löschen On Error Resume Next cmdBar.Controls(strCaption).Delete On Error GoTo 0 ' Schaltfläche einfügen Set ctl = cmdBar.Controls.Add( _ Type:=msoControlButton, _ Temporary:=True) With ctl .Caption = strCaption .Style = msoButtonCaption .OnAction = "MyMacro" End With End Sub

Befehlsleisten

Befehlsleisten

Listing 212

Klickt der Benutzer auf die neu erstellte Schaltfläche, wird die in der ONACTIONEigenschaft hinterlegte Prozedur aufgerufen.

363

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_04_AddMenuCommand '=================================================================== Public Sub MyMacro() MsgBox "Hello " & Application.UserName End Sub

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 363 Dienstag, 4. Dezember 2007 1:42 13

Set cmdBar = Application.CommandBars.ActiveMenuBar ' Evtl. bereits vorhandenes gleichnamiges Element löschen On Error Resume Next cmdBar.FindControl(Tag:="My Button").Delete On Error GoTo 0 ' Schaltfläche einfügen Set ctl = cmdBar.Controls.Add( _ Type:=msoControlButton, _ Temporary:=True)

Befehlsleisten Befehlsleisten

Public Sub AddMenuCommandTag() Dim cmdBar As CommandBar Dim ctl As CommandBarControl

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_04_AddMenuCommand '===================================================================

Befehlsleisten

Die obige Prozedur weist der neuen Schaltfläche über die Caption-Eigenschaft lediglich einen Beschriftungstext zur Identifikation zu, wodurch ein späterer Zugriff auf die Steuerelemente erschwert wird. Eine einfachere Identifikation der Steuerelemente wird dadurch erreicht, dass dem Element ein eindeutiger Text in der TAG-Eigenschaft zugewiesen wird. Der Menübefehl lässt sich anschließend über die FINDCONTROLMethode genau referenzieren. Im folgenden Beispiel wird der neuen Schaltfläche die TAG-Eigenschaft My Button zugewiesen. Die TAG-Eigenschaft erlaubt neben Leerzeichen auch die Verwendung von Sonderzeichen.

Befehlsleisten

Listing 213

Listing 214

Befehlsleisten

With ctl .Tag = "My Button"

364 >> Benutzerdefinierte Menübefehle löschen

Listing 214 (Forts.)

Obwohl alle Befehle, die auf der Menüleiste eingefügt wurden, in der Gruppe MENÜBEFEHLE angezeigt werden, gibt es keine Möglichkeit des direkten Zugriffs über den Index der Controls in dieser Gruppe. Das Problem liegt darin, dass es sich bei der Gruppe MENÜBEFEHLE im Grunde nach wie vor um eine der Menüleisten aus Excel 2003 handelt. Diese enthalten zwar auch noch alle Menüs und Untermenüs, jedoch werden sie in Excel 2007 nicht angezeigt. Sichtbar sind nur die Befehle, die per Code explizit eingefügt wurden.

Befehlsleisten

Befehlsleisten

.Caption = "Button with Tag" .Style = msoButtonCaption .OnAction = "MyMacro" End With End Sub

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 364 Dienstag, 4. Dezember 2007 1:42 13

149 Benutzerdefinierte Menübefehle löschen

Einen einfachen Nachweis über die integrierten Menüs und Befehle liefert der folgende Befehlsaufruf: im Direktfenster: ?Application.CommandBars("Worksheet Menu Bar").Controls(1).Caption

Nach Drücken der (Enter)-Taste wird als Ergebnis

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Date&i

im Direktfenster ausgegeben: Um einen benutzerdefinierten Menübefehl gezielt zu löschen, müssen die beim Erstellen angegebene Menüleiste und der genaue Beschriftungstext angegeben werden. In folgendem Code wurde die Schaltfläche auf der aktiven Menüleiste ohne Verwendung der TAG-Eigenschaft erstellt. Infolgedessen muss diese Referenzierung genau eingehalten werden. Um eine mögliche Fehlermeldung auszuschließen, falls die angegebene Menüleiste oder die zu löschende Schaltfläche nicht gefunden wurde, wird vorab eine Fehlerbehandlungsroutine gesetzt. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_05_DeleteMenuCommand '=================================================================== Public Sub DeleteMenuCommand() On Error Resume Next Application.CommandBars.ActiveMenuBar.Controls _ ("Button on the Worksheet Menu Bar").Delete End Sub Listing 215

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_05_DeleteMenuCommand '=================================================================== Public Sub DeleteButton() DeleteMenuCommandTag strTag:="My Button" End Sub Public Sub DeleteMenuCommandTag(strTag As String) Dim ctl As CommandBarControl ' Zuweisen des Controls Set ctl = Application.CommandBars.ActiveMenuBar.FindControl( _ Tag:=strTag, Recursive:=True) ' Befehlsleistensteuerelement löschen, wenn es gefunden wurde If Not ctl Is Nothing Then ctl.Delete End Sub Listing 216

Befehlsleisten Befehlsleisten Befehlsleisten

Um die Prozedur zum Löschen eines Menübefehls über die TAG-Eigenschaft variabel zu halten, wurde in der Argumentenliste der Parameter STRTAG definiert. Beim Aufruf der Prozedur muss der beim Erstellen angegebene TAG-Text aufgeführt werden.

Befehlsleisten

Die FINDCONTROL-Methode erlaubt zudem eine gezielte Fehlerbehandlungsroutine, indem auf eine Objektvariable ein Verweis auf das gesuchte Control gesetzt wird. Im Anschluss daran kann mit dem Schlüsselwort NOTHING eine Verbindung zu der Objektvariablen überprüft werden.

Befehlsleisten

Wenn dem benutzerdefinierten Befehlsleistensteuerelement beim Erstellen eine eindeutige TAG-Eigenschaft zugewiesen wurde, lässt sich das Element mittels der FINDCONTROL-Methode fehlerfrei identifizieren. In dieser Methode wird neben der gesuchten TAG-Eigenschaft der RECURSIVE-Parameter auf TRUE gesetzt. Dadurch wird nicht nur die angegebene Symbolleiste, sondern es werden auch alle zugehörigen Untersymbolleisten in die Suche einbezogen. Diese Methode hat also den Vorteil, dass man nicht auf die Angabe eines bestimmten Menüs der Menüleiste angewiesen ist, sondern die aktive Menüleiste angeben kann und dementsprechend alle weiteren Untermenüs durchsucht werden.

Befehlsleisten

365

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 365 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 366 Dienstag, 4. Dezember 2007 1:42 13

366 >> Gruppe Menübefehle löschen

150 Gruppe Menübefehle löschen Um die gesamte Gruppe MENÜBEFEHLE im Register ADD-INS zu löschen, müssen alle benutzerdefinierten Schaltflächen aus dieser Gruppe gelöscht werden. Wenn es sich nur um ein einzelnes Control in der Gruppe handelt, mag das noch recht einfach sein, wenn die TAG-Eigenschaft verwendet wurde oder die genaue Referenzierung bekannt ist. Bei mehreren Schaltflächen müssen diese alle einzeln gelöscht werden, was sich mit Hilfe einer Schleife auch bewerkstelligen ließe. Die einfachste Möglichkeit ist es aber, die Menüleiste zurückzusetzen, vorausgesetzt es handelt sich um eine der integrierten und nicht um eine benutzerdefinierte Menüleiste. Benutzerdefinierte Menüleisten können nicht zurückgesetzt werden, sondern müssen gelöscht werden. Beim Zurücksetzen der Arbeitsblatt- oder Diagrammmenüleiste werden alle Änderungen zurückgesetzt und übrig bleibt der Ausgangzustand von Excel 2003. Da in Excel 2007 diese Standard-Einstellung nicht angezeigt wird, wird die Gruppe Menübefehle ausgeblendet, da sie nur angezeigt wird, wenn sich mindestens eine sichtbare Schaltfläche auf ihr befindet. Die folgende Prozedur setzt die aktive Menüleiste zurück. Alle Schaltflächen, die in den vorangegangenen Beispielen erstellt wurden, werden daraufhin aus der Gruppe MENÜBEFEHLE gelöscht, so dass dadurch die gesamte Gruppe ausgeblendet wird. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_05_DeleteMenuCommand '=================================================================== Public Sub ResetMenuCommands() Application.CommandBars.ActiveMenuBar.Reset End Sub Listing 217

Dieser Einzeiler stellt zwar die einfachste Möglichkeit dar, die Gruppe MENÜBEFEHLE zu löschen, dabei wird jedoch vorausgesetzt, dass sich auf keiner weiteren Menüleiste benutzerdefinierte Befehle befinden. Die Gruppe MENÜBEFEHLE wird so lange in der Registerkarte ADD-INS angezeigt, wie eine Menüleiste über die Visible-Eigenschaft auf True gesetzt ist und sich auf ihr benutzerdefinierte Schaltflächen befinden. Wenn sich trotz Zurücksetzung der aktiven Menüleiste noch Schaltflächen in der Gruppe MENÜBEFEHLE befinden, setzen Sie die folgende Prozedur ein, welche alle integrierten Menüleisten zurücksetzt und benutzerdefinierte Menüleisten löscht.

Public Sub DeleteGroupMenuCommands() Dim cmb As CommandBar For Each cmb In Application.CommandBars ' Prüfung Menüleisten If cmb.Type = msoBarTypeMenuBar Then ' Prüfung, ob Befehlsleiste integriert ist If cmb.BuiltIn = True Then ' Integrierte Menüleisten zurücksetzen cmb.Reset Else ' Benutzerdefinierte Menüleisten löschen cmb.Delete End If End If Next cmb End Sub

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_05_DeleteMenuCommand '===================================================================

Befehlsleisten

367

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 367 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 132: Symbolleistenbefehle in Excel 2007

Folgende Prozedur erstellt auf der STANDARD-Symbolleiste eine Schaltfläche mit der Beschriftung Button on the Standard Toolbar.

Befehlsleisten Befehlsleisten

Analog zu den vorherigen Rezepten im Umgang mit benutzerdefinierten Befehlen in Menüleisten werden Befehle, die auf einer integrierten Symbolleiste erstellt werden, in der Gruppe SYMBOLLEISTENBEFEHLE angezeigt. Der einzige Unterschied besteht lediglich in der Zuweisung der Symbolleisten.

Befehlsleisten

151 Schaltflächen in integrierten Symbolleisten

Befehlsleisten

Listing 218

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 368 Dienstag, 4. Dezember 2007 1:42 13

368 >> Schaltflächen in integrierten Symbolleisten '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_06_ToolbarCommand '=================================================================== Public Dim Dim Dim

Sub AddToolbarCommand() cmdBar As CommandBar ctl As CommandBarButton strCaption As String

' Symbolleiste Standard Set cmdBar = Application.CommandBars("Standard") ' Schaltflächen Name und Bezeichnung zusammensetzen strCaption = "Button on the " & cmdBar.Name & " Toolbar" ' Evtl. bereits vorhandenes gleichnamiges Element löschen On Error Resume Next cmdBar.Controls(strCaption).Delete On Error GoTo 0 ' Schaltfläche einfügen Set ctl = cmdBar.Controls.Add( _ Type:=msoControlButton, _ Temporary:=True) With ctl .Caption = strCaption .Style = msoButtonCaption .OnAction = "MyMacro" End With End Sub Listing 219

Um eine einzelne Schaltfläche auf einer integrierten Symbolleiste zurückzusetzen, muss eine eindeutige Referenzierung auf das zu löschende Control erfolgen. Application.CommandBars("Standard").Controls _ ("Button on the Standard Toolbar").Delete

Zum Löschen aller benutzerdefinierten Schaltflächen auf einer Symbolleiste wird die Symbolleiste zurückgesetzt.

Befehlsleisten

Application.CommandBars("Standard").Reset

Beschreibung

msoBarLeft

Befehlsleiste wird am linken Seitenrand verankert.

msoBarTop

Befehlsleiste wird am oberen Seitenrand verankert.

msoBarRight

Befehlsleiste wird am rechten Seitenrand verankert.

msoBarBottom

Befehlsleiste wird am unteren Seitenrand verankert.

msoBarFloating

Gibt an, dass die neue Befehlsleiste nicht verankert ist. Wenn die erstellte Leiste eine Symbolleiste ist und das Argument nicht angegeben wird, wird die Leiste frei im Tabellenblatt angezeigt.

Tabelle 34: Position-Argument legt Seitenrandposition fest

Eine weitere Einschränkung besteht in Excel 2007 darin, dass benutzerdefinierte Symbolleisten nur eingeblendet werden, wenn sie mindestens eine Schaltfläche aufweisen. Werden mehrere benutzerdefinierte Symbolleisten erzeugt, so erscheinen sie der Reihe nach ihrer Erstellung in der Gruppe BENUTZERDEFINIERTE SYMBOLLEISTEN.

Achtung

Beim Erstellen einer benutzerdefinierten Symbolleiste wird der Wert des optionalen Temporary-Argumentes auf True gesetzt um die Symbolleiste temporär zu erstellen. Bis einschließlich Excel 2007 werden temporäre Symbolleisten beim Schließen der Excel-Anwendung automatisch gelöscht. Wenn eine Symbolleiste weder temporär erstellt noch beim Beenden der ExcelArbeitsmappe gelöscht wird, erscheint sie beim nächsten Start der ExcelAnwendung wieder im Register ADD-INS. Wenn der Benutzer auf eine Schaltfläche der Symbolleiste klickt, wird die entsprechende Excel-Arbeitsmappe mit den hinterlegten Aufrufprozeduren geöffnet, sofern sich der Speicherpfad oder der Dateiname nicht verändert hat. Wird die entsprechende Mappe nicht gefunden, erscheint eine Fehlermeldung. Um diesen Fehler zu vermeiden, empfiehlt es sich benutzerdefinierte Symbolleisten immer temporär zu erstellen.

Befehlsleisten Befehlsleisten

Konstante

Befehlsleisten

Bis Excel 2003 kann man beim Erstellen von Symbolleisten die angezeigte Position der Leiste festlegen. Diese Angabe wird jedoch bei der Code-Ausführung unter Excel 2007 nicht berücksichtigt.

Befehlsleisten

In der Regel werden alle Prozeduren, die bis Excel 2003 benutzerdefinierte Symbolleisten generieren, auch in Excel 2007 ausgeführt. Der größte Unterschied besteht in der neuen Excel-Version darin, dass eine benutzerdefinierte Symbolleiste in der Gruppe BENUTZERDEFINIERTE SYMBOLLEISTEN im Register ADD-INS angelegt wird und in ihrer Position nicht mehr verändert werden kann.

Befehlsleisten

152 Benutzerdefinierte Symbolleisten erstellen

Befehlsleisten

369

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 369 Dienstag, 4. Dezember 2007 1:42 13

370 >> Benutzerdefinierte Symbolleisten erstellen

Die folgende Prozedur erstellt bis Excel 2003 eine frei schwebende Symbolleiste mit zwei Schaltflächen.

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 370 Dienstag, 4. Dezember 2007 1:42 13

In Excel 2007 erscheint die Symbolleiste in der Gruppe BENUTZERDEFINIERTE SYMBOLLEISTEN im Register ADD-INS. In der Quickinfo der Schaltflächen wird der Name der benutzerdefinierten Symbolleiste MyCommandBar 1 vor der Schaltflächenbezeichnung My Button 2 angezeigt.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Abbildung 133: Benutzerdefinierte Symbolleiste in Excel 2003

Abbildung 134: Benutzerdefinierte Symbolleiste in Excel 2007

On Error Resume Next Application.CommandBars("MyCommandBar 1").Delete On Error GoTo 0 ' Benutzerdefinierte Symbolleiste erstellen Set cmdBar = Application.CommandBars.Add( _ Name:="MyCommandBar 1", _ Position:= msoBarFloating, _ Temporary:=True) ' Schaltfläche mit Beschriftung einfügen With cmdBar.Controls.Add(Type:=msoControlButton) .Style = msoButtonCaption .Caption = "My Button 1" .OnAction = "MyMacro" End With ' Schaltfläche mit Icon und Beschriftung einfügen With cmdBar.Controls.Add(Type:=msoControlButton) .Style = msoButtonIconAndCaption .Caption = "My Button 2" .FaceId = 351 .OnAction = "MyMacro" End With ' Symbolleiste anzeigen cmdBar.Visible = True End Sub

Befehlsleisten Befehlsleisten

Public Sub AddCommandBar1() Dim cmdBar As CommandBar

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_07_UserDefinedCommandBars '===================================================================

Befehlsleisten

371

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 371 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Listing 220

372 >> Benutzerdefinierte Symbolleisten löschen

153 Benutzerdefinierte Symbolleisten löschen Der Benutzer kann in Excel 2007 eine benutzerdefinierte Symbolleiste manuell löschen, indem er in der Gruppe BENUTZERDEFINIERTE SYMBOLLEISTEN einen Rechtsklick auf die gewünschte Leiste ausführt und im angezeigten Menü den Eintrag BENUTZERDEFINIERTE SYMBOLLEISTE LÖSCHEN auswählt. Anschließend erfolgt eine weitere Rückfrage, ob der Vorgang wirklich durchgeführt werden soll, da eine Symbolleiste durch den Benutzer manuell nicht wiederhergestellt werden kann.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 372 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Mit VBA werden benutzerdefinierte Symbolleisten durch die Delete-Methode ohne weitere Rückfragen gelöscht.

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_07_UserDefinedCommandBars '===================================================================

Befehlsleisten

Abbildung 135: Benutzerdefinierte Symbolleisten manuell löschen

Public Sub DeleteCommandBar () On Error Resume Next Application.CommandBars("MyCommandBar 1").Delete End Sub

In der Beispieldatei wurden auf dem Tabellenblatt zwei Schaltflächen eingefügt, um die Prozeduren AddCommandBar1 zum Erstellen und DeleteCommandBar zum Löschen der benutzerdefinierten Symbolleiste aufzurufen.

Befehlsleisten

Listing 221

373

154 Gruppen in Add-Ins Registerkarte löschen Es kann passieren, dass aus anderen Excel-Anwendungen oder aufgrund Ihrer eigenen Versuche noch Schaltflächen in einer oder mehreren der Gruppen 왘 Menübefehle 왘 Symbolleistenbefehle 왘 Benutzerdefinierte Symbolleisten

Eine Möglichkeit, alle Gruppen mit benutzerdefinierten Schaltflächen aus der ExcelAnwendung zu entfernen, ist, die Datei Excel12.xlb umzubenennen oder zu löschen. Beenden Sie Excel zunächst und löschen Sie dann die Datei. Die Excel-Anwendung wird beim nächsten Start ohne Gruppen mit Schaltflächen und folglich ohne den ADD-INS-Register geöffnet.

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Toolbar Commands ' Modul mdl_08_DeleteAllGroups '===================================================================

Befehlsleisten

Listing 222

Befehlsleisten

Um alle benutzerdefinierten Befehle per Code zu löschen, müssen alle integrierten Symbolleisten zurückgesetzt und benutzerdefinierte Symbolleisten gelöscht werden. Beim Durchlauf der CommandBars-Auflistung wird über die BuiltIn-Eigenschaft ermittelt, ob es sich jeweils um eine integrierte Symbolleiste handelt, und je nach Ergebnis die erforderliche Methode ausgeführt.

Befehlsleisten

Wenn selbst nach dem Beenden und Neustart der Excel-Anwendung diese Befehle nicht gelöscht werden, liegt es wahrscheinlich daran, dass diese Befehle nicht temporär erstellt wurden. Diese Änderungen der Symbolleisten werden wie in den vorherigen Excel-Versionen in der Symbolleistendatei Excel12.xlb gespeichert.

Befehlsleisten

Abbildung 136: Mögliche Gruppen in Add-Ins Registerkarte

Befehlsleisten

Befehlsleisten

im ADD-INS Register übrig geblieben sind und deren genaue Referenzierung unbekannt ist.

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 373 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 374 Dienstag, 4. Dezember 2007 1:42 13

374 >> Befehlsleistendatei finden Public Sub DeleteAllGroups() Dim cmdBar As CommandBar For Each cmdBar In Application.CommandBars ' Prüfung, ob Symbolleiste integriert ist If cmdBar.BuiltIn = True Then ' Integrierte Symbolleisten zurücksetzen cmdBar.Reset Else ' Nicht integrierte Symbolleisten löschen cmdBar.Delete End If Next cmdBar End Sub Listing 222 (Forts.)

155 Befehlsleistendatei finden Wenn Sie Befehle auf einer Menü- oder Symbolleiste hinzufügen oder eine benutzerdefinierte Symbolleiste erstellen, werden die Änderungen und die jeweilige Anordnung der Befehle jeweils beim Beenden von Excel in der Symbolleistendatei *.xlb gespeichert.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Der Speicherpfad der Excel12.xlb-Datei befindet sich standardmäßig unter: C:\Dokumente und Einstellungen\Benutzername\Anwendungsdaten\Microsoft\Excel Je nach Excel-Version sind der Dateiname sowie der Speicherpfad auf Ihrer Festplatte unterschiedlich. Excel-Version

Dateiname

Position

Excel 2007

Excel12.xlb

C:\Dokumente und Einstellungen\Benutzername\ Anwendungsdaten\Microsoft\Excel\

Excel 2003

Excel11.xlb

C:\Dokumente und Einstellungen\Benutzername\ Anwendungsdaten\Microsoft\Excel\

Excel 2002

Excel10.xlb

C:\Dokumente und Einstellungen\Benutzername\ Anwendungsdaten\Microsoft\Excel\

Excel 2000

Excel.xlb

C:\Dokumente und Einstellungen\Benutzername\ Anwendungsdaten\Microsoft\Excel

Excel 97

username8.xlb

Windows-Ordner, wenn keine andere Position von der Administration festgelegt wurde

Tabelle 35: Name und Pfad der Befehlsleistendatei

Ausführliche Informationen zu der Environ-Funktion finden Sie in der Kategorie »Allgemein«.

Abbildung 137: Meldungsfenster mit Speicherpfad der *.xlb-Dateien '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_02_xlbFile.xlsm ' Modul mdl_01_GetxlbPath '=================================================================== Public Sub GetxlbPath() Dim strFile As String Dim strPath As String ' Excel-Version ermitteln Select Case Val(Application.Version) Case 9 strFile = "Excel" Listing 223

Befehlsleisten Befehlsleisten Befehlsleisten

T ipp

Die folgende Prozedur ermittelt über die Version-Eigenschaft Ihre verwendete ExcelVersion. Verwenden Sie eine Version vor Excel 97, erscheint ein Meldungsfenster und die Prozedur wird beendet. Mittels der Environ-Funktion liefert die Umgebungsvariable APPDATA den Speicherpfad Ihrer *.xlb-Datei. Zusätzlich wird in der Zelle C5 der Beispieldatei ein Hyperlink zu dem entsprechenden Ordner hinterlegt. Klicken Sie im Anschluss an die Prozedur auf den Hyperlink, öffnet sich der Explorer und zeigt den Excel-Ordner mit den vorhandenen *.xlb-Dateien an.

Befehlsleisten

Unter Windows XP werden über die Windows-Suche START | SUCHEN die *.xlbDateien sowie der Ordner Anwendungsdaten eventuell nicht gefunden. Suchen Sie im Explorer manuell den Ordner über die oben angegebene Pfadangabe.

Befehlsleisten

Wenn sich in dem angegebenen Ordner zu Ihrer aktuellen Excel-Version keine *.xlb-Datei befindet, liegt das daran, dass noch keine Änderungen an den Symbolleisten vorgenommen wurden.

Befehlsleisten

375

Befehlsleisten

Hinwei s

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 375 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 376 Dienstag, 4. Dezember 2007 1:42 13

376 >> Kontextmenü mit Datum und Zeit erstellen Case 10 strFile = "Excel10" Case 11 strFile = "Excel11" Case 12 strFile = "Excel12" Case Else MsgBox "Die Excel-Version konnte nicht identifiziert" & _ "werden." & vbNewLine & _ "Die Prozedur wird beendet.", _ vbExclamation Exit Sub End Select ' Speicherpfad ermitteln strPath = Environ("APPDATA") & "\Microsoft\Excel" MsgBox "Die Befehlsleistendatei befindet sich im Ordner:" & _ vbNewLine & vbNewLine & _ strPath, _ vbInformation, _ "Speicherpfad " & strFile & ".xlb" ' Hyperlink in Zelle erstellen With ActiveSheet .Range("C5").Hyperlinks.Add _ Anchor:=.Range("C5"), _ Address:=strPath, _ TextToDisplay:=strFile & ".xlb" End With End Sub Listing 223 (Forts.)

156 Kontextmenü mit Datum und Zeit erstellen Üblicherweise werden Kontextmenüs durch Klicken mit der rechten Maustaste angezeigt. Es ist aber ohne weiteres möglich, ein Kontextmenü über eine Prozedur an einer beliebigen Stelle im Tabellenblatt anzuzeigen. Um ein Kontextmenü zu erstellen, erhält das Position-Argument der Add-Methode die Konstante msoBarPopup. Da ein leeres Kontextmenü leicht zu übersehen wäre, fügen wir in folgender Prozedur der Befehlsleiste eine Schaltfläche mit Uhrzeitsymbol FaceId hinzu. Die Aufschrift der Schaltfläche enthält über die Now-Funktion das aktuelle Datum und die Uhrzeit. Über die ShowPopup-Methode wird das Kontextmenü an den angegebenen Koordinaten angezeigt. Geben Sie keine Koordinaten an, wird das Kontextmenü an der aktuellen Mauszeigerposition angezeigt.

377

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '=================================================================== Public Sub ShowPopUp() Dim cmdBar As CommandBar Dim cmdBtn As CommandBarButton On Error Resume Next Application.CommandBars("MyContext").Delete On Error GoTo 0 ' Kontextmenü erstellen Set cmdBar = Application.CommandBars.Add( _ Name:="MyContext", _ Listing 224

Befehlsleisten Befehlsleisten

Sobald Sie im Tabellenblatt scrollen oder mit der linken Maustaste an eine beliebige Stelle innerhalb oder außerhalb der Excel-Anwendung klicken, wird das Kontextmenü ausgeblendet und die Prozedur fortgeführt, ohne dass die hinterlegte Prozedur WriteTime ausgeführt wird.

Befehlsleisten

Diese Art von Kontextmenü eignet sich zum Beispiel, um dem Anwender kurze Mitteilungen anstelle einer MsgBox anzuzeigen, oder um darin weitere Prozeduren zur Verfügung zu stellen.

Befehlsleisten

Die Anzeige-Koordinaten für Symbolleisten und Kontextmenüs richten sich nicht nach der Größe des Excel-Fensters, sondern nach der gesamten Bildschirmgröße. Wenn Sie das Excel-Fenster verkleinert haben, kann es passieren, dass eine Befehlsleiste mit festen Koordinaten außerhalb der Excel-Anwendung angezeigt wird.

Befehlsleisten

Hinweis

Abbildung 138: Kontextmenü mit Datum und Zeitangabe

Befehlsleisten

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 377 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

2471_Excel-VBA.book Seite 378 Dienstag, 4. Dezember 2007 1:42 13

378 >> Kontextmenü mit Datum und Zeit erstellen Position:=msoBarPopup, _ Temporary:=True)

With cmdBtn ' Symbol definieren .FaceId = 126 ' Datums- und Zeitangabe durch Now-Funktion .Caption = Now ' Prozedur zuweisen .OnAction = "WriteTime" End With ' Kontextmenü mit Positionsangaben anzeigen cmdBar.ShowPopup X:=950, Y:=600 End Sub Listing 224 (Forts.)

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ShowPopUp ' Modul mdl_03_PopUp '=================================================================== Public Sub WriteTime() ActiveCell.Value = Now End Sub

Befehlsleisten

Befehlsleisten

Befehlsleisten

Über die OnAction-Eigenschaft wird der Schaltfläche eine Prozedur zugewiesen, die ausgeführt wird, wenn der Benutzer auf die Schaltfläche drückt. In unserem Beispiel wird in der Prozedur WRITETIME der aktuelle Zeitstempel in die aktive Zelle geschrieben.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

' Schaltfläche auf Kontextmenü erstellen Set cmdBtn = cmdBar.Controls.Add(Type:=msoControlButton)

Listing 225

Solange das benutzerdefinierte Kontextmenü nicht ausdrücklich gelöscht oder die Anwendung zwischenzeitlich beendet wurde und dabei das temporäre Kontextmenü aus der CommandBars-Auflistung entfernt wurde, kann es über seinen Namen jederzeit angezeigt werden. Application.CommandBars("MyContext").ShowPopup X:=100, Y:=250

379

157 DropDown-Menü erzeugen

Befehlsleisten

In diesem Beispiel wird bis Excel 2003 rechts neben dem ?-Menü ein neues DropDownMenü mit weiteren Schaltflächen eingefügt. Diesen Schaltflächen sind verschiedene Prozeduren hinterlegt, welche in unserem Beispiel den Zellhintergrund der selektierten Zellen einfärbt.

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 379 Dienstag, 4. Dezember 2007 1:42 13

Bis auf die unterschiedliche Anzeige des neuen Menüs je nach verwendeter Excel-Version sind die nachfolgend beschriebenen Vorgehensweisen und Methoden in allen Excel-Versionen von Excel 97 bis Excel 2007 einsetzbar.

Befehlsleisten

Hinwei s

Abbildung 140: Aufgeklapptes DropDown-Menü mit Schaltflächen in Excel 2007

Befehlsleisten

Befehlsleisten

Befehlsleisten

Wird der Code in Excel 2007 ausgeführt, erscheint das DROPDOWN-Menü in der Gruppe MENÜBEFEHLE des Registers ADD-INS.

Befehlsleisten

Abbildung 139: Benutzerdefiniertes DropDown-Menü mit Schaltflächen in Excel2003

Befehlsleisten

Befehlsleisten

Befehlsleisten

380 >> DropDown-Menü erzeugen

Bis Excel 2003 soll das neue Menü auf der aktiven Menüleiste erstellt werden. Dementsprechend setzen wir einen Verweis auf die Variable cmdBar, welche als CommandBar deklariert wurde. In Excel 2007 spielt es keine Rolle, auf welcher Menü- oder Symbolleiste benutzerdefinierte Controls erstellt werden, da sie in jedem Fall in einer eigenen Gruppe der Multifunktionsleiste ADD-INS angezeigt werden. Achtung

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 380 Dienstag, 4. Dezember 2007 1:42 13

Wichtig ist in jedem Fall, dass Sie eine beliebige, bis Excel 2003 integrierte Befehlsleiste oder eine neu erstellte benutzerdefinierte Symbolleiste angeben und beim späteren Löschen der Controls die gleiche Symbolleiste angeben, die beim Erstellen verwendet wurde.

Bevor ein neues Menü oder Steuerelement erstellt wird, wird vorab ein evtl. gleichnamiges Menü gelöscht. Excel würde sonst bei jedem Durchlauf der Prozedur das Menü erneut erstellen. Für den Fall, dass das Menü nicht existiert, haben wir die On Error Resume Next-Fehlerroutine vorangestellt. Über die Add-Methode wird ein neues Steuerelement erzeugt und gleichzeitig ein Verweis auf die Variable ctlPopUp gesetzt. Mit dem Type-Argument legen Sie den Typ des Steuerelements, das zur angegebenen Befehlsleiste hinzugefügt werden soll, fest. Es stehen folgende MsoControlType-Konstanten zur Verfügung: Konstante

Beschreibung

msoControlButton

Erstellt ein Schaltflächen-Element

msoControlEdit

Erstellt ein Eingabefeld

msoControlDropdown

Erstellt ein DropDown-Feld

msoControlComboBox

Erstellt ein Kombinationsfeld

msoControlPopup

Erstellt ein DropDown-Menü

Tabelle 36: Mögliche Steuerelemente des Typ-Arguments

Der Wert des optionalen Temporary-Argumentes wird auf True gesetzt um das neue Steuerelement als temporäres Steuerelement zu erstellen.

Befehlsleisten

Befehlsleisten

Über die Caption-Eigenschaft wird der Schaltfläche der Beschriftungstext zugewiesen. ctlBarControl.Caption = "&Background-Colors"

Durch das vorangestellte &-Zeichen wird der nachfolgende Buchstabe der Beschriftung unterstrichen dargestellt.

Dies gilt zum einen für einfache Dialogaufrufe, wie z. B. den GEHE ZU-Dialog, der in beiden Excel-Versionen mit der Tastenkombination (Strg) (G) angezeigt wird. Alle Funktionen, die über Menüs und Untermenüs erreichbar waren, können weiterhin über die bekannten Tastenreihenfolgen aufgerufen werden. Zum Beispiel ist das Dialogfeld der bedingten Formatierung in Excel 2003 über den Menüpunkt FORMAT|BEDINGTE FORMATIERUNG erreichbar. Die Tastenkombination für den direkten Zugriff lautet (Alt) (T) (D). In Excel 2007 finden Sie die BEDINGTE FORMATIERUNG auf der Registerkarte START in der Gruppe FORMATVORLAGEN. Im Menü BEDINGTE FORMATIERUNG muss dann noch der letzte Eintrag REGELN VERWALTEN ausgewählt werden. Die Tastenabfolge dafür lautet (Alt) (S) (L) (R). Wenn Sie ein Tastenfreak sind und viele Funktionen bislang über Tastenkombinationen aufgerufen haben, müssen Sie Ihre altbekannten Tastenkombinationen nicht neu erlernen, sondern können weiterhin auch in Excel 2007 die Tastenkombinationen aus Excel 2003 anwenden. So wird mit der Tastenkombination (Alt) (T) (D) in allen Excel-Versionen von Excel 97 bis 2007 das Dialogfeld der bedingten Formatierung aufgerufen. Natürlich wird in der jeweils verwendeten Version das darin verfügbare Dialogfeld angezeigt. Um Tastenkombination für benutzerdefinierte Befehle in Excel 2007 anzuwenden müssen Sie zunächst zur Registerkarte ADD-INS wechseln. Drücken Sie die (Alt)-Taste und lassen Sie sie sofort wieder los, um alle zur Verfügung stehenden Tastenkürzel der Registerkarten bzw. direkten Befehle der Schnellzugriffsleiste anzuzeigen.

Befehlsleisten Befehlsleisten Befehlsleisten

Alle integrierten Funktionen und Befehle, die aus Excel 2003 in Excel 2007 übernommen wurden, können in der neuen Excel-Version mit den alten gewohnten Tastenkombinationen aufgerufen werden, auch wenn sie nicht anhand von angezeigten Zugriffstasten gekennzeichnet sind.

Befehlsleisten

Bis Excel 2003 kann das jeweilige Menü bzw. die Schaltfläche mit der Tastenkombination (Alt) (Buchstabe) aufgerufen werden.

Befehlsleisten

Abbildung 141: DropDown-Menü mit Zugriffstasten-Zeichen

Befehlsleisten

381

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 381 Dienstag, 4. Dezember 2007 1:42 13

382 >> DropDown-Menü erzeugen

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 382 Dienstag, 4. Dezember 2007 1:42 13

Drücken Sie die Tasten (Y) und (3) um zur Registerkarte ADD-INS zu wechseln. Anschließend wird die Zugriffstaste (C) für unser benutzerdefiniertes Menü angezeigt und kann durch den Benutzer ausgeführt werden.

Befehlsleisten

Befehlsleisten

Abbildung 142: Anzeige der Tastenkürzel nach Drücken der (Alt)-Taste.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Abbildung 143: Anzeige der Zugriffstaste des benutzerdefinierten Menüs

Die Zugriffstaste (C) wird im Code bei Zuweisung der Caption-Eigenschaft über das vorangestellte &-Zeichen definiert: ctrl.Caption = "Ba&ckground-Colors"

Nachdem Sie nun die Taste (C) gedrückt haben, werden die Zugriffstasten der einzelnen Befehle angezeigt und können erst jetzt ausgeführt werden.

Abbildung 144: Anzeige der Zugriffstasten im DropDown-Feld

>> Befehlsleisten

383

Um einer markierten Zelle oder einem Zellenbereich z. B. einen grünen Zellenhintergrund zuzuweisen, muss folgende Tastenfolge gedrückt werden:

Befehlsleisten

2471_Excel-VBA.book Seite 383 Dienstag, 4. Dezember 2007 1:42 13

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ColorMenu ' Modul mdl_09_ColorMenu '=================================================================== Public Sub AddColorMenu() Dim cmdBar As CommandBar Dim ctlPopUp As CommandBarControl

Befehlsleisten

Um die einzelnen Schaltflächen des DropDown-Menüs zu erstellen, wird jeweils die Prozedur AddControl aufgerufen. Diese Prozedur erwartet beim Aufruf die Argumente für das PopUp-Element auf der Symbolleiste, den Beschriftungstext Caption und den Namen des aufzurufenden Makros OnAction des Steuerelements.

Befehlsleisten

Im Vergleich zu Excel 2003 ist diese neue Art, Tastenkombinationen für Menübefehle direkt anzuwenden, um einiges umständlicher. Aber es gibt sicherlich etliche Anwender, die weiterhin lieber mit Tastenkombinationen Befehle aufrufen, anstatt immer wieder zwischen der Tastatur und dem Griff zur Maus zu wechseln.

Befehlsleisten

(Alt) + (Y3CG)

AddControl AddControl AddControl AddControl AddControl End Sub

ctlPopUp, ctlPopUp, ctlPopUp, ctlPopUp, ctlPopUp,

"&Red", "RedColor" "&Green", "GreenColor" "&Blue", "BlueColor" "&Yellow", "YellowColor" "&Clear Color", "NoColor"

Listing 226

Beim Aufruf der folgenden Prozedur werden das Control, auf dem die neue Schaltfläche eingefügt werden soll, der Beschriftungstext sowie der Name der aufzurufenden Prozedur übergeben. Über die Add-Methode wird dem DropDown-Menü ctlPopUp

Befehlsleisten

ctlPopUp.Caption = "Ba&ckground-Colors"

Befehlsleisten

Set ctlPopUp = cmdBar.Controls.Add( _ Type:=msoControlPopup, _ Temporary:=True)

Befehlsleisten

On Error Resume Next cmdBar.Controls("Background-Colors").Delete On Error GoTo 0

Befehlsleisten

Set cmdBar = Application.CommandBars.ActiveMenuBar

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 384 Dienstag, 4. Dezember 2007 1:42 13

384 >> DropDown-Menü erzeugen

eine Schaltfläche hinzugefügt. In einer With-Anweisung wird der Beschriftungstext über die Variable strCaption an die Caption-Eigenschaft übergeben. Die OnActionEigenschaft erhält den Namen des Visual Basic-Makros, das ausgeführt wird, wenn der Benutzer auf den Wert des Befehlsleistensteuerelements klickt. Diese ausgelagerte Prozedur erspart die fünffache Angabe der Befehle in der aufrufenden Prozedur AddColorMenu. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ColorMenu ' Modul mdl_09_ColorMenu '=================================================================== Public Sub AddControl(cmdBarCtrl As CommandBarControl, strCaption As String, _ strAction As String) With cmdBarCtrl.Controls.Add _ (Type:=msoControlButton, ID:=19 _ , Temporary:=True) .Caption = strCaption .OnAction = strAction End With End Sub

Befehlsleisten

Befehlsleisten

Befehlsleisten

Listing 227

Die folgenden Prozeduren werden ausgeführt, wenn der Benutzer auf die entsprechende Schaltfläche im Menü BACKGROUND-COLORS klickt. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle ColorMenu ' Modul mdl_09_ColorMenu '=================================================================== Public Sub RedColor() Selection.Interior.ColorIndex = 3 End Sub Public Sub GreenColor() Selection.Interior.ColorIndex = 4 End Sub

Befehlsleisten

Public Sub BlueColor() Selection.Interior.ColorIndex = 5 Listing 228

385

End Sub Public Sub YellowColor() Selection.Interior.ColorIndex = 6 End Sub Public Sub NoColor() Selection.Interior.ColorIndex = xlNone End Sub

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 385 Dienstag, 4. Dezember 2007 1:42 13

Tipp

In der abschließenden If...Then...Else-Anweisung wird anhand des Wahrheitswertes der Variablen blnCtrl das gesuchte Steuerelement angezeigt oder über ein Meldungsfenster mitgeteilt, dass das Control nicht gefunden wurde. Der Standardwert einer booleschen Variablen ist True und muss deshalb nicht ausdrücklich in einer If-Anweisung angegeben werden. Die Syntax If blnCtrl then entspricht der Syntax If blnCtrl = True then

Befehlsleisten Befehlsleisten Befehlsleisten

In einer For Each...Next-Anweisung wird jedes Steuerelement der aktiven Menüleiste durchlaufen. Um ein Control anzusprechen, wird dessen Existenz über die Caption-Eigenschaft überprüft. Über die Excel-Tabellenfunktionen WECHSELN(), in VBA mit der WorksheetFunction-Eigenschaft Substitute angewandt, wird das &-Zeichen durch einen Leerstring ausgetauscht. Dadurch ist in der folgenden If-Anweisung ein einwandfreier Vergleich zwischen der Caption-Eigenschaft und der Variablen strCtrl möglich. Ist die Enabled-Eigenschaft eines Controls auf False eingestellt, wird es zwar gefunden, kann aber, da es ausgegraut und somit inaktiv ist, nicht angezeigt werden. Das Gleiche gilt für die Visible-Eigenschaft. Nur wenn alle drei Kriterien, welche zum Anzeigen eines Menüs erforderlich sind, in der If-Anweisung zutreffen, wird die Variable blnCtrl auf True gestellt, ein Verweis auf das gefundene Steuerelement cmdBarCtrl gesetzt und die For Each...Next-Anweisung verlassen.

Befehlsleisten

Im folgenden Beispiel soll ein Steuerelement der aktiven Menüleiste aufgerufen werden. In eine InputBox wird der Name des gewünschten Controls eingegeben und in der Variablen strCtrl gespeichert. Wenn die Eingabezeile keinen Wert enthält, wird ein Leerstring "" zurückgegeben. Hat der Benutzer die ABBRECHEN-Schaltfläche der InputBox geklickt, enthält strCtrl den Wert Falsch. In beiden Fällen wird die Prozedur beendet.

Befehlsleisten

158 Steuerelement aufrufen

Befehlsleisten

Listing 228 (Forts.)

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 386 Dienstag, 4. Dezember 2007 1:42 13

386 >> Steuerelement aufrufen

Über die Execute-Methode wird das vorangestellte Steuerelement angezeigt. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle CallControl ' Modul mdl_10_CallControl '=================================================================== Public Dim Dim Dim Dim Dim

Sub CallControl() cmdBar As cmdBarCtrl As strCtrl As strCrtlCaption As blnCtrl As

Set cmdBar = Application.CommandBars.ActiveMenuBar strCtrl = Application.InputBox( _ Prompt:="Geben Sie den Namen eines Steuerelementes" _ & " der aktiven Menüleiste ein:", _ Title:="Suche Schaltfläche", _ Default:="Menu Button", _ Left:=260, _ Top:=230, _ Type:=2) If strCtrl = "" Or strCtrl = "Falsch" Then Exit Sub For Each cmdBarCtrl In cmdBar.Controls ' &-Zeichen aus Beschriftungstext entfernen strCrtlCaption = Application.WorksheetFunction. _ Substitute(cmdBarCtrl.Caption, "&", "") ' Prüfung, ob Beschriftungstext identisch ' und Steuerelement aktiviert und sichtbar ist If strCrtlCaption = strCtrl And _ cmdBarCtrl.Enabled And _ cmdBarCtrl.Visible Then blnCtrl = True ' Verweis auf Steuerelement Set cmdBarCtrl = cmdBar.Controls(strCtrl) Exit For End If Next cmdBarCtrl

Befehlsleisten

CommandBar CommandBarControl String String Boolean

Listing 229

387

If blnCtrl Then cmdBarCtrl.Execute Else MsgBox "Schaltfläche '" & strCtrl & "' nicht gefunden!" End If End Sub Listing 229 (Forts.)

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 387 Dienstag, 4. Dezember 2007 1:42 13

In Excel können Sie mit der Copy-Methode vorhandene Steuerelemente von einer Befehlleiste in eine andere kopieren. Die Syntax lautet: Ausdruck.Copy(Bar, Before)

In unserem Beispiel wird die Copy-Methode wie folgt angewandt:

Befehlsleisten

159 Steuerelemente kopieren

Wird nur das erste Argument, bzw. werden beide optionalen Argumente Bar und Before verwendet, kann auf die Benennung der Argumente verzichtet werden. Durch diese Schreibweise wird der Code allerdings schwerer verständlich: cmdBarCtrl.Copy cmdBar, 1

Befehlsleisten

cmdBarCtrl.Copy Bar:=cmdBar, Before:=1

Ausdruck stellt das zu kopierende Steuerelement dar und kann eines der folgenden

Beschreibung

CommandBarControl

Befehlsleistensteuerelement

CommandBarButton

Schaltflächensteuerelement

CommandBarPopup

Popupsteuerelement

CommandBarComboBox

Kombinationsfeldsteuerelement

Tabelle 37: CommandBar-Objekte, die kopiert werden können

Über das optionale Bar-Argument legen Sie die Zielbefehlsleiste fest, in die das kopierte Steuerelement eingefügt werden soll. Wenn Sie dieses Argument auslassen, wird das Steuerelement in dieselbe Befehlsleiste kopiert, in der es sich bereits befindet. Da das Element in die benutzerdefinierte Custom-Symbolleiste eingefügt werden soll, wird in unserem Beispiel ein entsprechender Verweis auf die Variable cmdBar gesetzt.

Befehlsleisten

Geben Sie für das optionale Before-Argument eine Zahl an, welche die Position für das neue Steuerelement auf der angegebenen Befehlsleiste festlegt. Das neue Steuer-

Befehlsleisten

Für das zu kopierende Steuerelement wird die Variable cmdBarCtrl reserviert. Es wird ein Verweis auf das Steuerelement REGISTERFARBE im Menü FORMAT |BLATT aus Excel 2003 gesetzt, das kopiert werden soll.

Befehlsleisten

Objekt

Befehlsleisten

Objekte sein, welches exakt referenziert werden muss.

388 >> Steuerelemente kopieren

element wird vor dem Steuerelement eingefügt, das sich an dieser Position befindet. Wenn dieses Argument ausgelassen wird, wird das Element an das Ende der Befehlsleiste kopiert. In der Beispieldatei wird das kopierte Element an erster Stelle eingefügt. Das Klicken auf diese Schaltfläche hat denselben Effekt wie das Klicken auf die Original-Schaltfläche. Nach Verfügbarkeit werden aktuelle Dialogfenster aus Excel 2007 angezeigt. Im Falle der Registerfarben wird allerdings das Dialogfeld FARBEN aus Excel 2003 angezeigt. Die Ausführung einer Farbwahl erfolgt anstandslos.

Abbildung 145: Kopiertes Steuerelement

Damit bei erneutem Ausführen der Prozedur nicht weitere gleiche Steuerelemente eingefügt werden, wird vorab ein evtl. vorhandenes gleichnamiges Steuerelement gelöscht. H i nwe i s

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 388 Dienstag, 4. Dezember 2007 1:42 13

Befinden sich mehrere gleichnamige Steuerelemente in der genannten Befehlsleiste, wird das von links zuerst gefundene Element gelöscht.

' Verweis auf zu kopierendes Element setzen Set cmdBarCtrl = Application.CommandBars(1) _ .Controls("Format") _ .Controls("Blatt") _ .Controls("&Registerfarbe...") ' Steuerelement kopieren und in neue Leiste ' an erster Stelle einfügen cmdBarCtrl.Copy Bar:=cmdBar, Before:=1 ' neue Befehlsleiste anzeigen cmdBar.Visible = True End Sub

Hinwei s

Listing 230

Bei Verwendung der Copy-Methode kann das neue Element nicht temporär erstellt werden. Wenn Sie es vor Beendigung der Excel-Anwendung nicht löschen, wird es dauerhaft in der Symbolleistenkonfigurationsdatei *.xlb gespeichert und steht, bis es gelöscht wird, in folgenden Excel-Anwendungen zur Verfügung. Kopieren Sie Befehle auf eine benutzerdefinierte Symbolleiste, die temporär erstellt wird. Bei Beendigung der Excel-Anwendung wird die temporäre Symbolleiste und damit auch das kopierte Steuerelement gelöscht.

Befehlsleisten Befehlsleisten

' Verweis auf neue Befehlsleiste setzen Set cmdBar = CommandBars.Add( _ Name:="Custom", _ Position:=msoBarTop, _ Temporary:=True)

Befehlsleisten

' Evtl. vorhandene Befehlsleiste löschen On Error Resume Next CommandBars("Custom").Delete On Error GoTo 0

Befehlsleisten

Public Sub CopyControl() Dim cmdBar As CommandBar Dim cmdBarCtrl As CommandBarControl

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle CopyControl ' Modul mdl_11_CopyControl '===================================================================

Befehlsleisten

389

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 389 Dienstag, 4. Dezember 2007 1:42 13

390 >> Original Symbolleisten aus Excel 2003 erstellen

In der Beispieldatei können Sie über eine Schaltfläche das kopierte Element löschen. Dieser haben wir die Prozedur DeleteCopyControl zugewiesen. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle CopyControl ' Modul mdl_11_CopyControl '=================================================================== Public Sub DeleteCopyControl() On Error Resume Next Application.CommandBars("Custom") _ .Controls("Registerfarbe...").Delete End Sub Listing 231

160 Original Symbolleisten aus Excel 2003 erstellen Im folgenden Beispiel werden alle Steuerelemente der FORMAT-Symbolleiste, die auch noch in Excel 2007 verfügbar sind, über die Copy-Methode in eine benutzerdefinierte Symbolleiste eingefügt, die dann im Register Add-Ins angezeigt wird. Beim Aufruf der Befehle aus dieser Leiste werden nach Möglichkeit die aktuellen Dialogfenster aus Excel 2007 angezeigt. In der Prozedur wird an die String-Variable der Name der zu kopierenden Symbolleiste zugewiesen. Um z. B. die Standard-Symbolleiste zu kopieren, ersetzen Sie im Code FORMATTING durch STANDARD. Für den Fall, dass Änderungen an der Original Format-Symbolleiste vorgenommen wurden, wird die Befehlsleiste auf deren Ausgangszustand zurückgesetzt. Der Text, der in der Quickinfo ausgegeben wird, entstammt jeweils der Quickinfo der neuen Excel-Version.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 390 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Abbildung 146: Format-Symbolleiste aus Excel 2003

strCmdBar = "Formatting" ' "Standard" ' kopiert die Befehlsleiste Standard ' Original Symbolleiste zurücksetzen Application.CommandBars(strCmdBar).Reset ' evtl. vorhandene Leiste löschen On Error Resume Next Application.CommandBars("My " & strCmdBar).Delete Set cmdBar = Application.CommandBars.Add( _ Name:="My " & strCmdBar, _ Temporary:=True) ' Alle Elemente der Original Symbolleiste durchlaufen For lngCtrl = 1 To CommandBars(strCmdBar).Controls.Count ' Verweis auf Control setzen Set cmdBarCtrl = Application.CommandBars(strCmdBar) _ .Controls(lngCtrl) ' Elemente der Original-Leiste in neue Leiste kopieren cmdBarCtrl.Copy Bar:=cmdBar Next lngCtrl ' Symbolleiste anzeigen cmdBar.Visible = True End Sub Listing 232

Befehlsleisten Befehlsleisten

String CommandBar CommandBarControl Long

Befehlsleisten

Sub CopyBar() strCmdBar As cmdBar As cmdBarCtrl As lngCtrl As

Befehlsleisten

Public Dim Dim Dim Dim

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle CopyControl ' Modul mdl_12_CopyBar '===================================================================

Befehlsleisten

391

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 391 Dienstag, 4. Dezember 2007 1:42 13

392 >> Kontextmenü als Symbolleiste verwenden

161 Kontextmenü als Symbolleiste verwenden Wie bereits geschrieben, sind in Excel 2007 sämtliche benutzerdefinierten Symbolleisten und Befehle nur noch auf der Multifunktionsleiste im Register Add-Ins zu finden. Wenn man sich bislang noch nicht mit der RibbonX-Programmierung beschäftigt hat, gibt es ein paar einfache Tricks, um dem Benutzer, auf ähnliche Weise wie über die gewohnten benutzerdefinierten Symbolleisten, eigene Befehle zur Verfügung zu stellen. In Excel 2007 können zwar keine normalen Symbolleisten mehr angezeigt werden, dafür funktionieren die Kontext-Menüs nach wie vor einwandfrei. Obwohl Kontext-Menüs vom Typ msoBarPopup ebenfalls zu der CommandBars-Auflistung gehören, können sie über die SHOW-Methode jederzeit angezeigt werden.

Hinweis

In diesem Beispiel wird auf einem Tabellenblatt ein ACTIVEX-Bezeichnungsfeld aus der ehemaligen Steuerelement-Toolbox Symbolleiste erstellt. In Office Excel 2007 finden Sie die Formular- und ACTIVEX-Steuerelemente im Register Entwicklertools (siehe Abbildung 147). Im Tabellenblatt werden die obersten 3 Zeilen über den Menüpunkt ANSICHT | FENSTER FIXIEREN festgestellt, so dass die Schaltfläche auch beim Scrollen nach unten dem Benutzer jederzeit zur Verfügung steht. Ausführliche Informationen zu Steuerelementen sind in Kapitel »Steuerelemente« beschrieben.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 392 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Abbildung 147: Formular- und ActiveX-Steuerelemente in Excel 2007

Beim Aktivieren des Tabellenblattes wird im Worksheet_Activate-Ereignis eine benutzerdefinierte Symbolleiste vom Typ msoBarPopup erstellt und beim Deaktivieren des Tabellenblattes im Worksheet_Deactivate-Ereignis wieder gelöscht. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle PopUp Toolbar '=================================================================== Private Sub Worksheet_Activate() CreatePopUpBar End Sub Private Sub Worksheet_Deactivate() DeleteMenuBar End Sub

Befehlsleisten

393

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 393 Dienstag, 4. Dezember 2007 1:42 13

Über den Schleifenzähler lngCtr werden beim Zuweisen der Schaltflächenbezeichnung Caption und der aufzurufenden Prozedur OnAction die jeweiligen Elemente der hinterlegten Arrays arCapNames und arMacNames herangezogen. Das SchaltflächenSymbol FaceID mit dem angegebenen Index 71 liefert ein Symbol, das die Zahl 1 darstellt. Zu diesem Index wird jeweils der Wert der Schleifenzähler-Variablen addiert.

Befehlsleisten Befehlsleisten

Das Kontextmenü soll vier Schaltflächen mit je einer zugewiesenen Prozedur beinhalten. Die Schaltflächen-Bezeichnungen sowie die entsprechenden Prozedurnamen werden in jeweils einem Datenfeld hinterlegt. Nachdem die benutzerdefinierte Symbolleiste als Kontextmenü über das POSITION-Argument msoBarPopup in einer WithAnweisung temporär erstellt wurde, werden alle Elemente des Datenfeldes (Array) arMacNames in einer For...Next-Schleife durchlaufen. Der Zähler der For...NextSchleife beginnt mit dem kleinsten verfügbaren Index des Arrays und wird durch die LBound-Funktion ermittelt. Das Ende des Schleifendurchlaufs wird mit Hilfe der UBound-Funktion bestimmt, die den größten verfügbaren Index des angegebenen Datenfeldes liefert. Da ein Datenfeld 0-basierend ist, ist der kleinste verfügbare Index mit 0 definiert. Der größte Index weist aufgrund des 0-basierenden Datenfeldes die Anzahl der aufgeführten Elemente minus 1 auf.

Befehlsleisten

Die in den Ereignisprozeduren aufgerufenen Prozeduren sind in einem Standardmodul des VBAProjektes gespeichert. Der Name der erstellten Symbolleiste MyToolBar wird am Anfang des Moduls in einer globalen Konstante deklariert, damit ein Zugriff auf die Symbolleiste aus allen Modulen des VBAProjektes erfolgen kann. Änderungen an der Bezeichnung müssen dadurch nur noch an einer Stelle für das gesamte VBAProjekt vorgenommen werden.

Befehlsleisten

Listing 233

Befehlsleisten

.FaceId = 71 + lngCtr

394 >> Kontextmenü als Symbolleiste verwenden

Da der kleinste Index des Datenfeldes 0 ist, wird beim ersten Durchlauf der Schleife kein weiterer Wert zu dem Index der FaceId addiert. Bei jedem weiteren Schleifendurchlauf erhöht sich der Schleifenzähler und dadurch auch der Index des zu verwendenden Symbols. Tipp

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 394 Dienstag, 4. Dezember 2007 1:42 13

Die mit Zahlen beschrifteten FACEID's sind von 0 bis 9 verfügbar und werden über die Indexe 70 = 0 bis 79 = 9

Befehlsleisten

Option Explicit

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle PopUp Toolbar ' Modul mdl_13_PopUpBar '===================================================================

Befehlsleisten

definiert.

' globale Konstante für Symbolleistenbezeichnung Public Const strMenuName As String = "MyToolBar" Public Dim Dim Dim

Sub CreatePopUpBar() lngCtr As Long arMacNames As Variant arCapNames As Variant

' Evtl. bereits vorhandene Symbolleiste löschen DeleteMenuBar ' Datenfeld mit Schaltflächen-Bezeichnungen arCapNames = Array("Makro1 Bezeichnung", _ "Makro2 Bezeichnung", _ "Makro3 Bezeichnung", _ "Makro4 Bezeichnung") ' Datenfeld mit Prozedurnamen arMacNames = Array("Makro1", _ "Makro2", _ "Makro3", _ "Makro4") ' Symbolleiste erstellen With Application.CommandBars.Add(Name:=strMenuName, _ Position:=msoBarPopup, Temporary:=True) Listing 234

Next lngCtr End With End Sub Public Sub DeleteMenuBar() On Error Resume Next Application.CommandBars(strMenuName).Delete On Error GoTo 0 End Sub Listing 234 (Forts.)

Befehlsleisten Befehlsleisten

Wenn der Benutzer den Mauszeiger über das Bezeichnungsfeld LABEL1 führt, wird das hinterlegte _MouseMove-Ereignis des Bezeichnungsfeldes ausgelöst. In dieser Ereignisprozedur wird das zuvor erstellte benutzerdefinierte Kontextmenü über die ShowPopUp-Methode angezeigt. Ohne Positionsangaben wird das Kontextmenü an der aktuellen Mauszeiger-Position dargestellt (siehe Abbildung 148).

Befehlsleisten

' Schaltflächen in Symbolleiste erstellen With .Controls.Add(Type:=msoControlButton) ' Anzeigeart der Schaltfläche .Style = msoButtonIconAndCaption ' Beschriftungstext aus Datenfeld .Caption = arCapNames(lngCtr) ' Schaltflächen-Symbol als fortlaufende Nummer .FaceId = 71 + lngCtr ' Beschriftungstext aus Datenfeld .OnAction = "'" & ThisWorkbook.Name & "'!" & arMacNames(lngCtr) End With

Befehlsleisten

' Alle Elemente des Arrays durchlaufen For lngCtr = LBound(arMacNames) To UBound(arMacNames)

Befehlsleisten

395

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 395 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Abbildung 148: Anzeige eines Kontextmenüs mit benutzerdefinierten Schaltflächen

396 >> Kontextmenü als Symbolleiste verwenden '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle PopUp Toolbar '=================================================================== Private Sub Label1_MouseMove(ByVal Button As Integer, _ ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) ' Prozeduraufruf zum Anzeigen des Kontextmenüs ShowMyPopUpBar End Sub Listing 235 '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle PopUp Toolbar ' Modul mdl_13_PopUpBar '=================================================================== Public Sub ShowMyPopUpBar() ' Fehlerroutine, falls Symbolleiste nicht erstellt wurde On Error Resume Next ' Benutzerdefinierte Symbolleiste anzeigen Application.CommandBars(strMenuName).ShowPopup ' Fehlerroutine zurücksetzen On Error GoTo 0 End Sub Listing 236

Befehlsleisten

Klickt der Benutzer auf eine Schaltfläche im Kontextmenü, wird die beim Erstellen der Schaltfläche zugewiesene Prozedur aufgerufen. Die angegebenen Prozeduren sind in einem Standardmodul des VBAProjektes gespeichert. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle PopUp Toolbar ' Modul mdl_13_PopUpBar '===================================================================

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 396 Dienstag, 4. Dezember 2007 1:42 13

Listing 237

Public Sub Makro2() MsgBox "Das ist Makro 2" End Sub Listing 237 (Forts.)

Um das Kontextmenü ohne Benutzung einer Schaltfläche und Ausführung eines Makros wieder auszublenden, kann der Anwender entweder eine beliebige Zelle auf dem Tabellenblatt markieren oder die (Esc)-Taste drücken.

162 Menüpunkte mit Hyperlinks In einer Zelle im Tabellenblatt können Sie über das Menü EINFÜGEN | HYPERLINK oder die Tastenkombination (Strg) (K) Hyperlinks erstellen. Diese können zu verschiedenen Objekten verlinken: 왘 Datei oder Webseite 왘 Bezug innerhalb der aktuellen Arbeitsmappe

Befehlsleisten

Public Sub Makro1() MsgBox "Das ist Makro 1" End Sub

Befehlsleisten

397

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 397 Dienstag, 4. Dezember 2007 1:42 13

Achtung

Wenn Sie nicht mit dem Internet verbunden sind, während Sie in der Beispieldatei auf einen Hyperlink klicken, erscheint nach kurzer Zeit eine Fehlermeldung.

Befehlsleisten

Die Prozedur MenuHyperlinks fügt in Excel 97–2003 an die letzte Stelle der aktiven Menüleiste ein neues DropDown-Menü mit weiteren Schaltflächen ein. In Excel 2007 wird das DropDown-Menü im Register ADD-INS in der Gruppe MENÜBEFEHLE angezeigt. Klicken Sie auf eine dieser Schaltflächen, wird Ihr Standard Browser gestartet und ruft die hinterlegte Adresse der Internetseite auf.

Befehlsleisten

Ebenso ist es möglich einer Befehlsschaltfläche auf einer Symbolleiste einen Hyperlink zu einer Webseite zuzuweisen. Die Prozedur MenuHyperlinks zum Erstellen des neuen Hyperlink-Menüs wird über eine Schaltfläche auf einem Tabellenblatt aufgerufen. Wenn Sie die Excel-Anwendung beenden, wird das Menü automatisch aus dem Speicher gelöscht, da es temporär erstellt wurde. Aus diesem Grund haben wir keine Prozedur zum Löschen des Menüs vorgesehen.

Befehlsleisten

왘 E-Mail-Adresse

Befehlsleisten

왘 Zu einem anderem Dokument

398 >> Menüpunkte mit Hyperlinks

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 398 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Abbildung 149: Neues DropDown-Menü mit Hyperlinks

Um das neue Menü HYPERLINKS zu erstellen, wird an die Variable mCmdBarPopUp ein Verweis auf dieses Menü gesetzt. Damit die Variable mCmdBarPopUp erhalten bleibt und in der zweiten Prozedur AddButton ebenfalls verwendet werden kann, muss sie oberhalb der ersten Prozedur deklariert werden. Das der Variablen vorangestellte m stellt ein Präfix für »Modul« dar. Es signalisiert, dass die Variable mit der Private-Anweisung deklariert wurde. Variablen vom Typ Private stehen nur in dem Modul zur Verfügung, in dem sie deklariert wurden. H i n we i s

Befehlsleisten

Befehlsleisten

Private mCmdBarPopUp As CommandBarPopup

Deklarieren Sie Variablen global, um sie in allen Modulen und Klassen des Projektes zur Verfügung zu stellen. Durch die Anweisung Dim gVarName As Datentyp

oder Public gVarName As Datentyp

Befehlsleisten

Befehlsleisten

oberhalb der ersten Prozedur werden Variablen global in einem Modul deklariert. Um diese Variablen im Code leichter zu erkennen, erhalten sie das Präfix g. Nachdem das neue Menü erstellt und über die Caption-Eigenschaft der Beschriftungstext H&yperlinks festgelegt wurde, werden die Schaltflächen mit Hyperlinks im DropDown-Menü erstellt. In unserem Beispiel werden dem Menü fünf Schaltflächen vom Typ msoControlButton hinzugefügt. Man könnte nun in der Prozedur fünfmal den gleichen Codeblock mit den individuellen Angaben hintereinander schreiben. Der folgende Codeblock unterscheidet sich jeweils nur in den Caption- und TooltipText-Angaben.

Für jede weitere Schaltfläche müssten Sie den kompletten Block wiederholt in die Prozedur einfügen. Diese mehrfache Wiederholung verbraucht unnötig Speicherplatz in einem Modul und der Überblick geht schnell verloren. Die Erstellung einer neuen Schaltfläche wird aus vorgenannten Gründen in der Prozedur AddButton ausgelagert. Beim Aufruf der Prozedur AddButton müssen lediglich der Beschriftungstext und die Adresse der Webseite als Argumente an die Parameter strCaption und strTooltip übergeben werden.

Befehlsleisten Befehlsleisten

Abbildung 150: Syntax mit Parametern der AddButton-Prozedur

Befehlsleisten

Befehlsleisten

Beim Schreiben der Anweisung zeigt der Editor die Parameter der Funktion an. Um nachträglich die Parameter abzulesen, platzieren Sie den Mauszeiger innerhalb der Aufrufzeile und wählen im Kontextmenü den Eintrag QUICKINFO oder PARAMETERINFO.

Befehlsleisten

Set cmdBarBtn = mCmdBarPopUp.Controls.Add( _ Type:=msoControlButton) With cmdBarBtn .Style = msoButtonIconAndCaption .FaceId = 610 .Caption = "Beschriftungstext" .TooltipText = "URL der Webseite" .HyperlinkType = msoCommandBarButtonHyperlinkOpen End With

Befehlsleisten

399

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 399 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 400 Dienstag, 4. Dezember 2007 1:42 13

400 >> Menüpunkte mit Hyperlinks '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Hyperlinks ' Modul mdl_14_MenuHyperlinks '=================================================================== Private mCmdBarPopUp As CommandBarPopup Public Sub MenuHyperlinks() Dim cmdBar As CommandBar Set cmdBar = CommandBars.ActiveMenuBar On Error Resume Next cmdBar.Controls("Hyperlinks").Delete On Error GoTo 0 ' Menü "Hyperlinks" erstellen Set mCmdBarPopUp = cmdBar.Controls.Add( _ Type:=msoControlPopup, _ Temporary:=True) ' Beschriftungstext mCmdBarPopUp.Caption = "H&yperlinks" ' erster Menüpunkt mit Hyperlink AddButton strCaption:="&Addison-Wesley", _ strTooltip:="http://www.addison-wesley.de" ' zweiter Menüpunkt mit Hyperlink AddButton strCaption:="&Melanie Breden", _ strTooltip:="http://melanie-breden.de/" ' dritter Menüpunkt mit Hyperlink AddButton strCaption:="M&ichael Schwimmer", _ strTooltip:="http://michael-schwimmer.de/" ' vierter Menüpunkt mit Hyperlink AddButton _ strCaption:="Mi&crosoft Support Newsgroups - &Excel", _ strTooltip:="http://www.microsoft.com/communities/newsgroups/en-us/" & _ "default.aspx?dg=microsoft.public.de.excel&cat=de_DE_" & _ "51272177-a45e-4eb0-84a1-79af866036b7&lang=de&cr=DE" End Sub

Befehlsleisten

Listing 238

401

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Modul mdl_14_MenuHyperlinks '=================================================================== ' Prozedur zum Erstellen der Schaltflächen im DropDown-Menü Private Sub AddButton(strCaption As String, strTooltip As String) Dim cmdBarBtn As CommandBarButton

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 401 Dienstag, 4. Dezember 2007 1:42 13

Listing 239

Befehlsleisten

With cmdBarBtn .Style = msoButtonIconAndCaption .FaceId = 610 .Caption = strCaption .TooltipText = strTooltip .HyperlinkType = msoCommandBarButtonHyperlinkOpen End With End Sub

Befehlsleisten

Set cmdBarBtn = mCmdBarPopUp.Controls.Add( _ Type:=msoControlButton)

Befehlsleisten Befehlsleisten

In diesem Beispiel wird dem Menü EINFÜGEN, (ID:=30005) der ARBEITSBLATT-MENÜLEISTE Application.CommandBars(1) an der zehnten Position ein Befehlsleistensteuerelement aus Excel 2003 temporär hinzugefügt. In Excel 2007 wird der Code nahtlos ausgeführt und die neue Schaltfläche in der Gruppe MENÜBEFEHLE im Register ADDINS erstellt. Bei jedem Klick auf das Steuerelement MY COMMENT wird die Prozedur MyComment gestartet. In der aktiven Zelle wird ein Kommentar mit der aktuellen Datum- und Zeitangabe sowie dem Zelleninhalt erstellt.

Befehlsleisten

163 Schaltfläche einem Menü hinzufügen

Befehlsleisten

Abbildung 151: Neue Befehlsschaltfläche in Menü einfügen

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 402 Dienstag, 4. Dezember 2007 1:42 13

402 >> Schaltfläche einem Menü hinzufügen '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Comments ' Modul mdl_15_AddMyComment '=================================================================== Public Sub AddMyComment() Dim cmdPopUp As CommandBarPopup Dim cmdButton As CommandBarButton ' Verweis auf Menü 'Einfügen' auf Arbeitsblatt-Menüleiste setzen Set cmdPopUp = Application.CommandBars(1) _ .FindControl(ID:=30005) ' Aufruf der Prozedur zum Löschen der Schaltfläche CmdButtonDelete ' Neue Schaltfläche erstellen Set cmdButton = cmdPopUp.Controls.Add _ (Before:=11, _ Temporary:=True) ' Neuer Schaltfläche Eigenschaften zuweisen With cmdButton .Style = msoButtonIconAndCaption .FaceId = 2056 .Caption = "&My Comment" .OnAction = "MyComment" End With End Sub Public Sub CmdButtonDelete() On Error Resume Next Application.CommandBars(1).FindControl(ID:=30005) _ .Controls("My Comment").Delete End Sub

Befehlsleisten

Befehlsleisten

Listing 240

Wenn Sie auf die Befehlsschaltfläche MY COMMENT im Menü EINFÜGEN klicken, wird die hinterlegte Prozedur MyComment aufgerufen. In dieser Prozedur wird die aktive Zelle bearbeitet. Wurde ein Bereich aus mehreren Zellen selektiert, wird die aktive, weiß hinterlegte Zelle angesprochen. Das Makro wird beendet, wenn die Zelle keinen Inhalt aufweist. Enthält diese Zelle bereits einen Kommentar, muss dieser zuerst gelöscht werden, da Excel sonst eine Fehlermeldung ausgeben würde. Anschließend wird mittels der AddComment-Methode dem Bereich ein neuer Kommentar hinzugefügt. Der Text setzt sich aus dem Wert der Now-Funktion, einem Zeilen-

Public Sub MyComment() Dim com As Comment ' Nachfolgende Befehle beziehen sich auf die aktive Zelle With ActiveCell ' Wenn Zelle ohne Inhalte, verlasse Prozedur If .Value = "" Then Exit Sub ' Wenn Zelle Kommentar enthält, diesen löschen If Not .Comment Is Nothing Then .Comment.Delete .AddComment (Now & Chr(10) & .Value) .Comment.Shape.TextFrame.AutoSize = True .Comment.Visible = True End With End Sub Listing 241

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_01_CommandBarsAndControls.xlsm ' Tabelle Comments ' Modul mdl_15_AddMyComment '===================================================================

Befehlsleisten

umbruch Chr(10) und dem Wert der aktiven Zelle .Value zusammen. Durch die Verwendung der AutoSize-Eigenschaft wird die Größe des Kommentarrahmens automatisch dem zugehörigen Text angepasst und zum Schluss der Kommentar über die Visible-Eigenschaft angezeigt.

Befehlsleisten

403

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 403 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

In diesem Beispiel zeigen wir Ihnen, wie Sie über ein DropDown-Feld bequem die Farben der Registerreiter ändern können. Beim Öffnen der Beispielmappe wird im Workbook_Activate-Ereignis die Prozedur AddTabColorIndex zur Erstellung der neuen Symbolleiste MY TABBAR aufgerufen. Da diese Leiste temporär erstellt wird, erübrigt sich ein ausdrückliches Löschen der Leiste beim Beenden der Excel-Anwendung. Beim Deaktivieren der Mappe durch den Wechsel in eine andere geöffnete ExcelArbeitsmappe und auch beim Beenden der Mappe wird die neu erstellte Befehlsleiste im Workbook_Deactivate gelöscht.

Befehlsleisten

Die Farbe einzelner Registerreiter können Sie am schnellsten über das Kontextmenü der Registerreiter REGISTERFARBE ändern. In Excel 2003 steht diese Funktion über das Menü FORMAT | BLATT | REGISTERFARBE zur Verfügung. In Excel 2007 zeigen Sie das Dialogfenster über den Register START | ZEILE | FORMAT | BLÄTTER ANORDNEN | REGISTERFARBE an.

Befehlsleisten

164 Blattregisterfarben über DropDownfeld auswählen

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 404 Dienstag, 4. Dezember 2007 1:42 13

404 >> Blattregisterfarben über DropDownfeld auswählen '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_03_TabColorIndex.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Activate() AddTabColorIndex End Sub Private Sub Workbook_Deactivate() On Error Resume Next Application.CommandBars("My TabBar").Delete End Sub Listing 242

Die benutzerdefinierte Symbolleiste MY TABBAR wird bis Excel 2003 über die Position-Eigenschaft an den unteren Seitenrand der Excel-Anwendung positioniert. Die Left-Eigenschaft gibt den Pixel-Abstand vom linken Seitenrand zum Beginn der Leiste an. In Excel 2007 wird die benutzerdefinierte Symbolleiste im Register ADD-INS angezeigt. Der Leiste werden drei Befehlsschaltflächen hinzugefügt. Das erste Control vom Typ msoControlButton ist eine einfache Schaltfläche und weist die Darstellungsart msoButtonIconAndCaption auf. Dadurch können ein Schaltflächensymbol Icon und ein Beschriftungstext Caption angezeigt werden. Die Auswirkung beim Klick auf diese Schaltfläche wird dem Anwender über die TooltipText-Eigenschaft vermittelt. Hier wird ein beschreibender Text hinterlegt. Die Tag-Eigenschaft gibt Informationen zum Befehlsleistensteuerelement zurück oder legt sie fest. Dies können z. B. Daten sein, die als Argument in Prozeduren verwendet werden können, oder Informationen, die das Steuerelement kennzeichnen. Wir verwenden die Tag-Eigenschaft, um beim Klick auf diese Schaltfläche wechselnde Informationen darin zu speichern und in weiteren Prozeduren auszulesen. Zu Beginn weist die erste Schaltfläche die Beschriftung AKTIVER REGISTERREITER auf. Änderungen der Farbe wirken sich dementsprechend nur auf den Tabellenregister des aktiven Tabellenblattes aus (siehe Abbildung 152). Beim Klick auf die erste Schaltfläche wird die Prozedur AllOrActiveSheet aufgerufen, welche über die OnAction-Eigenschaft hinterlegt ist. Die State-Eigenschaft wird zu Beginn auf msoButtonUp festgelegt. Die Schaltfläche wird dadurch als »nicht gedrückt« dargestellt.

405

Die ListHeaderCount-Eigenschaft wird verwendet um eine Trennlinie zwischen zwei Listenelemente zu erstellen. Der angegebene Wert gibt an, wie viele Listenelemente über der Trennlinie angezeigt werden. In unserem Beispiel wird für die ListHeaderCount-Eigenschaft ein Wert von –1 angegeben. Dieser zeigt an, dass im Kombinationsfeldsteuerelement keine Trennlinie vorhanden ist. Für das dritte Steuerelement der benutzerdefinierten Symbolleiste MY TABBAR wird wieder eine einfache Schaltfläche verwendet. Auf die Funktionsweisen der bei Klick auf die Schaltflächen aufgerufenen Prozeduren gehen wir an späterer Stelle ein. Nachfolgend sehen Sie zunächst die Prozedur zur Erstellung der Symbolleiste.

Befehlsleisten Befehlsleisten Befehlsleisten

Die AddItem-Methode fügt dem DropDown-Feld Listenelemente hinzu. Dabei wird zum einen der anzuzeigende Text festgelegt. Die Angabe des Textes ist zwingend notwendig. Das zweite optionale Argument Index gibt die Position des Elements in der Liste an. Wenn Sie dieses Argument auslassen, wird das Element am Ende der Liste hinzugefügt. Im Grunde könnte in diesem Beispiel auf die Index-Angabe verzichtet werden, da die Elemente in aufgeführter Reihenfolge fortlaufend angezeigt werden sollen. Die Angabe dient lediglich als Hinweis auf die ColorIndex-Eigenschaft. Diese ist in unserem Beispiel identisch mit der ListIndex-Eigenschaft, welche die Indexnummer des markierten Elements im Listenbereich des Kombinationsfeldsteuerelements der Befehlsleiste zurückgibt. Wenn die Farben der Standardpalette nicht verändert wurden, hat die Farbe Schwarz den Farbindex 1, Weiß den Farbindex 2 usw.

Befehlsleisten

Die zweite Schaltfläche ist vom Typ msoControlComboBox und stellt ein Kombinationsfeldsteuerelement dar. Über die DropDownLines-Eigenschaft wird die Anzahl der sichtbaren Zeilen im angegebenen DropDown-Feld festgelegt. Die DropDownWidth-Eigenschaft gibt die Breite (in Pixel) für das angegebene Element an.

Befehlsleisten

Abbildung 152: Register des aktiven Blattes wird blau gefärbt.

Befehlsleisten

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 405 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 406 Dienstag, 4. Dezember 2007 1:42 13

406 >> Blattregisterfarben über DropDownfeld auswählen '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_03_TabColorIndex.xlsm ' Modul mdl_01_AddTabColorIndex '=================================================================== Public Dim Dim Dim

Sub AddTabColorIndex() cmdBar As CommandBar cmdBarCbo As CommandBarComboBox cmdBarBtn As CommandBarButton

' Evtl. vorhandene Leiste löschen On Error Resume Next CommandBars("My TabBar").Delete On Error GoTo 0 ' Neue Symbolleiste am unteren Seitenrand erstellen Set cmdBar = CommandBars.Add( _ Name:="My TabBar", _ Position:=msoBarBottom, _ Temporary:=True) With cmdBar .Left = 150 .Visible = True End With ' erste Schaltfläche erstellen Set cmdBarBtn = cmdBar.Controls.Add(Type:=msoControlButton) With cmdBarBtn .Style = msoButtonIconAndCaption .FaceId = 1 .Caption = "aktiver Registerreiter" .TooltipText = "Wechsel zwischen aktivem " & _ "und allen Registerreitern" .Tag = "ActiveSh" .State = msoButtonUp .OnAction = "AllOrActiveSheet" End With ' DropDown-Menü erstellen Set cmdBarCbo = cmdBar.Controls.Add(Type:=msoControlComboBox) With cmdBarCbo .Caption = "Register-Farben" .TooltipText = "Farbe auswählen" .DropDownLines = 5 .DropDownWidth = 70 .AddItem "Schwarz", Index:=1 Listing 243

Klicken Sie in der neuen Symbolleiste auf die erste Schaltfläche AKTIVER REGISTERREITER, wird die Prozedur AllOrActiveSheet aufgerufen. Die Schaltfläche ist als Umschaltfläche zu betrachten. Da ein ToogleButton als Befehlsleistensteuerelement nicht zur Verfügung steht, wird der Anzeigestatus einer gedrückten, bzw. nicht gedrückten Schaltfläche über die State-Eigenschaft festgelegt. In dieser Prozedur werden vier Eigenschaften des angeklickten Steuerelementes verändert, oder genauer gesagt: gewechselt. Am Beispiel der State-Eigenschaft verdeutlichen wir die Funktionsweise der für jede Eigenschaft angewandten IIf-Funktion. Die IIf-Funktion gibt einen von zwei Teilen, abhängig von der Auswertung eines Ausdrucks, zurück. Die Syntax lautet: Objekt/Variable = IIf(expr, truepart, falsepart)

Geben Sie für expr einen auszuwertenden Ausdruck an, dessen Ergebnis Wahr oder Falsch sein kann. Ist der Ausdruck Wahr, wird der Wert des ersten Argumentes truepart zurückgegeben. Ist der Wahrheitswert Falsch, wird falsepart an das/die angegebene Objekt/Variable zurückgegeben. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_03_TabColorIndex.xlsm ' Modul mdl_02_AllOrActiveSheet '=================================================================== Listing 244

Befehlsleisten Befehlsleisten Befehlsleisten

Listing 243 (Forts.)

Befehlsleisten

' dritte Schaltfläche erstellen Set cmdBarBtn = cmdBar.Controls.Add(Type:=msoControlButton) With cmdBarBtn .Style = msoButtonIconAndCaption .FaceId = 964 .Caption = " Farbe zurücksetzen" .TooltipText = "Standardfarbe setzen" .OnAction = "ResetColor" End With End Sub

Befehlsleisten

.AddItem "Weiß", Index:=2 .AddItem "Rot", Index:=3 .AddItem "Grün", Index:=4 .AddItem "Blau", Index:=5 .AddItem "Gelb", Index:=6 .AddItem "Pink", Index:=7 .AddItem "Türkis", Index:=8 .OnAction = "PaintTabs" .ListHeaderCount = -1 End With

Befehlsleisten

407

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 407 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

2471_Excel-VBA.book Seite 408 Dienstag, 4. Dezember 2007 1:42 13

408 >> Blattregisterfarben über DropDownfeld auswählen Public Sub IIFTest() Dim lngWert As Long

Befehlsleisten

Befehlsleisten

Befehlsleisten

MsgBox lngWert & _ " ist " & _ IIf(lngWert > 10, "größer", "kleiner") & _ " 10" End Sub Listing 244 (Forts.)

Abbildung 153: Meldung mit integrierter Auswertung

Hinweis

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

lngWert = 5

IIf wertet immer sowohl den Teil truepart als auch den Teil falsepart aus, auch dann, wenn nur einer von beiden Teilen zurückgegeben wird. Aus diesem Grund kann es zu unerwünschten Nebeneffekten kommen. Wenn z. B. die Auswertung von falsepart zu einem Fehler aufgrund einer Division durch Null führt, tritt ein Fehler auch dann auf, wenn expr den Wert True hat.

In unseren Beispielen ermitteln wir den Wahrheitswert eines vorgegebenen Textausdruckes. Dieser kann nur True oder False sein und wird deswegen zu keinem Fehler führen. Die Codezeile: .State = IIf(.State = msoButtonUp, msoButtonDown, msoButtonUp)

wechselt den Status der State-Eigenschaft und kann ebenso in einer If...Then... Else-Anweisung programmiert werden, das Ergebnis ist identisch: If .State = msoButtonUp Then .State = msoButtonDown Else .State = msoButtonUp End If

Es obliegt nun dem Programmierer, für welche Methode er sich entscheidet. In folgender Prozedur werden die angegebenen Eigenschaften entsprechend dem Ergebnis aus den nachstehenden IIf-Funktionen eingestellt.

409

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_03_TabColorIndex.xlsm ' Modul mdl_02_AllOrActiveSheet '=================================================================== Public Sub AllOrActiveSheet() With Application.CommandBars("My TabBar").Controls(1) .State = IIf(.State = msoButtonUp, msoButtonDown, msoButtonUp)

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 409 Dienstag, 4. Dezember 2007 1:42 13

.Caption = IIf(.Caption = "aktiver Registerreiter", _ "alle Registerreiter", _ "aktiver Registerreiter")

Befehlsleisten

.FaceId = IIf(.FaceId = 1, 608, 1)

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_03_TabColorIndex.xlsm ' Modul mdl_03_PaintTabs '=================================================================== Public Dim Dim Dim

Sub PaintTabs() strTag As String intColor As Integer lngSheet As Long

strTag = Application.CommandBars("My TabBar") _ .Controls(1).Tag Listing 246

Befehlsleisten Befehlsleisten

Klicken Sie in der benutzerdefinierten Symbolleiste MY TABBAR auf eine Schaltfläche des aufgeklappten DropDown-Feldes, dann wird die Prozedur PaintTabs aufgerufen. Es muss ermittelt werden, ob nur der Registerreiter des aktiven Tabellenblattes oder alle Registerreiter mit einer bestimmten Farbe versehen werden sollen. Diese Informationen werden aus der Tag-Eigenschaft des ersten Steuerelementes und der ListIndex-Eigenschaft des zweiten Steuerelementes (DropDown-Feld) ausgelesen. In einer If...Then...Else-Anweisung werden diese Informationen umgesetzt und der/die Registerreiter gefärbt.

Befehlsleisten

Listing 245

Befehlsleisten

End With End Sub

Befehlsleisten

.Tag = IIf(.Tag = "AllSh", "ActiveSh", "AllSh")

Befehlsleisten

2471_Excel-VBA.book Seite 410 Dienstag, 4. Dezember 2007 1:42 13

410 >> Blattregisterfarben über DropDownfeld auswählen intColor = Application.CommandBars("My TabBar") _ .Controls(2).ListIndex

For lngSheet = 1 To Sheets.Count Sheets(lngSheet).Tab.ColorIndex = intColor Next ' bzw. "aktives" Blattregister einfärben ElseIf strTag = "ActiveSh" Then ActiveSheet.Tab.ColorIndex = intColor End If End Sub Listing 246 (Forts.)

Die dritte Schaltfläche FARBE ZURÜCKSETZEN ruft die Prozedur ResetColor auf. Hier wird über die Tag-Eigenschaft des ersten Steuerelementes festgestellt, von welchem Registerreiter die Farbe zurückgesetzt werden soll. Diese Anweisung entspricht dem Befehl KEINE FARBE im Dialog REGISTERFARBE ÄNDERN. Enthält die Tag-Eigenschaft den Wert AllSh, werden in einer For...Next-Anweisung alle Blätter der Beispieldatei durchlaufen und jeweils die eingestellte Farbe zurückgesetzt. Nur die Farbe des aktiven Arbeitsblattes wird zurückgesetzt, wenn die Tag-Eigenschaft des ersten Steuerelementes den Wert ActiveSh aufweist.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

' Anhand der Tag-Informationen "alle" Blattregister einfärben If strTag = "AllSh" Then

Abbildung 154: Farben aller Registereiter werden zurückgesetzt.

411

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_12_TabColorIndex.xls ' Modul mdl_04_ResetColor '=================================================================== Public Sub ResetColor() Dim strTag As String Dim lngSheet As Long

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 411 Dienstag, 4. Dezember 2007 1:42 13

' bzw. "aktives" Blattregister zurücksetzen ElseIf strTag = "ActiveSh" Then ActiveSheet.Tab.ColorIndex = -4142 End If End Sub Listing 247

Befehlsleisten

For lngSheet = 1 To Sheets.Count Sheets(lngSheet).Tab.ColorIndex = -4142 Next

Befehlsleisten

' Anhand der Tag-Informationen "alle" Blattregister ' zurücksetzen If strTag = "AllSh" Then

Befehlsleisten

strTag = Application.CommandBars("My TabBar") _ .Controls(1).Tag

Befehlsleisten

In diesem Beispiel wird der Schutz-Status direkt im Kontextmenü der Zelle angezeigt und kann mit einem Klick auf die jeweilige Schaltfläche geändert werden.

Befehlsleisten

In der Registerkarte START in der Gruppe ZELLEN werden im Auswahlfeld FORMAT die Schutz-Optionen für Zellen eingestellt. Den Schutz-Status der aktiven Zelle können Sie ebenfalls über das Zellenkontext-Menü ZELLEN FORMATIEREN oder die Tastenkombination (Strg) + (1) im Register SCHUTZ ablesen und ändern.

Befehlsleisten

165 Zellenschutz im Kontextmenü anzeigen und ändern

412 >> Zellenschutz im Kontextmenü anzeigen und ändern

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 412 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Abbildung 155: Zusätzliche Schaltflächen im Kontextmenü der Zelle

Wenn Sie die Beispieldatei öffnen, wird im Workbook_Activate-Ereignis die Prozedur AddLockedInContext aufgerufen. Diese fügt der Befehlsleiste CELL, also dem Kontextmenü der Zelle, zwei Schaltflächen hinzu. Da diese Schaltflächen temporär erstellt werden, erübrigt sich ein ausdrückliches Löschen der Leiste beim Beenden der ExcelAnwendung. Die neuen Kontexteinträge stehen nur in der Beispielmappe zur Verfügung. Beim Wechsel in eine andere geöffnete Excel-Arbeitsmappe werden sie über das Workbook_Deactivate-Ereignis gelöscht. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_04_ChangeLockedStatus.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Activate() AddLockedInContext End Sub

Befehlsleisten

Private Sub Workbook_Deactivate() On Error Resume Next Listing 248

Um die beiden eingefügten Steuerelemente auch optisch von den restlichen Schaltflächen des Menüs zu trennen, wird vor dem dritten Element eine Trennlinie mittels der BeginGroup-Eigenschaft eingefügt. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_04_ChangeLockedStatus.xlsm ' Modul mdl_01_AddLockedInContext '=================================================================== Public Sub AddLockedInContext() Dim cmdBar As CommandBar Dim cmdBarCtrl As CommandBarControl Set cmdBar = Application.CommandBars("Cell") On Error Resume Next cmdBar.Controls("Zelle gesperrt").Delete cmdBar.Controls("Formel ausgeblendet").Delete On Error GoTo 0 Set cmdBarCtrl = cmdBar.Controls.Add( _ Type:=msoControlButton, _ Before:=1, _ Temporary:=True) With cmdBarCtrl .Caption = "Zelle gesperrt" .OnAction = "LockedCells" End With

Befehlsleisten Befehlsleisten

Zu Beginn der Prozedur wird ein Verweis von der Befehlsleiste CELL (ZellenkontextMenü) auf die Variable cmdBar gesetzt. Im weiteren Code wird die CELL-Symbolleiste über cmdBar angesprochen. Nachdem evtl. vorhandene Schaltflächen gleichen Namens gelöscht wurden, werden die beiden neuen Schaltflächen ZELLE GESPERRT und FORMEL AUSGEBLENDET an den Anfang des Zellen-Kontextmenüs eingefügt. Die Namen der Prozeduren, die bei einem Klick auf die Schaltflächen ausgeführt werden sollen, werden der OnAction-Eigenschaft zugewiesen.

Befehlsleisten

Listing 248 (Forts.)

Befehlsleisten

With Application.CommandBars("Cell") .Controls("Cell Locked").Delete .Controls("Formula Hidden").Delete End With End Sub

Befehlsleisten

413

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 413 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Listing 249

Befehlsleisten

Befehlsleisten

Befehlsleisten

414 >> Zellenschutz im Kontextmenü anzeigen und ändern Set cmdBarCtrl = cmdBar.Controls.Add( _ Type:=msoControlButton, _ Before:=2, _ Temporary:=True) With cmdBarCtrl .Caption = "Formel ausgeblendet" .OnAction = "FormulaHidden" End With cmdBar.Controls(3).BeginGroup = True End Sub Listing 249 (Forts.)

Damit zu jeder Zelle im Tabellenblatt deren aktueller Schutz-Status angezeigt wird, setzen wir das Worksheet_BeforeRightClick-Ereignis ein. Sobald Sie mit der rechten Maustaste in eine Zelle klicken, werden zunächst die Schaltflächen über die StateEigenschaft aktualisiert. Mit der msoButtonDown-Konstante wird der Schaltfläche ein Häkchen hinzugefügt und signalisiert, dass die betreffende Eigenschaft aktiviert ist. Achtung

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 414 Dienstag, 4. Dezember 2007 1:42 13

Über die Locked-Eigenschaft wird überprüft, ob die selektierte Zelle, bzw. in einem markierten Bereich die aktive Zelle, gesperrt ist. In der Prozedur wird bewusst nicht die Variable Target für diese Kontrolle verwendet. Wenn ein Bereich aus mehreren Zellen markiert wurde, werden alle Zellen des Bereichs und deren Eigenschaften in der Variablen Target gespeichert. Wenn diese Zellen unterschiedliche Schutz-Eigenschaften aufweisen, kann Excel sich nicht zwischen True und False für die Locked-Eigenschaft entscheiden und liefert den Wert NULL an Target zurück. Das wiederum würde in der IIf-Funktion zu einem Fehler führen. Das Dialogfenster ZELLEN FORMATIEREN (siehe Abbildung 155) zeigt bei unterschiedlichen Zellenformatierungen ein graues Häkchen im jeweiligen Kontrollkästchen an.

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_04_ChangeLockedStatus.xlsm ' Ereignis Tabelle1 (Tabelle1) '=================================================================== Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, _ Cancel As Boolean)

Befehlsleisten

With Application.CommandBars("Cell") .Controls(1).State = _ Listing 250

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_04_ChangeLockedStatus.xlsm ' Modul mdl_02_LockedCells '=================================================================== Public Sub LockedCells() Selection.Locked = Not ActiveCell.Locked Application.CommandBars("Cell").Controls(1).State = _ IIf(ActiveCell.Locked, msoButtonDown, msoButtonUp) End Sub Listing 251 '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_04_ChangeLockedStatus.xlsm ' Modul mdl_03_FormulaHidden '=================================================================== Public Sub FormulaHidden() Selection.FormulaHidden = Not ActiveCell.FormulaHidden Application.CommandBars("Cell").Controls(2).State = _ IIf(ActiveCell.FormulaHidden, msoButtonDown, msoButtonUp) End Sub Listing 252

Befehlsleisten Befehlsleisten

Wenn Sie auf eine der eingefügten Schaltflächen klicken, wird die jeweils hinterlegte Prozedur aufgerufen. Die Einstellung der selektierten Zelle, bzw. aller Zellen im markierten Bereich Selection, wird entsprechend der aktiven Zelle gewechselt und die State-Eigenschaft der Schaltflächen angepasst.

Befehlsleisten

Listing 250 (Forts.)

Befehlsleisten

.Controls(2).State = _ IIf(ActiveCell.FormulaHidden, msoButtonDown, msoButtonUp) End With End Sub

Befehlsleisten

IIf(ActiveCell.Locked, msoButtonDown, msoButtonUp)

Befehlsleisten

415

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 415 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 416 Dienstag, 4. Dezember 2007 1:42 13

416 >> Kontextmenü durch Kaskaden-Menü ersetzen

166 Kontextmenü durch Kaskaden-Menü ersetzen Wenn Sie mit der rechten Maustaste auf eine Zelle oder eine Zeilen- bzw. Spaltenüberschrift klicken, wird das jeweilige Kontextmenü angezeigt. Diese Anzeige können Sie unterbinden, indem Sie die Enabled-Eigenschaft der Befehlsleisten auf False setzen. Folgende Prozeduren de- bzw. aktivieren die gängigsten Kontextmenüs im Tabellenblatt: '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_05_KaskadeContext.xlsm ' Modul mdl_01_ContextOnOff '=================================================================== ' Kontextmenüs deaktivieren Public Sub OnContext() ContextOnOff True End Sub ' Kontextmenüs aktivieren Public Sub OffContext() ContextOnOff False End Sub

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Listing 253 '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_05_KaskadeContext.xlsm ' Modul mdl_01_ContextOnOff '=================================================================== Public Sub ContextOnOff(blnContext As Boolean) With Application .CommandBars("Cell").Enabled = blnContext .CommandBars("Row").Enabled = blnContext .CommandBars("Column").Enabled = blnContext .CommandBars("System").Enabled = blnContext .CommandBars("Toolbar List").Enabled = blnContext .CommandBars("Ply").Enabled = blnContext End With End Sub Listing 254

In unserer Beispieldatei sollen die Kontextmenüs nur im Tabellenblatt CONTEXTOFF deaktiviert werden. Schreiben Sie dazu die Prozeduren OnContext und OffContext in die entsprechenden Ereignisprozeduren.

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_05_KaskadeContext.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Activate() If ActiveSheet.Name = "ContextOff" Then ContextOnOff False End If End Sub Private Sub Workbook_Deactivate() If ActiveSheet.Name = "ContextOff" Then ContextOnOff True End If End Sub

Befehlsleisten

417

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 417 Dienstag, 4. Dezember 2007 1:42 13

Listing 256

Erstellen Sie bei einem Rechtsklick im Tabellenblatt CONTEXTOFF über das Worksheet_ BeforeRightClick-Ereignis ein benutzerdefiniertes Kontextmenü. In diesem Beispiel besteht die erzeugte Befehlsleiste aus einem Kaskaden-Menü. Die einzelnen Stufen der Kaskade werden durch PopUp-Menüs erzeugt. Zeigen Sie das Kontextmenü im Anschluss mit der ShowPopUp-Methode an.

Befehlsleisten Befehlsleisten

Private Sub Worksheet_Deactivate() ContextOnOff True End Sub

Befehlsleisten

Private Sub Worksheet_Activate() ContextOnOff False End Sub

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_05_KaskadeContext.xls ' Ereignis Tabelle1 (ContextOff) '===================================================================

Befehlsleisten

Listing 255

418 >> Kontextmenü durch Kaskaden-Menü ersetzen

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Abbildung 156: Benutzerdefiniertes Kontextmenü ersetzt das Kontextmenü der Zelle

Hinwei s

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 418 Dienstag, 4. Dezember 2007 1:42 13

Wenn das auf den Rechtsklick folgende Kontextmenü nicht deaktiviert ist, wird es im Anschluss an das benutzerdefinierte Kontextmenü ebenfalls angezeigt.

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_05_KaskadeContext.xlsm ' Ereignis Tabelle1 (ContextOff) '=================================================================== Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, _ Cancel As Boolean) Dim cmdBar As CommandBar Dim cmdBarBtn As CommandBarButton Dim CtrlPop1 As CommandBarPopup Dim CtrlPop2 As CommandBarPopup On Error Resume Next Application.CommandBars("Context").Delete On Error GoTo 0 ' Befehlsleiste Kontextmenü Set cmdBar = Application.CommandBars.Add("Context", _ Position:=msoBarPopup, _ Temporary:=True) With cmdBar ' Schaltfläche in Kontextmenü Listing 257

' Schaltfläche im Untermenü 1 Set cmdBarBtn = CtrlPop1.Controls.Add(Type:=msoControlButton) With cmdBarBtn .Caption = "Control in 2. Stufe" ' weitere Eigenschaften End With ' Untermenü 2 im Untermenü 1 Set CtrlPop2 = CtrlPop1.Controls.Add(Type:=msoControlPopup) With CtrlPop2 .Caption = "2. Stufe" ' weitere Eigenschaften End With ' Schaltfläche im Untermenü 2 Set cmdBarBtn = CtrlPop2.Controls.Add(Type:=msoControlButton) With cmdBarBtn .Caption = "Control in 3. Stufe" ' weitere Eigenschaften End With End With cmdBar.ShowPopup End Sub

Befehlsleisten Befehlsleisten

' Untermenü 1 in Kontextmenü Set CtrlPop1 = cmdBar.Controls.Add(Type:=msoControlPopup) With CtrlPop1 .Caption = "1. Stufe" ' weitere Eigenschaften End With

Befehlsleisten

Set cmdBarBtn = cmdBar.Controls.Add(Type:=msoControlButton) With cmdBarBtn .Caption = "Control in Kontext" ' weitere Eigenschaften End With

Befehlsleisten

419

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 419 Dienstag, 4. Dezember 2007 1:42 13

Das Worksheet_BeforeRightClick-Ereignis wird ausgelöst, wenn Sie mit der rechten Maustaste auf einen Spalten-, Zeilenkopf oder eine bzw. mehrere Zellen klicken. Bevor die Prozedur beendet wird, wird das besagte Spalten-, Zeilen- oder ZellenKontextmenü angezeigt. Es gibt kein Objekt, das angibt, welches der drei Kontextmenüs durch den Rechtsklick aufgerufen wird. Um dennoch gezielt auf den Rechtsklick zu reagieren und ein einzelnes Kontextmenü ansprechen zu können, wird

Befehlsleisten

167 Welches Kontextmenü wurde aufgerufen?

Befehlsleisten

Listing 257 (Forts.)

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 420 Dienstag, 4. Dezember 2007 1:42 13

420 >> Welches Kontextmenü wurde aufgerufen?

anhand der markierten Zellen, Zeilen oder Spalten eine Berechnung durchgeführt. Anhand der Berechnung kann eindeutig bestimmt werden, welches Kontextmenü angezeigt werden soll. Setzen Sie den Parameter Cancel auf True, damit das Kontextmenü nicht angezeigt wird. Folgende If...Then...Else-Anweisung überprüft, ob eine oder mehrere Spalten markiert wurden. If Target.Count / Rows.Count = Target.Columns.Count Then Cancel = True ' Aufruf oder Code eines benutzerdefinierten Kontextmenüs End If

Das SPALTEN-Kontextmenü wird im Wahrheitsfall nur in dem Tabellenblatt deaktiviert, in welchem die Prozedur hinterlegt ist. Das ZEILEN- und ZELLEN-Kontextmenü wird beim jeweiligen Rechtsklick weiterhin angezeigt. In der Beispieldatei wird nach einem Rechtsklick ein Meldungsfenster angezeigt. Dieses enthält die Information, wo der Rechtsklick ausgeführt wurde. Das üblicherweise folgende Kontextmenü wird nicht angezeigt, da die Cancel-Eigenschaft im Anschluss an die If...Then...Else-Anweisung auf True gesetzt wurde. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_06_CellRowColumnContext.xlsm ' Ereignis Tabelle1 (Tabelle1) '=================================================================== Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, _ Cancel As Boolean) Dim strInfo As String If Target.Count / Rows.Count = Target.Columns.Count Then strInfo = "Spaltenkopf" ElseIf Target.Count / Columns.Count = Target.Rows.Count Then strInfo = "Zeilenkopf" ElseIf Target.Count / Rows.Count Target.Columns.Count Or _ Target.Count / Columns.Count Target.Rows.Count Then strInfo = "Zelle" End If

Befehlsleisten

Befehlsleisten

MsgBox strInfo & " wurde angeklickt" Cancel = True End Sub Listing 258

In Excel verwenden Sie die ZEICHEN-Funktion, um Zahlen in Zeichen umzuwandeln. Die Funktion erwartet eine Zahl zwischen 1 und 255, die das von Ihnen gewünschte Zeichen in der gewählten Schriftart angibt. Das jeweilige Zeichen ist Bestandteil des Zeichensatzes, der auf Ihrem Computer verwendet wird. Die Zahlen von 0 bis 32 entsprechen den nicht darstellbaren Standard-ASCII-Codes. Chr(10) gibt zum Beispiel ein Zeilenvorschubzeichen zurück. Im Tabellenblatt SONDERZEICHEN der Beispielmappe werden in einer Spalte alle verfügbaren Sonderzeichen der Schriftart Arial über die Zeichen-Funktion dargestellt. Die fortlaufende Angabe des Zahlenwertes erreichen wir durch die Funktion Zeile(). Diese gibt die Zeilenzahl der Zeile wieder, in welcher die Formel steht. Die Formel =ZEICHEN(ZEILE()) in Zelle A191 liefert das Zeichen ¿. Die erzeugten Sonderzeichen können Sie kopieren und über das ZELL-KONTEXTMENÜ | INHALTE EINFÜGEN | WERTE in feste Werte umwandeln. Ebenfalls können Sie den ermittelten Zeichencode mit gedrückter (Alt)-Taste und Eingabe des Zahlencodes über die Zehnertastatur eingeben. Damit der Unicode-Zeichensatz vervollständigt wird, müssen Sie der dreistelligen Codezahl eine 0 voranstellen. Das Promille-Zeichen ‰ erzeugen Sie zum Beispiel mit der Tastenkombination (Alt) (0137). Die Eingabe von Sonderzeichen lässt sich über ein zusätzliches Menü im Zellkontextmenü wesentlich vereinfachen. Klicken Sie auf eine der Schaltflächen, dann wird das auf der Schaltfläche dargestellte Zeichen an der aktuellen Cursorposition eingefügt (siehe Abbildung 157).

Befehlsleisten Befehlsleisten Befehlsleisten

In Excel 2002/2003 können Sie Sonderzeichen über das Menü EINFÜGEN | SONDERZEIin eine Zelle einfügen. In vorherigen Excel-Versionen ist dies nur sehr umständlich zu bewerkstelligen. In diesen Versionen können Sie zum Beispiel in Microsoft Word ein Sonderzeichen über das Menü EINFÜGEN | SONDERZEICHEN erstellen, kopieren und dann über die Zwischenablage in Ihre Excel-Datei einfügen. Diese Möglichkeit bietet auch die Zeichentabelle, welche Sie über die Windows-Schaltfläche START | PROGRAMME | ZUBEHÖR | SYSTEMPROGRAMME | ZEICHENTABELLE erreichen. In der Zeichentabelle ersehen Sie zu den ausgewählten Zeichen den entsprechenden vierstelligen Unicode-Zeichensatz. Mit diesem Zeichensatz ist es möglich, ein Zeichen direkt in ein Dokument oder eine Zelle einzufügen. Setzen Sie die Einfügemarke an die Stelle, an der das Sonderzeichen eingefügt werden soll, und halten Sie die (Alt)Taste gedrückt, während Sie über die Tasten der Zehnertastatur die Unicode-Zeichenwerte eingeben. CHEN

Befehlsleisten

Um in Excel 2007 ein Sonderzeichen in die aktive Zelle einzufügen, klicken Sie auf der Registerkarte Einfügen in der Gruppe Text auf Symbol.

Befehlsleisten

168 Symbole über Kontextmenü einfügen

Befehlsleisten

421

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 421 Dienstag, 4. Dezember 2007 1:42 13

422 >> Symbole über Kontextmenü einfügen

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 422 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 157: Sonderzeichen über Kontextmenü einfügen

Ermitteln Sie zunächst im Tabellenblatt SONDERZEICHEN der Beispieldatei die Zahlencodes der Zeichen, welche Sie im Kontextmenü anbieten wollen. Diese werden in den beiden Arrays varSymbol1 und varSymbol2 hinterlegt. In diesem Beispiel verwenden wir die FindControl-Methode, um das evtl. bereits vorhandene Steuerelement SONDERZEICHEN zu löschen. Zur Identifizierung wird die TagEigenschaft der Schaltfläche herangezogen. Diese gibt Informationen zum Befehlsleisten-Steuerelement zurück oder legt sie fest. Dies können z. B. Daten sein, die als Argument in Prozeduren verwendet werden können, oder Informationen, die das Steuerelement kennzeichnen. Der Tag-Eigenschaft der zu löschenden Schaltfläche wurde der Wert SpecialTag zugewiesen. Dadurch ist das Steuerelement in der FindControl-Methode eindeutig zu erkennen. Bevor dem Zellkontextmenü ein neues Menü hinzugefügt wird, erstellen Sie über die

BeginGroup-Eigenschaft vor dem ersten Element eine neue Gruppe. Diese erkennen

Sie an einer Trennlinie zwischen den Elementen auf der Befehlsleiste. Anschließend wird an erster Stelle des Zellenkontextmenüs das neue Menü SONDERZEICHEN vom Typ msoControlPopup eingefügt. Diesem wiederum werden zwei einfache Schaltflächen ZEICHEN2 und ZEICHEN1 vom Typ msoControlButton zugewiesen. Die Abfolge der Erstellung erfolgt in umgekehrter Reihenfolge, da das neue Element jeweils an erster Stelle im Kontextmenü eingefügt wird und somit die anderen Elemente eine Position nach unten verschiebt. Die in den Arrays aufgeführten Zahlencodes werden nacheinander in einer For...Next-Anweisungen den Schaltflächen ZEICHEN2 und ZEICHEN1 zugewiesen. Die Beschriftung der Schaltflächen wird über die Caption-Eigenschaft vorgenommen.

Den Tag-Eigenschaften der SONDERZEICHEN-Schaltflächen wird ebenfalls der Zahlencode zugewiesen. Dadurch kann das aufgerufene Makro InsertSymbol eindeutig bestimmen, welche Schaltfläche den Prozeduraufruf verursacht hat. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_07_InsertSymbol.xlsm ' Modul mdl_01_SymbolContext '=================================================================== Public Dim Dim Dim Dim Dim Dim Dim

Sub ContextInsertSymbol() cmdBar As CommandBar cmdBarCtrl As CommandBarControl ctrlPopUp As CommandBarControl cmdBarBtn As CommandBarButton varSymbol1() As Variant varSymbol2() As Variant lngItem As Long

' Hier die Zeichen ergänzen varSymbol1 = Array("137", "177", "178", "179", _ "188", "189", "190", "216") varSymbol2 = Array("131", "163", "166", "124", _ "139", "155", "171", "187", _ "153", "169", "174") On Error Resume Next Application.CommandBars("Cell").FindControl(Tag:="SpecialTag").Delete On Error GoTo 0 Set cmdBar = Application.CommandBars("Cell") ' Vor dem ersten Steuerelement des Zell-Kontextmenüs ' eine neue Gruppe beginnen Listing 259

Befehlsleisten

왘 Chr(Val(varSymbol2(lngItem))) Die Chr-Funktion wandelt den Zahlenwert in das entsprechende Zeichen, das dem angegebenen Zeichen-Code zugeordnet ist, um.

Befehlsleisten

왘 Val(varSymbol2(lngItem)) Über die Val-Funktion wird der in String-Form enthaltene Zahlencode in einen numerischen Wert umgewandelt

Befehlsleisten

왘 varSymbol2(lngItem) Gibt den fortlaufenden Zahlencode des zweiten Arrays varSymbol2 als String zurück

Befehlsleisten

Diese Syntax setzt sich aus folgenden Teilen zusammen:

Befehlsleisten

.Caption = Chr(Val(varSymbol2(lngItem)))

Befehlsleisten

423

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 423 Dienstag, 4. Dezember 2007 1:42 13

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 424 Dienstag, 4. Dezember 2007 1:42 13

424 >> Symbole über Kontextmenü einfügen cmdBar.Controls(1).BeginGroup = True 'Flüchtiges Menü im Zell-Kontextmenü erstellen Set cmdBarCtrl = cmdBar.Controls.Add( _ Type:=msoControlPopup, _ Before:=1, _ Temporary:=True) With cmdBarCtrl .Caption = "Sonderzeichen" .Tag = "SpecialTag" End With ' Zweites Untermenü anlegen Set ctrlPopUp = cmdBarCtrl.Controls.Add( _ Type:=msoControlPopup, _ Before:=1) ctrlPopUp.Caption = "Zeichen 2" For lngItem = 0 To UBound(varSymbol2) Set cmdBarBtn = ctrlPopUp.Controls.Add(msoControlButton) With cmdBarBtn .Caption = Chr(Val(varSymbol2(lngItem))) .Tag = varSymbol2(lngItem) .OnAction = "InsertSymbol" End With Next lngItem ' Erstes Untermenü anlegen Set ctrlPopUp = cmdBarCtrl.Controls.Add( _ Type:=msoControlPopup, _ Before:=1) ctrlPopUp.Caption = "Zeichen 1" For lngItem = 0 To UBound(varSymbol1) Set cmdBarBtn = ctrlPopUp.Controls.Add(msoControlButton) With cmdBarBtn .Caption = Chr(Val(varSymbol1(lngItem))) .Tag = varSymbol1(lngItem) .OnAction = "InsertSymbol" End With Next lngItem End Sub Listing 259 (Forts.)

Wenn Sie auf eine SONDERZEICHEN-Schaltfläche klicken, wird die Prozedur InsertSymbol aufgerufen. Jetzt gilt es nur noch zu ermitteln, welches Sonderzeichen an die

Listing 260

Wenn Sie die Beispieldatei öffnen, wird über das Workbook_Activate-Ereignis die Prozedur ContextInsertSymbol aufgerufen. Diese erstellt das Menü SONDERZEICHEN mit den beiden Untermenüs ZEICHEN1 und ZEICHEN2 im Kontextmenü der Zelle. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_07_InsertSymbol.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Private Sub Workbook_Activate() ContextInsertSymbol End Sub Listing 261

Wenn Sie von der Beispielmappe zu einer anderen Excel-Arbeitsmappe wechseln oder die Beispielmappe beenden, wird das Workbook_Deactivate-Ereignis aufgerufen. Über die FindControl-Methode wird das Menü SONDERZEICHEN anhand der Tag-Information identifiziert und gelöscht. '=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_07_InsertSymbol.xlsm ' Ereignis DieseArbeitsmappe '=================================================================== Listing 262

Befehlsleisten Befehlsleisten

Public Sub InsertSymbol() With ActiveCell .Value = .Value & _ Chr(Val(Application.CommandBars.ActionControl.Tag)) End With End Sub

Befehlsleisten

'=================================================================== ' Auf CD Buchdaten\Beispiele\06_Befehlsleisten\ ' Dateiname 06_07_InsertSymbol.xlsm ' Modul mdl_01_SymbolContext '===================================================================

Befehlsleisten

wandelt und im Tabellenblatt eingefügt.

Befehlsleisten

aktuelle Cursorposition eingefügt werden soll. Hierzu verwenden Sie die ActionControl-Eigenschaft. Sie gibt das CommandBarControl-Objekt zurück, dessen OnActionEigenschaft auf diese Prozedur eingestellt ist. Der in der Tag-Eigenschaft hinterlegte Zahlencode wird über die Chr-Funktion in das entsprechende Sonderzeichen umge-

Befehlsleisten

425

Befehlsleisten

>> Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 425 Dienstag, 4. Dezember 2007 1:42 13

426 >> Alle FaceID's auf einen Blick Private Sub Workbook_Deactivate() On Error Resume Next Application.CommandBars("Cell").FindControl(Tag:="SpecialTag").Delete End Sub Listing 262 (Forts.)

169 Alle FaceID's auf einen Blick Auf der Buch-CD haben wir im Beispielordner der Kategorie Befehlsleisten die Datei 06_08_FaceIDs.xlsx mit allen in MS Office zur Verfügung stehenden Schaltflächensymbolen mit ihren ID-Nummern hinterlegt. Die Symbole können z. B. auch in Word und Access verwendet werden. Bis Excel 2003 können die vorhandenen Symbole in den Symbolleisten zum Beispiel händisch durch ein anderes Icon ausgetauscht werden. Wählen Sie dazu ein Symbol aus der Übersicht aus und kopieren Sie es in die Zwischenablage. Öffnen Sie nun den ANPASSEN-Dialog über das Menü EXTRAS | ANPASSEN. Klicken Sie anschließend mit der rechten Maustaste auf die zu ändernde Schaltfläche und wählen Sie im aufgeklappten Kontextmenü den Eintrag SCHALTFLÄCHE EINFÜGEN. Entnehmen Sie der Übersicht eine FaceId-Nummer um das dazugehörige Symbol in Ihren VBA-Codes zum Erstellen von einfachen Schaltflächen msoControlButtons einzufügen. Die Symbole können auch direkt in Tabellenblätter eingefügt werden. Man kann sie vergrößern und es können Makros zugewiesen werden.

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

Befehlsleisten

2471_Excel-VBA.book Seite 426 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 158: Schaltflächensymbole und FaceID's in MS-Office

Objekte

Objekte

2471_Excel-VBA.book Seite 427 Dienstag, 4. Dezember 2007 1:42 13

Um einen Zellbereich samt Formatierungen und den darauf befindlichen Steuerelementen in eine Grafik umzuwandeln, kann man die Methode CopyPicture einsetzen. Der abfotografierte Bereich wird dabei als BILD oder BITMAP in die Zwischenablage befördert. Von dort kann er dann in einem Office-Dokument als Grafik eingefügt werden.

Objekte

171 Einen Bereich in eine Grafik umwandeln

Objekte

Diese Kategorie ist unter anderem ein Ausflug in den grafischen Bereich, denn Sie werden Tipps und Tricks erfahren, wie man Bereiche als Bild exportiert oder Icons aus anderen Dateien importiert. Weiterhin erfährt man, wie Daten geographisch genau auf Kartenmaterial projiziert werden. Es wird auch beschrieben, wie man animierte Grafiken anzeigt oder Video-/Audiodateien abspielt. Ein weiteres Thema ist der Windows Agent, der den Office-Assistenten ersetzen muss, da dieser in der aktuellen Version gestrichen wurde.

Objekte

170 Einführung

Objekte Objekte Objekte

In dem Dialogfenster, welches sich nun öffnet, kann man bei DARSTELLUNG auswählen, ob das Bild WIE ANGEZEIGT oder WIE AUSGEDRUCKT fotografiert werden soll. WIE ANGEZEIGT bedeutet, dass das Bild so ausgegeben wird, wie man es auf dem Bildschirm sehen kann. Wenn man WIE AUSGEDRUCKT wählt, hängt das Ergebnis vom verwendeten Drucker ab. Sollte man keinen Farbdrucker im Einsatz haben, wird das Bild schwarz-weiß angezeigt, also ebenso, wie es in der Seitenansicht zu sehen ist.

Objekte

Manuell funktioniert das, indem man nach dem Markieren des Zellbereiches auf das erweiterte Menü des Icons EINFÜGEN in der Gruppe ZWISCHENABLAGE der Registerkarte START klickt (Abbildung 159). Anschließend kann man den Menüpunkt ALS GRAFIK KOPIEREN auswählen.

2471_Excel-VBA.book Seite 428 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

428 >> Einen Bereich in eine Grafik umwandeln

Objekte

Objekte

Objekte

Abbildung 159: Manuelles Umwandeln eines Bereiches in eine Grafik

Wenn man bei DARSTELLUNG die Auswahl WIE ANGEZEIGT getroffen hat, kann man zudem das ZIELFORMAT bestimmen. Zur Auswahl stehen BILD und BITMAP. Wählt man BILD aus, wird die Grafik im META-Dateiformat in die Zwischenablage kopiert, welches aber nicht von allen Programmen unterstützt wird. Die VBA-Methode, welche das händische Kopieren ersetzt und auf das markierte Range-Objekt ausgeführt wird, nennt sich CopyPicture. Dabei kann man verschiedene Parameter mit an diese Methode übergeben, die Parameterübergabe ersetzt dabei den Dialog BILD KOPIEREN. Der Tabelle 38 können Sie die verfügbaren Konstanten zur Methode CopyPicture entnehmen, die als Parameter mit übergeben werden können. CopyPicture-Konstante

Index

Beschreibung

Appearance:=xlScreen

1

Wie angezeigt

Appearance:=xlPrinter

2

Wie ausgedruckt

Format:=xlPicture

-4147

Bild

Formt:=xlBitmap

2

Bitmap

Objekte

Tabelle 38: Konstanten zur Bilderzeugung

2471_Excel-VBA.book Seite 429 Dienstag, 4. Dezember 2007 1:42 13

Public Sub CopyMyPicture () With ActiveSheet ' Bereich A1:D5 fotografieren .Range("A1:D5").CopyPicture _ Appearance:=xlScreen, _ Format:=xlPicture ' Bild in Zelle A8 einfügen .Paste Destination:= .Range("A8") End With End Sub

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_01_Pictures.xlsm ' Tabelle Bereich abfotografieren ' Modul mdl_07_02_CopyPicture '===================================================================

Objekte

Das folgende Listing fotografiert den Bereich A1:D5 als Grafik in die Zwischenablage. Dabei wird WIE ANGEZEIGT fotografiert und das Format BILD verwendet. Anschließend wird das Bild in das aktive Tabellenblatt ab Zellposition A8 eingefügt.

Objekte

429

Objekte

>> Objekte

Listing 263

Objekte

Abbildung 160: Quellbereich und eingefügtes Bild

Objekte

Objekte

Objekte

Folgendermaßen sieht das Ergebnis aus:

2471_Excel-VBA.book Seite 430 Dienstag, 4. Dezember 2007 1:42 13

Objekte

430 >> Bereich als Grafik exportieren

172 Bereich als Grafik exportieren

Eine Möglichkeit, so etwas dennoch zu machen, besteht darin, den Grafikinhalt der Zwischenablage mit der Methode Chart.Paste in ein Diagramm einzufügen und dieses dann mit der Chart.Export-Methode in eine Grafikdatei auszugeben. Das funktioniert auch problemlos, der Nachteil dabei ist, dass jedes Mal ein Chart-Objekt mit der entsprechenden Grafik erzeugt und anschließend wieder gelöscht werden muss. Das hier vorgestellte Rezept geht einen anderen Weg. Dabei wird mit ein paar APIFunktionen der Grafikinhalt der Zwischenablage in ein Objekt vom Typ IPictureDisp umgewandelt. Dieses Objekt aus der Library stdole besitzt mehrere positive Eigenschaften. Zum einen wird es ausgiebig Excel-intern benutzt und lässt sich somit außer zum Export noch für andere Sachen verwenden, auf die aber erst im nächsten Rezept näher eingegangen wird. Zum anderen kann man es an die Prozedur SavePicture übergeben, die ein solches Objekt als Parameter erwartet und mit der die Ausgabe in eine Datei problemlos möglich ist. Die Abbildung (Abbildung 161) zeigt das Tabellenblatt mit dem Bereich A1:D5, welcher als Grafik exportiert werden soll.

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Der mit der Methode CopyPicture abfotografierte und in die Zwischenablage beförderte Bereich kann zum Exportieren in ein Zeichenprogramm eingefügt werden. Ein direkter Export in eine Grafikdatei ist aber standardmäßig nicht vorgesehen.

Abbildung 161: Bereich in der Blattansicht

Objekte

In der folgenden Abbildung (Abbildung 162) wird die ins Bitmap-Dateiformat (*.bmp) exportierte Grafik in der WINDOWS BILD- UND FAXANZEIGE gezeigt.

2471_Excel-VBA.book Seite 431 Dienstag, 4. Dezember 2007 1:42 13

431

Objekte

Objekte

>> Objekte

Sub TestExport() Dim objPic As IPictureDisp Dim strFilename As Variant

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_01_Pictures.xlsm ' Tabelle Grafik exportieren ' Modul mdl_07_03_Export '===================================================================

Objekte

Die Prozedur TestExport erfragt mit dem Excel-Dialog GetSaveAsFilename den Pfad und den Dateinamen, unter dem die Grafik exportiert werden soll. Ist ein gültiger Name gewählt worden, übergibt man den Bereich A1:D5 des Tabellenblattes GRAFIK EXPORTIEREN an die Funktion GetPictureFromRange. Diese wiederum liefert ein Bildobjekt vom Typ IPictureDisp zurück, welches man zusammen mit dem Pfad, inklusive dem Dateinamen, an die Prozedur SavePicture übergibt. Als Exportformat wird eine Bitmap gewählt, weshalb man beim Dateinamen die Endung »bmp« benutzt.

Objekte

Abbildung 162: Bereich als Grafik exportiert

' Verlassen, wenn kein Speicherort gewählt If strFilename = False Then Exit Sub

Objekte

' Dateiname und Pfad abfragen strFilename = Application.GetSaveAsFilename( _ "Export " & Format(Now(), "DD.MM.YYYY hh-mm-ss") & ".bmp", _ "Bitmaps (*.bmp), *.bmp")

' Die Grafik exportieren SavePicture objPic, strFilename

Objekte

' Picture-Objekt erzeugen Set objPic = GetPictureFromRange( _ Worksheets("Grafik exportieren").Range("A1:D5"))

End Sub

Objekte

Listing 264

2471_Excel-VBA.book Seite 432 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

432 >> Bereich als Grafik exportieren

Die benutzerdefinierte Funktion GetPictureFromRange übernimmt als Argument einen Bereich (Range) und gibt als Funktionsergebnis ein Bildobjekt vom Typ IPictureDisp zurück. Dazu wird der als Referenz übergebene Bereich mit der CopyPicture-Methode als Bild in die Zwischenablage transferiert, wo die Grafik anschließend wie angegeben (Format:=xlBitmap) als Bitmap vorliegen sollte. Da ich aber schon erlebt habe, dass stattdessen eine erweiterte Metafiledatei vorhanden ist, wird abgefragt, ob eine Bitmap vorliegt, und falls nicht, ob sich stattdessen eine Metafiledatei in der Zwischenablage befindet. Die Abfrage ist für die Funktion GetClipboardData wichtig, die als Argument einen Wert verlangt, der das auszulesende Format in der Zwischenablage angibt. Eine der zwei Konstanten Werte CF_BITMAP oder CF_ENHMETAFILE können dazu verwendet werden und werden je nach Format der Variablen lngGraphicTypeClip zugewiesen. Da auch bei der API-Funktion OleCreatePictureIndirect in dem als Argument übergebenen benutzerdefinierten Datentyp PICTDESC der Typ angegeben werden muss, wird die Variable lngVbPicType auf einen der zwei konstanten Werte vbPicTypeBitmap oder vbPicTypeEMetafile gesetzt. Der API-Funktion OleCreatePictureIndirect übergibt man nun den ausgefüllten Datentyp PICTDESC, der als Variable mit Namen udtPicdesc vorliegt. Außerdem wird noch die Schnittstellenkennung in Form des ausgefüllten Datentyps GUID benötigt, die als die Variable IID_IDispatch übergeben wird. Die Objektvariable objPic vom Typ IPictureDisp nimmt bei Erfolg das Bild der Zwischenablage auf und wird als Funktionsergebnis zurückgegeben, wenn der Rückgabewert der API-Funktion OleCreatePictureIndirect Null ist. Da man zu Beginn mit einer API-Funktion die Zwischenablage mit OpenClipboard geöffnet hat, muss man diese mit CloseClipboard unbedingt schließen, möchte man vermeiden, dass einem der Himmel auf den Kopf fällt. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_01_Pictures.xlsm ' Tabelle Grafik exportieren ' Modul mdl_07_03_IPictureDisp '=================================================================== Private Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type

Objekte

Listing 265

2471_Excel-VBA.book Seite 433 Dienstag, 4. Dezember 2007 1:42 13

Private Declare Function OpenClipboard _ Lib "user32" ( _ ByVal hwnd As Long _ ) As Long Private Declare Function CloseClipboard _ Lib "user32" () As Long

Objekte Objekte

Private Type PICTDESC cbSize As Long picType As Long hImage As Long Data1 As Long Data2 As Long End Type

433

Objekte

>> Objekte

Private Const CF_BITMAP = 2 Private Const CF_ENHMETAFILE = 14

Objekte

Declare Function OleCreatePictureIndirect _ Lib "olepro32.dll" ( _ pPictDesc As PICTDESC, _ RefIID As GUID, _ ByVal fPictureOwnsHandle As Long, _ ppvObj As IPicture _ ) As Long

Objekte

Private Declare Function IsClipboardFormatAvailable _ Lib "user32" ( _ ByVal wFormat As Long _ ) As Long

Objekte

Private Declare Function GetClipboardData _ Lib "user32" ( _ ByVal wFormat As Long _ ) As Long

Public Function GetPictureFromRange(SourceRange As Range) _ As IPictureDisp Dim udtPicdesc As PICTDESC Dim IID_IDispatch As GUID Dim objPic As IPictureDisp

Objekte

Private Const vbPicTypeBitmap = 1 Private Const vbPicTypeEMetafile = 4

Objekte

Listing 265 (Forts.)

2471_Excel-VBA.book Seite 434 Dienstag, 4. Dezember 2007 1:42 13

Objekte

434 >> Bereich als Grafik exportieren Dim Dim Dim Dim

hImage lngRet lngGraphicTypeClip lngVbPicType

As As As As

Long Long Long Long

Objekte

Objekte

On Error GoTo Errorhandler ' Schnittstellenkennung kPictureIID (GUID) With IID_IDispatch .Data1 = &H20400 .Data4(0) = &HC0 .Data4(7) = &H46 End With ' Bereich als Bitmap ins Clipboard SourceRange.CopyPicture _ Appearance:=xlScreen, Format:=xlBitmap

Objekte

Objekte

' Clipboard zum Zugriff öffnen OpenClipboard 0& If IsClipboardFormatAvailable(CF_BITMAP) 0 Then lngGraphicTypeClip = CF_BITMAP lngVbPicType = vbPicTypeBitmap ElseIf IsClipboardFormatAvailable(CF_ENHMETAFILE) 0 Then lngGraphicTypeClip = CF_ENHMETAFILE lngVbPicType = vbPicTypeEMetafile End If ' Überprüfen, ob Grafik im Clipboard If lngGraphicTypeClip 0 Then

Objekte

Objekte

' Handle auf Grafik im Clipboard hImage = GetClipboardData(lngGraphicTypeClip) With udtPicdesc .cbSize = Len(udtPicdesc) .picType = lngVbPicType .hImage = hImage End With ' Picture-Objekt erzeugen lngRet = OleCreatePictureIndirect( _ udtPicdesc, IID_IDispatch, 1&, objPic)

Objekte

Listing 265 (Forts.)

2471_Excel-VBA.book Seite 435 Dienstag, 4. Dezember 2007 1:42 13

If lngRet = 0 Then ' Kein Fehler Set GetPictureFromRange = objPic End If End If ' Die Fehlerbehandlung soll sicherstellen, dass ' das Clipboard auch bei Fehlern geschlossen wird Errorhandler: CloseClipboard

Objekte

435

Objekte

>> Objekte

Listing 265 (Forts.)

Objekte

End Function

Objekte Objekte

In diesem Rezept wird der Bereich A1:D5 als Bitmap in die Zwischenablage befördert und in ein Objekt vom Typ IPictureDisp umgewandelt. Das wird wiederum in einem Bildsteuerelement dargestellt, dessen Größe dem Originalbereich annähernd angepasst wird. Im nachfolgenden Bild sieht man das Image-Steuerelement mit sichtbarem Eigenschaftsfenster.

Objekte

Im vorherigen Rezept 172 wurde aus dem Inhalt der Zwischenablage ein Objekt vom Typ IPictureDisp erzeugt. Und genau solch ein Objekt kann man der Eigenschaft Picture zuweisen. Somit ist es möglich, beispielsweise auf einem Bildsteuerelement, einer Befehlsschaltfläche oder auch einer Userform einen abfotografierten Bereich ohne den Umweg über eine Grafikdatei darzustellen.

Objekte

Viele der in Excel verfügbaren ACTIVEX-Steuerelemente besitzen eine Eigenschaft mit dem Namen Picture. Dieser Eigenschaft kann man eine Grafik zuweisen, die dann auf dem Steuerelement angezeigt wird. Der Inhalt der Zwischenablage bleibt dabei aber außen vor, so dass man, wenn man einen abfotografierten Bereich verwenden will, normalerweise den Umweg über eine von einem Grafikprogramm erzeugte Grafikdatei gehen muss.

Objekte

173 Bereich als Hintergrund eines Steuerelementes

2471_Excel-VBA.book Seite 436 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

436 >> Bereich als Hintergrund eines Steuerelementes

Abbildung 163: Bereich als Schaltflächenhintergrund

In der Ereignisprozedur cmdToImage_Click wird mit Hilfe der in diesem Rezept nicht noch einmal abgedruckten Funktion GetPictureFromRange (siehe Rezept 172) aus einem übergebenen Bereich ein Bild abfotografiert und als Objekt vom Typ IPictureDisp zurückgeliefert. Das auf dem aktuellen Blatt befindliche Bildsteuerelement mit Namen IMGDESTINATION wird in der Größe etwa an die Größe des Bildes angepasst. Die Umrechnung der Steuerelementabmessung mit der Funktion HimetricToEM erfolgt deshalb, weil das Objekt vom Typ IPictureDisp andere Maßeinheiten verwendet. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_01_Pictures.xlsm ' Tabelle Grafik ins Bildsteuerelement ' Modul Klassenmodul "Grafik ins Bildsteuerelement" '===================================================================

Objekte

Listing 266

2471_Excel-VBA.book Seite 437 Dienstag, 4. Dezember 2007 1:42 13

437

Private Sub cmdToImage_Click() Dim objPic As IPictureDisp

Objekte

>> Objekte

With Me.OLEObjects("imgDestination")

Objekte

' Picture-Objekt erzeugen Set objPic = GetPictureFromRange( _ Me.Range("A1:D5"))

' Dem Steuerelement das Picture-Objekt zuweisen .Object.Picture = objPic

Objekte

' Breite und Höhe des Steuerelements anpassen .Width = HimetricToEM(objPic.Width) .Height = HimetricToEM(objPic.Height)

Ein Bild vom Typ IPictureDisp verwendet ausschließlich die Maßeinheit HIMETRIC, welche definiert ist als ein Tausendstel eines Zentimeters, der wiederum von der Auflösung und der Bildschirmgröße abhängig ist. Jetzt kommt das Problem, denn Excel verwendet gänzlich andere Maßeinheiten. In den Vorgängerversionen und auch noch in der Betaversion von Excel 2007 wurde die Maßeinheit PUNKT verwendet. Scheinbar sind die Maßeinheiten einiger Objekte auf EM umgestellt worden, denn ursprünglich in der Betaversion erstellte Umrechnungsfunktionen funktionieren in der finalen Version nicht mehr.

Objekte

Listing 266 (Forts.)

Objekte

End With End Sub

Aber nicht immer gilt diese Auflösung, weshalb die API-Funktion GetDeviceCaps zum Einsatz kommen sollte. Diese liefert Informationen über den übergebenen Gerätekontext DC, im Prinzip ist das die Darstellungsfläche eines Ausgabegerätes.

Objekte

Um eine Angabe, welche in der Maßeinheit HIMETRIC vorliegt, in eine vom Typ EM umzuwandeln, benötigt man die aktuelle Auflösung in DPI (DOT PER INCH), wobei hier Pixel statt der auch gebräuchlichen Angabe POINT gemeint sind. Die Auflösung beträgt in den meisten Fällen 96 DPI pro virtuellen INCH (2,54 cm), virtuell deshalb, weil die Größe des Monitors und die Anzahl der eingestellten Pixel in Höhe und Breite eine Rolle spielen.

Objekte

Das EM entspricht dem typografischen Begriff GEVIERT und gibt die Schrifthöhe einer Schriftart an. Damit kann man recht wenig anfangen, aber kurz gesagt ist 1 EM die Browserstandardschriftgröße und entspricht etwa 0,63 Pixel.

Objekte

In der Funktion HimetricToEM wird mit der API-Funktion GetDesktopWindow ein Handle zum Bildschirm zurückgeliefert. Mit der API GetDC leiht man sich den DC (DEVICE CONTEXT) des als HANDLE übergebenen Objektes aus. Die API GetDeviceCaps liefert zu

2471_Excel-VBA.book Seite 438 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

438 >> Bereich als Hintergrund eines Steuerelementes

diesem DC verschiedene Informationen, welche im zweiten Parameter angegeben werden. Das kann in diesem Beispiel einmal die Auflösung in X-Richtung (LOGPIXELSX) oder in Y-Richtung sein (LOGPIXELSY). Da es 2540 HIMETRIC-Einheiten pro virtuellen Inch gibt, teilt man die übergebene HIMETRIC-Angabe durch 2450, multipliziert sie mit der ermittelten Auflösung und erhält die Angabe in Pixel. Wie bereits erwähnt, sind 1 EM ca. 0,63 Pixel, also wird der ermittelte Pixelwert damit multipliziert. Möchte man die Angabe in PUNKT, muss man mit 0,75 multiplizieren (Funktion HimetricToPoint).

Objekte

Objekte

Objekte

Objekte

Es muss anschließend unbedingt der ausgeliehene DC zurückgegeben werden, was durch die API ReleaseDC erreicht wird. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_01_Pictures.xlsm ' Tabelle Grafik ins Bildsteuerelement ' Modul mdl_07_04_Himetric '=================================================================== Private Declare Function GetDC _ Lib "user32" ( _ ByVal hwnd As Long _ ) As Long Private Declare Function GetDeviceCaps _ Lib "gdi32" ( _ ByVal lngDC As Long, _ ByVal nIndex As Long _ ) As Long Private Declare Function ReleaseDC _ Lib "user32" ( _ ByVal hwnd As Long, _ ByVal lngDC As Long _ ) As Long

Objekte

Objekte

Private Declare Function GetDesktopWindow _ Lib "user32" () As Long Private Const LOGPIXELSX = 88& Private Const LOGPIXELSY = 90& Public Function HimetricToPoint( _ dblHimetric As Double, _ Optional y As Boolean _ ) As Double Listing 267

2471_Excel-VBA.book Seite 439 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte Dim dblPixel Dim lngDC

As Double As Long

Objekte

439

Y-Richtung = GetDeviceCaps(lngDC, LOGPIXELSY) X-Richtung = GetDeviceCaps(lngDC, LOGPIXELSX)

' Ausgeliehenen DC zurückgeben ReleaseDC GetDesktopWindow, lngDC

Objekte

If y Then ' DPI in dblPixel Else ' DPI in dblPixel End If

Objekte

' DC der Applikation ausleihen lngDC = GetDC(GetDesktopWindow)

Public Function HimetricToEM( _ dblHimetric As Double, _ Optional y As Boolean _ ) As Double As Double As Long

' DC der Applikation ausleihen lngDC = GetDC(GetDesktopWindow)

Y-Richtung = GetDeviceCaps(lngDC, LOGPIXELSY) X-Richtung = GetDeviceCaps(lngDC, LOGPIXELSX)

Objekte

If y Then ' DPI in dblPixel Else ' DPI in dblPixel End If

Objekte

Dim dblPixel Dim lngDC

Objekte

HimetricToPoint = 0.75 * dblPixel * dblHimetric / 2540 End Function

HimetricToEM = 0.63 * dblPixel * dblHimetric / 2540 End Function

Objekte

' Ausgeliehenen DC zurückgeben ReleaseDC GetDesktopWindow, lngDC

Anschließend wird dem Steuerelement über die Picture-Eigenschaft das Picture-Objekt zugewiesen.

Objekte

Listing 267 (Forts.)

2471_Excel-VBA.book Seite 440 Dienstag, 4. Dezember 2007 1:42 13

174 Iconpicker In vielen Laufzeitbibliotheken (.dll) oder ausführbaren Dateien (.exe) stecken, als alleinige oder zusätzliche Ressource, Icons. Dieses Rezept zeigt, wie man die darin enthaltenen Icons extrahiert und weiterverwendet. Man sollte aber immer darauf achten, dass man bei der Benutzung dieser Icons keine Copyright-Verletzung begeht. Die Verantwortung dabei liegt ausschließlich im Bereich des Anwenders.

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

440 >> Iconpicker

Abbildung 164: Iconpicker

Die Benutzerform enthält zur Entwurfszeit lediglich zwei Befehlsschaltflächen mit Namen cmdCopy und cmdIcon. Das Treeview-Steuerelement wird zur Laufzeit hinzugefügt und erst später mit Icons gefüllt. Die benutzerdefinierte Funktion GetPictureFromHandle wandelt ein Icon, das als Handle (Zeiger) auf ein Objekt im Speicher vorliegt, mit Hilfe einiger API-Funktionen in ein Objekt vom Typ IPictureDisp um, welches sich in Office-Programmen hervorragend einsetzen lässt.

Der API-Funktion OleCreatePictureIndirect übergibt man den ausgefüllten Datentyp PICTDESC, der als Variable mit Namen udtPicdesc vorliegt. Dort werden das Iconhandle und der Typ der Grafik eingetragen, in dem Fall vbPicTypeIcon. Außerdem wird noch die Schnittstellenkennung in Form des ausgefüllten Datentyps GUID benötigt, die als Variable mit dem Namen IID_IDispatch übergeben wird. Die Objektvariable objPic vom Typ IPictureDisp nimmt bei Erfolg das Bild der Zwischenablage auf und wird als Funktionsergebnis zurückgegeben, wenn der Rückgabewert der APIFunktion OleCreatePictureIndirect Null ist.

2471_Excel-VBA.book Seite 441 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte

Private Declare Function OleCreatePictureIndirect _ Lib "olepro32.dll" ( _ pPictDesc As PictDesc, _ RefIID As Guid, _ ByVal fPictureOwnsHandle As Long, _ ppvObj As IPicture _ ) As Long Private Declare Function ExtractIcon _ Lib "shell32.dll" Alias "ExtractIconA" ( _ ByVal hInst As Long, _ ByVal lpszExeFileName As String, _ ByVal nIconIndex As Long _ ) As Long

Objekte Objekte Objekte

Private Type PictDesc cbSize As Long picType As Long hImage As Long Data1 As Long Data2 As Long End Type

Objekte

Private Type Guid Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_02_Iconpicker.xlsm ' Tabelle Iconpicker ' Modul uf_07_05_GetIcon '===================================================================

Objekte

441

Const Const Const Const Const

Listing 268

vbPicTypeNone = 0 vbPicTypeBitmap = 1 vbPicTypeMetafile = 2 vbPicTypeIcon = 3 vbPicTypeEMetafile = 4

Objekte

Private Private Private Private Private

Objekte

Private Declare Function SetFocus _ Lib "user32" ( _ ByVal hwnd As Long _ ) As Long

2471_Excel-VBA.book Seite 442 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

442 >> Iconpicker Private Const GETCOUNT As Long = -1 Dim Dim Dim Dim Dim

mobjTreeView mobjTreeImage mobjIcon mstrCurDir mstrCurDrive

As As As As As

Object Object IPictureDisp String String

Public Function GetPictureFromHandle(lngPic As Long) _ As IPictureDisp Dim udtPicdesc As PictDesc Dim IID_IDispatch As Guid Dim objPic As IPictureDisp Dim hImage As Long Dim lngRet As Long ' Schnittstellenkennung kPictureIID (GUID) With IID_IDispatch .Data1 = &H20400 .Data4(0) = &HC0 .Data4(7) = &H46 End With With udtPicdesc .cbSize = Len(udtPicdesc) .picType = vbPicTypeIcon .hImage = lngPic End With ' Picture-Objekt erzeugen lngRet = OleCreatePictureIndirect( _ udtPicdesc, IID_IDispatch, 1&, objPic) If lngRet = 0 Then ' Kein Fehler Set GetPictureFromHandle = objPic End If End Function

Objekte

Objekte

Listing 268 (Forts.)

Beim Initialisieren der Benutzerform wird die Ereignisprozedur UserForm_Initialize ausgeführt. Dort wird ein Treeview-Objekt mit Hilfe der Controls.Add-Methode aus der Bibliothek MSCOMCTLLIB erzeugt und in die Benutzerform eingepasst. In der Ereignisprozedur cmdIcon_Click wird zu Beginn der interne Dialog zum Öffnen von Dateien gestartet. Damit man im Systemverzeichnis mit der Suche beginnen kann, wechselt man zuvor mit ChDrive und ChDir in das mit der Umgebungsvariablen (Environ) SYSTEMROOT ermittelte Verzeichnis.

2471_Excel-VBA.book Seite 443 Dienstag, 4. Dezember 2007 1:42 13

Private Sub UserForm_Initialize() mstrCurDir = CurDir mstrCurDrive = Left(mstrCurDir, 2) ' Treeview in Form einfügen Set mobjTreeView = Me.Controls.Add( _ "MSComCtlLib.TreeCtrl.2") With mobjTreeView .Name = "Tree" .Left = 10 .Top = 60 .Width = Me.Width - 25 .Height = Me.Height - 95 End With End Sub

Objekte Objekte Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_02_Iconpicker.xlsm ' Tabelle Iconpicker ' Modul uf_07_05_GetIcon '===================================================================

Objekte

Nun werden aus dem Treeview-Steuerelement alle Knoten entfernt und dieses somit geleert. Jetzt wird das ListImage- mit dem Treeview-Objekt verbunden und anschließend für jedes Icon mit der Nodes.Add-Methode ein eigener Knoten im TreeviewObjekt angelegt. Die ersten zwei Parameter geben die relative Position des Knotens an, werden diese Parameter weggelassen, legt man einen neuen Hauptknoten an. Der dritte Parameter ist ein eindeutiger Schlüssel, den man aber auch getrost weglassen kann, wenn man den Knoten nicht über den Schlüssel ansprechen muss. Der vierte Parameter bei der Add-Methode ist der Text, welcher ausgegeben wird, der fünfte gibt die Position des angezeigten Icons in der verbundenen ImageList an.

Objekte

Mit Hilfe der API-Funktion ExtractIcon wird anschließend die Anzahl der Icons ermittelt. Sind in der ausgewählten Datei keine vorhanden, wird die Prozedur verlassen. Sind welche vorhanden, wird mit Hilfe der Controls.Add-Methode ein neues ImageList-Steuerelement erzeugt, welches die Icons aufnehmen kann. Mit der APIFunktion ExtractIcon wird danach jedes einzelne Icon aus der Datei extrahiert und mit der Methode .ListImages.Add in das ImageList-Objekt transferiert. Zuvor wird das Icon allerdings noch mit Hilfe der benutzerdefinierten Funktion GetPictureFromHandle in ein Icon vom Typ IPictureDisp umgewandelt.

Objekte

443

Objekte

>> Objekte

Objekte

Listing 269

2471_Excel-VBA.book Seite 444 Dienstag, 4. Dezember 2007 1:42 13

Objekte

444 >> Iconpicker Private Sub UserForm_Terminate()

Objekte

Objekte

Objekte

Objekte

' Aktuelles Laufwerk und Verzeichnis zurücksetzen ChDrive mstrCurDrive ChDir mstrCurDrive End Sub Private Sub cmdIcon_Click() Dim strFile As String Dim lngIconsCount As Long Dim i As Long Dim lngHandleIcon As Long ' Anfangspfad zur Suche auf das ' Windows-Systemverzeichnis setzen ChDrive "c:" ChDir Environ$("systemroot") & "\system32" ' Dialog zur Dateiauswahl strFile = Application.GetOpenFilename( _ "Bibliotheken (*.dll),*.dll," & _ "Exedateien (*.exe),*.exe," & _ "Alle Dateien (*.*),*.*") ' Keine Datei ausgewählt, dann abbrechen If Dir$(strFile, vbReadOnly Or vbSystem Or vbHidden) _ = "" Then Exit Sub 'Anzahl der Icons ermitteln lngIconsCount = ExtractIcon(0&, strFile, GETCOUNT)

Objekte

Objekte

' Keine Icons in Datei If lngIconsCount = 0 Then Exit Sub ' Dateiname als Caption Me.Caption = Dir$(strFile, vbReadOnly Or vbSystem Or vbHidden) ' Bildcontainer neu erzeugen Set mobjTreeImage = Nothing Set mobjTreeImage = CreateObject( _ "MSComCtlLib.ImageListCtrl.2") For i = 0 To lngIconsCount - 1

Objekte

' Icon aus Datei extrahieren lngHandleIcon = ExtractIcon(0&, strFile, i) Listing 269 (Forts.)

2471_Excel-VBA.book Seite 445 Dienstag, 4. Dezember 2007 1:42 13

445

' Im Image-Steuerelement speichern mobjTreeImage.ListImages.Add , "Nr" & i, _ GetPictureFromHandle(lngHandleIcon)

Objekte

>> Objekte

' Alle Knoten löschen For i = .Nodes.Count To 1 Step -1 .Nodes.Remove i Next ' Die Bilderliste mit dem Treeview verbinden .Object.imagelist = mobjTreeImage

Objekte

With mobjTreeView

Objekte

Next

End With

Objekte

' Alle Icons anzeigen For i = 0 To lngIconsCount - 1 .Object.Nodes.Add , , "Nr.:" & i + 1, i + 1, i + 1 Next

End Sub

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_02_Iconpicker.xlsm ' Tabelle Iconpicker ' Modul uf_07_05_GetIcon '===================================================================

Objekte

Anschließend legen Sie mit der OleObjects.Add-Methode des aktiven Tabellenblattes eine neue Schaltfläche an und weisen der Picture-Eigenschaft das Icon zu. Schließlich setzen Sie den Fokus wieder auf das TreeView-Steuerelement, damit der aktuell gewählte Knoten optisch markiert bleibt, ohne dass man mit der (Tab)-Taste den Fokus händisch verschieben muss.

Objekte

Nach einem Klick auf die Schaltfläche cmdCopy wird die Objektvariable mobjIcon mit dem Icon des angewählten Eintrags des Treeview-Controls gefüllt. Dazu bedienen Sie sich der ExtractIcon-Methode des mit dem Treeview verbundenen TreeImage-Objektes. Als Index in die Liste dient der Index des ausgewählten Eintrags.

Objekte

Listing 269 (Forts.)

Objekte

Listing 270

2471_Excel-VBA.book Seite 446 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

446 >> Karte Private Sub cmdCopy_Click() Dim objIcon As Object Dim lngActItem As Long On Error Resume Next Err.Clear With mobjTreeView lngActItem = .SelectedItem Set mobjIcon = mobjTreeImage.ListImages(lngActItem).ExtractIcon End With If Err.Number = 0 Then Set objIcon=ActiveSheet.OLEObjects.Add( _ ClassType:="Forms.CommandButton.1") objIcon.Object.Picture = mobjIcon SetFocus mobjTreeView.hwnd End If End Sub

175 Karte Die vorgestellte Klasse bietet die Möglichkeit, beliebiges Kartenmaterial in Bildform, bei dem die Koordinaten des linken, rechten, oberen und unteren Randes bekannt sind, zu verwenden. Sind die Koordinaten nicht bekannt, sucht man sich diese am besten mit einem Routenplaner heraus. Daneben benötigt man die Koordinaten der darzustellenden Daten. In diesem Rezept wird als Ziel eine Fahne erzeugt, deren Spitze auf die gewünschte Koordinate zeigt und bei der die Beschriftung, in diesem Fall der Ortsname, auf der Fahne selbst angezeigt wird. Man könnte aber auch andere, einfachere Objekte, wie Punkte oder Ähnliches darstellen, der Code müsste dazu aber angepasst werden, wird dabei auch etwas unkomplizierter.

Objekte

Objekte

Objekte

Oft möchte man Daten in einer Karte darstellen. Leider bietet Excel von Haus aus keine solche Möglichkeit. In diesem Rezept wird dem abgeholfen.

Objekte

Objekte

Listing 270 (Forts.)

Die Tabelle PLZ enthält die Koordinaten der meisten Postleitzahlen Deutschlands. Auf dem Tabellenblatt INFOS kann man den Tabellenblattnamen eingeben, auf dem sich die Karte als Bild befindet. Weiterhin wird der Name des Shape-Objektes benötigt. Diesen Namen kann man festlegen, indem man die Karte markiert und in der Bearbeitungsleiste ganz links, dort wo normalerweise die aktuelle Zelladresse erscheint, einen Namen eingibt und mit der (Enter)-Taste bestätigt. Weiterhin kann man auf dem Blatt INFOS die Kartenkoordinaten in Grad eingeben. Über die Postleitzahlen, die in Spalte A ab Zeile 10 eingegeben werden, ermittelt man mit der Tabellenfunktion SVERWEIS die Längen- und Breitengrade, sowie den zugehörigen Ortsnamen. Nach einem Klick auf die Schaltfläche werden die dort eingegebenen Orte in der Karte dargestellt.

2471_Excel-VBA.book Seite 447 Dienstag, 4. Dezember 2007 1:42 13

447

Die nachfolgende Prozedur erledigt diese Aufgabe. Die Kommentare mit den bezeichneten Eigenschaften sind Voreinstellung und müssen nicht unbedingt gesetzt werden, wenn vom Benutzer keine abweichenden Einstellungen vorgesehen sind. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_03_Karte.xlsm ' Tabelle Infos ' Modul Tabelle Infos '===================================================================

Objekte

Die Klasse cls_07_05_Geo, welche die eigentliche Arbeit erledigt, kann recht einfach eingesetzt werden. Man erstellt eine Instanz derselben, setzt ein paar Eigenschaften, übergibt nacheinander die Daten an eine Methode und lässt diese durch einen weiteren Methodenaufruf anzeigen.

Objekte

Abbildung 165: Karte

Objekte

Objekte

Objekte

Objekte

Objekte

>> Objekte

Objekte

Listing 271

2471_Excel-VBA.book Seite 448 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

448 >> Karte Private Sub cmdAddItems_Click() Dim i As Long Dim objGeo As New clsGeo With objGeo ' Längengrad Karte links .LonLeft = Me.Range("B2") ' Längengrad Karte rechts .LonRight = Me.Range("C2")

Objekte

' Breitengrad Karte oben .LatTop = Me.Range("C3") ' Breitengrad Karte unten .LatBottom = Me.Range("B3")

Objekte

' Transparenz der Fahnen (optional) .Transparency = Me.Range("B6") ' Farbe der Fahnen (optional) .BackColor = RGB(255, 0, 0)

Objekte

' Farbe des Textes (Farbindex) (optional) .TextColor = 1 ' Textgröße (optional) .TextSize = 5 ' Höhe der Fahne in Prozent der Kartenhöhe (optional) .HeightPercent = 1.5

Objekte

Objekte

' Breite der Fahne in Prozent der Kartenbreite (optional) .WidthPercent = 15 ' Shapeobjekt übergeben (Tabellenblattname ' und Name der Karte aus dem Blatt) .Map = Worksheets(CStr(Me.Range("B4"))).Shapes( _ CStr(Me.Range("B5"))) For i = 11 To 30 If Me.Cells(i, 1) "" Then ' Darzustellende Koordinate hinzufügen ' Längengrad, Breitengrad, Beschriftung .AddItem Me.Cells(i, 2), Me.Cells(i, 3), Me.Cells(i, 4) End If

Objekte

Listing 271 (Forts.)

2471_Excel-VBA.book Seite 449 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte

Objekte

449

Next ' Daten anzeigen .InsertItems

Objekte

End With End Sub

Private Private Private Private Private Private Private Private Private Private Private Private Private Private

mcolData mobjMap mwsDestSheet mstrMap mdblLonLeft mdblLatTop mdbLonRight mdbLatBottom mdblWidth mdblHeight mdblTransparency mlngTextColorIndex mlngTextSize mlngColor

As As As As As As As As As As As As As As

New Collection Shape Worksheet String Double Double Double Double Double Double Double Long Long Long

Objekte Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_03_Karte.xlsm ' Tabelle Karte, Infos ' Modul cls_07_06_Geo '===================================================================

Objekte

Die Übergabe der Karte erfolgt als Referenz. In der Property Let-Prozedur-Map wird das Objekt in einer klassenweit gültigen Variable gespeichert. Über die Parent-Eigenschaften wird zudem das Arbeitsblatt ermittelt, in dem sich die Karte befindet.

Objekte

Nachfolgend der Code der Klasse cls_07_05_Geo. Die Property Let-Prozeduren nehmen die Koordinaten der Kartengrenzen in GRAD entgegen, es können die Textgröße, die Text- und die Hintergrundfarbe der Fahne übergeben werden. Zusätzlich lassen sich die Transparenz sowie die Höhe und Breite der Fahnen in Prozent zur Kartengröße festlegen. In der Initialisierungsroutine Class_Initialize werden einige dieser Eigenschaften voreingestellt, so dass man diese Werte nicht explizit angeben muss.

Objekte

Listing 271 (Forts.)

Listing 272

Objekte

' Koordinaten der Kartengrenzen Public Property Let LonLeft(ByVal vNewValue As Variant) mdblLonLeft = vNewValue

2471_Excel-VBA.book Seite 450 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

450 >> Karte End Property Public Property Let LatTop(ByVal vNewValue As Variant) mdblLatTop = vNewValue End Property Public Property Let LonRight(ByVal vNewValue As Variant) mdbLonRight = vNewValue End Property Public Property Let LatBottom(ByVal vNewValue As Variant) mdbLatBottom = vNewValue End Property

Public Property Let TextSize(ByVal vNewValue As Long) ' Textgröße mlngTextSize = vNewValue End Property Public Property Let TextColor(ByVal vNewValue As Long) ' Textfarbe als Index mlngTextColorIndex = vNewValue End Property Public Property Let BackColor(ByVal vNewValue As Long) ' Farbe Hintergrund mlngColor = vNewValue End Property Public Property Let Transparency(ByVal vNewValue As Double) ' Transparenz (0=Undurchsichtig, 1=Transparent) mdblTransparency = vNewValue End Property Public Property Let WidthPercent(ByVal vNewValue As Double) ' Fahnenbreite in Prozent von Kartenbreite If (vNewValue < 0) Or (vNewValue > 100) Then Exit Property mdblWidth = vNewValue End Property Public Property Let HeightPercent(ByVal vNewValue As Double) ' Fahnenhöhe in Prozent von Kartenhöhe If (vNewValue < 0) Or (vNewValue > 100) Then Exit Property mdblHeight = vNewValue End Property Private Sub Class_Initialize() ' Defaultwerte festlegen mdblWidth = 15 mdblHeight = 1.5 mlngTextColorIndex = 1 mlngColor = RGB(255, 0, 0) mlngTextSize = 5 End Sub Listing 272 (Forts.)

2471_Excel-VBA.book Seite 451 Dienstag, 4. Dezember 2007 1:42 13

Public Property Let Map(ByVal vNewValue As Shape) ' Die Karte wird als Shape-Objekt übergeben ' Das stellt sicher, dass ein solches Objekt ' existiert On Error Resume Next ' Zielobjekt in Variable speichern Set mobjMap = vNewValue

Objekte

451

Objekte

>> Objekte

' Der Name des Zielobjektes wird ermittelt mstrMap = mobjMap.Name End Property

Objekte

' Objekt Zielblatt wird erstellt Set mwsDestSheet = Worksheets(mobjMap.Parent.Parent.Name)

Public Sub AddItem(Lon As Double, Lat As Double, Text As String) ' Neuer darzustellender Wert in Collection einfügen On Error Resume Next Dim avarDummy(1 To 3) As Variant avarDummy(1) = Lon avarDummy(2) = Lat avarDummy(3) = Text mcolData.Add avarDummy End Sub Public Sub ClearItems() ' Die Collection zurücksetzen Set mcolData = New Collection End Sub

Objekte Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_03_Karte.xlsm ' Tabelle Karte, Infos ' Modul cls_07_06_Geo '===================================================================

Objekte

Die Prozedur AddItem, die sich nach außen als Methode zu erkennen gibt, nimmt die Koordinaten eines Punktes in Grad sowie den anzuzeigenden Text entgegen und speichert bei jedem Aufruf diese Informationen als neues Element in einer klassenweit gültigen Collection mcolData. Die Methode ClearItems löscht alle Elemente dieser Collection.

Objekte

Listing 272 (Forts.)

Objekte

Listing 273

2471_Excel-VBA.book Seite 452 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

452 >> Karte

Die wichtigste interne Funktion in der Klasse cls_07_05_Geo ist die zur Berechnung der Zielkoordinaten auf dem Tabellenblatt. Da die Koordinaten der linken, rechten, oberen und unteren Begrenzung der Karte bekannt sind und man die Abmessungen der Karte als Bildobjekt auslesen kann, lässt sich recht einfach die Position einer beliebigen Koordinate innerhalb des Kartenbereichs auf einem Tabellenblatt errechnen. Die Funktion POSITION BERECHNEN nimmt die X- bzw. Y-Position eines Punktes in Grad östlicher Länge und nördlicher Breite entgegen und gibt ein Array zurück, welches die Koordinaten des Punktes auf dem Platt beschreibt. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_03_Karte.xlsm ' Tabelle Karte, Infos ' Modul cls_07_06_Geo '=================================================================== Private Function PositionBerechnen( _ dblPosX As Double, dblPosY As Double _ ) As Variant Dim x As Double, y As Double Dim adblPosition(1 To 2) As Double With mobjMap x = .Width / (mdbLonRight - mdblLonLeft) y = .Height / (mdblLatTop - mdbLatBottom) adblPosition(1) = .Left + x * (dblPosX - mdblLonLeft) adblPosition(2) = .Top + y * (mdblLatTop - dblPosY) PositionBerechnen = adblPosition End With End Function

Objekte

Objekte

Objekte

Listing 274

Die öffentliche Funktion InsertItems durchläuft alle Elemente der Collection mcolData und legt für jedes Element eine eigene Fahne an. Zu Beginn wird ermittelt, ob genügend Informationen an die Klasse übergeben wurden, ist das nicht der Fall, wird abgebrochen. Anschließend werden alle Shape-Objekte auf dem Zielblatt gelöscht, nur die Karte wird nicht angerührt. Für jedes Fahnenelement wird nun mit Hilfe der Funktion PositionBerechnen die Position auf dem Tabellenblatt berechnet. Aus den Positionsdaten wird ein eindeutiger Name für das Shape-Objekt zusammengesetzt, um zu erkennen, ob sich an der gleichen Position bereits ein anderes Shape-Objekt befindet. Ist das nicht der Fall, wird ein neues Objekt an der gewünschten Position erstellt. Anschließend wird nachgeschaut, ob das erzeugte oder bereits vorhandene ShapeObjekt Text enthält. Ist bereits Text vorhanden, wird ein Zeilenumbruch eingefügt und der neue Text angehängt, andernfalls der Text ohne Zeilenumbruch hinzugefügt.

2471_Excel-VBA.book Seite 453 Dienstag, 4. Dezember 2007 1:42 13

On Error Resume Next ' Abbrechen, wenn nicht genügend Infos vorhanden If mcolData.Count = 0 Then Exit Function If mobjMap Is Nothing Then Exit Function If mdblLonLeft = mdbLonRight Then Exit Function If mdblLatTop = mdbLatBottom Then Exit Function ' Alle Shape-Objekte im Zielblatt löschen, ' außer das Karten-Objekt For Each objZiel In mwsDestSheet.Shapes If objZiel.Name mstrMap Then objZiel.Delete Next ' Alle Elemente der Daten-Collection durchlaufen For Each varDummy In mcolData

' Längen- und Breitengrad aus der Collection holen x = varDummy(1) y = varDummy(2) If x 0 And y 0 Then ' Daten vorhanden

Objekte Objekte

Function InsertItems() As Boolean varDummy As Variant varPos As Variant objZiel As Shape strName As String strDummy As String lngZeilen As Long x As Double y As Double

Objekte

Public Dim Dim Dim Dim Dim Dim Dim Dim

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_03_Karte.xlsm ' Tabelle Karte, Infos ' Modul cls_07_06_Geo '===================================================================

Objekte

Nun kann man daran gehen, die Breite, Höhe und die Position der Fahne anzupassen. Berücksichtigen muss man noch, dass lediglich die Pfeilspitze auf die Koordinate zeigen soll. Anschließend werden noch die Text-, die Hintergrundfarbe sowie die Transparenz und der Rahmen angepasst.

Objekte

453

Objekte

>> Objekte

Listing 275

Objekte

' Die Position auf dem Blatt berechnen varPos = PositionBerechnen(x, y)

2471_Excel-VBA.book Seite 454 Dienstag, 4. Dezember 2007 1:42 13

Objekte

454 >> Karte ' Namen aus der X- und Y-Position erzeugen strName = "X" & _ Format(varPos(1), "0.000") & _ Format(varPos(2), "0.000")

Objekte

Err.Clear ' Überprüfen, ob ein Shape an der gleichen Position, ' also mit gleichem Namen bereits vorhanden ist Set objZiel = mwsDestSheet.Shapes(strName)

Objekte

Objekte

If Err.Number 0 Then ' Bei einem Fehler ist das Shape noch nicht ' vorhanden. Dann Shape erzeugen. Set objZiel = mwsDestSheet.Shapes.AddShape( _ msoShapeRoundedRectangularCallout, _ 0, 0, mdblWidth, mdblHeight) ' Namen für das Shape vergeben, der sich aus der ' Position zusammensetzt objZiel.Name = strName End If

Objekte

Objekte

With objZiel ' Überprüfen, ob bereits Text vorhanden ist, ' wenn ja, Zeilenumbruch und neuen Text hinzu ' sonst Text ohne Zeilenumbruch hinzu strDummy = .TextFrame.Characters.Text If strDummy = "" Then .TextFrame.Characters.Text = varDummy(3) Else .TextFrame.Characters.Text = strDummy & _ vbLf & varDummy(3) End If

Objekte

strDummy = .TextFrame.Characters.Text ' Anzahl der Zeilen ermitteln lngZeilen = (Len(strDummy) - _ Len(Replace(strDummy, vbLf, ""))) _ / 2 + 1

Objekte

Listing 275 (Forts.)

2471_Excel-VBA.book Seite 455 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte ' Breite anpassen .Width = mdblWidth * (mobjMap.Width / 100)

Objekte

455

' Position Fahne setzen .Left = varPos(1) .Top = varPos(2) - .Height * 2 ' 2 mal Höhe nach oben

Objekte

' Höhe an die Anzahl der Zeilen anpassen .Height = mdblHeight * (mobjMap.Height / 100)* lngZeilen

' Pfeil von Unterkante nach unten (Plus), 2 mal Höhe .DrawingObject.ShapeRange.Adjustments.Item(2) = 2

Objekte

' Pfeil von Mitte nach links (Minus), 0,5 mal Breite .DrawingObject.ShapeRange.Adjustments.Item(1) = -0.5

' Rahmen anpassen .DrawingObject.Border.Color = mlngColor .DrawingObject.Border.Weight = 0 End With End If Next

Objekte

' Füllung anpassen .DrawingObject.ShapeRange.Fill.ForeColor.RGB = mlngColor .DrawingObject.ShapeRange.Fill.Transparency = _ mdblTransparency

Objekte

' Texteigenschaften anpassen .TextFrame.Characters.Font.Size = mlngTextSize .DrawingObject.Font.ColorIndex = mlngTextColorIndex

Listing 275 (Forts.)

Objekte

End Function

Nachfolgend einige Umwandlungsfunktionen, mit deren Hilfe man Koordinaten, die als Grad, Minuten und Sekunden vorliegen, in die Dezimalform und von der Dezimalform in die umgekehrte Richtung umrechnen kann. Die Ausgabe kann auch in Textform erfolgen. Auf dem Tabellenblatt UMRECHNUNG GRAD GAUSS findet man diese Funktionen als benutzerdefinierte Funktionen im Einsatz.

Objekte

Koordinaten liegen nicht immer in dem Format vor, welches beispielsweise für das vorherige Rezept 175 benötigt wurde.

Objekte

176 Koordinaten umrechnen

2471_Excel-VBA.book Seite 456 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

456 >> Koordinaten umrechnen '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_04_GaussKrüger.xlsm ' Tabelle Umrechnung Grad Gauss ' Modul mdl_07_07_Coordinate '=================================================================== Public Function CoordinateToDecimal( _ lngDegree As Long, _ lngMinute As Long, lngSecond As Long _ ) As Double CoordinateToDecimal = lngDegree + _ TimeSerial(0, lngMinute, lngSecond) * 24 End Function Public Function DecimalToTimeCoordinate( _ coordinate As Double _ ) As String DecimalToTimeCoordinate = _ Int(coordinate) & ":" & _ Minute(coordinate / 24) & ":" & _ Second(coordinate / 24) End Function Public Function CoordinateToTimeCoordinate( _ lngDegree As Long, _ lngMinute As Long, lngSecond As Long _ ) As String CoordinateToTimeCoordinate = _ lngDegree & ":" & _ lngMinute & ":" & _ lngSecond End Function Public Function CoordinateToDegreeCoordinate( _ lngDegree As Long, _ lngMinute As Long, lngSecond As Long _ ) As String CoordinateToDegreeCoordinate = _ lngDegree & "° " & _ lngMinute & "' " & _ lngSecond & "'' " End Function Public Function DecimalToDegreeCoordinate( _ coordinate As Double _ ) As String DecimalToDegreeCoordinate = _ Int(coordinate) & "° " & _ Minute(coordinate / 24) & "' " & _ Second(coordinate / 24) & "''" End Function Listing 276

2471_Excel-VBA.book Seite 457 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte

Dim dblBNull Dim dblBf

As Double As Double

Dim dblNf Dim dblEf Dim dblTf

As Double As Double As Double

Objekte Objekte

adblB(1 To 2) As Double adblL(1 To 2) As Double dblBreite As Double dblLänge As Double

Dim Pi

As Double

Objekte

Dim Dim Dim Dim

Objekte

Public Function Längengrad( _ Hochwert As Double, _ Rechtswert As Double _ ) As Double Dim dblRechts As Double Dim dblSektor As Double Dim dblÄquator As Double Dim dblPolar As Double Dim dblE As Double Dim dblN As Double Dim dblAlpha As Double Dim dblBeta As Double Dim dblGamma As Double Dim dblDelta As Double Dim dblEpsilon As Double Dim dblY0 As Double Dim dblL0 As Double Dim dblY As Double

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte\ ' Dateiname 07_04_GaussKrüger.xlsm ' Tabelle Umrechnung Grad Gauss ' Modul mdl_07_07_GaussKrueger '===================================================================

Objekte

Ein besonderes Problem stellt die Umrechnung von GAUß-KRÜGER-Koordinaten in die Gradform dar. Die zwei nachfolgenden Funktionen nehmen den Rechts- und Hochwert entgegen und liefern den Längen- und Breitengrad.

Objekte

457

Pi = 3.14159265358979

Objekte

Listing 277

2471_Excel-VBA.book Seite 458 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

458 >> Koordinaten umrechnen dblÄquator = 6377397.155 dblPolar = 6356078.962 dblE = (dblÄquator ^ 2 - dblPolar ^ 2) / dblÄquator ^ 2 dblN = (dblÄquator - dblPolar) / (dblÄquator + dblPolar) dblAlpha = (dblÄquator + dblPolar) / 2 * _ (1 + 0.25 * dblN ^ 2 + (1 / 64) * dblN ^ 4) dblBeta = (3 / 2) * dblN - (27 / 32) * dblN ^ 3 + (269 / 512) * _ dblN ^ 5 dblGamma = (21 / 16) * dblN ^ 2 - (55 / 32) * dblN ^ 4 dblDelta = (151 / 96) * dblN ^ 3 - (417 / 128) * dblN ^ 5 dblEpsilon = (1097 / 512) * dblN ^ 4 dblY0 = Int(Rechtswert / 10 ^ 6) dblL0 = dblY0 * 3 dblY = Rechtswert - dblY0 * 10 ^ 6 - 500000 dblBNull = Hochwert / dblAlpha dblBf = dblBNull + dblBeta * Sin(2 * dblBNull) + _ dblGamma * Sin(4 * dblBNull) + _ dblDelta * Sin(6 * dblBNull) + _ dblEpsilon * Sin(8 * dblBNull) dblNf = dblÄquator / (1 - dblE * Sin(dblBf) ^ 2) ^ 0.5 dblEf = (dblÄquator ^ 2 / dblPolar ^ 2 * dblE * Cos(dblBf) ^ 2) _ ^ 0.5 dblTf = Tan(dblBf) adblB(1) = dblTf / adblB(2) = dblTf / 6 * dblEf ^ 2 9 * dblTf ^ 2 * dblBreite = (dblBf

2 / dblNf ^ 2 * (-1 - dblEf ^ 2) * dblY ^ 2 24 / dblNf ^ 4 * (5 + 3 * dblTf ^ 2 + _ 6 * dblTf ^ 2 * dblEf ^ 2 - 4 * dblEf ^ 4 - _ dblEf ^ 4) * dblY ^ 4 + adblB(1) + adblB(2)) * 180 / Pi

adblL(1) = 1 / dblNf / Cos(dblBf) * dblY adblL(2) = 1 / 6 / dblNf ^ 3 / Cos(dblBf) * _ (-1 - 2 * dblTf ^ 2 - dblEf ^ 2) * dblY ^ 3 dblLänge = dblL0 + (adblL(1) + adblL(2)) * 180 / Pi

Objekte

Längengrad = dblLänge End Function Public Function Breitengrad( _ Hochwert As Double, _ Rechtswert As Double _ ) As Double

Objekte

Listing 277 (Forts.)

2471_Excel-VBA.book Seite 459 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte

Dim dblNf Dim dblEf Dim dblTf

As Double As Double As Double

Dim Dim Dim Dim

adblB(1 To 2) As Double adblL(1 To 2) As Double dblBreite As Double dblLänge As Double

Dim Pi

As Double

Pi = 3.14159265358979 dblÄquator = 6377397.155 dblPolar = 6356078.962 dblE = (dblÄquator ^ 2 - dblPolar ^ 2) / dblÄquator ^ 2 dblN = (dblÄquator - dblPolar) / (dblÄquator + dblPolar) dblAlpha = (dblÄquator + dblPolar) / 2 * _ (1 + 0.25 * dblN ^ 2 + (1 / 64) * dblN ^ 4) dblBeta = (3 / 2) * dblN - (27 / 32) * _ dblN ^ 3 + (269 / 512) * dblN ^ 5 dblGamma = (21 / 16) * dblN ^ 2 - (55 / 32) * dblN ^ 4 dblDelta = (151 / 96) * dblN ^ 3 - (417 / 128) * dblN ^ 5 dblEpsilon = (1097 / 512) * dblN ^ 4 dblY0 = Int(Rechtswert / 10 ^ 6) dblL0 = dblY0 * 3 dblY = Rechtswert - dblY0 * 10 ^ 6 - 500000 dblBNull = Hochwert / dblAlpha Listing 277 (Forts.)

Objekte Objekte Objekte

As Double As Double

Objekte

Dim dblBNull Dim dblBf

Objekte

Double Double Double Double Double Double Double Double Double Double Double Double Double Double

Objekte

As As As As As As As As As As As As As As

Objekte

dblRechts dblSektor dblÄquator dblPolar dblE dblN dblAlpha dblBeta dblGamma dblDelta dblEpsilon dblY0 dblL0 dblY

Objekte

Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim

459

2471_Excel-VBA.book Seite 460 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

460 >> Assistent MSAgent dblBf = dblBNull + dblBeta * Sin(2 * dblBNull) + _ dblGamma * Sin(4 * dblBNull) + _ dblDelta * Sin(6 * dblBNull) + _ dblEpsilon * Sin(8 * dblBNull) dblNf = dblÄquator / (1 - dblE * Sin(dblBf) ^ 2) ^ 0.5 dblEf = (dblÄquator ^ 2 / dblPolar ^ 2 * dblE * Cos(dblBf) ^ 2) _ ^ 0.5 dblTf = Tan(dblBf) adblB(1) = dblTf / adblB(2) = dblTf / 6 * dblEf ^ 2 9 * dblTf ^ 2 * dblBreite = (dblBf

Objekte

adblL(1) adblL(2) (-1 dblLänge

= = 2 =

2 / dblNf ^ 2 * (-1 - dblEf ^ 2) * dblY ^ 2 24 / dblNf ^ 4 * (5 + 3 * dblTf ^ 2 + _ 6 * dblTf ^ 2 * dblEf ^ 2 - 4 * dblEf ^ 4 - _ dblEf ^ 4) * dblY ^ 4 + adblB(1) + adblB(2)) * 180 / Pi

1 / dblNf / Cos(dblBf) * dblY 1 / 6 / dblNf ^ 3 / Cos(dblBf) * _ * dblTf ^ 2 - dblEf ^ 2) * dblY ^ 3 dblL0 + (adblL(1) + adblL(2)) * 180 / Pi

Breitengrad = dblBreite End Function

Objekte

Objekte

Objekte

Objekte

Listing 277 (Forts.)

177 Assistent MSAgent Office-Assistenten sind die animierten Figuren, die ihre Hilfe in Form von Sprechblasen anbieten. Dass diese Dinger ganz schön nerven können, ist unbestritten, Microsoft hat aber etwas übers Ziel hinausgeschossen und diese in Office 2007 komplett entfernt. Wer dennoch Assistenten benutzen möchte, kann stattdessen die Windows-Agenten verwenden.

2471_Excel-VBA.book Seite 461 Dienstag, 4. Dezember 2007 1:42 13

461

Nun benötigt man noch einen Charakter wie beispielsweise Merlin, der standardmäßig vorhanden sein sollte, wenn die CORE COMPONENTS bereits installiert sind. Im Ordner mit dem Namen C:\windows\msagent\Chars sollten Dateien mit der Endung .asc (Merlin.acs, Genie.acs) vorhanden sein, die jeweils einen eigenen Charakter repräsentieren. Übrigens findet man bei Microsoft noch einige andere Charaktere wie GENIE, ROBBY oder PEEDY zum Herunterladen. Microsoft hält sogar noch Links auf andere Seiten bereit, die Charaktere kostenfrei anbieten.

Objekte Objekte

Weiterhin sind die länderspezifischen Komponenten für die Sprachausgabe notwendig, das sind für den deutschen Sprachraum die LANGUAGE COMPONENTS (Agt0407.dll) in Deutsch. Die Datei sollte, wenn installiert, im Verzeichnis C:\windows\msagent\ intl, zu finden sein, die Installationsdatei dazu ist die Datei AgtX0407.exe. Dadurch ermöglicht man die Sprachausgabe von Sonderzeichen wie Ä, Ö oder Ü.

Objekte

Das Benutzen des Agenten ist recht einfach, sofern dieser auf dem System verfügbar ist. Das sollte zumindest unter Windows XP standardmäßig der Fall sein. Benötigt werden die MICROSOFT AGENT CORE FILES, die das Steuerelement für die Agenten bereitstellen. Um zu kontrollieren, ob das Steuerelement auf Ihrem System verfügbar ist, öffnen Sie den Ordner C:\Windows\msagent und suchen nach der Datei Agentsvr.exe. Die notwendigen AGENT CORE COMPONENTS (Msagent.exe ~395 KB) kann man ohne Probleme bei Microsoft kostenlos herunterladen.

Objekte

Abbildung 166: Merlin im Einsatz

Objekte

Objekte

Objekte

Objekte

>> Objekte

2471_Excel-VBA.book Seite 462 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

462 >> Assistent MSAgent

Abbildung 167: Merlin, Genie, Robby, Peedy

Wenn alle diese Voraussetzungen erfüllt sind, kann es trotzdem vorkommen, dass der Agent nicht auf Anhieb funktioniert, was an fehlenden Einträgen in der Registry liegen kann. Dem kann man dadurch abhelfen, indem man die Datei C:\WINDOWS\ msagent\agentctl.dll neu registriert. Dazu gibt man in Windows unter START | AUSFÜHREN, die Zeile REGSVR32 C:\WINDOWS\msagent\agentctl.dll ein und schließt mit der (Enter)-Taste ab. Der benutzerdefinierten Funktion Agent_Speak wird als erstes Argument der Text übergeben, der in der Sprechblase erscheinen und ausgesprochen werden soll. Diesem Text kann man noch Steuerkommandos übergeben, die zwischen zwei Backslashs (»\«) stehen, wobei der dazwischen stehende Text nicht ausgegeben wird. Damit ist es möglich, Worte besonders zu betonen oder die Lautstärke der Sprachausgabe zu ändern. Im Listing sind als Kommentar einige Steuerkommandos angegeben. Der zweite Parameter legt die Art der Animation fest. Damit kann man die Figuren beispielsweise zwinkern oder sich verbeugen lassen, die Namen der Animationen sind bei den verschiedenen Charakteren von Microsoft gleich. Nicht bei allen Charakteren funktioniert dagegen die Sprachausgabe und viele liefern keine Soundeffekte. Außerdem werden nicht alle Animationen von jedem Charakter unterstützt. Animation

Sprache Geräusche Animation

Sprache Geräusche

Acknowledge

Nein

Nein

LookLeftBlink

Nein

Nein

Alert

Ja

Nein

LookLeftReturn

Nein

Nein

Announce

Ja

Ja

LookRight

Nein

Nein

Blink

Nein

Nein

LookRightBlink

Nein

Nein

Confused

Ja

Ja

LookRightReturn

Nein

Nein

Congratulate

Ja

Ja

LookUp

Nein

Nein

Congratulate_2

Ja

Ja

LookUpBlink

Nein

Nein

Decline

Ja

Nein

LookUpReturn

Nein

Nein

DoMagic1

Ja

Nein

MoveDown

Nein

Ja

DoMagic2

Nein

Ja

MoveLeft

Nein

Ja

DontRecognize

Ja

Nein

MoveRight

Nein

Ja

Explain

Ja

Nein

MoveUp

Nein

Ja

GestureDown

Ja

Nein

Pleased

Ja

Nein

Objekte

Tabelle 39: Animationen

2471_Excel-VBA.book Seite 463 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte

Process

Nein

Ja

GestureRight

Ja

Nein

Processing

Nein

Ja

GestureUp

Ja

Nein

Read

Ja

Ja

GetAttention

Ja

Ja

ReadContinued

Ja

Ja

GetAttentionContinued

Ja

Ja

ReadReturn

Nein

Ja

GetAttentionReturn

Nein

Nein

Reading

Nein

Ja

Greet

Ja

Ja

RestPose

Ja

Nein

Hearing_1

Nein

Nein

Sad

Ja

Nein

Hearing_2

Nein

Nein

Search

Nein

Ja

Hearing_3

Nein

Nein

Searching

Nein

Ja

Hearing_4

Nein

Nein

Show

Nein

Ja

Hide

Nein

Ja

StartListening

Ja

Nein

Idle1_1

Nein

Nein

StopListening

Ja

Nein

Idle1_2

Nein

Nein

Suggest

Ja

Ja

Idle1_3

Nein

Nein

Surprised

Ja

Ja

Idle1_4

Nein

Nein

Think

Ja

Nein

Idle2_1

Nein

Nein

Thinking

Nein

Nein

Idle2_2

Nein

Nein

Uncertain

Ja

Nein

Idle3_1

Nein

Ja

Wave

Ja

Nein

Idle3_2

Nein

Ja

Write

Ja

Ja

LookDown

Nein

Nein

WriteContinued

Ja

Ja

LookDownBlink

Nein

Nein

WriteReturn

Nein

Ja

LookDownReturn

Nein

Nein

Writing

Nein

Ja

LookLeft

Nein

Nein

Tabelle 39: Animationen (Forts.)

Der dritte und vierte Parameter gibt die X- bzw. Y-Position an, an der die Figur erscheinen soll. Der Aufruf zum Starten der Animation kann auch als Tabellenfunktion erfolgen, was bei benutzerdefinierten Funktionen, die Aktionen anstoßen können, nicht selbstverständlich ist. Der vierte Parameter ist optional und gibt den Charakter an, der verwendet werden soll, voreingestellt ist der Charakter Merlin. An dieser Stelle kann man einen beliebigen Charakternamen übergeben.

Objekte

Nein

Objekte

Ja

Objekte

GestureLeft

Objekte

Sprache Geräusche

Objekte

Sprache Geräusche Animation

Objekte

Animation

Objekte

463

Objekte

Was alles mit dem Agenten und den einzelnen Charakteren möglich ist, kann man in der SDK DOCUMENTATION FOR MICROSOFT AGENT erfahren, welche man auf der Seite http://www.microsoft.com/msagent/downloads/developer.asp#alldocs herunterladen

2471_Excel-VBA.book Seite 464 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

464 >> Assistent MSAgent

kann. Dort stehen noch mehr nützliche Sachen zum Download bereit, darunter ein Editor für eigene Charaktere. Zu Beginn wird mit CreateObject ein Objekt vom Typ Agent.control angelegt. Bei einem Fehler, etwa wenn die CORE COMPONENTS nicht installiert oder korrekt registriert sind, wird die Funktion verlassen. Anschließend wird die Connected-Eigenschaft des Agent-Controls auf Wahr gesetzt und ein als Parameter übergebener Charakter geladen. Voreingestellt ist der Charakter Merlin. Mit Hilfe des Objektes objCharakter, welches anschließend zur Verfügung steht, legen Sie nun über die Eigenschaften Left und Top die X- und Y-Position fest, an der der Agent zu Beginn erscheinen soll. Möchten Sie, dass beim Erscheinen des Charakters keine Soundeffekte ausgegeben werden, muss die Eigenschaft SoundEffekts auf Falsch gesetzt werden (.SoundEffectsOn = False), in der vorliegenden Funktion ist diese Zeile auskommentiert. Mit der Eigenschaft LanguageID legen Sie die Ausgabesprache fest, der Hexadezimalwert &H407 steht dabei für die deutsche Sprache. Voraussetzung für das Funktionieren sind allerdings die LANGUAGE COMPONENTS in Deutsch, die in der Datei Agt0407.dll stecken. Anschließend wird der Agent mit der Show-Methode angezeigt und mit der MoveMethode an seine Zielposition gebracht, wobei der Agent während des Verschiebens animiert wird. Mit der Play-Methode wird nun die gewünschte Animation gestartet. In diesem Rezept wird kein Verweis auf das Agent-Objekt gesetzt, sondern mit der späten Bindung über CreateObject gearbeitet, weshalb Sie auch keine Ereignisse empfangen können, die das Objekt auslöst. Deshalb folgt nun eine Schleife, die so lange laufen sollte, bis die Sprachausgabe beendet ist. Das wird deshalb gemacht, weil nach dem Beenden der Funktion die Objektvariablen objCharakter und objAgent automatisch auf Nothing gesetzt und der Agent sofort entladen wird. Dem könnte man abhelfen, indem man die beiden Objekte auf Modulebene deklariert, dann bleibt der Agent aber so lange sichtbar, bis man die Objektvariablen objCharakter und objAgent auf Nothing setzt oder nach einem Rechtsklick über das Kontextmenü den Befehl »Ausblenden« wählt. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_05_Agent.xlsm ' Tabelle Agent ' Modul mdl_07_08_Agent '=================================================================== ' ' ' '

\chr=""monotone""\ monoton \Chr=""normal""\ flüstern \Chr=""Whisper""\ flüstern \Lst\ letzten Satz wiederholen

Listing 278

2471_Excel-VBA.book Seite 465 Dienstag, 4. Dezember 2007 1:42 13

Public Function Agent_Speak(strText As String, _ Optional Animation As String = "RestPose", _ Optional x As Long = 200, Optional y As Long = 200) Dim objCharakter As Object Dim objAgent As Object Dim varResult As Variant Dim dtmExit As Date

Objekte

\Map=""Woorschd""=""Wurst""\ Aussprache-Angezeigter Text \Pau=Millisekunde\ Pause \Rst\ alle Standards wiederherstellen \Spd=AnzahlWörter\ Wörter pro Minute \Vol=Lautstärke\ 0 bis 65535 \emp\ Wort betonen

Objekte

' ' ' ' ' '

465

Objekte

>> Objekte

Agent_Speak = strText

Set objAgent = CreateObject("Agent.control")

Objekte

' Evtl. Agent Core Components (Msagent.exe) installieren ' Language Components German AgtX0407.exe installieren

objAgent.Connected = True

Objekte

If objAgent Is Nothing Then Exit Function ' Bei Fehlern evtl. C:\WINDOWS\msagent\agentctl.dll ' registrieren. Start/Ausführen, Folgendes eingeben: ' regsvr32 C:\WINDOWS\msagent\agentctl.dll

' Für die Sprachausgabe ' Evtl. Text to Speech Engines German (Lhttsged.exe) ' und Sapi 4.0a Runtime Binaries (Spchapi.exe) installieren

Objekte

' Evtl. nachschauen, ob Charakter Merlin überhaupt vorhanden ist ' Datei : C:\WINDOWS\msagent\Chars\Merlin.acs objAgent.Characters.Load "Merlin", "Merlin.acs"

With objCharakter ' Position festlegen .Top = 0 .Left = 0

Objekte

' Charakter Merlin festlegen Set objCharakter = objAgent.Characters("Merlin")

Objekte

Listing 278 (Forts.)

2471_Excel-VBA.book Seite 466 Dienstag, 4. Dezember 2007 1:42 13

Objekte

466 >> Animierte Grafik ' Geräusche weglassen ' .SoundEffectsOn = False

Objekte

' Sprache einstellen .LanguageID = &H407 ' Merlin anzeigen .Show

Objekte

' Charakter verschieben nach .MoveTo x, y ' Animation starten .Play Animation ' Vorlesen lassen Set varResult = .Speak(strText)

Objekte

' Timeoutzeit dtmExit = Now() + TimeSerial(0, 0, 10) ' Warten, bis Vorlesen beeendet Do While varResult.Status 0

Objekte

DoEvents ' Timeout If Now() > dtmExit Then Exit Do Loop End With

Objekte

End Function Listing 278 (Forts.)

Objekte

Objekte

178 Animierte Grafik In Excel können ohne Probleme Grafiken mit der Dateierweiterung *.gif oder *.png, in ein Tabellenblatt eingebettet oder als Hintergrund von Steuerelementen oder Diagrammen verwendet werden. Leider werden darin steckende Animationen, die in Form aufeinanderfolgender Bilder vorliegen, nicht ausgeführt, lediglich das erste Bild wird angezeigt. Abhilfe schafft der Webbrowser, der als ACTIVEX-Objekt eingebettet wird. Dazu öffnet man die Registerkarte ENTWICKLERTOOLS und klickt auf das Icon EINFÜGEN. Aus der Werkzeugsammlung wird der Punkt WEITERE STEUERELEMENTE gewählt, das ist das

2471_Excel-VBA.book Seite 467 Dienstag, 4. Dezember 2007 1:42 13

467

Objekte

Objekte

Objekte

Objekte

Icon rechts unten mit dem gekreuzten Hammer und dem Schraubenschlüssel. Aus der Liste der weiteren Steuerelemente wählt man nun den Eintrag MICROSOFT WEB BROWSER und zieht ein Rechteck auf dem Tabellenblatt aus.

Objekte

>> Objekte

Objekte

Erstellt man eine Kopie eines Tabellenblattes, welches ein eingebettetes WebbrowserSteuerelement enthält, bekommt man möglicherweise eine Warnmeldung angezeigt, die nachfragt, ob man dieses Steuerelement aktivieren oder deaktivieren möchte. Ob dieser Dialog erscheint, hängt von den ACTIVEX-Einstellungen im Vertrauensstellungscenter ab.

Objekte

Über das Eigenschaftsfenster kann man nun einen einprägsamen Namen vergeben. Diesen Namen kann man auch so festlegen, indem man in der Bearbeitungsleiste ganz links, dort wo normalerweise die aktuelle Zelladresse erscheint, einen Namen eingibt und mit der (Enter)-Taste bestätigt. In diesem Rezept wurde der Name objOut benutzt. Im Eigenschaftsfenster kann man auch die Größe und Position des Objektes festlegen.

Objekte

Abbildung 168: Verweis auf den Webbrowser

2471_Excel-VBA.book Seite 468 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

468 >> Animierte Grafik

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Abbildung 169: Sicherheitshinweis

Um im Webbrowser-Objekt eine animierte Grafik anzeigen zu lassen, bedient man sich der Navigate-Methode. Die Prozedur Workbook_Open ist im Klassenmodul DieseArbeitsmappe zu finden und wird beim Öffnen der Arbeitsmappe ausgeführt. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_06_Animation.xlsm ' Tabelle Animation ' Modul DieseArbeitsmappe '=================================================================== Private Sub Workbook_Open() Worksheets("Animation").objOut.Navigate _ ThisWorkbook.Path & "\Earth.gif" End Sub Listing 279

Nach einem Klick auf die im Tabellenblatt untergebrachte Schaltfläche cmdGetFile wird die Ereignisprozedur cmdGetFile_Click ausgeführt. Darin wird mit der GetOpenFilename-Methode ein Dateipfad ermittelt, wobei als Dateifilter die Grafikdateien mit der Endung *.gif und *.png verwendet werden. Die Liste kann ohne Probleme auch auf die Dateien erweitert werden, die mit dem Internet Explorer angezeigt werden können. Auch hier wird die Navigate-Methode verwendet. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_06_Animation.xlsm ' Tabelle Animation ' Modul Tabelle Animation '=================================================================== Listing 280

2471_Excel-VBA.book Seite 469 Dienstag, 4. Dezember 2007 1:42 13

Private Sub cmdGetFile_Click() Dim objMediaPlayer As Object Dim varFilename As Variant ' Dateiname und Pfad abfragen varFilename = Application.GetOpenFilename( _ "Video/Audio-Dateien " & _ "(*.gif; *.png)," & _ "*.gif; *.png")

Objekte

469

Objekte

>> Objekte

' Animierte Grafiken anzeigen Me.objOut.Navigate varFilename

Objekte

' Verlassen, wenn kein Speicherort gewählt If varFilename = False Then Exit Sub

End Sub

Selbstverständlich kann das Webbrowser-Objekt auch Grafiken und sogar komplette Internetseiten anzeigen, die sich im World Wide Web befinden, dafür ist solch ein Browser ja schließlich erschaffen worden. Darauf wird im Kapitel »Web/Mail« näher eingegangen.

Objekte

Listing 280 (Forts.)

Objekte Objekte

Dazu öffnen Sie die Registerkarte ENTWICKLERTOOLS und klicken auf das Icon EINFÜGEN. Aus der Werkzeugsammlung wird der Punkt WEITERE STEUERELEMENTE gewählt, das ist das Icon rechts unten mit dem gekreuzten Hammer und dem Schraubenschlüssel. Aus der Liste der weiteren Steuerelemente wählen Sie nun den Eintrag MICROSOFT MEDIA PLAYER und ziehen ein Rechteck auf dem Tabellenblatt auf.

Objekte

Excel kann standardmäßig keine Video- oder Audiodateien abspielen. Wie schon zuvor beim Anzeigen von animierten Grafiken wird ein fremdes Objekt mittels OleAutomation eingebunden. Das Objekt, welches in diesem Rezept verwendet wird, ist der Media Player von Microsoft.

Objekte

179 Video-/Audiodateien abspielen

2471_Excel-VBA.book Seite 470 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

Objekte

470 >> Video-/Audiodateien abspielen

Abbildung 170: Media Player

Über das Eigenschaftsfenster können Sie einen einprägsamen Namen vergeben. Diesen Namen kann man auch festlegen, indem man in der Bearbeitungsleiste ganz links, dort, wo normalerweise die aktuelle Zelladresse erscheint, einen Namen eingibt und mit der (Enter)-Taste bestätigt. In diesem Rezept wurde der Name myPlayer benutzt. Im Eigenschaftsfenster können Sie auch die Größe und Position des Objektes festlegen. Nach einem Klick auf die im Tabellenblatt untergebrachte Schaltfläche cmdGetFile wird die Ereignisprozedur cmdGetFile_Click ausgeführt. Darin wird mit der GetOpenFilename-Methode ein Dateipfad ermittelt, wobei als Dateifilter die Media-Dateien mit der Endung *.avi, *.mpg, *.mpeg, *.wmv, und *.mp3 verwendet werden. Selbstverständlich kann die Liste auf alle Dateien erweitert werden, die mit dem Media Player abgespielt werden können.

2471_Excel-VBA.book Seite 471 Dienstag, 4. Dezember 2007 1:42 13

Private Sub cmdGetFile_Click() Dim varFilename As Variant ' Dateiname und Pfad abfragen varFilename = Application.GetOpenFilename( _ "Video/Audio-Dateien (*.avi; *.mpg; *.mpeg; *.wmv; *.mp3;" & _ "*.wma),*.avi; *.mpg; *.mpeg; *.wmv; *.mp3; *.wma") ' Verlassen, wenn keine Datei gewählt wurde If varFilename = False Then Exit Sub

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_06_Animation.xlsm ' Tabelle Player ' Modul Tabelle Player '===================================================================

Objekte

471

Objekte

>> Objekte

End Sub

Objekte

' Video/Audio abspielen Me.myPlayer.URL = varFilename

Listing 281

Objekte Objekte

Die existierenden Bildchen werden auf einer Userform in einem TREEVIEW-Steuerelement mit weiteren Informationen dargestellt. Wählen Sie ein Icon aus und klicken auf die Schaltfläche, wird das Icon in einem Bildsteuerelement auf dem aktivem Blatt dargestellt.

Objekte

Viele der in Excel verfügbaren Controls besitzen Icons, welche man auch für eigene Zwecke verwenden kann, dazu muss man aber die ID-Nummer des gewünschten Controls kennen. In diesem Rezept werden die ID-Nummern von 1 bis knapp 30.000 daraufhin überprüft, ob überhaupt ein Control mit dieser ID existiert und wenn ja, ob dieses eine FaceID besitzt, welche anzeigt, dass ein zugehöriges Bild existiert.

Objekte

180 Control-Icons extrahieren

2471_Excel-VBA.book Seite 472 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

Objekte

472 >> Control-Icons extrahieren

Objekte

Objekte

Objekte

Objekte

Objekte

Abbildung 171: Control-Icons

Da Icons normalerweise einen transparenten Hintergrund besitzen, der meistens die RGB-Farbe 0 hat, und diese Icons in diesem Rezept als Bild verwendet werden, kommt es zu Abweichungen zwischen dem Aussehen als Control und dem exportierten Bild. Die meisten Hintergründe sind deshalb also statt transparent schwarz. Auf dem Tabellenblatt CONTROL ICONS befinden sich zwei Schaltflächen. Ein Klick auf die Schaltfläche cmdAddImage (BILDSTEUERELEMENTE EINFÜGEN) zeigt die Userform UF_07_11_GETIMAGEMSO an. In der Ereignisprozedur der anderen Schaltfläche cmdDelete (ALLE BILDSTEUERELEMENTE LÖSCHEN) werden in einer Schleife alle Shapes des Tabellenblattes durchlaufen, handelt es sich bei dem Shape um ein Bildsteuerelement, wird es gelöscht. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_07_ImageMSO.xlsm ' Tabelle Control Icons ' Modul Tabelle Control Icons '=================================================================== Private Sub cmdAddImage_Click() If MsgBox("Das Einlesen der Control-Icons kann einige" & _ vbCrLf & _ "Minuten in Anspruch nehmen!" & _ vbCrLf & _ "Möchten Sie dennoch fortfahren?", _ vbYesNo Or vbQuestion) = vbYes Then _ uf_07_11_GetImageMSO.Show Listing 282

2471_Excel-VBA.book Seite 473 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte End Sub Private Sub cmdDelete_Click() Dim objShape As Object For Each objShape In Me.Shapes If objShape.OLEFormat.progID = "Forms.Image.1" Then objShape.Delete End If Next End Sub

Objekte

Objekte

473

Dim mobjTreeView Dim mobjTreeImage Dim mlngTop

As Object As Object As Long

Objekte

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_07_ImageMSO.xlsm ' Modul uf_07_11_GetImageMSO '===================================================================

Objekte

Beim Initialisieren der Benutzerform wird die Ereignisprozedur UserForm_Initialize ausgeführt. Dort wird ein Treeview-Objekt mit Hilfe der Controls.Add-Methode aus der Bibliothek MSCOMCTLLIB erzeugt und in die Benutzerform eingepasst. Die Eigenschaft HideSelection des Steuerelementes wird noch auf Falsch gesetzt und dient dazu, dass auch nach dem Verlust des Fokus der ausgewählte Eintrag optisch markiert bleibt. Anschließend rufen Sie die Prozedur AddIcons auf.

Objekte

Listing 282 (Forts.)

With mobjTreeView ' Treeview formatieren .Name = "Tree" .Left = 10 .Top = 40 .Width = Me.Width - 25 .Height = Me.Height - 90 .HideSelection = False End With

Objekte

' Treeview in Form einfügen Set mobjTreeView = Me.Controls.Add( _ "MSComCtlLib.TreeCtrl.2")

Objekte

Private Sub UserForm_Initialize()

End Sub Listing 283

Objekte

AddIcons

2471_Excel-VBA.book Seite 474 Dienstag, 4. Dezember 2007 1:42 13

In der Prozedur AddIcons wird zu Beginn mit Hilfe der Controls.Add-Methode ein neues ImageList-Steuerelement erzeugt, welches die Icons aufnehmen kann. In einer Schleife wird anschließend die Zählvariable i bei jedem Durchlauf um 1 erhöht. Diese wird zusammen mit der Methode FindControl als ID benutzt. Existiert ein solches Control, ist die Variable objControl nicht mehr Nothing. In diesem Fall wird auf die Eigenschaft FaceId zugegriffen, wenn das Control ein Bild besitzt, ist der Wert ungleich Null.

Jetzt wird das ListImage- mit dem Treeview-Objekt verbunden und anschließend wird für jedes Icon mit der Nodes.Add-Methode ein eigener Knoten im Treeview-Objekt angelegt. Die ersten zwei Parameter geben die relative Position des Knotens an, werden diese Parameter weggelassen, legt man einen neuen Hauptknoten an. Der dritte Parameter ist ein eindeutiger Schlüssel, der in diesem Rezept benötigt wird. Dazu wird der gleiche Schlüssel verwendet, den das zugehörige Icon in der ImageList besitzt, die ID steckt in der Collection colItems. Der vierte Parameter bei der AddMethode ist der Text, welcher ausgegeben wird, dieser wird auch aus der Collection colItems ausgelesen. Der fünfte Parameter gibt die Position des angezeigten Icons in der verbundenen ImageList an. Bis alle ID-Nummern durchprobiert sind, kann es etwas dauern. Bei meinem betagten Rechner dauert das etwa 45 Sekunden, deshalb bitte nicht die Geduld verlieren!

Objekte

Objekte

Objekte

Besitzt das Control ein Bild, wird der Objektvariablen objPic das Bild über die Picture-Eigenschaft des Controls zugewiesen und dieses mit der Methode .ListImages. Add in das ImageList-Objekt transferiert. In der Collection colItems wird als ein Element noch die ID und die Beschriftung des aktuellen Controls gespeichert. Das in der Collection gespeicherte Element besteht aus einem eindimensionalen Array mit zwei Elementen, wobei das erste Element die ID und das zweite den auszugebenden Text aufnimmt.

Objekte

Objekte

Objekte

Objekte

474 >> Control-Icons extrahieren

'=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_07_ImageMSO.xlsm ' Modul uf_07_11_GetImageMSO '=================================================================== Private Sub AddIcons() Dim objControl Dim lngFaceId Dim objPic Dim colItems Dim varItem Dim astrDummy(1 To 2) Dim i

Objekte

On Error Resume Next Listing 284

As As As As As As As

Object Long Object New Collection Variant String Long

2471_Excel-VBA.book Seite 475 Dienstag, 4. Dezember 2007 1:42 13

>> Objekte ' Bildcontainer neu erzeugen Set mobjTreeImage = Nothing Set mobjTreeImage = CreateObject( _ "MSComCtlLib.ImageListCtrl.2")

Objekte

475

For i = 1 To 32767

Objekte

On Error Resume Next

If Not (objControl Is Nothing) Then ' Ein Control mit der angegebenen ID existiert lngFaceId = 0 lngFaceId = objControl.FaceId

Objekte

' Versuchen, ein Control mit der ID zu finden Set objControl = CommandBars.FindControl(ID:=i)

' Bildobjekt holen Set objPic = objControl.Picture

Objekte

' ID und Beschriftung speichern Erase astrDummy astrDummy(1) = "ID=" & lngFaceId astrDummy(2) = "ID=" & lngFaceId & _ " Caption=" & objControl.Caption

Objekte

If lngFaceId > 0 Then ' Objekt mit Picture

' Infos über ID und Caption in Collection speichern colItems.Add astrDummy

Objekte

' Im Image-Steuerelement speichern mobjTreeImage.ListImages.Add , _ astrDummy(1), objPic

With mobjTreeView ' Die Bilderliste mit dem Treeview verbinden .Object.imagelist = mobjTreeImage

Objekte

End If End If Next

Listing 284 (Forts.)

Objekte

i = 0

2471_Excel-VBA.book Seite 476 Dienstag, 4. Dezember 2007 1:42 13

Objekte

Objekte

476 >> Control-Icons extrahieren For Each varItem In colItems i = i + 1 ' Knoten erzeugen, ID, Text und Bildnummer angeben .Object.Nodes.Add , , varItem(1), varItem(2), i Next End With End Sub

Objekte

Objekte

Objekte

Objekte

Listing 284 (Forts.)

Nach einem Klick auf die Schaltfläche cmdCopy wird die Objektvariable objIcon mit dem Icon des angewählten Eintrags des Treeview-Controls gefüllt. Dazu bedient man sich der ExtractIcon-Methode des mit dem Treeview verbundenen TreeImage-Objektes. Als Index in die Liste dient der Schlüssel des ausgewählten Eintrags. Anschließend legt man mit der OleObjects.Add-Methode des aktiven Tabellenblattes ein neues Bildsteuerelement an und weist der Picture-Eigenschaft das Icon zu. Leider ist es nicht möglich, über das von der Add-Methode zurückgelieferte Objekt die PictureSizeMode-Eigenschaft zu beeinflussen, der Versuch ergibt zwar keinen Fehler, bewirkt aber auch nichts. Deshalb wird die Eigenschaft über das Shape-Objekt des Tabellenblattes auf den Wert 3 gesetzt, das heißt, das Bild wird so vergrößert, dass es in den Container, also das Bildsteuerelement, passt. '=================================================================== ' Auf CD Buchdaten\Beispiele\07_Objekte ' Dateiname 07_07_ImageMSO.xlsm ' Modul uf_07_11_GetImageMSO '=================================================================== Private Sub cmdCopy_Click() Dim objImage As Object Dim lngActItem As Long Dim objIcon As Object Dim objNode As Object

Objekte

On Error Resume Next Err.Clear With mobjTreeView ' Ausgewählter Knoten Set objNode = mobjTreeView.SelectedItem

Objekte

' Zugehöriges Icon extrahieren Set objIcon = _ mobjTreeImage.ListImages(objNode.Key).ExtractIcon Listing 285

2471_Excel-VBA.book Seite 477 Dienstag, 4. Dezember 2007 1:42 13

End With

477 Objekte

>> Objekte

' Bildsteuerelement einfügen Set objImage = ActiveSheet.OLEObjects.Add( _ ClassType:="Forms.Image.1", _ DisplayAsIcon:=False, _ Left:=0, Top:=mlngTop, Width:=50, Height:=50)

Objekte

If Err.Number = 0 Then

' Bild festlegen objImage.Object.Picture = objIcon

Objekte

' Y-Position für nächstes Bild mlngTop = mlngTop + objImage.Height

End If End Sub

Objekte

' Umweg über das Shape-Objekt, der direkte Weg funktioniert_ ' nicht ActiveSheet.Shapes(objImage.Name _ ).DrawingObject.Object.PictureSizeMode = 3

Objekte

Objekte

Objekte

Objekte

Listing 285 (Forts.)

2471_Excel-VBA.book Seite 478 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

2471_Excel-VBA.book Seite 479 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Ein Diagramm wird in der Regel über die Registerkarte EINFÜGEN (Abbildung 172) der Multifunktionsleiste angelegt.

Diagramme

Diagramme sind ein wichtiges Instrument zur Visualisierung von Daten. Der Name Diagramm stammt von dem griechischen Wort diagramma ab, was soviel bedeutet wie geometrische Figur oder Umriss. Mit Hilfe von Diagrammen lassen sich zeitliche Abläufe leichter erfassen und komplexe Sachverhalte anschaulich darstellen.

Diagramme

181 Einführung

Markiert man das Diagramm, werden drei neue Registerkarten mit Namen ENTWURF, LAYOUT und FORMAT eingeblendet, deren Symbolleisten Zugriff auf jede beliebige

Diagramme

Am einfachsten markiert man zuvor die Daten, die anschließend im Diagramm dargestellt werden sollen. Falls das nicht geschehen ist, stellt das auch kein großes Problem dar, man kann ohne Mühe den Datenbereich sowie alle Beschriftungen und Formatierungen nachträglich ändern, oder wenn nötig neu angeben.

Diagramme

Abbildung 172: Diagramme einfügen

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 480 Dienstag, 4. Dezember 2007 1:42 13

480 >> Einführung

Eigenschaft des Diagramms geben. Über das Kontextmenü, welches nach einem Rechtsklick auf das Diagramm erscheint, können die Eigenschaften auch angepasst werden. Unter Excel 2007 sind viele verschiedene Diagrammtypen aus mehreren Diagrammfamilien verfügbar, die individuell nahezu beliebig formatiert werden können. Ein Statistiker oder Mathematiker wird darunter sicher einige Diagrammtypen vermissen, man muss aber anmerken, dass Excel kein spezielles Chart-Programm ist, sondern Diagramme sozusagen als zusätzliches Bonbon mitbringt. Für den Normalanwender und den täglichen Gebrauch sollten die vorhandenen Diagrammtypen aber ausreichen und sicherlich auch keine Wünsche offen lassen. Die verschiedenen Diagrammtypen sind in den 11 Familien (Abbildung 173) SÄULE, LINIE, TORTE, BALKEN, BEREICH, PUNKT (x y), KURS, OBERFLÄCHE, RING, BLASE und NETZ untergebracht.

Abbildung 173: Verfügbare Diagramme in Excel 2007

Nachfolgend eine Liste (Tabelle 40), die alle 73 verfügbaren Diagrammtypen enthält. Der Typ wird durch einen Wert dargestellt, für den auch eine vordefinierte Konstante in der Aufzählung (ENUM) XlChartType existiert. Gesetzt oder ausgelesen wird der Diagrammtyp über die Eigenschaft ChartType (objChart.Chart.ChartType). In der Beispieldatei 08_02_ ChartType.xlsm im Rezept 182 kann man sich nacheinander alle Typen als Diagramm anschauen. Beschreibung

Konstantenname

Wert

Punkte, nur Datenpunkte

xlXYScatter

-4169

Netz

xlRadar

-4151

Ring

xlDoughnut

-4120

3D Torte

xl3DPie

-4102

3D Linie

xl3DLine

-4101

3D Säulen

xl3DColumn

-4100

3D Fläche

xl3DArea

-4098

Fläche

xlArea

1

Linie

xlLine

4

Torte

xlPie

5

Blasendiagramm

xlBubble

15

Gruppierte Säulen vertikal

xlColumnClustered

51

Tabelle 40: Diagrammtypen, Konstanten und Werte

52

Gestapelte Säulen 100% vertikal

xlColumnStacked100

53

Gruppierte 3D-Säulen vertikal

xl3DColumnClustered

54

Gestapelte 3D-Säulen vertikal

xl3DColumnStacked

55

Gestapelte 3D-Säulen 100% vertikal

xl3DColumnStacked100

56

Gruppierte Säulen horizontal

xlBarClustered

57

Gestapelte Säulen horizontal

xlBarStacked

58

Gestapelte Säulen 100% horizontal

xlBarStacked100

59

Gruppierte 3D-Säulen horizontal

xl3DBarClustered

60

Gestapelte 3D-Säulen horizontal

xl3DBarStacked

61

Gestapelte 3D-Säulen 100% horizontal

xl3DBarStacked100

62

Gestapelte Linie

xlLineStacked

63

Gestapelte Linie 100%

xlLineStacked100

64

Linie mit Datenpunkten

xlLineMarkers

65

Gestapelte Linie mit Datenpunkten

xlLineMarkersStacked

66

Gestapelte Linie mit Datenpunkten 100%

xlLineMarkersStacked100

67

Kreis aus Kreis

xlPieOfPie

68

Explodierter Kreis

xlPieExploded

69

Explodierter 3D Kreis

xl3DPieExploded

70

Balken aus Kreis

xlBarOfPie

71

Punkte, interpol. Linien, Datenpunkte

xlXYScatterSmooth

72

Punkte, interpol. Linien

xlXYScatterSmoothNoMarkers

73

Punkte, gerade Linien, Datenpunkte

xlXYScatterLines

74

Punkte, gerade Linien

xlXYScatterLinesNoMarkers

75

Gestapelte Fläche

xlAreaStacked

76

Gestapelte Fläche 100%

xlAreaStacked100

77

Gestapelte 3D Fläche

xl3DAreaStacked

78

Gestapelte 3D Fläche 100%

xl3DAreaStacked100

79

Explodierter Ring

xlDoughnutExploded

80

Netz mit Datenpunkten

xlRadarMarkers

81

Gefülltes Netz

xlRadarFilled

82

3D-Oberfläche

xlSurface

83

3D-Oberfläche Drahtmodell

xlSurfaceWireframe

84

Oberfläche

xlSurfaceTopView

85

Tabelle 40: Diagrammtypen, Konstanten und Werte (Forts.)

Diagramme

xlColumnStacked

Diagramme

Gestapelte Säulen vertikal

Diagramme

Wert

Diagramme

Konstantenname

Diagramme

Beschreibung

Diagramme

481

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 481 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 482 Dienstag, 4. Dezember 2007 1:42 13

482 >> Einführung Beschreibung

Konstantenname

Wert

Oberfläche, Ansicht oben

xlSurfaceTopViewWireframe

86

Blasendiagramm 3D

xlBubble3DEffect

87

Kurs, Höchst-Tief-Geschlossen

xlStockHLC

88

Kurs, Öffnung-Höchst-Tief-Geschlossen

xlStockOHLC

89

Kurs, Volumen-Höchst-Tief-Geschlossen

xlStockVHLC

90

Kurs, Volumen-Öffnung-Höchst-TiefGeschlossen

xlStockVOHLC

91

Gruppierte Zylinder vertikal

xlCylinderColClustered

92

Gestapelte Zylinder vertikal

xlCylinderColStacked

93

Gestapelte Zylinder 100% vertikal

xlCylinderColStacked100

94

Gruppierte 3D-Zylinder vertikal

xlCylinderBarClustered

95

Gestapelte 3D-Zylinder vertikal

xlCylinderBarStacked

96

Gestapelte 3D-Zylinder 100% vertikal

xlCylinderBarStacked100

97

Gruppierte Zylinder horizontal

xlCylinderCol

98

Gruppierte Kegel vertikal

xlConeColClustered

99

Gestapelte Kegel vertikal

xlConeColStacked

100

Gestapelte Kegel 100% vertikal

xlConeColStacked100

101

Gruppierte 3D-Kegel vertikal

xlConeBarClustered

102

Gestapelte 3D-Kegel vertikal

xlConeBarStacked

103

Gestapelte 3D-Kegel 100% vertikal

xlConeBarStacked100

104

Gruppierte Kegel horizontal

xlConeCol

105

Gruppierte Pyramiden vertikal

xlPyramidColClustered

106

Gestapelte Pyramiden vertikal

xlPyramidColStacked

107

Gestapelte Pyramiden 100% vertikal

xlPyramidColStacked100

108

Gruppierte 3D-Pyramiden vertikal

xlPyramidBarClustered

109

Gestapelte 3D-Pyramiden vertikal

xlPyramidBarStacked

110

Gestapelte 3D-Pyramiden 100% vertikal

xlPyramidBarStacked100

111

Gruppierte Pyramiden horizontal

xlPyramidCol

112

Diagramme

Diagramme

Tabelle 40: Diagrammtypen, Konstanten und Werte (Forts.)

Ein Diagramm kann in einer Excel Arbeitsmappe auf zweierlei Arten existieren. Zum einen kann es als unabhängiges Chart-Objekt vorkommen, welches wie ein normales Tabellenblatt mit einem eigenen Tabellenreiter erscheint. In diesem Fall sind die auszuwertenden Daten auf einem gesonderten Tabellenblatt untergebracht und das Diagramm füllt das gesamte Blatt aus.

Sie können ein Diagramm, welches sich eingebettet in einem Tabellenblatt befindet, auch ohne Probleme in ein Diagrammblatt umwandeln und umgekehrt. Bei aktiviertem Diagramm ist auf der Registerkarte ENTWURF ganz rechts das Symbol DIAGRAMM VERSCHIEBEN (Abbildung 174) zu finden. In dem Kontextmenü, welches sich nach einem Rechtsklick auf das Diagramm öffnet, befindet sich auch ein Menüpunkt mit dem Namen DIAGRAMM VERSCHIEBEN.

Abbildung 174: Diagramm verschieben

Diagramme

Diagramme

Diagramme

Diagramme

Wird eines dieser zwei Menüs ausgewählt, erscheint ein Dialogfenster mit dem Dialogtitel DIAGRAMM VERSCHIEBEN, in dem man den zukünftigen Speicherort (NEUES BLATT oder OBJEKT IN) festlegen kann. Die Arbeitsmappe, die dem folgenden Bild zugrunde liegt, finden Sie übrigens unter Buchdaten\Beispiele\08_Diagramme\ 08_01_Lissajou.xlsm, ein eigenes Rezept dazu existiert aber nicht.

Diagramme

Im anderen Fall wird das Diagramm in ein normales Tabellenblatt eingebettet – als CONTAINER dient dabei ein Shape-Objekt. Das hat den Vorteil, dass man auf dem sichtbaren Tabellenblattbereich auch die zugehörige Wertetabelle und sonstige darzustellende Informationen unterbringen kann. Das Chart-Objekt selbst verfügt über keinerlei Eigenschaften, welche die Position und Größe angeben. In einem Tabellenblatt ist dafür der übergeordnete Container zuständig, im Falle eines eingebetteten Diagramms ist das also ein Shape-Object.

Diagramme

483

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 483 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 484 Dienstag, 4. Dezember 2007 1:42 13

484 >> Einführung

Während das unabhängige Chart-Objekt über die Charts-Auflistung erreichbar ist (Charts(1).Name), kann man ein eingebettetes Diagramm nur über die Shapes- (Worksheets(1).Shapes(1).Chart.Name) oder direkt über die ChartObjects-Auflistung (Worksheets(1).ChartObjects(1).Chart.Name) des jeweiligen Tabellenblattes erreichen. Das Objektmodell eines Diagramms ist recht umfangreich und leider nicht sehr einfach zu durchschauen. Ohne eine intensive Beschäftigung damit wird man sich kaum mehr als einen groben Überblick verschaffen können. Die in diesem Kapitel enthaltenen Rezepte sollen dazu beitragen, die wichtigsten Eigenschaften und Methoden der verschiedenen Objekte kennenzulernen, ein Codebeispiel sagt ja meistens mehr aus als tausend Worte. Nachfolgend finden Sie noch ein paar einführende Hinweise über die grobe Struktur des Objektmodells. Das Hauptobjekt eines Diagramms ist das Chart-Objekt. Es existiert wie bereits beschrieben, entweder als unabhängiges oder als untergeordnetes Objekt eines ShapeObjektes. Das Chart-Objekt verfügt über eigene Eigenschaften und Methoden, besitzt aber auch untergeordnete Objekte. Die direkt verfügbaren Eigenschaften eines Chart-Objekts sind beispielsweise die Type-Eigenschaft, welche den Diagrammtyp angibt, oder die Name-Eigenschaft, die den Diagrammnamen enthält. Eine über das Chart-Objekt erreichbare Funktion ist die SeriesCollection-Funktion, die ein Objekt zurückgibt, welches eine Datenreihe repräsentiert.

Diagramme

Die zur Verfügung stehenden Ereignisse eines Chart-Objektes sind Activate, BeforeDoubleClick, BeforeRightClick, Calculate, Deactivate, MouseDown, MouseUp, MouseMove, Resize, Select und SeriesChange.

Diagramme

Direkt verfügbare Methoden sind solche wie PrintOut zum Drucken oder Protect zum Schützen eines Diagramms.

왘 Die Objektklasse ChartTitle ermöglicht es dem Programmierer, das Aussehen und die Position des Diagrammtitels festzulegen.

Die dem Chart-Objekt untergeordneten Klassenobjekte wie beispielsweise BackWall, ChartArea, Corners, Floor, Legend, PlotArea und Walls dienen als die Ausgangspunkte für die unterschiedlichsten Formatierungen.

왘 Die Objektklasse DataTable ermöglicht es, Einfluss auf das Aussehen und die Position der Datentabelle zu nehmen.

Diagramme

왘 Die Objektklasse Legend erlaubt den Zugriff auf die Eigenschaften der Legende. 왘 Die ChartArea-Objektklasse umfasst die gesamte Fläche des Diagramms. Die über der ChartArea liegende Zeichnungsfläche (PlotArea) mit den dargestellten Daten und den Achsen verfügt über eine eigene Füllung, so dass beim Setzen der ChartArea-Eigenschaften optisch meist nur die Ränder betroffen sind.

Diagramme

왘 Die Objektklassen BackWall, Floor und Walls repräsentieren die Rückwand, den Boden und die Wände eines 3D-Diagramms 왘 Die Objektklasse Corners erlaubt den Zugriff auf die Ecken eines 3D-Diagramms.

H i n we i s

In einigen Rezepten dieses Kapitels stellen aus einem Tabellenblatt ausgelesene und verwendete Werte einen Index dar, beispielsweise solche, die einen Stil wie das Hintergrundmuster oder eine vordefinierte Positionen angeben. Mit einer Bildlaufleiste kann man nun nacheinander alle verfügbaren Stile oder Muster auswählen. Der Index kann dabei Werte zwischen 1 und der Anzahl der vorhandenen Elemente in der zugehörigen Aufzählung (Enum) annehmen. Die Min- und Max-Eigenschaftswerte der zugehörigen Bildlaufleisten begrenzen dabei die Auswahl. Ein Beispiel dafür wäre die Legendenposition, die verfügbaren Konstanten stecken in einer Aufzählung mit Namen XlLegendPosition. Die Konstantennamen können im Code genauso benutzt werden wie die Werte selbst. Mit dem Index in die Aufzählung selbst kann man aber noch nicht viel anfangen, deshalb benutzt man die selbst generierten Übersetzungsfunktionen, die mit dem Präfix Translate beginnen und die diesen Index in den Konstantennamen und den zugehörigen Wert umwandeln. Der Einfachheit halber liefern diese Funktionen die Ergebnisse als Text, wobei der Konstantenname und der zugehörige Wert durch ein Gleichheitszeichen voneinander getrennt sind. Public Function TranslateXlLegendPosition(lngNumber As Long) Select Case lngNumber Case 1 TranslateXlLegendPosition ="xlLegendPositionBottom = -4107" Case 2 TranslateXlLegendPosition ="xlLegendPositionCorner = 2" Case 3 TranslateXlLegendPosition ="xlLegendPositionLeft = -4131" Case 4

Diagramme Diagramme

Frisch hinzugekommen in Excel 2007 ist die Objektklasse ChartFormat, die weitaus umfangreichere Formatierungsmöglichkeiten zur Verfügung stellt, als es über die vorher erwähnten Objektklassen Border, Fill, Interior und Font möglich ist. Wo es in den nachfolgenden Rezepten sinnvoll ist, wird diese neue Objektklasse benutzt, zum Teil auch zusammen mit den traditionellen, die weiterhin angewandt werden können.

Diagramme

Die meisten der erwähnten Objektklassen mit grafischen Attributen enthalten wiederum die Objektklassen Border, Fill, Interior und Font, mit denen man Zugriff auf den Rahmen, die Füllung, den Innenbereich und die Schrifteigenschaften erhält.

Diagramme

Eine SeriesCollection enthält die Informationen der einzelnen Datenreihen und gibt Zugriff auf die Daten, die Linienformate und den Diagrammtyp der entsprechenden Reihe.

Diagramme

왘 Weitere im Chart-Objekt enthaltene Objektklassen sind die Klassen Columns3DGroup, Hyperlinks, PageSetup, Shapes und Sidewall. Auf diese Klassen wird aber nicht näher eingegangen, weitere Informationen dazu erhalten Sie aus der OnlineHilfe.

Diagramme

485

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 485 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

486 >> Diagramm programmgesteuert erzeugen

Hinweis

Diagramme

2471_Excel-VBA.book Seite 486 Dienstag, 4. Dezember 2007 1:42 13

TranslateXlLegendPosition ="xlLegendPositionRight = -4152" Case 5 TranslateXlLegendPosition ="xlLegendPositionTop = -4160" Case Else TranslateXlLegendPosition ="Benutzerdefiniert" End Select End Function

Der zurückgelieferte Text wird in den meisten Rezepten nach dem Übersetzen in das Tabellenblatt direkt neben die zugehörige Bildlaufleiste geschrieben. Der durch die Übersetzungsfunktion zurückgelieferte Text wird vor dem eigentlichen Zuweisen zu einer Eigenschaft mit Hilfe der Split-Funktion in ein Array umgewandelt, dessen erstes Element den Index 0 besitzt. Als Trennzeichen für die Split-Funktion wird das Gleichheitszeichen verwendet. Nach dem Splitten enthält das Element mit dem Index 1 den eigentlichen Wert als Text, und zwar mit einem führenden Leerzeichen. Dieses wird mit Hilfe der Umwandlungsfunktion cLng in einen Ganzzahlenwert vom Typ Long umgewandelt, der auch als Typ der zugrunde liegenden Konstanten verwendet wird. Diesen Wert übergibt man schließlich an die zu setzende Eigenschaft. Die folgende Codezeile würde den Wert –4107 zurückliefern: CLng(Split(TranslateXlLegendPosition(1), "=")(1))

Diagramme

Diagramme

Diagramme

Diagramme

Die Übersetzungsfunktionen sind alle gleich aufgebaut und werden aus Platzmangel in diesem Kapitel nicht abgedruckt. Zu finden sind diese in den Beispielmappen im jeweiligen Codemodul.

182 Diagramm programmgesteuert erzeugen Um sich einen Überblick darüber zu verschaffen, welche Arten von Diagrammen mit Excel überhaupt möglich sind, könnte man sich 73 verschiedene Diagramme erstellen und diese dann miteinander vergleichen. Das ist aber recht aufwendig, sehr unübersichtlich und erfordert einiges an Hard- und Softwareressourcen. Besser wäre es, sich nacheinander alle möglichen Diagrammtypen an der gleichen Position anzuschauen. Um das zu realisieren, könnte man sich irgendein Diagramm anlegen und anschließend den Diagrammtyp über ein VBA-Programm anpassen. Mitunter führt das aber zu Problemen, beispielsweise dann, wenn von einem Diagramm vom Typ BALLON auf eines vom Typ KURS gewechselt wird. Das liegt daran, dass sich die Anforderungen an den Datenbereich erheblich unterscheiden. Ein vorheriger Wechsel der Datenbereiche bereitet aber auch Probleme, deshalb wird in diesem Rezept ein anderer Weg gegangen. Nach einem Klick auf das Drehfeld oben links wird jeweils ein anderes Diagramm angezeigt. Dazu wird ein eventuell vorhandenes Diagramm gelöscht und ein neues hinzugefügt. Der Diagrammtyp, die Größe und Position, der Datenbereich und die Beschriftung des neuen Diagramms werden anschließend angepasst.

487

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_02_ChartType.xlsm ' Tabelle Typen ' Modul Tabellenblatt Typen '=================================================================== Private Sub spnChartNumber_Change() MakeChart spnChartNumber.Value End Sub

Diagramme

Ein Klick auf das oben links befindliche Drehfeld spnChartNumber löst bei einer Änderung des Wertes die Change-Ereignisprozedur aus. Die Eigenschaftswerte Min und Max des Drehfeldes sind so eingestellt, dass dieses Steuerelement nur Werte zwischen 0 und 72 annehmen kann. Der aktuelle Wert wird bei jeder Änderung an die Prozedur MakeChart übergeben.

Diagramme

Abbildung 175: Diagrammtypen anzeigen

Diagramme

Diagramme

Diagramme

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 487 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Listing 286

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 488 Dienstag, 4. Dezember 2007 1:42 13

488 >> Diagramm programmgesteuert erzeugen

Jeder an die Prozedur MakeChart als Parameter lngNumber übergebene Wert wird als Index in das zuvor erzeugte Array varCharts gewertet, welches die numerischen Eigenschaftswerte aller 73 möglichen Diagrammtypen enthält. Ist der übergebene Index außerhalb der oberen und unteren Grenze des Arrays, wird die Prozedur umgehend verlassen. Anschließend werten Sie den gewählten Diagrammtyp aus, der sich als Element im Array varChart an der Position des übergebenen Index befindet. Für den aktuell gewählten Diagrammtyp werden nun mit Hilfe der Select Case-Anweisung die auf diesen Typ zugeschnittenen Informationen in die zwei Variablen strConstName und strDescription geschrieben. Die Informationen, die anschließend in diesen zwei Variablen stecken, gelangen zusammen mit dem eigentlichen Diagrammwert in das Tabellenblatt TYPEN. Danach werden alle vorhandenen Diagramme auf diesem Tabellenblatt gelöscht und es wird mit der Anweisung Shapes.AddChart ein neues Diagramm eingefügt. Jetzt wird das Diagramm in Größe und Position angepasst. Dazu modifiziert man das Shape- und nicht das darin steckende Chart-Objekt. Über den ChartTitle-Eigenschaftswert des Chart-Objektes (objChart.Chart) wird der Diagrammtitel gesetzt. Anschließend wird der Inhalt des gesamten möglichen Wertebereiches F1:J5 im Tabellenblatt gelöscht. Für jeden Diagrammtyp werden mit Hilfe der Select CaseAnweisung andere, auf den jeweiligen Diagrammtyp zugeschnittene Werte in den Wertebereich geschrieben und danach das Diagramm entsprechend angepasst. Eine bedingte Formatierung im Wertebereich hebt die Zellen mit Inhalt farblich hervor. Bei Blasendiagrammen (Typ 15, 87) muss man etwas anders vorgehen. Es reicht hier nicht, einfach den Wertebereich festzulegen, wenn man die Größen der einzelnen Blasen selbst bestimmen möchte. Zuerst werden die zu setzenden Werte und Größen in den Bereich F1:J5 des Tabellenblatts TYPEN geschrieben. Daraufhin wird mit der Methode .Chart.SeriesCollection.NewSeries eine neue Datenreihe erzeugt. Danach wird der Diagrammtyp bestimmt, der Name, der Bereich der X-, Y- und Größenwerte dieser Datenreihe festgelegt. Zuletzt wird der Diagrammtyp angepasst und die Legende nach unten gesetzt. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_02_ChartType.xlsm ' Tabelle Typen ' Modul mdl_08_02_MakeChart '=================================================================== Listing 287

' Je nach gewähltem Diagrammtyp Infos über den Typ ' in zwei Variable bringen Select Case varCharts(lngNumber) Case xlColumnClustered ' 51 strConstName = "xlColumnClustered" strDescription = "Gruppierte Säulen vertikal" Case xlColumnStacked ' 52 strConstName = "xlColumnStacked" strDescription = "Gestapelte Säulen vertikal" Case xlColumnStacked100 ' 53 strConstName = "xlColumnStacked100" strDescription = "Gestapelte Säulen 100% vertikal" Case xl3DColumnClustered ' 54 strConstName = "xl3DColumnClustered" strDescription = "Gruppierte 3D-Säulen vertikal" Case xl3DColumnStacked ' 55 strConstName = "xl3DColumnStacked" strDescription = "Gestapelte 3D-Säulen vertikal" Case xl3DColumnStacked100 ' 56 strConstName = "xl3DColumnStacked100" strDescription = "Gestapelte 3D-Säulen 100% vertikal" Case xlBarClustered ' 57 strConstName = "xlBarClustered" strDescription = "Gruppierte Säulen horizontal" Case xlBarStacked ' 58 strConstName = "xlBarStacked" strDescription = "Gestapelte Säulen horizontal" Listing 287 (Forts.)

Diagramme Diagramme Diagramme

' Wenn für die Nummer kein entsprechendes Element ' existiert, Prozedur verlassen If lngNumber < LBound(varCharts) Then Exit Sub If lngNumber > UBound(varCharts) Then Exit Sub

Diagramme

' Array mit vorhandenen Diagrammtypen erzeugen varCharts = Array(51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, _ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, _ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 15, 87, 88, 89, 90, _ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, _ 105, 106, 107, 108, 109, 110, 111, 112, -4100, 4, -4101, _ -4102, 5, -4169, -4098, 1, -4120, -4151)

Diagramme

Sub MakeChart(lngNumber As Long) varCharts As Variant strConstName As String strDescription As String objChart As Object

Diagramme

Public Dim Dim Dim Dim

489

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 489 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 490 Dienstag, 4. Dezember 2007 1:42 13

490 >> Diagramm programmgesteuert erzeugen Case xlBarStacked100 ' 59 strConstName = "xlBarStacked100" strDescription = "Gestapelte Säulen 100% horizontal" Case xl3DBarClustered ' 60 strConstName = "xl3DBarClustered" strDescription = "Gruppierte 3D-Säulen horizontal" Case xl3DBarStacked ' 61 strConstName = "xl3DBarStacked" strDescription = "Gestapelte 3D-Säulen horizontal" Case xl3DBarStacked100 ' 62 strConstName = "xl3DBarStacked100" strDescription = "Gestapelte 3D-Säulen 100% horizontal" Case xlLineStacked ' 63 strConstName = "xlLineStacked" strDescription = "Gestapelte Linie" Case xlLineStacked100 ' 64 strConstName = "xlLineStacked100" strDescription = "Gestapelte Linie 100%" Case xlLineMarkers ' 65 strConstName = "xlLineMarkers" strDescription = "Linie mit Datenpunkten" Case xlLineMarkersStacked ' 66 strConstName = "xlLineMarkersStacked" strDescription = "Gestapelte Linie mit Datenpunkten" Case xlLineMarkersStacked100 ' 67 strConstName = "xlLineMarkersStacked100" strDescription = "Gestapelte Linie mit Datenpunkten 100%" Case xlPieOfPie ' 68 strConstName = "xlPieOfPie" strDescription = "Kreis aus Kreis" Case xlPieExploded ' 69 strConstName = "xlPieExploded" strDescription = "Explodierter Kreis" Case xl3DPieExploded ' 70 strConstName = "xl3DPieExploded" strDescription = "Explodierter 3D Kreis" Case xlBarOfPie ' 71 strConstName = "xlBarOfPie" strDescription = "Balken aus Kreis" Case xlXYScatterSmooth ' 72 strConstName = "xlXYScatterSmooth" strDescription = "Punkte, interpol. Linien, Datenpunkte" Case xlXYScatterSmoothNoMarkers ' 73 strConstName = "xlXYScatterSmoothNoMarkers" strDescription = "Punkte, interpol. Linien" Case xlXYScatterLines ' 74 strConstName = "xlXYScatterLines" Listing 287 (Forts.)

Listing 287 (Forts.)

Diagramme Diagramme Diagramme Diagramme Diagramme Diagramme

strDescription = "Punkte, gerade Linien, Datenpunkte" Case xlXYScatterLinesNoMarkers ' 75 strConstName = "xlXYScatterLinesNoMarkers" strDescription = "Punkte, gerade Linien" Case xlAreaStacked ' 76 strConstName = "xlAreaStacked" strDescription = "Gestapelte Fläche" Case xlAreaStacked100 ' 77 strConstName = "xlAreaStacked100" strDescription = "Gestapelte Fläche 100%" Case xl3DAreaStacked ' 78 strConstName = "xl3DAreaStacked" strDescription = "Gestapelte 3D Fläche" Case xl3DAreaStacked100 ' 79 strConstName = "xl3DAreaStacked100" strDescription = "Gestapelte 3D Fläche 100%" Case xlDoughnutExploded ' 80 strConstName = "xlDoughnutExploded" strDescription = "Explodierter Ring" Case xlRadarMarkers ' 81 strConstName = "xlRadarMarkers" strDescription = "Netz mit Datenpunkten" Case xlRadarFilled ' 82 strConstName = "xlRadarFilled" strDescription = "Gefülltes Netz" Case xlSurface ' 83 strConstName = "xlSurface" strDescription = "3D-Oberfläche" Case xlSurfaceWireframe ' 84 strConstName = "xlSurfaceWireframe" strDescription = "3D-Oberfläche Drahtmodell" Case xlSurfaceTopView ' 85 strConstName = "xlSurfaceTopView" strDescription = "Oberfläche" Case xlSurfaceTopViewWireframe ' 86 strConstName = "xlSurfaceTopViewWireframe" strDescription = "Oberfläche, Ansicht oben" Case xlBubble ' 15 strConstName = "xlBubble" strDescription = "Blasendiagramm" Case xlBubble3DEffect ' 87 strConstName = "xlBubble3DEffect" strDescription = "Blasendiagramm 3D" Case xlStockHLC ' 88 strConstName = "xlStockHLC" strDescription = "Kurs, Höchst-Tief-Geschlossen"

491

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 491 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 492 Dienstag, 4. Dezember 2007 1:42 13

492 >> Diagramm programmgesteuert erzeugen Case xlStockOHLC ' 89 strConstName = "xlStockOHLC" strDescription = "Kurs, Öffnung-Höchst-Tief-Geschlossen" Case xlStockVHLC ' 90 strConstName = "xlStockVHLC" strDescription = "Kurs, Volumen-Höchst-Tief-Geschlossen" Case xlStockVOHLC ' 91 strConstName = "xlStockVOHLC" strDescription = "Kurs, Volumen-Öffnung-Höchst" & _ "-Tief-Geschlossen" Case xlCylinderColClustered ' 92 strConstName = "xlCylinderColClustered" strDescription = "Gruppierte Zylinder vertikal" Case xlCylinderColStacked ' 93 strConstName = "xlCylinderColStacked" strDescription = "Gestapelte Zylinder vertikal" Case xlCylinderColStacked100 ' 94 strConstName = "xlCylinderColStacked100" strDescription = "Gestapelte Zylinder 100% vertikal" Case xlCylinderBarClustered ' 95 strConstName = "xlCylinderBarClustered" strDescription = "Gruppierte 3D-Zylinder vertikal" Case xlCylinderBarStacked ' 96 strConstName = "xlCylinderBarStacked" strDescription = "Gestapelte 3D-Zylinder vertikal" Case xlCylinderBarStacked100 ' 97 strConstName = "xlCylinderBarStacked100" strDescription = "Gestapelte 3D-Zylinder 100% vertikal" Case xlCylinderCol ' 98 strConstName = "xlCylinderCol" strDescription = "Gruppierte Zylinder horizontal" Case xlConeColClustered ' 99 strConstName = "xlConeColClustered" strDescription = "Gruppierte Kegel vertikal" Case xlConeColStacked ' 100 strConstName = "xlConeColStacked" strDescription = "Gestapelte Kegel vertikal" Case xlConeColStacked100 ' 101 strConstName = "xlConeColStacked100" strDescription = "Gestapelte Kegel 100% vertikal" Case xlConeBarClustered ' 102 strConstName = "xlConeBarClustered" strDescription = "Gruppierte 3D-Kegel vertikal" Case xlConeBarStacked ' 103 strConstName = "xlConeBarStacked" strDescription = "Gestapelte 3D-Kegel vertikal" Listing 287 (Forts.)

Listing 287 (Forts.)

Diagramme Diagramme Diagramme Diagramme Diagramme Diagramme

Case xlConeBarStacked100 ' 104 strConstName = "xlConeBarStacked100" strDescription = "Gestapelte 3D-Kegel 100% vertikal" Case xlConeCol ' 105 strConstName = "xlConeCol" strDescription = "Gruppierte Kegel horizontal" Case xlPyramidColClustered ' 106 strConstName = "xlPyramidColClustered" strDescription = "Gruppierte Pyramiden vertikal" Case xlPyramidColStacked ' 107 strConstName = "xlPyramidColStacked" strDescription = "Gestapelte Pyramiden vertikal" Case xlPyramidColStacked100 ' 108 strConstName = "xlPyramidColStacked100" strDescription = "Gestapelte Pyramiden 100% vertikal" Case xlPyramidBarClustered ' 109 strConstName = "xlPyramidBarClustered" strDescription = "Gruppierte 3D-Pyramiden vertikal" Case xlPyramidBarStacked ' 110 strConstName = "xlPyramidBarStacked" strDescription = "Gestapelte 3D-Pyramiden vertikal" Case xlPyramidBarStacked100 ' 111 strConstName = "xlPyramidBarStacked100" strDescription = "Gestapelte 3D-Pyramiden 100% vertikal" Case xlPyramidCol ' 112 strConstName = "xlPyramidCol" strDescription = "Gruppierte Pyramiden horizontal" Case xl3DColumn ' -4100 strConstName = "xl3DColumn" strDescription = "3D Säulen" Case xlLine ' 4 strConstName = "xlLine" strDescription = "Linie" Case xl3DLine ' -4101 strConstName = "xl3DLine" strDescription = "3D Linie" Case xl3DPie ' -4102 strConstName = "xl3DPie" strDescription = "3D Torte" Case xlPie ' 5 strConstName = "xlPie" strDescription = "Torte" Case xlXYScatter ' -4169 strConstName = "xlXYScatter" strDescription = "Punkte, nur Datenpunkte" Case xl3DArea ' -4098 strConstName = "xl3DArea"

493

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 493 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 494 Dienstag, 4. Dezember 2007 1:42 13

494 >> Diagramm programmgesteuert erzeugen strDescription = "3D Fläche" Case xlArea ' 1 strConstName = "xlArea" strDescription = "Fläche" Case xlDoughnut ' -4120 strConstName = "xlDoughnut" strDescription = "Ring" Case xlRadar ' -4151 strConstName = "xlRadar" strDescription = "Netz" End Select With Worksheets("Typen") ' Ausgabe der Typinformationen ins Tabellenblatt .Range("B3").Value = strConstName .Range("B4").Value = varCharts(lngNumber) .Range("B5").Value = strDescription ' Alle vorhandenen Charts löschen For Each objChart In .Shapes If objChart.Type = msoChart Then objChart.Delete Next ' Diagramm hinzufügen Set objChart = .Shapes.AddChart Do While objChart Is Nothing DoEvents Loop ' Diagramm positionieren objChart.Left = 0 objChart.Top = .Range("A7").Top objChart.Width = .Range("K6").Left objChart.Height = .Range("A30").Top - .Range("A7").Top ' Titel setzen objChart.Chart.HasTitle = True objChart.Chart.ChartTitle.Text = .Range("B5") ' Wertebereich löschen .Range("F1:J5").ClearContents ' Je nach Diagrammtyp unterschiedliche Werte ' in den Wertebereich schreiben Select Case varCharts(lngNumber) Case 83 To 86 Listing 287 (Forts.)

Listing 287 (Forts.)

Diagramme Diagramme Diagramme Diagramme Diagramme Diagramme

' Oberfläche .Range("F1") = "Reihe1" .Range("F2") = 10 .Range("F3") = 40 .Range("F4") = 30 .Range("F5") = 20 .Range("G1") = "Reihe2" .Range("G2") = 50 .Range("G3") = 30 .Range("G4") = 80 .Range("G5") = 50 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:G5"), _ PlotBy:=xlColumns Case 68 To 71, 80 To 82, -4102, 5, -4120, -4151 ' Kreis, Torte, Ring, Netz .Range("F1") = "Reihe1" .Range("F2") = 10 .Range("F3") = 40 .Range("F4") = 2 .Range("F5") = 3 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:F5"), _ PlotBy:=xlColumns Case 88 ' Kurs, Höchst-Tief-Geschlossen .Range("F1") = "Höchst" .Range("G1") = "Tief" .Range("H1") = "Geschlossen" .Range("F2") = 50 .Range("G2") = 10 .Range("H2") = 30 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:H2"), _ PlotBy:=xlColumns Case 89 ' Kurs, Öffnung-Höchst-Tief-Geschlossen .Range("F1") = "Öffnung" .Range("G1") = "Höchst" .Range("H1") = "Tief" .Range("I1") = "Geschlossen" .Range("F2") = 20 .Range("G2") = 40 .Range("H2") = 10

495

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 495 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 496 Dienstag, 4. Dezember 2007 1:42 13

496 >> Diagramm programmgesteuert erzeugen .Range("I2") = 30 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:I2"), _ PlotBy:=xlColumns Case 90 ' Kurs, Volumen-Höchst-Tief-Geschlossen .Range("F1") = "Volumen" .Range("G1") = "Höchst" .Range("H1") = "Tief" .Range("I1") = "Geschlossen" .Range("F2") = 20 .Range("G2") = 40 .Range("H2") = 10 .Range("I2") = 30 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:I2"), _ PlotBy:=xlColumns Case 91 ' Kurs, Volumen-Öffnung-Höchst-Tief-Geschlossen .Range("F1") = "Volumen" .Range("G1") = "Öffnung" .Range("H1") = "Höchst" .Range("I1") = "Tief" .Range("J1") = "Geschlossen" .Range("F2") = 20 .Range("G2") = 40 .Range("H2") = 50 .Range("I2") = 10 .Range("J2") = 30 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:J2"), _ PlotBy:=xlColumns Case 15, 87 ' Blasendiagramme .Range("F1") = "X-Werte" .Range("F2") = 10 .Range("F3") = 40 .Range("F4") = 30 .Range("F5") = 20 .Range("G1") = "Y-Werte" .Range("G2") = 50 .Range("G3") = 30 .Range("G4") = 80 .Range("G5") = 50 Listing 287 (Forts.)

' X-, Y-, Z-Werte und Reihenname festlegen With objChart.Chart.SeriesCollection(1) .XValues = "=Typen!$F$2:$F$5"' X-Werte .Values = "=Typen!$G$2:$G$5"' Y-Werte .BubbleSizes = "=Typen!$H$2:$H$5"' Z-Werte .Name = "=Typen!$B$3"' Reihenname End With Case Else .Range("F1") = "Reihe1" .Range("F2") = 10 .Range("F3") = 40 .Range("F4") = 30 .Range("F5") = 20 .Range("G1") = "Reihe2" .Range("G2") = 50 .Range("G3") = 30 .Range("G4") = 80 .Range("G5") = 50 ' Wertebereich festlegen, die Datenreihen ' befinden sich in Spalten objChart.Chart.SetSourceData Source:=Range("F1:G5"), _ PlotBy:=xlColumns End Select ' Typ anpassen objChart.Chart.ChartType = varCharts(lngNumber) ' Legendenposition unten objChart.Chart.Legend.Position = xlBottom

End With ' Worksheets("Typen")

Diagramme

' Typ bereits an dieser Stelle anpassen ' da sonst die Eigenschaft BubbleSizes fehlt objChart.Chart.ChartType = varCharts(lngNumber)

Diagramme

' Neue Serie hinzufügen objChart.Chart.SeriesCollection.NewSeries

Diagramme

"Größe" 10 40 30 20

Diagramme

= = = = =

Diagramme

.Range("H1") .Range("H2") .Range("H3") .Range("H4") .Range("H5")

497

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 497 Dienstag, 4. Dezember 2007 1:42 13

Listing 287 (Forts.)

Diagramme

End Sub

498 >> Diagrammtitel

183 Diagrammtitel Möchte man in einem Diagramm einen Diagrammtitel ohne Zuhilfenahme von VBA anzeigen, markiert man mit der Maustaste das Diagramm. Daraufhin erscheinen drei neue Registerkarten mit Namen ENTWURF, LAYOUT und FORMAT. Auf der Registerkarte LAYOUT findet man das Symbol mit der Beschriftung DIAGRAMMTITEL, mit deren Hilfe man festlegen kann, ob und wo der Diagrammtitel erscheint. Unter dem Punkt WEITERE TITELOPTIONEN kann man noch die Füllung, die Rahmenarten, die Rahmenfarbe, den Schatten, das 3D-Format und die Ausrichtung festlegen.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 498 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 176: Diagrammtitel

In diesem Rezept wird gezeigt, wie man den Text, die Schriftattribute, die Hintergrundfarbe und die Position des Diagrammtitels programmgesteuert anpassen kann. Dazu sind auf dem Tabellenblatt einige Schaltflächen und Bildlaufleisten untergebracht. 왘 Die zwei Bildlaufleisten rechts neben dem Diagramm sind dafür zuständig, die Position des Titels horizontal und vertikal zu verändern. 왘 Ein Klick auf die darunter liegende Schaltfläche schaltet zwischen der Standardposition und der benutzerdefinierten Position um. In der Standardposition

왘 Die darunter liegende Schaltfläche mit der Beschriftung FORMAT setzt die Schriftattribute, die Ausrichtung, den Text und die Hintergrundfarbe auf die Werte und Eigenschaften in Zelle I6. Ein Klick auf die Schaltfläche FORMAT löst das Click-Ereignis cmdFormat_Click aus. Zu Beginn wird darin der Titeltext an dem Zellinhalt I6 angepasst. Danach wird als erster Parameter an die Funktion FormatObjectLikeCell das anzupassende Objekt, in diesem Fall der Charttitel, übergeben. Als zweiter Parameter wird die Zelle übergeben, an deren Eigenschaften das Objekt angepasst werden soll, das ist die Zelle I6. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_03_Title.xlsm ' Tabelle Titel ' Modul Tabelle Titel '=================================================================== Private Sub cmdFormat_Click() Dim objTitle As ChartTitle ' Festlegen, dass Titel vorhanden ist. Me.ChartObjects(1).Chart.HasTitle = True

Diagramme

erscheint der Diagrammtitel zentriert über dem eigentlichen Diagramm, in der benutzerdefinierten Position bestimmen die zwei Bildlaufleisten die Position.

Diagramme

499

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 499 Dienstag, 4. Dezember 2007 1:42 13

' Titeltext anpassen objTitle.Text = Me.Range("I6").Value

Diagramme

Set objTitle = Me.ChartObjects(1).Chart.ChartTitle

Listing 288

Ein Klick auf die Schaltfläche mit Namen cmdAutomatic löst das Click-Ereignis cmdAutomatic_Click aus. Darin wird ermittelt, auf welchem Positionsmodus sich der Diagrammtitel gerade befindet. Ist die Position des Diagrammtitels auf xlChartElementPositionCustom gesetzt, wird die Beschriftung der Schaltfläche auf AUTOMATIK gesetzt, im anderen Fall auf BENUTZERDEFINIERT. Gleichzeitig wird die Position auf xlChartElementPositionAutomatic, im anderen Fall auf xlChartElementPositionCustom gesetzt.

Diagramme

End Sub

Diagramme

' Format anpassen FormatObjectLikeCell objTitle, Me.Range("I6")

Diagramme

Nach der Umschaltung auf den Modus BENUTZERDEFINIERT wird die Prozedur makeTitlePos aufgerufen.

Diagramme

Diagramme

2471_Excel-VBA.book Seite 500 Dienstag, 4. Dezember 2007 1:42 13

500 >> Diagrammtitel '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_03_Title.xlsm ' Tabelle Titel ' Modul Tabelle Titel '=================================================================== Private Sub cmdAutomatic_Click() With Me.ChartObjects(1).Chart.ChartTitle

Diagramme

If .Position = xlChartElementPositionAutomatic Then ' Positionsmodus steht auf "Automatik" ' Position auf "Benutzerdefiniert" .Position = xlChartElementPositionCustom

Diagramme

' Text des Buttons und Ausgabezelle anpassen cmdAutomatic.Caption = "Automatik" Me.Range("I4").Value = "Benutzerdefiniert" ' Position anpassen makeTitlePos

Diagramme

Diagramme

Else ' Positionsmodus steht auf "Benutzerdefiniert" ' Position auf "Automatik" .Position = xlChartElementPositionAutomatic ' Text des Buttons und Ausgabezelle anpassen cmdAutomatic.Caption = "Benutzerdefiniert" Me.Range("I4").Value = "Automatik" End If End With End Sub

Diagramme

Diagramme

Listing 289

Durch eine Änderung der Bildlaufleisten scrLeft oder scrTop wird eines der Ereignisse Change oder Scroll ausgelöst. Darin wird die Prozedur makeTitlePos aufgerufen, in welcher die X-Y-Position des Diagrammtitels geändert wird. Innerhalb der Prozedur makeTitlePos wird noch einmal nachgeschaut, ob der Modus auf BENUTZERDEFINIERT (xlChartElementPositionCustom) gesetzt ist. Ist das nicht der Fall, wird das Anpassen der Position unterlassen, im anderen Fall wird die Position des Diagrammtitels auf die Werte der beiden Bildlaufleisten scrLeft und scrTop gesetzt.

Private Sub scrLeft_Change() makeTitlePos End Sub Private Sub scrLeft_Scroll() makeTitlePos End Sub Private Sub scrTop_Change() makeTitlePos End Sub Private Sub scrTop_Scroll() makeTitlePos End Sub Private Sub makeTitlePos()

Diagramme

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_03_Title.xlsm ' Tabelle Titel ' Modul Tabelle Titel '===================================================================

Diagramme

Da Excel die Position so anpasst, dass der Diagrammtitel immer komplett sichtbar ist, müssen die Werte der zwei Bildlaufleisten scrLeft und scrTop nach dem Verschieben des Titels an die tatsächlich gesetzten Werte angepasst werden. Damit dabei nicht noch einmal ein Scroll- oder Change-Ereignis der Bildlaufleisten ausgelöst wird, wird das Auslösen von Ereignissen zu Beginn der Prozedur aus- und am Ende wieder eingeschaltet.

Diagramme

501

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 501 Dienstag, 4. Dezember 2007 1:42 13

' Festlegen, dass Titel vorhanden ist. Me.ChartObjects(1).Chart.HasTitle = True With Me.ChartObjects(1).Chart.ChartTitle

Diagramme

' Ereignisse deaktivieren Application.EnableEvents = False

Listing 290

Diagramme

' Position festlegen ' Position wird von Excel so angepasst, dass der Titel ' immer innerhalb des Diagramms bleibt. .Left = scrLeft.Value .Top = scrTop.Value

Diagramme

If .Position = xlChartElementPositionCustom Then ' Position benutzerdefiniert

Diagramme

Diagramme

2471_Excel-VBA.book Seite 502 Dienstag, 4. Dezember 2007 1:42 13

502 >> Diagrammtitel ' Wenn Abweichung zu den eingestellten Werten, dann die ' Werte der Scrollleisten auf aktuelle Position bringen If .Left scrLeft.Value Then scrLeft.Value = .Left If .Top scrTop.Value Then scrTop.Value = .Top End If End With

Diagramme

Diagramme

Diagramme

Diagramme

' Ereignisse aktivieren Application.EnableEvents = True End Sub Listing 290 (Forts.)

In der Prozedur FormatObjectLikeCell werden die gesetzten Eigenschaften der Schrift, der Ausrichtung und der Hintergrundfarbe der als Parameter übergebenen Zelle ausgelesen und die Eigenschaften des übergebenen Objektes an diese Eigenschaftswerte angepasst. Da das Interior-Objekt beispielsweise bei Datentabellen nicht vorhanden ist, wird bei einem Fehler versucht, über das neue Format-Objekt die Hintergrundfarbe zu setzen. Zurückgeliefert wird als Funktionsergebnis ein Wahrheitswert, der angibt, ob die Funktion fehlerfrei durchgelaufen ist. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_03_Title.xlsm ' Tabelle Titel ' Modul Tabelle Titel '=================================================================== Private Function FormatObjectLikeCell( _ objToFormat As Object, _ objCell As Range _ ) As Boolean Dim lngError As Long

Diagramme

Diagramme

On Error Resume Next Err.Clear With objCell.Cells(1).Characters.Font ' Schriftattribute des Objektes auf die der ' Ausgabezelle anpassen objToFormat.Font.Name = .Name objToFormat.Font.Size = .Size objToFormat.Font.Color = .Color objToFormat.Font.Italic = .Italic Listing 291

' Ausrichtung objToFormat.Orientation = objCell.Orientation ' Hintergrundfarbe anpassen lngError = Err.Number Err.Clear objToFormat.Interior.Color = objCell.Cells(1).Interior.Color If Err.Number 0 Then objToFormat.Format.Fill.BackColor.RGB = _ objCell.Cells(1).Interior.Color End If lngError = lngError Or Err.Number ' Wenn kein Fehler aufgetreten ist, True zurückgeben If lngError = 0 Then FormatObjectLikeCell = True

Diagramme

objToFormat.Font.Bold = .Bold objToFormat.Font.Strikethrough = .Strikethrough objToFormat.Font.Subscript = .Subscript objToFormat.Font.Superscript = .Superscript objToFormat.Font.Underline = .Underline End With

Diagramme

503

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 503 Dienstag, 4. Dezember 2007 1:42 13

End Function

Diagramme Diagramme

Möchten Sie in einem Diagramm eine Legende ohne Zuhilfenahme von VBA anzeigen, markieren Sie mit der Maustaste das Diagramm. Anschließend erscheinen drei neue Registerkarten mit den Namen ENTWURF, LAYOUT und FORMAT. Auf der Registerkarte LAYOUT finden Sie das Icon mit der Beschriftung LEGENDE, mit deren Hilfe Sie festlegen könen, ob und wo die Legende erscheint. Unter dem Punkt WEITERE LEGENDENOPTIONEN können Sie noch die Legendenoptionen, die Füllung, die Rahmenarten, die Rahmenfarbe und den Schatten bestimmen.

Diagramme

184 Legende

Diagramme

Listing 291 (Forts.)

504 >> Legende

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 504 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 177: Legende

In diesem Rezept wird gezeigt, wie man den Text, die Schriftattribute, die Hintergrundfarbe und die Position der Legende programmgesteuert anpassen kann. Dazu sind auf dem Tabellenblatt einige Schaltflächen und Bildlaufleisten untergebracht. 왘 Die zwei oberen Bildlaufleisten rechts neben dem Diagramm sind dafür zuständig, die Position der Legende horizontal und vertikal zu verändern. 왘 Die Bildlaufleiste darunter erlaubt es, die Legende an einige in Excel vordefinierte Positionen zu verschieben, die eingestellten X- bzw. Y- Positionen werden dann außer beim Modus BENUTZERDEFINIERT ignoriert. 왘 Nach einem Klick auf die Schaltfläche FORMAT werden die Formate der Zelle I5 auf die Legende angewendet. Ein Klick auf die Schaltfläche FORMAT löst das Click-Ereignis der Schaltfläche aus. Darin wird an die Funktion FormatObjectLikeCell als erster Parameter das anzupassende Objekt, in diesem Fall der Charttitel, übergeben. Als zweiter Parameter wird die Zelle übergeben, an deren Eigenschaften das Objekt angepasst werden soll, das ist die Zelle I5.

505

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_04_Legend.xlsm ' Tabelle Legende ' Modul Tabelle Legende '=================================================================== Private Sub cmdFormat_Click() Dim objLegend As Legend

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 505 Dienstag, 4. Dezember 2007 1:42 13

Set objLegend = Me.ChartObjects(1).Chart.Legend ' Format anpassen FormatObjectLikeCell objLegend, Me.Range("I5")

Diagramme

' Festlegen, dass Legende vorhanden ist. Me.ChartObjects(1).Chart.HasLegend = True

Die Übersetzungsfunktion TranslateXlLegendPosition findet man im Quelltext. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_04_Legend.xlsm ' Tabelle Legende ' Modul Tabelle Legende '=================================================================== Private Sub scrLegendPos_Change() makeLegendPos End Sub Private Sub scrLegendPos_Scroll() Listing 293

Diagramme Diagramme

In dieser Prozedur wird zuerst die Eigenschaft HasLegend auf Wahr gesetzt und damit sichergestellt, dass eine Legende angezeigt wird. Anschließend überprüft man die eingestellte Position der Legende. Dazu wird der Wert der Bildlaufleiste scrLegendPos an die Funktion TranslateXlLegendPosition übergeben, der zurückgelieferte Text wird in die Zelle I4 ausgegeben. Entspricht der Text dem Wort BENUTZERDEFINIERT, das heißt, die Stellung der Bildlaufleiste steht ganz rechts, ruft man die Prozedur makeUserDefinedLegendPos auf, im anderen Fall setzt man die Legendenposition auf die im Funktionsergebnis enthaltene vordefinierte Position.

Diagramme

Eine Wertänderung der Bildlaufleiste mit dem Namen scrLegendPos löst eines der zwei Ereignisse Change oder Scroll aus, wobei die Prozedur makeLegendPos aufgerufen wird.

Diagramme

Listing 292

Diagramme

End Sub

Diagramme

2471_Excel-VBA.book Seite 506 Dienstag, 4. Dezember 2007 1:42 13

506 >> Legende makeLegendPos End Sub

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Private Sub makeLegendPos() Dim strPosition As String With Me.ChartObjects(1).Chart ' Festlegen, dass Legende vorhanden ist. .HasLegend = True ' Positionsmodus bestimmen strPosition = TranslateXlLegendPosition(Me.scrLegendPos.Value) ' Positionsmodus in Zelle ausgeben Me.Range("I4") = strPosition If strPosition = "Benutzerdefiniert" Then ' Prozedur "makeUserDefinedLegendPos" aufrufen, ' wenn Modus = "Benutzerdefiniert" makeUserDefinedLegendPos Else ' Vordefinierte Legendenposition benutzen .Legend.Position = CLng(Split(strPosition, "=")(1)) End If End With End Sub Listing 293 (Forts.)

Innerhalb der Prozedur makeUserDefinedLegendPos wird noch einmal nachgeschaut, ob der Modus auf BENUTZERDEFINIERT gesetzt ist. Ist das nicht der Fall, wird das Anpassen der Position unterlassen, im anderen Fall wird die Position des Diagrammtitels auf die Werte der beiden Bildlaufleisten scrLeft und scrTop gesetzt. Da Excel die Position so anpasst, dass die Legende immer komplett sichtbar ist, müssen die Werte der zwei Bildlaufleisten nach dem Verschieben an die tatsächlich gesetzten Werte angepasst werden. Damit dabei nicht noch einmal ein Scroll- oder Change-Ereignis der Bildlaufleisten ausgelöst wird, wurde das Auslösen von Ereignissen zu Beginn der Prozedur aus- und am Ende wieder eingeschaltet. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_04_Legend.xlsm ' Tabelle Legende ' Modul Tabelle Legende '=================================================================== Listing 294

Private Sub scrTop_Change() makeUserDefinedLegendPos End Sub Private Sub scrTop_Scroll() makeUserDefinedLegendPos End Sub Private Sub makeUserDefinedLegendPos() Dim strPosition As String

Diagramme

Private Sub scrLeft_Change() makeUserDefinedLegendPos End Sub Private Sub scrLeft_Scroll() makeUserDefinedLegendPos End Sub

507

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 507 Dienstag, 4. Dezember 2007 1:42 13

' Beenden, wenn Modus "Benutzerdefiniert" If strPosition "Benutzerdefiniert" Then Exit Sub

Diagramme

' Positionsmodus bestimmen strPosition = TranslateXlLegendPosition(Me.scrLegendPos.Value)

' Position festlegen ' Position wird von Excel so angepasst, dass der Titel ' immer innerhalb des Diagramms bleibt. .Left = scrLeft.Value .Top = scrTop.Value ' Wenn Abweichung zu den eingestellten Werten, dann die ' Werte der Scrollleisten auf aktuelle Position bringen If .Left scrLeft.Value Then scrLeft.Value = .Left If .Top scrTop.Value Then scrTop.Value = .Top End With

Diagramme

With Me.ChartObjects(1).Chart.Legend

Diagramme

' Festlegen, dass Legende vorhanden ist. Me.ChartObjects(1).Chart.HasLegend = True

Diagramme

' Ereignisse deaktivieren Application.EnableEvents = False

Diagramme

Listing 294 (Forts.)

Diagramme

2471_Excel-VBA.book Seite 508 Dienstag, 4. Dezember 2007 1:42 13

508 >> Datentabelle formatieren ' Ereignisse aktivieren Application.EnableEvents = True

Diagramme

End Sub Listing 294 (Forts.)

Die Prozedur FormatObjectLikeCell wurde aus Platzmangel in diesem Rezept nicht mit abgedruckt, ist jedoch im Rezept 183 in diesem Kapitel mit einer Erklärung zu finden.

Sie können innerhalb eines Diagramms wahlweise die zugehörige Datentabelle einoder ausblenden. Zudem lässt sich auswählen, ob in der Datentabelle ein Legendensymbol angezeigt werden soll oder nicht. Möchte man in einem Diagramm eine Datentabelle ohne Zuhilfenahme von VBA anzeigen oder im Aussehen verändern, wird zunächst das Diagramm mit der Maustaste markiert. Daraufhin erscheinen drei neue Registerkarten mit Namen ENTWURF, LAYOUT und FORMAT. Auf der Registerkarte LAYOUT befindet sich das Symbol mit der Beschriftung DATENTABELLE, mit deren Hilfe die Datentabelle angepasst wird.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

185 Datentabelle formatieren

Abbildung 178: Datentabelle

In diesem Rezept wird gezeigt, wie man den Text, die Schriftattribute und die Rahmen der Datentabelle programmgesteuert anpassen kann. Dazu sind auf dem Tabellenblatt einige Schaltflächen und Bildlaufleisten untergebracht. 왘 Mit einem Kontrollkästchen können Sie festlegen, ob überhaupt eine Datentabelle angezeigt wird oder nicht. 왘 Ein weiteres Kontrollkästchen entscheidet darüber, ob ein horizontaler Rahmen zur Gliederung angezeigt wird 왘 Das dritte Kontrollkästchen ist dafür zuständig, die Anzeige eines vertikalen Rahmens zur Gliederung festzulegen. 왘 Mit einem weiteren Kontrollkästchen wird festgelegt, ob ein kompletter Rahmen um die Datentabelle angezeigt wird oder nicht. 왘 Das letzte Kontrollkästchen legt fest, oder die Legendensymbole in der Tabelle dargestellt werden.

Diagramme

509

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 509 Dienstag, 4. Dezember 2007 1:42 13

Listing 295

Diagramme Diagramme

Private Sub chkHorizontal_Click() ChangeOthers End Sub Private Sub chkVertical_Click() ChangeOthers End Sub Private Sub cmdOutline_Click() ChangeOthers End Sub Private Sub chkLegendSymbols_Click() ChangeOthers End Sub

Diagramme

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_05_DataTable.xlsm ' Tabelle Datentabelle ' Modul Tabelle Datentabelle '===================================================================

Diagramme

Eine Klick auf die Kontrollkästchen chkHorizontal, chkVertical, chkLegendSymbols oder auf die Schaltfläche cmdOutline ruft in der entsprechenden Ereignisprozedur die Prozedur ChangeOthers zum Anpassen verschiedener Eigenschaften wie Rahmenlinien oder Legendensymbole auf.

Diagramme

왘 Nach einem Klick auf die Schaltfläche FORMAT werden die Formate der Zelle E3 auf die Datentabelle angewendet.

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 510 Dienstag, 4. Dezember 2007 1:42 13

510 >> Datentabelle formatieren

Die Ereignisprozedur chkDataTable_Click, welche nach einem Klick auf das Kontrollkästchen chkDataTable ausgeführt wird, blendet je nach Zustand des Kontrollkästchens die Datentabelle ein oder aus. Dazu wird die Eigenschaft HasDataTable des Diagramms benutzt. Anschließend wird die Prozedur cmdFormat_Click aufgerufen, welche sich der Funktion FormatObjectLikeCell bedient, um die Texteigenschaften und den Hintergrund anzupassen. Die danach aufgerufene Prozedur ChangeFill ist für das Setzen der restlichen Eigenschaften wie Rahmenlinien oder Legendensymbole zuständig. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_05_DataTable.xlsm ' Tabelle Datentabelle ' Modul Tabelle Datentabelle '===================================================================

Diagramme

Private Sub chkDataTable_Click() ' Datentabelle abhängig vom Zustand ein- bzw. ausblenden Me.ChartObjects(1).Chart.HasDataTable = chkDataTable.Value cmdFormat_Click ChangeOthers

Diagramme

Diagramme

Diagramme

Diagramme

End Sub Listing 296

Ein Klick auf die Schaltfläche FORMAT löst das Click-Ereignis der Schaltfläche aus. Darin wird an die Funktion FormatObjectLikeCell als erster Parameter das anzupassende Objekt, in diesem Fall die Datentabelle, übergeben. Als zweiter Parameter wird die Zelle übergeben, an deren Eigenschaften das Objekt angepasst werden soll, das ist die Zelle E3. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_05_DataTable.xlsm ' Tabelle Datentabelle ' Modul Tabelle Datentabelle '=================================================================== Private Sub cmdFormat_Click() ' Verlassen, wenn keine Datentabelle vorhanden If Me.ChartObjects(1).Chart.HasDataTable = False Then Exit Sub Listing 297

>> Diagramme

511

FormatObjectLikeCell _ Me.ChartObjects(1).Chart.DataTable, Me.Range("E3")

Diagramme

2471_Excel-VBA.book Seite 511 Dienstag, 4. Dezember 2007 1:42 13

Anschließend wird der Wert des Kontrollkästchens chkHorizontal der Eigenschaft HasBorderHorizontal, der Wert des Kontrollkästchens chkLegendSymbols der Eigenschaft ShowLegendKey, der Wert des Kontrollkästchens chkVertical der Eigenschaft HasBorderVertical und der Wert des Kontrollkästchens cmdOutline der Eigenschaft HasBorderOutline zugewiesen. Mit diesen Zuweisungen wird festgelegt, ob die Datentabelle eine horizontale Rahmenlinie besitzt, Legendensymbole erscheinen und ob eine vertikale und eine Rahmenlinie zur Gliederung angezeigt werden. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_DataTable.xlsm ' Tabelle Datentabelle ' Modul Tabelle Datentabelle '===================================================================

Diagramme

In der Prozedur ChangeOthers wird zu Beginn ermittelt, ob das Diagramm eine Datentabelle besitzt, ist das nicht der Fall, wird die Prozedur verlassen. Im anderen Fall wird eine Objektvariable angelegt, die eine Referenz auf die vorhandene Datentabelle aufnimmt.

Diagramme

Die Prozedur FormatObjectLikeCell wurde aus Platzmangel in diesem Rezept nicht mit abgedruckt, ist jedoch im Rezept 183 in diesem Kapitel mit einer Erklärung zu finden.

Diagramme

Listing 297 (Forts.)

Diagramme

End Sub

' Verlassen, wenn keine Datentabelle vorhanden If Me.ChartObjects(1).Chart.HasDataTable = False Then Exit Sub

Diagramme

Private Sub ChangeOthers() Dim objDataTable As DataTable

' Rahmenlinie Horizontal objDataTable.HasBorderHorizontal = chkHorizontal.Value ' Legendensymbole in Datentabelle objDataTable.ShowLegendKey = chkLegendSymbols.Value

Diagramme

Set objDataTable = Me.ChartObjects(1).Chart.DataTable

Listing 298

Diagramme

' Rahmenlinie Vertikal objDataTable.HasBorderVertical = chkVertical.Value

Diagramme

2471_Excel-VBA.book Seite 512 Dienstag, 4. Dezember 2007 1:42 13

512 >> Datenreihen

' Datentabelle Gliederung objDataTable.HasBorderOutline = cmdOutline.Value

Listing 298 (Forts.)

186 Datenreihen Datenreihen (SERIEN) sind die Grundlage eines jeden Diagramms, sie können auf die unterschiedlichsten Arten dargestellt werden, beispielsweise in Form von Säulen, Balken, Ringen, Blasen, Linien usw. Aber auch das Aussehen lässt sich auf vielerlei Arten anpassen, beispielsweise können bei einem Liniendiagramm die Linienbreite, der Linientyp, das Linienmuster, die Farbe und die Transparenz verändert werden.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

End Sub

Abbildung 179: Datenreihen

In diesem Rezept werden bei einem Liniendiagramm die Linieneigenschaften einer Datenreihe (Serie) angepasst. Angesprochen werden die Datenreihen über das Objekt: SeriesCollection. Zum Anpassen des Aussehens wird die in Excel 2007 neu hinzugekommene Objektklasse ChartFormat benutzt. Die Steuerelemente befinden sich in den ersten 6 Zeilen. Die verknüpften Zellen befinden sich im Bereich C1, B2:B4, C6.

왘 Die 3 Drehfelder in Zeile 5 sind für Linienfarbe zuständig, die den Rot-, Grünund Blauwert einer RGB-Farbe festlegen. Die verknüpften Zellen für die Linienfarbe befinden sich im Bereich C5:E5. 왘 Für die Transparenz ist die Bildlaufleiste in Zeile 6 zuständig. Der Wertebereich der Bildlaufleiste geht von 0 bis 1000, für die Transparenz selbst wird dieser Wert skaliert. Als Eigenschaftswerte für die Transparenz sind Werte zwischen 0 und 1 zulässig. Auch in diesem Rezept werden Werte benutzt, die einen Index in eine Auflistung von Konstanten darstellen. Die Funktionen, die mit dem Präfix Translate beginnen, liefern den Konstantennamen und den Wert des übergebenen Index. Daraus kann man sich bei Bedarf mit Hilfe der Split-Funktion den Wert der Konstanten extrahieren. Die drei Übersetzungsfunktionen TranslateLineDashStyle, TranslateLineStyle, TranslatePatternType sind nicht mit abgedruckt, diese findet man aber im Quelltext. Damit nicht für jede Bildlaufleiste und jedes Drehfeld eine eigene Ereignisprozedur angelegt werden muss, überwacht man deren verknüpfte Zellen. Das spart einiges an Code, denn bei Bildlaufleisten müssen zwei verschiedene Ereignisse überwacht werden, um auf eine vorgenommene Änderung zu reagieren. Das Bewegen des Balkens mit der Maus löst das Scroll-Ereignis des Steuerelementes aus, das Change-Ereignis wird jedoch nicht getriggert. Das Ändern des Wertes durch Klick auf die Pfeile an den Enden löst das Change-Ereignis aus, das Scroll-Ereignis wird aber nicht getriggert. Zum Überwachen legt man also in einer beliebigen Zelle eine Formel an, die unsichtbar sein kann. Wir haben dafür die Funktion ZÄHLENWENN benutzt, welche den zu überwachenden Bereich als Argument zugewiesen bekommt. Eine Änderung in dem Bereich, sei es durch Handeingabe oder durch die Manipulation der Bildlaufleisten, löst anschließend das Worksheet_Calculate-Ereignis aus, das Change-Ereignis des Tabellenblattes würde hingegen nur durch eine Handeingabe getriggert. Die einzige Aufgabe des Worksheet_Calculate-Ereignisses besteht darin, die Prozedur ChangeStyle aufzurufen.

Diagramme

왘 Die Bildlaufleiste in Zeile 4 ist für den Typ der Linie in Bezug auf den Linienrahmen zuständig. Der Wert der Bildlaufleiste ist ein Index in die Aufzählung (Enum) XlLineStyle von Konstanten.

Diagramme

왘 Die Bildlaufleiste in Zeile 3 ist für den Typ der Linie in Bezug auf die Dicke, das heißt die Abfolge von Linien in der Y-Richtung zuständig. Der Wert der Bildlaufleiste ist ein Index in die Aufzählung (Enum) MsoLineStyle von Konstanten.

Diagramme

왘 Die Bildlaufleiste in Zeile 2 ist für den Linienstil in Bezug auf die Folge von Punkten, bzw. Strichen in X-Richtung zuständig. Der Wert der Bildlaufleiste ist ein Index in die Aufzählung (Enum) MsoLineDashStyle von Konstanten.

Diagramme

왘 Die erste Bildlaufleiste in der Zeile 1 gibt die Linienbreite an.

Diagramme

513

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 513 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Die Prozedur ChangeStyle hat die Aufgabe, die gesetzten Werte aus dem Tabellenblatt auszulesen und die Diagrammeigenschaften anzupassen. Während der Laufzeit wird

2471_Excel-VBA.book Seite 514 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

immer wieder vor dem Setzen eines Eigenschaftswertes die nachfolgende Aktion als Meldung in der Statusleiste ausgegeben (Application.StatusBar="Aktion").

Diagramme

514 >> Datenreihen

Zu Beginn der Prozedur werden verschiedene Objektvariablen definiert, die das einzige Chart-Objekt des Tabellenblattes und die darin enthaltene erste SeriesCollection aufnehmen. Die Objektvariable objLineFormat bekommt eine Referenz auf das in der Objektklasse ChartFormat enthaltene Line-Objekt der SeriesCollection. Über die Eigenschaften dieses Objektes können die Linieneigenschaften festgelegt und auch ausgelesen werden.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Dass das Schreiben auf das Tabellenblatt nicht versehentlich ein Ereignis auslöst, wird durch die Anweisung Application.EnableEvents = False verhindert. Danach werden die zu setzenden Linieneigenschaften der Datenreihe aus dem Tabellenblatt ausgelesen. Außerdem werden Objektvariablen vom Typ Range angelegt, die den Bereich im Tabellenblatt darstellen, in die später die über Konstanten definierten Stile im Klartext ausgegeben werden. Nun kann man darangehen, die Linieneigenschaften der Datenreihe anzupassen, dabei wird die in Excel 2007 neu hinzugekommene Objektklasse ChartFormat verwendet. Nacheinander werden nun die Linieneigenschaften gesetzt und die Information über den gewählten Konstantennamen und dessen Wert in das Tabellenblatt geschrieben. Leider funktioniert es in der aktuell vorliegenden Excel-Version nicht, das Muster der Linie auf den Defaultwert msoPatternMixed zu setzen, so dass man zum Zurücksetzen des Linienmusters den Umweg über die LineStyle-Eigenschaft des Border-Objektes gehen muss. Diese Eigenschaft wird dazu auf den Wert 1 (xlContinuous) gesetzt. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_06_LineStyle.xlsm ' Tabelle Linien ' Modul Tabelle Linien '=================================================================== Private Sub Worksheet_Calculate() ChangeStyle End Sub Public Dim Dim Dim Dim Dim Dim Dim

Sub ChangeStyle() strOutput objChart objLineFormat objSerCol lngLinePattern rngLinePatternOut lngLineStyle

Listing 299

As As As As As As As

String Object Object Object Long Range Long

As As As As As As As

Range Long Range Double Long Double Long

Application.EnableEvents = False ' Objektvariablen definieren Set objChart = Me.ChartObjects(1).Chart Set objSerCol = objChart.SeriesCollection(1) Set objLineFormat = objSerCol.Format.Line ' Linienmuster lngLinePattern = Me.Range("B4") Set rngLinePatternOut = Me.Range("C4") ' Mehrfachlinien etc. lngLineStyle = Me.Range("B2") Set rngLineStyleOut = Me.Range("C2")

Diagramme

rngLineStyleOut lngLineDash rngLineDashOut dblLineWidth lngLineColor dblLineTransparency i

Diagramme

Dim Dim Dim Dim Dim Dim Dim

515

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 515 Dienstag, 4. Dezember 2007 1:42 13

' Linienbreite dblLineWidth = Me.Range("C1")

Diagramme

' Linienstil (Punkt/Strich) lngLineDash = Me.Range("B3") Set rngLineDashOut = Me.Range("C3")

' Transparenz Linie dblLineTransparency = Me.Range("C6")

Diagramme

' Linienfarbe lngLineColor = RGB( _ Me.Range("C5"), Me.Range("D5"), Me.Range("E5"))

Listing 299 (Forts.)

Diagramme

' Linienmuster Application.StatusBar = "Linienmuster anpassen" strOutput = TranslatePatternType(lngLinePattern) If strOutput "" Then .Pattern = CLng(Split(strOutput, "=")(1)) rngLinePatternOut = strOutput Else

Diagramme

With objLineFormat

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 516 Dienstag, 4. Dezember 2007 1:42 13

516 >> Datenreihen ' Pattern auf msoPatternMixed setzen funktioniert ' nicht, deshalb über die Borders.LineStyle-Eigenschaft objSerCol.Border.LineStyle = xlContinuous rngLinePatternOut = ".Border.LineStyle = xlContinuous" End If ' Mehrfachlinien etc. Application.StatusBar = "Linienstil anpassen" strOutput = TranslateLineStyle(lngLineStyle) If strOutput "" Then .Style = CLng(Split(strOutput, "=")(1)) rngLineStyleOut = strOutput End If ' Linienstil (Punkt/Strich) Application.StatusBar = "Linienart anpassen" strOutput = TranslateLineDashStyle(lngLineDash) If strOutput "" Then .DashStyle = CLng(Split(strOutput, "=")(1)) rngLineDashOut = strOutput End If ' Linienstärke Application.StatusBar = "Liniendicke anpassen" .Weight = dblLineWidth ' Linienfarbe Application.StatusBar = "Linienfarbe anpassen" .ForeColor.RGB = lngLineColor

Diagramme

' Linientransparenz Application.StatusBar = "Linientransparenz anpassen" .Transparency = dblLineTransparency End With

Diagramme

Diagramme

Application.StatusBar = False Application.EnableEvents = True End Sub Listing 299 (Forts.)

517

187 Datenpunkte

Diagramme

Diagramme

Diagramme

Bei Kreis- oder Säulendiagrammen möchte man oft die einzelnen Datenpunkte individuell gestalten, bei Kreisdiagrammen sind das beispielsweise die einzelnen Kuchenstücke, die modifiziert werden sollen. Es reicht dabei aber nicht, die Datenreihen als Ganzes anzusprechen, man möchte ja schließlich die einzelnen Datenpunkte individuell formatieren, und diese sind wiederum untergeordnete Objekte der Datenreihe.

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 517 Dienstag, 4. Dezember 2007 1:42 13

왘 Die Rahmenfarbe wählt man dabei mit Hilfe der Rnd-Funktion zufällig aus, der Wert stellt einen Index in die Farbtabelle (ColorIndex) dar. In das Tabellenblatt

Diagramme

Zu Beginn der Click-Ereignisprozedur der Schaltfläche cmdChange wird eine Objektvariable angelegt, die eine Referenz auf das SeriesCollection-Objekt des ersten Diagramms des Tabellenblattes aufnimmt. Anschließend wird mit Randomize der Zufallszahlengenerator initialisiert. Danach werden in einer Schleife alle Datenpunkte der ersten Serie durchlaufen. Darin werden über das Border-Objekt nun die Farbe, die Linienart und die Liniendicke für den Rahmen des Datenpunkts gesetzt.

Diagramme

In diesem Rezept werden bei jedem Klick auf die Schaltfläche mit der Beschriftung »Zufallsgenerator« die Attribute Rahmenfarbe, Rahmenlinienart, Rahmenliniendicke, weiterhin die Hintergrundfarbe, das Muster und die Farbe der Füllung für jeden Datenpunkt zufällig ausgewählt, auf dem Tabellenblatt ausgegeben und im Diagramm gesetzt.

Diagramme

Abbildung 180: Datenpunkte

518 >> Datenpunkte

Diagramme

왘 Die Liniendicke des Datenpunkts wird zufällig ausgewählt. Der Wert dient als Index in eine Aufzählung von Konstanten. Der Name der Aufzählung ist XlBorderWeight. Die Übersetzungsfunktion TranslateXlBorderWeight liefert den Konstantennamen mitsamt dem zugehörigen Wert als Text. Dieser wird komplett in eine Zelle des Tabellenblattes ausgegeben. Vor dem Zuweisen wird noch mit Hilfe der Split-Funktion der Wert der Konstanten aus dem gelieferten Text extrahiert.

Diagramme

왘 Die Linienart des Datenpunkts wird zufällig ausgewählt. Der Wert dient als Index in eine Aufzählung von Konstanten. Der Namen der Aufzählung ist XlLineStyle. Die Übersetzungsfunktion TranslateXlLineStyle liefert den Konstantennamen mitsamt dem zugehörigen Wert als Text. Dieser wird komplett in eine Zelle des Tabellenblattes ausgegeben. Vor dem Zuweisen wird noch mit Hilfe der SplitFunktion der Wert der Konstanten aus dem gelieferten Text extrahiert.

Diagramme

왘 Über den Innenbereich eines Objekts (Interior) kann man die Hintergrundfarbe einstellen. Dazu wird wiederum ein Index in die Farbtabelle benutzt (ColorIndex), dieser wird mit Hilfe der Rnd-Funktion zufällig ausgewählt. In das Tabellenblatt wird anschließend die Farbe als Wert und als Hintergrundfarbe der Ausgabezelle ausgegeben. Danach wird erst die Hintergrundfarbe des jeweiligen Datenpunktes angepasst.

Diagramme

wird anschließend die Rahmenfarbe als numerischer Wert und als Hintergrundfarbe der gleichen Zelle ausgegeben.

왘 Anschließend wird das Muster (Pattern) gesetzt. Dazu wird mit Hilfe der RndFunktion ein Wert zufällig ausgewählt, der als Index in die Auflistung von Konstanten mit dem Namen XlPattern dient. Der von den Funktionen mit dem Präfix TranslateXlPattern gelieferte Text wird in das Tabellenblatt ausgegeben, mit Hilfe der Split-Funktion in den Wert der Konstanten umgewandelt und der Eigenschaft Pattern des Innenbereiches (Interior) zugewiesen.

Diagramme

Diagramme

2471_Excel-VBA.book Seite 518 Dienstag, 4. Dezember 2007 1:42 13

왘 Zum Schluss wird die Musterfarbe mit Hilfe der Rnd-Funktion zufällig ausgewählt, der Wert stellt einen Index in die Farbtabelle (ColorIndex) dar. In das Tabellenblatt wird anschließend die Rahmenfarbe als numerischer Wert und als Hintergrundfarbe der gleichen Zelle ausgegeben. Um den Datenpunkt anzupassen, wird der Index der Eigenschaft PatternColorIndex des Innenbereiches (Interior) zugewiesen.

Diagramme

Diagramme

Die Übersetzungsfunktionen TranslateXlBorderWeight, TranslateXlLineStyle und TranslateXlPattern sind nicht mit abgedruckt, diese findet man aber im Quelltext. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_07_DataPoints.xlsm ' Tabelle Datenpunkte ' Modul Tabelle Datenpunkte '=================================================================== Listing 300

Private Sub cmdChange_Click() Dim i As Long Dim lngColorBorder As Long Dim lngColorBack As Long Dim lngLineStyle As Long Dim lngLineWidth As Long Dim lngPattern As Long Dim lngPatternColor As Long Dim objSeries As SeriesCollection Dim objPoint As Object

519

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 519 Dienstag, 4. Dezember 2007 1:42 13

Randomize For Each objPoint In objSeries(1).Points

Diagramme

Set objSeries = Me.ChartObjects(1).Chart.SeriesCollection

' Liniendicke lngLineWidth = Int(4 * Rnd + 1) Me.Cells(4, i + 4) = _ TranslateXlBorderWeight(lngLineWidth) .Weight = CLng( _ Split(TranslateXlBorderWeight(lngLineWidth), "=")(1)) End With ' Hintergrundfarbe lngColorBack = Int(57 * Rnd) Me.Cells(5, i + 4) = lngColorBack Listing 300 (Forts.)

Diagramme

' Linienart lngLineStyle = Int(5 * Rnd + 1) Me.Cells(3, i + 4) = TranslateXlLineStyle(lngLineStyle) .LineStyle = CLng( _ Split(TranslateXlLineStyle(lngLineStyle), "=")(1))

Diagramme

' Rahmenfarbe lngColorBorder = Int((56 + 1) * Rnd) Me.Cells(2, i + 4) = lngColorBorder Me.Cells(2, i + 4).Interior.ColorIndex = lngColorBorder .ColorIndex = lngColorBorder

Diagramme

With .Border ' RAHMEN

Diagramme

i = i + 1

Diagramme

With objPoint ' DATENPUNKT

520 >> Achsen, Gitternetzlinien Me.Cells(5, i + 4).Interior.ColorIndex = lngColorBack .Interior.ColorIndex = lngColorBack ' Muster lngPattern = Int(19 * Rnd + 1) Me.Cells(6, i + 4) = TranslateXlPattern(lngPattern) .Interior.Pattern = CLng( _ Split(TranslateXlPattern(lngPattern), "=")(1))

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 520 Dienstag, 4. Dezember 2007 1:42 13

' Musterfarbe lngPatternColor = Int(57 * Rnd) Me.Cells(7, i + 4) = lngPatternColor Me.Cells(7, i + 4).Interior.ColorIndex = lngPatternColor .Interior.PatternColorIndex = lngPatternColor End With

Diagramme

Next End Sub Listing 300 (Forts.)

Die Achsenbeschriftungen können vielfältig formatiert werden, das Ein- und Ausblenden von Gitternetzlinien ist möglich. Die Skalierung kann an die eigenen Bedürfnisse angepasst werden, auch der Schnittpunkt der X- mit der Y-Achse lässt sich verändern. Möchte man in einem Diagramm die Achsen oder die Gitternetzlinien ohne Zuhilfenahme von VBA modifizieren, markiert man mit der Maustaste das Diagramm. Danach erscheinen drei neue Registerkarten mit Namen ENTWURF, LAYOUT und FORMAT. Auf der Registerkarte LAYOUT findet man die zwei Icons mit der Beschriftung ACHSEN und GITTERNETZLINIEN, mit deren Hilfe man alle möglichen Eigenschaften festlegen kann.

Diagramme

Diagramme

In einem Diagramm wird die vertikale Achse normalerweise zum Darstellen von Werten verwendet, die horizontale Achse enthält die Rubriken. Bei der Darstellung mehrerer Datenreihen ist es auch möglich, eine Sekundärachse mit einer anderen Skalierung zu verwenden und Datenreihen darauf abzubilden. Werden ausschließlich positive Werte dargestellt, kann die Größenachse sogar eine logarithmische Skalierung annehmen.

Diagramme

Diagramme

188 Achsen, Gitternetzlinien

521

왘 Die zwei Optionsschaltflächen in Reihe 6 entscheiden darüber, ob die Primär- oder Sekundärachse mit den darunter liegenden Steuerelementen bearbeitet werden kann. 왘 Mit der Bildlaufleiste in Zeile 8 wird der Minimumwert der gewählten Werteachse gesetzt. Möglich ist auch das Setzen auf eine automatische Wahl (Bildlaufleistenwert 0). 왘 Mit der Bildlaufleiste in Zeile 9 wird der Maximumwert der gewählten Werteachse gesetzt. Möglich ist auch das Setzen auf eine automatische Wahl (Bildlaufleistenwert 0). 왘 Mit der Bildlaufleiste in Zeile 10 wird das Hauptintervall festgelegt. Möglich ist auch das Setzen auf eine automatische Wahl (Bildlaufleistenwert 0).

Diagramme

Die Steuerelemente für die Werteachse Y befinden sich in den Zeilen 6 bis 19. Die verknüpften Zellen der Bildlaufleisten für die Y-Achse finden Sie im Bereich D8:D13.

Diagramme

In diesem Rezept werden die Eigenschaften der primären und sekundären Werteachse in Y-Richtung sowie die Eigenschaften der Rubrikenachse in der X-Richtung angepasst.

Diagramme

Abbildung 181: Achsen, Gitternetzlinien

Diagramme

Diagramme

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 521 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

왘 Mit der Bildlaufleiste in Zeile 11 wird das Hilfsintervall festgelegt. Möglich ist auch das Setzen auf eine automatische Wahl (Bildlaufleistenwert 0).

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 522 Dienstag, 4. Dezember 2007 1:42 13

522 >> Achsen, Gitternetzlinien

왘 Mit der Bildlaufleiste in Zeile 12 kann man festlegen, wo die Rubrikenachse die Werteachse schneidet, wenn der Modus auf Benutzerdefiniert (xlCustom) steht. 왘 Mit der Bildlaufleiste in Zeile 13 kann man festlegen, wo die Rubrikenachse die Werteachse schneidet, dabei wird ein vorgegebener Modus eingestellt. Der Wert der Bildlaufleiste gilt als Index in eine Liste von möglichen Konstanten. Der von den Funktionen mit dem Präfix TranslateAxis gelieferte Text wird in das Tabellenblatt ausgegeben. 왘 Das Kontrollkästchen in Zeile 14 entscheidet darüber, welche Serie auf der Primär- und welche auf der Sekundärachse abgebildet wird. 왘 Mit dem Kontrollkästchen in Zeile 15 wird festgelegt, ob eine logarithmische Skalierung verwendet wird. 왘 Das nächste Kontrollkästchen legt fest, ob die Größen in umgekehrter Reihenfolge dargestellt werden.

Diagramme

Diagramme

왘 Das folgende entscheidet darüber, ob das Hauptgitternetz angezeigt wird. 왘 Mit dem Kontrollkästchen in Zeile 18 wird festgelegt, ob das Hilfsgitternetz angezeigt wird. 왘 Mit der Schaltfläche in Zeile 19 wird das Aussehen der Beschriftung der aktuell über die Optionsschaltflächen gewählten Werteachse auf die Eigenschaften der nebenstehenden Zellen gebracht. Die Steuerelemente für die Rubrikenachse X befinden sich in den Zeilen 20 bis 25. Die verknüpften Zellen der Bildlaufleisten für die X-Achse befinden sich im Bereich D22:D24. 왘 Das Kontrollkästchen in Zeile 20 entscheidet darüber, ob die Y-Achse zwischen den Rubriken schneidet.

Diagramme

왘 Das Kontrollkästchen in Zeile 21 legt fest, ob die Rubriken in umgekehrter Reihenfolge angezeigt werden. 왘 Das Kontrollkästchen in Zeile 22 legt die Rubrikenzahl zwischen den Teilstrichbeschriftungen fest. 왘 Das Kontrollkästchen in Zeile 23 legt die Rubrikenanzahl zwischen den Teilstrichbeschriftungen fest.

Diagramme

Diagramme

왘 Das Kontrollkästchen in Zeile 24 legt fest, bei welcher Rubrikennummer die Größenachse (Y) schneidet. 왘 Mit der Schaltfläche in Zeile 25 wird das Aussehen der Beschriftung der Rubrikenachse auf die Eigenschaften der nebenstehenden Zellen gebracht. Damit nicht für jede Bildlaufleiste eine eigene Ereignisprozedur angelegt werden muss, überwacht man deren verknüpfte Zellen. Das spart einiges an Code, denn bei Bildlaufleisten müssen zwei verschiedene Ereignisse überwacht werden, um auf eine vorgenommene Änderung zu reagieren. Das Bewegen des Balkens mit der Maus löst das Scroll-Ereignis des Steuerelementes aus, das Change-Ereignis wird jedoch nicht

Zum Überwachen legt man also in einer beliebigen Zelle eine Formel an, die unsichtbar sein kann. Ich habe dafür die Funktion ZÄHLENWENN benutzt, welche den zu überwachenden Bereich als Argument zugewiesen bekommt. Eine Änderung in dem Bereich, sei es durch Handeingabe oder durch die Manipulation der Bildlaufleisten, löst anschließend das Worksheet_Calculate-Ereignis aus, das Change-Ereignis des Tabellenblattes würde hingegen nur durch eine Handeingabe getriggert. Die einzige Aufgabe des Worksheet_Calculate-Ereignis besteht darin, die Prozedur SetActXSettings und SetActYSettings aufzurufen. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '=================================================================== Private Sub Worksheet_Calculate() SetActYSettings SetActXSettings End Sub

Diagramme

getriggert. Das Ändern des Wertes durch Klick auf die Pfeile an den Enden löst das Change-Ereignis aus, das Scroll-Ereignis wird aber nicht ausgelöst.

Diagramme

523

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 523 Dienstag, 4. Dezember 2007 1:42 13

왘 Besitzt die Bildlaufleiste scrMaxY, welche den Maximalwert der gewählten Achse angibt, einen aktuellen Wert von Null, wurde Automatik gewählt, was als Information auf dem Tabellenblatt ausgegeben wird. Zudem wird die MaximumScaleIsAuto-Eigenschaft auf Wahr gesetzt. Bei einem Bildlaufleistenwert ungleich Null wird auch dieser Wert ausgegeben und die MaximumScale-Eigenschaft auf diesen Wert gesetzt. 왘 Bei aktuellen Werten der Bildlaufleiste scrMajorUnit (Hauptintervall) von Null wird die Information AUTOMATIK auf dem Tabellenblatt ausgegeben, außerdem wird die Eigenschaft MajorUnitIsAuto auf Wahr gesetzt. Bei einem Bildlaufleisten-

Diagramme Diagramme

왘 Besitzt die Bildlaufleiste scrMinY, welche den Minimalwert der gewählten Achse angibt, einen aktuellen Wert von Null, wurde Automatik gewählt, was als Information auf dem Tabellenblatt ausgegeben wird. Zudem wird die MinimumScaleIsAuto-Eigenschaft auf Wahr gesetzt. Bei einem Bildlaufleistenwert ungleich Null wird auch dieser Wert ausgegeben und die MinimumScale-Eigenschaft auf diesen Wert gesetzt.

Diagramme

In der Prozedur SetActYSettings wird zu Beginn die Objektvariable objAxes angelegt, die einen Objektverweis auf die Achsen erhält. Anschließend wird darüber die Rubrikenachse Y angesprochen, und zwar die, welche über Optionsschaltfläche optSecundary festgelegt wurde. Alle folgenden Operationen betreffen also entweder die Primär- oder die Sekundärachse.

Diagramme

Listing 301

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 524 Dienstag, 4. Dezember 2007 1:42 13

524 >> Achsen, Gitternetzlinien

wert ungleich Null wird dieser Wert ausgegeben und die MajorUnit-Eigenschaft auf diesen Wert gesetzt. 왘 Bei aktuellen Werten der Bildlaufleiste scrMinorUnit (Hilfsintervall) von Null wird die Information AUTOMATIK auf dem Tabellenblatt ausgegeben, außerdem wird die Eigenschaft MinorUnitIsAuto auf Wahr gesetzt. Bei einem Bildlaufleistenwert ungleich Null wird dieser Werte ausgegeben und die MinorUnit-Eigenschaft auf diesen Wert gesetzt. 왘 Ist der Wert des Kontrollkästchens chkLog auf Wahr, wird die Eigenschaft scaleType auf xlLogarithmic gesetzt, ansonsten auf xlLinear. Auch die Information über eine gesetzte oder ungesetzte Logarithmische Skalierung wird ausgegeben. 왘 Ist im Kontrollkästchen chkReversePlotOrderY ein Haken gesetzt, wird die Eigenschaft ReversePlotOrder auf Wahr, ansonsten auf Falsch gesetzt, wobei die Information über die Skalierung in umgekehrter Reihenfolge auf dem Tabellenblatt ausgegeben wird. 왘 Ist das Kontrollkästchen chkMajorGridlines auf Wahr gesetzt, wird die Eigenschaft HasMajorGridlines auf Wahr, ansonsten auf Falsch gesetzt. Auch diese Information wird ausgegeben, zudem wird noch die Farbe der Linie auf die Farbe der Teilstrichbeschriftungen und die Dicke der Linie auf 4 gesetzt, falls diese sichtbar ist. 왘 Ist das Kontrollkästchen chkMinorGridlines auf Wahr gesetzt, wird die Eigenschaft HasMinorGridlines auf Wahr, ansonsten auf Falsch gesetzt. Auch diese Information wird ausgegeben, zudem wird noch die Dicke der Linie auf 1 gesetzt, falls diese sichtbar ist. 왘 Die Bildlaufleiste scrYCrossesAt legt fest, wo die X-Achse auf der gewählten YAchse schneidet. Dieser Wert wird ausgegeben und die Eigenschaft CrossesAt auf diesen Wert gesetzt, wenn der Modus auf xlCustom steht. 왘 Die Bildlaufleiste scrCrossModus gibt den Modus an, wo die X-Achse auf der gewählten Y-Achse schneidet. Der Wert der Bildlaufleiste ist ein Index in eine Reihe von möglichen vordefinierten Konstanten. Dieser Index wird mit der Funktion TranslateAxis in einen Text übersetzt, der den Konstantennamen, ein Gleichheitszeichen und den Wert selbst enthält. Daraus wird der Wert extrahiert und an die Crosses-Eigenschaft übergeben. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '===================================================================

Diagramme

Private Sub SetActYSettings() Dim i As Long Dim lngModus As Long Listing 302

With objAxes(xlValue, lngModus) If scrMinY.Value = 0 Then ' Gewählte Y-Achse Minimum auf Automatik ' ausgeben Me.Cells(8, 5 + i).Value = "xlAutomatic" ' Setzen .MinimumScaleIsAuto = True Else ' Gewählte Y-Achse Minimum auf gesetzten Wert ' ausgeben Me.Cells(8, 5 + i).Value = scrMinY.Value ' Setzen .MinimumScale = scrMinY.Value End If If scrMaxY.Value = 0 Then ' Gewählte Y-Achse Maximum auf Automatik ' ausgeben Me.Cells(9, 5 + i).Value = "xlAutomatic" ' Setzen .MaximumScaleIsAuto = True Else ' Gewählte Y-Achse Maximum auf gesetzten Wert ' ausgeben Me.Cells(9, 5 + i).Value = scrMaxY.Value ' Setzen .MaximumScale = scrMaxY.Value End If If scrMajorUnit.Value = 0 Then ' Gewählte Y-Achse Hauptintervall auf Automatik ' ausgeben Listing 302 (Forts.)

Diagramme Diagramme

' Ereignisse ausschalten Application.EnableEvents = False

Diagramme

' Gewählte Y-Achse (Primär/Sekundär) If optSecundary Then i = 1 lngModus = IIf(optSecundary, xlSecondary, xlPrimary)

Diagramme

On Error GoTo Fehlerbehandlung Set objChart = Me.ChartObjects(1).Chart Set objAxes = objChart.Axes

Diagramme

As Chart As Axes

Diagramme

Dim objChart Dim objAxes

525

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 525 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 526 Dienstag, 4. Dezember 2007 1:42 13

526 >> Achsen, Gitternetzlinien Me.Cells(10, 5 + i).Value = "xlAutomatic" ' Setzen .MajorUnitIsAuto = True Else ' Gewählte Y-Achse Hauptintervall auf gesetzten Wert ' ausgeben Me.Cells(10, 5 + i).Value = scrMajorUnit.Value ' Setzen .MajorUnit = scrMajorUnit.Value End If If scrMinorUnit.Value = 0 Then ' Gewählte Y-Achse Hilfsintervall auf Automatik ' ausgeben Me.Cells(11, 5 + i).Value = "xlAutomatic" ' Setzen .MinorUnitIsAuto = True Else ' Gewählte Y-Achse Hilfsintervall auf gesetzten Wert ' ausgeben Me.Cells(11, 5 + i).Value = scrMinorUnit.Value ' Setzen .MinorUnit = scrMinorUnit.Value End If ' Gewählte Y-Achse Skalierung Log. setzen und ausgeben If chkLog.Value = True Then .ScaleType = xlLogarithmic Me.Cells(15, 5 + i).Value = "Wahr" Else .ScaleType = xlLinear Me.Cells(15, 5 + i).Value = "Falsch" End If ' Gewählte Y-Achse Skalierung umgekehrte Reihenfolge ' setzen und ausgeben If chkReversePlotOrderY.Value = True Then .ReversePlotOrder = True Me.Cells(16, 5 + i).Value = "Wahr" Else .ReversePlotOrder = False Me.Cells(16, 5 + i).Value = "Falsch" End If

Diagramme

' Gewählte Y-Achse Hauptgitternetz ' setzen und ausgeben Listing 302 (Forts.)

' X-Achse schneidet auf gewählter Y-Achse. Wert ausgeben Me.Cells(12, 5 + i).Value = scrYCrossesAt.Value ' X-Achse schneidet auf gewählter Y-Achse. Modus ausgeben Me.Cells(13, 5 + i).Value = TranslateAxis(scrCrossModus.Value) ' X-Achse schneidet auf gewählter Y-Achse. Modus setzen .Crosses=CLng(Split(TranslateAxis(scrCrossModus.Value),"=")(1)) If scrCrossModus.Value = 2 Then ' X-Achse schneidet auf gewählter Y-Achse. Wert setzen, ' wenn Modus auf "xlCustom" .CrossesAt = scrYCrossesAt.Value End If

Diagramme Diagramme Diagramme

' Gewählte Y-Achse Hilfsgitternetz ' setzen und ausgeben If chkMinorGridlines.Value = True Then .HasMinorGridlines = True Me.Cells(18, 5 + i).Value = "Wahr" .MinorGridlines.Format.Line.Weight = 1 Else .HasMinorGridlines = False Me.Cells(18, 5 + i).Value = "Falsch" End If

Diagramme

If chkMajorGridlines.Value = True Then .HasMajorGridlines = True Me.Cells(17, 5 + i).Value = "Wahr" .MajorGridlines.Format.Line.ForeColor.RGB = _ .TickLabels.Font.Color .MinorGridlines.Format.Line.Weight = 4 Else .HasMajorGridlines = False Me.Cells(17, 5 + i).Value = "Falsch" End If

527

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 527 Dienstag, 4. Dezember 2007 1:42 13

Listing 302 (Forts.)

Diagramme

' Ereignisse einschalten Application.EnableEvents = True Exit Sub Fehlerbehandlung: MsgBox Err.Description Resume Next End Sub

Diagramme

End With

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 528 Dienstag, 4. Dezember 2007 1:42 13

528 >> Achsen, Gitternetzlinien

In der Prozedur SetActXSettings wird zu Beginn die Objektvariable objAxes auf die Achsen des Diagramms angelegt. Danach wird die Kategorieachse X angesprochen. Erst legt man fest, wo die Y-Achse die X-Achse schneidet. Danach wird die Rubrikenzahl zwischen den Teilstrichbeschriftungen, die Anzahl Rubriken zwischen den Teilstrichen festgelegt und eingestellt, ob die Werteachse zwischen den Rubriken schneidet. Anschließend wird bestimmt, ob die Rubriken in umgekehrter Reihenfolge angezeigt werden. In der Fehlerbehandlung, die bei einem auftretenden Fehler abgearbeitet wird, gibt man die Fehlerbeschreibung in einer Meldung aus und kehrt zur nächsten ausführbaren Codezeile zurück. Damit diese Fehlerbehandlung nicht immer abgearbeitet wird, verlässt man die Prozedur vorher mit Exit Sub. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '=================================================================== Private Sub SetActXSettings() Dim objChart As Chart Dim objAxes As Axes On Error GoTo Fehlerbehandlung Set objChart = Me.ChartObjects(1).Chart Set objAxes = objChart.Axes With objAxes(xlCategory) ' Y-Achse schneidet auf X-Achse. .CrossesAt = scrXCrossesAt.Value ' Rubrikenzahl zwischen Teilstrichbeschriftung .TickLabelSpacing = scrTickLabelSpacing.Value ' Rubrikenanzahl zwischen Teilstrichen .TickMarkSpacing = scrTickMarkSpacing.Value ' Werteachse (Y) schneidet zwischen Rubriken .AxisBetweenCategories = chkAxisBetweenCategories.Value ' Rubriken in umgekehrter Reihenfolge .ReversePlotOrder = chkReversePlotOrderX.Value

Diagramme

End With Listing 303

Private Sub optPrimary_Click() ReadActYSettings End Sub Private Sub optSecundary_Click() ReadActYSettings End Sub Listing 304

In der Prozedur ReadActYSettings schaltet man zu Beginn die Ereignisse ab, damit bei einer Änderung eines Steuerelementes keine andere Ereignisprozedur ausgelöst wird. Die Variable i wird auf 1 gesetzt, wenn das Optionsfeld optSecundary auf Wahr gesetzt ist, und bleibt sonst auf Null. Dieser Wert wird zur Spaltennummer der Zelle hinzugefügt, aus denen die Informationen ausgelesen werden. Daraufhin liest man das Minimum und Maximum der gewählten Y-Achse aus dem Tabellenblatt aus und setzt die entsprechenden Bildlaufleisten auf diese Werte. Mit dem Haupt- und Hilfsintervall geht man ähnlich vor. Anschließend wird aus dem Tabellenblatt ausgelesen, ob eine logarithmische Skalierung eingestellt ist, und der Haken des Kontrollkästchens wird gesetzt oder gelöscht. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '=================================================================== Listing 305

Diagramme Diagramme

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '===================================================================

Diagramme

Die Auswahl der Primär- oder Sekundärachse mit einer der Optionsschaltflächen löst ein Klick-Ereignis aus, in dem die Prozedur ReadActYSettings aufgerufen wird. Darin werden die aktuellen Achseneinstellungen ausgelesen und die Steuerelemente auf die eingestellten Werte gesetzt.

Diagramme

Listing 303 (Forts.)

Diagramme

Exit Sub Fehlerbehandlung: MsgBox Err.Description Resume Next End Sub

Diagramme

529

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 529 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

2471_Excel-VBA.book Seite 530 Dienstag, 4. Dezember 2007 1:42 13

530 >> Achsen, Gitternetzlinien Private Sub ReadActYSettings() Dim i As Long Dim k As Long

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

If optSecundary Then i = 1 ' Ereignisse ausschalten Application.EnableEvents = False ' Gewählte Y-Achse If Me.Cells(8, 5 + scrMinY.Value = Else scrMinY.Value = End If

Minimum auslesen und Steuerelement setzen i).Value = "xlAutomatic" Then 0

' Gewählte Y-Achse If Me.Cells(9, 5 + scrMaxY.Value = Else scrMaxY.Value = End If

Maximum auslesen und Steuerelement setzen i).Value = "xlAutomatic" Then 0

Me.Cells(8, 5 + i).Value

Me.Cells(9, 5 + i).Value

' Gewählte Y-Achse Hauptintervall auslesen und Steuerelement ' setzen If Me.Cells(10, 5 + i).Value = "xlAutomatic" Then scrMajorUnit.Value = 0 Else scrMajorUnit.Value = Me.Cells(10, 5 + i).Value End If ' Gewählte Y-Achse Hilfsintervall auslesen und Steuerelement ' setzen If Me.Cells(11, 5 + i).Value = "xlAutomatic" Then scrMinorUnit.Value = 0 Else scrMinorUnit.Value = Me.Cells(11, 5 + i).Value End If ' Gewählte Y-Achse Skalierung Log. auslesen und Steuerelement ' setzen If LCase(Me.Cells(15, 5 + i).Value) = "wahr" Then chkLog.Value = True Else chkLog.Value = False End If Listing 305 (Forts.)

' Gewählte Y-Achse Anzeige Hauptgitternetz ' auslesen und Steuerelement setzen If LCase(Me.Cells(17, 5 + i).Value) = "wahr" Then chkMajorGridlines.Value = True Else chkMajorGridlines.Value = False End If ' Gewählte Y-Achse Anzeige Hilfsgitternetz ' auslesen und Steuerelement setzen If LCase(Me.Cells(18, 5 + i).Value) = "wahr" Then chkMinorGridlines.Value = True Else chkMinorGridlines.Value = False End If ' Ereignisse einschalten Application.EnableEvents = True End Sub Listing 305 (Forts.)

In der Ereignisprozedur der Schaltfläche cmdFontBackcolorX werden die Kategorieachse X und die Zelle E25 an die Funktion FormatObjectLikeCell übergeben. Die Achsenbeschriftung wird dort an die Attribute der Zelle E25 angepasst.

Diagramme Diagramme Diagramme

For k = 1 To 4 If InStr(1, TranslateAxis(k), Me.Cells(13, 5 + i).Value) Then ' Für gewählte Y-Achse Modus ermitteln ' und Steuerelement setzen scrCrossModus.Value = k Exit For End If Next

Diagramme

' Rubrikenachse (x) schneidet bei scrYCrossesAt.Value = Me.Cells(12, 5 + i).Value

Diagramme

' Gewählte Y-Achse Skalierung umgekehrte Reihenfolge ' auslesen und Steuerelement setzen If LCase(Me.Cells(16, 5 + i).Value) = "wahr" Then chkReversePlotOrderY.Value = True Else chkReversePlotOrderY.Value = False End If

Diagramme

531

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 531 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 532 Dienstag, 4. Dezember 2007 1:42 13

532 >> Achsen, Gitternetzlinien

In der Ereignisprozedur der Schaltfläche cmdFontBackcolorY wird nachgeschaut, ob die Primär- oder die Sekundärachse Y gewählt wurde. Zweimal wird anschließend die Funktion FormatObjectLikeCell aufgerufen, wobei als erstes Argument die Achsenbeschriftung und schließlich der Achsentitel der gewählten Achse als Objekt übergeben wird. Als zweites Argument wird die Zelle F19 oder E19 an die Funktion FormatObjectLikeCell übergeben. Die Prozedur FormatObjectLikeCell wurde aus Platzmangel in diesem Rezept nicht mit abgedruckt, ist jedoch im Rezept 183 in diesem Kapitel mit einer Erklärung zu finden. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '=================================================================== Private Sub cmdFontBackcolorX_Click() ' Beschriftung X-Achse FormatObjectLikeCell _ Me.ChartObjects(1).Chart.Axes(xlCategory), _ Me.Range("E25")

Diagramme

Diagramme

Diagramme

End Sub Private Sub cmdFontBackcolorY_Click() Dim lngModus As Long Dim rngDestination As Range ' Gewählte Y-Achse (Primär/Sekundär) lngModus = IIf(optSecundary, xlSecondary, xlPrimary) Set rngDestination = _ IIf(optSecundary, Me.Range("F19"), Me.Range("E19")) ' Beschriftung Y-Achse Achse FormatObjectLikeCell _ Me.ChartObjects(1).Chart.Axes(xlValue, lngModus).TickLabels, _ rngDestination ' Beschriftung Y-Achse Achsentitel FormatObjectLikeCell _ Me.ChartObjects(1).Chart.Axes(xlValue, lngModus).AxisTitle, _ rngDestination End Sub

Diagramme

Listing 306

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_08_AxisGrid.xlsm ' Tabelle Achsen ' Modul Tabelle Achsen '=================================================================== Private Sub chkSeries1_Click() Dim objChart As Chart Set objChart = Me.ChartObjects(1).Chart If chkSeries1 Then ' Serie 1 Primärachse, Serie 2 Sekundärachse objChart.SeriesCollection(1).AxisGroup = 1 objChart.SeriesCollection(2).AxisGroup = 2 ' Abstand zwischen Säulengruppen als Prozentsatz objChart.ChartGroups(1).GapWidth = 100 objChart.ChartGroups(2).GapWidth = 500 ' Ausgabe Me.Range("E14").Value = "Serie 1" Me.Range("F14").Value = "Serie 2" Else ' Serie 2 Primärachse, Serie 1 Sekundärachse objChart.SeriesCollection(2).AxisGroup = 1 objChart.SeriesCollection(1).AxisGroup = 2 ' Abstand zwischen Säulengruppen als Prozentsatz Listing 307

Diagramme Diagramme Diagramme

Schließlich wird noch auf dem Tabellenblatt der ursprüngliche Zustand hergestellt und die Steuerelemente werden an die Einstellungen der gewählten Achse mit Hilfe der Funktion ReadActYSettings angepasst. Damit bei einer Änderung kein Ereignis ausgelöst wird, schaltet man die Ereignisse mit Hilfe der Eigenschaft EnableEvents aus und am Ende wieder ein.

Diagramme

Danach werden die Formate und Einstellungen für jede der zwei Werteachsen neu gesetzt. Hierfür erfolgt ein Aufruf der Prozeduren SetActYSettings und cmdFontBackcolorY_Click. Danach wird die Optionsschaltfläche auf die noch nicht bearbeitete Achse gesetzt, mit der Prozedur ReadActYSettings die Werte der ausgewählten Achse ausgelesen und die Steuerelemente entsprechend angepasst. Nun kann man wiederum die Prozeduren SetActYSettings und cmdFontBackcolorY_Click aufrufen und dadurch die andere Achse anpassen.

Diagramme

Klickt man das Kontrollkästchen chkSeries1 an, wird festgelegt, welche Serie auf der Primär- und welche auf der Sekundärachse angezeigt wird. Da bei einer Änderung beide Säulengruppen die gleiche Breite zugewiesen bekommen und somit eine Serie teilweise verdeckt wird, passt man noch den Abstand zwischen Balken- oder Säulengruppen an. Anschließend wird noch ausgegeben, welche Serie auf welcher Achse liegt.

Diagramme

533

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 533 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 534 Dienstag, 4. Dezember 2007 1:42 13

534 >> Achsen, Gitternetzlinien objChart.ChartGroups(1).GapWidth = 100 objChart.ChartGroups(2).GapWidth = 500 ' Ausgabe Me.Range("E14").Value = "Serie 2" Me.Range("F14").Value = "Serie 1" End If ' Ereignisse ausschalten Application.EnableEvents = False ' Werte für beide Achsen neu auslesen und setzen If optPrimary Then ' Primärachse Einstellungen setzen SetActYSettings cmdFontBackcolorY_Click ' Werte Sekundärachse auslesen und Einstellungen setzen optSecundary.Value = True ReadActYSettings SetActYSettings cmdFontBackcolorY_Click ' Ursprüngliche Einstellungen im Tabellenblatt ' wiederherstellen optPrimary.Value = True ReadActYSettings Else ' Sekundärachse Einstellungen setzen SetActYSettings cmdFontBackcolorY_Click ' Werte Primärachse auslesen und Einstellungen setzen optPrimary.Value = True ReadActYSettings SetActYSettings cmdFontBackcolorY_Click ' Ursprüngliche Einstellungen im Tabellenblatt ' wiederherstellen optSecundary.Value = True ReadActYSettings End If ' Ereignisse einschalten Application.EnableEvents = True End Sub Listing 307 (Forts.)

Die Übersetzungsfunktion TranslateAxis findet man im Quelltext.

>> Diagramme

535

189 Marker

Diagramme

Diagramme

Diagramme

Diagramme

Markierer (MARKER) sind beispielsweise in Liniendiagrammen zu finden. Sie repräsentieren einzelne Datenpunkte und können für jede Datenserie gesondert formatiert werden.

Diagramme

2471_Excel-VBA.book Seite 535 Dienstag, 4. Dezember 2007 1:42 13

왘 Die Vordergrundfarbe wählt man dabei mit Hilfe der Rnd-Funktion zufällig aus, der Wert stellt einen Index in die Farbtabelle (ColorIndex) dar. In das Tabellenblatt wird anschließend die Vordergrundfarbe als Wert und als Hintergrundfarbe der

Diagramme

Zu Beginn der Click-Ereignisprozedur der Schaltfläche cmdChange wird eine Objektvariable angelegt, die eine Referenz auf das SeriesCollection-Objekt des ersten Diagramms des Tabellenblattes aufnimmt. Anschließend wird mit Randomize der Zufallszahlengenerator initialisiert. Danach werden in einer Schleife alle Serien durchlaufen, in diesem Rezept ist das aber nur eine einzige.

Diagramme

In diesem Rezept werden bei jedem Klick auf die Schaltfläche mit der Beschriftung »Zufallsgenerator« die Markerattribute Vordergrundfarbe, Hintergrundfarbe, Markerart und die Größe zufällig ausgewählt, auf dem Tabellenblatt ausgegeben und im Diagramm gesetzt.

Diagramme

Abbildung 182: Marker

Diagramme

2471_Excel-VBA.book Seite 536 Dienstag, 4. Dezember 2007 1:42 13

536 >> Marker

gleichen Zelle ausgegeben. Die Markerfarbe wird über die Eigenschaft MarkerForegroundColorIndex der Serie gesetzt.

왘 Der Markerstil wird auch zufällig ausgewählt. Der von der RND-Funktion gelieferte Wert dient als Index in die Auflistung von Konstanten. Der Name der Auflistung ist XlMarkerStyle. Die Übersetzungsfunktion TranslateXlMarkerStyle liefert den Konstantennamen mitsamt dem zugehörigen Wert als Text. Dieser wird komplett in eine Zelle des Tabellenblattes ausgegeben. Vor dem Zuweisen an die Eigenschaft MarkerStyle wird noch mit Hilfe der Split-Funktion aus dem von den Funktionen mit dem Präfix Translate gelieferten Text der Wert der Konstanten extrahiert. Die Übersetzungsfunktion TranslateXlMarkerStyle findet man im Quelltext.

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_09_Marker.xlsm ' Tabelle Marker ' Modul Tabelle Marker '=================================================================== Private Sub cmdChange_Click() Dim i As Long Dim lngColorBorder As Long Dim lngColorBack As Long Dim lngMarkerStyle As Long Dim lngMarkerSize As Long Dim objSeries As SeriesCollection

Diagramme

Diagramme

왘 Die Markergröße, die einen Wert zwischen 2 und 72 annehmen kann, wird mit Hilfe der Rnd-Funktion zufällig ausgewählt. Dieser Wert wird in das Tabellenblatt ausgegeben und der Eigenschaft MarkerSize der Serie zugewiesen.

Diagramme

Diagramme

Diagramme

왘 Ähnlich verfährt man mit der Hintergrundfarbe. Die Markerfarben selbst werden über die Eigenschaft MarkerBackgroundColorIndex der Serie gesetzt.

Set objSeries = Me.ChartObjects(1).Chart.SeriesCollection Application.ScreenUpdating = False

Diagramme

Randomize For i = 1 To objSeries.Count With objSeries(i)

Diagramme

' Vordergrundfarbe lngColorBorder = Int((56 + 1) * Rnd) Me.Cells(2, i + 1) = lngColorBorder Listing 308

' Hintergrundfarbe lngColorBack = Int((56 + 1) * Rnd) Me.Cells(3, i + 1) = lngColorBack Me.Cells(3, i + 1).Interior.ColorIndex = lngColorBack .MarkerBackgroundColorIndex = lngColorBack ' MarkerStil lngMarkerStyle = Int(12 * Rnd + 1) Me.Cells(4, i + 1) = TranslateXlMarkerStyle(lngMarkerStyle) .MarkerStyle = CLng( _ Split(TranslateXlMarkerStyle(lngMarkerStyle),"=")(1)) ' Markerdicke lngMarkerSize = Int(71 * Rnd + 2) Me.Cells(5, i + 1) = lngMarkerSize .MarkerSize = lngMarkerSize End With Next i

Diagramme

Me.Cells(2, i + 1).Interior.ColorIndex = lngColorBorder .MarkerForegroundColorIndex = lngColorBorder

Diagramme

537

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 537 Dienstag, 4. Dezember 2007 1:42 13

Listing 308 (Forts.)

Die Übersetzungsfunktion TranslateXlMarkerStyle findet man im Quelltext.

Diagramme

Application.ScreenUpdating = True End Sub

Diagramme

Möchte man in einem Diagramm die Datenbeschriftungen ohne Zuhilfenahme von VBA modifizieren, markiert man mit der Maustaste das Diagramm. Danach erscheinen drei neue Registerkarten mit Namen ENTWURF, LAYOUT und FORMAT. Auf der Registerkarte LAYOUT findet man ein Icon mit der Beschriftung DATENBESCHRIFTUNGEN, mit deren Hilfe man alle möglichen Eigenschaften festlegen kann.

Diagramme

Datenpunkte von Datenreihen können in einem Diagramm mit Beschriftungen versehen werden, um zusätzliche Informationen zu liefern. Neben einer standardmäßigen Darstellung der Werte können in Datenbeschriftungen Reihen- und Rubrikennamen, sowie die Legendensymbole angezeigt werden. Bei Blasendiagrammen kann man sogar die Größe der Blasen anzeigen.

Diagramme

190 Datenbeschriftungen

538 >> Datenbeschriftungen

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 538 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

Diagramme

Diagramme

Abbildung 183: Datenbeschriftungen

In diesem Rezept wird gezeigt, wie man die Schriftattribute und den Hintergrund der Datenbeschriftung programmgesteuert anpasst. Außerdem kann noch festgelegt werden, ob neben der Datenbeschriftung auch der Serienname, die Kategorie und die Legendensymbole dargestellt werden. Dazu sind auf dem Tabellenblatt einige Schaltflächen und Bildlaufleisten untergebracht. 왘 Mit einem Kontrollkästchen wird festgelegt, ob überhaupt die Datenbeschriftung angezeigt wird oder nicht. 왘 Ein weiteres Kontrollkästchen entscheidet darüber, ob der Serienname im Text der Datenbeschriftungen eingetragen wird. 왘 Das dritte Kontrollkästchen legt fest, ob die Kategorie im Text der Datenbeschriftungen dargestellt werden soll. 왘 Mit einem weiteren Kontrollkästchen kann man festlegen, ob die Legendensymbole zusätzlich zu den Datenbeschriftungen angezeigt werden. 왘 Nach einem Klick auf die Schaltfläche SCHRIFTATTRIBUTE werden die Formate der Zelle E3 auf die Datenbeschriftung übertragen. Eine Klick auf eines der drei Kontrollkästchen chkSeriesName, chkCategoryName oder chkLegendSymbols ruft die Prozedur ChangeOthers auf, in welcher die Sichtbarkeit des

Listing 309

Ein Klick auf das Kontrollkästchen chkDataLabel steuert über die Eigenschaft HasDataLabels abhängig vom Zustand des Kontrollkästchens die Sichtbarkeit der Datenbeschriftungen. Ist die Datenbeschriftung sichtbar, wird die Prozedur ChangeOthers aufgerufen. Zum Anpassen der Text- und Hintergrundeigenschaften wird die Prozedur cmdFormat_Click aufgerufen. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_10_DataLabel.xlsm ' Tabelle Datenbeschriftung ' Modul Tabelle Datenbeschriftung '=================================================================== Private Sub chkDataLabel_Click() ' Datenbeschriftung abhängig vom Zustand ein- bzw. ausblenden Me.ChartObjects(1).Chart.SeriesCollection(1).HasDataLabels = _ chkDataLabel.Value If chkDataLabel.Value = False Then Exit Sub ChangeOthers cmdFormat_Click End Sub

Diagramme Diagramme

Private Sub chkSeriesName_Click() ChangeOthers End Sub Private Sub chkCategoryName_Click() ChangeOthers End Sub Private Sub chkLegendSymbols_Click() ChangeOthers End Sub

Diagramme

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_10_DataLabel.xlsm ' Tabelle Datenbeschriftung ' Modul Tabelle Datenbeschriftung '===================================================================

Diagramme

Seriennamens und der Kategorie im Datenbeschriftungstext und das Anzeigen der Legendensymbole neben den Datenbeschriftungen gesetzt wird.

Diagramme

539

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 539 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Listing 310

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 540 Dienstag, 4. Dezember 2007 1:42 13

540 >> Datenbeschriftungen

Ein Klick auf die Schaltfläche mit der Beschriftung SCHRIFTATTRIBUTE löst das ClickEreignis cmdFormat_Click aus. Die Prozedur wird sofort verlassen, wenn die Datenbeschriftungen nicht aktiviert sind. Jeder einzelne Datenpunkt kann gesondert formatiert werden, deshalb werden in einer For Each-Schleife alle Datenpunkte nacheinander durchlaufen, wobei die Objektvariable objDataLabel den jeweiligen Datenpunkt aufnimmt. Dieser wird bei jedem Durchlauf als erster Parameter an die Funktion FormatObjectLikeCell übergeben, Als zweiter Parameter wird die Zelle übergeben, an deren Eigenschaften das Objekt angepasst werden soll, das ist die Zelle E3. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_10_DataLabel.xlsm ' Tabelle Datenbeschriftung ' Modul Tabelle Datenbeschriftung '=================================================================== Private Sub cmdFormat_Click() Dim objSeriesCollection As Series Dim objDataLabel As DataLabel Set objSeriesCollection = _ Me.ChartObjects(1).Chart.SeriesCollection(1)

Diagramme

' Verlassen, wenn keine Datentabelle vorhanden If objSeriesCollection.HasDataLabels = _ False Then Exit Sub ' Alle Datenbeschriftungen der Serie durchlaufen For Each objDataLabel In objSeriesCollection.DataLabels

Diagramme

Diagramme

Diagramme

' Label formatieren FormatObjectLikeCell objDataLabel, Me.Range("E3") Next End Sub Listing 311

In der Prozedur ChangeOthers wird über die Eigenschaften ShowSeriesName, ShowCategoryName und ShowLegendKey die Sichtbarkeit des Seriennamens, der Kategorie im Datenbeschriftungstext und das Anzeigen der Legendensymbole neben den Datenbeschriftungen gesteuert.

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_10_DataLabel.xlsm ' Tabelle Datenbeschriftung ' Modul Tabelle Datenbeschriftung '=================================================================== Private Sub ChangeOthers() Dim objSeriesCollection As Series Dim objDataLabels As DataLabels Dim objDataLabel As DataLabel Set objSeriesCollection = _ Me.ChartObjects(1).Chart.SeriesCollection(1) ' Verlassen, wenn keine Datenbeschriftung vorhanden If objSeriesCollection.HasDataLabels = False Then Exit Sub

Diagramme

541

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 541 Dienstag, 4. Dezember 2007 1:42 13

End Sub Listing 312

Diagramme

With objDataLabels .ShowSeriesName = chkSeriesName.Value .ShowCategoryName = chkCategoryName.Value .ShowLegendKey = chkLegendSymbols.Value End With

Diagramme

Set objDataLabels = objSeriesCollection.DataLabels

Diagramme

Manuell kann man Trendlinien hinzufügen, ändern oder entfernen, indem man auf die Diagrammfläche klickt und auf der Registerkarte Layout den Eintrag TRENDLINIE auswählt.

Diagramme

Trendlinien können zeigen, ob das zu erwartende Ergebnis, welches durch das Diagramm dargestellt wird, zu einem Gewinn oder zu einem Verlust tendiert. Je nach Diagrammtyp ist das ohne Trendlinie nur sehr schwer zu erkennen. Trendlinien sind Linien, die auf Basis der vorhandenen Daten zusätzlich zu einem Diagramm hinzugefügt werden können.

Diagramme

191 Trendlinien

542 >> Trendlinien

Diagramme

Dazu sind auf dem Tabellenblatt einige Schaltflächen und Bildlaufleisten untergebracht.

Diagramme

Diagramme

Abbildung 184: Trendlinien

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 542 Dienstag, 4. Dezember 2007 1:42 13

In diesem Rezept wird gezeigt, wie man die Sichtbarkeit, den Typ, die Ordnung einer Trendlinie, die Richtung der Trendperiode, das Anzeigen des Bestimmtheitsmaßes und der Formel anpassen kann. Außerdem können noch die Text- und Hintergrundattribute der angezeigten Formel verändert werden.

왘 Mit einem Kontrollkästchen kann man festlegen, ob überhaupt ein Trend angezeigt wird. 왘 Ein weiteres Kontrollkästchen entscheidet darüber, ob das Bestimmtheitsmaß angezeigt wird. 왘 Das dritte Kontrollkästchen legt fest, ob die Formel zur Berechnung der Trendlinie angezeigt wird. 왘 Die Bildlaufleiste scrType gibt den Trendlinientyp an. Der Wert der Bildlaufleiste ist ein Index in eine Reihe von möglichen vordefinierten Konstanten der Aufzählung XlTrendlineType. 왘 Die Bildlaufleiste scrOrder gibt die Ordnung der polynominalen Funktion an, die der Trendlinie zugrunde liegt. Es sind Ordnungen zwischen 2 und 6 möglich.

>> Diagramme

543

왘 Mit einer weiteren Bildlaufleiste kann man festlegen, um wie viel Perioden in Vorwärts-, bzw. Rückwärtsrichtung die Trendperiode angezeigt wird.

Diagramme

2471_Excel-VBA.book Seite 543 Dienstag, 4. Dezember 2007 1:42 13

In den Ereignisprozeduren der Kontrollkästchen chkDisplayEquation, chkDisplayRSquared, der Bildlaufleisten scrOrder und scrType wird die Prozedur ChangeOthers aufgerufen. In der Ereignisprozedur der Bildlaufleiste scrType wird mit der Funktion TranslateXlTrendlineType ein Index in eine Aufzählung von Konstanten in den Namen und Wert der Konstanten umgewandelt und ausgegeben.

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '===================================================================

Diagramme

왘 In Zelle F9 wird die zugrunde liegende Formel leicht überarbeitet ausgegeben, so dass sie fast unverändert als echte Formel verwendet werden kann.

Diagramme

왘 In Zelle F10 ist die Formel ausgegeben, so wie sie dem Diagramm entnommen wurde.

Diagramme

왘 Nach einem Klick auf die Schaltfläche FORMAT werden die Formate der Zelle E3 auf die Datenbeschriftung angewendet.

Private Sub scrType_Change() Me.Range("E5").Value = TranslateXlTrendlineType(scrType.Value) ChangeOthers End Sub Private Sub scrType_Scroll () Me.Range("E5").Value = TranslateXlTrendlineType(scrType.Value) ChangeOthers End Sub Listing 313

Diagramme Diagramme

Private Sub scrOrder_Change() ChangeOthers End Sub Private Sub scrOrder_Scroll() ChangeOthers End Sub

Diagramme

Private Sub chkDisplayRSquared_Click() ChangeOthers End Sub

Diagramme

Private Sub chkDisplayEquation_Click() ChangeOthers End Sub

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 544 Dienstag, 4. Dezember 2007 1:42 13

544 >> Trendlinien

In den Ereignisprozeduren der Bildlaufleiste scrPeriod wird die Prozedur Change-

Period aufgerufen.

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '=================================================================== Private Sub scrPeriod_Change() ChangePeriod End Sub Private Sub scrPeriod_Scroll () ChangePeriod End Sub

Diagramme

Diagramme

Listing 314

In der Click-Ereignisprozedur der Schaltfläche chkTrend wird zu Beginn eine Objektvariable auf die erste SeriesCollection angelegt. Anschließend wird der Wert des Kontrollkästchens chkTrend abgefragt, welcher angibt, ob eine Trendlinie angezeigt werden soll. Ist das der Fall und noch keine Trendlinie vorhanden, was man daran erkennt, dass die Count-Eigenschaft auf Null ist, wird mit der Add-Methode eine neue hinzugefügt. Ist bereits eine Trendlinie vorhanden, wird die Prozedur verlassen. Sofern eine Trendlinie vorhanden ist, was man daran erkennt, dass die Count-Eigenschaft ungleich Null ist, und man diese nicht mehr anzeigen möchte, wird diese mit der Delete-Methode gelöscht. Ist keine Trendlinie vorhanden, wird die Prozedur verlassen.

Diagramme

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '===================================================================

Diagramme

Schließlich werden noch die Prozeduren ChangeOthers, cmdFormat_Click und ChangePeriod aufgerufen.

Private Sub chkTrend_Click() Dim objSeriesCollection As Series Set objSeriesCollection = _ Me.ChartObjects(1).Chart.SeriesCollection(1)

Diagramme

If objSeriesCollection.Trendlines.Count = 0 Then Listing 315

>> Diagramme

545

' Keine Trendlinie vorhanden

Diagramme

2471_Excel-VBA.book Seite 545 Dienstag, 4. Dezember 2007 1:42 13

' Trendlinie hinzufügen objSeriesCollection.Trendlines.Add Else

Diagramme

If chkTrend.Value Then ' Trendlinie gewünscht

If chkTrend.Value = False Then ' Keine Trendlinie gewünscht Do While objSeriesCollection.Trendlines.Count > 0 ' Alle Trendlinien löschen objSeriesCollection.Trendlines(1).Delete Loop ' Prozedur verlassen Exit Sub End If

Diagramme

Else ' Trendlinie vorhanden

Diagramme

End If

Diagramme

' Prozedur verlassen Exit Sub

ChangeOthers ChangePeriod cmdFormat_Click

Diagramme

End If

End Sub

Anschließend wird an die Funktion FormatObjectLikeCell als erster Parameter das anzupassende Objekt übergeben, in diesem Fall die Datenbeschriftung der Trendlinie.

Diagramme

Ein Klick auf die Schaltfläche FORMAT löst das Click-Ereignis der Schaltfläche aus. Zuerst wird überprüft, ob überhaupt eine Trendlinie vorhanden, und wenn ja, ob das Bestimmtheitsmaß und/oder die Formel angezeigt wird. Ist das nicht der Fall, wird die Prozedur verlassen.

Diagramme

Listing 315 (Forts.)

Diagramme

Diagramme

2471_Excel-VBA.book Seite 546 Dienstag, 4. Dezember 2007 1:42 13

546 >> Trendlinien

Als zweiter Parameter wird die Zelle übergeben, an deren Eigenschaften das Objekt angepasst werden soll, das ist die Zelle E3. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '===================================================================

Diagramme

Private Sub cmdFormat_Click() Dim objSeriesCollection As Series Set objSeriesCollection = _ Me.ChartObjects(1).Chart.SeriesCollection(1) ' Verlassen, wenn keine Trendlinie vorhanden If objSeriesCollection.Trendlines.Count = 0 Then Exit Sub

Diagramme

With objSeriesCollection.Trendlines(1) If .DisplayEquation Or .DisplayRSquared Then ' Trendlinienbeschriftung sichtbar

Diagramme

' Label formatieren FormatObjectLikeCell .DataLabel, Me.Range("E3") End If End With End Sub

Diagramme

Diagramme

Diagramme

Listing 316

Ein Aufruf der Prozedur ChangePeriod legt fest, um wie viele Perioden in die Vergangenheit oder Zukunft die Trendlinie erweitert wird, eine gleichzeitige Erweiterung in beide Richtungen ist in diesem Rezept nicht vorgesehen. Die Bildlaufleiste scrPeriod liefert diese Informationen, ein negativer Wert stellt eine Erweiterung in die Vergangenheit, ein positiver Wert eine Erweiterung in die Zukunft dar. Dieser Wert wird anschließend in Zelle E7 ausgegeben. Zum Erweitern werden die Eigenschaften Forward und Backward der SeriesCollection gesetzt. Wird eine Erweiterung beim aktuellen Diagrammtyp nicht unterstützt, setzt man schließlich eine Meldung in einer Meldungsbox ab.

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '=================================================================== Private Sub ChangePeriod() Dim objSeriesCollection As Series Dim strMessage As String Me.Range("E7").Value = scrPeriod.Value Set objSeriesCollection = _ Me.ChartObjects(1).Chart.SeriesCollection(1)

Diagramme

547

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 547 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

On Error Resume Next Err.Clear If scrPeriod.Value > 0 Then ' Trend vorwärts um X Perioden .Forward = Abs(scrPeriod.Value) If Err.Number 0 Then strMessage = "Trends vorwärts bei diesem" & vbCrLf strMessage = strMessage & "Diagrammtyp nicht möglich!" End If Else ' Trend rückwärts um X Perioden .Backward = Abs(scrPeriod.Value) If Err.Number 0 Then strMessage = "Trends rückwärts bei diesem" & vbCrLf strMessage = strMessage & _ "Diagrammtyp nicht möglich!"&vbCrLf End If End If

Diagramme

If scrPeriod.Value = 0 Then .Forward = 0 .Backward = 0 End If

Diagramme

With objSeriesCollection.Trendlines(1)

Diagramme

If objSeriesCollection.Trendlines.Count = 0 Then Exit Sub ' Trendlinie vorhanden

Listing 317

Diagramme

If Err.Number 0 Then MsgBox strMessage

Diagramme

Diagramme

2471_Excel-VBA.book Seite 548 Dienstag, 4. Dezember 2007 1:42 13

548 >> Trendlinien Application.EnableEvents = False scrPeriod.Value = 0 Me.Range("E7").Value = 0 Application.EnableEvents = True End If End With End Sub

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Listing 317 (Forts.)

In der Prozedur ChangeOthers werden der Trendlinientyp, bei Polynominalfunktionen die Ordnung, die Sichtbarkeit des Bestimmtheitsmaßes und der Formel bestimmt. Die Bildlaufleiste scrType gibt den Trendlinientyp an. Der Wert der Bildlaufleiste ist ein Index in eine Reihe von möglichen vordefinierten Konstanten der Aufzählung XlTrendlineType. Die Eigenschaft Type der SeriesCollection nimmt den Wert des gewünschten Typs entgegen, wobei die Umwandlungsfunktion TranslateXlTrendlineType den Konstantennamen und den Wert als Text liefert. Die Eigenschaft DisplayEquation wird auf den Wert des Kontrollkästchens chkDisplayEquation und die Eigenschaft DisplayRSquared auf den Wert des Kontrollkästchens chkDisplayRSquared gebracht. Die Bildlaufleiste scrOrder gibt die Ordnung der polynominalen Funktion an, die der Trendlinie zugrunde liegt. Es sind Ordnungen zwischen 2 und 6 möglich. Dieser Wert wird an die Eigenschaft Order der SeriesCollection zugewiesen. Bei einem gewählten Trendlinientyp von GLEITENDER DURCHSCHNITT werden die Inhalte der Ausgabezellen F9 und F10 gelöscht, im anderen Fällen wird die Originalformel inkl. das eventuell angezeigte Bestimmtheitsmaß ausgelesen und in Zelle F10 ausgegeben. Die mit der benutzerdefinierten Funktion TranslateFunction in eine (fast) Excel-kompatible Formel umgewandelte Originalformel wird in Zelle F9 ausgegeben. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '=================================================================== Private Sub ChangeOthers() Dim objSeriesCollection As Series gesetzt. Set objSeriesCollection = _ Me.ChartObjects(1).Chart.SeriesCollection(1) Listing 318

>> Diagramme If objSeriesCollection.Trendlines.Count = 0 Then Exit Sub ' Verlassen, wenn keine Trendlinie sichtbar ist

549

Diagramme

2471_Excel-VBA.book Seite 549 Dienstag, 4. Dezember 2007 1:42 13

' Typ festlegen .Type = CLng( _ Split(TranslateXlTrendlineType(scrType.Value), "=")(1))

Diagramme

With objSeriesCollection.Trendlines(1)

' Formeln im Blatt löschen Me.Range("F9").Value = "" Me.Range("F10").Value = "" Else ' Bestimmtheitsmaß ausblenden .DisplayRSquared = False

Diagramme

If .Type = xlMovingAvg Then ' Gleitender Durchschnitt

Diagramme

' Grad der Polynominalfunktion festlegen If .Type = xlPolynomial Then .Order = scrOrder.Value

'Zeit lassen Application.Wait Now + TimeSerial(0, 0, 2)

Diagramme

' Formel einblenden .DisplayEquation = True

' Umgewandelte Formel ausgeben Me.Range("F9").Value = TranslateFunction(.DataLabel.Text) End If

Diagramme

' Originalformel auslesen und ausgeben Me.Range("F10").Value = .DataLabel.Text

' Bestimmtheitsmaß ein/ausblenden .DisplayRSquared = chkDisplayRSquared.Value End With

Diagramme

' Formel ein/ausblenden .DisplayEquation = chkDisplayEquation.Value

Listing 318 (Forts.)

Diagramme

End Sub

550 >> Trendlinien

Innerhalb der benutzerdefinierten Funktion ersetzt man im Funktionstext das Zeichen x durch die Zeichenfolge »*x«, da das Malzeichen zwischen Koeffizient und Variable generell fehlt. Die Zeichenfolge »ln(*x)«, die durch den ersten Austausch entstehen kann, wird durch die Zeichenfolge »*ln(x)« ersetzt. Anschließend ersetzt man noch das Zeichen »e« gegen den Wert der Euler’schen Zahl mit einem führenden Malzeichen. Da im angezeigten Formeltext der Exponent von x lediglich optisch anders dargestellt wird und sich sonst nicht als Exponent zu erkennen gibt, werden in einer Schleife alle Zeichenfolgen, die mit »x« beginnen und auf die eine beliebige Ziffer folgt, gegen das Zeichen x, gefolgt von dem Exponentenzeichen (»^«) und der nachfolgenden Ziffer ausgetauscht.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Die Funktion TranslateFunction übersetzt Funktionen, die als Trendlinienfunktion eines Diagramms zurückgegeben wurden, in ein Format, welches sich mit ein paar Handgriffen in die Formel eines Tabellenblattes umwandeln lässt. Dazu muss man anschließend lediglich den führenden Text »y = « durch »=« und das Zeichen »x« durch den Wert oder den Bezug ersetzen.

Diagramme

Diagramme

2471_Excel-VBA.book Seite 550 Dienstag, 4. Dezember 2007 1:42 13

Weiterhin tauscht man noch die Zeichenfolge »,*« gegen »*« und löscht vorhandene Punkte im Formeltext. Da am Ende des Funktionstextes noch ein Komma vorkommen kann, wird auch dieses bei Bedarf gelöscht. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_11_Trend.xlsm ' Tabelle Trendlinie ' Modul Tabelle Trendlinie '=================================================================== Private Function TranslateFunction(strFunction As String) As String Dim i As Long strFunction = Replace(strFunction, "x", "*x") strFunction = Replace(strFunction, "ln(*x)", "*ln(x)") strFunction = Replace(strFunction, "e", "*2,718281828459^(") If InStr(strFunction, "^(") Then strFunction = strFunction & ")" For i = 0 To 9 strFunction = Replace(strFunction, "x" & i, "x^" & i) Next strFunction = Replace(strFunction, ",*", "*") strFunction = Replace(strFunction, " ", "") If Right(strFunction, 1) = "," Then _ strFunction = Left(strFunction, Len(strFunction) - 1) TranslateFunction = strFunction End Function

Diagramme

Listing 319

Die Prozedur FormatObjectLikeCell wurde aus Platzmangel in diesem Rezept nicht mit abgedruckt, ist jedoch im Rezept 183 in diesem Kapitel mit einer Erklärung zu finden. Auch die Übersetzungsfunktion TranslateXlTrendlineType findet man aus dem gleichen Grund nur im Quelltext.

192 Hintergrund Diagramm- und Zeichnungsfläche

Auf dem Tabellenblatt befinden sich insgesamt 12 Bildlaufleisten und 6 Drehfelder. Für den Diagrammhintergrund ChartArea sind die Steuerelemente in den Zeilen 1–7 zuständig, die verknüpften Zellen befinden sich dabei im Bereich B2:B6, C7. Für die

Diagramme

Abbildung 185: Flächen anpassen

Diagramme

Diagramme

Diagramme

Diagramme

Ein Diagramm besitzt zwei Flächen, die mit beliebigen Mustern und Farbverläufen ausgestattet werden können. Das ist der Diagrammbereich ChartArea und die Zeichnungsfläche PlotArea. Der Diagrammbereich (ChartArea) ist die äußere große Fläche, welche das Diagramm sowie alle anderen Elemente beinhaltet. Die Zeichnungsfläche (PlotArea) ist der innere Bereich, der unter dem eigentlichen Diagramm, jedoch über dem Diagrammhintergrund liegt. Für jede der Flächen existiert ein Dialog, den man am einfachsten über einen Rechtsklick auf die entsprechende Fläche und die Auswahl des entsprechenden Menüpunktes aus dem Kontextmenü erreichen kann.

Diagramme

551

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 551 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

2471_Excel-VBA.book Seite 552 Dienstag, 4. Dezember 2007 1:42 13

552 >> Hintergrund Diagramm- und Zeichnungsfläche

Zeichnungsfläche PlotArea sind die Steuerelemente in den Zeilen 8–14 zuständig, die verknüpften Zellen befinden sich dabei im Bereich B9:B13, C14. 왘 Die drei Drehfelder in Zeile 1 und 8 sind für die Farbe zuständig.

Diagramme

왘 Die Bildlaufleisten in den Zeilen 2 und 9 legen den Fülltyp fest. 왘 Die Bildlaufleisten in den Zeilen 3 und 10 legen das Füllmuster fest. 왘 Die Bildlaufleiste in den Zeilen 4 und 11 legen die Füllrichtung des Farbverlaufes fest.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

왘 Die Bildlaufleisten in den Zeilen 5 und 12 geben vordefinierte Farbübergänge vor. 왘 Mit den Bildlaufleisten in den Zeilen 6 und 13 können verschiedene Texturen festgelegt werden. 왘 Mit den Bildlaufleisten in den Zeilen 7 und 14 kann man die Transparenz einstellen. Damit nicht für jede Bildlaufleiste und jedes Drehfeld eigene Ereignisprozeduren angelegt werden müssen, überwacht man deren verknüpfte Zellen. Zum Überwachen wird in einer beliebigen Zelle eine Formel angelegt. Wir haben dafür die Funktion ZÄHLENWENN benutzt, welche den zu überwachenden Bereich als Argument zugewiesen bekommt. Eine Änderung in dem Bereich, sei es durch Handeingabe oder durch die Manipulation der Bildlaufleisten, löst anschließend das Worksheet_CalculateEreignis aus. Das Change-Ereignis des Tabellenblattes würde hingegen nur durch eine Handeingabe getriggert. Die einzige Aufgabe des Worksheet_Calculate-Ereignisses besteht darin, die Prozedur ChangeStyle aufzurufen. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_12_AreaFormat.xlsm ' Tabelle Chart- und PlotArea ' Modul Tabelle Chart- und PlotArea '=================================================================== Private Sub Worksheet_Calculate() ChangeStyle End Sub Listing 320

Die Prozedur ChangeStyle hat die Aufgabe, die gesetzten Werte aus dem Tabellenblatt auszulesen und die Diagrammeigenschaften anzupassen. Während der Laufzeit wird immer wieder vor dem Setzen eines Eigenschaftswertes die nachfolgende Aktion als Meldung in der Statusleiste ausgegeben. Zu Beginn der Prozedur werden verschiedene Objektvariablen definiert, die das einzige Chart-Objekt des Tabellenblattes, das ChartArea- und das PlotArea-Objekt aufnehmen. Um durch das Schreiben auf das Tabellenblatt nicht versehentlich ein Ereignis auszulösen, wird das durch die Anweisung Application.EnableEvents = False ausgeschaltet.

Anschließend werden das Füllmuster, die Füllfarbe, Typ und Stil des Farbverlaufs, eine gewählte vordefinierte Textur und die Transparenz gesetzt. Die zu Beginn ausgelesenen Indices werden dazu mit Hilfe der Übersetzungsfunktionen in den Konstantennamen mitsamt dem zugehörigen Wert umgewandelt und im Tabellenblatt ausgegeben. Die Eigenschaften selbst bekommen den Wert der Konstanten zugewiesen, welche durch die Split-Funktion aus den verschiedenen (nicht mit abgedruckten) Übersetzungsfunktionen extrahiert wurde. Schließlich wird noch die Statusbar zurückgesetzt und das Auslösen von Ereignissen wieder aktiviert. '=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_12_AreaFormat.xlsm ' Tabelle Chart- und PlotArea ' Modul Codemodul Tabelle "Chart- und PlotArea" '=================================================================== Public Sub ChangeStyle() Dim strOutput Dim strOutput1 Dim Dim Dim Dim

objChart objChartArea objPlotArea objLineFormat

Listing 321

As String As String As As As As

Object Object Object Object

Diagramme Diagramme

Im gemeinsamen Programmteil wird mit Hilfe der Select Case-Anweisung und abhängig vom Füllungstyp die Fill-Eigenschaft des mit der With-Anweisung referenzierten Objektes modifiziert. Dazu bedient man sich der Methoden Solid, Patterned, PresetGradient und PresetTextured, andere Methoden wie UserTextured und UserPicture werden in diesem Rezept nicht unterstützt.

Diagramme

Mit der With-Anweisung kann man eine Reihe von Anweisungen für ein bestimmtes Objekt ausführen, ohne mehrmals den Namen angeben zu müssen. Das macht man sich zunutze und referenziert mit Hilfe der Objektvariablen objDummy einmal das ChartArea- und beim zweiten Schleifendurchlauf das PlotArea-Objekt.

Diagramme

Damit man Codeteile für beide Objekte gemeinsam benutzen kann, benötigt man Variablen, die beim ersten Schleifendurchlauf die Eigenschaftswerte für das ChartArea- und beim zweiten die für das PlotArea-Objekt aufnehmen. Das geschieht vor dem eigentlichen Setzen der Objekteigenschaften und die notwendigen Werte und Objekte werden abhängig von der Zählvariablen i zugewiesen.

Diagramme

Anschließend werden die Eigenschaften der PlotArea und der ChartArea gesetzt. Prinzipiell sind die anzusprechenden Eigenschaften beider Objekte identisch. Deshalb werden, um Code zu sparen, in einer Schleife zuerst die Eigenschaften des ChartArea-, dann die des PlotArea-Objektes gesetzt.

Diagramme

553

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 553 Dienstag, 4. Dezember 2007 1:42 13

554 >> Hintergrund Diagramm- und Zeichnungsfläche

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 554 Dienstag, 4. Dezember 2007 1:42 13

Dim objSerCol Dim objDummy

As Object As Object

Dim Dim Dim Dim Dim

lngAreaFillType rngAreaFillTypeOut lngAreaFillPattern rngAreaFillPatternOut lngAreaColor

As As As As As

Long Range Long Range Long

Dim Dim Dim Dim Dim Dim Dim

lngGradientStyle rngGradientStyleOut lngGradientType rngGradientTypeOut lngPresetTextures rngPresetTexturesOut dblAreaTransparency

As As As As As As As

Long Range Long Range Long Range Double

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Dim i '

As Long

On Error Resume Next Application.EnableEvents = False ' Objektvariablen definieren Set objChart = Me.ChartObjects(1).Chart Set objChartArea = objChart.ChartArea Set objPlotArea = objChart.PlotArea For i = 1 To 2 If i = 1 Then ' Alle Variablen auf die ChartArea-Werte ' im Tabellenblatt setzen ' Objektvariable auf ChartArea Set objDummy = objChartArea ' Fülltyp ChartArea lngAreaFillType = Me.Range("B2") Set rngAreaFillTypeOut = Me.Range("C2") ' Füllmuster ChartArea lngAreaFillPattern = Me.Range("B3") Set rngAreaFillPatternOut = Me.Range("C3") ' Füllfarbe ChartArea lngAreaColor = RGB( _ Me.Range("C1"), Me.Range("D1"), Me.Range("E1"))

Listing 321 (Forts.)

' Transparenz ChartArea dblAreaTransparency = Me.Range("C7") Else ' Alle Variablen auf die PlotArea-Werte ' im Tabellenblatt setzen ' Objektvariable auf PlotArea Set objDummy = objPlotArea ' Fülltyp PlotArea lngAreaFillType = Me.Range("B9") Set rngAreaFillTypeOut = Me.Range("C9") ' Füllmuster PlotArea lngAreaFillPattern = Me.Range("B10") Set rngAreaFillPatternOut = Me.Range("C10")

Diagramme

' Textur vordefiniert ChartArea lngPresetTextures = Me.Range("B6") Set rngPresetTexturesOut = Me.Range("C6")

Diagramme

' Farbverlauf vordefiniert ChartArea lngGradientType = Me.Range("B5") Set rngGradientTypeOut = Me.Range("C5")

Diagramme

' Farbverlauf Stil ChartArea lngGradientStyle = Me.Range("B4") Set rngGradientStyleOut = Me.Range("C4")

555

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 555 Dienstag, 4. Dezember 2007 1:42 13

' Farbverlauf vordefiniert PlotArea lngGradientType = Me.Range("B12") Set rngGradientTypeOut = Me.Range("C12") ' Textur vordefiniert ChartArea lngPresetTextures = Me.Range("B13") Set rngPresetTexturesOut = Me.Range("C13")

Diagramme

' Farbverlauf Stil PlotArea lngGradientStyle = Me.Range("B11") Set rngGradientStyleOut = Me.Range("C11")

Diagramme

' Füllfarbe PlotArea lngAreaColor = RGB( _ Me.Range("C14"), Me.Range("D8"), Me.Range("E8"))

Diagramme

Listing 321 (Forts.)

Diagramme

2471_Excel-VBA.book Seite 556 Dienstag, 4. Dezember 2007 1:42 13

556 >> Hintergrund Diagramm- und Zeichnungsfläche ' Transparenz PlotArea dblAreaTransparency = Me.Range("C14")

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

End If With objDummy.Format.Fill ' Gemeinsamer Codeteil for Plot- und ChartArea ' Es wurden lediglich die Variablenwerte angepasst ' Fülltyp festlegen Application.StatusBar = "Fülltyp " & IIf(i = 1, _ "ChartArea ", "PlotArea ") & "anpassen" strOutput = TranslateFillType(lngAreaFillType) If strOutput "" Then Select Case CLng(Split(strOutput, "=")(1)) Case 1 ' Solid ' Kein Füllmuster .Solid Case 2 ' Pattern ' Füllmuster .Patterned _ CLng(Split(TranslatePatternType( _ lngAreaFillPattern), "=")(1)) Case 3 ' Fill Gradient ' Farbverlauf Stil + Typ On Error Resume Next .PresetGradient _ CLng(Split(TranslateGradientStyle( _ lngGradientStyle), "=")(1)), 1, _ CLng(Split(TranslatePresetGradientType( _ lngGradientType), "=")(1)) On Error GoTo 0 Case 4 ' Fill Textur ' Textur vordefiniert .PresetTextured _ CLng(Split(TranslatePresetTexture( _ lngPresetTextures), "=")(1)) Case 5 ' Fill Background strOutput = strOutput & " Nicht unterstützt!" Case 6 ' Fill Picture strOutput = strOutput & " Nicht unterstützt!" End Select rngAreaFillTypeOut = strOutput End If

Diagramme

' Füllmuster Application.StatusBar = "Füllmuster " & IIf(i = 1, _ Listing 321 (Forts.)

' Farbverlauf Typ Application.StatusBar = "Farbverlauf Typ " & IIf(i = 1, _ "ChartArea ", "PlotArea ") & "anpassen" strOutput1 = TranslatePresetGradientType( _ lngGradientType) rngGradientTypeOut = strOutput1 ' Textur vordefiniert Application.StatusBar = "Textur " & IIf(i = 1, _ "ChartArea ", "PlotArea ") & "anpassen" strOutput = TranslatePresetTexture( _ lngPresetTextures) rngPresetTexturesOut = strOutput If .Type = 4 Then On Error Resume Next .PresetTextured CLng(Split(strOutput, "=")(1)) On Error GoTo 0 End If .Transparency = dblAreaTransparency End With Next i Application.StatusBar = False Application.EnableEvents = True

Diagramme Diagramme Diagramme

' Farbverlauf Stil Application.StatusBar = "Farbverlauf Stil " & IIf(i = 1, _ "ChartArea ", "PlotArea ") & "anpassen" strOutput = TranslateGradientStyle( _ lngGradientStyle) rngGradientStyleOut = strOutput

Diagramme

' Füllfarbe Application.StatusBar = "Füllfarbe " & IIf(i = 1, _ "ChartArea ", "PlotArea ") & "anpassen" .ForeColor.RGB = lngAreaColor

Diagramme

"ChartArea ", "PlotArea ") & "anpassen" strOutput = TranslatePatternType(lngAreaFillPattern) If .Type = 2 Then .Patterned CLng(Split(strOutput, "=")(1)) End If rngAreaFillPatternOut = strOutput

557

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 557 Dienstag, 4. Dezember 2007 1:42 13

Listing 321 (Forts.)

Diagramme

End Sub

Diagramme

2471_Excel-VBA.book Seite 558 Dienstag, 4. Dezember 2007 1:42 13

558 >> Wände, Böden und Perspektive von 3-D-Diagrammen

Die Übersetzungsfunktionen TranslateLineDashStyle, TranslateLineStyle, TranslatePatternType, TranslateFillType, TranslateGradientStyle, TranslateGradientStyle, TranslatePresetGradientType und TranslatePresetTexture findet man im

193 Wände, Böden und Perspektive von 3-D-Diagrammen In Excel stehen einige Diagrammtypen mit 3-D-Ansichten zur Verfügung. Damit lassen sich sehr schöne Effekte erzielen. Möchte man in einem 3-D-Diagramm die Wände, den Boden oder die 3-D-Einstellungen ohne Zuhilfenahme von VBA verändern, markiert man mit der Maustaste das Diagramm. Daraufhin erscheinen drei neue Registerkarten mit Namen ENTWURF, LAYOUT und FORMAT. Auf der Registerkarte LAYOUT findet man die Symbole mit der Beschriftung DIAGRAMMWAND, DIAGRAMMBODEN und 3-D-DREHUNG, mit deren Hilfe Dialoge zum Ändern der Eigenschaften angezeigt werden.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Quelltext.

Diagramme

Abbildung 186: 3-D-Diagramm anpassen

Auf dem Tabellenblatt sind 8 Bildlaufleisten und 9 Drehfelder. Die verknüpften Zellen befinden sich dabei im Bereich K1, K3, K5, K7, K8, L9:L11, L2:N2, L4:N4 und L6:N6. 왘 Die Bildlaufleiste in Zeile 1 ist für das Wandmuster zuständig. Ausgewählt wird damit ein vordefiniertes Muster aus der Aufzählung XlPattern. 왘 Die Bildlaufleiste in Zeile 3 ist für das Rückwandmuster zuständig. Ausgewählt wird damit ein vordefiniertes Muster aus der Aufzählung XlPattern. 왘 Die Bildlaufleiste in Zeile 5 ist für das Bodenmuster zuständig. Ausgewählt wird damit ein vordefiniertes Muster aus der Aufzählung XlPattern. 왘 Mit der Bildlaufleiste in Zeile 8 wird die Rahmendicke eingestellt. Ausgewählt wird damit ein vordefiniertes Muster aus der Aufzählung XlBorderWeight. 왘 Mit der Bildlaufleiste in Zeile 9 wird der Rahmenstil eingestellt. Ausgewählt wird damit ein vordefiniertes Muster aus der Aufzählung XlLineStyle.

Diagramme

In diesem Rezept können die Seitenwände, der Boden, die Rückwand, der Rahmen, die Rotation in X- bzw. Y-Richtung und die Betrachtungshöhe eines 3D-Diagramms per VBA angepasst werden. Zum Formatieren wird aber nicht die in Excel 2007 neu hinzugekommene ChartFormat-Objektklasse benutzt, lediglich die Standardeigenschaften werden verwendet. Dabei stehen zwar weniger Formatierungsmöglichkeiten zur Auswahl, der Code wird aber kompakter und ist universeller einsetzbar.

Diagramme

559

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 559 Dienstag, 4. Dezember 2007 1:42 13

왘 Mit der Bildlaufleiste in Zeile 10 wird die Rotation in X-Richtung eingestellt.

Private Sub Worksheet_Calculate() ChangeStyle End Sub Listing 322

Diagramme Diagramme

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_13_WallFloorRotate.xlsm ' Tabelle Wände, Böden, Ausrichtung ' Modul Tabelle Wände, Böden, Ausrichtung '===================================================================

Diagramme

Damit nicht für jede Bildlaufleiste und jedes Drehfeld eigene Ereignisprozeduren angelegt werden müssen, überwacht man deren verknüpfte Zellen. Zum Überwachen wird in einer beliebigen Zelle eine Formel angelegt. Ich habe dafür die Funktion ZÄHLENWENN benutzt, welche den zu überwachenden Bereich als Argument zugewiesen bekommt. Eine Änderung in dem Bereich, sei es durch Handeingabe oder durch die Manipulation der Bildlaufleisten, löst anschließend das Worksheet_CalculateEreignis aus, das Change-Ereignis des Tabellenblattes würde hingegen nur durch eine Handeingabe getriggert. Die einzige Aufgabe des Worksheet_Calculate-Ereignisses besteht darin, die Prozedur ChangeStyle aufzurufen.

Diagramme

왘 Mit der Bildlaufleiste in Zeile 11 wird die Rotation in Y-Richtung eingestellt.

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

2471_Excel-VBA.book Seite 560 Dienstag, 4. Dezember 2007 1:42 13

560 >> Wände, Böden und Perspektive von 3-D-Diagrammen

Die Prozedur ChangeStyle liest die gesetzten Werte aus dem Tabellenblatt und ändert die Diagrammeigenschaften. Zu Beginn werden die gesetzten Werte ausgelesen und in Variablen gespeichert. Einige der Werte stellen einen Index dar, beispielsweise solche, die einen Stil wie das Hintergrundmuster oder den Linienstil angeben. Der Index kann dabei Werte zwischen 1 und der Anzahl der vorhandenen Stile in der zugehörigen Auflistung annehmen. Die Min- und Max-Eigenschaftswerte der zugehörigen Bildlaufleisten begrenzen dabei die Auswahl. Mit dem Index selbst kann man noch nicht viel anfangen, deshalb existieren Übersetzungsfunktionen, die diesen in den Konstantennamen und den zugehörigen Wert umwandeln. Der Einfachheit halber liefern die Funktionen die Ergebnisse als Text, wobei der Konstantenname und der zugehörige Wert durch ein Gleichheitszeichen voneinander getrennt sind. Der zurückgelieferte Text wird nach dem Auslesen des Index direkt in das Tabellenblatt neben der zugehörigen Bildlaufleiste geschrieben. Anschließend werden die Rotation, die Perspektive und die Betrachtungshöhe des Diagramms angepasst. Die zugehörigen Eigenschaftswerte des Chart-Objektes sind Rotation, Perspective und Elevation. Zu beachten ist, dass der Eigenschaftswert RightAngleAxes auf Falsch gesetzt wird. Nun wird der Boden formatiert, das zu manipulierende Objekt ist das Floor-Klassenobjekt. Das Füllmuster (Interior.Pattern) wird durch einen Eigenschaftswert aus der Auflistung XlPattern bestimmt. Die Übersetzungsfunktion TranslateXlPattern liefert den Konstantenname und den zugehörigen Wert, welche durch ein Gleichheitszeichen voneinander getrennt sind. Diese, wie auch bei den anderen verwendeten Übersetzungsfunktionen, benötigen als Funktionsargument einen Ganzzahlenwert, welcher zwischen 1 und der Anzahl der vorhandenen Elemente in der zugehörigen Auflistung annehmen kann. Der durch die Übersetzungsfunktion zurückgelieferte Text wird mit der Split-Funktion in ein Array umgewandelt, dessen erstes Element den Index 0 besitzt, das Trennzeichen ist dabei das Gleichheitszeichen. Das Element mit dem Index 1 enthält nun den eigentlichen Wert in Textform mit einem führenden Leerzeichen, welches man mit Hilfe der Umwandlungsfunktion cLng in einen Ganzzahlenwert vom Typ Long umwandelt. Diesen Wert übergibt man an die Eigenschaft Pattern des InteriorObjektes. Die Füllfarbe des Bodens wird nur gesetzt, wenn es sich beim Muster um den Typ xlPatternNone (-4142) oder xlPatternSolid (1) handelt. Im anderen Fall wird die Farbe auf weiß gesetzt, damit das Muster, welches anschließend die gleiche Farbe zugewiesen bekommt, überhaupt zu sehen ist. Nun wenden wir uns dem Linienstil zu. Da die Variable lngLineStyle ein Index in die Auflistung XlLineStyle ist, wird sie ähnlich wie beim Muster mit der Übersetzungsfunktion TranslateXlLineStyle und der Split-Funktion in den Eigenschaftswert umgewandelt und der Eigenschaft Border.LineStyle des Floor-Klassenobjekt zugewiesen.

'=================================================================== ' Auf CD Buchdaten\Beispiele\08_Diagramme\ ' Dateiname 08_13_WallFloorRotate.xlsm ' Tabelle Wände, Böden, Ausrichtung ' Modul Tabelle Wände, Böden, Ausrichtung '=================================================================== Private Sub ChangeStyle() Dim strOutput Dim objChart Dim objFloor Dim objWalls Dim objBackWall Dim lngLineStyle Dim lngLineWidth Dim lngWallsPattern Dim rngWallsPatternOut Dim lngWallsColor Dim lngBackWallPattern Dim rngBackWallPatternOut Dim lngBackWallColor Dim lngFloorPattern Dim rngFloorPatternOut Dim lngFloorColor Dim lngRotation Dim lngPerspective Dim lngElevation

As As As As As As As As As As As As As As As As As As As

String Object Object Object Object Long Long Long Range Long Long Range Long Long Range Long Long Long Long

Diagramme Diagramme

Mit den Wänden (Walls) und der Rückwand (BackWall) wird nun genauso verfahren wie beim Boden (Floor), jedoch werden die auf dem Tabellenblatt individuell für diese Objekte gesetzten Werte benutzt. Lediglich der Rahmenstil ist für alle drei Objekte gleich.

Diagramme

Für eine Anpassung der Rahmendicke gehen wir wie folgt vor: Da die Variable lngLineWidth ein Index in die Auflistung XlBorderWeight ist, wird sie ähnlich wie beim Muster mit der Übersetzungsfunktion TranslateXlBorderWeight und der Split-Funktion in den Eigenschaftswert umgewandelt und der Eigenschaft Border.LineWeight zugewiesen.

Diagramme

561

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 561 Dienstag, 4. Dezember 2007 1:42 13

Listing 323

Diagramme

' Objektvariablen definieren Set objChart = Me.ChartObjects(1).Chart Set objFloor = objChart.Floor Set objWalls = objChart.Walls Set objBackWall = objChart.BackWall

Diagramme

Application.EnableEvents = False

Diagramme

Diagramme

2471_Excel-VBA.book Seite 562 Dienstag, 4. Dezember 2007 1:42 13

562 >> Wände, Böden und Perspektive von 3-D-Diagrammen ' Rotation, Perspektive und Betrachtungshöhe lngRotation = Me.Range("L9") lngPerspective = Me.Range("L10") lngElevation = Me.Range("L11") ' Linienstil (Punkt/Strich) lngLineStyle = Me.Range("K8") Me.Range("L8") = TranslateXlLineStyle(lngLineStyle)

Diagramme

Diagramme

Diagramme

' Linienbreite lngLineWidth = Me.Range("K7") Me.Range("L7") = TranslateXlBorderWeight(lngLineWidth) ' Muster/Farbe Wände lngWallsPattern = Me.Range("K1") Set rngWallsPatternOut = Me.Range("L1") lngWallsColor = RGB(Me.Range("L2"), Me.Range("M2"), _ Me.Range("N2")) ' Muster/Farbe Rückwand lngBackWallPattern = Me.Range("K3") Set rngBackWallPatternOut = Me.Range("L3") lngBackWallColor = RGB(Me.Range("L4"), Me.Range("M4"), _ Me.Range("N4")) ' Muster/Farbe Boden lngFloorPattern = Me.Range("K5") Set rngFloorPatternOut = Me.Range("L5") lngFloorColor = RGB(Me.Range("L6"), Me.Range("M6"), _ Me.Range("N6"))

Diagramme

Diagramme

Diagramme

On Error Resume Next With objChart ' Rotation, Perspektive und Betrachtungshöhe .Rotation = lngRotation .RightAngleAxes = False .Perspective = lngPerspective .Elevation = lngElevation End With With objFloor ' Füllmuster strOutput = TranslateXlPattern(lngFloorPattern) rngFloorPatternOut = strOutput .Interior.Pattern = CLng(Split(strOutput, "=")(1)) ' Füllfarbe If (.Interior.Pattern = -4142) Or _ Listing 323 (Forts.)

Listing 323 (Forts.)

Diagramme Diagramme Diagramme Diagramme Diagramme Diagramme

(.Interior.Pattern = 1) Then .Interior.Color = lngFloorColor Else ' Weiß .Interior.Color = RGB(255, 255, 255) End If ' Musterfarbe .Interior.PatternColor = lngFloorColor ' Rahmen, Linienstil und Farbe strOutput = TranslateXlLineStyle(lngLineStyle) .Border.LineStyle = CLng(Split(strOutput, "=")(1)) .Border.Weight = lngLineWidth End With With objWalls ' Füllmuster strOutput = TranslateXlPattern(lngWallsPattern) rngWallsPatternOut = strOutput .Interior.Pattern = CLng(Split(strOutput, "=")(1)) ' Füllfarbe If (.Interior.Pattern = -4142) Or _ (.Interior.Pattern = 1) Then .Interior.Color = lngWallsColor Else ' Weiß .Interior.Color = RGB(255, 255, 255) End If ' Musterfarbe .Interior.PatternColor = lngWallsColor ' Rahmen, Linienstil und Farbe strOutput = TranslateXlLineStyle(lngLineStyle) .Border.LineStyle = CLng(Split(strOutput, "=")(1)) .Border.Weight = lngLineWidth End With With objBackWall ' Füllmuster strOutput = TranslateXlPattern(lngBackWallPattern) rngBackWallPatternOut = strOutput .Interior.Pattern = CLng(Split(strOutput, "=")(1)) ' Füllfarbe If (.Interior.Pattern = -4142) Or _ (.Interior.Pattern = 1) Then .Interior.Color = lngBackWallColor Else ' Weiß .Interior.Color = RGB(255, 255, 255) End If ' Musterfarbe

563

Diagramme

>> Diagramme

Diagramme

2471_Excel-VBA.book Seite 563 Dienstag, 4. Dezember 2007 1:42 13

Diagramme

Diagramme

2471_Excel-VBA.book Seite 564 Dienstag, 4. Dezember 2007 1:42 13

564 >> Wände, Böden und Perspektive von 3-D-Diagrammen .Interior.PatternColor = lngBackWallColor ' Rahmen, Linienstil und Farbe strOutput = TranslateXlLineStyle(lngLineStyle) .Border.LineStyle = CLng(Split(strOutput, "=")(1)) .Border.Weight = lngLineWidth End With Application.EnableEvents = True End Sub

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Diagramme

Listing 323 (Forts.)

Die drei Übersetzungsfunktionen TranslateXlBorderWeight, TranslateXlLineStyle und TranslateXlPattern finden Sie im Quelltext.

Ereignisse

Ereignisse

2471_Excel-VBA.book Seite 565 Dienstag, 4. Dezember 2007 1:42 13

Wenn sich noch keine PERSONAL.xlsb in Ihrem XLSTART-Ordner befindet, wählen Sie bei der Makroaufzeichnung als Speicherort PERSÖNLICHE MAKROARBEITSMAPPE aus. Daraufhin wird die PERSONAL.xlsb angelegt und muss nur noch gespeichert werden. Diese Datei wird dann künftig bei jedem Start der Excel-Anwendung im Hintergrund mit geladen. Andere geöffneten ExcelArbeitsmappen können auf die in dieser Excel Datei gespeicherten Makros zugreifen.

Ereignisse Ereignisse

Ereignisse

Tip p

Das erste Makro erstellen die meisten Anwender, indem Sie auf der Registerkarte ENTWICKLERTOOLS in der Gruppe CODE die Schaltfläche MAKRO AUFZEICHNEN aufrufen, den Makrorekorder starten und dann einige Aktionen auf dem Tabellenblatt ausführen. In dem Dialogfenster MAKRO AUFZEICHNEN laut Abbildung 187 geben Sie vor, in welcher Arbeitsmappe das Makro gespeichert werden soll.

Ereignisse

Bevor wir auf die Ereignisse eingehen, geben wir Ihnen zum besseren Verständnis eine kurze Zusammenfassung über die Entstehung und Ausführung von herkömmlichen Prozeduren.

Ereignisse

194 Allgemeine Prozeduren

Excel erstellt nach dem Start der Makroaufzeichnung im entsprechenden VBAPROJECT der ausgewählten Arbeitsmappe ein neues Standardmodul. Die durchgeführten Aktionen, zum Beispiel:

Ereignisse

Abbildung 187: Speicherort des Makros vorgeben

왘 Daten eingeben 왘 Einrichten der Kopf- und Fußzeilen

Ereignisse

왘 Zellen formatieren

2471_Excel-VBA.book Seite 566 Dienstag, 4. Dezember 2007 1:42 13

Tipp

werden von Excel »mitgeschrieben« und entweder in dem neu angelegten oder in einem bereits vorhandenen Standardmodul gespeichert. Die Standardmodule werden standardmäßig mit MODUL(N) fortlaufend benannt, zum Beispiel MODUL1, MODUL2 etc. Im Eigenschaften-Fenster des Moduls können Sie zur besseren Orientierung den Modulnamen umbenennen. Der Modulname muss mit einem Buchstaben beginnen und darf keine Leer- oder Sonderzeichen enthalten. Achten Sie darauf, dass Modulnamen nicht identisch mit einem Makronamen sind, da es sonst zu Namenskonflikten kommen kann. (Modulname: MYMAKRO; Sub MyMakro)

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

566 >> Allgemeine Prozeduren

Abbildung 188: Module eines VBAProject '=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_01_Events.xlsm ' Modul mdl_MyMakro '=============================================================== Public Sub MyMakro() With Range("A1") .FormulaR1C1 = "=TODAY()" .NumberFormat = "MMMM YYYY" End With With Range("A1").Font .Name = "Arial" .FontStyle = "Fett" .Size = 14 End With End Sub Listing 324

Aufgezeichnete, bzw. selbst erstellte Makros können, wenn sie öffentlich mit der Bezeichnung Sub oder Public Sub deklariert sind, über verschiedene Möglichkeiten aufgerufen werden. Einen manuellen Aufruf erzielen Sie zum Beispiel über den

2471_Excel-VBA.book Seite 567 Dienstag, 4. Dezember 2007 1:42 13

567

Befinden Sie sich in der VBA-Umgebung, genügt es wenn Sie den Schreibcursor innerhalb einer Prozedur in einer Zeile positionieren. Durch Drücken der Taste (F5) wird das gesamte Makro durchlaufen. Durch einzelnes Drücken der Taste (F8) wird die aktivierte Prozedur in Einzelschritten ausgeführt. Dies sind nur zwei der möglichen Varianten ein Makro durch den Anwender manuell zu starten.

Ereignisse

Abbildung 189: Makro manuell starten

Ereignisse

Ereignisse

Ereignisse

Menüpunkt ENTWICKLERTOOLS | MAKROS. Wählen Sie aus den angezeigten Prozeduren das gewünschte Makro aus und klicken auf AUSFÜHREN um das Makro zu starten.

Ereignisse

>> Ereignisse

Excel unterscheidet bei den Ereignissen, ob es sich um eine Änderung handelt welche die Arbeitsmappe Workbook betrifft, oder ob eine Aktion in oder an einem Tabellenblatt Worksheet aufgetreten ist. Aus diesem Grund werden die entsprechenden Prozeduren in den dafür vorgesehenen Containern des VBAProjektes hinterlegt. In

Ereignisse

VBA ist eine ereignisorientierte Programmiersprache. Ereignisse kann man mit den Aktionen des Anwenders vergleichen. Öffnen Sie zum Beispiel eine Excel Datei, so ist das erste mögliche Ereignis bereits eingetreten. Excel interpretiert das Öffnen einer Datei als Workbook_Open-Ereignis. Das Schließen einer Datei wird von Excel über das Workbook_Close-Ereignis kontrolliert und stellt das letztmögliche Ereignis einer Excel-Arbeitsmappe dar. Dazwischen gibt es eine schier unzählige Anzahl von Ereignissen, von denen wir Ihnen in diesem Kapitel die wichtigsten anhand von Beispielen erklären werden.

Ereignisse

Im Gegensatz zu den oben beschriebenen, manuell zu startenden Makros, kann Excel auf bestimmte Ereignisse reagieren und dadurch automatisch hinterlegte Befehle zu dem jeweiligen Ereignis ausführen.

Ereignisse

195 Ereignis-Prozeduren

2471_Excel-VBA.book Seite 568 Dienstag, 4. Dezember 2007 1:42 13

Abbildung 188 sehen Sie, dass allgemeine Makros in Standardmodulen gespeichert werden. Ereignisse rund um die Arbeitsmappe werden im Codemodul des Klassenmoduls DIESEARBEITSMAPPE hinterlegt. Für die Tabellenblatt-Ereignisse ist das Codemodul des betreffenden Tabellenblattes, zum Beispiel TABELLE1, vorgesehen.

Ereignisse

Ereignisse

Ereignisse

568 >> Workbook-Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Abbildung 190: Speicherort für Workbook-Ereignisse

Ereignis-Prozeduren beginnen grundsätzlich mit den Wörtern Private Sub. Aus diesem Grund werden sie nicht wie öffentliche Prozeduren unter ENTWICKLERTOOLS | MAKROS in der Liste der vorhandenen Makros (siehe Abbildung 189) aufgeführt und können nicht manuell aufgerufen werden. In einer Arbeitsmappe können Sie jeweils nur ein gleichnamiges Ereignis einsetzen. Wollen Sie mehrere Befehle bei einem auftretenden Ereignis ausführen, müssen diese in »einer« Ereignis-Prozedur vereint und nacheinander abgearbeitet werden. Um Ihnen zu einem Ereignis verschiedene Beispiele aufzeigen zu können, verwenden wir unterschiedliche Arbeitsmappen. Dem Hinweistext oberhalb einer Prozedur entnehmen Sie jeweils den Dateinamen und das Modul, in welchem der Code zu finden ist. Nachfolgend werden die Workbook- und Worksheet-Ereignisse getrennt erläutert.

196 Workbook-Ereignisse Wie im vorherigen Abschnitt bereits erwähnt, werden die Workbook-Ereignisse im Container DIESEARBEITSMAPPE der VBAPROJECTE gespeichert. Befinden Sie sich bereits im VBA-Editor genügt ein Doppelklick auf DIESEARBEITSMAPPE um in der rechten Fensterhälfte das Codeblatt von DIESEARBEITSMAPPE anzuzeigen. Um ein neues Ereignis in Ihre Arbeitsmappe zu integrieren, müssen Sie nicht die komplette Syntax der Aufrufzeile auswendig lernen oder in der Online Hilfe oder sonstiger Lektüre nachschlagen. Oberhalb des Codefensters von DIESEARBEITSMAPPE befinden sich zwei Listenfelder. Klicken Sie zunächst auf den DropDown-Pfeil des linken Listenfeldes OBJEKT und wählen Sie den Eintrag WORKBOOK. Excel erstellt daraufhin die Codeschablone des ersten möglichen Ereignisses: Workbook_Open.

2471_Excel-VBA.book Seite 569 Dienstag, 4. Dezember 2007 1:42 13

569

Ereignisse

Ereignisse

>> Ereignisse

Ereignisse

Klicken Sie jetzt auf den DropDown-Pfeil des rechten Listenfeldes PROZEDUR und erhalten eine Liste aller verfügbarer Ereignisprozeduren für das Tabellenblatt. Durch Auswahl und Klick auf einen Eintrag in dieser Liste wird das entsprechende Codegerüst im Codeblatt erzeugt.

Ereignisse

Abbildung 191: Codegerüst einer Ereignis-Prozedur

Private Sub Workbook_Open() MsgBox "Hallo " & Application.UserName End Sub

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_01_ Events.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

Zwischen der Aufruf- und Schlusszeile können Sie die Befehlszeilen einfügen, die bei Eintritt des Ereignisses ausgeführt werden sollen. In unserem ersten Beispiel wird der hinterlegte Benutzername ausgelesen und in einem Meldungsfenster angezeigt. Wenn Sie die Beispieldatei öffnen und die Ausführung von Makros erlauben, wird das hinterlegte Workbook_Open-Ereignis ausgeführt. Sie werden über ein Meldungsfenster mit dem in den Excel-Optionen hinterlegtem Benutzernamen begrüßt.

Ereignisse

Abbildung 192: Listenfeld der vorhandenen Workbook-Ereignisprozeduren

In Excel 2007 wurden aufgrund neuer Funktionen in der Excel Bedienungsoberfläche auch einige entsprechende neue Ereignisse der Objektbibliothek hinzugefügt:

Ereignisse

Listing 325

2471_Excel-VBA.book Seite 570 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

570 >> Workbook-Ereignisse

왘 AfterXmlExport-Ereignis 왘 AfterXmlImport-Ereignis

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

왘 BeforeXmlImport-Ereignis 왘 RowsetComplete-Ereignis 왘 Sync-Ereignis Achtung

Ereignisse

Ereignisse

왘 BeforeXmlExport-Ereignis

Wenn Sie die oben genannten neuen Ereignisse in Dateien mit Excel 2007 erstellen, werden diese bei Verwendung der Datei in älteren Excel Versionen nicht ausgeführt. Eine Fehlermeldung erfolgt jedoch nicht.

Nachfolgend finden Sie eine Zusammenfassung aller möglichen Ereignisse, die Sie für die Arbeitsmappe verwenden können. In der zweiten Spalte »Beschreibung« erfahren Sie, wann der Aufruf erfolgt und welche Besonderheiten es zu den einzelnen Ereignissen gibt. Die Liste enthält alle möglichen Ereignisse, welche in der Excel-Version »Excel 2007« zur Verfügung stehen. In anderen Excel-Versionen kann es Abweichungen geben. Ereignis

Aufruf/Beschreibung

Workbook_Activate

Wenn eine Arbeitsmappe aktiviert wird.

Workbook_AddinInstall

Wenn ein Add-In eingebunden wird. 왘 durch Einbinden über den Add-Ins-Manager 왘 durch direktes Öffnen des Add-Ins

Workbook_AddinUninstall

Wenn ein Add-In über den Add-Ins-Manager deaktiviert wird.

Workbook_AfterXmlExport

Nachdem von Microsoft Excel XML-Daten aus der angegebenen Arbeitsmappe gespeichert oder exportiert wurden.

Workbook_AfterXmlImport

Nachdem eine bestehende XML-Datenverbindung aktualisiert wurde oder nachdem neue XML-Daten in die angegebene Microsoft Excel-Arbeitsmappe importiert wurden.

Workbook_BeforeClose

Bevor eine Arbeitsmappe geschlossen wird.

Workbook_BeforePrint

Bevor ein Druckauftrag ausgeführt wird.

Workbook_BeforeSave

Bevor eine Arbeitsmappe gespeichert wird.

Workbook_BeforeXmlExport

Bevor XML-Daten aus der angegebenen Arbeitsmappe von Microsoft Excel gespeichert oder exportiert werden.

Workbook_BeforeXmlImport

Bevor eine bestehende XML-Datenverbindung aktualisiert wird oder bevor neue XML-Daten in eine Microsoft ExcelArbeitsmappe importiert werden.

Tabelle 41: Alle Ereignisse für die Arbeitsmappe

2471_Excel-VBA.book Seite 571 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse

Workbook_Open

Wenn eine Arbeitsmappe geöffnet wird.

Workbook_PivotTableCloseConnection

Nachdem ein PivotTable-Bericht die Verbindung zu seiner Datenquelle geschlossen hat.

Workbook_PivotTableOpenConnection

Nachdem ein PivotTable-Bericht die Verbindung zu seiner Datenquelle geöffnet hat.

Workbook_RowsetComplete

Wenn der Benutzer einen Drillthrough durch das Recordset ausführt oder die Rowset-Aktion für eine OLAP-PivotTable aufruft.

Workbook_SheetActivate

Wenn ein beliebiges Tabellen- oder Diagrammblatt der Arbeitsmappe aktiviert wird.

Workbook_SheetBeforeDouble Click

Wenn in einer Zelle eines beliebigen Tabellenblattes der Arbeitsmappe mit der linken Maustaste ein Doppelklick durchgeführt wird.

Workbook_SheetBeforeRightClick

Wenn in einer Zelle oder Zeilen-/Spaltenkopf eines beliebigen Tabellenblattes der Arbeitsmappe ein Klick mit der rechten Maustaste durchgeführt wird. Die übliche Anzeige des Kontextmenüs nach einem Rechtsklick erfolgt nach Verarbeitung der EreignisProzedur.

Workbook_SheetCalculate

Nachdem in einem beliebigen Tabellenblatt einer beliebigen geöffneten Arbeitsmappe eine Neuberechnung ausgeführt wurde. Dieses Ereignis ist das einzige, welches auch bei Neuberechnungen in einer anderen geöffneten Arbeitsmappe aufgerufen wird.

Workbook_SheetChange

Nachdem auf einem beliebigen Tabellenblatt der Arbeitsmappe ein Zellinhalt geändert wird.

Ereignisse

Wenn ein neues Blatt in die Arbeitsmappe eingefügt wird. 왘 Tabellenblatt 왘 Diagrammblatt 왘 Makroblatt Tritt nicht ein wenn 왘 ein Blatt innerhalb der Arbeitsmappe kopiert oder verschoben wird. 왘 ein Blatt aus einer anderen Arbeitsmappe importiert wird.

Ereignisse

Workbook_NewSheet

Ereignisse

Wenn eine Arbeitsmappe deaktiviert wird, indem eine andere Excel-Arbeitsmappe aktiviert oder die Arbeitsmappe minimiert wird.

Ereignisse

Workbook_Deactivate

Ereignisse

Aufruf/Beschreibung

Ereignisse

Ereignis

Ereignisse

571

Ereignisse

Tabelle 41: Alle Ereignisse für die Arbeitsmappe (Forts.)

2471_Excel-VBA.book Seite 572 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

572 >> Workbook-Ereignisse Ereignis

Aufruf/Beschreibung

Workbook_SheetDeactivate

Nachdem ein beliebiges Tabellenblatt verlassen wurde und dafür ein anderes Tabellenblatt der Arbeitsmappe aktiviert wird. 왘 Tritt vor dem Workbook_SheetActivate-Ereignis ein.

Workbook_SheetFollowHyperlink

Wenn der Anwender auf einen in einer Zelle hinterlegten Hyperlink in einer beliebigen Tabelle klickt.

Workbook_SheetPivotTableUpdate

Wenn eine Pivot-Tabelle auf einem beliebigen Tabellenblatt aktualisiert wird.

Workbook_SheetSelectionChange

Wenn sich die Zellmarkierung auf einem beliebigen Tabellenblatt der Arbeitsmappe ändert. 왘 Bei Zellwechsel 왘 Bei Markierung von Zeilen-/Spaltenköpfen

Workbook_Sync

Wenn die lokale Kopie eines Arbeitsblatts, das Teil eines Dokumentarbeitsbereichs ist, mit der Kopie auf dem Server synchronisiert wird.

Workbook_WindowActivate

Wenn das Arbeitsmappenfenster der Arbeitsmappe aktiviert wird. 왘 Tritt nach dem Workbook_Activate -Ereignis ein.

Workbook_WindowDeactivate

Wenn das Arbeitsmappenfenster der Arbeitsmappe deaktiviert wird. 왘 Tritt vor dem Workbook_Deactivate -Ereignis ein.

Workbook_WindowResize

Wenn die Größe des Arbeitsmappenfensters geändert oder die Arbeitsmappe minimiert wird. Ist das Arbeitsmappenfenster nicht maximiert und wird von einer anderen Arbeitsmappe zu dieser gewechselt, treten folgende Ereignisse nacheinander ein: 1. Workbook_Activate 2. Workbook_WindowActivate 3. Workbook_WindowResize

Tabelle 41: Alle Ereignisse für die Arbeitsmappe (Forts.)

Ereignisse

Ereignisse

In der Beispieldatei werden alle Workbook-Ereignisse überwacht. Sobald ein Ereignis eintritt, werden Sie über ein Meldungsfenster mit Angabe des aufgerufenen Ereignisses informiert. Da wir hier aus Platzgründen nicht alle Makros der Beispieldatei aufführen können, stellen wir Ihnen an dieser Stelle stellvertretend für alle weiteren Ereignisse das erste und letzte Ereignis aus der Liste vor.

2471_Excel-VBA.book Seite 573 Dienstag, 4. Dezember 2007 1:42 13

Private Sub Workbook_Activate() MsgBox "Workbook_Activate" End Sub Private Sub Workbook_WindowResize(ByVal Wn As Window) MsgBox "Workbook_WindowResize" End Sub Listing 326

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_02_AllWorkbookEvents.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

573

Ereignisse

>> Ereignisse

=DATUM(JAHR(HEUTE());1;1) ' für Januar

zusammen und sind im benutzerdefinierten Format »MMMM« formatiert. Die Beschriftung der Tabellenregister haben wir nicht händisch nach dem entsprechenden Monat aus dem Zellinhalt A1 vorgenommen, sondern diese Aufgabe einem kleinen Makro übergeben. Die erste Möglichkeit, die Monatsnamen mit VBA zu ermitteln besteht darin, den Datumswert über die Value-Eigenschaft der Zelle A1 mit der Format-Funktion analog zum benutzerdefinierten Zahlenformat in einen vergleichbaren String umzuwandeln.

Ereignisse

Oft verwendet man eine Exceldatei um Daten eines Jahres in einzelnen Monatsblättern abzulegen. Praktisch wäre es, wenn gleich nach dem Öffnen einer Jahresmappe das Tabellenblatt des aktuellen Monats angezeigt würde. In unserer Beispieldatei 09_03_WorkbookOpenFindSheet.xls stehen in jedem Tabellenblatt in der Zelle A1 fortlaufend die Monatsnamen. Diese setzten sich aus der Formel

Ereignisse

197 Aktuelles Monatsblatt anzeigen

Ereignisse

Zu den wichtigsten Ereignissen haben wir in den nächsten Rezepten einige Beispiele zusammengestellt.

Als Alternative bietet es sich an, nicht den tatsächlichen Wert der Zelle über die Value-Eigenschaft anzunehmen, sondern den sichtbaren Text der Zelle, wie er durch das definierte benutzerdefinierte Zahlenformat angezeigt wird. Der angezeigte Text einer Zelle wird mit der Text-Eigenschaft ermittelt:

Ereignisse

Format(ws.Range("A1").Value, "MMMM")

Kommt derselbe Monatsname in mehreren Tabellenblättern in der Zelle A1 vor, würde Excel bei dem Versuch einen bereits verwendeten Tabellennamen noch einmal zu vergeben eine Fehlermeldung ausgeben. Diese Fehlermeldung fangen wir in der

Ereignisse

ws.Range("A1").Text

2471_Excel-VBA.book Seite 574 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

574 >> Aktuelles Monatsblatt anzeigen

Prozedur RenameSheetName mit der Anweisung On Error Resume Next ab. Der ursprüngliche Tabellenname wird in diesem Fall beibehalten. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_03_WorkbookOpenFindSheet.xlsm ' Modul mdl_01_RenameSheetName ‘=============================================================== Public Sub RenameSheetName() Dim ws As Worksheet ' Alle Tabellenblätter durchlaufen For Each ws In ActiveWorkbook.Worksheets On Error Resume Next ' Monatsname mit Text-Eigenschaft auslesen ws.Name = ws.Range("A1").Text Next End Sub Listing 327

Nach dem Öffnen der Datei wird das Workbook_Open-Ereignis aktiv und liest den aktuellen Monat anhand des eingestellten Datums aus der Systemsteuerung aus. Dieses Datum wird im Monatsformat MMMM in der Variablen strName festgehalten. Anstelle der Format-Funktion kann man in VBA die MonthName-Funktion dazu verwenden, aus der numerischen Bezeichnung eines Monats (1–12) den entsprechenden Monatsnamen als Zeichenfolge zu ermitteln. Die Syntax dazu lautet: MonthName(Monat[Abbreviate])

Über den optionalen Parameter Abbreviate kann angegeben werden, ob der Monatsname in abgekürzter Schreibweise Jan zurückgegeben wird. Die Standardeinstellung dieses Arguments ist False. Das bedeutet, wenn er in der Methode ausgelassen wird, wird der ermittelte Monatsname in ausgeschriebener Schreibweise geliefert: Januar. Um den aktuellen Monat als numerischen Wert zu ermitteln, verwendet man die

Month-Funktion und gibt das Datum über die Date-Funktion an. Im Monat März

liefert folgende Syntax den Wert 3:

Ereignisse

Month(Date)

-> 3

Diese beiden verschachtelten Funktionen werden nun in der MonthName-Funktion integriert. Folgende Syntax liefert die Zeichenkette März: MonthName(Month(Date))

-> März

Ereignisse

Durch obige Syntax wird der ermittelte Monatsname in ausgeschriebener Schreibweise zurückgegeben. Um den Monatsnamen in abgekürzter Schreibweise zu erhalten verwendet man: MonthName(Month(Date), Abbreviate := true)

-> Mrz

2471_Excel-VBA.book Seite 575 Dienstag, 4. Dezember 2007 1:42 13

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_03_WorkbookOpenFindSheet.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_Open() Dim strName As String Dim ws As Worksheet

Ereignisse

Excel würde eine Fehlermeldung ausgeben, wenn in der Arbeitsmappe kein Tabellenblatt mit dem Namen des aktuellen Monats existiert. Aus diesem Grund fragen wir in einer Schleife alle vorhandenen Tabellenblattnamen ab. Wenn das Blatt gefunden ist, wird es selektiert und die Prozedur beendet. Ist kein Tabellenblatt mit dem angeforderten Monat vorhanden, erscheint eine im Code definierte Fehlermeldung.

Ereignisse

575

Ereignisse

>> Ereignisse

' Alle Tabellenblätter der aktiven Arbeitsmappe durchlaufen For Each ws In ActiveWorkbook.Worksheets ' Prüfung, ob Blattname mit Monatsname übereinstimmt If ws.Name = strName Then

Ereignisse

' aktuellen Monatsname aus Datum ermitteln strName = Format(Date, "MMMM")

Listing 328

Ereignisse Ereignisse

' Meldung wird nur angezeigt, wenn in Schleifendurchlauf ' kein Tabellenblatt mit aktuellem Monatsnamen gefunden wurde MsgBox "Das Tabellenblatt" & _ vbNewLine & _ " """ & strName & """" & _ vbNewLine & _ "existiert nicht in dieser Arbeitsmappe!", _ vbExclamation End Sub

Ereignisse

' Prozedur verlassen Exit Sub End If Next

Ereignisse

' Tabellenblatt aktivieren Worksheets(strName).Select

2471_Excel-VBA.book Seite 576 Dienstag, 4. Dezember 2007 1:42 13

198 Ereignisse ignorieren Es gibt einen kleinen Trick, um Ereignisprozeduren schon vor dem Öffnen einer Excel-Datei vorübergehend zu deaktivieren.

H i n we i s

Für das folgende Beispiel ist es in Excel 2007 notwendig, die Einstellungen für Makros wie folgt vorzunehmen. Zeigen Sie mit Klicks auf die OFFICE-SCHALTFLÄCHE | EXCEL-OPTIONEN | VERTRAUENSSTELLUNGSCENTER | EINSTELLUNGEN FÜR DAS VERTRAUENSSTELLUNGSCENTER | EINSTELLUNGEN FÜR MAKROS die möglichen Optionen zu Behandlung von Makros an (siehe Abbildung 193). Aktivieren Sie die Option ALLE MAKROS MIT BENACHRICHTIGUNG DEAKTIVIEREN. Beim Deaktivieren von Ereignissen bei Dateiöffnung spielt es keine Rolle, ob die zu öffnende Excel Datei in einem VERTRAUENSWÜRDIGEN SPEICHERORT gespeichert ist oder nicht.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

576 >> Ereignisse ignorieren

Ereignisse

Ereignisse

Hinweis

Ereignisse

Abbildung 193: Sicherheits Einstellungen für Makros

Bis einschließlich Excel 2003 muss die Sicherheitsstufe auf Mittel eingestellt sein. Dann erhalten Sie beim Öffnen einer Excel-Arbeitsmappe die Makros enthält, einen Startdialog. In diesem müssen Sie angeben, ob die Datei mit oder ohne Makrounterstützung geöffnet wird. Halten Sie die (Shift)-Taste auf Ihrer Tastatur gedrückt und klicken dann im Startdialog auf die Schaltfläche MAKROS AKTIVIEREN. Auf diese Weise werden alle vorhandenen Ereignis-Prozeduren ignoriert.

In Excel 2007 hat sich die Vorgehensweise zur vorherigen Versionen verändert. Die Ursache liegt in der neuen Funktionsweise des Vertrauensstellungsscenters begründet. So ist es nicht mehr möglich, Ereignisse beim Start einer Datei zu deaktivieren, wenn die Datei über den Windows Explorer geöffnet wird. Einzig beim Öffnen einer Excel-Arbeitsmappe direkt aus Excel heraus können vorhandene Ereignisprozeduren deaktiviert werden. Starten Sie eine Excel-Arbeitsmappe

2471_Excel-VBA.book Seite 577 Dienstag, 4. Dezember 2007 1:42 13

Starten Sie die Beispieldatei über die OFFICE SCHALTFLÄCHE | ÖFFNEN. Suchen Sie die Datei auf Ihrem Computer und markieren sie im Öffnen-Dialogfenster. Halten Sie nun die (Shift)-Taste gedrückt während Sie die Schaltfläche ÖFFNEN ausführen. In der Datei sind das Workbook_Open-, sowie Worksheet_SelectionChange-Ereignis hinterlegt. Diese werden solange nicht ausgeführt bis Ereignisse durch einen Sub-Aufruf aktiviert werden. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_04_IgnoreEvents.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse Ereignisse

Im Gegensatz zu einer Arbeitsmappe in welcher Makros deaktiviert wurden, werden bei dieser Methode manuell aufgerufene Makros weiterhin ausgeführt. Sobald eine allgemeine Prozedur abgearbeitet wurde, sind auch die Ereignis-Prozeduren wieder einsatzbereit. Befindet sich eine benutzerdefinierte Funktion in einem Modul der Datei, dann wird diese durch eine Neuberechnung des Tabellenblattes aufgerufen. Dieser Vorgang löst ebenfalls die Aktivierung von Ereignis-Prozeduren aus.

Ereignisse

entweder aus der Liste der ZULETZT VERWENDETEN DOKUMENTE, oder öffnen eine beliebige Excel-Datei über die ÖFFNEN-Schaltfläche im Menü der Office-Schaltfläche. Halten Sie bereits beim Aufruf zum Öffnen einer Excel-Arbeitsmappe die (Shift)-Taste gedrückt. Je nach Einstellungen im Vertrauensstellungcenter erfolgt eine zusätzliche Abfrage, ob Makros de- oder aktiviert werden sollen. Wenn die Datei aus einem Ordner heraus geöffnet wird, der nicht als vertrauenswürdiger Speicherort definiert ist, wird der aus Excel 2003 bekannte Makro Hinweisdialog angezeigt. Im Gegensatz zu älteren Excel-Versionen muss hier nicht die (Shift)-Taste gedrückt werden, während die Schaltfläche MAKROS AKTIVIEREN ausgeführt wird.

Ereignisse

577

Ereignisse

>> Ereignisse

Private Sub Worksheet_SelectionChange(ByVal Target As Range) ‘ Zellbezug der aktuellen Zellmarkierung anzeigen MsgBox Target.Address(0, 0) End Sub Listing 330

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_04_IgnoreEvents.xlsm ' Ereignis EnableEvents ‘===============================================================

Ereignisse

Listing 329

Ereignisse

Private Sub Workbook_Open() MsgBox "Datei wird geöffnet" End Sub

2471_Excel-VBA.book Seite 578 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

578 >> Ereignisse aus- und einschalten

Zur Aktivierung von ignorierten Ereignissen muss ein beliebiges Makro oder Funktion durchlaufen werden. Die Prozedur muss nicht einmal Befehle enthalten, der Makroaufruf alleine reicht schon für die Aktivierung aus. In der Prozedur AbleEvents haben wir das kürzeste Makro, dass es in VBA gibt, einer Schaltfläche zugewiesen. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_04_IgnoreEvents.xlsm ' Modul mdl_01_AbleEvents ‘===============================================================

Ereignisse

Public Sub AbleEvents() End Sub Listing 331

Ereignisse

Ereignisse

199 Ereignisse aus- und einschalten Wenn Sie eine Excel-Datei mit deaktivierten Makros öffnen, dann werden in der Arbeitsmappe weder Ereignis-Prozeduren noch allgemeine Makros und Funktionen ausgeführt. Erst nachdem die Mappe geschlossen wurde und mit aktivierten Makros startet, sind alle verfügbaren Prozeduren wieder einsatzbereit. Haben Sie eine Arbeitsmappe mit Makrounterstützung geöffnet, dann sind vorhandene Ereignis-Prozeduren wie Workbook_Open und Workbook_Aktivate bereits abgearbeitet. Erst danach können Ereignisse mit der EnableEvents-Eigenschaft deaktiviert werden. Wenn Sie zum Beispiel eine Datei speichern wollen, ohne das BeforeSave-Ereignis auszulösen, deaktivieren Sie vorab alle Ereignisse. Application.EnableEvents = False ActiveWorkbook.Save

Ereignisse

Ereignisse

Ereignisse

Application.EnableEvents = True

Damit Ereignis-Prozeduren wieder ausgeführt werden, muss dieser Befehl am Ende der Prozedur wieder zurückgesetzt werden. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_04_IgnoreEvents.xlsm ' Modul mdl_02_Events ‘=============================================================== Public Sub EventsDeaktivate() ‘ Ereignisse deaktivieren Application.EnableEvents = False End Sub Listing 332

2471_Excel-VBA.book Seite 579 Dienstag, 4. Dezember 2007 1:42 13

In der Beispielmappe zeigt das StartSheet ein Excel-Meldungsfenster in Form einer Grafik, welche wir selbst angefertigt haben, an (Wie die Grafik erzeugt wurde erfahren Sie nach dem Codebeispiel). Erstellen Sie eine Prozedur und lassen Ihren Text in einem Meldungsfenster MsgBox anzeigen. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_05_UnableWithoutMakros.xlsm ' Tabelle StartSheet ' Modul mdl_01_ErrorMessage ‘=============================================================== Public Sub ErrorMessage() MsgBox _ "Sollte dieser Startbildschirm nicht automatisch " & _ "nach ca. 5 Sekunden ausgeblendet werden," & _ vbNewLine & _ "wurde die Ausführung von Makros in dieser Arbeitsmappe" & _ " untersagt!" & _ Listing 333

Ereignisse Ereignisse

Das Prinzip ist relativ einfach. Vor jedem Speichern der Datei wird ein »Startblatt« StartSheet eingeblendet und aktiviert. Alle anderen Tabellen- und Diagrammblätter der Arbeitsmappe werden mit der xlSheetVeryHidden-Methode der Worksheet-Eigenschaft Visible ausgeblendet. Durch diese Eigenschaft können die ausgeblendeten Blätter über START | ZELLEN | FORMAT | SICHTBARKEIT | AUSBLENDEN & EINBLENDEN | BLATT EINBLENDEN nicht mehr eingeblendet werden. Nach dem Speichervorgang werden die verwendeten Blätter der Arbeitsmappe wieder sichtbar gemacht und das StartSheet ausgeblendet. Beim Öffnen der Datei ist also nur ein Blatt in der Arbeitsmappe sichtbar: das StartSheet. Hier können Sie Informationen für den Anwender hinterlegen. Den Informationstext schreiben Sie zum Beispiel in eine Zelle des Startblattes und formatieren das Blatt nach Ihren eigenen Vorstellungen.

Ereignisse

Manchmal wird eine Excel-Datei durchgängig von Makros unterstützt und gesteuert. Zum Beispiel wird beim Öffnen der Arbeitsmappe eine Symbolleiste mit integrierten Prozeduren zur Bedienung des Programms erstellt, oder bestimmte Funktionen sollen für den Anwender nicht ausführbar sein. Wir wollen nun erreichen, dass eine Datei für den Anwender nur mit Makrounterstützung zu gebrauchen ist.

Ereignisse

200 Excel-Datei ohne Makros unbrauchbar

Ereignisse

Listing 332 (Forts.)

Ereignisse

Public Sub EventsAktivate() ‘ Ereignisse aktivieren Application.EnableEvents = True End Sub

Ereignisse

579

Ereignisse

>> Ereignisse

2471_Excel-VBA.book Seite 580 Dienstag, 4. Dezember 2007 1:42 13

vbNewLine & vbNewLine & _ "Mögliche Einstellungen für Makros im „ & _ „Vertrauensstellungscenter:" & _ vbNewLine & _ "- Alle Makros ohne Benachrichtigung deaktivieren" & _ vbNewLine & _ "- Alle Makros außer digital signierten deaktivieren" & _ vbNewLine & _ "- Beim Programmstart wurden Makros deaktiviert" & _ vbNewLine & vbNewLine & _ "Diese Datei kann ohne Makrounterstützung nicht" & _ " bearbeitet werden." & _ vbNewLine & _ "Zur Bearbeitung müssen Sie diese Datei neu starten und" & _ " Makros aktivieren.", _ vbExclamation + vbDefaultButton2, _ "Information" End Sub Listing 333 (Forts.)

Rufen Sie das Makro manuell mit der Taste (F5) auf um das Meldungsfenster anzuzeigen. Aus dieser Meldung können Sie nun eine eigenständige Grafik erzeugen indem Sie die Tastenkombination (Alt) (Druck) drücken, während die Meldung auf dem Bildschirm angezeigt wird. Durch diese Tastenkombination wird das aktive Fenster (Meldungsfenster) als Grafik in die Zwischenablage befördert. Nachdem Sie das Meldungsfenster mit einem Klick auf OK geschlossen haben, fügen Sie über START | EINFÜGEN die erzeugte Grafik, auch »Screenshot« (Bildschirmfoto) genannt, in Ihr Tabellenblatt ein.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

580 >> Excel-Datei ohne Makros unbrauchbar

Abbildung 194: Meldungsfenster als Grafik erstellen

Auf den zweiten Blick fällt Ihnen bestimmt auf, dass die Abbildung 194 kein Originalabbild des erzeugten Meldungsfensters aus dem Makro ErrorMessage ist. Wir haben den OK-Button und das Schließen-Kreuz verschwinden lassen. Diese Grafik

2471_Excel-VBA.book Seite 581 Dienstag, 4. Dezember 2007 1:42 13

Markieren Sie die Grafik und klicken oberhalb der Registerkarten auf dem neuen Register BILDTOOLS | FORMAT. Daraufhin wird eine Multifunktionsleiste mit Funktionen zur Bildbearbeitung angezeigt. Klicken Sie in der Gruppe SCHRIFTGRAD auf ZUSCHNEIDEN und führen den Cursor an den oberen/unteren Rand der Grafik. Halten Sie jeweils die linke Maustaste gedrückt und schieben die Grafik zum Abschneiden zur Mitte der Grafik, bis die gewünschte Größe erreicht ist.

Ereignisse

Die Liste der verschiedenen Optionen zum Blattschutz wurde mit Excel 2002 eingeführt und steht vorherigen Excel-Versionen nicht zur Verfügung.

Arbeiten Sie mit älteren Excel-Versionen als Excel 2002, dann ist es möglich, bei eingeschaltetem Blattschutz gesperrte Zellen auszuwählen. Erst bei dem Versuch einen Inhalt zu ändern wird Excel mit einer Fehlermeldung antworten. Um in älteren Excel-Versionen das Selektieren gesperrter Zellen bei eingestelltem Blattschutz zu verhindern, müssen Sie bei jedem Öffnen der Arbeitsmappe im Workbook_Open-Ereignis den Befehl dazu neu setzen. Verwenden Sie dazu folgende Anweisung:

Ereignisse

Abbildung 195: Blattschutzoptionen auswählen

Ereignisse

Ereignisse

Hinweis

Das Startblatt wurde mit einem Blattschutz und dem Passwort Codebook versehen. Da die Beispieldatei mit der Excel 2007-Version erstellt wurde haben wir im Register ÜBERPRÜFEN in der Gruppe ÄNDERUNGEN | BLATT SCHÜTZEN nur die Option NICHT GESPERRTE ZELLEN AUSWÄHLEN aktiviert. Diese Einstellung bewirkt, dass auf diesem Blatt nur die nicht gesperrten Zellen markiert oder geändert werden können.

Ereignisse

ruft keine Aktionen hervor, und würde als »echtes« Dialogfeld eventuell Verwirrung beim Anwender stiften.

Ereignisse

581

Ereignisse

>> Ereignisse

Ereignisse

Worksheets("Tabelle1").EnableSelection = xlUnlockedCells

2471_Excel-VBA.book Seite 582 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Tipp

Ereignisse

582 >> Excel-Datei ohne Makros unbrauchbar

Ausführliche Informationen und Beispiele zum Blattschutz finden Sie in der Kategorie »Allgemein«

Kommen wir wieder zurück zu unserer Beispielmappe. Zunächst beschäftigen wir uns mit dem Ausblenden der relevanten Blätter der Datei und dem Anzeigen des Startblattes. Das Makro HideSheets wird in einem allgemeinen Modul mit der Option Private Module-Anweisung gespeichert (siehe auch Abschnitt 197, auf Seite 573). In diesem Modul wird die Variable wsMemorySheet öffentlich deklariert, damit das Makro ShowSheets, das in einem anderen Modul gespeichert ist, ebenfalls auf diese Variable zugreifen kann. Bevor die Blätter ausgeblendet werden, wird der Name des gerade aktiven Blattes in dieser Variablen gespeichert. Beim späteren Einblenden der Blätter nach dem Speichervorgang, wird das vor der Speicherung aktive Blatt wieder selektiert. Ohne diese Maßnahme würde Excel das letzte Blatt in der Reihe der Tabellenregister auf dem Bildschirm anzeigen und nicht das zuletzt aktive. Weitere Erläuterungen zum Ablauf des Makros wurden als Kommentar im Code hinterlegt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_05_UnableWithoutMakros.xlsm ' Modul mdl_02_HideSheets ‘===============================================================

Ereignisse

Ereignisse

Ereignisse

Option Explicit Option Private Module Public wsMemorySheet As Worksheet Public Sub HideSheets() Dim objSheet As Object Dim strName As String ' Alle nachfolgende genannten Arbeitsblätter referenzieren ' auf diese Arbeitsmappe With ThisWorkbook ' Aktives Tabellenblatt vor Speicherung merken Set wsMemorySheet = .ActiveSheet ' Name des Startblattes strName = "StartSheet" ' Startblatt einblenden .Worksheets(strName).Visible = xlSheetVisible

Ereignisse

' Alle Blätter bis auf das "StartSheet" verstecken Listing 334

2471_Excel-VBA.book Seite 583 Dienstag, 4. Dezember 2007 1:42 13

For Each objSheet In .Sheets If objSheet.Name strName Then objSheet.Visible = xlSheetVeryHidden End If Next objSheet End With End Sub

Ereignisse

583

Ereignisse

>> Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_05_UnableWithoutMakros.xlsm ' Modul mdl_03_ShowSheets ‘=============================================================== Option Explicit Option Private Module

Ereignisse

Das nachfolgende Makro blendet alle Blätter der Arbeitsmappe wieder ein und versteckt das Startblatt vor dem Zugriff des Anwenders.

Ereignisse

Listing 334 (Forts.)

' Name des Startblattes strName = "StartSheet"

Ereignisse

Public Sub ShowSheets() Dim objSheet As Object Dim strName As String

' Startblatt verstecken .Worksheets(strName).Visible = xlSheetVeryHidden

Ereignisse

' Alle Blätter einblenden For Each objSheet In .Sheets If objSheet.Name strName Then objSheet.Visible = xlSheetVisible End If Next objSheet

Ereignisse

' Alle nachfolgende genannten Arbeitsblätter referenzieren ' auf diese Arbeitsmappe With ThisWorkbook

Listing 335

Ereignisse

' Prüfung, ob Variable initialisiert ist If Not wsMemorySheet Is Nothing Then ' Aktives Tabellenblatt vor Speicherung selektieren

2471_Excel-VBA.book Seite 584 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

584 >> Excel-Datei ohne Makros unbrauchbar wsMemorySheet.Select End If End With

Ereignisse

Ereignisse

Ereignisse

Ereignisse

End Sub Listing 335 (Forts.)

Wenn Sie in der Beispieldatei Makros deaktivieren, dann sehen Sie nur das Startblatt STARTSHEET mit der als Grafik hinterlegten Meldung. Um den Eindruck einer nicht funktionsfähigen Datei zu verstärken, wurde vor dem letzten Schließen der Datei die Anzeige der Blattregister sowie der Bildlaufleisten ausgeblendet. In Excel 2007 finden Sie diese Einstellungen über die OFFICE-SCHALTFLÄCHE | EXCEL-OPTIONEN | ERWEITERT | OPTIONEN FÜR DIESE ARBEITSMAPPE. Bei einem Öffnen der Arbeitsmappe ohne Makrounterstützung werden die deaktivierten Optionen nicht angezeigt werden. Kommen wir nun zu den Ereignis-Prozeduren dieses Beispiels, welche im Klassenmodul DIESEARBEITSMAPPE hinterlegt sind. Starten Sie die Beispieldatei mit Makrounterstützung, dann wird zunächst das Startblatt angezeigt, bevor direkt im Anschluss das Workbook_Open-Ereignis und das darin enthaltene Makro ShowSheets aufgerufen wird. Für einen kurzen Augenblick ist das Startblatt für den Anwender sichtbar. Damit dieses Aufblitzen des Tabellenblattes mit der Informationsmeldung nicht als Fehler bewertet wird, halten wir das Makro über die Wait-Methode fünf Sekunden lang an, bevor die Bildschirmaktualisierung wieder aktiviert und das Makro beendet wird. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_05_UnableWithoutMakros.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

Ereignisse

Private Sub Workbook_Open() 'Bildschrimaktualisierung ausschalten Application.ScreenUpdating = False ' Blätter einblenden ShowSheets ' Blattregister und Bildlaufleisten einblenden With ActiveWindow .DisplayWorkbookTabs = True .DisplayHorizontalScrollBar = True .DisplayVerticalScrollBar = True End With

Ereignisse

Listing 336

2471_Excel-VBA.book Seite 585 Dienstag, 4. Dezember 2007 1:42 13

585

' offizielles Anfangsblatt selektieren Worksheets(1).Select

Ereignisse

>> Ereignisse

'Bildschrimaktualisierung einschalten Application.ScreenUpdating = True End Sub

Ereignisse

' Makro 5 Sekunden anhalten Application.Wait (Now + TimeValue("0:00:05"))

Sobald die Datei vom Anwender gespeichert wird, müssen wir eingreifen, um »vor« dem Speichervorgang alle sichtbar vorhandenen Blätter der Datei aus- und das Startblatt wieder einzublenden. Schauen wir uns zunächst die Aufrufzeile des Workbook_BeforeSave-Ereignisses_ an:

Ereignisse

Listing 336 (Forts.)

Innerhalb des Workbook_BeforeSave-Ereignisses soll die Arbeitsmappe zwischen dem Aus- und Einblenden der Blätter gespeichert werden. Da in der Ereignisprozedur der eigentliche, vom Anwender ausgelöste, Speicher Befehl unterdrückt und durch VBA Code ersetzt wird, muss über den SaveAsUI-Parameter ermittelt werden, welche Speicherart der Anwender gewählt hat. In einer If...Then...Else-Anweisung wird der Wahrheitswert der Variablen SaveAsUI ermittelt, um den SPEICHERN UNTER-Befehl ebenfalls zu berücksichtigen.

Ereignisse Ereignisse

Der Wert Wahr wird an die Variable SaveAsUI übertragen, wenn die Speicherungsart SPEICHERN UNTER auswählt wurde. Standardmäßig kann diese Funktion entweder über die OFFICE-SCHALTFLÄCHE | SPEICHERN UNTER, die Taste (F12) oder durch VBA-Code herbeigeführt werden.

Ereignisse

Hat der Anwender die Funktion SPEICHERN gewählt, dann wird der Variablen SaveAsUI der Wert Falsch übergeben. Dabei spielt es keine Rolle, ob der Speicher-Befehl über die OFFICE-SCHALTFLÄCHE | SPEICHERN, das Speichern-Symbol in der Schnellstartleiste oder durch die Tastenkombination (Strg) (S) ausgelöst wurde. Auch bei einem durch VBA ausgelösten Speichervorgang wird zwischen SPEICHERN und SPEICHERN UNTER unterschieden und der Wert der jeweiligen Speicherart den Parameter SaveAsUI übergeben.

Ereignisse

In der Parameterliste wird der Parameter SaveAsUI vom Datentyp Boolean angegeben. Durch das vorangestellte Schlüsselwort ByVal gilt dieser Parameter als Wertparameter und tritt innerhalb der Prozedur als eigenständige Variable auf. Der Wert dieser Variablen kann durch die nachfolgende Prozedur verändert werden. Welcher Wert an SaveAsUI übergeben wird, entscheidet sich anhand der ausgeführten Speicherart durch die das Ereignis aufgerufen wurde.

Ereignisse

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, _ Cancel As Boolean)

2471_Excel-VBA.book Seite 586 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

586 >> Excel-Datei ohne Makros unbrauchbar

Der zweite Parameter, Cancel vom Datentyp Boolean, der in der Aufrufzeile des Workbook_BeforeSave-Ereignisses angegeben wird, ist für unsere Beispieldatei besonders wichtig. Wird der Standardwert False innerhalb der Prozedur nicht auf True geändert, dann wird der Speicherbefehl, welches das Ereignis ausgelöst hat, vor Beendigung der Prozedur nochmals ausgeführt. Dabei wird ein vorheriger Speichervorgang durch den Code nicht berücksichtigt. Dies wäre für unser Beispiel fatal, weil zu diesem Zeitpunkt wieder alle Blätter sichtbar sind und in diesem Zustand gespeichert würden. Bei einem erneuten Öffnen der Beispielmappe stünden alle Blätter zur Verfügung und das Startblatt bliebe im Hintergrund versteckt. Setzen Sie den Wahrheitswert des Parameters Cancel auf True um den Ereignis-Speichervorgang zu unterdrücken. Deaktivieren Sie vor dem Speichern alle Ereignis-Aufrufe über die EnableEventsEigenschaft. Der Befehl ThisWorkbook.Save würde ansonsten einen weiteren Aufruf des Workbook_BeforeSave-Ereignisses bewirken. Im weiteren Verlauf der aufgerufenen Prozeduren würde dies unweigerlich zu Fehlermeldungen führen. Aktivieren Sie nach dem Speichervorgang die Ereignis-Aufrufe wieder, damit Excel wieder auf eintretende Ereignisse reagieren kann. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_05_UnableWithoutMakros.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, _ Cancel As Boolean) 'Bildschrimaktualisierung ausschalten Application.ScreenUpdating = False

Ereignisse

Ereignisse

'Blätter ausblenden HideSheets 'Ereignisse deaktivieren Application.EnableEvents = False If SaveAsUI = True Then ' »Speichern unter« wurde gewählt Application.Dialogs(xlDialogSaveAs).Show Else ' »Speichern« wurde gewählt ThisWorkbook.Save

Ereignisse

Listing 337

2471_Excel-VBA.book Seite 587 Dienstag, 4. Dezember 2007 1:42 13

587

End If

Ereignisse

>> Ereignisse

' Speichern aufgrund Workbook_BeforeSave-Ereignis zurücksetzen Cancel = True End Sub Listing 337 (Forts.)

Ereignisse

Will der Benutzer die Beispielmappe zu diesem Rezept schließen, dann wird die Arbeitsmappe im Workbook_Close-Ereignis für den nächsten Öffnen-Vorgang vorbereitet. Das Workbook_Close-Ereignis tritt ein, wenn der Anwender über die OFFICESCHALTFLÄCHE | SCHLIESSEN oder das »Schließen-Kreuz« des aktiven Fensters, bzw. die Tastenkombination (Strg) (F4) die Datei schließen will.

Ereignisse

' Bildschrimaktualisierung einschalten Application.ScreenUpdating = True

Ereignisse

' Blätter einblenden ShowSheets

Ereignisse

' Ereignisse aktivieren Application.EnableEvents = True

Ereignisse

Bis Excel 2003 war es möglich, über das DATEI-Menü mit einem kleinen Trick alle derzeitigen Arbeitsmappen zu schließen. Halten Sie in den Versionen vor Excel 2007 die (Shift)-Taste gedrückt und klicken mit der rechten Maustaste auf den Menüpunkt DATEI. Im Gegensatz zu der üblichen Option SCHLIESSEN sehen Sie jetzt die Option ALLE SCHLIESSEN.

Ereignisse

Das Workbook_Close-Ereignis wird ebenfalls ausgelöst, wenn die gesamte ExcelAnwendung mit allen geöffneten Arbeitsmappen geschlossen wird.

Ereignisse

Abbildung 196: Aktive Excel-Datei schließen

2471_Excel-VBA.book Seite 588 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

588 >> Excel-Datei ohne Makros unbrauchbar

In Excel 2007 wurde der Befehl ALLE SCHLIESSEN nicht in die Multifunktionsleiste aufgenommen. Um den Befehl anzuwenden, muss der Befehl über das ANPASSEN Dialogfenster, dass Sie über die EXCEL-OPTIONEN anzeigen können zur SYMBOLLEISTE FÜR DEN SCHNELLZUGRIFF hinzugefügt werden.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Abbildung 197: Geänderte Schließen-Option in Excel 2003

Abbildung 198: Einen Befehl der Schnellstart Symbolleiste hinzufügen

Alternativ können Sie über das »Schließen-Kreuz« der Excel-Anwendung, bzw. die Tastenkombination (Alt) (F4) alle geöffneten Excel-Dateien und die Excel-Anwendung selbst schließen. Werden in einer Excel-Datei nach dem letzten Speichervorgang weitere Änderungen durchgeführt, dann werden Sie vor dem Schließen von Excel über ein Meldungsfenster gefragt, ob Sie diese Änderungen speichern wollen. In unserem Beispiel wollen

2471_Excel-VBA.book Seite 589 Dienstag, 4. Dezember 2007 1:42 13

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_05_UnableWithoutMakros.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_BeforeClose(Cancel As Boolean) ' Bildschrimaktualisierung ausschalten Application.ScreenUpdating = False

Ereignisse

wir aber auf jeden Fall die Datei vor dem Schließen speichern, um unser Startblatt für die nächste Dateiöffnung wieder hervorzuholen. Über dieser Speicherung setzen Sie den Benutzer der Datei durch ein Meldungsfenster in Kenntnis. Bevor die Datei gespeichert und anschließend geschlossen wird, werden alle Blätter der Datei durch das aufgerufene Makro HideSheets wieder versteckt, das Startblatt angezeigt und die Blattregister sowie Bildlaufleisten ausgeblendet.

Ereignisse

589

Ereignisse

>> Ereignisse

' Blattregister und Bildlaufleisten ausblenden With ActiveWindow .DisplayWorkbookTabs = False .DisplayHorizontalScrollBar = False .DisplayVerticalScrollBar = False End With

Ereignisse

' Blätter ausblenden HideSheets

Ereignisse

MsgBox "Diese Datei wird beim Beenden automatisch gespeichert"

' Ereignisse deaktivieren Application.EnableEvents = False

' Ereignisse aktivieren Application.EnableEvents = True

Ereignisse

ThisWorkbook.Save

Ereignisse

Listing 338

Ereignisse

' Bildschrimaktualisierung einschalten Application.ScreenUpdating = True End Sub

2471_Excel-VBA.book Seite 590 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

201 Datei nur mit Makrounterstützung anzeigen Es gibt eine sehr einfache Möglichkeit, die Anzeige einer Excel-Arbeitsmappe zu verhindern, wenn Makros vom Benutzer deaktiviert werden. Beim Schließen der Beispielmappe wird dazu im Workbook_BeforeClose-Ereignis die IsAddin-Eigenschaft auf True gestellt. Dadurch besitzt die Arbeitsmappe folgende Merkmale: 왘 Das Arbeitsmappenfenster ist nicht sichtbar. 왘 Es können keine Tabellenblätter eingeblendet werden. 왘 Eventuell in der Arbeitsmappe enthaltene Makros werden im Makro-Dialogfeld nicht dargestellt (das Dialogfeld wird angezeigt, wenn Sie auf der Registerkarte Ansicht auf Makros klicken). 왘 Sie werden nicht aufgefordert, die Arbeitsmappe zu speichern, falls Änderungen vorgenommen werden, während die Arbeitsmappe geöffnet ist. 왘 Makros der Arbeitsmappe können, obwohl sie nicht angezeigt werden, über das Makro-Dialogfeld ausgeführt werden. 왘 Wenn Sie beim Öffnen der Arbeitsmappe die (Shift)-Taste gedrückt halten, hat dies keine Wirkung. 왘 Durch die Dateiendung *.xls wird die Arbeitsmappe nicht als Add-In (*.xla) erkannt und steht nicht unter EXCEL-OPTIONEN | ADD-INS ... zur Auswahl zur Verfügung. Nachdem die IsAddin-Eigenschaft auf True gestellt wurde, muss die Arbeitsmappe mit VBA-Code gespeichert werden. Excel würde ansonsten beim Beenden das SPEICHERN-Dialogfenster anzeigen. Würde dieses verneint und wurde die Datei vorher mit der IsAddin-Eigenschaft False gespeichert, würde die Mappe mit dem Standardwert False der AddIns-Eigenschaft gespeichert. Achtung

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

590 >> Datei nur mit Makrounterstützung anzeigen

Diese Methode funktioniert in allen Excel-Versionen von 97 bis 2003 und dem Dateiformat *.xls einwandfrei. In Excel 2007 hingegen ist es nicht mehr möglich die IsAddin-Eigenschaft auf True zu setzen und die Datei anschließend in einem für Makros erlaubten Dateiformate *.xlsm oder *.xlsb zu speichern. Wird versucht die Datei als *.xlsm zu speichern, erfolgt ein Hinweisfenster, dass die Datei nicht in diesem Dateiformat gespeichert werden kann. Die Speicherung als *.xlsb wird zwar unter VBA anstandslos ausgeführt, jedoch wird die IsAddIn-Eigenschaft bei der nächsten Dateiöffnung automatisch auf False gestellt. Dabei spielt es keine Rolle, ob die Datei mit oder ohne Makrounterstützung geöffnet wird. Durch dieses Verhalten eignen sich die neuen Dateiformate nicht dazu eine Excel 2007 Arbeitsmappe gegen Deaktivierung von Makros zu schützen. Zum jetzigen Standpunkt empfehlen wir, die Datei in Excel 2007 im alten Dateiformat als Excel 97–2003-Arbeitsmappe (*.xls) zu speichern.

2471_Excel-VBA.book Seite 591 Dienstag, 4. Dezember 2007 1:42 13

Wenn der Anwender diese Datei ohne Makrounterstützung öffnet, wird sie als Add-In geladen und das Arbeitsmappenfenster wird in der Excel-Ansicht nicht angezeigt. Sie können die Datei dann lediglich im Visual Basic-Editor sehen und bearbeiten. Um die Mappe wieder normal ansehen und zu bearbeiten, stellen Sie die IsAddin-Eigenschaft im Eigenschaftsfenster des Codemoduls DieseArbeitsmappe auf False. Makros sind dadurch jedoch weiterhin deaktiviert. Anwender, welche keine VBA-Kenntnisse haben, oder ein vorhandenes VBA-Projekt-Passwort nicht kennen, müssen zunächst die Excel-Anwendung beenden. Nur dadurch wird die Add-In-Mappe ebenfalls geschlossen. Wird die Datei anschließend mit Makrounterstützung geöffnet, erfolgt im Workbook_Open-Ereignis die Einstellung der IsAddin-Eigenschaft auf False. Dadurch ist die Arbeitsmappe wieder eine voll funktionsfähige Excel-Arbeitsmappe und verhält sich ganz normal. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_06_JustWithMacros.xls ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_Open() ThisWorkbook.IsAddin = False End Sub

Ereignisse Ereignisse

Listing 339

Ereignisse

Private Sub Workbook_BeforeClose(Cancel As Boolean) With ThisWorkbook .IsAddin = True .Save End With End Sub

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_06_JustWithMacros.xls ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

591

Ereignisse

>> Ereignisse

Über den Befehl START | ZELLEN | EINFÜGEN | BLATT EINFÜGEN oder die Tastenkombination (Shift) (F11) fügen Sie in die aktive Arbeitsmappe ein neues Tabellenblatt ein. Sowohl bei diesem manuellen Einfügen durch den Anwender, als auch durch das Einfügen neuer Blätter via VBA-Code wird das Workbook_NewSheet-Ereignis ausgelöst. Nachfolgende Befehle fügen in der aktiven Arbeitsmappe jeweils ein Tabellenblatt ein.

Ereignisse

202 Registerreiter neu nummerieren

Ereignisse

Listing 340

2471_Excel-VBA.book Seite 592 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

592 >> Registerreiter neu nummerieren Sheets.Add

' erstellt ein Tabellenblatt

Sheets.Add Type:=xlWorksheet ' erstellt ein Tabellenblatt

Um ein Diagrammblatt einzufügen, verwenden Sie die XlSheetType-Konstante xlChart: ' erstellt ein Diagrammnblatt

Das neu erstellte Tabellenblatt wird automatisch zum aktiven Blatt und im Tabellenregister links neben dem zuletzt aktiven Blatt eingefügt. Excel gibt diesem Tabellenblatt selbständig einen Namen, welcher sich standardmäßig aus dem Wort TABELLE und der Anzahl der seit Erstellung der Arbeitsmappe eingefügten Blätter zusammensetzt. Bestand eine Arbeitsmappe zum Beispiel aus zehn Tabellenblättern und Sie haben neun davon gelöscht, dann wird ein neu erstelltes Tabellenblatt den Namen TABELLE11 erhalten, obwohl in dem Augenblick nur zwei Tabellenblätter in der Arbeitsmappe vorhanden sind. Unabhängig von den Tabellenblättern werden Diagrammblätter in gleicher Weise benannt und durchnummeriert, DIAGRAMM1, DIAGRAMM2 etc. Auf einem Tabellenblatt eingebettete Diagramme können in ein eigenständiges Diagrammblatt verschoben werden, indem Sie das Diagramm markieren und über die Registerkarten DIAGRAMMTOOLS | ENTWURF den Befehl DIAGRAMM VERSCHIEBEN anklicken.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Sheets.Add Type:=xlChart

Ereignisse

Abbildung 199: Diagramm in Neues Blatt verschieben

2471_Excel-VBA.book Seite 593 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse

Ausführliche Informationen zu Diagrammen finden Sie in der Kategorie »Diagramme«.

In Abbildung 200 sehen Sie, dass durch das Einfügen, Löschen oder Verschieben von Blättern in einer Arbeitsmappe leicht ein heiles Durcheinander der einzelnen Registerbeschriftungen entstehen kann.

Abbildung 200: Registerreiterbeschriftung

Nachdem Sie ein Tabellen- oder Diagrammblatt in Ihre Arbeitsmappe eingefügt haben, vergibt Excel nach oben beschriebener Namensgebung einen entsprechenden Namen. Erst im Anschluss an die Namensvergabe wird das Workbook_NewSheet-Ereignis ausgelöst. Überraschenderweise gibt es in Excel kein analoges Ereignis, das vor dem Löschen eines Blattes ausgelöst wird.

Ereignisse Ereignisse

Mit nachfolgenden Makro werden alle in der Excel-Datei vorhandenen Blätter beschriftet und fortlaufend nummeriert. Die beiden Blatt-Typen, Tabellenblatt und Diagrammblatt, werden dabei getrennt durchnummeriert. Das Ergebnis sehen Sie in Abbildung 201.

Ereignisse

' erstellt ein Diagrammblatt ' erstellt ein Diagrammblatt

Ereignisse

H i n we i s

Charts.Add Sheets.Add Type:=xlChart

Ereignisse

Mit folgenden Syntaxen erzeugen Sie mit VBA ein neues Diagrammblatt in der aktiven Arbeitsmappe.

Ereignisse

Auch für das Einfügen eines Diagrammblattes gibt es eine Tastenkombination: Markieren Sie den Bereich Ihrer Tabelle, welche Sie als Diagramm erstellen möchten und drücken die Tastenkombination (Windows-Taste) (F11). Anhand des markierten Bereichs erstellt Excel daraufhin ein neues Diagrammblatt mit den Standardeinstellungen der Diagramm-Optionen.

Ereignisse

593

Ereignisse

Abbildung 201: Geordnete Registerreiterbeschriftung

2471_Excel-VBA.book Seite 594 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

594 >> Registerreiter neu nummerieren

In der Beispieldatei erfolgt im Workbook_NewSheet-Ereignis lediglich ein Aufruf der Prozedur RenameSheetTabs zur Durchführung der Beschriftung. Die Prozedur RenameSheetTabs wird in einem allgemeinen Modul gespeichert. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_07_RenameWorkbookTabs.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Private Sub Workbook_NewSheet(ByVal Sh As Object) RenameSheetTabs End Sub Listing 341 ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_07_RenameWorkbookTabs.xlsm ' Modul mdl_01_RenameSheetTabs ‘=============================================================== Public Dim Dim Dim

Sub RenameSheetTabs() lngItem As Long lngSh As Long lngCh As Long

' Bildschirmaktualisierung aussschalten Application.ScreenUpdating = False ' alle Blätter fortlaufend nummerieren, um Fehler' meldungen durch doppelte Namensvergabe verhindert For lngItem = 1 To ActiveWorkbook.Sheets.Count Sheets(lngItem).Name = lngItem Next lngItem ' Beginn der Nummerierungen bei 1 lngSh = 1 lngCh = 1 ' Alle Arbeitsblätter der Datei durchlaufen For lngItem = 1 To ActiveWorkbook.Sheets.Count ' Prüfung, ob Arbeitsblatt ein Tabellenblatt ist If TypeName(Sheets(lngItem)) = "Worksheet" Then ' Tabellenblätter durchnummerieren Sheets(lngItem).Name = "Seite " & lngSh Listing 342

2471_Excel-VBA.book Seite 595 Dienstag, 4. Dezember 2007 1:42 13

lngSh = lngSh + 1 ' Prüfung, ob Arbeitsblatt ein Diagrammblatt ist ElseIf TypeName(Sheets(lngItem)) = "Chart" Then ' Diagrammblätter durchnummerieren Sheets(lngItem).Name = "Diagramm " & lngCh lngCh = lngCh + 1 End If

Ereignisse

595

Ereignisse

>> Ereignisse

' Bildschirmaktualisierung einschalten Application.ScreenUpdating = True End Sub Listing 342 (Forts.)

Ereignisse

Next lngItem

Ereignisse

Abbildung 203: Fehlermeldung bei doppelter Namensvergabe

Ereignisse

Abbildung 202: Fehlermeldung bei Namensvergabe

Ereignisse

Ereignisse

Wenn Sie einen Registerreiter beschriften wollen, müssen dabei mehrere Kriterien beachtet werden: Siehe Abbildung 202 und Abbildung 203.

Ereignisse

203 Neues Blatt beschriften

2471_Excel-VBA.book Seite 596 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Hinwei s

Im Gegensatz zu vorherigen Excel-Versionen kann der Benutzer in Excel 2007 über die Oberfläche keine unzulässigen Sonderzeichen in Registerbeschriftungen schreiben. : \ / ? * [ ]

Der Versuch ein nicht erlaubtes Sonderzeichen zu schreiben wird von Excel ignoriert. Eine Fehlermeldung wird bei dieser Aktion nicht ausgegeben.

Ereignisse

Ereignisse

596 >> Neues Blatt beschriften

Hingegen löst die Verwendung von Sonderzeichen als Registerbeschriftung mit VBA Code die Fehlermeldung in Abbildung 202 aus. In diesem Beispiel verwenden wir das Workbook_NewSheet-Ereignis um ein neu eingefügtes Blatt über ein Eingabefenster InputBox zu beschriften. Die Kopf- und Fußzeilen werden ebenfalls über diese Prozedur eingerichtet. In der Aufrufzeile

Ereignisse

Private Sub Workbook_NewSheet(ByVal Sh As Object)

wird der Parameter Sh als eigenständige Object-Variable an die Prozedur übergeben. Diese enthält alle Eigenschaften des eingefügten Blattes. In unserem Code wird diese Variable zum Beispiel dazu verwendet, den Blattnamen als Default-Text in der Eingabezeile einer InputBox anzuzeigen. Des Weiteren können Sie dem Sh-Objekt innerhalb der ausgelösten Ereignis-Prozedur auch Methoden zuweisen. Mit nachfolgendem Befehl wird das eingefügte Blatt an die letzte Stelle der Registereiter gesetzt.

Ereignisse

In unserem Beispiel erfolgt die Namensvergabe über eine InputBox. Diese wird innerhalb einer Do...Loop-Schleife solange aufgerufen, bis Sie entweder einen gültigen Namen eingeben, oder deren ABBRECHEN-Schaltfläche anklicken. Die Verwendung der ABBRECHEN Schaltfläche liefert den booleschen Wert False. Da die InputBox aber einen Wert vom String Datentyp erwartet, muss die Variable zur Aufnahme des Eingabewertes beide Datentypen verwalten können. Aus diesem Grund wird die verwendete Variable als Variant deklariert. Achtung

Ereignisse

Ereignisse

Sh.Move After:=Sheets(Sheets.Count)

Eine Variant-Variable, die einen String-Wert enthält, kann nicht mit einer If...Then...Else-Anweisung auf einen booleschen Wert überprüft werden. Folgender Code liefert eine Typenunverträglichkeit-Fehlermeldung, wenn die Variable einen Text enthält: If varSheetName = False Then

Verwenden Sie zur Überprüfung eines booleschen Wertes in einer Variant-Variablen stattdessen die Select Case-Anweisung:

Ereignisse

Select Case varSheetName Case False

2471_Excel-VBA.book Seite 597 Dienstag, 4. Dezember 2007 1:42 13

Die Fehlerroutine zur Überprüfung eines gültigen Blattnamens erfolgt in der Funktion IsSheetNameOK(MyName As String) und wird in der Loop Until-Zeile der Do...Loop-Schleife aufgerufen. Die Do...Loop-Schleife wird solange wiederholt, bis die Funktion IsSheetNameOK den booleschen Wert Wahr zurückgibt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_08_NewSheetName.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_NewSheet(ByVal Sh As Object) Dim varSheetName As Variant

Ereignisse

Nachdem die InputBox abgebrochen und die nachfolgende Sicherheitsabfrage mit OK bestätigt wurde, wird das eingefügte Blatt gelöscht und die Prozedur beendet.

Ereignisse

597

Ereignisse

>> Ereignisse

' in MsgBox wurde Ja geklickt ' Warnhinweise deaktivieren Application.DisplayAlerts = False

Ereignisse Ereignisse

' Auswertung der »Abbrechen« Schaltfläche Select Case varSheetName Case False ' Abbrechen wurde geklickt If MsgBox("Soll das neu erstellte Blatt " & _ vbNewLine & _ " """ & Sh.Name & """" & _ vbNewLine & _ " wirklich gelöscht werden?", _ vbYesNo + vbQuestion, _ "Wirklich Abbrechen?") _ = vbYes Then

Ereignisse

' Sprungmarke definieren NameInput: ' Eingabe Dialogfeld für neuen Blattnamen varSheetName = Application.InputBox( _ Prompt:="Geben Sie einen Tabellenblattnamen ein", _ Default:=Sh.Name, _ Type:=2)

Ereignisse

Do

Listing 343

Ereignisse

' Blatt löschen Sh.Delete

2471_Excel-VBA.book Seite 598 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

598 >> Neues Blatt beschriften ' Warnhinweise aktivieren Application.DisplayAlerts = True ' Prozedur verlassen Exit Sub Else ' in MsgBox wurde Nein geklickt ' erneuter Aufruf der InputBox GoTo NameInput End If End Select ' Schleife solange aufrufen, bis ein gültiger _ Blattname eingegeben wurde Loop Until IsSheetNameOK(varSheetName) = True

Ereignisse

Ereignisse

Ereignisse

Ereignisse

' Makroaufruf für Kopf- und Fußzeilen HeaderAndFooter strSheetName:=varSheetName End Sub Listing 343 (Forts.)

Beim Aufruf der IsSheetNameOK-Funktion wird ein Wert vom Datentyp String erwartet. Tatsächlich soll aber die Variable varSheetName vom Datentyp Variant beim Aufruf der Funktion übergeben werden. Dabei spielt es keine Rolle, dass die VariantVariable einen String-Wert enthält. Ohne weitere Definierung des Argumenttyps in der Funktion wird das Argument als Verweis ByRef an die aufrufende Prozedur oder Funktion übergeben. ByRef ist in Visual Basic der Standardwert zur Übergabe von Argumenten und ist optional, d.h. er muss nicht zwingend vor dem Argument genannt werden. Wird kein Argumenttyp angegeben, ist das definierte Argument automatisch vom Typ ByRef. Um eine Übergabe des vermeintlich falschen Datentyps zu gewährleisten, muss der Parameter strNewName in der Argumentenliste der IsSheetNameOK Funktion als Wert definiert werden. Dies erreichen Sie durch Voranstellen des Schlüsselwortes ByVal. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_08_NewSheetName.xlsm ' Modul mdl_01_FunctionIsSheetNameOK ‘=============================================================== Public Function IsSheetNameOK(ByVal strNewName As String) As Boolean Dim bytSh As Byte

Ereignisse

' Fehlerbehandlung zurückstellen Listing 344

2471_Excel-VBA.book Seite 599 Dienstag, 4. Dezember 2007 1:42 13

On Error Resume Next

599 Ereignisse

>> Ereignisse

'Prüfung ob Name bereits existiert For bytSh = 1 To ActiveWorkbook.Sheets.Count If Sheets(bytSh).Name = strNewName Then MsgBox "Der Tabellenname existiert bereits in der" & _ " Datei!" & _ vbNewLine & _ "Geben Sie einen anderen Namen ein!", _ Listing 344 (Forts.)

Ereignisse Ereignisse Ereignisse

' Namenseingabe hat mehr als 31 Zeichen If Len(strNewName) > 31 Then MsgBox "Der Dateiname enthält " & Len(strNewName) & _ " Zeichen!" & _ vbNewLine & _ "Kürzen Sie den Tabellennamen auf max. 31" & _ " Zeichen!", _ vbCritical, _ "Fehler in der Zeichenlänge" Exit Function End If

Ereignisse

' keine Eingabe in InputBox If strNewName = "" Then MsgBox "Es wurde kein Name angegeben!" & _ vbNewLine & _ "Geben Sie für das neu erstellte Blatt einen " & _ "Namen ein!", _ vbCritical, _ "Fehler: keine Eingabe" Exit Function End If

Ereignisse

' Auswertung des Err-Objektes ' bei gültiger Namensvergabe erfolgt keine Fehlermeldung If Str(Err.Number) = 0 Then ' Funktion erhält den Wert IsSheetNameOK = True Else ' Beschriftung des Blattes hat Fehler verursacht; _ Überprüfung welche Ursache die Fehlermeldung hatte

Ereignisse

' Tabellenblatt umbenennen ActiveSheet.Name = strNewName

Ereignisse

' nichtverarbeitete Fehler aus dem Err-Objekt löschen Err.Clear

2471_Excel-VBA.book Seite 600 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

600 >> Neues Blatt beschriften vbCritical, _ "Name bereits vorhanden" Exit Function End If Next ' keine Übereinstimmung der vorherigen Überprüfungen MsgBox "Der gewählte Tabellenblattname enthält unzulässige" & _ "Sonderzeichen!" & _ vbNewLine & _ "Geben Sie einen anderen Namen ein!", _ vbCritical, _ "Blattname enthält eins der Sonderzeichen: " & _ " : \ / ? * [ ]" End If End Function

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Listing 344 (Forts.)

Nachdem der neue Tabellenblattname zugewiesen wurde, wird als letzter Befehl in der Workbook_NewSheet-Prozedur das Makro HeaderAndFooter zur Erstellung der Kopfund Fußzeilen aufgerufen. Hier besteht nun die Möglichkeit über eine InputBox den Text der mittleren Kopfzeile einzugeben. Belassen Sie die Eingabezeile der INPUTBOX leer, oder klicken auf die Schaltfläche ABBRECHEN, dann wird kein Text in die Kopfzeile geschrieben. Den Text der linken- und rechten Fußzeile können Sie dem nachfolgenden Code entnehmen. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_08_NewSheetName.xlsm ' Modul mdl_02_HeaderAndFooter ‘=============================================================== Public Sub HeaderAndFooter(ByVal strSheetName As String) Dim strCenterHeader As String strCenterHeader = Application.InputBox( _ Prompt:="Welcher Text soll in der mittleren Kopfzeile" & _ " erstellt werden?", _ Title:="Kopf- und Fußzeilen", _ Type:=2) With ActiveSheet.PageSetup ' Wenn Abbrechen der Inputbox dann leere Kopfzeile ' erstellen .CenterHeader = IIf(strCenterHeader = "Falsch", "", _ strCenterHeader) Listing 345

2471_Excel-VBA.book Seite 601 Dienstag, 4. Dezember 2007 1:42 13

.LeftFooter = "Das Excel-VBA-Codebook, 2007" ' Angabe des Pfades, Dateiname und Blattname .RightFooter = ActiveWorkbook.Path & _ Chr(10) & _ ActiveWorkbook.Name & _ Chr(10) & _ strSheetName End With End Sub

Ereignisse

601

Ereignisse

>> Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_09_DeleteFastChart.xlsm ' Modul mdl_01_FastChart ‘=============================================================== Public gobjChart As Object Public Sub FastChart() ' erste Zelle in benutzten Bereich markieren ActiveSheet.UsedRange.Cells(1).Select ' Ereignisse deaktivieren Application.EnableEvents = False

Ereignisse

Dadurch kann das Diagrammblatt in anderen Prozeduren identifiziert und bearbeitet werden.

Ereignisse

In diesem Beispiel wird nach Klick auf einen Button das Makro FastChart aufgerufen. Der benutzte Bereich des aktiven Tabellenblattes wird über diese Prozedur als Diagramm in einem neuen Diagrammblatt angezeigt. Nachdem das Diagrammblatt erstellt wurde, wird es der öffentlichen Objekt-Variablen gobjChart zugewiesen.

Ereignisse

204 Diagramm nach Ansicht löschen

Ereignisse

Listing 345 (Forts.)

' Ereignisse aktivieren Application.EnableEvents = True

Ereignisse

' Diagrammblatt einfügen Charts.Add

Listing 346

Ereignisse

' Objekt-Variablen aktives Blatt zuweisen Set gobjChart = ActiveSheet End Sub

2471_Excel-VBA.book Seite 602 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

602 >> Tabellenblatt-Ereignisse (Worksheet)

Nachdem Sie sich das Diagrammblatt angeschaut und zu einem x-beliebigen Blatt der Arbeitsmappe wechseln, soll das soeben erstellte Diagrammblatt wieder gelöscht werden. Schreiben Sie den Code dazu in das Workbook_SheetActivate-Ereignis. Es wird ausgelöst nachdem ein Blatt der Arbeitsmappe aktiviert wurde. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_09_DeleteFastChart.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

Ereignisse

Ereignisse

Private Sub Workbook_SheetActivate(ByVal Sh As Object) ' Prüfung ob Objekt-Variable initialisiert ist If gobjChart Is Nothing Then Exit Sub With Application ' Ereignisse deaktivieren .EnableEvents = False ' Fehlermeldungen deaktivieren .DisplayAlerts = False ' Diagrammblatt löschen gobjChart.Delete ' Fehlermeldungen aktivieren .DisplayAlerts = True ' Ereignisse aktivieren .EnableEvents = True End With

Ereignisse

' öffentliche Objekt-Variable zurücksetzen Set gobjChart = Nothing End Sub Listing 347

Ereignisse

Ereignisse

205 Tabellenblatt-Ereignisse (Worksheet) Neben den Workbook-Ereignissen, welche die gesamte Excel-Datei betreffen, gibt es für jedes einzelne Tabellenblatt unabhängige Worksheet-Ereignisse. Jedes Tabellenblatt einer Excel-Arbeitsmappe verwaltet seine Ereignis-Prozeduren in »seinem« Klassenmodul. Klicken Sie im Projekt-Explorer des VBA-Editors doppelt auf einen Tabellennamen, damit in der rechten Fensterhälfte das Codeblatt zu dieser Tabelle angezeigt wird.

2471_Excel-VBA.book Seite 603 Dienstag, 4. Dezember 2007 1:42 13

Um von der Excel-Tabellenansicht schnell zum VBA-Editor mit dem dazugehörigen Codemodul zu wechseln, klicken Sie mit der rechten Maustaste auf den Tabellenregister und wählen den Befehl CODE ANZEIGEN.

In Excel 2007 ist das Worksheet_PivotTableUpdate-Ereignis zu den Ereignissen der Worksheet-Objekte in die Excel Objektbibliothek hinzugekommen. Folgende Ereignisse stehen jedem Tabellenblatt in Excel 2007 zur Verfügung: Ereignis

Aufruf/Beschreibung

Worksheet_Activate

Nachdem das Tabellenblatt aktiviert wurde

Worksheet_BeforeDoubleClick

Nach einem Doppelklick mit der linken Maustaste 왘 Bevor die Standardfunktion des Doppelklicks ausgeführt wird (Zellbearbeitung)

Ereignisse

Löschen Sie Ereignis-Prozeduren in dem Codeblatt, die Sie nicht benötigen, oder auch solche Codeschablonen, die keine Befehle enthalten. Diese würden sonst bei jedem eintretenden Ereignis unnötig aufgerufen.

Ereignisse

Tipp

Nach Auswahl eines Ereignisses aus dem Listenfeld wird die entsprechende Codeschablone in dem Codeblatt ausgegeben. Schreiben Sie die Befehle, die beim Eintritt des gewählten Ereignisses ausgeführt werden soll, zwischen die aufgeführte Aufrufund Endzeile der Ereignis-Prozedur.

Ereignisse

Abbildung 204: Klassenmodul der Tabelle mit verfügbaren Ereignisprozeduren

Ereignisse

Ereignisse

Klicken Sie oberhalb des Codefensters auf den linken Dropdown-Pfeil und wählen den Eintrag WORKSHEET. Daraufhin wird die Codeschablone des Worksheet_SelectionChange-Ereignisses erstellt. Im rechten Listenfeld werden alle verfügbaren Ereignisse für die Tabelle aufgeführt.

Ereignisse

603

Ereignisse

Tipp

>> Ereignisse

Ereignisse

Tabelle 42: Ereignisse für das Tabellenblatt in Excel 2007

2471_Excel-VBA.book Seite 604 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

604 >> Tabellenblatt-Ereignisse (Worksheet) Ereignis

Aufruf/Beschreibung

Worksheet_BeforeRightClick

Nach einem Klick mit der rechten Maustaste 왘 Bevor die Standardfunktion des rechten Mausklicks ausgeführt wird (Kontextmenü)

Worksheet_Calculate

Nachdem das Tabellenblatt neu berechnet wurde 왘 Zellformatierungen lösen keine Neuberechnung aus

Worksheet_Change

Nachdem der Inhalt einer Zelle in dem Tabellenblatt durch eine Eingabe oder durch eine externe Verknüpfung verändert oder gelöscht wurde 왘 Wird nach Aktivierung eines Tabellenblattes, vor dem Sheet_Aktivate-Ereignis ausgelöst 왘 Zellformatierungen lösen kein Change-Ereignis aus

Worksheet_Deactivate

Nachdem das Tabellenblatt deaktiviert wurde

Worksheet_FollowHyperlink

Nachdem auf einen Hyperlink geklickt wurde

Worksheet_PivotTableUpdate

Nachdem ein PivotTable-Bericht für ein Arbeitsblatt aktualisiert wurde.

Worksheet_SelectionChange

Nachdem die Auswahl der markierten Zelle(n) verändert wurde 왘 Bei Zellwechsel 왘 Bei Markierung von Zeilen-/Spaltenköpfen, Bereichen 왘 Zellformatierungen lösen kein SelectionChange-Ereignis aus

Tabelle 42: Ereignisse für das Tabellenblatt in Excel 2007 (Forts.)

In der Beispieldatei werden alle Worksheet-Ereignisse überwacht. Sobald ein Ereignis eintritt, werden Sie über ein Meldungsfenster mit Angabe des aufgerufenen Ereignisses informiert. Da wir hier aus Platzgründen nicht alle Ereignisprozeduren der Beispieldatei aufführen wollen, stellen wir Ihnen an dieser Stelle stellvertretend für alle weiteren Ereignisse das erste Ereignis aus der Liste vor. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_10_AllWorksheetsEvents.xlsm ' Tabelle AllEvents ' Ereignis Tabelle1 (AllEvents) ‘=============================================================== Private Sub Worksheet_Activate() MsgBox "Worksheet_Activate" End Sub Listing 348

2471_Excel-VBA.book Seite 605 Dienstag, 4. Dezember 2007 1:42 13

In diesem Beispiel wird die Anzeige des Kontextmenüs nur im Bereich A1:E25 des Tabellenblattes deaktiviert. Drücken Sie außerhalb des genannten Bereichs die rechte Maustaste, dann wird das übliche Zellen-Kontextmenü angezeigt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_10_AllWorksheetsEvents.xlsm ' Tabelle BeforeRightClick ' Ereignis Tabelle2 (BeforeRightClick) ‘=============================================================== Private Sub Worksheet_BeforeRightClick _ (ByVal Target As Range, Cancel As Boolean) ' Prüfung, ob aktive Zelle im angegebenen Bereich liegt If Not Application.Intersect(Target, Range("A1:E25")) _ Is Nothing Then ' Anzeige des Kontextmenüs deaktivieren Cancel = True End If

Ereignisse Ereignisse

Weitere Informationen zu Kontextmenüs finden Sie in der Kategorie »Befehlsleisten«.

Ereignisse

Hinweis

Wenn Sie mit der rechten Maustaste in eine Zelle, oder einen markierten Zellenbereich auf dem Tabellenblatt klicken, wird üblicherweise das Kontextmenü der Zelle angezeigt. Dieser Rechtsklick löst vor dem Anzeigen des Kontextmenüs das Worksheet_BeforeRightClick-Ereignis aus. Beim Aufruf dieses Ereignisses wird der Parameter Cancel vom Datentyp Boolean an die Prozedur übergeben. Cancel weist zu Beginn der Ereignisprozedur den Standardwert False auf. Setzen Sie dessen Wert im Verlauf der Prozedur auf True, dann bleibt nach Beendigung der Prozedur die Anzeige des Kontextmenüs aus.

Ereignisse

206 Zellenkontextmenü verhindern

Ereignisse

605

Ereignisse

>> Ereignisse

207 Auf den Spuren von Target In einigen Ereignissen wird in der Aufrufzeile die Variable Target an die nachfolgende Prozedur übergeben. Neben der Adresse werden alle Eigenschaften wie Zellenwert oder Formatierungen der auslösenden Zelle oder Bereichs an die Variable

Ereignisse

Listing 349

Ereignisse

End Sub

2471_Excel-VBA.book Seite 606 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

606 >> Auf den Spuren von Target Target übergeben. Am Beispiel des Worksheet_SelectionChange-Ereignisses zeigen wir

Ihnen, welche Informationen in dieser Variablen stecken und wie diese ausgewertet und geändert werden können.

Ereignisse

Ereignisse

Ereignisse

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

Das Worksheet_SelectionChange-Ereignis tritt ein, wenn durch den Anwender oder durch VBA-Code die Zellmarkierung auf dem Tabellenblatt geändert wurde. Dabei spielt es keine Rolle, ob nur eine Zelle A1, ein zusammenhängender Bereich A1:C10, eine ganze Zeile A1:IV265 oder Spalte A1:A65536 oder einzelne Zellen A1, A3, A5 mittels gedrückter (Strg)-Taste ausgewählt wurden. Wird der Variablen Target in der Prozedur keine Eigenschaft hinzugefügt, liefert diese standardmäßig den Wert einer »einzelnen« markierten Zelle. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle Target_Default ' Ereignis Tabelle1 (Target_Default) ‘=============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' Wert einer einzelnen selektierten Zelle MsgBox Target ' entspricht Target.Value End Sub

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Listing 350

Abbildung 205: Wert einer einzelnen selektierten Zelle

Sobald mehrere Zellen selektiert wurden, verursacht obige Prozedur eine Fehlermeldung, da die Variable Target alle markierten Zellen beinhaltet und dadurch kein eindeutiger Zellbezug hergestellt werden kann. Folgende Syntax gibt sowohl den Wert einer markierten Zelle als auch in einem Bereich aus mehreren Zellen den Wert der ersten Zelle zurück:

2471_Excel-VBA.book Seite 607 Dienstag, 4. Dezember 2007 1:42 13

Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' Wert der ersten Zelle eines Bereichs MsgBox Target.Cells(1, 1) End Sub

Ereignisse

Alle verfügbaren Eigenschaften und Methoden zu dem Schlüsselwort Target erhalten Sie, indem Sie das Wort Target gefolgt von einem Punkt schreiben. Wählen Sie aus der aufklappenden Intellisense-Liste das Gewünschte aus.

Ereignisse

Abbildung 206: Wert der ersten Zelle eines Bereichs

Ereignisse

Ereignisse

Listing 351

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle Target_Range ' Ereignis Tabelle2 (Target_Range) ‘===============================================================

Ereignisse

607

Ereignisse

>> Ereignisse

Ereignisse

Abbildung 207: Mögliche Eigenschaften und Methoden zu Target

2471_Excel-VBA.book Seite 608 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

608 >> Bereichsauswahl verhindern

Die Eigenschaften der auslösenden Zelle oder Bereichs können innerhalb der Prozedur geändert werden. Die Adresse bleibt jedoch unveränderbar.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Zu verschiedenen Tabellenblatt-Ereignissen haben wir nachfolgend einige Beispiele aus der Praxis zusammengestellt.

208 Bereichsauswahl verhindern Auf sehr einfache Weise können Sie verhindern, dass der Anwender einen Bereich aus mehreren Zellen markieren kann. Dies ist sinnvoll, wenn Sie zum Beispiel auf einzelne Zellen in einem Tabellenblatt einen Selektier-Schutz gelegt haben, so dass diese Zellen nicht auswählbar sind. Durch Markierung eines Bereichs in welchem diese geschützten Zellen enthalten sind, werden diese Zellen aber dennoch erreichbar und können kopiert werden. Mittels nachfolgender Prozedur wird auch eine Mehrfachmarkierung durch Drücken der (Strg)-Taste und Auswahl einzelner Zellen unterbunden. Bevor innerhalb der Prozedur mit VBA eine andere Zelle selektiert wird, werden die Ereignisse deaktiviert. Blieben die Ereignisse aktiv, würde durch eine Änderung der Zellmarkierung das Selection_Change-Ereignis wiederholt aufgerufen, was letztendlich in einer Endlosschleife enden kann. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle Select one Cell ' Ereignis Tabelle3 (Select one Cell) ‘=============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' Wenn 1 Zelle markiert ist, verlasse Prozedur If Target.Count = 1 Then Exit Sub ' Ereignisse deaktivieren Application.EnableEvents = False ' erste Zelle des markierten Bereichs selektieren Target.Cells(1, 1).Select ' Ereignisse aktivieren Application.EnableEvents = True End Sub Listing 352

2471_Excel-VBA.book Seite 609 Dienstag, 4. Dezember 2007 1:42 13

Jede Änderung der Zellenauswahl wird im Tabellenblatt in der ersten freien Zelle in Spalte A protokolliert. Über die Tabellen-Funktion CountA (Anzahl2) wird die Anzahl der nichtleeren Zellen in Spalte A ermittelt. Zu diesem Wert wird die Zahl 1 addiert um die erste leere Zeile wiederzugeben. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle CurserLog ' Ereignis Tabelle4 (CurserLog) ‘=============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) Cells(WorksheetFunction.CountA(Columns(1)) + 1, 1) _ .Value = Target.Address(False, False) End Sub

Ereignisse

209 Cursorbewegungen protokollieren

Ereignisse

609

Ereignisse

>> Ereignisse

Ereignisse Ereignisse Ereignisse

Sie können in einer Tabelle die Zoom-Einstellung verkleinern, um einen größeren Bereich einzusehen. Oft ist es dann nicht mehr möglich, den Zelleninhalt einer ausgewählten Zelle oder Bereichs zu lesen, da die Schriftgröße zu klein ist. Folgende Worksheet_SelectionChange-Prozedur wird ausgelöst, wenn die Zellenauswahl im Tabellenblatt geändert wird. Zunächst wird die Schriftgröße aller Zellen im benutzten Bereich UsedRange auf 10 und die Schriftfarbe auf Automatik eingestellt. Diese Einstellungen entsprechen der Ausgangsformatierung der Tabelle. Allen Zellen im neu markierten Bereich Target wird die Schriftgröße 25 und die Schriftfarbe 5 zugewiesen. Wenn die Grundeinstellungen der Farbpalette unverändert sind, entspricht der Farbindex 5 der Farbe Blau. Anschließend wird über die AutoFit-Methode die Spaltenbreite aller Spalten im Tabellenblatt automatisch geändert, um eine optimale Anpassung zu erreichen.

Ereignisse

210 Markierten Zellenbereich vergrößern

Ereignisse

Listing 353

2471_Excel-VBA.book Seite 610 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

610 >> Markierten Zellenbereich vergrößern

Ereignisse

Abbildung 208: Vergrößerte Ansicht der Zellenauswahl ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle Enlargement ' Ereignis Tabelle5 (Enlargement) ‘===============================================================

Ereignisse

' Alle folgenden Objekte referenzieren auf das eigene Tabellenblatt With Me ' Methoden für den benutzten Bereich ' Alle Zellen zurücksetzen With .UsedRange ' Schriftgröße .Font.Size = 10 ' Schriftfarbe .Font.ColorIndex = xlAutomatic End With

Ereignisse

Ereignisse

' Bildschirmaktualisierung ausschalten Application.ScreenUpdating = False

Ereignisse

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

' Markierten Bereich vergrößern With Target ' Schriftgröße .Font.Size = 25 ' Schriftfarbe Listing 354

2471_Excel-VBA.book Seite 611 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse .Font.ColorIndex = 5 End With ' Spaltenbreite automatisch anpassen .Columns.AutoFit End With ' Bildschirmaktualisierung einschalten Application.ScreenUpdating = True End Sub

Ereignisse

Ereignisse

611

xlDefault

Standardmauszeiger

xlIBeam

I-Mauszeiger

xlNorthwestArrow

Nordwestpfeil-Zeiger

xlWait

Sanduhrzeiger

Tabelle 43: Verfügbare Mauszeiger

In der Beispielmappe wird über das Worksheet_SelectionChange-Ereignis bei Auswahl einer Zelle im Bereich D5:E25 der Mauszeiger in eine Eieruhr xlWait verwandelt. Klicken Sie auf eine Zelle außerhalb dieses Bereichs, nimmt der Mauszeiger wieder seine Standardform xlDefault an. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle ChangeCursor ' Ereignis Tabelle6 (ChangeCursor) ‘=============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' Markierten Bereich überprüfen If Application.Intersect(Target, Range("D5:G25")) Is Nothing Then ' Standardmauszeiger aktivieren Application.Cursor = xlDefault

Ereignisse

Erscheinungsbild

Ereignisse

XlMousePointer-Konstanten

Ereignisse

Über die Cursor-Eigenschaft können Sie das Erscheinungsbild des Mauszeigers in Microsoft Excel festlegen. Es stehen vier Mauszeiger zur Verfügung:

Ereignisse

211 Cursor in eine Eieruhr verwandeln

Ereignisse

Listing 354 (Forts.)

Ereignisse

Listing 355

2471_Excel-VBA.book Seite 612 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Else ' Sanduhrzeiger aktivieren Application.Cursor = xlWait End If End Sub Listing 355 (Forts.)

Achtung

Ereignisse

Ereignisse

Ereignisse

612 >> Formeln in Kommentaren anzeigen

Die Cursor-Eigenschaft wird nicht automatisch zurückgesetzt, wenn das Ausführen eines Makros beendet ist. Sie sollten den Mauszeiger auf xlDefault zurücksetzen, bevor Sie das Tabellenblatt oder die Arbeitsmappe verlassen.

Wenn Sie in der Beispielmappe zu einem anderen Tabellenblatt wechseln, wird im Worksheet_Deactivate-Ereignis der Mauszeiger auf sein Standard-Erscheinungsbild zurückgesetzt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Ereignis Tabelle6 (ChangeCursor) ‘=============================================================== Private Sub Worksheet_Deactivate() ' Standardmauszeiger aktivieren Application.Cursor = xlDefault End Sub

Ereignisse

Ereignisse

Ereignisse

Listing 356

212 Formeln in Kommentaren anzeigen Ob sich ein Zelleninhalt aus einem festen Wert oder einer Formel ergibt, erfahren Sie üblicherweise nur durch einen Blick auf den Inhalt der Bearbeitungsleiste. In diesem Beispiel wird bei jeder Änderung der Zellmarkierung eine vorhandene Formel im Kommentar der Zelle angezeigt. Damit beim Löschen vorhandener Kommentare das Worksheet_SelectionChange-Ereignis nicht erneut aufgerufen wird, werden vorab alle Ereignisse über die EnableEvents-Eigenschaft deaktiviert. Falls ein Bereich aus mehreren Zellen markiert wurde, werden die nachfolgenden Befehle in der With-Anweisung auf die erste Zelle der Markierung Target reduziert. With Target.Cells(1, 1)

Die Prozedur würde ohne die Referenzierung auf eine Zelle im weiteren Verlauf keinen eindeutigen Zellbezug für die Erstellung eines Kommentars herstellen können und eine Fehlermeldung hervorrufen. Damit bei einer Änderung der Markierung über

2471_Excel-VBA.book Seite 613 Dienstag, 4. Dezember 2007 1:42 13

die Pfeiltasten der Tastatur ebenfalls vorhandene Formeln im Kommentartext angezeigt werden, stellen wir die Visible-Eigenschaft des Comment-Objektes auf True. Die Größe des Kommentar-Rahmens wird automatisch eingestellt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_11_SelectionChange.xlsm ' Tabelle FormulaInfo ' Modul Tabelle7(FormulaInfo) ‘===============================================================

Ereignisse

613

Ereignisse

>> Ereignisse

' mit erster Zelle der Markierung With Target.Cells(1, 1) ' Prüfung, ob Zelle eine Formel enthält If .HasFormula Then ' Kommentar in Zelle einfügen und zugleich ' Formeltext in Kommentarfenster einfügen Set cmt = .AddComment(.FormulaLocal)

Ereignisse

' Prüfung, ob Tabellenblatt Kommentare enthält If Comments.Count > 0 Then ' vorhandene Kommentare löschen UsedRange.SpecialCells(xlCellTypeComments).ClearComments End If

Ereignisse

' Ereignisse deaktivieren Application.EnableEvents = False

Ereignisse

Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim cmt As Comment

' Kommentargröße an Text anpassen cmt.Shape.TextFrame.AutoSize = True End If

Ereignisse

' Kommentar anzeigen cmt.Visible = True

Listing 357

Ereignisse

' Ereignisse aktivieren Application.EnableEvents = True End Sub

Ereignisse

End With

2471_Excel-VBA.book Seite 614 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

614 >> Bei Blattwechsel Monatsspalten anzeigen

213 Bei Blattwechsel Monatsspalten anzeigen Im folgenden Beispiel wurde im Tabellenblatt CALENDAR ein Terminkalender erstellt. Neben jeder Monatsspalte befindet sich eine weitere Spalte für eigene Eintragungen. Bei Dateiöffnung wird im Workbook_Open-Ereignis das Tabellenblatt START aktiviert. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_12_MonthColumns.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_Open() Worksheets("Start").Select End Sub Listing 358

Über ein KONTROLLKÄSTCHEN auf dem Tabellenblatt START kann selektiert werden, ob Sie beim Wechsel zu dem Tabellenblatt CALENDAR nur die relevanten Spalten des aktuellen Monats zur Ansicht erhalten möchten, oder der gesamte Kalender angezeigt werden soll. Sobald Sie von einem anderen Tabellenblatt dieser Arbeitsmappe zu dem Tabellenblatt CALENDAR wechseln, wird das Worksheet_Aktivate-Ereignis der Tabelle ausgelöst, welches im Klassenmodul Tabelle2 (Calendar) hinterlegt ist. Als Erstes wird der Zustand des Kontrollkästchens abgefragt. Ist die CheckBox1 aktiviert beträgt dessen Wert True und der gesamte Kalender soll angezeigt werden. Folglich werden alle Spalten der Tabelle A:X eingeblendet. Wenn das Kontrollkästchen deaktiviert wurde, sollen nur die Spalten des aktuellen Monats in der Tabelle angezeigt werden. Die CheckBox1 hat in dem Fall den Wert False. Daraufhin werden die relevanten Spalten der Tabelle A:X, welche in Zeile drei jeweils Monatsnamen in den Spaltenüberschriften enthalten, ausgeblendet. Das Schlüsselwort Me bezieht sich auf das aktive Tabellenblatt. Der aktuelle Monat wird laut Systemeinstellung in der langen Schreibweise in die Variable strMonth gespeichert. so dass über die Find-Methode die Spalte des gesuchten Monats ermittelt werden kann. Diese wird in der Variablen intCol gespeichert und anschließend mitsamt der zu dem Monat gehörenden Nebenspalte eingeblendet. Natürlich soll die jeweilige Monatsspalte nach Aktivierung des Tabellenblattes CALENDAR auch im Sichtbereich liegen. Würde man lediglich die Zelle A1 mit Range("A1").Select markieren, um zum Anfang der Tabelle zu springen, bliebe der Sichtbereich jedoch weiterhin auf der ursprünglichen Zelle, obwohl die Zelle A1 markiert ist. Über die GoTo-Methode wird ein angegebener Bereich aktiviert. Für diese Methode können Sie das optionale Argument Scroll angeben, um Bildläufe im Zielfenster durchzuführen. Geben Sie den Wert True an, führt Excel die nötigen Bildläufe durch, damit die obere linke Zelle des Bereichs als obere linke Zelle des Fensters erscheint. Geben Sie für das Argument den Wert False an, führt Excel keine Bildläufe durch. Der Standardwert ist False.

2471_Excel-VBA.book Seite 615 Dienstag, 4. Dezember 2007 1:42 13

' Mit eigenem Tabellennblatt With Me ' Prüfung ders Kontrollkästchens If Worksheets(1).CheckBox1.Value = True Then ' CheckBox "Gesamte Kalenderansicht" wurde aktiviert ' Alle Spalten des Bereichs einblenden .Columns("A:X").EntireColumn.Hidden = False Else ' CheckBox "Gesamte Kalenderansicht" wurde deaktiviert ' Alle Spalten des Bereichs ausblenden .Columns("A:X").EntireColumn.Hidden = True ' aktuellen Monat in langer Schreibweise auslesen strMonth = Format(Date, "MMMM") ' Spaltennummer des aktuellen Monats auslesen intCol = .Rows(3).Find(what:=strMonth, lookat:=xlValue).Column ' Aktuelle Monats- und Nebenspalte einblenden .Range(Columns(intCol), Columns(intCol + 1)) _ .EntireColumn.Hidden = False End If

Ereignisse Ereignisse Ereignisse

' Bildschirmaktualisierung ausschalten Application.ScreenUpdating = False

Ereignisse

Private Sub Worksheet_Activate() Dim intCol As Integer Dim strMonth As String

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_12_MonthColumns.xlsm ' Tabelle Calendar ' Ereignis Tabelle2 (Calendar) ‘===============================================================

615

Ereignisse

>> Ereignisse

' Sichtbereich festlegen Application.Goto .Range("A1"), True

' Bildschirmaktualisierung einschalten Application.ScreenUpdating = True End Sub

Ereignisse

End With

Ereignisse

Listing 359

2471_Excel-VBA.book Seite 616 Dienstag, 4. Dezember 2007 1:42 13

214 Blattschutz ohne Blattschutz Sie können in einem Tabellenblatt Zellen und Bereiche sperren, ohne dafür einzelne Zellen zu sperren und den Blattschutz zu aktivieren. Verwenden Sie dazu das Worksheet_SelectionChange-Ereignis des Tabellenblattes. Beim Aufruf des Ereignisses wird die Adresse der markierten Zelle oder Bereichs über die Variable Target an die Prozedur übergeben. Mit der Intersect-Methode wird anschließend die Schnittmenge des markierten und des erlaubten Bereichs Range("E10:I25") ermittelt. Der Variablen Target wird dieser neue Bereich zugewiesen. Wurden Zellen außerhalb des erlaubten Bereichs E10:I25 markiert, werden diese dadurch in der neu zugewiesenen Target-Variablen ignoriert. In der äußeren If-Abfrage wird der Inhalt der Variablen Target überprüft. Enthält dieser keinen Wert, bedeutet das, dass keine Zelle im erlaubten Bereich markiert wurde. In der folgenden If-Abfrage wird nun ermittelt, ob die statische Variable rngLastRange einen Wert enthält. Die Static-Anweisung wird verwendet, um den Wert der Variablen rngLastRange während der gesamten Laufzeit des Moduls zu speichern.

Ereignisse

Die Variable rngLastRange enthält noch keinen Wert, wenn die Ereignis-Prozedur das erste Mal durch eine Änderung der Zellmarkierung ausgelöst wird. Demzufolge wird die erste Zelle E10, die sich im zulässigen Bereich befindet, selektiert. Die Variable rngLastRange erhält einen Wert, wenn eine Zelle bzw. Bereich im erlauben Bereich markiert wurde. Diese Zelle wird dann bei späterer Markierung von Zellen außerhalb des definierten Bereichs statt der Zelle E10 markiert. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_13_SheetProtection.xlsm ' Tabelle ProtectRange ' Ereignis Tabelle1 (ProtectRange) ‘===============================================================

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

616 >> Blattschutz ohne Blattschutz

Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' Statische Variable behält Wert während der Laufzeit ' der Arbeitsmappe Static rngLastRange As Range

Ereignisse

' Target auf Zellen im angegebenen Bereich reduzieren Set Target = Intersect(Target, Range("E10:I25")) ' Ereignisse deaktivieren Application.EnableEvents = False

Ereignisse

' Prüfung ob Target initialisiert ist If Target Is Nothing Then Listing 360

2471_Excel-VBA.book Seite 617 Dienstag, 4. Dezember 2007 1:42 13

' Ereignisse aktivieren Application.EnableEvents = True End Sub Listing 360 (Forts.)

Ereignisse Ereignisse

Abbildung 209: Formularzellen definieren

Ereignisse

Ereignisse

Neben einem zusammenhängenden Bereich können auch einzelne Zellen zur Markierung freigegeben werden. Auf diese Art können in einem Formular auch einzelne Zellen bearbeitet werden.

Ereignisse

' statischer Variablen aktuelle Markierung zuweisen Set rngLastRange = Target

Ereignisse

' Prüfung, ob statischer Bezug initialisiert ist If rngLastRange Is Nothing Then ' Alternative Startzelle Range("E10").Select Else ' Letzte Zelle im definierten Bereich markieren rngLastRange.Select End If Else ' Markierungänderung erfolgt im definierten Bereich ' Neu definierten Target markieren, falls Zellen ' innerhalb und außerhalb des def. Bereichs markiert wurden Target.Select End If

Ereignisse

617

Ereignisse

>> Ereignisse

2471_Excel-VBA.book Seite 618 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

618 >> Ereignisbedingte Formatierung ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_13_SheetProtection.xlsm ' Tabelle ProtectCells ' Ereignis Tabelle2 (ProtectCells) ‘=============================================================== Private Sub Worksheet_SelectionChange(ByVal Target As Range) Static rngLastRange As Range

Ereignisse

Ereignisse

Ereignisse

' Target auf angegebene Zellen überprüfen und neu initialisieren Set Target = Intersect(Target, Range("G12,G14,G16,G18,G20")) Application.EnableEvents = False If Target Is Nothing Then If rngLastRange Is Nothing Then Range("G12").Select Else rngLastRange.Select End If Else Target.Select End If Set rngLastRange = Target Application.EnableEvents = True End Sub Listing 361

Ereignisse

In Excel 2007 wurde die bedingte Formatierung von Grund auf neu konzipiert. Mit Hilfe der bedingten Formatierung können Daten sowohl für die Analyse als auch für die Präsentation optisch kommentiert werden. Damit Ausnahmen leichter gefunden und wichtige Trends in Ihren Daten schneller erkannt werden, können Sie beliebig viele bedingte Formatierungsregeln implementieren und verwalten, die zahlreiche optische Formatierungen in Form von Farbskalen, Datenbalken und Symbolsätzen auf Daten anwenden.

Ereignisse

In Excel ist es mit der Funktion BEDINGTE FORMATIERUNG möglich, das Zellenformat entsprechend dem Zellenwert vorzugeben. Diese Option finden Sie in Excel 2007 im Register START in der Gruppe FORMATVORLAGEN. Bis einschließlich Excel 2003 konnten über die bedingte Formatierung jedoch nur maximal drei Bedingungen je Zelle festgelegt werden.

Ereignisse

215 Ereignisbedingte Formatierung

Wenn in älteren Excel Versionen die maximale Verfügbarkeit von drei Formatierungsregeln nicht ausgereicht haben, bediente man sich des Worksheet_Change-Ereig-

2471_Excel-VBA.book Seite 619 Dienstag, 4. Dezember 2007 1:42 13

Mit Excel 2007 wurden Designfarben eingeführt, welche die Eigenschaft ThemeColor aufweisen. Diese Eigenschaft ist in den Objektbibliotheken vorheriger Excel-Versionen nicht vorhanden. Wenn Sie Designfarben in Ihrem Programmcode verwenden und das Programm auch in anderen Versionen als Excel 2007 ausgeführt werden soll, muss vorab eine Versionsprüfung über die Application.Version-Eigenschaft vorgenommen werden. Alternativ können Sie anstatt einer Designfarbe eine Standardfarbe oder eine andere Farbe über die Schaltfläche Weitere Farben wählen. Den jeweiligen Index weiterer Farben erhalten Sie, wenn Sie ein Makro aufzeichnen und die gewünschten Farben auswählen.

Ereignisse Ereignisse

Eine Übersicht der RGB-Standardfarben finden Sie im Anhang. In der Kategorie »Einstieg« werden ein Beispiel und Erläuterungen zu RGB-Farben bereitgestellt.

Sowohl die Color-, als auch die ColorIndex-Eigenschaft können in allen Excel Versionen von Excel 97 bis Excel 2007 angewendet werden. Lediglich bei der Aufzeichnung von Makros werden unterschiedliche Eigenschaften verwendet. Die Funktionalität bleibt jedoch bei beiden Eigenschaften in allen Versionen erhalten.

Ereignisse

Tipp

Zeichnet man in Excel 2007 mit dem Makrorekorder das Einfärben von Zellen mit den Standardfarben auf, erhält man eine andere Syntax als noch in Excel 2003. Auffällig ist hierbei, dass die bisher verwendete ColorIndex-Eigenschaft bei der Makroaufzeichnung durch die Color-Eigenschaft ersetzt wurde. An die Color-Eigenschaft können Farben über die RGB-Funktion angegeben werden. Die Farbe Schwarz hat zum Beispiel den RGB-Wert (0,0,0).

Ereignisse

Achtung

In dem folgenden Beispiel erhalten alle Zellen mit Zahlenwerten zwischen 1 und 90 einen farbigen Zellenhintergrund aus der Standard-Farbpalette. Zum Beispiel werden Zellen mit Zahlenwerten zwischen 1 und 10 mit dem Farbindex 1 eingefärbt. In unserem Beispiel gehen wir davon aus, dass die Einstellungen der Farbpalette nicht geändert wurde.

Ereignisse

In unserer Beispieldatei wird diese Art der bedingten Formatierung nur in einem Tabellenblatt der Arbeitsmappe verwendet. Aus diesem Grund wird der Code in das Worksheet_Change-Ereignis des Tabellen-Codeblattes geschrieben. Wenn Sie dieses Beispiel in allen Tabellenblättern Ihrer Arbeitsmappe nutzen wollen, verwenden Sie das Workbook_SheetChange-Ereignis. Die Prozedur wird in dem Fall in das Modul DIESEARBEITSMAPPE geschrieben.

Ereignisse

nisses, um auf Änderungen von Zellwerten zu reagieren und auf diese Weise die bedingte Formatierung zu erweitern. Auf diese Weise konnten beliebig vielen Bedingungen mit entsprechenden Formatierungen für einzelne Zellen definiert werden.

Ereignisse

619

Ereignisse

>> Ereignisse

2471_Excel-VBA.book Seite 620 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

620 >> Ereignisbedingte Formatierung

Kommen wir nun zur Beschreibung der Beispielprozedur. Das Worksheet_ChangeEreignis wird ausgelöst, wenn sich der Inhalt einer oder mehrerer Zellen ändert. Der geänderte Bereich wird über die Variable Target an die Ereignis-Prozedur übergeben. Um auszuschließen, dass das Einfügen oder Löschen von Spalten oder Zeilen der Auslöser des Change-Ereignisses war, wird die Anzahl markierter Zellen mit der Spalten-/Zeilenanzahl der Arbeitsmappe verglichen. Da eine Excel 2007 Arbeitsmappe, die in einem der neuen XML Dateiformate gespeichert ist wesentlich mehr Spalten und Zeilen enthält als eine Excel 2003 Arbeitsmappe im Format *.xls, kann die Berechnung der vorhandenen Spalten/Zeilen nicht über eine fest definierte Zahl erfolgen. Aus diesem Grund wird die tatsächlich vorhandene Spalten- bzw. Zeilenanzahl über die Column- bzw. Row-Eigenschaft ermittelt und der Anzahl geänderter Zellen gegenübergestellt. Zur Prüfung, ob eine oder mehrere Spalten geändert wurden, multipliziert man zunächst die Anzahl geänderter Spalten mit der Anzahl tatsächlicher Zeilen im Tabellenblatt:

Ereignisse

Ereignisse

Target.Columns.Count * Me.Rows.Count

Das Schlüsselwort Me wird in Klassenmodulen verwendet und steht für das Objekt der Klasse. In der Beispielprozedur steht Me quasi für das eigene, aktive Tabellenblatt. Wenn zum Beispiel eine Spalte gelöscht wurde, liefert obige Syntax in einer Excel 2003 Arbeitsmappe den Wert 65536. In einer Arbeitsmappe mit xml-Dateiformat (*.xlsx oder *.xlsm) liefert die gleiche Syntax aufgrund der erhöhten Zeilenanzahl den Wert 1048576. Bei mehr Spalten multipliziert sich der Wert entsprechend der Anzahl Spalten. Der so ermittelte Wert wird mit der Anzahl geänderter Zellen verglichen. Target.Cells.Count

Ereignisse

Ereignisse

Ereignisse

Sind beide Werte identisch, dann wurden ganze Spalten verändert, wobei wir davon ausgehen, dass der Anwender keine Werte in komplette Spalten/Zeilen ändert, sondern dass es sich hierbei um das Löschen/Einfügen von Spalten/Zeilen handelt. Wenn ein Vergleich der beiden Ausdrücke WAHR ist, wird die Prozedur mit Exit Sub vorzeitig verlassen. If Target.Columns.Count * Me.Rows.Count = Target.Cells.Count Then Exit Sub

Im Tabellenblatt sollen lediglich die Zellen im Bereich A1:D20 nach ihrem jeweiligen Zahlenwert farbig formatiert werden. Die Intersect-Methode gibt ein Range-Objekt zurück, das die rechteckige Schnittmenge von zwei oder mehreren Bereichen darstellt. In unserem Beispiel setzt sich die Schnittmenge aus dem geänderten Bereich Target und dem zu überwachenden Bereich Range("A1:D20") zusammen. Wurden mehrere Zellen in einem Durchgang geändert (zum Beispiel durch Copy/Paste), werden nur die Zellen formatiert, die innerhalb des angegebenen Bereichs liegen.

2471_Excel-VBA.book Seite 621 Dienstag, 4. Dezember 2007 1:42 13

621

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_14_EventFormatConditional.xlsm ' Ereignis Tabelle1 ‘=============================================================== Private Sub Worksheet_Change(ByVal Target As Range) Dim rngCell As Range Dim lngColor As Long ' Prüfung, ob ganze Spalten/Zeilen geändert wurden If Target.Columns.Count * Me.Rows.Count = _ Target.Cells.Count Or _ Target.Rows.Count * Me.Columns.Count = _ Target.Cells.Count Then Exit Sub

Ereignisse Ereignisse

In einer For ... Each-Schleife wird jede Zelle im Bereich Target überprüft. Befindet sich der Wert der Zelle rngCell, in den definierten Bereichen, wird der jeweilige Farbindex an die Variable lngColor übergeben und die Select Case-Anweisung verlassen. Anschließend erhält die Zelle rngCell die Füllfarbe über den angegebenen Farbindex der Variablen lngColor. Enthält die Zelle keinen angegebenen Zahlen- oder Textwert wird eine evtl. vorhandene Füllfarbe der Zelle gelöscht, indem der Farbindex 0 angewandt wird.

Ereignisse

Abbildung 210: Ereignisbedingte Formatierung

Ereignisse

Ereignisse

Ereignisse

Ereignisse

>> Ereignisse

Ereignisse

Listing 362

2471_Excel-VBA.book Seite 622 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

622 >> Ereignisbedingte Formatierung durch Formelbezüge ' Schnittmenge aus definierten Bereich mit ' tatsächlich geändertem Bereich ermitteln Set Target = Intersect(Target, Range("A1:D20")) ' Prüfung ob Bereich Zellen beinhaltet If Target Is Nothing Then Exit Sub ' Jede Zelle in Bereich durchlaufen For Each rngCell In Target ' Auswertung jeder Zelle im geänderten Bereich Select Case rngCell.Value Case 1 To 10 lngColor = 1 ' Schwarz Case 11 To 20 lngColor = 2 ' Weiss Case 21 To 30 lngColor = 3 ' Rot Case 31 To 40 lngColor = 4 ' Grün Case 41 To 50 lngColor = 5 ' Blau Case 51 To 60 lngColor = 6 ' Gelb Case 61 To 70 lngColor = 7 ' Rosa Case 71 To 80 lngColor = 8 ' Cyan Case 81 To 90 lngColor = 9 ' Braun Case Else lngColor = 0 ' keine Farbe End Select ' Hintergrundfarbe zuweisen rngCell.Interior.ColorIndex = lngColor Next rngCell End Sub

Ereignisse

Ereignisse

Listing 362 (Forts.)

216 Ereignisbedingte Formatierung durch Formelbezüge Die Ereignis-bedingte Formatierung aus dem vorherigen Beispiel funktioniert nur bei direkter Eingabe in dem Tabellenblatt, in dessen Codemodul die Prozedur hinterlegt ist. Werden die Werte durch Formelbezüge berechnet, wird das Worksheet_ChangeEreignis nur in dem Tabellenblatt ausgelöst, in welchen die Quelldaten für die For-

2471_Excel-VBA.book Seite 623 Dienstag, 4. Dezember 2007 1:42 13

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_14a_EventFormatConditional.xlsm ' Ereignis Tabelle1 (DataSource) ‘===============================================================

Ereignisse

Abbildung 211: Ereignisbedingte Formatierung mit Formelbezügen

Ereignisse

Ereignisse

Ereignisse

In diesem Beispiel befinden sich die Quelldaten in dem Tabellenblatt DataSource. Die Zellen im Tabellenblatt FormatConditional beinhalten lediglich einen Formelbezug auf die Quelldaten. Die Abbildung 211 verdeutlicht die Ausgangssituation. Sie zeigt beide Tabellenblätter der Beispieldatei nebeneinander in einer Excel-Anwendung an. Diese Anordnung erreichen Sie über das Menü ANSICHT | FENSTER | ALLE ANORDNEN | VERTIKAL. Wenn Sie dann das aktive Fenster verkleinern, wird das neue Fenster der Arbeitsmappe in der Excel-Anwendung sichtbar. Wählen Sie das zweite Tabellenblatt durch Klicken auf den Registerreiter aus und ziehen mit der Maus beide Fenster auf eine optimale Größe und Position. Auf diese Weise können Sie im Tabellenblatt DataSource Änderungen vornehmen und gleichzeitig im Tabellenblatt FormatConditional die Auswirkungen der Ereignis-bedingten Formatierung sehen.

Ereignisse

melberechnungen geändert werden. Dementsprechend muss zusätzlich das Tabellenblatt der Quelldaten über dessen Worksheet_Change-Ereignis auf Änderungen überwacht werden.

Ereignisse

623

Ereignisse

>> Ereignisse

Listing 363

Ereignisse

Private Sub Worksheet_Change(ByVal Target As Range) Dim rngFormCond As Range Dim rngCell As Range

2471_Excel-VBA.book Seite 624 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

624 >> Ereignisbedingte Formatierung durch Formelbezüge Dim bytColor

As Byte

' Prüfung, ob ganze Spalten/Zeilen geändert wurden With Target If.Columns.Count * Me.Rows.Count = .Cells.Count Or _ .Rows.Count * Me.Columns.Count = .Cells.Count _ Then Exit Sub End With ' Bereich der überwacht wird (Quelldaten für Formelbezüge) Set Target = Intersect(Target, Range("A1:B20")) ' Prüfung, ob Target initialisiert ist If Target Is Nothing Then Exit Sub ' Bereich der bedingten Formatierung Set rngFormCond = _ Worksheets("FormatConditional").Range("A1:B20") ' Bereich der in anderem Tabellenblatt formatiert werden soll For Each rngCell In rngFormCond Select Case rngCell.Value Case 1 To 10 bytColor = 1 ' Schwarz Case 11 To 20 bytColor = 2 ' Weiss Case 21 To 30 bytColor = 3 ' Rot Case 31 To 40 bytColor = 4 ' Grün Case 41 To 50 bytColor = 5 ' Blau Case 51 To 60 bytColor = 6 ' Gelb Case 61 To 70 bytColor = 7 ' Rosa Case 71 To 80 bytColor = 8 ' Cyan Case 81 To 90 bytColor = 9 ' Braun Case Else bytColor = 0 ' keine Farbe End Select rngCell.Interior.ColorIndex = bytColor Next rngCell End Sub Listing 363 (Forts.)

2471_Excel-VBA.book Seite 625 Dienstag, 4. Dezember 2007 1:42 13

217 Makro aus Hyperlink aufrufen

Ereignisse

Ereignisse

Makros lassen sich in Tabellenblättern auch über Hyperlinks aufrufen. Zeigen Sie über die Registerkarte EINFÜGEN | HYPERLINK oder mit der Tastenkombination (Strg) (K) den HYPERLINK-BEARBEITEN-Dialog an. Legen Sie dann den Zellentext MyMessage, welcher zugleich der Name der aufzurufenden Prozedur ist, fest. Da der Hyperlink auf kein Objekt verweist, geben Sie als Hyperlink-Adresse die Zelladresse an, in welcher der Hyperlink hinterlegt ist. Bestätigen Sie Ihre Eingabe mit einem Klick auf die OKSchaltfläche.

Ereignisse

625

Ereignisse

>> Ereignisse

In der folgenden If-Anweisung wird der auslösende Zellbezug mit dem Zellverweis verglichen. Sind diese beiden Zellbezüge identisch, wird eine Prozedur aufgerufen. Die TextToDisplay-Eigenschaft gibt den angezeigten Text des auslösenden Hyperlinks zurück. Diese Zeichenfolge entspricht dem Makronamen einer in einem allgemeinen Modul hinterlegten Prozedur. Über die Run-Methode wird diese Prozedur aufgerufen. Die On Error GoTo-Anweisung verzweigt zu der Sprungmarke ERRORHANDLER, wenn die Prozedur nicht gefunden wird.

Ereignisse Ereignisse

Um die hinterlegte Zelladresse des angeklickten Hyperlinks zu ermitteln, verwenden wir die SubAddress-Eigenschaft. Diese gibt die Position innerhalb des mit dem Hyperlink verbundenen Dokuments zurück. Die ermittelte Zeichenkette enthält den Blattnamen mit der Zelladresse auf den der Hyperlink verweist. Über die Excel-Tabellenfunktion Mid und der InStr-Funktion wird die Zelladresse separiert und an die Variable strHyp übergeben.

Ereignisse

Bei einem Klick auf einen Hyperlink wird das Worksheet_FollowHyperlink-Ereignis ausgelöst. In der folgenden Ereignis-Prozedur muss zuerst überprüft werden ob sich der Zellbezug, auf den der Hyperlink verweist, auf die eigene Zellposition bezieht. Dadurch erfolgt die Unterscheidung, ob der Hyperlink ein Makro aufruft, oder auf einen Zellbezug verweist.

Ereignisse

Abbildung 212: Zelltext und Hyperlinkadresse festlegen

2471_Excel-VBA.book Seite 626 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

626 >> Makro aus Hyperlink aufrufen ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_15_FollowHyperlink.xlsm ' Ereignis Tabelle1 (MakroByHyperlink) ‘=============================================================== Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink) Dim strHyp As String ' Zelladressse aus Zellenbezug (Blattname!Adresse) ' extrahieren strHyp = _ Mid(Target.SubAddress, InStr(Target.SubAddress, "!") + 1, 7) ' Vergleich auslösende Zelle mit Hyperlink Bezug If Target.Parent.Address(0, 0) = strHyp Then On Error GoTo ERRORHANDLER Application.Run Target.TextToDisplay Exit Sub ERRORHANDLER: MsgBox _ "Die Prozedur '" & Target.TextToDisplay & _ "' wurde nicht gefunden", _ vbExclamation End If End Sub Listing 364

In der Beispieldatei wurden in drei Zellen Hyperlinks mit Makroaufrufen eingefügt. Klicken Sie auf einen dieser Hyperlinks um die jeweils gleichnamige Prozedur des Zellenwertes aufzurufen. Der vierte Hyperlink ruft kein Makro auf, sondern verlinkt auf das Tabellenblatt MAKROBYHYPERLINK. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_15_FollowHyperlink.xlsm ' Modul mdl_01_HyperlinkMacros ‘=============================================================== Public Sub BlueColor() Range("A14:I16").Interior.ColorIndex = 37 End Sub

Ereignisse

Public Sub MyMessage() MsgBox "Hallo " & Application.UserName Listing 365

2471_Excel-VBA.book Seite 627 Dienstag, 4. Dezember 2007 1:42 13

627

End Sub

Ereignisse

>> Ereignisse

Listing 365 (Forts.)

Ereignisse

Public Sub ShowTheTime() MsgBox "Es ist jetzt " & Time & " Uhr" End Sub

Ereignisse Ereignisse

Beim Aufruf der Worksheet_FollowHyperlink-Ereignisprozedur wird die Variable Target übergeben. Diese enthält alle Informationen die den Hyperlink betreffen. Allerdings liefert Target nicht direkt das Objekt aus welchem der Hyperlink aufgerufen wurde. Wenn der Hyperlink in eine Zelle eingefügt wurde, gibt die Parent-Eigenschaft das übergeordnete Range-Objekt des Objektes Target, also die Zelle, in welcher der Hyperlink hinterlegt ist, zurück. Über die Address-Eigenschaft des Range-Objektes wird die Zelladresse ermittelt. Der Tabellenblattname wird über das Schlüsselwort Me ermittelt. Me bezieht sich auf die Klasse, in welcher der Code ausgeführt wird. Die Name-Eigenschaft gibt den Namen des Objekts Me, also den Tabellenblattnamen zurück, in dem die Prozedur hinterlegt ist. In einem Meldungsfenster wird der Tabellenblattname mit dem auslösenden Zellbezug zu einer Zeichenkette verbunden.

Ereignisse

218 Adresse zu Hyperlink ermitteln

MsgBox "Der Hyperlink wurde aus der Zelle:" & _ vbCr & "'" & _ Me.Name & "!" & _ Target.Parent.Address(0, 0) & _ Listing 366

Ereignisse

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_15_FollowHyperlink.xlsm ' Ereignis Tabelle2 (HyperlinkAddress) ‘===============================================================

Ereignisse

Abbildung 213: Zelladresse des auslösenden Hyperlinks

2471_Excel-VBA.book Seite 628 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

628 >> Autoprozeduren "'" & vbCr & _ "aufgerufen.", _ vbInformation

Ereignisse

End Sub Listing 366 (Forts.)

219 Autoprozeduren

Ereignisse

Public Sub Auto_Open()

oder Public Sub Auto_Close()

beginnen. Dies sind so genannte Autoprozeduren. Seit Einführung von Ereignisprozeduren in Excel 97 stehen sie in neueren Excel-Versionen nur noch aus Kompatibilitätsgründen zur Verfügung. Im Gegensatz zu den Ereignisprozeduren werden sie nicht in einem Klassenmodul sondern in einem beliebigen allgemeinen Modul gespeichert. Üblicherweise werden in der derzeitigen VBA-Programmierung mit Microsoft Visual Basic 6.5 die analogen Ereignisse Workbook_Open bzw. _Close des Workbook-Objektes verwendet. Da aber noch ältere Dateien mit diesen Makros ausgestattet sind und Autoprozeduren bis nachweislich Excel 2007 funktionsfähig sind, stellen wir Ihnen hier ein Beispiel dazu vor. Im Abschnitt 195 haben wir Sie darauf hingewiesen, dass in einer Arbeitsdatei nur ein gleichnamiges Ereignis im Klassenmodul DIESEARBEITSMAPPE hinterlegt werden darf. Ebenso verhält es sich mit den Autoprozeduren. Sind zum Beispiel mehrere Auto_Open-Prozeduren in einer Arbeitsdatei gespeichert, erfolgt beim Öffnen der Datei eine Fehlermeldung und keine der hinterlegten Prozeduren wird ausgeführt. Dabei ist es gleichgültig ob die Prozeduren in einem oder in verschiedenen Modulen gespeichert sind. Wenn in einer Excel-Datei eine Prozedur mit Auto_Open bzw. Auto_Close existiert, werden diese Prozeduren automatisch beim Öffnen oder Schließen der Datei ausgeführt. Hinweis

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Vielleicht haben Sie schon einmal Prozeduren gesehen die mit

Wenn das Laden oder Schließen einer Excel-Datei durch VBA-Code ausgelöst wird, werden Autoprozeduren nicht automatisch ausgeführt. Führen Sie die RunAutoMacros-Methode für die betreffende Arbeitsmappe aus, um die Prozeduren dennoch auszuführen.

In der Beispieldatei 09_16a_AutoMacros.xlsm befinden sich zwei Schaltflächen, über welche die Testdatei 09_16b_TestAutoMacros.xlsm geöffnet und geschlossen werden

2471_Excel-VBA.book Seite 629 Dienstag, 4. Dezember 2007 1:42 13

Public Sub Auto_Open() MsgBox _ "Die Datei:" & vbNewLine & _ ThisWorkbook.Name & _ vbNewLine & "wird geöffnet." End Sub

Public Sub Auto_Close() MsgBox _ "Die Datei:" & vbNewLine & _ ThisWorkbook.Name & _ vbNewLine & "wird geschlossen." End Sub

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_16b_TestAutoMacros.xlsm ' Modul mdl_01_AutoMacros ‘===============================================================

Ereignisse

kann. Diese Testdatei enthält ein Auto_Open- und ein Auto_Close-Ereignis, die in einem Standardmodul gespeichert sind.

Ereignisse

629

Ereignisse

>> Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_16a_AutoMacros.xlsm ' Modul mdl_01_WorkbookOpen ‘=============================================================== Public Sub WorkbookOpenWithAutoMacros() Dim strWb As String

Ereignisse

In der Beispieldatei soll die Testdatei im Hintergrund geöffnet, also nicht angezeigt werden. Dementsprechend stellen wir die Bildschirmaktualisierung ScreenUpdating zunächst auf False. Anschließend wird die Testdatei über die Open-Methode geöffnet und die Auto_Open-Prozedur der Testdatei über die RunAutoMacros-Methode aufgerufen. Bevor die Bildschirmaktualisierung wieder eingeschaltet wird, muss die aufrufende Datei aktiviert werden, da sonst nach Beendigung der Prozedur die Testdatei angezeigt würde.

Ereignisse

220 Datei öffnen und Auto_Open-Prozedur aufrufen

Ereignisse

Listing 367

Listing 368

Ereignisse

' Pfad und Name der Testdatei

2471_Excel-VBA.book Seite 630 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

630 >> Datei schließen und Auto_Close-Prozedur aufrufen strWb = _ ThisWorkbook.Path & "\09_16b_TestAutoMacros.xlsm"

Ereignisse

' Bildschirmaktualisierung ausschalten Application.ScreenUpdating = False ' Datei öffnen Workbooks.Open strWb

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

' Auto_Open-Prozedur der Testdatei aufrufen ActiveWorkbook.RunAutoMacros xlAutoOpen ' Diese Arbeitsmappe aktivieren ThisWorkbook.Activate ' Bildschirmaktualisierung einschalten Application.ScreenUpdating = True End Sub Listing 368 (Forts.)

221 Datei schließen und Auto_Close-Prozedur aufrufen Um eine Datei zu schließen, muss vorab überprüft werden, ob diese überhaupt geöffnet ist, da sonst eine Fehlermeldung ausgegeben wird. In einer For Each-Schleife werden die Namen aller geöffneten Arbeitsmappen der Excel-Instanz mit dem Namen der zu öffnenden Datei verglichen. Wird die Datei gefunden, wird die der Testdatei zugeordnete Auto_Close-Prozedur ausgeführt. Im Anschluss daran wird die Testdatei geschlossen. Damit beim Schließen der Datei mögliche Änderungen keine Speicherabfrage hervorrufen, wird das SaveChanges-Argument auf False gesetzt und die Prozedur anschließend mit Exit Sub verlassen. Die im Anschluss an die For Each-Schleife aufgeführte Meldung wird nur dann angezeigt, wenn die angegebene Datei nicht in der Workbooks-Auflistung vorhanden ist. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_16a_AutoMacros.xlsm ' Modul mdl_02_WorkbookClose ‘=============================================================== Public Sub WorkbookCloseWithAutoMacros() Dim strWb As String Dim Wb As Workbook

Ereignisse

' Name der Testdatei Listing 369

2471_Excel-VBA.book Seite 631 Dienstag, 4. Dezember 2007 1:42 13

631

strWb = "09_16b_TestAutoMacros.xlsm"

Ereignisse

>> Ereignisse

' Prozedur verlassen Exit Sub End If Next ' Meldung dass angegebene Datei nicht geöffnet ist MsgBox _ "Die Datei:" & vbNewLine & _ strWb & vbNewLine & _ "ist nicht geöffnet.", _ vbExclamation

Ereignisse Ereignisse

' In gesuchter Arbeitsmappe auszuführen With Workbooks(strWb) ' Auto_Close Prozedur ausführen .RunAutoMacros xlAutoClose ' Datei schließen, Änderungen nicht speichern .Close SaveChanges:=False End With

Ereignisse

' Alle geöffneten Arbeitsmappe der Excel Instanz durchlaufen For Each Wb In Application.Workbooks ' Vergleich über Dateinamen If Wb.Name = strWb Then

Ereignisse

' Bildschirmaktualisierung ausschalten Application.ScreenUpdating = False

222 Begrüßung nach der Tageszeit Wie im oberen Abschnitt bereits erwähnt, darf in einer Excel-Arbeitsmappe jeweils nur eine gleichnamige Ereignis- bzw. Autoprozedur gespeichert sein. Es ist aber durchaus möglich, in »einer« Excel-Datei ein Workbook_Open »und« ein Auto_OpenMakro zu hinterlegen. In unserer Beispieldatei haben wir beide Möglichkeiten, ein Makro bei Dateiöffnung zu starten, hinterlegt.

Ereignisse

Listing 369 (Forts.)

Ereignisse

' Bildschirmaktualisierung einschalten Application.ScreenUpdating = True End Sub

Ereignisse

Als Erstes wird das Workbook_Open-Ereignis ausgelöst. Nach dessen Abarbeitung erfolgt der Aufruf der Auto_Open-Prozedur. Entsprechend dieser Abfolge gehen wir in der Beschreibung nacheinander vor.

2471_Excel-VBA.book Seite 632 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

632 >> Zoomfaktor über Bildschirmauflösung einstellen

Beim Öffnen der Datei wird die aktuelle Uhrzeit aus der Systemsteuerung in einer Select...Case-Anweisung überprüft. Entspricht ein Case Is-Wert der aktuellen Uhrzeit, wird der hinterlegte Text in einem Meldungsfenster ausgegeben. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_17a_AutoOpenZoom.xlsm ' Ereignis DieseArbeitsmappe ‘===============================================================

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Private Sub Workbook_Open() Dim strText As String Select Case Hour(Time) Case Is < 5 strText = "Ist da ein Nachtschwärmer unterwegs?" Case Is < 8 strText = "Heute bist Du ja ein Frühaufsteher" Case Is < 10 strText = "Guten Morgen" Case Is < 14 strText = "Einen schönen Tag wünsch ich Dir" Case Is < 17 strText = "Einen schönen Nachmittag wünsch ich Dir" Case Is < 24 strText = "Einen schönen guten Abend" End Select MsgBox "Es ist " & Time & " Uhr" & _ vbNewLine & _ vbNewLine & _ strText End Sub Listing 370

223 Zoomfaktor über Bildschirmauflösung einstellen In einem größeren Unternehmen wird über ein Netzwerk oft von mehreren Anwendern auf die gleiche Datei zugegriffen. Wenn die einzelnen Benutzer unterschiedliche Bildschirmeinstellungen verwenden, wird die Tabelle teilweise zu groß, oder zu klein dargestellt. Um eine individuelle Ansicht zu erhalten, stellt jeder Benutzer dieser Datei den Zoomfaktor über den Befehl ANSICHT | ZOOM oder den Schieberegler in der Statuszeile auf seine Bildschirmeinstellung ein.

2471_Excel-VBA.book Seite 633 Dienstag, 4. Dezember 2007 1:42 13

633

Ereignisse

Ereignisse

>> Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_17a_AutoOpenZoom.xlsm ' Modul mdl_01_AutoOpenZoom ‘=============================================================== Declare Function GetSystemMetrics Lib "user32" _ (ByVal nindex As Long) As Long

Ereignisse Ereignisse

Bei Dateiöffnung wird über eine Auto_Open-Prozedur die aktuelle Bildschirmeinstellung der jeweiligen Arbeitsstation, an welcher die Arbeitsmappe geöffnet wurde, aus der SYSTEMSTEUERUNG | ANZEIGE | EINSTELLUNGEN über die API-Funktion GetSystemMetrics ausgelesen. Über eine Select...Case-Schleife wird entsprechend der ausgelesenen Bildschirmbreite der im Code definierte Zoomfaktor an die Variable Zoomfactor übergeben. Nachdem der Zoomfaktor eingestellt wurde, informiert Sie ein Meldungsfenster über die aktuellen Bildschirmeinstellungen sowie den eingestellten Zoomfaktor. In der Praxis können Sie auf das Meldungsfenster verzichten. Durch ein vorangestelltes Hochkomma ' in der ersten Zeile des MsgBox-Codes wird dieser auskommentiert und beim Makrodurchlauf nicht abgearbeitet. Sie können die entsprechenden Zeilen der MsgBox auch aus dem Code löschen. Die Funktionalität der ZoomEinstellung bleibt davon unberührt.

Ereignisse

Diese umständliche, manchmal auch etwas nervige Handhabung, können Sie sich von Excel abnehmen lassen.

Ereignisse

Abbildung 214: Zoom-Einstellung

Sub Auto_Open() lngWidth As Long lngHeigh As Long Zoomfactor As Integer

Listing 371

Ereignisse

Public Dim Dim Dim

Ereignisse

Public Const SM_CXSCREEN = 0 Public Const SM_CYSCREEN = 1

2471_Excel-VBA.book Seite 634 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

634 >> Zoomfaktor mit Workbook_Open lngWidth = GetSystemMetrics(SM_CXSCREEN) lngHeigh = GetSystemMetrics(SM_CYSCREEN) Select Case lngWidth Case Is >= 800 Zoomfactor = 80 Case Is >= 1024 Zoomfactor = 100 Case Is >= 800 Zoomfactor = 80 Case Is >= 1280 Zoomfactor = 120 End Select Application.ActiveWindow.Zoom = Zoomfactor MsgBox "Bildschirmgröße: " & _ lngWidth & " x " & lngHeigh & _ vbCr & vbCr & _ "Zoomfaktor : " & Zoomfactor & " %" End Sub Listing 371 (Forts.)

Ereignisse

Ereignisse

Ereignisse

Ereignisse

224 Zoomfaktor mit Workbook_Open Eine praktische Verwendung der Zoomeinstellung anhand der Bildschirmeinstellung findet sich auch am heimischen PC. Hinterlegen Sie die Prozeduren aus der Beispielmappe in der Standardarbeitsmappe Mappe.xltx. Diese ist im Ordner XLSTART gespeichert und dient als Vorlage wenn eine neue Datei erstellt wird. Die Datei Mappe.xltx ist mit der Datei Normal.dotx aus MS Word vergleichbar. Legen Sie eine neue Datei an, dann wird automatisch der passende Zoomfaktor zur aktuellen Bildschirmeinstellung eingestellt. Wird die Datei auf einem anderen Rechner mit anderen Bildschirmeinstellungen geöffnet, erfolgt ebenfalls eine Anpassung des Zoomfaktors. Haben Sie Excel unter Windows XP installiert befindet sich der XLStart-Ordner im Regelfall im Speicherpfad: C:\Dokumente und Einstellungen\Benutzername\Anwendungsdaten\Microsoft\Excel\ XLStart. Wenn Microsoft Office Excel 2007 auf Windows Vista installiert wurde, finden Sie die Datei Mappe.xltx im Pfad: C:\Users\Benutzername\AppData\Roaming\Microsoft\Excel\XLSTART Das Makro aus dem Abschnitt 223 können Sie nicht eins zu eins in das Klassenmodul DIESEARBEITSMAPPE kopieren um es in einer Workbook_Open-Prozedur anzuwenden. Die Deklarierung der im Makro verwendeten DLL-Funktion user32, sowie die öffent-

2471_Excel-VBA.book Seite 635 Dienstag, 4. Dezember 2007 1:42 13

Damit auch ein neu eingefügtes Tabellenblatt den korrekten Zoomfaktor erhält, wird im Workbook_NewSheet-Ereignis ebenfalls der Makro-Aufruf ZoomControl hinterlegt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_17b_WorkbookOpenZoom.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_Open() ZoomControl End Sub Private Sub Workbook_NewSheet(ByVal Sh As Object) ZoomControl End Sub

Ereignisse

In der Beispielmappe hinterlegen wir die benötigten Deklarierungen zur Zoomeinstellung sowie das Makro ZoomControl in einem allgemeinen Modul. Das Makro ZoomControl wird im Workbook_Open-Ereignis aufgerufen.

Ereignisse

lich deklarierten Konstanten SM_CXSCREEN und SM_CYSCREEN müssen in einem allgemeinen Modul gespeichert werden.

Ereignisse

635

Ereignisse

>> Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_17b_WorkbookOpenZoom.xlsm ' Modul mdl_01_Zoom ‘===============================================================

Ereignisse

Listing 372

Public Dim Dim Dim

Sub ZoomControl() lngWidth lngHeigh Zoomfactor

lngWidth = GetSystemMetrics(SM_CXSCREEN) lngHeigh = GetSystemMetrics(SM_CYSCREEN)

Ereignisse

Public Const SM_CXSCREEN = 0 Public Const SM_CYSCREEN = 1

Ereignisse

Declare Function GetSystemMetrics Lib "user32" _ (ByVal nindex As Long) As Long

Listing 373

Ereignisse

Select Case lngWidth Case Is >= 800

2471_Excel-VBA.book Seite 636 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

636 >> Zeitgesteuerte Makros Zoomfactor = Case Is >= 1024 Zoomfactor = Case Is >= 800 Zoomfactor = Case Is >= 1280 Zoomfactor = End Select

80 100 80 120

Ereignisse

Ereignisse

Application.ActiveWindow.Zoom = Zoomfactor End Sub Listing 373 (Forts.)

225 Zeitgesteuerte Makros Wollen Sie ein Makro täglich zu einer bestimmten Zeit automatisch aufrufen, verwenden Sie die OnTime-Methode, welche zu den Zeitereignissen zählt. Diese Methode bewirkt, dass eine Prozedur zu einem bestimmten Zeitpunkt in der Zukunft ausgeführt wird, oder nachdem eine bestimmte Zeitspanne vergangen ist. Die Syntax der OnTime-Methode mit ihren Parametern lautet:

Ereignisse

Ereignisse

Ereignisse

Ereignisse

OnTime(EarliestTime, Procedure, [LatestTime], [Schedule])

Die ersten beiden Parameter sind zwingend anzugeben. Parameter drei und vier sind optional, dass bedeutet dass sie nicht angegeben werden müssen. Enthalten sie aber einen Wert, wird dieser bei der Verarbeitung der Methode angewandt. Im ersten Beispiel wird zehn Sekunden nachdem das Makro OnTime1 aufgerufen wurde, das Makro myMakro1 ausgeführt. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Modul mdl_01_OnTimeMakros ‘=============================================================== Public Sub OnTime1() ' Prozedur in 10 Sek. aufrufen Application.OnTime Now + TimeValue("00:00:10"), "myMakro1" End Sub Public Sub myMakro1() MsgBox "Hallo " & Application.UserName & _ vbNewLine & vbNewLine & _ "hier kommt Makro1" End Sub Listing 374

2471_Excel-VBA.book Seite 637 Dienstag, 4. Dezember 2007 1:42 13

Listing 375

Die Zeit, zu der das Makro OnTime3 ausgeführt werden soll, steht in der benannten Zelle MyTime des Tabellenblattes und wird beim Durchlaufen der Codezeilen in die Prozedur eingelesen. Dadurch muss bei einer Änderung der Aufrufzeit nicht der Code geändert werden, sondern lediglich die Zeitangabe in der Zelle. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Modul mdl_01_OnTimeMakros ‘=============================================================== Public Sub OnTime3() Dim MyTime As Variant ' Zeit für Prozeduraufruf aus Zelle ermitteln MyTime = Format(Range("MyTime").Value, "hh:mm:ss") Application.OnTime TimeValue(MyTime), "myMakro3" End Sub Public Sub myMakro3() MsgBox "Hallo " & Application.UserName & _ vbNewLine & vbNewLine & _ "hier kommt Makro3" End Sub

Ereignisse Ereignisse

Public Sub myMakro2() MsgBox "Hallo " & Application.UserName & _ vbNewLine & vbNewLine & _ "hier kommt Makro2" End Sub

Ereignisse

Public Sub OnTime2() ' Prozdur zu festgelegter Zeit aufrufen Application.OnTime TimeValue("10:15:00"), "myMakro2" End Sub

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Modul mdl_01_OnTimeMakros ‘===============================================================

Ereignisse

Makros können zu einer vorgegebenen Zeit ausgeführt werden. Die Angabe eines künftigen Datums ist mit der OnTime-Methode nicht möglich.

Ereignisse

637

Ereignisse

>> Ereignisse

Ereignisse

Listing 376

2471_Excel-VBA.book Seite 638 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

638 >> Uhrzeit in Statuszeile zeitbegrenzt anzeigen

226 Uhrzeit in Statuszeile zeitbegrenzt anzeigen Bei den bisherigen Beispielen zur OnTime-Methode wurden nur die ersten beiden, zwingend anzugebenden, Parameter verwendet: die »Startzeit« und der »Name« des aufgerufenen Makros. Im vierten Parameter LatestTime kann der letzte Zeitpunkt angegeben werden, zu dem die angegebene Prozedur gestartet werden soll. Um einen periodischen Aufruf einer Prozedur zu erreichen, setzen Sie die Startzeit des aufgerufenen Makros aus der aktuellen Uhrzeit plus einer angegebenen Zeitspanne zusammen und geben den Makronamen der eigenen Prozedur als Aufrufmakro an. Public Sub Test() MsgBox "Test" Application.OnTime Now + TimeValue("00:00:10"), "Test" End Sub

Der vorgenannte Code würde ohne weitere Anweisungen in einer Endlosschleife enden. Sie können ihn im VBA-Editor auf die harte Tour beenden, indem Sie zum Beispiel in der Aufrufzeile der Prozedur den Namen der Prozedur ändern, was eine Fehlermeldung bewirkt, da das aufgerufene Makro nicht gefunden wird. Löschen Sie während der Laufzeit der Endlosschleife die OnTime-Anweisung im Code, erfolgt ebenfalls ein Abbruch. Wie Sie sehen, ist die Beendigung einer Zeitschleife nicht ganz einfach, aber nicht unmöglich. Aus diesem Grund beschreiben wir die Vorgehensweise entsprechend ausführlich. Der letzte Zeitpunkt und somit die Beendigung der vormals Endlosschleife wird über den Parameter LatestTime angegeben. Dadurch wird die einmal angestoßene Zeitschleife nicht unendlich ausgeführt. In der Prozedur StatusBarTime1 wird das aktuelle Datum sowie die Uhrzeit alle zehn Sekunden als Text in der Statuszeile angezeigt. Für den spätesten Zeitpunkt wird die Startzeit plus eine Minute in der Variablen StopTime gespeichert, damit die entstandene Zeitschleife nach einer Minute beendet und keine Endlosschleife erzeugt wird. Hier ergibt sich das Problem, dass die Variable StopTime jeweils zu Beginn des Makros einen neuen Wert annehmen würde, nämlich die aktuelle Systemzeit plus eine Minute und somit wäre die Prozedur wieder in einer Endlosschleife. Um dieses Problem auszumerzen, verwenden wir die Variable blnTime vom Datentyp Boolean. Standardmäßig hat eine Variable dieses Datentyps den Wert False. Diese Wahrheitsprüfung setzten wir in einer If...Then-Anweisung ein. Da die Variable blnTime beim ersten Makrodurchlauf noch den Wert False hat, wird diese Schleife zunächst abgearbeitet und der letzte Zeitpunkt des Makroaufrufes in die Variable StopTime geschrieben. Gleich im Anschluss daran wird blnTime auf True gesetzt, damit beim erneuten Durchlauf des Makros diese If...Then-Schleife nicht noch einmal durchlaufen wird. Die Zeitangaben werden nun bei jedem Makrodurchlauf über die StatusBar-Eigenschaft in der Statuszeile angezeigt. Im Anschluss daran kommt die OnTime-Methode zum Zuge und meldet das Makro für die nächste Zeitanzeige an. Bei Erreichen der Endzeit muss die Verwaltung der Statuszeile wieder an Excel zurückgegeben werden.

2471_Excel-VBA.book Seite 639 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse

As Double As Double As Boolean

Public Sub StatusBarTime1() 'nächster Makroaufruf in 10 Sekunden dbl_ETime = Now + TimeValue("00:00:10") If blnETime = False Then 'Uhrzeit in Statuszeile 1 Minute lang anzeigen dbl_StopTime = Now + TimeValue("00:01:00") blnTime = True End If With ThisWorkbook ' Uhrzeit in Statuszeile ausgeben Application.StatusBar = _ Format(Now, "DDDD DD.MM.YYYY hh:mm:ss") End With ' Zeitversetzter Makroaufruf Application.OnTime _ EarliestTime:=dbl_ETime, _ Procedure:="StatusBarTime1", _ LatestTime:=dbl_StopTime Listing 377

Ereignisse Ereignisse Ereignisse

Dim dbl_ETime Dim dbl_StopTime Public blnTime

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Modul mdl_02_StatusBar_1 ‘===============================================================

Ereignisse

Da die Variable blnTime sowohl in einem Modul als auch im Workbook_Close-Ereignis verwendet wird, muss sie durch die vorangestellte Public-Anweisung global deklariert werden. Sie kann dadurch aus allen Modulen des VBA-Projektes angesprochen werden.

Ereignisse

Die verwendeten Variablen müssen vor dem Sub-Aufruf deklariert werden, damit sie bei erneutem Schleifendurchlauf ihren gespeicherten Wert behalten und im Makro korrekt abgearbeitet werden können.

Ereignisse

Die zuletzt geschriebene Zeit würde sonst in der Statuszeile stehen bleiben. Dazu wird der letztmalige Zeitpunkt des Aufrufzeitpunkts dbl_ETime mit der Endzeit dbl_StopTime verglichen. Ist die Endzeit größer, wird die Statuszeile zurück-, sowie die Variable blnTime auf False gesetzt. Bei einem erneuten Makroaufruf wird dadurch die korrekte Zuweisung der Endzeit wieder ermöglicht.

Ereignisse

639

2471_Excel-VBA.book Seite 640 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

640 >> Uhrzeit in Statuszeile steuern If dbl_ETime >= dbl_StopTime Then ' Statuszeile zurücksetzen Application.StatusBar = False blnTime = False End If End Sub Listing 377 (Forts.)

Ereignisse

Ereignisse

Die Anzeige der Uhrzeit soll »nur« in unserer Beispieldatei angezeigt werden. Dementsprechend wird bei Deaktivierung der Mappe die Statuszeile zurückgesetzt, damit Excel deren Verwaltung in anderen Arbeitsmappen übernehmen kann. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Ereignis Diese Arbeitsmappe ‘=============================================================== Private Sub Workbook_Deactivate() Application.StatusBar = False End Sub

Ereignisse

Ereignisse

Listing 378

Spätestens wenn die Arbeitsmappe geschlossen wird, muss die Variable blnTime auf False gesetzt werden, um einen Abbruch der Zeitschleife sicherzustellen. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Ereignis Diese Arbeitsmappe ‘=============================================================== Private Sub Workbook_BeforeClose(Cancel As Boolean) blnTime = True End Sub

Ereignisse

Ereignisse

Listing 379

227 Uhrzeit in Statuszeile steuern Die erste Variante zur Anzeige der Uhrzeit in der Statuszeile wird durch die Angabe der »Endzeit« für eine bestimmte Zeitspanne angezeigt. Genauso gut können Sie die Anzeige mittels einer booleschen Variablen per »Knopfdruck« regeln. Im folgenden Makro nutzen wir den Standardwert False einer Variablen vom Datentyp Boolean. Dabei wird die aktualisierte Uhrzeit solange in die Statuszeile geschrieben bis über ein weiteres Makro der Wahrheitswert der verwende-

2471_Excel-VBA.book Seite 641 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Modul mdl_03_StatusBar_2 ‘===============================================================

' Zeitversetzter Makroaufruf Application.OnTime _ EarliestTime:= dbl_ETime2, _ Procedure:="StatusBarTime2" Else ' Statuszeile zurücksetzen Application.StatusBar = False blnTime2 = False End If End Sub Public Sub SetblnTime2() ' Prüf- Variable aktivieren blnTime2 = True End Sub Listing 380

Ereignisse Ereignisse

' Prüfung boolescher Variable If blnTime2 = False Then ' Uhrzeit in Stauszeile ausgeben Application.StatusBar = _ Format(Now, "DDDD DD.MM.YYYY hh:mm:ss")

Ereignisse

Public Sub StatusBarTime2() 'nächster Makroaufruf in 3 Sekunden dbl_ETime2 = Now + TimeValue("00:00:03")

Ereignisse

' Uhrzeit in Statuszeile bis auf Widerrruf anzeigen

Ereignisse

As Double As Boolean

Ereignisse

Dim dbl_ETime2 Public blnTime2

Ereignisse

ten Variablen auf True gesetzt und somit die Anzeige beendet wird. Die Stopp-Prozedur SetBolTime2 wurde wie die Aufrufprozedur einer Schaltfläche im Tabellenblatt zugewiesen.

Ereignisse

641

2471_Excel-VBA.book Seite 642 Dienstag, 4. Dezember 2007 1:42 13

228 Uhrzeitmeldung nach Zeitplan ausführen Das Makro OnTime4Start veranschaulicht die Verwendung des vierten Parameter Schedule der OnTime-Methode. Der Wert True führt eine neue OnTime-Prozedur aus. False löscht eine vorher eingestellte Prozedur. Der Standardwert ist True. Bei der folgenden Prozedur wird alle fünf Sekunden die aktuelle Uhrzeit in einem Meldungsfenster angezeigt. Um diese Schleife zu unterbrechen setzen Sie ein weiteres Makro ein. In diesem Stopp-Makro OnTime4Stop wird die termingesetzte Prozedur OnTime4Start wieder gelöscht, indem dem vierten Parameter der OnTime-Methode der Wert False zugewiesen wird. In dieser Prozedur muss sowohl die »genaue« Zeit als auch der »genaue« Name der Prozedur angegeben werden, welche gelöscht werden soll. Wenn VBA in der Liste der vorgemerkten Prozeduren die zu löschende Prozedur nicht findet, kommt es zu einer Fehlermeldung. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_18_OnTime.xlsm ' Modul mdl_04_ScheduleTime ‘=============================================================== Dim ET

As Variant

Public Sub OnTime4Start() ' Ausführzeit speichern ET = Now + TimeValue("00:00:05") MsgBox " es ist jetzt " & Format(Time, "hh:mm:ss") & " Uhr"

Ereignisse

' Zeitgesteuerter Prozeduraufruf Application.OnTime _ EarliestTime:=ET, _ Procedure:="OnTime4Start" End Sub Public Sub OnTime4Stop() ' Fehlerbehandlung, falls Prozeduraufruf gelöscht wurde On Error Resume Next

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

642 >> Uhrzeitmeldung nach Zeitplan ausführen

' Zeitgesteuerter Prozeduraufruf zurücksetzen Application.OnTime _ EarliestTime:=ET, _ Procedure:="OnTime4Start", _ Schedule:=False End Sub

Ereignisse

Listing 381

2471_Excel-VBA.book Seite 643 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse

Zusatztasten

Aktion

(2)

Die Zahl 2 wird geschrieben

(Shift) (2)

Das Anführungszeichen " wird geschrieben

(Strg) (2)

Markierte Zellen erhalten das Format Fett

(Strg) (Shift) (2)

Markierte Zellen erhalten das Wissenschaft-Format 0,00E+00

(Alt) (2)

Bis Excel 2003 keine Aktion Excel 2007: Anzeige der Liste der verfügbaren Rückgängig Aktionen

(AltGr) (2)

Die hochgestellte

Mit der OnKey-Methode können Aktionen auf alle Tasten und Tastenkombinationen individuell definiert werden. Die nachfolgende Übersicht zeigt die verwendeten Zusatztasten und Syntaxen zu den in Tabelle 44 genannten Tastenkombinationen. Zusatztasten

Syntax der OnKey-Methode

(2) über den Schreibblock der Tastatur

Application.OnKey "2"

(Shift) (2)

Application.OnKey "+2"

(Strg) (2)

Application.OnKey "^2"

(Strg) (Shift) (2)

Application.OnKey "^+2"

(Alt) (2)

Application.OnKey "%2"

(AltGr) (2)

Application.OnKey "^%2"

Tabelle 45: Zusatztasten-Übersicht

Ereignisse

Eine Übersicht aller in Excel zur Verfügung stehenden Tastenkombinationen finden Sie in der Online-Hilfe von Excel. Drücken Sie die Taste (F1), um die Microsoft Excel-Hilfe aufzurufen und schreiben in die Suchzeile das Wort Tastenkombinationen. Aus den aufgelisteten Themen wählen Sie Tastenkombinationen und Funktionstasten in Excel.

Ereignisse

Tipp

Tabelle 44: Tastenkombinationen mit der Zahl 2

Ereignisse

wird geschrieben

Ereignisse

2

Ereignisse

Jeder Tastendruck auf der Tastatur löst eine Aktion in der gerade aktiven Anwendung aus und stellt somit ein Ereignis dar. Drücken Sie in Excel eine oder mehrere Tasten gleichzeitig, wird eine bestimmte – für diese Taste/Tastenkombination definierte – Aktion ausgeführt. Am Beispiel der Zahl 2 zeigen wir Ihnen die verschiedenen Auswirkungen von Tastenkombinationen in Microsoft Office Excel.

Ereignisse

229 Tastenkombinationen erstellen

Ereignisse

643

Ereignisse

Aus den Zusatztasten laut Tabelle 45 können beliebige Kombinationen erstellt werden.

2471_Excel-VBA.book Seite 644 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

644 >> Tastenkombinationen erstellen

Sie können einer vorhandenen Tastenkombination eine neue Aktion in Form einer Prozedur zuweisen. Ebenfalls ist es möglich standardmäßig nicht verwendete Kombinationen zu belegen. Dadurch werden keine von Excel verwendeten Kombinationen außer Kraft gesetzt. Nachdem die Prozedur MyOnKey2 durchlaufen wurde, wird beim Drücken der Tastenkombination (Strg) (Shift) (2) das Makro MyProcedure aufgerufen. Üblicherweise würden die markierten Zellen im Wissenschafts-Format formatiert. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_19_OnKey.xlsm ' Modul mdl_01_MyOnKey ‘=============================================================== Public Sub MyOnKey2() ' STRG + Shift + 2 Makro zuweisen Application.OnKey "^+2", "MyProcedure" End Sub Public Sub MyProcedure() MsgBox _ "Sie haben gedrückt" End Sub

Ereignisse

Ereignisse

Listing 382

Um der Tastenkombination (Strg) (Shift) (2) deren ursprüngliche Bedeutung (Wissenschafts-Format) wieder zuzuweisen, verwenden Sie folgende Prozedur: ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_19_OnKey.xlsm ' Modul mdl_01_MyOnKey ‘=============================================================== Public Sub ResetOnKey() ' STRG + Shift + 2 zurücksetzten Application.OnKey "^2" End Sub

Ereignisse

Ereignisse

Listing 383

Die von Excel zur Verfügung gestellten Tastenkombinationen können auch ganz deaktiviert werden. Nach dem Durchlauf der Prozedur DeaktivateOnKey bewirkt das Drücken der Tasten (Strg) (Shift) (2) keine Aktion mehr.

2471_Excel-VBA.book Seite 645 Dienstag, 4. Dezember 2007 1:42 13

>> Ereignisse

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_19_OnKey.xlsm ' Modul mdl_01_MyOnKey ‘===============================================================

Ereignisse

645

Public Sub DeaktivateOnKey() ' STRG + Shift + 2 deaktivieren Application.OnKey "^+2", "" End Sub

(PAUSE)

{BREAK}

(CapsLock)

{CAPSLOCK}

(Entf)

{DELETE} oder {DEL}

(¼)

{DOWN}

(Ende)

{END}

(Enter) (Zehnertastatur)

{ENTER}

(Enter) (Schreibtastatur)

~ (Tilde)

(ESC)

{ESCAPE} oder {ESC}

(HILFE)

{HELP}

(Pos1)

{HOME}

(Einfg)

{INSERT}

(æ)

{LEFT}

(Num)

{NUMLOCK}

(Bild¼)

{PGDN}

(Bild½)

{PGUP}

(Enter)

{RETURN}

(Æ)

{RIGHT}

(ROLLEN)

{SCROLLOCK}

(Tab)

{TAB}

Tabelle 46: Tasten, die nicht gedruckt werden

Ereignisse

{BACKSPACE} oder {BS}

Ereignisse

(Backspace)

Ereignisse

Code

Ereignisse

TASTE

Ereignisse

Um einem der Sonderzeichen (+, ^ , % , usw.) eine Prozedur zuzuweisen, schließen Sie das Zeichen in geschweifte Klammern ein. Verwenden Sie für Zeichen, die beim Drücken einer Taste nicht angezeigt werden (z.B. EINGABE oder TAB), die Codes aus der Tabelle 46. Jeder Code in der Tabelle steht für eine Taste auf der Tastatur.

Ereignisse

Listing 384

2471_Excel-VBA.book Seite 646 Dienstag, 4. Dezember 2007 1:42 13

TASTE

Code

(½)

{UP}

(F1) bis (F15)

{F1} bis {F15}

Tabelle 46: Tasten, die nicht gedruckt werden (Forts.)

Sie können bereits zu Beginn einer Makroaufzeichnung eine Tastenkombination zum späteren Aufruf der Prozedur zuweisen.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

646 >> Tastenkombinationen erstellen

Ereignisse

Ereignisse

Ereignisse

Hinwei s

Ereignisse

Abbildung 215: Tastenkombination zuweisen

Wenn Sie einem Makro eine bereits bestehende Tastenkombination zuweisen, wird deren ursprüngliche Bedeutung zurückgesetzt. Weisen Sie einem Makro zum Beispiel die Tastenkombination (Strg) (A) zu, wird die ursprüngliche Bedeutung (ganzes Tabellenblatt markieren) ignoriert. Spätestens nach einem Excel-Neustart werden aber alle Standard-Tastenkombinationen wieder hergestellt und mit der Tastenkombination (Strg) (A) werden wieder alle Zellen des aktiven Tabellenblattes markiert.

Geben Sie in dem Dialog aus Abbildung 215 im Feld TASTENKOMBINATION einen Buchstaben ein, um dem ausgewählten Makro eine Tastenkombination zuzuweisen. Die endgültigen Tastenkombinationen setzen sich immer folgendermaßen zusammen: (Strg) (eingegebener_Buchstabe). Wenn Sie während der Eingabe des Buchstabens die (Shift)-Taste gedrückt halten, setzt sich die endgültige Tastenkombination folgendermaßen zusammen: (Strg) (Shift) (eingegebener_Buchstabe). Wollen Sie einem bestehenden Makro nachträglich eine Tastenkombination zuweisen, markieren Sie im Makrodialog die gewünschte Prozedur und klicken auf die Schaltfläche OPTIONEN. In dem darauf erscheinenden Fenster MAKROOPTIONEN können Sie eine neue Tastenkombination eingeben, oder eine bestehende ändern.

2471_Excel-VBA.book Seite 647 Dienstag, 4. Dezember 2007 1:42 13

647

Ereignisse

Ereignisse

Ereignisse

>> Ereignisse

Um sich in größeren Tabellen leichter orientieren zu können, gibt es die Möglichkeit die Aktionen der Pfeiltasten zu beeinflussen. Üblicherweise wird der Cursor durch Betätigen der Pfeiltasten jeweils um eine Zelle versetzt. Pfeil oben und -unten wechselt die Zeile, Pfeil links und -rechts die Spalte. In diesem Beispiel bringen wir die Zusatztaste (Alt) mit ins Spiel. Drücken Sie die Pfeiltasten jeweils in Verbindung mit der (Alt)-Taste, dann wird sowohl die ganze Zeile als auch die Spalte der aktiven Zelle aktiviert, also farblich hervorgehoben. Durch die Markierung verändert sich der Zellenhintergrund selbständig, Es wird dabei keine Hintergrundfarbe zugewiesen, was deutlich wird, wenn die Markierung durch Klick auf eine einzelne Zelle aufgehoben wird. Wenn eine Gruppe aus mehreren Zellen markiert wurde, ist die aktive Zelle an ihrem weißen Zellenhintergrund zu erkennen. In der Beispielmappe haben wir in den Zellen des benutzten Bereichs Formeln hinterlegt (siehe Abbildung 217). Diese zeigen die Zeilen und Spaltennummer der jeweiligen Zelle in zwei Zeilen an. Einen manuellen Zeilenumbruch in einer Zelle erzeugen Sie über die Tastenkombination (Alt) (Enter). Wir setzen für einen Zeilenumbruch die Funktion ZEICHEN ein. Das Zeichen 10 steht für einen Zeilenumbruch. In dem Dia-

Ereignisse Ereignisse

230 Navigation mit Fadenkreuz

Ereignisse

Mit VBA lassen sich über die OnKey-Methode beliebige Kombinationen aus Zusatztasten mit Buchstaben, Zahlen oder Befehlstasten erstellen.

Ereignisse

Über die Dialog-Fenster MAKRO AUFZEICHNEN (siehe Abbildung 215) und MAKROOPTIONEN (siehe Abbildung 216) können Sie einer Prozedur nur Tastenkombinationen mit Buchstaben zuweisen. Als Zusatztasten sind nur die Taste (Strg) oder die Kombination (Strg) (Shift) zulässig.

Ereignisse

Hi n we is

Abbildung 216: Makro nachträglich Tastenkombination zuweisen

2471_Excel-VBA.book Seite 648 Dienstag, 4. Dezember 2007 1:42 13

logfeld ZELLEN FORMATIEREN, dass Sie über die Registerkarte START in der Gruppe ZELLEN | FORMAT | ZELLEN FORMATIEREN anzeigen können, wurde auf der Registerkarte AUSRICHTUNG die Option ZEILENUMBRUCH aktiviert. Die normale Bedeutung der Pfeiltasten (Zellenweise Cursorbewegung in einer Tabelle) wird durch dieses Beispiel nicht beeinträchtigt.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

648 >> Navigation mit Fadenkreuz

Abbildung 217: Spalte und Zeile der aktiven Zelle werden hervorgehoben.

Beim Öffnen der Beispielmappe wird über das Workbook_Activate-Ereignis die Prozedur ShortcutOn aufgerufen. Wechseln Sie in eine andere geöffnete Excel-Datei, oder beenden Sie die Beispieldatei oder Excel, wird das Workbook_Deactivate-Ereignis ausgelöst. Hier wird die Prozedur ShortcutOff zum Zurücksetzen der Tastenkombinationen angegeben. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_20_Navigation.xlsm ' Ereignis DieseArbeitsmappe ‘=============================================================== Private Sub Workbook_Activate() ShortcutOn End Sub

Ereignisse

Private Sub Workbook_Deactivate() ShortcutOff End Sub Listing 385

2471_Excel-VBA.book Seite 649 Dienstag, 4. Dezember 2007 1:42 13

Public Sub ShortcutOn() Application.OnKey "%{UP}", "ArrowUp" Application.OnKey "%{DOWN}", "ArrowDown" Application.OnKey "%{LEFT}", "ArrowLeft" Application.OnKey "%{RIGHT}", "ArrowRight" End Sub Public Sub ShortcutOff() Application.OnKey "%{UP}", "" Application.OnKey "%{DOWN}", "" Application.OnKey "%{LEFT}", "" Application.OnKey "%{RIGHT}", "" End Sub

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_20_Navigation.xlsm ' Modul mdl_01_ShortcutOnOff ‘===============================================================

Ereignisse

In der Prozedur ShortcutOn werden über die OnKey-Methode die einzelnen Makros zur Markierung der Zeilen und Spalten an die Tastenkombinationen (Alt) (Pfeiltasten) zugewiesen. Über die ShortcutOff-Prozedur werden die definierten Tastenkombinationen wieder gelöscht.

Ereignisse

649

Ereignisse

>> Ereignisse

Public Sub ArrowUp() Mark -1, 0 End Sub

Ereignisse

‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_20_Navigation.xlsm ' Modul mdl_02_Arrows ‘===============================================================

Ereignisse

Die folgenden Prozeduren rufen jeweils die Prozedur Mark auf. Am Beispiel der Prozedur ArrowUp verdeutlichen wir die Übergabe der genannten Argumente an die MarkProzedur. Das Makro ArrowUp wird ausgelöst, wenn die Tastenkombination (Alt) (½) gedrückt wurde. Durch die Pfeiltaste wird normalerweise die Zellenmarkierung einer einzelnen Zelle verschoben. Durch (½) wird die Zelle oberhalb der aktiven Zelle in der gleichen Spalte selektiert. Die aktive Zelle wird also um –1 Zeile und um 0 Spalten verschoben.

Ereignisse

Listing 386

Listing 387

Ereignisse

Public Sub ArrowDown() Mark 1, 0

2471_Excel-VBA.book Seite 650 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

650 >> Navigation mit Fadenkreuz End Sub

Ereignisse

Public Sub ArrowLeft() Mark 0, -1 End Sub Public Sub ArrowRight() Mark 0, 1 End Sub

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Listing 387 (Forts.)

Am Beispiel der ArrowUp-Prozedur werden beim Aufruf der Mark-Prozedur die mitgegebenen Argumente –1 und 0 an die Parameter lngRow und lngCol übergeben. Das erste Argument lngRow gibt die Zeilen-, das zweite Argument die Spaltenverschiebung zur aktiven Zelle an. Die drei weiteren Arrow-Prozeduren geben jeweils die entsprechenden Werte zur Zeilen- und Spaltenverschiebung an. In der Variablen rngCell wird mit der Offset-Methode ein Verweis auf die neue Zellposition gesetzt. Die Union-Methode gibt die Vereinigung von mindestens zwei Bereichen zurück. Durch Columns(rngCell.Column) wird die ganze Spalte, durch Rows(rngCell.Row) die ganze Zeile der neuen Zelladresse in der Union-Methode zusammengebracht. Es entsteht ein Kreuz welches als Mittelpunkt die aktive Zelle enthält (siehe Abbildung 217). Über die Goto-Methode werden die Zeile und Spalte welche in der Union-Methode vereint wurden, markiert. Die in der Variablen rngCell gespeicherte Zelladresse wird aktiviert, weil sonst die erste Zelle der Zeile als aktive Zelle angenommen und als aktive Zelle entsprechend mit weißem Zellenhintergrund angezeigt würde. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_20_Navigation.xlsm ' Modul mdl_03_Mark ‘=============================================================== Public Sub Mark(lngRow As Long, lngCol As Long) Dim rngCell As Range ' Fehlerbehandlung, falls sich aktive am Rand der Tabelle ' befindet On Error Resume Next ' Zelle in Pfeilrichtung versetzen Set rngCell = ActiveCell.Offset(lngRow, lngCol)

Ereignisse

With ActiveSheet ' Vereinigung der aktiven Spalte und Zeile zum Listing 388

2471_Excel-VBA.book Seite 651 Dienstag, 4. Dezember 2007 1:42 13

' Navigationskreuz Application.Goto _ Union(.Columns(rngCell.Column), .Rows(rngCell.Row)) End With ' aktive Zelle aktivieren rngCell.Activate End Sub

Ereignisse

651

Ereignisse

>> Ereignisse

231 Makro rückgängig machen

Die Methoden OnUndo und OnRepeat müssen am Schluss einer Prozedur aufgerufen werden. Dadurch wird verhindert, dass die Prozeduren zum Wiederholen oder Rückgängigmachen durch nachfolgende Aktionen in der Prozedur überschrieben werden. In unserem Beispiel greifen die Prozeduren MyOnUndo und MyOnRepeat beide auf die Variablen grngCell und gstrUndo zu. Dementsprechend müssen diese Variablen global deklariert werden.

Ereignisse Ereignisse

Mit VBA ist es jedoch möglich die Befehle eines Makros rückgängig zu machen. Schreiben Sie eine Prozedur, die exakt das zurücksetzt, was in dem Makro ausgeführt wurde. Mit der OnUndo-Methode legen Sie den Text des Befehls RÜCKGÄNGIG und den Namen der Prozedur fest, die ausgeführt wird, wenn der Benutzer den Befehl RÜCKGÄNGIG wählt. Es ist nicht zwingend erforderlich, den Namen der Arbeitsmappe, in der die angegebene Prozedur gespeichert ist anzugeben. Wir empfehlen den Dateinamen zusätzlich vor dem Makronamen zu schreiben. Falls eine andere Excel Arbeitsmappe als die, in welcher die Prozeduren gespeichert sind aktiv ist, würde Excel eine Fehlermeldung ausgeben, weil das angegebene Makro in der gerade aktiven Mappe nicht gefunden wird.

Ereignisse

Abbildung 218: Deaktivierte Funktionen nach Makroausführung

Ereignisse

Ereignisse

Nach Ausführung von VBA-Makros, welche Änderungen an der Tabelle vornehmen, ist die Funktion RÜCKGÄNGIG nicht mehr möglich. Alle vorhandenen Einträge, die beim Klick auf den DropDown-Pfeil des Symbols RÜCKGÄNGIG auf der Schnellzugriffleiste aufgeführt waren, werden gelöscht. Diese Einträge können nicht wiederhergestellt werden.

Ereignisse

Listing 388 (Forts.)

2471_Excel-VBA.book Seite 652 Dienstag, 4. Dezember 2007 1:42 13

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Hinwei s

Ereignisse

652 >> Makro rückgängig machen

Die Variablen werden mit Public dimensioniert und oberhalb der ersten Prozedur in einem Standardmodul deklariert. Dadurch sind sie in jedem Modul für alle Prozeduren sichtbar. Die Variable grngCell setzt sich zum Beispiel aus dem Präfix g für Global, rng für den Datentyp Range und Cell als Nomen zusammen. Durch diese Bezeichnungen sind Variablen im Code leichter zu identifizieren. Variablen auf Modulebene können mit dem Präfix m gekennzeichnet werden.

In der Prozedur MyOnUndo wird in der Variablen grngCell ein Verweis auf die aktive Zelle gesetzt. Anschließend wird der Text »Das Excel-VBA-Codebook, 2007« in diese Zelle geschrieben. In der Variablen gstrUndo wird der Anzeigetext für die Befehle RÜCKGÄNGIG und WIEDERHOLEN gespeichert. Dieser setzt sich aus den ersten zehn Zeichen des Eingabetextes und der Adresse der geänderten Zelle zusammen. Der Anzeigetext mstrUndo, sowie der Prozedurname MyOnRepeat, die beim Klick auf die Schaltfläche RÜCKGÄNGIG ausgeführt werden sollen, werden an die OnUndo–Methode übergeben. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_21_OnUndoOnRepeat.xlsm ' Modul mdl_01_OnUndo ‘=============================================================== Public grngCell As Range Public gstrUndo As String Public Sub MyOnUndo() ' Verweis auf aktive Zelle Set grngCell = ActiveCell ' Text in Zelle schreiben grngCell .Value = "Das Excel-VBA-Codebook, 2007" ' Anzeigetext zusammensetzen gstrUndo = _ Left(grngCell .Value, 10) & " in " & grngCell .Address(0, 0) ' Anzeigetext und Rückgängig-Makro übergeben Application.OnUndo "Undo: " & gstrUndo, "MyOnRepeat" End Sub Listing 389

Abbildung 219: Text mit hinterlegter Prozedur im Rückgängig-Befehl

2471_Excel-VBA.book Seite 653 Dienstag, 4. Dezember 2007 1:42 13

Achtung

Mit der OnRepeat-Methode wird der Text des Befehls WIEDERHOLEN festgelegt. Geben Sie hier den Namen der Prozedur an, die ausgeführt wird, wenn der Benutzer den Befehl WIEDERHOLEN auf der Schnellzugriffleiste wählt. Im Gegensatz zu der OnUndo-Methode wird bei der OnRepeat-Methode das entsprechende WIEDERHOLEN Standard-Symbol mit Dropdownfeld auf der Schnellstartleiste nicht aktiviert und die übergebene Prozedur nicht zur Auswahl angeboten.

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Die Ursache liegt darin, dass Excel für den WIEDERHOLEN-Befehl zwei verschiedene Befehle zur Verfügung stellt, die allerdings beide die gleiche Bezeichnung Wiederholen führen. Der Standard WIEDERHOLEN-Befehl wird dabei als Dropdownfeld in der Standardinstallation von Excel auf der Schnellstartleiste angezeigt. Die Verwendung der OnRepeat-Methode mit VBA wirkt sich jedoch nur auf den WIEDERHOLEN-Befehl und nicht auf das entsprechende Dropdownfeld aus.

Ereignisse

232 Befehl »Wiederholen« aktivieren

Ereignisse

653

Ereignisse

>> Ereignisse

Ereignisse

Abbildung 220: Wiederholen-Befehl und Wiederholen-Dropdownfeld

2471_Excel-VBA.book Seite 654 Dienstag, 4. Dezember 2007 1:42 13

Im Anpassen-Dialogfenster (Abbildung 220) wird in der Liste der Befehle vor dem WIEDERHOLEN-Dropdownfeld (Redo) der WIEDERHOLEN-Befehl (Repeat) aufgeführt. Fügen Sie den WIEDERHOLEN-Befehl entweder zusätzlich, oder im Austausch mit dem WIEDERHOLEN-Dropdownfeld auf der Schnellstartleiste ein, um die OnRepeat-Methode für den Anwender zur Verfügung zu stellen. Klicken Sie nach Ausführung der Prozedur MyOnUndo auf den RÜCKGÄNGIG-Befehl, den Sie über den Anpassen-Dialog auf der Schnellstartleiste eingefügt haben. Daraufhin wird die Prozedur MyOnRepeat aufgerufen. Durch die Code Ausführung wird die Eingabe des Textes »Das Excel-VBA-Codebook, 2007« rückgängig gemacht, indem der Inhalt der Zelle grngCell gelöscht wird. Anschließend wird der Anzeigetext mittels der Variablen gstrUndo sowie der Prozedurname MyOnUndo an die OnRepeat-Methode übergeben. Nach Beendigung der Prozedur steht nun auf der Schnellstartleiste die Wiederholung der Eingabe »Das Excel-VBA-Codebook, 2. Auflage« zur Verfügung. ‘=============================================================== ' Auf CD Buchdaten\Beispiele\09_Ereignisse\ ' Dateiname 09_21_OnUndoOnRepeat.xlsm ' Modul mdl_02_OnRepeat ‘=============================================================== Public Sub MyOnRepeat() ' Text aus Zelle löschen grngCell .ClearContents ' Anzeigetext und Wiederholungs-Makro übergeben Application.OnRepeat "Repeat: " & gstrUndo, "MyOnUndo" End Sub Listing 390

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

Ereignisse

654 >> Befehl »Wiederholen« aktivieren

Ereignisse

Ereignisse

Abbildung 221: Text mit hinterlegter Prozedur im Wiederholen-Befehl

UserForm

UserForm

2471_Excel-VBA.book Seite 655 Dienstag, 4. Dezember 2007 1:42 13

Um eine UserForm anzulegen, können Sie in der VBA-Umgebung den Menüpunkt EIN| USERFORM verwenden. Alternativ dazu kann man mit der rechten Maustaste im Projektfenster auf das gewünschte Projekt klicken und aus dem erscheinenden Kontextmenü den Eintrag EINFÜGEN | USERFORM wählen. Daraufhin wird ein leeres Formular erzeugt und im Entwurfsmodus angezeigt. FÜGEN

An dieser Stelle sollte man der UserForm gleich einen einprägsamen Namen geben, im Eigenschaftsfenster ist die Eigenschaft Name dafür zuständig. Am besten setzt man noch die Zeichenfolge »uf« vor den Namen als Kennzeichen für eine UserForm. Solche Präfixe werden häufig eingesetzt, um den Typ und die Gültigkeit von Variablen oder Objekten auf den ersten Blick erschließbar zu machen. Auch der Text der Titelleiste kann nun über die Eigenschaft Caption festgelegt werden. Wenn Sie das Formular anklicken, wird die Symbolleiste WERKZEUGSAMMLUNG eingeblendet. Sollte die Symbolleiste wider Erwarten nicht angezeigt werden, dann wird diese eingeblendet, indem Sie auf den Menüpunkt ANSICHT | WERKZEUGSAMMLUNG oder alternativ auf das entsprechende Symbol in der Symbolleiste klicken (es stellt gekreuzt einen Hammer und einen Schraubenschlüssel dar).

UserForm UserForm UserForm

Es werden in diesem Kapitel aber ausschließlich Steuerelemente in Bezug auf UserForm beschrieben. Zudem können auf Grund der Vielfältigkeit nicht alle möglichen Eigenschaften und Methoden der beschriebenen Steuerelemente berücksichtigt werden

UserForm

Dieses Kapitel ist so aufgebaut, dass zu allen verfügbaren Steuerelementen ein Beispiel mit ein paar grundlegenden Eigenschaften und Methoden vorhanden ist. Im ersten Teil findet man Rezepte, welche die einzelnen Steuerelemente beschreiben. Erst wenn ein Steuerelement beschrieben wurde, wird es in den weiteren Beispielen zu finden sein.

UserForm

UserFormen können zudem unabhängig voneinander und in nahezu beliebiger Anzahl existieren, mit jeweils einem eigenen Satz von Variablen, Eigenschaften und Methoden, selbst wenn die zugrunde liegende UserForm die gleiche ist. Grenzen werden lediglich durch das Betriebssystem und die Ausstattung der Hardware gesetzt.

UserForm

Eine UserForm (Benutzerform) ist im Grunde genommen ein Formular, welches als CONTAINER für verschiedene Steuerelemente Verwendung findet. Anders als bei Tabellenblättern, die ja auch Steuerelemente aufnehmen können, ist dieser Container in Form und Position nicht mehr abhängig von der übergeordneten Excel-Applikation.

UserForm

233 Einstieg

2471_Excel-VBA.book Seite 656 Dienstag, 4. Dezember 2007 1:42 13

UserForm

UserForm

UserForm

UserForm

656 >> Einstieg

UserForm

UserForm

UserForm

UserForm

Abbildung 222: UserForm

In der Werkzeugsammlung befinden sich die verschiedenen Steuerelemente, um die UserForm zu gestalten und mit Leben zu erfüllen. Aktivieren Sie per einfachen Mausklick einfach das gewünschte Symbol und ziehen Sie in der UserForm mit gedrückter linker Maustaste einen Rahmen auf. Das Steuerelement wird im Bereich dieses Rahmens angelegt. Es kann anschließend beliebig verschoben und durch Ziehen an den Eck- oder Seitenpunkten in der Größe verändert werden. In welcher Reihenfolge man später mit Hilfe der (Tab)-Taste den Fokus auf ein Steuerelement lenken kann, wird über die TabIndex-Eigenschaft festgelegt. Bei jedem neu hinzugefügten Steuerelement auf einer UserForm, wird der Index um 1 erhöht, eine doppelte Vergabe eines INDICES im gleichen Container ist nicht möglich. Steuerelemente, die in einen Container wie Frame- (Rahmen), Image- (Anzeige) oder Page-Steuerelement (Multiseiten) eingefügt werden, bekommen einen eigenen Index, dessen Zählung wieder mit Null beginnt. Diese Steuerelemente bekommen ab der Indexposition des Containers nacheinander den Fokus.

Setzt man die Tabstop-Eigenschaft auf Falsch, kann dieses Steuerelement nicht mehr über die (Tab)-Taste den Fokus bekommen, der Wert der TabIndex-Eigenschaft bleibt dabei erhalten. Das Setzen des Fokus über einen Mausklick ist weiterhin noch möglich.

2471_Excel-VBA.book Seite 657 Dienstag, 4. Dezember 2007 1:42 13

Per Doppelklick auf das Steuerelement gelangt man in das Codemodul des Formulars und dort in die Standardereignisprozedur dieses Steuerelementes, sofern noch keine andere Ereignisprozedur dafür angelegt ist. Möchte man sich ansehen, welche Ereignisprozeduren für dieses Steuerelement überhaupt möglich sind, und möglicherweise eine dieser Prozeduren benutzen, kann man folgendermaßen vorgehen:

Um das Codemodul anzuzeigen, ohne gleich eine Prozedur anzulegen, kann man das linke der drei Icons im oberen Teil des Projektexplorers (in der linken rechteckigen Markierung Abbildung 223) anklicken. Das mittlere schaltet wieder in den Entwurfsmodus der UserForm zurück.

UserForm

Wenden wir uns nun der Werkzeugsammlung zu.

UserForm

Abbildung 223: Ereignisprozeduren

UserForm

UserForm

Über dem Codefenster der UserForm befinden sich zwei Dropdownfelder (Markierung Abbildung 223). In dem linken wählen Sie ein Objekt aus, im rechten befinden sich die dazugehörigen Ereignisprozeduren. Wählen Sie eine davon aus, wird der Prozedurrumpf dieser Ereignisprozedur im Codefenster angelegt.

UserForm

Da man später auf verschiedene Aktionen, beispielsweise das Klicken auf ein Steuerelement oder die Eingabe von Text reagieren will, können Ereignisprozeduren hinterlegt werden, die bei einem bestimmten Ereignis abgearbeitet werden. Welche Ereignisprozeduren möglich sind, hängt letztendlich vom jeweiligen Steuerelement ab.

UserForm

657

UserForm

>> UserForm

UserForm

Abbildung 224: Werkzeugsammlung

2471_Excel-VBA.book Seite 658 Dienstag, 4. Dezember 2007 1:42 13

UserForm

UserForm

UserForm

UserForm

UserForm

UserForm

UserForm

658 >> Einstieg

In der VBA-Codesprache werden die Elemente jeweils über den englischen Begriff angesprochen. Wenn man mit der Maustaste auf eines der Symbole zeigt und einen kurzen Moment wartet, wird in der Quickinfo der zugehörige deutsche Begriff angezeigt. Eine Übersicht über beide Begriffe kann man der Tabelle 47 entnehmen. Die Reihenfolge in der Werkzeugsammlung (Abbildung 224) ist von links nach rechts und von oben nach unten, die in der Tabelle 47 entsprechend von oben nach unten. Icon

Deutsche Bezeichnung

Englische Bezeichnung

Präfix

Bezeichnungsfeld

Label

lbl

Textfeld

TextBox

txt

Kombinationsfeld

ComboBox

cmb

Listenfeld

ListBox

lst

Kontrollkästchen

CheckBox

chk

Optionsfeld

OptionButton

opt

Umschaltfeld

ToggleButton

tgl

Rahmen

Frame

frm

Befehlsschaltfläche

CommandButton

cmd

Register

TabStrip

tbs

Multiseiten

MultiPage

mpg

Bildlaufleiste (vertikal/horizontal)

ScrollBar

vsb/hsb

Drehfeld

SpinButton

spn

Anzeige

Image

img

RefEdit

RefEdit

ref

UserForm

Tabelle 47: Deutsche und englische Bezeichnungen zu den Steuerelementen

2471_Excel-VBA.book Seite 659 Dienstag, 4. Dezember 2007 1:42 13

Die angegebenen Präfixe (Vorsilben) sind lediglich Empfehlungen und keinesfalls bindend. Sie können diese auch ignorieren und die beim Einfügen der Steuerelemente vergebenen Namen weiter verwenden. Man sollte sich aber darüber im Klaren sein, dass solche Präfixe und sprechende Namen den Programmcode lesbarer machen und in Programmiererkreisen üblich sind. Am besten also, wenn Sie gleich zu Beginn etwas Disziplin an den Tag legen und diese Konventionen einhalten, es wird dann irgendwann zur Routine.

UserForm

659

UserForm

>> UserForm

Wie UserFormen angelegt werden, konnte man im vorherigen Abschnitt nachlesen (Rezept 233). In diesem Rezept erfahren Sie, wie diese angezeigt und initialisiert werden. Um die UserForm zu starten, die in der VBA-Umgebung gerade bearbeitet wird, betätigt man die Taste (F5). Um die UserForm programmgesteuert aufzurufen, wird die Show-Methode der UserForm verwendet.

UserForm

234 UserForm anzeigen

Der verwendete Parameter vbModal ist Standard und kann somit auch weggelassen werden. Dieser Parameter bedeutet, dass nach dem Aufruf in der aufrufenden Prozedur die weitere Programmausführung angehalten wird, bis die UserForm ausgeblendet oder entladen wird. Möchte man mit der Programmausführung in der aufrufenden Prozedur unverzüglich fortfahren, benutzt man stattdessen den Parameter vbModeless. Es können beliebig viele, voneinander unabhängige existierende UserFormen angezeigt werden, die auf einem einzigen Entwurf beruhen. Man muss nur dafür sorgen, dass für jede angezeigte UserForm kurzzeitig eine eigene Objektvariable bereitsteht. Im diesem Rezept werden fünf gleichartige UserFormen angezeigt, welche alle die Eigenschaften der UserForm ufFirstStep besitzen. Nach dem Anzeigen wird jeweils der Text der Titelleiste angepasst und die Position in X- und Y-Richtung um 20 Punkte verschoben.

UserForm UserForm

Listing 391

UserForm

Private Sub CommandButton1_Click() ufTest.Show vbModal End Sub

UserForm

Dazu kann man beispielsweise im Tabellenblatt eine Schaltfläche aus der Symbolleiste STEUERELEMENT-TOOLBOX anlegen. Klickt man im Entwurfsmodus doppelt auf die Schaltfläche, wird die Standardereignisprozedur hinterlegt, in diesem Fall das Klickereignis. Zwischen beiden Codezeilen schreibt man den Namen der UserForm und verwendet die Methode Show:

UserForm

ufTest.Show

2471_Excel-VBA.book Seite 660 Dienstag, 4. Dezember 2007 1:42 13

UserForm

UserForm

660 >> UserForm anzeigen '=================================================================== ' Auf CD Buchdaten\Beispiele\10_UserForm\ ' Dateiname 10_01_Multiform.xlsm ' Tabelle Multiform ' Modul Tabelle Multiform '========================================