Access 2000 Programmierung - Kompendium. Platin Edition
 9783827257062, 3827257069 [PDF]

  • 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

Access 2000 Programmierung

Access 2000 Programmierung eBook Die nicht autorisierte Weitergabe dieses eBooks an Dritte ist eine Verletzung des Urheberrechts!

Markt&Technik Verlag

Die Deutsche Bibliothek – CIP-Einheitsaufnahme Ein Titeldatensatz für diese Publikation ist bei der Deutschen Bibliothek erhältlich Die Informationen in diesem Buch 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, die in diesem Buch erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. 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 04 03 02 01 00

ISBN 3-8272-5706-9 © 2000 by Markt&Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Übersetzung und fachliche Begutachtung: G&U Technische Dokumentation, Flensburg Lektorat: Rainer Fuchs, [email protected] Herstellung: Claudia Bäurle, [email protected] Einbandgestaltung: Grafikdesign Heinz H. Rauner, München Satz: reemers publishing services gmbh, Krefeld Bildnachweis: VCL/Bavaria Druck und Verarbeitung: Bercker, Kevelaer Printed in Germany

Inhaltsverzeichnis

Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Symbole im Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Die Autorin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Teil I

Grundlagen der Entwicklung mit Access . . . . . . . . . . . . . . . . . 23

1

Access als Entwicklungswerkzeug . . . . . . . . . . . . . . . . . . . . .25

1.1 1.2 1.3 1.4 1.5 1.6 1.7

Welche Arten von Anwendungen können mit Access entwickelt werden? . Access als skalierbares Produkt . . . . . . . . . . . . . . . . . . . . . . . . Was genau ist eine Datenbank ? . . . . . . . . . . . . . . . . . . . . . . . . Datenbankobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objektbenennung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hardwareanforderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wie beginne ich mit der Entwicklung einer Access-Anwendung? . . . . . .

2

Was jeder Entwickler über Tabellen wissen sollte . . . . . . . . . . 53

2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9

Mit Tabellen arbeiten . . . . . . . . . . . . . . . . . . . Eine Tabelle von Grund auf entwerfen . . . . . . . . . . Den für Ihre Daten geeigneten Feldtyp auswählen . . . Feldeigenschaften . . . . . . . . . . . . . . . . . . . . . Der allgegenwärtige Primärschlüssel . . . . . . . . . . Der Nachschlage-Assistent . . . . . . . . . . . . . . . . Tabelleneigenschaften . . . . . . . . . . . . . . . . . . Mit Hilfe von Indizes die Geschwindigkeit verbessern . Access-Tabellen und das Internet . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . .

. . . . . . . . .

. . . . . . .

. . . . . . . . .

. 25 . 30 . 30 . 31 . 42 . 43 . 44

. 53 . 54 . 57 . 63 . 74 . 75 . 77 . 79 . 79

6

Inhaltsverzeichnis

3

Beziehungen: Ihr Schlüssel zur Datensicherheit . . . . . . . . . . . 89

3.1 3.2 3.3 3.4 3.5

Beziehungstypen . . . . . . . . . . Beziehungen einrichten . . . . . . Für referentielle Integrität sorgen Vorteile von Beziehungen . . . . . Indizes und Beziehungen . . . . .

4

Was jeder Entwickler über Abfragen wissen sollte . . . . . . . . . 105

4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13

Was ist eine Abfrage und wann wird sie eingesetzt? . . . Alles, was Sie über Abfragen wissen sollten. . . . . . . . Ihr Abfrage-Ergebnis sortieren . . . . . . . . . . . . . . . Ihre Abfrage mit Hilfe von Kriterien verbessern . . . . . . In Kriterien mit Datumsangaben arbeiten . . . . . . . . . Abfrage-Ergebnisse aktualisieren . . . . . . . . . . . . . Abfragen auf der Grundlage mehrerer Tabellen erstellen Berechnete Felder erstellen . . . . . . . . . . . . . . . . . Der Ausdrucks-Generator . . . . . . . . . . . . . . . . . . Daten mit Hilfe von Abfragen zusammenfassen. . . . . . Felder aus der Ausgabe ausschließen . . . . . . . . . . . Nullwerte und Abfrage-Ergebnisse . . . . . . . . . . . . . Ihre Abfragen mit Hilfe von Feld-, Feldlisten- und Abfrage-Eigenschaften verbessern . . . . . . . . . . . . . Parameterabfragen, wenn die Kriterien beim Entwurf noch nicht bekannt sind . . . . . . . . . . . . . . . . . . .

4.14

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. . . . .

. . . . . . . . . . . .

. 89 . 92 . 96 . 101 . 102

. 105 . 106 . 112 . 113 . 116 . 118 . 119 . 125 . 127 . 128 . 132 . 133

. . . . . . . . . . . . 136 . . . . . . . . . . . . 138

5

Was jeder Entwickler über Formulare wissen sollte . . . . . . . . . 143

5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8

Verwendungen für Formulare . . . . . . . . . . . . . . . . . . . . . Aufbau eines Formulars . . . . . . . . . . . . . . . . . . . . . . . . Ein neues Formular erstellen . . . . . . . . . . . . . . . . . . . . . Mit dem Formularentwurfsfenster umgehen . . . . . . . . . . . . Das geeignete Steuerelement auswählen . . . . . . . . . . . . . . Ein Steuerelement durch ein anderes ersetzen . . . . . . . . . . . Bedingte Formatierung . . . . . . . . . . . . . . . . . . . . . . . . Welche Formulareigenschaften stehen zur Verfügung und warum sollten sie benutzt werden? . . . . . . . . . . . . . . . . . Welche Steuerelementeigenschaften stehen zur Verfügung und warum sollten sie benutzt werden? . . . . . . . . . . . . . . . . . Gebundene, ungebundene und berechnete Steuerelemente . . . Formulare mit Hilfe von Ausdrücken erweitern . . . . . . . . . . .

5.9 5.10 5.11

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. 143 . 146 . 147 . 151 . 159 . 169 . 170

. . . . . . . 171 . . . . . . . 179 . . . . . . . 185 . . . . . . . 185

7

Inhaltsverzeichnis

5.12 5.13 5.14 5.15

Die Befehlsschaltflächen-Assistenten: Programmierung ohne Eingabe Formulare auf der Grundlage mehrerer Tabellen . . . . . . . . . . . . . Formulare auf Abfragen aufsetzen . . . . . . . . . . . . . . . . . . . . . Access-Formulare und das Internet . . . . . . . . . . . . . . . . . . . .

6

Was jeder Entwickler über Berichte wissen sollte . . . . . . . . . . 205

6.1 6.2 6.3 6.4 6.5 6.6

6.14

Berichtstypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufbau eines Berichts . . . . . . . . . . . . . . . . . . . . . . . . . Einen neuen Bericht erstellen . . . . . . . . . . . . . . . . . . . . Das Berichtsentwurfsfenster . . . . . . . . . . . . . . . . . . . . . Das geeignete Steuerelement auswählen . . . . . . . . . . . . . . Welche Berichtseigenschaften stehen zur Verfügung und warum sollten sie benutzt werden? . . . . . . . . . . . . . . . . . Welche Steuerelementeigenschaften stehen zur Verfügung und warum sollten sie benutzt werden? . . . . . . . . . . . . . . . . . Seitenumbrüche einfügen . . . . . . . . . . . . . . . . . . . . . . Gebundene, ungebundene und berechnete Steuerelemente . . . Berichte mit Hilfe von Ausdrücken erweitern . . . . . . . . . . . . Berichte auf der Grundlage mehrerer Tabellen . . . . . . . . . . . Sortierreihenfolge und Gruppierung . . . . . . . . . . . . . . . . . Durch Aufsetzen der Berichte auf gespeicherte Abfragen Geschwindigkeit und Wiederverwendbarkeit verbessern . . . . . Access-Berichte und das Internet . . . . . . . . . . . . . . . . . .

7

VBA: Eine Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

7.1 7.2

Was ist VBA? . . . . . . . . . . . . . . . . . . . . . Was sind die Klassen-, Standard-, Formular- und Berichtsmodule von Access? . . . . . . . . . . . . Mit Variablen arbeiten. . . . . . . . . . . . . . . . Kommentare in den Code einfügen . . . . . . . . Das Zeichen für die Fortsetzung der Zeile . . . . . Die VBA-Steuerstrukturen. . . . . . . . . . . . . . Parameter über- und Werte zurückgeben . . . . . Vom Modulfenster aus Prozeduren ausführen . . Das Objekt DoCmd: Makro-Aktionen durchführen Integrierte Funktionen. . . . . . . . . . . . . . . . Mit Konstanten arbeiten . . . . . . . . . . . . . . Werkzeuge für die Arbeit im VBE . . . . . . . . . . Den VBE individuell anpassen . . . . . . . . . . .

6.7 6.8 6.9 6.10 6.11 6.12 6.13

7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11 7.12 7.13

. . . . .

. . . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

187 189 193 195

. 205 . 210 . 211 . 215 . 219

. . . . . . . 223 . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. 227 . 230 . 231 . 231 . 231 . 238

. . . . . . . 242 . . . . . . . 243

. . . . . . . . . . . . . . . . 251 . . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. 254 . 265 . 270 . 271 . 271 . 280 . 281 . 281 . 282 . 287 . 290 . 302

8

Inhaltsverzeichnis

8

Objekte, Eigenschaften, Methoden und Ereignisse . . . . . . . . . 307

8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 8.10

Das Objektmodell von Access. . . . . . . . . . . . . . . . . . Objekte, Eigenschaften, Ereignisse und Methoden . . . . . . Access-Objekte mit Hilfe des Objektkatalogs kennen lernen Sich auf Objekte beziehen. . . . . . . . . . . . . . . . . . . . Eigenschaften und Methoden leicht gemacht . . . . . . . . . Objektvariablen deklarieren und zuweisen . . . . . . . . . . Unterschiede zwischen Objekten und Auflistungen . . . . . Objekte an Unterroutinen und Funktionen übergeben . . . . Den Typ eines Steuerelements bestimmen . . . . . . . . . . Spezielle Eigenschaften mit Objektbezug . . . . . . . . . . .

9

Fortgeschrittene Verwendung von Formularen . . . . . . . . . . . . 335

9.1 9.2 9.3 9.4 9.5 9.6 9.7

9.17

Formulare ergänzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was sind Formularereignisse und wann sollten sie verwendet werden? . . Die Reihenfolge der Formularereignisse . . . . . . . . . . . . . . . . . . . . Abschnitts- und Steuerelementereignisse und ihre Verwendung . . . . . . Die Reihenfolge der Steuerelementereignisse . . . . . . . . . . . . . . . . Das Schlüsselwort Me . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Welche Arten von Formularen kann ich erstellen und wann sind sie geeignet? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Integrierte Dialogfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formularen benutzerdefinierte Menüs, Symbolleisten und Kontextmenüs hinzufügen. . . . . . . . . . . . . . . . . . . . . . . . . . . . Die integrierten Funktionen zur Formularfilterung ausnutzen . . . . . . . . Objekte aus anderen Anwendungen einfügen: Verknüpfen oder Einbetten OpenArgs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Datenherkunft eines Formulars wechseln . . . . . . . . . . . . . . . . . Fortgeschrittener Umgang mit Kombinations- und Listenfeldern . . . . . . Fortgeschrittener Umgang mit Unterformularen . . . . . . . . . . . . . . . Ein Formular mit der zu Grunde liegenden Datensatzgruppe in Einklang bringen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzerdefinierte Eigenschaften und Methoden erstellen . . . . . . . . .

10

Fortgeschrittene Verwendung von Berichten . . . . . . . . . . . . . 399

10.1 10.2 10.3

Mit Berichten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 Für Berichte verfügbare Ereignisse und wann sie verwendet werden sollten . 399 Ereignisreihenfolge für Berichte . . . . . . . . . . . . . . . . . . . . . . . . . . 403

9.8 9.9 9.10 9.11 9.12 9.13 9.14 9.15 9.16

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . .

. 307 . 312 . 316 . 320 . 321 . 323 . 325 . 327 . 328 . 330

. 335 . 336 . 346 . 348 . 354 . 355

. . 356 . . 364 . . . . . . .

. 368 . 373 . 375 . 377 . 377 . 380 . 388

. . 389 . . 390

9

Inhaltsverzeichnis

10.4 10.5 10.6

Für Berichtsabschnitte verfügbare Ereignisse und wann sie verwendet werden sollten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 Spezielle Berichtseigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . 408 Praktische Anwendungen für Berichtsereignisse und -eigenschaften . . . . . 410

11

Fortgeschrittene Abfragetechniken . . . . . . . . . . . . . . . . . . . . 431

11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 11.10 11.11 11.12 11.13

Aktionsabfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Spezielle Abfrage-Eigenschaften . . . . . . . . . . . . . . . . . . . . Abfragen optimieren. . . . . . . . . . . . . . . . . . . . . . . . . . . Kreuztabellenabfragen . . . . . . . . . . . . . . . . . . . . . . . . . Äußere Verknüpfungen . . . . . . . . . . . . . . . . . . . . . . . . . Selbstverknüpfungen . . . . . . . . . . . . . . . . . . . . . . . . . . SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Union-Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pass-Through-Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . Die Weitergabe von Nullwerten und Abfrage-Ergebnisse . . . . . . Unterabfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Ergebnis einer Funktion als Abfragekriterium verwenden . . . Die Werte für eine Parameterabfrage aus einem Formular einlesen

12

Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte? . . . 479

12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 12.10 12.11 12.12

Datenzugriffsobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . ActiveX-Datenobjekte und Datenzugriffsobjekte im Vergleich . . . . Das Datenobjektmodell von ActiveX . . . . . . . . . . . . . . . . . . . Arten von ADO-Datensatzgruppen . . . . . . . . . . . . . . . . . . . . Mit ADO-Recordset-Eigenschaften und -Methoden umgehen . . . . . Tabellendaten mit Hilfe von ADO-Code bearbeiten. . . . . . . . . . . Datenbankobjekte mit Hilfe von ADO-Code erstellen und bearbeiten Das Datenzugriffsobjektmodell (DAO) . . . . . . . . . . . . . . . . . . DBEngine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CurrentDB(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arten von DAO-Datensatzgruppen . . . . . . . . . . . . . . . . . . . . Zwischen den verfügbaren Arten von DAO-Datensatzgruppenobjekten wählen . . . . . . . . . . . . . . . . Mit DAO-Recordset-Eigenschaften und -Methoden umgehen . . . . . Tabellendaten mit Hilfe von DAO-Code bearbeiten. . . . . . . . . . . Datenbankobjekte mit Hilfe von DAO-Code erstellen und bearbeiten Die DAO-Container-Auflistung . . . . . . . . . . . . . . . . . . . . . .

12.13 12.14 12.15 12.16

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. 432 . 441 . 444 . 450 . 457 . 459 . 460 . 467 . 468 . 469 . 470 . 471 . 473

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. 479 . 480 . 481 . 486 . 490 . 500 . 504 . 508 . 516 . 517 . 517

. . . . .

. . . . .

. . . . .

. . . . .

. 519 . 519 . 531 . 535 . 539

10

Inhaltsverzeichnis

Teil II Falls etwas nicht nach Plan läuft . . . . . . . . . . . . . . . . . . . . . . 545 13

Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung . . . . 547

13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 13.10 13.11

Fehler vermeiden . . . . . . . . . . . . . . . . . . . . . Die Leistungsfähigkeit des Direktfensters nutzen . . Den Debugger aufrufen . . . . . . . . . . . . . . . . . Haltepunkte einsetzen . . . . . . . . . . . . . . . . . . Code schrittweise durchgehen . . . . . . . . . . . . . Die nächste auszuführende Anweisung festlegen . . Das Fenster Aufrufeliste . . . . . . . . . . . . . . . . . Mit dem Lokal-Fenster arbeiten. . . . . . . . . . . . . Mit Überwachungsausdrücken arbeiten . . . . . . . . Die Ausführung nach einem Laufzeitfehler fortsetzen Gefundenes im Direktfenster ansehen . . . . . . . . .

14

Fehlerbehandlung: Vorbereitung auf das Unvermeidliche . . . . 575

14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 14.10 14.11 14.12

Fehler beheben . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlerbehandlung implementieren . . . . . . . . . . . . . . . . . Mit Fehlerereignissen arbeiten . . . . . . . . . . . . . . . . . . . On Error-Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . Resume-Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . Fehlerinformationen löschen . . . . . . . . . . . . . . . . . . . . Verschachtelte Fehlerbehandlungsroutinen. . . . . . . . . . . . Das Objekt Err . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einen Fehler auslösen . . . . . . . . . . . . . . . . . . . . . . . . Die Auflistung Errors . . . . . . . . . . . . . . . . . . . . . . . . . Eine allgemeine Fehlerbehandlungsroutine erstellen . . . . . . Verhindern, dass die eigene Fehlerbehandlung aufgerufen wird

15

Optimieren Ihrer Anwendung . . . . . . . . . . . . . . . . . . . . . . . . 603

15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9

Mehr Leistung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einführung in die Optimierung . . . . . . . . . . . . . . . . . . . . . Hard- und Software-Konfiguration modifizieren . . . . . . . . . . . Was bringt Jet 4.0 für die Verbesserung der Leistung? . . . . . . . . Mit Hilfe der Leistungsanalyse Problembereiche ermitteln . . . . . Tabellen mit dem Ziel optimaler Leistung gestalten . . . . . . . . . Abfragen mit dem Ziel optimaler Leistung gestalten . . . . . . . . . Anders programmieren, um die Leistung zu optimieren . . . . . . . Formulare und Berichte mit dem Ziel optimaler Leistung gestalten

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . .

. 548 . 549 . 555 . 555 . 558 . 562 . 563 . 565 . 565 . 571 . 572

. 575 . 576 . 577 . 579 . 582 . 584 . 585 . 586 . 586 . 588 . 589 . 600

. 603 . 603 . 604 . 608 . 610 . 611 . 613 . 614 . 624

11

Inhaltsverzeichnis

Teil III Mehrbenutzer- und Unternehmensanwendungen entwickeln . 629 16

Eine Strategie für die Entwicklung von Access-Anwendungen . 631

16.1 16.2 16.3 16.4 16.5 16.6 16.7

Leistungssteigerungen . . . . . . . . . . . . . . . . . . . . . . . . Datenbanken in Tabellen und andere Objekte zerlegen . . . . . . Abfragen oder eingebettete SQL-Anweisungen als Grundlage für Formulare und Berichte . . . . . . . . . . . . . . . . . . . . . . . . Die Laufzeit-Engine von Access. . . . . . . . . . . . . . . . . . . . Eine ausführbare Datei und eine Access-Datenbank im Vergleich Die Bedeutung der Absicherung der Datenbank . . . . . . . . . . Access als Front-End. . . . . . . . . . . . . . . . . . . . . . . . . .

17

Mehrbenutzeranwendungen entwickeln . . . . . . . . . . . . . . . . 649

17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 17.10 17.11 17.12 17.13

Anwendungsentwicklung unter Berücksichtigung der Ansprüche mehrerer Benutzer . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Sperrmechanismen von Access . . . . . . . . . . . . . . . . . Strategien zum Sperren und Aktualisieren . . . . . . . . . . . . . Sperrstrategien für Formulare . . . . . . . . . . . . . . . . . . . . Datensatzgruppen sperren . . . . . . . . . . . . . . . . . . . . . . Sperrkonflikte effizient erledigen . . . . . . . . . . . . . . . . . . Einen Datensatz auf seinen Sperrstatus prüfen . . . . . . . . . . Code zum Aktualisieren oder erneuten Abfragen. . . . . . . . . . Die .LDB-Datei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Benutzerliste. . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzerdefinierte Zähler erstellen . . . . . . . . . . . . . . . . . Ungebundene Formulare . . . . . . . . . . . . . . . . . . . . . . . Höhere Leistung durch Replikation . . . . . . . . . . . . . . . . .

18

Externe Daten verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . 681

18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 18.10

Verbindung mit externen Datenquellen . . . . . . . . . . . . . Daten importieren, verknüpfen und öffnen: wann und warum Externe Daten importieren . . . . . . . . . . . . . . . . . . . . Eine Verknüpfung zu externen Daten erstellen . . . . . . . . . Eine externe Tabelle öffnen . . . . . . . . . . . . . . . . . . . . Die Einstellungen in der Windows-Registry . . . . . . . . . . . Die Eigenschaft Jet OLEDB:Link Provider String . . . . . . . . Mit Kennwörtern arbeiten . . . . . . . . . . . . . . . . . . . . . Verknüpfungen aktualisieren und löschen . . . . . . . . . . . Spezielle Überlegungen . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . 631 . . . . . . . 632 . . . . .

. . . . . . . . . . . . .

. . . . . . . . . .

. . . . .

. . . . . . . . . . . . .

. . . . . . . . . .

. . . . .

. . . . . . . . . . . . .

. . . . . . . . . .

. . . . .

. . . . . . . . . . . . .

. . . . . . . . . .

. . . . .

. . . . . . . . . . . . .

. . . . . . . . . .

. . . . .

. . . . . . . . . . . . .

. . . . . . . . . .

. 634 . 635 . 642 . 643 . 644

. 649 . 655 . 656 . 660 . 663 . 667 . 674 . 675 . 676 . 677 . 678 . 678 . 678

. 681 . 682 . 685 . 689 . 697 . 699 . 700 . 701 . 702 . 704

12

Inhaltsverzeichnis

18.11 18.12 18.13

Problemlösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706 Leistung und Verknüpfungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706 Mit HTML-Dokumenten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . 707

19

Client-Server-Techniken . . . . . . . . . . . . . . . . . . . . . . . . . . . 715

19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 19.10 19.11 19.12 19.13

Das Client-Server-Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Soll das Client-Server-Modell eingesetzt werden? . . . . . . . . . . . . . . . Die Rollen, die Access im Anwendungsentwurfsmodell spielt . . . . . . . . . Die Client-Server-Schlagworte . . . . . . . . . . . . . . . . . . . . . . . . . . Upsizing: Was dabei zu bedenken ist . . . . . . . . . . . . . . . . . . . . . . Das Upsizing aktiv vorbereiten . . . . . . . . . . . . . . . . . . . . . . . . . . Der Upsizing-Assistent. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine ODBC-Datenquelle definieren . . . . . . . . . . . . . . . . . . . . . . . . Mit einem Datenbank-Server Verbindung aufnehmen . . . . . . . . . . . . . Mit verknüpften Tabellen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . Pass-Through-Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gespeicherte Prozeduren erstellen und ausführen . . . . . . . . . . . . . . . Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen .

20

Client-Server-Strategien . . . . . . . . . . . . . . . . . . . . . . . . . . . 765

20.1 20.2 20.3 20.4 20.5 20.6

Effizientes Vorgehen . . . . . . . . . . . . . . . . . . . . Den günstigsten Typ für eine Datensatzgruppe wählen Pass-Through-Abfragen und gespeicherte Prozeduren. Access-Datenprojekte . . . . . . . . . . . . . . . . . . . Den Umgang mit Daten optimieren. . . . . . . . . . . . Abfragen und Formulare optimieren . . . . . . . . . . .

21

Eine Client-Server-Anwendung in Aktion . . . . . . . . . . . . . . . . 777

21.1 21.2 21.3

Zum Gesamtzusammenhang . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777 Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen . . . . 777 Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . 798

22

Transaktionsverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . 809

22.1 22.2 22.3 22.4 22.5

Von Atomarität bis Konsistenz . . . . . . . . . . . . Die Vorteile . . . . . . . . . . . . . . . . . . . . . . . Das Standardverhalten verändern . . . . . . . . . . Explizite Transaktionsverarbeitung implementieren Einige Bemerkungen zur Transaktionsverarbeitung

. . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. . . . . .

. . . . .

. 715 . 716 . 722 . 725 . 726 . 730 . 730 . 734 . 740 . 740 . 748 . 750 . 753

. 765 . 765 . 768 . 768 . 769 . 769

. 809 . 810 . 812 . 813 . 815

13

Inhaltsverzeichnis

22.6 22.7

Transaktionsverarbeitung in einer Mehrbenutzerumgebung . . . . . . . . . . 820 Transaktionsverarbeitung in einer Client-Server-Umgebung . . . . . . . . . . 825

23

Replikation leicht gemacht . . . . . . . . . . . . . . . . . . . . . . . . . 831

23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 23.10 23.11 23.12 23.13 23.14 23.15

Datenänderungen weiterreichen . . . . . . . . . . . . . . . . . . . . . . . . Einsatzmöglichkeiten der Replikation . . . . . . . . . . . . . . . . . . . . . Wann ist Replikation nicht geeignet? . . . . . . . . . . . . . . . . . . . . . Replikation implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . Die Architektur der Replikation: Was setzt die Replikation in Bewegung? . Replikationstopologien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Änderungen an Ihrer Datenbank durch Replikation . . . . . . . . . . . . . Eine Datenbank replikationsfähig machen . . . . . . . . . . . . . . . . . . Verhindern, dass Objekte repliziert werden. . . . . . . . . . . . . . . . . . Zusätzliche Replikate erstellen . . . . . . . . . . . . . . . . . . . . . . . . . Replikate synchronisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . Replikationskonflikte beheben . . . . . . . . . . . . . . . . . . . . . . . . . Den Replikations-Manager verwenden . . . . . . . . . . . . . . . . . . . . Partielle Replikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Replikation mittels Code implementieren . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. 831 . 832 . 834 . 834 . 836 . 838 . 841 . 843 . 845 . 847 . 848 . 850 . 852 . 865 . 867

Teil IV Fortgeschrittene Programmierung . . . . . . . . . . . . . . . . . . . . 873 24

Fortgeschrittene VBA-Techniken . . . . . . . . . . . . . . . . . . . . . 875

24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 24.10

Für erfahrenere Programmierer. . . . . . . . . . . . . . . . . . Was sind benutzerdefinierte Typen und wozu können sie verwendet werden? . . . . . . . . . . . . . . . . . . . . . . . . Mit Konstanten arbeiten . . . . . . . . . . . . . . . . . . . . . Mit Datenfeldern arbeiten. . . . . . . . . . . . . . . . . . . . . Fortgeschrittene Methoden der Verwendung von Funktionen Mit Empty und Null arbeiten . . . . . . . . . . . . . . . . . . . Benutzerdefinierte Auflistungen erstellen und verwenden . . Kompilieroptionen verstehen und effektiv nutzen . . . . . . . Code-Module im- und exportieren . . . . . . . . . . . . . . . . Mit Projekteigenschaften arbeiten . . . . . . . . . . . . . . . .

25

ActiveX-Steuerelemente verwenden . . . . . . . . . . . . . . . . . . . 907

25.1 25.2

Wozu dienen ActiveX-Steuerelemente? . . . . . . . . . . . . . . . . . . . . . . 907 ActiveX-Steuerelemente im Rahmen von Access 2000 verwenden . . . . . . . 908

. . . . . . . . . 875 . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. 876 . 878 . 882 . 886 . 891 . 896 . 899 . 900 . 901

14

25.3 25.4 25.5 25.6 25.7 25.8 25.9 25.10 25.11 25.12

Inhaltsverzeichnis

Eigenschaften eines ActiveX-Steuerelements während des Entwurfs festlegen . . . . . . . . . . . . . . . . . . . . . . . Behandlungsroutinen für die Ereignisse eines ActiveX-Steuerelements programmieren . . . . . . . . . . Das Kalender-Steuerelement verwenden . . . . . . . . . . Das Steuerelement UpDown verwenden. . . . . . . . . . . Das Steuerelement StatusBar verwenden . . . . . . . . . . Das Steuerelement Common Dialog . . . . . . . . . . . . . Das RichText-Steuerelement verwenden . . . . . . . . . . Das TabStrip-Steuerelement verwenden . . . . . . . . . . Das ImageList-Steuerelement verwenden . . . . . . . . . . Aspekte der Weitergabe und Lizenzierung . . . . . . . . .

. . . . . . . . . . . 914 . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. 915 . 917 . 920 . 922 . 924 . 927 . 930 . 933 . 934

26

Automatisierung: Mit anderen Anwendungen kommunizieren . . . . . . . . . . . . . . 937

26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 26.10 26.11

Von außen mit Access arbeiten . . . . . . . . . . . . . . . . . . . Begriffe zur Automatisierung . . . . . . . . . . . . . . . . . . . . Einen Objektvariablenverweis auf Ihre Anwendung deklarieren Ein Automatisierungsobjekt erstellen . . . . . . . . . . . . . . . Ein Automatisierungsobjekt anpassen . . . . . . . . . . . . . . . Excel mit Access steuern. . . . . . . . . . . . . . . . . . . . . . . Ein Excel-Automatisierungsobjekt schließen . . . . . . . . . . . Mit Hilfe von Access ein Diagramm erstellen . . . . . . . . . . . Word von Access aus steuern . . . . . . . . . . . . . . . . . . . . PowerPoint von Access aus steuern . . . . . . . . . . . . . . . . Access von anderen Anwendungen aus steuern . . . . . . . . .

27

Die Leistungsfähigkeit des Windows-API ausschöpfen . . . . . . 965

27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8

Fundgrube Windows-Bibliotheken . . . . . . . . . . . . . . . . . . Eine externe Funktion für den Compiler deklarieren . . . . . . . . Mit Konstanten und Typen arbeiten . . . . . . . . . . . . . . . . . DLL-Funktionen aufrufen: Wichtige Aspekte . . . . . . . . . . . . Unterschiede zwischen 16- und 32-Bit-APIs . . . . . . . . . . . . . API-Funktionen verwenden . . . . . . . . . . . . . . . . . . . . . . Informationen über die Arbeitsumgebung erlangen . . . . . . . . Laufwerkstypen und verfügbaren Platz auf Laufwerken ermitteln

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. 937 . 938 . 939 . 940 . 942 . 943 . 947 . 947 . 952 . 954 . 957

. 965 . 966 . 972 . 979 . 979 . 980 . 980 . 986

15

Inhaltsverzeichnis

28

Die Leistungsfähigkeit von Klassenmodulen ausnutzen . . . . 991

28.1 28.2 28.3 28.4 28.5 28.6

Die Vorteile von Klassenmodulen . . . . . . . . Objektorientierung – Eine Einführung . . . . . . Klassenmodule erstellen und verwenden . . . . Mehrere Instanzen von Klassen erstellen . . . . Die Ereignisse Initialize und Terminate . . . . . Mit benutzerdefinierten Auflistungen arbeiten .

29

Eigene Bibliotheken erstellen . . . . . . . . . . . . . . . . . . . . . . 1021

29.1 29.2 29.3 29.4 29.5

Bibliotheksdatenbanken . . . . . . . . . . . . . . . . . . . . Eine Datenbank zur Verwendung als Bibliothek vorbereiten Einen Verweis erstellen . . . . . . . . . . . . . . . . . . . . . Fehlersuche in einer Bibliotheksdatenbank. . . . . . . . . . Eine Access-Bibliothek sichern . . . . . . . . . . . . . . . . .

30

Generatoren, Assistenten und Menü-Add-Ins einsetzen . . . . 1039

30.1 30.2 30.3 30.4

Hilfsmittel – Aufbau und Installation. Generatoren verwenden. . . . . . . . Assistenten einsetzen . . . . . . . . . Menü-Add-Ins verwenden. . . . . . .

31

Access und das Internet. . . . . . . . . . . . . . . . . . . . . . . . . . . 1065

31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 31.10 31.11 31.12 31.13

Neuerungen von Access im Zusammenhang mit dem Internet . . . Datenbankobjekte als HTML speichern . . . . . . . . . . . . . . . . Verknüpfungen mit HTML-Dateien . . . . . . . . . . . . . . . . . . . HTML-Dateien importieren . . . . . . . . . . . . . . . . . . . . . . . Zwischen statischen und dynamischen HTML-Formaten abwägen . Mit Active Server Pages (ASP-Dateien) arbeiten . . . . . . . . . . . Mit HTX/IDC-Dateien arbeiten . . . . . . . . . . . . . . . . . . . . . Testen der ASP- und HTX/IDC-Dateien. . . . . . . . . . . . . . . . . Mit HTML-Vorlagen arbeiten . . . . . . . . . . . . . . . . . . . . . . Daten an einen FTP- oder HTTP-Server senden . . . . . . . . . . . . Hyperlinks nutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Symbolleiste Web . . . . . . . . . . . . . . . . . . . . . . . . . . Replikation über das Internet implementieren . . . . . . . . . . . .

32

Datenzugriffsseiten verwenden . . . . . . . . . . . . . . . . . . . . . 1083

32.1 32.2

Datenzugriffsseiten verstehen . . . . . . . . . . . . . . . . . . . . . . . . . . 1083 Datenzugriffsseiten erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . 1084

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . .

. . . . . .

. . . . .

. . . .

. . . . . .

. . . . .

. . . .

. . . . . .

. . . . .

. . . .

. . . . . .

. . . . .

. . . .

. . . . . .

. . . . .

. . . .

. . . . . . . . . . . . .

. . . . . .

. . . . .

. . . .

. . . . . . . . . . . . .

. . . . . .

. . . . .

. . . .

. . . . . . . . . . . . .

. . . . . .

. . . . .

. . . .

. . . . . . . . . . . . .

. 991 . 992 . 993 . 997 . 997 . 998

. . . . .

. . . .

. . . . . . . . . . . . .

1021 1022 1024 1033 1034

1039 1040 1051 1057

1065 1066 1069 1072 1073 1074 1075 1076 1077 1078 1080 1081 1082

16

32.3 32.4 32.5 32.6

Inhaltsverzeichnis

Wichtige Eigenschaften einer Datenzugriffsseite anpassen . . Ändern der Eigenschaften zur Navigation in den Datensätzen Gruppierte Datenzugriffsseiten erstellen . . . . . . . . . . . . Datenzugriffsseiten mit VBScript ausbauen . . . . . . . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

1093 1095 1097 1100

Teil V Die Anwendung abrunden . . . . . . . . . . . . . . . . . . . . . . . . . 1107 33

Datenbanksicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1109

33.1 33.2

33.6

Vom Kennwort bis zur Hochsicherheit . . . . . . . Sicherheit auf Freigabe-Ebene implementieren: Ein Datenbank-Kennwort einrichten . . . . . . . . Eine Datenbank verschlüsseln . . . . . . . . . . . Sicherheit auf Benutzerebene einrichten . . . . . Eine zusätzliche Sicherheitsebene bereitstellen: Eine MDE-Datei erstellen . . . . . . . . . . . . . . Spezielle Fragestellungen . . . . . . . . . . . . . .

34

Fortgeschrittene Sicherheitstechniken . . . . . . . . . . . . . . . . 1147

34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 34.10 34.11 34.12

Sicherheit für Gruppenarbeit . . . . . . . . . . . . . . . . . . . . . . . . . . Gruppen mit Hilfe von Code verwalten . . . . . . . . . . . . . . . . . . . . . Benutzer mit Hilfe von Code verwalten . . . . . . . . . . . . . . . . . . . . Alle Gruppen und Benutzer auflisten . . . . . . . . . . . . . . . . . . . . . . Mit Kennwörtern arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . Berechtigungen für Objekte mit Hilfe von Code zuweisen und widerrufen . Eine Datenbank mit Hilfe von Code verschlüsseln . . . . . . . . . . . . . . Mit Hilfe von Abfragen Sicherheit auf Feldebene erreichen . . . . . . . . . Benutzer und Gruppen von der Erstellung von Objekten ausschließen . . Sich als ein anderer Benutzer anmelden, um verbotene Aufgaben auszuführen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Client-Server-Anwendungen schützen . . . . . . . . . . . . . . . . . . . . . Sicherheit und Replikation . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

Anwendungsdokumentation . . . . . . . . . . . . . . . . . . . . . . . . 1173

35.1 35.2 35.3 35.4

Für Systempflege, zum Nachschlagen . . . . . . . . . . . Ihrer Anwendung die Dokumentation selbst überlassen . Der Datenbank-Dokumentierer . . . . . . . . . . . . . . . Mit Hilfe von Code eine eigene Dokumentation erstellen

33.3 33.4 33.5

. . . . . . . . . . . . . . . 1109 . . . . . . . . . . . . . . . 1110 . . . . . . . . . . . . . . . 1111 . . . . . . . . . . . . . . . 1113 . . . . . . . . . . . . . . . 1137 . . . . . . . . . . . . . . . 1139

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . . . . . . .

1147 1148 1151 1157 1160 1164 1167 1167 1169

. 1170 . 1170 . 1170

. . . .

1173 1174 1181 1185

Inhaltsverzeichnis

17

36

Ihre Anwendung warten . . . . . . . . . . . . . . . . . . . . . . . . . . 1189

36.1 36.2

Weg mit ungenutztem Speicher . . . . . . . . . . . . . . . . . . . . . . . . . 1189 Ihre Datenbank komprimieren . . . . . . . . . . . . . . . . . . . . . . . . . . 1189

37

Ihre Anwendung verteilen . . . . . . . . . . . . . . . . . . . . . . . . . 1197

37.1 37.2 37.3 37.4

Eine Applikation für viele . . . . . . . . . . . . . . . . . . . . . . . Der Package and Deployment Wizard . . . . . . . . . . . . . . . . Das Package and Deployment Wizard-Add-In laden . . . . . . . . Ihre Anwendung zur Ausführung mit einer vollständigen Kopie von Access verteilen . . . . . . . . . . . . . . . . . . . . . . . . . . Vollversionen im Unterschied zu Laufzeitversionen von Access . Ihre Datenbank für die Verwendung mit der Laufzeitversion von Access vorbereiten. . . . . . . . . . . . . . . . . . . . . . . . . . . Andere Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . .

37.5 37.6 37.7

. . . . . . 1197 . . . . . . 1198 . . . . . . 1198 . . . . . . 1200 . . . . . . 1200 . . . . . . 1203 . . . . . . 1225

Teil VI Anhänge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1231 A

Namenskonventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1233

B

Die Buch-CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1241 Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1243

Vorwort Zum Thema »Access« gibt es bereits eine Vielzahl hevorragender Bücher. Warum sollte man noch ein weiteres schreiben? In den Gesprächen mit vielen Kursteilnehmern, denen ich bei meinen Reisen durch das Land begegnete, wurde immer wieder eine Beschwerde geäußert. Anstelle mehrerer großartiger Bücher für die Benutzergemeinde oder einer Fülle ausgezeichneter Bücher für erfahrene Access-Entwickler wünschen sich meine Schüler ein Buch für Entwickler, die über Grund- oder fortgeschrittene Kenntnisse verfügen. Sie wünschen sich ein Buch, das mit den Grundlagen beginnt und so gewährleistet, daß keine Wissenslücken entstehen, und ihnen einige der fortgeschrittenen Aspekte der Entwicklung mit Access näherbringt. Begleitend wünschen sie sich praktische Programmierbeispiele, die sie leicht in ihre eigenen Anwendungen einbinden können. Ich habe dieses Buch speziell im Hinblick auf diese Anforderungen geschrieben. Es beginnt mit einer Einführung in die Entwicklung mit Access. Darin wird erläutert, welche Arten von Anwendungen mit Access entwickelt werden können, und es werden die Komponenten einer Access-Anwendung vorgestellt. Nachdem Sie verstanden haben, was eine Access-Anwendung ist und wann die Entwicklung einer solchen sinnvoll ist, lernen Sie die zum Programmieren einer richtigen AccessAnwendung notwendigen Schritte kennen. Vor dem Erstellen der ersten Anwendungskomponente werden mehrere Vorgehensweisen erörtert. Damit wird sichergestellt, dass Sie sich als Entwickler dieser Anwendung bewusst machen, welche Punkte Sie beim Entwurf speziell für Ihre Umgebung berücksichtigen müssen. Nachdem Sie das Gesamtbild kennengelernt haben, sind Sie bereit, sich an Einzelheiten der Objekte einer Access-Datenbank heranzuwagen. Die Kapitel 2 bis 6 behandeln die Grundlagen von Tabellen, Beziehungen, Abfragen, Formularen und Berichten. Diese Kapitel sollen einen Ansatz für die Entwicklung dieser Datenbankobjekte aus der Sicht des Entwicklers bereitstellen. Obwohl dieser Text mit den Grundlagen beginnt, liefert er viele Tipps, Tricks und Einwände, die der Dokumentation oder den für Endanwender bestimmten Büchern nicht zu entnehmen sind. Wenn Sie im Hinblick auf das Erstellen von Tabellen, Abfragen, Formularen und Berichten über eine solide Wissensgrundlage verfügen, sind Sie in der Lage sich ganz auf die Programmierung zu konzentrieren. Die Kapitel 7 und 8 geben Ihnen einen

20

Vorwort

tiefen Einblick in die Sprache VBA. Wieder beginnen Sie mit den Grundlagen und werden langsam an die Finessen von Visual Basic für Applikationen und dem Objektmodell von Access herangeführt. Im Text werden viele praktische Beispiele vorgestellt, damit Sie jedes Thema wirklich eingehend verarbeiten können. Die Kapitel 9 bis 11 umfassen eine fortgeschrittene Erörterung von Abfragen, Formularen und Berichten. Wenn Sie an dieser Stelle angelangt sind, sollten Sie mit den Grundlagen des Erstellens von Datenbankobjekten vertraut sein. In diesen Kapiteln werden die Grundlagen des Entwurfs von Tabellen, Abfragen, Formularen und Berichten mit den in den Kapiteln 7 und 8 behandelten Techniken zur Verwendung von VBA und Objekten kombiniert. Die in Kapitel 9 bis 11 beschriebenen leistungsfähigen Methoden verleihen Ihnen die Fachkenntnisse, die Sie zum Entwerfen der für Ihre Anwendung erforderlichen komplexen Abfragen, Formulare und Berichte brauchen. Bevor Sie die Grenze zu den vielen Feinheiten der Access-Entwicklungsumgebung überschreiten, bleibt noch ein grundlegendes Thema zu erörtern. Kapitel 12 gibt eine Einführung in ActiveX-Datenobjekte und Datenzugriffsobjekte. Nachdem Sie Kapitel 12 gelesen haben, werden Sie den Unterschied zwischen ActiveX-Datenobjekten und Datenzugriffsobjekten verstehen. Sie werden erfahren, wie Sie sich von gebundenen Objekten lösen können, indem Sie die Daten innerhalb Ihrer Datenbank mit Hilfe von Code bearbeiten. Leider verlaufen die Dinge nicht immer wie geplant. Unabhängig vom Grad Ihrer Fachkenntnisse werden Sie häufiger ratlos über einem Programm-Code sitzen und nach Antworten suchen. Kapitel 13 zeigt Ihnen, wie Sie die Fehlersuche wirksam einsetzen können, um mögliche Probleme mit dem Programm-Code zu lösen. Alle Aspekte der Fehlersuche werden in diesem Kapitel behandelt. Selbst wenn Ihre Anwendung sorgfältig auf Fehler überprüft wurde, sind Sie dafür verantwortlich, eine Möglichkeit zu schaffen, mit der Fehler innerhalb Ihrer Anwendung behandelt werden können. Kapitel 14 zeigt Ihnen alles, was Sie wissen müssen, um die Fehlerbehandlung in Ihre Anwendung zu implementieren. Im Text sowie auf der CDROM mit Programmierbeispielen finden Sie eine generische Fehlerbehandlungsroutine, die Sie leicht in eine beliebige eigene Anwendung einbinden können. Mit der in den ersten 15 Kapiteln geschaffenen Grundlage sind Sie für den Übergang zu den umfangreicheren und komplexeren Gesichtspunkten der Sprache VBA und der Access-Entwicklungsumgebung gerüstet. Die Kapitel 16 bis 23 behandeln alle Aspekte der Entwicklung von Anwendungen für eine Mehrbenutzer- oder ClientServer-Umgebung. Sie lernen Sperrstrategien kennen und erfahren, wie Sie mit Fremddateiformaten in Access umgehen und wie Sie ODBC zum Entwerfen von Client-Server-Anwendungen einsetzen. Transaktionsverarbeitung, Anwendungsoptimierung und Replikation werden ebenfalls in diesem Kapitel behandelt. Als Access-Entwickler ist Ihre Welt nicht nur auf Access begrenzt. Um als solcher effektiv und produktiv zu sein, müssen Sie wissen, wie Sie mit anderen Anwendungen kommunizieren können und wie Sie ActiveX-Steuerelemente, Bibliotheken,

Symbole im Text

21

Menü-Add-ins, Assistenten und Generatoren verwenden, die Ihnen bei der Anwendungsentwicklung helfen. Die Kapitel 25 bis 30 befassen sich mit OLE, indem ActiveX-Steuerelemente, Access und das Internet verwendet werden und die Anwendungsentwicklung mit Visual SourceSafe, Bibliotheken und Add-ins vorgenommen wird. Nach dem Studium dieser Kapitel werden Sie verstehen, wie Sie sich die Verwendung externer Objekte und Funktionen zunutze machen können, um Ihre Anwendungen ohne große Mühe vielseitig zu gestalten. Schließlich sind Sie bereit, Ihrer Anwendung den Feinschliff zu geben. Die Kapitel 31 bis 37 beschäftigen sich mit dem Windows-API, der Sicherheit, der Dokumentation, der Pflege, der Hilfe und der Verteilung. Sie werden lernen, wie Sie Ihre Anwendung richtig sichern, so dass der Entwicklungsaufwand für die Anwendung nicht beeinträchtigt wird. Außerdem erfahren Sie, wie einfach es ist, der Anwendung den letzten Schliff zu verleihen, der ihr ein professionelles Aussehen verleiht und sie von anderen Anwendungen abhebt.

Anmerkung des Übersetzers Dieses Buch verwendet für jedes seiner Kapitel amerikanische Beispieldatenbanken. Daher kann es vorkommen, dass in manchen Formularen und Berichten sowie dementsprechend natürlich auch in einigen Screenshots Felder enthalten sind, für die es im deutschsprachigen Raum keine genaue Entsprechung gibt. Als Beispiele erfüllen diese Inhalte jedoch ihren Zweck.

Symbole im Text Wir verwenden im Text verschiedene Symbole, die eine schnelle Orientierung in diesem umfangreichen Kompendium sicherstellen. Im Text werden Sie den folgenden Sinnbildern begegnen: An dieser Stelle geben wir Praxistipps und lassen Sie so an unseren Erfahrungen aus der täglichen Arbeit mit dem Programm teilhaben.

Hier geben wir Ihnen Hinweise, die auf Besonderheiten aufmerksam machen oder allgemeine Informationen zu entsprechenden Funktionen vermitteln. An einigen Stellen sind so auch Warnungen hervorgehoben.

Dieses Icon verweist auf eine Folge von Arbeitsschritten, die Sie zu einem Ergebnis führen.

22

Vorwort

Mit dem CD-Symbol sind Verweise auf die Buch-CD gekennzeichnet. Hier finden Sie z.B. die Bezeichnungen der im Buch verwendeten Beispieldateien. Außerdem sind hier häufig kommentierende Hinweise angehängt.

Die Autorin Alison Balter ist Präsidentin der 1990 gegründeten Marina Consulting Group LLC, einem Unternehmen in Westlake Village, Kalifornien, und eine erfahrene Ausbilderin und Beraterin für Anwendungsschulungen und -entwicklungen unter Windows. Während ihrer fünfzehnjährigen Tätigkeit in der Computerindustrie hat sie in vielen großen Unternehmen und Regierungsbehörden Schulungen und Beratungen durchgeführt. Bei der Marina Consulting Group LLC handelt es sich um einen von Microsoft zertifizierten Lösungslieferanten, und auch Alison Balter wurde von Microsoft als Fachberaterin zertifiziert. Als eine der ersten in der Computerindustrie wurde sie von Microsoft als so genannter Solution Provider anerkannt. Alison Balter ist die Autorin von über 200 weltweit vertriebenen EDV-Schulungsvideos. Sie hält in ganz Nordamerika Schulungen über Microsoft Access, Visual Basic, Visual InterDev und Visual Basic for Applications ab. Außerdem ist sie regelmäßig in Live-Sendungen der National Technological University vertreten. Sie schreibt regelmäßig für Computerzeitschriften und ist als Buchautorin bekannt. Außerdem nimmt sie immer wieder an nationalen Gesprächsrunden über Access, Visual Basic und Visual InterDev teil. Als aktive Teilnehmerin vieler Benutzergruppen und anderer Organisationen war Alison Balter die Präsidentin der Independent Computer Consultants Association of Los Angeles und der Los Angeles Clipper Users' Group.

Grundlagen der Entwicklung mit Access

Teil I

1 2 3 4 5 6 7 8 9 10 11 12

Access als Entwicklungswerkzeug Was jeder Entwickler über Tabellen wissen sollte Beziehungen: Ihr Schlüssel zur Datenintegrität Was jeder Entwickler über Abfragen wissen sollte Was jeder Entwickler über Formulare wissen sollte Was jeder Entwickler über Berichte wissen sollte VBA: Eine Einführung Objekte, Eigenschaften, Methoden und Ereignisse Fortgeschrittene Formulartechniken Fortgeschrittene Berichtstechniken Fortgeschrittene Abfragetechniken Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

Access als Entwicklungswerkzeug

Kapitel

Hier lesen Sie:

 Welche Arten von Anwendungen können mit Access entwickelt werden?  Access als skalierbares Produkt  Was genau ist eine Datenbank?  Datenbankobjekte  Objektbenennung  Hardwareanforderungen  Wie beginne ich mit der Entwicklung einer Access-Anwendung?

1.1

Welche Arten von Anwendungen können mit Access entwickelt werden?

Access bietet eine Vielzahl von Möglichkeiten für unterschiedliche Datenbankanforderungen. Es kann zur Entwicklung von sechs verschiedenen Arten von Anwendungen verwendet werden:

 Persönliche Anwendungen  Anwendungen für kleinere Geschäftsbereiche  Anwendungen für Unternehmensabteilungen  Anwendungen für gesamte Unternehmen  Als Front-End für unternehmensweite Client-Server-Anwendungen  Anwendungen für Intranet/Internet-Anwendungen

26

1.1.1

Kapitel 1: Access als Entwicklungswerkzeug

Access als Entwicklungsplattform für persönliche Anwendungen

Auf unterster Ebene kann Access verwendet werden, um einfache persönliche Datenbankanwendungen zu entwickeln. Dennoch warne ich Benutzer vor diesem Gedanken. Benutzer, die Access kaufen, um damit alles zu vereinfachen, von der Verwaltung ihres Weinkellers bis zur Übersicht über ihre privaten Finanzen, werden oft enttäuscht. Denn der Schein trügt, Access sei kinderleicht zu benutzen. Seine wundervollen integrierten Assistenten machen Access zu einem Produkt, das scheinbar jedermann leicht benutzen kann. Nach dem Beantworten einer Reihe von Fragen verfügen Sie bereits über fertige Übersichten, Dateneingabemasken, Berichte usw. Als Access auf den Markt kam, fragten mich viele Leute, ob ich nicht davon betroffen sei, dass nun mein Beruf als Programmierer und Ausbilder unwichtig würde, weil doch mit Access nun wirklich jedermann Datenbankanwendungen selbst schreiben könne. Dazu möchte ich aber Folgendes bemerken: Es ist zwar richtig, dass ein Benutzer einfache Access-Anwendungen erstellen kann, ohne sich einen einzigen Gedanken über den Entwurf zu machen und ohne eine einzige Programmzeile selbst zu schreiben, aber es bedarf doch für die meisten Anwendungen zumindest eines Minimums an Entwurf und Programmierung. Sie werden keinerlei Probleme haben, solange Sie sich mit einer von einem AccessAssistenten erzeugten persönlichen Anwendung mit nur wenigen kleinen Verfeinerungen zufrieden geben. Sie werden aber sehr schnell auf Probleme stoßen, sobald Sie eine solche Anwendung wirklich an Ihre persönlichen Bedürfnisse anpassen wollen.

1.1.2

Access als Entwicklungsplattform für kleinere Geschäftsbereiche

Access eignet sich sehr gut zum Entwickeln von Anwendungen für kleinere Geschäftsbereiche. Die Assistenten ermöglichen den Entwicklern das schnelle und leichte Entwerfen von Anwendungen, mit Programm-Modulen lassen sich ganze Bibliotheken mit immer wieder benutzbaren Funktionen zusammenstellen, und die Möglichkeit, Programmteile mit Formularen und Berichten zu verknüpfen, erlaubt das Erstellen besonders leistungsfähiger Formulare und Berichte. Die wesentliche Einschränkung beim Einsatz von Access zum Entwickeln von Anwendungen für kleinere Geschäftsbereiche sind die Zeit und das Geld, die man für eine Entwicklung aufzuwenden bereit ist. Viele Benutzer verwenden zu Beginn ihrer Anwendungsentwicklung Access-Assistenten und erst später bemerken sie, dass sie die Anwendungen vervollständigen wollen und dass sie die dazu nötigen Arbeitsschritte nicht mehr beherrschen. Die Inhaber kleiner Firmen haben dieses Problem häufig in noch ausgeprägterer Form. Die Anforderungen an Anwendungen für kleinere Geschäftsbereiche sind üblicherweise viel höher als die Anforderungen an persönliche Anwendungen. Ich selbst wurde oft von Ärzten, Rechtsanwälten und

Welche Arten von Anwendungen können mit Access entwickelt werden?

27

anderen Selbstständigen zu Hilfe gerufen, die während der Entwicklung einer Anwendung in eine Sackgasse geraten waren. Immer waren sie erschrocken darüber, wie teuer es wurde, ihre Anwendung wirklich einsetzbar zu machen.

1.1.3

Access als Entwicklungsplattform für Unternehmensabteilungen

Access eignet sich ideal für das Entwickeln von Abteilungsanwendungen in großen Unternehmen. Es ist recht einfach, die Arbeitspatzrechner aller Benutzer einer überschaubaren Abteilung auf die für Access erforderliche Hardware aufzurüsten, und es ist zum Beispiel erheblich einfacher, für nur 15 Benutzer zusätzlichen Hauptspeicher zu kaufen als für 4.000 Benutzer. Das Leistungsvermögen von Access reicht für die meisten Abteilungsanwendungen, die noch ohne eine Client-Server-Lösung auskommen können. Schließlich verfügen die meisten Abteilungen in großen Unternehmen über eigene Entwicklungsbudgets, um gut entworfene Anwendungen zu erstellen. Glücklicherweise findet sich außerdem in fast jeder Abteilung ein PC-Begeisterter, der überglücklich ist, wenn er beim Entwurf von Formularen und Berichten mitwirken kann. Dies gibt der Abteilung dann sogar ein besonderes Gefühl der Verbundenheit mit ihren Anwendungen, weil ihre eigenen Mitarbeiter ja bei deren Entwicklung mitgeholfen haben. Und es macht auch mein Dasein als hauptberuflicher Entwickler erheblich einfacher: Ich kann mich auf die wesentlichen Kernpunkte der Anwendungsentwicklung konzentrieren und den Entwurf von Formularen und Berichten getrost den PC-Spezialisten in den jeweiligen Abteilungen überlassen.

1.1.4

Access als Entwicklungsplattform für das gesamte Unternehmen

Am besten eignet sich Access aber wohl für die Entwicklung von Anwendungen, die über ein ganzes Unternehmen verteilt eingesetzt werden. Wie erfolgreich ein solches Bemühen ist, hängt jedoch vom einzelnen Unternehmen ab. Die Zahl der AccessBenutzer, die gleichzeitig auf eine Access-Anwendung zugreifen, ist ebenso wie die Anzahl der Datensätze innerhalb einer Tabelle begrenzt, sofern man Wert auf eine akzeptable Anwendungsgeschwindigkeit legt. Diese Grenzwerte hängen unter anderem von folgenden Fragen ab:

 Wie stark ist das Netzwerk belastet?  Mit wieviel Arbeitspeicher und mit wie vielen Prozessoren ist der Server ausgestattet?

 Wie wird der Server eingesetzt? Müssen Microsoft Office-Anwendungen zunächst vom Server auf die einzelnen Arbeitspatzrechner heruntergeladen werden?

 Welche Arten von Aufgaben werden von den Benutzern der Anwendung erledigt? Sind dies einfache Abfragen, geben die Benutzer Daten ein, werden umfangreiche Berichte erzeugt usw.?

28

Kapitel 1: Access als Entwicklungswerkzeug

 Laufen Access und Ihre Access-Anwendung auf dem Server oder auf Ihrer eigenen Arbeitsstation?

 Welches Netzwerksystem wird benutzt? Meine übliche Faustregel für eine Access-Anwendung ist, dass sich bei mehr als zehn bis fünfzehn gleichzeitigen Benutzern und bei mehr als 100.000 Datensätzen allgemein schlechte Antwortzeiten einstellen, wenn es sich nicht um eine Client-Server-Anwendung handelt. Bedenken Sie jedoch, dass diese Zahlen über einen breiten Bereich variieren können, weil sie von den genannten Faktoren abhängen und auch davon beeinflusst werden, was Sie und andere Benutzer unter guten Antwortzeiten verstehen. Die Kriterien für einen Übergang zu einem Client-Server-Datenbanksystem sind in Kapitel 19 beschrieben. Entwickler verstehen oft nicht, welche Bedeutung Access beim Einsatz in einem Client-Server-System zukommt. Ich werde oft gefragt: »Ist Access denn kein Client-Server-System?« Die Antwort sieht so aus, dass Access ein außergewöhnliches Programm ist, weil es einerseits eine Datei-Server-Anwendung außerhalb der eigenen Arbeitsstation ist, während es andererseits als Front-End für eine Client-ServerDatenbank dienen kann. Hier eine Erklärung: Wenn Sie Access kaufen und eine Anwendung entwickeln, die Daten in eine Access-Datenbank auf einem Datei-Server schreibt, so findet dennoch die eigentliche Verarbeitung der Daten auf dem Arbeitsplatzrechner statt. Dies bedeutet, dass bei jedem Start einer Abfrage oder eines ganzen Berichts zunächst alle Daten vom Datei-Server auf die Arbeitsstation übertragen werden müssen. Die Abfrage selbst läuft dann auf der Arbeitsstation ab, und deren Ergebnis wird als Tabelle oder als Bericht angezeigt. Es ist offensichtlich, dass diese Arbeitsweise erheblichen Datenverkehr im Netzwerk verursacht, ganz besonders, wenn mehrere Benutzer gleichzeitig auf große Access-Tabellen zugreifen. Tatsächlich können derartige Anwendungen ein ganzes Netzwerk weitgehend lahmlegen.

1.1.5

Access als Entwicklungsplattform für unternehmensweite ClientServer-Anwendungen

Eine Client-Server-Datenbank, wie etwa Microsoft SQL Server oder Oracle, verarbeitet Datenbankabfragen auf dem Server und überträgt danach nur die Ergebnisse zur Arbeitsstation. Die Server-Software selbst kann dem Benutzer aber keine Daten anzeigen – dazu ist Access nötig. Als Front-End kann Access die Ergebnisse von Datenbankabfragen in Berichten, Tabellen oder Formularen optisch aufbereiten. Werden die Daten in einer solchen Tabelle vom Benutzer wiederum verändert, so werden diese veränderten Daten anschließend an die Back-End-Datenbank zurückübertragen. Dies geschieht entweder durch eine Verknüpfung mit den externen Datenbanken – diese erscheinen dem Benutzer dann wie interne Access-Tabellen – oder durch die unmittelbare Verwendung der Client-Server-Fähigkeiten von Access.

Welche Arten von Anwendungen können mit Access entwickelt werden?

29

Bei Access 2000 gibt es so genannte Access-Projektdateien (nicht zu verwechseln mit Microsoft-Projektdateien), die besonders das Entwickeln von Anwendungen unterstützen, die für Client-Server-Umgebungen geeignet sind. Diese Access-Projektdateien, die oft auch als ADP-Dateien bezeichnet werden, enthalten alle Formulare, Berichte, Makros, Programmteile und Datenzugriffsseiten. Das Projekt wird mit der Back-End-Datenbank verknüpft, welche die Datentabellen, Prozeduren, virtuellen Sichten und Datenbankdiagramme enthält, über die das Programm auf die Datenbank zugreift. Aus einer Projektdatei heraus können Sie leicht die auf einem Server gespeicherten Objekte verändern und beeinflussen, indem Sie die bequeme grafische Benutzerschnittstelle von Access verwenden. ADP-Dateien können den Entwicklungsablauf für Client-Server-Anwendungen erheblich beschleunigen. Weil Access 2000 einen integrierten Datenspeicher enthält, ist es sogar möglich, eine Client-Server-Anwendung auf der Arbeitsstation zu entwickeln und sie danach auf einfache Weise in eine SQL Server 6.5- oder SQL Server 7-Datenbank zu übertragen. Die verschiedenen Möglichkeiten und Techniken für das Entwickeln von Client-ServerAnwendungen sind in Kapitel 19 und Kapitel 20 genauer beschrieben. Access wird zu einem ganz besonders leistungsfähigen Entwicklungswerkzeug, wenn man die Netzwerkbelastung dadurch vermindert, dass die eigentlichen Datenbankabfragen auf dem Back-End-System ausgeführt werden. Dann kann Access riesige Datenmengen verarbeiten und zahlreiche gleichzeitig aktive Benutzer bedienen. Die wesentliche Frage für Entwickler solcher großer Access-Anwendungen ist dann, über welche Hardware jeder einzelne Benutzer verfügt. Denn obwohl die Datenbankabfragen auf dem Server abgewickelt werden, was das Datennetz erheblich entlastet, muss sich doch die Anwendung selbst im Speicher jedes einzelnen Rechners befinden. Die Hardwareanforderungen für eine Access-Anwendung werden später in diesem Kapitel noch ausführlicher erläutert. Grundsätzlich gilt: Bevor Sie mit der Entwicklung einer großen und leistungsfähigen Access-Anwendung beginnen, müssen Sie zunächst die Hardwareausstattung aller späteren Benutzer dieser Anwendung kennen.

1.1.6

Access als Entwicklungsplattform für Intranet-/InternetAnwendungen

Intranet- und Internet-Benutzer können ihre Anwendungsdaten verändern, indem sie für den Zugriff einen Browser und so genannte Datenzugriffsseiten verwenden. Datenzugriffsseiten sind HTML-Dokumente, die direkt mit den Daten in einer Datenbank verknüpft sind. Sie werden außerhalb der eigentlichen Datenbank gespeichert und genauso verwendet wie normale Access-Formulare; allerdings werden sie üblicherweise in Verbindung mit dem Microsoft Internet Explorer 5.0 anstatt mit Microsoft Access eingesetzt. Der Internet Explorer 5.0 wird zusammen mit Office 2000 ausgeliefert. Verwendet man Datenzugriffsseiten, so wird im Hintergrund dynamisch HTML benutzt. Da Datenzugriffsseiten ausschließlich vom Internet Explorer 5.0 unterstützt werden, sind sie allerdings weit besser für den Einsatz in Intranets als für Internet-Lösungen geeignet.

30

Kapitel 1: Access als Entwicklungswerkzeug

Außer über Datenzugriffsseiten können Sie Ihre Datenbankobjekte auch als statische oder als dynamische HTML-Seiten veröffentlichen. Statische Seiten sind StandardHTMLs und können mit einem beliebigen Browser betrachtet werden. Datenbankobjekte lassen sich entweder im HTX/IDC- oder im ASP-Dateiformat, aber auch dynamisch publizieren. HTX/IDC-Dateien werden vom Webserver dynamisch angezeigt und hängen nicht vom verwendeten Browser ab. ASP-Dateien, die von Microsoft Access bereitgestellt werden, werden ebenfalls dynamisch vom Webserver veröffentlicht, sie benötigen aber den Internet Explorer 4.0 oder höher auf der ClientArbeitsstation. Intranet- und Internet-Entwicklung unter Microsoft Access wird in Kapitel 31 und Kapitel 32 genauer beschrieben.

1.2

Access als skalierbares Produkt

Eine der stärksten Seiten von Access ist seine leichte Anpassbarkeit an unterschiedlich große Aufgaben. So kann eine Anwendung, die zunächst für eine einzige Arbeitsstation entwickelt wurde, nach und nach zu einer unternehmensweiten Client-Server-Anwendung erweitert werden. Auf diese Weise lässt sich eine Anwendung mit wenig oder sogar ohne jeden zusätzlichen Aufwand an größere Aufgaben anpassen, wenn nur der ursprüngliche Datenbankentwurf gut ist. Diese Eigenschaft macht Access zu einem hervorragenden Werkzeug für aufstrebende Unternehmen und für Anwendungen, die zunächst nur auf Abteilungsebene entwickelt und getestet werden, um erst später im ausgereiften Zustand unternehmensweit zum Einsatz zu kommen. Eine weitere hervorstechende Eigenschaft von Access besteht darin, dass es einen hohen Sicherheitsstandard und das Festlegen von Datenbankregeln zulässt und dass dies sowohl beim Front- als auch beim Back-End möglich ist – früher ging dies nur bei Back-End-Datenbanken. In Kapitel 33 und Kapitel 34 werden Sie sehen, dass sich Sicherheitsregeln auf jedes Element einer Access-Datenbank anwenden lassen, und zwar sowohl auf Benutzer- als auch auf Gruppenebene. Regeln für die referentielle Integrität lassen sich für die ganze Datenbank definieren, so dass man zum Beispiel sicherstellen kann, dass Bestellungen für nicht vorhandene Kunden gar nicht erst eingegeben werden können. Plausibilitätsprüfungen für Daten können auf Feldoder Datensatzebene definiert werden, um so die Datenintegrität in der Datenbank sicherzustellen. Mit anderen Worten: Access bietet nun eine Reihe von Eigenschaften, die bisher nur für Datenbank-Server der obersten Leistungs- und Preisklasse verfügbar waren.

1.3

Was genau ist eine Datenbank ?

Der Begriff »Datenbank« hat für unterschiedliche Personen zwei recht unterschiedliche Bedeutungen: Lange Zeit, insbesondere in der Welt der xBase-Datenbanken (dBase, FoxPro, CA-Clipper), bezeichnete der Begriff lediglich eine Ansammlung von

Datenbankobjekte

31

Feldern und Datensätzen (die in Access Tabelle genannt wird). In einer Client-Server-Umgebung bezeichnet »Datenbank« dagegen die Gesamtheit aller Daten, einschließlich der damit verbundenen Datenstrukturen, Indizes, Regeln, Trigger und Prozeduren. Bei Access schließlich umfasst der Begriff die Gesamtheit aller Tabellen, Abfragen, Formulare, Berichte, Datenzugriffsseiten, Makros und Code-Module, die das gesamte System ausmachen.

1.4

Datenbankobjekte

Access-Datenbanken bestehen aus Tabellen, Abfragen, Formularen, Berichten, Datenzugriffsseiten, Makros und Code-Modulen. Jedes dieser Objekte hat besondere Aufgaben. Die Access-Umgebung enthält noch einige weitere Objekte, wie zum Beispiel Beziehungen, Befehlsschaltflächen, Datenbankeigenschaften und Angaben zum Import und Export von Daten. Mit diesen Objekten lassen sich leistungsfähige, benutzerfreundliche und vielfältige Anwendungen erstellen. Abbildung 1.1 zeigt das Access-Datenbankfenster. Beachten Sie hier im linken Bildteil die sieben aufgeführten Objektklassen. Diese Objektklassen, die eine Access-Datenbank ausmachen, werden Sie in den folgenden Abschnitten kennenlernen.

1.4.1

Tabellen: Ein Lager für Ihre Daten

Tabellen sind der Ausgangspunkt jeder Anwendung. Ob Ihre Daten in einer AccessDatenbank gespeichert sind oder ob Sie auf externe Daten zugreifen, indem Sie verknüpfte Tabellen verwenden, immer greifen alle anderen Objekte Ihrer Datenbank direkt oder indirekt auf Tabellen zu.

Abbildung 1.1: Das Datenbankfenster von Access mit Symbolen für jede Art von Datenbankobjekten

32

Kapitel 1: Access als Entwicklungswerkzeug

Um alle Tabellen zu sehen, die in einer geöffneten Datenbank enthalten sind, müssen Sie das Symbol TABELLEN in der Objektliste anklicken. (Beachten Sie jedoch, dass ausgeblendete Tabellen unsichtbar sind, wenn sie nicht zuvor ausdrücklich über das Kontrollkästchen AUSGEBLENDETE OBJEKTE der Registerkarte ANSICHT des über EXTRAS|OPTIONEN erreichbaren Dialogfelds OPTIONEN eingeblendet werden.) Die Daten innerhalb einer Tabelle können Sie mit einem Doppelklick auf den Namen dieser Tabelle anzeigen. Das gleiche erreichen Sie, wenn Sie den Namen der Tabelle und anschließend die Schaltfläche ÖFFNEN anklicken. Die Daten in der Tabelle werden auf einem Datenblatt angezeigt, welches alle Felder und Datensätze enthält (siehe Abbildung 1.2). Viele Eigenschaften eines Datenblatts lassen sich verändern und Sie können Daten im Datenblatt suchen und filtern. Ist die Tabelle mit einer anderen Tabelle verknüpft (zum Beispiel mit der Kunden- oder Bestellungentabelle der Nordwind-Datenbank), so können Sie sogar die verknüpfte Tabelle anzeigen, um die darin gespeicherten Daten zu sehen. Diese Möglichkeiten werden jedoch in diesem Buch nicht behandelt, da sie im Access-Benutzerhandbuch und in jedem anderen einführenden Access-Buch beschrieben sind.

Abbildung 1.2: Datenblattansicht der Tabelle Kunden in der Nordwind-Datenbank

Als Entwickler müssen Sie oft auf den Entwurf einer Tabelle zurückgreifen, den man als deren Bauplan oder als Schablone bezeichnen könnte. Um den Tabellenentwurf zu sehen, markieren Sie die Tabelle und klicken dann die Schaltfläche ENTWURF (siehe Abbildung 1.3). In der Entwurfsansicht können Sie alle Feldnamen, Datentypen, Feld- und Tabelleneigenschaften betrachten und verändern. Access bietet Ihnen jede Möglichkeit, um den Entwurf Ihrer Tabelle Ihren besonderen Bedürfnissen anzupassen. Diese Punkte sind Gegenstand von Kapitel 2.

33

Datenbankobjekte

Abbildung 1.3: Der Entwurf der Kundentabelle

1.4.2

Beziehungen: Die Tabellen miteinander verbinden

Um die Integrität Ihrer Daten zu gewährleisten und das Zusammenwirken mit anderen Objekten der Datenbank zu erleichtern, müssen Sie zwischen den Tabellen Ihrer Datenbank Beziehungen definieren. Dies geschieht mittels des Fensters BEZIEHUNGEN. Zu diesem Fenster gelangen Sie durch Auswahl des Eintrags BEZIEHUNGEN aus dem Menü EXTRAS oder durch Anklicken der Schaltfläche BEZIEHUNGEN in der Symbolleiste (siehe Abbildung 1.4). In diesem Fenster können Sie die Beziehungen innerhalb der Datenbank betrachten und verändern. Wenn Sie oder ein anderer Entwickler einige Beziehungen definiert hat, die in dem Fenster BEZIEHUNGEN aber nicht sichtbar sind, so wählen Sie BEZIEHUNGEN|ALLE ANZEIGEN, um die möglicherweise ausgeblendeten Tabellen und Beziehungen sichtbar zu machen. Beachten Sie, dass viele der Beziehungen in Abbildung 1.4 durch eine Linie angedeutet sind, an deren einem Ende eine 1 und an dem anderen ein Unendlich-Symbol steht. Dies zeigt an, dass zwischen den verbundenen Tabellen eine 1:n-Beziehung besteht. Durch einen Doppelklick auf die Verbindungslinie öffnet sich das Dialogfeld BEZIEHUNGEN BEARBEITEN (siehe Abbildung 1.5). Dort können Sie den genauen Typ der Beziehung zwischen den Tabellen festlegen. Die Beziehung zwischen den Tabellen Kunden und Bestellungen ist zum Beispiel eine 1:n-Beziehung mit so genannter »referentieller Integrität«, was bedeutet, dass keine Bestellungen für nicht vorhandene Kunden eingegeben werden können. Beachten Sie, dass das Kontrollkästchen AKTUALISIERUNGSWEITERGABE AN DETAILFELD aktiviert ist. Dies zeigt an, dass beim Verändern einer Kundennummer (CustomerID) alle Datensätze, in denen diese Kundennummer enthalten ist, ebenfalls verändert werden. Da das Kontrollkästchen LÖSCHWEITERGABE AN DETAILDATENSATZ nicht aktiviert ist, lassen sich Kunden nicht aus der Kundentabelle löschen, solange es noch zugehörige Bestellungen in der Bestellungentabelle gibt.

34

Kapitel 1: Access als Entwicklungswerkzeug

Abbildung 1.4: Das Fenster Beziehungen, in dem Sie die Beziehungen in der Datenbank betrachten und verwalten

Abbildung 1.5: Das Dialogfeld Beziehungen bearbeiten, in dem Sie die Eigenschaften einer Beziehung zwischen Tabellen festlegen können

Kapitel 3 behandelt ausführlich das Festlegen und Pflegen von Beziehungen zwischen Tabellen. Vorläufig ist für Sie nur wichtig, dass Beziehungen schon beim Entwurf einer Datenbank so früh und so genau wie möglich festgelegt werden sollten. Dies ist eine wesentliche Voraussetzung für den erfolgreichen Entwurf und die erfolgreiche Entwicklung Ihrer Anwendung.

1.4.3

Abfragen: Gespeicherte Fragen oder Aktionen zur Anwendung auf Ihre Daten

Access-Abfragen sind leistungsfähig und vielseitig. Auswahlabfragen erlauben es, die in einer Tabelle vorhandenen Daten anzuschauen, Zusammenfassungen zu erstellen und Berechnungen mit diesen Daten durchzuführen. Aktionsabfragen ermöglichen das Addieren, Verändern und Löschen von Daten. Um eine Abfrage auszuführen, wählen Sie im Datenbankfenster unter OBJEKTE eine Abfrage aus und starten diese

Datenbankobjekte

35

durch einen Doppelklick. (Das gleiche bewirken Sie auch durch einfaches Anklicken und anschließendes Klicken auf ÖFFNEN.) Beim Ausführen einer Auswahlabfrage erscheint ein Datenblatt, das alle in der Abfrage aufgeführten Datenfelder enthält und alle Datensätze anzeigt, die den in der Abfrage genannten Auswahlkriterien entsprechen (siehe Abbildung 1.6). Wenn Sie eine Aktionsabfrage starten, wird die dort vorgesehene Aktion ausgeführt. So könnte zum Beispiel eine neue Tabelle erstellt oder eine vorhandene Tabelle um neue Datensätze erweitert werden. Grundsätzlich können Sie die Daten im Ergebnis einer Abfrage aktualisieren, weil es sich bei diesem Ergebnis tatsächlich um eine dynamische Menge von Datensätzen handelt, die als »Dynaset« bezeichnet wird und auf den Daten Ihrer Tabelle beruht.

Abbildung 1.6: Das Ergebnis der Ausführung der Abfrage Personalumsätze

Wenn Sie eine Abfrage speichern, so werden nur deren Definition sowie die Struktur und das Aussehen des Ergebnisdatenblatts in der Datenbank gespeichert. Access bietet ein leicht bedienbares, benutzerfreundliches Werkzeug für den Entwurf Ihrer Abfragen, das in Abbildung 1.7 zu sehen ist. Um dieses Fenster zu öffnen, wählen Sie in der Objektliste des Datenbankfensters den Eintrag ABFRAGEN, wählen die zu ändernde Abfrage aus und klicken auf ENTWURF. Die in Abbildung 1.6 gezeigte Abfrage wählt Daten aus den Tabellen Personal und Bestellungen sowie der Abfrage Bestellzwischensummen aus. Aus der Tabelle Personal werden die Felder Land, Nachname und Vorname, aus Bestellungen die Felder Versanddatum und Bestell-Nr und aus der Abfrage Bestellzwischensummen das Feld Zwischensumme dargestellt, wobei in der Ausgabemenge nur Daten aus einem bestimmten Zeitraum enthalten sind. Diese besondere Abfrageart heißt »Parameterabfrage«, weil einige oder alle Abfragebedingungen als Parameter eingegeben werden können, deren aktueller Wert erst beim Beginn der Abfrage feststeht. Abfragen werden in Kapitel 4 und in Kapitel 11 ausführlich behandelt. Weil Abfragen aber die Grundlage für die meisten Formulare und Berichte sind, finden sie auch in anderen Kapiteln dieses Buchs Berücksichtigung, wann immer Abfragen auf andere Objekte einer Datenbank Bezug nehmen.

36

1.4.4

Kapitel 1: Access als Entwicklungswerkzeug

Formulare: Daten anzeigen, bearbeiten und hinzufügen

In der Datenblattansicht einer Tabelle können Sie zwar Daten eingeben und verändern, es ist aber kaum möglich, die Benutzertätigkeiten zu steuern oder die Dateneingabe zu vereinfachen. Hierfür verwendet man in Access Formulare. Access-Formulare können sehr unterschiedlich sein und einen sehr großen Funktionsumfang besitzen.

Abbildung 1.7: Der Entwurf einer Abfrage, die Daten aus den Tabellen Personal und Bestellungen sowie der Abfrage Bestellzwischensummen anzeigt

Um ein Formular zu betrachten, wählen Sie aus der Objektliste den Eintrag FORMULARE aus und aktivieren diesen durch Doppelklick. Alternativ können Sie auch einmal auf FORMULARE und anschließend auf ÖFFNEN klicken. Abbildung 1.8 zeigt ein Formular in der Formularansicht. Dieses Formular besteht eigentlich aus drei einzelnen Formularen, nämlich einem Hauptformular und zwei Unterformularen. Das Hauptformular enthält Daten aus der Kundentabelle, und die Unterformulare zeigen Daten aus den Tabellen Bestellungen und Bestelldetails. Wenn nun der Benutzer sich die Kunden nacheinander ansieht, so werden ihm jeweils auch die mit diesen Kunden verknüpften Bestellungen angezeigt, und beim Anklicken einer Einzelbestellung eines Kunden sieht er die einzelnen Positionen dieser Bestellung. Wie Tabellen und Abfragen können auch Formulare in der Entwurfsansicht betrachtet werden. Um einen solchen Formularentwurf zu sehen, klicken Sie in der Objektliste auf FORMULARE, wählen das anzupassende Formular aus und klicken dann auf ENTWURF. Abbildung 1.9 zeigt das Formular Kundenbestellungen in der Entwurfsansicht. Beachten Sie die beiden Unterformulare innerhalb des Hauptformulars. Formulare werden ausführlich in Kapitel 5 und in Kapitel 9 erläutert. Außerdem werden sie an zahlreichen anderen Stellen dieses Buchs beschrieben, wenn sie beim Entwurf einer Beispielanwendung eine Rolle spielen.

Datenbankobjekte

37

Abbildung 1.8: Das Formular Kundenbestellungen umfasst Informationen zu den Kunden, zu den Bestellungen und zu den Bestelldetails

Abbildung 1.9: Der Entwurf des Formulars Kundenbestellungen enthält zwei Unterformulare

1.4.5

Berichte: Daten in Informationen verwandeln

Formulare dienen hauptsächlich der Eingabe und Bearbeitung von Informationen, mit Berichten können Sie dagegen Ihre Daten übersichtlich aufbereiten und zum Beispiel auf einem Drucker ausgeben. Abbildung 1.10 zeigt einen Bericht in der so genannten »Vorschau«. Um einen Bericht in der Vorschau anzusehen, wählen Sie in der Objektliste den Eintrag BERICHTE und doppelklicken auf den gewünschten Bericht oder Sie klicken zuerst auf den Bericht und dann auf VORSCHAU. Beachten Sie die in den Bericht eingebettete Grafik sowie andere Einzelheiten, wie etwa die schattierte Zeile. Berichte können wie Formulare sehr kunstvoll und aufwendig gestaltet sein und wertvolle Informationen enthalten.

38

Kapitel 1: Access als Entwicklungswerkzeug

Abbildung 1.10: Eine Voransicht des KatalogBerichts

Falls Sie es bisher noch nicht erraten haben: Auch Berichte können in einer Entwurfsansicht betrachtet werden (siehe Abbildung 1.11). Um den Entwurf eines beliebigen Berichts zu sehen, wählen Sie in der Objektliste den Eintrag BERICHTE, wählen den gewünschten Bericht aus und klicken danach auf ENTWURF. Abbildung 1.11 zeigt einen Bericht mit mehreren Abschnitten. Sie können den Berichts- und den Seitenkopf, einen Kopfbereich Kategoriename und den Detailbereich sehen – und das sind nur einige wenige der innerhalb eines Berichts möglichen Abschnitte. Ebenso wie ein Formular Unterformulare enthalten kann, kann auch ein Bericht Unterberichte enthalten. Berichte werden ausführlich in Kapitel 6 und Kapitel 10 sowie an vielen anderen Stellen dieses Buchs behandelt, weil sie in zahlreichen Beispielen Verwendung finden.

Abbildung 1.11: Entwurfsansicht des KatalogBerichts

Datenbankobjekte

1.4.6

39

Datenzugriffsseiten: Formulare, die mit einem Browser betrachtet werden

Datenzugriffsseiten, die schon weiter oben erwähnt wurden, sind in Access 2000 neu hinzugekommen. Sie bieten Ihnen die Möglichkeit, Daten in Ihrer Datenbank mit Hilfe eines Browsers zu betrachten und zu verändern. Obwohl sie außerhalb der Access-Datenbankdateien gespeichert werden, ähnelt ihre Erstellung und Pflege der von Formularen. Abbildung 1.12 zeigt eine Datenzugriffsseite, die innerhalb von Access betrachtet wird. Zwar werden Datenzugriffsseiten normalerweise für die Betrachtung in einem Browser erstellt, doch sie können auch innerhalb einer AccessAnwendung angesehen werden. Auch Datenzugriffsseiten können in einer Entwurfsansicht betrachtet und verändert werden. Abbildung 1.13 zeigt eine Datenzugriffsseite in der Entwurfsansicht. Wie Sie sehen, ähnelt die Entwurfsansicht einer Datenzugriffsseite derjenigen eines Formulars. Dadurch gestaltet sich das Arbeiten mit Datenzugriffsseiten und das Verbreiten Ihrer Anwendung über ein Intranet sehr einfach.

Abbildung 1.12: Ein Beispiel einer Datenzugriffsseite auf der Grundlage der Tabelle Personal

1.4.7

Makros: Ihr System automatisieren

Makros in Access unterscheiden sich deutlich von Makros in anderen Sprachen. Sie können nicht aufgezeichnet werden, wie dies bei Word und Excel möglich ist, und sie werden auch nicht als VBA-Programm gespeichert. Mit Access-Makros können Sie die meisten der manuell über Tastatur, Menü oder Symbolleisten ausführbaren Anweisungen automatisch ablaufen lassen. Makros erlauben sogar das Formulieren logischer Abhängigkeiten für den Ablauf Ihrer Datenbankanwendung. Sollen jedoch

40

Kapitel 1: Access als Entwicklungswerkzeug

Abbildung 1.13: Eine Datenzugriffsseite in der Entwurfsansicht

die Tätigkeiten Ihrer Anwendung besonders effektiv durchgeführt werden, so empfiehlt sich zum Programmieren VBA (Visual Basic für Applikationen) anstelle von Makros, denn VBA bietet deutlich mehr Möglichkeiten. Obwohl in früheren Versionen von Access einige Abläufe ausschließlich mit Hilfe von Makros realisiert werden konnten, werden sie von Entwicklern heutzutage nur sehr selten verwendet. Die Entwicklung von Anwendungen mit Makros wird deshalb in diesem Buch nicht behandelt. Um ein Makro auszuführen, gehen Sie folgendermaßen vor: Wählen Sie aus der Objektliste den Eintrag MAKROS, klicken Sie das gewünschte Makro an und klicken Sie danach auf AUSFÜHREN. Anschließend werden die im Makro definierten Anweisungen ausgeführt. Um den Entwurf eines Makros zu sehen, wählen Sie aus der Objektliste den Eintrag MAKROS aus, klicken das zu verändernde Makro an und klicken danach auf ENTWURF, um so das Entwurfsfenster zu öffnen (siehe Abbildung 1.14). Das hier abgebildete Makro verfügt über vier Spalten. Die erste Spalte ist die Namensspalte, in der die Namen von Unterprogrammen innerhalb von Makros festgelegt werden können. In der zweiten Spalte können Sie Bedingungen formulieren, die erfüllt sein müssen, damit die Aktion in der dritten Spalte ausgeführt wird. In die vierte Spalte schließlich können beliebige Kommentare eingetragen werden. In der unteren Hälfte des Entwurfsfensters geben Sie Argumente für die ausgewählte Aktion an. In Abbildung 1.14 wurde die Aktion MsgBox ausgewählt, die vier Argumente akzeptiert: Meldung, Signalton, Typ und Titel.

41

Datenbankobjekte

Abbildung 1.14: Der Entwurf des Makros Kunden mit Makronamen, Bedingungen, Aktionen und Kommentaren

1.4.8

Module: Die Grundlage der Anwendungsentwicklung

»Module« sind die Grundlage jeder Anwendung und erlauben Ihnen den Aufbau von Funktionsbibliotheken, deren einzelne Elemente Sie anschließend überall in Ihrer Anwendung einsetzen können. Module werden üblicherweise aus Unterroutinen und Funktionen gebildet, wobei Funktionen immer einen Wert zurückgeben, was bei Unterroutinen nicht der Fall ist. Mit Hilfe von Code-Modulen können Sie folgende Aufgaben erledigen:

 Fehler behandeln  Variablen deklarieren und verwenden  Datensatzgruppen durchlaufen und bearbeiten  Funktionen des Windows-API oder anderer Bibliotheken aufrufen  Systemobjekte wie Tabellen und Abfragen erstellen und bearbeiten  Transaktionen verarbeiten  Funktionen ausführen, die nicht als Makros verfügbar sind  komplexe Abläufe testen und korrigieren  Bibliotheksdatenbanken erstellen Dies sind nur einige der vielen Möglichkeiten, die Sie sich mit der Benutzung von Modulen erschließen. Um ein schon bestehendes Modul zu betrachten, klicken Sie in der Objektliste auf MODULE, wählen das gewünschte Modul aus und klicken dann auf Entwurf, um das Entwurfsfenster zu öffnen (siehe Abbildung 1.15). Das hier gezeigte Code-Modul enthält einen Abschnitt Allgemeine Deklarationen sowie eine

42

Kapitel 1: Access als Entwicklungswerkzeug

Funktion mit dem Namen IsLoaded. Module und VBA sind in Kapitel 7 und in Kapitel 24 beschrieben und werden darüber hinaus an sehr vielen Stellen des ganzen Buchs behandelt.

Abbildung 1.15: Das globale CodeModul in der Entwurfsansicht mit dem Abschnitt Allgemeine Deklarationen der Funktion IsLoaded

1.5

Objektbenennung

Eine wesentliche Grundlage für erfolgreiches Programmieren in Access wie in jeder anderen Programmiersprache ist es, Namenskonventionen festzulegen, die für die weitere Arbeit absolut verbindlich sein müssen. Achten Sie beim Festlegen solcher Konventionen vor allem auf diese drei Dinge:

 Einfachheit  Lesbarkeit  Akzeptanz in Entwicklerkreisen Die so genannten »Reddick-Namenskonventionen«, die von Greg Reddick stammen, sind mit Abstand die besten, die bisher für das Entwickeln von Anwendungen vorgeschlagen wurden. Die Reddick-Namenskonventionen unterstützen ein standardisiertes Vorgehen bei der Benennung von Objekten. Sie wurden von den Leszynski/Reddick-Namenskonventionen abgeleitet, die schon in Access 1.x und 2.0 überaus beliebt waren. Diese Standards wurden von den Programmentwicklern anerkannt und intensiv angewendet, so dass sie in den meisten guten Büchern über Programmentwicklung und in vielen Zeitschriftenartikeln der letzten Jahre zu finden sind. Die neuen ReddickNamenskonventionen wurden überarbeitet, um vor allem solche Entwickler zu unterstützen, die die VBA-Sprache gleichzeitig in Access, Visual Basic, Excel und anderen Microsoft-Produkten einsetzen. Diese Konventionen bieten Ihnen eine

Hardwareanforderungen

43

leicht benutzbare und nachvollziehbare Richtschnur für Objektnamen in allen diesen Programmumgebungen. Eine Zusammenfassung der Reddick-Namenskonventionen finden Sie im Anhang. Ich werde von diesen Vereinbarungen überall im Buch Gebrauch machen und auf bestimmte Aspekte gezielt eingehen, wenn sie gerade von Bedeutung sind.

1.6

Hardwareanforderungen

Ein Nachteil von Access sind die ständig steigenden Hardwareanforderungen bei neuen Versionen. Die Hardwareanforderungen eines Entwicklers sind andere als die eines Endbenutzers, weshalb dieser Abschnitt aus zwei Teilen besteht. Achten Sie beim Lesen dieser Anforderungen außerdem immer auf den Unterschied zwischen tatsächlich erforderlicher und empfohlener Hardwareausstattung.

1.6.1

Welche Hardware benötigt der Entwickler?

Gemäß Microsoft-Handbuch sind dies die offiziellen Mindestvoraussetzungen, um Access 2000 einsetzen zu können:

 386DX-Prozessor (empfohlen: 486)  Windows 95 oder Windows NT 3.51 oder höher  12 MB RAM für Windows 95  16 MB RAM für Windows NT  VGA-Grafikkarte (empfohlen: SVGA, 256 Farben)  Zeigegerät (zum Beispiel eine Maus) Trotzdem sind meine eigenen Empfehlungen für einen Entwicklungsrechner noch sehr viel höher, weil Sie ja möglicherweise neben Access noch andere Anwendungen auf Ihrem System einsetzen wollen. Außerdem ist es mit Sicherheit in Ihrem Interesse, die Wahrscheinlichkeit eines Systemabsturzes oder anderer Probleme zu verringern, die durch einen zu kleinen Arbeitsspeicher verursacht werden können. Ich empfehle deshalb für ein Entwicklungssystem die folgende Ausstattung:

 Pentium 133 oder höher  64 MB RAM für Windows 95 oder 98, 64 MB RAM für Windows NT (oder mehr, falls Sie mehrere Anwendungen gleichzeitig einsetzen wollen)

 hochauflösender Bildschirm – je größer, desto besser, und möglichst mit SVGAGrafikkarte

44

Kapitel 1: Access als Entwicklungswerkzeug

Wenn Sie Anwendungen an einem hochauflösenden Bildschirm entwickeln, sollten Sie die Formulare trotzdem so gestalten, dass sie auch auf dem schlechtesten üblicherweise eingesetzten Bildschirm noch richtig angezeigt werden können. Auch wenn Ihnen die hohe Auflösung Ihres eigenen Systems beim Entwickeln Vorteile bietet, sollten Sie dennoch stets daran denken, dass viele Benutzer nur Bildschirme mit geringerer Auflösung einsetzen. Grundsätzlich gilt für die Hardware eines Entwicklungssystems: je mehr, desto besser. Man kann nie genügend Arbeitsspeicher und nie genügend Plattenplatz haben. Sie werden umso mehr Freude mit Access haben, je mehr Arbeits- und Plattenspeicher Sie in Ihre Arbeitsstation eingebaut haben.

1.6.2

Welche Hardware benötigt der Benutzer?

Wenngleich ein Benutzersystem bei weitem nicht so gut ausgestattet sein muss wie ein Entwicklersystem, empfehle ich dennoch zusätzlich zu den von Microsoft genannten Anforderungen Folgendes:

 Pentium 133 oder höher  48 MB RAM für Windows 95 oder Windows 98, 64 MB RAM für Windows NT (oder noch mehr, wenn Ihre Anwendung OLE unterstützt oder Ihr Benutzer neben Access noch andere Programme einsetzt)

1.7

Wie beginne ich mit der Entwicklung einer Access-Anwendung?

Viele Entwickler erliegen dem Trugschluss, man brauche für das Entwickeln einer Access-Anwendung keinerlei Systemanalyse und keinerlei Datenbankentwurf, weil Access doch eine so bequeme und weitgehend automatisierte Entwicklungsumgebung bietet. Ein größeres Missverständnis ist kaum denkbar: Schon früher in diesem Kapitel habe ich erwähnt, dass sich Access-Anwendungen trügerisch leicht erstellen lassen, was aber ohne eine saubere Planung schnell zu einem heillosen Durcheinander führen kann.

1.7.1

Aufgabenanalyse

Der erste Schritt beim Entwicklungsablauf besteht darin, die gewünschte Aufgabe gründlich zu analysieren oder jeden einzelnen Vorgang im Laufe eines Arbeitstages des späteren Benutzers genau zu überdenken – eine sehr lästige, aber unumgängliche Arbeit. Als ich selbst in einem großen Unternehmen meine erste Stelle als Programmierer in einer Großrechnerumgebung angetreten hatte, musste ich eine Checkliste für Arbeitsabläufe sorgfältig befolgen. Ich musste herausfinden, welche täglichen

Wie beginne ich mit der Entwicklung einer Access-Anwendung?

45

Aufgaben jeder Benutzer des Systems hatte, jeden Arbeitsschritt beschreiben, den Ablauf der einzelnen Arbeitsschritte von einem Benutzer zum nächsten dokumentieren, den Zusammenhang der einzelnen Arbeitsschritte untereinander herausfinden und schließlich den Zusammenhang der Arbeitsschritte mit den Unternehmenszielen beschreiben. Heute, im Zeitalter der schnellen Anwendungsentwicklung und des schnellen Technologiewandels, verschwindet dieser Teil des Entwicklungsprozesses offenbar aus dem Blickfeld. Ich behaupte jedoch, dass ein Entwickler später wesentliche Teile seiner Anwendung neu schreiben muss, wenn er die einzelnen Arbeitsschritte nicht zu Beginn der Entwicklung sorgfältig untersucht hat.

1.7.2

Datenanalyse und Entwurf

Nachdem Sie alle Arbeitsschritte untersucht und beschrieben haben, die für Ihr Entwicklungsprojekt wichtig sind, können Sie mit der Datenanalyse und dem Entwurf Ihrer Anwendung beginnen. Dabei müssen Sie für jeden einzelnen Arbeitsschritt jede erforderliche Einzelinformation beschreiben. Diese Einzeldaten werden danach zu Themen zusammengefasst und aus jedem Thema entsteht anschließend eine Tabelle in Ihrer Datenbank. Ein Thema könnte beispielsweise ein Kunde sein, dann wird jedes Datenelement, das zu diesem Kunden in irgendeiner Beziehung steht, ein Feld in der Kundentabelle. Name, Adresse, Telefonnummer, Kreditlimit und andere wichtige Informationen würden also Felder in der Kundentabelle. Für jedes Datenelement sollten Sie die folgenden Eigenschaften festlegen:

 den geeigneten Datentyp  die benötigte Feldgröße  Gültigkeitsregeln Außerdem sollten Sie für jedes Datenelement bestimmen, ob es später veränderbar sein soll und ob die Daten vom Benutzer eingegeben werden oder ob der Inhalt vom System selbst errechnet wird. Dann können Sie herausfinden, ob Ihre Tabellenstrukturen in Normalform vorliegen oder nicht. Regeln leicht gemacht Mit dem Begriff »Normalisierung« beschreibt man das Überprüfen eines Tabellenentwurfs hinsichtlich einer Reihe bestimmter Regeln, die – wenn sie eingehalten werden – bewirken, dass eine Anwendung möglichst effektiv abläuft. Diese Regeln beruhen auf der Mengenlehre und wurden erstmals von Dr. E. F. Codd vorgeschlagen. Obwohl Sie sich jahrelang mit dem Thema Normalisierung beschäftigen können, so ist doch das Hauptziel der Normalisierung sehr einfach zu formulieren: Eine Anwendung soll möglichst effektiv ablaufen, ohne dass nennenswerte Veränderungen an der Datenstruktur oder an den Programmen vorgenommen werden müssen. Es folgen sechs wichtige Regeln für die Normalisierung:

46

Kapitel 1: Access als Entwicklungswerkzeug

 Felder sollen atomar sein, was bedeutet, dass Daten so weit wie möglich zerlegt werden sollten. Beispielsweise würden Sie anstelle eines Feldes Name eher zwei Felder erstellen: eines für den Vor- und eines für den Nachnamen. Auf diese Weise lassen sich Daten erheblich leichter handhaben. Nur so kann man zum Beispiel bequem und ohne nennenswerten Aufwand alle Daten der Tabelle unabhängig von den Nachnamen nach den Vornamen sortieren oder nach einem bestimmten Vornamen suchen.

 Jeder Datensatz sollte eine eindeutige Kennzeichnung enthalten, die ihn von jedem anderen Datensatz der Tabelle unterscheidet. Wenn Sie zum Beispiel Kundendaten verändern, können Sie auf diese Weise sicherstellen, dass wirklich die Daten des richtigen Kunden verändert werden. Eine solche eindeutige Kennzeichnung nennt man einen »Primärschlüssel«.

 Der Primärschlüssel besteht aus einem Feld oder einer Gruppe von Feldern, die einen Datensatz eindeutig kennzeichnen. Manchmal lässt sich hier ein natürlicher Schlüssel verwenden, wie etwa das Geburtsdatum in einem Personaldatensatz, die ja einem Mitarbeiter eindeutig und unveränderbar zugeordnet ist. Der Kundenname in einem Kundendatensatz lässt sich dagegen nicht als Primärschlüssel benutzen, weil mehrere Kunden den gleichen Namen haben können. In solchen Fällen muss man einen künstlichen Primärschlüssel erzeugen, wie zum Beispiel eine Kundennummer.

 Ein Primärschlüssel soll kurz, einfach und feststehend sein. »Kurz« bedeutet, er soll nur wenige Zeichen lang sein, »einfach« bedeutet, dass die Benutzer bequem mit ihm umgehen können, und »feststehend« bedeutet, dass er selten oder nie geändert wird. Eine Kundennummer würde sich zum Beispiel im Gegensatz zu einem Kundennamen nur selten ändern.

 Jedes Feld innerhalb einer Tabelle sollte zusätzliche Informationen über den mit dem Primärschlüssel gekennzeichneten Datensatz enthalten. Jedes Feld eines Kundensatzes enthält beispielsweise zusätzliche Daten über diesen Kunden mit seiner eindeutigen Kundennummer.

 Informationen sollten stets nur einmal, also nur an einer einzigen Stelle, in der Datenbank gespeichert sein. So sollte beispielsweise ein Kundenname nicht in mehreren Datensätzen auftauchen. Betrachten wir ein Beispiel: Das in Abbildung 1.16 dargestellte Datenblatt ist ein Beispiel für eine nicht normalisierte Tabelle. Beachten Sie, dass das Feld CustInfo bei jeder Bestellung wiederholt wird. Würde sich nun die Adresse des Kunden ändern, müsste man diese Änderung in sämtlichen Bestelldatensätzen nachträglich vornehmen. Das Feld CustInfo ist außerdem nicht atomar: Eine Sortierung nach Städtenamen ist unmöglich, weil sich diese nicht am Anfang der Adresse befinden. Wenn der Name eines Artikels geändert wird, müsste man diese Änderung ebenfalls in allen entsprechenden Datensätzen einzeln nachtragen. Das vielleicht schwierigste Problem in diesem Beispiel betrifft aber die bestellten Artikel: Bei dieser Datenbank-

Wie beginne ich mit der Entwicklung einer Access-Anwendung?

47

struktur benötigt man für jede bestellte Position vier Datenfelder: Name, Lieferant, Bestellmenge und Preis. Mit einer solchen Datenbankstruktur ist es extrem aufwendig, zusammenfassende Berichte zu erstellen, die Benutzer für ihre tägliche Arbeit benötigen.

Abbildung 1.16: Eine nicht normalisierte Tabelle

Abbildung 1.17 zeigt die gleichen Daten in normalisierter Form. Beachten Sie, dass die Daten sich nun in vier unterschiedlichen Tabellen befinden: tblCustomers, tblOrders, tblOrderDetails und tblSuppliers. Die Tabelle tblCustomers enthält ausschließlich Datensätze, die jeweils die Daten eines bestimmten Kunden enthalten und durch eine Kundennummer (CustID) eindeutig gekennzeichnet sind. Dieses Feld dient außerdem zur Verknüpfung mit der Tabelle tblOrders, d.h. mit den Bestellungen. Die Tabelle tblOrders enthält ihrerseits nur Informationen über die Bestellungen als Ganzes, nicht jedoch Angaben zu den einzelnen Bestellpositionen. Sie umfasst insbesondere das Feld CustID des Kunden, von dem die Bestellung stammt, sowie das Bestelldatum. Die Tabelle tblOrders steht über eine Bestellnummer (OrderID) mit der Tabelle tblOrderDetails in Beziehung. Die Tabelle tblOrderDetails speichert Informationen über jeden im Rahmen einer Bestellung bestellten Artikel, wobei die Anzahl der bestellten Artikel unbegrenzt ist. Je mehr Positionen bestellt werden, um so mehr Datensätze werden an diese Tabelle tblOrderDetails angefügt. Schließlich sind die Lieferantendaten in einer eigenen Tabelle tblSuppliers abgelegt, so dass eine eventuelle Veränderung von Lieferantendaten in der Datenbank nur an einer einzigen Stelle zu berücksichtigen ist.

48

Kapitel 1: Access als Entwicklungswerkzeug

Abbildung 1.17: Den Regeln entsprechend in vier getrennte Tabellen aufgeteilte Daten

1.7.3

Prototypen

Bei der Untersuchung der betrieblichen Abläufe und der Datenstrukturen hat sich seit den Tagen der Großrechner nicht viel getan, die Erstellung von Prototypen funktioniert aber mittlerweile vollkommen anders. Bei der Entwicklung von Anwendungssystemen für Großrechner oder für DOS-basierende Sprachen war es wichtig, jede Bildschirmmaske und jeden Bericht sehr genau und sehr aufwendig zu beschreiben. Ich erinnere mich daran, dass damals die Benutzer jeden Bildschirm- und Berichtsentwurf vorab gegenzeichnen mussten. Dies galt auch für einfache Änderungen wie etwa das Verschieben eines Feldes auf dem Bildschirm oder das Einfügen einer zusätzlichen Summenzeile in einen Bericht. Nachdem der Benutzer den Entwurf abgezeichnet hatte, verschwanden die Programmierer für mehrere Tage und arbeiteten hart an dieser Änderung. Wollten die Benutzer nach einigen Monaten abermals Änderungen an Masken oder Berichten, bedeutete dies erneute Planungsarbeit, erneute Entwürfe und erneuten Programmieraufwand. Dieser Entwicklungsprozess läuft heute ganz anders ab. Sobald die Arbeitsabläufe beschrieben und die Daten grundlegend analysiert sind, kann der Entwickler die Tabellen und deren Beziehungen zueinander entwerfen. Danach kann er mit dem Entwurf der Formulare und Berichte beginnen. Während es früher Wochen oder Monate dauerte, ehe ein Entwickler seine Arbeitsergebnisse dem Benutzer vorzeigen konnte, dauert es heute nur wenige Tage, um mit den Access-Assistenten schnell erste Prototypen von Formularen und Berichten zu entwerfen.

1.7.4

Testen

Testen kann man nie genug, auch wenn die Tests noch so sorgfältig sind. Ich empfehle Ihnen, Ihre Anwendung, wenn diese später unter Windows 95, 98 und NT laufen soll, in jeder dieser Umgebungen zu testen. Ich rate Ihnen außerdem, Ihre Anwendung auf einem System zu testen, das sozusagen den kleinsten gemeinsamen

Wie beginne ich mit der Entwicklung einer Access-Anwendung?

49

Nenner aller späteren Benutzer darstellt – denn es könnte sein, dass die Anwendung auf Ihrem eigenen leistungsfähigen System ganz hervorragend läuft, während sie auf einem leistungsschwächeren Benutzersystem einbricht. Meistens ist es hilfreich, sowohl die einzelnen Teile einer Anwendung als auch die Anwendung als Ganzes zu testen. Suchen Sie sich einen Stab von Testpersonen und achten Sie darauf, dass dabei vom blutigen Anfänger bis zum Computerexperten alle denkbaren Benutzertypen vertreten sind. Denn diese unterschiedlichen Personen werden möglicherweise ganz unterschiedliche Probleme in Ihrer Anwendung entdecken. Ganz besonders wichtig ist, dass nicht Sie selbst der einzige Tester Ihrer Anwendung sind, weil ein Entwickler für das Finden von Fehlern in seiner eigenen Anwendung ziemlich ungeeignet ist.

1.7.5

Implementierung

Nach der Testphase können Sie Ihre Anwendung auf die Menschheit loslassen – oder zumindest hoffen Sie das. Verteilen Sie Ihre Anwendung zunächst nur an einige Ihrer Benutzer und erklären Sie diesen, dass es sich vorläufig noch um eine Testphase handelt. Machen Sie diesen Benutzern deutlich, dass es eine Ehre ist, als erste ein neues System testen und benutzen zu dürfen, aber erwähnen Sie auch, dass noch Fehler auftreten können und dass solche Fehler unbedingt an Sie, den Entwickler, zu melden sind. Wenn Sie anders vorgehen, also Ihre neue Anwendung gleich an viele Benutzer verteilen und sich dann schwerwiegende Fehler in Ihrer Anwendung herausstellen, ist es erfahrungsgemäß recht schwierig, das erschütterte Vertrauen der Benutzer wiederzugewinnen. Deshalb ist es so überaus wichtig, Ihre neue Anwendung behutsam im betrieblichen Alltag einzuführen.

1.7.6

Systempflege

Da Access auf die schnelle Anwendungsentwicklung ausgelegt ist, wird die für die Systempflege aufzuwendende Zeit länger, als dies in der Vergangenheit bei den Großrechnern der Fall war. Die Benutzeransprüche werden immer größer, d.h., je mehr Wünsche Sie erfüllen, umso mehr Wünsche werden die Benutzer haben. Für einen Berater ist das großartig. Aber achten Sie darauf, nicht in eine ungewollte Abhängigkeit zu geraten: Wenn Sie sich nur noch mit der Pflege Ihrer alten Anwendungen befassen, werden Sie irgendwann keine Zeit mehr für neue Entwicklungen haben. Man kann drei Arten von Pflegearbeiten unterscheiden: Fehlerbeseitigung, zusätzliche Benutzeranforderungen und Feinheiten. Fehler müssen immer schnellstmöglich beseitigt werden. Die Auswirkungen zusätzlicher Benutzeranforderungen müssen den Benutzern deutlich vor Augen geführt werden, einschließlich des nötigen zeitlichen und finanziellen Aufwands. Und Feinheiten, nebensächliche Verzierungen an Formularen und Berichten? Da sollten Sie versuchen, die Benutzer möglichst stark mit einzubeziehen. Zeigen Sie den Benutzern, wie sie selbst Formulare erweitern und

50

Kapitel 1: Access als Entwicklungswerkzeug

Berichte ihren Wünschen anpassen können. Bedenken Sie stets: zufriedene und produktive Benutzer sind das wichtigste Ziel jeder Entwicklung.

1.7.7

Für die Praxis

Ein Beratungsunternehmen in der Computerbranche Im Verlauf dieses Buchs wird beispielhaft eine Anwendung entwickelt, nämlich ein Zeit- und Abrechnungssystem für ein Beratungsunternehmen in der Computerbranche. Zunächst wollen wir für diese Anwendung eine grobe Struktur entwerfen: Das geplante System soll Kunden, Kundenkontakte und Kundenprojekte aufzeigen. Der Benutzer soll damit alle berechneten Stunden und alle aufgelaufenen Kosten pro Kunde und pro Projekt ausweisen können. Es soll außerdem möglich sein, über jeden Angestellten und jeden Subunternehmer wichtige Informationen abzurufen. Die Tabellen in dem geplanten System sollen zunächst mit dem Datenbank-Assistenten erstellt werden, danach werden sie bei Bedarf angepasst und erhalten Namen nach den Reddick-Namenskonventionen. Das von Ihnen entworfene System wird anschließend weit leistungsfähiger und vielseitiger sein als das vom DatenbankAssistenten bereitgestellte. Wir werden in diesem System zehn Tabellen verwenden. Einige dieser Tabellen werden in Kapitel 2 erstellt und Sie finden alle Tabellen in den Anwendungsdatenbanken auf der beiliegenden CD-ROM:

 tblClients – Diese Tabelle enthält alle kundenspezifischen Informationen und steht in Beziehung zur Tabelle tblProjects, in der alle Daten für jedes Projekt eines Kunden gespeichert sind.

 tblProjects – Diese Tabelle enthält alle projektspezifischen Informationen und steht gleich zu mehreren Tabellen in Beziehung: tblClients, tblPayments, tblEmpoyees und tblTimeCardExpenses.

 tblTimeCardHours – In dieser Tabelle werden für jedes Projekt und für jeden Angestellten alle aufgewendeten Arbeitsstunden aufgezeichnet. Es bestehen Beziehungen zu tblProjects, tblTimeCards und tblWorkCodes.

 tblPayments – In diese Tabelle werden alle Zahlungen gespeichert, die mit einem bestimmten Projekt in Zusammenhang stehen. tblPayments steht in Beziehung zu den Tabellen tblProjects und tblPaymentMethods.

 tblTimeCardExpenses – Diese Tabelle enthält alle Spesen pro Projekt und Mitarbeiter und steht in Beziehung zu tblProjects, tblTimeCards und tblExpenseCodes.

 tblEmployees – Diese Tabelle enthält personalbezogene Daten und steht in Beziehung zu tblProjects und tblTimeCards.

Wie beginne ich mit der Entwicklung einer Access-Anwendung?

51

 tblTimeCards – In dieser Tabelle werden die Arbeitszeiten jedes einzelnen Mitarbeiters eingetragen. Tatsächlich dient tblTimeCards als Verbindung zwischen der m:n-Beziehung zwischen den Tabellen tblEmployees und tblTimeCardExpenses und der Beziehung zwischen tblEmployees und tblTimeCardHours. tblTimeCards steht in Beziehung zu tblEmployees, tblTimeCardHours und tblTimeCardExpenses.

 tblExpenseCodes – Diese Tabelle dient zum Nachschlagen der gültigen Codes für die unterschiedlichen Spesenarten und steht in Beziehung zu tblTimeCardExpenses.

 tblWorkCodes – Diese Tabelle dient zum Nachschlagen der gültigen Codes für die unterschiedlichen Arten von Arbeit und steht in Beziehung zu tblTimeCardHours.

 tblPaymentMethods – Diese Tabelle dient zum Nachschlagen der gültigen Codes für die unterschiedlichen Zahlungsweisen und steht in Beziehung zu tblPayments. Die Beziehungen zwischen diesen Tabellen werden in Kapitel 3 ausführlich behandelt und sind in Abbildung 1.18 grafisch dargestellt.

Abbildung 1.18: Beziehungen zwischen den Tabellen im Zeitund Abrechnungssystem

Was jeder Entwickler über Tabellen wissen sollte

Kapitel

Hier lesen Sie:

 Mit Tabellen arbeiten  Den für Ihre Daten geeigneten Feldtyp auswählen  Feldeigenschaften  Der allgegenwärtige Primärschlüssel  Der Nachschlage-Assistent  Tabelleneigenschaften  Mit Hilfe von Indizes die Geschwindigkeit verbessern  Access-Tabellen und das Internet

2.1

Mit Tabellen arbeiten

Es gibt mehrere Möglichkeiten, zu einer schon bestehenden Access 2000-Datenbank eine neue Tabelle hinzuzufügen: Sie können sich den Entwurf durch einen AccessAssistenten erleichtern, eine Tabelle von Grund auf entwerfen, ein datenblattähnliches Format in eine Tabelle umwandeln, eine Tabelle aus einer anderen Datenbank kopieren und Ihre Datenbank mit einer externen Tabelle verknüpfen. In diesem Kapitel wird beschrieben, wie man eine Tabelle von Grund auf entwirft – das Importieren und Verknüpfen von Tabellen wird sehr ausführlich in nahezu allen Kapiteln dieses Buches behandelt. Auf die beiden anderen Möglichkeiten wird jedoch in diesem Buch nicht eingegangen, weil sie für die meisten betrieblichen Anwendungen nicht geeignet sind. Wenn Sie eine neue Tabelle entwerfen wollen, müssen Sie zunächst in der Objektliste des Datenbankfensters das Symbol TABELLEN anklicken. Dies gilt für alle oben genannten Möglichkeiten. Danach erscheinen Symbole, die Ihnen das Erstellen

54

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

einer Tabelle in der Entwurfsansicht, mit Hilfe des Tabellen-Assistenten oder durch die Eingabe von Daten ermöglichen (siehe Abbildung 2.1).

Abbildung 2.1: Um eine neue Tabelle zu erstellen, klicken Sie auf das Tabellensymbol im Datenbankfenster

2.2

Eine Tabelle von Grund auf entwerfen

Eine Tabelle von Grund auf zu entwerfen bietet eine besonders große Flexibilität und fördert gute Entwurfsprinzipien. Für den Entwurf einer normalen betrieblichen Anwendung ist dies fast immer der beste Weg. Um eine Tabelle von Grund auf zu entwerfen, wählen Sie in der Objektliste TABELLEN|NEU und klicken danach zweimal auf das Symbol ERSTELLT EINE TABELLE IN DER ENTWURFSANSICHT. Danach erscheint das Tabellenentwurfsfenster, wie es in Abbildung 2.2 zu sehen ist. Führen Sie dann die folgenden Schritte aus: 1. Geben Sie jedem Tabellenfeld in der Spalte FELDNAME einen Namen. Sie können stattdessen auch die Schaltfläche AUFBAUEN auf der Symbolleiste anklicken (die Schaltfläche mit dem Zauberstab), um das Dialogfeld FELD-GENERATOR zu öffnen, das in Abbildung 2.3 dargestellt ist. Dieser Generator erlaubt die Auswahl vordefinierter Felder mit vordefinierten Eigenschaften. Natürlich können Sie diese Eigenschaften jederzeit nach Ihren eigenen Vorstellungen verändern. 2. Springen Sie mit dem Tabulator zur Spalte FELDDATENTYP. Wählen Sie den Standard-Feldtyp Text aus, oder entscheiden Sie sich mit Hilfe des aufklappbaren Kombinationsfeldes für einen anderen Feldtyp. Hinweise zur Auswahl des für Ihre Daten geeigneten Feldtyps finden Sie im Absatz »Den für Ihre Daten geeigneten Feldtyp auswählen« in diesem Kapitel. Beachten Sie beim Benutzen des Feld-Generators, dass Sie den hier angebotenen Feldtyp jederzeit an Ihre Bedürfnisse anpassen können.

Eine Tabelle von Grund auf entwerfen

55

Abbildung 2.2: Die Tabellenentwurfsansicht wird benutzt, um Feldnamen, Datentypen und Beschreibungen für alle Felder in einer Tabelle einzugeben

Abbildung 2.3: Das Dialogfeld Feld-Generator gibt Ihnen die Möglichkeit, aus einer Liste vordefinierter Felder mit vordefinierten Eigenschaften auszuwählen

3. Springen Sie mit dem Tabulator zur Spalte BESCHREIBUNG. Was Sie in diese Spalte schreiben, erscheint später in der Statuszeile, wenn der Benutzer Daten in dieses Feld eingibt. Diese Spalte ist also besonders wichtig für die Dokumentation der Daten, die in diesem Feld gespeichert werden. 4. Geben Sie nun bei Bedarf noch weitere Felder ein. Wenn Sie ein zusätzliches Feld zwischen zwei vorhandenen Feldern einfügen wollen, klicken Sie in der Symbolleiste auf die Schaltfläche ZEILEN EINFÜGEN. Das neue Feld wird so oberhalb des von Ihnen angeklickten Feldes eingefügt. Um dagegen ein Feld zu entfernen, klicken Sie auf die Schaltfläche ZEILEN LÖSCHEN. 5. Um Ihre Angaben zu speichern, klicken Sie in der Symbolleiste auf die Schaltfläche SPEICHERN. Es erscheint nun das Dialogfeld SPEICHERN UNTER (siehe Abbildung 2.4). Geben Sie jetzt noch einen Namen für Ihre neue Tabelle an und klicken Sie dann auf OK. Danach erscheint ein Dialogfeld, das Ihnen vorschlägt, einen Primärschlüssel festzulegen, denn jede Tabelle sollte einen Primärschlüssel haben. Primärschlüssel werden ausführlich im noch folgenden Abschnitt »Der allgegenwärtige Primärschlüssel« behandelt.

56

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

Abbildung 2.4: Verwenden Sie das Dialogfeld Speichern unter, um einer Tabelle einen Namen zu geben

Die Namensregeln für Tabellen ähneln den Regeln für Feldnamen, allerdings sollten Tabellennamen immer mit den drei Buchstaben tbl beginnen. Die Namensregeln werden ausführlich in Kapitel 1 und im Anhang beschrieben.

Feldnamen können bis zu 64 Zeichen lang sein. Aus praktischen Gründen ist aber eine Beschränkung auf zehn bis fünfzehn Zeichen zu empfehlen – das ist genug, um einem Feld einen aussagekräftigen Namen zu geben.

Feldnamen können jede beliebige Kombination von Buchstaben, Ziffern, Leerzeichen und anderen Zeichen enthalten, mit Ausnahme von Punkten, Ausrufezeichen, Fragezeichen, Akzenten und Klammern. Ich empfehle Ihnen aber, ausschließlich Buchstaben zu verwenden. Leerzeichen innerhalb von Feldnamen können bei der Formulierung von Abfragen, Modulen und anderen Datenbankobjekten schnell zum Problem werden. Seien Sie nicht beunruhigt darüber, dass Ihre Benutzer diese Feldnamen ohne Leerzeichen später sehen könnten; weiter hinten in diesem Kapitel werden Sie erfahren, wie Sie die für einen Benutzer sichtbaren Feldbeschriftungen festlegen können. Feldnamen dürfen nicht mit Leerzeichen beginnen. Wie schon erwähnt, sollten Feldnamen grundsätzlich gar keine Leerzeichen enthalten, so dass diese Einschränkung nicht von Belang ist. Versuchen Sie nie, Eigenschaftswörter, Schlüsselwörter, Funktionsnamen oder die Namen anderer Access-Objekte als Feldnamen zu verwenden. Obwohl Ihr Programm unter gewissen Umständen korrekt ausgeführt werden könnte, könnten Sie in anderen Fällen unvorhersehbare Ergebnisse erhalten. Sie sollten auch berücksichtigen, dass nicht alle Back-End-Datenbanken sämtliche bei Access möglichen Feldtypen verarbeiten können. Wenn Sie daran frühzeitig denken, können Sie später recht einfach den Übergang von einem Einzelplatzsystem zu einem Client-Server-System durchführen. Außerdem sollten Sie berücksichtigen, dass bei den meisten Back-End-Datenbanken die Länge von Feldnamen und die in den Feldnamen erlaubten Sonderzeichen stärker eingeschränkt sind, als dies bei Access der Fall ist. Um Probleme bei der Übergabe von Access-Tabellen auf BackEnd-Datenbank-Server zu vermeiden, sollten Sie dies bei der Benennung von Datenfeldern rechtzeitig bedenken.

Den für Ihre Daten geeigneten Feldtyp auswählen

57

Ich empfehle Ihnen dringend, Ihre Tabellen, Abfragen, Formulare, Berichte, Makros und Module immer ausführlich zu beschreiben. Diese Dokumentation hilft später Ihnen selbst oder demjenigen, der Ihre Anwendungen zu pflegen hat, notwendige Änderungen durchzuführen. Die Dokumentation Ihrer Anwendung wird ausführlich in Kapitel 35 behandelt.

2.3

Den für Ihre Daten geeigneten Feldtyp auswählen

Der Datentyp, den Sie für die einzelnen Felder wählen, kann auf die Leistung und die Funktionalität Ihrer Anwendung einen sehr starken Einfluss haben. Mehrere Faktoren können die Wahl des Datentyps für die Felder Ihrer Tabelle beeinflussen:

 die Art der Daten, die in dem Feld gespeichert werden  ob die Daten in Berechnungen verwendet werden müssen  ob die Daten in diesem Feld sortiert werden sollen  die Art und Weise, wie Sie diese Daten sortieren wollen  wie wichtig Plattenspeicherplatz für Sie ist Die Art der Daten, die in den Feldern gespeichert werden sollen, hat den größten Einfluss auf die Wahl des für Ihre Daten geeigneten Feldtyps. Müssen Sie zum Beispiel Zahlen mit führenden Nullen speichern, können Sie kein Zahlenfeld verwenden, weil bei diesem führende Nullen unterdrückt werden. Diese Einschränkung betrifft zum Beispiel Postleitzahlen, die ja durchaus mit führenden Nullen beginnen können, sowie Abteilungsnummern. Wenn es unwichtig ist, ob führende Nullen tatsächlich in den Tabellen gespeichert werden, und wenn Sie die führenden Nullen nur bei der Ausgabe von Formularen und Berichten benötigen, so lässt sich dies mit den so genannten Formatierungseigenschaften bewerkstelligen. Diese werden im Abschnitt »Feldeigenschaften« dieses Kapitels genauer beschrieben. Sofern die in einem Datenfeld gespeicherten Daten in Berechnungen verwendet werden sollen, müssen Sie für dieses Datenfeld den Feldtyp ZAHL oder WÄHRUNG auswählen, da kein anderer Feldtyp sich in Berechnungen verwenden lässt. Die einzige Ausnahme ist das Datumsfeld, welches in Berechnungen benutzt werden kann, die auf dem Datum oder der Zeit beruhen. Sie müssen auch beizeiten überlegen, ob Sie die in einem Feld gespeicherten Daten sortieren oder als Index verwenden wollen. Bedenken Sie, dass Memo-, OLE- und

58

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

Hyperlink-Felder nicht sortiert werden können. Verwenden Sie diese Feldtypen also nicht, wenn ein Feld sortiert oder als Index verwendet werden soll. Weiterhin müssen Sie darüber nachdenken, wie die Daten später sortiert werden sollen. Zahlen, die in einem Textfeld gespeichert sind, werden zum Beispiel in der Reihenfolge 1, 10, 100, 2, 20, 200 usw. sortiert, was der normalen ASCII-Reihenfolge entspricht. Andererseits werden Zahlen, die in einem numerischen oder in einem Währungsfeld gespeichert sind, in der erwarteten numerischen Reihenfolge sortiert (also: 1, 2, 10, 20, 100, 200 usw.). Auch wenn Sie nun glauben, das Sortieren von Zahlen in ASCII-Reihenfolge könne gar nicht sinnvoll sein: es gibt durchaus sinnvolle Einsatzgebiete, wie etwa das Sortieren unterschiedlich langer Telefonvorwahlen. Schließlich sollten Sie noch bedenken, wie wichtig und kostbar Plattenspeicher für Sie ist. Die verschiedenen Datentypen benötigen unterschiedlich viel Speicherplatz. Auch dies kann wichtig werden, wenn Sie einen Feldtyp für ein Datenfeld auswählen. Es gibt in Access neun verschiedene Felddatentypen: Text, Memo, Zahl, Datum/Zeit, Währung, AutoWert (in Access 2.0 als Zähler bekannt), Ja/Nein, OLE-Objekt und Hyperlink. Tabelle 2.1 enthält alle wichtigen Informationen für die Verwendungszwecke dieser Feldtypen und gibt darüber hinaus auch Auskunft über die jeweilige Speicherbelegung. Feldtyp

Verwendungszweck

Speicherbelegung

Text

Abhängig von den tatsächlich im Daten, die aus Text oder Zahlen Feld gespeicherten Daten: 0 bis 255 oder einer Kombination von Text und Zahlen bestehen, sofern mit den Bytes Zahlen nicht gerechnet wird; zum Beispiel Namen, Adressen, Abteilungsnummern, Telefonnummern

Memo

0 bis 64.000 Bytes Beliebiger Text, der aus beliebigen Zeichen bestehen kann; zum Beispiel Anmerkungen und Beschreibungen

Zahl

1, 2, 4 oder 8 Bytes, abhängig von der Daten (aber keine Währungsangaben), mit denen auch Berechnungen gewählten Feldgröße (16 Bytes bei Replikations-ID) durchgeführt werden können; zum Beispiel Jahreszahlen, Codes wie etwa Mitarbeiternummern oder Zahlungsweisen

Datum/Zeit

Datum und Uhrzeit; zum Beispiel Bestelldatum oder Geburtstag

8 Bytes

Tabelle 2.1: Geeignete Verwendungszwecke und Speicherbelegung für die verschiedenen Feldtypen von Access

Den für Ihre Daten geeigneten Feldtyp auswählen

59

Feldtyp

Verwendungszweck

Speicherbelegung

Währung

Währungsangaben; zum Beispiel Gebühren und Preise

8 Bytes

AutoWert

Ausschließlich fortlaufende Zahlen oder Zufallszahlen; zum Beispiel Rechnungs- oder Projektnummern

4 Bytes (16 Bytes bei ReplikationsID)

Ja/Nein

Felder, die nur einen von zwei Wer- 1 Bit ten annehmen können (ja/nein, wahr/falsch); zum Beispiel eine Angabe, ob eine Rechnung schon bezahlt ist oder nicht, oder eine Angabe, ob eine Stelle unbefristet ist

OLE-Objekt

Objekte wie etwa Word-Dokumente 0 Bytes bis zu einem Gigabyte, oder Excel-Tabellen; zum Beispiel abhängig von den tatsächlich im Feld Mitarbeiterberichte oder Budgetügespeicherten Daten bersichten

Hyperlink

Text oder eine Kombination von Text und Zahlen, die als HyperlinkAdresse verwendet wird; zum Beispiel Webseiten oder Netzwerkdateien

0 bis 2048 Bytes für jeden der drei Teile, aus denen eine Adresse besteht (insgesamt bis zu 64.000 Zeichen)

Tabelle 2.1: Geeignete Verwendungszwecke und Speicherbelegung für die verschiedenen Feldtypen von Access (Forts.)

Der Felddatentyp Hyperlink enthält ein Hyperlink-Objekt, das aus drei Teilen besteht. Der erste Teil wird Anzeigetext genannt und ist der Text, der im Feld selbst erscheint. Der zweite Teil ist der aktuelle Dateipfad (UNC) oder die aktuelle Seite (URL), auf die dieses Feld verweist. Der dritte Teil enthält die Unteradresse, d.h. eine Adresse innerhalb der Datei oder der Seite. Der schwierigste Teil beim Auswählen eines Feldtyps besteht darin, herauszufinden, welcher Typ in welcher Situation der beste ist. Im Folgenden wird deshalb ausführlich beschrieben, welche Eigenschaften jeder einzelne Feldtyp hat und wie er am sinnvollsten zu verwenden ist. Das wird Sie bei dieser schwierigen Aufgabe unterstützen.

2.3.1

Textfelder: Der gebräuchlichste Felddatentyp

Die meisten Felder sind Textfelder. Viele Entwickler begreifen nicht, dass es am besten ist, auch Zahlen in Textfeldern zu speichern, sofern sie nicht für irgendwelche

60

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

Berechnungen benötigt werden. Beispiele sind Telefonnummern, Teilenummern oder Postleitzahlen. Textfelder sind zwar standardmäßig nur 50 Zeichen lang, sie können aber bei Bedarf bis zu 255 Zeichen aufnehmen. Access belegt Plattenspeicherplatz dynamisch, was bedeutet, dass für jedes Feld nur soviel Platz verwendet wird, wie dies der Anzahl der tatsächlich im Feld gespeicherten Zeichen entspricht. Ein sehr groß vereinbartes Feld belegt also nicht zwangsläufig auch sehr viel Speicherplatz. Dennoch können Sie die Verarbeitungsgeschwindigkeit erhöhen, wenn Sie die Feldgröße möglichst klein angeben. Die maximale Anzahl von Zeichen, die Sie in einem Textfeld speichern können, kann mit Hilfe der Eigenschaft Feldgröße festgelegt werden.

2.3.2

Memofelder: Für die langen Notizen und Kommentare

Memofelder können bis zu 64 Kilobyte Text aufnehmen (also etwa 64.000 Zeichen). Dies entspricht annähernd 16 eng bedruckten Seiten. Memofelder eignen sich hervorragend für jede Art von Dokumentation oder für Anmerkungen, die Sie zusammen mit den eigentlichen Tabellendaten speichern wollen. Bedenken Sie aber, dass Memofelder nicht als Sortierkriterien benutzt werden können.

2.3.3

Zahlenfelder: Wenn Sie rechnen müssen

Zahlenfelder verwendet man für Daten, mit denen irgendwelche Berechnungen durchgeführt werden sollen. Wenn jedoch Geldbeträge in Berechnungen eingehen und das Ergebnis dieser Berechnungen besonders genau sein soll, sollten Sie eher Währungs- als Zahlenfelder benutzen. Man kann ein Zahlenfeld auf sechs verschiedene Arten vereinbaren, weil es nämlich bei Access 2000 sechs unterschiedliche Zahlendarstellungen gibt: Der Datentyp BYTE speichert ganze Zahlen zwischen 0 und 255, der Datentyp INTEGER kann eine ganze Zahl zwischen -32.768 und 32.767 aufnehmen und der Datentyp LONG INTEGER erlaubt das Speichern einer ganzen Zahl zwischen -2.147.483.648 und 2.147.483.647. Alle drei Datentypen gestatten sehr schnelle Berechnungen, wobei jeder Typ eine zunehmende Menge an Speicherplatz benötigt. In zwei weiteren Datentypen, SINGLE und DOUBLE, werden Zahlen im Fließkommaformat gespeichert, was die Rechengeschwindigkeit deutlich herabsetzt. SINGLE erlaubt eine Genauigkeit von sieben Stellen, während bei DOUBLE sogar vierzehn Stellen möglich sind. Der siebte Datentyp, REPLIKATIONS-ID, unterstützt einen eindeutigen Bezeichner, der für die Synchronisierung von Daten erforderlich ist.

2.3.4

Datum/Uhrzeit-Felder: Verfolgen, wann Ereignisse eintreten

In Datum/Uhrzeit-Feldern werden Kalenderdaten und Uhrzeiten gespeichert. Mit diesen Daten lassen sich dann typische Berechnungen durchführen, wie etwa die Ermittlung des Zeitraums zwischen zwei Uhrzeiten oder zwischen zwei Kalenderdaten. Beim Sortieren wird die für Kalenderdaten und Uhrzeiten gebräuchliche Rei-

Den für Ihre Daten geeigneten Feldtyp auswählen

61

henfolge berücksichtigt. Access speichert Datum und Uhrzeit intern als acht Byte lange Fließkommazahl, die Uhrzeit wird als Bruchteil eines ganzen Tages dargestellt. Jede Änderung des Datums oder der Uhrzeit, die Sie über die Systemsteuerung von Windows vornehmen, wirkt sich unmittelbar auf alle Ihre Datum/Uhrzeit-Felder aus. Dies gilt auch für Datumsformate: ändern Sie zum Beispiel das Format DATUM, KURZ in den Ländereinstellungen, so verändern Sie damit unmittelbar auch alle Datumsformate in Ihren Formularen, Berichten und Datenblättern.

2.3.5

Währungsfelder: Geldbeträge speichern

Ein Währungsfeld ist eine besondere Form eines Zahlenfeldes, in dem ausschließlich Geldbeträge gespeichert werden. Ein Währungsfeld kann vor dem Komma bis zu fünfzehn Stellen aufnehmen, nach dem Komma wird hingegen nur mit vier Stellen gerechnet, um Rundungsfehler zu vermeiden. Zu bemerken ist, dass Berechnungen mit solchen Währungsfeldern recht langsam ablaufen, was an der hohen Stellenzahl und Genauigkeit dieses Feldtyps liegt. Jede Änderung, die Sie in der Windows-Systemsteuerung am Format von Währungsdaten vornehmen, wird unmittelbar in Ihre Daten übernommen. Natürlich wandelt Access nicht von selbst die Währungsbeträge gemäß dem aktuellen Währungskurs um, wenn Sie etwa das Währungssymbol von Dollar in DM umsetzen. Aber wie bei den Datumsformaten wird auch ein in den Ländereinstellungen der Windows-Systemsteuerung verändertes Währungssymbol unmittelbar in allen Ihren Formularen, Berichten und Datenblättern angepasst.

2.3.6

AutoWert-Felder: Für eindeutige Datensatzbezeichner

Das AutoWert-Feld von Access 2000 entspricht dem Zähler-Feld von Access 2.0. Die Einträge in AutoWert-Feldern werden immer dann automatisch erzeugt, wenn ein Datensatz zur Datenbank hinzugefügt wird. In Access 2.0 mussten die Werte in Zähler-Feldern fortlaufend sein, während die AutoWert-Felder in Access 2000 sowohl fortlaufende als auch Zufallszahlen erlauben. Zufallszahlen sind immer dann nützlich, wenn verschiedene Benutzer unabhängig voneinander zusätzliche Datensätze in die Datenbank eingeben, denn es ist sehr unwahrscheinlich, dass Access zwei verschiedenen Datensätzen die gleiche zufällig erzeugte Zahl als Datensatzbezeichner zuweist. Ein Sonderfall eines AutoWert-Feldes ist die Replikations-ID: Hier, bei der Replikation von Datenbanken, dient die Zufallszahl zur eindeutigen Kennzeichnung, um damit die Replikate zu synchronisieren. Einige wichtige Punkte über fortlaufende AutoWert-Felder sollten Sie sich einprägen: Wenn ein Benutzer einen Datensatz aus einer Tabelle löscht, ist dessen eindeutige Datensatznummer für immer verloren. Ebenso verschwindet die eindeutige

62

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

Nummer eines Datensatzes, der von einem Benutzer hinzugefügt, danach aber wieder durch »Rückgängig machen« entfernt wird. Sie können sich jedoch Ihre eigenen Zählerwerte erzeugen, falls Sie in Ihrer Anwendung dieses Verhalten von Access nicht akzeptieren wollen. Dieses Thema wird in Kapitel 17 beschrieben.

2.3.7

Ja/Nein-Felder: Wenn eine von zwei Antworten korrekt ist

In Ja/Nein-Feldern können Sie ein logisches Wahr oder Falsch bzw. ein Ja oder Nein speichern. Tatsächlich enthält ein solches Feld den Wert -1 für Ja und 0 (Null) für Nein (oder keinen Wert für keine Angabe). Das Ausgabeformat für ein solches Ja/ Nein-Feld bestimmt, was der Benutzer wirklich zu sehen bekommt (normalerweise Ja/Nein, Wahr/Falsch, Ein/Aus oder eine dritte Angabe – keinen Wert – wenn Sie die Eigenschaft DreifacherStatus aktiviert haben). Ja/Nein-Felder eignen sich für solche Daten, die nur genau zwei Werte annehmen können. Sie belegen im Speicher nur ein einziges Bit und schränken den Benutzer auf nur zwei mögliche Eingabewerte ein.

2.3.8

OLE-Objektfelder: Wo Sie nahezu alles speichern können

In OLE-Objektfeldern kann man beliebige Daten speichern, die von irgendeiner anderen OLE-Anwendung unter Windows übermittelt werden, einschließlich Datenblättern aus Tabellenkalkulationen, Textdokumenten, Audio- und VideoDateien. Es gibt viele betriebliche Anwendungen für OLE-Objektfelder, wie zum Beispiel das Speichern von Lebensläufen, Mitarbeiterbeurteilungen, Budgets oder Video-Clips. Dennoch ist es oftmals effizienter, ein Hyperlink-Feld zu verwenden, um lediglich eine Adresse zu speichern, als das ganze Objekt selbst in einem OLEObjektfeld abzulegen.

2.3.9

Hyperlink-Felder: Ihre Verknüpfung zum Internet

In Hyperlink-Feldern werden so genannte URLs gespeichert (URL – Uniform Resource Locator). Hierbei handelt es sich um Verknüpfungen auf Seiten, die irgendwo im WWW (World Wide Web) bzw. im Internet gespeichert sind. Auch das Speichern von UNC-Pfaden (UNC – Universal Naming Convention), also von Verknüpfungen mit anderswo gespeicherten Dateiverzeichnissen, ist möglich. Ein Hyperlink-Feld besteht genaugenommen aus drei Teilen: erstens aus dem, was der Benutzer sieht, zweitens aus dem URL oder der UNC und drittens aus einer Unteradresse, wie zum Beispiel einem Bereichsnamen oder einem WWW-Lesezeichen. Sobald ein Eintrag in ein Hyperlink-Feld aufgenommen wurde, dient dieser Eintrag als direkte Verknüpfung mit der Seite oder der Datei, die durch diese Adresse gekennzeichnet wird. Hyperlink-Felder werden im Abschnitt »Access-Tabellen und das Internet« am Ende dieses Kapitels ausführlich beschrieben.

Feldeigenschaften

2.4

63

Feldeigenschaften

Nachdem Sie Felder zu Ihrer Tabelle hinzugefügt haben, müssen Sie deren Eigenschaften festlegen. Mit Hilfe der Feldeigenschaften können Sie steuern, wie die Daten später gespeichert werden, wie sie zu verwenden sind und welche Daten in diese Felder eingegeben werden können. Die verfügbaren Feldeigenschaften hängen von dem zuvor ausgewählten Felddatentyp ab. Die umfassendsten Eigenschaften bietet der Feldtyp Text (siehe Abbildung 2.5). In den folgenden Abschnitten wird jede einzelne Feldeigenschaft einzeln beschrieben.

Abbildung 2.5: Feldeigenschaften für ein Textfeld

2.4.1

Feldgröße: Die Feldeingabe begrenzen

Die erste Eigenschaft eines Feldes ist die Feldgröße, die jedoch nur bei Text- und Zahlenfeldern angegeben werden kann. Wie bereits erwähnt, sollte die Größe eines Feldes auf den kleinstmöglichen Wert festgelegt werden, um Speicherplatz zu sparen und besonders bei Zahlenfeldern die spätere Verarbeitungsgeschwindigkeit zu erhöhen. Erstellen Sie eine Tabelle mit folgenden Feldern und Feldtypen: CompanyID (Firmennummer): AutoWert CompanyName (Firmenname): Text State (Land): Text

64

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

PhoneNumber (Telefon): Text ContactDate (Kontaktdatum): Datum/Uhrzeit CreditLimit (Kreditlimit): Währung 1. Um die Feldgröße des Feldes STATE auf zwei Zeichen zu begrenzen, klicken Sie irgendwo auf dieses Feld und geben danach die Ziffer 2 in die Zeile FELDGRÖSSE ein. 2. Wechseln Sie zur Datenblatt-Ansicht. Sie werden nun aufgefordert, die Tabelle zu speichern. Geben Sie ihr den Namen tblCustomers. Da Sie bisher keinen Primärschlüssel vergeben haben, werden Sie nun dazu aufgefordert. Sobald Sie Daten in das Feld State eingeben, werden Sie feststellen, dass hier höchstens zwei Zeichen möglich sind. Dieses Beispiel ist wie alle noch folgenden Beispiele auch auf der beiliegenden CDROM enthalten. Sie finden dieses Beispiel unter dem Namen Chap2TryIt.MDB. Überprüfen Sie anhand dieser Angaben, ob Sie die Feldeigenschaften richtig angegeben haben.

2.4.2

Format: Bestimmen, wie Daten angezeigt werden

Die zweite Feldeigenschaft ist das FORMAT, das für alle Feldtypen außer für OLEObjektfelder anzugeben ist. Mit Hilfe der Feldeigenschaft FORMAT legen Sie fest, wie Ihre Daten angezeigt werden. Access bietet Ihnen die Möglichkeit, aus mehreren vorhandenen Formaten auszuwählen oder Ihre eigenen Formate zu erstellen. Die verfügbaren Formate hängen jeweils vom Felddatentyp ab. So können Sie in Access zum Beispiel aus einer Vielzahl unterschiedlicher Formate für Datum und Uhrzeit auswählen (zum Beispiel: Datum, kurz (21.10.99), Datum, mittel (21. Okt. 99), Datum, lang (Donnerstag, 21. Oktober 1999), Zeit, kurz (18:30), Zeit, lang (18:30:54). Dabei hängen die genauen Formate und Sprachen auch noch von der in der Windows-Systemsteuerung vorgenommenen Ländereinstellung ab. Bei Währungsfeldern sind u.a. diese Formate möglich: Standardzahl (4.311,52), Festkommazahl (4311,52) und Währung (4.311,52 DM). Setzen Sie das Format des Feldes ContactDate auf Datum, mittel. Wechseln Sie danach zur Datenblattansicht und geben Sie einige Daten in unterschiedlichen Formaten ein, zum Beispiel 07/08/99 und 13. September 1999. Beachten Sie, dass es keine Rolle spielt, in welchem Format Sie die Daten eingeben: sobald die Daten vollständig eingegeben sind, werden sie im Format Datum, mittel, also in der Form 13. Sep. 99, angezeigt.

Feldeigenschaften

2.4.3

65

Eingabeformat: Bestimmen, wie Daten in ein Feld übernommen werden

Eine andere wichtige Feldeigenschaft ist das Eingabeformat, das für die Feldtypen Text, Zahl, Datum/Uhrzeit und Währung verfügbar ist. Die Angabe Format gibt an, wie Daten angezeigt werden, während Eingabeformat bestimmt, welche Daten eingegeben werden dürfen. Mit Hilfe des Eingabeformats können Sie auch zeichenweise überprüfen, welche Art von Daten eingegeben wird (Buchstaben, Ziffern, Sonderzeichen) und ob ein bestimmtes Zeichen erforderlich ist. Der Eingabeformat-Assistent (siehe Abbildung 2.6) hilft Ihnen beim Erstellen üblicherweise benutzter Eingabeformate für Text- und Zahlenfelder. Den Eingabeformat-Assistenten rufen Sie auf, indem Sie im Eingabeformatfeld die rechte Schaltfläche anklicken. Der Eingabeformat-Assistent ist nur dann verfügbar, wenn Sie beim Einrichten von Access die Komponente ERWEITERTE ASSISTENTEN ausgewählt haben.

Abbildung 2.6: Der Eingabeformat-Assistent hilft Ihnen beim Festlegen eines Eingabeformats

Das Eingabeformat 000-00-0000;;_ (das in die Form 000\-00\-0000;;_ umgewandelt wird, sobald Sie das Eigenschaftsfeld mit der Tabulatortaste verlassen) sorgt beispielsweise dafür, dass eine gültige amerikanische Sozialversicherungsnummer eingegeben wird. Alle Zeichen vor dem ersten Semikolon bezeichnen das aktuelle Eingabeformat. Die Nullen zeigen an, dass hier nur Ziffern von 0 bis 9 eingegeben werden dürfen. Die Bindestriche sind Füllzeichen und erscheinen später zur optischen Gliederung im Eingabeformat. Zwischen den beiden Semikolons können Sie noch ein Zeichen eingeben, das festlegt, ob die im Eingabeformat angezeigten Füllzeichen (hier die Bindestriche) ebenfalls im Feld gespeichert werden sollen: 0 bedeu-

66

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

tet, dass diese Füllzeichen gespeichert werden, 1 oder Leer unterdrückt die Speicherung. Das letzte Zeichen (nach dem zweiten Semikolon, in diesem Fall ein Unterstrich) gibt an, welches Zeichen dem Benutzer die Stelle im Eingabeformat anzeigen soll, an der er das nächste Zeichen einzugeben hat. Ein etwas ausführlicheres Beispiel: Im Eingabeformat \(999”) ”000\-0000;;_ bewirkt der erste Backslash (\), dass das danach folgende Zeichen (Klammer auf) später genau so angezeigt wird. Die Ziffern 999 erlauben wahlweise die Eingabe von Ziffern oder Leerzeichen, die beiden folgenden Zeichen zwischen den beiden Anführungszeichen (Klammer zu und Leerzeichen) sollen wiederum genauso in das Eingabeformat übernommen werden. 000 verlangt die Eingabe von drei Ziffern zwischen 0 und 9. Der Bindestrich nach dem nächsten umgekehrten Schrägstrich wird abermals genau so in das Eingabeformat übernommen. Danach verlangt 0000 die Eingabe von vier Ziffern zwischen 0 und 9. Zwischen den beiden folgenden Semikolons befindet sich kein weiteres Zeichen, was bedeutet, dass die weiter vorne angegebenen Anführungszeichen nicht in das Eingabeformat übernommen werden. Nach dem zweiten Semikolon folgt noch ein Unterstrich, der im Eingabeformat festlegt, dass hier der Benutzer das nächste Zeichen einzugeben hat. Benutzen Sie den Eingabeformat-Assistenten, um ein Eingabeformat für das Feld PhoneNumber hinzuzufügen, das Sie als Textfeld eingerichtet haben sollten.

1. Klicken Sie zunächst auf das Feld PhoneNumber und dann auf EINGABEFORMAT. 2. Klicken Sie auf die Schaltfläche mit den drei Punkten. 3. Wählen Sie TELEFONNUMMER aus der Liste der vorhandenen Eingabeformate, und legen Sie fest, dass die Daten ohne Symbole gespeichert werden sollen. 4. Wechseln Sie zur Datenblattansicht und geben Sie nun eine Telefonnummer ein. Beachten Sie, wie die Einfügemarke die Trennzeichen überspringt. Versuchen Sie, das Feld für die Vorwahl freizulassen (dies sollte möglich sein). 5. Versuchen Sie nun, irgendwo in dieses Feld einen Buchstaben einzugeben. Dies sollte nicht möglich sein. 6. Versuchen Sie abschließend, innerhalb der Telefonnummer ein Leerzeichen statt einer Ziffer einzugeben. Access sollte auch dies verhindern. Wenn Sie ein Eingabefeld verwenden, befindet sich der Benutzer stets im Überschreibmodus. Dieses Verhalten ist in Access standardmäßig vorgesehen und lässt sich nicht verändern.

Feldeigenschaften

2.4.4

67

Beschriftung: Eine große Zeitersparnis

Die nächste verfügbare Feldeigenschaft ist die Beschriftung. Der hier von Ihnen eingegebene Text wird später als Spaltenüberschrift in der Datenblattansicht, in Formularen und in Berichten angezeigt. Er erscheint außerdem als Beschriftung für gebundene Steuerelemente, wenn Sie sie in Formularen und Berichten verwenden. Die Eigenschaft Beschriftung ist besonders wichtig, wenn Ihre Feldnamen keine Leerzeichen enthalten und deshalb für Benutzer schwer verständlich sein können. Der Benutzer sieht später nur die hier angegebenen Beschriftungen und nicht die ursprünglichen Feldnamen. Der Begriff »gebundenes Steuerelement« bezieht sich auf ein Steuerelement, das mit dem Feld einer Tabelle oder einer Abfrage verbunden ist. Der Begriff der »gebundenen Bezeichnung« wird als Bezug auf ein Bezeichnungsfeld verwendet, das zu einem gebundenen Steuerelement gehört.

Es ist wichtig, die Eigenschaft Beschriftung für Felder festzulegen, bevor Sie irgendwelche Formulare oder Berichte definieren, die darauf Bezug nehmen. Beim Generieren eines Formulars oder Berichts sucht Access zunächst nach der aktuell vorhandenen Beschriftung. Wird die Beschriftung erst zu einem späteren Zeitpunkt hinzugefügt oder geändert, werden die Überschriften für dieses Feld in bereits vorhandenen Formularen und Berichten nicht angepasst.

2.4.5

Standardwert: Zeit für die Dateneingabe einsparen

Eine weitere wichtige Feldeigenschaft ist der Standardwert. Dieser definiert den Wert, den Access in ein Feld einträgt, wenn der Benutzer neue Datensätze zu einer Tabelle hinzufügt. Standardwerte, bei denen es sich sowohl um Texte als auch um Ausdrücke handeln kann, können der Person, welche die Daten in die Datenbank eingibt, viel Zeit sparen. Die Richtigkeit der eingegebenen Daten wird jedoch nicht überprüft. Standardwerte werden automatisch in alle Abfragen und Formulare übertragen, in denen dieses Feld enthalten ist. Im Gegensatz zur Feldeigenschaft Beschriftung geschieht dies unabhängig davon, ob eine Abfrage oder ein Formular vor oder nach der Eingabe eines Standardwerts in ein Feld erstellt wurde.

68

Kapitel 2: Was jeder Entwickler über Tabellen wissen sollte

Tragen Sie die folgenden Standardwerte für die Felder State, ContactDate und CreditLimit ein: State: CA ContactDate: =Date() CreditLimit: 1000 Wechseln Sie nun in die Datenblattansicht und fügen Sie einen neuen Datensatz hinzu. Beachten Sie, dass die obigen Standardwerte für die Felder State, ContactDate und CreditLimit erscheinen. Diese Standardwerte können Sie jedoch bei Bedarf mit anderen Werten überschreiben.

2.4.6

Gültigkeitsregel: Steuern, was in ein Feld eingegeben wird

Die Feldeigenschaft Standardwert schlägt dem Benutzer einen Wert vor, die Feldeigenschaft Gültigkeitsregel schränkt dagegen die Werte ein, die ein Benutzer in ein Feld eingeben kann. Die Datenbank-Engine achtet danach streng darauf, dass solche Gültigkeitsregeln nicht verletzt werden. Wie die Feldeigenschaft Standardwert kann auch die Feldeigenschaft Gültigkeitsregel Text oder einen gültigen Access-Ausdruck enthalten. Benutzerdefinierte Funktionen lassen sich hier jedoch ebensowenig verwenden wie Formulare, Abfragen oder Tabellen. Wenn Sie die Feldeigenschaft Gültigkeitsregel setzen, ohne eine Gültigkeitsmeldung festzulegen, zeigt Access automatisch eine Standardfehlermeldung an, wann immer die Gültigkeitsregel verletzt wird. Um eine benutzerdefinierte Fehlermeldung anzuzeigen, müssen Sie Ihren Meldungstext in die Feldeigenschaft Gültigkeitsmeldung eintragen.

Fügen Sie die folgenden Gültigkeitsregeln zu den Feldern Ihrer Tabelle hinzu (Access setzt die Kürzel der amerikanischen Bundesstaaten in Anführungszeichen, sobald Sie das Eigenschaftsfeld mit dem Tabulator verlassen): State: In (CA, AZ, NY, MA, UT) ContactDate: . In dem Beispiel in Abbildung 5.7 wurden mehrere Felder aus der Abfrage qryClients ausgewählt.

Abbildung 5.6: Eine Liste mit Tabellen und Abfragen, die zur Benutzung im FormularAssistenten zur Verfügung steht

Abbildung 5.7: Ausgewählte Felder aus der Abfrage qryClients

Ein neues Formular erstellen

149

Nachdem Sie die gewünschten Felder ausgewählt haben, klicken Sie auf WEITER. Der zweite Schritt des Formular-Assistenten erlaubt Ihnen, das gewünschte Layout für Ihr Formular anzugeben. Sie können zwischen EINSPALTIG, TABELLARISCH, DATENBLATT oder IN BLÖCKEN wählen, doch die gebräuchlichste Wahl ist EINSPALTIG. Klicken Sie auf WEITER, nachdem Sie ein Formularlayout ausgewählt haben. Im dritten Schritt des Formular-Assistenten können Sie eines von mehreren vordefinierten Formaten für Ihr Formular auswählen (siehe Abbildung 5.8). Zwar können alle Eigenschaften, die durch den Formular-Assistenten festgelegt worden sind, nach dem Erstellen des Formulars in der Entwurfsansicht geändert werden, aber um Zeit zu sparen, ist es am besten, das richtige Format jetzt auszuwählen. Klicken Sie auf WEITER, nachdem Sie sich für ein Format entschieden haben.

Abbildung 5.8: Ein Formularformat auswählen

Im letzten Schritt des Formular-Assistenten geben Sie einen Titel für Ihr Formular an. (Wenn Sie den Standardwert stehen lassen, bekommt das Formular denselben Namen wie die zu Grunde liegende Tabelle oder Abfrage, was zu Verwirrung führen kann.) Unglücklicherweise wird der Titel des Formulars gleichzeitig auch sein Name. Geben Sie deshalb den Text ein, den Sie als Namen des Formulars verwenden wollen. Wenn Sie der standardmäßigen Namensvergabe folgen wollen, sollten Sie den Namen des Formulars mit der Bezeichnung »frm« beginnen. Vielleicht haben Sie Bedenken hinsichtlich der Änderung des Titels in der Entwurfsansicht des Formulars. In diesem Schritt des Formular-Assistenten können Sie entscheiden, ob Sie das Ergebnis Ihrer Arbeit sehen oder das Formular in der Entwurfsansicht öffnen wollen. Es ist meistens am besten, das Ergebnis zu betrachten und den Formularentwurf zu bearbeiten, nachdem Sie einen Blick auf die Arbeit des Formular-Assistenten geworfen haben.

150

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Ein anderer Weg, um den Formular-Assistenten zu starten, besteht darin, in der Objektliste auf das TABELLEN- oder ABFRAGEN-Symbol und anschließend auf die Tabelle oder Abfrage zu klicken, die dem Formular zu Grunde liegen soll. Wählen Sie im aufklappbaren Listenfeld NEUES OBJEKT die Option FORMULAR, um das Dialogfeld NEUES FORMULAR zu öffnen. Wählen Sie dort FORMULAR-ASSISTENT. In diesem Fall brauchen Sie nicht das Listenfeld TABELLEN/ABFRAGEN zu benutzen, um eine Tabelle oder Abfrage auszuwählen. Die Tabelle oder Abfrage, die Sie vor Aufruf des Formular-Assistenten ausgewählt hatten, wird automatisch verwendet.

5.3.2

Ein Formular in der Entwurfsansicht erstellen

Auch wenn die Formular-Assistenten leistungsfähig und nützlich sind, werden Sie es dennoch in vielen Fällen bevorzugen, ein Formular von Grund auf zu entwerfen, insbesondere wenn Sie ein Formular erstellen, das nicht mit Daten verknüpft ist. Um ein Formular ohne den Assistenten zu erstellen, klicken Sie in der Objektliste auf FORMULAR. Doppelklicken Sie das Symbol ERSTELLT EIN FORMULAR IN DER ENTWURFSANSICHT oder klicken Sie die Schaltfläche NEU, um das Dialogfeld NEUES FORMULAR zu öffnen, und wählen Sie dort ENTWURFSANSICHT (die Standardauswahl). Falls Sie NEU geklickt haben, um das Dialogfeld NEUES FORMULAR zu öffnen, und Ihr Formular an Daten gebunden ist, wählen Sie aus dem Listenfeld im Dialogfeld NEUES FORMULAR die zu Grunde liegende Tabelle oder Abfrage aus. Klicken Sie auf OK, um in das Formularentwurfsfenster zu gelangen (siehe Abbildung 5.9).

Abbildung 5.9: Benutzen Sie das Formularentwurfsfenster, um ein Formular zu erstellen und anzupassen

Mit dem Formularentwurfsfenster umgehen

5.4

151

Mit dem Formularentwurfsfenster umgehen

Das Formularentwurfsfenster wird benutzt, um ein Formular zu erstellen und anzupassen. Mit diesem Fenster können Sie Objekte zu einem Formular hinzufügen und sie über das Eigenschaftenfenster anpassen. Microsoft hat viele Formular- und Steuerelementeigenschaften definiert. Wenn Sie diese Eigenschaften beherrschen, können Sie das Erscheinungsbild und die Funktionalität Ihrer Formulare maßschneidern.

5.4.1

Die Werkzeuge des Formularentwurfsfensters

Auch der beste Entwickler braucht die richtigen Werkzeuge für seine Arbeit. Glücklicherweise gibt Microsoft Ihnen Werkzeuge an die Hand, mit denen Sie ebenso ansprechende wie zweckmäßige Formulare erstellen können. Das Formularentwurfsfenster beinhaltet eine Symbolleiste, eine Toolbox und das Formular, das Sie gerade entwerfen. Weitere Werkzeuge sind verfügbar, um Ihnen bei der Entwurfsarbeit zu helfen, einschließlich der Feldliste und des Eigenschaftenfensters. Standardmäßig erscheinen zwei Symbolleisten, wenn Sie sich in der Entwurfsansicht eines Formulars befinden: die Symbolleiste FORMULARENTWURF und FORMATIERUNG. Die Symbolleiste FORMULARENTWURF besitzt Schaltflächen zum Sichern, Drucken, Kopieren, Ausschneiden, Einfügen und Durchführen anderer Standardaufgaben innerhalb des Formulars. Außerdem beinhaltet sie Schaltflächen, die es Ihnen erlauben, die verschiedenen Entwurfsfenster (wie z.B. die Toolbox) ein- und auszublenden. Die Symbolleiste FORMATIERUNG besitzt Schaltflächen für die grafische Bearbeitung der Eigenschaften und Objekte des Formulars. Sie können die Schrift, die Schriftgröße und die Farbe ausgewählter Objekte auf dem Formular verändern. Die Symbolleiste FORMATIERUNG bietet Ihnen außerdem die Möglichkeit, Text mit den Formaten Fett, Unterstrichen und Kursiv zu versehen, die Ausrichtung zu ändern und ausgewählten Objekten Spezialeffekte hinzuzufügen. Die benötigten Werkzeuge ein- und ausblenden Es stehen Ihnen mehrere Felder zur Verfügung, die Ihnen beim Formularentwurf helfen, wenn Sie sich in der Entwurfsansicht befinden. In Abhängigkeit davon, ob Sie einen hochauflösenden Monitor besitzen, finden Sie es möglicherweise lästig, wenn alle Fenster gleichzeitig geöffnet sind. Tatsächlich macht das Formular bei einer niedrigen Bildschirmauflösung und vielen geöffneten Fenstern eher den Eindruck, als wäre es unter all den Fenstern begraben. Dies ist der Grund, weshalb Microsoft dafür gesorgt hat, dass Sie jedes Fensters ein- und ausblenden können. Die Symbolleiste FORMULARENTWURF enthält Schaltflächen für die Feldliste, die Toolbox und das Eigenschaftenfenster, die eben diesem Zweck dienen. Das erste Anklicken öffnet das jeweilige Fenster, das zweite schließt es. Abbildung 5.10 zeigt ein Formular, bei dem die Feldliste, die Toolbox und das Eigenschaftenfenster geöffnet sind. Obwohl die Größe jedes Fensters nach Belieben einstellbar ist (und die Toolbox an der Ecke eines Fenster festgemacht werden kann), ist

152

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

die Entwurfsumgebung auf diesem niedrig auflösenden Bildschirm mit all diesen offenen Fenstern völlig überfrachtet. Einer der Tricks beim Arbeiten mit Access besteht darin zu wissen, wann es sinnvoll ist, jede Werkzeugsammlung verfügbar zu haben. Das Ziel besteht darin, möglichst oft das richtige Fenster zur richtigen Zeit offen zu haben. Die Feldliste, die Toolbox und das Eigenschaftenfenster können durch Betätigen der Umschaltflächen in der Symbolleiste, über die Schaltfläche SCHLIESSEN jedes Fensters oder über das Menü ANSICHT ausgeblendet werden.

Abbildung 5.10: Formularentwurf mit angezeigten Entwurfsfenstern

5.4.2

Dem Formular Felder hinzufügen

Felder können einem Formular ganz einfach mit Hilfe der Feldliste hinzugefügt werden, welche alle Felder enthält, die zur Datenquelle des Formulars gehören. So ist z.B. die Datenquelle des Formulars in Abbildung 5.10 die Abfrage qryClients. In der Feldliste werden die Felder aufgeführt, die Bestandteil der Abfrage sind. Zwei Schritte sind nötig, um ein Feld zu einem Formular hinzuzufügen: 1. Stellen Sie sicher, dass die Feldliste sichtbar ist. Klicken Sie andernfalls auf die Schaltfläche FELDLISTE in der Symbolleiste. 2. Finden Sie das Feld, das Sie zu dem Formular hinzufügen wollen, klicken Sie es an und ziehen Sie es von der Feldliste an die Stelle im Formular, wo es erscheinen soll. Der gewählte Platz wird die obere linke Ecke des Textfeldes und die zugehörige Bezeichnung erscheint links davon.

Mit dem Formularentwurfsfenster umgehen

153

Ein Steuerelement ist ein Objekt, das Sie zu einem Formular oder einem Bericht hinzufügen können. Steuerelemente sind u.a. Textfelder, Kombinationsfelder, Listenfelder und Auswahlfelder. Um mehrere Felder gleichzeitig zu einem Formular hinzuzufügen, können Sie mehrere Felder aus der Feldliste auswählen. Drücken Sie die (Strg)-Taste, um Felder auszuwählen, die nicht aufeinander folgen, oder die (ª)-Taste zur Auswahl von aufeinander folgenden Feldern. Halten Sie beispielsweise die (Strg)-Taste gedrückt und klicken Sie auf drei nicht aufeinander folgende Felder. Jedes Feld wird markiert. Klicken Sie nun auf ein Feld, halten Sie die (ª)-Taste gedrückt und klicken Sie auf ein anderes Feld. Dadurch werden alle Felder dazwischen ausgewählt. Wenn Sie alle Felder auswählen wollen, doppelklicken Sie auf die Kopfzeile der Feldliste. Klicken Sie dann auf irgendeines der markierten Felder und ziehen Sie es auf das Formular, woraufhin alle markierten Felder auf einmal zum Formular hinzugefügt werden.

5.4.3

Formularobjekte auswählen, verschieben, ausrichten und in der Größe verändern

Sie sollten einige wichtige Kniffe kennenlernen, wenn Sie Formularobjekte auswählen, verschieben, ausrichten oder ihre Größe festlegen. Diese Kniffe werden Ihnen Stunden von Frustration und verschwendeter Zeit ersparen. Formularobjekte auswählen Der einfachste Weg, ein einzelnes Objekt auszuwählen, besteht darin, es anzuklicken. Nachdem das Objekt ausgewählt ist, können Sie es verschieben und zum Beispiel seine Größe oder seine Eigenschaften bearbeiten. Das Auswählen mehrerer Objekte ist etwas schwieriger und kann auf verschiedene Arten erfolgen. Welche Methode am sinnvollsten ist, ergibt sich aus der jeweiligen Situation. Um mehrere Objekte auszuwählen, können Sie die (ª)-Taste drücken und jedes auszuwählende Objekt anklicken. Jedes ausgewählte Objekt wird von Anfassern umgeben, die anzeigen, dass es ausgewählt ist. Abbildung 5.11 zeigt ein Formular mit vier ausgewählten Objekten. Es ist wichtig zu wissen, welche Objekte tatsächlich ausgewählt sind. In diesem Fall sind dies das Textfeld ClientID, das Text- und Bezeichnungsfeld Address sowie die Bezeichnung CompanyName, während das Bezeichnungsfeld ClientID und das Textfeld CompanyName nicht ausgewählt sind. Wenn Sie die Abbildung genau betrachten, werden Sie feststellen, dass die ausgewählten Objekte vollständig von Anfassern umgeben sind. Das Bezeichnungsfeld ClientID und das Textfeld CompanyName haben einfache Anfasser, weil sie zu ausgewählten Objekten gehören. Wenn Sie irgendeine Eigenschaft der ausgewählten Objekte ändern, werden diese beiden Felder dadurch nicht beeinträchtigt.

154

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.11: Objekte auf einem Formular auswählen

Sie können Objekte auch mit Hilfe eines Rahmens auswählen, sofern sie auf dem Formular benachbart liegen. Bewegen Sie den Mauszeiger zu einer leeren Stelle auf dem Formular (nicht über ein Objekt), klicken Sie und ziehen Sie dann den Rahmen auf. Sie können nun eine feine Linie um die Objekte sehen, die Ihr Rahmen umgibt. Wenn Sie loslassen, werden alle Objekte innerhalb des Rahmens ausgewählt, auch wenn sie nur teilweise eingekreist waren. Wenn Sie für irgendein Objekt die Auswahl aufheben wollen, halten Sie die (ª)-Taste gedrückt und klicken auf das Objekt, für das Sie die Auswahl aufheben möchten. Einer der elegantesten Wege, mehrere Objekte auszuwählen, ist der Gebrauch der waagerechten und senkrechten Lineale, die an den Rändern des Formularentwurfsfensters zu sehen sind. Klicken und ziehen Sie innerhalb des Lineals. Wenn Sie innerhalb des senkrechten Lineals klicken und die Maus bewegen, erscheinen zwei senkrechte Linien, die den Auswahlbereich anzeigen. Wenn Sie die Maustaste loslassen, werden alle Objekte innerhalb der Linien ausgewählt. Genau wie beim Auswählen von Objekten mit Hilfe eines Rahmens können Sie die Auswahl für einzelne Objekte aufheben, indem Sie die (ª)-Taste gedrückt halten und das entsprechende Objekt anklicken. Objekte verschieben Um ein einzelnes Steuerelement zusammen mit seinem Bezeichnungsfeld zu verschieben, brauchen Sie es nicht vorher auszuwählen. Bewegen Sie Ihre Maus über das Objekt, klicken Sie es an und ziehen Sie. Es erscheint ein Umriss, der die neue Position des Objekts anzeigt. Wenn das Objekt an der gewünschten Stelle ist, lassen Sie die Maustaste los. Das Bezeichnungsfeld bewegt sich zusammen mit dem zugehörigen Steuerelement. Um mehrere Objekte gleichzeitig zu verschieben, müssen Sie die zu verschiebenden Objekte erst auswählen. Benutzen Sie dazu eine der im vorigen Abschnitt beschrie-

Mit dem Formularentwurfsfenster umgehen

155

benen Methoden. Bewegen Sie Ihre Maus über irgendeines der ausgewählten Objekte, klicken und ziehen Sie. Es erscheint ein Umriss, der die neuen Positionen der Objekte anzeigt. Wenn die Objekte an der gewünschten Stelle sind, lassen Sie die Maustaste los. Eine besondere Technik ist nötig, wenn Sie ein Steuerelement unabhängig von seinem zugehörigen Bezeichnungsfeld verschieben wollen. Wenn Sie ein Steuerelement anklicken, z.B. ein Textfeld, und die Maus über die Begrenzung dieses Steuerelements bewegen, erscheint ein Symbol in Form einer Hand mit fünf aufwärts zeigenden Fingern. Wenn Sie das Objekt nun anklicken und ziehen, werden Steuerelement und zugehöriges Bezeichnungsfeld als Einheit verschoben, wobei ihre Beziehung zueinander erhalten bleibt. Wenn Sie den Mauszeiger über den größeren Anfasser in der oberen linken Ecke des Objekts bewegen, erscheint er als Hand, bei der nur der Zeigefinger aufwärts zeigt. Wenn Sie jetzt klicken und ziehen, wird das Steuerelement unabhängig von seinem Bezeichnungsfeld verschoben und die Beziehung dieser Felder zueinander ändert sich. Objekte aneinander ausrichten Access macht es einfach, Objekte auszurichten. Abbildung 5.12 zeigt einige nicht ausgerichtete Objekte. Beachten Sie, dass die gebundenen Bezeichnungsfelder dreier Objekte ausgewählt sind. Wenn Sie diese Bezeichnungsfelder ausrichten, bleiben die Steuerelemente (in diesem Fall Textfelder) an ihren ursprünglichen Positionen. Wenn Sie die Textfelder ebenfalls auswählen, werden diese versuchen, sich an den Bezeichnungsfeldern auszurichten. Weil Access keine Überlappung von Objekten zulässt, enden die Textfelder unmittelbar neben ihren Bezeichnungsfeldern. Zum linksbündigen Ausrichten beliebiger Objekte (auch solcher unterschiedlicher Art) wählen Sie die gewünschten Objekte aus und klicken AUF FORMAT|AUSRICHTEN|LINKSBÜNDIG oder Sie klicken mit der rechten Maustaste auf die Objekte und wählen AUSRICHTEN|LINKSBÜNDIG. Die ausgewählten Objekte werden daraufhin ausgerichtet (siehe Abbildung 5.13). Sie können die linke, rechte, obere oder untere Kante aller Objekte auf einem Formular ausrichten. Es ist nützlich, die Entwurfswerkzeuge, die Sie üblicherweise benutzen, zur Symbolleiste hinzuzufügen.

Verwechseln Sie nicht den Menübefehl FORMAT|AUSRICHTEN mit den Ausrichtungswerkzeugen in der Symbolleiste FORMATIERUNG. FORMAT|AUSRICHTEN richtet Objekte aneinander aus, während die Werkzeuge in der Symbolleiste den Text eines Objekts innerhalb seiner Begrenzung ausrichten.

156

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.12: Das Formular vor dem Ausrichten der Objekte

Abbildung 5.13: Das Formular nach dem Ausrichten der Objekte

Am Raster ausrichten Die Funktion AM RASTER AUSRICHTEN entscheidet darüber, ob sich Objekte an den Rasterlinien auf dem Formular ausrichten, wenn Sie sie verschieben oder ihre Größe anpassen. Sie finden diese Funktion im Menü FORMAT. Wenn Sie die Funktion deaktivieren, können Sie die Objekte ohne Rücksicht auf die Rasterlinien verschieben. Ich bevorzuge es, das Merkmal AM RASTER AUSRICHTEN ständig eingeschaltet zu lassen. Um diese Funktion gegebenenfalls vorübergehend auszuschalten, benutze ich einen besonderen Trick – lassen Sie die (Strg)-Taste gedrückt, wenn Sie Objekte anklicken und verschieben. Das Merkmal AM RASTER AUSRICHTEN wird ignoriert.

Mit dem Formularentwurfsfenster umgehen

157

Fortgeschrittene Techniken zur Änderung der Objektgröße Genauso wie es verschiedene Möglichkeiten gibt, Objekte zu verschieben, gibt es auch mehrere Wege zum Ändern der Objektgröße. Wenn ein Objekt ausgewählt ist, kann jeder Anfasser außer dem in der oberen linken Ecke des Objekts zum Ändern der Größe benutzt werden. Die Anfasser oben und unten am Objekt erlauben die Änderung der Höhe und die links und rechts die der Breite. Mit den Anfassern in der oberen rechten, unteren rechten und unteren linken Ecke können Sie Höhe und Breite gleichzeitig anpassen. Zum Ändern der Objektgröße bewegen Sie den Mauszeiger auf einen der Anfasser, klicken und ziehen. Sie können mehrere Objekte auswählen und ihre Größe auf einmal anpassen. Jedes der ausgewählten Objekte wächst oder schrumpft um den gleichen Betrag, wobei ihr Größenverhältnis erhalten bleibt. Access bietet mehrere leistungsstarke Möglichkeiten, die Größe mehrerer Objekte anzupassen. Diese finden Sie unter FORMAT|GRÖSSE :

 An Textgröße: Passt die Objektgröße an den Text im Objekt an  Am Raster: Passt die Objektgröße an die nächstgelegenen Rasterlinien an  Am Höchsten: Passt die Objektgröße an die Höhe des höchsten ausgewählten Objekts an

 Am Niedrigsten: Passt die Objektgröße an die Höhe des niedrigsten ausgewählten Objekts an

 Am Breitesten: Passt die Objektgröße an die Breite des breitesten ausgewählten Objekts an

 Am Schmalsten: Passt die Objektgröße an die Breite des schmalsten ausgewählten Objekts an Etwas verwirrend ist dabei die Option FORMAT|GRÖSSE|AN TEXTGRÖSSE. Tatsächlich wird die Größe des Textfeldes nicht perfekt an die Größe des darin enthaltenen Textes angepasst, denn in einer Umgebung mit proportionalen Schriften ist es unmöglich, ein Textfeld an den größten denkbaren Eintrag anzugleichen. Im Allgemeinen können Sie aber Textfelder mit einer vernünftigen Höhe und Breite ausstatten. Verwenden Sie die Eigenschaft FELDGRÖSSE, um den eingebbaren Text zu begrenzen. Wenn die Eingabe für den zugewiesenen Platz zu groß ist, kann der Benutzer den zusätzlichen Text per Bildlauf betrachten. Wie der nächste Tipp zeigt, ist FORMAT|GRÖSSE|AN TEXTGRÖSSE EHER FÜR BEZEICHNUNGS- ALS FÜR TEXTFELDER GEEIGNET. Um die Größe eines BEZEICHNUNGSFELDES schnell an seinen Text anzupassen, wählen Sie es aus und doppelklicken auf einen der Anfasser mit Ausnahme desjenigen in der oberen linken Ecke.

158

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Den Objektabstand steuern Access bietet Ihnen ausgezeichnete Werkzeuge, um die Objekte auf Ihrem Formular in gleichmäßigem Abstand voneinander anzuordnen. Um den vertikalen Abstand zwischen ausgewählten Objekten anzugleichen, wählen Sie FORMAT|VERTIKALER ABSTAND|ANGLEICHEN. In Abbildung 5.15 sehen Sie das Ergebnis der Anwendung dieses Befehls auf die ausgewählten Objekte aus Abbildung 5.14.

Abbildung 5.14: Das Formular vor dem Verändern des vertikalen Abstands

Der horizontale Abstand zwischen Objekten kann ausgeglichen werden durch FORABSTAND|ANGLEICHEN. Verwandte Befehle sind FORMAT|VERTIKALER ABSTAND|VERGRÖSSERN (oder VERKLEINERN) und FORMAT|HORIZONTALER ABSTAND|VERGRÖSSERN (oder VERKLEINERN). Diese Befehle erhalten die Beziehung zwischen Objekten, während deren Abstand im gleichen Verhältnis vergrößert oder verkleinert wird. MAT|HORIZONTALER

5.4.4

Die Aktivierreihenfolge der Objekte bearbeiten

Die Aktivierreihenfolge der Objekte auf einem Formular hängt von der Reihenfolge ab, in der Sie die Objekte zum Formular hinzufügen. Diese Reihenfolge ist für den Benutzer aber nicht immer sinnvoll. Es kann erforderlich sein, die Aktivierreihenfolge der Objekte auf dem Formular zu verändern. Hierzu wählen Sie ANSICHT|AKTIVIERREIHENFOLGE, um das Dialogfeld REIHENFOLGE zu öffnen (siehe Abbildung 5.16). Dieses Dialogfeld bietet zwei Möglichkeiten. Benutzen Sie die Schaltfläche AUTOMATISCH, damit Access die Aktivierreihenfolge entsprechend der Anordnung der Objekte in einem Abschnitt des Formulars festlegt. Wenn Sie jedoch die Aktivierreihenfolge der Objekte anpassen wollen, klicken Sie auf die jeweilige graue Schaltfläche links neben dem Objektnamen im Feld DEFINIERTE REIHENFOLGE und ziehen das Objekt an die gewünschte Stelle.

159

Das geeignete Steuerelement auswählen

Abbildung 5.15: Das Formular nach dem Verändern des vertikalen Abstands

Sie müssen die Aktivierreihenfolge der Objekte für jeden Abschnitt des Formulars getrennt festlegen. Hierzu wählen Sie den entsprechenden Abschnitt aus dem Dialogfeld REIHENFOLGE und die Aktivierreihenfolge der Objekte für den Abschnitt. Wenn Ihr Formular keinen Kopf oder Fuß besitzt, sind die Abschnitte FORMULARKOPF und FORMULARFUß nicht verfügbar.

Abbildung 5.16: Verwenden Sie das Dialogfeld Reihenfolge, um die Aktivierreihenfolge der Objekte in jedem Abschnitt eines Formulars auszuwählen

5.5

Das geeignete Steuerelement auswählen

Windows-Programmierung im Allgemeinen und Access-Programmierung im Besonderen sind nicht einfach auf das Schreiben von Code begrenzt. Der Erfolg Ihrer Anwendung steht und fällt mit Ihrem Geschick zur Gestaltung einer benutzerfreundlichen Schnittstelle. Access und die Windows-Programmierumgebung bieten eine

160

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Vielzahl von Steuerelementen, von denen jedes eine bestimmte Situation abdeckt. In den folgenden Abschnitten wird jedes Steuerelement vorgestellt und erläutert, wann und wie es benutzt werden sollte.

5.5.1

Bezeichnungen

Mit Bezeichnungen werden Ihren Benutzern Informationen angezeigt. Wenn Sie Steuerelemente wie Textfelder, Kombinationsfelder usw. zu Ihrem Formular hinzufügen, werden automatisch zugehörige Bezeichnungsfelder erzeugt, die nach Belieben verändert oder gelöscht werden können. Ihre standardmäßige Beschriftung hängt von der Beschriftungseigenschaft des Feldes ab, das dem entsprechenden Steuerelement zugrundeliegt. Wenn nichts in die Beschriftungseigenschaft des Feldes eingegeben wurde, wird der Feldname als Beschriftung des Bezeichnungsfeldes verwendet. Das Werkzeug BEZEICHNUNG, das Sie in der Toolbox finden, kann benutzt werden, um beliebigen Text zum Formular hinzuzufügen. Klicken Sie dazu erst auf das Werkzeug BEZEICHNUNG, dann auf das Bezeichnungsfeld und ziehen Sie das Steuerelement anschließend an die gewünschte Stelle auf dem Formular. Bezeichnungsfelder werden oft benutzt, um ein Formular zu beschreiben oder dem Benutzer eine Gebrauchsanweisung zu geben. Bezeichnungsfelder können hinsichtlich Schriftart, Größe, Farbe usw. angepasst werden. Entwickler können VBA-Code verwenden, um die Eigenschaften von Bezeichnungsfeldern zur Laufzeit zu verändern. Benutzer haben diese Möglichkeit hingegen nicht. Manchmal geht die Verbindung eines Bezeichnungsfeldes zu seinem Textfeld verloren. Das bedeutet, dass das Bezeichnungsfeld nicht mehr gemeinsam mit dem zugehörigen Textfeld verschoben, in der Größe verändert und ausgewählt wird. Um diese Verbindung wiederherzustellen, schneiden Sie das Bezeichnungsfeld aus (Strg)+(x), klicken das Textfeld an und drücken (Strg)+(v) zum Einfügen. Wenn Sie absichtlich die Verbindung zwischen Bezeichnungsfeld und zugehörigem Steuerelement lösen wollen, schneiden Sie es einfach aus und fügen es wieder in das Formular ein, ohne das Steuerelement auszuwählen, zu dem es gehört hat. Damit können Sie z.B. das Steuerelement verbergen, ohne das Bezeichnungsfeld mit auszublenden.

5.5.2

Textfelder

Textfelder werden benutzt, um Informationen vom Benutzer entgegenzunehmen. Gebundene Textfelder zeigen und empfangen Informationen, die in einer Tabelle gespeichert werden, ungebundene Textfelder dagegen sammeln Informationen vom Benutzer, die sich nicht auf ein bestimmtes Feld in einem bestimmten Datensatz beziehen. Ein Textfeld kann beispielsweise verwendet werden, um die Parameter für einen Bericht vom Benutzer abzufragen.

Das geeignete Steuerelement auswählen

161

Textfelder werden automatisch zu einem Formular hinzugefügt, wenn Sie ein Feld aus der Feldliste anklicken, auf das Formular ziehen und das Anzeigesteuerelement für dieses Feld auf Textfeld gesetzt ist. Das Anzeigesteuerelement ist das standardmäßige Steuerelement für ein Objekt und wird beim Entwurf der zu Grunde liegenden Tabelle festgelegt. Ein anderer Weg, um ein Textfeld hinzuzufügen, besteht darin, das Werkzeug TEXTFELD aus der Toolbox auszuwählen, indem Sie auf das Textfeld klicken und es auf das Formular ziehen. Dieser Vorgang erzeugt ein ungebundenes Textfeld. Wenn Sie das Textfeld mit Daten verbinden wollen, müssen Sie die Eigenschaft STEUERELEMENTINHALT setzen.

5.5.3

Kombinationsfelder

Access bietet mehrere einfache Möglichkeiten, ein Kombinationsfeld zu einem Formular hinzuzufügen. Wenn die Eigenschaft STEUERELEMENT ANZEIGEN eines Feldes auf KOMBINATIONSFELD gesetzt worden ist, wird beim Hinzufügen eines Feldes automatisch ein Kombinationsfeld auf dem Formular erzeugt. Dieses kennt automatisch seine Datenquelle sowie andere wichtige Eigenschaften. Wenn die Eigenschaft STEUERELEMENT ANZEIGEN eines Feldes nicht auf KOMBINATIONSFELD gesetzt ist, führt der einfachste Weg zum Erzeugen eines Kombinationsfeldes auf dem Formular über den Steuerelement-Assistenten. Der SteuerelementAssistent unterstützt Sie beim Hinzufügen von Kombinationsfeldern, Listenfeldern, Optionsgruppen und Unterformularen zu Ihrem Formular. Die Benutzung des Assistenten spart Zeit und Kraft, obwohl alle Eigenschaften, die durch den Kombinationsfeld-Assistenten gesetzt werden, manuell verändert werden können. Soll der Kombinationsfeld-Assistent gestartet werden, wenn Sie ein Kombinationsfeld zum Formular hinzufügen, stellen Sie sicher, dass das Werkzeug STEUERELEMENT-ASSISTENTEN in der Toolbox angeklickt (eingeschaltet) worden ist, bevor Sie das Kombinationsfeld hinzufügen. Um ein Kombinationsfeld zu einem Formular hinzuzufügen, wählen Sie das Werkzeug KOMBINATIONSFELD in der Toolbox, klicken es an und ziehen das Kombinationsfeld dann auf das Formular. Dadurch wird der Kombinationsfeld-Assistent gestartet, dessen erster Schritt in Abbildung 5.17 dargestellt wird. Sie werden gefragt, ob das Kombinationsfeld die Werte aus einer Tabelle oder Abfrage verwenden soll, ob Sie die Werte lieber selbst eingeben möchten oder ob das Kombinationsfeld benutzt werden soll, um einen bestimmten Datensatz zu suchen. Nehmen Sie die erste Möglichkeit, wenn Ihr Kombinationsfeld Daten verwenden soll, die in einem Feld gespeichert sind, wie zum Beispiel das Bundesland, in dem ein bestimmter Kunde wohnt. Ich benutze selten, wenn überhaupt, die zweite Möglichkeit, bei der man die Werte für das Kombinationsfeld eingeben muss, weil damit ein erhöhter Pflegeaufwand verbunden ist. Jedesmal, wenn Sie einen Eintrag zum Kombinationsfeld hinzufügen wollen, müssen Sie die gesamte Anwendung verändern. Die dritte und letzte Möglichkeit ist optimal, wenn das Kombinationsfeld zum Finden bestimmter Datensätze benutzt werden soll. So kann ein Kombinationsfeld beispiels-

162

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

weise in den Formularkopf eingebaut werden, um eine Liste von Kunden anzuzeigen, wodurch nach der Auswahl eines Kunden der entsprechende Datensatz angezeigt wird. Diese Möglichkeit gibt es allerdings nur, wenn das Formular mit einer Datenquelle verbunden ist.

Abbildung 5.17: Der erste Schritt im Kombinationsfeld-Assistenten: die Datenquelle auswählen

Im zweiten Schritt des Kombinationsfeld-Assistenten wählen Sie eine Tabelle oder Abfrage, um das Kombinationsfeld mit Leben zu füllen. Durch Auswahl einer Abfrage bekommen Sie eine höhere Verarbeitungsgeschwindigkeit. Der dritte Schritt des Kombinationsfeld-Assistenten erlaubt Ihnen die Auswahl der Felder, die in Ihrem Kombinationsfeld auftauchen sollen (siehe Abbildung 5.18.) Das Kombinationsfeld, das im Beispiel erstellt wird, wird benutzt, um den Kunden zu einem bestimmten Projekt zu suchen. Obwohl das Feld CompanyName das einzige Feld ist, das im Kombinationsfeld sichtbar sein soll, wurden sowohl CompanyName als auch ClientID ausgewählt, weil ClientID ein notwendiges Element des Kombinationsfeldes ist. Nach der Auswahl eines Firmennamens im Kombinationsfeld wird die zugehörige Kundennummer im Feld ClientID der Tabelle tblProjects gespeichert. Im vierten Schritt des Kombinationsfeld-Assistenten bestimmen Sie die Breite jedes Feldes im Kombinationsfeld. Beachten Sie in Abbildung 5.19, dass Access das Ausblenden des Schlüsselfelds ClientID vorschlägt, damit der Benutzer eine aussagekräftige Beschreibung sieht, während Access den entsprechenden Schlüsselwert in den Datensatz schreibt. Im fünften Schritt des Kombinationsfeld-Assistenten bestimmen Sie, ob sich Access die ausgewählten Werte einfach merken oder sie in einem bestimmten Feld einer Tabelle speichern soll. In dem Beispiel in Abbildung 5.20 wird der aus dem Kombinationsfeld ausgewählte Wert im Feld ClientID in der Tabelle tblProjects gespeichert.

Das geeignete Steuerelement auswählen

163

Abbildung 5.18: Der dritte Schritt im Kombinationsfeld-Assistenten: Felder auswählen

Abbildung 5.19: Der vierte Schritt im Kombinationsfeld-Assistenten: Spaltenbreiten festlegen

Der sechste und letzte Schritt des Kombinationsfeld-Assistenten fragt nach dem Text, der als Bezeichnung für das Kombinationsfeld dienen soll. Die Schaltfläche FERTIG STELLEN vollendet den Vorgang, erstellt das Kombinationsfeld und füllt alle seine Eigenschaften mit den entsprechenden Werten. Obwohl der Kombinationsfeld-Assistent ein hilfreiches Werkzeug ist, muss man wissen, welche Eigenschaften er vergibt. Abbildung 5.21 zeigt das Eigenschaftenfenster für ein Kombinationsfeld. Viele dieser Eigenschaften werden in anderen Kapiteln behandelt, aber lesen Sie jetzt ein wenig darüber, welche Eigenschaften vom Kombinationsfeld-Assistenten festgelegt werden.

164

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.20: Der fünfte Schritt im Kombinationsfeld-Assistenten: angeben, wo der ausgewählte Wert gespeichert werden wird

Die Eigenschaft STEUERELEMENTINHALT gibt das Feld an, in dem die ausgewählte Eingabe gespeichert wird. In Abbildung 5.21 ist dies das Feld ClientID der Tabelle tblProjects. Die Eigenschaft HERKUNFTSTYP bestimmt, ob die Quelle des Kombinationsfeldes eine Tabelle/Abfrage, eine Werteliste oder eine Feldliste ist. In dem Beispiel hat HERKUNFTSTYP den Wert TABELLE/ABFRAGE. Die DATENSATZHERKUNFT ist der Name der aktuellen Tabelle oder Abfrage, die benutzt wird, um das Kombinationsfeld mit Leben zu füllen. In dem Beispiel ist die Datensatzherkunft tblClients. Die Eigenschaft SPALTENANZAHL legt fest, wie viele Spalten das Kombinationsfeld enthält, und die Eigenschaft SPALTENBREITEN gibt die Breite jeder Spalte an. In dem Beispiel ist die Breite der ersten Spalte null, wodurch die Spalte unsichtbar wird. Die Eigenschaft GEBUNDENE SPALTE schließlich gibt an, welche Spalte im Kombinationsfeld verwendet wird, um Daten der Quelle zu speichern. In dem Beispiel ist das Spalte 1. Kombinationsfelder sind sehr leistungsfähige Steuerelemente, aber Sie müssen viel darüber wissen, um ihre Möglichkeiten auszuschöpfen. Die weiteren Möglichkeiten von Kombinationsfeldern finden Sie in Kapitel 9.

5.5.4

Listenfelder

Listenfelder ähneln Kombinationsfeldern, aber es gibt drei große Unterschiede:

 Sie brauchen mehr Platz auf dem Bildschirm.  Sie lassen nur eine Auswahl aus der angezeigten Liste zu, d.h., Sie können in einem Listenfeld keine neuen Werte eingeben (was bei einem Kombinationsfeld möglich ist).

 Sie können die Auswahl mehrerer Werte zulassen.

Das geeignete Steuerelement auswählen

165

Abbildung 5.21: Eigenschaften eines Kombinationsfeldes, die zeigen, dass das Feld ClientID als Quelle für das Kombinationsfeld Combo5 ausgewählt worden ist

Sie können die Eigenschaft STEUERELEMENT ANZEIGEN eines Feldes nicht nur auf KOMBINATIONSFELD, sondern auch auf LISTENFELD setzen. Wenn Sie dies tun, wird dem Formular beim Ablegen eines Feldes auf ihm automatisch ein Listenfeld hinzugefügt. Der Listenfeld-Assistent ähnelt dem Kombinationsfeld-Assistenten sehr. Nach dem Durchlaufen des Listenfeld-Assistenten sind die betroffenen Listenfeldeigenschaften die gleichen wie die Kombinationsfeldeigenschaften. Weitere Techniken zum Umgang mit Listenfeldern finden Sie in Kapitel 9.

5.5.5

Kontrollkästchen

Kontrollkästchen werden benutzt, wenn Sie dem Benutzer nur die Eingabe eines von zwei Werten erlauben wollen. Die Werte können auf JA/NEIN, WAHR/FALSCH oder EIN/AUS beschränkt werden. Sie können einem Formular auf verschiedene Arten Kontrollkästchen hinzufügen: 1. Setzen Sie die Eigenschaft STEUERELEMENT ANZEIGEN des zu Grunde liegenden Feldes auf KONTROLLKÄSTCHEN, klicken Sie dann auf das Feld in der Feldliste und ziehen Sie es auf das Formular. 2. Klicken Sie auf das Werkzeug KONTROLLKÄSTCHEN in der Toolbox, klicken Sie dann auf das Feld in der Feldliste und ziehen Sie es auf das Formular. Diese Methode fügt dem Formular ein Kontrollkästchen hinzu, auch wenn die Eigenschaft STEUERELEMENT ANZEIGEN des zu Grunde liegenden Feldes nicht auf KONTROLLKÄSTCHEN gesetzt ist. 3. Klicken Sie auf das Werkzeug KONTROLLKÄSTCHEN in der Toolbox und klicken Sie dann auf die gewünschte Position, um dem Formular ein Kontrollkästchen

166

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

hinzuzufügen. Dieses Kontrollkästchen ist ungebunden. Um es mit Daten zu verbinden, müssen Sie die Eigenschaft Steuerelementinhalt festlegen. Sie können die Eigenschaft DREIFACHER STATUS eines Kontrollkästchens verwenden, um einen dritten Wert, NULL, zuzulassen.

5.5.6

Optionsfelder

Optionsfelder können alleine oder als Teil einer Optionsgruppe verwendet werden. Ein Optionsfeld alleine kann zum Anzeigen eines Wahr/Falsch-Wertes benutzt werden, aber das ist nicht der Sinn von Optionsfeldern. Für diesen Zweck sind Kontrollkästchen vorgesehen. Als Teil einer Optionsgruppe zwingen Optionsfelder den Benutzer dazu, zwischen einer Reihe sich gegenseitig ausschließender Optionen auszuwählen, wie zum Beispiel zwischen American Express, MasterCard, Visa oder Discover im Falle einer Kreditkarte. Dieser Gebrauch von Optionsfeldern wird im Abschnitt »Optionsfelder« behandelt.

5.5.7

Umschaltflächen

Genau wie Optionsfelder können Umschaltflächen alleine oder als Teil einer Optionsgruppe benutzt werden. Eine Umschaltfläche kann selbst einen Wahr/FalschWert anzeigen, aber dies ist nicht der normale Gebrauch. Stattdessen werden Umschaltflächen üblicherweise als Teil einer Optionsgruppe eingesetzt, wie im nächsten Abschnitt erläutert wird.

5.5.8

Optionsgruppen

Optionsgruppen erlauben dem Benutzer, aus einer sich gegenseitig ausschließenden Reihe von Optionen auszuwählen. Sie können Kontrollkästchen, Umschaltflächen oder Optionsfelder enthalten, aber der gebräuchlichste Inhalt einer Optionsgruppe sind Optionsfelder. Der einfachste Weg, eine Optionsgruppe zu einem Formular hinzuzufügen, ist die Benutzung des Optionsgruppen-Assistenten. Damit der Optionsgruppen-Assistent startet, muss die Schaltfläche STEUERELEMENT-ASSISTENTEN in der Toolbox aktiviert sein. Klicken Sie in der Toolbox auf OPTIONSGRUPPE und ziehen Sie die Optionsgruppe dann im Formular auf. Im ersten Schritt des Optionsgruppen-Assistenten, gezeigt in Abbildung 5.22, geben Sie den Text zu jedem Element der Optionsgruppe ein. Im zweiten Schritt wählen Sie anschließend die Standardauswahl für die Optionsgruppe. Diese Vorgaben werden wirksam, wenn der Tabelle, die dem Formular zugrunde liegt, ein neuer Datensatz hinzugefügt wird. Im dritten Schritt wählen Sie zu jedem Optionsfeld Werte aus

Das geeignete Steuerelement auswählen

167

(siehe Abbildung 5.23). Der Datensatz speichert dann nicht den zu jedem Optionsfeld angezeigten Text, sondern den entsprechenden numerischen Wert. Im Beispiel in Abbildung 5.23 wird bei Auswahl der Option CHECK die Zahl 2 gespeichert. Der vierte Schritt des Optionsgruppen-Assistenten fragt, ob Sie die Werte für die Optionsgruppe für eine spätere Verwendung aufbewahren wollen oder ob die Werte in einem Feld gespeichert werden sollen. In Abbildung 5.24 wird der Wert der Optionsgruppe zum Beispiel im Feld PaymentMethodID gespeichert. Im fünften Schritt des Optionsgruppen-Assistenten können Sie aus einer Vielfalt von Stilen für die Optionsgruppen-Schaltflächen auswählen, einschließlich Optionsfeldern, Kontrollkästchen und Umschaltflächen. Ferner können Sie zwischen Effekten für Ihre Schaltflächen wählen, wie graviert, flach, erhöht, schattiert oder vertieft. Der Assistent gibt Ihnen eine Voransicht jeder Möglichkeit. Der sechste und letzte Schritt des Optionsgruppen-Assistenten erlaubt Ihnen das Hinzufügen einer entsprechenden Beschriftung zu der Optionsgruppe. Die vollständige Gruppe von Options-Schaltflächen sehen Sie in Abbildung 5.25.

Abbildung 5.22: Der erste Schritt im Optionsgruppen-Assistenten: zu Optionen Text hinzufügen

Abbildung 5.23: Der dritte Schritt im Optionsgruppen-Assistenten: Optionswerte auswählen

168

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.24: Der vierte Schritt im Optionsgruppen-Assistenten: die Gruppe mit Daten verbinden

Abbildung 5.25: Das Resultat der Ausführung des OptionsgruppenAssistenten

Sie sollten wissen, dass der Optionsgruppen-Assistent die Eigenschaften des Rahmens, der Optionsfelder innerhalb des Rahmens und der Bezeichnungen, die mit den Optionsfeldern verbunden sind, festlegt. Die Eigenschaften des Rahmens werden in Abbildung 5.26 gezeigt. Der Steuerelementinhalt des Rahmens und die Standardauswahl der Optionsgruppe werden durch den Optionsgruppen-Assistenten vergeben. Jedes einzelne Optionsfeld erhält dann einen Wert und die Beschriftung der zugehörigen Bezeichnung wird vergeben.

Ein Steuerelement durch ein anderes ersetzen

169

Abbildung 5.26: Ein Optionsgruppenrahmen mit den Eigenschaften der ausgewählten Schaltfläche

5.6

Ein Steuerelement durch ein anderes ersetzen

Beim ersten Entwurf eines Formulars fällt Ihnen vielleicht nicht unbedingt für jedes Feld das richtige Steuerelement ein oder Sie denken, das ideale Steuerelement gefunden zu haben, nur um später feststellen zu müssen, dass Ihre Wahl den Vorstellungen des Benutzers nicht so ganz gefällt. In Access ist es einfach, ein Steuerelement durch ein anderes zu ersetzen. Sie können z.B. ein Listenfeld in ein Kombinationsfeld umwandeln.

5.6.1

Ein Textfeld in ein Kombinationsfeld verwandeln

Eine der häufigsten Arten der Umwandlung ist die vom Textfeld in ein Kombinationsfeld. Hierzu klicken Sie mit der rechten Taste auf das Textfeld, wählen Sie ÄNDERN IN und suchen dann das Steuerelement aus, in das Sie das Textfeld verwandeln wollen. Die verfügbaren Steuerelemente hängen von der Art des umzuwandelnden Steuerelements ab. Ein Textfeld kann beispielsweise in ein Bezeichnungsfeld, Listenfeld oder Kombinationsfeld verwandelt werden (siehe Abbildung 5.27). Nach dem Verwandeln eines Textfeldes in ein Kombinationsfeld bearbeiten Sie die entsprechenden Steuerelementeigenschaften. Dabei müssen die Eigenschaften DATENSATZHERKUNFT, GEBUNDENE SPALTE, SPALTENANZAHL und SPALTENBREITEN festgelegt werden. Für die Datensatzherkunft müssen Sie eine Tabelle oder Abfrage angeben. Wenn Sie eine Tabelle auswählen und auf die Schaltfläche mit den drei Punkten klicken, werden Sie gefragt, ob Sie eine Abfrage für diese Tabelle erstellen möchten. Nachdem Sie JA ausgewählt haben, können Sie eine Abfrage erstellen, die nur die Felder im Kombinationsfeld enthält. Anschließend können Sie auswählen, ob die Daten in der zugrunde liegenden Tabelle über eine gebundene Spalte

170

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.27: Ein Textfeld in ein anderes Steuerelement verwandeln

gespeichert werden sollen. So könnte beispielsweise der Benutzer den Namen eines Projekts auswählen, für das eine Zahlung erfolgen soll, aber statt des Namens wird die ProjectID in der Tabelle tblPayments gespeichert. Setzen Sie die Spaltenanzahl auf die Anzahl der Spalten, die in der zugrunde liegenden Abfrage ausgewählt worden sind; die Spaltenbreite kann danach so verändert werden, dass die Schlüsselspalte verborgen ist.

5.6.2

Kombinationsfeld in Listenfeld

Das Ändern eines Kombinationsfeldes in ein Listenfeld ist ein wesentlich einfacherer Vorgang als das Verwandeln eines Textfeldes in ein Kombinationsfeld oder in ein Listenfeld, weil Kombinationsfelder und Listenfelder sehr viele gemeinsame Eigenschaften haben. Zum Verwandeln eines Kombinationsfeldes in ein Listenfeld klicken Sie einfach mit der rechten Taste auf das Kombinationsfeld und wählen ÄNDERN IN|LISTENFELD.

5.7

Bedingte Formatierung

Neu in Access 2000 ist die bedingte Formatierung, mit deren Hilfe Daten in Abhängigkeit von bestimmten Kriterien unterschiedlich angezeigt werden können. Um Daten mit bedingter Formatierung anzuzeigen, folgen Sie diesen Schritten: 1. Wählen Sie das Steuerelement, das Sie bedingt formatieren wollen. 2. Wählen Sie FORMAT|BEDINGTE FORMATIERUNG. Daraufhin erscheint das Dialogfeld BEDINGTE FORMATIERUNG.

Welche Formulareigenschaften stehen zur Verfügung?

171

3. Wählen Sie FELDWERT IST, AUSDRUCK IST oder FELD HAT FOKUS aus dem ersten Kombinationsfeld aus. 4. Wählen Sie im zweiten Kombinationsfeld den entsprechenden Operator aus. 5. Geben Sie in den Textfeldern rechts die Werte ein, gegen die Sie prüfen möchten. 6. Wählen Sie die Formatierung aus (fett, kursiv, Hintergrundfarbe usw.), die bei erfüllter Bedingung angewendet werden soll. 7. Klicken Sie auf HINZUFÜGEN, um weitere Formate hinzuzufügen. 8. Klicken Sie auf OK, um die bedingte Formatierung durchzuführen.

5.8

Welche Formulareigenschaften stehen zur Verfügung und warum sollten sie benutzt werden?

Formulare haben viele Eigenschaften, die ihr Aussehen und Verhalten beeinflussen. Die Eigenschaften fallen unter die folgenden Kategorien: FORMAT, DATEN, EREIGNIS und ANDERE. Zum Anzeigen der Eigenschaften eines Formulars müssen Sie es auswählen: 1. Klicken Sie auf die Schaltfläche zur Formularauswahl (die schmale graue Schaltfläche am Schnittpunkt der waagerechten und senkrechten Lineale). 2. Wählen Sie BEARBEITEN|FORMULAR AUSWÄHLEN.

5.8.1

Das Eigenschaftenfenster

Zum Anzeigen der Eigenschaften klicken Sie nach dem Auswählen des Formulars auf die Schaltfläche EIGENSCHAFTEN in der Symbolleiste. Das Eigenschaftenfenster, zu sehen in Abbildung 5.28, enthält fünf Registerkarten: FORMAT, DATEN, EREIGNISSE, ANDERE und ALLE. Viele Entwickler sehen gerne alle Eigenschaften auf einmal, jedoch besitzt ein Formular davon insgesamt 81! Der nach Kategorien getrennte Aufruf ist viel übersichtlicher als sich alle 81 Eigenschaften auf einmal anzusehen. Die Kategorie FORMAT enthält die physischen Attribute des Formulars, die das Erscheinungsbild des Formulars beeinflussen (z.B. die Hintergrundfarbe). Die Kategorie DATEN umfasst alle Eigenschaften, die sich auf die Daten beziehen, mit denen das Formular verbunden ist, wie beispielsweise die dem Formular zu Grunde liegende Datenquelle. Die Kategorie EREIGNISSE fasst alle Windows-Ereignisse zusammen, auf die ein Formular reagieren kann. Sie können beispielsweise Code schreiben, der nach dem Laden des Formulars, der Aktivierung, dem Anzeigen des nächsten Datensatzes usw. ausgeführt wird. Die Kategorie ANDERE enthält schließlich die Eigenschaften, die nicht in eine der übrigen drei Kategorien hineinpassen.

172

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.28: Die Formateigenschaften eines Formulars

5.8.2

Wichtige Formulareigenschaften

Wie bereits erwähnt, besitzen Formulare 81 Eigenschaften, von denen 32 EREIGNISEigenschaften sind, die in Kapitel 9 behandelt werden. Der folgende Abschnitt behandelt die Eigenschaften der Kategorien FORMAT, DATEN und ANDERE. Formateigenschaften eines Formulars Die Formateigenschaften eines Formulars beeinflussen sein Erscheinungsbild. Formulare verfügen über 26 Formateigenschaften: Beschriftung: Die Eigenschaft BESCHRIFTUNG legt den Text fest, der in der Titelzeile des Formulars erscheint. Diese Eigenschaft kann zur Laufzeit verändert werden. Sie können beispielsweise den Benutzernamen oder den Namen des Kunden, für den eine Rechnung geschrieben wird, hier einblenden. Standardansicht: Die Eigenschaft STANDARDANSICHT bietet die Auswahl zwischen drei Möglichkeiten:

 EINZELNES FORMULAR: Es kann nur ein Datensatz zurzeit angesehen werden.  ENDLOSFORMULAR: So viele Datensätze, wie in das Formularfenster passen, werden gleichzeitig angezeigt, jeder als Detailabschnitt eines einzelnen Formulars.

 DATENBLATT: Zeigt die Datensätze in einer ähnlichen Form wie eine Kalkulationstabelle an, wobei die Zeilen Datensätzen und die Spalten Feldern entsprechen. Die ausgewählte Einstellung wird die Standardansicht des Formulars.

Welche Formulareigenschaften stehen zur Verfügung?

173

Zugelassene Ansichten: Die Eigenschaft ZUGELASSENE ANSICHTEN legt fest, ob der Benutzer zwischen Formular- und Datenblattansicht hin- und herwechseln darf. In der Standardansicht wurde die standardmäßige Ansicht vorgegeben, ZUGELASSENE ANSICHTEN dagegen legt fest, ob der Benutzer die Standardansicht verlassen darf. Bildlaufleisten: Die Eigenschaft BILDLAUFLEISTEN legt fest, ob Bildlaufleisten erscheinen sollen, wenn die Objekte auf dem Formular nicht ins Formularfenster passen. Mögliche Optionen sind IN BEIDEN RICHTUNGEN, NUR VERTIKAL, NUR horizontal oder NEIN. Datensatzmarkierer: Ein Datensatzmarkierer ist der graue Balken links neben einem Datensatz in der Formularansicht oder das graue Feld links neben jedem Datensatz in der Datenblattansicht. Er wird gebraucht, um einen Datensatz auszuwählen, der kopiert oder gelöscht werden soll. Die Eigenschaft DATENSATZMARKIERER legt fest, ob Datensatzmarkierer vorhanden sind. Wenn Sie dem Benutzer ein benutzerdefiniertes Menü an die Hand geben, können Sie den Datensatzmarkierer entfernen, so dass der Benutzer Datensätze nur kopieren oder löschen kann, wenn Ihre Anwendung um diese Fähigkeiten erweitert wurde. Navigationsschaltflächen: Navigationsschaltflächen sind die Steuerelemente, die im Fuß des Formulars erscheinen und dem Benutzer erlauben, sich innerhalb des Formulars von Datensatz zu Datensatz zu bewegen. Die Eigenschaft NAVIGATIONSSCHALTFLÄCHEN legt fest, ob die Navigationsschaltflächen sichtbar sind. Für Dialogformulare sollten Sie diese Eigenschaft auf Nein setzen, genauso wie dies für reine Dateneingabeformulare sinnvoll sein kann, und Sie können eigene Symbolleisten oder Befehlsschaltflächen einfügen, welche die normalen Möglichkeiten erweitern oder einschränken. Beispielsweise könnte es erforderlich sein, dem Benutzer in einer Client-Server-Umgebung die Möglichkeit zu verweigern, zum ersten oder letzten Datensatz zu springen, weil das in einer derartigen Umgebung sehr viel Zeit kosten kann. Trennlinien: Die Eigenschaft TRENNLINIEN zeigt an, ob zwischen den Datensätzen eine Trennungslinie erscheinen soll, wenn die Standardansicht des Formulars auf ENDLOSFORMULAR gesetzt wird. Größe anpassen: Diese Eigenschaft legt fest, ob die Größe des Formulars automatisch an die Darstellung eines vollständigen Datensatzes angepasst wird. Automatisch Zentrieren: Diese Eigenschaft legt fest, ob das Formular beim Öffnen automatisch im Anwendungsfenster zentriert wird. Rahmenart: Diese Eigenschaft ist viel umfassender als ihr Name vermuten lässt. Die Rahmenart kann die Werte KEINE, DÜNN, VERÄNDERBAR und DIALOG annehmen. Bei Begrüßungsbildschirmen wird die Rahmenart oft auf KEINE gesetzt, wodurch das Formular keine Begrenzung bekommt. Eine dünne Begrenzung ist nicht in der Größe veränderbar, was bedeutet, dass der Befehl GRÖSSE ÄNDERN im Systemmenü

174

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

des Formulars nicht verfügbar ist. Diese Einstellung stellt eine gute Wahl für Formulare dar, die auch dann noch im Vordergrund bleiben, wenn andere Formulare den Fokus erhalten. Eine veränderbare Begrenzung ist der Standard für die meisten Formulare. Hier enthält das Kontextmenü des Steuerelements alle Standardoptionen. Ein Dialograhmen ähnelt einer dünnen Begrenzung. Ein Formular mit dieser Rahmenart kann nicht maximiert, minimiert oder in der Größe verändert werden. Wenn die Begrenzung des Formulars auf DIALOG gesetzt ist, sind die Optionen MAXIMIEREN, MINIMIEREN und GRÖSSE ÄNDERN nicht im Systemmenü des Formulars verfügbar. Zum Erstellen benutzerdefinierter Dialogfelder wird oft die Rahmenart DIALOG zusammen mit den Eigenschaften POPUP und GEBUNDEN verwendet. Mit Systemmenüfeld: Die Eigenschaft MIT SYSTEMMENÜFELD legt fest, ob ein Formular ein Systemmenüfeld hat. Verwenden Sie diese Option sparsam. Eine Ihrer Verantwortlichkeiten als Access-Programmierer besteht darin, Ihre Anwendung an die Windows-Standards anzulehnen. Wenn Sie sich die Windows-Programme ansehen, mit denen Sie arbeiten, werden Sie nur sehr wenige Formulare ohne Systemmenüfeld finden. Sie können daraus ableiten, wie Ihre eigenen Anwendungen aussehen sollten. MinMaxSchaltflächen: Die Eigenschaft MINMAXSCHALTFLÄCHEN gibt an, ob das Formular Schaltflächen zum Minimieren und Maximieren besitzt. Die Möglichkeiten sind KEINE VORHANDEN, MIN, MAX, und BEIDE. Wenn Sie eine oder beide Schaltflächen entfernen, stehen die entsprechenden Optionen auch nicht mehr im Systemmenüfeld. Die Eigenschaft MINMAXSCHALTFLÄCHEN wird bei Formularen mit der Rahmenart KEINE oder DIALOG ignoriert. Genau wie die Eigenschaft MIT Systemmenüfeld verwende ich diese Eigenschaft selten. Damit meine Anwendungen dem Windows-Standard entsprechen, wähle ich vielmehr die passende Rahmenart und lasse deren vorgegebene Attribute stehen. Schließen-Schaltfläche: Diese Eigenschaft legt fest, ob der Benutzer das Formular über das Systemmenü oder durch Doppelklicken auf das Systemmenüsymbol schließen kann. Wenn Sie diese Eigenschaft auf Nein setzen, müssen Sie dem Benutzer eine andere Möglichkeit zum Schließen des Formulars bieten. Ansonsten könnte es passieren, dass der Benutzer seinen Computer neu starten muss, um Ihre Anwendung zu schließen. Direkthilfe Schaltfläche: Diese Eigenschaft legt fest, ob Sie die Schaltfläche DIREKTHILFE in die Titelleiste einfügen wollen. Diese Vorgehensweise funktioniert nur, wenn die Min-Max-Eigenschaft auf NEIN gesetzt ist. Wenn die Eigenschaft SCHALTFLÄCHE DIREKTHILFE auf JA gesetzt ist, kann der Benutzer zuerst auf die DIREKTHILFE-Schaltfläche und dann auf ein Objekt auf dem Formular klicken, um die Hilfe für dieses Objekt anzuzeigen. Wenn für das ausgewählte Objekt keine eigene Hilfe existiert, wird die Hilfe für das Formular oder ggf. die Microsoft AccessHilfe angezeigt.

Welche Formulareigenschaften stehen zur Verfügung?

175

Breite: Die Eigenschaft BREITE gibt die Breite des Formulars an. Diese Option wird meistens durch Anklicken und Ziehen des Formulars auf die gewünschte Größe gesetzt. Sie können diese Eigenschaft aber auch von Hand festlegen, wenn Sie wollen, dass mehrere Formulare exakt die gleiche Größe haben. Bild, Bildtyp, Bildgrößenmodus, Bildausrichtung und Bildnebeneinander: Die Eigenschaft BILD lässt Sie die Attribute einer Bitmap auswählen und anpassen, die als Hintergrund für das Formular verwendet wird. Raster X, Raster Y: Diese Eigenschaften können benutzt werden, um den Abstand der horizontalen und vertikalen Linien festzulegen, die in der Entwurfsansicht auf dem Formular erscheinen. Durch das Festlegen dieser Eigenschaften haben Sie Einfluss darauf, wie präzise Ihre Objekte auf dem Formular positioniert werden, wenn die Option AM RASTER AUSRICHTEN aktiv ist. Drucklayout: Diese Eigenschaft gibt an, ob Bildschirm- oder Druckerschriftarten auf dem Formular verwendet werden. Wenn Sie das Formular lieber für den Druck optimieren wollen als für die Anzeige, sollten Sie diese Eigenschaft auf JA setzen. Unterdatenblatthöhe: Die Unterdatenblatthöhe legt die maximale Höhe für ein Unterdatenblatt fest. Unterdatenblatt erweitert: Diese Eigenschaft legt fest, ob ein Unterdatenblatt anfänglich im erweiterten Format angezeigt wird. Besitzt die Eigenschaft den Wert NEIN, erscheint das Unterdatenblatt anfänglich in einem minimierten und sonst in einem erweiterten Format. Palettenherkunft: Die Eigenschaft PALETTENHERKUNFT legt die Quelle für die Auswahl der Farben eines Formulars fest. Dateneigenschaften eines Formulars Die Dateneigenschaften eines Formulars steuern die Datenquelle des Formulars, welche Art von Tätigkeiten der Benutzer mit den Daten im Formular durchführen kann und wie die Daten im Formular in einer Mehrbenutzerumgebung gesperrt werden. Ein Formular besitzt zehn Dateneigenschaften. Datenherkunft: Die Eigenschaft DATENHERKUNFT bezeichnet die Tabelle, gespeicherte Abfrage oder SQL-Anweisung, auf der die Datensätze des Formulars aufgebaut sind. Nach der Auswahl einer Datenherkunft für ein Formular können seine Steuerelemente mit den Feldern in dieser Datenquelle verbunden werden. Das Feldlistenfenster steht erst zur Verfügung, nachdem die Datenherkunft des Formulars festgelegt worden ist.

176

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Die Datenherkunft eines Formulars kann zur Laufzeit geändert werden. Infolgedessen können Sie generische, wiederverwendbare Formulare für viele Situationen erstellen. Filter: Die Eigenschaft Filter lädt automatisch einen gespeicherten Filter zusammen mit dem Formular. Ich ziehe es vor, ein Formular auf einer Abfrage aufzubauen, welche die Darstellung der Daten auf dem Formular einschränkt. Der Abfrage können zur Laufzeit Parameter übergeben werden, um zu steuern, welche Daten angezeigt werden. Sortiert nach: Diese Eigenschaft legt die Reihenfolge der Datensätze im Formular fest und kann zur Laufzeit verändert werden, um die Datensätze unterschiedlich sortiert anzuzeigen. Filter zulassen: Diese Eigenschaft entscheidet darüber, ob Datensätze zur Laufzeit gefiltert werden können. Wird sie auf NEIN gesetzt, werden sämtliche Filteroptionen für den Benutzer deaktiviert. Bearbeitungen, Löschen, Anfügen zulassen: Mit diesen Eigenschaften bestimmen Sie, ob der Benutzer im Formular Datensätze bearbeiten, löschen oder hinzufügen kann. Diese Optionen ersetzen jedoch nicht die Zugriffsberechtigungen, die für die dem Formular zugrunde liegenden Tabellen oder Abfragen eingerichtet worden sind. Das Thema Datensicherheit wird in den Kapiteln 33 und 34 behandelt. Daten eingeben: Die Eigenschaft DATEN EINGEBEN legt fest, ob Ihr Benutzer in einem Formular ausschließlich Daten hinzufügen kann. Setzen Sie diese Eigenschaft auf JA, wenn Ihre Benutzer bestehende Datensätze weder ansehen noch bearbeiten, sondern nur neue Datensätze erfassen sollen. Recordsettyp: Die Eigenschaft RECORDSETTYP eröffnet drei Optionen: DYNASET, Dynaset (INKONSISTENTE AKTUALISIERUNGEN) und SNAPSHOT. Jede dieser Möglich-

keiten besitzt unterschiedliche Leistungsmerkmale und Bearbeitungsmöglichkeiten. Durch Angabe der Option DYNASET wird der Datensatz vollständig aktualisierbar, außer wenn er oder einzelne seiner Felder aus anderen Gründen nicht geändert werden können. Ein Beispiel hierfür ist ein Formular, das auf einer Abfrage mit einer 1:n-Beziehung aufbaut. Das Verknüpfungsfeld auf der Einserseite der Beziehung kann nur geändert werden, wenn das Merkmal AKTUALISIERUNGSWEITERGABE AN Detailfeld gesetzt ist. Die Option DYNASET (INKONSISTENTE AKTUALISIERUNGEN) erlaubt das Bearbeiten aller Tabellen und gebundenen Daten. Dies kann inkonsistente Änderungen von Daten in den an der Abfrage beteiligten Tabellen zur Folge haben. Die Option SNAPSHOT erlaubt keinerlei Aktualisierungen. Datensätze sperren: Diese Eigenschaft legt den Sperrmechanismus fest, der auf die Daten der dem Formular zu Grunde liegenden Datensätze angewendet wird. Es stehen drei Optionen zur Verfügung. Die Option KEINE SPERRUNGEN – der am wenigsten einschränkende Sperrmechanismus – realisiert ein »optimistisches Sperren«, das

Welche Formulareigenschaften stehen zur Verfügung?

177

heißt, Access versucht nicht, den Datensatz zu sperren, bis der Benutzer ihn verlässt. Diese Option kann zu Konflikten führen, wenn zwei Benutzer gleichzeitig denselben Datensatz bearbeiten wollen. Die Option ALLE DATENSÄTZE sperrt sämtliche Datensätze, die dem Formular zugrunde liegen, solange dieses geöffnet ist. Dies ist die am meisten einschränkende Option und sollte nur benutzt werden, wenn der Benutzer des Formulars sicherstellen muss, dass andere Benutzer diese Datensätze nur ansehen, aber nicht bearbeiten dürfen. Die Option BEARBEITETER DATENSATZ sperrt einen 2 KB großen Bereich mit Datensätzen, sobald der Benutzer beginnt, die Daten im Formular zu bearbeiten. Diese Option realisiert ein »pessimistisches Sperren«. Auch wenn sie Konflikte dadurch verhindert, dass zwei Benutzer nicht gleichzeitig denselben Datensatz verändern können, kann sie zu Sperrkonflikten führen. Diese drei Sperrmechanismen werden detailliert in Kapitel 17 behandelt. Andere Eigenschaften eines Formulars Popup: Die Eigenschaft POPUP gibt an, ob das Formular immer im Vordergrund angezeigt wird. Sie wird für benutzerdefinierte Dialogfelder oft zusammen mit der Eigenschaft GEBUNDEN auf JA gesetzt. Gebunden: Die Eigenschaft GEBUNDEN gibt an, ob einem Formular der Fokus entzogen werden kann, während es geöffnet ist. Besitzt die Eigenschaft den Wert JA, muss das Formular geschlossen werden, bevor der Benutzer mit der Anwendung weiterarbeiten kann. Wie bereits erwähnt, wird diese Eigenschaft gemeinsam mit der Eigenschaft POPUP in benutzerdefinierten Dialogfeldern verwendet. Zyklus: Die Eigenschaft ZYKLUS steuert das Verhalten der Tabulatortaste im Formular. Die Optionen sind ALLE DATENSÄTZE, AKTUELLER DATENSATZ und AKTUELLE SEITE. Wenn die Eigenschaft ZYKLUS auf ALLE DATENSÄTZE gesetzt ist, gelangt der Benutzer oder die Benutzerin zum nächsten Datensatz, wenn er oder sie auf dem letzten Steuerelement des Formulars die Tabulatortaste drückt. Beim Wert AKTUELLER DATENSATZ gelangt der Benutzer vom letzten Steuerelement auf dem Formular zum ersten Steuerelement im selben Datensatz. Die Option AKTUELLE Seite, die es nur für mehrseitige Formulare gibt, legt fest, dass der Benutzer durch Drücken der Tabulatortaste vom letzten Steuerelement auf der Seite zum ersten Steuerelement auf derselben Seite gelangt. Alle drei Optionen werden durch die Tabulatorreihenfolge der Objekte auf dem Formular beeinflusst. Menüleiste: Die Eigenschaft MENÜLEISTE bestimmt, welche Menüleiste dem Formular zugeordnet wird. Die Menüleiste, die in Access 2000 manchmal auch als Befehlsleiste bezeichnet wird, wird im Dialogfeld ANPASSEN erstellt, in das man aus dem Ansichtsmenü durch Auswahl von SYMBOLLEISTE|ANPASSEN gelangt. Menüs werden in Kapitel 9 behandelt. Symbolleiste: Die Eigenschaft Symbolleiste bestimmt, welche Symbolleiste dem Formular zugeordnet wird. Die Symbolleiste, die in Access 2000 ebenfalls manchmal als »Befehlsleiste« bezeichnet wird, wird im Dialogfeld ANPASSEN erstellt. Die ausge-

178

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

wählte Symbolleiste wird immer dann angezeigt, wenn das Formular den Fokus hat. Symbolleisten werden in Kapitel 9 behandelt. Kontextmenü, Kontextmenüleiste: Die Eigenschaft KONTEXTMENÜ gibt an, ob ein Kontextmenü angezeigt wird, wenn der Benutzer mit der rechten Maustaste auf ein Objekt auf dem Formular klickt. Mit der Eigenschaft KONTEXTMENÜLEISTE können Sie einem Objekt auf dem Formular oder dem Formular selbst ein benutzerdefiniertes Kontextmenü zuweisen. Genau wie die Standardmenüleiste wird auch die Kontextmenüleiste im Dialogfeld ANPASSEN erstellt, in das man aus dem Ansichtsmenü durch Auswahl von SYMBOLLEISTE|ANPASSEN gelangt. Kontextmenüs werden in Kapitel 9 behandelt. Schneller Laserdruck: Die Eigenschaft SCHNELLER LASERDRUCK legt fest, ob Linien und Rechtecke zusammen mit dem Formular gedruckt werden. Wenn diese Eigenschaft auf JA gesetzt wird, werden Sie feststellen, dass die Ausgabe des Formulars auf einem Laserdrucker erheblich beschleunigt wird. Hilfedatei, Hilfekontext-ID: Mit den Eigenschaften HILFEDATEI und HILFEKONweisen Sie dem Formular eine bestimmte Hilfedatei und Stichworte zu.

TEXT-ID

Marke: Die Eigenschaft MARKE ist eine zusätzliche Eigenschaft, in der beliebige Informationen über das Formular gespeichert werden können. Diese Eigenschaft wird oft zur Laufzeit gesetzt und abgefragt, um notwendige Informationen über das Formular zu speichern. Beispielsweise könnte man einem Satz von Formularen, die gemeinsam aus dem Speicher entfernt werden sollen, eine Marke hinzufügen. Enthält Modul: Die Eigenschaft ENTHÄLT MODUL bestimmt, ob das Formular ein Klassenmodul enthält. Wenn zu Ihrem Formular kein Code gehört, können Ladezeit, Ausführungsgeschwindigkeit und Datenbankgröße erheblich reduziert werden, indem diese Eigenschaft auf NEIN gesetzt wird. Entwurfsänderungen zulassen: Die Eigenschaft ENTWURFSÄNDERUNGEN ZULASbestimmt, ob der Formularentwurf beim Betrachten geändert werden kann. Wenn diese Eigenschaft auf ALLE ANSICHTEN gesetzt ist, steht das Eigenschaftenfenster auch in der Formularansicht zur Verfügung und Änderungen an den Formulareigenschaften innerhalb der Formularansicht bleiben erhalten, wenn das Formular gespeichert wird. SEN

Welche Steuerelementeigenschaften stehen zur Verfügung?

5.9

179

Welche Steuerelementeigenschaften stehen zur Verfügung und warum sollten sie benutzt werden?

Es hängt von der Art des Steuerelements ab, welche Steuerelementeigenschaften verfügbar sind. Die gebräuchlicheren Eigenschaften werden in diesem Abschnitt behandelt, während die übrigen überall im Buch erläutert werden, sobald sie für bestimmte Dinge wichtig sind.

5.9.1

Formateigenschaften eines Steuerelements

Format: Die Eigenschaft FORMAT eines Steuerelements bestimmt, wie die Daten im Steuerelement angezeigt werden. Das Steuerelement erbt sein Format automatisch von seiner zu Grunde liegenden Datenquelle. Diese Eigenschaft wird in drei Situationen genutzt:

 wenn die Eigenschaft FORMAT für das zu Grunde liegende Feld nicht gesetzt ist  wenn Sie das Feldformat überschreiben wollen  wenn Sie einem ungebundenen Steuerelement ein Format geben wollen Sie können aus einer Vielfalt vordefinierter Werte für das Format eines Steuerelements auswählen oder eigene Formate erstellen. Ich verändere diese Eigenschaft oft zur Laufzeit, um das Format eines Steuerelements abhängig von einer bestimmten Bedingung zu verändern. Beispielsweise ist das Format für eine Visa-Kartennummer ein anderes als das für eine ATM-Kartennummer. Dezimalstellenanzeige: Die Eigenschaft DEZIMALSTELLENANZEIGE bestimmt darüber, wie viele Dezimalstellen im Steuerelement erscheinen sollen. Diese Eigenschaft wird zusammen mit der Eigenschaft FORMAT benutzt, um das Erscheinungsbild des Steuerelements festzulegen. Beschriftung: Die Eigenschaft BESCHRIFTUNG wird benutzt, um dem Benutzer hilfreiche Informationen anzuzeigen. Sie steht allerdings nur für Bezeichnungen, Befehlsschaltflächen und Umschaltflächen zur Verfügung. Hyperlink-Adresse: Die Eigenschaft HYPERLINK-ADRESSE ist nur für Befehlsschaltflächen, Bilder und ungebundene Bezeichnungen verfügbar. Sie enthält den UNCPfad (Pfad zu einer Datei) oder URL (Adresse einer Webseite), der mit dem Steuerelement verbunden ist. Wenn das Formular aktiv ist und der Mauszeiger über das Steuerelement bewegt wird, zeigt ein Klick auf das Steuerelement die angegebene Datei oder Webseite an. Hyperlink-Unteradresse: Wie die Eigenschaft HYPERLINK-ADRESSE ist auch die Eigenschaft HYPERLINK-UNTERADRESSE nur für Befehlsschaltflächen, Bilder und ungebundene Bezeichnungen verfügbar. Die Hyperlink-Unteradresse ist eine Zei-

180

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

chenfolge, die auf eine Stelle in dem Dokument verweist, das in der Eigenschaft HYPERLINK-ADRESSE angegeben wurde. Sichtbar: Die Eigenschaft SICHTBAR bestimmt, ob ein Steuerelement sichtbar ist. Diese Eigenschaft kann abhängig von bestimmten Umständen zur Laufzeit umgeschaltet werden. Beispielsweise könnte eine Frage auf dem Formular nur für Datensätze zutreffen, in denen das Geschlechtsmerkmal auf weiblich gesetzt ist. Andernfalls sollte die Frage nicht sichtbar sein. Anzeigen: Die Eigenschaft ANZEIGEN wird benutzt, wenn Sie bestimmte Steuerelemente nur auf dem Bildschirm oder nur auf dem Drucker ausgeben wollen. Die drei Optionen lauten IMMER, NUR BEIM DRUCKEN oder NUR AM BILDSCHIRM. Ein Beispiel für den Gebrauch der Eigenschaft ANZEIGEN ist eine Bezeichnung mit Anweisungen, die nur auf dem Bildschirm, aber nicht auf dem Ausdruck, erscheinen sollen. Bildlaufleisten: Die Eigenschaft BILDLAUFLEISTEN bestimmt, ob Bildlaufleisten erscheinen, wenn die Daten im Steuerelement nicht in die Ausdehnung des Steuerelements hineinpassen. Die Optionen lauten KEINE und VERTIKAL. Ich setze die Eigenschaft BILDLAUFLEISTEN oft auf VERTIKAL, wenn das Steuerelement Daten aus einem Memofeld anzeigen soll. Die Bildlaufleisten erleichtern es dem Benutzer, mit einer großen Datenmenge in einem Memofeld umzugehen. Vergrößerbar, Verkleinerbar: Die Eigenschaften VERGRÖSSERBAR und VERKLEINERBAR beziehen sich nur auf den Ausdruck des Formulars. Die Eigenschaft VERKLEINERBAR kommt dann zur Anwendung, wenn keine Daten in das Steuerelement eingegeben worden sind. Wurde diese Eigenschaft auf JA gesetzt, wird ein Steuerelement ohne Daten weggelassen, so dass keine Leerzeilen gedruckt werden. Links, Oben, Breite, Höhe: Diese Eigenschaften legen die Position und Größe des Steuerelements fest. Hintergrundart, Hintergrundfarbe: Die Eigenschaft HINTERGRUNDART kann auf NORMAL oder TRANSPARENT gesetzt sein. Beim Wert TRANSPARENT sieht man die Hintergrundfarbe des Formulars durch das Steuerelement hindurch. Dies ist oftmals die bevorzugte Einstellung für eine Optionsgruppe. Die Eigenschaft HINTERGRUNDFARBE bestimmt die Hintergrundfarbe (im Gegensatz zur Textfarbe) für das Steuerelement. Ist die Hintergrundart eines Steuerelements auf TRANSPARENT gesetzt, wird seine Hintergrundfarbe ignoriert. Spezialeffekt: Die Eigenschaft SPEZIALEFFEKT fügt 3-D-Effekte zum Steuerelement hinzu. Die Optionen für diese Eigenschaft sind FLACH, ERHÖHT, VERTIEFT, GRAVIERT, SCHATTIERT und UNTERSTRICHEN. Jeder dieser Effekte gibt dem Steuerelement ein anderes Aussehen.

Welche Steuerelementeigenschaften stehen zur Verfügung?

181

Rahmenart, -farbe, breite: Diese Eigenschaften betreffen Aussehen, Farbe und Breite des Rahmens eines Steuerelements. Die Optionen für RAHMENART sind TRANSPARENT, DURCHGEZOGEN, STRICHLINIEN, KURZE STRICHLINIEN, PUNKTE, WENIGE PUNKTE , STRICHLINIE PUNKT und STRICHLINIE PUNKT PUNKT. Die Eigenschaft RAHMENFARBE bestimmt die Farbe des Rahmens und kann aus einer Vielzahl von Farben ausgewählt werden. Die Eigenschaft RAHMENBREITE kann auf eine von verschiedenen Punktgrößen festgelegt werden. Ist die Rahmenart eines Steuerelements auf TRANSPARENT gesetzt, wird seine Rahmenfarbe ignoriert. Textfarbe, Schriftart, Schriftgrad, Schriftbreite, Kursiv, Unterstrichen: Diese Eigenschaften steuern das Erscheinungsbild von Text in einem Steuerelement. Wie ihre Namen vermuten lassen, erlauben sie die Auswahl von Farbe, Schriftart, Größe und Dicke für den Text und legen fest, ob der Text kursiv oder unterstrichen erscheint. Diese Eigenschaften können als Antwort auf ein Laufzeitereignis verändert werden. Zum Beispiel kann sich die Textfarbe eines Steuerelements ändern, wenn der Wert darin einen bestimmten Betrag übersteigt. Die Auswahlmöglichkeiten für die Schriftbreite übersteigen in der Regel die Fähigkeiten der meisten Schriftarten und Drucker – normalerweise haben Sie nur die Wahl zwischen normal und fett, welchen Wert Sie auch auswählen. Textausrichtung: Die Eigenschaft TEXTAUSRICHTUNG wird oft mit der Steuerelementausrichtung verwechselt. Die Eigenschaft TEXTAUSRICHTUNG bestimmt, wie die Daten innerhalb des Steuerelements ausgerichtet werden. Linker Rand, Oberer Rand, Rechter Rand, Unterer Rand: Diese Eigenschaften geben an, wie weit der Text vom linken, oberen, rechten und unteren Rand des Steuerelements entfernt ist. Sie sind besonders nützlich bei großen Steuerelementen wie Textfeldern, denen Memofelder zugrunde liegen. Zeilenabstand: Die Eigenschaft ZEILENABSTAND definiert den Abstand der Zeilen in einem mehrzeiligen Steuerelement. Diese Eigenschaft kommt am häufigsten bei Textfeldern zum Einsatz, denen Memofelder zugrunde liegen. Ist Hyperlink: Wenn diese Eigenschaft auf JA gesetzt ist, werden die Daten im Steuerelement als Hyperlink formatiert. Wenn die Daten im Steuerelement eine gültige Verknüpfung enthalten (z.B. http:\\microsoft.com), werden die Daten als Hyperlink funktionieren.

5.9.2

Dateneigenschaften eines Formulars

Steuerelementinhalt : Die Eigenschaft STEUERELEMENTINHALT bestimmt, welches Feld aus einer Datenquelle dem Steuerelement zu Grunde liegt. Eine Quelle kann auch jeder gültige Access-Ausdruck sein.

182

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Eingabeformat: Die Eigenschaften FORMAT und DEZIMALSTELLENANZEIGE beeinflussen das Erscheinungsbild des Steuerelements, während die Eigenschaft EINGABEFORMAT vorgibt, welche Daten in das Steuerelement eingegeben werden können. Falls vorhanden, wird das Eingabeformat des Feldes, das dem Steuerelement zugrunde liegt, automatisch an das Steuerelement vererbt. Wurde kein Eingabeformat als Feldeigenschaft definiert, kann das Eingabeformat direkt im Formular eingegeben werden. Andernfalls kann das Eingabeformat des Steuerelements die Eingabemöglichkeiten weiter einschränken. Wenn die Eigenschaften FORMAT und EINGABEFORMAT eines Steuerelements unterschiedlich sind, bestimmt der Wert von FORMAT die Anzeige der Daten im Steuerelement so lange, bis das Steuerelement den Fokus erhält. Wenn das Steuerelement den Fokus hat, gilt das EINGABEFORMAT. Standardwert: Die Eigenschaft STANDARDWERT eines Steuerelements bestimmt, welcher Wert neuen Datensätzen zugeordnet wird, die im Formular eingegeben werden. Diese Eigenschaft kann innerhalb der Feldeigenschaften gesetzt werden. Ein Standardwert, der an ein Feld vergeben wird, wird automatisch an das Formular vererbt. Der Standardwert für das Steuerelement überschreibt den eines Feldes. Gültigkeitsregel, Gültigkeitsmeldung: Die Gültigkeitsregel und die Gültigkeitsmeldung für ein Steuerelement haben die gleiche Wirkung wie für ein Feld. Auf dem Niveau der Datenbank-Engine gelten zwingende Gültigkeitsregeln, weshalb die Gültigkeitsregel für ein Steuerelement nicht derjenigen des zugehörigen Feldes widersprechen darf. Andernfalls kann der Benutzer keine Daten in das Steuerelement eingeben. Aktiviert: Die Eigenschaft Aktiviert bestimmt, ob ein Steuerelement den Fokus bekommen darf. Beim Wert NEIN erscheint das Steuerelement abgeblendet. Gesperrt: Die Eigenschaft GESPERRT legt fest, ob die Daten im Steuerelement verändert werden können. Wenn die Eigenschaft GESPERRT auf JA gesetzt ist, kann das Steuerelement den Fokus erhalten, aber nicht bearbeitet werden. Die Eigenschaften AKTIVIERT und GESPERRT eines Steuerelements stehen in Wechselwirkung zueinander. Tabelle 5.1 verdeutlicht diesen Zusammenhang.

Welche Steuerelementeigenschaften stehen zur Verfügung?

Aktiviert

Gesperrt

Wirkung

ja

ja

Das Steuerelement kann den Fokus bekommen und seine Daten können kopiert, aber nicht geändert werden.

ja

nein

Das Steuerelement kann den Fokus bekommen und seine Daten können geändert werden.

nein

ja

Das Steuerelement kann keinen Fokus bekommen.

nein

nein

Das Steuerelement kann keinen Fokus bekommen, seine Daten erscheinen abgeblendet.

183

Tabelle 5.1: Wie aktivierte und gesperrte Eigenschaften zusammenhängen

Filter anwenden: Die Eigenschaft FILTER ANWENDEN zeigt an, ob die Werte, die einem gebundenen Textfeld zugewiesen sind, im Fenster FORMULARBASIERTER FILTER erscheinen sollen.

5.9.3

Andere Eigenschaften eines Formulars

Name: Die Eigenschaft NAME erlaubt Ihnen, das Steuerelement zu benennen. Dieser Name dient zum Ansprechen des Steuerelements im Code und taucht in verschiedenen aufklappbaren Listen auf, die alle Steuerelemente eines Formulars anzeigen. Es ist wichtig, dass Ihre Steuerelemente einen Namen haben, denn benannte Steuerelemente verbessern die Lesbarkeit Ihres Codes und erleichtern die Arbeit mit Access-Formularen und anderen Objekten. Die Regeln zur Namensvergabe für Steuerelemente werden im Anhang abgehandelt. Statusleistentext: Die Eigenschaft STATUSLEISTENTEXT gibt den Text an, der in der Statusleiste erscheint, wenn das Steuerelement den Fokus erhält. Das Setzen dieser Eigenschaft überschreibt die Eigenschaft BESCHREIBUNG, die im Tabellenentwurf vorhanden sein kann. Eingabetasten-Verhalten: Die Eigenschaft EINGABETASTEN-VERHALTEN bestimmt, ob die Eingabetaste die Einfügemarke zum nächsten Steuerelement springen lässt oder im aktuellen Steuerelement eine neue Zeile einfügt. Letzteres wird oft bei Textfeldern angewandt, die den Inhalt von Memofeldern anzeigen. AutoKorrektur zulassen: Die Eigenschaft AUTOKORREKTUR ZULASSEN legt fest, ob im Steuerelement die AutoKorrektur verfügbar ist. Die AutoKorrektur berichtigt automatisch häufige Schreibfehler. Vertikal: Die Eigenschaft VERTIKAL steuert, ob der Text im Steuerelement horizontal oder vertikal angezeigt wird. Die Vorgabe lautet NEIN bzw. horizontal. Wenn VERTIKAL ausgewählt ist, wird der Text im Steuerelement um 90° gedreht.

184

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Automatisch weiter: Ist die Eigenschaft AUTOMATISCH WEITER auf JA gesetzt, springt die Einfügemarke automatisch zum nächsten Steuerelement, wenn das letzte Zeichen eines Eingabeformats eingegeben worden ist. Manche Benutzer mögen diese Option, andere finden sie lästig, besonders wenn es aus manchen Feldern nur mit der Tabulatortaste weitergeht und aus anderen nicht. Standard: Die Eigenschaft STANDARD bezieht sich auf eine Befehlsschaltfläche oder ein ActiveX-Steuerelement und bestimmt, ob das Steuerelement die Standardschaltfläche auf dem Formular darstellt. Abbrechen: Die Eigenschaft ABBRECHEN bezieht sich auf eine Befehlsschaltfläche oder ein ActiveX-Steuerelement und gibt an, dass der Code des Steuerelements ausgeführt werden soll, wenn das Formular aktiv ist und die Esc-Taste gedrückt wird. Makro Wiederholen: Die Eigenschaft MAKRO WIEDERHOLEN bestimmt, ob eine Prozedur oder ein Makro wiederholt ausgeführt werden sollen, solange die Befehlsschaltfläche gedrückt ist. Statusleistentext: Die Eigenschaft STATUSLEISTENTEXT bestimmt die Meldung, die in der Statusleiste erscheint, wenn das Steuerelement den Fokus hat. In Reihenfolge: Die Eigenschaft IN REIHENFOLGE legt fest, ob die Tabulatortaste benutzt werden kann, um zu einem Steuerelement zu gelangen. Diese Eigenschaft sollte für Steuerelemente, deren Werte selten verändert werden, auf NEIN gesetzt werden. Wird das Steuerelement doch einmal gebraucht, kann der Benutzer es anklicken. Reihenfolgenposition: Die Eigenschaft REIHENFOLGENPOSITION legt den Platz in der Tabulatorreihenfolge für das Steuerelement fest. Im Allgemeinen setze ich die Eigenschaft REIHENFOLGENPOSITION über ANSICHT|AKTIVIERREIHENFOLGE, statt den Wert direkt in der Eigenschaft REIHENFOLGENPOSITION des Steuerelements einzutragen. Kontextmenüleiste: Die Kontextmenüleiste ordnet einem Steuerelement ein bestimmtes Menü zu. Die Menüleiste erscheint, wenn der Benutzer mit der rechten Maustaste auf das Steuerelement klickt. SteuerelementTipp-Text: Die Eigenschaft STEUERELEMENTTIPP-TEXT legt den Kurzhinweis für das Steuerelement fest. Der Kurzhinweis erscheint automatisch, sobald der Benutzer den Mauszeiger über das Steuerelement bewegt und einen Moment dort lässt. HilfekontextID: Die Eigenschaft HILFEKONTEXTID bestimmt die Hilfsanzeige, die dem Steuerelement zugeordnet ist. Marke: Die Eigenschaft MARKE ist eine zusätzliche Eigenschaft, in der beliebige Informationen über ein Steuerelement gespeichert werden können und die zur Laufzeit gelesen und geändert werden kann.

Gebundene, ungebundene und berechnete Steuerelemente

5.10

185

Gebundene, ungebundene und berechnete Steuerelemente

 Es gibt wichtige Unterschiede zwischen gebundenen und ungebundenen Steuerelementen. »Ungebundene Steuerelemente« zeigen Informationen an oder empfangen Informationen vom Benutzer, die nicht in der Datenbank gespeichert werden sollen. Hier einige Beispiele für ungebundene Steuerelemente:

 Ein Bezeichnungsfeld, das dem Benutzer Anweisungen gibt  Ein Logo, das auf dem Formular angezeigt wird  Ein Kombinations- oder Textfeld auf dem Formular, in das der Benutzer Parameter für einen Bericht eingeben kann

 Ein Rechteck, das auf das Formular gebracht wird, um mehrere Steuerelemente logisch zu gruppieren »Gebundene Steuerelemente« werden benutzt, um Informationen anzuzeigen und zu bearbeiten, die in einer Datenbanktabelle gespeichert sind. Ein gebundenes Steuerelement erscheint automatisch in dem Formular, das in seiner Eigenschaft STEUERELEMENT ANZEIGEN angegeben wurde, und das Steuerelement erbt automatisch viele der Attribute von dem Feld, an das es gebunden ist. Die Eigenschaft STEUERELEMENT ANZEIGEN wird im Tabellenentwurf festgelegt und bestimmt, welcher Art das gebundene Steuerelement ist, das zu einem Formular oder Bericht hinzugefügt wird. Ein »berechnetes Steuerelement« ist eine besondere Art von Steuerelement, das die Ergebnisse einer Berechnung anzeigt. Die Daten in einem berechneten Steuerelement können vom Benutzer nicht verändert werden. Der Wert des Steuerelements ändert sich automatisch, wenn sich die Werte des Ausdrucks ändern, der ihn berechnet. Beispielsweise ändert sich die Gesamtsumme, wenn der Preis oder die Menge verändert wird.

5.11

Formulare mit Hilfe von Ausdrücken erweitern

Wie im vorigen Abschnitt erwähnt, kann ein Steuerelement jeden beliebigen Ausdruck als Datensatzherkunft verwenden. Soll ein Ausdruck als Datenquelle des Steuerelements dienen, muss dem Ausdruck ein Gleichheitszeichen vorangestellt werden. Die Datenquelle kann von Hand eingegeben werden oder Sie benutzen den Ausdrucks-Generator, um den Vorgang zu vereinfachen.

186

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Um einen Ausdruck zur Datenquelle eines Steuerelements hinzuzufügen, beginnen Sie mit dem Hinzufügen eines ungebundenes Steuerelements zum Formular. Um den Ausdrucks-Generator zu starten, klicken Sie auf die Eigenschaft DATENSATZHERKUNFT des Formulars und anschließend auf die Schaltfläche mit den drei Punkten. Dies bringt Sie ins Dialogfeld AUSDRUCKS-GENERATOR (siehe Abbildung 5.29.) Im Listenfeld links wählen Sie die Art des Objekts aus, das Sie im Ausdruck verwenden wollen. Das mittlere und rechte Listenfeld lässt Sie die Elemente festlegen, die Sie in Ihren Ausdruck einfügen wollen. Der Ausdrucks-Generator ist sinnvoll, wenn Ihnen die jeweilige für den Ausdruck erforderliche Syntax nicht vertraut ist. Ein Ausdruck kann auch direkt in das Textfeld des Steuerelementinhalts eingegeben werden. Um den Ausdruck leichter betrachten zu können, steht Ihnen die ZoomFunktion zur Verfügung (Umschalt+F2). Das Dialogfeld ZOOM für den Steuerelementinhalt sehen Sie in Abbildung 5.30. Der dort dargestellte Ausdruck berechnet die Auszahlungssumme. Wenn die Auszahlungssumme größer oder gleich 1000 ist, wird die Meldung »Big Hitter« und sonst nichts angezeigt.

Abbildung 5.29: Der Ausdrucks-Generator hilft Ihnen beim Hinzufügen eines Ausdrucks als Datenquelle für ein Steuerelement

Abbildung 5.30: Das Dialogfeld ZOOM für eine Steuerelementquelle

Die Befehlsschaltflächen-Assistenten: Programmierung ohne Eingabe

5.12

187

Die Befehlsschaltflächen-Assistenten: Programmierung ohne Eingabe

Mit dem Befehlsschaltflächen-Assistenten können Sie Ihren Formularen schnell und einfach Funktionalität hinzufügen. Der Assistent schreibt den Code für 33 häufig erforderliche Aufgaben aus den Bereichen Datensatznavigation, Datensatzoperationen, Formularoperationen, Berichtsoperationen, Anwendung und Diverse. Der Befehlsschaltflächen-Assistent wird automatisch aufgerufen, wenn Sie eine Befehlsschaltfläche hinzufügen und gleichzeitig die Schaltfläche STEUERELEMENT-ASSISTENTEN aktiviert ist. Den ersten Schritt des Befehlsschaltflächen-Assistenten sehen Sie in Abbildung 5.31. Hier geben Sie die Art der Aktivität und die besonderen Aktionen an, welche die Befehlsschaltfläche durchführen soll. Die folgenden Schritte des Assistenten unterscheiden sich in Abhängigkeit von der ausgewählten Kategorie und Aktion.

Abbildung 5.31: Der erste Schritt des BefehlsschaltflächenAssistenten

Abbildung 5.32 zeigt, wie der zweite Schritt des Befehlsschaltflächen-Assistenten aussieht, wenn im ersten Schritt die Kategorie FORMULAROPERATIONEN und FORMULAR ÖFFNEN ausgewählt wurden. Beachten Sie, dass dieser Schritt fragt, welches Formular Sie öffnen wollen. Nachdem Sie ein Formular ausgewählt und WEITER angeklickt haben, werden Sie gefragt, ob Access das Formular öffnen und bestimmte Daten zum Anzeigen suchen soll, oder ob Sie möchten, dass das Formular geöffnet wird und alle Datensätze angezeigt werden. Wenn Sie angeben, dass nur bestimmte Datensätze angezeigt werden sollen, erscheint das Dialogfeld aus Abbildung 5.33. Dieses fordert Sie auf, Felder auszuwählen, die eine Beziehung zwischen den beiden Formularen herstellen. Im nächsten Schritt des Assistenten wählen Sie einen Text oder ein Bild für die Befehlsschaltfläche aus. Der letzte Schritt des Assistenten fragt Sie nach dem Namen für die Befehlsschaltfläche.

188

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.32: Der Befehlsschaltflächen-Assistent erwartet die Auswahl des Namens eines zu öffnenden Formulars

Abbildung 5.33: Der Befehlsschaltflächen-Assistent erwartet die Auswahl der Felder mit Bezug auf jedes Formular

Am Befehlsschaltflächen-Assistenten überrascht am meisten, wie unterschiedlich er in Abhängigkeit von den ausgewählten Merkmalen funktioniert. Er gestattet das Hinzufügen komplizierterer Funktionalitäten zu Ihrer Anwendung, ohne dass Sie eine einzige Zeile Code schreiben müssen. Den Code, der für das eben genannte Beispiel generiert wurde, sehen Sie in Abbildung 5.34; er wird viel verständlicher, wenn Sie die nächsten Kapitel gelesen haben. Der Vorteil des vom BefehlsschaltflächenAssistenten generierten Codes ist, dass er vollständig verändert werden kann, nachdem er geschrieben wurde. Access nimmt Ihnen also einiges an Routinearbeit ab und liefert ein Ergebnis, das Sie ganz an Ihre Vorstellungen anpassen können.

189

Formulare auf der Grundlage mehrerer Tabellen

Abbildung 5.34: Der vom BefehlsschaltflächenAssistenten erzeugte Code

5.13

Formulare auf der Grundlage mehrerer Tabellen

Viele Formulare sind auf mehreren Tabellen aufgebaut. Beispielsweise wird ein Formular, das oben einen Kunden und darunter dessen Aufträge zeigt, als 1:n-Formular betrachtet. Formulare können auch auf einer Abfrage basieren, die mehrere Tabellen verknüpft. Anstatt in solch einem Formular eine 1:n-Beziehung zu sehen, werden die beiden Tabellen als eine angezeigt, wobei jeder Datensatz auf der Mehrfachseite der Beziehung mit seinen übergeordneten Daten erscheint.

5.13.1

1:n-Formulare erstellen

Es gibt verschiedene Möglichkeiten, 1:n-Formulare zu erstellen. Wie bei vielen anderen Arten von Formularen können Sie sich von einem Assistenten helfen lassen oder das Formular eigenhändig entwerfen. Weil alle Methoden der Formularerstellung für Benutzer und Entwickler gleichermaßen nützlich sind, werden in diesem Abschnitt die verfügbaren Optionen behandelt. Ein 1:n-Formular mit Hilfe des Formular-Assistenten erstellen Das Erstellen eines 1:n-Formulars mit Hilfe des Formular-Assistenten ist ein einfacher Vorgang, der zehn Schritte umfasst:

190

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

1. Klicken Sie in der Objektliste auf FORMULAR und doppelklicken Sie dann auf ERSTELLT EIN FORMULAR UNTER VERWENDUNG DES ASSISTENTEN. 2. Wählen Sie aus dem aufklappbaren Listenfeld TABELLEN/ABFRAGEN die Tabelle oder Abfrage aus, die auf der 1-Seite der Beziehung erscheinen soll. 3. Wählen Sie die Felder aus, die Sie von der 1-Seite der Beziehung aus verwenden wollen. 4. Wählen Sie aus dem aufklappbaren Listenfeld TABELLEN/ABFRAGEN die Tabelle oder Abfrage aus, die auf der Mehrfachseite der Beziehung erscheinen soll. 5. Wählen Sie die Felder aus, die Sie von der Mehrfachseite der Beziehung aus verwenden wollen. 6. Klicken Sie auf WEITER. 7. Entscheiden Sie, ob das übergeordnete Formular mit Unterformularen oder ob die untergeordneten Formulare als verknüpfte Formulare erscheinen sollen (siehe Abbildung 5.35). Klicken Sie auf WEITER.

Abbildung 5.35: Der Formular-Assistent beim Erstellen eines 1:nFormulars

8. Wenn Sie die Option FORMULAR MIT UNTERFORMULAR(EN) auswählen, müssen Sie angeben, ob das Unterformular in tabellarischer Form oder als Datenblatt erscheinen soll. Diese Option ist nicht verfügbar, wenn im siebten Schritt VERKNÜPFTE FORMULARE ausgewählt wurde. Klicken Sie auf WEITER. 9. Wählen Sie ein Format für das Formular aus und klicken Sie auf WEITER. 10. Geben Sie dem Formular und dem Unterformular einen Namen und klicken Sie auf FERTIG STELLEN.

191

Formulare auf der Grundlage mehrerer Tabellen

Das Ergebnis ist ein Hauptformular, das ein Unterformular enthält. Ein Beispiel sehen Sie in Abbildung 5.36

Abbildung 5.36: Das Ergebnis des Erstellens eines 1:n-Formulars mit dem FormularAssistenten

Ein 1:n-Formular mit Hilfe des Unterformular/Unterbericht-Assistenten erstellen Ein 1:n-Formular kann auch durch Erstellen des übergeordneten Formulars und anschließendes Hinzufügen eines Unterformular/-berichts-Steuerelements aus der Toolbox geschaffen werden. Wenn Sie den Unterformular/Unterberichts-Assistenten benutzen wollen, überzeugen Sie sich davon, dass das Werkzeug STEUERELEMENT-ASSISTENTEN ausgewählt ist, bevor Sie das Unterformular/-berichts-Steuerelement zum Hauptformular hinzufügen. Danach folgen sechs Schritte: 1. Klicken Sie auf das Steuerelement UNTERFORMULAR/-BERICHT. 2. Klicken Sie auf die Stelle des Hauptformulars, an der Sie das Unterformular einfügen möchten. Dadurch wird der Unterformular-Assistent aufgerufen. 3. Entscheiden Sie, ob Sie ein bestehendes Formular als Unterformular verwenden oder ein neues Unterformular auf einer Tabelle oder Abfrage aufbauen wollen. 4. Wenn Sie TABELLEN/ABFRAGEN auswählen, fragt der nächste Schritt des Unterformular-Assistenten nach der Tabelle/Abfrage und den Feldern, die Sie daraus verwenden wollen (siehe Abbildung 5.37). Wählen Sie die Felder aus und klicken Sie auf WEITER. 5. Der nächste Schritt des Unterformular-Assistenten fragt Sie nach der Beziehung zwischen den Feldern der beiden Formulare. Sie können die vorgeschlagene Beziehung auswählen oder eine eigene definieren (siehe Abbildung 5.38). 6. Benennen Sie das Unterformular und klicken Sie auf FERTIG STELLEN. Das entstandene Formular sollte so ähnlich aussehen wie ein Formular, das mit dem Formular-Assistenten erstellt worden ist. Das Erstellen eines 1:n-Formulars auf diese Art stellt einfach nur eine Alternative zum Formular-Assistenten dar.

192

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.37: Felder zum Einbinden in das Unterformular auswählen

Abbildung 5.38: Die Beziehung zwischen dem Haupt- und dem Unterformular definieren

Ein anderer Weg zum Hinzufügen eines Unterformulars zu einem Hauptformular besteht darin, ein Formular im Datenbankfenster anzuklicken und auf das Hauptformular zu ziehen. Access versucht anschließend, die Beziehung zwischen den beiden Formularen herauszufinden.

Formulare auf Abfragen aufsetzen

5.13.2

193

Unterformulare

Nachdem ein Unterformular hinzugefügt worden ist, müssen Sie verstehen, wie man damit arbeitet. Machen Sie sich zunächst mit den folgenden Eigenschaften eines Unterformular-Steuerelements vertraut: Herkunftsobjekt: Der Name des Formulars, der im Steuerelement angezeigt wird Verknüpfen von: Die Felder des Unterformulars, die dieses mit dem Hauptformular verknüpfen Verknüpfen nach: Die Felder des Hauptformulars, durch die das Unterformular mit diesem verknüpft wird Ebenso sollten Sie verstehen, wie Unterformulare geändert werden. Eine Möglichkeit besteht darin, das Unterformular wie jedes andere Formular zu öffnen. Nach dem Schließen und Sichern des Formulars erscheinen alle Änderungen dann automatisch im Hauptformular. Die andere Möglichkeit ist, das Unterformular aus dem Hauptformular heraus zu bearbeiten. Bei geöffnetem Hauptformular sieht man auch das Unterformular. Alle Änderungen, die innerhalb des Hauptformulars am Entwurf des Unterformulars durchgeführt werden, sind dauerhaft. Die Standardansicht des Unterformulars ist DATENBLATT oder ENDLOSFORMULAR, je nachdem, wie Sie das Unterformular unter Verwendung welcher Optionen hinzugefügt haben. Wenn Sie die Standardansicht verändern wollen, bearbeiten Sie einfach die Standardansicht des Unterformulars. Wenn ein Unterformular in der Datenblattansicht gezeigt wird, ist die Reihenfolge der Felder im Unterformular völlig unabhängig von dem Datenblatt, das im Hauptformular erscheint. Die Reihenfolge der Spalten hängt ausschließlich von der Aktivierreihenfolge der Felder im Unterformular ab. Sie müssen daher die Aktivierreihenfolge der Felder im Unterformular bearbeiten, um die Reihenfolge der Felder im Datenblatt zu verändern.

5.14

Formulare auf Abfragen aufsetzen

Eine Strategie der Formularerstellung ist das Aufsetzen auf Abfragen, wodurch Sie grundsätzlich eine optimale Geschwindigkeit und eine hohe Flexibilität erzielen. Anstatt alle Felder und Datensätze über das Netzwerk zu senden, übertragen Sie nur diejenigen, die wirklich gebraucht werden. Die Vorteile dieser Strategie werden erheblich deutlicher, wenn Sie in einer Client-Server-Umgebung tätig sind, in der die Abfrage auf dem Server abgearbeitet wird. Auch in einer Umgebung, in der die Daten im Access-Dateiformat (.MDB) auf einem Datei-Server gespeichert werden, kann ein Formular, das auf einer Abfrage basiert, die Vorteile der Indizierung und der Spei-

194

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

cherverwaltung von Access besser ausnutzen. Durch das Aufsetzen des Formulars auf einer Abfrage haben Sie zudem eine bessere Kontrolle darüber, welche Datensätze in das Formular aufgenommen werden und in welcher Reihenfolge sie erscheinen. Außerdem können Sie ein Formular auch auf einer 1:n-Verknüpfung aufbauen, wobei Haupt- und Detailinformationen wie ein Datensatz dargestellt werden. Beachten Sie, dass in Abbildung 5.39 die Kunden- und Projektinformationen auf dem Formular so erscheinen, als wären sie ein Datensatz.

Abbildung 5.39: Ein Formular auf der Grundlage einer 1:nAbfrage

5.14.1

Eingebettete SQL-Anweisungen und gespeicherte Abfragen im Vergleich

In früheren Access-Versionen boten gespeicherte Abfragen eine bessere Leistung als eingebettete SQL-Anweisungen. Der Grund dafür liegt darin, dass Access beim Speichern einer Abfrage diese kompiliert und einen Abfrageplan generiert, der Informationen über das Optimieren der Abfrage hinsichtlich Datenmenge und verfügbarer Indizes enthält. Wenn in früheren Access-Versionen ein Formular auf einer eingebetteten SQL-Anweisung aufgebaut war, wurde die SQL-Anweisung bei jedem Öffnen des Formulars erneut kompiliert und optimiert. In Access 2000 werden eingebettete SQL-Anweisungen jedoch genauso kompiliert wie gespeicherte Abfragen. Vielleicht fragen Sie sich jetzt, ob es in Access 2000 besser ist, eine Abfrage auf einer gespeicherten Abfrage oder auf einer SQL-Anweisung aufzubauen. Ich bevorzuge Folgendes: Habe ich vor, dieselbe oder eine vergleichbare Abfrage zusammen mit mehreren Formularen und Berichten zu verwenden, erstelle ich eine Abfrage und baue die Formulare und Berichte darauf auf. Dadurch muss ich die Abfrage nicht doppelt und dreifach erstellen. Brauche ich dagegen eine Abfrage, die nur in einem Formular vorkommt, baue ich sie als eingebettete SQL-Anweisung auf. Dadurch spare ich in der Datenbank den Platz, den eine Abfrage nun einmal einnimmt.

Access-Formulare und das Internet

195

Ein Abfrageplan kann manchmal ungenau sein, weil er die Abfrage anhand der Datenmenge in den Tabellen optimiert, die dem Formular zugrundeliegen. Unterliegt die Datenmenge in diesen Tabellen starken Schwankungen, muss der Abfrageplan neu erstellt werden. Dies kann durch Öffnen, Ausführen und Speichern der Abfrage oder durch Komprimieren der Datenbank geschehen.

5.15

Access-Formulare und das Internet

Microsoft hat die Entwicklung Internet-fähiger Anwendungen vereinfacht, indem Hyperlinks zu Formularen hinzugefügt und Access-Formulare als HTML oder im Microsoft-IIS-Format (Version 1 oder 2) gespeichert werden können. Diese Möglichkeiten werden in den folgenden Abschnitten behandelt.

5.15.1

Einem Formular einen Hyperlink hinzufügen

Hyperlinks können zu ungebundenen Bezeichnungsfeldern (Bezeichnungsfelder, die nicht mit einem Textfeld oder einem anderen Objekt verbunden sind), Schaltflächen und Bild-Steuerelementen hinzugefügt werden. Sind sie vorhanden, kann der Benutzer zu einem Dokument (UNC) oder einer Homepage (URL) springen, indem er einfach das Steuerelement mit dem Hyperlink anklickt. Zum Hinzufügen eines Hyperlinks zu einem Bezeichnungsfeld, einer Schaltfläche oder einem Bild-Steuerelement gehen Sie folgendermaßen vor: 1. Klicken Sie das Steuerelement an, um es auszuwählen. 2. Sehen Sie sich die Steuerelementeigenschaften an. 3. Wählen Sie die Registerkarte FORMAT des Eigenschaftenfensters. 4. Klicken Sie auf die Eigenschaft HYPERLINK-ADRESSE. 5. Klicken Sie auf die Erstellen-Schaltfläche (die drei Punkte), um das Dialogfeld HYPERLINK EINFÜGEN zu öffnen (siehe Abbildung 5.40). 6. Haben Sie unter LINK ZU die Schaltfläche DATEI ODER WEBSEITE ausgewählt, können Sie einen Dateipfad oder einen URL im Textfeld eingeben oder auf DATEI bzw. WEBSEITE klicken, um eine Datei oder URL zu suchen. Sie können auch Hyperlinks auf zuletzt verwendete Dateien, betrachtete Webseiten oder eingefügte Verknüpfungen erzeugen. Wenn Sie unter LINK ZU die Schaltfläche AKTUELLE DATENBANK auswählen, können Sie eine Verknüpfung zu einem Objekt in der aktuellen Datenbank erstellen (siehe Abbildung 5.41). Wählen Sie NEUE SEITE ERSTELLEN, um eine neue Datenzugriffsseite zu erstellen, oder wählen Sie E-MAIL-ADRESSE aus, um eine Verknüpfung zu einer E-Mail-Adresse zu definieren.

196

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Abbildung 5.40: Mit Hilfe des Dialogfelds Hyperlink einfügen eine Verknüpfung zu einer Datei oder einem URL einrichten

Abbildung 5.41: Innerhalb einer Access-Datenbank einen Ort für einen Hyperlink festlegen

7. Klicken Sie auf OK, um den Vorgang abzuschließen. Der Inhalt des Textfeldes DATEITYP ODER WEBSEITE wird zur Hyperlink-Adresse und der Objektname wird zur Hyperlink-Unteradresse (siehe Abbildung 5.42). Das Verwenden einer Hyperlink-Adresse zum Öffnen eines Objekts in einer Access-Datenbank anstelle des Klick-Ereignisses BEIM KLICKEN der Schaltfläche und VBA-Code erlaubt es Ihnen, das Klassenmodul des Formulars zu entfernen (vorausgesetzt, dies ist die einzige Prozedur, die Sie für das Formular benötigen) und damit die Leistung des Formulars zu optimieren.

Access-Formulare und das Internet

197

Abbildung 5.42: Für ein Bezeichnungssteuerelement definierte HyperlinkAdresse und -Subadresse

5.15.2

Ein Formular als HTML speichern

Formulare können auf zwei Arten als HTML-Dokumente gespeichert werden. Die erste Methode sieht vor, das Formular als HTML zu speichern, indem Sie DATEI|EXPORTIEREN auswählen. (Sie können das Formular auch im Datenbankfenster mit der rechten Maustaste anklicken und EXPORTIEREN auswählen.) Dies ruft das Dialogfeld EXPORTIEREN VON FORMULAR auf. Wählen Sie HTML-DOKUMENTE (*.HTML;*.HTM) aus dem aufklappbaren Listenfeld DATEITYP aus. Geben Sie einen Dateinamen für das HTML-Dokument ein. Wenn nach dem Sichern des HTML-Dokuments der standardmäßige Browser des Systems geladen werden soll, klicken Sie auf AUTOSTART. Klicken Sie danach auf SPEICHERN. Es erscheint das Dialogfeld HTML-AUSGABEOPTIONEN. Klicken Sie ggf. auf DURCHSUCHEN, um eine HTML-Vorlage zu finden. Klicken Sie anschließend auf OK, um das Dialogfeld HTML-AUSGABEOPTIONEN zu schließen. Nur das Datenblatt, das dem Formular zugeordnet ist, wird als HTML gespeichert, das Format des Formulars selbst dagegen nicht. Die andere Methode besteht in der Auswahl von DATEI|SPEICHERN UNTER. Wählen Sie in diesem Fall DATENZUGRIFFSSEITE aus dem aufklappbaren Listenfeld ALS. Weitergehende Informationen finden Sie in Kapitel 32.

198

5.15.3

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Ein Formular für den Internet Information Server oder als Active Server Pages speichern

Formulare können auch für den Microsoft Internet Information Server (Version 1 oder 2) oder als Active Server Pages gespeichert werden. Beide Möglichkeiten erstellen dynamische Formulare. Im Falle des Microsoft IIS werden die .HTX- und .IDCDateien benutzt, um eine .HTM-Datei mit den aktuellen Daten aufzubauen. Die .IDCDatei enthält Informationen über die Datenquelle einschließlich des Datenquellennamens, des Benutzernamens, des Passwortes und der Abfrage, welche die Datensatzherkunft des erstellten Formulars zurückgibt. Die .HTX-Datei ist eine HTMLDatei, die Code enthält, welcher angibt, wo die zurückgegebenen Daten eingefügt werden sollen. Mit Hilfe von Active Server Pages erstellt der Microsoft Information Server ebenfalls eine .HTM-Datei mit den aktuellen Daten. Diese und andere Punkte zum Erstellen von Access-Anwendungen für das Internet werden detaillierter in Kapitel 31 behandelt.

5.15.4

Für die Praxis

Formulare für Ihre Anwendung entwerfen Das Zeit- und Abrechnungssystem erfordert verschiedene Formulare. Die wichtigeren werden in diesem Abschnitt entworfen und sind auf der CD-ROM in der Datei CHAP5.MDB enthalten.

Die Formulare, die in diesem Abschnitt erstellt werden, sind recht komplex. Wenn Sie es vorziehen, können Sie die vollständigen Formulare aus CHAP5.MDB benutzen, anstatt sie selbst aufzubauen.

5.15.5

Das Kundenformular entwerfen

Abbildung 5.43 zeigt das Formular frmClients, ein 1:n-Formular mit einem Unterformular namens fsubClients. Das Hauptformular baut auf der Abfrage qryClients auf, während dem Unterformular die Abfrage qryClientsSub zugrunde liegt. Der Formularfuß enthält drei Schaltflächen. Die Schaltfläche VIEW PROJECTS öffnet das Formular frmProjects mit einer Where-Bedingung, wobei nur die Projekte gezeigt werden, die zum Kunden auf dem Hauptformular gehören. Die Schaltfläche VIEW PAYMENTS öffnet das Formular frmPayments für die Projekte, die im Unterformular fsubClients ausgewählt worden sind. Anstatt in der Anweisung OpenForm eine WhereBedingung zu benutzen, werden die Kriterien in der Abfrage gesetzt, die dem Formu-

Access-Formulare und das Internet

199

Abbildung 5.43: Das frmClientsFormular zeigt alle Projekte, die mit einem ausgewählten Kunden in Zusammenhang stehen

lar frmPayment zu Grunde liegt. Das Formular frmTimeCards wird ohne Rücksicht auf den ausgewählten Kunden geöffnet, wenn man auf die Schaltfläche VIEWTIMECARDS klickt. Man kann hier unabhängig vom Kunden Zeitkarten für jedes Projekt eingeben. Das Formular kann auch mit einem Hyperlink geöffnet werden. Werfen Sie jetzt einen Blick auf die Schritte, die erforderlich sind, um eine Schaltfläche hinzuzufügen, wie z.B. die Schaltfläche VIEW PROJECTS. Zu diesem Zweck können Sie vom Schaltflächen-Assistenten Gebrauch machen. Wählen Sie im Assistenten die Kategorie FORMULAROPERATIONEN und als Aktion FORMULAR ÖFFNEN. Überzeugen Sie sich davon, dass Sie das Formular frmProjects mit einer WhereBedingung öffnen, indem Sie im dritten Schritt des Befehlsschaltflächen-Assistenten die Option DAS FORMULAR ÖFFEN UND BESTIMMTE DATEN SUCHEN UND ANZEIGEN auswählen. Nennen Sie die Schaltfläche cmdProjects. Es muss noch eine wichtige Zeile zu dem Stück Code hinzugefügt werden, das der Schaltflächen-Assistent geschrieben hat. Hierzu klicken Sie auf die Schaltfläche, deren Code Sie bearbeiten wollen, während Sie sich in der Entwurfsansicht für frmClients befinden. Betrachten Sie die Ereigniseigenschaften der Schaltfläche und klicken Sie dann die Schaltfläche mit den drei Punkten rechts vom Ereignis BEIM KLICKEN für die Schaltfläche an. Fügen Sie die folgende Zeile Code vor der Zeile stDocNAme = "frmProjects" ein: DoCmd.RunCommand acCmdSaveRecord

Diese Code-Zeile sichert den aktuellen Kundendatensatz, bevor eines der anderen Formulare geöffnet wird. Die vollständige Routine könnte zum Beispiel folgendermaßen aussehen: Sub cmdProjects_Click() On Error GoTo Err_cmdProjects_Click

200

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Dim stDocName As String Dim stLinkCriteria As String DoCmd.RunCommand acCmdSaveRecord stDocName = "frmProjects" stLinkCriteria = "[ClientID]=" & Me.[txtClientID] DoCmd.OpenForm stDocName, , , stLinkCriteria Exit_cmdProjects_Click: Exit Sub Err_cmdProjects_Click: MsgBox Err.Description Resume Exit_cmdProjects_Click End Sub

Nennen Sie die beiden anderen Schaltflächen cmdPayments und cmdTimeCards. Legen Sie die Eigenschaft HYPERLINK-ADRESSE für jede Schaltfläche so fest, dass sie auf die aktuelle Datenbank zeigt. Setzen Sie die Eigenschaft HYPERLINK-UNTERADRESSE von cmdPayments so, dass sie das Formular frmPayments öffnet, und geben Sie die Eigenschaft HYPERLINK-UNTERADRESSE von cmdTimeCards so an, dass das Formular frmTimeCards geöffnet wird.

5.15.6

Das Zeitkartenformular entwerfen

Das Formular frmTimeCards basiert auf der Abfrage qryTimeCards und enthält zwei Unterformulare (siehe Abbildung 5.44). Das erste Unterformular heißt fsubTimeCards und das zweite fsubTimeCardsExpenses. Das Unterformular fsubTimeCards baut auf der Abfrage qrySubTimeCards auf und enthält ein berechnetes Steuerelement im Formularfuß. Dieses Steuerelement heißt txtTotalHoursWorked und enthält den Ausdruck =Summe(BillableHours), der die Summe der abrechenbaren Stunden im Unterformular ermittelt. Das Unterformular fsubTimeCardsExpenses basiert auf der Abfrage qrySubTimeCardsExpenses und umfasst ebenfalls ein berechnetes Steuerelement im Formularfuß. Das Steuerelement heißt txtTotalExpenses und enthält den Ausdruck =Summe(ExpenseAmount), der die Summe der Ausgaben im Unterformular ermittelt. Der Fuß des Formulars frmTimeCards enthält zwei Steuerelemente: txtTotalBillableHours und txtTotalExpenses, wobei das Steuerelemente txtTotalBillableHours den folgenden Ausdruck einschließt: =[fsubTimeCards].[Formular]![txtTotalHoursWorked]

Access-Formulare und das Internet

201

Abbildung 5.44: Das frmTimeCards-Formular zeigt alle Arbeitszeiten und Ausgaben für einen bestimmten Mitarbeiter

Dieser Ausdruck übernimmt das Ergebnis der Berechnung des Steuerelements txtTotalHoursWorked auf dem Unterformular fsubTimeCards. Das Steuerelement txtTotalExpenses umfasst den folgenden Ausdruck: =[fsubTimeCardsExpenses].[Formular]![txtTotalExpenses]

Dieser Ausdruck weist das Ergebnis der Berechnung des Steuerelements txtTotalExpenses auf dem Unterformular fsubTimeCardsExpenses zu.

5.15.7

Das Zahlungenformular entwerfen

Das Formular frmPayments basiert auf der Abfrage qryPayments, welche das folgende Kriterium für die ProjectID (Projektnummer) enthält: [Formulare]![frmClients]![fsubClients].[Formular]![ProjectID]

Dieses Kriterium betrachtet das Feld ProjectID aus dem Unterformular fsubClients, das Teil des Formulars frmClients ist, und stellt sicher, dass Sie nur Zahlungen sehen, die mit dem ausgewählten Projekt zusammenhängen. Das Formular frmPayments sehen Sie in Abbildung 5.45. Das Textfeld ProjectName enthält diesen Ausdruck: [Formulare]![frmClients]![fsubClients].[Formular]![txtProject Name]

Dieser Ausdruck zeigt den Projektnamen aus dem Unterformular fsubClients auf dem Formular frmClients an.

202

5.15.8

Kapitel 5: Was jeder Entwickler über Formulare wissen sollte

Das Projektformular entwerfen

Das Formular frmProjects ist komplexer als die anderen: es enthält zwei Unterformulare, von denen eines über dem anderen liegt. Die Schaltfläche View Expenses ist ein Umschalter, der den Benutzer sowohl Ausgaben als auch Stunden sehen lässt (siehe Abbildung 5.46)

Abbildung 5.45: Das frmPayments-Formular dient der Eingabe von Zahlungen in Zusammenhang mit einem bestimmten Projekt

Abbildung 5.46: Das frmProjects-Formular erlaubt dem Benutzer das Betrachten der Ausgaben und Zeiten, die für ein bestimmtes Projekt angefallen sind

Das Formular frmProjects beruht auf der Abfrage qryProjects, die den folgenden Ausdruck als Kriterium für die CientID hat: [Formulare]![frmClients]![txtClientID]

Dieser Ausdruck bedeutet, dass nur Projekte angezeigt werden, bei denen die ClientID im Formular frmClients dargestellt wird. Die beiden Unterformulare sind fsubProjects und fsubProjectExpenses. Der Code, der ihre Sichtbarkeit umschaltet, wird in Kapitel 8 behandelt. Das Formular fsubProjects basiert auf qrySubProjects und das Formular fsubProjectExpenses auf qrySubProjectExpenses. Das Formular frmProjects enthält ebenso wie die beiden Unterformulare verschiedene berechnete Steuerelemente.

Access-Formulare und das Internet

5.15.9

203

Was noch vor uns liegt

Die in diesem Beispiel erstellte Anwendung ist dem Zeit- und Abrechnungssystem nachgebildet, das vom Datenbank-Assistenten erstellt wurde. Sie werden diese Anwendung von Grund auf selbst aufbauen und so alles über ihre Bestandteile lernen. Außerdem werden Sie dieser Anwendung bedeutend mehr Funktionalität hinzufügen. Am Ende wird Ihre Anwendung weit leistungsfähiger sein als die Anwendung, die der Datenbank-Assistent erstellt hat.

Was jeder Entwickler über Berichte wissen sollte

Kapitel

Hier lesen Sie:

 Berichtstypen  Einen neuen Bericht erstellen  Das Berichtsentwurfsfenster  Das geeignete Steuerelement auswählen  Welche Berichtseigenschaften stehen zur Verfügung und warum sollten sie benutzt werden?

 Welche Steuerelementeigenschaften stehen zur Verfügung und warum sollten sie benutzt werden?

 Berichte auf der Grundlage mehrerer Tabellen  Sortierreihenfolge und Gruppierung  Durch Aufsetzen der Berichte auf gespeicherte Abfragen die Geschwindigkeit und die Wiederverwendbarkeit verbessern

 Access-Berichte und das Internet

6.1

Berichtstypen

Der Berichts-Generator von Microsoft Access ist sehr leistungsfähig und bietet eine Vielzahl von Möglichkeiten. Es gibt viele verschiedene Berichtstypen in Access 2000:

 Detailberichte  zusammenfassende Berichte  Kreuztabellenberichte  Berichte mit Grafiken und Diagrammen

206

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

 Berichte mit Formularen  Berichte mit Etiketten  Berichte mit einer beliebigen Kombination dieser Elemente

6.1.1

Detailberichte

Ein Detailbericht liefert einen Eintrag für jeden im Bericht enthaltenen Datensatz. Wie Sie in Abbildung 6.1 sehen können, gibt es in der Tabelle Bestellungen im Zeitraum 1995-96 für jede Bestellung einen Eintrag. Die Detailangaben des Berichts sind nach Ländern und innerhalb der Länder nach Verkaufsberatern gruppiert. Zusätzlich werden Zwischensummen für die Verkaufsberater und Länder angegeben. Am Ende des Berichts erscheint die Endsumme für alle Datensätze in diesem Bericht. Der Bericht basiert auf einer Parameterabfrage, welche die im Bericht anzuzeigenden Daten nach Kriterien begrenzt, die der Benutzer zur Laufzeit vorgibt.

Abbildung 6.1: Ein Beispiel für einen Detailbericht

6.1.2

Zusammenfassende Berichte

Ein zusammenfassender Bericht gibt Ihnen eine Zusammenfassung für alle Datensätze, die im Bericht enthalten sind. In Abbildung 6.2 werden nur die Gesamtumsätze je Quartal und Jahr im Bericht angezeigt. Die zu Grunde liegenden Datensätze, aus denen diese Zusammenfassung resultiert, erscheinen in diesem Bericht nicht. Der Bericht basiert auf einer Abfrage, welche die Nettoumsätze nach der BESTELLNR zusammenfasst. Der Bericht selbst enthält in seinem Detailbereich keine Steuerelemente. Sämtliche Steuerelemente befinden sich in den Kopf- und Fußbereichen

Berichtstypen

207

von Gruppen, die sich auf das Quartal und das Jahr des Lieferdatums beziehen. Da im Detailbereich des Berichts keine Steuerelemente zu finden sind, druckt Access nur die Zusammenfassung.

Abbildung 6.2: Ein Beispiel für einen zusammenfassenden Bericht

6.1.3

Kreuztabellenberichte

Kreuztabellenberichte zeigen zusammengefasste Daten an, die nach einer Datenmenge auf der linken Seite des Berichts und einer anderen Menge im oberen Teil gruppiert sind. Der Bericht in Abbildung 6.3 zeigt Umsätze je Produkt und Mitarbeiter. Der Bericht basiert auf einer Kreuztabellenabfrage und wurde mit etwas Programmierung erstellt. Das Programm ist erforderlich, weil bei jedem Ausführen des Berichts unter Umständen eine andere Anzahl von Mitarbeitern in den Spalten des Berichts dargestellt werden muss. Mit anderen Worten: die Anzahl der benötigten Spalten kann von Bericht zu Bericht variieren. Dieser Bericht sowie die erforderlichen Verfahren, um ihn zu erstellen, werden in Kapitel 10 erklärt.

6.1.4

Berichte mit Grafiken und Diagrammen

Auch wenn der Satz »Ein Bild sagt mehr als tausend Worte« ein Klischee ist, so ist er dennoch wahr – Untersuchungen zeigen, dass man sich Daten besser merkt, wenn sie in einem Bild anstatt als Zahlen angezeigt werden. Glücklicherweise macht Access das Einfügen von Grafiken und Diagrammen recht einfach. Wie in Abbildung 6.4 zu sehen ist, kann ein Bericht entworfen werden, der Zahlen und Diagramme

208

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Abbildung 6.3: Ein Beispiel für einen Kreuztabellenbericht

verbindet. Der Bericht in Abbildung 6.4 zeigt die Umsätze pro Produkt sowohl als Zahlen als auch in Form eines Balkendiagramms. Der Hauptbericht ist nach Produktkategorien gruppiert und enthält einen Unterbericht, der auf einer Abfrage basiert, welche die Umsätze nach den Feldern KATEGORIE-NR, KATEGORIENAME und ARTIKELNAME für einen bestimmten Datenbereich zusammenfasst. Das Diagramm summiert die Artikelumsätze nach dem Artikelnamen, um die Informationen grafisch darzustellen.

Abbildung 6.4: Ein Beispiel für einen Bericht mit einem Diagramm

Berichtstypen

6.1.5

209

Berichte mit Formularen

Benutzer brauchen häufig einen Bericht, der wie ein gedrucktes Formular aussieht. Der Berichts-Generator von Access mit seinen vielen grafischen Hilfsmitteln erlaubt Ihnen das schnelle Erstellen von Berichten, die selbst das eleganteste Eingabeformular nachahmen. Der Bericht in Abbildung 6.5 erstellt eine Rechnung für einen Kunden und basiert auf einer Abfrage, die Informationen aus den Tabellen Kunden, Bestellungen, Bestelldetails, Artikel, Personal und Versandtermin herauszieht. Die Berichtseigenschaft Filter ist so gesetzt, dass die im Bericht auftauchenden Daten auf die letzten sechs Datensätze in der Tabelle Bestellungen begrenzt werden. Die Verwendung von Grafiken, Farben, Schriften, Schattierungen und anderen besonderen Effekten gibt dem Formular ein professionelles Aussehen.

Abbildung 6.5: Ein Beispiel für einen Bericht, der ein Formular enthält

6.1.6

Berichte mit Etiketten

Das Erstellen von Adressetiketten erfolgt in Access 2000 einfach mit Hilfe des Etiketten-Assistenten. Adressetiketten sind lediglich eine besondere Art von Berichten, bei denen die Seiteneinrichtung die Anzahl der Etiketten pro Seite sowie die Größe jedes Etiketts festlegt. Ein Beispiel für einen mit dem Etiketten-Assistenten erstellten Adressetikettenbericht sehen Sie in Abbildung 6.6. Dieser Bericht basiert auf der Tabelle Kunden, hätte aber auch ebenso einfach auf einer Abfrage aufbauen können, welche die erzeugten Adressetiketten einschränkt.

210

6.2

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Aufbau eines Berichts

Berichte können sich aus vielen Teilen zusammensetzen, die als »Abschnitte« des Berichts bezeichnet werden. Ein neuer Bericht besteht automatisch aus den folgenden drei Abschnitten, die in Abbildung 6.7 zu sehen sind:

 Seitenkopf  Detailbereich  Seitenfuß

Abbildung 6.6: Ein Beispiel für einen Bericht mit Adressetiketten

Abbildung 6.7: Abschnitte eines Berichts

Einen neuen Bericht erstellen

211

Der Detailbereich ist der wichtigste Abschnitt eines Berichts. Er wird benutzt, um die Daten der zu Grunde liegenden Tabelle oder einer Abfrage darzustellen. Bestimmte Berichte wie zum Beispiel zusammenfassende Berichte besitzen einen leeren Detailbereich. Dafür enthalten zusammenfassende Berichte Daten in Gruppenköpfen und -füßen (wird am Ende dieses Abschnitts genauer erläutert). Der Seitenkopf ist der Teil, der automatisch am Anfang jeder Seite des Berichts gedruckt wird. Er enthält oftmals Informationen wie etwa den Titel des Berichts. Der Seitenfuß wird automatisch am Ende jeder Seite des Berichts ausgedruckt und enthält üblicherweise Informationen wie beispielsweise die Seitenzahl und das Datum. Jeder Bericht kann nur einen Seitenkopf und einen Seitenfuß haben. Zusätzlich zu den drei Abschnitten, die jedem Bericht automatisch hinzugefügt werden, können Berichte die folgenden Abschnitte enthalten:

 Berichtskopf  Berichtsfuß  Gruppenköpfe  Gruppenfüße Ein Berichtskopf ist ein Abschnitt, der nur einmal am Anfang des Berichts gedruckt wird, während der Berichtsfuß am Ende des Berichts erscheint. Jeder Access-Bericht kann nur einen Berichtskopf und einen Berichtsfuß besitzen. Der Berichtskopf wird oft genutzt, um ein Deckblatt für den Bericht zu erstellen. Er kann Bilder und andere Effekte enthalten, so dass er ein professionelles Aussehen erhält. Der Berichtsfuß wird in der Regel für Endsummen genutzt, kann aber auch andere zusammenfassende Informationen enthalten. Zusätzlich zu den Kopf- und Fußbereichen des Berichts und der Seiten kann ein Access-Bericht bis zu 10 Gruppenköpfe und -füße aufweisen. Berichtsgruppen trennen Daten logisch und physisch. Der Gruppenkopf wird vor den Detaildaten der Gruppe und der Gruppenfuß danach ausgegeben. Sie könnten zum Beispiel Kundenumsätze nach Land und Stadt gruppieren, wobei der Name des Landes oder der Stadt für jede relevante Datensatzgruppe mit ausgegeben wird. Wenn Sie die Umsätze für jedes Land und jede Stadt addieren wollen, können Sie die Länder- und Städtenamen in die Gruppenköpfe und die Summen in die entsprechenden Gruppenfüße einfügen.

6.3

Einen neuen Bericht erstellen

Sie können einen neuen Bericht auf mehrere Arten erstellen – die gebräuchlichste ist es, im Datenbankfenster aus der Objektliste den Eintrag BERICHTE zu wählen und dann auf ERSTELLT EINEN NEUEN BERICHT UNTER VERWENDUNG DES ASSISTENTEN doppelzuklicken. Wenn Sie es vorziehen, können Sie auch auf NEU klicken, um das

212

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Dialogfeld NEUER BERICHT zu öffnen (siehe Abbildung 6.8). Hier können Sie aus vielen verfügbaren Möglichkeiten zur Erstellung eines Berichts auswählen. Berichte können über die Entwurfsansicht von Grund auf oder mit der Hilfe von fünf Assistenten neu erstellt werden. Drei der Assistenten helfen Ihnen bei der Erstellung von Standardberichten, einer erstellt Berichte mit Diagrammen und der andere automatisiert das Erstellen von Adressetiketten. Die Berichts-Assistenten sind so leistungsfähig, dass ich einen von ihnen für fast jeden meiner Berichte benutze, um das erste Fundament zu legen.

Abbildung 6.8: Im Dialogfeld Neuer Bericht können Sie zwischen der Entwurfsansicht und einem von fünf Assistenten wählen

6.3.1

Einen Bericht mit Hilfe des Berichts-Assistenten erstellen

Um einen Bericht mit Hilfe des Berichts-Assistenten zu erstellen, klicken Sie in der Objektliste einmal auf BERICHTE und dann doppelt auf ERSTELLT EINEN BERICHT UNTER VERWENDUNG DES ASSISTENTEN. Dies startet den Berichts-Assistenten. Der erste Schritt besteht nun darin, die Tabelle oder die Abfrage auszuwählen, welche die Daten für den Bericht bereitstellt. Ich bevorzuge es, meine Berichte auf Abfragen aufzubauen. Das verbessert im Allgemeinen die Geschwindigkeit, da es die kleinstmögliche Datenmenge liefert. In einer Client-Server-Umgebung ist dies besonders wichtig, da die Abfrage meistens auf dem Server ausgeführt wird und nur die Resultate über das Netzwerk übertragen werden. Berichte auf Abfragen aufzubauen, verbessert auch Ihre Möglichkeiten, Berichten verschiedene Kriterien zugrundezulegen. Nachdem Sie die Tabelle oder Abfrage ausgewählt haben, können Sie die Felder auswählen, die Sie in den Bericht aufnehmen wollen. Die in der ausgewählten Tabelle oder Abfrage enthaltenen Felder werden im Listenfeld auf der linken Seite angezeigt. Um Felder zum Bericht hinzuzufügen, doppelklicken Sie auf den Namen des hinzuzufügenden Feldes oder klicken einmal auf den Feldnamen und dann auf die Schaltfläche >. Im Beispiel in Abbildung 6.9 wurden sechs Felder der Tabelle tblClients ausgewählt.

Einen neuen Bericht erstellen

213

Abbildung 6.9: Der erste Schritt im Berichts-Assistenten: Tabellen-/Feldauswahl

Nachdem Sie die Tabelle oder Abfrage sowie die gewünschten Felder ausgewählt haben, klicken Sie auf WEITER. Sie werden nun aufgefordert, Gruppierungsebenen hinzuzufügen, die den Bericht um Berichtsgruppierungen erweitern. Fügen Sie Gruppierungsebenen hinzu, wenn Sie Datenreihen optisch trennen oder im Bericht zusammenfassende Berechnungen (Zwischensummen) auftauchen müssen. Berichtsgruppierungen werden später in diesem Kapitel behandelt. Wenn Ihr Bericht keine Gruppierungen benötigt, klicken Sie auf WEITER. Im dritten Schritt des Berichts-Assistenten wählen Sie die Sortierreihenfolge für Ihren Bericht aus. Da die Sortierung einer zu Grunde liegenden Abfrage von der für den Bericht bestimmten Sortierreihenfolge ersetzt wird, ist es eine gute Idee, eine Sortierreihenfolge für den Bericht festzulegen. Sie können mit Hilfe des Assistenten bis zu vier Sortierebenen vorgeben. Im Beispiel in Abbildung 6.10 wird der Bericht nach dem Feld ClientID sortiert. Nachdem Sie die Felder, nach denen Sie sortieren wollen, ausgewählt haben, klicken Sie auf WEITER. Im vierten Schritt des Berichts-Assistenten entscheiden Sie sich für das Layout und die Seitenausrichtung. Die Layoutmöglichkeiten variieren in Abhängigkeit davon, was in den vorherigen Schritten des Assistenten ausgewählt worden ist. Die Seitenausrichtung kann Hoch- oder Querformat sein. Dieser Schritt des Berichts-Assistenten lässt Sie außerdem festlegen, ob Access die Breite jedes Feldes automatisch so festlegt, dass jeweils alle Felder auf eine Seite passen. Nachdem Sie Access diese Informationen gegeben haben, klicken Sie auf WEITER. Der fünfte Schritt des Berichts-Assistenten betrifft die Auswahl eines Berichtsformates. Die Auswahlmöglichkeiten sind FETT, FORMAL, GESCHÄFTLICH, INFORMELL, KOMPAKT und WEICHES GRAU. Sie können jeden Stil in einer Vorschau betrachten,

214

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Abbildung 6.10: Der dritte Schritt im Berichts-Assistenten: Berichtsdaten sortieren

bevor Sie sich entscheiden. Jedes vom Berichts-Assistenten angewandte Formatattribut sowie alle anderen auf diese Weise definierten Berichtseigenschaften können nach der Fertigstellung des Berichts jederzeit in der Entwurfsansicht verändert werden. Klicken Sie nach dem Auswählen des Formats auf WEITER. Der letzte Schritt des Berichts-Assistenten fragt Sie nach dem Titel für den Bericht. Dieser Titel wird sowohl als Name als auch als Überschrift für den Bericht benutzt. Ich wähle für gewöhnlich den von Access vorgeschlagenen Berichtsnamen und ändere den Titel, wenn der Berichts-Assistent fertig ist. Sie haben dann immer noch die Möglichkeit, sich eine Berichtsvorschau anzusehen oder den Berichtsentwurf anzupassen. Wenn Sie sich dafür entscheiden, den Entwurf doch noch zu verändern, werden Sie in die Entwurfsansicht versetzt (siehe Abbildung 6.11). Eine Vorschau des Berichts kann zu jeder Zeit aufgerufen werden.

Abbildung 6.11: Entwurfsansicht eines fertiggestellten Berichts

Das Berichtsentwurfsfenster

215

Sie können den Berichts-Assistenten auch starten, indem Sie aus der Objektleiste im Datenbankfenster TABELLEN oder ABFRAGEN auswählen und dann auf die Tabelle oder Abfrage klicken, die dem Bericht zugrunde liegen soll. Benutzen Sie dann das aufklappbare Listenfeld NEUES OBJEKT auf der Symbolleiste, um dort den Eintrag BERICHT auszuwählen. Im Dialogfeld NEUER BERICHT wählen Sie nun die Option BERICHTS-ASSISTENT. Es ist nicht erforderlich, das Listenfeld zur Tabellen-/Abfrageauswahl zu benutzen, um eine Tabelle oder Abfrage auszuwählen, da diejenige, die Sie vor dem Aufrufen des Assistenten markiert hatten, automatisch für Sie ausgewählt wird.

6.3.2

Einen Bericht in der Entwurfsansicht erstellen

Obwohl Sie normalerweise bei dem Großteil Ihrer Berichte mit den Berichts-Assistenten anfangen, sollten Sie verstehen, wie man einen neuen Bericht in der Entwurfsansicht erstellt. Um einen Bericht zu erstellen, ohne einen Assistenten zu verwenden, klicken Sie in der Objektliste auf das Symbol BERICHTE und dann doppelt auf ERSTELLT EINEN BERICHT IN DER ENTWURFSANSICHT. Sie gelangen dadurch in das Berichtsentwurfsfenster. Anschließend müssen Sie als Datensatzquelle des Berichts die Tabelle oder Abfrage festlegen, auf welcher der Bericht basieren soll. Ein anderer Weg, um in der Entwurfsansicht einen Bericht zu erstellen, besteht darin, in der Objektliste das Symbol BERICHTE auszuwählen und dann auf NEU zu klicken. Dies öffnet ebenfalls das Dialogfeld NEUER BERICHT. Klicken Sie nun auf ENTWURFSANSICHT, benutzen Sie das aufklappbare Listenfeld, um die Tabelle oder Abfrage auszuwählen, auf welcher der Bericht beruhen soll, und klicken Sie dann auf OK. Sie gelangen wiederum in das Berichtsentwurfsfenster.

6.4

Das Berichtsentwurfsfenster

Das Berichtsentwurfsfenster wird benutzt, um einen Bericht zu erstellen und ihn zu verändern. Mit diesem Fenster können Sie Objekte zu dem Bericht hinzufügen sowie deren Eigenschaften ändern. Microsoft stellt zahlreiche Eigenschaften für Berichte, Berichtsgruppierungen und Steuerelemente bereit. Sie können Berichte mit vielfältigem Aussehen und unterschiedlicher Funktionalität erstellen, indem Sie diese Eigenschaften verändern.

6.4.1

Die Werkzeuge für den Berichtsentwurf

Um Ihnen beim Entwerfen von Berichten zu helfen, stehen verschiedene Werkzeuge für den Berichtsentwurf zur Verfügung. Darunter befinden sich das EIGENSCHAFTENFENSTER, die TOOLBOX, die FELDLISTE und das GRUPPIERUNGSFENSTER. Zwei Symbolleisten sind dazu da, das Entwickeln und Anpassen Ihrer Berichte zu vereinfachen: die Symbolleiste BERICHTSENTWURF und die Symbolleiste FORMATIERUNG. Die Symbolleiste BERICHTSENTWURF bietet Werkzeuge, um Ihren Bericht abzuspei-

216

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

chern, anzusehen und auszudrucken sowie um Berichtsobjekte auszuschneiden, zu kopieren und einzufügen. Die Symbolleiste FORMAT soll Ihnen helfen, das Aussehen Ihres Berichts anzupassen. Sie enthält Werkzeuge, um die Schriftart, Schriftgröße, Schriftausrichtung, Farbe, Schattierung und sonstige Attribute der Berichtsobjekte anzupassen. Die TOOLBOX, die FELDLISTE sowie die Fenster EIGENSCHAFTEN, SORTIEREN und GRUPPIEREN sind alle als ein- und ausblendbar entworfen. Das bedeutet, dass die Schaltflächen auf der Symbolleiste BERICHTSENWURF diese nützlichen Fenster abwechselnd verstecken oder anzeigen. Wenn Sie einen hochauflösenden Monitor besitzen, werden Sie wahrscheinlich alle Fenster stets geöffnet haben. Wenn Sie hingegen einen niedrigauflösenden Monitor Ihr Eigen nennen, sollten Sie ausprobieren, wann Sie welches Fenster geöffnet haben müssen, um effektiv zu arbeiten.

6.4.2

Dem Bericht Felder hinzufügen

Am leichtesten können Felder hinzugefügt werden, indem man die FELDLISTE benutzt. Wenn die FELDLISTE geöffnet ist, klicken Sie einfach auf ein Feld und ziehen es auf den gewünschten Abschnitt. Wie bei Formularen können mehrere Felder gleichzeitig hinzugefügt werden. Benutzen Sie die (Strg)-Taste, um nicht aneinander grenzende Felder auszuwählen, die (ª)-Taste, um benachbarte Felder auszuwählen, oder doppelklicken Sie auf die Titelleiste der Feldliste, um alle Felder auszuwählen. Dann ziehen Sie die Felder als eine Einheit auf den Bericht. Ein Problem beim Hinzufügen von Feldern zu einem Bericht ist, dass sowohl die Felder als auch die dazugehörigen Bezeichnungen in den gleichen Abschnitt des Berichts gesetzt werden. Das bedeutet, dass beim Ziehen eines Feldes in den Detailbereich sowohl das Feld als auch die dazugehörige Bezeichnung im Detailbereich erscheint. Wenn Sie gerade einen tabellarischen Bericht erstellen, ist das nicht wünschenswert. Sie müssen also die dazugehörigen Bezeichnungen ausschneiden und im Seitenkopfbereich des Berichts einfügen.

6.4.3

Berichtsobjekte auswählen, verschieben, ausrichten und in der Größe verändern

Microsoft Access bietet mehrere Methoden, die Ihnen helfen, Berichtsobjekte auszuwählen, zu verschieben, anzuordnen und in ihrer Größe zu ändern. Die Effektivität der Methoden hängt von der Situation ab. Mit zunehmender Erfahrung werden Sie wissen, wann Sie welche Methode anwenden sollten. Das Auswählen, Verschieben, Anordnen sowie Ändern der Größe eines Berichtsobjekts ähnelt sehr den entsprechenden Methoden für Formularobjekte. Die Methoden werden in diesem Kapitel daher nur kurz beschrieben. Eine detailliertere Erklärung zu jeder Methode erfahren Sie in Kapitel 5.

Das Berichtsentwurfsfenster

217

Berichtsobjekte auswählen Um ein einzelnes Berichtsobjekt auszuwählen, klicken Sie es an. Um das ausgewählte Objekt herum erscheinen daraufhin Anfasser. Nachdem das Objekt ausgewählt wurde, können Sie jedes seiner Merkmale (Eigenschaften) verändern, seine Größe ändern, es bewegen oder ausrichten. Um mehrere Objekte auszuwählen, die man als Einheit handhaben kann, nutzen Sie eine der folgenden Methoden:

 Halten Sie die (ª)-Taste gedrückt, während Sie auf die verschiedenen Objekte klicken. Jedes Objekt, auf das Sie klicken, wird der Auswahl hinzugefügt.

 Positionieren Sie Ihren Mauszeiger auf einer freien Fläche Ihres Berichts. Klicken und ziehen Sie, um die Objekte, die Sie auswählen wollen, mit einem Auswahlrahmen einzufangen. Wenn Sie die Maus loslassen, werden alle Objekte ausgewählt, die sich zumindest teilweise innerhalb des Rahmens befinden.

 Klicken Sie auf das horizontale oder vertikale Lineal und ziehen Sie es. Dabei erscheinen Linien, welche die mögliche Auswahl anzeigen. Wenn Sie die Maustaste loslassen, werden alle Objekte innerhalb der Linien ausgewählt. Stellen Sie sicher, dass Sie verstehen, welche Objekte tatsächlich ausgewählt sind. Angehängte Bezeichnungen können einige Verwirrung auslösen. Abbildung 6.12 zeigt einen Bericht mit vier ausgewählten Objekten: das Bezeichnungsfeld rptClients, das Bezeichnungsfeld Contact First Name, das Textfeld City und das Textfeld ContactFirstName. Das Bezeichnungsfeld City ist nicht ausgewählt. Es ist nur von einem Auswahlanfasser umgeben, da es an das Textfeld City gebunden ist. Wenn Sie die Eigenschaften der ausgewählten Objekte ändern würden, wäre das Bezeichnungsfeld City nicht betroffen. Objekte verschieben Wenn Sie ein einzelnes Steuerelement zusammen mit seiner Bezeichnung verschieben wollen, klicken Sie auf das Objekt und ziehen es an seinen neuen Platz. Das Objekt und die gebundene Bezeichnung bewegen sich als eine Einheit. Um mehrere Objekte zu bewegen, benutzen Sie eine der Methoden, die im vorherigen Abschnitt erklärt worden sind, um die zu bewegenden Objekte auszuwählen. Nachdem Sie die Objekte ausgewählt haben, klicken Sie auf irgendeines von ihnen und ziehen es. Die ausgewählten Objekte und ihre gebundenen Bezeichnungen werden zusammen verschoben. Ein Objekt ohne seine gebundene Bezeichnung zu verschieben, ist etwas kniffliger. Wenn er über dem Mittelpunkt oder der Kante eines ausgewählten Objekts (nicht über den Anfassern zur Größenveränderung) steht, sieht der Mauszeiger wie eine Hand mit allen fünf Fingern nach oben aus. Dies zeigt an, dass das ausgewählte

218

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Objekt und seine gebundene Bezeichnung als Einheit bewegt werden. So bleibt ihre Verbindung bestehen. Wenn Sie hingegen den Mauszeiger direkt über den Auswahlanfasser in der oberen linken Ecke des Objekts stellen, sieht er wie eine Hand mit ausgestrecktem Zeigefinger aus. Dies zeigt an, dass das Objekt und die gebundene Bezeichnung voneinander unabhängig bewegt werden. Sie können nun zum Beispiel die Entfernung zwischen den Objekten ändern.

Abbildung 6.12: Objekte in einem Access-Bericht auswählen

Objekte aneinander ausrichten Um Objekte aneinander auszurichten, müssen Sie diese erst auswählen. Wählen Sie dazu FORMAT AUSRICHTEN und dann LINKS, RECHTS OBEN, UNTEN oder AM RASTER. Die ausgewählten Objekte werden sich anschließend aneinander ausrichten. Achten Sie auf die »Stolperfallen«, wenn Sie Berichtsobjekte ausrichten. Wenn Sie mehrere Textfelder und die dazugehörigen Bezeichnungen ausgewählt haben und dann ausrichten, versucht Access, die linken Seiten der Textfelder und die linken Seiten der Bezeichnungen aneinander auszurichten. Um dieses Problem zu umgehen, müssen Sie die Textfelder separat von den gebundenen Bezeichnungen ausrichten. Während des Ausrichtungsprozesses wird Access nie Objekte überlappen lassen. Wenn die auszurichtenden Objekte nicht zueinander passen, kann Access sie nicht ausrichten. Wenn Sie zum Beispiel versuchen, die Unterkanten mehrerer Objekte horizontal auszurichten und sie nicht in die Breite des Berichts passen, richtet Access nur die Objekte aus, die auf die Linie passen.

Das geeignete Steuerelement auswählen

219

Am Raster ausrichten Die Funktion AM RASTER AUSRICHTEN ist eine Umschaltfläche, die sich im FORMATMenü befindet. WENN AM RASTER AUSRICHTEN ausgewählt ist, rasten alle Objekte, die Sie verschieben oder in der Größe verändern, an den Gitternetzlinien des Berichts ein. Um die Funktion AM RASTER AUSRICHTEN kurzzeitig auszuschalten, halten Sie die (Strg)-Taste gedrückt, während Sie Objekte in der Größe verändern oder bewegen. Fortgeschrittene Techniken zur Änderung der Objektgröße Access bietet viele Techniken, die ihnen helfen, Objektgrößen zu ändern. Ein ausgewähltes Objekt verfügt über acht Größenanfasser, von denen alle außer dem oberen linken genutzt werden können, um die Objektgröße zu ändern. Klicken Sie einfach auf einen der Größenanfasser und ziehen Sie an ihm. Wenn mehrere Objekte ausgewählt sind, wirken sich die Größenänderungen bei allen gleich aus. Auch das Menü FORMAT GRÖSSE kann Ihnen helfen, Objektgrößen zu ändern. Es bietet sechs Optionen: AN TEXTGRÖSSE, AN RASTER, AM HÖCHSTEN, AM NIEDRIGSTEN, AM SCHMALSTEN und AM BREITESTEN. Diese Optionen werden genauer in Kapitel 5 besprochen. Access bietet einen tollen Trick, der hilft, die Größe von Bezeichnungen anzupassen: Doppelklicken Sie einfach auf irgendeinen Größenanfasser und die Objektgröße wird automatisch so festgelegt, dass der enthaltene Text vollständig hineinpasst. Den Objektabstand steuern Access erleichtert Ihnen auch die Steuerung des Objektabstands. Sowohl der horizontale als auch der vertikale Abstand zwischen den ausgewählten Objekten kann angeglichen werden. Wählen Sie zuerst die Objekte und dann FORMAT|HORIZONTALER ABSTAND|ANGLEICHEN oder FORMAT|VERTIKALER ABSTAND|ANGLEICHEN aus. Sie können auch den relativen Abstand zwischen den Objekten erhalten, während Sie den Abstand zwischen ihnen vergrößern oder verkleinern. Um das zu tun, wählen Sie FORMAT|HORIZONTALER / VERTIKALER ABSTAND|VERGRÖSSERN / VERMINDERN.

6.5

Das geeignete Steuerelement auswählen

Berichte enthalten üblicherweise Bezeichnungen, Textfelder, Linien, Rechtecke, Bildelemente sowie gebundene und ungebundene Objektrahmen. Die anderen Steuerelemente werden in der Regel für Berichte genutzt, die wie Formulare aussehen sollen. Die verschiedenen Steuerelemente, die in einen Bericht eingefügt werden können, sowie ihre Anwendungsmöglichkeiten werden in den folgenden Abschnitten behandelt.

220

6.5.1

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Bezeichnungen

Bezeichnungen werden benutzt, um dem Benutzer Informationen anzuzeigen, und kommen in der Regel als Berichts-, Spalten- oder Gruppenüberschriften in Ihrem Bericht zum Einsatz. Obwohl der dargestellte Text zur Laufzeit durch Programme verändert werden kann, können Bezeichnung nicht direkt an die Daten gekoppelt werden. Um eine Bezeichnung zu einem Bericht hinzuzufügen, benutzen Sie das Werkzeug BEZEICHNUNG aus der TOOLBOX. Klicken Sie das Werkzeug an und ziehen Sie die Bezeichnung auf den Bericht.

6.5.2

Textfelder

Textfelder werden benutzt, um Feldinhalte oder das Ergebnis eines Ausdrucks darzustellen, und kommen in allen Abschnitten des Berichts zum Einsatz. Beipielsweise kann ein Textfeld im Seitenkopf einen Ausdruck enthalten, der den Zeitraum anzeigt, der die Grundlage des Berichts darstellt. In einem Gruppenkopf kann ein Textfeld genutzt werden, um die Überschrift für diese Gruppe anzuzeigen. Die Möglichkeiten sind endlos, da das Textfeld jeden gültigen Ausdruck enthalten kann. Um ein Textfeld zu einem Bericht hinzuzufügen, wählen Sie das Werkzeug TEXTaus der TOOLBOX. Klicken und ziehen Sie das Textfeld an seinen Platz im Bericht. Ein Textfeld kann auch eingefügt werden, indem man ein Feld von der FELDLISTE in den Bericht zieht. Dies funktioniert immer dann, wenn die Eigenschaft ANZEIGE des Feldes auf TEXTFELD gesetzt ist.

FELD

6.5.3

Linien

Linien kann man verwenden, um Objekte in einem Bericht optisch voneinander zu trennen. Zum Beispiel kann eine Linie unter einen Abschnitt oder eine Zwischensumme gesetzt werden. Um einem Bericht eine Linie hinzuzufügen, klicken Sie auf das Werkzeug Linie, um es auszuwählen. Dann klicken und ziehen Sie, um die Linie in Ihren Bericht einzufügen. Einmal hinzugefügt, besitzt die Linie mehrere Eigenschaften, die Sie verändern können, um so ihr Aussehen anzupassen. Um sicherzugehen, dass die Linie absolut gerade ist, drücken Sie die (ª)-Taste, während Sie klicken und ziehen, um die Linie zu zeichnen.

6.5.4

Rechtecke

Rechtecke können benutzt werden, um Gegenstände im Bericht optisch zusammenzufassen, die vom Sinn her zusammengehören. Sie können auch angewandt werden, um bestimmte Steuerelemente in Ihrem Bericht herausragen zu lassen. Ich ziehe oft

Das geeignete Steuerelement auswählen

221

Rechtecke um wichtige Zwischen- oder Endsummen herum, bei denen ich sicher gehen möchte, dass der Leser des Berichts sie wahrnimmt. Um einem Bericht ein Rechteck hinzuzufügen, klicken Sie auf das Werkzeug RECHTECK aus der TOOLBOX, um es auszuwählen. Dann klicken und ziehen Sie, um das Rechteck in Ihren Bericht zu setzen. Das Rechteck kann einige Objekte verdecken, die schon in Ihrem Bericht vorhanden sind. Um dieses Problem zu beheben, kann die Eigenschaft Hintergrundfarbe des Rechtecks auf Transparent gesetzt werden. Diese Einstellung ist in Ordnung, solange das Rechteck eine Hintergrundfarbe haben muss. Wenn das so ist, wählen Sie FORMAT|IN DEN HINTERGRUND, um die Objekte so anzuordnen, dass das Rechteck hinter den anderen Objekten des Berichts liegt.

6.5.5

Gebundene Objektfelder

Mit gebundenen Objektfeldern können Sie Daten in OLE-Feldern darstellen, die Objekte aus anderen Anwendungen enthalten wie zum Beispiel Bilder, Tabellenkalkulationen und Textverarbeitungsdokumente. Um ein gebundenes Objektfeld zu einem Bericht hinzuzufügen, klicken Sie auf das Werkzeug GEBUNDENES OBJEKTFELD in der TOOLBOX. Dann ziehen Sie das Feld auf Ihren Bericht. Setzen Sie anschließend die Eigenschaft STEUERELEMENTINHALT des Objekts auf das entsprechende Feld. Sie können ein gebundenes Objektfeld einem Bericht auch hinzufügen, indem Sie ein OLE-Feld aus der Feldliste ziehen und es auf Ihrem Bericht ablegen.

6.5.6

Ungebundene Objektfelder

Ungebundene Objektfelder können benutzt werden, um Logos und andere Bilder zu ihrem Bericht hinzuzufügen. Anders als gebundene Objektfelder sind sie aber nicht an zu Grunde liegende Daten gebunden. Um ein ungebundenes Objektfeld zu Ihrem Bericht hinzuzufügen, klicken Sie auf das Werkzeug OBJEKTFELD in der Toolbox. Ziehen Sie das Objektfeld an seinen Platz in Ihrem Bericht. Dies öffnet, wie Abbildung 6.13 zeigt, das Dialogfeld OBJEKT EINFÜGEN, mit dessen Hilfe Sie ein neues OLE-Objekt erstellen oder ein vorhandenes aus einer Datei einfügen können. Wenn Sie auf AUS DATEI ERSTELLEN klicken, verändert sich das Dialogfeld OBJEKT EINFÜGEN, so dass es aussieht wie in Abbildung 6.14. Klicken Sie auf DURCHSUCHEN und machen Sie die Datei ausfindig, die Sie Ihrem Bericht hinzufügen möchten. Das Dialogfeld OBJEKT EINFÜGEN bietet Ihnen die Möglichkeit, eine Verknüpfung mit dem OLE-Objekt anzulegen oder es einzubetten. Wenn Sie VERKNÜPFEN wählen, wird ein Verweis auf das OLE-Objekt erstellt. In diesem Fall enthält der Bericht lediglich eine Bitmap, während er sich weiterhin auf die Datei auf der Festplatte bezieht. Wenn Sie VERKNÜPFEN nicht aktivie-

222

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

ren, wird das ausgewählte Objekt kopiert und in den Bericht eingebettet. Das Objekt wird zu einem Bestandteil der Access-MDB-Datei und es wird kein Verweis auf das Originalobjekt unterhalten.

Abbildung 6.13: Verwenden Sie das Dialogfeld Objekt einfügen, um ein neues oder vorhandenes Objekt in ein ungebundenes Objektfeld einzufügen

Es ist meistens vorzuziehen, ein Bild-Steuerelement anstelle eines ungebundenen Objektfeldes zu verwenden, wenn gleichbleibende Informationen, wie zum Beispiel ein Logo, dargestellt werden sollen, da das Bild-Steuerelement wesentlich weniger Ressourcen verbraucht als ein ungebundenes Objektfeld. Bild-Steuerelemente werden im nächsten Abschnitt behandelt. Abbildung 6.15 zeigt einen Bericht mit einem Bild-Steuerelement.

Abbildung 6.14: Das Dialogfeld Objekt einfügen mit ausgewählter Option Aus Datei erstellen

6.5.7

Bild-Steuerelemente

Bild-Steuerelemente sind die beste Möglichkeit, um gleichbleibende Bilder wie etwa Logos in einem Bericht darzustellen. Ein ungebundenes Objektfeld kann, nachdem

223

Welche Berichtseigenschaften stehen zur Verfügung?

Abbildung 6.15: Ein Bericht mit einem ungebundenen Objektfeld

es in den Bericht eingefügt wurde, verändert werden. Sie können aber nicht die Anwendung des Objekts öffnen und ein Bild verändern, nachdem es in den Bericht eingefügt wurde. Diese Beschränkung bedeutet allerdings, dass wesentlich weniger Ressourcen benötigt werden, was die Leistung spürbar verbessert.

6.5.8

Andere Steuerelemente

Wie schon vorher in diesem Abschnitt erwähnt, ist es Standard, hauptsächlich Bezeichnungs- und Textfelder in Ihren Berichten zu verwenden. Andere Steuerelemente können aber, wo es sinnvoll ist, hinzugefügt werden. Um andere Steuerelemente einzufügen, klicken Sie das Steuerelement an und ziehen es an die Zielposition in Ihrem Bericht.

6.6

Welche Berichtseigenschaften stehen zur Verfügung und warum sollten sie benutzt werden?

Berichte haben viele verschiedene Eigenschaften, die verändert werden können, um Aussehen und Verhalten des Berichts zu beeinflussen. Wie Formulareigenschaften sind die Berichtseigenschaften in Kategorien unterteilt: FORMAT, DATEN, EREIGNIS und ANDERE. Um die Eigenschaften eines Berichts anzusehen, wählen Sie zuerst den Bericht aus anstatt einen der Abschnitte des Berichts. Dazu gibt es zwei Möglichkeiten:

 Klicken Sie auf den Berichtsmarkierer. Dies ist die kleine graue Schaltfläche an der Schnittstelle zwischen horizontalem und vertikalem Lineal.

224

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

 Wählen Sie BEARBEITEN|BERICHT AUSWÄHLEN. Nachdem ein Bericht ausgewählt wurde, können Sie seine Eigenschaften betrachten und verändern.

6.6.1

Das Eigenschaftenfenster

Nachdem ein Bericht ausgewählt wurde, zeigt das Eigenschaftenfenster alle Eigenschaften, die mit dem Bericht zusammenhängen. Um einen Bericht auszuwählen und das Eigenschaftenfenster gleichzeitig zu öffnen, doppelklicken Sie auf den Berichtsmarkierer. Ein Bericht verfügt in seinem Eigenschaftenfenster über 37 Eigenschaften (es gibt noch weitere Eigenschaften, die nur über Programm-Code erreichbar sind), die in entsprechende Kategorien im Eigenschaftenfenster unterteilt sind. Dreißig der Eigenschaften beziehen sich auf das Format des Berichts, seine Daten und andere Spezialeigenschaften. Die verbleibenden sieben Eigenschaften beziehen sich auf Ereignisse, die auftreten, wenn der Bericht gestartet wird. Die Format-, Daten- und anderen Eigenschaften werden hier behandelt, während die Ereigniseigenschaften Gegenstand von Kapitel 10 sind.

6.6.2

Die Formateigenschaften eines Berichts

Ein Bericht besitzt die folgenden 15 Formateigenschaften, um sein Aussehen zu beeinflussen: Beschriftung: Die Eigenschaft BESCHRIFTUNG ist der Text, der im Fenstertitel erscheint, wenn sich der Benutzer den Bericht ansieht. Sie kann zur Laufzeit verändert werden, um die Titelzeile an eine bestimmte Situation anzupassen. Seitenkopf, Seitenfuß: Die Eigenschaften SEITENKOPF und SEITENFUSS legen fest, auf welchen Seiten diese Abschnitte erscheinen. Die Optionen sind ALLE SEITEN, AUSSER BERICHTSKOPF, AUSSER BERICHTSFUSS UND AUSSER BERICHTSKOPF/-FUSS. Da Sie eventuell nicht möchten, dass der Seitenkopf oder Seitenfuß mit auf die gleichen Seiten wie der Berichtskopf oder Berichtsfuß gedruckt wird, geben Ihnen diese Eigenschaften die Kontrolle darüber, wo diese Abschnitte gedruckt werden. Gruppe zusammenhalten: In Access können Sie eine Datengruppe zusammen auf einer Seite halten, indem Sie die Eigenschaft GRUPPE ZUSAMMENHALTEN benutzen. Die Option PRO SEITE zwingt die Datengruppe, auf einer Seite zu bleiben, während die Option PRO SPALTE dafür sorgt, dass die Datengruppe innerhalb einer Spalte bleibt. Eine »Datengruppe« bezeichnet alle Daten innerhalb einer Berichtsgruppe (wie zum Beispiel alle Kunden in einer Stadt). Breite: Die Eigenschaft BREITE legt fest, wie breit die Abschnitte des Berichts sind. Bild, Bildtyp, Bildgrößenmodus, Bildausrichtung, Bild nebeneinander, Bildseiten: Der Hintergrund eines Berichts kann ein Bild sein. Die Bildeigenschaften legen fest, welches Bild als Hintergrund verwendet wird und welche Eigenschaften auf es angewendet werden.

Welche Berichtseigenschaften stehen zur Verfügung?

225

Raster X/Raster Y: Die Eigenschaften RASTER X und RASTER Y legen die Dichte der Gitternetzlinien im Berichtsentwurfsfenster fest. Drucklayout: Die Eigenschaft DRUCKLAYOUT gibt an, ob Bildschirm- oder Druckerzeichensätze im Bericht benutzt werden. Wenn Sie den Bericht für die Ansicht am Bildschirm optimieren wollen, wählen Sie NEIN, bei beabsichtigter Ausgabe auf den Drucker hingegen JA. Diese Möglichkeit ist nicht so wichtig, wenn Sie TrueType-Schriften benutzen, da TrueType-Schriften auf dem Bildschirm und auf dem Drucker gleich gut ausgegeben werden. Palettenherkunft: Die Eigenschaft PALETTENHERKUNFT legt die Quelle für die für den Bericht auswählbaren Farben fest.

6.6.3

Die Dateneigenschaften eines Berichts

Ein Bericht besitzt die folgenden fünf Dateneigenschaften, die benutzt werden, um Informationen über die dem Bericht zu Grunde liegenden Daten einzugeben. Datenherkunft: Die Eigenschaft DATENHERKUNFT legt die Tabelle oder Abfrage fest, deren Daten dem Bericht zu Grunde liegen und kann zur Laufzeit verändert werden. Deshalb ist es sehr einfach, allgemeine Berichte zu erstellen, die immer wieder andere Datenquellen nutzen. Filter: Die Eigenschaft FILTER erlaubt es Ihnen, den Bericht mit einem speziellen Filter zu öffnen. Ich bevorzuge es normalerweise, den Bericht auf einer Abfrage aufzubauen anstatt einen Filter darauf anzuwenden. Andererseits kann es sinnvoll sein, den Bericht auf einer Abfrage aufzubauen, dann aber unter bestimmten temporären Umständen zur Laufzeit einen Filter anzuwenden und wieder zu entfernen. Filter aktiv: Die Eigenschaft FILTER AKTIV legt fest, ob ein Berichtsfilter angewandt wird. Wenn der Wert dieser Eigenschaft auf NEIN gesetzt ist, wird die Filtereigenschaft ignoriert. Sortiert nach: Die Eigenschaft SORTIERT werden, wenn der Bericht geöffnet wird.

NACH

legt fest, wie die Datensätze sortiert

Sortierung aktiv: Die Eigenschaft SORTIERUNG AKTIV bestimmt, ob die Eigenschaft SORTIERT NACH des Berichts benutzt wird. Wenn der Wert dieser Eigenschaft auf NEIN gesetzt ist, wird die Eigenschaft SORTIERT NACH ignoriert.

6.6.4

Andere Berichtseigenschaften

Ein Bericht verfügt über zehn Eigenschaften, die zur Kategorie ANDERE gehören. Diese Eigenschaften, die im Folgenden vorgestellt werden, erlauben es Ihnen, andere wichtige Aspekte des Berichts vorzugeben. Datensätze sperren: Die Eigenschaft DATENSÄTZE SPERREN legt fest, ob die Tabellen, die benutzt werden, um den Bericht zu erstellen, während der Laufzeit des

226

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Berichts gesperrt werden sollen. Die zwei Werte für diese Eigenschaft sind KEINE SPERRUNGEN und ALLE DATENSÄTZE, wobei KEINE SPERRUNGEN der Standardwert ist. Er bedeutet, dass kein Datensatz in den zu Grunde liegenden Tabellen des Berichts gesperrt wird, solange der Bericht ausgeführt wird. Das kann verheerend sein, wenn komplizierte Berichte gestartet werden. Die Daten im Bericht könnten geändert werden, während der Bericht ausgeführt wird, was die Zahlen für Summen und Prozentanteile ungültig werden ließe. Obwohl die Option ALLE DATENSÄTZE für diese Eigenschaft alle Datensätze in allen Tabellen sperrt, die im Bericht enthalten sind (und somit jegliche Dateneingaben verhindert, solange der Bericht ausgeführt wird), ist dies ein notwendiges Übel, um genaue Berichte zu erstellen. Datumsgruppierung: Die Eigenschaft DATUMSGRUPPIERUNG legt fest, wie die Gruppierung von Datumsangaben in Ihrem Bericht erfolgt. Die Einstellung USSTANDARD bedeutet, dass Access die Standards für die Vereinigten Staaten für Berichtsgruppierungen benutzt. Sonntag ist also der erste Tag der Woche, die erste Woche beginnt am ersten Januar und so weiter. Der Wert SYSTEMEINSTELLUNGEN VERWENDEN bedeutet, dass die Gruppierungen auf den regionalen Ländereinstellungen in der Systemsteuerung basieren statt auf den US-Standards. Menüleiste: Die Eigenschaft MENÜLEISTE gibt Ihnen die Möglichkeit, eine eigene Menüleiste mit dem Bericht zu verknüpfen, die sichtbar wird, wenn der Benutzer sich den Bericht ansieht. Durch Hinzufügen eines eigenen Menüs können Sie beeinflussen, was der Benutzer tun kann, während der Bericht aktiv ist. Symbolleiste: Die Eigenschaft SYMBOLLEISTE erlaubt es Ihnen, eine eigene Symbolleiste mit dem Bericht zu verknüpfen, die sichtbar wird, wenn der Benutzer sich den Bericht ansieht. Kontextmenüleiste: Die Eigenschaft KONTEXTMENÜLEISTE legt fest, welches Kontextmenü mit dem Bericht assoziiert wird, während er sich in der Voransicht befindet. Die Kontextmenüleiste erscheint, wenn der Benutzer mit der rechten Maustaste auf das Vorschaufenster klickt. Schneller Laserdruck: Die Eigenschaft SCHNELLER LASERDRUCK legt fest, ob Linien und Rechtecke durch Buchstabenzeichen ersetzt werden sollen, wenn Sie den Bericht auf einem Laserdrucker ausdrucken. Wenn eine schnelle Druckausgabe Ihr Ziel ist und Sie einen Laserdrucker einsetzen, sollten Sie diese Eigenschaft auf JA setzen. Hilfedatei, Hilfekontext-ID: Mit den Eigenschaften HILFEDATEI, HILFEKONTEXTID können Sie eine Hilfedatei und ein Hilfethema mit Ihrem Bericht verknüpfen. Marke: Die Eigenschaft MARKE ist eine zusätzliche Eigenschaft, um benutzerdefinierte Informationen entweder in der Entwurfsphase oder zur Laufzeit zu speichern. Dies ist die Art von Microsoft Access, Ihnen eine zusätzliche Eigenschaft an die Hand zu geben. Access macht keinen Gebrauch von dieser Eigenschaft. Wenn Sie selbst keinen Nutzen daraus ziehen, wird sie nie benutzt.

Welche Steuerelementeigenschaften stehen zur Verfügung?

227

Enthält Modul: Die Eigenschaft ENTHÄLT MODUL legt fest, ob ein Bericht ein verknüpftes Modul enthält. Wenn kein Programmtext im Bericht enthalten ist, kann das Ausschalten der Klassenmodule sowohl die Leistung verbessern als auch die Größe der Datenbank reduzieren. Ein Bericht ohne ein Klassenmodul wird als »leichtgewichtiges Objekt« angesehen, das schneller geladen und angezeigt wird als ein Objekt mit verknüpftem Klassenmodul. Ein paar der Verhaltensweisen der Eigenschaft ENTHÄLT MODUL verdienen besondere Beachtung. Wenn ein Bericht erstellt wird, lautet der Wert für die Eigenschaft ENTHÄLT MODUL standardmässig NEIN. Access setzt die Eigenschaft ENTHÄLT MODUL automatisch auf JA, wenn Sie versuchen, ein Modul von diesem Bericht aus einzusehen. Wenn Sie die Eigenschaft ENTHÄLT MODUL auf NEIN setzen, löscht Access das Klassenmodul des Objekts und den ganzen Programm-Code, der darin enthalten ist.

6.7

Welche Steuerelementeigenschaften stehen zur Verfügung und warum sollten sie benutzt werden?

Wie Berichte besitzen auch Steuerelemente Eigenschaften. Die meisten Steuerelementeigenschaften können während des Entwurfs und zur Laufzeit geändert werden, was Ihnen gestattet, Ihre Berichte auf einfache Weise flexibel zu machen. So sind zum Beispiel manche Steuerelemente nur dann sichtbar, wenn bestimmte Bedingungen erfüllt sind.

6.7.1

Die Formateigenschaften eines Steuerelements

Sie können verschiedene Formateigenschaften des ausgewählten Objekts verändern, indem Sie die Symbolleiste FORMATIERUNG benutzen. Wenn Sie es bevorzugen, können Sie aber all diese Eigenschaften auch im Eigenschaftenfenster verändern. Format: Die Eigenschaft FORMAT legt fest, wie die Daten im Steuerelement dargestellt werden. Diese Eigenschaft wird automatisch von dem zu Grunde liegenden Feld geerbt. Wenn Sie möchten, dass die Formatierung des Steuerelements von der des zu Grunde liegenden Feldes abweicht, müssen Sie die Eigenschaft FORMAT des Steuerelements ändern. Beschriftung: Die Eigenschaft BESCHRIFTUNG gibt den Text für Bezeichnungsfelder und Befehlsschaltflächen an. Eine Beschriftung ist eine Zeichenfolge, die bis zu 2048 Zeichen enthalten kann. Hyperlink-Adresse: Die Eigenschaft HYPERLINK-ADRESSE ist eine Zeichenfolge, die einen UNC-Pfad (Netzwerkpfad) oder einen URL (Webadresse) darstellt.

228

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Befehlsschaltflächen, Bild-Steuerelemente und Bezeichnungsfelder enthalten alle die Eigenschaft HYPERLINK-ADRESSE. Hyperlink-Unteradresse: Die Eigenschaft HYPERLINK-UNTERADRESSE ist eine Zeichenfolge, welche einen Ort innerhalb des Dokuments darstellt, das in der Eigenschaft HYPERLINK-ADRESSE genannt ist. Befehlsschaltflächen, Bild-Steuerelementes und Bezeichnungsfelder enthalten alle die Eigenschaft HYPERLINK-UNTERADRESSE. Dezimalstellenanzeige: Die Eigenschaft DEZIMALSTELLENANZEIGE definiert die Anzahl der Dezimalstellen für Zahlenwerte. Sichtbar: Die Eigenschaft SICHTBAR legt fest, ob ein Steuerelement sichtbar ist. In vielen Fällen wollen Sie die Sichtbarkeit eines Steuerelements je nach Situation einund ausschalten. Duplikate ausblenden: Die Eigenschaft DUPLIKATE AUSBLENDEN versteckt doppelte Datenwerte im Detailbereich eines Berichts. Doppelte Datenwerte treten auf, wenn ein oder mehrere aufeinander folgende Datensätze in einem Bericht in einem oder mehreren Feldern den gleichen Wert aufweisen. Vergrößerbar, Verkleinerbar: Wenn die Eigenschaft VERGRÖSSERBAR auf JA gesetzt ist, erlaubt sie dem Steuerelement, sich vertikal auszubreiten, um für die ganzen Daten Platz zu schaffen. Die Eigenschaft VERKLEINERBAR entfernt leere Zeilen, wenn im jeweiligen Datensatz in einem Feld keine Daten existieren. Dies kann zum Beispiel sinnvoll sein, wenn Sie in Briefetiketten standardmäßig zwei Zeilen für Adressdaten vorsehen, dies bei einem Datensatz aber nicht ausgenutzt wird und Sie nicht möchten, dass auf dem Etikett eine Leerzeile erscheint. Links, Oben, Breite, Höhe: Diese Eigenschaften bestimmen die Größe und Position des Steuerelements auf dem Bericht. Hintergrundart, Hintergrundfarbe: Die Eigenschaft HINTERGRUNDART kann auf NORMAL oder TRANSPARENT gesetzt werden. Wenn sie auf TRANSPARENT gesetzt ist, scheint die Farbe des Berichts durch das Steuerelement hindurch. Beim Wert NORMAL bestimmt die Eigenschaft HINTERGRUNDFARBE die Farbe des Objekts. Spezialeffekt: Die Eigenschaft SPEZIALEFFEKT fügt dem Steuerelement einen 3-DEffekt hinzu. Rahmenart, Rahmenfarbe, Rahmenbreite: Diese Eigenschaften bestimmen das Erscheinungsbild des Objektrahmens. Textfarbe, Schriftart, Schriftgrad, Schriftbreite, Kursiv, Unterstrichen: Die Rahmeneigenschaften beeinflussen den Rahmen des Objekts. Diese Schrifteigenschaften hingegen bestimmen das Aussehen des Textes im Steuerelement. Textausrichtung: Die Eigenschaft TEXTAUSRICHTUNG bestimmt die Ausrichtung von Text innerhalb des Steuerelements. Sie kann auf LINKSBÜNDIG, ZENTRIERT, RECHTSBÜNDIG oder VERTEILEN gesetzt werden. Beim Wert VERTEILEN wird der Text in Blocksatz dargestellt.

Welche Steuerelementeigenschaften stehen zur Verfügung?

229

Linker Rand, Oberer Rand, Rechter Rand, Unterer Rand: Diese Eigenschaften werden benutzt, um festzulegen, wie weit entfernt von der linken, oberen, rechten und unteren Kante des Steuerelements der Text gedruckt wird. Diese Eigenschaften sind besonders für große Steuerelemente nützlich, die viel Text enthalten, wie zum Beispiel ein Memofeld auf einer Rechnung. Zeilenabstand: Die Eigenschaft ZEILENABSTAND wird benutzt, um den Abstand zwischen den Zeilen des Textes im Steuerelement festzulegen. Ist Hyperlink: Die Eigenschaft IST HYPERLINK wird genutzt, um festzulegen, ob der Text im Steuerelement als Hyperlink dargestellt werden soll. Wenn die Eigenschaft IST HYPERLINK auf JA gesetzt und der Text innerhalb des Steuerelements ein gültiger Link ist, fungiert der Text als Hyperlink. (Das ist nur dann sinnvoll, wenn Sie den Bericht im HTML-Format speichern.)

6.7.2

Die Dateneigenschaften eines Steuerelements

Die Dateneigenschaften eines Steuerelements legen Informationen über die Daten fest, die dem Bericht zu Grunde liegen. Steuerelementinhalt: Die Eigenschaft STEUERELEMENTINHALT legt das Feld in der Datenquelle des Berichts fest, welches das Steuerelement ausfüllt. Ein Steuerelementinhalt kann auch ein gültiger Ausdruck sein. Laufende Summe: Die Eigenschaft LAUFENDE SUMME (die es nur bei Berichten gibt) ist recht leistungsfähig. Sie kann genutzt werden, um Summen über alle Datensätze oder nur für die Datensätze einer Gruppe zu bilden. Sie kann auf NEIN, ÜBER GRUPPE und ÜBER ALLES gesetzt werden. Wenn sie auf ÜBER GRUPPE gesetzt wird, sammelt der Wert im Textfeld die Daten von allen Datensätzen innerhalb der Gruppe, wird aber jedes Mal wieder zurückgesetzt, wenn der Gruppenwert sich ändert. Ein Beispiel hierfür ist ein Bericht, der Einlagenbeträge für jeden Staat anzeigt, wobei eine laufende Summe für alle Einlagen innerhalb des Staates gebildet wird. Jedesmal, wenn der Staat wechselt, wird der Betrag auf Null gesetzt. Wenn die Eigenschaft den Wert ÜBER ALLES aufweist, wird die Summe über den ganzen Bericht weitergebildet.

6.7.3

Die anderen Eigenschaften eines Steuerelements

Die anderen Eigenschaften eines Steuerelements sind solche, die nicht in eine der anderen Kategorien passen. Name: Die Eigenschaft NAME bietet Ihnen einen einfachen und selbstdokumentierenden Weg, um auf das Steuerelement aus einem VBA-Programm und auch aus vielen anderen Situationen heraus zuzugreifen. Sie sollten alle Ihre Steuerelemente benennen. Lesen Sie den Anhang, um genauere Informationen zu erhalten.

230

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Vertikal: Die Eigenschaft VERTIKAL legt fest, ob der Text innerhalb des Steuerelements vertikal dargestellt werden soll. Der Standardwert lautet NEIN. Marke: Wie die Eigenschaft MARKE eines Berichts gibt die Eigenschaft MARKE eines Steuerelements Ihnen einen benutzerdefinierten Eintrag für Ihr Steuerelement. Sie können beliebige zusätzliche Informationen in die Eigenschaft MARKE eintragen. Ein von Entwicklern häufig begangener Fehler besteht darin, Steuerelementen Namen zu geben, die mit Access-Namen in Konflikt treten. Diese Art Fehler ist sehr schwer aufzuspüren. Stellen Sie sicher, dass Sie eindeutige Namen sowohl für Felder als auch für Steuerelemente benutzen. Geben Sie weiterhin niemals einem Steuerelement den gleichen Namen wie einem Feld, das innerhalb seines Ausdrucks auftaucht. Der Ausdruck =ClientName & Titel sollte nicht den Namen »ClientName« bekommen. Das würde eine Fehlermeldung auslösen. Geben Sie einem Steuerelement nicht den gleichen Namen wie seinem Inhalt. Access gibt gebundenen Steuerelementen den gleichen Namen wie deren Felder, Sie müssen diese also umbenennen, um Probleme zu vermeiden. Wenn Sie diese einfachen Warnungen befolgen, werden Sie sich eine Menge Ärger ersparen.

6.8

Seitenumbrüche einfügen

Seitenumbrüche können so gesetzt werden, dass sie vor, innerhalb oder nach einem Abschnitt auftauchen. Die Art und Weise, wie Sie jeden Seitenumbruchtyp setzen, ist recht unterschiedlich. Um einen Seitenumbruch innerhalb eines Abschnitts zu setzen, müssen Sie das Werkzeug SEITENWECHSEL aus der Toolbox benutzen. Klicken Sie auf das Werkzeug SEITENWECHSEL in der Toolbox und dann dort in den Bericht, wo Sie den Seitenumbruch einfügen möchten. Um einen Seitenumbruch vor beziehungsweise nach einem Abschnitt einzufügen, setzen Sie die Eigenschaft NEUE SEITE des Abschnitts auf VOR BEREICH, NACH BEREICH bzw. VOR & NACH. Die Eigenschaft NEUE SEITE gilt für Gruppenköpfe, Gruppenfüße und den Detailbereich des Berichts. Achten Sie darauf, einen Seitenumbruch nicht innerhalb eines Steuerelements des Berichts zu setzen. Der Seitenumbruch wird dann inmitten der Daten des Steuerelements auftauchen.

Gebundene, ungebundene und berechnete Steuerelemente

6.9

231

Gebundene, ungebundene und berechnete Steuerelemente

Drei Arten von Steuerelemente können in einen Bericht eingefügt werden: gebundene, ungebundene und berechnete Steuerelemente. Ungebundene Steuerelemente wie zum Beispiel in den Bericht aufgenommene Logos sind nicht an Daten gebunden, während gebundene Steuerelemente direkt von den Daten innerhalb eines Feldes der zu Grunde liegenden Tabelle oder Abfrage abhängen. Berechnete Steuerelemente enthalten gültige Ausdrücke. Sie können alles enthalten, von einer Seitenzahl bis hin zu ausgeklügelten Finanzkalkulationen. Die meisten komplexen Berichte enthalten eine Kombination aus vielen gebundenen, ungebundenen und berechneten Steuerelementen.

6.10

Berichte mit Hilfe von Ausdrücken erweitern

Berechnete Steuerelemente benutzen Ausdrücke als ihre Steuerelementinhalte. Um ein berechnetes Steuerelement zu erstellen, müssen Sie erst ein ungebundenes Steuerelement zu Ihrem Bericht hinzufügen. Ausdrücke müssen mit einem Gleichheitszeichen (=) beginnen; ein Beispiel für einen Berichtsausdruck ist =Summe([BillableHours]). Dieser Ausdruck addiert, wenn er in den Berichtsfuß gesetzt wird, die Inhalte des Steuerelements BillableHours aller Datensätze im Bericht. Sie können einen Ausdruck aufbauen, indem Sie ihn direkt als Steuerelementinhalt eingeben oder den Ausdrucks-Generator verwenden, der in Kapitel 5 behandelt wird.

6.11

Berichte auf der Grundlage mehrerer Tabellen

Der Großteil Ihrer Berichte wird wahrscheinlich auf mehr als einer Tabelle beruhen. Das ist so, da eine ordentlich strukturierte Datenbank es meistens verlangt, dass Sie die Tabellendaten wieder zusammenführen, um ihrem Benutzer wertvolle Informationen zu geben. Ein Bericht, der die Daten aus Kunden-, Bestellungen-, Bestelldetailund Produkttabellen kombiniert, kann zum Beispiel die folgenden Informationen liefern:

 Kundeninformationen: Firmenname und Adresse  Bestellinformationen: Bestelldatum und Liefermethode  Bestelldetailinformationen: bestellte Menge, Preis  Produkttabelle: Produktbeschreibung Ein solcher, mehrere Tabellen verwendender Bericht, kann direkt auf den Tabellen beruhen, deren Daten er anzeigt, oder er kann auf einer Abfrage basieren, welche die Tabellen schon zusammengefügt hat und so eine flache Tabellenstruktur bietet.

232

6.11.1

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

1:n-Berichte erstellen

Sie können 1:n-Berichte erstellen, indem Sie den Berichts-Assistenten benutzen oder den Bericht von Grund auf aufbauen. Unterschiedliche Situationen erfordern verschiedene Vorgehensweisen, von denen einige in den folgenden Abschnitten behandelt werden. Einen 1:n-Bericht mit Hilfe des Berichts-Assistenten erstellen Einen 1:n-Bericht mit Hilfe des Berichts-Assistenten zu erstellen, ist recht einfach. Folgen Sie einfach diesen Schritten: 1. Klicken Sie in der Objektliste auf BERICHTE und doppelklicken Sie dann auf ERSTELLT EINEN BERICHT UNTER VERWENDUNG DES ASSISTENTEN. 2. Benutzen Sie das aufklappbare Listenfeld TABELLEN/ABFRAGEN, um die erste Tabelle oder Abfrage auszuwählen, deren Daten im Bericht erscheinen sollen. 3. Bestimmen Sie die Felder, die Sie aus dieser Tabelle einfügen wollen. 4. Wählen Sie nacheinander alle Tabellen oder Abfragen aus, die Sie in den Bericht einfügen wollen, und markieren Sie die erforderlichen Felder. 5. Klicken Sie auf WEITER, nachdem Sie alle gewünschten Felder aus allen Tabellen und Abfragen für Ihren Bericht ausgewählt haben. Der zweite Schritt des Berichts-Assistenten bietet Ihnen Vorschläge für das Layout Ihrer Daten (siehe Abbildung 6.16). Sie können die Vorschläge von Access annehmen oder eine andere der verfügbaren Layoutmöglichkeiten auswählen. Klicken Sie auf WEITER.

Abbildung 6.16: Der zweite Schritt im Berichts-Assistenten: ein Layout auswählen

Berichte auf der Grundlage mehrerer Tabellen

233

6. Im dritten Schritt des Berichts-Assistenten werden Sie gefragt, ob Sie irgendwelche Gruppierungen hinzufügen möchten. Gruppierungen können benutzt werden, um Daten optisch zu trennen und Zwischensummen zu bilden. Im Beispiel in Abbildung 6.17 wurde der Bericht nach Städten und Firmennamen gruppiert. Nachdem Sie Gruppierungen ausgewählt haben, klicken Sie auf WEITER.

Abbildung 6.17: Der dritte Schritt im Berichts-Assistenten: Gruppierungen auswählen

7. Im nächsten Schritt des Berichts-Assistenten können Sie auswählen, wie Sie die Datensätze im Detailbereich des Berichts sortiert haben möchten (siehe Abbildung 6.18). Dieser Schritt des Assistenten erlaubt es Ihnen auch, zusammenfassende Berechnungen anzugeben, die auf Ihre Daten angewendet werden sollen. Mit Hilfe der Schaltfläche ZUSAMMENFASSUNGSOPTIONEN können Sie sich auch dazu entscheiden, den Prozentwert der gesamten Berechnungen aufzuführen. 8. Im fünften Schritt des Berichts-Assistenten wählen Sie das Layout und die Ausrichtung Ihres Berichts aus. Die Layoutoptionen lauten ABGESTUFT, IN BLÖCKEN, GLIEDERUNG 1, GLIEDERUNG 2, LINKS AUSRICHTEN 1 und LINKS AUSRICHTEN 2. 9. Der sechste Schritt des Berichts-Assistenten lässt Sie aus vordefinierten Formaten für Ihren Bericht auswählen. Die Formate sind FETT, FORMAL, GESCHÄFTLICH, INFORMELL, KOMPAKT und WEICHES GRAU. Sie können sich jedes Format in einer Vorschau ansehen.

234

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Abbildung 6.18: Der vierte Schritt im Berichts-Assistenten: eine Sortierreihenfolge auswählen

Abbildung 6.19: Zusammenfassende Berechnungen hinzufügen

10. Im siebten und letzten Schritt des Berichts-Assistenten legen Sie einen Titel für den Bericht fest. Der Titel wird gleichzeitig auch der Name für den Bericht. Ich wähle einen angemessenen Namen und ändere den Titel, nachdem der Assistent fertig ist. Der letzte Schritt gibt Ihnen auch die Möglichkeit zu entscheiden, ob Sie den fertigen Bericht sofort betrachten oder noch einmal die Entwurfsansicht sehen wollen. Den im vorherigen Beispiel erstellten Bericht sehen Sie in Abbildung 6.20. Beachten Sie, dass der Bericht nach den Feldern ORT und FIRMA sortiert und gruppiert wurde.

Berichte auf der Grundlage mehrerer Tabellen

235

Die Daten des Berichts sind nach den Feldern BESTELLDATUM und ARTIKELGRUPPE innerhalb der FIRMENGRUPPE sortiert.

Abbildung 6.20: Ein fertiggestellter 1:n-Bericht

Diese Methode zum Erstellen von 1:n-Berichten ist bei weitem die einfachste. In der Tat war das Verfahren des Verknüpfens im Hintergrund eine der Hauptverbesserungen in Access für Windows 95. Es wird von den Assistenten genutzt, wenn Sie Felder aus verschiedenen Tabellen auswählen, um zu bestimmen, wie die komplexen Abfragen, die für den Bericht oder das Formular benötigt werden, zu erstellen sind. Dieses Verfahren spart Ihnen viel Zeit und sorgt dafür, dass Sie beim Erstellen eines Berichts von unnötig komplexen Entscheidungen verschont bleiben. Obwohl Sie von dieser Funktion Gebrauch machen sollten, ist es wichtig, dass Sie als Entwickler wissen, was hinter den Kulissen passiert. Die folgenden zwei Abschnitte geben Ihnen dieses notwendige Wissen. Einen Bericht auf der Grundlage einer 1:n-Abfrage erstellen Eine andere beliebte Methode zum Erstellen eines Berichts besteht darin, ihn auf einer 1:n-Abfrage aufzubauen. Ein 1:n-Bericht, der auf diesem Wege entsteht, wird genauso erstellt, als würde er auf den Daten einer einzelnen Tabelle beruhen. Zuerst erstellen Sie die Abfrage, die dem Bericht zu Grunde liegen soll (siehe Abbildung 6.21). Wenn Sie die Abfrage fertig gestellt haben, können Sie diese anstelle all der Tabellen auswählen (wie es im vorhergegangenen Abschnitt gemacht wurde). Nachdem die Abfrage ausgewählt wurde, gehen Sie zum Erstellen des Berichts genauso vor wie im vorangegangenen Beispiel.

236

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Abbildung 6.21: Ein Beispiel für eine Abfrage, die als Grundlage für einen 1:n-Bericht fungiert

Einen 1:n-Bericht mit Hilfe des Unterberichts-Assistenten erstellen Ein 1:n-Bericht kann auch erstellt werden, indem Sie den Hauptbericht erstellen und dann ein Unterbericht-Steuerelement hinzufügen. Diese Methode wird oft benutzt, um Berichte wie etwa Rechnungen zu erstellen, welche die Berichtsdaten in einer 1:n-Beziehung anstatt in einem unstrukturierten Format darstellen (wie in Abbildung 6.20 gezeigt). Wenn Sie den Unterformular/Unterberichts-Assistenten benutzen wollen, müssen Sie sicherstellen, dass das Werkzeug STEUERELEMENT-ASSISTENTEN ausgewählt ist, bevor Sie das Unterformular/Unterbericht-Steuerelement dem Hauptbericht hinzufügen. Gehen Sie dazu wie folgt vor: 1. Klicken Sie die Schaltfläche UNTERFORMULAR/-BERICHT in der Symbolleiste an, um das Werkzeug auszuwählen. 2. Klicken Sie auf die Stelle im Hauptbericht, an der das Steuerelement erscheinen soll. UNTERFORMULAR/UNTERBERICHT-Steuerelemente werden in der Regel in den Detailbereich des Berichts eingefügt. Wenn Sie das UNTERFORMULAR/ UNTERBERICHT-Steuerelement in den Bericht gesetzt haben, wird der UNTERBERICHTS-ASSISTENT aufgerufen. 3. Geben Sie an, ob Sie möchten, dass der Unterbericht auf einem bereits vorhandenen Bericht oder Formular basiert, oder ob Sie einen neuen Unterbericht basierend auf einer Abfrage oder Tabelle erstellen möchten. Klicken Sie auf WEITER. 4. Wenn Sie sich für die zweite Möglichkeit entschieden haben, müssen Sie die Tabelle oder Abfrage auswählen, auf der Ihr Unterbericht basieren soll. Sie können sogar Felder von mehr als einer Tabelle oder Abfrage auswählen. Wenn Sie fertig sind, klicken Sie auf WEITER.

Berichte auf der Grundlage mehrerer Tabellen

237

5. Der nächste Schritt des Unterberichts-Assistenten schlägt eine Beziehung zwischen dem Hauptbericht und dem Unterbericht vor (siehe Abbildung 6.22). Sie können die ausgewählte Beziehung akzeptieren oder eine eigene definieren. Wenn Sie fertig sind, klicken Sie auf WEITER. 6. Der letzte Schritt des Unterberichts-Assistenten fragt Sie nach dem Namen des Unterberichts. Gemäß Konvention sollte der Name mit »rsub« beginnen. Klicken Sie auf FERTIG STELLEN, wenn Sie fertig sind.

Abbildung 6.22: Der UnterberichtsAssistent: die Beziehung festlegen

Wie Sie in Abbildung 6.23 sehen können, wird die 1:n-Beziehung zwischen zwei Tabellen durch diese Art von Bericht klar hervorgehoben. Im Beispiel wird jeder Kunde aufgelistet. Alle Detaildatensätze, welche die Bestellungen von jedem Kunden in der Liste wiedergeben, werden gleich hinter den Kundendaten aufgeführt.

6.11.2

Unterberichte

Wenn ein Unterbericht zu einem Bericht hinzugefügt wurde, ist es wichtig zu verstehen, welche Eigenschaften durch den Unterberichts-Assistenten festgelegt wurden, damit Sie das Steuerelement ggf. ändern können. Sie sollten sich mit einigen Eigenschaften eines Unterberichts vertraut machen: Herkunftsobjekt: Der Name des Berichts oder eines anderen Objekts, das im Steuerelement dargestellt wird Verknüpfen von: Die Felder aus dem Unterbericht, die den Unterbericht mit dem Hauptbericht verknüpfen

238

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Abbildung 6.23: Ein fertiggestellter 1:n-Bericht, der mit dem Unterformular-/Unterberichts-Assistenten erstellt wurde

Verknüpfen nach: Die Felder aus dem Hauptbericht, die den Hauptbericht mit dem Unterbericht verknüpfen Vergrößerbar: Legt fest, ob sich das Steuerelement in vertikaler Richtung vergrößern kann, um den Daten im Unterbericht Platz zu verschaffen Verkleinerbar: Legt fest, ob leere Zeilen entfernt werden sollen, wenn im Unterbericht keine Daten vorhanden sind Sie sollten nicht nur wissen, wie Sie mit den Eigenschaften eines Unterberichts umgehen, sondern Sie sollten den Unterbericht auch aus dem Hauptbericht heraus verändern können. Sie können den Unterbericht immer bearbeiten, indem Sie ihn in der Liste der Berichte im Datenbankfenster auswählen. Um das zu tun, klicken Sie auf den zu modifizierenden Bericht und dann auf ENTWURF. Sie können einen Unterbericht auch verändern, indem Sie seine Objekte direkt im Hauptbericht auswählen.

6.12

Sortierreihenfolge und Gruppierung

Entgegen der Sortierung in Formularen wird die Sortierung der Daten innerhalb eines Berichts nicht von der zu Grunde liegenden Abfrage vererbt. In der Tat beeinflusst die zugrunde liegende Abfrage die Sortierung des Berichts nur dann, wenn keine Sortierung für den Bericht angegeben wurde. Jede Sortierreihenfolge, die in der Abfrage festgelegt wurde, wird komplett von der Sortierreihenfolge des Berichts überschrieben, deren Festlegung im Dialogfeld SORTIEREN UND GRUPPIEREN erfolgt (siehe Abbildung 6.24). Das Sortieren sowie das Gruppieren des Berichts wird von den Optionen beeinflusst, die Sie auswählen, wenn Sie den Berichts-Assistenten ausführen. Das Dialogfeld SORTIEREN UND GRUPPIEREN können Sie benutzen, um Sortier- beziehungsweise Gruppierungsmöglichkeiten für Ihren Bericht hinzuzufü-

239

Sortierreihenfolge und Gruppierung

gen, zu entfernen oder zu verändern. Sortierungen beeinflussen schlicht die Reihenfolge der Datensätze im Bericht. Gruppierungen fügen Gruppenköpfe und -füße zu ihrem Bericht hinzu.

Abbildung 6.24: Das Fenster Sortieren und gruppieren bei einer Gruppierung nach Stadt- und Firmennamen sowie einer Sortierung nach dem Bestelldatum und der Artikelbezeichnung

6.12.1

Eine Sortierreihenfolge und eine Gruppierung hinzufügen

Häufig möchten Sie eine Sortierung oder eine Gruppierung zu einem Bericht hinzufügen. Um das zu tun, folgen Sie diesen vier Schritten: 1. Klicken Sie auf der Symbolleiste BERICHTSENTWURF auf SORTIEREN PIEREN, um das Dialogfeld SORTIEREN UND GRUPPIEREN zu öffnen.

UND GRUP-

2. Klicken Sie auf den Markierer der Zeile, über der Sie die Sortierung oder Gruppierung einfügen möchten. In Abbildung 6.25 wird eine Sortierung oder Gruppierung über der Gruppierung ORT eingefügt. Drücken Sie die (Einfg)-Taste, um eine leere Zeile in das Dialogfeld SORTIEREN UND GRUPPIEREN einzufügen.

Abbildung 6.25: Eine Sortier- oder Gruppierungsstufe einfügen

3. Klicken Sie in das Feld FELD/AUSDRUCK und benutzen Sie die aufklappbare Liste, um das Feld auszuwählen, nach dem Sie sortieren oder gruppieren wollen. 4. Setzen Sie die Eigenschaften, um festzulegen, auf welche Weise sortiert oder gruppiert werden soll (siehe nächster Abschnitt).

240

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Um eine hinzugefügte Sortierung oder Gruppierung wieder zu entfernen, klicken Sie den Markierer der Zeile im Dialogfeld SORTIEREN UND GRUPPIEREN an, die Sie entfernen möchten. Dann drücken Sie die (Entf)-Taste. Sie werden gewarnt, dass alle Steuerelemente in den Gruppenköpfen- und füßen verloren gehen.

6.12.2

Sortier- und Gruppeneigenschaften

Jede Gruppierung in einem Bericht verfügt über Eigenschaften, welche die Attribute der Gruppe festlegen. Jede Gruppe besitzt darüber hinaus fünf Eigenschaften, die angeben, ob das Feld oder der Ausdruck zum Sortieren, Gruppieren oder für beides benutzt wird (siehe Abbildung 6.26). Außerdem können Sie mit Hilfe dieser Eigenschaften Details über die Gruppierungsoptionen festlegen. Die Sortier- und Gruppeneigenschaften sind Folgende: Gruppenkopf: Die Eigenschaft GRUPPENKOPF gibt an, ob die ausgewählte Gruppe einen Kopfbereich enthält. Wenn Sie die Eigenschaft GRUPPENKOPF auf JA setzen, erscheint eine zusätzliche Zeile im Bericht, die Sie nutzen können, um Informationen über die Gruppe anzuzeigen. Wenn Sie zum Beispiel nach Ländern gruppieren, kann der Gruppenkopf benutzt werden, um den Namen des Landes anzuzeigen, das Sie gerade drucken. Wenn die beiden Eigenschaften GRUPPENKOPF und GRUPPENFUSS auf NEIN stehen, wird das Feld nur benutzt, um die Sortierreihenfolge der Datensätze für den Bericht festzulegen.

Abbildung 6.26: Das Fenster Sortieren und Gruppieren mit fünf Sortier- und Gruppeneigenschaften

Gruppenfuß: Die Eigenschaft GRUPPENFUSS gibt an, ob die ausgewählte Gruppe einen Fußbereich enthält. Wenn Sie die Eigenschaft GRUPPENFUSS auf JA setzen, erscheint eine zusätzliche Zeile im Bericht. Der Gruppenfußbereich kann verwendet werden, um zusammenfassende Informationen über die Gruppe darzustellen wie zum Beispiel Zwischensummen. Gruppieren nach: Die Eigenschaft GRUPPIEREN NACH legt das fest, was eine neue Gruppe ausmacht. Sie wird oft in Situationen benutzt, in denen Abteilungsdaten

Sortierreihenfolge und Gruppierung

241

zusammengefasst werden müssen. Anstatt zum Beispiel nach der ganzen Abteilungsnummer zu gruppieren, möchten Sie eventuell nur nach den ersten drei Ziffern Gruppen bilden. Intervall: Die Eigenschaft INTERVALL wird zusammen mit der Eigenschaft GRUPPIEREN NACH benutzt, um einen Intervallwert anzugeben, nach dem Daten gruppiert werden. Wenn zum Beispiel die Eigenschaft GRUPPIEREN NACH für ein Textfeld auf ANFANGSZEICHEN gesetzt ist und das Intervall auf 3 steht, werden die Felddaten nach den ersten drei Buchstaben gruppiert. Zusammenhalter: Die Eigenschaft ZUSAMMENHALTER legt fest, ob Access versucht, die gesamte Gruppe auf einer Seite zusammenzuhalten. Die drei Optionen lauten NEIN, GANZE GRUPPE, und MIT 1. DETAILDATENSATZ. Die Option GANZE GRUPPE bedeutet, dass Access versucht, die ganze Gruppe auf einer Seite zu behalten, was den Gruppenkopf, den Gruppenfuß und den Detailbereich mit einschließt. Die Möglichkeit MIT 1. DETAILDATENSATZ bedeutet, dass Access den Gruppenkopf nur dann auf eine Seite druckt, wenn es auch den ersten Detaildatensatz mit auf die gleiche Seite drucken kann. Wenn Sie die Eigenschaft ZUSAMMENHALTER auf GANZE GRUPPE gesetzt haben und die Gruppe zu groß ist, um auf eine Seite zu passen, ignoriert Access diese Einstellung. Weiterhin ignoriert Access die Eigenschaft ZUSAMMENHALTER, wenn Sie diese auf MIT 1. DETAILDATENSATZ setzen und entweder der Gruppenkopf oder der Detaildatensatz zu groß ist, um auf eine Seite zu passen.

6.12.3

Was sind Gruppenkopf- und -fußeigenschaften und warum sollten sie verwendet werden?

Jeder Gruppenkopf und -fuß hat seine speziellen Eigenschaften, die sein Verhalten festlegen: Neue Seite: Die Eigenschaft NEUE SEITE kann auf KEINE, VOR, NACH und VOR & NACH gesetzt werden. Beim Wert KEINE erscheint kein Seitenwechsel vor oder nach dem Berichtsabschnitt, bei VOR wird ein Seitenwechsel vor und bei NACH hinter dem Berichtsabschnitt eingefügt. Bei Auswahl von VOR & NACH erscheint ein Seitenwechsel sowohl vor dem Berichtsabschnitt als auch danach. Neue Zeile oder Spalte: Die Eigenschaft NEUE ZEILE ODER SPALTE legt fest, ob ein Spaltenwechsel erfolgt, wenn der Berichtsabschnitt gedruckt wird. Diese Eigenschaft gilt nur für mehrspaltige Berichte. Die Auswahlmöglichkeiten sind KEINE, VOR, NACH und VOR & NACH. Wie die Eigenschaft NEUE SEITE bestimmt diese Eigenschaft, ob ein Spaltenwechsel auftritt, bevor und/oder nachdem der Berichtsabschnitt gedruckt wurde, bzw. ob der Berichtsabschnitt überhaupt eine Rolle spielt.

242

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Zusammenhalten: Die Eigenschaft ZUSAMMENHALTEN gibt an, ob Sie möchten, dass Access versucht, den gesamten Berichtsabschnitt zusammen auf eine Seite zu drucken. Wenn diese Eigenschaft auf JA gesetzt ist, druckt Access den Abschnitt auf der nächsten Seite, wenn es den gesamten Abschnitt nicht mehr auf der aktuellen Seite drucken kann. Wenn sie auf NEIN gesetzt ist, druckt Access so viel von dem Abschnitt auf die aktuelle Seite wie möglich und fügt dann einen Seitenumbruch ein. Wenn ein Abschnitt die Seitenlänge überschreitet, beginnt Access den Druck auf einer neuen Seite und fährt mit dem Drucken auf der Folgeseite fort. Sichtbar: Die Eigenschaft SICHTBAR bestimmt, ob der Abschnitt sichtbar ist. Häufig muss ein spezieller Berichtsbereich zur Laufzeit wegen verschiedener Umstände versteckt werden. Das kann leicht erledigt werden, indem man den Wert der Eigenschaft SICHTBAR des Berichtsabschnitts mit einem VBA-Programm verändert, welches auf das FORMAT-Ereignis reagiert. Vergrößerbar, Verkleinerbar: Die Eigenschaft VERGRÖSSERBAR legt fest, ob sich der Abschnitt vertikal ausdehnen soll, um den Daten darin Platz zu verschaffen. Die Eigenschaft VERKLEINERBAR gibt an, ob sie möchten, dass der Abschnitt vertikal schrumpft und so Leerzeilen unterdrückt. Bereich wiederholen: Die Eigenschaft BEREICH WIEDERHOLEN ist sehr nützlich. Mit ihrer Hilfe können Sie festlegen, ob der Gruppenkopf auf jeder nachfolgenden Seite wiederholt wird, wenn der Berichtsabschnitt mehr als eine Seite für den Ausdruck braucht.

6.13

Durch Aufsetzen der Berichte auf gespeicherte Abfragen Geschwindigkeit und Wiederverwendbarkeit verbessern

Normalerweise ist es am besten, Ihren Access-Bericht auf einer Abfrage aufzubauen. Das bietet Ihnen mehrere Vorteile:

 Die Abfrage, die dem Bericht zugrunde liegt, kann von anderen Formularen und Berichten genutzt werden.

 Kompliziertere Berechnungen brauchen nur noch einmal erstellt zu werden – Sie müssen sie nicht mehr für jeden Bericht (oder jedes Formular) neu erstellen. Mit früheren Versionen von Access wurden Berichte, die auf gespeicherten Abfragen beruhten, schneller geöffnet als Berichte mit eingebetteten SQL-Anweisungen. Das war so, weil Access einen Abfrageplan erstellte, wann immer Sie eine Abfrage entworfen und abgespeichert hatten. Dieser Abfrageplan ist ein Ausführungsplan, der auf der Datenmenge in den Abfragetabellen sowie auf den verfügbaren Indizes in jeder Tabelle beruht. Wenn Sie in den früheren Versionen von Access einen Bericht starteten, der auf einer eingebetteten SQL-Anweisung beruhte, wurde die Abfrage

Access-Berichte und das Internet

243

kompiliert. Dabei wurde der Abfrageplan zur Laufzeit berechnet, was die Ausführung der Abfrage verlangsamte. In Access 2000 werden Abfragepläne für SQLAnweisungen zu dem Zeitpunkt erstellt, an dem das Formular oder der Bericht abgespeichert wird. Abfragepläne werden zusammen mit dem betreffenden Formular oder Bericht gespeichert. Was sind also die Vorteile davon, einen Bericht auf einer gespeicherten Abfrage anstatt auf einer eingebetteten SQL-Anweisung aufzusetzen? Häufig werden Sie mehrere Berichte und Formulare erstellen, die auf den gleichen Informationen beruhen. Eine eingebettete SQL-Anweisung kann nicht von mehreren Datenbankobjekten gemeinsam genutzt werden, sondern Sie müssen die Anweisung zumindest in jedes Formular und in jeden Bericht, das bzw. den Sie erstellen, hineinkopieren. Berichte und Formulare auf Abfragen aufzubauen, löst dieses Problem. Sie erstellen die Abfrage nur einmal und ändern sie später im Fall der Fälle ebenfalls nur einmal. Viele Formulare und Berichte können alle die gleiche Abfrage benutzen (einschließlich ihrer Kriterien, Ausdrücke und so weiter). Berichte enthalten häufig komplexe Ausdrücke. Wenn ein bestimmter Ausdruck nur in einem Bericht verwendet wird, geht nichts verloren, wenn man diesen Ausdruck in eine eingebettete SQL-Anweisung schreibt. Auf der anderen Seite werden jedoch viele komplexe Ausdrücke in mehreren Formularen und Berichten eingesetzt. Durch das Einbinden dieser Ausdrücke in Abfragen, auf denen die Berichte und Formulare aufbauen, brauchen Sie den Ausdruck nur noch einmal zu erstellen. Es ist einfach, eine eingebettete SQL-Anweisung als Abfrage zu speichern. Somit können Sie den BERICHTS-ASSISTENTEN benutzen, um einen Bericht zu erstellen, der mehrere Tabellen verwendet, und Sie können dann die resultierende SQLAnweisung als Abfrage speichern. Wenn der Bericht in der Entwurfsansicht geöffnet ist, öffnen Sie dazu das EIGENSCHAFTENfenster, klicken auf die Registerkarte DATEN und klicken anschließend im Feld DATENHERKUNFT auf die Schaltfläche mit den drei Punkten. Die eingebettete SQL-Anweisung erscheint nun als Abfrage. Wählen Sie DATEI|SPEICHERN ALS BZW. DATEI|EXPORTIEREN, geben Sie einen Namen für die Abfrage ein und klicken Sie jetzt auf OK. Schließen Sie das Abfragefenster; damit geben Sie an, dass Sie die Eigenschaft DATENHERKUNFT neu festlegen. Ihre Abfrage basiert nun auf einer gespeicherten Abfrage anstatt einer eingebetteten SQL-Anweisung.

6.14

Access-Berichte und das Internet

Microsoft hat es durch das Hinzufügen von Hyperlinks und dadurch, dass es Ihnen erlaubt wird, einen Access-Bericht als HTML-Dokument zu speichern, leichter gemacht, Internet-fähige Anwendungen zu entwickeln. Diese Funktionen werden in den folgenden Abschnitten behandelt.

244

6.14.1

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Einem Bericht einen Hyperlink hinzufügen

Hyperlinks können an Berichte in Form von Bezeichnungsfeldern hinzugefügt werden. Sobald Sie einen Hyperlink hinzugefügt haben, fungiert er als direkte Verbindung zu einer UNC- oder URL-Adresse. Um einen Hyperlink zu einem Bericht hinzuzufügen, folgen Sie diesen Schritten: 1. Wenn das Berichtsfenster in der Entwurfsansicht geöffnet ist, fügen Sie ein Bezeichnungsfeld zu dem Bericht hinzu. 2. Setzen Sie die Eigenschaft HYPERLINK-ADRESSE auf den UNC-Pfad oder URL, auf den Sie verweisen möchten. Der einfachste Weg dazu ist es, in das Feld der Eigenschaft HYPERLINK-ADRESSE und dann auf die Schaltfläche mit den drei Punkten zu klicken, um das Dialogfeld HYPERLINK EINFÜGEN zu öffnen. 3. Geben Sie den UNC-Pfad oder URL in das Textfeld DATEITYP ODER WEBSEITE ein. Sie können die Schaltfläche DATEI benutzen, um einen UNC-Pfad zu suchen, oder mit Hilfe der Schaltfläche WEBSEITEN einen URL ausfindig machen. 4. Wenn Sie eine Hyperlink-Unteradresse eingeben wollen, klicken Sie auf TEXTMARKE. Die Hyperlink-Unteradresse kann ein Abschnittsname, eine Foliennummer oder jeder andere bekannte Ort im Dokument sein, das im Textfeld DATEITYP ODER WEBSEITE steht. 5. Klicken Sie auf OK. Die Eigenschaften HYPERLINK-ADRESSE und HYPERLINKUNTERADRESSE enthalten nun die Informationen aus dem Dialogfeld HYPERLINK EINFÜGEN. Die Eigenschaften HYPERLINK-ADRESSE und HYPERLINK-UNTERADRESSE kommen nur dann ins Spiel, wenn ein Bericht als HTML-Dokument gespeichert und in einem Webbrowser, wie zum Beispiel dem Internet Explorer 5.0, angesehen wird. Das Abspeichern eines Berichts als HTML-Dokument wird im folgenden Abschnitt behandelt.

6.14.2

Einen Bericht als HTML speichern

Um einen Bericht als HTML abzuspeichern, wählen Sie DATEI|EXPORTIEREN. Benutzen Sie dann das aufklappbare Listenfeld DATEITYP, um HTML-Dokumente (*.htm, *.html) auszuwählen. Wählen Sie einen Speicherort und einen Namen für die Datei aus und klicken Sie auf SPEICHERN. Das Dokument wird als HTML gespeichert und bekommt den Namen und Ort, den Sie angegeben haben. Aktivieren Sie das Kontrollkästchen AUTOSTART, um den Bericht in Ihrem standardmäßigen Webbrowser anzuzeigen, nachdem das HTML erzeugt wurde.

Access-Berichte und das Internet

6.14.3

245

Für die Praxis

Berichte für Ihre Anwendung erstellen Das Zeit- und Abrechnungssystem benötigt mehrere Berichte, die Sie im Verlaufe dieses Buchs entwerfen werden. Einige der einfacheren werden hier erstellt.

6.14.4

Den Bericht rptClientListing entwerfen

Der Bericht rptClientListing listet alle Kunden in der Tabelle tblClients auf. Der Bericht enthält den Firmennamen, den Kontaktnamen, die Stadt, das Bundesland, die Postleitzahl und die Bürotelefonnummer eines jeden Kunden und ist nach dem Firmennamen sortiert. Der Bericht rptClientListing basiert auf einer Abfrage namens qryClientListing, die in Abbildung 6.27 gezeigt wird. Sie enthält die Felder COMPANYNAME (Firmenname), CITY (Stadt), STATE (Bundesland), OFFICEPHONE (Telefon) und FAX. Die Abfrage enthält zudem noch einen Ausdruck CONTACTNAME, der die Felder CONTACTFIRSTNAME und CONTACTLASTNAME aneinanderhängt. Der Ausdruck sieht so aus: ContactName: [ContactFirstName] & " " & [ContactLastName]

Abbildung 6.27: Die Abfrage qryClientListing – eine Grundlage für den Bericht rptClientListing

Um den Bericht zu erstellen, gehen Sie wie folgt vor: 1. Wählen Sie BERICHTE aus der Objektliste, und doppelklicken Sie auf ERSTELLT EINEN BERICHT UNTER VERWENDUNG DES ASSISTENTEN. 2. Benutzen Sie das Listenfeld TABELLEN/ABFRAGEN, um die Abfrage qryClientListing auszuwählen (siehe Abbildung 6.28). Klicken Sie auf OK. 3. Klicken Sie auf die Schaltfläche >>, um anzugeben, dass Sie alle Felder in der Abfrage in Ihren Bericht einfügen möchten. Klicken Sie auf WEITER. 4. Fügen Sie keine Gruppierungen für den Bericht hinzu. Klicken Sie auf WEITER.

246

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Abbildung 6.28: Die Abfrage qryClientListing auswählen

5. Benutzen Sie das erste aufklappbare Listenfeld, um COMPANYNAME als Sortierfeld auszuwählen (siehe Abbildung 6.29). Klicken Sie auf WEITER.

Abbildung 6.29: Das Feld COMPANYNAME als Sortierreihenfolge festlegen

6. Wählen Sie QUERFORMAT als Seitenausrichtung und klicken Sie auf WEITER. 7. Wählen Sie ein Format für den Bericht aus und klicken Sie auf WEITER. 8. Geben Sie dem fertigen Bericht den Titel rptClientListing. Klicken Sie dann auf FERTIG STELLEN.

Access-Berichte und das Internet

247

9. Der fertig gestellte Bericht sollte so aussehen wie in Abbildung 6.30. Klicken Sie auf ENTWURF, um den Bericht in der Entwurfsansicht zu öffnen. Beachten Sie, wie sowohl der Name als auch der Titel des Berichts rptClientListing lauten. Ändern Sie den Titel des Berichts in Client Listing by Company Name (siehe Abbildung 6.31).

Abbildung 6.30: Eine Voransicht des fertig gestellten Berichts

Abbildung 6.31: Den Berichtstitel ändern

6.14.5

Den Bericht rptTimeSheet entwerfen

Der Bericht rptTimeSheet ist viel komplexer als der Bericht rptClientListing. Er enthält zwei Unterberichte: rsubTimeSheet und rsubTimeSheetExpenses.

248

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Der Bericht rptTimeSheet wird in Abbildung 6.32 gezeigt. Er basiert auf der Abfrage qryTimeSheet (siehe Abbildung 6.33) Diese enthält Felder aus den beiden Tabellen tblTimeCards und tblEmployees.

Abbildung 6.32: Der Bericht rptTimeSheet in der Entwurfsansicht

Abbildung 6.33: Die Abfrage QRYTIMESHEET in der Entwurfsansicht

Der Bericht rptTimeSheet besitzt einen Seitenkopf, der den Titel des Berichts enthält. Der Kopfbereich TimeCardID umfasst die Felder EmployeeName und DateEntered aus der Abfrage qryTimeSheet. Der Detailbereich des Berichts besteht aus den beiden Unterberichten rsubTimeSheet und rsubTimeSheetExpenses. Der Seitenfuß enthält zwei Ausdrücke: einen für das Datum und einen für die Seitenzahl. Sie sehen so aus: =Jetzt() ="Page " & [Seite] & " of " & [Seiten]

Der Bericht rsubTimeSheet basiert auf qrySubTimeSheet. Diese Abfrage enthält die folgenden Felder aus den Tabellen tblProjects und tblTimeCardHours:

249

Access-Berichte und das Internet

TblProjects: ProjectName TblTimeCardsHours: TimeCardID, TimeCardDetailID, DateWorked, WorkDescription, BillableHours, BillingRate und der Ausdruck HourlyBillings: [tblTimeCardHours].[BillingRate]*[BillableHours]

Der Entwurf von rsubTimeSheet wird in Abbildung 6.34 gezeigt. Dieser Unterbericht kann leicht von einem Assistenten erstellt werden. Wählen Sie alle Felder außer TimeCardID und TimeCardDetailID aus der Abfrage qrySubTimeSheets aus. Geben Sie an, dass Ihre Daten nach tblTimeCardHours angezeigt werden sollen. Fügen Sie keine Gruppierungen hinzu und sortieren Sie den Bericht nicht. Wenn Sie mit dem Assistenten fertig sind, ändern Sie den Entwurf des Berichts. Entfernen Sie die Beschriftung aus dem Berichtskopf und verschieben Sie alles aus dem Seitenkopf in den Berichtskopf. Schieben Sie den Seitenkopf zusammen, entfernen Sie alles aus dem Seitenfuß und fügen Sie einen Berichtsfuß mit dem Ausdruck =Summe([HourlyBillings]) hinzu.

Abbildung 6.34: Der Bericht rsubTimeSheet in der Entwurfsansicht

Ändern Sie das Format der Steuerelemente HourlyBillings und TotalHourlyBillings in Währung. Benutzen Sie das Dialogfeld SORTIEREN UND GRUPPIEREN, um nach TimeCardID und TimeCardDetailID zu sortieren. Der Bericht rsubTimeSheetExpenses basiert auf der Abfrage qrySubTimeSheetExpense, welche die folgenden Felder aus den Tabellen tblProjects, tblExpenseCodes und tblTimeCardExpenses enthält. tblProjects: ProjectName tblTimeCardsExpenses: TimeCardID, TimeCardExpenseID, ExpenseDate, ExpenseDescription und ExpenseAmount tblExpenseCodes: ExpenseCode

Der Entwurf von rsubTimeSheetExpenses wird in Abbildung 6.35 gezeigt. Dieser Unterbericht kann leicht von einem Assistenten erstellt werden. Wählen Sie alle Felder der Abfrage qrySubTImeExpense außer TimeCardID und TimeCardExpenseID aus und geben Sie an, dass die Daten nach tblTimeCardExpenses angezeigt werden sollen. Fügen Sie keine Gruppierungen hinzu und sortieren Sie den Bericht auch nicht. Wenn Sie mit dem Assistenten fertig sind, verändern Sie den Entwurf des Berichts.

250

Kapitel 6: Was jeder Entwickler über Berichte wissen sollte

Entfernen Sie die Beschriftung des Berichtskopfs und verschieben Sie alles aus dem Seitenkopf in den Berichtskopf. Schieben Sie den Seitenkopf zusammen, entfernen Sie alles aus dem Seitenfuß und fügen Sie einen Berichtsfuß mit dem Ausdruck =Summe([ExpenseAmount]) hinzu.

Abbildung 6.35: Der Bericht rsubTimeSheetExpenses in der Entwurfsansicht

Ändern Sie das Format der Steuerelemente ExpenseAmount und TotalExpenseAmount in Währung und benutzen Sie das Dialogfeld SORTIEREN UND GRUPPIEREN, um nach TimeCardID und TimeCardExpenseID zu sortieren.

VBA: Eine Einführung

Kapitel Hier lesen Sie:

 Was versteht man unter Klassen-, Standard-, Formular- und Berichtsmodulen von Access?

 Mit Variablen arbeiten  Parameter über- und Werte zurückgeben  Vom Modulfenster aus Prozeduren ausführen  Das Objekt DoCmd  Mit integrierten Funktionen arbeiten  Mit Konstanten arbeiten  Werkzeuge für den Visual Basic Editor (VBE)  Den VBE individuell anpassen

7.1

Was ist VBA?

Visual Basic für Applikationen (VBA) ist die Entwicklungssprache für Microsoft Access 2000, eine konsistente Sprache für die Anwendungsentwicklung in der Office-Suite von Microsoft, zu der jetzt auch Outlook gehört. Der Sprachkern, seine Konstrukte und die Umgebung sind für Microsoft Access 2000, Microsoft Visual Basic, Microsoft Excel, Microsoft Word, Microsoft Outlook (für die Programmierung innerhalb der gesamten Anwendung) und Microsoft Project gleich. Unterschiedlich sind jedoch die integrierten Objekte der einzelnen Anwendungen. Access besitzt beispielsweise ein Objekt CurrentProject, Excel dagegen ein Objekt mit dem Namen Workbook. Die Objekte der einzelnen Anwendungen sind mit bestimmten Eigenschaften (Attributen) und Methoden (Aktionen) (und in einigen Fällen auch mit Ereignissen) verknüpft. In diesem Kapitel bekommen Sie einen Überblick über die Sprache VBA und ihre Konstrukte.

252

Kapitel 7: VBA: Eine Einführung

Anders als Word- oder Excel-Makros sind Access-Makros keine Sub-Prozeduren innerhalb von Modulen, sondern Datenbankobjekte eines eigenen Typs mit einer eigenen Schnittstelle. Deshalb lassen sich Access-Makros nicht zum Erlernen der Programmierung in VBA einsetzen, wie es möglich ist, wenn man ein Word- oder Excel-Makro aufzeichnet und anschließend den dazugehörenden VBA-Code analysiert. Einfache Access-Anwendungen kann man unter Verwendung von Makros schreiben. Das geht zwar für die schnelle Entwicklung von Prototypen und sehr einfache Anwendungen in Ordnung, aber der größte Teil der ernsthaften Entwicklung in Access erfolgt mit VBA. Anders als mit Makros lässt sich mit VBA Folgendes realisieren:

 Arbeit mit komplexen logischen Strukturen (Case-Anweisungen, Schleifen usw.)  Verwendung von Konstanten und Variablen  Nutzung von Funktionen und Aktionen, die in Makros nicht zur Verfügung stehen

 Ausführen von Aktionen mit Datensatzgruppen in Form von Schleifen  Transaktionsverarbeitung  Erstellen von und Arbeit mit Datenbankobjekten per Programm  Implementieren einer Fehlerbehandlung  Erstellen von Bibliotheken mit benutzerdefinierten Funktionen  Aufrufen von Windows-API-Funktionen  Ausführen komplexer DDE- und OLE-Automatisierungsbefehle Die Sprache VBA ermöglicht den Einsatz komplexer logischer Strukturen, während Sie mit Makros lediglich die einfache If...Then...Else-Logik verwenden können. VBA bietet Ihnen eine Vielzahl logischer Konstrukte und Schleifen, die weiter hinten in diesem Kapitel behandelt werden. In VBA können Sie außerdem Variablen und Konstanten deklarieren und dann damit arbeiten. Sie können den Variablen einen geeigneten Gültigkeitsbereich zuweisen und sie als Parameter an Unterroutinen und Funktionen übergeben. Wie Sie später sehen werden, bilden Variablen und Konstanten einen integralen Bestandteil aller Access-Anwendungen. Viele wichtige Merkmale der Sprache VBA sind nicht über Makro-Aktionen verfügbar. Wenn Sie versuchen, eine Anwendung ausschließlich mit Makros zu entwickeln, können Sie einen großen Teil der vielfältigen Möglichkeiten von VBA nicht nutzen. Außerdem lassen sich viele der in Makros und Modulen vorhandenen Aktionen mit Hilfe von VBA-Code wesentlich effizienter erledigen.

Was ist VBA?

253

Komplexe Access-Anwendungen verlangen häufig, dass eine Datensatzgruppe durchlaufen und dabei mit jedem Datensatz der Gruppe eine bestimmte Aktion ausgeführt wird. Das ist mit Makros nicht möglich. Mit Hilfe von VBA und ActiveXDatenobjekten lassen sich Daten dagegen hinzufügen, löschen, aktualisieren und bearbeiten. ActiveX-Datenobjekte werden in Kapitel 12 vorgestellt. Bei der Bearbeitung von Datensatzgruppen wollen Sie sicherstellen, dass die gesamte Verarbeitung erfolgreich abgeschlossen ist, bevor die Daten dauerhaft aktualisiert werden. Mit Hilfe der Methoden BeginTrans, CommitTrans und RollbackTrans können Sie gewährleisten, dass die Aktualisierung nur erfolgt, wenn alle Teile einer Transaktion erfolgreich durchgeführt wurden. Transaktionsverarbeitung kann, wenn sie korrekt ausgeführt wird, die Leistung Ihrer Anwendung wesentlich verbessern, weil Daten erst dann auf die Festplatte geschrieben werden, wenn der Prozess abgeschlossen ist. Transaktionsverarbeitung und ihre Vorzüge werden in Kapitel 22 behandelt. Mit Access-Makros kann man Datenbankobjekte zur Laufzeit weder erstellen noch modifizieren. Mit VBA können Sie Datenbanken, Tabellen, Abfragen und weitere Datenbankobjekte anlegen und bestehende Objekte verändern. Für diese Fähigkeit gibt es viele praktische Anwendungen. (Weitere Einzelheiten hierzu finden Sie in Kapitel 12.) Wenn die Benutzer beispielsweise nebenbei Abfragen erstellen können, möchten Sie ihnen vielleicht die Möglichkeit an die Hand geben, Abfragen mit Hilfe eines bereitgestellten Front-End-Formulars zu gestalten und für die spätere Wiederverwendung zu speichern. Mit Access-Makros lässt sich keine Fehlerbehandlung implementieren. Falls während der Ausführung eines Access-Makros mit der Laufzeitversion von Access ein Fehler auftritt, wird der Benutzer aus der Anwendung (und damit aus der AccessLaufzeitversion) katapultiert. Mit Hilfe von Fehlerbehandlungsverfahren können Sie exakt festlegen, was passieren soll, wenn es während der Ausführung Ihrer Anwendung zu einem Fehler kommt. Die Fehlerbehandlung wird in Kapitel 14 eingehender besprochen. Darüber hinaus erleichtert VBA die Zusammenstellung von Code-Bibliotheken mit wiederverwendbaren Funktionen, das Gestalten und Testen komplexer Prozesse und sogar das Schreiben eigener Add-Ins. Selbst wenn Sie nur relativ einfache Anwendungen entwickeln, sollen Sie in der Lage sein, allgemeine Funktionsbibliotheken anzulegen, die sich in all Ihren Access-Anwendungen einsetzen lassen. Das ist bei Verwendung von Makros extrem schwierig, wenn nicht unmöglich. Viele leistungsfähige Funktionen, die VBA nicht bietet, sind als Teil von Windows selbst verfügbar. Als Windows-API (Application Programming Interface) werden die nahezu 1.000 Windows-Funktionen bezeichnet, die Microsoft den Access-Programmierern zur Verfügung stellt. Diese sind nicht über Access-Makros erreichbar; mit Hilfe von VBA-Code lassen sie sich dagegen deklarieren und aufrufen, was sowohl die Leistung als auch die Funktionalität Ihrer Anwendungen erhöht. Das WindowsAPI ist Thema von Kapitel 27.

254

Kapitel 7: VBA: Eine Einführung

DDE (Dynamic Data Exchange) und Automatisierung ermöglichen die Kommunikation zwischen Ihren Access-Anwendungen und anderen Programmen. DDE ist zwar ein älteres Verfahren als die Automatisierung, wird aber immer noch zur Kommunikation mit einigen Anwendungen eingesetzt, die die Automatisierung nicht unterstützen. Mit der Automatisierung werden Automatisierungs-Server-Anwendungen wie Excel und Project und deren Objekte gesteuert. (Alle Microsoft-OfficeAnwendungen sind Automatisierungs-Server.) Die Automatisierung wird in Kapitel 26 dargestellt. Makros können zwar schnelle Lösungen für einfache Probleme bieten, aber ihre Beschränktheit macht VBA zur einzigen echten Möglichkeit für die Entwicklung komplexer Lösungen. Um den Übergang von Makros zu Modulen zu vereinfachen, stellt Microsoft eine Funktion bereit, die Makros in VBA-Module konvertiert.

7.2

Was sind die Klassen-, Standard-, Formularund Berichtsmodule von Access?

VBA-Code wird in Einheiten verfasst, die als Unterroutinen und Funktionen bezeichnet und in Modulen gespeichert werden. Access-Module sind entweder Standard- oder Klassenmodule. Standardmodule werden erstellt, indem man das Modulsymbol im Datenbankfenster auswählt und dann auf NEU klickt. Klassenmodule können selbstständige Objekte sein oder mit einem Formular oder Bericht verknüpft werden. Um ein selbstständiges Klassenmodul anzulegen, wählen Sie im Menü EINFÜGEN den Befehl KLASSENMODUL. Außerdem erstellt Microsoft Access immer, wenn Sie ein Formular oder einen Bericht mit Code hinterlegen, ein Klassenmodul, das mit diesem Formular oder Bericht verknüpft ist und den betreffenden Code enthält. Spezielle Module eines Formulars oder Berichts werden im Allgemeinen als »Formular- und Berichtsklassenmodule« bezeichnet, ihr Code häufig als »Code Behind Forms« (CBF). CBF wird im jeweiligen Formular bzw. Bericht erstellt und abgelegt und von darin auftretenden Ereignissen ausgelöst. Eine »Unterroutine« (Unterprozedur) ist eine Routine, die auf ein Ereignis reagiert oder eine Aktion durchführt. Eine »Ereignisprozedur« ist eine spezielle Art Unterroutine, die automatisch in Reaktion auf ein Ereignis wie zum Beispiel einen Mausklick auf eine Befehlsschaltfläche oder das Laden eines Formulars ausgeführt wird; sie kann keinen Wert zurückgeben. Eine »Funktion« ist eine spezielle Art Routine, weil sie – anders als Unterroutine – einen Wert zurückgeben kann. Wie eine Unterroutine lässt sich auch eine Funktion von einem Ereignis auslösen.

Was sind die Module von Access?

7.2.1

255

Wo entsteht VBA-Code?

Der gesamte VBA-Code wird im Visual Basic Editor geschrieben (auch VBE genannt). Sobald Sie versuchen, auf den Code in einem Standard- oder Klassenmodul zuzugreifen, gelangen Sie in den VBE (zu sehen in Abbildung 7.1). Die VBEUmgebung in Microsoft Access ist jetzt mit den anderen Microsoft-Office-Produkten konsistent. Es handelt sich um ein von Microsoft Access getrenntes Fenster, das über eine Menüleiste, eine Symbolleiste, ein Projektfenster, ein Eigenschaftenfenster, ein Direktfenster, ein Lokalfenster, ein Überwachungsfenster, einen Objektkatalog und ein Code-Fenster verfügt. Die einzelnen Komponenten des VBE werden bei Bedarf in diesem Kapitel und im weiteren Verlauf des Buchs erläutert.

Abbildung 7.1: Der Visual Basic Editor (VBE)

7.2.2

Die Anatomie eines Moduls

Alle Module, sowohl Standard- als auch Klassenmodule, enthalten einen Abschnitt ALLGEMEINE DEKLARATIONEN (siehe Abbildung 7.2). Wie der Name schon sagt, werden dort Variablen und Konstanten deklariert, die für alle Funktionen und Unterroutinen des Moduls sichtbar sein sollen, sowie Optionen festgelegt. Diese Variablen werden als Variablen »auf Modulebene« oder »private« Variablen bezeichnet. Im Abschnitt ALLGEMEINE DEKLARATIONEN eines Moduls können Sie auch öffentliche Variablen deklarieren, die von allen Funktionen und Prozeduren in allen Modulen der Datenbank gesehen und modifiziert werden können.

256

Kapitel 7: VBA: Eine Einführung

Abbildung 7.2: Im Abschnitt Allgemeine Deklarationen eines Moduls werden private und öffentliche Variablen deklariert

Die öffentlichen Variablen von Access 2000 ersetzen die globalen Variablen von Access 2.0. Globale Variablen werden in Access 2000 zwar noch unterstützt, aber es gibt feine Unterschiede zwischen öffentlichen und globalen Variablen; diese werden später noch behandelt. Ein Modul besteht ebenfalls aus benutzerdefinierten Unterroutinen und Funktionen. Abbildung 7.3 zeigt eine Unterroutine mit dem Namen SayHello. Beachten Sie das aufklappbare Listenfeld im linken oberen Teil des Fensters mit dem Titel CHAP7EX – MODUL (CODE), das als Objektliste bezeichnet wird. Unterroutinen und Funktionen sind manchmal mit einem bestimmten Objekt wie zum Beispiel einem Formular oder einem Steuerelement innerhalb eines Formulars verknüpft und dort wird diese Verknüpfung angezeigt. Hier ist unsere Unterroutine SayHello nicht mit einem Objekt verknüpft, weshalb die Objektliste den Eintrag (ALLGEMEIN) ENTHÄLT. Access 2000 besitzt eine Umgebungsoption mit dem Namen VOLLSTÄNDIGE MODULANSICHT, mit deren Hilfe Sie mehrere Unterroutinen und Funktionen eines Moduls gleichzeitig sehen können. Beachten Sie den Unterschied zwischen den Abbildungen 7.3 und 7.4! Im Code-Fenster in Abbildung 7.3 ist jeweils nur eine Unterroutine sichtbar, im Code-Fenster in Abbildung 7.4 sehen Sie dagegen die Auswirkungen der vollständigen Modulansicht – mehrere Unterroutinen sind sichtbar, jeweils durch eine feine horizontale Linie getrennt. In Access 2000 ist die volle Modulansicht standardmäßig eingestellt. Um diese Einstellung zu ändern, wählen Sie im VBE EXTRAS|OPTIONEN, klicken auf die Registerkarte EDITOR und aktivieren den Eintrag STANDARDGEMÄSS GANZES MODUL ANZEIGEN. Wenn Sie vorübergehend in die Prozeduransicht wechseln wollen, klicken Sie auf die Schaltfläche PROZEDURANSICHT in der linken unteren Ecke des Modulfensters; über die Schaltfläche VOLLSTÄNDIGE MODULANSICHT kehren Sie anschließend in die volle Modulansicht zurück.

Was sind die Module von Access?

257

Abbildung 7.3: Ein Beispiel für eine benutzerdefinierte Unterroutine mit dem Namen SayHello

Abbildung 7.4: In der vollständigen Modulansicht können Sie mehrere Prozeduren gleichzeitig sehen

7.2.3

Option Explicit

Option Explicit ist eine Anweisung, die in den Abschnitt ALLGEMEINE DEKLARATIO-

jedes Moduls aufgenommen werden kann, auch in das Klassenmodul eines Formulars oder Berichts. Wenn diese Anweisung eingesetzt wird, müssen alle Variablen innerhalb des Moduls vor der Verwendung deklariert werden, sonst kommt es beim Kompilieren des Moduls zu einer Fehlermeldung, die besagt, dass eine Variable nicht definiert wurde. Wenn der Compiler ohne Option Explicit auf eine nicht deklarierte Variable trifft, behandelt VBA diese einfach als neue Variable und fährt ohne Warnung fort. Auf den ersten Blick scheint es vielleicht besser zu sein, auf die Anweisung Option Explicit zu verzichten, weil sie Compiler-Fehler auslöst, die sonst nicht auftreten würden; richtig ist jedoch das genaue Gegenteil. Sie sollten diese Anweisung in ausnahmslos jedem Modul verwenden. Sehen Sie sich beispielsweise folgenden Code an: NEN

258

Kapitel 7: VBA: Eine Einführung

intAmount = 2 intTotal = intAmont * 2

Das Ziel dieses Codes ist natürlich die Multiplikation des Wertes der Variablen intAmount, in diesem Fall 2, mit 2. Beachten Sie jedoch, dass der Variablenname in der zweiten Zeile falsch geschrieben ist. Wenn Option Explicit nicht aktiv ist, sieht VBA intAmont als neue Variable an und fährt einfach mit der Verarbeitung fort. Die Variable intTotal wird auf 0 anstatt auf 4 gesetzt und es gibt keinen einzigen Hinweis auf den Fehler. Ergebnisse dieser Art lassen sich durch die Verwendung von Option Explicit völlig vermeiden. In Access 2.0 mussten Sie die Anweisung Option Explicit in jedes Modul, jedes Formular und jeden Bericht von Hand einfügen. Seit Access 97 haben Entwickler die Möglichkeit, Access global anzuweisen, die Anweisung Option Explicit in alle neuen Module aufzunehmen. In Access 2000 wählen Sie dazu im VBE EXTRAS|OPTIONEN und klicken auf der Registerkarte EDITOR auf VARIABLENDEKLARATION ERFORDERLICH. Es ist wichtig, die Anweisung Option Explicit in alle Module zu integrieren; deshalb sollten Sie darauf achten, dass diese Option auf True gesetzt ist. Die Standardeinstellung bei der Installation von Microsoft Access 2000 ist False! Option Explicit erspart Ihnen stundenlange Fehlersuche und verhindert, dass »Ihr Pieper losgeht«, nachdem Ihre Anwendung an die Benutzer verteilt wurde. Außer dem Abschnitt ALLGEMEINE DEKLARATIONEN und benutzerdefinierten Prozeduren, Formularen und Berichten enthalten Klassenmodule noch Ereignisprozeduren, die mit einem bestimmten Objekt in einem Formular verknüpft sind. Beachten Sie in Abbildung 7.5, dass die aufklappbare Objektliste den Eintrag cmdHello anzeigt, also den Namen des Objekts, dessen Ereignisroutinen Sie gerade betrachten. Das aufklappbare Listenfeld auf der rechten Seite zeigt alle Ereignisse, die man für eine Befehlsschaltfläche programmieren kann; jedes davon erstellt eine eigene Ereignisroutine. Beim Durchlesen dieses Buches bieten sich viele Gelegenheiten dazu.

7.2.4

Ereignisprozeduren erstellen

Ereignisprozeduren werden automatisch erstellt, wenn Sie Ereignis-Code für ein Objekt schreiben. Die Routine Private Sub cmdHello_Click wird beispielsweise erstellt, wenn Sie Code in den Abschnitt für das in Abbildung 7.5 gezeigte ClickEreignis der Schaltfläche cmdHello einfügen. Um zum Ereignis-Code für ein Objekt zu gelangen, unternehmen Sie Folgendes: 1. Klicken Sie in der Entwurfsansicht auf das Objekt und dann auf die Schaltfläche EIGENSCHAFTEN in der Symbolleiste oder klicken Sie mit der rechten Maustaste auf das Objekt und wählen Sie im Kontextmenü EIGENSCHAFTEN. 2. Klicken Sie auf die Registerkarte EREIGNIS.

259

Was sind die Module von Access?

Abbildung 7.5: Eine Ereignisprozedur für das Click-Ereignis der Befehlsschaltfläche cmdHello

3. Wählen Sie das Ereignis aus, für das Sie Code schreiben wollen (z.B. das Ereignis BEIM KLICKEN). 4. Wählen Sie im aufklappbaren Listenfeld den Eintrag [EREIGNISPROZEDUR] aus. 5. Klicken Sie auf die Schaltfläche mit den drei Punkten, die Sie im Visual Basic Editor (VBE) in den Ereignis-Code für dieses Objekt bringt. Wie am Anfang des Kapitels gesagt wurde, wird der Visual Basic Editor (VBE) in einem eigenen Fenster geöffnet. Er bietet eine mit allen anderen Microsoft-OfficeAnwendungen konsistente Programmierumgebung. Im VBE hinzugefügte Module erscheinen erst im Datenbank-Container, wenn sie im VBE gespeichert wurden.

7.2.5

Funktionen und Unterroutinen erstellen

Sie können auch eigene Prozeduren schreiben, die nicht an ein bestimmtes Objekt oder Ereignis gebunden sind und je nach Art und Ort der Deklaration von einer beliebigen Stelle in Ihrer Anwendung oder von einem bestimmten Code-, Formularoder Berichtsmodul aus aufgerufen werden können. In einem Code-Modul eine benutzerdefinierte Routine erstellen 1. Klicken Sie in der Objektliste im Datenbankfenster auf MODULE. 2. Klicken Sie auf NEU, um ein neues Modul zu erstellen, oder wählen Sie ein vorhandenes Modul aus und klicken Sie auf ENTWURF, um den VBE aufzurufen. 3. Wählen Sie im Aufklappmenü MODUL EINFÜGEN in der Symbolleiste (zweites Symbol von links) oder im Menü EINFÜGEN den Punkt PROZEDUR. Es erscheint das Dialogfeld PROZEDUR HINZUFÜGEN (siehe Abbildung 7.6).

260

Kapitel 7: VBA: Eine Einführung

4. Geben Sie den Namen der Prozedur ein. 5. Wählen Sie als Prozedurtyp Sub, Function oder Property. 6. Um die Prozedur für die gesamte Anwendung verfügbar zu machen, wählen Sie als Gültigkeitsbereich Public; um sie für dieses Modul »privat« zu deklarieren, wählen Sie Private. 7. Geben Sie zum Schluss an, ob alle Variablen der Prozedur statisch sein sollen. (Statische Variablen werden in diesem Kapitel unter »Gültigkeitsbereich und Lebensdauer von Variablen: Variablen mit möglichst geringer Sichtbarkeit wählen« behandelt.) Klicken Sie danach auf OK.

Abbildung 7.6: Im Dialogfeld Prozedur hinzufügen geben Sie Namen, Typ und Gültigkeitsbereich der zu erstellenden Prozedur an

In einem Formular- oder Berichtsklassenmodul eine benutzerdefinierte Routine erstellen 1. Wählen Sie in der Entwurfsansicht eines Formulars oder Berichts im Menü den Eintrag ANSICHT. Beachten Sie das Symbol neben dem Menüpunkt CODE. Dasselbe Symbol finden Sie auch in der Symbolleiste. Sie können den hinter einem Formular oder Bericht liegenden Code einsehen, indem Sie auf das Symbol in der Symbolleiste oder im Menü ANSICHT auf CODE klicken. In beiden Fällen gelangen Sie in den VBE. 2. Wählen Sie im Aufklappmenü MODUL EINFÜGEN in der Symbolleiste (zweites Symbol von links) oder im Menü EINFÜGEN den Punkt PROZEDUR, um das Dialogfeld PROZEDUR HINZUFÜGEN zu öffnen. 3. Geben Sie den Namen der Prozedur ein. 4. Wählen Sie als Prozedurtyp Sub, Function oder Property. 5. Um die Prozedur für die gesamte Anwendung verfügbar zu machen, wählen Sie als Gültigkeitsbereich Public, um sie für dieses Modul »privat« zu deklarieren, Private.

Was sind die Module von Access?

261

6. Geben Sie zum Schluss an, ob alle Variablen der Prozedur statisch sein sollen. (Statische Variablen werden in diesem Kapitel unter »Gültigkeitsbereich und Lebensdauer von Variablen: Variablen mit möglichst geringer Sichtbarkeit wählen« behandelt.) Klicken Sie auf OK, wenn Sie fertig sind. Unabhängig davon, ob Sie eine Prozedur in einem Standard- oder in einem Klassenmodul erstellen, können Sie jetzt den Code für die Prozedur eingeben. Eine hervorragende Abkürzung ist dabei die direkte Eingabe des Namens der neuen Prozedur im Code-Fenster mit vorangestellter Bezeichnung als Unterroutine oder Funktion. Ein Beispiel: Sub Whatever oder Function Whatever. Damit wird eine neue Unterroutine oder Funktion erstellt, sobald Sie (¢) drücken.

7.2.6

Ereignis- und benutzerdefinierte Prozeduren aufrufen

Ereignisprozeduren werden automatisch aufgerufen, wenn ein Ereignis für ein Objekt eintritt. So wird der Code für das Click-Ereignis für eine bestimmte Befehlsschaltfläche ausgeführt, wenn ein Benutzer auf diese Schaltfläche klickt. Die übliche Methode, benutzerdefinierte Prozeduren aufzurufen, ist die Verwendung des Schlüsselworts Call – z.B. Call SayHello. Dieselbe Prozedur lässt sich aber auch ohne die Verwendung des Schlüsselworts aufrufen: SayHello. Die Verwendung des Schlüsselworts Call ist zwar nicht unbedingt erforderlich, macht die Anweisung aber selbstdokumentierend und leichter lesbar. Eine benutzerdefinierte Prozedur lässt sich aus einer Ereignisroutine oder aus einer anderen benutzerdefinierten Routine oder Funktion aufrufen.

7.2.7

Gültigkeitsbereich und Lebensdauer von Prozeduren

Der Gültigkeitsbereich einer Prozedur kann öffentlich oder privat sein. Er legt fest, wie weit sie von anderen Prozeduren aufgerufen werden kann. Außer dem Gültigkeitsbereich kann auch die Positionierung einer Prozedur Funktionalität und Leistung Ihrer Anwendung merklich beeinflussen. Ein weiteres Attribut von Prozeduren betrifft die Lebensdauer der in ihr deklarierten Variablen. Standardmäßig besitzen die in einer Prozedur deklarierten Variablen eine Lebensdauer, d.h. sie haben nur solange einen Wert und eine Bedeutung, wie die Prozedur ausgeführt wird. Wenn die Ausführung abgeschlossen ist, werden die von ihr deklarierten Variablen aus dem Speicher entfernt. Diese Standardlebensdauer kann durch die Verwendung des Schlüsselwortes Static geändert werden.

262

Kapitel 7: VBA: Eine Einführung

Öffentliche Prozeduren Eine öffentliche Prozedur innerhalb eines Code-Moduls lässt sich von jeder Stelle innerhalb der Anwendung aufrufen. In einem Modul deklarierte Prozeduren sind automatisch öffentliche Prozeduren, d.h. Prozeduren, die Sie in ein Code-Modul einfügen, lassen sich von jeder Stelle innerhalb der Anwendung aufrufen, falls Sie nichts Gegenteiliges angeben. Möglicherweise meinen Sie, dass zwei öffentliche Prozeduren nicht denselben Namen tragen können. Dies gilt zwar für frühere Access-Versionen, aber nicht mehr für Access 2000. Wenn zwei öffentliche Prozeduren den Namen gemeinsam haben, muss die aufrufende Prozedur explizit angeben, welche Prozedur gemeint ist. Das wird in folgendem Code-Abschnitt aus dem Klassenmodul von frmHello in der Beispieldatenbank Chap7ex.mdb deutlich: Private Sub cmdSayGoodBye_Click() Call basUtils.SayGoodBye End Sub

Dieser und der gesamte Beispiel-Code dieses Kapitels steht in der Datei Chap7ex.mdb auf der CD mit dem Beispiel-Code. Die Routine SayGoodBye kommt in zwei Access-Code-Modulen vor. Das Präfix basUtils gibt jedoch an, dass sich die auszuführende Routine im Standardmodul mit dem Namen basUtils befindet. In Formular- oder Berichtsklassenmodulen deklarierte Prozeduren sind ebenfalls automatisch öffentlich und lassen sich daher von jeder Stelle innerhalb der Anwendung aufrufen. Die Prozedur cbfIAmPublic (siehe Abbildung 7.7) steht im Formular frmHello, kann aber trotzdem von jeder Stelle innerhalb der Anwendung aufgerufen werden. Die einzige Voraussetzung besteht darin, dass das Formular mit der Prozedur in der Formularansicht geöffnet ist. Die Prozedur cbfIAmPublic kann mit folgender Syntax (die Sie im Standardmodul basHello finden) von jeder Stelle innerhalb der Anwendung aufgerufen werden: Sub CallPublicFormProc() Call Forms.frmHello.cbfIAmPublic End Sub

Obwohl alle Prozeduren (bis auf Ereignisprozeduren) standardmäßig öffentlich sind, sollte das Schlüsselwort Public verwendet werden, um darauf hinzuweisen, dass die Prozedur für alle Unterroutinen und Funktionen in der Datenbank sichtbar ist.

Was sind die Module von Access?

263

Abbildung 7.7: Eine öffentliche Prozedur eines Formulars ist für alle Unterroutinen und Funktionen in der Datenbank sichtbar

Private Prozeduren Wie bereits erwähnt, sind alle benutzerdefinierten Prozeduren automatisch öffentlich. Wenn eine in einem Modul deklarierte Prozedur nur innerhalb des Moduls gültig sein soll, d.h., dass sie nur von Routinen in diesem Modul aufgerufen werden kann, müssen Sie sie explizit als privat deklarieren (siehe Abbildung 7.8).

Abbildung 7.8: Diese private Prozedur ist nur für Unterroutinen und Funktionen im Modul basUtils sichtbar

Die in Abbildung 7.8 gezeigte Prozedur IAmPrivate befindet sich im Standardmodul basUtils. Da sie privat ist, kann sie nur von anderen Routinen in diesem Modul aufgerufen werden. Vorrang des Gültigkeitsbereichs Private Prozeduren haben grundsätzlich Vorrang vor öffentlichen. Wenn eine private Prozedur denselben Namen trägt wie eine öffentliche, wird die private Prozedur ausgeführt, sofern sie von einer Routine in dem Modul aufgerufen wird, in dem sie deklariert wurde. Namenskonflikte zwischen privaten und öffentlichen Prozeduren treten daher nicht auf.

264

Kapitel 7: VBA: Eine Einführung

Entwickler fragen sich oft, wo sie Code unterbringen sollen: in Formular- oder Berichtsklassenmodulen oder in Standardmodulen. Beide Methoden haben Vorund Nachteile. Die Platzierung von Code in Standardmodulen bedeutet, dass sich der Code mühelos von jeder Stelle in der Anwendung aufrufen lässt, ohne dass ein bestimmtes Formular oder ein bestimmter Bericht geladen sein muss. Öffentliche Routinen in Standardmodulen lassen sich auch aus anderen Datenbanken aufrufen. Deshalb eignen sich Standardmodule hervorragend für allgemeine Routinen, die als Teil einer Bibliothek zur Verfügung stehen sollen. Access 2000 lädt Module nur bei Bedarf, was bedeutet, dass Prozeduren nur Platz im Arbeitsspeicher belegen, solange sie verwendet werden. Dies gilt insbesondere, wenn Sie Ihre Module sorgfältig planen (siehe Kapitel 15). Unabhängig davon, wann der Code geladen wird, besteht ein Vorteil der Platzierung von Code hinter Formularen oder Berichten (statt in Modulen) darin, dass das Formular bzw. der Bericht abgeschlossen und deshalb portierbar ist. Sie können das Formular bzw. den Bericht in eine beliebige andere Datenbank importieren und es/er funktioniert immer noch erwartungsgemäß. Dieser objektorientierte Ansatz bedeutet, dass das Formular nichts aus der Außenwelt voraussetzt. Wie Sie sehen können, hat jede der beiden Methoden Vor- und Nachteile. Als allgemeine Regel sollten Sie eine für ein bestimmtes Formular oder einen Bericht spezifische Routine im Formular bzw. Bericht unterbringen, eine weitläufig benutzte Routine jedoch in einem Modul. Statische Prozeduren Wenn eine Prozedur als statisch deklariert wurde, behalten alle in ihr deklarierten Variablen zwischen den einzelnen Aufrufen der Prozedur ihren Wert. Dies stellt eine Alternative zur expliziten Deklaration der einzelnen Variablen als statisch dar. Es folgt ein Beispiel für eine statische Prozedur, das Sie im Modul basVariable finden: Static Sub IncrementThem() Dim intCounter1 As Integer Dim intCounter2 As Integer Dim intCounter3 As Integer intCounter1 = intCounter1 + 1 intCounter2 = intCounter2 + 1 intCounter3 = intCounter3 + 1 MsgBox intCounter1 & " – " & intCounter2 & " – " & intCounter3 End Sub

Normalerweise würde jede Variable in dieser Prozedur bei jedem Start der Prozedur wieder mit 0 initialisiert, d.h., im Meldungsfeld erscheinen nur Einsen, wenn die Prozedur ausgeführt wird. Da die Prozedur aber als statisch deklariert wurde, behalten die Variablen von einem Aufruf zum anderen ihren Wert, d.h., die Werte im Meldungsfeld werden bei jeder Ausführung höher. Dieses Verhalten sollte Ihnen nach der Behandlung der Variablen weiter hinten in diesem Kapitel erheblich klarer werden.

Mit Variablen arbeiten

7.3

265

Mit Variablen arbeiten

Beim Anlegen von VBA-Variablen ist vieles zu bedenken. Die Art, wie Sie eine Variable deklarieren, legt ihren Gültigkeitsbereich, ihre Lebensdauer und noch anderes fest. Die folgenden Punkte werden dazu beitragen, dass Sie die Deklaration von Variablen in VBA besser verstehen.

7.3.1

Variablen deklarieren

Es gibt in VBA verschiedene Methoden, Variablen zu deklarieren: eine standardmäßige und drei weitere. Sie können beispielsweise einfach x=10 deklarieren. Auf diese Art deklarieren Sie die Variablen eigentlich überhaupt nicht, sondern sie werden im Grunde bei der Verwendung deklariert. Diese Methode ist recht gefährlich, da anfällig für Tippfehler und andere Probleme. Wenn Sie sich an die weiter vorn empfohlene Vorgehensweise halten, grundsätzlich die Anweisung Option Explicit zu verwenden, lässt Access die Deklaration von Variablen in dieser Art nicht zu. Sie können genauso gut Dim intCounter eingeben: Die Dim-Anweisung deklariert die Variable. Bei dieser Methode besteht das einzige Problem darin, dass Sie dem Compiler gegenüber den Typ der Variablen nicht deklariert haben und es sich daher um eine Variable des Typs Variant handelt. Ein anderer häufig vorkommender Fehler ist die Deklaration mehrerer Variablen in einer Zeile wie in folgendem Beispiel: Dim intCounter, intAge, intWeight As Integer

In dieser Zeile wird nur die letzte Variable explizit als Variable des Typs Integer deklariert, die anderen jedoch implizit als Variablen des Typs Variant. Wenn Sie vorhaben, mehrere Variablen in einer Zeile zu deklarieren, müssen Sie sicherstellen, dass jede einzeln deklariert wird, wie es im folgenden Beispiel zu sehen ist: Dim intCounter As Integer, intAge As Integer, intWeight As Integer

Die effizienteste und sicherste Methode der Variablendeklaration ist die eindeutige Zuweisung von Typen gegenüber dem Compiler und die Deklaration jeder Variablen in einer eigenen Code-Zeile: Dim intCounter As Integer Dim strName As String

Wie Sie sehen können, werden bei eindeutiger Typzuweisung sowohl der Name der Variablen als auch der Typ der Daten deklariert, welche sie enthalten kann. Das ermöglicht dem Compiler, Fehler wie z.B. das Ablegen einer Zeichenfolge in einer Variablen des Typs Integer abzufangen, bevor das Programm ausgeführt wird. Bei korrekter Implementierung kann diese Methode außerdem die für die Ausführung des Programms benötigten Ressourcen reduzieren, indem es für jede Variable den kleinstmöglichen Datentyp auswählt.

266

Kapitel 7: VBA: Eine Einführung

Variablen des Typs Variant sollten Sie nach Möglichkeit meiden. Sie erfordern nicht nur eine beträchtliche Menge Speicherplatz, sondern sind außerdem langsam, weil sie vom Compiler zur Laufzeit aufgelöst werden müssen. Bestimmte Situationen erfordern jedoch Variant-Variablen. Ein Beispiel dafür ist der Wunsch, dass die Variable zu verschiedenen Zeiten verschiedene Arten von Daten aufnehmen soll, ein anderer Fall der Wunsch, zwischen einer leeren Variablen (einer noch nicht initialisierten) und einer Variablen mit einem Nullwert oder einer Zeichenfolge der Länge null unterscheiden zu können. Darüber hinaus sind Variant-Variablen die einzigen, die den Sonderwert Null enthalten können. Leere Variablen und Null-Werte werden in Kapitel 24 behandelt.

7.3.2

VBA-Datentypen

VBA stellt eine Reihe von Datentypen für Variablen bereit. Tabelle 7.1 enthält eine Liste der verfügbaren Typen, die jeweilige Namenskonvention, die erforderliche Speicherplatzmenge, die Art der aufzunehmenden Daten und die Standardwerte. Datentyp

Beispiel für NamensKonvention

Speicherplatz

Speicherbereich

Standardwert

Byte

bytValue

1 Byte

0 bis 255

0

Boolean

boolAnswer

2 Bytes

True oder False

False

Integer

intCounter

2 Bytes

-32768 bis 32767

0

Long Integer

lngAmount

4 Bytes

-2,147 483 648 bis 2,147 483647

0

Single

sngAmount

4 Bytes

-3.402823E38 bis -1.401298E-45 für negative Werte; 1.401298E-45 bis 3.402823E38 für positive Werte

0

Double

dblValue

8 Bytes

0 1.79769313486231E308 bis 4.94065645841247E-324 für negative Werte; 4.94065645841247E-324 bis 1.79769313486231E308 für positive Werte

Tabelle 7.1: Datentypen und Namenskonventionen

267

Mit Variablen arbeiten

Datentyp

Beispiel für NamensKonvention

Speicherplatz

Speicherbereich

Standardwert

Currency

curSalary

8 Bytes

-922 337 203 685 477.5808 bis 922 337 203 685 477.5807

0

Date

dtmStartDate

8 Bytes

1/1/10 bis 12/31/9999

4 Bytes

beliebiges Objekt

Object Reference objExcel Fixed String

strName

verschieden bis zu 65.526 Zeichen

""

Variable String

strName

verschieden bis ca. 2 Mrd. Zeichen

""

Variant

varData

verschieden Kann alle anderen Datentypen außer Fixed String enthalten

leer

Benutzer-definierter Datentyp

typEmp

verschieden Basiert auf Elementen

Decimal

decTaxAmount

12 Bytes

+/-79 228 162 514 264 337 0 593 543 950 335 ohne Dezimalstellen +/7.922816251426433759354 3950335 mit 28 Dezimalstellen

Tabelle 7.1: Datentypen und Namenskonventionen (Forts.)

7.3.3

Gültigkeitsbereich und Lebensdauer von Variablen: Variablen mit möglichst geringer Sichtbarkeit wählen

Sie haben bereits von den verschiedenen Variablentypen in VBA gehört. Wie Prozeduren besitzen auch Variablen einen Gültigkeitsbereich. Eine Variable kann als lokal, privat (für das Modul) oder öffentlich deklariert werden. Sie sollten versuchen, in Ihrem Code lokale Variablen zu verwenden, weil diese gegen die versehentliche Änderung durch andere Routinen abgeschirmt sind. Variablen besitzen außerdem ein Attribut, das als Lebensdauer bezeichnet wird und häufig die Zeit angibt, während der die Variable tatsächlich existiert, d.h. die Zeitspanne, für die ihr Wert erhalten bleibt. In den folgenden Abschnitten werfen wir einen genaueren Blick darauf, wie Gültigkeitsbereich und Lebensdauer von Variablen festgelegt werden.

268

Kapitel 7: VBA: Eine Einführung

Lokale Variablen Lokale Variablen stehen nur in der Prozedur zur Verfügung, in der sie deklariert wurden. Sehen Sie sich folgendes (nicht in der Datenbank Chap7ex enthaltene) Beispiel an: Private Sub cmdOkay_Click Dim strAnimal As String StrAnimal = "Dog" Call ChangeAnimal Debug.Print strAnimal End Sub

'immer noch Hund

Private Sub ChangeAnimal StrAnimal = "Cat" End Sub

Dieser Code kann sich auf dreierlei Weise verhalten. Wenn Option Explicit wirksam wäre, was bedeutet, dass alle Variablen vor der Verwendung deklariert werden müssten, würde dieser Code zu einem Compiler-Fehler führen. Wenn die Anweisung Option Explicit nicht verwendet würde, würde die Variable strAnimal nur im Kontext der Unterroutine ChangeAnimal in Cat geändert. Wenn die Anweisung Dim strAnimal As String in den Abschnitt DEKLARATIONEN des Moduls verschoben wird, ändert sich der Wert der Variablen in "Cat". Beachten Sie in der oben abgedruckten Ereignisroutine cmdOkayClick die Anweisung Debug.Print. Der Ausdruck, der auf die Anweisung folgt, wird im Direktfenster angezeigt. Dieses Werkzeug hilft Ihnen bei der Fehlerbehebung in Ihren Anwendungen und lässt sich von fast allen Stellen in Ihrer Anwendung aus aufrufen, und zwar am einfachsten mit der Tastenkombination (Strg)(G), mit der Sie in den VBE im Direktfenster gelangen und sich die dort ausgegebenen Ausdrücke ansehen können. Das Direktfenster wird in Kapitel 13 ausführlich erläutert. Statische Variablen: Ein Spezialtyp lokaler Variablen Die folgenden Beispiele veranschaulichen den Unterschied zwischen lokalen und statischen Variablen. Lokale Variablen werden jedesmal neu initialisiert, wenn der Code aufgerufen wird. Die folgende Prozedur lässt sich ausführen, indem Sie das Formular frmScopeAndLifeTime öffnen und auf die Schaltfläche LOCAL AGE klicken. Beachten Sie, dass bei jedem Ausführen der Prozedur im Textfeld txtNewAge die Zahl 1 erscheint. Private Sub cmdLocalAge_Click() Dim intAge As Integer intAge = intAge + 1 Me.txtNewAge = intAge End Sub

Mit Variablen arbeiten

269

Immer wenn dieser Code ausgeführt wird, initialisiert die Dim-Anweisung die Variable intAge mit Null. Das ist ganz anders bei folgendem Code, der die Verwendung einer statischen Variablen veranschaulicht: Private Sub cmdStaticAge_Click() Static sintAge As Integer sintAge = sintAge + 1 Me.txtNewAge = sintAge End Sub

Immer wenn dieser Code ausgeführt wird, wird die Variable sintAge erhöht und dieser Wert bleibt erhalten. Das lässt sich überprüfen, indem Sie das Formular frmScopeAndLifeTime öffnen und auf die Schaltfläche STATIC AGE klicken. Private Variablen Bis jetzt beschränkte sich die Darstellung auf Variablen, die nur innerhalb einer einzigen Prozedur gültig sind. Private Variablen (auf Modulebene) sind für alle Routinen innerhalb des Moduls sichtbar, in dem sie deklariert wurden, nicht jedoch für andere Module. Insofern sind sie für das Modul privat. Sie werden mit Hilfe einer PrivateAnweisung wie der folgenden im Abschnitt ALLGEMEINE DEKLARATIONEN eines Formulars, Berichts oder Access-Moduls deklariert: [Allgemeine Deklarationen] Option Explicit Private mintAge As Integer

Der Wert einer als privat deklarierten Variablen kann von jeder Unterroutine oder Funktion innerhalb des Moduls geändert werden. Die folgende Unterroutine erhöht beispielsweise den Wert der privaten Variablen mintAge um 1. Der Code lässt sich durch Öffnen des Formulars frmScopeAndLifeTime und einen Klick auf die Schaltfläche MODULE AGE ausführen. Private Sub cmdModuleAge_Click() mintAge = mintAge + 1 Me.txtNewAge = mintAge End Sub

Beachten Sie die Namenskonvention, dem Namen der Variablen den Buchstaben m als Präfix voranzustellen, um sie als privat auf Modulebene zu kennzeichnen. Sie sollten Privatdeklarationen nur für Variablen verwenden, die für mehrere Prozeduren desselben Moduls sichtbar sein müssen, und sich zum Ziel setzen, nach Möglichkeit mit lokalen Variablen zu arbeiten, um den Code modular und »kugelsicher« zu gestalten.

270

Kapitel 7: VBA: Eine Einführung

Öffentliche Variablen Auf öffentliche Variablen kann der gesamte VBA-Code Ihrer Anwendung zugreifen. Sie sind normalerweise auf Anmelde-IDs, Umgebungseinstellungen und ähnliche Variablen beschränkt, die für die gesamte Anwendung sichtbar sein müssen. Die Deklaration öffentlicher Variablen kann im Abschnitt ALLGEMEINE DEKLARATIONEN eines Moduls erfolgen und sieht folgendermaßen aus: Option Explicit Public gintAge As Integer

Beachten Sie das Präfix g (ein Relikt der alten globalen Variablen), das richtige Präfix für eine in einem Standardmodul deklarierte öffentliche Variable. Dieser Standard wird verwendet, weil solche Variablen nicht nur für das Modul sichtbar sind, in dem sie deklariert wurden, sondern auch für andere Module. Der folgende Code, der zum Click-Ereignis der Befehlsschaltfläche cmdPublic gehört, setzt die öffentliche Variable gintCounter um 1 herauf. Er lässt sich ausführen, wenn Sie das Formular frmScopeAndLifeTime öffnen und auf die Schaltfläche PUBLIC AGE klicken. Private Sub cmdPublicAge_Click() gintAge = gintAge + 1 Me.txtNewAge = gintAge End Sub

7.4

Kommentare in den Code einfügen

Kommentare, die seit Access 97 farblich gekennzeichnet werden, werden unter Verwendung eines Apostrophs in Module eingefügt. Außerdem kann man das Schlüsselwort Rem verwenden, aber im Allgemeinen wird das Apostroph bevorzugt. Dieses Zeichen lässt sich an den Anfang der Code-Zeile oder an eine beliebige Stelle innerhalb der Zeile setzen. Alles, was darauf folgt, wird als Kommentar angesehen. In Abbildung 7.9 sehen Sie Code mit Kommentaren.

Abbildung 7.9: Code mit Kommentaren, die verdeutlichen, was die Unterroutine macht

Das Zeichen für die Fortsetzung der Zeile

7.5

271

Das Zeichen für die Fortsetzung der Zeile

Access-Basic-Code, wie er in Access 2.0 verwendet wurde, besaß kein Zeichen für die Fortsetzung der Zeile. Deshalb mussten Sie viel mit dem Bildlauf arbeiten und eine Menge Tricks auf Lager haben, um eine fortlaufende Code-Zeile zu simulieren. Mit VBA lösen Access 97 und 2000 das Problem: Das Zeichen für die Fortsetzung der Zeile ist der Unterstrich. Abbildung 7.10 veranschaulicht seine Verwendung.

Abbildung 7.10: Das Zeichen für die Fortsetzung der Zeile wird verwendet, um die Lesbarkeit einer langen Code-Zeile zu verbessern

7.6

Die VBA-Steuerstrukturen

VBA gibt dem Entwickler verschiedene Konstrukte für Schleifen und Entscheidungen an die Hand. Die gebräuchlichsten werden in den folgenden Abschnitten vorgestellt und sind im Formular frmControlStructures zu finden.

7.6.1

If...Then...Else

Das Konstrukt If...Then...Else wertet aus, ob eine Bedingung zutrifft. Im folgenden Beispiel geschieht alles zwischen If und Else, falls die Anweisung als True ausgewertet wird, der Code zwischen Else und End If wird dagegen ausgeführt, wenn sie False ergibt. Der Else-Teil ist optional. Private Sub cmdIfThenElse_Click() If IsNull(Me.txtName) Or IsNull(Me.txtAge) Then MsgBox "Name or Age Is Blank" Else MsgBox "Your Name Is " & Me.txtName _ & "And Your Age Is " & Me.txtAge End If End Sub

272

Kapitel 7: VBA: Eine Einführung

Der Code prüft, ob das Textfeld txtName oder das Textfeld txtAge den Wert Null enthält. Je nach Ergebnis werden unterschiedliche Meldungen ausgegeben. Auch einzeilige If-Anweisungen folgender Art sind zulässig: If IsNull(Me.txtValue) Then MsgBox "You Must Enter a Value"

Dieses Format für eine If-Anweisung ist jedoch nicht zu empfehlen, weil es die Lesbarkeit verringert. Eine andere sinnvolle Form einer If-Anweisung ist die Anweisung ElseIf, mit der Sie eine unbegrenzte Anzahl von Bedingungen in einer If-Anweisung auswerten können. Der folgende Code (der in der Datenbank Chap7Ex nicht enthalten ist) liefert ein Beispiel dafür: Sub MultipleIfs(intNumber As Integer) If intNumber = 1 Then MsgBox "You entered a One" ElseIf intNumber = 2 Then MsgBox "You entered a Two" ElseIf intNumber >= 3 And intNumber = 100000, "Great Job", "Keep Plugging") End Function

Die VBA-Steuerstrukturen

273

Diese Funktion wertet den Parameter curSales daraufhin aus, ob dessen Wert größer oder gleich 100.000 DM ist. Wenn dies zutrifft, gibt sie die Zeichenfolge "Great Job" zurück, sonst die Zeichenfolge "Keep Plugging". Es wird sowohl der Wahr- als auch der Falsch-Teil der IIf-Anweisung ausgewertet. Daher wird, wenn in einem der beiden Teile des Ausdrucks ein Problem auftritt (z.B. eine Division durch Null), ein Fehler gemeldet. Die Funktion IIf wird am häufigsten in einem berechneten Steuerelement eines Formulars oder Berichts oder zum Erstellen eines neuen Feldes in einer Abfrage eingesetzt. Das wahrscheinlich gebräuchlichste Beispiel stellt ein IIf-Ausdruck dar, der bestimmt, ob der Wert eines Steuerelements Null ist. Falls dies zutrifft, kann der Ausdruck auf Wunsch eine Null bzw. eine leere Zeichenfolge zurückgeben und andernfalls den Wert des Steuerelements. Der folgende Ausdruck wertet zum Beispiel den Wert eines Steuerelements in einem Formular aus: =IIf(IsNull(Forms!frmOrders.txtFreight),0,Forms!frmOrders.txtFreight)

Dieser Ausdruck gibt entweder eine Null oder den Frachtwert im Steuerelement txtFreight aus.

Man kann mit der Funktion IIf zwar auch Null-Werte behandeln, aber dafür ist die integrierte Funktion NZ besser geeignet, welche die IIf-eigenen Schwierigkeiten umgeht.

7.6.3

Bedingtes If: Bedingte Kompilierung

Bedingte Kompilierung ermöglicht Ihnen, Code-Teile in Abhängigkeit von bestimmten Kriterien auszuführen. Diese Möglichkeit ist in einigen Situationen sinnvoll: 1. wenn bestimmte Teile Ihres Codes in der Demo-Version Ihres Programms und andere in der Version für den Verkauf ausgeführt werden sollen; 2. wenn Sie Ihre Anwendung in mehreren Ländern vertreiben und bestimmte Code-Abschnitte nur für einige Länder gelten, für andere aber nicht; 3. wenn bestimmte Teile des Codes nur während des Tests der Anwendung ausgeführt werden sollen. Bedingte Kompilierung wird mit der Direktive #If...Then...#Else durchgeführt, die hier gezeigt wird. Sie finden sie unter der Befehlsschaltfläche CONDITIONAL COMPILATION im Formular frmControlStructures: Private Sub cmdConditionalCompilation_Click() #If LANGUAGE = "Spanish" Then MsgBox "Hola, Que Tal?"

274

Kapitel 7: VBA: Eine Einführung

#Else MsgBox "Hello, How Are You" #End If End Sub

Die Compiler-Konstante, hier Language, kann an zwei Stellen deklariert werden: im Abschnitt ALLGEMEINE DEKLARATIONEN eines Moduls oder im Dialogfeld PROJEKTEIGENSCHAFTEN. Eine im Abschnitt ALLGEMEINE DEKLARATIONEN eines Moduls deklarierte Compiler-Konstante sieht folgendermaßen aus: #Const Language = "Spanish"

Der Nachteil dieser Konstanten besteht darin, dass sie sich nicht als öffentliche Konstante deklarieren lassen. Mit der Direktiven #Const kann man keine öffentlichen Compiler-Konstanten deklarieren, d.h. alle im Abschnitt ALLGEMEINE DEKLARATIONEN eines Moduls deklarierten Compiler-Konstanten können nur in diesem Modul verwendet werden. Der wesentliche Vorteil von Compiler-Konstanten dieser Art besteht darin, dass sie eine Zeichenfolge enthalten können. Die im vorigen Abschnitt deklarierte Konstante Language bekommt beispielsweise den Wert "Spanish". Öffentliche Compiler-Konstanten kann man durch Änderung der Projekteigenschaften deklarieren. Da ihr Gültigkeitsbereich öffentlich ist, kann von jeder beliebigen Stelle in der Anwendung auf Compiler-Konstanten verwiesen werden, die in den Projekteigenschaften deklariert wurden. Ihr wesentlicher Nachteil liegt darin, dass sie nur ganze Zahlen enthalten können. Sie müssten dann zum Beispiel Language = 1 eingeben. Um Compiler-Konstanten mit Hilfe des Dialogfeldes PROJEKTEIGENSCHAFTEN zu definieren, klicken Sie mit der rechten Maustaste im Projektfenster und wählen EIGENSCHAFTEN VON PROJEKT aus; dabei ist PROJEKT der Name des Projekts, an dem Sie arbeiten. Dann können Sie die benötigten Werte in das Textfeld mit der Beschriftung ARGUMENTE FÜR BEDINGTE KOMPILIERUNG eingeben. Es dürfen auch mehrere sein, die durch einen Doppelpunkt getrennt werden, zum Beispiel Language = 1 : Version = 2. Mit der Compiler-Direktive Language = 1 sähe der Code folgendermaßen aus: Sub ConditionalIf() #If Language = 1 Then MsgBox "Hola, Que Tal?" #Else MsgBox "Hello, How Are You?" #EndIf End Sub

Damit dieser Code korrekt ausgeführt wird, müssen Sie die Konstantendeklaration aus dem vorigen Beispiel entfernen.

Beachten Sie, dass die Anweisung ConditionalIf jetzt die Konstante Language daraufhin prüft, ob sie die Ganzzahl 1 ergibt.

Die VBA-Steuerstrukturen

275

Es ist wichtig, dass bedingte Konstanten nicht dasselbe sind wie normale Konstanten oder Variablen mit dem Standardkonstrukt If...Then...Else. Normale Konstanten oder Variablen werden zur Laufzeit ausgewertet, was bei jeder Ausführung Verarbeitungszeit erfordert. Bedingte Konstanten und bedingte If...Then...Else-Anweisungen steuern, welche Code-Abschnitte tatsächlich kompiliert werden. Die gesamte Auflösung findet während der Kompilierung statt – damit entfällt unnötige Verarbeitung zur Laufzeit.

7.6.4

Select Case

Anstelle mehrerer If..Then...Else-Anweisungen ist eine Select Case-Anweisung häufig verständlicher, wie Sie hier sehen. Sie finden diesen Code unter der Schaltfläche SELECT CASE des Formulars frmControlStructures. Private Sub cmdCase_Click() Dim intAge As Integer If IsNull(Me.txtAge) Then intAge = 0 Else intAge = Val(Me.txtAge) End If Select Case intAge Case 0 MsgBox "You Must Enter a Number" Case 1 To 18 MsgBox "You Are Just a Kid" Case 19, 20, 21 MsgBox "You Are Almost an Adult" Case 22 To 40 MsgBox "Good Deal" Case Is > 40 MsgBox "Getting Up There!" Case Else MsgBox "You Entered An Invalid Number" End Select End Sub

Diese Unterroutine konvertiert zunächst mit Hilfe der Funktion NZ eine Null oder einen Leerwert im Steuerelement txtAge in 0; jeder andere Wert wird in intAge gespeichert. Dann wertet die Select Case-Anweisung die Variable intAge aus. Wenn der Wert 0 ist, wird ein Meldungsfeld mit dem Text You Must Enter a Number eingeblendet. Wenn der Wert zwischen 1 und 18 (einschließlich) liegt, enthält das Meldungsfeld die Aussage You Are Just a Kid. Bei Eingabe von 19, 20 oder 21 lautet die Meldung You Are Almost an Adult, bei einem Wert zwischen 22 und 40 (inklusive) Good Deal, und bei einem Wert über 40 heißt sie Getting Up There. Bei anderen Werten erhält der Benutzer die Meldung, dass er eine ungültige Zahl eingegeben hat.

276

7.6.5

Kapitel 7: VBA: Eine Einführung

Schleifen

VBA bietet mehrere Schleifenstrukturen, die in diesem Abschnitt fast alle erläutert werden. Sehen Sie sich folgendes Beispiel an (das Sie unter der Befehlsschaltfläche Do While...Loop des Formulars frmControlStructures finden): Sub cmdDoWhileLoop_Click() Do While Nz(Me!txtAge)< 35 Me.txtAge = Nz(Me!txtAge) + 1 Loop End Sub

In dieser Struktur wird der Code innerhalb der Schleife nicht ausgeführt, wenn der Wert in txtAge größer oder gleich 35 ist. Wenn der Code wenigstens einmal bedingungslos ausgeführt werden soll, müssen Sie folgendes Konstrukt verwenden (das Sie unter der Befehlsschaltfläche Do...Loop While des Formulars frmControlStructures finden): Sub cmdDoLoopWhile_Click() Do Me.txtAge = Nz(Me!txtAge) + 1 Loop While Nz(Me!txtAge) < 35 End Sub

Dieser Code wird einmal ausgeführt, auch wenn txtAge auf 35 gesetzt wurde. Die Do While...Loop-Schleife im vorigen Beispiel wird ausgewertet, bevor der Code ausgeführt wird, und garantiert daher die Ausführung nicht. Die Do...Loop While-Schleife wird erst am Schleifenende ausgewertet und garantiert daher die Ausführung. Alternativen zu Do While...Loop und Do...Loop While stellen die Konstrukte Do Until...Loop und Do...Loop Until dar. Do Until...Loop (zu finden unter der gleichnamigen Befehlsschaltfläche im Formular frmControlStructures) funktioniert folgendermaßen: Sub cmdDoUntil_Click() Do Until Nz(Me!txtAge) = 35 Me.txtAge = Nz(Me!txtAge) + 1 Loop End Sub

Diese Schleife wird solange ausgeführt, bis txtAge den Wert 35 erreicht. Das Konstrukt Do...Loop Until (zu finden unter der gleichnamigen Befehlsschaltfläche im Formular frmControlStructures) stellt eine weitere Variante dar:

Die VBA-Steuerstrukturen

277

Sub cmdLoopUntil_Click() Do Me.txtAge = Nz(Me!txtAge) + 1 Loop Until Nz(Me!txtAge) = 35 End Sub

Wie das Konstrukt Do...Loop While wertet auch Do...Loop Until die Bedingung erst am Schleifenende aus, so dass der Code innerhalb der Schleife garantiert mindestens einmal ausgeführt wird. Eine Schleife lässt sich leicht aus Versehen so schreiben, dass sie endlos weiterläuft, wie Sie in folgendem Beispiel sehen (das Sie nicht in Chap7Ex finden):

Sub EndlessLoop() Dim intCounter As Integer IntCounter As Integer IntCounter = 5 Do Debug.Print intCounter IntCounter = intCounter + 1 Loop until intCounter = 5 End Sub

Dieser Code setzt intCounter auf 5. Die Schleife erhöht intCounter um eins und prüft dann, ob intCounter gleich 5 ist. Wenn dies nicht zutrifft, wird der Code in der Schleife noch einmal ausgeführt. Da die Variable intCounter niemals den Wert 5 annehmen wird (weil sie mit 6 beginnt), wird die Schleife endlos fortgesetzt. Sie müssen sie mit (Strg)+(Pause) verlassen; diese Tastenkombination funktioniert jedoch in der Laufzeitversion von Access nicht.

7.6.6

For...Next

Das Konstrukt For...Next wird verwendet, wenn Sie eine bestimmte Anzahl von Wiederholungen durchführen wollen. Sie finden es unter der gleichnamigen Befehlsschaltfläche im Formular frmControlStructures und es sieht folgendermaßen aus: Sub cmdForNext_Click() Dim intCounter As Integer For intCounter = 1 To 5 Me!txtAge = Nz(Me!txtAge) + 1 Next intCounter End Sub

278

Kapitel 7: VBA: Eine Einführung

Beachten Sie, dass die Variable intCounter selbsterhöhend ist. Sowohl Anfangs- als auch Endwert können Variablen sein. Eine For...Next-Anweisung kann auch eine Schrittweite übernehmen, wie Sie gleich sehen (der Zähler wird bei jedem Schleifendurchlauf um den Wert von Step hochgesetzt): Sub ForNextStep() 'Beachten Sie, dass Sie diesen Code nicht in der Datenbank Chap7ex.mdb finden. Dim intCounter As Integer For intCounter = 1 To 5 Step 2 Me!txtAge = Nz(Me!txtAge) + 1 Next intCounter End Sub

7.6.7

With...End With

Die Anweisung With...End With führt eine Folge von Anweisungen für dasselbe Objekt aus. Ein Beispiel (zu finden unter der gleichnamigen Befehlsschaltfläche im Formular frmControlStructures): Private Sub cmdWithEndWith_Click() With Me.txtAge .BackColor = 16777088 .ForeColor = 16711680 .Value = "Hello World" .FontName = "Arial" End With End Sub

Dieser Code führt vier Operationen am Textfeld txtAge im aktuellen Formular aus, welche die Eigenschaften BackColor, ForeColor, Value und FontName des Textfeldes ändern. Die Anweisung With...End With verfügt über zwei wesentliche Vorzüge. Einer besteht lediglich in geringerem Eingabeaufwand: Sie brauchen nicht für jede Aktion, die ausgeführt werden soll, den Objektnamen zu wiederholen. Der wichtigere betrifft die Leistung: Da nur einmal (und nicht mehrmals) auf das Objekt verwiesen wird, ist die Ausführung effizienter. Die Vorteile fallen noch deutlicher aus, wenn sich das With...End With-Konstrukt innerhalb einer Schleife befindet.

7.6.8

For Each...Next

Die Anweisung For Each...Next führt eine Gruppe von Anweisungen für jedes Element eines Datenfelds oder einer Auflistung aus. Das folgende Beispiel (das Sie unter der gleichnamigen Befehlsschaltfläche im Formular frmControlStructures finden) veranschaulicht die Verwendung dieses leistungsfähigen Konstrukts:

Die VBA-Steuerstrukturen

279

Private Sub cmdForEachNext_Click() Dim ctl As Control For Each ctl In Controls With ctl .ForeColor = 16711680 .FontName = "Arial" .FontSize = 14 End With Next ctl End Sub

Der Code durchläuft die Steuerelemente eines Formulars in Form einer Schleife und ändert dabei die Eigenschaften ForeColor, FontName und BackColor aller Steuerelemente. Wie im vorhergehenden Beispiel wird auch hier das Konstrukt With...End With verwendet, diesmal wie häufig zusammen mit For Each...Next. Es folgt ein Beispiel für das Konstrukt With...End With (zu finden unter der gleichnamigen Befehlsschaltfläche im Formular frmControlStructures): Private sub cmdForEachWith_Click() With Me.txtAge .BackColor = 16777088 .ForeColor = 16711680 .Value = "Hello World" .FontName = "Arial" End With End Sub

Mit diesem Code werden drei Eigenschaften des Steuerelements txtAge geändert: ForeColor, FontName und FontSize. Denken Sie vor der Umsetzung all dieser wertvollen Informationen in die Praxis daran, dass noch keine Fehlerbehandlung in den Code integriert wurde. Wenn eines der Steuerelemente des Beispielformulars keine Eigenschaft namens ForeColor, FontName oder FontSize besitzt, führt die Ausführung zu einem Fehler. In Kapitel 8 lernen Sie, wie man den Typ eines Objekts bestimmt, bevor man einen Befehl für dieses ausführt. Wenn man vor dem Versuch, die Eigenschaften eines Objekts zu ändern, seinen Typ kennt, kann dies zur Vermeidung von Fehlern beitragen.

280

7.7

Kapitel 7: VBA: Eine Einführung

Parameter über- und Werte zurückgeben

Sowohl Unterroutinen als auch Funktionen können Argumente (Parameter) übernehmen, aber nur Funktionen können Werte zurückgeben. Die folgende Unterroutine (die Sie unter der Befehlsschaltfläche PASS PARAMETERS des Formulars frmParametersAndReturnValues finden) übernimmt zwei Parameter, nämlich txtFirstName und txtLastName, und zeigt dann ein Meldungsfeld mit dem ersten Buchstaben der übergebenen Parameter an. Private Sub cmdPassParamters_Click() Call Initials(Nz(Me.txtFirstName), Nz(Me.txtLastName)) End Sub Sub Initials(strFirst As String, strLast As String) 'Diese Prozedur finden Sie, wenn Sie in der Objektliste 'des VBE-Fensters Allgemein auswählen MsgBox "Your Initials Are " & _ Left(strFirst, 1) & _ Left(strLast, 1) End Sub

Beachten Sie, dass der Text in den Steuerelementen txtFirstName und txtLastName des aktuellen Formulars (dargestellt durch das Schlüsselwort Me) an die Unterroutine Initials übergeben wird, wobei die Parameter strFirst und strLast heißen. Das erste Zeichen beider Parameter wird im Meldungsfeld angezeigt. Dieser Code übergibt lediglich Werte und arbeitet dann mit diesen. Das folgende Beispiel (das Sie unter der Befehlsschaltfläche RETURN VALUES des Formulars frmParametersAndReturnValues finden) verwendet eine Funktion, um einen Wert zurückzugeben. Private Sub cmdReturnValues_Click() Dim strInitials As String strInitials = ReturnInit(Me.txtFirstName, Me.txtLastName) MsgBox "Your Initials Are " & strInitials End Sub Function ReturnInit(strFName, strLName As String) As String 'Diese Prozedur finden Sie, wenn Sie in der Objektliste 'des VBE-Fensters Allgemein auswählen ReturnInit = Left$(strFname, 1) & Left(strLName, 1) End Function

Beachten Sie, dass in diesem Beispiel die Funktion ReturnInit aufgerufen wird, welche die in den beiden Textfeldern stehenden Werte als Parameter sendet. Die Funktion setzt ReturnInit (den Funktionsnamen) auf die ersten Zeichen der Zeichenfolgen, gibt damit den Wert an die aufrufende Routine (cmdReturnValues_Click) zurück und setzt strInitials auf den Rückgabewert.

Vom Modulfenster aus Prozeduren ausführen

281

Beachten Sie, dass die Funktion ReturnInit so gestaltet ist, dass sie zwei Zeichenfolgen als Parameter übernimmt. Das ist aus dem Schlüsselwort As String zu entnehmen, das auf jeden Parameter folgt. Außerdem soll die Funktion eine Zeichenfolge zurückgeben, was Sie aus dem Schlüsselwort As String im Anschluss an die Parameterliste (außerhalb der Klammern) erkennen. Wenn Sie nicht explizit festlegen, dass die Funktion einen bestimmten Datentyp zurückgeben soll, gibt sie den Typ Variant zurück.

7.8

Vom Modulfenster aus Prozeduren ausführen

In Access 2000 ist das Testen von Prozeduren vom Modulfenster aus einfach – klicken Sie einfach irgendwo innerhalb der auszuführenden Prozedur und drücken Sie die Taste (F5) oder klicken Sie auf die Schaltfläche SUB/USERFORM AUSFÜHREN in der Symbolleiste. Dann wird die Prozedur, in der Sie sich befinden, genauso ausgeführt, als ob Sie sie per Programm oder mit Hilfe des Direktbereichs im Testfenster aufgerufen hätten.

7.9

Das Objekt DoCmd: Makro-Aktionen durchführen

Die Access-Umgebung ist reich an Objekten mit integrierten Eigenschaften und Methoden. Mit Hilfe von VBA-Code lassen sich die Eigenschaften ändern und die Methoden ausführen. Eines der in Access verfügbaren Objekte heißt DoCmd und wird zur Ausführung von Makro-Aktionen in VBA-Prozeduren eingesetzt. Die MakroAktionen werden dabei als Methoden des Objekts DoCmd behandelt und die Syntax dafür sieht folgendermaßen aus: DoCmd.ActionName [Argumente]

Ein praktisches Beispiel: DoCmd.OpenReport strReportName, acPreview

Die Methode OpenReport ist eine Methode des Objekts DoCmd, die einen Bericht ausführt. Die beiden ersten Parameter, die sie übernimmt, sind der Name des gewünschten Berichts und die Ansicht, in der dieser erscheinen soll (Vorschau-, Normal- oder Entwurfsansicht). Beides sind Argumente der Methode. Zu den meisten Makro-Aktionen gibt es entsprechende Methoden von DoCmd, die Sie in der Hilfe finden (für einige jedoch nicht): AddMenu, MsgBox, RunApp, RunCode, SendKeys, SetValue, StopAllMacros und StopMacro. Dabei ist allein die Methode SendKeys für VBA-Programmierer von Bedeutung. Für die übrigen Makro-Aktionen gibt es entweder im VBA-Code keine Verwendung oder sie lassen sich mit Hilfe von VBA-

282

Kapitel 7: VBA: Eine Einführung

Funktionen oder -Befehlen effizienter ausführen. Die Sprache VBA besitzt zum Beispiel eine Funktion namens MsgBox, die wesentlich leistungsfähiger ist als die MakroEntsprechung. Viele der Methoden von DoCmd besitzen optionale Parameter. Falls Sie kein Argument liefern, wird der Standardwert verwendet. Sie können Kommata als Platzhalter einsetzen, um die Positionen fehlender Argumente zu markieren, wie Sie hier sehen: DoCmd.OpenForm "frmOrders", , ,"[OrderAmount] > 1000"

Die Methode OpenForm des Objekts DoCmd übernimmt sieben Parameter, von denen die letzten sechs optional sind. Im Beispiel werden zwei Parameter explizit genannt. Der erste ist der Name des Formulars, eine notwendige Angabe. Der zweite und der dritte Parameter fehlen, d.h., Sie haben die Standardwerte akzeptiert. Die als Platzhalter verwendeten Kommata sind erforderlich, weil ein weiterer Parameter explizit angegeben ist. Es handelt sich um den vierten, die Where-Bedingung des Formulars: den Datensatz, in dem die Bestellmenge größer als 1.000 ist. Die übrigen Parameter sind nicht genannt, also werden für diese die Standardwerte benutzt. Wenn Sie wollen, können Sie für die Übergabe benannte Parameter verwenden, die später behandelt werden. Diese können die oben genannte Syntax wesentlich vereinfachen, weil die Argumente nicht in einer bestimmten Reihenfolge erscheinen und weil Sie keine Kommata zählen müssen. Die Syntax kann folgendermaßen geändert werden: DoCmd.OpenForm FormName:="frmOrders", WhereCondition:= "[OrderAmount] > 1000"

7.10

Integrierte Funktionen

VBA besitzt eine reichhaltige und umfassende Funktionsbibliothek sowie Werkzeuge, um ihre Benutzung zu erleichtern.

7.10.1

Integrierte Funktionen

Einige der häufiger verwendeten Funktionen und Beispiele werden in den folgenden Abschnitten vorgestellt. Schauen Sie einmal an einem Regentag in die Online-Hilfe oder die »Sprachreferenz von Microsoft Access Visual Basic«, um sich mit den übrigen vertraut zu machen. Die folgenden Beispiele dienen lediglich der Veranschaulichung und sind nicht in der Datenbank Chap7Ex zu finden.

Integrierte Funktionen

283

Format Die Funktion Format formatiert Ausdrücke in der angegebenen Art. Der erste Parameter ist der zu formatierende Ausdruck, der zweite das anzuwendende Format. Ein Beispiel: Sub FormatData() Debug.Print Format$(50, "Currency") 'Gibt $50.00 aus Debug.Print Format$(Now, "Short Date") 'Gibt das aktuelle Datum aus Debug.Print Format$(Now, "DDDD") 'Gibt die verbale Bezeichnung des Tages aus Debug.Print format$(Now, "DDD") 'Gibt den Tag mit drei Zeichen aus Debug.Print Format$(Now, "YYYY") 'Gibt das Jahr vierstellig aus Debug.Print Format$(Now, "WW") 'Gibt die Wochennummer aus End Sub

Instr Die Funktion Instr gibt die Stelle an, an der eine Zeichenfolge innerhalb einer anderen Zeichenfolge anfängt: Sub InstrExample() Debug.Print InStr("Alison Balter", "Balter") 'Gibt 8 zurück Debug.Print InStr("Hello", "l") 'Gibt 3 zurück End Sub

Left Die Funktion Left gibt die angegebene Anzahl Zeichen einer Zeichenfolge von links aus: Sub LeftExample() Debug.Print Left$("Hello World", 7) 'Gibt Hello Windows aus End Sub

Right Die Funktion Right gibt die angegebene Anzahl Zeichen einer Zeichenfolge von rechts aus: Sub RightExample() Debug.Print Right$("Hello World", 7) 'Gibt o World aus End Sub

Mid Die Funktion Mid gibt eine Teilzeichenkette mit der genannten Zeichenzahl aus. Das Beispiel beginnt mit dem vierten Zeichen und gibt fünf Zeichen zurück:

284

Kapitel 7: VBA: Eine Einführung

Sub MidExample() Debug.Print Mid$("Hello World", 4, 5) 'Gibt lo Wo aus End Sub

UCase Die Funktion UCase gibt eine Zeichenfolge vollständig in Großbuchstaben zurück: Sub UCaseExample() Debug.Print UCase$("Hello World") 'Gibt HELLO WORLD aus End Sub

DatePart Die Funktion DatePart gibt den angegebenen Teil des Datums zurück: Sub DatePartExample() Debug.Print DatePart("YYYY", Now) 'Gibt das Jahr aus Debug.Print DatePart("M", Now) 'Gibt die Monatsnummer aus Debug.Print DatePart("Q", Now) 'Gibt die Nummer des Quartals aus Debug.Print DatePart("Y", Now) 'Gibt den Tag im Jahr aus Dbug.Print DatePart("WW", Now) 'Gibt die Wochennummer aus End Sub

DateDiff Die Funktion DateDiff gibt den Abstand zwischen zwei Daten aus: Sub DateDiffExample() Debug.Print DateDiff("d", Now, "12/31/99") ''Tage bis zum 32.12.1999 Debug.Print DateDiff("m", Now, "12/31/99") ''Monate bis zum 31.12.1999 Debug.Print DateDiff("yyyy", Now, "12/31/99") ''Jahre bis zum 31.12.1999 Debug.Print DateDiff("q", Now, "12/31/99) ''Quartale bis zum 31.12.1999 End Sub

DateAdd Die Funktion DateAdd gibt das Ergebnis der Addition einer angegebenen Zeitspanne zu oder ihre Subtraktion von einem Datum aus: Sub DateAddExample() Debug.Print DateAdd("d", 3, Now) 'Heute plus drei Tage

Integrierte Funktionen

Debug.Print 'Heute plus Debug.Print 'Heute plus Debug.Print 'Heute plus Debug.Print 'Heute plus End Sub

7.10.2

285

DateAdd("m", 3, Now) drei Monate DateAdd("yyyy", 3, Now) drei Jahre DateAdd("q", 3, Now) drei Quartale DateAdd("ww", 3, Now) drei Wochen

Funktionen leicht gemacht mit dem Objektkatalog

Mit dem Objektkatalog können Sie sich Elemente der Typbibliothek einer ActiveXKomponente ansehen. Im Klartext: mit dem Objektkatalog können Sie die Methoden, Eigenschaften und Konstanten einer Komponente durchblättern. Außerdem können Sie Informationen kopieren und in Ihren Code einfügen sowie die Parameter einer Methode hinzufügen. Mit folgenden Schritten sehen Sie die verfügbaren Methoden durch, kopieren die gewünschte Methode und fügen sie in Ihren Code ein: 1. Wählen Sie im VBE den Menübefehl ANSICHT|OBJEKTKATALOG (beachten Sie, dass Sie auch ein Symbol in der Symbolleiste finden, das Sie verwenden können) oder öffnen Sie mit (F2) das Fenster OBJEKTKATALOG (siehe Abbildung 7.11).

Abbildung 7.11: Der Objektkatalog mit allen Klassen der Datenbank Chap7Ex und allen Elementen des Moduls basUtils

2. Das Fenster OBJEKTKATALOG ist in horizontaler Richtung in zwei Flächen geteilt. Die Objektliste links oben dient zum Filtern der Elemente, die im unteren Teil

286

Kapitel 7: VBA: Eine Einführung

des Fensters angezeigt werden sollen. Wählen Sie in dieser Objektliste das Projekt bzw. die Bibliothek aus, deren Klassen und Elemente Sie im unteren Teil ansehen wollen. 3. Wählen Sie im unteren Teil des Fensters im linken Listenfeld, in dem Klassenmodule, Vorlagen für neue Objekte, Standardmodule und Module mit Unterroutinen und Funktionen aufgelistet sind, die Klasse aus. 4. Wählen Sie im Listenfeld ELEMENTE VON eine Eigenschaft, eine Methode, ein Ereignis, eine Konstante, eine Funktion oder eine Anweisung der Klasse aus. In Abbildung 7.11 ist im Listenfeld links das Modul basUtils hervorgehoben. Beachten Sie, dass die zu basUtils gehörenden Unterroutinen und Funktionen im Listenfeld rechts erscheinen. 5. Klicken Sie auf die Schaltfläche IN ZWISCHENABLAGE KOPIEREN (die dritte von rechts in der oberen Symbolleiste des Fensters OBJEKTKATALOG), um die Funktion und ihre Parameter in die Zwischenablage zu kopieren, so dass Sie sie leicht in Ihren Code einfügen können. Das Beispiel in Abbildung 7.11 zeigt die Auswahl einer benutzerdefinierten Funktion, die aus einem Modul der Datenbank gewählt wurde, aber Sie können auch eine beliebige integrierte Funktion auswählen. Abbildung 7.12 zeigt ein Beispiel, in dem die Funktion DatePart aus der VBA-Bibliothek gewählt wurde. Der Objektkatalog stellt alle Bibliotheken bereit, auf welche die Datenbank verweist. In den Kapiteln 8 und 26 wird er ausführlicher behandelt.

Abbildung 7.12: Im Objektkatalog ist die VBA-Bibliothek ausgewählt

Mit Konstanten arbeiten

7.11

287

Mit Konstanten arbeiten

Eine »Konstante« ist ein aussagekräftiger Name für eine nichtssagende Zahl oder Zeichenfolge. Konstanten können nur für Werte verwendet werden, die sich zur Laufzeit nicht ändern. Ein Steuer- oder Provisionssatz könnte beispielsweise in Ihrer gesamten Anwendung als Konstante auftreten. In Access gibt es drei Arten von Konstanten:

 symbolische Konstanten  interne Konstanten  systemdefinierte Konstanten Symbolische Konstanten werden mit Hilfe des Schlüsselworts Const angelegt und dienen dazu, die Lesbarkeit Ihres Codes zu verbessern und die Pflege zu erleichtern. Anstatt bei jedem Verweis auf den Steuersatz die Zahl .0875 zu nennen, können Sie die Konstante mccurTaxRate verwenden. Wenn sich der Steuersatz ändert und Sie den Wert in Ihrem Code anpassen müssen, ist dies nur an einer Stelle erforderlich. Außerdem ist die Bezeichnung mccurTaxRate – anders als die Zahl .0875 – selbstdokumentierend. Interne Konstanten sind in Microsoft Access integriert und Teil der Sprache. Als Access-Programmierer können Sie Konstanten, die von Microsoft Access, Visual Basic, DAO und Active Data Objects (ADO) bereitgestellt werden, sowie Konstanten aus allen Objektbibliotheken verwenden, die Sie in Ihrer Anwendung einsetzen. Es gibt nur drei systemdefinierte Konstanten und diese stehen allen Anwendungen auf Ihrem Rechner zur Verfügung: True, False und Null.

7.11.1

Mit symbolischen Konstanten arbeiten

Wie bereits erwähnt, wird eine symbolische Konstante mit Hilfe des Schlüsselworts Const deklariert (in einer Unterroutine oder Funktion oder im Abschnitt ALLGEMEIN eines Formular- oder Berichtsmoduls). Für Konstanten ist in Access 2000 strenge Typzuweisung möglich. Deklaration und Verwendung einer privaten Konstanten würden folgendermaßen aussehen: Private Const TAXRATE As Currency = .0875

Wenn dieser Code im Abschnitt DEKLARATIONEN eines Moduls steht, legt er eine private Konstante namens TAXRATE mit dem Wert .0875 an, die folgendermaßen verwendet wird: Function TotalAmount(curSaleAmount As Currency) TotalAmount = curSaleAmount * TAXRATE End Function

288

Kapitel 7: VBA: Eine Einführung

Diese Routine multipliziert den Wert von curSaleAmount, den sie als Parameter übernimmt, mit der Konstanten TAXRATE und gibt das Ergebnis zurück, indem sie den Funktionsnamen mit dem Produkt der beiden Werte gleichsetzt. Der Vorteil der Konstanten liegt in diesem Beispiel darin, dass der Code besser lesbar ist als die Zeile TotalAmount = curSaleAmount * .0875. Der Gültigkeitsbereich symbolischer Konstanten Genauso wie normale Variablen haben auch benutzerdefinierte Konstanten einen Gültigkeitsbereich. Im vorangegangenen Beispiel haben Sie eine private Konstante angelegt. Mit der folgenden Anweisung wird, wenn sie im Abschnitt DEKLARATIONEN eines Moduls steht, eine öffentliche Konstante erzeugt: Public Const TAXRATE = .0875 As Currency

Da diese Konstante als öffentlich deklariert wurde, können alle Unterroutinen und Funktionen (einschließlich der Ereignisroutinen) in der gesamten Anwendung auf sie zugreifen. Um die Vorzüge einer öffentlichen Konstanten besser zu verstehen, können Sie sich einen Fall denken, in dem viele Funktionen und Unterroutinen auf die Konstante TAXRATE verweisen. Stellen Sie sich vor, was passiert, wenn sich der Steuersatz ändern sollte: ohne Konstante müssten Sie die gesamte Anwendung durchgehen und den alten Steuersatz durch den neuen ersetzen. Da jedoch Ihre öffentliche Konstante nur an einer einzigen Stelle deklariert wurde, können Sie die eine Code-Zeile mit der Konstantendeklaration mühelos ändern. Die Werte von Konstanten lassen sich definitionsgemäß nicht zur Laufzeit ändern. Bei einem solchen Versuch erhalten Sie folgende Fehlermeldung des VBA-Compilers: Assignment to constant not permitted Abbildung 7.13 zeigt dieses Meldungsfeld. Sie können erkennen, dass der Versuch gemacht wurde, den Wert der Konstanten TAXRATE zu ändern, was zu einem Compiler-Fehler führte. Wenn Sie den Wert zur Laufzeit ändern müssen, sollten Sie erwägen, den Wert in einer Tabelle abzulegen, anstatt ihn als Konstante zu deklarieren. Sie können den Wert dann beim Laden der Anwendung in eine Variable einlesen und bei Bedarf ändern. Wenn Sie wollen, können Sie den neuen Wert in die Tabelle zurückschreiben.

7.11.2

Mit internen Konstanten arbeiten

Microsoft Access deklariert eine Reihe interner Konstanten, die sich in Code-, Formular- und Berichtsmodulen verwenden lassen. Da sie von Microsoft Access reserviert wurden, können Sie weder ihre Werte ändern noch ihre Namen erneut verwenden; die Konstanten können jedoch jederzeit ohne Deklaration benutzt werden.

Mit Konstanten arbeiten

289

Sie sollten interne Konstanten in Ihrem Code verwenden, wo immer es möglich ist. Das macht den Code nicht nur leichter lesbar, sondern auch besser auf zukünftige Access-Versionen portierbar. Möglicherweise ändert Microsoft irgendwann den Wert einer Konstanten, aber der Name wird wahrscheinlich nicht geändert werden. Alle internen Konstanten erscheinen im Objektkatalog, der mit einem Klick auf das Werkzeug OBJEKTKATALOG in der Symbolleiste von Visual Basic aktiviert wird. Um die Konstanten anzuzeigen, die zur Access-Bibliothek gehören, wählen Sie in der aufklappbaren Liste PROJEKT/BIBLIOTHEK im Objektkatalog den Eintrag ACCESS. Klicken Sie dann im Listenfeld KLASSEN auf KONSTANTEN, um die Liste der Konstanten im Listenfeld ELEMENTE VON 'KONSTANTEN' auszugeben.

Abbildung 7.13: Der Versuch, den Wert einer Konstanten zu ändern

In der in Abbildung 7.14 gezeigten Liste beginnen alle Konstantennamen mit ac. Alle VBA-Konstanten besitzen das Präfix vb, alle DAO-Konstanten db und alle AccessKonstanten ac. Um sich die Konstanten von Visual Basic anzusehen, wählen Sie im Listenfeld PROJEKT/BIBLIOTHEK den Eintrag VBA und dann in der Klassenliste den Eintrag KONSTANTEN. Wenn das Projekt, mit dem Sie arbeiten, einen Verweis auf die ADO-Bibliothek enthält, können Sie die dazugehörigen Konstanten sehen, indem Sie im Listenfeld PROJEKT/BIBLIOTHEK den Eintrag ADODB wählen. Anschließend klicken Sie auf . Damit wird eine Liste der ADODB-Konstanten (mit dem Präfix ad) geöffnet.

290

Kapitel 7: VBA: Eine Einführung

Abbildung 7.14: Mit Hilfe des Objektkatalogs interne Konstanten ansehen

7.12

Werkzeuge für die Arbeit im VBE

Wenn Sie die branchenüblichen Tipps und Tricks, von denen viele in diesem Kapitel erläutert werden, effizient nutzen, können Sie viel Zeit sparen. Diese Tricks helfen Ihnen dabei, sich in der Programmierumgebung zu bewegen und Ihren Code schnell und mühelos zu ändern. Dazu gehört die Möglichkeit, problemlos in eine benutzerdefinierte Prozedur zu wechseln, innerhalb von Modulen Stellen zu suchen und zu ersetzen, Hilfe zu VBA-Funktionen und -Befehlen zu finden und das Code-Fenster zu teilen, um zwei Prozeduren gleichzeitig einsehen zu können. Die Entwicklungsumgebungen von Access 97 und Access 2000 sind besser als ihre Vorgänger. Es wurden Fähigkeiten hinzugefügt, die das Programmieren erleichtern und angenehmer gestalten, wie zum Beispiel folgende:

 Eigenschaften und Methoden auflisten  Konstanten auflisten  Direkthilfe zu Befehlen und Funktionen  Parameterinformationen  Vollenden eines Wortes durch Access  Einsehen von Funktionsdefinitionen Alle diese bei der Programmierung hilfreichen Funktionen stehen mit einem Rechtsklick zur Verfügung, wenn sich der Cursor im Modulfenster befindet.

291

Werkzeuge für die Arbeit im VBE

7.12.1

Eigenschaften und Methoden auflisten

Mit dem Merkmal EIGENSCHAFTEN UND METHODEN ANZEIGEN können Sie alle Objekte, Eigenschaften und Methoden anschauen, die für das aktuelle Objekt zur Verfügung stehen. Um es aufzurufen, klicken Sie mit der rechten Maustaste hinter dem Namen des Objekts und wählen dann EIGENSCHAFTEN/METHODEN ANZEIGEN. (Sie können auch (Strg)+(J) drücken.) Dann erscheinen die anwendbaren Objekte, Eigenschaften und Methoden in einem Listenfeld (siehe Abbildung 7.15). Das richtige Objekt bzw. die richtige Eigenschaft oder Methode finden Sie auf eine der folgenden Arten:

 Sie fangen an, den Namen des Objekts, der Eigenschaft oder der Methode einzugeben.

 Sie bewegen sich mit Hilfe des Aufwärts- oder Abwärtspfeils durch die Liste.  Sie bewegen die Liste mit Hilfe des Bildlaufs und markieren Ihre Auswahl.

Abbildung 7.15: Die Liste der Eigenschaften und Methoden des Objekts TextBox

Mit folgenden Methoden fügen Sie die Auswahl in Ihren Code ein:

 Doppelklicken Sie auf den Eintrag.  Markieren Sie den Eintrag mit einem Klick und drücken Sie dann (ÿ) oder (¢), um die Auswahl einzufügen und in die nächste Zeile zu gelangen.

292

Kapitel 7: VBA: Eine Einführung

Mit der Option ELEMENTE AUTOMATISCH AUFLISTEN, die Sie auf der Registerkarte EDITOR des Dialogfeldes OPTIONEN finden, veranlassen Sie, dass die Merkmale EIGENSCHAFTEN UND METHODEN ANZEIGEN und KONSTANTEN ANZEIGEN automatisch aufgerufen werden, sobald Sie den Namen eines Objekts oder einer Eigenschaft eingeben.

7.12.2

Konstanten auflisten

Mit dem Merkmal KONSTANTEN ANZEIGEN wird eine aufklappbare Liste geöffnet, die gültige Konstanten für eine von Ihnen eingegebene Eigenschaft sowie für Funktionen mit Argumenten anzeigt, die Konstanten sind. Es funktioniert ähnlich wie das Merkmal EIGENSCHAFTEN UND METHODEN ANZEIGEN. Um es aufzurufen, klicken Sie mit der rechten Maustaste hinter dem Namen der Eigenschaft oder des Arguments (bei mehreren Argumenten muss das vorangehende mit einem Komma abgetrennt sein) und wählen dann KONSTANTEN ANZEIGEN. (Sie können auch (Strg)+(ª)+(J) drücken.) Dann erscheint eine Liste der gültigen Konstanten (siehe Abbildung 7.16). Die gewünschte Konstante wählen Sie mit Hilfe einer der im vorigen Abschnitt genannten Methoden aus.

Abbildung 7.16: Die Liste der Konstanten für den Parameter vbMsgBoxStyle

7.12.3

QuickInfo

Das Merkmal QUICKINFO liefert Ihnen die vollständige Syntax für eine Funktion, Anweisung, Prozedur, Methode oder Variable. Um diese zu verwenden, klicken Sie mit der rechten Maustaste hinter den Namen der Funktion, Anweisung, Prozedur, Methode oder Variablen und wählen QUICKINFO (oder drücken (Strg)+(I)). Dann

Werkzeuge für die Arbeit im VBE

293

wird ein Tipp mit der korrekten Syntax für das Element eingeblendet (siehe Abbildung 7.17). Während Sie einen Parameter in das Element eingeben, wird dieser bis zur Eingabe des Kommas, das ihn vom nächsten Parameter trennt, in fetter Schrift dargestellt.

Abbildung 7.17: Die Syntax der Funktion MsgBox

Mit der Option AUTOMATISCHE QUICKINFO, die Sie im Dialogfeld OPTIONEN finden, wird das Merkmal QUICKINFO automatisch aufgerufen, sobald Sie den Namen eines Objekts oder einer Eigenschaft eingeben.

7.12.4

Parameterinfo

Das Merkmal PARAMETERINFO liefert Ihnen Informationen über die Parameter einer Funktion, Anweisung oder Methode. Um diese zu verwenden, klicken Sie mit der rechten Maustaste hinter das Begrenzungszeichen, welches das Ende des Namens der Funktion, Anweisung oder Methode angibt, und wählen PARAMETERINFO (oder drücken (Strg)+(ª)+(I)). Dann wird eine aufklappbare Liste mit Informationen über die Parameter der Funktion oder Anweisung eingeblendet, die erst geschlossen wird, nachdem alle erforderlichen Parameter eingegeben sind, die Funktion mit optionalen Parametern vervollständigt ist oder wenn die Taste (ESC) gedrückt wird. Das Merkmal PARAMETERINFO liefert nur Informationen über die Ursprungsfunktion. Wenn Parameter einer Funktion selbst Funktionen sind, müssen Sie die QUICKINFO verwenden, um Informationen über die eingebetteten Funktionen zu erhalten.

294

7.12.5

Kapitel 7: VBA: Eine Einführung

Wort vervollständigen

Das Merkmal WORT VERVOLLSTÄNDIGEN vervollständigt ein Wort, das Sie gerade eingeben. Um es zu verwenden, müssen Sie zunächst eine ausreichende Anzahl Zeichen eingeben, damit Visual Basic das gewünschte Wort erkennen kann. Danach klicken Sie mit der rechten Maustaste und wählen WORT VERVOLLSTÄNDIGEN (oder Sie drücken (Strg)+(_____)). Dann stellt Visual Basic das Wort fertig.

7.12.6

Definition

Das Merkmal DEFINITION zeigt die Stelle im Code-Fenster, an der die ausgewählte Variable oder Prozedur definiert wurde. Um eine Definition zu bekommen, klicken Sie mit der rechten Maustaste auf den Namen der Variablen oder Prozedur Ihres Interesses und wählen DEFINITION (oder drücken (SHIFT)+(F2)). Damit wird der Cursor in das Modul an die Stelle verschoben, an der die Variable oder Prozedur definiert wurde. Wenn Sie Erfahrungen mit VBA gesammelt haben, können Sie Bibliotheken mit VBA-Funktionen und Unterroutinen anlegen. Wenn Sie sich den Aufruf einer bestimmten Unterroutine oder Funktion ansehen, wollen Sie normalerweise den zu Grunde liegenden Code sehen. Glücklicherweise gibt es in VBA einen schnellen und einfachen Weg, von Prozedur zu Prozedur zu wechseln. Nehmen Sie an, in Ihrer Anwendung steht folgender Code: Private sub cmdOkay_Click() Dim iAgeInTen As Integer If IsNull(Me!txtName) Or IsNull(Me!txtAge) Then MsgBox "You must fill in name and age" Exit Sub Else MsgBox "Your Name Is: " & Me!txtName & "_ And your Age Is: " & Nz(Me!txtAge) Call EvaluateAge (Nz(Me!txtAge)) IAgeInTen = AgePlus10(Fix(Val(Me!txtAge))) MsgBox "In 10 Years You Will Be " & iAgeInTen End If End Sub

Wenn Sie schnell in die Prozedur EvaluateAge gelangen wollen, brauchen Sie nur den Cursor an eine beliebige Stelle des Prozedurnamens zu setzen und dann (ª)+(F2) zu drücken. Damit gelangen Sie unmittelbar in die Prozedur. Mit (Strg)+(ª)+(F2) kehren Sie in die Routine zurück, aus der Sie gekommen sind (in diesem Fall cmdOkay_Click). Das funktioniert sowohl bei Funktionen als auch bei Unterroutinen.

295

Werkzeuge für die Arbeit im VBE

Sie können, wenn Sie das lieber mögen, auch mit der rechten Maustaste auf den Namen der Routine klicken, in die Sie springen wollen, und dann DEFINITION wählen. Um in die Ausgangsprozedur zurückzukehren, klicken Sie wiederum mit der rechten Taste und wählen dann LETZTE POSITION.

Wenn sich die Definition in einer Bibliothek befindet, auf die verwiesen wird, wird der Objektkatalog aufgerufen und die Definition angezeigt.

7.12.7

Geheimnisse der Programmierumgebung aufgelöst

Wenn Sie als Entwickler erst mit VBA beginnen, könnte der VBE Sie in Verwirrung stürzen. Sprechen wir zunächst über das Code-Fenster. Es besitzt zwei Kombinationsfelder, wie Sie in Abbildung 7.18 sehen. Im linken Feld werden Objekte aufgelistet. Bei einem Formular oder Bericht sind alle Objekte aufgeführt, bei einem Standardmodul, das keine Objekte besitzt, erscheint nur der Eintrag (ALLGEMEIN).

Abbildung 7.18: Das Code-Fenster mit dem Kombinationsfeld Objekte

Das rechte Kombinationsfeld enthält alle mit einem bestimmten Objekt verknüpften Ereignisprozeduren. Abbildung 7.19 zeigt alle Ereignisprozeduren, die zu einer Schaltfläche gehören. Beachten Sie, dass nur das Click-Ereignis in fetter Schrift erscheint, weil es als einziges mit einer Ereignisprozedur versehen wurde.

296

Kapitel 7: VBA: Eine Einführung

Abbildung 7.19: Das Code-Fenster mit dem Kombinationsfeld Prozedur

7.12.8

Das Projektfenster

Mit Hilfe des Projektfensters, das Sie in Abbildung 7.20 sehen, können Sie leicht zwischen den Modulen wechseln, die den Objekten in Ihrer Datenbank zugrunde liegen. Die Elemente Ihres Projekts werden im Projektfenster hierarchisch in Form eines Baumes dargestellt. Sie sind in Access-Klassen und -Module unterteilt. Sämtliche Formular-, Berichts- und Klassenmodule sind unter KLASSEN UND MODULE zu finden, alle Standardmodule unter MODULE. Um den hinter einem Objekt liegenden Code zu sehen, führen Sie einfach im Projektfenster einen Doppelklick auf das Objekt aus. Um das Objekt selbst zu sehen, z.B. ein Formular, klicken Sie im Projektfenster einmal auf den Namen des Formulars und dann auf das Werkzeug OBJEKT ANSEHEN (das zweite Symbol von links in der Symbolleiste des Projektfensters). Damit kehren Sie zu Microsoft Access zurück und das ausgewählte Objekt ist jetzt aktiv. Sie können auch das Objekt anklicken und dann CODE ANZEIGEN wählen (das linke Symbol in der Symbolleiste des Projektfensters), um den Code einzusehen, oder OBJEKT ANZEIGEN, um das Objekt anzusehen. Das Kontextmenü ermöglicht auch das Einfügen von Modulen und Klassenmodulen, den Im- und Export von Dateien, das Ausdrucken des ausgewählten Objekts und das Einsehen der Datenbankeigenschaften. Diese Merkmale werden in Kapitel 24 abgehandelt.

Werkzeuge für die Arbeit im VBE

297

Abbildung 7.20: Das Projektfenster mit allen Klassen und Modulen, die im Projekt Chap7ex enthalten sind

7.12.9

Das Eigenschaftenfenster

Das in Abbildung 7.21 gezeigte Eigenschaftenfenster ermöglicht das Ansehen und Ändern von Objekteigenschaften im VBE. Oben im Eigenschaftenfenster finden Sie ein Kombinationsfeld, in dem Sie das Objekt auswählen können, dessen Eigenschaften Sie ändern wollen. Dort werden sowohl das im Projektfenster ausgewählte übergeordnete Objekt (z.B. das Formular) als auch die in diesem enthaltenen Objekte (z.B. die Steuerelemente) aufgeführt. Nachdem ein Objekt ausgewählt wurde, lassen sich seine Eigenschaften in der Eigenschaftenliste ändern. Sie können entweder alphabetisch oder nach Kategorien geordnet dargestellt werden. Im Beispiel wurde die Befehlsschaltfläche cmdIfThenElse ausgewählt und die Eigenschaften der Schaltfläche nach Kategorien geordnet angezeigt.

7.12.10 Das Werkzeug Ansicht Microsoft Access Wenn Sie irgendwann in die Access-Anwendungsumgebung zurückkehren möchten, klicken Sie einfach auf das Symbol ANSICHT MICROSOFT ACCESS (das linke Symbol) in der Symbolleiste. Danach können Sie mit Hilfe der Taskleiste oder einer der weiter vorn in diesem Kapitel genannten Methoden in den VBE zurückkehren.

7.12.11

Suchen und ersetzen

Häufig benennen Sie eine Variable nur vorläufig, um später zu entscheiden, dass Sie den Namen ändern wollen. VBA besitzt für diesen Zweck eine hervorragende Funktion zum Suchen und Ersetzen. Sie können einfach nach Daten suchen oder nach

298

Kapitel 7: VBA: Eine Einführung

Abbildung 7.21: Das Eigenschaftenfenster mit den nach Kategorien geordneten Eigenschaften einer Befehlsschaltfläche

einem Wert und ihn durch einen anderen ersetzen. Um das Dialogfeld SUCHEN aufzurufen, das Sie in Abbildung 7.22 sehen, wählen Sie BEARBEITEN|SUCHEN oder drücken (Strg)(F).

Abbildung 7.22: Das Dialogfeld Suchen ist für die Suche nach strMessage im aktuellen Modul vorbereitet

Geben Sie den zu suchenden Text in das Textfeld SUCHEN ein. Beachten Sie, dass Sie in AKTUELLER PROZEDUR, AKTUELLEM MODUL, AKTUELLEM PROJEKT oder MARKIERTEM TEXT suchen können. Die Funktion NUR GANZES WORT SUCHEN findet den Text nicht, wenn er Teil eines Wortes ist. Wenn Sie NUR GANZES WORT SUCHEN aktivieren und dann nach »Zahl« suchen, findet VBA das Wort »Zahlen« nicht. Weitere Optionen betreffen die Groß- und Kleinschreibung sowie den Mustervergleich. Außerdem können Sie das Dialogfeld ERSETZEN benutzen, das über das Menü BEARBEITEN|ERSETZEN oder mit (Strg)(H) (oder mit (ALT)(E), (E)) aufgerufen wird, um einen Text zu suchen und durch einen anderen Text zu ersetzen (siehe Abbildung 7.23). Es bietet alle Merkmale des Dialogfeldes SUCHEN und darüber hinaus die Möglichkeit, einen Text zum Ersetzen einzugeben. Außerdem können Sie

Werkzeuge für die Arbeit im VBE

299

ERSETZEN oder ALLE ERSETZEN wählen. ERSETZEN verlangt bei jedem Vorgang eine Bestätigung, ALLE ERSETZEN jedoch nicht. Ich empfehle Ihnen, sich die Zeit zum Bestätigen der einzelnen Ersetzungen zu nehmen, weil man allzu leicht die durchschlagende Wirkung des globalen Suchens und Ersetzens falsch einschätzt.

Abbildung 7.23: Das Dialogfeld Ersetzen ist für die Suche nach strMessage im aktuellen Projekt und das Ersetzen durch strNewMessage vorbereitet

7.12.12 Die Hilfe Ein sehr sinnvolles, aber wenig bekanntes Merkmal von VBA ist die kontextsensitive Hilfe während der Programmierarbeit. Drücken Sie, während sich der Cursor in einem beliebigen VBA-Befehl oder in einer Funktion befindet, die Taste (F1), um kontextsensitive Hilfe zu diesem Befehl oder dieser Funktion einzublenden. Die meisten Hilfethemen bieten Ihnen praktische Beispiele, die den Befehl oder die Funktion innerhalb einer Routine zeigen. In Abbildung 7.24 sehen Sie die Hilfe für das Konstrukt With...End With. Beachten Sie, dass das Hilfefenster die Syntax für den Befehl, eine detaillierte Beschreibung aller Befehlsparameter sowie Bemerkungen zur Verwendung des Befehls enthält. Am oberen Rand des Fensters finden Sie Hypertext-Verknüpfungen zu verwandten Themen (Siehe auch) sowie eine Verknüpfung zu einem Verwendungsbeispiel. Wenn Sie auf BEISPIEL klicken, erscheint ein spezielles Beispiel für das Konstrukt, das Sie kopieren und in ein Modul einfügen können (siehe Abbildung 7.25). Dieses Merkmal stellt eine hervorragende Methode dar, etwas über die verschiedenen Teile von VBA zu erfahren.

7.12.13 Das Code-Fenster teilen Das VBA-Code-Fenster lässt sich teilen, damit Sie zwei Routinen desselben Moduls gleichzeitig betrachten können. Diese Option ist hilfreich, wenn Sie versuchen, ein Problem zu lösen, das zwei Prozeduren oder Ereignisroutinen in einem umfangreichen Modul betrifft. Ein Beispiel für ein geteiltes Code-Fenster sehen Sie in Abbildung 7.26. Um das Fenster zu teilen, wählen Sie FENSTER|TEILEN. Beachten Sie das Teilungsfeld. Bewegen Sie den Mauszeiger auf die graue Schaltfläche FENSTER TEILEN direkt über dem vertikalen Rollbalken des Code-Fensters. Die Größe der beiden Fenster lässt sich verändern, indem Sie auf das Teilungsfeld klicken und es dann verschieben. Das Fenster lässt sich nur in zwei Hälften teilen.

300

Kapitel 7: VBA: Eine Einführung

Abbildung 7.24: Hilfe zu With...End With

Abbildung 7.25: Ein Beispiel für With....End With

Danach können Sie mit Hilfe der aufklappbaren Listen OBJEKT und PROZEDUR in die Prozedur Ihrer Wahl wechseln. Diese Listen gelten jeweils für den Teil des geteilten Fensters, der zuletzt aktiv war.

301

Werkzeuge für die Arbeit im VBE

Abbildung 7.26: In einem geteilten Code-Fenster können Sie zwei Routinen betrachten

Nur Routinen desselben Moduls lassen sich im selben Code-Fenster betrachten, aber man kann mehrere Code-Fenster gleichzeitig öffnen. Sobald Sie ein Access-, Formular- oder Berichtsmodul öffnen, gelangen Sie in ein anderes Fenster. Jedes Modulfenster lässt sich in der Größe verändern, verschieben und teilen.

7.12.14 Die Arbeitsposition mit Hilfe von Lesezeichen markieren Die Programmierumgebung von Access 2000 lässt das Anlegen von Markierungen – so genannten »Lesezeichen« – zu, damit Sie mühelos an wichtige Stellen in Ihren Modulen zurückkehren können. Um ein Lesezeichen einzufügen, klicken Sie mit der rechten Maustaste in die Code-Zeile, in die Sie das Lesezeichen setzen wollen, und wählen UMSCHALTEN|LESEZEICHEN oder Sie wählen im Menü BEARBEITEN den Eintrag LESEZEICHEN|LESEZEICHEN SETZEN/ZURÜCKSETZEN. Sie können beliebig viele Lesezeichen einfügen. Zwischen den Lesezeichen wechseln Sie mit BEARBEITEN|LESEZEICHEN|NÄCHSTES LESEZEICHEN oder BEARBEITEN|LESEZEICHEN|VORHERIGES LESEZEICHEN. Ein Lesezeichen ist ein Schalter, den Sie mit UMSCHALTEN|LESEZEICHEN im Kontextmenü oder mit LESEZEICHEN|LESEZEICHEN SETZEN/ZURÜCKSETZEN im Menü BEARBEITEN entfernen können. Wenn alle Lesezeichen gelöscht werden sollen, wählen Sie BEARBEITEN|LESEZEICHEN|ALLE LESEZEICHEN LÖSCHEN. Lesezeichen werden beim Schließen der Datenbank nicht gespeichert.

302

Kapitel 7: VBA: Eine Einführung

Verwechseln Sie die hier beschriebenen Lesezeichen nicht mit Lesezeichen in Datensatzgruppen, die in Kapitel 12 behandelt werden.

7.13

Den VBE individuell anpassen

Access 2000 bietet Access-Programmierern weitreichende Möglichkeiten, Aussehen und Verhalten des VBE individuell anzupassen. Mit EXTRAS|OPTIONEN gelangen Sie bei aktiviertem VBE zu den Umgebungsoptionen. Abbildung 7.27 zeigt das Dialogfeld OPTIONEN, dessen verschiedene Aspekte in diesem Abschnitt ausführlich erläutert werden.

Abbildung 7.27: Das Dialogfeld Optionen

7.13.1

Programmieroptionen: Die Registerkarte Editor

Die Programmieroptionen befinden sich auf der Registerkarte EDITOR des Dialogfeldes OPTIONEN. Dazu gehören AUTOMATISCH EINZUG VERGRÖSSERN, TAB-SCHRITTWEITE, AUTOMATISCHE SYNTAXÜBERPRÜFUNG, VARIABLENDEKLARATION ERFORDERLICH, AUTOMATISCHE QUICKINFO, ELEMENTE AUTOMATISCH AUFLISTEN und AUTOMATISCHE DATEN-TIPS. Das Merkmal AUTOMATISCH EINZUG VERGRÖSSERN aktiviert den automatischen Einzug nachfolgender Code-Zeilen, d.h., dass beim Einziehen einer Zeile die nachfolgenden genauso weit eingezogen werden, bis Sie etwas anderes angeben.

Den VBE individuell anpassen

303

Die AUTOMATISCHE SYNTAXÜBERPRÜFUNG legt fest, ob Access bei jeder Betätigung der Taste (¢) nach der Eingabe einer Code-Zeile die Syntax prüft. Viele Entwickler halten diese Option für ein Ärgernis. Es kommt nämlich nicht selten vor, dass man bei der Eingabe einer Code-Zeile einen Tippfehler in einer vorhergehenden Zeile bemerkt. Wenn man dann die angefangene Zeile verlässt, um den Fehler zu korrigieren, bevor man ihn vergessen hat, bekommt man eine Meldung über falsche Syntax. Die Option VARIABLENDEKLARATION ERFORDERLICH ist unverzichtbar. Wenn sie aktiv ist, müssen alle Variablen vor Gebrauch deklariert werden, denn sie fügt die Zeile Option Explicit in den Abschnitt DEKLARATIONEN aller Module ein. Damit werden Sie gezwungen, Variablen zu deklarieren. Dadurch werden viele harmlose Tippfehler schon vom Compiler und nicht erst zur Laufzeit von den Benutzern entdeckt. Mit der Option ELEMENTE AUTOMATISCH AUFLISTEN legen Sie fest, ob die Merkmale EIGENSCHAFTEN/METHODEN ANZEIGEN und KONSTANTEN ANZEIGEN bei der Eingabe von Code im Code-Fenster automatisch aufgerufen werden, welche Ihnen durch Bereitstellen einer gültigen Liste von Eigenschaften, Methoden und Konstanten bei der Programmierarbeit helfen. Weitere Informationen dazu finden Sie in Kapitel 8. Die Option AUTOMATISCHE QUICKINFO bestimmt, ob die Syntax einer Prozedur oder Methode automatisch angezeigt wird. Wenn sie aktiv ist, werden die entsprechenden Informationen eingeblendet, sobald Sie einen Prozedur- oder Methodennamen eingeben, auf den ein Leerzeichen, ein Punkt oder eine öffnende Klammer folgt. Das Merkmal AUTOMATISCHE DATEN-TIPS zeigt beim Testen den aktuellen Wert eines ausgewählten Wertes an, wenn Sie im Unterbrechungsmodus den Mauszeiger auf die Variable setzen. Diese Funktion wird in Kapitel 13 näher erläutert.

7.13.2

Farbe, Schriftarten und -größe des Programm-Codes: Die Registerkarte Editor-Format

In Access 2000 lassen sich Farbe, Schriftart und -größe des Programm-Codes innerhalb der Programmierumgebung anpassen. Außerdem können Sie Vorder- und Hintergrundfarbe für Text im Code-Fenster, ausgewählten Text, Syntaxfehlermeldungen, Kommentare, Schlüsselwörter usw. angeben. Der Text im Code-Fenster lässt sich in einer beliebigen Windows-Schriftart in beliebiger Größe darstellen, aber damit er besser lesbar ist, sollten Sie die Schriftart FixedSys wählen.

7.13.3

Allgemeine Optionen: Die Registerkarte Allgemein

Die Registerkarte ALLGEMEIN fasst verschiedene Optionen zusammen, die das Verhalten der Entwicklungsumgebung beeinflussen. Die Option RASTER ANZEIGEN legt beispielsweise fest, ob ein Raster für Formulare angezeigt wird; die RASTEREINHEITEN

304

Kapitel 7: VBA: Eine Einführung

bestimmen den Abstand der Rasterlinien. Die weiteren Optionen auf dieser Registerkarte finden Sie in Kapitel 24.

7.13.4

Verankerungsoptionen: Die Registerkarte Verankern

Auf dieser Registerkarte können Sie angeben, ob sich die Fenster innerhalb des VBE koppeln lassen, d.h. ob sich ein Fenster an einer Seite eines anderen andockbaren Fensters »befestigen« lässt. Wenn das Fenster an eine beliebige Stelle verschoben und dort abgelegt werden kann, ist es nicht koppelbar. Folgende Fenster lassen sich koppeln: das Direktfenster, das Überwachungsfenster, das Projektfenster, das Eigenschaftenfenster und der Objektkatalog. Alle hier genannten Anpassungsoptionen gelten für die gesamte Access-Umgebung, d.h. sie beeinflussen alle Datenbanken.

7.13.5

Für die Praxis

Erforderliche Ereignisroutinen, benutzerdefinierte Funktionen, und Unterroutinen für das Zeit- und Abrechnungssystem In diesem Beispiel, das Sie in der Beispieldatenbank CHAP7.MDB finden, werden ein Formular, eine Abfrage und ein Bericht verwendet, um Kriterien zu ermitteln und dann über den Client eine Vorschau über Absatzinformationen für einen bestimmten Datumsbereich zu geben. Der Bericht rptClientInformationByProject basiert auf einer Abfrage namens qryBillingDetailByClient, welche Informationen aus einem Formular mit dem Titel frmPrintClientBilling benötigt. Dieses Formular, das Sie in Abbildung 7.28 sehen, muss geöffnet sein, damit der Vorgang erfolgreich ausgeführt wird, weil die Kriterien für die Abfrage von dort geholt werden. Der Code für die beiden Befehlsschaltflächen, der im Formular frmPrintClientBilling steht, sieht folgendermaßen aus: Sub cmdRunReport_Click() If IsNull(Me.txtStartDate) Or _ IsNull(Me.txtEndDate) Then MsgBox "Both the Start Date and End Date Must Be Filled In" Else Call RunReport("rptClientInformationByProject") End If End Sub

Den VBE individuell anpassen

305

Sub cmdClose_Click() DoCmd.Close End Sub

Abbildung 7.28: Das Formular Berichtskriterien, das die notwendigen Informationen für die dem Bericht über Abrechnungsdetails zu Grunde liegende Abfrage anfordert

Die erste Routine wertet die beiden Textfelder aus, um sicherzustellen, dass sie ausgefüllt sind. Wenn eines davon den Wert Null enthält, wird eine Meldung angezeigt, während sonst die benutzerdefinierte Routine RunReport ausgeführt wird. Die zweite Routine schließt lediglich das Formular. Die Unterroutine RunReport ist Teil eines Moduls mit dem Namen basUtils und sieht folgendermaßen aus: Sub RunReport(strReportName As String) DoCmd.OpenReport strReportName, acPreview End Sub

Die Routine übernimmt den Namen eines Berichts als Parameter und führt diesen Bericht aus. Der übrige Code, der im Bericht rptClientInfomationByClient zu finden ist, gehört zum Ereignis Open des Berichts und lautet folgendermaßen: Private Sub Report_Open(Cancel As Integer) If Not IsLoaded("frmPrintClientBilling") Then MsgBox "Print Client Billing Form Must Be Open to Run This Report", _ vbCritical, "Error!!" Cancel = True End If End Sub

306

Kapitel 7: VBA: Eine Einführung

Diese Routine ruft die benutzerdefinierte Funktion IsLoaded auf. Falls diese den Wert False zurückgibt, was bedeutet, dass das geforderte Kriterienformular nicht geöffnet ist, wird eine Meldung ausgegeben und der Bericht abgebrochen. Die Funktion IsLoaded im Modul basUtils sieht wie folgt aus: Function IsLoaded(ByVal strFormName As String) As Integer Const CLOSED = 0 Const DESIGN = 0 If SysCmd(acSysCmdGetObjectState, acForm, strFormName) CLOSED Then If Forms(strFormName).CurrentView DESIGN Then IsLoaded = True End If End If End Function

Diese Funktion ermittelt mit Hilfe der integrierten Funktion SysCmd, ob ein Formular geladen wurde. Nachdem ihr das Argument acSysCmdGetObjectState (Typ und Name des Objekts, dessen Status ausgewertet werden soll) übergeben wurde, gibt sie True oder False zurück. Dieser Wert wird mit einer benutzerdefinierten Konstanten namens CLOSED verglichen, die gleich 0 bzw. False ist. Wenn das Formular nicht geschlossen ist, wird mit Hilfe der Eigenschaft CurrentView des Formulars geprüft, ob es in der Entwurfsansicht geöffnet wurde. Wenn dies nicht zutrifft, muss es in der Formular- oder Datenblattansicht geöffnet sein und die Funktion gibt True zurück. Wenn der angegebene Datumsbereich keine Zeilen zurückgibt, erscheint im Bericht die Meldung #Error, die sich mit Hilfe des Ereignisses NoDate eines Berichts korrigieren lässt. Dieses Ereignis wird in Kapitel 10 erläutert.

Objekte, Eigenschaften, Methoden und Ereignisse

Kapitel

Hier lesen Sie:

 Das Objektmodell von Access  Objekte, Eigenschaften, Ereignisse und Methoden  Access-Objekte mit Hilfe des Objektkatalogs kennen lernen  Eigenschaften und Methoden leicht gemacht  Objektvariablen deklarieren und zuweisen  Unterschiede zwischen Objekten und Auflistungen  Den Typ eines Steuerelements bestimmen  Spezielle Eigenschaften mit Objektbezug

8.1

Das Objektmodell von Access

Objekte sind die Bestandteile einer Datenbank. Sie umfassen Tabellen, Abfragen, Formulare, Berichte, Datenzugriffsseiten, Makros und Module, die im Datenbankfenster erscheinen. Auch die Steuerelemente (Eingabefelder, Listenfelder usw.) eines Formulars oder Berichts sind Objekte. Der Schlüssel für eine erfolgreiche Programmierung liegt in Ihrer Fähigkeit, Datenbankobjekte mit Hilfe von VBA-Code während der Ausführung zu manipulieren. Außerdem ist es sehr nützlich, wenn Sie in der Lage sind, Anwendungsobjekte während der Ausführung hinzuzufügen, zu verändern oder zu entfernen. Die Beispiele dieses Kapitels finden Sie in der Datenbank Chap8Ex auf der beiliegenden CD-ROM.

308

8.1.1

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Das Application-Objekt

Die Access-Hilfe gibt einen Überblick über den Aufbau des Objektmodells von Access. An der Spitze dieses Modells befindet sich das Application-Objekt, welches sich auf die aktive Access-Anwendung bezieht. Es enthält alle weiteren AccessObjekte und -Auflistungen, einschließlich der Auflistungen Forms, Reports, DataAccessPages und Modules sowie der Objekte CurrentData, CurrentProject, CodeProject, CodeData, Screen und DoCmd. Mit dem Application-Objekt können Sie die Eigenschaften eines Befehls verändern oder Access-Befehle selbst ausführen. So können Sie zum Beispiel festlegen, ob die integrierten Menüleisten von Access während der Ausführung der Anwendung zur Verfügung stehen sollen oder nicht. Das Objektmodell finden Sie in der Hilfe von Access 2000 unter dem Thema INFORMATIONEN ZUR PROGRAMMIERUNG/MS ACCESS VISUAL BASICSPRACHVERZEICHNIS.

8.1.2

Die Forms-Auflistung

Die Forms-Auflistung enthält alle zur Zeit geöffneten Formulare der Datenbank. Mit ihrer Hilfe können Sie eine Aktion wie zum Beispiel das Verändern der Farbe für jedes geöffnete Formular durchführen. Die Forms-Auflistung ist nicht das gleiche wie die Liste aller Formulare einer Datenbank. Diese Liste ist Bestandteil des Objekts CurrentProject, welches später in diesem Kapitel erklärt wird. Der folgende Code durchsucht die Forms-Auflistung und gibt den Namen jedes Formulars aus. Er ist im Modul basApplicationObject in der Datenbank Chap8Ex zu finden. Zu Beginn wird eine Variable für das Formularobjekt eingerichtet. Anschließend wird mit dem Konstrukt For Each ... Next jedes Formular der Forms-Auflistung herausgesucht (der Auflistung der geöffneten Formulare) und dessen Name ausgegeben. Öffnen Sie ein neues Formular, bevor Sie den Code ausführen. Führen Sie anschließend den Code aus und werfen Sie einen Blick in das DIREKTFENSTER. Schließen Sie einen Teil der Formulare und führen Sie den Code erneut aus. Die im DIREKTFENSTER angezeigte Liste der Formulare sollte jetzt anders aussehen. Das DIREKTFENSTER und dessen Verwendung werden in Kapitel 13 behandelt.

Das Objektmodell von Access

309

Sub IterateOpenForms() Dim frm As Form For Each frm in Forms Debug.Print frm.Name Next frm End Sub

Beachten Sie, dass Sie sich nicht auf Application.Forms beziehen müssen. Wenn Sie VBA-Code für Access schreiben, wird immer das Application-Objekt vorausgesetzt.

8.1.3

Die Reports-Auflistung

Wie die Forms-Auflistung alle gerade geöffneten Formulare enthält, so enthält die Reports-Auflistung dementsprechend alle zur Zeit geöffneten Berichte. Mit Hilfe der Reports-Auflistung können Sie mit jedem geöffneten Bericht eine Aktion durchführen. Der folgende Code durchsucht die Reports-Auflistung und gibt den Namen jedes Berichts an. Er ist im Modul basApplicationObject zu finden. Zu Beginn wird eine Variable für das Berichtsobjekt eingerichtet. Anschließend wird mit Hilfe des Konstrukts For Each ... Next jeder Bericht der Reports-Auflistung herausgesucht (der Auflistung der geöffneten Berichte) und dessen Name ausgegeben. Sub IterateOpenReports() Dim rpt As Report For Each rpt in Reports Debug.Print rpt.Name Next rpt End Sub

8.1.4

Die DataAccessPages-Auflistung

So wie die Forms-Auflistung alle gerade geöffneten Formulare und die Reports-Auflistung alle zurzeit geöffneten Berichte enthält, umfasst die DataAccessPages-Auflistung alle aktuell geöffneten Datenzugriffsseiten. Mit Hilfe der DataAccessPages-Auflistung können Sie eine Aktion mit jeder geöffneten Datenzugriffsseite durchführen.

8.1.5

Die Modules-Auflistung

Die Modules-Auflistung enthält alle geöffneten Standard- und Klassenmodule, wobei es keine Rolle spielt, ob sie kompiliert wurden oder Code enthalten, der gerade ausgeführt wird.

310

8.1.6

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Das CurrentProject-Objekt

Das CurrentProject-Objekt gibt einen Verweis auf das aktuelle Projekt zurück. Es enthält Eigenschaften wie Name, Path und Connection und umfasst die folgenden Auflistungen: AllDataAccessPages, AllForms, AllMacros, AllModules und AllReports. Mit diesen Auflistungen können alle in der Datenbank gespeicherten Datenzugriffsseiten, Formulare, Makros, Module und Berichte ermittelt werden. Sie unterscheiden sich von den Auflistungen DataAccessPage, Forms, Macros, Modules und Reports insofern, als sie sich auf alle Objekte des aktuellen Projekts beziehen und nicht nur auf die gerade geöffneten. Der folgende Code sucht die Eigenschaften Name und Path des aktuellen Projekts heraus. Er verwendet das Konstrukt With ... End With, um die Eigenschaften des Objekts CurrentProject zu ermitteln. Sub CurrentProjectObject() With CurrentProject Debug.Print .Name Debug.Print .Path End With End Sub

Wie bereits erwähnt wurde, enthält das CurrentProject-Objekt Auflistungen, die sich auf verschiedene Objekte Ihrer Datenbank beziehen. Der folgende Code durchsucht die AllForms-Auflistung von CurrentProject und gibt den Namen jedes Formulars aus. SubIterateAllForms() Dim vnt As Variant With CurrentProject For Each vnt In .AllForms Debug.Print vnt.Name Next vnt End With End Sub

Die AllForms-Auflistung des CurrentProject-Objekts kann leicht mit der FormsAuflistung verwechselt werden. Die AllForms-Auflistung des CurrentProjectObjekts umfasst alle gespeicherten Formulare, die Bestandteil der Datenbank sind. Die Forms-Auflistung enthält hingegen nur die Formulare, die zurzeit im Arbeitsspeicher ausgeführt werden. Möchten Sie eine Liste aller Formulare einer Datenbank anzeigen lassen, müssen Sie die AllForms-Auflistung des CurrentProject-Objekts benutzen. Möchten Sie hingegen die Überschrift aller geöffneten Formulare ändern, dann müssen Sie die FormsAuflistung verwenden.

Das Objektmodell von Access

8.1.7

311

Das CurrentData-Objekt

Während Sie mit dem CurrentProject-Objekt auf die Anwendungskomponenten in Ihrer Datenbank zugreifen und diese verändern können, dient das CurrentDataObjekt zum Verweis auf die Datenelemente der Datenbank. Das CurrentData-Objekt enthält fünf Auflistungen: AllDatabaseDiagramms, AllQueries, AllStoredProcedures, AllTables und AllViews. Mit Hilfe dieser Auflistungen werden alle Diagramme, Abfragen, gespeicherten Prozeduren und Ansichten der Datenbank herausgesucht und verändert. Der folgende Code durchsucht die Auflistung AllTables des CurrentData-Objekts und gibt den Namen jeder Tabelle der Datenbank aus. SubIterateAllTables() Dim vnt As Variant With CurrentData For Each vnt In .AllTables Debug.Print vnt.Name Next vnt End With End Sub

8.1.8

Das CodeProject-Objekt

Das CodeProject-Objekt wird verwendet, wenn die Datenbank Code-Bibliotheken einrichtet. Es ist mit dem Objekt CurrentProject vergleichbar, verweist jedoch auf die in der Bibliotheksdatenbank gespeicherten Eigenschaften und Auflistungen. Bibliotheksdatenbanken werden in Kapitel 29 behandelt.

8.1.9

Das CodeData-Objekt

Während das CodeProject-Objekt auf die in der Bibliotheksdatenbank gespeicherten Anwendungsobjekte verweist, dient das CodeData-Objekt zum Verweis auf die Datenelemente einer Code-Bibliothek. Hierzu gehören die Diagramme, Abfragen, gespeicherten Prozeduren, Tabellen und Ansichten der Datenbank, die innerhalb der Bibliotheken gespeichert sind.

8.1.10

Das Screen-Objekt

Mit Hilfe des Screen-Objekts können Sie sich auf das Formular, das Datenblatt, die Datenzugriffsseite oder das Steuerelement beziehen, welches den Fokus hat. Das Screen-Objekt umfasst Eigenschaften, die sich auf das aktive Formular, den aktiven Bericht, das aktive oder das vorherige Steuerelement beziehen. Über diese Eigenschaften können Sie sowohl das gerade aktive Formular, den Bericht oder das Steuerelement auch das vor dem aktuellen Steuerelement aktive Steuerelement bearbeiten.

312

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Falls Sie versuchen, sich auf das Screen-Objekt zu beziehen, wenn kein Formular oder Bericht aktiv ist, führt dies zu einem Laufzeitfehler.

8.1.11

Das DoCmd-Objekt

Das DoCmd-Objekt dient der Ausführung von Makrobefehlen oder Access-Aktionen aus VBA-Codes heraus. Der Name der Methode wird nach einem Punkt angegeben. Die meisten Methoden (z.B. die Methode OpenQuery) benötigen weitere Argumente. Mit der OpenQuery-Methode werden Access-Abfragen ausgeführt. Dabei werden folgende Argumente übergeben:

 Abfragename – Der Name der auszuführenden Abfrage  Ansicht – Datenblatt, Entwurf oder Vorschau  Datenmodus – Hinzufügen, Bearbeitung oder Schreibgeschützt Es folgt ein Beispiel für die Methode OpenQuery des DoCmd-Objekts: DoCmd.OpenQuery "qryCustomers", acNormal, acReadOnly

Die Methode OpenQuery wird vom DoCmd-Objekt ausgeführt. Das erste Argument (der Abfragename) lautet "qryCustomer". Dies ist der Name der als Datenblattansicht (und nicht als Entwurf oder Vorschau) geöffneten Abfrage. Die Abfrage wird im schreibgeschützten Modus geöffnet, was bedeutet, dass die angezeigten Daten nicht verändert werden können.

8.2

Objekte, Eigenschaften, Ereignisse und Methoden

Vielen Benutzern ist das Konzept der Objekte, Eigenschaften und Ereignisse unverständlich, insbesondere dann, wenn sie bisher mit einer Sprache gearbeitet haben, die auf Prozeduren basiert. Wenn Sie ein produktiver und erfolgreicher Access-Programmierer werden wollen, müssen Sie die Access-Objekte, die Eigenschaften und die Ereignisse, auf die jedes Objekt reagieren kann, genau kennen.

8.2.1

Was genau sind Objekte?

Wie bereits in diesem Kapitel erwähnt wurde, gehören alle Bestandteile Ihrer Datenbank zu den »Objekten«. Sie umfassen die Tabellen, Abfragen, Formulare, Berichte, Datenzugriffsseiten, Makros und Module sowie die Komponenten dieser Objekte. Ein Tabellenobjekt enthält zum Beispiel Feld- und Indexobjekte, während ein Formular verschiedene Steuerelemente umfasst (Textfelder, Kombinationsfelder, Listenfelder usw.). Jedes Objekt einer Datenbank besitzt bestimmte Eigenschaften, die

Objekte, Eigenschaften, Ereignisse und Methoden

313

seine Erscheinung und sein Verhalten bestimmen. Jedes Objekt verfügt außerdem über spezielle Methoden, wobei es sich um die Aktionen handelt, die mit ihm durchgeführt werden können.

8.2.2

Was genau sind Eigenschaften?

Eine »Eigenschaft« ist ein Attribut eines Objekts. Jedes Objekt verfügt über mehrere Eigenschaften. Häufig teilen unterschiedliche Objektarten die gleichen Eigenschaften. In anderen Fällen beziehen sich die Objekteigenschaften auf ein spezielles Objekt. Formulare, Kombinationsfelder und Textfelder besitzen beispielsweise alle die Eigenschaft Width. Ein Formular weist außerdem die Eigenschaft RecordSource auf, über die Kombinations- und Textfelder nicht verfügen. Die meisten Eigenschaften können während des Entwurfs festgelegt und bei der Ausführung verändert werden. Bei einigen ist dies jedoch nicht möglich und auf andere kann nicht während des Entwurfs zugegriffen werden (ihre Änderung ist ausschließlich bei der Ausführung möglich). Die integrierte Hilfe von Access liefert zu jeder Eigenschaft folgende Hinweise:

 Sie können die Eigenschaft über Eigenschaftenfenster, Makros oder Visual Basic setzen.

 Sie können die Eigenschaft nur in der Entwurfsansicht setzen.  Sie können über Visual Basic oder ein Makro auf diese Eigenschaft zugreifen. Jede dieser Beschreibungen gibt an, wann eine Eigenschaft verändert werden kann. Als Entwickler legen Sie die Werte vieler Objekteigenschaften während des Entwurfs fest. Dies sind die so genannten Starteigenschaften für die Ausführung. Weite Teile des VBA-Codes verändern diese Werte während der Ausführung, wenn auf unterschiedliche Situationen reagiert wird. Ein Textfeld besitzt zum Beispiel die Eigenschaft Visible. Bezahlt eine Kunde bar, möchten Sie möglicherweise das Textfeld mit der Kreditkartennummer gar nicht anzeigen lassen. Bezahlt er per Kreditkarte, dann können Sie der Eigenschaft Visible des Textfelds für die Kreditkarte den Wert True zuweisen. Dies ist nur eine von vielen Möglichkeiten, wie Sie die Eigenschaften eines Objekts während der Ausführung verändern können, um auf ein eingetretenes Ereignis oder eine durchgeführte Aktion zu reagieren. Sie werden sich fragen, wie Sie alle mit einem bestimmten Objekt verbundenen Eigenschaften setzen können (sowohl die, die während des Entwurfs festgelegt werden können, als auch diejenigen, die während der Ausführung verändert werden). Sie können sich selbstverständlich die Eigenschaften, die während des Entwurfs festgelegt werden, anzeigen lassen, wenn Sie das Objekt markieren. Alle Eigenschaften eines Objekts können Sie sich einfach durch Drücken der Taste (F1) für die Hilfe anzeigen lassen. Klicken Sie auf die Registerkarte INDEX und geben Sie den Namen des Objekts ein, dessen Eigenschaften Sie anzeigen lassen möchten. In Abbildung 8.1 wurde im Textfeld das Wort Combo eingegeben. Klicken Sie dann auf die Schaltflä-

314

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

che SUCHEN. Beachten Sie am Ende der Liste den Eintrag für die Eigenschaften des Kombinationsfelds. Wenn Sie auf diesen Eintrag klicken, werden Ihnen in der rechten Hälfte des Fensters Informationen zu den Eigenschaften des Kombinationsfelds angezeigt (siehe Abbildung 8.2). Möchten Sie mehr über eine bestimmte Eigenschaft erfahren, dann klicken Sie diese einfach an. In Abbildung 8.3 wurde die Eigenschaft Column gewählt. Sie können auch den Objektkatalog verwenden, um sich alle Eigenschaften eines Objekts schnell und einfach anzeigen zu lassen.

Abbildung 8.1: Das Dialogfeld der Hilfe

8.2.3

Was genau sind Ereignisse?

Das Betriebssystem Windows wird über Ereignisse gesteuert, was bedeutet, dass das Betriebssystem auf viele Ereignisse reagiert, die durch Benutzeraktionen und das Betriebssystem selbst ausgelöst werden. Access legt durch sein Objektmodell viele dieser Ereignisse offen. Ein »Ereignis« einer Access-Anwendung ist etwas, worauf Ihre Anwendung reagieren kann. Zu den Ereignissen zählen Mausbewegungen, Veränderungen der Daten, das Öffnen eines Formulars, das Hinzufügen eines Datensatzes und vieles andere mehr. Benutzer können genau wie Anwendungen Ereignisse auslösen. Sie müssen festlegen, was als Antwort auf die Ereignisse geschehen soll. Sie können mit Hilfe von Makros oder mit VBA-Code auf die Ereignisse reagieren. Jedes Access-Objekt reagiert auf unterschiedliche Ereignisse. Führen Sie die folgenden Schritte durch, um alle mit einem bestimmten Objekt verknüpften Ereignisse anzeigen zu lassen: 1. Wählen Sie das Objekt aus (z.B. ein Textfeld). 2. Öffnen Sie das Fenster EIGENSCHAFTEN.

315

Objekte, Eigenschaften, Ereignisse und Methoden

Abbildung 8.2: Eine Liste der Eigenschaften des Kombinationsfeldes

Abbildung 8.3: Die Hilfe zu der Column-Eigenschaft eines Kombinationsfeldes

3. Klicken Sie auf die Registerkarte EREIGNIS (siehe Abbildung 8.4). 4. Durchsuchen Sie die Liste der verfügbaren Ereignisse.

316

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Abbildung 8.4: Die Liste der mit einem Textfeld verknüpften Ereignisse

8.2.4

Was genau sind Methoden?

»Methoden« sind Aktionen, die Sie für Objekte aus Ihrer Datenbank durchführen können. Die unterschiedlichen Objekte verfügen nicht nur über Eigenschaften und Ereignisse, sondern ihnen sind auch verschiedene Methoden zugeordnet. Eine Methode ist mit einer Funktion oder Subroutine vergleichbar, mit dem Unterschied, dass sich die Methode nur auf ein bestimmtes Objekt bezieht. Wenn Sie in der Online-Hilfe nach dem Schlüsselwort Methode suchen, dann finden Sie im Listenfeld THEMA AUSWÄHLEN einen Themenliste (siehe Abbildung 8.6). Falls Sie aus der Themenliste den Begriff Verzeichnis der Methoden auswählen, erscheint die zugehörige Hilfeseite. Die Methoden sind nach den Objekten gegliedert. Wird ein bestimmtes Objekt markiert, erhalten Sie Hilfe zu diesem speziellen Objekt. Sie können anschließend auf METHODEN klicken, um das Dialogfeld THEMEN GEFUNDEN mit einer Liste der Methoden dieses Objekts zu öffnen (siehe Abbildung 8.7). Wenn Sie bei einer Methodenbeschreibung auf die Verknüpfung BETRIFFT klicken, erhalten Sie eine Liste aller Objekte, auf die die gewählte Methode anwendbar ist. Klicken Sie auf den Eintrag BEISPIEL, wird Ihnen ein Beispiel mit Code für die Implementierung der gewählten Methode angezeigt.

8.3

Access-Objekte mit Hilfe des Objektkatalogs kennen lernen

Der Objektkatalog ist ein leistungsfähiges Werkzeug, mit dessen Hilfe Sie etwas über die Objekte und ihren Einsatz lernen können, die Bestandteil von Access 2000 und Microsoft Windows sind. Der Objektkatalog zeigt Informationen zu Microsoft Access-Objekten und zu anderen Objekten an. Er hilft Ihnen beim Programmieren und führt alle Eigenschaften sowie die damit verbundenen Methoden eines bestimmten Objekts auf.

317

Access-Objekte mit Hilfe des Objektkatalogs kennen lernen

Abbildung 8.5: Wie Sie Hilfe zu den Methoden erhalten

Abbildung 8.6: Der VerzeichnisEintrag der Methoden bietet Hilfen zu allen neuen Methoden und Auflistungen

Access-Objekte sind sehr komplex. Sie verfügen über viele Eigenschaften und Methoden. Der Objektkatalog erleichtert Ihnen das Verständnis der Objekte, Eigenschaften und Methoden. Er unterstützt Sie bei der Verwendung dieser Elemente, indem er Folgendes macht:

318

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Abbildung 8.7: Das Dialogfeld Themen gefunden zeigt alle mit dem Formularobjekt verknüpften Methoden an

 die verfügbaren Objekttypen anzeigen  Ihnen ein schnelles Wechseln zwischen den Prozeduren der Anwendungen erlauben

 die mit einem bestimmten Objekt verknüpften Eigenschaften und Methoden anzeigen

 Code finden und in Ihre Anwendung einfügen

8.3.1

Den Objektkatalog verwenden

Der Objektkatalog kann einfach aus dem Editor von Visual Basic aufgerufen werden. Sie können auf die Schaltfläche OBJEKTKATALOG in der Symbolleiste klicken, die Taste (F2) drücken oder die Menüoption ANSICHT|OBJEKTKATALOG wählen. Abbildung 8.8 zeigt des Dialogfeld des Objektkatalogs Der Objektkatalog zeigt zwei Informationsebenen der gewählten Bibliothek oder Datenbank an. Wenn Sie die Datenbank Chap8Ex geöffnet haben und im aufklappbaren Listenfeld PROJEKT/BIBLIOTHEK den Eintrag Chap8Ex.MDB wählen, sieht Ihr Bildschirm ähnlich wie in Abbildung 8.8 aus. Das Listenfeld KLASSEN zeigt alle Module einschließlich der Formular- und Berichtsmodule an, während im Listenfeld ELEMENT VON alle im gewählten Modul definierten Prozeduren erscheinen. Beachten Sie das Modul basUtils, welches Bestandteil der Datenbank Chap8Ex.MDB ist. Wenn Sie in das Listenfeld auf der rechten Seite schauen, können Sie die Funktionen des

Access-Objekte mit Hilfe des Objektkatalogs kennen lernen

319

Abbildung 8.8: Das Dialogfeld des Objektkatalogs mit einem ausgewählten Datenbankobjekt

Moduls basUtils sehen. Sie können jedes Formular- und Berichtsmodul in dem Listenfeld auf der linken Seite markieren und so alle damit verbundenen Methoden und Eigenschaften im Listenfeld auf der rechten Seite anzeigen lassen. Sie können im Listenfeld PROJEKT/BIBLIOTHEK eine andere Objektbibliothek wählen (sofern auf eine solche verwiesen wird). Das Listenfeld KLASSEN zeigt die für die gewählte Bibliothek oder Datenbank definierten Methoden, Eigenschaften und Datenelemente an (siehe Abbildung 8.9). Im Kombinationsfeld BIBLIOTHEK wurde der Eintrag Access ausgewählt, so dass das Listenfeld auf der linken Seite alle Klassen von Access 2000 anzeigt. Das Listenfeld auf der rechten Seite zeigt alle Elemente des gewählten Objekts, bei dem es sich in diesem Fall um das Application-Objekt handelt. Wenn Sie sich im aufklappbaren Listenfeld BIBLIOTHEK auf andere Bibliothekstypen beziehen, können Sie auch weitere Bibliotheken hinzufügen. Diese Möglichkeit wird in Kapitel 26 behandelt.

8.3.2

Code-Vorlagen in eine Prozedur einfügen

Haben Sie die gewünschte Methode oder Eigenschaft gefunden, besteht die Möglichkeit, diese in Ihre Anwendung einzufügen. Heben Sie die Markierung der Methode oder Eigenschaft nicht auf und klicken Sie im Objektkatalog einfach auf die Schaltfläche IN ZWISCHENABLAGE KOPIEREN. Anschließend fügen Sie diese in das entsprechende Modul ein. Benötigen Sie weitere Informationen zu einer bestimmten Methode oder zu einer Eigenschaft, klicken Sie im Objektkatalog auf die Schaltfläche HILFE oder drücken die Taste (F1).

320

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Abbildung 8.9: Im Objektkatalog die Access-2000-Bibliothek auswählen

8.4

Sich auf Objekte beziehen

Access-Objekte sind in »Auflistungen« unterteilt, bei denen es sich um Gruppen von Objekten gleichen Typs handelt. Die Forms-Auflistung ist beispielsweise eine Sammlung aller geöffneten Formulare einer Datenbank. Jedes Formular verfügt über eine Auflistung Controls, die alle Steuerelemente dieses Formulars enthält. Jedes Steuerelement ist ein Objekt, auf welches Sie sich über die Auflistung beziehen müssen, zu der es gehört. Auf ein Formular beziehen Sie sich zum Beispiel über die Forms-Auflistung. VBA bietet Ihnen drei Möglichkeiten, sich auf ein Objekt zu beziehen. Möchten Sie sich beispielsweise auf das Formular frmProjects beziehen, können Sie unter den drei folgenden Varianten wählen:

 Forms!frmProjects  Forms("frmProjects")  Forms(0) Falls Sie die Variante Forms(0) wählen, muss es sich bei frmProjects um das erste geöffnete Formular handeln. Sie müssen dabei allerdings berücksichtigen, dass zwar jedem geladenen Formular eine Elementnummer zugewiesen wird, diese sich jedoch verändern kann, wenn während der Ausführung weitere Formulare geladen oder entladen werden. Das dritte geladene Formular kann zum Beispiel ursprünglich als Element Zwei bezeichnet worden sein. Wird das zweite Formular entladen, erhält das dritte die Nummer Eins. Sie können sich also nicht auf eine dem Formular zugewiesene Elementnummer verlassen, da diese Nummern sich verändern.

Eigenschaften und Methoden leicht gemacht

321

Sie müssen sich auf ein Steuerelement eines Formulars zuerst über die Forms-Auflistung und dann über das spezielle Formular beziehen. Der Verweis sieht wie folgt aus: Forms!frmProjects.txtClientsID

In diesem Beispiel gibt Forms den Namen der Auflistung, frmProjects den Namen des speziellen Formulars und txtClientsID den Namen eines Steuerelements des Formulars frmProjects an. Dieser Code ist in dem Code-Modul von frmProjects zu finden. Er könnte ungefähr so aussehen: Me.txtClientID

ME bezieht sich auf das derzeitige Formular oder den aktuellen Bericht. Dies ist ein

sehr allgemeiner Ansatz, da der Code in jedes Formular kopiert werden kann, welches über ein txtClientID-Steuerelement verfügt. Er würde auch dann korrekt ausgeführt. Der Verweis auf ein Steuerelement eines Berichts ist dem Verweis auf ein Steuerelement eines Formulars sehr ähnlich. Ein Beispiel: Reports!rptTimeSheet.txtHoursBilled

Dieses Beispiel bezieht sich auf das Textfeld txtHoursBilled des Berichts rptTimeSheeet, der Bestandteil der Reports-Auflistung ist. Wenn Sie wissen, wie Sie sich auf ein Objekt beziehen müssen, dann können Sie Code verfassen, der die Eigenschaften verändert und die Methoden ausführt.

8.5

Eigenschaften und Methoden leicht gemacht

Um die Eigenschaften eines Objekts zu verändern und dessen Methoden auszuführen, müssen Sie sich auf das Objekt beziehen und anschließend die entsprechende Eigenschaft oder Methode angeben. Zum Beispiel: Forms!frmHello.cmdHello.Visible = False

Diese Code-Zeile bezieht sich auf die Eigenschaft Visible des Steuerelements cmdHello, das sich im Formular frmHello der Forms-Auflistung befindet. Beachten Sie, dass Sie den Objektnamen frmHello als der Forms-Auflistung zugehörig erkennen müssen. Möchten Sie die Caption-Eigenschaft von frmHello dahingehend ändern, dass die Überschrift »Hello World« lautet, dann müssen Sie den folgenden Code verwenden: Forms!frmHello.Caption = "Hello World"

322

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Manchmal ist es nicht einfach festzustellen, ob es sich um eine Eigenschaft oder eine Methode eines Objekts handelt. Es gibt aber eine Reihe einfacher Möglichkeiten, dies zu ermitteln. Eine Eigenschaft wird immer in einer Art Ausdruck verwendet. Sie können eine Eigenschaft beispielsweise irgendeinem Wert gleichsetzen: Forms!frmClients.txtAdress.Visible = False In diesem Fall stellen Sie den Wert der Eigenschaft Visible des Textfelds txtAdress aus dem Formular frmClients vom Wert True auf False um. Sie können den Wert einer Eigenschaft auch suchen und einer Variablen zuweisen: strFirstName = Forms!frmClients.txtFirstName.Value Außerdem können Sie den Wert einer Eigenschaft auch in einem Ausdruck verwenden: MsgBox Form!frmClients.txtFirstName,Value Der Grundgedanke hierbei ist, dass eine Eigenschaft immer irgendwo in einem Ausdruck verwendet wird. Sie kann mit etwas gleichgesetzt werden, als Wert für etwas anderes fungieren oder in einer anderen Form in einem Ausdruck zum Einsatz kommen. Eine Methode ist dagegen eine mit einem Objekt durchgeführte Aktion. Die Syntax für eine Methode lautet Objekt.Methode. Eine Methode kann nicht mit etwas anderem gleichgesetzt werden. Häufig erstellen Sie jedoch eine Objektvariable und weisen dieser etwas zu, indem Sie eine Methode aufrufen. Eine Methode sieht wie folgt aus: Forms!frmHello.txtHelloWorld.SetFocus Hier wird die Methode SetFocus für das Textfeld txtHelloWorld ausgeführt. Eine Methode, die eine Objektvariable zurückgibt, sieht folgendermaßen aus: Dim cbr As CommandBar Set cbr = CommandBars.Add("MyNewCommandBar") In diesem Beispiel wird die Methode Add der CommandBars-Auflistung verwendet, um der Objektvariablen cbr des Objekts CommandBar einen Wert zuzuweisen. Weitere Informationen finden Sie im Abschnitt »Objektvariablen deklarieren und zuweisen« weiter hinten in diesem Kapitel. Viele Benutzer sind unsicher, wann ein Ausrufungszeichen (!) und wann ein Punkt gesetzt wird. Sie können ein Ausrufungszeichen immer dann verwenden, wenn Sie ein Objekt von der dazugehörigen Auflistung trennen, wie in den folgenden zwei Beispielen: Forms!frmClients

Forms!frmClients!txtClientID Im ersten Beispiel ist frmClients Bestandteil der Forms-Auflistung, während im zweiten txtClientID zur Auflistung Controls des Formulars frmClient gehört.

Objektvariablen deklarieren und zuweisen

323

In den meisten Fällen kann ein Punkt für die Trennung von Objekt und Auflistung verwendet werden. Das kommt daher, weil es sich beim Ausdruck Me!txtClientID eigentlich um eine Abkürzung für den vollständigen Verweis Me.Controls!txtClientID handelt. Weil Controls die standardmäßige Auflistung eines Formulars ist, können Sie in der Anweisung Controls weglassen und zu Me.txtClientID abkürzen. Der Vorteil der Verwendung eines Punkts anstelle eines Ausrufungszeichens liegt darin, dass Ihnen Intellisense-Technologie zur Verfügung steht. Um dies zu testen, erstellen Sie ein Formular und fügen ein Steuerelement mit dem Namen txtFirstName hinzu. Gehen Sie im Code hinter das Formular und geben Sie Me!. ein. Sie werden bemerken, dass Intellisense nicht aufgerufen wird. Geben Sie als nächstes Me. ein. In diesem Fall wird Intellisense aufgerufen. Intellisense erleichtert die Entwicklungsarbeit durch Bereitstellung eines Listenfelds mit geeigneten gültigen Eigenschaften, Methoden, Konstanten usw. Der Punkt dient nicht nur zur Trennung eines Objekts von dessen Auflistung, sondern auch zur Trennung eines Objektformulars von einer Eigenschaft oder Methode. Der Code sieht folgendermaßen aus: Forms!frmClients.RecordSource = "tblClients" Forms!frmClients!txtClientID.Visible = False

Im ersten Beispiel wird der Eigenschaft RecordSource von frmClients der Wert tblClients zugewiesen, während im zweiten Fall die Eigenschaft Visible des Textfelds txtClientID des Formulars frmClients den Wert False erhält.

8.5.1

Standardeigenschaften

Jedes Objekt verfügt über eine Standardeigenschaft. Wenn Sie mit dieser arbeiten, müssen Sie sich im Code nicht explizit darauf beziehen. Betrachten Sie die beiden folgenden Beispiele: Forms!frmHello.txt.Value = "Hello World" Forms!frmHello.txt = "Hello World"

Die Eigenschaft Value ist die Standardeigenschaft eines Textfelds, Sie müssen sich daher in Ihrem Code nicht explizit darauf beziehen. Allerdings erhöht es die Lesbarkeit des Codes, wenn Sie die Anweisung explizit angeben, weil ungeübte Programmierer nicht erraten müssen, welche Eigenschaft hier verändert wird.

8.6

Objektvariablen deklarieren und zuweisen

»Objektvariablen« sind Variablen, die auf ein Objekt eines bestimmten Typs verweisen, wie zum Beispiel auf Datenbanken, Datensätze, Formulare, Steuerelemente oder auch von anderen Anwendungen erstellte Objekte. Sie erlauben Ihnen, Verweisabkürzungen einzuführen und Objekte an Subroutinen und Funktionen zu übergeben.

324

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Durch Verwendung kurzer Namen zum Verweis auf Objekte mit langen Namen können Sie Ihren Code flüssiger gestalten und optimieren, indem Sie einen direkten Zeiger auf ein bestimmtes Objekt zur Verfügung stellen. Als erstes müssen Sie eine Objektvariable deklarieren. Dann weisen Sie der Objektvariablen ein bestimmtes Objekt zu (bzw. zeigen auf es): Private Sub cmdChangeCaption_Click() Dim cmdAny As CommandButton Set cmdAny = Me!cmdHello cmdAny.Caption = "Hello" End Sub

Dieser Code erzeugt eine Objektvariable mit dem Namen cmdAny vom Typ commandButton. Mit der Set-Anweisung weisen Sie anschließend mit Hilfe des Schlüsselworts Me der CommandButton-Objektvariablen das Objekt cmdHello des aktuellen Formulars zu. Zum Schluss verändern Sie die Überschrift der Objektvariablen cmdAny. Weil eine Objektvariable einen Verweis auf das ursprüngliche Objekt darstellt, ändern Sie tatsächlich die Überschrift der Schaltfläche cmdHello.

8.6.1

Objektvariablen und herkömmliche Variablen im Vergleich

Der Unterschied zwischen Objektvariablen und herkömmlichen Variablen soll mit dem folgenden Beispiel veranschaulicht werden: Dim intVar1 As Integer Dim intVar2 As Integer intVar1 = 5 intVar2 = intVar1 intVar1 = 10 Debug.Print intVar1 ' Gibt 10 aus Debug.Print intVar2 ' Gibt 5 aus

Dieser Code verwendet ganz normale Variablen. Wenn Sie diese Variablen deklarieren, erhält jede einen eigenen Speicherplatz. Der Variablen intVar2 wird zwar ursprünglich der Wert von intVar1 zugewiesen, eine Veränderung des Wertes von intVar1 hat aber keine Auswirkungen auf intVar2. Hierin unterscheidet sich der folgende Code, in dem Objektvariablen benutzt werden: Private Sub Command5_Click() Dim ctlText As TextBox Set ctlText = Forms!frmSales!txtProductID ctlText.Text = "New Text" debug.Print Forms!frmSales!txtProductID.Text 'Druckt den neuen Text End Sub

Unterschiede zwischen Objekten und Auflistungen

325

Diese Routine erzeugt eine Objektvariable mit dem Namen ctlText vom Typ TextBox. Anschließend wird der Objektvariablen das Textfeld Forms!frmSales!txtProductID zugewiesen. In der nächsten Zeile wird die Eigenschaft Text der Objektvariablen verändert. Weil die Objektvariable eigentlich auf das Textfeld des Formulars verweist, gibt die Anweisung Debug.Print den neuen Text aus.

8.6.2

Generische und spezielle Objektvariablen

Access unterstützt die Verwendung generischer Objektvariablen für Anwendungen, Steuerelemente, Formulare und Berichte. Mit generischen Objektvariablen können Sie auf jedes Objekt dieses generischen Typs verweisen: Private Sub ChangeVisible_Click() Dim ctlAny As Control Set ctlAny = Me!txtCustomerID ctlAny.Visible = False End Sub

In diesem Beispiel kann mit ctlAny auf jedes Steuerelement verwiesen werden. Vergleichen Sie den vorangegangenen Code mit dem folgenden: Private Sub ChangeVisible_Click() Dim txtAny As TextBox Set txtAny = Me!txtCustomerID txtAny.Visible = False End Sub

In diesem Fall kann mit der Objektvariablen nur auf ein Textfeld verwiesen werden.

8.6.3

Speicherbereinigung

Wenn Sie die Arbeit mit einer Objektvariablen beendet haben, sollten Sie ihr den Wert Nothing zuweisen. Im folgenden Beispiel gibt diese Anweisung alle mit dem Objekt verbundenen Speicher- und Systemressourcen frei: Set frmNew = Nothing

8.7

Unterschiede zwischen Objekten und Auflistungen

Für viele Benutzer ist die Unterscheidung zwischen einem Objekt und einer Auflistung verwirrend. Sie müssen sich ein Objekt als Element einer Auflistung vorstellen. Bei frmHello handelt es sich beispielsweise um ein Formular, welches ein Element der Forms-Auflistung ist. cmdHello stellt eine Schaltfläche des Formulars frmHello dar und gehört zur Auflistung Controls. Manchmal müssen Sie bestimmte Objekte bearbeiten, manchmal müssen Sie aber auch eine ganze Auflistung von Objekten verändern.

326

8.7.1

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Mit einem einzelnen Objekt umgehen

Sie haben bereits einiges über den Umgang mit einem einzelnen Objekt gelernt, wie beispielsweise das Setzen der Eigenschaft Enabled für ein Textfeld: txtCustomerID.Enabled = False

Diese Zeile betrifft nur ein Textfeld und nur eine der Eigenschaften. Wenn Sie ein einzelnes Objekt behandeln, ist es aber auch denkbar, dass Sie mehrere Eigenschaften gleichzeitig bearbeiten möchten. In diesem Fall ist es meist am effektivsten, wenn Sie das Konstrukt With ... End With benutzen, das im folgenden Abschnitt erklärt wird. With...End With: Mehrere Befehle auf ein einziges Objekt anwenden Eine Möglichkeit, mehrere Eigenschaften eines Objekts zu ändern, besteht darin, nacheinander den Wert jeder Eigenschaft zu ändern: txtcustomerID.Enabled = False txtcustomerID.SpecialEffect = 1 txtcustomerID.FontSize = 16 txtcustomerID.FontWeight = 700

Betrachten Sie im Vergleich hierzu den folgenden Code: With txtcustomerID .Enabled = False .SpecialEffect = 1 .FontSize = 16 .FontWeight = 700 End With

Dieser Code verwendet das Konstrukt With ... End With, um mehrere Eigenschaften eines Objekts festzulegen. Neben der besseren Lesbarkeit des Codes bietet diese Anweisung auch eine leichte Verbesserung der Geschwindigkeit.

8.7.2

Mit einer Objektauflistung umgehen

Eine »Auflistung« ist mit einem Objektfeld vergleichbar. Das besondere an diesem Feld ist die Tatsache, dass es von Access definiert und unterhalten wird. Für Microsoft Access ist jede Auflistung ein Objekt mit jeweils eigenen Eigenschaften und Methoden. Durch VBA wird es leichter, die Auflistungen von Access-Objekten zu bearbeiten. Sie verwenden hierfür das im folgenden Abschnitt beschriebene Konstrukt For Each...Next.

Objekte an Unterroutinen und Funktionen übergeben

327

For...Each: Denselben Befehl auf mehrere Objekte anwenden Im Abschnitt »Den Typ eines Steuerelements bestimmen« weiter hinten in diesem Kapitel erfahren Sie, wie Sie die Auflistung der Steuerelemente eines Formulars in einer Schleife durchlaufen und dabei Aktionen mit allen Schaltflächen durchführen. Dies veranschaulicht eine praktische Verwendung einer Auflistung. Im folgenden Beispiel durchläuft die Schleife alle geöffneten Formulare und verändert jeweils die Überschrift: Sub FormCaption() Dim frm As Form For Each frm in Forms frm.Caption = frm.Caption " – " CurrentUser Next frm End Sub

In dieser Routine wird mit Hilfe eines Konstrukts For Each...Next in einer Schleife jedes Formular der Forms-Auflistung bearbeitet und eine Überschrift zugewiesen, die aus der Bezeichnung des Formulars und dem Benutzernamen besteht. Beim Durchlaufen der Schleife bezieht sich der Ausdruck frm.Caption auf jedes einzelne Element der Forms-Auflistung.

8.8

Objekte an Unterroutinen und Funktionen übergeben Sie können einer Subroutine oder einer Funktion nicht nur eine Zeichenfolge oder eine Zahl, sondern auch ein Objekt übergeben. Den Code hierfür finden Sie im Modul basExamples in der Datenbank Chap8Ex:

Sub ChangeCaption(frmAny as Form) frmAny.Caption = frmAny.Caption & ": " & CurrentUser End Sub

Die Routine ChangeCaption erhält einen Verweis in Form eines Parameters. Die Überschrift des Formulars wird in dieser Prozedur so verändert, dass sie den Namen des aktuellen Benutzers enthält. Die ChangeCaption-Routine wird folgendermaßen aufgerufen: Private Sub cmdChangeCaption_Click() Call ChangeCaption(Me) End Sub

328

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

In diesem Beispiel ruft das Click-Ereignis der Schaltfläche cmdChangeCaption die Routine ChangeCaption auf, indem es einen Verweis auf das Formular sendet, in welchem sich die Schaltfläche befindet. Dieser ist Bestandteil des Formulars frmChangeCaption.

8.9

Den Typ eines Steuerelements bestimmen

Wenn Sie generischen Code schreiben, kann es notwendig sein, dass Sie den Typ eines Steuerelements bestimmen. Vielleicht möchten Sie in einer Schleife alle Steuerelemente eines Formulars durchsuchen und die Eigenschaft Enabled aller Schaltflächen umschalten. Dies tun Sie über die Eigenschaft ControlType eines Steuerelements. Es folgt ein Beispiel für die Verwendung dieser Eigenschaft (Sie finden dieses Beispiel in der Datenbank Chap8Ex.MDB im Modul basExamples.): Sub FlipEnabled(frmAny As Form, ctlAny As Control) Dim ctl As Control ' Verwenden des Konstrukts For...Each zum Durchlaufen der Controls-Auflistung ctlAny.Enabled = True ctlAny.SetFocus For Each ctl In frmAny.Controls ' Bestimmen des Steuerelementtyps If ctl.ControlType = acCommandButton Then 'Sicherstellen, dass kein Versuch unternommen wird, die_ Befehlsschaltfläche zu deaktivieren, welche diese Routine aufgerufen hat If ctl.Name ctlAny.Name Then ctl.Enabled = Not ctl.Enabled End If End If Next ctl End Sub

Vom Formular frmTypeOf wird die Prozedur FlipEnabled aufgerufen. Jede Schaltfläche des Formulars (ADD, EDIT, DELETE usw.) sendet das Formular und den Namen eines Steuerelements an die FlipEnabled-Routine. Das gesendete Steuerelement soll nach der Ausführung der Routine den Fokus erhalten. Im folgenden Beispiel wird die Schaltfläche cmdSave an die FlipEnabled-Routine gesendet. Diese Routine setzt den Fokus auf die Schaltfläche SAVE: Private Sub cmdAdd_Click() Call FlipEnabled(Me, Me!cmdSave) End Sub

Die Routine FlipEnabled erhält das Formular und die Schaltfläche als Parameter. Sie aktiviert die übergebene Schaltfläche und setzt den Fokus darauf. Anschließend verwendet die Routine das VBA-Konstrukt For...Each, um alle Steuerelemente des For-

Den Typ eines Steuerelements bestimmen

329

mulars zu erreichen. Innerhalb des For...Each-Konstrukts wird eine Gruppe von Anweisungen für jedes Objekt im Feld oder in der Auflistung (in diesem Fall der Auflistung der Steuerelemente) wiederholt. Jedes Steuerelement des Formulars wird ausgewertet, um festzustellen, ob es sich um eine Schaltfläche handelt. Ist dies der Fall (und wurde diese Schaltfläche nicht an die Routine übergeben), dann schaltet die Routine die Eigenschaft Enabled des Steuerelements um. Die folgenden VBA-eigenen Konstanten werden bei der Bewertung der Eigenschaft ControlType eines Steuerelements berücksichtigt: VBA-Konstante

Typ des Steuerelements

acLabel

Bezeichnungsfeld

acRectangle

Rechteck

acLine

Linie

acImage

Bild

acCommandButton

Befehlsschaltfläche

acOptionButton

Optionsschaltfläche

acCheckBox

Kontrollkästchen

acOptionGroup

Optionsgruppe

acBoundObjectFrame

Gebundenes Objektfeld

acTextBox

Textfeld

acListBox

Listenfeld

acComboBox

Kombinationsfeld

acSubform

Unterformular/-bericht

acObjectFrame

Objektfeld oder Diagramm

acPageBreak

Seitenumbruch

acPage

Seite

acCustomControl

ActiveX-Steuerelement

acToggleButton

Umschaltfläche

acTabCtl

Registerkarte

Tabelle 8.1: Typen der Steuerelemente

330

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

8.10

Spezielle Eigenschaften mit Objektbezug

Mit VBA ist eine bequeme Ausführung von Aktionen mit dem aktiven Steuerelement und anderen speziellen Objekten möglich. Die folgende Liste enthält besondere Objekteigenschaften des Objektmodells von Access.

 Die Eigenschaft ActiveControl bezieht sich auf das Steuerelement, welches den Fokus für ein Bildschirmobjekt, ein Formular oder einen Bericht besitzt.

 Die Eigenschaft ActiveForm bezieht sich auf das Formular, das den Fokus besitzt.  Die Eigenschaft ActiveReport bezieht sich auf den Bericht, der den Fokus besitzt.  Die Eigenschaft Form bezieht sich auf das Formular eines untergeordneten Formulars oder auf des Formular selbst.

 Me bezieht sich auf das Formular oder den Bericht, für das bzw. den gerade Code ausgeführt wird.

 Modules bezieht sich auf das Modul eines Formulars oder Berichts.  Die Eigenschaft Parent bezieht sich auf Formulare, Berichte oder Steuerelemente, die ein Steuerelement enthalten.

 PreviousControl bezieht sich auf das Steuerelement, welches unmittelbar vor dem aktiven Steuerelement den Fokus besaß.

 Die Eigenschaft RecordsetClone bezieht sich auf ein Duplikat des dem Formular zugrunde liegenden Datensatzes.

 Die Eigenschaft Report bezieht sich auf den Bericht, der ein untergeordnetes Formular enthält, oder auf den Bericht selbst.

 Die Eigenschaft Section bezieht sich auf den Abschnitt in einem Formular oder Bericht, in dem sich ein bestimmtes Steuerelement befindet. Im folgenden Beispiel wird gezeigt, wie mit Hilfe der Eigenschaft Screen.ActiveForm eine Unterroutine die Überschrift des aktiven Formulars ändern kann: Sub ChangeCaption() Screen.ActiveForm.Caption = Screen.ActiveForm.Caption & _ " – " & CurrentUser() End Sub

Diese Subroutine verändert die Überschrift des aktiven Formulars durch Anhängen des Wertes der Eigenschaft CurrentUser an das Ende der Überschrift.

Spezielle Eigenschaften mit Objektbezug

8.10.1

331

Für die Praxis

Umgang mit Objekten Objekte kommen überall in unserem Zeit-und Abrechnungssytem zum Einsatz. In fast allen Teilen der Anwendung werden die in diesem Kapitel beschriebenen Möglichkeiten verwendet. Das nachfolgende Beispiel wendet die eben vorgestellten Techniken an, um als Antwort auf Veränderungen des Benutzers an den Daten des Formulars frmClients Schaltflächen zu aktivieren und zu deaktivieren. Sie finden das Beispiel in der Datenbank CHAP8.MDB auf der beiliegenden CD-ROM.

8.10.2

Befehlsschaltflächen aktivieren und deaktivieren

Wenn der Benutzer gerade dabei ist, Daten eines Formulars zu verändern, werden die Anwendungsmodule Project, Time Cards, Payments und Invoice mit Sicherheit nicht benötigt. Es ist also sinnvoll, diese Optionen zu deaktivieren, bis der Benutzer die Änderungen an den Kundendaten gesichert hat. Zu Beginn sind die Schaltflächen VIEW PROJECTS, VIEW TIME CARDS, VIEW PAYMENTS und VIEW INVOICE des Formulars aktiviert, während die Schaltfläche SAVE deaktiviert ist. Die Eigenschaft KeyPreview des Formulars ist auf Yes gesetzt, so dass das Formular alle Eingaben anzeigt, bevor die einzelnen Steuerelemente diese verarbeiten. Das Ereignis KeyDown des Formulars sieht wie folgt aus: Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If Not cmdSave.Enabled Then If ImportantKey(Keycode, Shift) Then Call FlipEnabled (Me, Activecontrol) Me.NavigationButtons = False End If Else If KeyCode = vbkeyPageDown Or KeyCode = vbKeyPageup Then Keycode = 0 End If End If End Sub

Das Ereignis KeyDown erhält automatisch den Code der Taste, die gedrückt wurde, sowie die Information, ob gleichzeitig die (ª)-Taste, (Alt) oder (Strg) gedrückt wurden. Die Ereignisroutine überprüft, ob die Schaltfläche SAVE bereits aktiviert ist. Ist dies der Fall, muss sie nicht fortgesetzt werden, da die Eigenschaft Enabled bereits gesetzt wurde. Ist die Schaltfläche SAVE noch nicht aktiviert, wird die Funktion ImportantKey aufgerufen. Ihr wird die gedrückte Taste sowie die Tatsache kundgetan, ob die (ª)-Taste, (Alt) oder (Strg) gedrückt wurde. Die Funktion ImportantKey sieht wie folgt aus:

332

Kapitel 8: Objekte, Eigenschaften, Methoden und Ereignisse

Function ImportantKey(Keycode, Shift) ImportantKey = False If Shift = 4 Then Exit Function End If If Keycode = vbKeyDelete Or Keycode = vbKeyBaok Or (Keycode > 31 _ And Keycode < 256) Then If Keycode = vbKeyflight or Keycode = vbKeyLeft or _ Keycode = vbKeyup or Keycode = vbKeyDown or _ Keycode = vbKeyPageup or Keycode = vbkeyPageDown Then Else ImportantKey = True End If End If End Funotion

Diese generische Funktion aus basUtils legt als Standardrückgabewert False fest und überprüft, ob die (Alt)-Taste gedrückt wurde. War dies der Fall, hat der Benutzer einen Menübefehl oder ein Tastenkürzel gewählt, was bedeutet, dass die Schaltflächen nicht umgeschaltet werden müssen und die Funktion daher beendet werden kann. Wurde die (Alt)-Taste nicht gedrückt, wird die tatsächlich gedrückte Taste ausgewertet. Wurden die Tasten (Entf), (æ) oder eine andere Taste mit einem ANSI-Wert zwischen 31 und 235 (mit Ausnahme der Pfeiltasten, der (½)- und (¼)Taste) gedrückt, wird von dieser Funktion der Wert True zurückgegeben. Anschließend ruft das Ereignis KeyDown des Formulars die Routine FlipEnabled auf: Sub FlipEnabled(frmAny As Form, ctlAny As Control) Dim ctl As Control If Typeof ctlAny Is CommandButton Then ctlAny.Enabled = True ctlAny.SetFocus End If For Each ctl In frmAny.Controls If Typeof ctl Is CommandButton Then If ctl.Name ctlAny.Name Then ctl.Enabled = Not ctl.Enabled End If End If Next ctl End Sub

Diese generische Routine, die Sie ebenfalls in basUtils finden, setzt die Eigenschaft Enabled jeder Schaltfläche des Formulars, mit Ausnahme derjenigen, die ihr übergeben wurde. Die Routine FlipEnabled erhält ein Formular und ein Steuerelement als Parameter. Sie erzeugt zu Beginn eine Steuerelementvariable und testet anschließend, ob dieses übergebene Steuerelement eine Schaltfläche war. War dies der Fall, wird die Schaltfläche aktiviert und erhält den Fokus. Die Routine durchsucht dann

Spezielle Eigenschaften mit Objektbezug

333

in einer Schleife jedes Steuerelement des Formulars, welches ihr übergeben wurde, darauf, ob es sich bei den Steuerelementen um Schaltflächen handelt. Findet sie eine Schaltfläche, deren Name nicht mit dem Namen des übergebenen Steuerelements übereinstimmt, wird die Eigenschaft Enabled dieser Schaltfläche umgeschaltet. Dem liegt folgender Gedanke zu Grunde: Wenn der Benutzer die Schaltfläche SAVE anklickt, dann kann diese nicht sofort deaktiviert werden, weil sie noch den Fokus hat. Zuerst muss ein gewähltes Steuerelement (das der Routine übergebene) deaktiviert und der Fokus der aktivierten Schaltfläche übergeben werden. Nachdem das Steuerelement aktiviert wurde, möchten Sie aber sicher nicht, dass es sofort wieder deaktiviert wird, damit es aus der verarbeitenden Schleife entfernt werden muss. Wurde die Routine FlipEnabled ausgeführt, wird der Wert der Eigenschaft NavigationButtons des Formulars auf False gesetzt. Dies ist ein wichtiger Schritt, weil der Benutzer auf keinen Fall in der Lage sein darf, sich während der Bearbeitung der Daten des Formulars von einem Datensatz zum anderen zu bewegen. Andererseits müssen Sie Schaltflächen aber auch wieder umschalten. Das Ereignis Click der Schaltfläche SAVE besteht aus folgendem Code: Private Sub cmdSave_C1ick() DoCmd.RunCommand Command:=acCmdSaveRecord Call FlipEnabled(Me, Me!Projects) Me.NavigationButtons = True End Sub

Mit diesem Code wird der aktuelle Datensatz gespeichert und die Routine FlipEnabled aufgerufen. Die FlipEnabled-Routine versetzt die Schaltflächen wieder in den Ausgangszustand. Sie können auch eine Schaltfläche zum Abbrechen hinzufügen, mit der die Änderungen rückgängig gemacht und die Schaltflächen gleichfalls zurückgesetzt werden. Außerdem sollten Sie den Benutzer daran hindern, zu anderen Datensätzen wechseln zu können, bevor er die Schaltfläche SAVE gewählt hat, beziehungsweise die Schaltflächen umschalten, wenn die Schaltfläche SAVE gewählt wurde und der Benutzer zu anderen Datensätzen wechselt. Tun Sie dies nicht, werden die Datensätze von Access automatisch gespeichert, wenn der Benutzer zu einem anderen Datensatz wechselt, und die Schaltflächen spiegeln einen unsauberen Zustand des Formulars wieder.

Fortgeschrittene Verwendung von Formularen

Kapitel

Hier lesen Sie:

 Was sind Formularereignisse und wann sollten sie verwendet werden?  Abschnitts- und Steuerelementereignisse und ihre Verwendung  Welche Arten von Formularen kann ich erstellen und wofür eignen sie sich?  Formularen benutzerdefinierte Menüs, Symbolleisten und Kontextmenüs hinzufügen

 Objekte aus anderen Anwendungen einfügen  Benutzerdefinierte Eigenschaften und Methoden erstellen

9.1

Formulare ergänzen

Auf Grund der grafischen Benutzerschnittstelle von Access stehen Formulare häufig im Mittelpunkt Ihrer Bemühungen, so dass Sie alle Formular- und Steuerelementereignisse kennen und wissen sollten, welchen Code Sie für jede einzelne Aufgabe programmieren müssen. Außerdem sollten Sie die verfügbaren Formulare kennen und wissen, wie Sie deren Aussehen und Verhalten beeinflussen können. Oftmals müssen Sie eigene Formulare entwickeln, weil Sie eines der integrierten Dialogfelder von VBA oder der Werkzeuge der Microsoft Office 2000 Developer Edition verwenden wollen. Gleichgültig, welche Art von Formular Sie erstellen, Sie sollten in jedem Fall alle Vorteile der in diesem Kapitel vorgestellten Tricks und Hinweise nutzen, um Ihrem Formular Menü- und Symbolleisten hinzuzufügen.

336

9.2

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Was sind Formularereignisse und wann sollten sie verwendet werden?

Microsoft Access löst 30 Formularereignisse aus, die jeweils unterschiedlichen Zwecken dienen. Access reagiert auch auf Ereignisse in Formularabschnitten oder von Steuerelementen. Die folgenden Abschnitte behandeln die Formularereignisse und deren Verwendung.

9.2.1

Current (Beim Anzeigen)

Das Ereignis Beim Anzeigen bzw. current eines Formulars ist eines der am häufigsten programmierten Ereignisse. Es tritt immer dann ein, wenn der Fokus von einem Datensatz zum nächsten wechselt. Das Current-Ereignis eignet sich hervorragend, um Code einzufügen, der jedesmal beim Anzeigen des Datensatzes ausgeführt werden soll. Es kann zum Beispiel erwünscht sein, dass der Firmenname mit einem bestimmten Hintergrund erscheint, wenn es sich um einen wichtigen Kunden handelt. Der folgende Code befindet sich im Current-Ereignis des Formulars frmClients, das Bestandteil unseres Zeit- und Abrechnungssytems ist: Private Sub Form_Current() If IsNull(Me.txtclientID) Then Me.txtcontactFirstName SetFocus End If End Sub

Diese Zeilen verschieben den Fokus zum Steuerelement txtContactFirstName, wenn der Wert des Feldes txtClientID des Datensatzes, der vom Benutzer den Fokus erhält, gleich Null ist. Dazu kommt es, wenn der Benutzer einen neuen Datensatz hinzufügt.

9.2.2

BeforeInsert (Vor Eingabe)

Das Ereignis Vor Eingabe bzw. BeforeInsert tritt ein, wenn der erste Buchstabe eines neuen Datensatzes eingegeben wird, jedoch bevor der neue Datensatz tatsächlich erstellt ist. Gibt der Benutzer in einem Text- oder Kombinationsfeld Zeichen ein, kommt es zum BeforeInsert-Ereignis, bevor das Change-Ereignis des Text- oder Kombinationsfelds eintritt. Das Formular frmProjects unseres Zeit- und Abrechnungssytems enthält ein Beispiel für die praktische Verwendung des Ereignisses BeforeInsert: Private Sub Form_BeforeInsert(Cancel As Integer) Me.ClientID = Forms.frmClients.txtClientID End Sub

Was sind Formularereignisse und wann sollten sie verwendet werden?

337

Das Formular frmProjects wird immer vom Formular frmClients aufgerufen. Die Routine für das Ereignis BeforeInsert des Formulars frmProjects setzt den Wert des Textfeldes txtClientID auf den des Textfeldes txtClientID des Formulars frmClients.

9.2.3

AfterInsert (Nach Eingabe)

Das Ereignis Nach Eingabe bzw. AfterInsert tritt ein, nachdem ein Datensatz tatsächlich eingefügt wurde. Es kann zum Wiederauffinden eines Datensatzes verwendet werden, wenn ein neuer Datensatz hinzugefügt wird. Die Reihenfolge der Ereignisse beim Einfügen eines neuen Datensatzes durch den Benutzer sieht wie folgt aus: BeforeInsert(Vor Eingabe)?BeforeUpdate(Vor Aktualisierung)?AfterUpdate (Nach Aktualisierung)-AfterInsert(Nach Eingabe)

Das Ereignis BeforeInsert tritt ein, wenn der Benutzer den ersten Buchstaben eingibt. Zum Ereignis BeforeUpdates kommt es, wenn der Benutzer den Datensatz aktualisiert. Das Ereignis AfterUpdate findet statt, wenn der Datensatz aktualisiert wird und das Ereignis AfterInsert tritt auf, wenn es sich bei dem aktualisierten Datensatz um einen neuen Datensatz handelt.

9.2.4

BeforeUpdate (Vor Aktualisierung)

Das Ereignis Vor Aktualisierung bzw. BeforeUpdate wird vor dem Aktualisieren des Datensatzes ausgelöst. Es tritt auf, wenn der Benutzer versucht, zu einem anderen Datensatz zu wechseln (auch wenn es sich um einen Datensatz eines untergeordneten Formulars handelt) oder wenn der Befehl DATENSÄTZE|DATENSATZ SPEICHERN ausgeführt wird. Das BeforeUpdate-Ereignis kann dazu verwendet werden, den Aktualisierungsvorgang abzubrechen, wenn umfangreiche Überprüfungen durchgeführt werden sollen. Fügt der Benutzer einen Datensatz hinzu, tritt das Ereignis BeforeUpdate vor dem Ereignis BeforeInsert ein. Die Nordwind-Datenbank von Access enthält ein hervorragendes Beispiel für den Einsatz des Ereignisses BeforeUpdate: Private Sub Form_BeforeUpdate(Cancel As Integer) ' Wenn die Anzahl der im Textfeld "Postleitzahl" eingegebenen Stellen ' für den im Textfeld "Land" eingegebenen Wert ungültig ist, eine ' Meldung anzeigen und den Postleitzahlenwert zurücksetzen. Select Case Me!Land Case IsNull(Me![Land]) Exit Sub Case "Frankreich", "Italien", "Spanien", "Deutschland" If Len(Me![Postleitzahl]) 5 Then MsgBox "Postleitzahl muss 5 Zeichen lang sein.", _

338

Kapitel 9: Fortgeschrittene Verwendung von Formularen

0, "Postleitzahlenfehler" Cancel = True Me![Postleitzahl].SetFocus End If Case "Australien", "Singapur" If Len(Me![Postleitzahl]) 4 Then MsgBox "Postleitzahl muss 4 Zeichen lang sein.", _ 0, "Postleitzahlenfehler" Cancel = True Me![Postleitzahl].SetFocus End If Case "Kanada" If Not Me![Postleitzahl] Like "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" Then MsgBox "Postleitzahl ist ungültig. Beispiel für _ kanadische Postleitzahl: H1J 1C3", 0, "Postleitzahlenfehler" Cancel = True Me![Postleitzahl].SetFocus End If End Select

End Sub

Dieser Code des Lieferantenformulars stellt fest, ob die Postleitzahl dem gewählten Land entspricht. Ist dies nicht der Fall, wird eine Meldung angezeigt und dem Parameter Cancel der Wert True zugewiesen, was den Aktualisierungsvorgang abbricht. Aus Gründen der Bequemlichkeit für den Benutzer wird der Fokus dem Steuerelement für die Postleitzahl übergeben. Beachten Sie, dass sich die Beispiele aus der Nordwind-Datenbank nicht an den Benennungs- und Programmierkonventionen orientieren, die in diesem Buch eingehalten werden. Um bei der Betrachtung des Codes aus der Nordwind-Datenbank von Access 2000 Irrtümer zu vermeiden, wurden alle Nordwind-Beispiele unverändert gelassen, anstatt sie den Reddick-Namenskonventionen anzupassen.

9.2.5

AfterUpdate (Nach Aktualisierung)

Das Ereignis Nach Aktualisierung bzw. AfterUpdate tritt ein, wenn der geänderte Datensatz aktualisiert wird. Mit diesem Ereignis können Sie Kombinationsfelder verwandter Formulare aktualisieren oder die Veränderung des Datensatzes protokollieren. Es folgt ein Beispiel: Private Sub Form_AfterUpdate() Me.cboSelectProduct.Requery End Sub

Was sind Formularereignisse und wann sollten sie verwendet werden?

339

Dieser Code aktualisiert das Kombinationsfeld cboSelectProduct, nachdem der bearbeitete Datensatz aktualisiert wurde.

9.2.6

Dirty (Bei Änderung)

Das Ereignis Bei Änderung bzw. Dirty tritt auf, wenn der Inhalt des Formulars oder des Textes eines Kombinationsfelds verändert wird oder es zu einer programmgesteuerten Änderung der Text-Eigenschaft eines Steuerelements kommt. Ein Beispiel: Private Sub Form_Dirty(Cancel As Integer) Call FlipEnabled(Me, ActiveControl Me.NavigationButtons = False End Sub

Dieser Code aus dem Formular frmClients unseres Zeit- und Abrechnungssytems ruft die Methode FlipEnabled auf, um die Befehlsschaltflächen des Formulars umzuschalten. Dadurch werden die Schaltflächen SAVE und CANCEL aktiviert und die übrigen Schaltflächen des Formulars deaktiviert. Der Code deaktiviert gleichzeitig die Pfeiltasten, so dass der Benutzer nicht zu anderen Datensätzen wechseln kann, solange sich die Daten nicht im korrekten Zustand befinden.

9.2.7

Delete (Beim Löschen)

Das Ereignis Beim Löschen bzw. Delete tritt beim Versuch eines Benutzers auf, einen Datensatz zu löschen, bevor dieser tatsächlich aus der Tabelle entfernt wurde. Dieses Ereignis eignet sich sehr gut für Code, der das Löschen eines Datensatzes nur unter bestimmten Bedingungen zulässt. Wird das Ereignis Delete abgebrochen, werden die Ereignisse BeforeDelConfirm und AfterDelConfirm nicht ausgeführt und der Datensatz nicht gelöscht. Löscht der Benutzer mehrere Datensätze, tritt das Ereignis Delete nach dem Löschen jedes Datensatzes ein. So können Sie für jeden Datensatz eine Bedingung auswerten und dann entscheiden, ob der Datensatz gelöscht werden soll.

9.2.8

BeforeDelConfirm (Vor Löschbestätigung)

Das Ereignis Vor Löschbestätigung bzw. BeforeDelConfirm findet nach einem DeleteEreignis statt, jedoch bevor das Dialogfeld für die Bestätigung des Löschens angezeigt wird. Brechen Sie das BeforeDelConfirm-Ereignis ab, wird der Datensatz über den Puffer für gelöschte Datensätze wiederhergestellt und das Dialogfeld zur Bestätigung des Löschens wird nicht angezeigt.

340

9.2.9

Kapitel 9: Fortgeschrittene Verwendung von Formularen

AfterDelConfirm (Nach Löschbestätigung)

Das Ereignis Nach Löschbestätigung bzw. AfterDelConfirm tritt ein, nachdem der Datensatz tatsächlich gelöscht oder das Löschen abgebrochen wurde. Wurde das Ereignis BeforeDelConfirm nicht abgebrochen, findet das Ereignis AfterDelConfirm nach dem Anzeigen des Dialogfelds für die Bestätigung statt.

9.2.10

Open (Beim Öffnen)

Das Ereignis Beim Öffnen bzw. Open tritt beim Öffnen eines Formulars vor der Anzeige des ersten Datensatzes ein. Mit Hilfe dieses Ereignisses können Sie genau steuern, was beim Öffnen des ersten Formulars geschieht. Der Code für das Ereignis Open des Formulars frmProjects des Zeit- und Abrechnungssytems sieht wie folgt aus: Private Sub Form_Open(Cancel As Integer) If Not IsLoaded("frmClients") Then MsgBox "Open the Projects form using the " & _ "Projects button on the Clients Form" Cancel = True End If End Sub

Dieser Code überprüft, ob das Formular frmClients geladen wurde. Ist dies nicht geschehen, erscheint ein Meldungsfeld und der Parameter Cancel erhält den Wert True, was das Laden des Formulars verhindert.

9.2.11

Load (Beim Laden)

Zum Ereignis Beim Laden bzw. Load kommt es, wenn ein Formular geöffnet wurde und der erste Datensatz angezeigt wird. Dieses Ereignis tritt vor dem Ereignis Open ein. Das Open-Ereignis eines Formulars kann das Öffnen eines Formulars abbrechen, was für das Ereignis Load nicht zutrifft. Die folgende Routine gehört zum Ereignis Load des Zeit- und Abrechnungssytems: Private Sub Form_Load() If Me.DataEntry And Not (IsNull(Me.OpenArgs)) Then Me.txtExpenseCode = Me.OpenArgs End If End Sub

Diese Routine untersucht die als Argument beim Öffnen an das Formular überreichte Zeichenfolge. Hat die Zeichenfolge OpenArg nicht den Wert Null, wenn das Formular im Modus für die Dateneingabe geöffnet wurde, erhält das Textfeld txtExpenseCode den gleichen Wert wie das Argument zum Öffnen. Mit diesem Code kann das Formular im Wesentlichen zwei Dinge durchführen: Wurde das Formular im Datenbankfenster geöffnet, wird keine besondere Verarbeitung vorgenommen.

Was sind Formularereignisse und wann sollten sie verwendet werden?

341

Wurde es jedoch vom Unterformular fsubTimeCardsExpenses aus geöffnet, erfolgt das Öffnen im Dateneingabemodus und der vom Benutzer angegebene Kostenschlüssel wird im Textfeld txtExpenseCode platziert.

9.2.12

Resize (Bei Größenänderung)

Das Ereignis Bei Größenänderung bzw. Resize findet statt, wenn ein Formular geöffnet oder die Größe eines Formulars verändert wird.

9.2.13

Unload (Beim Entladen)

Das Ereignis Beim Entladen bzw. Unload tritt beim Schließen eines Formulars auf, bevor es tatsächlich vom Bildschirm entfernt wird. Es wird ausgelöst, wenn der Benutzer im Menü DATEI die Option SCHLIESSEN wählt, die Anwendung durch Auswahl von SCHLIESSEN in der TASK-LISTE beendet, Windows beendet oder wenn Ihr Code das Formular schließt. Mit Hilfe des Codes für das Ereignis Unload können Sie sicherstellen, dass das Formular ordnungsgemäß entladen wird. Es kann darüber hinaus Code enthalten, der bei jedem Entladen ausgeführt werden soll. Ein Beispiel: Private Sub Form_Unload(Cancel As Integer) If Me.cmdSave.Enabled Then Select Case MsgBox("Do You Want To Save", _ vbYesNoCancel + vbCritical, _ "Please Respond") Case vbYes DoCmd.RunCommand Command:=acCmdSaveRecord Cancel = False Case vbNo On Error Resume Next DoCmd.RunCommand Command:=acCmdUndo Cancel = False Case vbCancel Cancel = True End Select End If End Sub

Dieser Code gehört zum Ereignis Unload des Formulars frmClients unseres Zeit- und Abrechnungssytems und überprüft, ob die Schaltfläche SAVE aktiviert ist. Ist das der Fall, befindet sich das Formular nicht im korrekten Zustand. Der Benutzer wird gefragt, ob er die Änderung des Datensatzes speichern möchte. Bestätigt er diese Anfrage, werden die Daten gespeichert und das Formular wird entladen. Antwortet er mit NEIN, werden die Änderungen verworfen und anschließend wird das Formular entladen. Wählt er die Option ABBRECHEN, wird der Wert des Parameters Cancel auf False gesetzt und das Formular nicht entladen.

342

9.2.14

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Close (Beim Schließen)

Das Ereignis Beim Schließen bzw. Close tritt beim Schließen und Entfernen eines Formulars vom Bildschirm nach dem Ereignis Unload auf. Denken Sie daran, dass Sie das Ereignis Unload, jedoch nicht das Ereignis Close abbrechen können. Der folgende Code gehört zum Close-Ereignis des Formulars frmClients, welches Bestandteil des Zeit- und Abrechnungssystems ist: Private Sub Form_Close() If Iskoaded("frmProjects") Then DoCmd.Close acForm, "frmProjects" End If End Sub

Wenn das Formular frmClients geschlossen wird, überprüft der Code, ob das Formular frmProjects geöffnet ist. Trifft dies zu, wird es ebenfalls geschlossen.

9.2.15

Activate (Bei Aktivierung)

Das Ereignis Bei Aktivierung bzw. Activate tritt auf, wenn das Formular den Fokus erhält und zum aktiven Fenster wird. Es wird beim Öffnen des Formulars ausgelöst, wenn der Benutzer auf das Formular oder eines seiner Steuerelemente klickt oder wenn der VBA-Code die Methode SetFocus anwendet. Der folgende Code gehört zum Ereignis Activate des Formulars frmClients unseres Zeit- und Abrechnungssystems. Er aktualisiert das Unterformular subform immer dann, wenn das Hauptformular aktiviert wird: Private Sub Form_Activate() Me.fsubClients.Requery End Sub

9.2.16

Deactivate (Bei Deaktivierung)

Das Ereignis Bei Deaktivierung bzw. Deactivate wird ausgelöst, wenn das Formular den Fokus verliert, was eintritt, wenn eine Tabelle, eine Abfrage, ein Formular, ein Bericht, ein Makro, ein Modul oder ein Datenbankfenster aktiviert wird. Es wird jedoch nicht ausgelöst, wenn ein Dialogfeld, ein Popup-Formular oder eine andere Anwendung aktiviert wird. Das folgende Beispiel verdeutlicht die Verwendung des Ereignisses Deactivate: Private Sub Form_Deactivate() ' Mit Hilfe der Eigenschaft AllowEdits die zu verbergende Symbolleiste bestimmen ' Symbolleiste Formularansicht anzeigen If Me.AllowEdits = True Then DoCmd.ShowToolbar "Enter or Edit Products 2", acToolbarNo Else DoCmd.ShowToolbar "Enter or Edit Products 1", acToolbarNo

Was sind Formularereignisse und wann sollten sie verwendet werden?

343

End If DoCmd.ShowToolbar "Form View", acToolbarWhereApprop End Sub

Dieser Code wertet die Eigenschaft AllowEdits aus, um die zurzeit aktive benutzerdefinierte Symbolleiste zu ermitteln. Die entsprechende Symbolleiste wird verborgen und die Standardsymbolleiste der Formularansicht angezeigt.

9.2.17

GotFocus (Bei Fokuserhalt)

Zum Ereignis Bei Fokuserhalt bzw. GotFocus kommt es, wenn ein Formular den Fokus erhält. Es tritt nur ein, wenn sich im Formular keine sichtbaren aktivierten Steuerelemente befinden. Dieses Ereignis wird selten in einem Formular genutzt.

9.2.18

LostFocus (Bei Fokusverlust)

Das Ereignis Bei Fokusverlust bzw. LostFocus findet statt, wenn ein Formular den Fokus verliert, allerdings nur, wenn das Formular keine sichtbaren aktivierten Steuerelemente enthält. Auch dieses Ereignis wird selten in einem Formular genutzt.

9.2.19

Click (Beim Klicken)

Das Ereignis Beim Klicken bzw. Click tritt auf, wenn ein Benutzer auf einen leeren Bereich eines Formulars, auf ein deaktiviertes Steuerelement des Formulars oder den Datensatzmarkierer klickt.

9.2.20

DblClick (Beim Doppelklicken)

Das Ereignis Beim Doppelklicken bzw. DblClick wird ausgelöst, wenn der Benutzer doppelt auf einen leeren Bereich eines Formulars, auf ein deaktiviertes Steuerelement oder den Datensatzmarkierer des Formulars klickt.

9.2.21

MouseDown (Bei Maustaste Ab)

Zum Ereignis Bei Maustaste Ab bzw. MouseDown kommt es, wenn ein Benutzer auf einen leeren Bereich eines Formulars, auf ein deaktiviertes Steuerelement oder den Datensatzmarkierer klickt. Dieses Ereignis tritt jedoch vor dem Ereignis Click auf. Mit seiner Hilfe können Sie feststellen, welche Maustaste gedrückt wurde.

9.2.22

MouseMove (Bei Mausbewegung)

Das Ereignis Bei Mausbewegung bzw. MouseMove findet statt, wenn der Benutzer den Mauszeiger über einen leeren Bereich des Formulars, über ein deaktiviertes Steuerelement des Formulars oder über den Datensatzmarkierer bewegt. Es wird kontinuierlich erzeugt, während der Mauszeiger über das Formular bewegt wird. Dieses Ereignis tritt vor dem Auslösen des Click-Ereignisses auf.

344

9.2.23

Kapitel 9: Fortgeschrittene Verwendung von Formularen

MouseUp (Bei Maustaste Auf)

Das Ereignis Bei Maustaste Auf bzw. MouseUp tritt ein, wenn der Benutzer die Maustaste loslässt. Wie das Ereignis MouseDown tritt es vor dem Ereignis Click auf. Mit seiner Hilfe können Sie ebenfalls feststellen, welche Maustaste gedrückt wurde.

9.2.24

KeyDown (Bei Taste Ab)

Das Ereignis Bei Taste Ab bzw. KeyDown tritt auf, wenn sich auf dem Formular keine Steuerelemente befinden oder die Formulareigenschaft KeyPreview des Formulars den Wert Yes hat. Trifft letzteres zu, werden alle Tastaturereignisse des Formulars berücksichtigt und für das Steuerelement mit dem Fokus ausgelöst. Wenn der Benutzer eine Taste gedrückt hält, tritt das KeyDown-Ereignis wiederholt auf, bis die Taste losgelassen wird. Es folgt ein Beispiel: Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If Me.Dirty Then If KeyCode = vbKeyPageDown Or _ KeyCode = vbKeyPageUp Then KeyCode = 0 End If End If End Sub

Dieser Code aus dem Formular frmClients des Zeit- und Abrechnungssystems prüft, ob sich das Formular im korrekten Zustand befindet. Ist dies nicht der Fall und wurde die Taste (Bild¼) oder (Bild½) gedrückt, wird der Tastendruck ignoriert. Dies verhindert, dass der Benutzer sich zu einem anderen Datensatz bewegt, ohne zuvor die Schaltfläche SAVE oder CANCEL geklickt zu haben.

9.2.25

KeyUp (Bei Taste Auf)

Wie das Ereignis Bei Taste ab bzw. KeyDown tritt auch das Ereignis Bei Taste Auf bzw. KeyUp nur dann auf, wenn sich auf dem Formular keine Steuerelemente befinden oder die Eigenschaft KeyPreview des Formulars den Wert Yes hat. Dieses Ereignis findet nur einmal statt, unabhängig davon, wie lange die Taste gedrückt wird. Der Tastendruck kann durch Zuweisen des Werts Zero für KeyCode abgebrochen werden.

9.2.26

KeyPress (Bei Taste)

Das Ereignis Bei Taste bzw. KeyPress tritt auf, wenn der Benutzer eine einem ANSICode entsprechende Taste oder Tastenkombination drückt und wieder loslässt. Befinden sich auf dem Formular keine Steuerelemente oder wurde die Eigenschaft KeyPreview des Formulars auf Yes gesetzt, findet dieses Ereignis nicht statt. Der Tastendruck kann durch Zuweisen des Werts Zero für KeyCode abgebrochen werden.

Was sind Formularereignisse und wann sollten sie verwendet werden?

9.2.27

345

Error (Bei Fehler)

Das Ereignis Bei Fehler bzw. Error wird immer dann ausgelöst, wenn ein Fehler auftritt, während sich der Benutzer auf dem Formular befindet. Fehler der Jet-Engine von Microsoft werden abgefangen, für die Fehler von Visual Basic gilt dies jedoch nicht. Mit diesem Ereignis können Standardfehlermeldungen unterdrückt werden. VBA-Fehler müssen mit Hilfe des Konstrukts On Error behandelt werden. Das ErrorEreignis und der Umgang mit VBA-Fehlern werden in Kapitel 14 behandelt.

9.2.28

Filter (Bei Filter)

Das Ereignis Bei Filter bzw. Filter findet statt, wenn der Benutzer eine der Optionen FORMULARBASIERTER FILTER oder SPEZIALFILTER/-SORTIERUNG gewählt hat. Mit diesem Ereignis können Sie zuvor festgelegte Filter entfernen, Standardeinstellungen für einen Filter angeben, einen benutzerdefinierten Filter aktivieren oder verhindern, dass bestimmte Steuerelemente im Fenster FORMULARBASIERTER FILTER zur Verfügung stehen.

9.2.29

ApplyFilter (Bei angewendetem Filter)

Das Ereignis Bei angewendetem Filter bzw. ApplyFilter wird initiiert, wenn der Benutzer eine der Optionen FILTER/SORTIERUNG ANWENDEN, AUSWAHLBASIERTER FILTER oder FILTER/SORTIERUNG ENTFERNEN auswählt. Außerdem tritt das Ereignis beim Schließen der Fenster SPEZIALFILTER/SORTIERUNG und FORMULARBASIERTER FILTER auf. Mit diesem Ereignis können Sie dafür sorgen, dass der richtige Filter verwendet wird, um die Anzeige des Formulars zu verändern, bevor der Filter angewendet wird, oder um Veränderungen rückgängig zu machen, die vorgenommen wurden, als das Filter-Ereignis eintrat.

9.2.30

Timer (Zeitgeber)

Das Ereignis Zeitgeber bzw. Timer und die Eigenschaft TimerInterval bzw. Zeitgeberintervall eines Formulars arbeiten Hand in Hand. Die Eigenschaft TimerInterval kann auf einen Wert zwischen 0 und 2.147.483.647 gesetzt werden. Der gewählte Wert legt die Häufigkeit in Millisekunden fest, mit der das Timer-Ereignis auftritt. Ist der Wert der Eigenschaft TimerInterval beispielsweise auf 0 gesetzt, tritt das TimerEreignis überhaupt nicht ein. Bei einem Wert von 5000 Millisekunden wird das Ereignis alle 5 Sekunden ausgelöst. Im folgenden Beispiel wird mit dem Timer-Ereignis die Sichtbarkeit des Bezeichnungsfelds des Formulars umgeschaltet, wodurch ein Blinken erzeugt wird. Die Eigenschaft TimerInterval kann anfänglich auf einen beliebigen Wert ungleich 0 gesetzt werden, sie wird jedoch anschließend bei jeder Ausführung des Codes um 50 Millisekunden reduziert. Dadurch blinkt das Steuerelement immer schneller. Das Timer-Ereignis tritt solange auf, bis die Eigenschaft TimerInterval schließlich den Wert 0 erreicht.

346

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Private Sub Form_Timer() If Me.Label2.Visible = True Then Me.Label2.Visible = False Else Me.Label2.Visible = True End If Me.TimerInterval = Me.TimerInterval – 50 If Me.TimerInterval = 0 Then Me.Label2.Visible = True End If End Sub

9.3

Die Reihenfolge der Formularereignisse

Die Reihenfolge der Ereignisse ist etwas rätselhaft. Am besten kann man sie deutlich machen, wenn man Debug.Print-Anweisungen in die Ereignisroutinen aufnimmt, über deren Ereignisse man etwas erfahren möchte. Diese Technik wird in Kapitel 13 behandelt. Beachten Sie jedoch, dass es sich bei der Reihenfolge der Ereignisse nicht um eine exakte Wissenschaft handelt. Es ist nahezu unmöglich, für alle Situationen zu ermitteln, wann Ereignisse eintreten. Dennoch ist es hilfreich, wenn Sie die Grundsätze kennen, nach denen bestimmte Ereignisse ausgelöst werden.

9.3.1

Was geschieht beim Öffnen eines Formulars?

Wenn der Benutzer ein Formular öffnet, kommt es zu folgender Ereigniskette: Open (Beim Öffnen)->Load (Beim Laden)->Resize (Bei Größenänderung)->Activate (Bei Aktivierung)->Current (Beim Anzeigen)

Nachdem diese Formularereignisse stattgefunden haben, kommt es beim ersten Steuerelement zu den Ereignissen Enter (Beim Hingehen) und GotFocus (Bei Fokuserhalt). Beachten Sie, dass Sie das Öffnen eines Formulars nur während des Ereignisses Open bzw. Beim Öffnen abbrechen können.

9.3.2

Was geschieht beim Schließen eines Formulars?

Schließt der Benutzer ein Formular, finden folgende Ereignisse statt: Unload (Beim Entladen)->Deactivate (Bei Deaktivierung)->Close (Beim Schließen)

Vor diesen Ereignissen werden die Ereignisse Exit (Beim Verlassen) und LostFocus (Bei Fokusverlust) des aktiven Steuerelements ausgelöst.

Die Reihenfolge der Formularereignisse

9.3.3

347

Was geschieht beim Ändern der Formulargröße?

Ändert der Benutzer die Größe eines Formulars, werden unterschiedliche Ereignisse ausgelöst, je nachdem, ob das Formular minimiert, wiederhergestellt oder maximiert wird. Beim Minimieren geschieht Folgendes: Resize (Bei Größenänderung)->Deactivate (Bei Deaktivierung)

Beim Wiederherstellen eines minimierten Formulars, treten die folgenden Ereignisse auf: Activate (Bei Aktivierung)->Resize (Bei Größenänderung)

Maximiert der Benutzer ein Formular oder stellt er es wieder her, tritt nur das Ereignis Resize (Bei Größenänderung) ein.

9.3.4

Was geschieht bei der Fokusübergabe von einem Formular zu einem anderen?

Wechselt der Benutzer von einem Formular zum anderen, tritt für das erste Formular das Ereignis Deactivate (Bei Deaktivierung) ein. Anschließend kommt es für das zweite Formular zum Ereignis Activate (Bei Aktivierung). Denken Sie aber daran, dass das Ereignis Deactivate (Bei Deaktivierung) nicht stattfindet, wenn der Fokus zu einem Dialogfeld, einem Popup-Formular oder einer anderen Anwendung wechselt.

9.3.5

Was geschieht beim Drücken einer Taste?

Gibt der Benutzer einen Buchstaben ein und hat die Eigenschaft Tastenvorschau des Formulars den Wert True, kommt es zu folgenden Ereignissen: KeyDown (Bei Taste Ab)->KeyPress (Bei Taste)->Dirty (Bei Änderung)->KeyUp (Bei Taste auf)

Wenn Sie das KeyDown-Ereignis abfangen und KeyCode auf den Wert 0 setzen, werden die verbleibenden Ereignisse nicht mehr ausgelöst. Das Ereignis KeyPress erfasst nur ANSI-Tastenwerte. Dieses Ereignis ist am einfachsten zu behandeln. Sie müssen jedoch die Ereignisse KeyDown und KeyUp berücksichtigen, wenn Sie Tasten wie die (ª)-, (Alt)- oder (Strg)-Taste abfangen wollen, die keinen ANSI-Zeichen entsprechen.

9.3.6

Was geschieht beim Eintreten einer Mausaktion?

Klickt der Benutzer die Maustaste, kommt es zu folgenden Ereignissen: MouseDown (Bei Maustaste Ab)->MouseUp (Bei Maustaste Auf)->Click (Beim Klicken)

348

Kapitel 9: Fortgeschrittene Verwendung von Formularen

9.4

Abschnitts- und Steuerelementereignisse und ihre Verwendung

Für Abschnitte gibt es nur fünf Ereignisse: Click (Beim Klicken), DblClick (Beim Doppelklicken), MouseDown (Bei Maustaste Ab), MouseMove (Bei Mausbewegung) und MouseUp (Bei Maustaste auf). Diese Ereignisse spielen in Ihren Anwendungen nur selten eine wichtige Rolle. Jedes Steuerelement reagiert auf eine eigene Anzahl von Ereignissen. Viele Ereignisse sind für die meisten Steuerelemente gleich, andere hingegen sind für einzelne Steuerelemente spezifisch. Einige reagieren auch nur auf sehr wenige Ereignisse. In den folgenden Abschnitten werden alle Steuerelementereignisse erläutert. Da jedes Ereignis berücksichtigt wird, erfahren Sie, für welche Steuerelemente die Ereignisse von Bedeutung sind.

9.4.1

BeforeUpdate (Vor Aktualisierung)

Das Ereignis Vor Aktualisierung bzw. BeforeUpdate tritt bei Textfeldern, Optionsgruppen, Kombinationsfeldern und gebundenen Objektfeldern auf. Es wird vor der Aktualisierung der geänderten Daten ausgelöst. Der folgende Code gehört zum BeforeUpdate-Ereignis des Steuerelements Kunden-Code des Formulars Bestellungen aus der Nordwind-Datenbank: Private Sub KundenCode_BeforeUpdate(Cancel As Integer) ' Wenn Kombinationsfeld "KundenCode" leer ist, Meldung anzeigen. Dim strMsg As String, strTitle As String Dim intStyle As Integer If IsNull(Me!KundenCode) Or Me!KundenCode = "" Then strMsg = "Sie müssen einen Wert aus der Liste 'Rechnung an' auswählen." strTitle = "Kunde für Rechnung erforderlich" intStyle = vbOKOnly MsgBox strMsg, intStyle, strTitle Cancel = True End If End Sub

Dieser Code überprüft, ob das Steuerelement Kunden-Code den Wert Null oder eine Zeichenfolge mit der Länge 0 hat. Trifft dies zu, wird eine Meldung angezeigt und das Update-Ereignis abgebrochen.

Abschnitts- und Steuerelementereignisse und ihre Verwendung

9.4.2

349

AfterUpdate (Nach Aktualisierung)

Das Ereignis AfterUpdate bzw. AfterUpdate tritt bei Textfeldern, Optionsgruppen, Kombinationsfeldern und gebundenen Objektfeldern auf. Es wird ausgelöst, bevor die geänderten Daten des Steuerelements aktualisiert werden. Der folgende Code gehört zum AfterUpdate-Ereignis des Steuerelements txtBeginDate aus dem Formular frmPrintInvoice des Zeit- und Abrechnungssystems: Private Sub txtBeginDate_AfterUpdate() Me.fsubPrintInvoiceTime.Requery Me.fsubPrintlnvoiceExpenses.Requery End Sub

Dieser Code benötigt bei der Aktualisierung des Steuerelements txtBeginDate die Unterformulare fsubPrintInvoiceTime und fsubPrintInvoiceExpenses. Das stellt sicher, dass die beiden Unterformulare die entsprechenden Kosten und Ausgaben für den gewählten Zeitraum anzeigen.

9.4.3

Updated (Bei OLE-Aktualisierung)

Das Ereignis Bei OLE-Aktualisierung bzw. Updated tritt nur bei gebundenen Objektfeldern auf. Es wird ausgelöst, wenn die Daten des OLE-Objekts verändert wurden.

9.4.4

Updated (Bei OLE-Aktualisierung)

Das Ereignis Bei Änderung bzw. Change tritt beim Ändern der Daten in Text- und Kombinationsfeldern auf. Bei einem Textfeld wird das Ereignis ausgelöst, wenn ein Buchstabe eingegeben wird. Bei einem Kombinationsfeld wird es durch die Eingabe eines Buchstabens oder die Auswahl eines Wertes in der Liste ausgelöst. Dieses Ereignis benutzen Sie, um Vorgänge zu behandeln, die auf einer Buchstabenfolge basieren.

9.4.5

Updated (Bei OLE-Aktualisierung)

Zum Ereignis Bei Nicht in Liste bzw. NotInList kommt es nur im Zusammenhang mit Kombinationsfeldern, wenn der Benutzer im Textfeld einen Wert eingibt, der nicht in der Liste des Kombinationsfelds vorhanden ist. Auf diese Weise können Sie dem Benutzer gestatten, einen neuen Wert der Liste des Kombinationsfelds hinzuzufügen. Damit dieses Ereignis ausgelöst wird, muss die Eigenschaft LimitToList (Nur Listeneinträge) auf Yes bzw. Ja gesetzt sein. Es folgt ein Beispiel für das Formular frmPayments aus dem Zeit- und Abrechnungssystem: Private Sub cboPaymentMethodID_NotInList(NewData As String, Response As Integer) If MsgBox("Payment Method Not Found, Add?", _ vbYesNo + vbQuestion, _ "Please Respond") = vbYes Then

350

Kapitel 9: Fortgeschrittene Verwendung von Formularen

DoCmd.OpenForm "frmPaymentMethods", _ Datamode:=acFormAdd, _ WindowMode:=acDialog, _ OpenArgs:=NewData If IsLoaded("frmPaymentMethods") Then Response = acDataErrAdded DoCmd.Close acForm, "frmPaymentMethods" Else Response = acDataErrContinue End If Else Response = acDataErrContinue End If End Sub

Dieser Code wird ausgeführt, wenn der Benutzer eine Zahlungsart eingibt, die im Kombinationsfeld cboPaymentMethodID nicht vorhanden ist. Der Benutzer wird gefragt, ob der Eintrag hinzugefügt werden soll. Bestätigt er die Anfrage, wird das Formular frmPaymentMethods angezeigt. Andernfalls muss er einen anderen Eintrag in der Liste des Kombinationsfelds auswählen. Das Ereignis NotInList wird im Abschnitt »Mit dem Ereignis NotInList umgehen« noch eingehender behandelt.

9.4.6

Enter (Beim Hingehen)

Das Ereignis Beim Hingehen bzw. Enter bezieht sich auf Textfelder, Optionsgruppen, Kombinationsfelder, Listenfelder, Schaltflächen, Objektfelder und Unterformulare. Es wird ausgelöst, bevor ein Steuerelement tatsächlich den Fokus von einem anderen Steuerelement des gleichen Formulars übernimmt und bevor das Ereignis GotFocus (Bei Fokuserhalt) eintritt. Folgendes Beispiel stammt aus dem Formular frmTimeCards des Zeit- und Abrechnungssytems: Private Sub fsubTimeCards_Enter() If IsNull(Me.cboEmployeelD) Then MsgBox "Enter employee before entering time or expenses" CboEmployeelD.SetFocus End If End Sub

Wechselt der Benutzer zum Unterformulars fsubTimeCards, testet dessen EnterEreignis, ob die Angestelltennummer auf dem Hauptformular eingegeben wurde. Ist dies nicht geschehen, wird eine Meldung angezeigt und der Fokus dem Steuerelement cboEmployeeID des Hauptformulars übergeben.

Abschnitts- und Steuerelementereignisse und ihre Verwendung

9.4.7

351

Exit (Beim Verlassen)

Das Ereignis Beim Verlassen bzw. Exit tritt bei Textfeldern, Optionsgruppen, Kombinationsfeldern, Listenfeldern, Schaltflächen, Objektfeldern und Unterformularen ein. Es wird direkt vor dem Ereignis LostFocus (Bei Fokusverlust) ausgelöst.

9.4.8

GotFocus (Bei Fokuserhalt)

Das Ereignis Bei Fokuserhalt bzw. GotFocus wird durch Textfelder, Umschaltflächen, Optionsfelder, Kontrollkästchen, Kombinationsfelder, Listenfelder und Befehlsschaltflächen initiiert. Es wird ausgelöst, wenn der Fokus infolge eines Benutzereingriffs einem Steuerelement entzogen wird oder der Code die Methoden SetFocus, SelectObject, GoToRecord, GoToControl oder GoToPage ausführt. Steuerelemente erhalten den Fokus nur, wenn sie sichtbar und aktiviert sind.

9.4.9

LostFocus (Bei Fokusverlust)

Das Ereignis Bei Fokusverlust bzw. LostFocus bezieht sich auf Textfelder, Umschaltflächen, Optionsfelder, Kontrollkästchen, Kombinationsfelder, Listenfelder und Befehlsschaltflächen. Es wird ausgelöst, wenn der Fokus infolge eines Benutzereingriffs einem Steuerelement entzogen wird oder der Code die Methoden SetFocus, SelectObject, GoToRecord, GoToControl oder GoToPage ausführt. Der Unterschied zwischen den Ereignissen GotFocus/LostFocus und Enter/Exit liegt im Zeitpunkt des Eintritts. Wird der Fokus einem anderen Formular übergeben oder dem aktuellen Formular zurückgegeben, löst dies die Ereignisse GotFocus und LostFocus des Steuerelements aus. Die Ereignisse Enter und Exit finden nicht statt, wenn das Formular den Fokus verliert oder zurückerhält. Außerdem muss erwähnt werden, dass keines dieser Ereignisse stattfindet, wenn eine Auswahl über das Menü oder die Symbolleisten getroffen wird.

9.4.10

Click (Beim Klicken)

Das Ereignis Beim Klicken bzw. Click spielt bei Bezeichnungsfeldern, Textfeldern, Optionsgruppen, Kombinationsfeldern, Listenfeldern, Schaltflächen und Objektfeldern eine Rolle. Es tritt ein, wenn der Benutzer eine Maustaste über einem Steuerelement drückt und wieder loslässt. Das folgende Beispiel stammt aus dem Formular frmProjects des Zeit- und Abrechnungssytems: Private Sub cmdToggleView_Click() If Me.cmdToggleView.Caption = "&View Expenses" Then Me.fsubProjects.Visible = False Me.fsubProjectExpenses.Visible = True Me.cmdToggleView.Caption = "&View Hours"

352

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Else Me.fsubProjectExpenses.Visible = False Me.fsubProjects.Visible = True Me.cmdToggleView.Caption = "&View Expenses" End If End Sub

Dieser Code überprüft die Beschriftung der Schaltfläche cmdToggleView. Lautet diese "&View Expenses" (das &-Zeichen kennzeichnet ein Tastenkürzel), wird das Unterformular fsubProjects verborgen, das Unterformular fsubProjectsExpenses sichtbar gemacht und die Beschriftung der Schaltfläche cmdToggleView zu "&View Hours" geändert. Andernfalls wird das Unterformular fsubProjectsExpenses verborgen, das Unterformular fsubProjects sichtbar gemacht und die Beschriftung der Schaltfläche cmdToggleView in "&View Expenses" geändert. Das Click-Ereignis wird ausgelöst, wenn der Benutzer die Maustaste über einem Objekt klickt. Außerdem tritt es in folgenden Situationen ein: – wenn die Leertaste gedrückt wird, während eine Schaltfläche den Fokus besitzt – wenn die Eigenschaft Default (Standard) einer Schaltfläche auf Yes bzw. Ja gesetzt ist und die Eingabetaste gedrückt wird – wenn die Eigenschaft Cancel (Abbrechen) einer Schaltfläche auf Yes bzw. Ja gesetzt ist und die (Esc)-Taste gedrückt wird – wenn ein Tastenkürzel für eine Schaltfläche benutzt wird

9.4.11

DblClick (Beim Doppelklicken)

Das Ereignis Beim Doppelklicken bzw. DblClick bezieht sich auf Bezeichnungsfelder, Textfelder, Optionsgruppen, Kombinationsfelder, Listenfelder, Schaltflächen und Objektfelder. Es tritt ein, wenn der Benutzer eine Maustaste über einem Steuerelement innerhalb sehr kurzer Zeit zweimal klickt und wieder loslässt. Das folgende Beispiel stammt aus dem Formular fsubTimeCards des Zeit- und Abrechnungssytems: Private Sub cboWorkCodeID_DblClick(Cancel As Integer) On Error GoTo Err_cboWorkCodeID_DblClick Dim lngWorkCodeID As Long If IsNull(Me.cboWorkCodeID) Then Me.cboWorkCodeID.Text = "" Else lngWorkCodeID = Me.cboWorkCodeID Me.cboWorkCodeID = Null End If DoCmd.OpenForm "frmWorkCodes", , , , , acDialog, "GotoNew" Me.cboWorkCodeID.Requery

Abschnitts- und Steuerelementereignisse und ihre Verwendung

353

If lngWorkCodeID 0 Then Me.cboWorkCodeID = lngWorkCodeID Exit_cboWorkCodeID_DblClick: Exit Sub Err_cboWorkCodeID_DblClick: MsgBox Err.Description Resume Exit_cboWorkCodeID_DblClick End Sub

In diesem Beispiel wertet der Code das Kombinationsfeld cboWorkCodeID aus, um festzustellen, ob der Wert gleich Null ist. Ist dies der Fall, wird der Text des Kombinationsfelds auf eine Zeichenfolge der Länge Null gesetzt. Andernfalls wird eine Long Integer-Variable auf den gleichen Wert wie den des Kombinationsfelds und der Wert des Kombinationsfelds auf Null gesetzt. Das Formular frmWorkCodes wird angezeigt. Wurde es wieder geschlossen, wird das Kombinationsfeld cboWorkCodeID angefordert. Hat die Long Integer-Variable nicht den Wert Null, wird der Wert des Kombinationsfelds dem Wert der Long Integer-Variablen gleichgesetzt.

9.4.12

MouseDown (Bei Maus Ab)

Das Ereignis Bei Maus Ab bzw. MouseDown kann bei Bezeichnungsfeldern, Textfeldern, Optionsgruppen, Kombinationsfeldern, Listenfeldern, Schaltflächen und Objektfeldern eintreten. Es findet vor dem Click-Ereignis statt, wenn die Maustaste über einem Steuerelement ausgelöst wird.

9.4.13

MouseMove (Bei Mausbewegung)

Das Ereignis Bei Mausbewegung bzw. MouseMove gilt für Bezeichnungsfelder, Textfelder, Optionsgruppen, Kombinationsfelder, Listenfelder, Schaltflächen und Objektfelder. Es wird ausgelöst, wenn der Mauszeiger über ein Steuerelement bewegt wird.

9.4.14

MouseUp (Bei Maustaste Auf)

Das Ereignis Bei Maustaste Auf bzw. MouseUp bezieht sich auf Bezeichnungsfelder, Textfelder, Optionsgruppen, Kombinationsfelder, Listenfelder, Schaltflächen und Objektfelder. Es wird vor dem Click-Ereignis ausgelöst, wenn die Maustaste über einem Steuerelement losgelassen wird.

9.4.15

KeyDown (Bei Taste Ab)

Das Ereignis Bei Taste Ab bzw. KeyDown bezieht sich auf Textfelder, Umschaltflächen, Optionsschaltfelder, Kontrollkästchen, Kombinationsfelder, Listenfelder und gebundene Objektfelder. Es ereignet sich, wenn der Benutzer innerhalb eines Steuerelements eine Taste drückt. Es tritt wiederholt auf, bis die Taste wieder freigegeben wird, und kann durch Setzen von KeyCode auf den Wert Zero abgebrochen werden.

354

9.4.16

Kapitel 9: Fortgeschrittene Verwendung von Formularen

KeyUp (Bei Taste Auf)

Das Ereignis Bei Taste Auf bzw. KeyUp bezieht sich auf Textfelder, Umschaltflächen, Optionsschaltfelder, Kontrollkästchen, Kombinationsfelder, Listenfelder und gebundene Objektfelder. Es wird ausgelöst, wenn eine Taste innerhalb eines Steuerelements losgelassen wird. Es tritt nur einmal auf, unabhängig davon, wie lange die Taste gedrückt wird.

9.4.17

KeyPress (Bei Taste)

Das Ereignis Bei Taste bzw. KeyPress bezieht sich auf Textfelder, Umschaltflächen, Optionsschaltfelder, Kontrollkästchen, Kombinationsfelder, Listenfelder und gebundene Objektfelder. Es wird ausgelöst, wenn der Benutzer eine ANSI-Taste drückt und wieder loslässt, während das Steuerelement den Fokus besitzt. Wird KeyCode gleich Zero gesetzt, bricht das Ereignis ab.

9.5

Die Reihenfolge der Steuerelementereignisse

So wie die Formularereignisse beim Öffnen, Aktivieren und bei anderen Operationen in einer bestimmten Reihenfolge auftreten, so finden auch Steuerelementereignisse in einer festgelegten Abfolge statt. Wenn Sie den Ereigniscode für ein Steuerelement schreiben, müssen Sie wissen, in welcher Reihenfolge die Steuerelementereignisse ablaufen.

9.5.1

Was geschieht, wenn ein Steuerelement den Fokus erhält oder abgibt?

Bei der Übergabe des Fokus an ein Steuerelement kommt es zu folgenden Ereignissen: Enter (Beim Hingehen)->GotFocus (Bei Fokuserhalt)

Erfolgt die Übergabe des Fokus an das Steuerelement beim Öffnen des Formulars, laufen die Formular- und Steuerelementereignisse in der folgenden Reihenfolge ab: Open (Beim Öffnen; Formular) ->Activate (Bei Aktivierung; Formular)->Current; Formular->Enter (Beim Hingehen; Steuerelement) ÊGotFocus (Bei Fokuserhalt; Steuerelement)

Gibt das Steuerelement den Fokus ab, treten folgende Ereignisse ein: Exit (Beim Verlassen)->LostFocus (Bei Fokusverlust)

Gibt das Steuerelement den Fokus ab, weil das Formular geschlossen wird, kommt es zu den Ereignissen:

Das Schlüsselwort Me

355

Exit (Beim Verlassen; Steuerelement)->LostFocus (Bei Fokusverlust; Steuerelement)>Unload (Beim Entladen; Formular)->Deactivate (Bei Deaktivierung; Formular)>Close (Beim Schließen; Formular)

9.5.2

Was geschieht beim Aktualisieren der Daten in einem Steuerelement?

Ändern Sie die Daten in einem Steuerelement und verschieben anschließend den Fokus zu einem anderen Steuerelement, treten folgende Ereignisse ein: BeforeUpdate (Vor Aktualisierung)->AfterUpdate (Nach Aktualisierung)->Exit (Beim Verlassen)->LostFocus (Bei Fokusverlust)

Nach der Eingabe eines Zeichens in ein Text- oder Kombinationsfeld finden vor Übergabe des Fokus an ein anderes Steuerelement folgende Ereignisse statt: KeyDown (Bei Taste Ab)->KeyPress (Bei Taste)->Change (Bei Änderung)->KeyUp (Bei Taste Auf)

Bei einem Kombinationsfeld ereignet sich dies nach dem KeyUp-Ereignis, wenn das NotInList-Ereignis ausgelöst wird.

9.6

Das Schlüsselwort Me

Das Schlüsselwort Me gleicht einer implizit deklarierten Variablen. Es steht jeder Prozedur eines Formular- oder Berichtsmoduls zur Verfügung. Mit Me kann sehr gut Code für ein Formular oder einen Bericht verfasst werden. Sie können den Namen des Formulars oder Berichts ändern und der Code bleibt davon unberührt. Ein Beispiel: Me.RecordSource = "qryProjects"

Es ist auch nützlich, Me (das aktuelle Formular bzw. der aktuelle Bericht) an eine generische Prozedur in einem Modul zu übergeben, wie dies im folgenden Beispiel geschieht: Call ChangeCaption(Me)

Die Prozedur ChangeCaption sieht wie folgt aus: Sub ChangeCaption(frmAny As Form) If IsNull(frmAny.Caption) Then frmAny.Caption = "Form for – " & CurrentUser Else frmAny.Caption = frmAny.Caption & " – " & CurrentUser End If End Sub

356

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Die Prozedur ChangeCaption eines Moduls erhält ein beliebiges Formular als Parameter und wertet dann die Überschrift des übergebenen Formulars aus. Hat sie den Wert Null, weist ChangeCaption dem Formular die Beschriftung "Formular für " in Verbindung mit dem Benutzernamen zu. Andernfalls wird an die vorhandene Überschrift der Benutzername angehängt.

9.7

Welche Arten von Formularen kann ich erstellen und wann sind sie geeignet?

Mit Microsoft Access können Sie eine Vielzahl von Formularen erstellen. Wenn Sie mit den verfügbaren Eigenschaften des Formular-Assistenten von Access arbeiten, können Sie Formulare mit unterschiedlichem Erscheinungsbild und verschiedenen Funktionen einrichten. In diesem Kapitel werden die wichtigsten Formulararten beschrieben. Sie können aber selbstverständlich auch eigene Formulare entwerfen. Dabei sollten Sie jedoch auf eine Übereinstimmung mit den Standards für WindowsAnwendungen achten.

9.7.1

Einzelne Formulare: Einen Datensatz zur Zeit betrachten

Eine der gängigsten Formulararten gestattet Ihnen das Betrachten eines einzelnen Datensatzes. Das Formular in Abbildung 9.1 zeigt dem Benutzer beispielsweise einen Kundendatensatz an, von dem aus er bei Bedarf zu anderen Datensätzen wechseln kann.

Abbildung 9.1: Ein einzelnes Formular

Das Erstellen eines einzelnen Formulars ist einfach: wählen Sie für die Eigenschaft Standardansicht einfach den Wert Einzelnes Formular (siehe Abbildung 9.2).

357

Welche Arten von Formularen kann ich erstellen und wann sind sie geeignet?

Abbildung 9.2: Die Eigenschaft Standardansicht des Formulars festlegen

9.7.2

Endlosformulare: Mehrere Datensätze gleichzeitig betrachten

Häufig möchten die Benutzer mehrere Datensätze zur gleichen Zeit betrachten können. Hierfür erstellen Sie ein Endlosformular, wie es in Abbildung 9.3 zu sehen ist. Wählen Sie für die Standardansicht den Eintrag Endlosformular.

Abbildung 9.3: Ein Endlosformular

Oft werden im Zusammenhang mit Endlosformularen Unterformulare verwendet. Im Allgemeinen zeigt ein Unterformular mehrere Datensätze an. Die im Unterformular angezeigten Datensätze beziehen sich alle auf den im Hauptformular enthaltenen Datensatz. Abbildung 9.4 zeigt ein Beispiel mit zwei Unterformularen, deren Eigenschaft Standardansicht auf Endlosformular gesetzt ist. Ein Unterformular zeigt alle Bestellungen eines bestimmten Kunden und ein weiteres alle Einzelheiten einer ausgewählten Bestellung an.

358

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Abbildung 9.4: Ein Formular mit Endlosunterformularen

9.7.3

Mehrseitige Formulare: Wenn nicht alles auf einen Bildschirm passt

Der mangelnde Platz auf dem Bildschirm ist immer ein Problem, das Sie aber mit einem mehrseitigen Formular umgehen können. Die Abbildungen 9.5 und 9.6 zeigen die zwei Seiten des mehrseitigen Personalformulars, welches in der NordwindDatenbank zu finden ist. Wenn Sie das Formular in der Entwurfsansicht betrachten, erkennen Sie ein Steuerelement für einen Seitenumbruch etwa bei der 7-cm-Marke des Formulars (siehe Abbildung 9.7). Um einen Seitenumbruch einzufügen, wählen Sie in der Toolbox das Symbol für den Seitenwechsel. Anschließend klicken Sie auf die Stelle im Formular, an welcher der Umbruch erscheinen soll.

Abbildung 9.5: Die erste Seite eines mehrseitigen Formulars

359

Welche Arten von Formularen kann ich erstellen und wann sind sie geeignet?

Abbildung 9.6: Die zweite Seite eines mehrseitigen Formulars

Abbildung 9.7: Die Entwurfsansicht eines mehrseitigen Formulars

Wenn Sie ein mehrseitiges Formular erstellen, müssen Sie fünf wichtige Schritte beachten: 1. Wählen Sie für die Standardansicht die Option EINZELNES Formular aus. 2. Setzen Sie die Eigenschaft BILDLAUFLEISTEN des Formulars auf NEIN oder NUR HORIZONTAL. 3. Setzen Sie die Größenanpassung auf NEIN. 4. Platzieren Sie den Seitenwechsel genau auf der Hälfte des Detailbereichs, wenn das Formular über zwei Seiten verfügen soll. Möchten Sie mehrere Seiten einrichten, dann teilen Sie die Gesamthöhe des Detailbereichs durch die Anzahl der

360

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Seiten und fügen die Seitenwechsel an den entsprechenden Positionen auf dem Formular ein. 5. Legen Sie die Größe des Formularfensters so fest, dass genau eine Seite des Formulars hineinpasst.

9.7.4

Formulare mit Registerkarten: Für Übersichtlichkeit sorgen

Ein Formular mit Registerkarten stellt eine Alternative zu mehrseitigen Formularen dar. Access 97 und Access 2000 verfügen über ein integriertes Steuerelement für Registerkarten, mit dem Sie auf einfache Weise Gruppen von Steuerelementen zusammenfassen können. Ein Formular mit Registerkarten kann beispielsweise auf einer Registerkarte die Kunden, auf der nächsten die Bestellungen des ausgewählten Kunden und auf einer weiteren Einzelheiten einer bestimmten Bestellung anzeigen. Das Formular in Abbildung 9.8 enthält ein Registerkartensteuerelement. Es handelt sich um das Formular Personal aus der Nordwind-Datenbank. Auf der einen Registerkarte werden die Personaldaten und auf der anderen die persönlichen Daten des Mitarbeiters angezeigt. Hierfür ist keine Programmierung erforderlich.

Abbildung 9.8: Ein mehrseitiges Formular mit Registerkarten

Ein Registersteuerelement hinzufügen und seine Seiten bearbeiten Um einem Formular eine Registerkarte hinzuzufügen, wählen Sie in der Toolbox einfach das Symbol für das Registersteuerelement und legen es auf dem Formular ab. Standardmäßig erscheinen zwei Registerseiten. Um weitere Registerkarten hinzuzufügen, klicken Sie mit der rechten Maustaste auf das Steuerelement und wählen die Option SEITE EINFÜGEN. Möchten Sie eine Registerkarte entfernen, klicken Sie mit der rechten Maustaste auf die entsprechende Registerkarte und wählen die Option SEITE LÖSCHEN. Die Reihenfolge der Registerkarten ändern Sie, indem Sie ebenfalls mit der rechten Maustaste die Karte anklicken und anschließend die Option SEITENREIHENFOLGE wählen.

Welche Arten von Formularen kann ich erstellen und wann sind sie geeignet?

361

Zu Registerkarten Steuerelemente hinzufügen Sie können den Registerkarten in der gleichen Weise Steuerelemente hinzufügen, wie Sie dies auch bei einem Formular tun. Vergessen Sie jedoch nicht, vor dem Hinzufügen der Steuerelemente die Registerkarte durch Anklicken auszuwählen. Wählen Sie keine bestimmte Registerkarte aus, erscheinen die Steuerelemente auf jeder Karte. Die Aktivierreihenfolge von Steuerelementen verändern Die Steuerelemente jeder Registerkarte weisen eine eigene Aktivierreihenfolge auf. Um diese zu ändern, klicken Sie mit der rechten Maustaste auf die Registerkarte und wählen die Option AKTIVIERREIHENFOLGE. Sie können dann die Steuerelemente für die Seite beliebig neu anordnen. Die Eigenschaften des Registersteuerelements verändern Um die Eigenschaften des Registersteuerelements zu ändern, markieren Sie dieses durch Anklicken (damit soll keine bestimmte Seite ausgewählt werden). Ob Sie das Registersteuerelement gewählt haben, können Sie erkennen, wenn in der linken Ecke der Titelleiste des Eigenschaftenfensters REGISTERSTEUERELEMENT angezeigt wird (siehe Abbildung 9.9). Zu den Eigenschaften eines Registersteuerelements gehören der Name, die Schriftart auf den Registerkarten und anderes mehr.

Abbildung 9.9: Die Eigenschaften eines Registersteuerelements

Die Eigenschaften jeder Seite ändern Wählen Sie eine bestimmte Seite des Registersteuerelements aus, um dessen Eigenschaften zu ändern. Sie erkennen die Auswahl wiederum daran, dass in der linken Ecke der Titelleiste des Eigenschaftenfensters SEITE angezeigt wird (siehe Abbildung 9.10). Auf dieser Registerkarte können Sie den Namen der Seite und die Beschriftung eingeben sowie einen Hintergrund einstellen usw.

362

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Abbildung 9.10: Die Eigenschaften der Registerseite

9.7.5

Übersichtsformulare: Ihre Anwendung steuern

Mit einem Übersichtsformular können Sie Ihre Anwendung sehr gut steuern. Ein Übersichtsformular ist ein Formular mit Schaltflächen, mit denen Sie sich zu anderen Übersichtsformularen oder Formularen und Berichten bewegen können, die Ihr System bilden. Abbildung 9.11 enthält ein Übersichtsformular. Der Benutzer kann mit verschiedenen Komponenten der Datenbank arbeiten. Das Übersichtsformular unterscheidet sich von anderen Formularen dadurch, dass sein Zweck allein darin besteht, durch die Anwendung zu führen. Normalerweise ist als Rahmenart DIALOG festgelegt. Bildlaufleisten, Datensatzmarkierer oder Navigationsschaltflächen fehlen meist. Abgesehen von diesen Eigenschaften handelt es sich beim Übersichtsformular um ein ganz normales Formular. Es gibt viele Arten von Navigationsformularen und für welches Sie sich entscheiden, hängt von Ihren Erfordernissen ab.

Abbildung 9.11: Ein Beispiel für ein Übersichtsformular

Welche Arten von Formularen kann ich erstellen und wann sind sie geeignet?

9.7.6

363

Der Begrüßungsbildschirm: Ein professioneller Start einer Anwendung

Begrüßungsbildschirme verleihen Ihren Anwendungen einen professionellen Anstrich und führen den Benutzern etwas vor, während die Anwendung geladen wird. Mit den folgenden Schritten erstellen Sie ein Formular für einen Begrüßungsbildschirm: 1. Erstellen Sie ein neues Formular. 2. Setzen Sie die Eigenschaften Bildlaufleisten, Datensatzmarkierer und Navigationsschaltflächen auf Nein, Größe anpassen und Automatisch zentrieren auf Ja und Rahmenart auf Keine. 3. Setzen Sie die Eigenschaften PopUp und Gebunden auf Ja. 4. Fügen Sie dem Formular ein Bild hinzu und setzen Sie die Eigenschaften für das Bild fest. 5. Ergänzen Sie das Formular nach Bedarf mit geeignetem Text. 6. Setzen Sie die Eigenschaft Zeitgeberintervall auf die Zeit in Sekunden, für die der Begrüßungsbildschirm angezeigt werden soll. 7. Programmieren Sie das Ereignis Timer bzw. Bei Zeitgeber des Formulars für DoCmd.Close. 8. Programmieren Sie das Ereignis Unload bzw. Beim Entladen zum Öffnen Ihres Hauptübersichtsformulars. Da das Timer-Ereignis des Begrüßungsbildschirms das Formular nach dem angegebenen Zeitintervall schließt, entlädt sich der Begrüßungsbildschirm von alleine. Während des Entladens wird das Übersichtsformular geladen. Der Begrüßungsbildschirm ist in der Datenbank CHAP9EX.MDB unter dem Namen frmSplash zu finden. Beim Entladen wird das Formular frmSwitchBoard geöffnet. Sie können das Formular Ihres Begrüßungsbildschirms auch auf andere Weise implementieren. Das Formular kann beispielsweise über ein Startformular aufgerufen werden, dessen Routine für das Ereignis Open bzw. Beim Öffnen einfach nur das Formular des Begrüßungsbildschirms öffnet. Das Problem bei dieser Lösung liegt jedoch darin, dass beim Laden und Entladen des Übersichtsformulars während der Ausführung der Anwendung der Begrüßungsbildschirm noch einmal angezeigt wird. Sie können auch einen Begrüßungsbildschirm anzeigen lassen, der eine BitmapDatei mit dem Namen Ihrer Datenbank aus dem gleichen Verzeichnis der Datenbankdatei enthält. Beim Laden der Anwendung wird dann der Begrüßungsbildschirm für einige Sekunden angezeigt. Der Nachteil dabei ist, dass Sie weniger Steuerungsmöglichkeiten darüber haben, wann und wie lange der Begrüßungsbildschirm angezeigt wird.

364

9.7.7

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Dialogformulare: Informationen sammeln

Dialogformulare dienen üblicherweise dazu, Informationen vom Benutzer einzuholen. Zu Dialogformularen werden sie durch die Tatsache, dass sie gebunden sind. Das bedeutet, dass der Benutzer nicht mit der Anwendung fortfahren kann, bevor er nicht das Formular ausgefüllt hat. Dialogformulare werden im Allgemeinen dann eingesetzt, wenn Sie bestimmte Informationen vom Benutzer benötigen, damit Ihre Anwendung mit der Verarbeitung fortfahren kann. Bei einem benutzerdefinierten Dialogformular handelt es sich um ein normales Formular mit der Rahmenart Dialog, dessen Eigenschaft Gebunden auf Ja gesetzt wurde. Vergessen Sie nicht, eine Möglichkeit einzurichten, das Formular zu schließen, da die Benutzer das gebundene Formular sonst mit dem Klammeraffengriff ((Strg)+(Alt)+(Entf)) oder schlimmer noch mit der (æ)-Taste schließen müssen. Das Formular frmArchivePayments aus der Datenbank CHAP9EX.MDB ist ein Beispiel für ein Dialogformular. Das Festlegen der Eigenschaften Rahmenart auf Dialog und Gebunden auf Ja verhindert zwar, dass der Benutzer außerhalb des Formulars klicken und so die Anwendung fortsetzen kann, die Ausführung des Codes, der das Formular geöffnet hat, wird jedoch nicht angehalten. Angenommen, es soll ein Dialogformular geöffnet werden, um die Parameter für einen Bericht zu erfassen, und anschließend der Bericht mit diesen Parametern geöffnet werden; in diesem Fall muss die OpenForm-Methode zum Öffnen des Formulars die Option acDialog im Argument WindowMode enthalten, da sonst der Code nach der OpenForm-Methode fortgesetzt und der Bericht geöffnet wird, bevor die Parameter vom Benutzer abgefragt wurden.

9.8

Integrierte Dialogfelder

Access verfügt über zwei integrierte Dialogfelder: das Standardmeldungsfeld von Windows und das Eingabedialogfeld. Zum Microsoft Office Developer-Paket gehört das ActiveX-Steuerelement Common Dialog, mit dem Sie Zugriff auf andere typische Dialogfelder haben.

9.8.1

Meldungsfelder

Ein Meldungsfeld ist ein vordefiniertes Dialogfeld, das Sie in Ihre Anwendungen einbinden und mit Hilfe von Parametern anpassen können. VBA verwendet die Anweisung MsgBox (die eine Nachricht nur anzeigt) und die Funktion MsgBox, die eine Nachricht anzeigt und entsprechend einer Benutzerreaktion einen Wert zurückgibt. Das Meldungsfeld von VBA ist das gleiche, welches die meisten Windows-Anwendungen standardmäßig verwenden, so dass es den meisten Benutzern bereits vertraut ist. Anstatt ein eigenes Dialogfeld für Standardantworten erstellen zu müssen, können Sie diese bereits vorhandene Standardschnittstelle benutzen.

Integrierte Dialogfelder

365

Die Funktion MsgBox Die Funktion MsgBox übernimmt fünf Parameter. Der erste enthält die anzuzeigende Nachricht, und der zweite, numerische Parameter gibt an, welche Schaltflächen und Symbole angezeigt werden sollen. Die Tabellen 9.1 und 9.2 enthalten die nummerischen Werte für den zweiten Parameter. Anstelle dieser Werte können Sie auch die vordefinierten Konstanten aus der Tabelle einsetzen. Der dritte Parameter enthält die Beschriftung des Meldungsfelds. Der vierte und fünfte Parameter geben die Hilfedatei und die Kontext-ID an, damit dem Benutzer während der Anzeige des Meldungsfelds Hilfe zur Verfügung steht. MsgBox "Dies ist eine Nachricht", vblnformation, "Dies ist die Überschrift"

In diesem Beispiel werden die Nachricht »Dies ist eine Nachricht« und das Informationssymbol angezeigt. Die Überschrift des Meldungsfelds lautet »Dies ist die Überschrift«. In dem Meldungsfeld befindet sich die Schaltfläche OK, mit der das Dialogfeld geschlossen wird. Die MsgBox-Funktion wird normalerweise nur zum Anzeigen der Schaltfläche OK verwendet. Sie kann aber auch für verschiedene Kombinationen von Standardschaltflächen benutzt werden. Bei dieser Verwendung gibt sie die vom Benutzer gedrückte Schaltfläche zurück. Schaltflächen

Wert

vordefinierte Konstante

Nur OK

0

vbOKOnly

OK und ABBRECHEN

1

vbOKCancel

ABBRECHEN, WIEDERHOLEN und IGNORIEREN

2

vbAbortRetryIgnore

JA, NEIN und ABBRECHEN

3

vbYesNoCancel

JA und NEIN

4

vbYesNo

WIEDERHOLEN und IGNORIEREN

5

vbRetryCancel

Tabelle 9.1: Werte für die anzuzeigenden Schaltflächen

Die Werte aus Tabelle 9.1 müssen zu einem Wert aus der Tabelle 9.2 addiert werden, wenn Sie ein anderes Symbol als das Standardsymbol des Dialogfelds einschließen möchten.

366

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Symbol

Wert

Vordefinierte Konstante

KRITISCH (STOPPZEICHEN)

16

vbCritical

BESTÄTIGUNG (FRAGEZEICHEN)

32

vbQuestion

WARNUNG (!)

48

vbExclamation

INFORMATION (I)

64

vbInformation

Tabelle 9.2: Die Werte für die anzuzeigenden Symbole

Das Meldungsfeld des folgenden Beispiels zeigt die Schaltflächen JA, NEIN und ABBRECHEN an: Sub MessageBoxFunction() Dim intAnswer As Integer intAnswer = MsgBox("Sind Sie sicher?", vbYesNocancel + vbQuestion,_ "Bitte antworten Sie!") End Sub

Dieses Meldungsfeld zeigt auch das Fragezeichen an (siehe Abbildung 9.12). Der Funktionsaufruf gibt mit der Integer-Variablen intAnswer einen Wert zurück.

Abbildung 9.12: Das von der Funktion MsgBox angezeigte Dialogfeld

Mit dem Rückgabewert der Variablen können Sie wie im folgenden Beispiel die entsprechende Reaktion des Programms in Abhängigkeit von der Benutzereingabe festlegen: Sub MessageBoxAnswer() Dim intAnswer As Integer intAnswer = MsgBox("Are You Sure?", vbYesNoCancel + vbQuestion, _ "Please Respond") Select Case intAnswer Case vbYes MsgBox "I'm Glad You are Sure!!" Case vbNo MsgBox "Why Aren't You Sure?" Case vbCancel MsgBox "You Coward! You Bailed Out!!" End Select End Sub

Integrierte Dialogfelder

367

Dieser Code wertet die Antwort des Benutzers aus und zeigt eine entsprechende Nachricht an. In der Praxis würde der Code in der Case-Anweisung selbstverständlich sinnvolleren Zwecken dienen. Tabelle 9.3 führt die Rückgabewerte für die unterschiedlichen Schaltflächen der Funktion MsgBox auf. Antwort

Wert

Vordefinierte Konstante

OK

1

vbOK

Abbrechen

2

vbCancel

Abbruch

3

vbAbort

Wiederholen

4

vbRetry

Ignorieren

5

vbIgnore

Ja

6

vbYes

Nein

7

vbNo

Tabelle 9.3: Die Rückgabewerte der Funktion MsgBox

9.8.2

Eingabefelder

Die Funktion InputBox zeigt ein Dialogfeld mit einem einfachen Textfeld an und gibt den vom Benutzer eingegebenen Text zurück: Sub InputBoxExample() Dim strName As String strName = InputBox("Wie heißen Sie?",_ "Überschrift", "Standardwert") MsgBox "Sie haben eingegeben: " & strName End Sub

Diese Unterroutine zeigt das in Abbildung 9.13 gezeigte Eingabefeld an. Beachten Sie, dass der erste Parameter eine Nachricht, der zweite die Überschrift und der dritte den Standardwert enthält. Der zweite und dritte Parameter sind optional.

Abbildung 9.13: Ein Beispiel für die Verwendung der Funktion InputBox zum Einholen von Informationen

368

9.8.3

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Standardmäßige Dialogfelder

Wie bereits erwähnt wurde, handelt es sich bei dem Steuerelement für standardmäßige Dialogfelder um ein OCX-Steuerelement, welches Bestandteil von ODE ist. Sie können damit standardgemäße Windows-Dialogfelder anzeigen, wie zum Beispiel DATEI SPEICHERN, DATEI ÖFFNEN, DATEI DRUCKEN, DRUCKER EINRICHTEN, SCHRIFTARTEN und FARBEN. Das standardgemäße Steuerelement für Dialogfelder (Common Dialog) wird in Kapitel 25 behandelt.

9.9

Formularen benutzerdefinierte Menüs, Symbolleisten und Kontextmenüs hinzufügen

Sie können unbegrenzt viele eigene Menüs definieren und mit Ihren Formularen und Berichten anzeigen lassen. Jedes Menü kann mit einem oder mehreren Formularen verbunden sein. Oft werden Einschränkungen bezüglich der möglichen Benutzeraktionen während der Bearbeitung eines Formulars oder Berichts vorgenommen. Durch eigene Menüs können Sie die durchführbaren Aktionen einschränken und anpassen.

9.9.1

Ein Menü entwerfen

Vor Access 97 wurde eine benutzerdefinierte Menüleiste dadurch eingerichtet, dass der Eigenschaft MenuBar der Name eines Menüleistenmakros zugewiesen wurde. Diese Funktion wird nur noch aus Gründen der Abwärtskompatibilität unterstützt. In Access 97 und Access 2000 werden benutzerdefinierte Menüleisten, Symbolleisten und Popup-Menüs insgesamt als »Befehlsleisten« bezeichnet. Um eines dieser drei Objekte zu erstellen, wählen Sie ANSICHT|SYMBOLLEISTEN|ANPASSEN. Nachdem Sie eine eigene Menüleiste, eine Symbolleiste oder ein Popup-Menü erstellt haben, können Sie über die Eigenschaften eine Verknüpfung mit Formularen und Berichten herstellen. Mit den folgenden Schritten erstellen Sie eine eigene Menüleiste: 1. Wählen Sie ANSICHT|SYMBOLLEISTEN|ANPASSEN oder klicken Sie mit der rechten Maustaste auf eine beliebige Symbolleiste und wählen Sie die Option ANPASSEN. 2. Im Dialogfeld ANPASSEN wählen Sie auf der Registerkarte SYMBOLLEISTEN die Option NEU (siehe Abbildung 9.14). 3. Wenn Sie der neuen Befehlsleiste einen Namen zuweisen, wird diese anschließend angezeigt. 4. Klicken Sie im Dialogfeld ANPASSEN auf die Schaltfläche EIGENSCHAFTEN, um die Eigenschaften der neu erstellten Symbolleiste anzeigen zu lassen. Benennen Sie Ihre neue Symbolleiste im Dialogfeld SYMBOLLEISTENEIGENSCHAFTEN, wäh-

Formularen benutzerdefinierte Menüs hinzufügen

369

len Sie den Typ und die zulässige Art des Andockens aus und stellen Sie die übrigen Eigenschaften der Befehlsleiste ein. Im aufklappbaren Listenfeld TYP können Sie zwischen den Einträgen SYMBOLLEISTE, MENÜLEISTE und POPUP auswählen. Als Optionen für das Andocken stehen Ihnen ALLE ZULASSEN, ÄNDERUNGEN NICHT MÖGLICH, NICHT VERTIKAL und NICHT HORIZONTAL zur Verfügung. Sie können auch festlegen, ob der Benutzer das Menü oder die Symbolleiste anpassen oder verschieben darf. 5. Wählen Sie die gewünschten Optionen und klicken Sie auf die Schaltfläche SCHLIESSEN.

Abbildung 9.14: Das Dialogfeld Anpassen zum Erstellen einer neuen Befehlsleiste verwenden

Sie können der Symbolleiste, der Menüleiste oder dem Popup-Menü jetzt Elemente hinzufügen. Der Ablauf unterscheidet sich jeweils geringfügig, je nach der Art der Befehlsleiste. Um einer Befehlsleiste Elemente hinzuzufügen, klicken Sie im Dialogfeld ANPASSEN auf die Registerkarte BEFEHLE (siehe Abbildung 9.15). Ziehen Sie die gewünschten Befehlssymbole in die neue Befehlsleiste. Es folgen einige Hinweise, die Ihnen beim Erstellen eigener Menüleisten, Symbolleisten und Popup-Menüs helfen können:

 Um der Menüleiste ein vollständiges, integriertes Menü hinzuzufügen, wählen Sie im Listenfeld KATEGORIEN den Eintrag Eingebaute Menüs. Klicken Sie auf das gewünschte Menü und ziehen Sie dieses aus dem Dialogfeld BEFEHLE hinüber in die Menüleiste Ihres eigenen Menüs.

 Um ein eigenes Menüelement zu erstellen, wählen Sie im Listenfeld KATEGORIEN den Eintrag Neues Menü. Klicken Sie auf die Option NEUES MENÜ und ziehen Sie diese in die Menüleiste. Klicken Sie mit der rechten Maustaste auf das Menü und geben Sie im Textfeld NAME einen Namen ein.

370

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Abbildung 9.15: Der Befehlsleiste mit der Registerkarte Befehle neue Elemente hinzufügen

 Möchten Sie dem Menü einen eingebauten Befehl hinzufügen, dann wählen Sie im Listenfeld KATEGORIE die entsprechende Kategorie aus und ziehen den Befehl in das Menüfeld. Das neue Element erscheint unterhalb der Menüoption.

 Um ein Menü mit einem Trennstrich zu unterteilen, klicken Sie mit der rechten Maustaste auf das Menüelement, welches auf den Trennstrich folgen soll, und wählen GRUPPIERUNG BEGINNEN. Heben Sie die Auswahl des Kontrollkästchens GRUPPIERUNG BEGINNEN wieder auf, wird der Trennstrich wieder entfernt.

 Menüelemente können als Text oder Schaltflächensymbol mit Text angezeigt werden. Wählen Sie die entsprechende Variante, indem Sie mit der rechten Maustaste ein Menüelement anklicken und anschließend eine der Optionen NUR TEXT (IMMER), NUR TEXT (IN MENÜS) oder SCHALTFLÄCHENSYMBOL UND TEXT wählen. Entscheiden Sie sich für eines der verfügbaren Schaltflächensymbole. Möchten Sie das Symbol verändern, klicken Sie mit der rechten Maustaste auf das Menüelement und wählen SCHALTFLÄCHE BEARBEITEN. Dies öffnet das Dialogfeld SCHALTFLÄCHEN-EDITOR (siehe Abbildung 9.16). Möchten Sie den ursprünglichen Zustand eines Schaltflächensymbols wiederherstellen, klicken Sie mit der rechten Maustaste auf das Menüelement und wählen die Option SCHALTFLÄCHE ZURÜCKSETZEN.

 Möchten Sie mehrere Eigenschaften eines Menüelements auf einmal ändern, klicken Sie mit der rechten Maustaste auf das Menüelement und wählen die Option EIGENSCHAFTEN, um das Dialogfeld STEUERELEMENT-EIGENSCHAFTEN zu öffnen (siehe Abbildung 9.17). Hier können Sie die Attribute eines Menüelements wie zum Beispiel die Beschriftung, die QUICKINFO, die Hilfedatei und die Hilfekontext-ID festlegen. Außerdem können Sie mit einem benutzerdefinierten Menüelement auch eine Aktion verknüpfen, was im nächsten Abschnitt beschrieben wird.

Formularen benutzerdefinierte Menüs hinzufügen

371

Abbildung 9.16: Mit dem Schaltflächen-Editor Schaltflächensymbole verändern oder erstellen

Abbildung 9.17: Die Eigenschaften eines Menüelements im Dialogfeld Steuerelement-Eigenschaften bearbeiten

9.9.2

Einen Menüeintrag mit einem Befehl verbinden

Access bietet Ihnen die Möglichkeit, die benutzerdefinierten Menüs mit Hilfe von integrierten Befehlen und Funktionen auf einfache Weise anzupassen. Integrierte Befehle müssen Sie lediglich in die Befehlsleiste ziehen. Damit ein Befehlsleistenelement eine selbst entwickelte Funktion ausführt, müssen Sie ein Element erstellen und dessen Eigenschaften einrichten: 1. Wählen Sie im Listenfeld KATEGORIEN des Dialogfelds ANPASSEN die Kategorie Datei.

372

Kapitel 9: Fortgeschrittene Verwendung von Formularen

2. Klicken Sie die Option BENUTZERDEFINIERT an und ziehen Sie diese aus dem Listenfeld BEFEHLE an die entsprechende Position in Ihrem Menü. 3. Klicken Sie mit der rechten Maustaste auf das neue Menüelement und wählen Sie die Option EIGENSCHAFTEN. 4. Geben Sie den Namen der aufzurufenden Funktion oder Unterroutine im aufklappbaren Listenfeld BEI AKTION ein. Handelt es sich bei der aufzurufenden Prozedur um eine Funktion, müssen Sie dem Funktionsnamen ein Gleichheitszeichen voranstellen und nach dem Funktionsnamen die Parameter in Klammern angeben. 5. Klicken Sie auf die Schaltfläche SCHLIESSEN, um das Dialogfeld STEUERELEMENT-EIGENSCHAFTEN zu schließen. 6. Klicken Sie auf die Schaltfläche SCHLIESSEN, um das Dialogfeld ANPASSEN zu schließen.

9.9.3

Menüs löschen und umbenennen

Über das Dialogfeld ANPASSEN können Sie auch Menüs löschen oder umbenennen. Führen Sie hierzu die folgenden Schritte durch: 1. Klicken Sie mit der rechten Maustaste auf eine Befehlsleiste und wählen Sie die Option ANPASSEN. 2. Markieren Sie im Listenfeld SYMBOLLEISTEN die Befehlsleiste, die Sie löschen oder umbenennen möchten. 3. Klicken Sie auf die Schaltflächen LÖSCHEN oder UMBENENNEN, um die Befehlsleiste zu löschen bzw. umzubenennen.

9.9.4

Programmgesteuerte Befehlsleistenbearbeitung

Sie können Befehlsleisten auch mit Hilfe von VBA-Code hinzufügen, verändern oder entfernen, was Ihren Anwendungen Flexibilität verleiht. So können Sie zum Beispiel eine Befehlsleiste als Reaktion auf unterschiedliche Bedingungen innerhalb der Anwendung verändern. Außerdem können Sie den Benutzern auch die Möglichkeit einräumen, die Befehlsleisten Ihrer Anwendung selbst zu verändern, wie dies am Beispiel des Moduls basExamples aus der Datenbank CHAP9EX.MDB gezeigt wird. Sub CreateCustomCommandBar() On Error Resume Next Dim cbr As CommandBar Dim btn As CommandBarButton Set cbr = CommandBars("My Command Bar") If Err 0 Then Set cbr = CommandBars _ .Add(Name:="My Command Bar", Position:=msoBarTop)

Die integrierten Funktionen zur Formularfilterung ausnutzen

373

End If Set btn = cbr.Controls("Are You Sure?") If Err 0 Then ' Befehlsschaltfläche ist noch nicht vorhanden => Erstellen Set btn = cbr.Controls.Add(msoControlButton, , , , True) End If With btn .Caption = "Are You Sure?" .BeginGroup = True .OnAction = "MessageBoxAnswer" .Style = msoButtonCaption End With End Sub

Dieser Code zeigt, dass Sie über VBA die vollständige Kontrolle über das Menüleistenobjekt haben. Zuerst werden Objektvariablen der Typen CommandBar und CommandBarButton erzeugt. Die CommandBar-Objektvariable wird auf den Wert "My Command Bar" gesetzt. Führt dies zu einem Fehler, dann wissen Sie, dass "My Command Bar" gar nicht existiert. Mit der Methode Add wird die Befehlsleiste hinzugefügt und am oberen Rand des Bildschirms platziert. Anschließend versucht die Routine, auf die Schaltfläche "Sind Sie sicher?" in der Befehlsleiste zu verweisen. Führt dies zu einer Fehlermeldung, wird mit der Add-Methode der Steuerelementeauflistung des CommandBar-Objekts die Befehlsschaltfläche der Auflistung hinzugefügt. Die Beschriftung der Schaltfläche wird auf "Are You sure?" gesetzt, eine Gruppe hinzugefügt und die Aktion der Schaltfläche erhält den Aufruf der Unterroutine MessageBoxAnswer. Für die Anzeige wird festgelegt, dass nur die Beschriftung angezeigt wird.

9.10

Die integrierten Funktionen zur Formularfilterung ausnutzen

Access verfügt über zahlreiche Eigenschaften zum Filtern von Formularen, die Bestandteil der Benutzerschnittstelle sind. Sie können die Eigenschaften in Ihre Anwendung übernehmen, sie vollständig weglassen oder ihr Verhalten steuern. Damit Ihre Anwendung das Verhalten steuern kann, muss sie auf das Filter-Ereignis reagieren, was dadurch geschieht, dass sie erkennt, wann ein Datenfilter in das Formular eingefügt wird. Wurde der Filter erkannt, wird der Code zum Filter-Ereignis ausgeführt. In bestimmten Fällen kann es wünschenswert sein, das Standardverhalten des Filterbefehls zu verändern, vielleicht um einem Benutzer eine spezielle Nachricht anzuzeigen oder mit dem Code eine bestimmte Aktion durchzuführen. Es ist auch möglich, dass die Anwendung auf ein Filter-Ereignis reagieren soll, weil Sie die Anzeige des Formulars vor der Anwendung des Filters ändern möchten. Zum Beispiel können

374

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Sie für einen bestimmten Filter ausgewählte Felder deaktivieren oder verbergen. Wird der Filter entfernt, können Sie wieder zur normalen Ansicht zurückkehren. Access teilt Ihnen nicht nur mit, dass ein Filter-Ereignis eingetreten ist, sondern auch, wie der Filter eingerichtet wurde. Ausgerüstet mit diesen Informationen können Sie den Filter abfangen und dessen Verhalten wie gewünscht ändern. Wählt ein Benutzer die Option FORMULARBASIERTER FILTER oder SPEZIALFILTER/ -SORTIERUNG, erhält der Parameter FilterType einen Wert, der angibt, wie der Filter angewendet werden soll. Wählt der Benutzer die Option FORMULARBASIERTER FILTER, entspricht dieser Wert der Konstanten acFilterByForm, wählt er jedoch die Option SPEZIALFILTER/-SORTIERUNG, dann wird der Parameter der Konstanten acFilterAdvanced gleichgesetzt. Der folgende Code veranschaulicht die Verwendung dieser beiden Konstanten: PRIVATE SUB FORM_FILTER(CANCEL AS INTEGER, FILTERTYPE AS INTEGER)

SELECT CASE FILTERTYPE CASE ACFILTERBYFORM MSGBOX "YOU JUST SELECTED FILTER BY FORM" CASE ACFILTERADVANCED MSGBOX "YOU ARE NOT ALLOWED TO SELECT ADVANCED FILTER/SORT" CANCEL = TRUE END SELECT END SUB

Dieser Code des Filter-Ereignisses wertet die Filterart aus. Wurde die Option FORMULARBASIERTER FILTER gewählt, wird ein Meldungsfeld angezeigt und die Filterung verläuft wie gewöhnlich. Wählt der Benutzer dagegen die Option SPEZIALFILTER/ -SORTIERUNG, wird ihm mitgeteilt, dass dies nicht möglich ist und das Filtern abgebrochen. Sie können nicht nur überprüfen, wie der Filter aufgerufen wurde, sondern auch den Vorgang abfangen, wenn der Filter angewendet wird. Hierfür fügen Sie den folgenden Code in die Routine für das ApplyFilter-Ereignis des Formulars ein: Private Sub Form_ApplyFilter(Cancel As Integer, ApplyType As Integer) Dim intAnswer As Integer If ApplyType = acApplyFilter Then intAnswer = MsgBox("You Selected the Criteria: & _ Chr(13) & Chr(10) & Me.Filter & _ Chr(13) & Chr(10) & Are You Sure You Wish _ to Proceed?", vbYesNo + vbQuestion) If intAnswer = vbNo Then Cancel = True End If End If End Sub

Objekte aus anderen Anwendungen einfügen: Verknüpfen oder Einbetten

375

Dieser Code wertet den Parameter ApplyType aus. Ist der Wert gleich der Konstanten acApplyFilter, wird ein Meldungsfeld angezeigt und der Benutzer gefragt, ob er den Filter anwenden möchte. Bestätigt der Benutzer die Anfrage, wird der Filter angewendet, andernfalls wird das Filtern abgebrochen.

9.11

Objekte aus anderen Anwendungen einfügen: Verknüpfen oder Einbetten

Microsoft Access ist eine ActiveX-Client-Anwendung, was bedeutet, dass AccessAnwendungen Objekte von anderen Anwendungen enthalten können. Access 97 und Access 2000 sind gleichzeitig aber auch ActiveX-Server-Anwendungen. Der Einsatz von Access als ActiveX-Server wird in Kapitel 26 behandelt. Dieses Kapitel behandelt außerdem die Fähigkeit von Access, andere Anwendungen über Code zu steuern. In den folgenden Abschnitten lernen Sie, wie Sie Objekte in Ihr Access-Formular einbetten und mit diesem verknüpfen können.

9.11.1

Gebundene OLE-Objekte

Gebundene OLE-Objekte sind an Daten eines OLE-Felds der Tabelle Ihrer Datenbank gebunden. Ein Beispiel hierfür ist das Feld Foto aus der Tabelle Personal der Nordwind-Datenbank. Der Feldtyp der Tabelle Personal, der Multimediadaten unterstützt, heißt OLE-Objekt. Jeder Datensatz der Tabelle kann ein eigenes OLEObjekt enthalten. Das Formular Personal enthält ein gebundenes OLE-Steuerelement, dessen Steuerelementquelle das Feld Foto der Personal-Tabelle ist. Klicken Sie direkt auf das Foto eines Mitarbeiters, kann das OLE-Objekt direkt bearbeitet werden. Das Bild des Mitarbeiters ist unmittelbar in die Personal-Tabelle eingebettet. Das bedeutet, dass die mit dem OLE-Objekt verbundenen Daten tatsächlich in der Tabelle Personal der Access-Datenbankdatei (MDB) gespeichert werden. Wenn die eingebetteten Objekte den OLE-Standard 2.0 unterstützen, können sie direkt bearbeitet werden. Dieser Vorgang wird »direkte Aktivierung« genannt. Führen Sie die folgenden Schritte durch, um ein neues Objekt einzufügen: 1. Wechseln Sie zu dem Datensatz, der das OLE-Objekt enthalten soll. 2. Klicken mit der rechten Maustaste das OLE-Objekt-Steuerelement an und wählen Sie die Option OBJEKT EINFÜGEN, um das Dialogfeld OBJEKT EINFÜGEN zu öffnen. 3. Wählen Sie einen Objekttyp. Möchten Sie ein eingebettetes Objekt erzeugen, wählen Sie NEU ERSTELLEN. Möchten Sie eine vorhandene Datei einbetten oder verknüpfen, dann wählen Sie AUS DATEI ERSTELLEN. 4. Markieren Sie die Option AUS DATEI ERSTELLEN, ändert sich das Dialogfeld OBJEKT EINFÜGEN und sieht so wie in Abbildung 9.18 aus.

376

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Abbildung 9.18: Das Dialogfeld Objekt einfügen nach dem Markieren der Option Aus Datei erstellen

5. Wenn Sie eine Verknüpfung zu einer vorhandenen Datei erstellen möchten, aktivieren Sie das Kontrollkästchen VERKNÜPFEN. Aktivieren Sie dieses Kontrollkästchen nicht, wenn Sie eine vorhandene Datei einbetten möchten. Wenn Sie die Datei verknüpfen, enthält die Access-Tabelle einen Verweis auf die Datei sowie eine Darstellung der Daten des Objekts (eine Bitmap). Betten Sie die Datei ein, kopiert Access die Originaldatei und platziert die Kopie in der Access-Tabelle. 6. Klicken Sie auf die Schaltfläche DURCHSUCHEN und wählen Sie die einzubettende oder zu verknüpfende Datei aus. 7. Klicken Sie auf OK. Mit einem Doppelklick auf ein verknüpftes Objekt starten Sie die Anwendung, mit der das Objekt erstellt wurde. Zu einer direkten Aktivierung kommt es dabei nicht (siehe Abbildung 9.19).

Abbildung 9.19: Ein verknüpftes Objekt bearbeiten

OpenArgs

9.11.2

377

Ungebundene OLE-Objekte

Ungebundene OLE-Objekte werden nicht in der Datenbank gespeichert. Sie sind stattdessen Bestandteil des Formulars, in dem sie erstellt wurden. Wie die gebundenen können auch die ungebundenen Objekte verknüpft oder eingebettet werden. Ein ungebundenes OLE-Objekt erstellen Sie, indem Sie dem Formular ein ungebundenes Objektfeld hinzufügen.

9.12

OpenArgs

Über die Eigenschaft OpenArgs können Sie einem Formular beim Öffnen Informationen übergeben. Das Argument OpenArgs der Methode OpenForm dient zur inhaltlichen Füllung der OpenArgs-Eigenschaft eines Formulars während der Ausführung. Die Methode funktioniert wie folgt: DoCmd.OpenForm "frmPaymentMethods", _ Datamode:=acFormAdd, _ WindowMode:=acDialog, _ OpenArgs:=NewData

Dieser Code stammt aus dem Formular frmPayments des Zeit- und Abrechnungssytems. Er öffnet das Formular frmPaymentMethods, wenn eine neue Zahlungsart im Kombinationsfeld cboPaymanetMethodID hinzugefügt wird, und sendet dem Formular frmPaymentMethods das OpenArgs-Argument mit den im Kombinationsfeld hinzugefügten Daten. Die Routine zum Ereignis Load des Formulars frmPaymentMethods sieht wie folgt aus: Private Sub Form_Load() If Not IsNull(Me.OpenArgs) Then Me.txtPaymentMethod.Value = Me.OpenArgs End If End Sub

Dieser Code weist dem Textfeld txtPaymentMethod den Wert des beim Öffnen übergebenen Arguments zu. Hierzu kommt es nur, wenn das Formular frmPaymentMethods über das Formular frmPayments geöffnet wird.

9.13

Die Datenherkunft eines Formulars wechseln

Vielen Entwicklern ist nicht klar, wie einfach die Eigenschaft RecordSource (Datenherkunft) eines Formulars während der Ausführung neu gesetzt werden kann. Dieser Vorgang bietet eine gute Möglichkeit, Daten von mehr als einer Tabelle oder Abfrage mit den gleichen Feldern in einem Formular anzeigen zu lassen. Außerdem lassen sich so sehr gut die zu einem bestimmten Zeitpunkt im Formular angezeigten

378

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Daten einschränken. Durch die Technik des Änderns der Eigenschaft RecordSource während der Ausführung kann die Leistung stark verbessert werden, insbesondere bei Client-/Server-Anwendungen (siehe Listing 9.1). Dieses Beispiel stammt aus dem Formular frmShowSales der Datenbank CHAP9EX (siehe Abbildung 9.20).

Abbildung 9.20: Ändern der Eigenschaft RecordSource eines Formulars während der Ausführung Listing 9.1: Ändern der Eigenschaft RecordSource eines Formulars während der Ausführung Private Sub cmdShowSales_Click() 'Enddatum > Anfangsdatum? If Me.txtEndingDate < Me.txtBeginningDate Then MsgBox "The Ending Date must be later than the Beginning Date." txtBeginningDate.SetFocus Exit Sub End If ' '

SQL-Anweisung mit Suchkriterien erstellen und Datenherkunft festlegen

Dim strSQL As String Dim strRestrict As String Dim lngX As Long lngX = Me.optSales.Value strRestrict = ShowSalesValue(lngX) ' SQL-Anweisung erstellen strSQL = "SELECT DISTINCTROW tblCustomers.CompanyName, _ qryOrderSubtotals.OrderID, " strSQL = strSQL & "qryOrderSubtotals.Subtotal , tblOrders.ShippedDate " strSQL = strSQL & "FROM tblCustomers INNER JOIN (qryOrderSubtotals INNER JOIN _

Die Datenherkunft eines Formulars wechseln

379

tblOrders ON " strSQL = strSQL & "qryOrderSubtotals.OrderID = tblOrders.OrderID) ON " strSQL = strSQL & "tblCustomers.CustomerID = tblOrders.CustomerID " strSQL = strSQL & "WHERE (tblOrders.ShippedDate Between Forms!frmShowSales!txtBeginningDate " strSQL = strSQL & "And Forms!frmShowSales!txtEndingDate) " strSQL = strSQL & "And " & strRestrict strSQL = strSQL & " ORDER BY qryOrderSubtotals.Subtotal DESC;" ' Datenherkunft festlegen Me.fsubShowSales.Form.RecordSource = strSQL ' ' ' If

Falls den Kriterien keine Datensätze entsprechen, die Datenherkunft des_ Unterformulars zurücksetzen, eine Meldung anzeigen und den Fokus aufs_ Textfeld BeginningDate bewegen Me.fsubShowSales.Form.RecordsetClone.RecordCount = 0 Then Me.fsubShowSales.Form.RecordSource = "SELECT CompanyName FROM tblCustomers WHERE False;" MsgBox "No records match the criteria you entered.", vbExclamation, "No Records Found" Me.txtBeginningDate.SetFocus Else ' Steuerelement im Detailbereich aktivieren EnableControls Me, acDetail, True ' Einfügemarke auf ShowSalesSubform bewegen Me.fsubShowSales!txtCompanyName.SetFocus End If End Sub Private Function ShowSalesValue(lngOptionGroupValue As Long) As String ' Rückgabewerte wurden in der Optionsgruppe Sales ausgewählt ' Konstanten für Optionsgruppenwerte definieren Const conSalesUnder1000 = 1 Const conSalesOver1000 = 2 Const conAllSales = 3 ' Create restriction based on value of option group. Select Case lngOptionGroupValue Case conSalesUnder1000: ShowSalesValue = "qryOrderSubtotals.Subtotal < 1000" Case conSalesOver1000: ShowSalesValue = "qryOrderSubtotals.Subtotal >= 1000" Case Else ShowSalesValue = "qryOrderSubtotals.Subtotal = True" End Select End Function

380

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Zu Beginn der Routine wird der Wert der Optionsgruppe optSales des Hauptformulars frmShowSales in einer Variablen vom Typ Long Integer gespeichert. Anschließend wird die Funktion ShowSalesValue aufgerufen, die drei Konstanten deklariert. Danach wird der übergebene Parameter ausgewertet (die Variable vom Typ Long Integer mit dem Wert der Optionsgruppe). Anhand dieses Werts wird eine Auswahlzeichenfolge für die Zwischensumme gebildet, die Bestandteil der SQL-Anweisung für die Datenherkunft des Unterformulars wird und den Bereich der im Unterformular angezeigten Verkaufszahlen eingrenzt. Die Routine ShowSales bildet anschließend eine Zeichenfolge mit einer SQL-Anweisung, welche alle erforderlichen Felder der Tabelle tblCustomers und der Abfrage qryOrderSubtotals auswählt. Sie bildet eine WHERE-Klausel, die sowohl txtBeginningDate und txtEndingDate vom Hauptformular als auch den von der Funktion ShowSalesValue als Zeichenfolge zurückgegebenen Wert einschließt. Wenn die SQL-Anweisung zusammengestellt ist, wird die RecordSource-Eigenschaft des Unterformularsteuerelements der SQL-Anweisung gleichgesetzt. Die RecordCount-Eigenschaft von RecordSetClone (der dem Formular zu Grunde liegende Datensatz) wird ausgewertet, um festzustellen, ob irgendein Datensatz die in RecordSource angegebenen Kriterien erfüllt. Hat der Datensatzzähler den Wert Null, werden im Unterformular keine Datensätze angezeigt und der Benutzer wird darauf hingewiesen, dass kein Datensatz die angegebenen Kriterien erfüllt. Werden hingegen Datensätze gefunden, wird der Abschnitt Detail aktiviert und der Fokus dem Unterformular übergeben.

9.14

Fortgeschrittener Umgang mit Kombinationsund Listenfeldern

Kombinations- und Listenfelder sind sehr leistungsfähig. Zu den wichtigsten Fähigkeiten eines erfahrenen Access-Programmierers gehört es daher, korrekt auf das Ereignis NotInList eines Kombinationsfelds zu reagieren, das Kombinationsfeld mit Hilfe von Code zu füllen und mehrere Einträge in einem Listenfeld zu markieren. Diese Fähigkeiten werden in den folgenden Abschnitten behandelt.

9.14.1

Mit dem Ereignis NotInList umgehen

Wie bereits erwähnt, tritt das Ereignis NotInList (Nicht in Liste) auf, wenn ein Benutzer im Textbereich eines Kombinationsfelds Werte eingibt, die sich nicht in dessen Liste befinden. Zu diesem Ereignis kommt es nur, wenn die Eigenschaft LimitToList (Nur Listeneinträge) des Kombinationsfelds den Wert True hat. Es liegt bei Ihnen, ob Sie auf dieses Ereignis reagieren wollen. Es kann sinnvoll sein, nicht nur mit der standardgemäßen Fehlermeldung zu antworten, wenn die LimitToList-Eigenschaft den Wert True hat und der Benutzer versucht, einen Eintrag hinzuzufügen. Gibt der Benutzer beispielsweise bei einer Bestel-

Fortgeschrittener Umgang mit Kombinations- und Listenfeldern

381

lung den Namen eines neuen Kunden ein, sollten Sie mit der Anzeige eines Meldungsfelds reagieren, in dem der Benutzer gefragt wird, ob er wirklich einen neuen Kunden anlegen möchte. Erfolgt darauf eine Bestätigung, können Sie das Kundenformular anzeigen lassen. Nachdem Sie die Eigenschaft LimitToList auf den Wert True gesetzt haben, wird der für das Ereignis NotInList eingefügte Code ausgeführt, wenn der Benutzer versucht, einen Eintrag einzugeben, der nicht in der Liste des Kombinationsfelds enthalten ist. Es folgt ein Beispiel: Private Sub cboPaymentMethodID_NotInList(NewData As String, Response As Integer) If MsgBox("Payment Method Not Found, Add?", _ vbYesNo + vbQuestion, _ "Please Respond") = vbYes Then DoCmd.OpenForm "frmPaymentMethods", _ Datamode:=acFormAdd, _ WindowMode:=acDialog, _ OpenArgs:=NewData If IsLoaded("frmPaymentMethods") Then Response = acDataErrAdded DoCmd.Close acForm, "frmPaymentMethods" Else Response = acDataErrContinue End If Else Response = acDataErrContinue End If End Sub

Dieser Code zum Ereignis NotInList Ihres Kombinationsfelds zeigt ein Meldungsfeld an, mit dem der Benutzer gefragt wird, ob er die Zahlungsart hinzufügen möchte. Wird dies abgelehnt, kehrt er ohne Standardfehlermeldung wieder zum Formular zurück, muss aber nach wie vor einen gültigen Wert in das Kombinationsfeld eintragen. Bestätigt der Benutzer die Anfrage, wird ihm das Formular frmPaymentMethods angezeigt, um die Zahlungsart hinzuzufügen. Die Prozedur NotInList akzeptiert ein Argument mit einer Antwort, mit dem Sie VBA mitteilen können, was nach der Ausführung des Codes geschehen soll. Eine der drei folgenden Konstanten kann als Antwort mit dem Argument übergeben werden:

 acDataErrAdded – Diese Konstante wird benutzt, wenn der neue Wert in die Datenherkunft des Kombinationsfelds eingefügt werden soll. Zum Hinzufügen des neuen Wertes in die Liste wird das Kombinationsfeld benötigt.

 acDataErrDisplay – Diese Konstante wird verwendet, wenn VBA die Standardfehlermeldung anzeigen soll.

382

Kapitel 9: Fortgeschrittene Verwendung von Formularen

 acDataErrContinue – Mit dieser Konstanten wird die VBA-eigene Fehlermeldung unterdrückt und die von Ihnen vorgegebene angezeigt. Access benötigt aber dennoch einen gültigen Eintrag im Kombinationsfeld.

9.14.2

Popup-Formulare

Die gerade beschriebene NotInList-Technik benutzt ein Popup-Formular. Gibt der Benutzer an, dass er die neue Zahlungsart hinzufügen möchte, wird das Formular frmPaymentMethods gebunden angezeigt. Dadurch wird die Ausführung des Codes in dem Formular angehalten, welches das Formular frmPaymentsMethod lädt. (In diesem Fall ist dies das Formular frmPayments.) Das Formular frmPaymentsMethod kann als Popup-Formular betrachtet werden, weil es gebunden ist und Informationen vom Formular frmPayments verwendet und das Formular frmPayments entweder auf die Schaltfläche OK oder auf die Schaltfläche ABBRECHEN reagiert. Der Code zum Ereignis Load des Formulars frmPaymentMethods des Zeit- und Abrechnungssystems sieht wie folgt aus: Private Sub Form_LOad() Me.txtPaymentMethod.Value = Me.OpenArgs End Sub

Dieser Code nutzt die als Argument erhaltenen Informationen zum Füllen des Textfelds txtPaymentMethod. Die Ausführung des Codes wird erst fortgesetzt, wenn der Benutzer die Schaltfläche OK oder CANCEL klickt. Wurde die Schaltfläche OK betätigt, wird folgender Code ausgeführt: Private Sub cmdOK_Click() Me.Visible = False End Sub

Beachten Sie, dass hier das Formular frmPaymentsMethod verborgen und nicht geschlossen wird. Nach Anklicken der Schaltfläche CANCEL, wird der folgende Code ausgeführt: Private Sub cmdCancel_Click() DoCmd.RunCommand acCmdUndo DoCmd.Close End Sub

Der mit der Schaltfläche CANCEL verbundene Code macht zuerst die vom Benutzer durchgeführten Veränderungen rückgängig. Anschließend wird das Formular frmPaymentMethods geschlossen. Bei Rückkehr zum NotInList-Ereignis des Kombinationsfelds cboPaymentMethod des Formulars frmPayments wird folgender Code ausgeführt: If IsLoaded("frmPaymentMethods") Then Response = acDataErrAdded DoCmd.Close acForm, "frmPaymentMethods"

Fortgeschrittener Umgang mit Kombinations- und Listenfeldern

383

Else Response = acDataErrContinue End If

Es wird überprüft, ob das Formular frmPaymentMethods noch geladen ist. Ist dies der Fall, muss der Benutzer auf die Schaltfläche OK geklickt haben. Der Response-Parameter wird mit acDataErrAdded gleichgesetzt, was anzeigt, dass der neue Eintrag in das Kombinationsfeld und die zu Grunde liegende Datenquelle eingefügt wurde. Abschließend wird das Formular frmPaymentMethods geschlossen. Ist das frmPaymentMethods-Formular nicht geladen, muss der Benutzer die Schaltfläche CANCEL angeklickt haben. Der Benutzer kehrt zum Kombinationsfeld zurück, wo er einen anderen Eintrag wählen muss. Die einzelnen Schritte lassen sich wie folgt zusammenfassen: 1. Das Popup-Formular wird gebunden geöffnet (wobei der Parameter WindowMode der Konstanten acDialog gleichgesetzt ist). 2. Gegebenenfalls wird der Parameter OpenArgs übergeben. 3. Bei Rückgabe eines Wertes an das ursprüngliche Formular wird überprüft, ob das Popup-Formular noch geladen ist. 4. Ist dies der Fall, werden die Informationen verwendet und das Formular anschließend geschlossen.

9.14.3

Ein Kombinations- oder Listenfeld mit Hilfe einer CallbackFunktion ausfüllen

Wie Sie wissen, kann ein Kombinationsfeld leicht durch Setzen der Eigenschaften des Steuerelements ausgefüllt werden. In den meisten Situationen reicht diese Maßnahme aus. Manchmal ist es jedoch erforderlich, ein Kombinationsfeld oder Listenfeld über das Programm etwa mit Hilfe von Werten eines Felds auszufüllen. Außerdem kann es notwendig sein, das Feld mit Tabellen- oder Berichtsnamen oder anderen Datenbankbestandteilen zu füllen. Um ein Kombinations- oder Listenfeld mit Hilfe von Code füllen zu können, erstellen Sie eine Callback-Funktion, die Access mitteilt, wie viele Zeilen und Spalten das Kombinations- oder Listenfeld enthalten soll und mit welchen Daten das Feld gefüllt wird. Dieser Funktion wird der Typ der Zeilenquellen für das Kombinations- oder Listenfeld übergeben. Access ruft diese Funktion auf und benutzt die Rückgabewerte zum Ausfüllen des Kombinations- oder Listenfelds. Das Beispiel in Listing 9.2 finden Sie im Formular frmSendToExcel der CHAP9EX-Datenbank. Listing 9.2: Ein Listenfeld mit Hilfe einer Callback-Funktion ausfüllen Function FillWithTableList(ctl As Control, vntID As Variant, _ lngRow As Long, lngCol As Long, intCode As Integer) _ As Variant

384

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Dim cat As ADOX.Catalog Dim tdf As ADOX.Table Dim qdf As ADOX.View Dim intCounter As Integer Static sastrTables() As String Static sintNumTables As Integer Dim varRetVal As Variant varRetVal = Null Select Case intCode Case acLBInitialize ' Initialisierung Set cat = New ADOX.Catalog cat.ActiveConnection = CurrentProject.Connection 'Die Gesamtanzahl der Tabellen und Abfragen ermitteln sintNumTables = cat.Tables.Count + cat.Views.Count ReDim sastrTables(sintNumTables – 2) ' Jede Tabelle ermitteln und den Namen dem Listenfeld hinzufügen For Each tdf In cat.Tables If Left(tdf.Name, 4) "MSys" Then sastrTables(intCounter) = tdf.Name intCounter = intCounter + 1 End If Next tdf ' Jede Abfrage ermitteln und den Namen dem Listenfeld hinzufügen For Each qdf In cat.Views sastrTables(intCounter) = qdf.Name intCounter = intCounter + 1 Next qdf varRetVal = sintNumTables Case acLBOpen Öffnen varRetVal = Timer 'Eindeutige ID für Steuerelement erzeugen Case acLBGetRowCount 'Anzahl der Zeilen bestimmen varRetVal = sintNumTables Case acLBGetColumnCount 'Anzahl der Spalten bestimmen varRetVal = 1 Case acLBGetColumnWidth 'Spaltenbreite bestimmen varRetVal = -1 '-1 erzwingt Standardbreite Case acLBGetValue 'Daten empfangen varRetVal = sastrTables(lngRow) End Select FillWithTableList = varRetVal End Function

Die Funktion muss fünf vordefinierte Argumente enthalten, von denen das erste ein Steuerelement und die übrigen vom Typ Variant sein müssen. Die Funktion selbst muss einen Variant-Wert zurückgeben. Tabelle 9.4 führt die Parameter auf.

Fortgeschrittener Umgang mit Kombinations- und Listenfeldern

Argument

Beschreibung

fld

Eine Steuerelementvariable, die sich auf das zu füllende Kombinationsoder Listenfeld bezieht

id

Ein eindeutiger Wert, der das zu füllende Steuerelement angibt. Dieses Argument ist nützlich, wenn Sie mehr als nur ein Kombinations- oder Listenfeld mit der gleichen Funktion ausfüllen.

row

Die auszufüllende Zeile (auf Null basierend)

col

Die auszufüllende Spalte (auf Null basierend)

code

Ein Wert, der die gesuchte Information angibt

385

Tabelle 9.4: Die fünf vordefinierten Argumente einer Funktion Callback

Die List-Funktion wird mehrmals aufgerufen. Bei jedem Aufruf stellt Access automatisch einen anderen Wert mit der angeforderten Information für den Code bereit. Die Kodierung wird mit den in Tabelle 9.5 aufgeführten Werten durchgeführt. Code

vordefinierte Konstante

Beschreibung

Rückgabewert

0

acLBInitialize

Initialisieren

Ungleich Null, wenn die Funktion die Liste füllen kann. False oder Null, wenn es Probleme gibt

1

acLBOpen

Öffnen

Ein ID-Wert ungleich Null, wenn die Funktion die Liste füllen kann. False oder Null, wenn es Probleme gibt

3

acLBGetRowCount

Anzahl der Zeilen

Anzahl der Zeilen der Liste

4

acLBGetColumnCount

Anzahl der Spalten

Anzahl der Zeilen der Spalte

5

acLBGetColumnWidth

Spaltenbreite

Die Breite der angegebenen Spalte

6

acLBGetValue

Listeneintrag

Der Listeneintrag, der in der angegebenen Zeile und Spalte angezeigt wird

7

acLBGetFormat

Formatierungszeichenfolge

Formatierungszeichenfolge für die Formatierung des Listeneintrags

Tabelle 9.5: Bedeutung der Kodierungen

386

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Code

vordefinierte Konstante

Beschreibung

Rückgabewert

8

acLBClose

Wird nicht verwendet

9

acLBEnd

Ende (letzter Aufruf) Keiner

Tabelle 9.5: Bedeutung der Kodierungen (Forts.)

Die Funktion wird für die Codes 0, 1, 3 und 4 einmal automatisch aufgerufen. Diese Aufrufe initialisieren den Prozess und legen die Anzahl der Zeilen und Spalten des Kombinations- oder Listenfelds fest. Beim Code 5 wird die Funktion zweimal aufgerufen: einmal, um die Gesamtbreite des Felds zu bestimmen, und ein zweites Mal, um die Spaltenbreite festzulegen. Wie oft der Aufruf bei den Codes 6 und 7 erfolgt, hängt von der Anzahl der Zeilen des Felds ab (Code 3). Code 9 wird aufgerufen, wenn das Formular geschlossen oder das Kombinations- oder Listenfeld abgefragt wird. Ausgestattet mit diesem Wissen können Sie einen Blick auf die Funktion FillWithTableList werfen, bei der es sich um die Callback-Funktion zum Ausfüllen des Listenfelds handelt. Aufgabe dieser Funktion ist es, das Listenfeld mit einer Liste der Tabellen und Abfragen der aktuellen Datenbank zu füllen. Wählt der Benutzer eine Tabelle oder Abfrage aus und klickt dann auf die Schaltfläche SEND TO EXCEL, werden die Daten der ausgewählten Tabelle oder Abfrage an Excel gesendet. Die Callback-Funktion verwendet ADO-Code zum Zählen aller in der aktuellen Datenbank gefundenen Tabellen und Abfragen. ADOs (ActiveX-Datenobjekte) werden in Kapitel 12 behandelt. Jedes Element der Case-Struktur dieser Routine wird aufgerufen, wenn der entsprechende Code von Access gesendet wird. Dabei geschieht Folgendes: 1. Sendet Access den Code 0, werden die Tabellen und Ansichten gezählt. Die Routine durchläuft in einer Schleife jede Tabelle und Abfrage der Datenbank. Handelt es sich nicht um eine Systemtabelle, wird der Name dem Feld sastrTables hinzugefügt. Der Rückgabewert der Funktion entspricht der Anzahl der Tabellen und Abfragen der Datenbank. 2. Sendet Access den Code 1, ist der Rückgabewert ein eindeutiger Wert, der dem Rückgabewert der Timer-Funktion entspricht. 3. Wenn Access den Code 3 sendet, wird der Rückgabewert der Anzahl der Tabellen und Abfragen der Datenbank gleichgesetzt. 4. Beim Code 4 wird der Rückgabewert auf 1 gesetzt (eine Spalte). 5. Code 5 setzt den Rückgabewert gleich -1 und legt damit eine Standardbreite für das Kombinations- oder Listenfeld fest.

Fortgeschrittener Umgang mit Kombinations- und Listenfeldern

387

6. Den Code 6 ruft Access anschließend entsprechend des Rückgabewertes für die Anzahl der Zeilen des Kombinations- oder Listenfelds automatisch auf. Bei jedem Aufruf von Code 6 wird die Objektvariable des Formulars einem anderen Element der Formularauflistung gleichgesetzt. Die Funktion gibt den Namen der Tabelle oder Abfrage zurück. Der Name der Tabelle oder Abfrage ist der Wert, welcher dem Listenfeld hinzugefügt wird. Auf den ersten Blick mag das alles etwas kompliziert erscheinen. Wenn Sie aber erst einmal mehrere Kombinations- oder Listenfelder gefüllt haben, werden Sie sehen, dass es doch recht einfach ist. Sie müssen lediglich die Case-Struktur der Funktion FillWithTableList kopieren und als Vorlage für alle Ihre Callback-Routinen verwenden.

9.14.4

Mehrfachauswahl in einem Listenfeld

Die Listenfelder von Access 97 und Access 2000 verfügen über eine Eigenschaft für die Mehrfachauswahl. Hat sie den Wert True, kann der Benutzer mehrere Elemente eines Listenfelds auswählen. Das Programm kann anschließend auswerten, welche Elemente ausgewählt wurden und mit diesen Aktionen durchführen. Das Formular frmReportEngine aus der Datenbank CHAP9EX enthält ein Beispiel für die Mehrfachauswahl in einem Listenfeld. Listing 9.3 enthält den Code für das Ereignis Click der Schaltfläche RUN REPORTS. Listing 9.3: Ermitteln der ausgewählten Elemente eines Listenfelds für die Mehrfachauswahl Private Sub cmdRunReports_Click() Dim varItem As Variant Dim lst As ListBox Set lst = Me.lstReports ' Die Einfachauswahl hat den Wert 0, die Mehrfachauswahl den Wert 1 ' und die erweiterte Mehrfachauswahl den Wert 2 If lst.MultiSelect > 0 Then ' Alle Elemente der ItemSelected-Auflistung durchsuchen und über das ' Spaltenfeld die zugehörigen Werte ermitteln If lst.ItemsSelected.Count > 0 Then For Each varItem In lst.ItemsSelected DoCmd.OpenReport lst.ItemData(varItem), acViewPreview Next varItem End If End If End Sub

Zuerst wird überprüft, ob es sich um ein Listenfeld für die Mehrfachauswahl handelt. Trifft dies zu und wurde mindestens ein Bericht ausgewählt, werden alle Listeneinträge in einer Schleife durchsucht und jeder ausgewählte Bericht anschließend angezeigt.

388

9.15

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Fortgeschrittener Umgang mit Unterformularen

Viele unerfahrene Access-Programmierer verstehen die Zusammenhänge für das Erstellen und Verändern eines Unterformulars sowie für das Verweisen auf die Steuerelemente des Unterformulars nicht. Sie sollten deshalb die folgenden wichtigen Punkte berücksichtigen, wenn Sie mit Unterformularen arbeiten:

 Der einfachste Weg, einem Hauptformular ein Unterformular hinzuzufügen, besteht darin, das Hauptformular zu öffnen und anschließend das Unterformular in das Hauptformular zu ziehen.

 Die Eigenschaften LinkChildFields (Verknüpfen von) und LinkMasterFields (Verknüpfen nach) des Unterformulars legen fest, welche Felder des Hauptformulars mit welchen Feldern des Unterformulars verknüpft werden. Für diese Eigenschaften kann ein einzelner Feldname oder eine durch Semikolons getrennte Liste angegeben werden. Bei richtiger Angabe sorgen diese Eigenschaften dafür, dass alle Datensätze des Unterformulars sich auf den gerade angezeigten Datensatz des Hauptformulars beziehen.

9.15.1

Die Steuerelemente in Unterformularen ansprechen

Vielen Programmierern ist nicht klar, wie man die Steuerelemente eines Unterformulars richtig anspricht. Sie müssen jedes Objekt eines Unterformulars über das Steuerelement des Unterformulars im Hauptformular ansteuern, wie dies im folgenden Beispiel geschieht: Forms.frmCustomer.fsubOrders

Dieses Beispiel bezieht sich auf das Steuerelement fsubOrders des Formulars frmCustomer. Möchten Sie ein bestimmtes Steuerelement des Unterformulars fsubOrders ansprechen, dann können Sie auf die Auflistung der Steuerelemente des Unterformulars verweisen: Forms.frmCustomer.fsubOrders!txtOrderID

Sie können sich auch implizit auf das Steuerelement des Unterformulars beziehen: Forms!frmCustomer!fsubOrders!txtOrderID

Beide Möglichkeiten sprechen das Steuerelement txtOrderID im Formular des fsubOrder-Steuerelements auf dem Formular frmCustomer an. Um eine Eigenschaft dieses Steuerelements zu verändern, können Sie den Ausdruck wie folgt ergänzen: Forms.frmCustomer.fsubOrders!txtOrderID.Enabled = False

Mit dieser Zeile wird der Wert der Eigenschaft Enabled des txtOrdersID-Steuerelements im Formular des fsubOrders-Steuerelements auf den Wert False gesetzt.

Ein Formular mit der zu Grunde liegenden Datensatzgruppe in Einklang bringen

9.16

389

Ein Formular mit der zu Grunde liegenden Datensatzgruppe in Einklang bringen

Die Eigenschaft RecordSetClone eines Formulars dient zum Verweis auf die zu Grunde liegende Datensatzgruppe. Sie können diese Datensatzgruppe unabhängig davon verändern, was augenblicklich im Formular angezeigt wird. Ein Beispiel: Private Sub cboCompany_AfterUpdate() Me.RecordsetClone.FindFirst "[ClientID] = " & cboCompany.Value If Me.RecordsetClone.NoMatch Then MsgBox "Client Not Found" Else Me.Bookmark = Me.RecordsetClone.Bookmark End If End Sub

In diesem Beispiel wird die Methode FindFirst zur Verwendung mit der Eigenschaft RecordSetClone des Formulars aufgerufen. Die Methode sucht in der dem Formular zu Grunde liegenden Datensatzgruppe nach einem Datensatz, dessen ClientID gleich dem aktuellen Wert des Kombinationsfelds ist. Findet die Methode eine Übereinstimmung, wird das Lesezeichen des Formulars mit dem Lesezeichen der dem Formular zu Grunde liegenden Datensatzgruppe gleichgesetzt. Dieser Code kann auch durch Verwendung einer Objektvariablen zum Verweis auf RecordSetClone umgeschrieben werden: Private Sub cboCompany_AfterUpdate() Dim rs As DAO.Recordset Set rs = Me.RecordsetClone rs.FindFirst "[ClientID] = " & cboCompany.Value If rs.NoMatch Then MsgBox "Client Not Found" Else Me.Bookmark = Me.RecordsetClone.Bookmark End If End Sub

Dieser Code erzeugt eine Objektvariable, die auf die Eigenschaft RecordSetClone des Formulars verweist. Die Objektvariable der Datensatzgruppe kann durch Me.RecordSetClone ersetzt werden, weil sie auf den dem Formular zu Grunde liegenden Datensatz verweist.

390

9.17

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Benutzerdefinierte Eigenschaften und Methoden erstellen

Formulare und Berichte werden als »Klassenmodule« bezeichnet, was bedeutet, dass sie als Vorlagen für Objekte dienen, die Sie während der Ausführung als Instanzen erstellen. Öffentliche Prozeduren eines Formulars oder Berichts werden während der Ausführung zu benutzerdefinierten Eigenschaften und Methoden des Formularobjekts. Mit Hilfe von VBA-Code können Sie die Werte der benutzerdefinierten Eigenschaften des Formulars festlegen und deren Methoden ausführen.

9.17.1

Benutzerdefinierte Eigenschaften erstellen

Benutzerdefinierte Eigenschaften eines Formulars oder Berichts können auf zwei Arten erstellt werden:

 Sie erstellen für das Formular oder den Bericht öffentliche Variablen.  Sie erstellen die PropertyLet- und PropertyGet- Routinen. Eine öffentliche Variable als Formulareigenschaft erstellen und verwenden Mit den folgenden Schritten erstellen Sie eine benutzerdefinierte Formular- oder Berichtseigenschaft, die auf einer öffentlichen Variablen beruht, und greifen auf diese zu. Das Beispiel ist in den Formularen frmPublicProperties und frmChangePublicProperty der Datenbank CHAP9EX zu finden. 1. Erstellen Sie zuerst ein Formular für die benutzerdefinierte Eigenschaft (öffentliche Variable). 2. Platzieren Sie eine öffentliche Variable im Abschnitt Allgemeine Deklarationen des Formulars oder Berichts (siehe Abbildung 9.21).

Abbildung 9.21: Im Abschnitt Allgemeine Deklarationen eines Klassenmoduls eine öffentliche Variable erstellen

Benutzerdefinierte Eigenschaften und Methoden erstellen

391

3. Fügen Sie in dem Formular oder Bericht Code für den Zugriff auf die öffentliche Variable ein. Der Code in Abbildung 9.21 erzeugt eine öffentliche Variable mit dem Namen CustomCaption. Der Code zum Ereignis Click der Schaltfläche cmdChangeCaption weist der Caption-Eigenschaft des Formulars frmPublicProperties den Wert der öffentlichen Variablen zu. 4. Erstellen Sie ein Formular, einen Bericht oder ein Modul, mit dem der Wert der benutzerdefinierten Eigenschaft verändert wird. Abbildung 9.22 zeigt ein Formular mit dem Namen frmChangePublicProperty.

Abbildung 9.22: Die Ansicht des Formulars frmChangePublicProperty

5. Fügen Sie den Code hinzu, der den Wert der benutzerdefinierten Eigenschaft verändert. Der Code für die in Abbildung 9.21 gezeigte Schaltfläche cmdChangeCaption verändert den Wert der benutzerdefinierten Eigenschaft CustomCaption des Formulars frmPublicProperties. Um die benutzerdefinierte Eigenschaft des vorangegangenen Beispiels zu testen, führen Sie das Formular frmPublicProperties aus der Datenbank CHAP9EX.MDB auf der beiliegenden CD-ROM aus. Wenn Sie auf die Schaltfläche CHANGE FORM CAPTION klicken, passiert gar nichts, weil der Wert für die benutzerdefinierte Eigenschaft nicht gesetzt wurde. Öffnen Sie das frmChangePublicProperty-Formular und klicken Sie auf die Schaltfläche CHANGE FORM PROPERTY. Kehren Sie dann zum Formular frmChangePublicProperties zurück und klicken Sie noch einmal die Schaltfläche CHANGE FORM CAPTION. Jetzt sollte sich die Überschrift des Formulars verändern. Schließen Sie das Formular frmPublicProperties und versuchen Sie die Schaltfläche CHANGE FORM PROPERTY zu klicken. Es kommt zu einem Laufzeitfehler mit dem Hinweis, dass das angesprochene Formular nicht geöffnet ist. Mit dem folgenden Code für das Click-Ereignis von cmdPublicFormProperty können Sie diesen Fehler entfernen:

392

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Private Sub cmdPublicFormProperty_Click() Form_frmPublicProperties.CustomCaption = _ "This is a Custom Caption" Forms!frmPublicProperties.Visible =True End Sub

Dieser Code verändert mit der Syntax Formular_Formularname.Eigenschaft den Wert der Public-Eigenschaft. Ist das Formular nicht geladen, wird dies nachgeholt, das Formular bleibt aber verborgen. Die nächste Anweisung weist der Eigenschaft Visible den Wert True zu. Mit den PropertyLet- und PropertyGet-Routinen benutzerdefinierte Eigenschaften erstellen und verwenden Eine PropertyLet-Routine ist eine spezielle Unterroutine, die immer dann automatisch ausgeführt wird, wenn der Wert der Eigenschaft verändert wird. Auch eine PropertyGet-Routine ist eine spezielle Routine, die jedesmal automatisch ausgeführt wird, wenn der Wert der benutzerdefinierten Eigenschaft benötigt wird. Die Eigenschaft wird nicht mit Hilfe einer öffentlichen Variablen erstellt, sondern durch Einfügen zweier spezieller Routinen: PropertyLet und PropertyGet. Dieses Beispiel finden Sie in den Formularen frmPropertyGetLet und frmChangeWithLet der Datenbank CHAP9EX.MDB. Führen Sie die folgenden Schritte durch, um die PropertyLet- und PropertyGet-Routinen einzufügen: 1. Wählen Sie EINFÜGEN|PROZEDUR. Dies öffnet das in Abbildung 9.23 gezeigte Dialogfeld. 2. Geben Sie im Textfeld NAME den Namen der Prozedur ein. 3. Markieren Sie im Abschnitt TYP die Option PROPERTY. 4. Wählen Sie als Gültigkeitsbereich PUBLIC, damit die Eigenschaft außerhalb des Formulars sichtbar ist. 5. Klicken Sie auf OK. Die PropertyGet- und PropertyLet-Unterroutinen werden nun in das Modul eingefügt (siehe Abbildung 9.24). Beachten Sie, dass der Code zum Ereignis Click für die Schaltfläche cmdChangeCaption nicht verändert wurde. Die PropertyGet-Routine, die immer dann automatisch ausgeführt wird, wenn sich der Wert der Eigenschaft CustomCaption verändert, übernimmt einen Wert in Großbuchstaben und platziert diesen in einer privaten Variablen mit dem Namen mstrCustomCaption. Die PropertyGet-Routine nimmt den Wert der privaten Variablen und gibt dem Anfragenden den Wert der Eigenschaft zurück. Die Abfolge der Ereignisse lautet wie folgt (der Code gehört zum Formular frmChangeWithLet): Private Sub cmdPublicFormProperty_Click() Form_frmPropertyGetLet.CustomCaption = "This is a Custom Caption" Forms!frmPropertyGetLet.Visible = True End Sub

393

Benutzerdefinierte Eigenschaften und Methoden erstellen

Abbildung 9.23: Eine neue Prozedur mit dem Dialogfeld Prozedur hinzufügen einfügen

Abbildung 9.24: Mit dem Dialogfeld Prozedur hinzufügen erstellte Unterroutinen

Diese Routine versucht, der benutzerdefinierten Eigenschaft CustomCaption den Wert "This is a Custom Caption" zuzuweisen. Da sich der Wert der Eigenschaft ändert, wird die PropertyLet-Routine des Formulars frmPropertyGetLet automatisch ausgeführt: Public Property Let CustomCaption(ByVal CustomCaption As String) mstrCustomCaption = UCase$(CustomCaption) End Property

Die PropertyLet-Routine erhält den Wert "This is a Custom Caption" als Parameter. Sie verwendet die UCase-Funktion, um den übergebenen Wert zu bearbeiten und in Großbuchstaben umzuwandeln. Anschließend wird der bearbeitete Wert der privaten Variablen mstrCustomCaption zugewiesen. Die PropertyGet-Routine wird nicht eher ausgeführt, ehe der Benutzer nicht im Formular frmPropertyGetLet auf die

394

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Schaltfläche cmdChangeCaption klickt. Der Code zum Ereignis Click der Schaltfläche cmdChangeCaption sieht wie folgt aus: Private Sub cmdChangeCaption_Click() Me.Caption = CustomCaption End Sub

Da diese Routine den Wert der benutzerdefinierten Eigenschaft CustomCaption benötigt, wird die PropertyGet-Routine automatisch ausgeführt: Public Property Get CustomCaption() As String CustomCaption = mstrCustomCaption End Property

Die PropertyGet-Routine übernimmt den Wert der privaten Variablen, die von der PropertyLet-Routine zugewiesen wurde, und gibt ihn als Wert der Eigenschaft zurück. Sie werden sich vielleicht fragen, warum diese Lösung der Deklaration einer öffentlichen Variablen vorzuziehen ist. Die Verwendung der UCase-Anweisung innerhalb von PropertyLet sollte dies eigentlich deutlich machen. Bei Verwendung einer öffentlichen Variablen können Sie nicht viel tun, um den übergebenen Wert zu überprüfen oder zu verändern. Die PropertyLet-Routine bietet Ihnen jedoch die Möglichkeit, den Wert der Eigenschaft zu überprüfen und zu verändern. Da die veränderte Variable einer privaten Variablen zugewiesen und anschließend der Wert der privaten Variablen für die Rückgabe der Eigenschaft benötigt wird, haben Sie die vollständige Kontrolle darüber, was intern mit der Eigenschaft geschieht. Dieser Abschnitt bietet nur eine Einführung zu den benutzerdefinierten Eigenschaften und Methoden. Eine ausführliche Diskussion der benutzerdefinierten Klassen, Eigenschaften und Methoden finden Sie in Kapitel 28.

9.17.2

Benutzerdefinierte Methoden erstellen

Benutzerdefinierte Methoden sind öffentliche Funktionen und Unterroutinen eines Formular- oder Berichtsmoduls. Wie Sie noch erfahren werden, können sie mit der Syntax Objekt.Methode aufgerufen werden. Mit den folgenden Schritten wird eine benutzerdefinierte Methode erstellt (Sie finden die Beispiele in den Formularen frmMethods und frmExecuteMethod der Datenbank CHAP9EX): 1. Öffnen Sie den Bericht oder das Formular, welches die benutzerdefinierte Methode enthalten soll. 2. Erstellen Sie eine öffentliche Funktion oder Unterroutine (siehe Abbildung 9.25). 3. Öffnen Sie das Formular-, Berichts- oder Code-Modul, welches die benutzerdefinierte Methode ausführt.

Benutzerdefinierte Eigenschaften und Methoden erstellen

395

Abbildung 9.25: Die benutzerdefinierte Methode ChangeCaption

4. Verwenden Sie die Syntax Objekt.Methode, um die benutzerdefinierte Methode aufzurufen (siehe Abbildung 9.26).

Abbildung 9.26: Der Code für das Ereignis Click von cmdExecuteMethod

Abbildung 9.25 zeigt die benutzerdefinierte Methode ChangeCaption des Formulars frmMethods. Diese Methode ändert die Überschrift eines Formulars. Abbildung 9.26 zeigt die Routine für das Ereignis Click der Schaltfläche cmdExecuteMethod des frmExecuteMethod-Formulars. Das Ereignis verwendet die Methode ChangeCaption des Formulars frmMethods und weist anschließend der Eigenschaft Visible des Formulars den Wert True zu.

396

9.17.3

Kapitel 9: Fortgeschrittene Verwendung von Formularen

Für die Praxis

Erweiterte Techniken für Ihre Anwendung nutzen Viele der Beispiele in diesem Kapitel stammen aus dem Zeit- und Abrechnungssystem. Um Ihre eigene Anwendung aufzubessern, beginnen Sie damit, ein Startformular einzurichten, welches einen Begrüßungsbildschirm anzeigt und anschließend einige Einrichtungsfunktionen durchführt. Die Änderungen finden Sie in der Datei CHAP9EX.MDB.

9.17.4

Die Dinge mit einem Startformular zum Laufen bringen

Das Formular frmSwitchboard ist für die Anzeige des Begrüßungsbildschirms und die Durchführung erforderlicher Vorbereitungsmaßnahmen verantwortlich. Der Code zum Ereignis Load des Formulars frmSwitchboard sieht wie folgt aus: Private Sub Form_Load() DoCmd.Hourglass True DoCmd.OpenForm "frmSplash" Call GetCompanyInfo DoCmd.Hourgalss False End Sub

Die Ereignisroutine Form_Load ruft zuerst die Sanduhr auf. Anschließend wird das Begrüßungsformular geöffnet. Danach wird die Routine GetCompanyInfo aufgerufen, um die vielleicht von der Anwendung benötigte Typstruktur CompanyInfo auszufüllen. Typstrukturen werden im Kapitel 24 behandelt. Zum Schluss wird die Sanduhr wieder deaktiviert.

9.17.5

Einen Begrüßungsbildschirm erstellen

Der Begrüßungsbildschirm in Abbildung 9.27 trägt den Namen frmSplash. Das Zeitgeberintervall ist auf 3000 Millisekunden (3 Sekunden) eingestellt. Das Ereignis Timer sieht wie folgt aus: Private Sub Form_Timer() DoCmd.Close acForm, Me.Name End Sub

Abbildung 9.27: Ein vorhandenes Formular als Begrüßungsbildschirm benutzen

Benutzerdefinierte Eigenschaften und Methoden erstellen

397

Der Code hinter dem Ereignis Timer entlädt das Formular. Die Popup-Eigenschaft für frmSplash hat den Wert Ja. Für die Rahmenart ist der Wert Keine eingestellt. Daten-

satzmarkierer und Navigationsschaltflächen wurden entfernt.

Fortgeschrittene Verwendung von Berichten

Kapitel

Hier lesen Sie:

 Warum dieses Kapitel von Bedeutung ist  Für Berichte verfügbare Ereignisse und wann sie verwendet werden sollten  Ereignisreihenfolge für Berichte  Für Berichtsabschnitte verfügbare Ereignisse und wann sie verwendet werden sollten

 Spezielle Berichtseigenschaften  Praktische Anwendungen für Berichtsereignisse und -eigenschaften

10.1

Mit Berichten arbeiten

Kapitel 6 behandelt alle Grundlagen für den Berichtsentwurf. Berichte sind ein entscheidender Bestandteil fast jeder Anwendung, so dass Sie von Glück reden können, dass Ihnen in Access 2000 ein äußerst leistungsfähiges Berichtswerkzeug zur Verfügung steht. Die meisten Berichte sind zwar leicht zu erstellen, aber je länger Sie sich mit der Entwicklung von Access-Anwendungen beschäftigen, umso mehr werden Sie sich für die Feinheiten des Berichtsentwurfs mit Access interessieren. Dieses Kapitel behandelt Berichtsereignisse, erweiterte Techniken sowie Tipps und Tricks für den praktischen Umgang mit Berichten.

10.2

Für Berichte verfügbare Ereignisse und wann sie verwendet werden sollten

Die Berichtsereignisse sind zwar nicht so zahlreich wie die Formularereignisse, mit den abgefangenen Berichtsereignissen können Sie jedoch steuern, was beim Erstellen des Berichts geschieht. In diesem Abschnitt werden die Berichtsereignisse behan-

400

Kapitel 10: Fortgeschrittene Verwendung von Berichten

delt und der Abschnitt »Für Berichtsabschnitte verfügbare Ereignisse und wann sie verwendet werden sollten« widmet sich speziellen Ereignissen der Berichtsabschnitte.

10.2.1

Das Ereignis Open (Beim Öffnen)

Das Ereignis Open bzw. Beim Öffnen ist das erste Ereignis eines Berichts und tritt ein, bevor der Bericht gedruckt oder angezeigt und die dem Bericht zu Grunde liegende Abfrage ausgeführt wird. Es folgt ein Beispiel für die Verwendung des Ereignisses Open: Private Sub Report_Open(Cancel As Integer) On Error Resume Next DoCmd.OpenForm "frmReportDateRange", _ WindowMode:=acDialog, _ OpenArgs:="rptProjectBillingsbyWorkCode" If Not IsLoaded("frmReportDateRange") Then MsgBox "Criteria Form Not Successfully Loaded, " & _ "Canceling Report" Cancel = True End If End Sub

Sie finden dieses Beispiel im Bericht rptProjectBillingsByWorkCode aus der Datenbank CHAP10.MDB auf der dem Buch beiliegenden CD-ROM. Es wird versucht, das Formular frmReportDateRange zu öffnen, bei dem es sich um das Formular mit den Kriterien für die Parameter der dem Bericht zu Grunde liegenden Abfrage handelt. Kann das Formular nicht geladen werden, wird der Bericht abgebrochen.

10.2.2

Das Ereignis Close (Beim Schließen)

Das Ereignis Close bzw. Beim Schließen tritt vor dem Ereignis Deactivate (Bei Deaktivierung) beim Schließen eines Berichts ein. Das folgende Beispiel soll die Behandlung des Ereignisses Open veranschaulichen: Private Sub Report_Close() DoCmd.Close acForm, "frmReportDateRange" End Sub

Sie finden dieses Beispiel im Bericht rptProjectBillingsByWorkCode aus der Datenbank CHAP10.MDB auf der dem Buch beiliegenden CD-ROM. Das Formular frmReportDateRange mit den Kriterien wird beim Schließen des Berichts geschlossen, falls das Formular noch geöffnet ist.

Für Berichte verfügbare Ereignisse und wann sie verwendet werden sollten

10.2.3

401

Das Ereignis Activate (Bei Aktivierung)

Zum Ereignis Activate bzw. Bei Aktivierung des Berichts kommt es, wenn der Bericht zum aktiven Fenster wird. Es tritt nach dem Ereignis Open und vor dem Ausdrucken des Berichts ein. Häufig wird es zur Anzeige einer benutzerdefinierten Symbolleiste verwendet, die immer dann sichtbar ist, wenn der Bericht aktiv ist. Ein Beispiel: Private Sub Report_Activate() 'Die Access-eigene Symbolleiste Druckvorschau verbergen 'Die benutzerdefinierte Symbolleiste Druckvorschau anzeigen DoCmd.ShowToolbar "Druckvorschau", acToolbarNo DoCmd.ShowToolbar "Benutzerdefinierte Druckvorschau", acToolbarYes End Sub

Dieser Code verbirgt die Symbolleiste DRUCKVORSCHAU und zeigt die benutzerdefinierte Symbolleiste BENUTZERDEFINIERTE DRUCKVORSCHAU an. Wie Sie sehen werden, besteht zwischen diesem Ereignis und dem Ereignis Deactivate beim Anzeigen und Verbergen der benutzerdefinierten Symbolleiste des Berichts eine Wechselwirkung, wenn der Bericht zum aktiven Fenster wird und der Benutzer den Fokus einem anderen Fenster übergibt.

10.2.4

Das Ereignis Deactivate (Bei Deaktivierung)

Das Ereignis Deactivate bzw. Bei Deaktivierung tritt beim Wechseln zu einem anderen Access-Fenster oder beim Schließen des Berichts ein. Es tritt nicht ein, wenn der Fokus einer anderen Anwendung übergeben wird. Folgendes Beispiel veranschaulicht die Verwendung des Ereignisses Deactivate: Private Sub Report_Deactivate() 'Die Symbolleiste Benutzerdefinierte Druckvorschau verbergen 'Die eingebaute Symbolleiste Druckvorschau anzeigen DoCmd.ShowToolbar "Benutzerdefinierte Druckvorschau", acToolbarNo DoCmd.ShowToolbar "Druckvorschau", acToolbarWhereApprop End Sub

Diese Routine verbirgt die beim Auftreten des Ereignisses Activate angezeigte benutzerdefinierte Symbolleiste und weist an, dass die Symbolleiste DRUCKVORSCHAU gegebenenfalls wieder angezeigt wird. In diesem Fall soll die Symbolleiste nicht sofort erscheinen, sondern die Anzeige wieder so zurückgesetzt werden, dass sie nur angezeigt wird, wenn dies dem normalen Verhalten von Access entspricht. Diese Aufgabe übernimmt die Konstante acToolbarWhereApprop.

402

Kapitel 10: Fortgeschrittene Verwendung von Berichten

Dieser Code der Ereignisse Activate und Deactivate zeigt eine Möglichkeit, wie Symbolleisten verborgen und angezeigt werden können. Die gleiche Aufgabe kann auch die Eigenschaft Toolbar eines Berichts übernehmen. Möchten Sie jedoch mehr als eine Symbolleiste anzeigen lassen, während der Bericht aktiv ist, müssen Sie den Code zum Verbergen und Anzeigen der Symbolleisten in den Routinen zu den Ereignissen Activate und Deactivate unterbringen.

10.2.5

Das Ereignis NoDate (Bei Ohne Daten)

Entspricht kein Datensatz den Kriterien der dem Bericht zu Grunde liegenden Datensatzgruppe RecordSource, wird der Bericht ohne Daten gedruckt und #Error aus dem Detailabschnitt des Berichts angezeigt. Dieses Problem können Sie mit dem nachfolgenden Ereignis NoData bzw. Bei Ohne Daten vermeiden: Private Sub Report_NoData(Cancel As Integer) MsgBox "There ist no Data for this report._ Canceling Report..." Cancel = True End Sub

Sie finden dieses Beispiel im Bericht rptProjectBillingsByWorkCode aus der Datenbank CHAP10.MDB auf der dem Buch beiliegenden CD-ROM. Werden von der dem Bericht zu Grunde liegenden Datensatzgruppe keine Daten zurückgegeben, wird dem Benutzer ein Meldungsfeld angezeigt und Cancel erhält den Wert True. Dadurch wird der Bericht beendet und nicht weiter ausgeführt.

10.2.6

Das Ereignis Page (Bei Seite)

Mit dem Ereignis Page bzw. Bei Seite können Sie unmittelbar vor dem Senden der Seite an den Drucker etwas durchführen. Zum Beispiel können Sie mit dem Ereignis Page die Seite mit einer Umrandung versehen: Private Sub Report_Page() Me.Line (0, 0)-(Me.ScaleWidth, Me.ScaleHeight – 10), _ RGB(255, 0, 0), _ B End Sub

Diesen Code finden Sie im Bericht rptTimeSheet aus der Datenbank CHAP10.MDB. Er zeichnet eine rote Linie um den Bericht herum, die in der linken oberen Ecke beginnt und zur rechten unteren Ecke hinunterläuft. Mit den Eigenschaften ScaleWidth und ScaleHeight wird festgelegt, wo die rechte untere Ecke des Druckbereichs des Berichts liegt. Der dritte Parameter B erzeugt mit Hilfe der Koordinaten der gegenüberliegenden Ecken das Rechteck.

Ereignisreihenfolge für Berichte

10.2.7

403

Das Ereignis Error (Bei Fehler)

Kommt es beim Formatieren oder Drucken des Berichts zu einem Jet-Engine-Fehler, wird das Ereignis Error bzw. Bei Fehler ausgelöst. Dieser Fehler tritt normalerweise auf, wenn keine Datenherkunft für den Bericht vorliegt oder ein anderer diese exklusiv benutzt. Ein Beispiel: Private Sub Report_Error(DataErr As Integer, Response As Integer) If DataErr = 2580 Then MsgBox "Keine Datenherkunft für diesen Bericht vorhanden" Response = acDataErrContinue End If End Sub

Dieser Code reagiert auf den Wert 2580 für DataErr, was bedeutet, dass die Datenherkunft des Berichts nicht zur Verfügung steht. Dem Benutzer wird eine benutzerdefinierte Meldung angezeigt und die Access-Fehlermeldung unterdrückt.

10.3

Ereignisreihenfolge für Berichte

Es ist wichtig, die Reihenfolge der Ereignisse eines Berichts zu kennen. Wenn der Benutzer einen Bericht öffnet, sich eine Vorschau anzeigen lässt und den Bericht wieder schließt, treten der Reihe nach die folgenden Ereignisse auf: Open (Beim Öffnen)->Activate (Bei Aktivierung)->Close(Beim Schließen)->Deactivate (Bei Deaktivierung)

Wechselt der Benutzer zu einem anderen Bericht oder Formular, treten die folgenden Ereignisse auf: Deactivate (Bei Deaktivierung; aktueller Bericht)-> Activate (Bei Aktivierung; Formular oder Bericht)

Das Ereignis Deactivate tritt nicht ein, wenn der Benutzer zu einem Dialogfeld oder Formular, dessen Eigenschaft PopUp den Wert True hat, oder zum Fenster einer anderen Anwendung wechselt.

10.4

Für Berichtsabschnitte verfügbare Ereignisse und wann sie verwendet werden sollten

So wie der Bericht selbst über Ereignisse verfügt, so verfügt auch jeder Berichtsabschnitt über Ereignisse. Die drei Abschnittsereignisse sind die Ereignisse Format (Beim Formatieren), Print (Beim Drucken) und Retreat (Bei Rücknahme), die in den folgenden Abschnitten behandelt werden.

404

Kapitel 10: Fortgeschrittene Verwendung von Berichten

10.4.1

Das Ereignis Format (Beim Formatieren)

Das Ereignis Format bzw. Beim Formatieren tritt ein, nachdem Access die Daten für einen Berichtsabschnitt ausgewählt hat, jedoch bevor Access die Daten formatiert oder druckt. Mit diesem Ereignis können Sie das Layout des Abschnitts beeinflussen oder die Ergebnisse von Daten des Abschnitts vor dem Drucken berechnen. Listing 10.1 enthält ein Beispiel. Listing 10.1: Das Layout eines Berichts über das Ereignis Format beeinflussen Private Sub Detail2_Format(Cancel As Integer, FormatCount As Integer) ' Feststellen, ob Datensätze gedruckt werden sollen oder Fortsetzungen folgen ' Hinweis anzeigen, wenn die maximale Anzahl der _ ' Datensätze für die Seite erreicht wurde If (Me.txtRow = Me.txtOrderPage * (Me.txtRowsPerPage – 1) + 1) _ And Me.txtRow Me.txtRowCount Then Me.txtContinued.Visible = True End If ' Seitenumbruch anzeigen und Steuerelemente im Datensatz verbergen With Me If .txtContinued.Visible Then .txtDetailPageBreak.Visible = True .txtProductID.Visible = False .txtProductName.Visible = False .txtQuantity.Visible = False .txtUnitPrice.Visible = False .txtDiscount.Visible = False .txtExtendedPrice.Visible = False ' Increase value in Order Page. .NextRecord = False .txtOrderPage = Me.txtOrderPage + 1 Else ' Den Zeilenzähler erhöhen, wenn ein Datensatz gedruckt wird .txtRow = Me.txtRow + 1 End If End With End Sub

Sie finden diesen Code im Bericht rptInvoice aus der Datenbank CHAP10EX.MDB auf der beiliegenden CD-ROM. Der Bericht enthält Steuerelemente, die überwachen, wie viele Zeilen mit Datensätzen auf jeder Seite gedruckt werden sollen. Ist die maximale Anzahl erreicht, erscheint ein Steuerelement mit dem Hinweis, dass der Text auf der nächsten Seite fortgesetzt wird. Wenn das Steuerelement sichtbar ist, ist auch

Für Berichtsabschnitte verfügbare Ereignisse

405

das Steuerelement für den Seitenumbruch sichtbar, während alle Steuerelemente, welche die Einzelheiten des Berichts anzeigen, verborgen sind. Der Bericht wird auf diese Weise daran gehindert, zum nächsten Datensatz überzugehen.

Ein weiteres Beispiel für das Ereignis Format finden Sie im Seitenkopf des Berichts rptEmployeeSales aus der Datenbank CHAP10EX.MDB. Da es sich hier um einen ungebundenen Bericht handelt, dessen Steuerelemente mit Hilfe von VBA-Code während der Ausführung gefüllt werden, muss der Bericht ermitteln, was im Berichtskopf zu stehen hat. Dies variiert in Abhängigkeit von den Ergebnissen der Kreuztabellenabfrage, auf der der Bericht beruht. Listing 10.2 enthält den entsprechenden Code. Listing 10.2: Ungebundene Steuerelemente während der Ausführung mit Hilfe des Ereignisses Format ausfüllen Private Sub PageHeader0_Format(Cancel As Integer, FormatCount As Integer) Dim intX As Integer ' Die Spaltenüberschriften in Textfelder des Seitenkopfs setzen For intX = 1 To mintColumnCount Me("Head" + Format(intX)) = mrstReport(intX – 1).Name Next intX ' Das nächste verfügbare Textfeld Totals zur Beschriftung machen Me("Head" + Format(mintColumnCount + 1)) = "Totals" ' Nicht benutzte Textfelder im Seitenkopf verbergen For intX = (mintColumnCount + 2) To conTotalColumns Me("Head" + Format(intX)).Visible = False Next intX End Sub

Der Code durchläuft jede Spalte der Datensatzgruppe, die aus der Kreuztabellenabfrage resultiert (in der Routine zum Berichtsereignis Open). Die Seitenüberschrift des Berichts wird mit den Namen der Spalten des Abfrage-Ergebnisses gefüllt. Die letzte Seitenüberschrift erhält den Wert von Totals. Abschließend werden alle (zusätzlichen) Textfelder verborgen. Auf weitere Beispiele für die Verwendung des Ereignisses Format wird in diesem Abschnitt noch eingegangen. Durch Einfügen von Code für das Ereignis Format des Detailabschnitts des Berichts können Sie steuern, was geschieht, wenn die einzelnen Zeilen des Detailabschnitts gedruckt werden.

406

Kapitel 10: Fortgeschrittene Verwendung von Berichten

10.4.2

Das Ereignis Print (Beim Drucken)

Der Code zum Ereignis Print bzw. Beim Drucken wird ausgeführt, wenn die Daten des Abschnitts für das Drucken formatiert wurden, jedoch bevor sie tatsächlich gedruckt werden. Dieses Ereignis tritt für die einzelnen Abschnitte zu folgenden Zeitpunkten ein:

 Detailabschnitt: Unmittelbar vor dem Drucken der Daten  Gruppenköpfe: Unmittelbar vor dem Drucken des Gruppenkopfes. Das Ereignis Print des Gruppenkopfs bezieht sich sowohl auf den Gruppenkopf als auch auf

die erste Zeile mit Daten der Gruppe.

 Gruppenfüße: Unmittelbar vor dem Drucken des Gruppenfußes. Das Ereignis Print hat Zugriff auf den Gruppenfuß sowie auf die letzte Datenzeile der Gruppe.

Listing 10.3 stammt aus der Routine zum Ereignis Print des Detailabschnitts des Berichts rptEmployeeSales der Datenbank CHAP10EX.MDB.

Listing 10.3: Beispiel für die Verwendung des Ereignisses Print zur Berechnung der Spalten- und Zeilensummen Private Sub Detail1_Print(Cancel As Integer, PrintCount As Integer) Dim intX As Integer Dim lngRowTotal As Long ' Hat PrintCount den Wert1, wird die Varaible rowTotal initialsiert ' Den Spaltensummen hinzufügen If Me.PrintCount = 1 Then lngRowTotal = 0 For intX = 2 To mintColumnCount ' Mit Spalte 2 beginnen (erstes Textfeld mit Kreuztabellenerten), ' Gesamtsumme für die aktuelle Zeile des Detailabschnitts berechnen lngRowTotal = lngRowTotal + Me("Col" + Format(intX)) ' Den Kreuztabellenwert der Summe der aktuellen Spalte hinzufügen mlngRgColumnTotal(intX) = mlngRgColumnTotal(intX) + _ Me("Col" + Format(intX)) Next intX ' Die Summe der Zeile im Textfeld des Detailabschnitts unterbringen Me("Col" + Format(mintColumnCount + 1)) = lngRowTotal ' Die Zeilensumme der Gesamtsumme hinzufügen mlngReportTotal = mlngReportTotal + lngRowTotal End If End Sub

Für Berichtsabschnitte verfügbare Ereignisse

407

Der Code beginnt mit der Auswertung der Eigenschaft PrintCount. Ist ihr Wert gleich 1, so bedeutet dies, dass das Ereignis Print für diesen Abschnitt zum ersten Mal auftritt, so dass der Wert für die Zeilensumme auf 0 gesetzt werden kann. Der Code durchläuft mit einer Schleife anschließend jedes Steuerelement des Abschnitts und bildet die Summen für jede Spalte des Berichts und die jeweilige Zeile. Nach Verlassen der Schleife platziert die Routine die Zeilensumme im entsprechenden Steuerelement und addiert diesen Wert zum Gesamtwert des Berichts. Der Detailabschnitt des Berichts kann jetzt gedruckt werden. Oft besteht Unklarheit darüber, wann Routinen für das Ereignis Format und wann sie für das Ereignis Print geschrieben werden sollten. Wenn Sie etwas durchführen, was das Seitenlayout nicht betrifft, sollten Sie das Ereignis Print verwenden. Führen Sie jedoch etwas durch, was das Erscheinungsbild des Berichts (das Layout) verändert, dann verwenden Sie das Ereignis Format.

10.4.3

Das Ereignis Retreat (Bei Rücknahme)

Manchmal muss sich Access beim Drucken zum vorhergehenden Abschnitt zurückbewegen, z.B. wenn im Dialogfeld SORTIEREN UND GRUPPIEREN die Eigenschaft ZUSAMMENHALTEN auf Mit 1. Detaildatensatz oder Ganze Gruppe gesetzt wurde. Access muss den Gruppenkopf und den ersten Detaildatensatz oder bei der Einstellung Ganze Gruppe die gesamte Gruppe formatieren. Anschließend wird festgestellt, ob der Abschnitt in die aktuelle Seite eingepasst werden kann. Die beiden Abschnitte werden zurückgenommen und anschließend formatiert und gedruckt. Ein RetreatEreignis tritt für jeden Abschnitt auf. Es folgt ein Beispiel für das Ereignis Retreat des Detailabschnitts eines Berichts: Private Sub Detail1_Retreat() ' Bei Rückgabe immer Rückkehr zum vorherigen Datensatz mrstReport.MovePrevious End Sub

Dieser Code gehört zum Ereignis Retreat des Berichts rptEmployeeSales aus der Datenbank CHAP10EX.MDB. Da es sich hier um einen ungebundenen Bericht handelt, muss der Bericht bei jedem Retreat-Ereignis zum vorherigen Datensatz der Datensatzgruppe zurückgegeben werden.

Beim Umgang mit ungebundenen Berichten müssen Sie immer sorgfältig darauf achten, dass der Datensatzzeiger mit dem Bericht in Einklang bleibt. Wurde der Datensatzzeiger beispielsweise hochgesetzt und tritt dann das Retreat-Ereignis ein, muss er wieder auf den vorherigen Datensatz zurückgesetzt werden.

408

10.4.4

Kapitel 10: Fortgeschrittene Verwendung von Berichten

Reihenfolge von Abschnittsereignissen

Die Ereignisse der Berichtsabschnitte verfügen genau wie die des Berichts über eine bestimmte Reihenfolge. Alle Format- und Print-Ereignisse der Abschnitte finden nach den Ereignissen Open und Activate, aber noch vor den Ereignissen Close und Deactivate des Berichts statt. Die Reihenfolge sieht wie folgt aus: Open (Bericht)->Activate (Bericht)->Format(Berichtsabschnitt)-> Print(Berichtsabschnitt)->Close (Bericht)->Deactivate (Bericht)

10.5

Spezielle Berichtseigenschaften

Viele Berichtseigenschaften stehen nur während der Ausführung zur Verfügung. Mit ihrer Hilfe können Sie die Verarbeitung des Berichts deutlich verfeinern. Diese Eigenschaften werden in den folgenden Abschnitten behandelt. Beispiele finden Sie im Abschnitt »Praktische Anwendungen für Berichtsereignisse und Anwendungen« dieses Kapitels.

10.5.1

MoveLayout

Die Eigenschaft MoveLayout zeigt Access an, ob zum nächsten Druckabschnitt der Seite übergegangen werden soll. Hat diese Eigenschaft den Wert False, wird die Druckposition nicht vorgeschoben.

10.5.2

NextRecord

Die Eigenschaft NextRecord gibt an, ob ein Abschnitt zum nächsten Datensatz übergehen soll. Hat die Eigenschaft den Wert False, wird der Übergang zum nächsten Datensatz unterdrückt.

10.5.3

PrintSection

Die Eigenschaft PrintSection bestimmt, ob der Abschnitt gedruckt wird. Setzen Sie die Eigenschaft auf den Wert False, können Sie das Ausdrucken dieses Abschnitts unterdrücken.

10.5.4

Zusammenspiel von MoveLayout, NextRecord und PrintSection

Durch eine Kombination der Eigenschaften MoveLayout, NextRecord und PrintSection können Sie genau festlegen, wo, wie und ob Daten gedruckt werden. Tabelle 10.1 veranschaulicht diesen Zusammenhang.

Spezielle Berichtseigenschaften

409

MoveLayout NextRecord PrintSection Auswirkung True

True

True

Wechsel zur nächsten Position und zum nächsten Datensatz und Drucken der Daten

True

False

True

Unter Beibehaltung des Datensatzes zur nächsten Position wechseln und drucken

True

True

False

Wechsel zur nächsten Position und zum nächsten Datensatz, aber die Daten nicht drucken; auf diese Weise wird ein Datensatz ausgelassen und stattdessen ein Leerraum gedruckt

True

False

False

Unter Beibehaltung des Datensatzes zur nächsten Position wechseln, aber nicht drucken; ohne zum nächsten Datensatz zu wechseln, wird ein Leerraum erzeugt

False

True

True

Die Position beibehalten, zum nächsten Datensatz wechseln und die Daten drucken; hierdurch wird ein Datensatz mit einem anderen überlagert

False

False

True

Nicht zulässig

False

True

False

Die Position beibehalten, zum nächsten Datensatz wechseln und das Drucken unterbrechen; hierdurch wird ein Datensatz ausgelassen, ohne einen Leerraum zu hinterlassen

False

False

False

Nicht zulässig

Tabelle 10.1: Das Zusammenspiel von MoveLayout, NextRecord und PrintSection

10.5.5

FormatCount

Die Eigenschaft FormatCount wertet aus, wie oft das Ereignis Format im aktuellen Berichtsabschnitt eingetreten ist. Beim Eintritt des Ereignisses Retreat tritt das Ereignis Format immer mehrfach auf. Durch Überprüfen der FormatCount-Eigenschaft können Sie dafür sorgen, dass umfangreiche Anweisungen aus dem Code zum Ereignis Format nur einmal ausgeführt werden.

10.5.6

PrintCount

Die Eigenschaft PrintCount gibt an, wie oft das Ereignis Print für den aktuellen Abschnitt eingetreten ist. Wenn das Ereignis Retreat auftritt, tritt das Ereignis Print immer mehrfach auf. Durch Überprüfen der Eigenschaft PrintCount können Sie dafür sorgen, dass Code für das Ereignis Print nur einmal ausgeführt wird.

410

10.5.7

Kapitel 10: Fortgeschrittene Verwendung von Berichten

HasContinued

Die Eigenschaft HasContinued gibt an, ob ein Teil des gerade bearbeiteten Abschnitts auf einer vorherigen Seite gedruckt wurde. Über diese Eigenschaft können Sie bestimmte Berichtssteuerelemente verbergen oder anzeigen (zum Beispiel Fortsetzung von ...), wenn der Abschnitt eine Fortsetzung hat.

10.5.8

WillContinue

Die Eigenschaft WillContinue gibt an, ob der aktuelle Abschnitt auf einer anderen Seite fortgesetzt wird. Mit dieser Eigenschaft können Sie wie bei HasContinued bestimmte Steuerelemente anzeigen oder verbergen, wenn ein Abschnitt auf einer anderen Seite fortgesetzt wird.

10.6

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

Beim Entwickeln von Berichten sollten Sie darauf achten, dass der Bericht in so vielen Situationen wie möglich benutzt werden kann, was bedeutet, dass Sie den Bericht möglichst flexibel gestalten müssen. Anstatt mehrere ähnliche Berichte zu unterhalten, die bei Veränderungen jeweils alle mitgeändert werden müssen, können Sie einen Bericht anlegen, der für mehrere Situationen geeignet ist. Mittels der in diesem Abschnitt vorgestellten Ereignisse und Eigenschaften können Sie genau das erreichen. Dies kann beinhalten, dass Sie während der Ausführung die Datenherkunft wechseln, aber den gleichen Bericht zum Ausdrucken der Datenzusammenfassung oder der Detaildaten oder für beide Zwecke verwenden, die Druckposition ändern oder auch einen Bericht auf Grundlage einer Kreuztabellenabfrage mit ungebundenen Steuerelementen erstellen. Diese Möglichkeiten des Berichtsentwurfs werden in den folgenden Abschnitten behandelt.

10.6.1

Die Datenherkunft eines Berichts wechseln

Es gibt viele Situationen, in denen Sie zur Laufzeit die Datenherkunft eines Berichts wechseln müssen. Hierdurch geben Sie den Benutzern die Möglichkeit, die Bedingungen für den Bericht und die Abfrage, auf welcher der Bericht basiert, erkennbar zu verändern. Der Bericht rptClientListing aus der Datenbank CHAP10.MDB enthält den Code aus Listing 10.4. Listing 10.4: Mit Hilfe des Open-Ereignisses des Berichts die Datenherkunft wechseln Private Sub Report_Open(Cancel As Integer) On Error Resume Next DoCmd.OpenForm "frmClientListingCriteria", WindowMode:=acDialog If Not IsLoaded("frmClientListingCriteria") Then

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

411

MsgBox "Criteria form not successfully loaded, " & _ "Canceling Report" Cancel = True Else Select Case Forms!frmClientListingCriteria.optCriteria.Value Case 1 Me.RecordSource = "qryClientListingCity" Case 2 Me.RecordSource = "qryClientListingStateProv" Case 3 Me.RecordSource = "qryClientListing" End Select End If End Sub

Dieser Code öffnet zu Beginn das Formular frmClientListingCriteria, wenn dies nicht bereits geschehen ist. Das Formular wird gebunden geladen und erwartet die Auswahl der Berichtskriterien durch den Benutzer (siehe Abbildung 10.1). Nachdem der Benutzer die Berichtsvorschau gewählt hat, setzt das Formular die eigene Visible-Eigenschaft auf den Wert False. Dadurch wird die Ausführung des Berichts fortgesetzt, das Formular jedoch im Speicher behalten, so dass dessen Steuerelemente für den VBA-Code zugänglich sind. Dann wird der Wert des Optionsfeldes optCriteria des Formulars ausgewertet. Je nachdem, welches Optionsfeld gewählt wurde, wird die Eigenschaft RecordSource des Berichts auf die entsprechende Abfrage gesetzt. Der folgende Code gehört zum Ereignis Close des Berichts: Private Sub Report_Close() DoCmd.Close acForm, "frmClientListingCriteria" End Sub

Abbildung 10.1: Die Eigenschaft RecordSource mit den Auswahlkriterien festlegen

Dieser Code schließt das Formular mit den Auswahlkriterien, wenn der Bericht geschlossen wird. Das Formular frmClientListingCriteria enthält wichtigen Code für das Erstellen des Berichts. Dieser gehört zum Ereignis AfterUpdate der Optionsgruppe optCriteria (siehe Listing 10.5).

412

Kapitel 10: Fortgeschrittene Verwendung von Berichten

Listing 10.5: Die Behandlungsroutine für das Ereignis AfterUpdate von optCriteriaCombo verbirgt und zeigt Kombinationsfelder an. Private Sub optCriteria_AfterUpdate() Select Case optCriteria.Value Case 1 Me.cboCity.Visible = True Me.cboStateProv.Visible = False Case 2 Me.cboStateProv.Visible = True Me.cboCity.Visible = False Case 3 Me.cboCity.Visible = False Me.cboStateProv.Visible = False End Select End Sub

Dieser Code wertet die Optionsgruppe aus. Er verbirgt und zeigt die Kombinationsfelder cboCity und cboState an, je nachdem, welches Optionsfeld gewählt wurde. Anschließend werden diese Kombinationsfelder als Kriterien für die dem Bericht rptClientListing zu Grunde liegende Abfrage benutzt.

10.6.2

Zusammenfassung und/oder Details anzeigen

Viele Programmierer erstellen drei Berichte für ihre Benutzer: einen für die Anzeige der Zusammenfassung, einen für die Details und einen, der beides anzeigt. Das ist völlig überflüssig. Da die Berichtsabschnitte während der Ausführung optional verborgen oder angezeigt werden können, können Sie einen Bericht für alle drei Aufgaben erstellen. Der Bericht rptClientBillingsByProject aus der Datenbank CHAP10.MDB veranschaulicht diese Möglichkeit. Platzieren Sie den Code aus Listing 10.6 in der Routine für das Open-Ereignis des Berichts. Listing 10.6: Das Open-Ereignis des Berichts verwenden, um Berichtsabschnitte bei Bedarf ein- und auszublenden Private Sub Report_Open(Cancel As Integer) DoCmd.OpenForm "frmReportDateRange", _ WindowMode:=acDialog, OpenArgs:="rptClientBillingsbyProject" If Not IsLoaded("frmReportDateRange") Then Cancel = True Else Select Case Forms!frmReportDateRange!optDetailLevel.Value Case 1 Me.Caption = Me.Caption & " – Summary Only" Me.lblTitle.Caption = Me.lblTitle.Caption & " – Summary Only" Me.Detail.Visible = False Case 2 Me.Caption = Me.Caption & " – Detail Only"

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

413

Me.lblTitle.Caption = Me.lblTitle.Caption & " – Detail Only" Me.GroupHeader0.Visible = False Me.GroupFooter1.Visible = False Me.CompanyNameDet.Visible = True Case 3 Me.Caption = Me.Caption & " – Summary and Detail" Me.lblTitle.Caption = Me.lblTitle.Caption & " – Summary and Detail" Me.CompanyNameDet.Visible = False End Select End If End Sub

Zuerst wird das Formular frmReportDateRange aus der Datenbank CHAP10.MDB geöffnet (siehe Abbildung 10.2). Dieses Formular verfügt über eine Optionsgruppe, mit der der Benutzer gefragt wird, ob er eine Zusammenfassung, Details oder beides angezeigt bekommen möchte. Wird die Zusammenfassung gewählt, werden die Beschriftung des Berichtsfensters und das Etikett lblTitle geändert und die Eigenschaft Visible des Detailabschnitts auf den Wert False gesetzt. Wählt der Benutzer die Details, wird die Beschriftung des Berichtsfensters und das Etikett lblTitle entsprechend angepasst und der Wert der Eigenschaft Visible des Gruppenkopf- und des Gruppenfußabschnitts auf den Wert False gesetzt. Ferner wird im Detailabschnitt ein Steuerelement mit dem Firmennamen eingeblendet. Das Steuerelement CompanyName erscheint im Detailabschnitt, wenn nur die Berichtsdetails gedruckt werden, ist jedoch unsichtbar, wenn die Zusammenfassung und die Details gedruckt werden. Wurde Both für die Details gewählt, werden keine Abschnitte verborgen. Die Beschriftung des Berichtsfensters und das Etikett lblTitle werden geändert und das Steuerelement CompanyName verborgen.

Abbildung 10.2: Mit den Auswahlkriterien die Details festlegen

Den Code für die Schaltfläche PREVIEW des Formulars finden Sie in Listing 10.7. Listing 10.7: Der Code, der den vom Benutzer angegebenen Datumsbereich überprüft Private Sub cmdPreview_Click() If IsNull(Me.txtBeginDate) Or IsNull(Me.txtEndDate) Then MsgBox "You must enter both beginning and ending dates."

414

Kapitel 10: Fortgeschrittene Verwendung von Berichten

Me.txtBeginDate.SetFocus Else If Me.txtBeginDate > Me.txtEndDate Then MsgBox "Ending date must be greater than Beginning date." Me.txtBeginDate.SetFocus Else Me.Visible = False End If End If End Sub

Dieser Code stellt fest, ob sowohl das Anfangs- als auch das Enddatum angegeben wurden, und prüft, ob das Anfangs- vor dem Enddatum liegt. Sind beide Bedingungen erfüllt, wird die Visible-Eigenschaft des Formulars auf False gesetzt. Andernfalls wird eine entsprechende Fehlermeldung angezeigt.

10.6.3

Mehrere Etiketten drucken

Oftmals möchten die Benutzer mehrere Kopien des gleichen Etiketts drucken. Dies kann mit Hilfe der Eigenschaften MoveLayout, NextRecord, PrintSection und PrintCount geschehen. Das Formular in Abbildung 10.3 trägt den Namen frmClientLabelCriteria und befindet sich in der Datenbank CHAP10.MDB. Es fordert den Benutzer auf, eine Firma auszuwählen und die Anzahl der Etiketten anzugeben, die für diese Firma ausgedruckt werden sollen. Listing 10.8 enthält den Code für die Befehlsschaltfläche PRINT LABELS. Listing 10.8: Der Code, mit dem der Bericht lblClientMailingLabels für eine ausgewählte Firma gedruckt wird Sub cmdPrintLabels_Click() On Error GoTo Err_cmdPrintLabels_Click Dim stDocName As String stDocName = "lblClientMailingLabels" DoCmd.OpenReport stDocName, acPreview, , "CompanyName = '" & Me.cboCompanyName.Value & "'" Exit_cmdPrintLabels_Click: Exit Sub Err_cmdPrintLabels_Click: MsgBox Err.Description Resume Exit_cmdPrintLabels_Click End Sub

415

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

Abbildung 10.3: Die Abfrage des Firmennamens und der Anzahl der zu druckenden Etiketten über die Kriterienauswahl

Beachten Sie, dass die Routine den im Kombinationsfeld ausgewählten Firmennamen als Kriterium für die Ausführung des Berichts lblClientMailingLabels verwendet. Das Ereignis Open dieses Berichts sieht wie folgt aus: Private Sub Report_Open(Cancel As Integer) If Not IsLoaded("frmClientLabelCriteria") Then MsgBox "You must Run This Report From Label Criteria Form" Cancel = True End If End Sub

Dieser Code überprüft, ob das Formular frmClientLabelCriteria geöffnet ist. Ist dies nicht der Fall, wird eine Nachricht angezeigt und der Bericht abgebrochen. Der Schlüssel für den gesamten Ablauf liegt in der Routine für das Ereignis Print des Detailabschnitts: Private Sub Detail_Print(Cancel As Integer, PrintCont AsInteger) If PrintCount < Forms!frmClientLabelCriteria.txtNumberOfLabels Then Me.NextRecord = False End If End Sub

Dieser Code vergleicht die Eigenschaft PrintCount mit der Anzahl der Etiketten, die der Benutzer drucken möchte. Solange der Wert von PrintCount niedriger als die Anzahl der angeforderten Etiketten ist, wird der Datensatzzeiger nicht hochgesetzt. Auf diese Weise werden mehrere Etiketten des gleichen Datensatzes gedruckt.

10.6.4

Die Position des Ausdrucks bestimmen

Manchmal möchten die Benutzer mehrere Kopien des gleichen Etiketts drucken, wobei sich das Adressetikett an einer bestimmten Position auf der Seite befinden soll. Dies wird dadurch erreicht, dass das Drucken mit dem ersten ungenutzten Etikett beginnt. Das Formular frmClientLabelPosition aus der Datenbank CHAP10.MDB lässt

416

Kapitel 10: Fortgeschrittene Verwendung von Berichten

den Benutzer die Position des ersten Etiketts durch Angabe der zu überspringenden Etiketten angeben (siehe Abbildung 10.4). Der Code für das Ereignis Open des Etiketts lblClientMailLabelsSkip sieht wie folgt aus: Private Sub Report_Open(Cancel As Integer) If Not IsLoaded("frmClientLabelPosition") Then MsgBox "You Must Run This Report From Label Criteria Form" Cancel = True Else mboolFirstLabel = True End If End Sub

Abbildung 10.4: Die Angabe der zu überspringenden Etiketten mit der Kriterienauswahl

Der Code überprüft, ob das Formular frmClientLabelPosition geladen ist und weist der privaten Variablen mboolFirstLabel den Wert True zu. Die Routine für das Ereignis Print des Detailabschnitts sieht wie folgt aus: Private Sub Detail_Print(Cancel As Integer, PrintCount As Integer) If PrintCount > mlngReportTotal = mlngReportTotal + lngRowTotal End If End Sub

Dieser Code berechnet den Gesamtwert der Zeile und platziert ihn in der letzten Spalte des Berichts. Er berechnet außerdem die Spaltensummen und den Wert für mlngReportTotal, der die Gesamtsumme aller Spalten und Zeilen enthält. Hierfür wird geprüft, ob die Eigenschaft PrintCount dieses Abschnitts den Wert 1 hat. Trifft dies zu, wird die Variable lngRowTotal auf den Wert 0 zurückgesetzt. Beginnend mit der zweiten Spalte (Spalte 1 enthält den Produktnamen) wird durch Überprüfen jedes Steuerelements der Zeile eine Zeilensumme gebildet, deren Wert zu lngRowTotal addiert wird. Beim Passieren jeder Spalte der Zeile wird auch der Wert jeder Spalte dem entsprechenden Element im privaten Feld mlngRgColumnTotal hinzuaddiert. Die Zeilensumme wird gedruckt und zur Gesamtsumme des Bericht hinzugezählt. Wenn das Ereignis Retreat eintritt, wird folgender Code ausgeführt: Private Sub Detail1_Retreat() ' Bei erneuter Ausführung des Detailabschnitts zurück zum vorhergehenden ' Datensatz. mrstReport.MovePrevious End Sub

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

423

Dieser Code setzt den Datensatzzeiger zurück auf den letzten Datensatz der Datensatzgruppe. Zum Schluss wird der Berichtsfuß gedruckt, was das Ereignis Print für die Fußzeile auslöst: Private Sub ReportFooter4_Print(Cancel As Integer, PrintCount As Integer) Dim intX As Integer ' Die Spaltensummen in Textfelder des Berichtsfußes setzen ' Beginnend mit Spalte 2 (erstes Textfeld mit Kreuztabellenwert) For intX = 2 To mintColumnCount Me("Tot" + Format(intX)) = mlngRgColumnTotal(intX) Next intX ' Gesamtsumme in Textfeld des Berichsfußes setzen Me("Tot" + Format(mintColumnCount + 1)) = mlngReportTotal ' Nicht genutzte Textfelder im Berichtskopf verbergen For intX = mintColumnCount + 2 To conTotalColumns Me("Tot" + Format(intX)).Visible = False Next intX End Sub

Dieses Ereignis durchläuft in einer Schleife jedes Steuerelement des Berichtsfußes und füllt jedes Steuerelement mit dem entsprechenden Element aus dem Feld mlngRgColumnTotal. Auf diese Weise erhalten Sie die Spaltensummen des Berichts. Am Ende wird die Gesamtsumme in der nächsten verfügbaren Spalte gedruckt. Alle weiteren Textfelder werden bei der Anzeige verborgen.

10.6.6

Die ersten und letzten Seiteneinträge im Seitenkopf drucken

Eine weitere sinnvolle Vorgehensweise ist das Drucken der ersten und letzten Seiteneinträge im Berichtskopf. Dies veranschaulicht der Bericht rptCustomerPhoneList aus der Datenbank CHAP10EX.MDB der beiliegenden CD-ROM (siehe Abbildung 10.7). Der Code für diesen Bericht basiert darauf, dass Access den Bericht zweimal durchläuft. Beim ersten Durchlauf wird einer Variablen gboolLastPage der Wert False zugewiesen. Den Wert True erhält diese Variable nur, wenn das Ereignis Format des Berichtsfußes am Ende des ersten Durchlaufs ausgeführt wird. Berücksichtigen Sie diesen Umstand, wenn Sie den Code des Berichts betrachten.

424

Kapitel 10: Fortgeschrittene Verwendung von Berichten

Abbildung 10.7: Der erste und der letzte Eintrag werden im Berichtskopf gedruckt

Die erste Routine, welche das Erstellen des Berichts betrifft, ist die Ereignisroutine Format für den Berichtskopf: Private Sub PageHeader0_Format(Cancel As Integer, FormatCount As Integer) ' Im zweiten Durchgang die Textfelder FirstEntry und LastEntry füllen>> If gboolLastPage = True Then Reports!rptCustomerPhoneList.txtFirstEntry = _ Reports!rptCustomerPhoneList.txtCompanyName Reports!rptCustomerPhoneList.txtLastEntry = _ gstrLast(Reports!rptCustomerPhoneList.Page) End If End Sub

Die Routine Format für den Seitenkopf prüft, ob die Variable gboolLastPage den Wert True hat. Beim ersten Durchlauf des Berichts hat diese Variable den Wert False. Beim zweiten Durchlauf werden die Textfelder txtFirstEntry und txtLastEntry mit Daten gefüllt (beide erscheinen im Berichtskopf). Das Textfeld txtFirstEntry erhält den Wert des Steuerelements txtCompanyName des aktuellen Datensatzes (der erste Datensatz der Seite) und txtLastEntry die entsprechende Elementnummer aus dem Feld CustomerPhoneList. Jedes Element des Felds CustomerPhoneList wird mit Hilfe des Format-Ereignisses des Seitenfußes beim ersten Durchlauf des Berichts gefüllt. Als nächstes wird der Code zum Ereignis Format des Seitenfußes ausgeführt: Private Sub PageFooter2_Format(Cancel As Integer, FormatCount As Integer) ' Beim ersten Durchlauf die Feldgröße erhöhen und den letzten Datensatz der Seite ' dem Feld hinzufügen

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

425

If Not gboolLastPage Then ReDim Preserve gstrLast(Reports!rptCustomerPhoneList.Page + 1) gstrLast(Reports!rptCustomerPhoneList.Page) = _ Reports!rptCustomerPhoneList.txtCompanyName End If End Sub

Dieses Ereignis stellt fest, ob die Variable gboolLastPage den Wert False hat. Ist dies der Fall (was während des ersten Durchlaufs des Berichts zutrifft), wird das Feld gstrLast für das Hinzufügen eines neuen Elements neu dimensioniert. Der Wert des Steuerelements txtCompanyName des letzten Datensatzes der Seite wird in dem neuen Element des Felds gstrLast gespeichert. Dieser Wert erscheint unter Umständen im Seitenkopf dieser Seite als letzter Firmenname der Seite. Abschließend wird die Routine zum Ereignis Format des Berichtsfußes ausgeführt: Private Sub ReportFooter4_Format(Cancel As Integer, FormatCount As Integer) Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset ' Nach Abschluß des ersten Durchlaufs ein Flag setzen gboolLastPage = True ' Datensatzgruppe für den Bericht öffnen rst.Open "tblCustomers", CurrentProject.Connection, adOpenStatic ' Zum letzten Datensatz in der Datensatzgruppe wechseln rst.MoveLast ' Letzten Datensatz in das Feld einfügen>> ReDim Preserve gstrLast(Reports!rptCustomerPhoneList.Page + 1) gstrLast(Reports!rptCustomerPhoneList.Page) = rst!CompanyName End Sub

Die Routine für den Berichtsfuß weist der Variablen gboolLastPage den Wert True zu und öffnet mit Hilfe der Kundentabelle eine Datensatzgruppe. Dies ist die Datensatzgruppe, auf der der Bericht basiert. Dann wechselt die Routine zum letzen Datensatz der Datensatzgruppe und fügt den Wert des Feldes CompanyName des letzten Datensatzes der Datensatzgruppe in ein zusätzliches Element des Datenfelds ein. Der erste Durchlauf des Berichts ist damit abgeschlossen. Wenn sich der Benutzer bei einer Druckvorschau zu jeder Seite des Berichts bewegt oder wenn die Ausgabe der einzelnen Seiten erfolgt, wird das Format-Ereignis für den Seitenkopf ausgeführt. Der Firmenname des ersten Datensatzes der Seite wird im Steuerelement txtFirst Entry platziert und das entsprechende Element aus dem Feld gstrLast im Steuerelement txtLastEntry untergebracht.

426

Kapitel 10: Fortgeschrittene Verwendung von Berichten

10.6.7

Einen mehrzeiligen Kreuztabellenbericht erstellen

Kreuztabellenabfragen sind naturgemäß in ihren Ergebnissen eingeschränkt, da sie im Ergebnis nicht mehrere Datenzeilen unterbringen können. So haben Sie beispielsweise nicht die Möglichkeit, die Monate als Spaltenüberschrift zu wählen und anschließend den niedrigsten, den durchschnittlichen und den höchsten Umsatz jedes einzelnen Mitarbeiters als Beschriftung für die Zeilen festzulegen. Der in Abbildung 10.8 gezeigte Bericht rptSalesAverages aus der Datenbank CHAP10EX.MDB löst dieses Problem.

Abbildung 10.8: Ein Beispiel für einen mehrzeiligen Kreuztabellenbericht

Jedes Mal, wenn die Routine für das Ereignis Format des Seitenkopfes ausgeführt wird, wird der Wert des Steuerelements txtPrintWhat auf den Wert 0 gesetzt: Private Sub PageHeader1_Format(Cancel As Integer, FormatCount As Integer) ' Das Textfeld PrintWhat am Anfang der Seite auf 0 setzen. Me.txtPrintWhat = 0 End Sub

Nach der Ausführung der Format-Ereignisroutine des Seitenkopfes wird die Routine zum Ereignis Format des Gruppenkopfs gestartet: Private Sub GroupHeader2_Format(Cancel As Integer, FormatCount As Integer) ' Druckinformationen in den Zeilenüberschriften in der richtigen Reihenfolge ' Die Textfelder SalespersonLastName und FirtsName drucken,

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

427

' die Ettiketten Minimum, Average und Maximum verbergen, ' das Textfeld PrintWhat auf -1 setzen und nicht zum ' nächsten Datensatz übergehen With Me If .txtPrintWhat = 0 Then .txtSalespersonLastName.Visible = True .txtFirstName.Visible = True .lblMinimum.Visible = False .lblAverage.Visible = False .lblMaximum.Visible = False .txtPrintWhat = True .NextRecord = False ' Die Textfelder SalespersonLastName und FirtsName verbergen und ' die Ettiketten für Minimum, Average und Maximum drucken und ' das Textfeld PrintWhat auf 0 setzen Else .txtSalespersonLastName.Visible = False .txtFirstName.Visible = False .lblMinimum.Visible = True .lblAverage.Visible = True .lblMaximum.Visible = True .txtPrintWhat = 0 End If End With End Sub

Wenn das Ereignis Format für das Feld LastName des Gruppenkopfes (GroupHeader2) zum ersten Mal auftritt, ist der Wert des Steuerelements txtPrintWhat gleich False. Die Steuerelemente txtSalePersonalLastName und txtFirstName werden sichtbar gemacht und die Steuerelemente lblMinimum, lblAverage und lblMaximum verborgen. Der Wert des Steuerelements txtPrintWhat wird schließlich wieder auf False gesetzt. Sonst enthält der Bericht nur noch eine Routine für das Ereignis Format des Gruppenkopfs mit dem Auslieferungsdatum (GroupHeader3): Private Sub GroupHeader3_Format(Cancel As Integer, FormatCount As Integer) ' Daten in der richtigen Spalte drucken ' Nicht um nächsten Datensatz übergehen oder den nächsten Abschnitt drucken>> If Me.Left < Me.txtLeftMargin + (Month(Me.ShippedDate) + 1) _ * Me.txtColumnWidth Then Me.NextRecord = False Me.PrintSection = False End If End Sub

Dieser Code vergleicht die Eigenschaft Left des Berichts mit dem Ergebnis eines Ausdrucks. Die Eigenschaft Left gibt die Entfernung des aktuellen Abschnitts von

428

Kapitel 10: Fortgeschrittene Verwendung von Berichten

der linken Ecke der Seite an. Diese Zahl wird mit dem Wert verglichen, der sich ergibt, wenn zum Steuerelement txtLeftMargin der aktuelle Monat plus 1 addiert und anschließend mit dem Wert des Steuerelements txtColumnWidth multipliziert wird. Ergibt der Ausdruck den Wert True, wird den Eigenschaften NextRecord und PrintSection der Wert False zugewiesen. Dadurch wird der Drucker veranlasst, sich zur nächsten Druckposition zu begeben, den Datensatz aber beizubehalten und nichts zu drucken, so dass eine Leerzeile im Bericht entsteht. Sie werden sich fragen, wofür dieser komplizierte Ausdruck notwendig ist. Einfach ausgedrückt, handelt es sich um einen Algorithmus, der dafür sorgt, dass gedruckt wird und Access zum nächsten Datensatz nur dann wechselt, wenn die Daten für den Monat Januar zum Drucken bereit sind.

10.6.8

Für die Praxis

Der Bericht rptEmployeeBillingsByProject Fast jeder Bericht des Zeit- und Abrechnungssytems verwendet eine der in diesem Kapitel vorgestellten Lösungen. Tatsächlich sind die in diesem Kapitel behandelten Berichte rptClientListing, rptClientBillingsByProjetct, lblClientMailingLabels und lblClientMailingLabelsskip ein elementarer Bestandteil dieser Anwendung. Der Bericht rptEmployeeBillingsByProject wurde in diesen Kapitel nicht erläutert. Die in diesem Bericht enthaltene Routine für das Ereignis NoDate sieht wie folgt aus: Private Sub Report_NoDate(Cancel As Integer) MsgBox "There is no data for this report. Canceling report..." Cancel = True End Sub

Enthält die Eigenschaft RecordSource des Berichts keine Daten, wird ein Meldungsfeld angezeigt und der Bericht abgebrochen. Die Routine für das Ereignis Open des Berichts sieht wie folgt aus: Private Sub Report_Open(Cancel As Integer) DoCmd.OpenForm "frmReportDateRange", WindowMode:=acDialog, OpenArgs:="rptClientBillingsbyProject" If Not IsLoaded("frmReportDateRange") Then Cancel = True Else Select Case Forms!frmReportDateRange!optDetailLevel.Value Case 1 Me.Caption = Me.Caption & " – Summary Only" Me.lblTitle.Caption = Me.lblTitle.Caption & " – Summary Only" Me.Detail.Visible = False Case 2 Me.Caption = Me.Caption & " – Detail Only" Me.lblTitle.Caption = Me.lblTitle.Caption & " – Detail Only" Me.GroupHeader0.Visible = False

Praktische Anwendungen für Berichtsereignisse und -eigenschaften

429

Me.GroupFooter1.Visible = False Me.CompanyNameDet.Visible = True Case 3 Me.Caption = Me.Caption & " – Summary and Detail" Me.lblTitle.Caption = Me.lblTitle.Caption & " – Summary and Detail" Me.CompanyNameDet.Visible = False End Select End If End Sub

Dieser Code öffnet ein Formular mit dem Namen frmReportDateRange (siehe Abbildung 10.9), das erforderlich ist, weil damit die Kriterien für die dem Bericht zu Grunde liegende Abfrage festgelegt werden. Wird dieses Formular nicht erfolgreich geladen, wird der Bericht abgebrochen.

Abbildung 10.9: Ein Formular für die Kriterienauswahl

Das abschließende Close-Ereignis führt zur Ausführung folgenden Codes: Private Sup Report_Close() DoCmd.Close acForm, "frmReportDateChange" End Sub

Der Bericht räumt nach dem Schließen auf und beendet das Kriterienformular.

Fortgeschrittene Abfragetechniken

Kapitel

Hier lesen Sie:

 Aktionsabfragen  Spezielle Abfrage-Eigenschaften  Abfragen optimieren  Kreuztabellenabfragen  Äußere Verknüpfungen  Selbstverknüpfungen  SQL  Union-Abfragen  Pass-Through-Abfragen  Die Weitergabe von Nullwerten und Abfrage-Ergebnisse  Unterabfragen  Das Ergebnis einer Funktion als Abfragekriterium verwenden  Die Werte für eine Parameterabfrage aus einem Formular einlesen In Kapitel 4 haben Sie die Grundlagen des Aufbaus von Abfragen kennengelernt. Access besitzt jedoch wesentlich weiter reichendere Möglichkeiten. Neben den verhältnismäßig einfachen Auswahlabfragen, die in Kapitel 4 behandelt wurden, können Sie auch Kreuztabellenabfragen, Union-Abfragen, Abfragen mit Selbstverknüpfungen sowie Abfragen mit vielen weiteren Auswahlkriterien durchführen. Auch Abfragen, die die Informationen verändern und nicht nur suchen, sind ohne Weiteres möglich. Dieses Kapitel behandelt diese Themen sowie weitere Möglichkeiten zum Aufbau von Abfragen.

432

11.1

Kapitel 11: Fortgeschrittene Abfragetechniken

Aktionsabfragen

Mit Aktionsabfragen können Sie problemlos Daten verändern, ohne dafür Code schreiben zu müssen. Häufig ist diese Methode sogar wesentlich effektiver als das Programmieren einer speziellen Routine. Es stehen vier Arten von Aktionsabfragen zur Verfügung: Aktualisierungs-, Lösch-, Anfüge- und Tabellenerstellungsabfragen. Mit einer Aktualisierungsabfrage verändern Sie die Daten einer Tabelle, mit einer Löschabfrage entfernen Sie Datensätze, mit einer Anfügeabfrage fügen Sie einer vorhandenen Tabelle Datensätze hinzu und mit der Tabellenerstellungsabfrage erstellen Sie eine vollständig neue Tabelle. Jeder Abfragetyp und dessen Verwendung wird in den folgenden Abschnitten erklärt.

11.1.1

Aktualisierungsabfragen

Mit einer Aktualisierungsabfrage werden alle oder einige Datensätze geändert, die bestimmte Kriterien erfüllen. Dabei kann der Inhalt eines oder mehrerer Felder in mehreren Tabellen in einem Durchgang geändert werden (beispielsweise ist es möglich, das Gehalt der Mitarbeiter eines bestimmten Bundeslandes um 10% zu erhöhen). Wie bereits erwähnt wurde, sind Aktualisierungsabfragen meist effektiver als eine Veränderung der Daten mit Hilfe von VBA-Code und stellen somit eine angemessene Methode zur Veränderung von Tabellendaten dar. Mit den folgenden Schritten führen Sie eine Aktualisierungsabfrage durch: 1. Klicken Sie in der Objektliste des Datenbankfensters auf ABFRAGEN. 2. Doppelklicken Sie auf ERSTELLT SICHT.

EINE NEUE

ABFRAGE

IN DER

ENTWURFSAN-

3. Im Dialogfeld TABELLE ANZEIGEN wählen Sie die Tabellen oder Abfragen für die Aktualisierungsabfrage und klicken anschließend auf HINZUFÜGEN. Zum Fortfahren klicken Sie auf die Schaltfläche SCHLIESSEN. 4. Um Access mitzuteilen, dass Sie eine Aktualisierungsabfrage zusammenstellen, öffnen Sie über die Symbolleiste das Dropdown-Menü ABFRAGETYP und wählen AKTUALISIERUNGSABFRAGE. Sie können dies auch über den Menübefehl ABFRAGE|AKTUALISIERUNGSABFRAGE tun. 5. Fügen Sie der Abfrage Felder hinzu, die Sie für die Kriterien benötigen oder die durch die Abfrage aktualisiert werden sollen. In Abbildung 11.1 wurde der Abfrage das Feld StateProvince hinzugefügt, weil dieses Feld für die Formulierung des Abfragekriteriums benötigt wird. Das Feld DefaultTrans wurde gewählt, weil dieses Feld aktualisiert werden soll. 6. Fügen Sie je nach Bedarf weitere Felder für die Abfragekriterien hinzu. In Abbildung 11.1 wurde StateProvince der Wert CA zugewiesen.

433

Aktionsabfragen

7. Geben Sie den entsprechenden Ausdruck für die Aktualisierung ein. Im Beispiel aus Abbildung 11.1 wird das Feld DefaultRate um 10% erhöht. Abbildung 11.1: Eine Aktualisierungsabfrage, mit welcher der Wert des Felds DefaultRate für alle Kunden in Kalifornien erhöht wird

8. Klicken Sie in der Symbolleiste auf AUSFÜHREN. Daraufhin erscheint das in Abbildung 11.2 gezeigte Meldungsfeld. (Im Abschnitt »Spezielle Anmerkungen zu Aktionsabfragen« dieses Kapitels wird noch erklärt, wie Sie dieses Meldungsfeld durch Programmierung unterdrücken können.) Klicken Sie auf JA, um fortzufahren. Alle Datensätze, die der angegebenen Bedingung entsprechen, werden nun aktualisiert. Abbildung 11.2: Das Meldungsfeld, mit dem Sie die Aktualisierungsabfrage bestätigen

Access-Aktualisierungsabfragen sollten in der Bezeichnung das Präfix qupd enthalten. Jede Aktionsabfrage sollte ein entsprechendes Präfix erhalten, das kenntlich macht, um welchen Abfragetyp es sich handelt. Tabelle 11.1 führt die passenden Präfixe für die Aktionsabfragen auf. Abfragetyp

Präfix

Beispiel

Aktualisierung

qupd

qupdDefaultRate

Löschen

qdel

qdelOldTimeCards

Anhängen

qapp

qappArchiveTimeCards

Tabelle erstellen

qmak

qmakTempSales

Tabelle 11.1: Präfixe für die Bezeichnung der Aktionsabfragen

434

Kapitel 11: Fortgeschrittene Abfragetechniken

Der Aktionsabfragetyp wird im Datenbankfenster jeweils mit einem eigenen Symbol angezeigt.

Alle Access-Abfragen werden als SQL-Anweisungen (SQL – Structured Query Language) gespeichert. (Die SQL-Variante von Access wird im Abschnitt »SQL« dieses Kapitels erörtert.) Der SQL-Code einer Abfrage kann über die Option SQL-ANSICHT des Menüs ANSICHT aus der Menüleiste angezeigt werden. Der SQL-Code der Aktualisierungsabfrage von Access sieht wie folgt aus: UPDATE tblClients SET tblClients._ DefaultRate = [DefaultRate]*1.1 WHERE (((tblClients.StateProvince)="CA"));

Die von der Aktualisierungsabfrage sowie von den Aktionsabfragen durchgeführten Aktionen sind nicht umkehrbar. Sie müssen äußerste Vorsicht walten lassen, wenn Sie eine Aktionsabfrage durchführen.

Es ist wichtig zu beachten, dass bei aktivierter Option AKTUALISIERUNGSWEITERGABE AN DETAILFELD FÜR REFERENTIELLE INTEGRITÄT und bei einer Veränderung des Primärschlüssels durch eine Aktualisierungsabfrage der Fremdschlüssel aller entsprechenden Datensätze der damit verbundenen Tabellen aktualisiert wird. Wurde die Option AKTUALISIERUNGSWEITERGABE AN DETAILFELD nicht aktiviert und die referentielle Integrität erzwungen, erlaubt die Aktualisierungsabfrage nicht, dass die betroffenen Datensätze geändert werden.

11.1.2

Löschabfragen

Anstatt Tabellendaten nur zu verändern, entfernen Löschabfragen die Daten auf Dauer aus der Tabelle, wenn bestimmte Bedingungen erfüllt sind. Häufig werden sie zum Entfernen alter Datensätze benutzt, etwa um alle Datensätze des letzten Jahres zu löschen. Mit den folgenden Schritten führen Sie eine Löschabfrage durch: 1. Wählen Sie in der ENTWURFSANSICHT über das Listenfeld ABFRAGETYP der Symbolleiste die Option LÖSCHABFRAGE. Sie können dies auch über den Menübefehl ABFRAGE|LÖSCHABFRAGE tun. 2. Fügen Sie die Abfragekriterien hinzu. In der Abfrage des Beispiels aus Abbildung 11.3 werden alle Zeitkarten gelöscht, die älter als 365 Tage sind.

435

Aktionsabfragen

Abbildung 11.3: Mit einer Löschabfrage werden alle Zeitkarten gelöscht, die älter als 365 Tage sind

3. Klicken Sie in der Symbolleiste auf AUSFÜHREN. Es erscheint das in Abbildung 11.4 gezeigte Meldungsfeld. Dieses Meldungsfeld können Sie durch Programmierung unterdrücken (siehe »Spezielle Anmerkungen zu Aktionsabfragen« weiter hinten in diesem Kapitel).

Abbildung 11.4: Das Bestätigungsfeld für die Löschabfrage

4. Klicken Sie auf JA, um die Datensätze permanent aus der Tabelle zu löschen. Hinter der Löschabfrage verbirgt sich der folgende SQL-Code: DELETE tblTimeCards.DateEntered FROM tblTimeCards WHERE (((tblTimeCards.DateEntered) 50] [OrderDate] Between #1/1/98# And #12/31/98# [State = "CA"]

Mit dem Rushmore-Verfahren können auch Abfragen mit durch die Operatoren Und oder Oder verknüpften Ausdrücken optimiert werden. Lassen sich beide Ausdrücke vollständig optimieren, wird die gesamte Abfrage optimiert. Ist allerdings nur ein Ausdruck vollständig optimierbar und sind beide mit Und verknüpft, wird die Abfrage nur partiell optimiert. Bei einer Verknüpfung mit Or findet keine Optimierung statt.

11.3.5

Wichtige Anmerkungen zum Rushmore-Verfahren

Die folgenden Punkte sollten Sie beim Rushmore-Verfahren berücksichtigen:

 Abfragen mit dem Operator Nicht bzw. Not können nicht optimiert werden.  Die Funktion Anzahl(*) bzw. Count(*) wird durch das Verfahren sehr stark optimiert.

 Absteigende Indizes werden nur im Ausdruck = optimiert.  Das Rushmore-Verfahren kann nicht für Abfragen von ODBC-Datenquellen verwendet werden.

 Mehrfachindizes können im Zusammenhang mit dem Rushmore-Verfahren nur benutzt werden, wenn das Kriterium in der Reihenfolge des Index steht. Gibt es zum Beispiel einen Index für das Feld LastName in Verbindung mit dem Feld FirstName, kann der Index für die Suche nach LastName oder eine Kombination aus LastName und FirstName verwendet werden, nicht jedoch in einem Ausdruck, der auf dem Feld FirstName basiert.

450

11.4

Kapitel 11: Fortgeschrittene Abfragetechniken

Kreuztabellenabfragen

Eine Kreuztabellenabfrage fasst Abfrage-Ergebnisse durch Anzeigen eines Felds einer Tabelle auf der linken Seite des Datenblatts und durch zusätzliche Angaben im oberen Bereich des Datenblatts zusammen. Sie kann zum Beispiel den Betrag der Verkäufe eines Vertreters für jede Firma zusammenfassen. Der Name jeder Firma kann in der linken Spalte der Ausgabe stehen, während in der oberen Zeile die einzelnen Vertreter angeführt werden. Die Beträge erscheinen in der entsprechenden Zelle des Abfrage-Ergebnisses (siehe Abbildung 11.20). Kreuztabellenabfragen sind wahrscheinlich die umfangreichsten und am schwierigsten zu erstellenden Abfragen. Aus diesem Grund stellt Microsoft den KreuztabellenAssistenten zur Verfügung. In den folgenden Abschnitten wird das Erstellen von Kreuztabellenabfragen mit und ohne den Kreuztabellen-Assistenten beschrieben.

Abbildung 11.20: Ein Beispiel für eine Kreuztabellenabfrage, welche die Verkaufsbeträge der Vertreter für jede Firma angibt

11.4.1

Mit Hilfe des Kreuztabellen-Assistenten eine Kreuztabellenabfrage erstellen

Führen Sie die folgenden Schritte durch, um mit Hilfe des Kreuztabellen-Assistenten eine Kreuztabellenabfrage zu erstellen: 1. Wählen Sie in der Objektliste des Datenbankfensters ABFRAGEN und klicken Sie auf NEU. 2. Wählen Sie die Option KREUZTABELLENABFRAGE-ASSISTENT und klicken Sie auf OK .

Kreuztabellenabfragen

451

3. Wählen Sie die Tabelle oder Abfrage aus, welche die Grundlage der Abfrage bilden soll. Soll die Abfrage Felder von mehreren Tabellen berücksichtigen, dann müssen Sie die Kreuztabellenabfrage auf einer anderen Abfrage aufbauen, die sich auf die Tabellen und Felder bezieht, die Sie benötigen. Klicken Sie auf WEITER. 4. Wählen Sie die Felder aus, deren Werte Sie als Zeilenüberschrift für die Ausgabe der Abfrage verwenden wollen. In Abbildung 11.21 wurden die Felder Artikelname und Kunden-Code als Zeilenüberschrift gewählt. Klicken Sie auf WEITER.

Abbildung 11.21: Die Angabe der Zeilen für eine Kreuztabellenabfrage

5. Wählen Sie das Feld aus, dessen Wert als Spaltenüberschrift für die Ausgabe der Abfrage dienen soll. In Abbildung 11.22 wurde das Feld Bestelldatum als Spaltenüberschrift gewählt. Klicken Sie auf WEITER. 6. Handelt es sich bei dem als Überschrift gewählten Feld um ein Datumsfeld, fordert der Kreuztabellen-Assistent Sie auf, ein Intervall für die Gruppierung anzugeben. In Abbildung 11.23 wird das Feld Bestelldatum nach Quartalen gruppiert. Wählen Sie das gewünschte Intervall und klicken Sie auf WEITER. 7. Im nächsten Schritt fragt der Kreuztabellen-Assistent, welches Feld die Zahl enthält, die Sie für die Berechnung des Wertes jedes Spalten- und Zeilenunterabschnitts verwenden möchten. In Abbildung 11.24 wird das Feld Anzahl für jedes Produkt und jeden Kunden pro Quartal summiert. Klicken Sie auf WEITER. 8. Im letzten Schritt geben Sie den Namen für Ihre Abfrage ein. Zum Abschluss klicken Sie auf FERTIG STELLEN.

452

Kapitel 11: Fortgeschrittene Abfragetechniken

Abbildung 11.22: Angabe der Spalten für eine Kreuztabellenabfrage

Abbildung 11.23: Die Angabe eines Intervalls für die Kreuztabellenabfrage

Kreuztabellenabfragen

453

Abbildung 11.24: Die Angabe des Felds, welches die Kreuztabellenabfrage für die Berechnung benutzen soll

Abbildung 11.25 zeigt eine vollständige Kreuztabellenabfrage in der Entwurfsansicht. Beachten Sie die einzelnen wichtigen Attribute und die Kreuztabellenzeile in der Entwurfsansicht. Die Felder Artikelname und Kunden-Code wurden als Zeilenüberschriften angegeben und dienen als Gruppierungsspalte der Abfrage. Die Spaltenüberschrift enthält folgenden Ausdruck: "Qtr" & Format([OrderDate], "q")

Abbildung 11.25: Eine vollständige Kreuztabellenabfrage in der Entwurfsansicht

Dieser Ausdruck gibt das formatierte Bestelldatum für die Anzeige des Quartals zurück. Er wird auch für die Gruppierung verwendet. Das Feld Anzahl wird als ein

454

Kapitel 11: Fortgeschrittene Abfragetechniken

Wert angegeben. Die Zelle Gesamtsumme der Spalte zeigt an, dass dieses Feld eine Summe bildet (im Gegensatz zu Zählungen oder Durchschnittswerten). Beachten Sie die Spalte mit der Überschrift Gesamtsumme von Anzahl. Diese Spalte zeigt die Summen aller Spalten der Abfrage an. Sie entspricht der Spalte, welche die Werte enthält, mit Ausnahme des Alias im Namensfeld und der Tatsache, dass die Kreuztabellenzelle auf Zeilenüberschrift gesetzt wurde und nicht auf Wert (siehe Abbildung 11.26).

Abbildung 11.26: Eine Aufsummierungsspalte in einer Kreuztabellenabfrage in der Entwurfsansicht

11.4.2

Ohne den Kreuztabellen-Assistenten eine Kreuztabellenabfrage erstellen

Sie können mit dem Kreuztabellen-Assistenten zwar sehr viele Kreuztabellenabfragen erstellen, Sie sollten aber auch in der Lage sein, eine solche Abfrage ohne den Assistenten zu erstellen. Mit diesem Wissen können Sie vorhandene Kreuztabellenabfragen ändern und erhalten die bestmöglichen Steuerungsmöglichkeiten beim Erstellen neuer Abfragen. Führen Sie die folgenden Schritte durch, um eine Kreuztabellenabfrage ohne den Kreuztabellen-Assistenten zu erstellen: 1. Wählen Sie in der Objektliste des Datenbankfensters ABFRAGEN und klicken Sie auf NEU. 2. Klicken Sie doppelt auf ERSTELLT SICHT.

EINE NEUE

ABFRAGE

IN DER

ENTWURFSAN-

3. Wählen Sie die Tabelle oder Abfrage aus, die in die Entwurfsansicht der Abfrage übernommen werden soll. Klicken Sie auf die Schaltfläche HINZUFÜGEN, um die Tabelle oder Abfrage hinzuzufügen. Klicken Sie auf SCHLIESSEN. 4. Wählen Sie im Menü ABFRAGE die Option KREUZTABELLENABFRAGE.

Kreuztabellenabfragen

455

5. Fügen Sie der Entwurfsansicht die für die Ausgabe der Abfrage gewünschten Felder hinzu. 6. Klicken Sie auf die Kreuztabellenzeile jedes Felds, welches Sie als Zeilenüberschrift benutzen möchten. Wählen Sie im aufklappbaren Listenfeld ZEILENÜBERSCHRIFT aus. 7. Klicken Sie auf die Kreuztabellenzeile jedes Felds, welches Sie als Spaltenüberschrift benutzen möchten. Wählen Sie im aufklappbaren Listenfeld SPALTENÜBERSCHRIFT aus. 8. Klicken Sie auf die Kreuztabellenzeile jedes Felds, dessen Wert in die Kreuztabelle aufgenommen werden soll. Wählen Sie im aufklappbaren Listenfeld KREUZTABELLE den Eintrag WERT aus. 9. Wählen Sie im aufklappbaren Listenfeld FUNKTION eine geeignete zusammenfassende Funktion aus. 10. Geben Sie die gewünschten Zeitintervalle oder die zu verwendenden Ausdrücke ein. 11. Geben Sie die Kriterien für die Abfrage ein. 12. Legen Sie die Sortierreihenfolge jeder Spalte je nach Bedarf fest. 13. Führen Sie zum Schluss die Abfrage aus. Abbildung 11.27 zeigt eine Abfrage, in der für die Spaltenüberschrift der Monat aus dem Feld ProjectBeginDate gewählt wurde. Die Zeilenüberschrift stammt aus dem Feld EmployeeName. Die Summe des Felds ProjectTotalsEstimate bildet den Wert der Abfrage. Auch das Projetktanfangsdatum wurde als WHERE-Klausel (bzw. als Bedingung) in die Entwurfsansicht der Abfrage aufgenommen. Abbildung 11.28 zeigt die Ergebnisse der Abfrage.

Abbildung 11.27: Eine ohne den KreuztabellenAssistenten erstellte Kreuztabellenabfrage, welche die geschätzten Auftragssummen pro Mitarbeiter und Monat anzeigt

456

Kapitel 11: Fortgeschrittene Abfragetechniken

Abbildung 11.28: Das Ergebnis der in Abbildung 11.27 gezeigten Kreuztabellenabfrage

11.4.3

Feste Spaltenüberschriften erstellen

Wenn Sie keine festen Spaltenüberschriften benutzen, enthält die Ausgabe des Abfrage-Ergebnisses alle Spalten in alphabetischer Reihenfolge. Enthält Ihr AbfrageErgebnis beispielsweise die Monatsnamen, erscheinen diese in der Reihenfolge Apr, Aug, Dez usw. Durch Verwendung fester Spaltenüberschriften teilen Sie Access die Reihenfolge der Spaltenüberschriften für das Abfrage-Ergebnis mit. Spaltenüberschriften können über die Eigenschaft Fixierte Spaltenüberschriften festgelegt werden (siehe Abbildung 11.29).

Abbildung 11.29: Die Eigenschaft Fixierte Spaltenüberschriften

Alle festen Spaltenüberschriften müssen mit den zu Grunde liegenden Daten genau übereinstimmen, weil sonst Informationen unbeabsichtigt im Abfrage-Ergebnis ausgelassen werden. Wurde beispielsweise für die Spaltenüberschrift der Monat Juni eingegeben und mit der Formatanweisung für die Datenausgabe der Monat Jun festgelegt, werden alle Daten für den Monat Juni in den Abfrage-Ergebnissen ausgelassen.

Äußere Verknüpfungen

11.4.4

457

Wichtige Anmerkungen zu Kreuztabellenabfragen

Unabhängig davon, wie Kreuztabellenabfragen erstellt werden, sollten Sie einige spezielle Eigenarten beim Umgang mit diesen Abfragen berücksichtigen: 1. Sie können nur einen Wert und eine Spaltenüberschrift. jedoch mehrere Zeilenüberschriften für eine Kreuztabellenabfrage wählen. 2. Die Ergebnisse einer Kreuztabellenabfrage können nicht aktualisiert werden. 3. Sie können keine Kriterien für das Feld Wert angeben. Tun Sie dies trotzdem, erhalten Sie eine Fehlermeldung mit dem Hinweis, dass Sie für das gleiche Feld, mit dem Sie den Wert der Kreuztabellenabfrage eingeben, keine Kriterien angeben können. Ist es erforderlich, dass Sie ein Kriterium für das Feld mit dem Wert angeben, dann müssen Sie zuerst eine andere Abfrage erstellen, die Ihr Auswahlkriterium enthält, und die Kreuztabellenabfrage auf dieser Abfrage aufbauen. 4. Alle Parameter der Kreuztabellenabfrage müssen im Dialogfeld ABFRAGEPARAMETER explizit deklariert werden.

11.5

Äußere Verknüpfungen

Äußere Verknüpfungen werden verwendet, wenn Datensätze von der 1-Seite einer 1:n-Beziehung in den Abfrage-Ergebnissen enthalten sein sollen, unabhängig davon, ob es in den Tabellen der n-Seite übereinstimmende Datensätze gibt. Bei einer Kunden- und Bestellungentabelle wollen die Benutzer beispielsweise oft, dass das Abfrage-Ergebnis nur die Aufträge eines Kunden enthält. Eine innere Verknüpfung (die Standardverknüpfung) kann dies bewerkstelligen. In anderen Situationen wollen die Benutzer im Abfrage-Ergebnis alle Kunden unabhängig davon angezeigt bekommen, ob Bestellungen vorliegen oder nicht. Hierfür ist eine äußere Verknüpfung erforderlich. Es gibt zwei Arten äußerer Verknüpfungen: linke und rechte. Eine linke äußere Verknüpfung liegt vor, wenn alle Datensätze der 1-Seite einer 1:n-Beziehung im Abfrage-Ergebnis unabhängig davon enthalten sind, ob es auf der n-Seite weitere Datensätze gibt. Eine rechte äußere Verknüpfung bedeutet, dass alle Datensätze der n-Seite einer Beziehung im Abfrage-Ergebnis unabhängig davon erscheinen, ob auf der 1Seite der Beziehung Datensätze vorhanden sind. Eine rechte äußere Verknüpfung darf nicht entstehen, wenn referentielle Integrität notwendig ist. Um eine äußere Verknüpfung einzurichten, müssen Sie die Verknüpfung zwischen den Tabellen der Abfrage verändern: 1. Klicken Sie doppelt auf die Zeile, welche die Tabellen im Abfrageraster miteinander verbindet.

458

Kapitel 11: Fortgeschrittene Abfragetechniken

2. Sie gelangen in das Dialogfeld VERKNÜPFUNGSEIGENSCHAFTEN (siehe Abbildung 11.30). Wählen Sie die gewünschte Verknüpfung aus. Um eine linke äußere Verknüpfung zwischen den Tabellen einzurichten, wählen Sie die zweite Option (die dritte entspricht einer rechten äußeren Verknüpfung). Beachten Sie, dass in Abbildung 11.30 die Beschreibung wie folgt lautet: »Beinhaltet ALLE Datensätze aus 'tblClients' und nur die Datensätze aus 'tblProjects', bei denen die Inhalte der verknüpften Felder beider Tabellen gleich sind.«

Abbildung 11.30: Eine linke äußere Verknüpfung einrichten

3. Klicken Sie auf OK, um die Verknüpfung zu akzeptieren. Daraufhin wird zwischen beiden Tabellen eine äußere Verknüpfung eingerichtet. Beachten Sie, dass die Verbindungslinie zwischen den beiden Tabellen nun einen Pfeil aufweist, der auf die n-Seite der Verknüpfung verweist. Die SQL-Anweisung, welche eine linke äußere Verknüpfung erzeugt, sieht wie folgt aus: SELECT DISTINCTROW tblClients.ClientID, tblClients.CompanyName FROM tblClients LEFT JOIN tblProjects ON tblClients.ClientID = tblProjects.ClientID;

Eine linke äußere Verknüpfung kann auch zur Ermittlung aller Datensätze der 1Seite einer Verknüpfung verwendet werden, die über keinen entsprechenden Datensatz auf der n-Seite verfügen. Hierfür geben Sie als Kriterium für ein beliebiges Feld der n-Seite Is Null bzw. ISTNULL ein. In der Abfrage aus Abbildung 11.31 werden nur die Kunden ohne Bestellungen angezeigt.

Selbstverknüpfungen

459

Abbildung 11.31: Eine Abfrage, die Kunden ohne Bestellungen anzeigt

11.6

Selbstverknüpfungen

Mit einer Selbstverknüpfung können Sie eine Tabelle mit sich selbst verknüpfen. Dies wird oft getan, um den Anschein zu erwecken, die Informationen einer einzigen Tabelle seien in zwei unterschiedlichen Tabellen enthalten. Ein klassisches Beispiel stellen die Angestellten und die Vorgesetzten dar. Eine Angestelltentabelle enthält unter anderem zwei Felder: eines mit der Angestelltennummer des im Datensatz beschriebenen Angestellten und ein weiteres mit der Angestelltennummer des Vorgesetzten. Möchten Sie eine Liste mit den Namen der Angestellten und ihrer Vorgesetzten anzeigen lassen, dann benötigen Sie hierfür eine Selbstverknüpfung. Mit den folgenden Schritten richten Sie eine Selbstverknüpfung ein: 1. Klicken Sie im Datenbankfenster auf die Registerkarte ABFRAGEN und klicken Sie anschließend auf die Schaltfläche NEU. 2. Wählen Sie ENTWURFSANSICHT und klicken Sie auf OK. 3. Fügen Sie im Dialogfeld TABELLE ANZEIGEN die Tabelle für die Selbstverknüpfung in der Abfrage zweimal hinzu. Klicken Sie auf die Schaltfläche SCHLIESSEN. Beachten Sie, dass die zweite Instanz der Tabelle mit einem Unterstrich und der Zahl 1 erscheint. 4. Um den Alias der zweiten Tabelle zu ändern, klicken Sie in der Entwurfsansicht der Abfrage mit der rechten Maustaste an den oberen Rand der Tabelle und wählen EIGENSCHAFTEN. Ändern Sie die Eigenschaft ALIAS wie gewünscht. In Abbildung 11.32 wurde als Alias Supervisor angegeben. 5. Um die Verknüpfung zwischen der Tabelle und dem Alias einzurichten, ziehen Sie das Feld aus der einen Tabelle in das entsprechende Feld der Alias-Tabelle. In Abbildung 11.33 wurde das Feld SupervisorID der Tabelle tblEmployees mit dem Feld EmployeeID der Alias-Tabelle verknüpft.

460

Kapitel 11: Fortgeschrittene Abfragetechniken

Abbildung 11.32: Eine Selbstverknüpfung einrichten

6. Ziehen Sie die gewünschten Felder auf das Abfrageraster. In Abbildung 11.33 werden die Felder FirstName und LastName aus der Tabelle tblEmployees übernommen. Der Ausdruck SupervisorName (eine Zusammensetzung aus dem Vorund Nachnamen des Vorgesetzten) stammt aus der Kopie der Alias-Tabelle. Selbstverknüpfungen können im Dialogfeld für die Verknüpfungen als dauerhaft festgelegt werden, um etwa referentielle Integrität zu erreichen. In dem Beispiel mit den Angestellten und deren Vorgesetzten kann eine dauerhafte Beziehung mit referentieller Integrität eingerichtet werden, damit sichergestellt ist, dass die Angestelltennummern der Vorgesetzten nicht zusammen mit Angestelltennummern von Angestellten eingegeben werden können, die gar nicht existieren.

Abbildung 11.33: Einrichten einer Selbstverknüpfung zwischen einer Tabelle und einem Alias

11.7

SQL

Access SQL ist die den Access-Abfragen zu Grunde liegende Sprache. Deshalb sollten Sie etwas über deren Herkunft und Funktionsweise wissen. Mit Access SQL können Sie Abfragen aufbauen, ohne die Abfrage-Entwurfsansicht zu benutzen. Vielleicht müssen Sie zum Beispiel als Reaktion auf eine Benutzerschnittstelle mit

SQL

461

Ihrer Anwendung aus dem Stegreif eine SQL-Anweisung formulieren. Außerdem unterstützt Access SQL bestimmte Operationen, welche die grafische Benutzeroberfläche der Abfrageansicht nicht unterstützt. Diese SQL-Anweisungen müssen Sie über das Menü ANSICHT und die Option SQL-ANSICHT erstellen.

11.7.1

Was ist SQL und woher stammt es?

SQL ist eine Standardsprache, von der viele Dialekte abgeleitet wurden. Sie wurde in den frühen siebziger Jahren in einem Forschungslabor von IBM entwickelt und 1974 erstmals in einem Forschungsbericht formal beschrieben, der anläßlich eines Kongresses einer Gesellschaft für Rechenmaschinen veröffentlicht wurde. Die Jet-Engine 4.0, die zum Lieferumfang von Access 2000 gehört, unterstützt Access SQL und SQL-92.

11.7.2

Was müssen Sie über SQL wissen?

Sie müssen zumindest die Grundlagen von SQL kennen und wissen, wie Sie mit Hilfe von SQL-Anweisungen und -Syntax Daten auswählen, aktualisieren, löschen und anfügen können. SQL besteht eigentlich nur aus sehr wenigen Worten, deren gebräuchlichste in den folgenden Abschnitten vorgestellt werden. SQL-Syntax SQL ist sehr leicht zu erlernen. Wenn Sie Daten suchen, formulieren Sie eine SELECT-Anweisung. Die SELECT-Anweisung setzt sich aus Klauseln zusammen, welche die Auswahl der Daten festlegen. Während der Ausführung wählen die SELECTAnweisungen die Datenzeilen aus und geben sie als Datensatzgruppe zurück. Die SELECT-Klausel Die SELECT-Anweisung gibt an, welche Spalten einer Tabelle mit den Daten der Datensatzgruppe zurückgegeben werden sollen. Die einfachste SELECT-Anweisung sieht wie folgt aus: SELECT *

Diese Anweisung durchsucht alle Spalten einer Tabelle. Die nächste Anweisung durchsucht nur die Spalten ClientID und CompanyName: SELECT ClientID, CompanyName

Sie können nicht nur Tabellenspalten angeben, sondern auch Ausdrücke: SELECT ClientID, [City & ", " & [State] & " " & [PostalCode] AS Address

Diese SELECT-Anweisung durchsucht die Spalte ClientID sowie eine Pseudospalte mit Namen Address, die einen Ausdruck enthält, der sich aus den Spalten City, State und PostalCode zusammensetzt.

462

Kapitel 11: Fortgeschrittene Abfragetechniken

Die FROM-Klausel Die FROM-Klausel gibt die Tabellen und Abfragen an, aus denen die Datensätze ausgewählt werden sollen. Sie kann einen Alias enthalten, mit dem Sie sich auf eine Tabelle beziehen: FROM tblClients AS Clients

In diesem Beispiel lautet der Name der Tabelle tblClients und der Alias Clients. Kombinieren Sie die SELECT-Klausel mit einer FROM-Klausel, dann sieht die SQLAnweisung wie folgt aus: SELECT ClientID, CompanyName FROM tblClients

Diese Anweisung durchsucht die Spalten ClientID und CompanyName der Tabelle tblClients. Die WHERE-Klausel Die WHERE-Klausel schränkt die Auswahl der mit der SELECT-Anweisung gefundenen Datensätze ein. Eine WHERE-Klausel kann bis zu 40 Spalten umfassen, die mit den Schlüsselwörtern AND oder OR kombiniert werden. Eine einfache WHERE-Klausel sieht folgendermaßen aus: WHERE Country = "USA"

Mit AND können die Kriterien der WHERE-Klausel weiter eingeschränkt werden: WHERE Country = "USA" AND ContactTitle Like "Sales*"

Diese WHERE-Klausel gibt nur solche Datensätze zurück, die im Feld Country den Eintrag USA enthalten und deren Feld ContactTitle mit Sales beginnt. Anstelle von AND können Sie auch OR verwenden: WHERE Country = "USA" OR Country = "Canada"

Diese Klausel gibt alle Datensätze zurück, die im Feld Country den Eintrag USA oder Canada enthalten. Betrachten Sie zum Vergleich das folgende Beispiel: WHERE Country = "USA" OR ContactTitle Like "Sales*"

Diese Anweisung gibt alle Datensätze zurück, die im Feld Country den Eintrag USA enthalten, sowie diejenigen, deren Feld ContactTitle mit Sales beginnt. Handelsvertreter aus China werden von dieser Klausel ebenfalls zurückgegeben, weil auch deren Feld ContactTitle mit Sales beginnt. Die Kombination der WHERE-Klausel mit den Klauseln SELECT und FROM sieht wie folgt aus: SELECT ClientID, CompanyName FROM tblClients WHERE Country = "USA" OR Country = "Canada"

SQL

463

Die ORDER BY-Klausel Die ORDER BY-Klausel legt die Sortierreihenfolge der zurückgegebenen Zeilen fest. Es handelt sich um eine optionale Klausel, die wie folgt aussieht: ORDER BY ClientID

In dieser Klausel können auch mehrere Felder angegeben werden: ORDER BY Country, ClientID

Werden mehrere Felder angegeben, gibt das an linker Stelle stehende Feld die primäre Sortierung an. Jedes weitere Feld dient als untergeordnete Sortierung. Kombiniert mit dem Rest der SELECT-Anweisung ergibt sich folgender Ausdruck: SELECT ClientID, CompanyName FROM tblClients WHERE Country = "USA" OR Country = "Canada" ORDER BY ClientID

Die JOIN-Klausel Häufig müssen Sie SELECT-Anweisungen formulieren, die Daten in mehreren Tabellen suchen. In solchen Fällen ist es erforderlich, dass Sie die Tabellen mit der JOINKlausel verknüpfen. Diese Klausel unterscheidet sich in Abhängigkeit davon, ob Sie Tabellen mit einer inneren, linken äußeren oder rechten äußeren Verknüpfung miteinander verbinden. Es folgt ein Beispiel für eine innere Verknüpfung: SELECT DISTINCTROW tblClients.ClientID, tblClients.CompanyName, tblProjectsProjectName, tblProjects.ProjectDescription FROM tblClients INNER JOIN tblProjects ON tblClients.ClientID = tblProjects.ClientID

Beachten Sie, dass als Ergebnis der Abfrage vier Spalten zurückgegeben werden. Zwei Spalten stammen aus der Tabelle tblClients und zwei aus tblProjects. Die SELECT-Anweisung verwendet eine innere Verknüpfung von tblClients mit tblProjects über das Feld ClientID. Das bedeutet, dass nur Kunden mit Bestellungen als Ergebnis der Abfrage angezeigt werden. Vergleichen Sie diese Anweisung mit der folgenden: SELECT DISTINCTROW tblClients.ClientID, tblClients.CompanyName, tblProjectsProjectName, tblProjects.ProjectDescription FROM tblClients LEFT JOIN tblProjects ON tblClients.ClientID = tblProjects.ClientID

In diesem Beispiel werden die Tabellen tblClients und tblProjects über das Feld ClientID mit der LEFT JOIN-Klausel verknüpft. Das Ergebnis enthält alle Datensätze, egal ob Aufträge vorliegen oder nicht.

464

Kapitel 11: Fortgeschrittene Abfragetechniken

Das Wort OUTER wird bei der Klausel LEFT JOIN automatisch vorausgesetzt.

Die Klauseln ALL, DISTINCTROW und DISTINCT Die ALL-Klausel einer SELECT-Anweisung legt fest, dass alle Zeilen, die mit der WHEREKlausel übereinstimmen, zu den Ergebnissen gehören. Das Schlüsselwort DISTINCT wird benutzt, damit Access entsprechend den Feldern des Abfrage-Ergebnisses doppelte Zeilen entfernt. Dies hat die gleichen Auswirkungen wie das Setzen der Eigenschaft Keine Duplikate auf JA in der grafischen Entwurfsansicht. Wird das Schlüsselwort DISTINCTROW verwendet, entfernt Access alle doppelten Zeilen basierend auf allen Spalten aller Tabellen, so wie dies auch über Einstellen der Eigenschaft Eindeutige Datensätze auf JA in der grafischen Entwurfsansicht geschieht. Die GROUP BY-Klausel Mit der GROUP BY-Klausel werden statistische Summen berechnet. Sie wird auch erzeugt, wenn Sie in der grafischen Entwurfsansicht eine Summenabfrage zusammenstellen. Im folgenden Beispiel gibt die SELECT-Anweisung das Land, die Stadt und die Gesamtfrachtkosten für jede Kombination aus Land und Stadt an: SELECT DISTINCTROW tblCustomers.Country, tblCustomers.City Sum(tblOrders.Freight) AS SumOfFreight FROM tblCustomers INNER JOIN tblOrders ON tblCustomers.CustomerID = tblOrders.CustomerID GROUP BY tblCustomers.Country, tblCustomers.City

Die GROUP BY-Klausel zeigt an, dass keine Einzelheiten der ausgewählten Datensätze, sondern nur die in der GROUP BY-Klausel angegebenen Felder einmalig angezeigt werden. Eines der Felder der SELECT-Anweisung muss eine zusammenfassende Funktion enthalten. Das Ergebnis dieser zusammenfassenden Funktion wird zusammen mit den in der GROUP BY-Klausel angegebenen Feldern angezeigt. Die HAVING-Klausel Die HAVING-Klausel ist mit der WHERE-Klausel vergleichbar, unterscheidet sich jedoch in einem entscheidenden Punkt: sie wird nach der Zusammenfassung der Daten angewendet. Im folgenden Beispiel wird die Bedingung > 1000 nach der zusammenfassenden Funktion SUM für das Gruppieren angewendet: SELECT DISTINCTROW tblCustomers.Country, tblCustomers.City Sum(tblOrders.Freight) AS SumOfFreight FROM tblCustomers INNER JOIN tblOrders ON tblCustomers.CustomerID = tblOrders.CustomerID GROUP BY tblCustomers.Country, tblCustomers.City HAVING (((Sum(tblOrders.Freight))>1000))

SQL

11.7.3

465

Das Gelernte anwenden

Sie können an zwei unterschiedlichen Stellen mit SQL-Anweisungen arbeiten und diese eingeben:

 Im Fenster SQL-ANSICHT einer Abfrage  In VBA-Programmen Betrachten wir diese Möglichkeiten etwas genauer. Das grafische QBE-Raster als Zwei-Wege-Werkzeug Zum Schreiben von SQL-Anweisungen bietet sich die SQL-Ansicht einer Abfrage an: 1. Beginnen Sie damit, eine neue Abfrage zu erstellen. 2. Fügen Sie einige Felder und vielleicht auch einige Kriterien hinzu. 3. Wählen Sie im Menü ANSICHT die Option SQL-ANSICHT. 4. Versuchen Sie, die SQL-Anweisung mit Hilfe des in diesem Kapitel Gelernten zu ändern. 5. Wählen Sie über die Schaltfläche ANSICHT der Symbolleiste die Option ENTWURFSANSICHT. Wenn Sie nicht gegen SQL-Syntaxregeln verstoßen haben, können Sie ohne Probleme wieder zur Entwurfsansicht wechseln und das grafische Ergebnis Ihrer Veränderungen betrachten. Haben Sie einen Syntaxfehler in die SQL-Anweisung eingebaut, wird eine Fehlermeldung angezeigt, wenn Sie zur Entwurfsansicht der Abfrage zurückkehren wollen. SQL-Anweisungen in VBA-Code einbinden SQL-Anweisungen können auch direkt aus dem VBA-Code heraus ausgeführt werden. Hierfür stehen Ihnen zwei Möglichkeiten zur Verfügung:

 Sie erstellen eine temporäre Abfrage und führen diese aus.  Sie öffnen mit der SQL-Anweisung eine Datensatzgruppe als Grundlage für die Datensatzgruppe. VBA erlaubt das Erstellen einer Abfrage im Handumdrehen. Sie können die Abfrage ausführen, müssen sie aber nicht speichern. In der folgenden Funktion CurrentDB werden die Klammern ausgelassen, weil VBA bei Funktionen ohne Argumente keine Klammern benötigt. Sie können selbst entscheiden, ob Sie diese verwenden möchten. Der Code sieht folgendermaßen aus: Sub CreateTempQuery() Dim cmd As ADODB.Command Dim rst As ADODB.Recordset Set cmd = New ADODB.Command

466

Kapitel 11: Fortgeschrittene Abfragetechniken

With cmd .ActiveConnection = CurrentProject.Connection .CommandText = "Select ProjectID, ProjectName from " & _ "tblProjects Where ProjectTotalEstimate > 30000" .CommandType = adCmdText .Prepared = True Set rst = .Execute End With Do Until rst.EOF Debug.Print rst!ProjectID, rst!ProjectName rst.MoveNext Loop End Sub

Die Arbeit mit Datensatzgruppen wird in Kapitel 12 ausführlich behandelt. Zunächst einmal brauchen Sie nur zu verstehen, dass dieser Code eine temporäre Abfragedefinition mit einer SQL-Anweisung erstellt. In diesem Beispiel wird die Abfragedefinition der Datenbank nicht hinzugefügt, sondern die SQL-Anweisung ausgeführt, aber nicht gespeichert. Eine SQL-Anweisung kann auch Bestandteil der Open-Methode einer Datensatzgruppe sein: Sub OpenRWithSQL() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.Open "Select ProjectId, ProjectName from " & _ "tblProjects Where ProjectTotalEstimate > 30000", _ CurrentProject.Connection Do Until rst.EOF Debug.Print rst!ProjectID, rst!ProjectName rst.MoveNext Loop End Sub

Auch dieser Code wird in Kapitel 12 ausführlicher erörtert. Beachten Sie, dass das Datensatzgruppenobjekt zwei Parameter erhält. Bei dem ersten handelt es sich um eine SQL-Anweisung und beim zweiten um das Objekt Connection.

Union-Abfragen

11.8

467

Union-Abfragen

Mit einer Union-Abfrage können Sie die Daten zweier Tabellen mit ähnlichen Strukturen kombinieren. Die Ausgabe enthält Daten beider Tabellen. Eine Tabelle tblTimeCards kann beispielsweise aktuelle und eine Tabelle tblTimeCardsArchive archivierte Stempelkarten enthalten. Schwierig wird es, wenn Sie einen Bericht mit den Daten beider Tabellen erstellen möchten. Hierfür formulieren Sie eine UnionAbfrage für die Datenherkunft des Berichts: 1. Klicken Sie im Datenbankfenster in der Liste der Objekte auf ABFRAGEN und klicken Sie anschließend doppelt auf ERSTELLT EINE NEUE ABFRAGE IN DER ENTWURFSANSICHT. 2. Klicken Sie im Dialogfeld TABELLEN ANZEIGEN auf die Schaltfläche SCHLIESSEN, ohne eine Tabelle ausgewählt zu haben. 3. Wählen Sie ABFRAGE|SQL SPEZIFISCH|UNION, um ein SQL-Fenster zu öffnen. 4. Geben Sie die UNION-SQL-Klausel ein. Beachten Sie, dass Sie nicht in die Entwurfsansicht zurückkehren können (siehe Abbildung 11.34). 5. Klicken Sie in der Symbolleiste auf die Schaltfläche AUSFÜHREN, um die Abfrage auszuführen.

Abbildung 11.34: Ein Beispiel für eine UnionAbfrage, bei der die Tabelle tblTimeCards mit der Tabelle tblTimeCardsArchive verknüpft wird

468

11.9

Kapitel 11: Fortgeschrittene Abfragetechniken

Pass-Through-Abfragen

Mit der Pass-Through-Abfrage können Sie nicht interpretierte SQL-Anweisungen an die zu Grunde liegende Datenbank senden, wenn Sie etwas anderes als die JetEngine einsetzen. Diese nicht interpretierten Anweisungen sind in einem SQL-Format verfasst, das der spezifischen Datenbank entspricht. Die Jet-Engine erkennt diese Anweisung, unternimmt aber keinen Versuch, die Syntax zu analysieren oder zu verändern. Pass-Through-Abfragen werden in unterschiedlichen Situationen verwendet:

 Die durchzuführende Aktion wird vom Back-End-Datenbank-Server aber nicht von Access oder ODBC-SQL unterstützt.

 Access oder der ODBC-Treiber führen eine mangelhafte Syntaxanalyse der SQLAnweisung durch und senden sie in optimierter Form an die Back-End-Datenbank.

 Sie möchten eine gespeicherte Prozedur auf dem Back-End-Datenbank-Server ausführen.

 Sie möchten sicherstellen, dass die SQL-Anweisung auf dem Server ausgeführt wird.

 Sie möchten Daten mehrerer Tabellen des Datenbank-Servers miteinander verknüpfen. Führen Sie die Verknüpfung ohne eine Pass-Through-Abfrage aus, wird sie im Arbeitsspeicher des Rechners des Benutzers vorgenommen, nachdem alle erforderlichen Daten über das Netzwerk gesendet wurden. Die Pass-Through-Abfragen bieten zwar viele Vorteile, sie sind jedoch kein Allheilmittel. Außerdem besitzen Sie einige Nachteile:

 Da Sie SQL-Anweisungen senden, die für einen speziellen Datenbank-Server bestimmt sind, müssen Sie alle umschreiben, wenn Sie zu einem anderen Server wechseln möchten.

 Die von einer Pass-Through-Abfrage zurückgegebenen Ergebnisse können nicht aktualisiert werden.

 Die Jet-Engine führt keine Syntaxüberprüfung der Abfrage durch, bevor diese an das Datenbank-Back-End weitergereicht wird. Nachdem Sie nun die Vor- und Nachteile einer Pass-Through-Abfrage kennen, sollen Sie jetzt lernen, wie eine solche Abfrage erstellt wird: 1. Klicken Sie im Datenbankfenster in der Liste der Objekte auf ABFRAGEN und klicken Sie anschließend doppelt auf ERSTELLT EINE NEUE ABFRAGE IN DER ENTWURFSANSICHT. 2. Klicken Sie im Dialogfeld TABELLEN ANZEIGEN auf die Schaltfläche SCHLIESSEN, ohne eine Tabelle ausgewählt zu haben.

469

Die Weitergabe von Nullwerten und Abfrage-Ergebnisse

3. Wählen Sie ABFRAGE|SQL öffnen.

SPEZIFISCH|PASS-THROUGH,

um ein SQL-Fenster zu

4. Geben Sie die SQL-Anweisung im Dialekt des Back-End-Datenbank-Servers ein. 5. Öffnen Sie das Dialogfeld EIGENSCHAFTEN und geben Sie für die ODBC-Verbindung die entsprechende Zeichenfolge ein (siehe Abbildung 11.35).

Abbildung 11.35: Eine SQL-PassThrough-Abfrage, die bestimmte Felder der SalesTabelle der Datenquelle PublisherInfo auswählt

6. Klicken Sie in der Symbolleiste auf die Schaltfläche AUSFÜHREN, um die Abfrage auszuführen.

11.10

Die Weitergabe von Nullwerten und AbfrageErgebnisse

Null-Werte können an den Abfrage-Ergebnissen schwere Schäden auslösen, da sie

weitergereicht werden. Betrachten Sie Abbildung 11.36 und beachten Sie dabei, dass beim Einfügen von Werten in den Feldern parts oder labor das Resultat der Addition beider Felder Null ist, wenn eines der Felder Null-Werte enthält. In Abbildung 11.37 wurde dieser Fehler berichtigt. Die beiden Werte werden mit dem folgenden Ausdruck addiert: TotalPrice: NZ([Parts]) + NZ([Labor])

Dieser Ausdruck wandelt mit der Nz-Funktion vor der Addition die Null-Werte in 0 um.

470

Kapitel 11: Fortgeschrittene Abfragetechniken

Abbildung 11.36: Weitergabe von Null in einem Abfrage-Ergebnis

Abbildung 11.37: Eine Möglichkeit, die Weitergabe von Null zu unterbinden

11.11

Unterabfragen

Mit Unterabfragen können Sie eine SELECT-Anweisung in eine andere SELECT-Anweisung einbetten. Platzieren Sie eine Unterabfrage in den Kriterien einer Abfrage, dann basiert eine Abfrage auf den Ergebnissen einer anderen. Abbildung 11.38 zeigt ein Beispiel für eine Unterabfrage. Die gezeigte Abfrage findet alle Kunden ohne Bestellungen. Die SQL-Anweisung sieht wie folgt aus: SELECT DISTINCTROW tblClients.ClientsID, tblClients.CompanyName FROM tblClients WHERE tblClients.ClientID NOT In (Select ClientID from tblProjects)

Diese Abfrage führt zuerst die SELECT-Anweisung Select ClientID from tblProjects aus. Das Ergebnis dient anschließend als Kriterium für die erste Abfrage.

Das Ergebnis einer Funktion als Abfragekriterium verwenden

471

Abbildung 11.38: Eine Abfrage mit einer Unterabfrage

11.12

Das Ergebnis einer Funktion als Abfragekriterium verwenden

Oft ist nicht bekannt, dass der Rückgabewert einer Funktion als Ausdruck in einer Abfrage oder als Parameter für eine Abfrage verwendet werden kann. Die Abfrage in Abbildung 11.39 wertet den Rückgabewert der Funktion Initials mit einer Bedingung aus, um festzustellen, ob ein Mitarbeiter Bestandteil des AbfrageErgebnisses ist. Die unten aufgeführte Initials-Funktion (Sie finden diese auch im Modul basUtils der Datenbank CHAP11EX.MDB auf der beiliegenden CD-ROM) übernimmt zwei Zeichenfolgen und gibt den ersten Buchstaben jeder Zeichenfolge gefolgt von einem Punkt zurück: Function Initials(strFirstName As String, _ strLastName As String) As String Initials = Left(strFirstName, 1) & "." & _ Left(strLastName, 1) & "." End Function

Abbildung 11.39: Eine Abfrage, die den Rückgabewert einer Funktion als Ausdruck benutzt

472

Kapitel 11: Fortgeschrittene Abfragetechniken

Der Rückgabewert einer Funktion kann auch als Kriterium einer Abfrage dienen (siehe Abbildung 11.40). Die Abfrage dieser Abbildung benutzt eine Funktion HighlyPaid, um zu ermitteln, welche Datensätze im Abfrage-Ergebnis erscheinen. Diese Funktion, die Sie auch auf der beiliegenden CD-ROM im Modul basUtils der Datenbank CHAP11EX.MDB finden, sieht folgendermaßen aus: Function HighlyPaid(strTitle) As Currency Dim curHighRate As Currency Select Case strTitle Case "Sr. Programmer" curHighRate = 60 Case "Systems Analyst" curHighRate = 80 Case "Project Manager" curHighRate = 100 Case Else curHighRate = 50 End Select HighlyPaid = curHighRate End Function

Die Funktion übernimmt den Titel des Mitarbeiters als Parameter. Anschließend wertet sie diesen Wert aus und gibt einen Schwellenwert an die Abfrage zurück, der als Kriterium für die Spalte Billing Rate der Abfrage dient.

Abbildung 11.40: Eine Abfrage, die den Rückgabewert einer Funktion als Kriterium verwendet

Die Werte für eine Parameterabfrage aus einem Formular einlesen

11.13

473

Die Werte für eine Parameterabfrage aus einem Formular einlesen

Die größte Frustration bei Parameterabfragen kommt auf, wenn mehrere Parameter für die Ausführung der Abfrage erforderlich sind. Der Benutzer wird mit mehreren Dialogfeldern für die einzelnen Parameter der Abfrage konfrontiert. Die folgenden Schritte erläutern, wie eine Parameterabfrage die Werte über ein Formular erhält: 1. Erstellen Sie ein neues, ungebundenes Formular. 2. Fügen Sie Textfelder oder andere Steuerelemente für die Kriterien der einzelnen Parameter der Abfrage hinzu. 3. Bezeichnen Sie jedes Steuerelement so, dass Sie beim Lesen erkennen können, welche Daten das Steuerelement enthält. 4. Fügen Sie dem Formular eine Befehlsschaltfläche hinzu und lassen Sie diese die Parameterabfrage aufrufen (siehe Abbildung 11.41)

Abbildung 11.41: Der Code für das Ereignis Click der Befehlsschaltfläche, welche die Parameterabfrage aufruft

5. Speichern Sie das Formular. 6. Erstellen Sie die Abfrage und fügen Sie die Parameter hinzu. Jeder Parameter sollte sich auf ein Steuerelement des Formulars beziehen (siehe Abbildung 11.42).

474

Kapitel 11: Fortgeschrittene Abfragetechniken

Abbildung 11.42: Parameter, die sich auf Steuerelemente eines Formulars beziehen

7. Klicken Sie mit der rechten Maustaste in die obere Hälfte des Abfrage-Entwurffensters und wählen Sie PARAMETER. Definieren Sie im Dialogfeld PARAMETER für jeden Parameter einen Datentyp (siehe Abbildung 11.43).

Abbildung 11.43: Im Dialogfeld Parameter können Sie den Datentyp der einzelnen Parameter der Abfrage auswählen

8. Speichern und schließen Sie die Abfrage. 9. Tragen Sie die Werte im Kriterienformular ein und führen Sie durch Klicken auf die Befehlsschaltfläche die Abfrage aus.

11.13.1

Für die Praxis

Anwendung der Techniken in Ihren Anwendungen Die in diesem Kapitel vorgestellten erweiterten Abfragetechniken werden für unser Zeit- und Abrechnungssytems genutzt. Schauen Sie sich einige praktische Anwendungen dieser erweiterten Techniken an.

Die Werte für eine Parameterabfrage aus einem Formular einlesen

475

Die Beispiele dieses Abschnitts sind in der Datenbank CHAP11.MDB auf der beiliegenden CD-ROM enthalten.

11.13.2 Zahlungsarchivierung Nach einiger Zeit kann es erforderlich sein, dass Sie einige der Daten der Tabelle tblPayments archivieren. Die Zahlungsdaten werden mit zwei Abfragen archiviert. Die erste Abfrage mit dem Namen qappAppendToPaymentArchive ist eine Anfügeabfrage, die alle Daten eines bestimmten Zeitraums an die Tabelle tblPaymentsArchive sendet (siehe Abbildung 11.44). Die zweite Abfrage mit dem Namen qdelRemoveFromPayments ist eine Löschabfrage, die alle archivierten Daten aus der Tabelle tblPayments entfernt (siehe Abbildung 11.45). Die Archivierung wird über ein Formular mit der Bezeichnung frmArchivePayments durchführt, in dem der Zeitraum zur Laufzeit vom Benutzer eingegeben wird (siehe Abbildung 11.46).

Abbildung 11.44: Die Anfügeabfrage qappAppendToPaymentArchive

Abbildung 11.45: Die Löschabfrage qdelRemoveFromPayments

476

Kapitel 11: Fortgeschrittene Abfragetechniken

Abbildung 11.46: Das Formular mit den Kriterien für den Archivierungsvorgang

11.13.3 Alle Zahlungen anzeigen Bei bestimmten Gelegenheiten wollen Sie vielleicht Daten beider Tabellen miteinander kombinieren. Hierfür müssen Sie eine Union-Abfrage zum Verknüpfen der Tabellen tblPayments und tblPaymentsArchive erstellen. Abbildung 11.47 enthält den Entwurf für diese Abfrage.

Abbildung 11.47: Die Tabellen tblPayments und tblPaymentsArchive mit einer Union-Abfrage verknüpfen

11.13.4 Eine Ländertabelle erstellen Da Sie regelmäßig die Länder und Bundesländer bearbeiten, benötigen Sie wahrscheinlich eine Liste, die Ihnen alle Länder und Bundesländer Ihrer aktuellen Kunden anzeigt. Abbildung 11.48 enthält die hierfür erforderliche Abfrage. Sie benutzt die Tabelle tblClients ohne Duplikate für das Feld StateProvince. Es handelt sich hier um eine Tabellenerstellungsabfrage, welche die eindeutigen Werte dieser Liste nimmt und in die Tabelle tblProvinceState ausgibt.

Die Werte für eine Parameterabfrage aus einem Formular einlesen

477

Abbildung 11.48: Eine Tabellenerstellungsabfrage, die eine Tabelle tblStateProvince erstellt

Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

Kapitel

Hier lesen Sie:

 Datenzugriffsobjekte  ActiveX und Datenzugriffsobjekte im Vergleich  Das Datenobjektmodell  Arten von ADO-Datensatzgruppen  ADO-Recordset-Eigenschaften und Methoden  Tabellendaten bearbeiten  Datenbankobjekte erstellen  Das Datenzugriffsobjektmodell (DAO)  CurrentDB()  Arten von DAO-Datensatzgruppen  Zwischen Datensatzgruppenobjekten wählen  Mit DAO-Recordset-Eigenschaften und Methoden umgehen  Mit DAO-Code Tabellendaten bearbeiten  Datenbankobjekte erstellen  Die DAO-Container-Auflistung

12.1

Datenzugriffsobjekte

ActiveX-Datenobjekte (ADO) und Datenzugriffsobjekte werden eingesetzt, um JetEngine-Objekte mit Hilfe von Code zu erstellen, zu verändern und zu entfernen. Diese verleihen Ihnen die Flexibilität, um über die Benutzerschnittstelle hinaus die in

480

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

der Jet-Engine und anderen Formaten gespeicherten Daten zu bearbeiten. Mit Hilfe von ActiveX-Datenobjekten oder Datenzugriffsobjekten können Sie diese Aufgaben durchführen:

 die Struktur einer bestehenden Datenbank analysieren  Tabellen oder Abfragen hinzufügen oder verändern  neue Datenbanken erstellen  die grundlegenden Definitionen von Abfragen modifizieren, indem Sie die der Abfrage zu Grunde liegenden SQL-Befehle verändern

 durch Datensatzmengen navigieren  Tabellendaten verändern

12.2

ActiveX-Datenobjekte und Datenzugriffsobjekte im Vergleich

In den früheren Ausgaben dieses Buchs wurde lediglich auf Datenzugriffsobjekte (DAO) verwiesen. ActiveX-Datenobjekte (ADO) wurden nicht erwähnt. Der Grund hierfür liegt darin, dass sich ActiveX-Datenobjekte bei der Veröffentlichung von Access 97 noch in einem sehr frühen Entwicklungsstadium befanden. Als ich mit dem Schreiben dieses Buchs begann, musste ich eine Entscheidung treffen, ob ich ADO, DAO oder beides behandeln soll. Ich habe mir diese Frage eine ganze Zeit lang durch den Kopf gehen lassen. Obwohl ich empfehle, neue Entwicklungen mit Hilfe von ADO vorzunehmen, wäre das Entfernen der DAO betreffenden Erläuterungen aus diesem Buch verfrüht. Ich habe mich entschieden, in diesem Kapitel sowohl ADO als auch DAO zu besprechen. In der ersten Hälfte dieses Kapitels wird ADO abgedeckt. Falls Sie eine neue Anwendung entwickeln oder die Möglichkeit haben, eine bereits bestehende Anwendung zu überarbeiten, ist die erste Hälfte des Kapitels für Sie gedacht. Wenn Sie nicht mit DAO vertraut sind und mit vorhandenen Anwendungen arbeiten müssen, stellt Ihnen die zweite Hälfte des Kapitels die Grundlagen von DAO bereit. Wenn Sie schließlich bereits über DAO-Kenntnisse verfügen und DAO und ADO vergleichen und gegenüberstellen wollen, zeigt Ihnen dieses Kapitel, wie Sie diese Aufgaben mit Hilfe der beiden Datenzugriffsverfahren durchführen können. Obwohl DAO in diesem Kapitel behandelt wird, werden im Rest dieses Buches alle erforderlichen Datenzugriffe mit ADO vorgenommen.

Das Datenobjektmodell von ActiveX

12.3

481

Das Datenobjektmodell von ActiveX

Abbildung 12.1 zeigt einen Überblick über das von Microsoft stammende Datenobjektmodell (ADO-Modell) von ActiveX. Im Gegensatz zu dem Datenzugriffsobjektmodell (DAO-Modell) ist das ADO-Objektmodell nicht hierarchisch aufgebaut.

Fehler Felder Connection

Eigenschaften

Command

Datensatz Eigenschaften Parameter Eigenschaften Eigenschaften

12.3.1

Abbildung 12.1: Das ADO-Objektmodell

Das Connection-Objekt

Das Connection-Objekt definiert eine Sitzung für einen Benutzer und eine Datenquelle. Obwohl das ADO-Objekt nicht als hierarchisch erachtet wird, wird das Connection-Objekt als das sich auf der höchsten Ebene befindende ADO-Objekt betrachtet. Nach dem Erstellen eines ADO-Objekts können Sie dieses mit mehreren Datensatzgruppen verwenden. Das verbessert die Leistung und vereinfacht Ihren Programm-Code wesentlich. Ein Connection-Objekt muss vor seiner Verwendung deklariert werden. Diese Deklaration sieht folgendermaßen aus: Dim cnn as ADODB.Connection

Nach dem Deklarieren des Connection-Objekts muss eine neue Objektinstanz von Connection gebildet werden. Der Code hat folgendes Aussehen: Set cnn = New ADODB.Connection

Dieses Connection-Objekt muss dann geöffnet werden. Die Methode Open des Connection-Objekts erhält eine Verbindungszeichenfolge sowie als Parameter optional eine Benutzerkennung, ein Passwort und Optionen. Unten sehen Sie ein Beispiel für die einfachste Verwendung der Methode Open: cnn.Open CurrentProject.Connection

482

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

In diesem Beispiel wird die Verbindung mit der Methode Open des ConnectionObjekts hergestellt. Die Verbindungszeichenfolge wird bereitgestellt, die von der Eigenschaft Connection des Objekts CurrentProject zurückgegeben wird. Auf diese Weise wird eine Verbindung geöffnet, die auf der mit der aktuellen Datenbank assoziierten Verbindung basiert. Der Verweis auf die mit dem aktuellen Projekt verknüpfte Verbindung lässt sich wie folgt ändern: cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" &_ "Persist Security Info=False;" &_ "User ID=Admin;" &_ "Data Source=Q:\Clients\sams\" &_ "Mastering Access 2000 Development\Databases" &_ "\Chap12Ex.mdb;"

Die vollständige zum Einrichten einer Verbindung erforderliche Routine sehen Sie in Listing 12.1. Listing 12.1:

Erstellen eines Connection-Objekts

Sub CreateConnection() Dim cnn As ADODB.Connection Set cnn = New ADODB.Connection cnn.Open CurrentProject.Connection cnn.Close Set cnn = Nothing End Sub

Listing 12.1 und der überwiegende Teil des in diesem Kapitel aufgeführten Codes befinden sich auf der diesem Buch beiliegenden CD-ROM in der Datei CHAP12EX.MDB.

12.3.2

Das Recordset-Objekt

Ein Recordset-Objekt wird eingesetzt, um Datensätze als eine Gruppe zu betrachten, und verweist auf die von einer Datenanforderung zurückgegebene Zeilenmenge. Wie bei einem Connection-Objekt müssen Sie ein Recordset-Objekt vor seiner Verwendung deklarieren. Der Code sieht wie folgt aus: Dim rst as ADODB.Recordset

Nach dem Deklarieren des Recordset-Objekts muss eine Instanz von diesem gebildet werden. Dies funktioniert so: Set rst = New ADODB.Recordset

Wie beim Connection-Objekt wird die Methode Open verwendet, damit das RecordsetObjekt auf eine Datensatzmenge zeigt. Der Code hat folgendes Aussehen: rst.Open "Select * From tblClients", CurrentProject.Connection

Das Datenobjektmodell von ActiveX

483

Der erste Parameter der Methode Open gibt die Datenquelle an. Bei der Quelle kann es sich um den Namen einer Tabelle, eine SQL-Anweisung, den Namen einer gespeicherten Prozedur, den Variablennamen eines Command-Objekts oder den Dateinamen einer persistenten Datensatzgruppe handeln. Im Beispiel ist die SQL-Anweisung Select die Quelle. Der zweite Parameter der Methode Open muss entweder eine gültige Verbindungszeichenfolge oder der Name eines Connection-Objekts sein. Im Beispiel gibt die Eigenschaft Connection des Objekts CurrentProject eine Zeichenfolge zurück, die als Verbindungszeichenfolge verwendet wird. Der vollständige Code ist in Listing 12.2 aufgeführt. Listing 12.2:

Erstellen einer Datensatzgruppe mit Hilfe einer Verbindungszeichenfolge

Sub CreateRecordset1() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.Open "Select * From tblClients", CurrentProject.Connection Debug.Print rst.GetString rst.Close Set rst = Nothing End Sub

Beachten Sie, dass nach dem Öffnen der Datensatzgruppe das Resultat der Methode GetString des Recordset-Objekts im Direktfenster ausgegeben wird. Die Methode GetString des Recordset-Objekts erstellt auf der Basis der in der Datensatzgruppe enthaltenen Daten eine Zeichenfolge. Zum jetzigen Zeitpunkt ist dies ein einfaches Verfahren, um zu überprüfen, ob Ihr Code wie erwartet funktioniert. Beachten Sie ebenfalls, dass die Methode Close des Recordset-Objekts zum Schließen der Datensatzgruppe verwendet wird. Die Methode Close bewirkt, wenn sie auf ein Connectionoder ein Recordset-Objekt angewendet wird, die Freigabe der zugewiesenen Systemressourcen, entfernt das Objekt jedoch nicht aus dem Arbeitsspeicher. Dazu setzt man den Wert des Recordset-Objekts auf Nothing. Obwohl dieser Code recht gut arbeitet, ziehe ich es vor, vor dem Ausführen der Methode Open die Parameter der Methode als Eigenschaften des Recordset-Objekts zu setzen. Sie werden feststellen, dass auf diese Weise Ihr Code beim Hinzufügen von Parametern zur Methode Open wesentlich lesbarer wird. Den Code finden Sie in Listing 12.3. Listing 12.3:

Erstellen einer Datensatzgruppe mit Hilfe der Eigenschaft ActiveConnection

Sub CreateRecordset2() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.Open "Select * From tblClients" Debug.Print rst.GetString rst.Close Set rst = Nothing End Sub

484

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

Letztlich kann man anstelle einer Connection-Zeichenfolge ein Connection-Objekt einsetzen. Dasselbe Connection-Objekt lässt sich für mehrere Datensatzgruppen verwenden. Den Code sehen Sie in Listing 12.4. Listing 12.4:

Erstellen eines Datensatzes mit Hilfe eines Connection-Objekts

Sub CreateRecordset3() Dim cnn As ADODB.Connection Dim rst1 As ADODB.Recordset Dim rst2 As ADODB.Recordset Set cnn = New ADODB.Connection Set rst1 = New ADODB.Recordset Set rst2 = New ADODB.Recordset cnn.ConnectionString = CurrentProject.Connection cnn.Open rst1.ActiveConnection = cnn rst1.Open "Select * From tblClients" rst2.ActiveConnection = cnn rst2.Open "Select * From tblPayments" Debug.Print rst1.GetString Debug.Print rst2.GetString rst1.Close rst2.Close cnn.Close Set rst1 = Nothing Set rst2 = Nothing Set cnn = Nothing End Sub

Beachten Sie, dass sowohl rst1 als auch rst2 dasselbe Connection-Objekt verwenden.

12.3.3

Das Command-Objekt

Das ADO-Objekt Command verkörpert eine mit einer Datenquelle ausgeführte Abfrage, SQL-Anweisung oder gespeicherte Prozedur. Obwohl nicht in jedem Fall erforderlich, ist ein Command-Objekt insbesondere beim Ausführen von parametrisierten Abfragen und gespeicherten Prozeduren hilfreich. Genau wie beim Connection- und Recordset-Objekt muss das Command-Objekt vor seiner Verwendung deklariert werden: Dim cmd as ADODB.Command

Das Datenobjektmodell von ActiveX

485

Als nächstes muss eine Instanz des Command-Objekts gebildet werden: Set cmd = New ADODB.Command

Nach dem Erstellen einer Instanz des Command-Objekts müssen Sie dessen Eigenschaften ActiveConnection und CommandText setzen. Wie bei einem Recordset-Objekt kann es sich bei der Eigenschaft ActiveConnection entweder um eine Verbindungszeichenfolge oder um einen Verweis auf ein Connection-Objekt handeln. Die Eigenschaft CommandText ist die vom Command-Objekt verwendete SQL-Anweisung oder gespeicherte Prozedur. Die Eigenschaften ActiveConnection und CommandText sehen wie folgt aus: cmd.ActiveConnection = CurrentProject.Connection cmd.CommandText = "tblClients"

Den vollständigen Code finden Sie in Listing 12.5. Listing 12.5:

Ein Command-Objekt verwenden

Sub CommandObject() Dim rst As ADODB.Recordset Dim cmd As ADODB.Command Set cmd = New ADODB.Command cmd.CommandText = "Select * from tblClients" cmd.ActiveConnection = CurrentProject.Connection Set rst = cmd.Execute Debug.Print rst.GetString rst.Close Set cmd = Nothing Set rst = Nothing End Sub

In diesem Beispiel wird eine Instanz des Command-Objekts gebildet. Die Eigenschaft CommandText wird auf eine SQL-Anweisung gesetzt und die Eigenschaft ActiveConnection weist auf die mit der aktuellen Datenbank assoziierte Verbindung. Die Ergebnisse der SQL-Anweisung werden mit Hilfe der Methode Execute des CommandObjekts in das Recordset-Objekt zurückgegeben.

486

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

12.4

Arten von ADO-Datensatzgruppen

Die Methode Open eines Recordset-Objekts verfügt über drei Parameter, die sich auf die Art der erstellten Datensatzgruppe auswirken. Diese Parameter sind: CursorType, LockType und Options. Diese Parameter werden kombiniert, um festzulegen, welche Bewegungsarten innerhalb einer Datensatzgruppe ausführbar sind, in welchen Fällen von anderen Benutzern an den einer Datensatzgruppe zu Grunde liegenden Daten vorgenommene Änderungen sichtbar sind und ob die Daten der Datensatzgruppe aktualisiert werden können.

12.4.1

Der Parameter CursorType

Wenn Sie eine Datensatzgruppe öffnen, wird der Parameter CursorType standardmäßig auf adOpenForwardOnly gesetzt. Dies bedeutet, dass Sie sich lediglich vorwärts durch die Datensätze der Datensatzgruppe bewegen und keine von anderen Benutzern vorgenommenen Hinzufügungen, Bearbeitungen oder Löschungen sehen können. Außerdem sind viele Eigenschaften und Methoden wie beispielsweise die Eigenschaft RecordCount und die Methode MovePrevious nicht verfügbar. Für den Parameter CursorType stehen drei weitere Werte zur Verfügung: adOpenStatistic, adOpenKeyset und adOpenDynamic. Die Option adOpenStatistic ermöglicht, sich vorwärts und rückwärts durch die Datensätze einer Datensatzgruppe zu bewegen, aber von anderen Benutzern an den der Datensatzgruppe zu Grunde liegenden Daten vorgenommene Änderungen werden von der Datensatzgruppe nicht wahrgenommen. Die Option adOpenKeyset bietet dasselbe wie die Option adOpenStatistic, darüber hinaus werden von anderen Benutzern durchgeführte Veränderungen in der Datensatzgruppe sichtbar. Schließlich werden bei der Option adOpenDynamic alle von anderen Benutzern vorgenommenen Hinzufügungen, Bearbeitungen und Löschungen von der Datensatzgruppe erkannt. Die Eigenschaft CursorType der Datensatzgruppe lässt sich auf eine von zwei Weisen setzen, wobei eine die Verwendung als Parameter der Methode Open des RecordsetObjekts ist. Dies wird in Listing 12.6 veranschaulicht. Listing 12.6:

CursorType als Parameter der Open-Methode

Sub StaticRecordset1() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.Open "Select * from tblClients", _ CursorType:=adOpenStatic Debug.Print rst.RecordCount

Arten von ADO-Datensatzgruppen

487

rst.Close Set rst = Nothing

End Sub

Beachten Sie, dass in Listing 12.6 die Eigenschaft CursorType als Parameter der Methode Open erscheint. Vergleichen Sie Listing 12.6 und Listing 12.7. Listing 12.7:

Die Eigenschaft CursorType als Eigenschaft des Recordset-Objekts angeben

Sub StaticRecordset2() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.Open "Select * from tblClients" Debug.Print rst.RecordCount rst.Close Set rst = Nothing

End Sub

In Listing 12.7 wird der Parameter CursorType vor dem Ausführen der Methode Open als Eigenschaft des Recordset-Objekts gesetzt. Durch Abtrennen der Eigenschaften von der Methode Open wird die Lesbarkeit des Codes verbessert.

12.4.2

Der Parameter LockType

Obwohl die Eigenschaft CursorType festlegt, welche Bewegungen innerhalb der Datensatzgruppe erfolgen können und ob von anderen Benutzern vorgenommene Änderungen erkannt werden, wirkt sich der Parameter CursorType nicht in geringster Weise auf die Aktualisierbarkeit der Daten einer Datensatzgruppe aus. Tatsächlich wird eine Datensatzgruppe standardmäßig im schreibgeschützten Modus geöffnet. Die Datensatzgruppe lässt sich ausschließlich durch Ändern der Eigenschaft LockType aktualisierbar machen. Der Parameter LockType verfügt über die Optionen adLockReadOnly, adLockPessimistic, adLockOptimistic und adLockBatchOptimistic. Die voreingestellte Option adLockReadOnly gestattet keine Änderungen an der Datensatzgruppe. Die anderen Optionen erlauben das Aktualisieren der Daten der Datensatzgruppe. Die Unterschiede liegen im Zeitpunkt, zu dem die Datensätze gesperrt werden. Bei der Option adLockPessimistic wird der Datensatz gesperrt, sobald der Bearbeitungsprozess einsetzt. Bei der Option adLockOptimistic wird der Datensatz

488

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

beim Aufrufen der Methode Update gesperrt. Mit Hilfe der Option adLockBatchOptimistic können Sie die Sperrung hinausschieben, bis ein Stapel von Datensätzen aktualisiert wird. Alle diese Optionen werden eingehend in Kapitel 17 besprochen. Die Eigenschaft LockType lässt sich wie die Eigenschaft CursorType als Parameter der Methode Open oder als Eigenschaft des Recordset-Objekts setzen. Listing 12.8 zeigt die Einrichtung des Sperrentyps als Eigenschaft des Recordset-Objekts. Listing 12.8:

Konfiguration des Parameters LockType

Sub OptimisticRecordset()

Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.LockType = adLockOptimistic rst.Open "Select * from tblClients" rst!City = "Westlake Village" rst.Update Debug.Print rst!City rst.Close Set rst = Nothing

End Sub In Listing 12.8 wird die Eigenschaft LockType auf adLockOptimistic gesetzt. Der Datensatz wird gesperrt, sobald die Methode Update des Recordset-Objekts aufgerufen wird.

12.4.3

Der Parameter Options

Der Parameter Options legt fest, wie der Datenanbieter das die Quelle bezeichnende Argument einrichten soll. Die gültigen Auswahlmöglichkeiten sind in Tabelle 12.1 aufgeführt. Wert

Beschreibung

AdCmdText

Der Datenanbieter bewertet die Quelle als Befehl.

AdCmdTable

Zum Zurückgeben aller Zeilen der in der Quelle angegebenen Tabelle wird eine SQL-Anweisung erzeugt.

Tabelle 12.1: Gültige Auswahlmöglichkeiten für den Parameter Options

Arten von ADO-Datensatzgruppen

489

Wert

Beschreibung

AdCmdTableDirect

Der Datenanbieter gibt alle Zeilen der in der Quelle genannten Tabelle zurück.

AdCmdStoredProc

Der Datenanbieter bewertet die Quelle als gespeicherte Prozedur.

AdCmdUnknown

Der Typ des Befehls in der Quelle ist unbekannt.

AdCmdFile

Die Quelle wird als beständige Datensatzgruppe bewertet.

AdAsyncExecute

Die Quelle wird asynchron ausgeführt.

AdAsyncFetch

Die anfängliche, in der Eigenschaft Initial Fetch Size angegebene Menge wird abgerufen.

adAsyncFetchNonBlocking

Der Primär-Thread wird während des Datenabrufs niemals blockiert.

Tabelle 12.1: Gültige Auswahlmöglichkeiten für den Parameter Options (Forts.)

Die Voreinstellung für den Wert des Parameters Options ist adCmdUnknown. Falls der Parameter Options nicht ausdrücklich angegeben wird, versucht der Datenanbieter diesen während der Ausführung des Codes zu ermitteln, was sich nachteilig auf die Leistung auswirkt. Aus diesem Grund ist das Angeben dieses Parameters von Bedeutung. Listing 12.9 veranschaulicht die Verwendung des Options-Parameters der Methode Open. Listing 12.9:

Der Parameter Options der Methode Open

Sub OptionsParameter() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.LockType = adLockOptimistic rst.Open "Select * from tblClients", _ Options:=adCmdText rst!City = "Westlake Village" rst.Update Debug.Print rst!City rst.Close Set rst = Nothing

End Sub

In Listing 12.9 wird der Parameter Options auf adCmdText gesetzt. Dies führt dazu, dass die Quelle als SQL-Anweisung bewertet wird.

490

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

12.5

Mit ADO-Recordset-Eigenschaften und -Methoden umgehen

Das ADO-Recordset-Objekt verfügt über eine Vielzahl von Eigenschaften und Methoden, die Ihnen das Navigieren durch eine Datensatzgruppe, das Sortieren, Filtern und Finden von Daten sowie das Aktualisieren der in einer Datensatzgruppe enthaltenen Daten gestattet. Die am häufigsten eingesetzten Eigenschaften und Methoden werden in den folgenden Abschnitten behandelt.

12.5.1

Methoden zum Verschieben von Datensätzen

Wenn Sie eine Variable des Recordset-Objekts gesetzt haben, möchten Sie vermutlich die Daten innerhalb der Datensatzgruppe bearbeiten. Tabelle 12.2 zeigt einige Methoden, mit deren Hilfe Sie sich durch die Datensätze einer Datensatzgruppe bewegen können. Methode

Bewegung

MoveFirst

Zum ersten Datensatz einer Datensatzgruppe

MoveLast

Zum letzten Datensatz einer Datensatzgruppe

MovePrevious

Zum vorhergehenden Datensatz einer Datensatzgruppe

MoveNext

Zum nächsten Datensatz einer Datensatzgruppe

Tabelle 12.2: Methoden zum Navigieren durch die Datensätze einer Datensatzgruppe

Listing 12.10 zeigt ein Beispiel für die Verwendung der Methoden, die zum Navigieren durch die Datensätze eines Recordset-Objekts dienen. Listing 12.10: Methoden zum Bewegen durch die Datensätze eines Recordset-Objekts Sub RecordsetMovements() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.Open "Select * from tblProjects" Debug.Print rst!ProjectID rst.MoveNext Debug.Print rst!ProjectID rst.MoveLast Debug.Print rst!ProjectID rst.MovePrevious

Mit ADO-Recordset-Eigenschaften und -Methoden umgehen

491

Debug.Print rst!ProjectID rst.MoveFirst Debug.Print rst!ProjectID rst.Close Set rst = Nothing End Sub

Dieser Code öffnet eine auf der Tabelle tblProjects basierende Datensatzgruppe. Sobald die Datensatzgruppe geöffnet ist, wird die ProjectID im Direktfenster ausgegeben. Die Methode MoveNext des Recordset-Objekts wird verwendet, um sich zum nächsten Datensatz zu bewegen. Wieder wird die ProjectID im Direktfenster ausgegeben. Die Methode MovePrevious bewegt den Datensatzzeiger einen Datensatz zurück und zieht die erneute Ausgabe der ProjectID nach sich. Schließlich setzt die Methode MoveFirst den Datensatzzeiger auf den ersten Datensatz und die ProjectID wird ausgegeben. Die Datensatzgruppe wird geschlossen und das Recordset-Objekt zerstört.

12.5.2

Beschränkungen einer Datensatzgruppe

Bevor Sie mit dem Navigieren durch Datensatzgruppen beginnen können, müssen Sie zwei Eigenschaften von Datensatzgruppen verstehen: BOF und EOF. Die Namen dieser Eigenschaften sind veraltete Abkürzungen, die für »beginning of file« (Dateianfang) und »end of file« (Dateiende) stehen. Mit ihrer Hilfe wird bestimmt, ob Sie die Grenzen Ihrer Datensatzgruppe erreicht haben. Die Eigenschaft BOF ist True, wenn sich der Datensatzzeiger vor dem ersten Datensatz befindet, und die Eigenschaft EOF hat den Wert True, wenn der Datensatzzeiger hinter dem letzten Datensatz steht. Sie werden die Eigenschaft EOF normalerweise einsetzen, wenn Sie sich mit Hilfe der Methode MoveNext in Vorwärtsrichtung durch Ihre Datensatzgruppe bewegen. Diese Eigenschaft erhält den Wert True, wenn Sie durch die letzte Ausführung der Methode MoveNext die Grenzen der Datensatzgruppe verlassen haben. Analog dazu ist BOF am hilfreichsten, wenn Sie die Methode MovePrevious einsetzen. Sie müssen einige wichtige Merkmale der Eigenschaften BOF und EOF beachten: 1. Falls eine Datensatzgruppe keine Datensätze enthält, haben sowohl die Eigenschaft BOF als auch die Eigenschaft EOF den Wert True. 2. Wenn Sie eine Datensatzgruppe mit mindestens einem Datensatz öffnen, werden die Eigenschaften BOF und EOF auf False gesetzt. 3. Falls der Datensatzzeiger auf den ersten Datensatz einer Datensatzgruppe weist und die Methode MovePrevious ausgeführt wird, erhält die Eigenschaft BOF den Wert True. Wenn Sie noch einmal versuchen, die Methode MovePrevious auszuführen, tritt ein Laufzeitfehler auf.

492

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

4. Falls sich der Datensatzzeiger auf dem letzten Datensatz einer Datensatzgruppe befindet und die Methode MoveNext aufgerufen wird, wird die Eigenschaft EOF auf den Wert True gesetzt. Wenn Sie erneut versuchen, die Methode MoveNext auszuführen, zieht dies einen Laufzeitfehler nach sich. 5. Wenn die Eigenschaften BOF und EOF auf True gesetzt werden, behalten sie diesen Wert solange bei, bis Sie einen gültigen Datensatz ansteuern. 6. Wenn der einzige Datensatz einer Datensatzgruppe gelöscht wird, bleiben die Eigenschaften BOF und EOF solange False, bis Sie versuchen, sich auf einen anderen Datensatz zuzubewegen. Listing 12.11 zeigt ein Beispiel dafür, wie man mit Hilfe der Eigenschaft EOF die Grenzen einer Datensatzgruppe bestimmt. Listing 12.11: Bestimmen der Grenzen einer Datensatzgruppe Sub DetermineLimits() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.Open "Select * from tblProjects" Do Until rst.EOF Debug.Print rst![ClientID] rst.MoveNext Loop rst.Close Set rst = Nothing End Sub

In Listing 12.11 wird eine Datensatzgruppe auf der Grundlage der Tabelle tblProjects geöffnet und die Eigenschaft EOF ausgewertet. Solange die Eigenschaft EOF gleich False ist, wird der Inhalt des Felds ClientID ausgegeben und der Datensatzzeiger rückt auf den nächsten Datensatz der Datensatzgruppe vor.

12.5.3

Die Anzahl der Datensätze in einer Datensatzgruppe feststellen

Die Eigenschaft RecordCount gibt die Anzahl der Zeilen einer Datensatzgruppe zurück. Nicht alle Arten von Datensatzgruppen und Datenanbietern unterstützen die Eigenschaft RecordCount. Falls diese Eigenschaft nicht unterstützt wird, tritt kein Fehler auf, sondern der Wert von RecordCount wird auf -1 gesetzt. Listing 12.12 zeigt ein Beispiel.

Mit ADO-Recordset-Eigenschaften und -Methoden umgehen

493

Listing 12.12: Eine die Eigenschaft RecordCount nicht unterstützende Datensatzgruppe Sub CountRecordsBad() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.Open "Select * from tblProjects" Debug.Print rst.RecordCount rst.Close Set rst = Nothing End Sub

'Gibt -1 aus

Da der Parameter CursorType standardmäßig den Wert adOpenForwardOnly aufweist ist und ein nur Vorwärtsbewegungen gestattender Cursor die Eigenschaft RecordCount nicht unterstützt, wird im Direktfenster -1 ausgegeben. Listing 12.13 behebt dieses Problem. Listing 12.13: Eine die Eigenschaft RecordCount unterstützende Datensatzgruppe Sub CountRecordsGood() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.Open "Select * from tblProjects" Debug.Print rst.RecordCount rst.Close Set rst = Nothing

'Gibt RecordCount aus

End Sub

Beachten Sie, dass CursorType auf adOpenStatic gesetzt wird. Da statische Cursors die Eigenschaft RecordCount unterstützen, wird die korrekte Anzahl von Datensätzen im Direktfenster ausgegeben. Falls Sie mit der DAO-Eigenschaft RecordCount vertraut sind, wird Sie die ADO-Eigenschaft RecordCount möglicherweise überraschen. Bei DAO gibt die Eigenschaft RecordCount lediglich die Anzahl der besuchten Datensätze der Datensatzgruppe zurück. Dies bedeutet, dass Sie sich beim Verwenden von DAO auf dem letzten Datensatz der Datensatzgruppe bewegen müssen, um eine genaue Zählung der Datensätze zu erhalten. Obwohl dieser Schritt bei der Verwendung von ADO überflüssig ist, müssen Sie beachten, dass der Versuch, die Eigenschaft RecordCount abzurufen, zu einem gravierenden Leistungseinbruch führen kann. Ob sich das Abrufen von RecordCount nachteilig auf die Leistung auswirkt, hängt vom jeweiligen Datenanbieter der Datenbank ab.

494

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

Eine wichtige Verwendung der Eigenschaft RecordCount besteht in der Feststellung, dass eine Datensatzgruppe Datensätze enthält. Dieser wichtige Verwendungszweck der Eigenschaft RecordCount wird in Listing 12.14 veranschaulicht. Listing 12.14: Überprüfung, ob in einer Datensatzgruppe Datensätze zurückgegeben werden Sub CheckARecordset() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenStatic rst.Open "Select * from tblEmpty" If Not AreThereRecords(rst) Then MsgBox "Recordset Empty...Unable to Proceed" End If rst.Close Set rst = Nothing End Sub Function AreThereRecords(rstAny As ADODB.Recordset) As Boolean AreThereRecords = rstAny.RecordCount End Function

Die Routine CheckARecordset öffnet eine auf der Tabelle mit der Bezeichnung tblEmpty basierende Datensatzgruppe. Die Tabelle tblEmpty enthält keine Daten. Die Routine CheckARecordset ruft die Funktion AreThereRecords auf und übergibt ihr einen Verweis auf die Datensatzgruppe. Die Funktion AreThereRecords wertet die Eigenschaft RecordCount der ihr übergebenen Datensatzgruppe aus. Sie gibt den Wert False zurück, wenn RecordCount den Wert Null aufweist, und True, wenn der Parameter RecordCount einen anderen Wert als Null hat.

12.5.4

Datensätze sortieren, filtern und finden

Manchmal ist das Sortieren, Filtern und Finden von Daten innerhalb einer Datensatzgruppe erforderlich. Die Eigenschaften Sort und Filter sowie die Methode Find ermöglichen Ihnen das Durchführen dieser Aufgaben. Diese Methoden werden in den folgenden Abschnitten erläutert. Eine Datensatzgruppe sortieren Die Eigenschaft Sort ermöglicht Ihnen das Sortieren der Daten einer bestehenden Datensatzgruppe. Ihre Verwendung wird in Listing 12.15 dargestellt.

Mit ADO-Recordset-Eigenschaften und -Methoden umgehen

495

Listing 12.15: Die Eigenschaft Sort des Recordset-Objekts Sub SortRecordset() Dim rst As ADODB.Recordset Dim intCounter As Integer Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorLocation = adUseClient rst.Open "Select * from tblTimeCardHours" Debug.Print "NOT Sorted!!!" Do Until rst.EOF Debug.Print rst![DateWorked] rst.MoveNext Loop Debug.Print "Now Sorted!!!" rst.Sort = "[DateWorked]" Do Until rst.EOF Debug.Print rst![DateWorked] rst.MoveNext Loop rst.Close Set rst = Nothing End Sub

Der Code beginnt, indem eine auf den tblTimeCardHours-Tabellen aufbauende Datensatzgruppe geöffnet wird. Die Ausgabe der Datensätze der Datensatzgruppe erfolgt in ihrer »natürlichen« Reihenfolge. Als nächstes werden die Daten mit Hilfe der Eigenschaft Sort nach dem Feld DateWorked sortiert. Beachten Sie, dass die Eigenschaft Sort auf einen Feldwert gesetzt wird. Wenn Sie eine Sortierung nach mehr als einem Feld vornehmen wollen, müssen die Feldnamen durch Kommata voneinander getrennt werden. Wenn die Datensätze erneut ausgegeben werden, erscheinen sie in der durch das Feld DateWorked vorgegebenen Reihenfolge. Zum Sortieren in absteigender Reihenfolge muss auf den Feldnamen ein Leerzeichen und danach das Schlüsselwort DESC folgen.

Eine Datensatzgruppe filtern In manchen Fällen kann es vorkommen, dass Sie aus den in einer Datensatzgruppe zurückgegebenen Daten eine Untermenge von diesen auswählen wollen. Die Eigenschaft Filter hilft Ihnen beim Durchführen dieser Aufgabe. Ihre Verwendung wird in Listing 12.16 verdeutlicht.

496

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

Listing 12.16: Die Eigenschaft Filter des Recordset-Objekts Sub FilterRecordSet() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenKeyset rst.LockType = adLockOptimistic rst.Open "Select * from tblTimeCardhours" Debug.Print "Without Filter" Do Until rst.EOF Debug.Print rst![DateWorked] rst.MoveNext Loop rst.Filter = "DateWorked >= #1/1/1995# and DateWorked = 30000" qdf.SQL = strSQL End Sub

Dieser Code erstellt mit Hilfe der Methode CreateQueryDef des Database-Objekts eine neue Abfragedefinition. Dann setzt er die mit dieser verbundene SQL-Anweisung. Das dient zum Anlegen und Speichern der Abfrage. Sie müssen sich im Klaren darüber sein, dass die Methode CreateTablDef im Gegensatz zur Methode CreateQueryDef des Database-Objekts, welche der Datenbank die Abfragedefinition sofort hinzufügt, die Tabellendefinition nicht umgehend der Datenbank übergibt. Um der Datenbank die Tabellendefinition tatsächlich anzuhängen, müssen Sie die Append-Methode der TableDefs-Auflistung verwenden.

Die DAO-Container-Auflistung

539

Sie können eine temporäre Abfragedefinition erstellen, indem Sie bei der Methode CreateQueryDef eine Zeichenfolge mit einer Länge von Null als Namensargument verwenden.

12.16

Die DAO-Container-Auflistung

Eine Container-Auflistung unterhält Informationen über gespeicherte DatabaseObjekte. Zu den Objekttypen der Container-Auflistung gehören Datenzugriffsseiten, Datenbanken, Tabellen (einschließlich Abfragen), Beziehungen, Systembeziehungen, Formulare, Berichte, Scripts (Makros) und Module. Die Container-Auflistung ist verantwortlich dafür, Jet über die Objekte der Benutzerschnittstelle zu informieren. Jet ist das übergeordnete Objekt von Datenbanken, Tabellen, Beziehungen und Systembeziehungen. Bei Formularen, Berichten, Scripts und Modulen ist die AccessAnwendung das übergeordnete Objekt. Jedes Container-Objekt besitzt eine Auflistung von Document-Objekten. Dabei handelt es sich um die eigentlichen Formulare, Berichte und anderen Objekte, die einen Teil der Datenbank bilden. Die Document-Objekte enthalten lediglich zusammenfassende Informationen über jedes Objekt (Erstellungsdatum, Eigentümer usw.), jedoch nicht die eigentlichen Objektdaten. Um innerhalb eines Containers auf ein bestimmtes Dokument zu verweisen, müssen Sie eins von zwei Verfahren einsetzen: Containers("Name")

oder Containers!Name

Zum Auflisten jedes Container-Objekts und der mit diesem verbundenen DocumentObjekte müssen Sie den in Listing 12.65 gezeigten Code verwenden. Listing 12.65: Jedes Container-Objekt und das damit verbundene Document-Objekt auflisten Sub ListAllDBObjects() Dim db As Database Dim con As Container Dim doc As Document Set db = CurrentDb For Each con In db.Containers Debug.Print "*** " & con.Name & " ***" For Each doc In con.Documents Debug.Print doc.Name Next doc Next con End Sub

540

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

Dieser Code geht mit Hilfe einer Schleife alle Dokumente aller Container durch und druckt diese aus.

12.16.1 Für die Praxis Diese Verfahren bei Ihren Anwendungen einsetzen Für die in diesem Kapitel vorgestellten Verfahrensweisen gibt es zahllose Anwendungsmöglichkeiten. In diesem Abschnitt werden lediglich einige der Möglichkeiten zum Anwenden dieser Techniken erläutert. Die an dieser Stelle angeführten Beispiele befinden sich in der Datenbankdatei CHAP12.MDB.

12.16.2 Methoden für den Umgang mit Datensatzgruppen auf einem Dateneingabeformular In manchen Fällen möchten Sie unter Umständen die Funktionen zum Bewegen durch die Datensätze sowie die zum Hinzufügen, Bearbeiten oder Entfernen bei einem Formular deaktivieren und alle diese Funktionen selbst programmieren. Das Durchführen dieser Arbeiten wäre möglicherweise sinnvoll, wenn Sie mit ClientServer-Daten arbeiten und zusätzliche Möglichkeiten zum Steuern der Dateneingabeumgebung haben wollen. Das Einsetzen dieser Techniken wäre auch dann angebracht, wenn Sie Anwendungen sowohl für die Access- als auch die Visual-BasicUmgebung schreiben und die größtmögliche Code-Kompatibilität anstreben. Unabhängig von Ihren Gründen für das Einsetzen der folgenden Verfahren ist es nützlich zu wissen, wie man einem Formular ein Recordset-Objekt zuweist und dann die dem Formular zu Grunde liegende Datensatzgruppe zum Anzeigen und Bearbeiten der Daten einsetzt.

Abbildung 12.3: Das frmRecordsetDialogfeld

Die DAO-Container-Auflistung

541

Abbildung 12.3 zeigt ein Formular, dessen zum Navigieren und zur Datensatzauswahl dienende Schaltflächen entfernt wurden. Das Formular enthält sechs Schaltflächen: MOVE PREVIOUS (), ADD, DELETE, FIND und EXIT. All diese Schaltflächen verwenden die dem Formular zu Grunde liegende Datensatzgruppe, um sich innerhalb des Formulars von Datensatz zu Datensatz zu bewegen und die darin enthaltenen Daten zu bearbeiten. Die Eigenschaft RecordSource ist nicht gesetzt. Das Ereignis Load ist dafür verantwortlich, dem Formular ein Recordset-Objekt zuzuweisen. Listing 12.66 zeigt das Ereignis Load des Formulars. Listing 12.66: Das Ereignis Load wird eingesetzt, um dem Formular ein Recordset-Objekt zuzuweisen Private Sub Form_Load() Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.CursorType = adOpenKeyset rst.LockType = adLockOptimistic rst.Open "Select * from tblClients", Options:=adCmdText Set Me.Recordset = rst End Sub

Der Code beginnt, indem er ein ADODB-Recordset-Objekt deklariert und eine Instanz von ihm bildet. Danach setzt er drei Eigenschaften: ActiveConnection, CursorType und LockType. Die Methode Open wird zum Öffnen einer auf der Tabelle tblClients basierenden Datensatzgruppe eingesetzt. Schließlich wird die Datensatzgruppe mit Hilfe der Set-Anweisung der dem Formular zu Grunde liegenden Datensatzgruppe zugewiesen. Wenn einem Formular eine ADO-Datensatzgruppe zugewiesen wird und dieses Formular auf Jet-Daten aufbaut, wird das Formular im schreibgeschützten Modus erstellt. Falls eine ADO-Datensatzgruppe einem auf SQL-Daten basierenden Formular zugewiesen wird, wird das Formular im Lesen/Schreiben-Modus angelegt. Listing 12.67 zeigt den Code für die Schaltfläche zum Ansteuern des vorhergehenden Datensatzes Listing 12.67: Code für die Schaltfläche zum Ansteuern des vorhergehenden Datensatzes Private Sub cmdPrevious_Click() Me.Recordset.MovePrevious If Me.Recordset.BOF Then Me.Recordset.MoveNext

542

Kapitel 12: Was sind ActiveX-Datenobjekte und Datenzugriffsobjekte?

MsgBox "Already at First Record!!" End If Me.Bookmark = Me.Recordset.Bookmark End Sub

Diese Routine führt die Methode MovePrevious mit der Eigenschaft Recordset des Formulars aus. Falls die Eigenschaft BOF den Wert True annimmt und auf diese Weise anzeigt, dass sich der Datensatzzeiger vor dem ersten gültigen Datensatz befindet, wird die Methode MoveNext mit der Formulareigenschaft Recordset ausgeführt, damit der Datensatzzeiger auf den ersten Datensatz der Datensatzgruppe zurückkehrt. Schließlich wird die Textmarke des Formulars mit der Textmarke der Eigenschaft Recordset synchronisiert. Listing 12.67 zeigt den Code für die Schaltfläche zum Ansteuern des nächsten Datensatzes. Listing 12.68: Code für die Schaltfläche zum Ansteuern des nächsten Datensatzes Private Sub cmdNext_Click() Me.Recordset.MoveNext If Me.Recordset.EOF Then Me.Recordset.MovePrevious MsgBox "Already at Last Record!!" End If Me.Bookmark = Me.Recordset.Bookmark End Sub

Wie in Listing 12.69 zu sehen ist, ist der Code für die Schaltfläche zum Hinzufügen eines Datensatzes ein wenig problematisch. Listing 12.69: Code für die Schaltfläche zum Hinzufügen eines Datensatzes Private Sub cmsAdd_Click() Me.Recordset.AddNew Me.Recordset!CompanyName = "New Company" Me.Recordset.Update Me.Bookmark = Me.Recordset.Bookmark End Sub

Die Methode AddNew wird mit der Eigenschaft Recordset des Formulars ausgeführt. Diese Methode legt im Speicher einen Puffer an, der zum Aufnehmen der neuen Daten dient. Durch das Aufrufen der Methode Update wird der Datensatzzeiger auf den neuen Datensatz bewegt. Da es sich bei dem Feld CompanyName um ein erforderliches Feld handelt, müssen Sie dieses mit Daten füllen, bevor Sie die Methode Update für die Eigenschaft Recordset aufrufen. Durch das Setzen der Formulartextmarke auf die Eigenschaft Bookmark der Datensatzgruppe synchronisieren Sie das Formular mit dem neuen Datensatz. In einer Produktionsumgebung ist es sinnvoll, alle Textfelder zu leeren und den Benutzer vor dem Ausführen der Methoden AddNew oder Update zum Speichern oder Abbrechen zu zwingen.

Die DAO-Container-Auflistung

543

Der Ablauf beim Löschen eines Datensatzes ist, wie in Listing 12.70 gezeigt, recht einfach. Listing 12.70: Einen Datensatz löschen Private Sub cmdDelete_Click() Dim intAnswer As Integer intAnswer = MsgBox("Are You Sure???", vbYesNo + vbQuestion, "Delete Current _ Record?") If intAnswer = vbYes Then Me.Recordset.Delete Call cmdNext_Click Me.Refresh End If End Sub

Dieser Code überprüft, ob der Benutzer den Datensatz wirklich löschen will, und ruft dann für die Formulareigenschaft Recordset die Methode Delete auf. Da der aktuelle Datensatz nicht mehr gültig ist, ruft der Code das Ereignis Click der Schaltfläche cmdNext auf. Der letzte Teil des am Formular beteiligten Codes ist der Code für die Schaltfläche zum Finden eines Datensatzes und wird in Listing 12.71 gezeigt. Listing 12.71: Der Code für die Schaltfläche zum Finden eines Datensatzes Private Sub cmdFind_Click() Dim strClientID As String Dim varBookmark As Variant varBookmark = Me.Recordset.Bookmark strClientID = InputBox("Enter Client ID of Client You Want to Locate") Me.Recordset.Find "ClientID = " & strClientID, Start:=1 If Me.Recordset.EOF Then MsgBox "Client ID " & strClientID & " Not Found!!" Me.Recordset.Bookmark = varBookmark Else Me.Bookmark = Me.Recordset.Bookmark End If End Sub

Die Routine beginnt, indem sie die Textmarke des aktuellen Datensatzes in einer Variant-Variablen speichert. Der Benutzer wird zur Angabe der von ihm gesuchten Client-ID aufgefordert und dann wird die Methode Find für die Formulareigenschaft Recordset aufgerufen. Falls die Eigenschaft EOF den Wert True hat, wird der Benutzer gewarnt und die Textmarke des Datensatzes auf den in der Variant-Variablen enthaltenen Wert gesetzt, so dass der Datensatzzeiger auf die Position zurückkehrt, die er vor der Suche innehatte. Wenn die Client-ID gefunden wird, wird die Textmarke des Formulars mit der der Eigenschaft Bookmark der Eigenschaft Recordset synchronisiert.

Falls etwas nicht nach Plan läuft

Teil II

13 Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung 14 Fehlerbehandlung: Vorbereitung auf das Unvermeidliche 15 Optimieren Ihrer Anwendung

Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Kapitel

Hier lesen Sie:

 Fehler vermeiden  Die Leistungsfähigkeit des Direktfensters nutzen  Den Debugger aufrufen  Haltepunkte zur Problemlösung einsetzen  Code schrittweise durchgehen  Die nächste auszuführende Anweisung festlegen  Das Fenster Aufrufeliste  Mit dem Lokal-Fenster arbeiten  Mit Überwachungsausdrücken arbeiten  Die Verarbeitung nach einem Laufzeitfehler fortsetzen  Gefundenes im Direktfenster ansehen Auch ein guter Programmierer ist nicht unbedingt in der Lage, alles im ersten Anlauf richtig zu machen. Um als VBA-Programmierer volle Effizienz zu erreichen, müssen Sie die Kunst der Fehlersuche beherrschen – den Vorgang, Probleme in Ihrer Anwendung aufzuspüren und zu lösen. Dazu gehört die Lokalisierung und das Erkennen von Problembereichen in Ihrem Code. Die Fehlersuche ist ein Pflichtbestandteil der Anwendungsentwicklung. Glücklicherweise stellt der Visual Basic Editor von Access 2000 ausgezeichnete Werkzeuge zur Unterstützung der Fehlersuche bereit. Mit diesen Werkzeugen können Sie den Code schrittweise durchgehen und nach Bedarf Halte- und Überwachungspunkte setzen. Die Verwendung der VBA-Werkzeuge zur Fehlersuche ist wesentlich effizienter, als aufs Geratewohl in Korrekturen zu Ihrer Anwendung herumzustochern. Ein leistungsfähiger Befehl aus den Access 2000-Fehlersuchwerkzeugen kann Ihnen stundenlange Fehlversuche ersparen. Genau genommen kann darin der Unterschied zwi-

548

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

schen dem erfolgreichen Abschluss und der unendlichen Fortsetzung des Entwicklungsprozesses mit ungelöst hinterlassenen Problemen liegen.

13.1

Fehler vermeiden

Die beste Methode, mit Fehlern umzugehen, besteht darin, sie von vornherein zu vermeiden. Korrekte Programmiertechniken können dabei wirklich hilfreich sein. Die Verwendung von Option Explicit, strenge Typisierung, Benennungsstandards und enge Gültigkeitsbereiche können dazu beitragen, Fehler in Ihrem Code zu verhindern.

13.1.1

Option Explicit

Die Anweisung Option Explicit verlangt, dass alle Variablen vor ihrer Verwendung deklariert werden. Die Aufnahme dieser Anweisung in jedes Formular-, Code- und Berichtsmodul hilft dem VBA-Compiler, Schreibfehler in Variablennamen zu finden. Wie in Kapitel 7 ausführlich dargestellt wurde, ist die Anweisung Option Explicit ein Befehl, der im Abschnitt Allgemeine Deklarationen jedes Code-, Formular- oder Berichtsmoduls stehen kann. Der Befehl kann manuell in jedes Programm eingefügt werden. Er lässt sich auch, falls Sie dies vorziehen, automatisch einfügen, indem Sie im Visual Basic Editor (VBE) zunächst EXTRAS|OPTIONEN und dann auf der Registerkarte EDITOR den Punkt VARIABLENDEKLARATION ERFORDERLICH wählen.

13.1.2

Strenge Typisierung

Die strenge Typisierung von Variablennamen wird in Kapitel 7 behandelt. »Strenge Typisierung« bedeutet, dass Sie bei der Deklaration angeben, welcher Datentyp in der Variablen gespeichert wird. Beispielsweise wird mit Dim intCounter As Integer eine Variable initialisiert, die Zahlen vom Datentyp Integer enthält. Wenn Sie intCounter irgendwo in Ihrem Code eine Zeichenfolge zuweisen, fängt der Compiler den Fehler ab.

13.1.3

Namenskonventionen

Auch Namenskonventionen können Sie ein Stück auf dem Weg der Fehlervermeidung voranbringen. Die sorgfältige Benennung von Variablen macht Ihren Code leichter lesbar und die beabsichtigte Verwendung der Variablen klarer. Problemcode hebt sich eher ab, wenn Namenskonventionen überlegt eingesetzt werden. Namenskonventionen werden in Kapitel 1 behandelt und im Anhang detailliert ausgeführt.

Die Leistungsfähigkeit des Direktfensters nutzen

13.1.4

549

Gültigkeitsbereich von Variablen

Schließlich lässt sich das Risiko, dass ein Code-Fragment versehentlich eine Variable in einem anderen Fragment überschreibt, dadurch reduzieren, dass man den Variablen den kleinstmöglichen Gültigkeitsbereich zuweist. Wenn es möglich ist, sollten Sie lokale Variablen verwenden. Verwenden Sie Variablen auf Modulebene und globale Variablen nur dann, wenn der Wert der Variablen für mehrere Unterroutinen bzw. Module sichtbar sein muss. Weitere Informationen zu den Fragen im Zusammenhang mit dem Gültigkeitsbereich von Variablen finden Sie in Kapitel 7.

13.1.5

Fehler kommen vor!

Was Sie auch immer tun mögen, um Probleme und Fehler zu vermeiden – Fehler schleichen sich leider trotzdem in Ihren Code ein. Wahrscheinlich die hinterhältigste Sorte sind Logikfehler. Ein »Logikfehler« ist tückisch, weil er dem Compiler entgeht: Ihr Code lässt sich kompilieren, funktioniert aber nicht so wie geplant. Fehler dieser Art zeigen sich möglicherweise, wenn ein Laufzeitfehler auftritt oder wenn Sie nicht die erwarteten Ergebnisse bekommen. An dieser Stelle kommt der Debugger zu Hilfe.

13.2

Die Leistungsfähigkeit des Direktfensters nutzen

Das Direktfenster erfüllt mehrere Aufgaben. Es bietet Ihnen eine großartige Möglichkeit, VBA- und benutzerdefinierte Funktionen zu testen, es ermöglicht Ihnen während der Ausführung des Codes den Wert von Variablen abzufragen und zu ändern und Sie können sich die Ergebnisse der Debug.Print-Anweisungen ansehen. Um das Direktfenster vom Visual Basic Editor aus zu öffnen, wählen Sie eine der folgenden drei Möglichkeiten:

 Klicken Sie in der Symbolleiste DEBUGGEN auf das Werkzeug DIREKTFENSTER.  Wählen Sie ANSICHT|DIREKTFENSTER.  Drücken Sie (Strg)(G). Sie sehen das Direktfenster in Abbildung 13.1. Die Testwerkzeuge sind über eine eigene Symbolleiste erreichbar, nämlich über die Symbolleiste DEBUGGEN. Um diese anzuzeigen, klicken Sie mit der rechten Maustaste auf eine beliebige Symbol- oder Menüleiste und wählen aus der Liste der verfügbaren Symbolleisten DEBUGGEN.

550

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Abbildung 13.1: Das Direktfenster ermöglicht Ihnen, Funktionen zu testen und den Wert von Variablen abzufragen und zu ändern

13.2.1

Den Wert von Variablen und Eigenschaften prüfen

Das Direktfenster ermöglicht Ihnen, den Wert von Variablen und Eigenschaften zu prüfen, während Ihr Code ausgeführt wird. Das kann in Bezug darauf, was in Ihrem Code tatsächlich geschieht, recht erhellend sein. Um mit dem Direktfenster zu üben, brauchen Sie noch nicht einmal Code auszuführen. Sie müssen nur, wenn Sie sich in einem Formular, Bericht oder Modul befinden, (Strg)(G) drücken, um das Fenster aufzurufen. Um zu sehen, wie das funktioniert, tun Sie Folgendes: 1. Starten Sie das Formular frmClients aus der Datenbank CHAP13EX.MDB auf der Begleit-CD. 2. Drücken Sie (Strg)+(G), um das Direktfenster zu öffnen und zu aktivieren. Sie gelangen in den Visual Basic Editor (VBE) im Direktfenster. 3. Geben Sie ?Forms!frmClients.txtClientID.Value ein und drücken Sie (¢). Die ClientID des aktuellen Clients erscheint in der nächsten Zeile. 4. Geben Sie ?Forms!frmClients.txtCompanyName.Visible ein und drücken Sie (¢). In der nächsten Zeile erscheint das Wort True, das angibt, dass das Steuerelement sichtbar ist. 5. Geben Sie ?Forms!frmClients.txtAddress.BackColor ein und drücken Sie (¢). In der nächsten Zeile erscheint die Zahl -2147483643, welche die Hintergrundfarbe des AdressSteuerelements angibt.

Die Leistungsfähigkeit des Direktfensters nutzen

551

Ihr Bildschirm sollte jetzt so aussehen wie der in Abbildung 13.2. Sie können mit der Abfrage der Werte von Variablen oder Eigenschaften in Ihrem VBA-Code fortfahren.

Abbildung 13.2: Die Verwendung des Direktfensters zum Prüfen der Werte von Eigenschaften

13.2.2

Werte von Variablen und Eigenschaften festlegen

Sie können das Direktfenster auf drei Arten aufrufen: Sie können auf die Schaltfläche DIREKTFENSTER in der Symbolleiste DEBUGGEN klicken, (Strg)+(G) drücken oder ANSICHT|DIREKTFENSTER wählen. Ein Vorteil der Tastenkombination besteht darin, dass das Direktfenster aufgerufen wird, ohne dass ein Code-Fenster aktiv ist. Der Klick auf die Schaltfläche DIREKTFENSTER der Symbolleiste und die Wahl des Menüpunkts ANSICHT|DIREKTFENSTER sind nur vom VBE aus möglich. Sie können sich im Direktfenster nicht nur etwas anzeigen lassen – Sie können es auch benutzen, um die Werte von Variablen und Steuerelementen zu ändern, während Ihr Code ausgeführt wird. Dieses Merkmal wird noch wertvoller, wenn Sie feststellen, dass Sie Code innerhalb einer Prozedur erneut ausführen können, nachdem Sie den Wert einer Variablen geändert haben. Und so geht's: 1. Rufen Sie, falls nötig, das Direktfenster auf. Denken Sie daran, dass Sie dazu (Strg)+(G) drücken können. 2. Geben Sie im Direktbereich Forms!frmClients.txtContactTitle.Value ein. Drücken Sie (¢). Der Wert des Feldes Contact Title des aktuellen Datensatzes ändert sich daraufhin in Hello.

552

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

3. Geben Sie ein: Forms!frmClients.txtCompanyName.Visible = False. Drücken Sie (¢). Das Steuerelement txtCompanyName im Formular frmClients wird verborgen. 4. Geben Sie Forms!frmClients.txtAddress.BackColor = 123456 ein. Drücken Sie (¢). Die Hintergrundfarbe des Steuerelements txtAddress im Formular frmClients wechselt auf Grün. Das Direktfenster und Ihr Formular sehen jetzt aus wie in Abbildung 13.3.

Abbildung 13.3: Festlegen der Werte von Eigenschaften mit Hilfe des Direktfensters

Das Direktfenster ist zum Testen und für die Fehlersuche äußerst wertvoll. Die hier vorgestellten Beispiele zeigen erst den Anfang seiner Leistungsfähigkeit und Flexibilität. Änderungen an Daten während der Arbeit im Direktfenster sind permanent. Dagegen werden Änderungen an den Eigenschaften von Steuerelementen oder den Werten von Variablen nicht mit dem Formular oder Bericht zusammen gespeichert.

13.2.3

Löschen des Direktfensters

Das Direktfenster zeigt die letzten 200 Ausgabezeilen an. Wenn weitere Code-Zeilen hinzugefügt werden, verschwinden ältere Zeilen. Wenn Sie Access vollständig verlassen und in das Direktfenster zurückkehren, ist es leer. Wenn Sie es zu einem anderen Zeitpunkt löschen wollen, sind folgende drei Schritte nötig: 1. Drücken Sie, während das Direktfenster aktiv ist, (Strg)+(Pos1), um an den Anfang des Direktfensters zu gelangen.

Die Leistungsfähigkeit des Direktfensters nutzen

553

2. Halten Sie die Umschalttaste gedrückt und drücken Sie (Strg)+(Ende), um zur letzten Anweisung im Direktfenster zu kommen. 3. Drücken Sie (Entf).

13.2.4

Mit den integrierten Funktionen üben

Sie können mit dem Direktfenster neben dem Prüfen der Werte von Variablen und Eigenschaften auch jede beliebige VBA-Funktion prüfen. Dazu geben Sie die Funktion und ihre Argumente in das Direktfenster ein und stellen ihr ein Fragezeichen voran. Der folgende Code gibt beispielsweise den aktuellen Monat zurück: ?datepart("m",date)

Die nächste Zeile nennt Ihnen das Datum heute in einem Monat: ?dateadd("m",1,date)

Die nächste Zeile sagt Ihnen, wie viele Tage zwischen dem aktuellen Datum und dem Ende des Jahrtausends liegen: ?datediff("d",date(),#12/31/1999#)

13.2.5

Unterroutinen, Funktionen und Methoden ausführen

Außer dem Testen aller VBA-Funktionen ermöglicht das Direktfenster auch das Testen aller benutzerdefinierten Unterroutinen, Funktionen und Methoden. Das ist eine hervorragende Möglichkeit, Fehler in benutzerdefinierten Funktionen zu suchen. Um zu sehen, wie es funktioniert, führen Sie folgende Schritte aus: 1. Öffnen Sie das Modul basExamples in der Datenbank CHAP13EX.MDB auf der Begleit-CD. 2. Starten Sie das Direktfenster, falls es noch nicht geöffnet ist. 3. Geben Sie ?ReturnInitsFunc("Bill","Gates") ein. Damit wird die benutzerdefinierte Funktion ReturnInitsFunc aufgerufen sowie als erster Parameter "Bill" und als zweiter "Gates" übergeben. Im Direktfenster erscheint der Wert B.G.. Dies ist der Rückgabewert der Funktion. 4. Geben Sie Call ReturnInitsSub("Bill","Gates") ein. Damit wird die benutzerdefinierte Unterroutine ReturnInitsFunc aufgerufen sowie als erster Parameter "Bill" und als zweiter "Gates" übergeben. Der Wert B.G. erscheint nun in einem Meldungsfeld. Beachten Sie den Unterschied zwischen dem Aufrufen einer Funktion und dem Aufrufen einer Unterroutine. Da die Funktion einen Wert zurückgibt, müssen Sie sie unter Verwendung eines Fragezeichens aufrufen. Dagegen verwenden Sie beim Aufrufen einer Unterroutine das Schlüsselwort Call.

554

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Sie können eine Unterroutine aus dem Direktfenster auch mit folgender Syntax aufrufen: RoutineName Parameter1, Parameter2, ... Beachten Sie, dass die Parameter nicht in Klammern zu stehen brauchen, wenn Sie das Schlüsselwort Call weglassen.

13.2.6

Etwas zur Laufzeit in das Direktfenster ausgeben

Die Möglichkeit, etwas in das Direktfenster auszugeben, ist nützlich, weil Sie prüfen können, was geschieht, wenn Ihr Code ausgeführt wird, ohne die Ausführung unterbrechen zu müssen. Außerdem ist es wertvoll, etwas in ein Fenster ausgeben zu können, während Sie testen, ohne mit der Benutzerschnittstelle Ihres Codes in Berührung zu kommen. Sie können ein Formular testen, ohne unterbrochen zu werden, und dann zurückkehren und sich die Werte von Variablen ansehen usw. Und so funktioniert dieser Vorgang: 1. Geben Sie CallLoopThroughCollection ein. Damit wird die benutzerdefinierte Unterroutine LoopThroughCollection aufgerufen. Die Werte Skating, Basketball, Hockey und Skiing erscheinen. Die Routine gibt sie in das Direktfenster aus. 2. Öffnen Sie in der Formularansicht das Formular frmDebugPrint. 3. Drücken Sie (ÿ), um vom Feld FIRST NAME zum Feld LAST NAME zu kommen. 4. Drücken Sie (ÿ), um zum Feld FIRST NAME zurückzukehren. 5. Geben Sie Ihren Vornamen ein.

Abbildung 13.4: Verwendung von Debug.PrintAnweisungen zur Ausgabe von Werten in das Direktfenster

Den Debugger aufrufen

555

6. Öffnen Sie das Direktfenster. Nehmen Sie zur Kenntnis, dass alle Anweisungen in das Direktfenster ausgegeben wurden (siehe Abbildung 13.4). Diese Debug.Print-Anweisungen sind in allen entsprechenden Formular- und Steuerelementereignissen enthalten.

13.3

Den Debugger aufrufen

Der Access-Debugger lässt sich auf unterschiedliche Art aufrufen:

 Setzen Sie in Ihrem Code einen Haltepunkt.  Fügen Sie in Ihren Code einen Überwachungsausdruck ein.  Drücken Sie (Strg)+(Pause), während der Code ausgeführt wird.  Fügen Sie eine Stopp-Anweisung in Ihren Code ein. Ein »Haltepunkt« ist ein unbedingter Punkt, an dem Sie die Ausführung des Codes aussetzen können. Er ist temporär, weil er nur wirkt, solange die Datenbank geöffnet ist. Mit anderen Worten: Haltepunkte werden nicht zusammen mit der Datenbank gespeichert. Ein »Überwachungsausdruck« ist eine Bedingung, unter der Sie die Ausführung des Codes aussetzen können. Möglicherweise ist das der Fall, wenn eine Variable counter einen bestimmten Wert erreicht. Ein Überwachungsausdruck ist ebenfalls temporär; er wird gelöscht, wenn Sie die Datenbank schließen. Eine Stopp-Anweisung ist permanent. Falls Sie vergessen, Stopp-Anweisungen aus Ihrem Code zu entfernen, stoppt die Anwendung die Ausführung auch dann, wenn der Benutzer sie einsetzt.

13.4

Haltepunkte einsetzen

Wie bereits erwähnt, ist ein Haltepunkt ein Punkt, an dem die Ausführung des Codes in jedem Fall angehalten wird. Sie können mehrere Haltepunkte in Ihren Code einfügen. Während der Ausführung können Sie Haltepunkte setzen und entfernen. Ein Haltepunkt gibt Ihnen die Möglichkeit, die Code-Ausführung in einem verdächtigen Code-Bereich anzuhalten. Sie können dann alles untersuchen, was bei der Ausführung des Codes an diesem Punkt geschieht. Durch strategisches Verteilen von Haltepunkten in Ihrem Code können Sie Code-Abschnitte, die bereits getestet sind, schnell ausführen und nur in Problembereichen anhalten. Um einen Haltepunkt zu setzen, ist Folgendes nötig: 1. Setzen Sie den Cursor in die Code-Zeile, in der Sie den Debugger starten wollen. 2. Ein Haltepunkt kann auf vier verschiedene Arten eingefügt werden:

556

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

– Drücken Sie die Funktionstaste (F9). – Klicken Sie in den grauen Randbereich links von der Code-Zeile, die den Haltepunkt enthalten soll. – Klicken Sie auf die Schaltfläche HALTEPUNKT DEBUGGEN.

EIN/AUS

in der Symbolleiste

– Wählen Sie DEBUGGEN|HALTEPUNKT EIN/AUS. Die Code-Zeile mit dem Haltepunkt erscheint in einer anderen Farbe; der Haltepunkt selbst wird durch einen Punkt gekennzeichnet. 3. Starten Sie das Formular, den Bericht oder das Modul mit dem Haltepunkt. VBA unterbricht die Ausführung genau vor der Ausführung der Code-Zeile, in der Sie den Haltepunkt platziert haben. Die Anweisung, die als nächste auszuführen ist, erscheint in einer Kontrastfarbe (Standard ist Gelb). Nachdem Ihr Code jetzt unterbrochen ist, können Sie ihn Zeile für Zeile schrittweise durchgehen, den Wert von Variablen ändern und u.a. Ihre Aufrufeliste ansehen. Denken Sie daran, dass ein Haltepunkt eigentlich ein Schalter ist. Wenn Sie einen Haltepunkt entfernen wollen, klicken Sie in den grauen Randbereich, drücken (F9) oder klicken in der Symbolleiste DEBUGGEN auf HALTEPUNKT EIN/AUS. Haltepunkte werden beim Schließen der Datenbank, beim Öffnen einer anderen Datenbank oder beim Verlassen von Access gelöscht. Am einfachsten lernen Sie den Debugger kennen, indem Sie ihn tatsächlich verwenden. Das folgende Beispiel vermittelt Ihnen Anfangserfahrungen im Setzen von Haltepunkten und Anhalten der Code-Ausführung. Es wird später weiterentwickelt. Beginnen Sie mit der Erstellung eines Formulars frmDebug, welches eine Befehlsschaltfläche mit dem Namen cmdDebug enthält. Versehen Sie die Schaltfläche mit der Beschriftung START DEBUG PROCESS. Fügen Sie den folgenden Code in die Routine für das Click-Ereignis der Befehlsschaltfläche ein: Sub cmdDebug_Click () Call Func1 End Sub

Erstellen Sie ein Modul basFuncs. Nehmen Sie in dieses drei Funktionen auf: Sub Func1 () Dim intTemp As Integer intTemp = 10 Debug.Print "We Are Now In Func1()" Debug.Print intTemp Call Func2 End Sub

Haltepunkte einsetzen

557

Sub Func2 () Dim strName As String strName = "Bill Gates" Debug.Print "We Are Now In Func2()" Debug.Print strName Call Func3 End Sub Sub Func3 () Debug.Print "We Are Now In Func3()" MsgBox "Hi there From The Func3() Sub Procedure" End Sub

Jetzt sollten Sie testen. Beginnen Sie mit der Platzierung eines Haltepunkts im ClickEreignis von cmdDebug in der Zeile Call Func1. Es folgen die einzelnen Schritte: 1. Klicken Sie an einer beliebigen Stelle in der Zeile Call Func1. 2. Klicken Sie in dem grauen Randbereich, drücken Sie die Funktionstaste (F9), klicken Sie auf die Schaltfläche HALTEPUNKT EIN/AUS in der Symbolleiste DEBUGGEN oder wählen Sie DEBUGGEN|HALTEPUNKT EIN/AUS. Die Zeile mit dem Haltepunkt wechselt die Farbe (sie wird standardmäßig rot). 3. Gehen Sie in die Formularansicht und klicken Sie auf die Schaltfläche START DEBUG PROCESS. Access unterbricht die Ausführung genau vor der Ausführung der Zeile, in der Sie den Haltepunkt gesetzt haben. VBA stellt die Zeile Call Func1 in einer anderen Farbe (standardmäßig in Gelb) dar und deutet damit an, dass es im Begriff ist, diese Zeile auszuführen (siehe Abbildung 13.5).

Abbildung 13.5: Anhalten der Code-Ausführung an einem Haltepunkt

558

13.5

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Code schrittweise durchgehen

Access 2000 stellt Ihnen für das schrittweise Testen von Code drei Hauptoptionen zur Verfügung, die sich jeweils ein wenig unterscheiden. Die Option EINZELSCHRITT ermöglicht das schrittweise Testen jeder Code-Zeile in einer Unterroutine oder Funktion, während die Option PROZEDURSCHRITT eine Prozedur ausführt, ohne jede Code-Zeile einzeln abzuarbeiten. Die Option PROZEDUR ABSCHLIESSEN führt den gesamten Code in verschachtelten Prozeduren aus und führt Sie dann zu der Prozedur zurück, welche die Code-Zeile aufgerufen hat, in der Sie sich befinden. Das Wissen, welche Option die richtige für die Lösung eines bestimmten Problems ist, stellt eine erworbene Fähigkeit dar, die sich mit fortgesetzter Entwicklungserfahrung bildet.

13.5.1

Die Option Einzelschritt

Beim Erreichen eines Haltepunkts können Sie so fortfahren, dass Sie Ihren Code zeilenweise ausführen oder die Ausführung bis zum nächsten Haltepunkt fortsetzen. Um den Code Zeile für Zeile durchzugehen, klicken Sie in der Symbolleiste DEBUGGEN auf EINZELSCHRITT, drücken (F8) oder wählen DEBUGGEN|EINZELSCHRITT. Das folgende Beispiel veranschaulicht den Vorgang des schrittweisen Testens, der Ausgabe der Werte von Variablen in das Direktfenster und der Änderung der Werte von Variablen mit Hilfe des Direktfensters. Sie können den Testvorgang von dem Haltepunkt aus fortsetzen, den Sie im vorhergehenden Beispiel gesetzt haben. Gehen Sie zwei Schritte weiter (drücken Sie (F8)). Sie sollten sich jetzt in Func1 befinden, im Begriff, die Zeile intTemp = 10 auszuführen (siehe Abbildung 13.6). Beachten Sie, dass VBA nicht bei der Zeile Dim intTemp As Integer angehalten hat. Der Debugger stoppt grundsätzlich nicht bei Variablendeklarationen. Die Debug-Anweisungen sind im Begriff, etwas in das Direktfenster auszugeben. Noch hat Ihr Code nichts in das Fenster ausgegeben. Drücken Sie (F8) (einen Schritt weiter) noch dreimal, bis Sie die Zeile Debug.Print intTemp ausgeführt haben. Ihr Bildschirm sollte dann so aussehen wie in Abbildung 13.7. Beachten Sie die Ergebnisse der Debug.Print-Anweisungen. Nachdem Sie jetzt gesehen haben, wie man Variablen und die Ergebnisse von Ausdrücken im Direktfenster anzeigen kann, sollten Sie einen Blick darauf werfen, wie Sie das Direktfenster zur Veränderung der Werte von Variablen und Steuerelementen verwenden können. Ändern Sie zuerst den Wert von intTemp. Klicken Sie in das Direktfenster und geben Sie intTemp = 50 ein. Wenn Sie (¢) drücken, ändern Sie tatsächlich den Wert von intTemp. Geben Sie ?intTemp ein und Sie sehen, dass Access den Wert 50 zurückgibt. Außerdem können Sie den Wert von intTemp im LokalFenster sehen. Beachten Sie in Abbildung 13.8, dass die Variable intTemp gemeinsam mit ihrem Wert und ihrem Typ erscheint.

Code schrittweise durchgehen

559

Abbildung 13.6: Das Direktfenster hat innerhalb von Func1 angehalten

Abbildung 13.7: Das Direktfenster mit Einträgen, die von Debug.PrintAnweisungen erzeugt wurden

560

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Abbildung 13.8: Das Direkt- und das Lokal-Fenster nach der Änderung des Wertes von intTemp

13.5.2

Ausführen bis zum nächsten Haltepunkt

Angenommen, Sie haben einen Haltepunkt erreicht, erkennen aber, dass das Problem weiter hinten im Code liegt. Eigentlich befindet es sich sogar in einer anderen Funktion. Sie wollen vielleicht nicht Schritt für Schritt bis zu der störenden Funktion weitergehen. Lokalisieren Sie die fragliche Funktion mit Hilfe des Dropdown-Menüs PROZEDUR und setzen Sie in der Zeile, in der Sie mit dem schrittweisen Testen weitermachen wollen, einen Haltepunkt. Jetzt können Sie mit der Ausführung des Codes fortfahren, bis Access diese Zeile erreicht. Dazu klicken Sie in der Symbolleiste DEBUGGEN auf FORTSETZEN, drücken (F5) oder wählen AUSFÜHREN|FORTSETZEN. Ihr Code wird weiter ausgeführt und hält an dem Haltepunkt an, den Sie gerade gesetzt haben. Um zu sehen, wie dies funktioniert, setzen Sie den Testvorgang mit dem nächsten Beispiel fort. Sie können sich auch dafür entscheiden, die Ausführung des Codes bis zu dem Punkt fortzusetzen, an dem sich der Cursor befindet. Dazu wählen Sie im Menü DEBUGGEN den Eintrag AUSFÜHREN BIS CURSOR-POSITION oder drücken die Tastenkombination (Strg)+(F8).

Nehmen wir an, Sie erkennen, dass sich Ihr Problem in Func3 befinden könnte. Sie möchten nicht schrittweise bis zu Func3 weitergehen. Kein Problem! Sehen Sie sich mit Hilfe des Dropdown-Menüs PROZEDUR Func3 an, wie in Abbildung 13.9 gezeigt. Setzen Sie in der Zeile Debug.Print "We Are Now in Func3()" einen Haltepunkt. Dann können Sie die Ausführung des Codes fortsetzen, bis Access diese Zeile

Code schrittweise durchgehen

561

erreicht. Um die Ausführung fortzusetzen, klicken Sie in der Symbolleiste DEBUGGEN auf FORTSETZEN, drücken (F5) oder wählen AUSFÜHREN|FORTSETZEN. Ihr Code wird weiter ausgeführt und an dem Haltepunkt unterbrochen, den Sie gerade gesetzt haben. Drücken Sie noch einmal (F5). Der Code wird bis zum Ende ausgeführt. Kehren Sie in die Formularansicht zurück.

13.5.3

Die Option Prozedurschritt

Manchmal haben Sie eine Unterroutine bereits vollständig getestet und auf Fehler geprüft. Sie wollen die Routine, in der Sie sich gerade befinden, weiter schrittweise untersuchen, aber nicht die Ausführung von Unterroutinen beobachten. In diesem Fall verwenden Sie die Option PROZEDURSCHRITT. Um eine Unterroutine oder Funktion als Ganzes auszuführen, klicken Sie in der Symbolleiste DEBUGGEN auf PROZEDURSCHRITT, drücken (SHIFT)+(F8) oder wählen DEBUGGEN|PROZEDURSCHRITT. Der Code innerhalb der Unterroutine oder Funktion, die Sie abarbeiten, wird nun ausgeführt, aber nicht schrittweise. Um mit der Option PROZEDURSCHRITT zu experimentieren, halten Sie sich an das nächste Beispiel.

Abbildung 13.9: Mit Hilfe des Dropdown-Menüs Prozedur sehen Sie sich eine weitere Funktion an

Klicken Sie wieder auf das offene Formular und noch einmal auf die Schaltfläche START DEBUG PROCESS. Da Ihre Haltepunkte immer noch gesetzt sind, werden Sie in die Code-Zeile Call Func1 geführt. Wählen Sie im Menü DEBUGGEN den Eintrag ALLE HALTEPUNKTE LÖSCHEN oder entfernen Sie diese mit der Tastenkombination (Strg)+(SHIFT)+(F9). Gehen Sie fünf Schritte weiter ((F8)), bis Sie im Begriff sind, die Zeile Call Func2 auszuführen. Nehmen wir an, Sie haben Func2 und Func3 getestet

562

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

und wissen, dass diese nicht die Ursache der Probleme in Ihrem Code sind. Klicken Sie, während Func2 als nächste auszuführende Zeile hervorgehoben ist, in der Symbolleiste auf PROZEDURSCHRITT. Beachten Sie, dass sowohl Func2 als auch Func3 ausgeführt werden, Sie jetzt jedoch so weit sind, Func1 weiter schrittweise durchzugehen. In diesem Fall werden Sie in die Zeile End Sub geführt, die unmittelbar auf den Aufruf von Func2 folgt.

13.5.4

Die Option Prozedur abschließen

Die Option PROZEDUR ABSCHLIESSEN wird verwendet, um die aktuelle Prozedur zu verlassen und zu der Prozedur zurückzukehren, welche die Code-Zeile aufgerufen hat, in der man sich befindet. Sie machen von dieser Möglichkeit Gebrauch, wenn Sie versehentlich eine Prozedur schrittweise ausführen und bemerken, dass sie vollständig getestet ist. Sie wollen den gesamten Code ausführen, der von der Prozedur, in der sie sind, aufgerufen wird, und dann in die aufrufende Prozedur zurückgehen, so dass Sie den Testvorgang fortsetzen können. Um zu testen, wie das funktioniert, halten Sie sich an das folgende Beispiel. 1. Setzen Sie im Aufruf von Func2 einen Haltepunkt. 2. Klicken Sie auf die Schaltfläche ZURÜCKSETZEN in der Symbolleiste, um die Ausführung des Codes zu unterbrechen. 3. Aktivieren Sie das Formular frmDebug und klicken Sie auf die Befehlsschaltfläche START DEBUG PROCESS. 4. Gehen Sie einen Schritt weiter, um in die erste Zeile von Func2 zu kommen. 5. Nehmen wir an, Sie erkennen, dass Sie einen Schritt zu weit gegangen sind. In Wirklichkeit hatten Sie vor, Func2 und alle von dieser Prozedur aufgerufenen Prozeduren als Ganzes auszuführen. Kein Problem! Klicken Sie auf die Schaltfläche PROZEDUR ABSCHLIESSEN, um Func2 zu verlassen und in die Zeile zurückzukehren, die auf die Zeile folgt, in der Func2 aufgerufen wurde. In diesem Fall sollten Sie sich in der Anweisung End Sub von Func1 wiederfinden.

13.6

Die nächste auszuführende Anweisung festlegen

Nachdem Sie den Code schrittweise durchgearbeitet, den logischen Fluss beobachtet und einige Variablen geändert haben, wollen Sie vielleicht den Code von einer früheren Anweisung an noch einmal ausführen. Die einfachste Möglichkeit, dies zu tun, besteht darin, auf den gelben Pfeil am Rand zu klicken und ihn zu der Anweisung zu ziehen, mit der Sie die Ausführung fortsetzen wollen. Wenn es Ihnen lieber ist, können Sie an einer beliebigen Stelle in der Code-Zeile klicken, in der Sie mit der Aus-

Das Fenster Aufrufeliste

563

führung beginnen wollen, und dann DEBUGGEN|NÄCHSTE ANWEISUNG FESTLEGEN wählen. Beachten Sie unabhängig von der gewählten Methode die Kontrastfarbe (normalerweise Gelb), die besagt, dass die nächste auszuführende Code-Zeile jetzt oberhalb dieser Anweisung steht. Sie können dann mit (F8) den Code schrittweise prüfen oder mit (F5) die normale Ausführung des Codes fortsetzen. Access lässt Sie die nächste ausführbare Code-Zeile nur innerhalb einer Prozedur festlegen. Die Option kann verwendet werden, um Code-Zeilen noch einmal auszuführen oder eine problematische Zeile zu überspringen. Das folgende Beispiel zeigt, wie der Wert einer Variablen geändert und der Code nach der Änderung erneut ausgeführt wird. Das vorhergehende Beispiel hat Sie in der letzten Code-Zeile (der Anweisung End Sub) von Func1 zurückgelassen. Sie wollen den Wert von intTemp ändern und dann alles noch einmal ausführen. 1. Gehen Sie in das Direktfenster und geben Sie intTemp = 100 ein. 2. Sie müssen die nächste auszugebende Anweisung in der Zeile Debug.Print "We Are Now In Func1" festlegen. Dazu klicken Sie auf den gelben Pfeil und ziehen diesen von der Anweisung End Sub in die genannte Code-Zeile. Beachten Sie die Kontrastfarbe (Gelb), die besagt, dass sich die nächste auszuführende Code-Zeile jetzt oberhalb der Anweisung befindet. 3. Drücken Sie (F8) (Einzelschritt) zweimal. Der Code wird jetzt mit dem Wert 100 für intTemp ausgeführt. Sehen Sie sich das Direktfenster noch einmal an. Beachten Sie die Änderung der Ergebnisse.

13.7

Das Fenster Aufrufeliste

Sie haben gelernt, wie man Haltepunkte setzt, wie man Code schrittweise und als ganze Prozedur abarbeitet, wie man das Direktfenster einsetzt, wie man die nächste auszuführende Code-Zeile festlegt und wie man die Ausführung bis zum nächsten Haltepunkt fortsetzt. Beim Erreichen eines Haltepunkts ist es häufig wichtig zu erfahren, welche Funktionen aufgerufen wurden, um Sie zu diesem Punkt zu bringen. Hier kann die Aufrufeliste helfen. Um das Fenster AUFRUFELISTE zu öffnen, klicken Sie auf die Schaltfläche AUFRUFELISTE in der Symbolleiste oder wählen ANSICHT|AUFRUFELISTE. Das Fenster in Abbildung 13.10 erscheint. Wenn Sie die Code-Zeile sehen wollen, von der aus eine bestimmte Funktion oder Unterroutine aufgerufen wurde, doppelklicken Sie auf diese Funktion und klicken dann auf ANZEIGEN. Obwohl der Ausführungspunkt nicht in die aufrufende Funktion oder Unterroutine wandert, können Sie den Code in der Prozedur sehen.

564

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Wenn Sie mit der Ausführung des Codes fortfahren wollen, drücken Sie (F8). Sie kehren in die Prozedur zurück, die Sie gerade untersucht haben, und die nächste Code-Zeile wird ausgeführt. Wenn Sie (F5) drücken, wird Ihr Code ausgeführt, bis ein weiterer Haltepunkt oder ein Überwachungsausdruck erreicht ist. Wenn Sie dahin zurückkehren wollen, wo Sie waren, ohne weitere Code-Zeilen auszuführen, wählen Sie DEBUGGEN|NÄCHSTE ANWEISUNG ANZEIGEN. Führen Sie das nächste Beispiel aus, um diesen Vorgang zu testen.

Abbildung 13.10: Mit Hilfe des Fensters Aufrufeliste die Liste ansehen

1. Klicken Sie auf die Schaltfläche ZURÜCKSETZEN, um die Ausführung des Codes abzubrechen, falls Sie sich noch im Unterbrechungsmodus befinden. 2. Entfernen Sie den Haltepunkt im Aufruf von Func2. 3. Gehen Sie in die Prozedur Func3 in basFuncs. Setzen Sie in der Zeile Debug.Print "We Are Now In Func3()" einen Haltepunkt. 4. Starten Sie das Formular frmDebug und klicken Sie auf die Befehlsschaltfläche. Sie werden in die Zeile mit dem Haltepunkt in Func3 versetzt. 5. Öffnen Sie mit einem Klick auf die Schaltfläche AUFRUFELISTE in der Symbolleiste das Fenster AUFRUFELISTE. Wenn Sie die Code-Zeile sehen wollen, die aus Func1 heraus Func2 aufgerufen hat, doppelklicken Sie auf Func1. Obwohl der Ausführungspunkt nicht nach Func1 wandert, können Sie den Code in der Prozedur sehen. Um in die nächste auszuführende Code-Zeile zurückzukehren, wählen Sie DEBUGGEN|NÄCHSTE ANWEISUNG ANZEIGEN. 6. Drücken Sie (F5) und der Rest des Codes wird ausgeführt.

565

Mit dem Lokal-Fenster arbeiten

13.8

Mit dem Lokal-Fenster arbeiten

Mit Hilfe des Lokal-Fensters können Sie sich alle Variablen im aktuellen StackBereich sowie ihre Werte ansehen und diese ändern. Um auf das Lokal-Fenster zuzugreifen, klicken Sie in der Symbolleiste auf LOKAL-FENSTER oder wählen im Menü ANSICHT den Eintrag LOKAL-FENSTER. Es erscheinen drei Spalten: AUSDRUCK, WERT und TYP. Die Spalte AUSDRUCK zeigt Ihnen die Variablen, die benutzerdefinierten Typen, die Datenfelder und die anderen innerhalb der aktuellen Prozedur sichtbaren Objekte. Die Spalte WERT enthält den aktuellen Wert der Variablen oder des Ausdrucks. Die Spalte TYP gibt an, welchen Datentyp die Variable enthält. Variablen, die hierarchische Informationen wie beispielsweise Datenfelder enthalten, werden mit einer Schaltfläche dargestellt, die das Ein- und Ausblenden der Hierarchie-Ebenen ermöglicht. Die im Lokal-Fenster enthaltenen Informationen sind dynamisch. Sie werden bei Ausführung des Codes und beim Wechsel von Routine zu Routine automatisch aktualisiert. Abbildung 13.11 veranschaulicht, wie Sie mit Hilfe des Lokal-Fensters die für die Unterroutine Func2 verfügbaren Variablen anzeigen können. Um dieses Beispiel selbst auszuprobieren, entfernen Sie alle vorhandenen Haltepunkte. Setzen Sie dann in der Code-Zeile DebugPrint.strName in Func2 einen neuen Haltepunkt. Klicken Sie auf ZURÜCKSETZEN, falls noch Code ausgeführt wird. Um den Code bis zum Haltepunkt auszuführen, klicken Sie auf die Befehlsschaltfläche START DEBUG PROCESS. Klicken Sie auf die Schaltfläche LOKAL-FENSTER in der Symbolleiste. Klicken Sie auf das Pluszeichen, um den Inhalt der öffentlichen Variablen gintCounter zu sehen.

Abbildung 13.11: Das Lokal-Fenster

Im Lokal-Fenster lässt sich der Wert einer Variablen ändern, nicht jedoch ihr Name oder ihr Typ.

13.9

Mit Überwachungsausdrücken arbeiten

Manchmal reicht es nicht, den Wert einer Variablen oder eines Ausdrucks mit Hilfe des Direktfensters zu überprüfen. Vielleicht wollen Sie den Wert eines Ausdrucks ständig im Auge behalten. Mit Access 95 wurde die Möglichkeit eingeführt, Überwachungsausdrücke zu setzen. Das ist vor dem Start einer Prozedur oder während einer

566

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

Unterbrechung der Code-Ausführung möglich. Nachdem ein Überwachungsausdruck hinzugefügt wurde, erscheint dieser im Überwachungsfenster. Wie Sie sehen werden, gibt es verschiedene Arten von Überwachungsausdrücken.

13.9.1

Automatische Daten-Tipps verwenden

Die schnellste und einfachste Möglichkeit, sich den in einer Variablen enthaltenen Wert anzusehen, besteht in der Verwendung der Option AUTOMATISCHE DATENTIPPS. Diese steht für die Arbeit mit Modulen zur Verfügung und zwar nur im Unterbrechungsmodus. Sie ziehen dann einfach die Maus über die Variable oder den Ausdruck, deren/dessen Wert Sie prüfen wollen. Zusammen mit dem aktuellen Wert erscheint dann ein Tipp. Um die Option AUTOMATISCHE DATEN-TIPPS zu aktivieren, wählen Sie vom Visual Basic Editor (VBE) aus EXTRAS|OPTIONEN, klicken auf die Registerkarte EDITOR und aktivieren die Option AUTOMATISCHE DATEN-TIPPS, die Sie unter den Optionen für die Code-Einstellungen finden.

13.9.2

Die Option Aktuellen Wert anzeigen

Die Option AKTUELLEN WERT ANZEIGEN stellt die einfachste Art eines Überwachungsausdrucks dar. Um sie einzufügen, markieren Sie den Namen der Variablen oder des Ausdrucks, den Sie überwachen wollen, und klicken auf die Schaltfläche AKTUELLEN WERT ANZEIGEN in der Symbolleiste. Das Dialogfeld AKTUELLEN WERT ANZEIGEN (Abbildung 13.12) wird eingeblendet. Sie können auf HINZUFÜGEN klicken, um den Ausdruck als permanenten Überwachungsausdruck einzufügen, oder auf ABBRECHEN, um sich den aktuellen Wert anzusehen, ohne ihn als Überwachungsausdruck einzufügen. Wenn Sie auf HINZUFÜGEN klicken, sehen Sie das Fenster ÜBERWACHUNGSAUSDRÜCKE, das aussieht wie in Abbildung 13.13. Es wird im nächsten Abschnitt ausführlicher behandelt.

Abbildung 13.12: Mit dem Dialogfeld Aktuellen Wert anzeigen können Sie schnell den Wert einer Variablen ansehen oder einen Ausdruck als permanenten Überwachungsausdruck hinzufügen

Abbildung 13.13: Das Fenster Überwachungsausdrücke mit einem typischen Eintrag

Mit Überwachungsausdrücken arbeiten

13.9.3

567

Einen Überwachungsausdruck hinzufügen

Wie Sie gesehen haben, können Sie einen Überwachungsausdruck mit Hilfe des Dialogfeldes AKTUELLEN WERT ANZEIGEN hinzufügen. Auf diese Art lässt sich der Charakter des Überwachungsausdrucks jedoch nicht vollständig steuern. Dazu müssen Sie DEBUGGEN|ÜBERWACHUNG HINZUFÜGEN wählen. Dann erscheint das Dialogfeld ÜBERWACHUNG HINZUFÜGEN, das Sie in Abbildung 13.14 sehen. Wenn Sie über AKTUELLEN WERT ANZEIGEN oder DEBUGGEN|ÜBERWACHUNG HINZUFÜGEN einen Überwachungsausdruck setzen, können Sie dessen Einzelheiten leicht anpassen, indem Sie mit der rechten Maustaste im Fenster ÜBERWACHUNGSAUSDRÜCKE auf den Ausdruck klicken und anschließend ÜBERWACHUNG BEARBEITEN wählen.

Abbildung 13.14: Mit dem Dialogfeld Überwachung hinzufügen lassen sich die Einzelheiten eines Überwachungsausdrucks leicht festlegen

Im Textfeld AUSDRUCK geben Sie eine Variable, eine Eigenschaft, einen Funktionsaufruf oder irgendeinen anderen gültigen Ausdruck ein. Wichtig ist, die Prozedur und das Modul zu markieren, in der/dem der Ausdruck überwacht werden soll. Als nächstes geben Sie an, ob Sie den Wert des Ausdrucks nur im Direktfenster beobachten wollen oder eine Unterbrechung wünschen, wenn der Ausdruck True wird oder sich ändert. Die letzten beiden Optionen werden in den nächsten Abschnitten ausführlich behandelt. Das nächste Beispiel führt Sie durch den Vorgang, einen Überwachungsausdruck hinzuzufügen und die zu überwachende Variable beim schrittweisen Durchlaufen des Codes zu beobachten. Es veranschaulicht, wann eine Variable gültig wird bzw. ihre Gültigkeit verliert und wie sie während der Ausführung ihren Wert ändert.

568

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

1. Halten Sie zunächst die Ausführung des Codes an, falls sie gerade läuft, und entfernen Sie alle Haltepunkte. 2. Klicken Sie auf die Variable strName in Func2. 3. Klicken Sie mit der rechten Maustaste und wählen Sie ÜBERWACHUNG HINZUFÜGEN. 4. Klicken Sie auf OK, um die Prozedur Func2 als Kontext für die Variable und basFuncs als Modul für die Variable zu bestätigen. 5. Setzen Sie in der Zeile strName = "Bill Gates" einen Haltepunkt. 6. Starten Sie das Formular frmDebug und klicken Sie auf die Befehlsschaltfläche. Sehen Sie sich das Fenster ÜBERWACHUNGSAUSDRÜCKE an und beachten Sie, dass der Wert von strName eine Zeichenkette der Länge Null ist. 7. Gehen Sie einen Schritt weiter und beachten Sie, dass strName den Wert Bill Gates annimmt. 8. Gehen Sie noch drei Schritte weiter. Beachten Sie, dass strName, obwohl Sie sich in der Routine Func3 befinden, immer noch den Wert Bill Gates hat. Das liegt daran, dass sich die Variable nach wie vor im Kontext von basFuncs.Func2 im Speicher befindet. 9. Gehen Sie vier Schritte weiter, bis Sie zur Anweisung End Sub von Func2 zurückgekehrt sind. Die Variable Func2 befindet sich immer noch im Kontext. 10. Gehen Sie noch einen Schritt weiter. Die Variable strName befindet sich nun nicht mehr im Kontext, weil Func2 ausgeführt wurde.

13.9.4

Einen Überwachungsausdruck bearbeiten

Nachdem Sie einen Überwachungsausdruck hinzugefügt haben, möchten Sie vielleicht seine Einzelheiten bearbeiten oder ihn vollständig entfernen. Dazu verwenden Sie das Dialogfeld ÜBERWACHUNG BEARBEITEN. Unternehmen Sie Folgendes: 1. Aktivieren Sie das Fenster ÜBERWACHUNGSAUSDRÜCKE. 2. Markieren Sie den Ausdruck, den Sie bearbeiten wollen. 3. Wählen Sie DEBUGGEN|ÜBERWACHUNG BEARBEITEN oder klicken Sie mit der rechten Maustaste und wählen Sie ÜBERWACHUNG BEARBEITEN. Es erscheint das Dialogfeld in Abbildung 13.15. 4. Nehmen Sie Änderungen am Überwachungsausdruck vor oder klicken Sie auf LÖSCHEN, um ihn zu entfernen.

Mit Überwachungsausdrücken arbeiten

569

Abbildung 13.15: Sie können das Feld Überwachung bearbeiten einsetzen, um die Einzelheiten eines Überwachungsausdrucks zu ändern, nachdem Sie ihn hinzugefügt haben

13.9.5

Unterbrechen, wenn ein Ausdruck True ist

Ein leistungsfähiger Aspekt eines Überwachungsausdrucks ist der Umstand, dass Sie die Ausführung unterbrechen können, sobald ein Ausdruck True wird. Sie könnten beispielsweise eine Unterbrechung herbeiführen, sobald eine Public-Variable einen bestimmten Wert erreicht. Eine solche Situation kann eintreten, wenn eine Publicoder Private-Variable irgendwie verändert wird und Sie feststellen möchten, wo dies geschieht. Schauen Sie sich den folgenden Code an, der sich im Modul basFuncs von CHAP13EX.MDB befindet: Sub ChangeGlobal1() gintCounter = 50 Call ChangeGlobal2 End Sub Sub ChangeGlobal2() gintCounter = gintCounter + 10 Call ChangeGlobal3 End Sub Sub ChangeGlobal 3() Dim intCounter As Integer For intCounter = 1 To 10 gintCounter = gintCounter + intCounter Next intCounter End Sub

Vielleicht stellen Sie fest, dass gintCounter irgendwie eine Zahl über 100 erreicht und Sie sind nicht sicher, warum. Um das Problem zu lösen, fügen Sie den in Abbildung 13.16 gezeigten Überwachungsausdruck hinzu. Beachten Sie, dass der Ausdruck, auf den Sie prüfen, gintCounter > 100 heißt. Sie haben den Haltepunkt so gesetzt, dass der Code abgebrochen wird, sobald der Ausdruck True wird. Um den Code zu testen,

570

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

geben Sie im Direktfenster ChangeGlobal1 ein und drücken (¢). Der Code sollte in der Routine ChangeGlobal3 abgebrochen werden, was besagt, dass diese Routine der Übeltäter ist.

Abbildung 13.16: Definieren eines Überwachungsausdrucks, der zum Abbruch der Code-Ausführung führt, sobald der Ausdruck True wird

13.9.6

Abbrechen, wenn sich ein Ausdruck ändert

Anstatt abzubrechen, wenn ein Ausdruck True wird, wollen Sie vielleicht abbrechen, sobald sich der Wert des Ausdrucks ändert. Das ist eine hervorragende Möglichkeit, die Stelle zu ermitteln, an der sich der Wert einer Variablen auf geheimnisvolle Weise verändert. Wie UNTERBRECHEN, WENN DER WERT TRUE IST eignet sich die Option UNTERBRECHEN, WENN WERT GEÄNDERT WURDE hervorragend für die Verfolgung von Problemen mit öffentlichen und privaten Variablen. Betrachten Sie den Überwachungsausdruck, der in Abbildung 13.17 gesetzt wird. Er steht im Kontext aller Prozeduren in allen Modulen. Er soll abbrechen, sobald sich der Wert von gintCounter ändert. Wenn Sie die Routine ChangeGlobal1 ausführen, stellen Sie fest, dass der Code in der Routine ChangeGlobal1 anhält, unmittelbar nachdem der Wert von gintCounter auf 50 gesetzt wurde. Wenn Sie (F5) drücken, um die Ausführung fortzusetzen, hält der Code in ChangeGlobal2 unmittelbar nach der Erhöhung von gintCounter um 10 an. Anders ausgedrückt: die Ausführung des Codes bricht nach jeder Modifikation des Wertes von gintCounter ab.

Abbildung 13.17: Erstellen eines Überwachungsausdrucks, der den Abbruch der Code-Ausführung veranlasst, sobald sich der Wert eines Ausdrucks ändert

571

Die Ausführung nach einem Laufzeitfehler fortsetzen

13.10

Die Ausführung nach einem Laufzeitfehler fortsetzen

Beim Testen treffen Sie häufig auf Laufzeitfehler, die sich ganz einfach beheben lassen. Wenn ein Laufzeitfehler auftritt, wird ein ähnliches Dialogfeld wie in Abbildung 13.18 eingeblendet. Wenn Sie auf DEBUGGEN klicken, gelangen Sie im Code-Fenster in die Zeile, die den Fehler ausgelöst hat. Nach der Korrektur des Problems klicken Sie auf die Schaltfläche FORTSETZEN in der Symbolleiste oder wählen AUSFÜHREN|FORTSETZEN.

Abbildung 13.18: Das Dialogfeld für Laufzeitfehler

Abbildung 13.19 zeigt zum Beispiel einen Fehler wegen Division durch Null, nachdem im Dialogfeld mit dem Laufzeitfehler auf DEBUGGEN geklickt wurde. Der Wert von int2 wurde auf 20 gesetzt. Die Code-Ausführung kann jetzt ohne Fehler fortgesetzt werden.

Abbildung 13.19: Der Testmodus nach einem Fehler wegen Division durch Null

Häufig zeigt VBA nach dem Auftreten eines Fehlers eine Meldung an, die Ihnen die Möglichkeit gibt, Ihren Code zurückzusetzen. Wenn Sie dies tun, verlieren alle Variablen (inklusive Public- und Static-Variablen) ihre Werte. Sie können auch in der Symbolleiste auf ZURÜCKSETZEN klicken. Sie müssen sich entscheiden, ob es besser ist, mit gesetzten Variablen fortzufahren oder die Variablen zurückzusetzen und dann fortzufahren.

572

Kapitel 13: Fehlersuche: Ihr Schlüssel zur erfolgreichen Entwicklung

13.11

Gefundenes im Direktfenster ansehen

Obwohl der Debugger von Access hervorragend ist, gibt es im Testvorgang als solchem eine Reihe potentieller Probleme, u.a. folgende:

 Der Testvorgang kann die Code-Ausführung unterbrechen, insbesondere, wenn es um Formulare geht. Wenn dies geschieht, ist es am günstigsten, Debug.PrintAnweisungen in den Code einzufügen und zu prüfen, was geschieht, nachdem der Code ausgeführt wurde.

 Ähnlich wie beim vorigen Problem ist die Fehlerprüfung bei Code schwierig, in dem GotFocus- und LostFocus-Ereignisse vorkommen. Der Wechsel in den VBE (Visual Basic Editor) löst das LostFocus-Ereignis des Steuerelements aus. Die Rückkehr zum Formular führt dazu, dass das GotFocus-Ereignis des Steuerelements erneut eintritt. Wiederum stellt Debug.Print eine hervorragende Lösung dar. Sie könnten auch daran denken, Informationen zur Einsicht nach der Ausführung des Codes in ein Fehlerprotokoll zu schreiben.

 Code, der die Objekte Screen.ActiveForm und Screen.ActiveControl verwendet, macht beim Testen Ärger. Wenn die IDE aktiv ist, gibt es kein aktives Formular und kein aktives Steuerelement. Das Problem wird weniger kritisch, wenn Sie solche Zeilen nach Möglichkeit vermeiden.

 Seien Sie sich schließlich bewusst, dass das Zurücksetzen des Codes zu Problemen führen kann. Wenn Sie Umgebungseinstellungen ändern, finden Sie sich nach der Ausführung Ihrer Anwendung in der veränderten Umgebung wieder. Wenn Sie die Ausführung nach dem Fehler ohne Zurücksetzen fortsetzen, können alle möglichen anderen Probleme auftreten. Es ist günstig, eine spezielle Hilfsroutine zu schreiben, die die Umgebung zurücksetzt.

13.11.1

Für die Praxis

Echte Anwendungen testen Wenden Sie bei der Entwicklung des Zeit- und Abrechnungssystems die gelernten Techniken an, die Ihnen helfen, die auftretenden Probleme zu lösen. Für den Augenblick sollten Sie jedoch den Debugger verwenden, um schrittweise vorzugehen und bei einer der Routinen aus der erwähnten Anwendung mehr über den Testvorgang zu erfahren. Öffnen Sie das Formular frmClients in CHAP13EX.MDB in der Entwurfsansicht. Setzen Sie in der Code-Zeile If IsNull(Me![ClientID]) Then im Click-Ereignis der Schaltfläche VIEW PROJECT einen Haltepunkt (siehe Abbildung 13.20). Starten Sie das Formular und klicken Sie auf die Befehlsschaltfläche PROJEKT ANZEIGEN. Gehen Sie den Code schrittweise durch und beobachten Sie die Ausführung.

Gefundenes im Direktfenster ansehen

573

Abbildung 13.20: Setzen eines Haltepunkts in frmClients

Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Kapitel

Hier lesen Sie:

 Fehler beheben  Fehlerbehandlung implementieren  Mit Fehlerereignissen arbeiten  On Error-Anweisungen  Resume-Anweisungen  Fehlerinformationen löschen  Verschachtelte Fehlerbehandlungsroutinen  Das Objekt Err  Einen Fehler auslösen  Die Auflistung Errors  Eine allgemeine Fehlerbehandlungsroutine erstellen  Verhindern, dass Ihre eigenen Fehlerbehandlungsroutinen aufgerufen werden

14.1

Fehler beheben

Fehler kommen vor, selbst ohne Zutun des Programmierers. Sie müssen Ihre Programme und Daten durch Fehlerbehandlung vor den negativen Auswirkungen von Fehlern schützen. Fehlerbehandlung wird auch als Fehlerbehebung bezeichnet. »Fehlerbehandlung« ist der Vorgang, die Reaktion von Jet oder VBA auf einen Fehler abzufangen. Sie ermöglicht dem Entwickler, die Schwere eines Fehlers zu ermitteln und in Reaktion darauf das Richtige zu tun. Dieses Kapitel zeigt Ihnen die Techniken, die zur erfolgreichen Implementierung der Fehlerbehandlung in Ihren Anwendungen erforderlich sind.

576

14.2

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Fehlerbehandlung implementieren

Ohne Fehlerbehandlung ist der Benutzer Ihrer Anwendung gezwungen, den Anwendungs-Code abrupt zu verlassen. Sehen Sie sich das Beispiel in Listing 14.1 an. Listing 14.1:

Ein Beispiel für Code ohne Fehlerbehandlung

Private Sub cmdCauseError_Click() Call TestError1(txtValue1, txtValue2) End Sub Sub TestError1(Numerator As Integer, Denominator As Integer) Debug.Print Numerator / Denominator MsgBox "I am in Test Error" End Sub

Das Klickereignis hinter der Befehlsschaltfläche ruft die Routine TestError1 auf und übergibt ihr die Werte aus zwei Textfeldern. TestError1 akzeptiert diese Parameter und versucht, den ersten Parameter durch den zweiten zu dividieren. Wenn der zweite Parameter gleich 0 ist, tritt ein Laufzeitfehler auf. Da keine Fehlerbehandlung aktiv ist, bricht das Programm ab. Abbildung 14.1 zeigt die Fehlermeldung, die der Benutzer erhält. Wie Sie sehen können, lauten die Wahlmöglichkeiten FORTFAHREN, BEENDEN, DEBUGGEN und HILFE. Wenn der Benutzer DEBUGGEN wählt, wird das Modulfenster eingeblendet und er gelangt im Testmodus in die Code-Zeile, die den Fehler ausgelöst hat. Die Auswahl von FORTFAHREN (die nicht immer zur Verfügung steht) weist Access an, den Fehler zu ignorieren und die Ausführung des Programms fortzusetzen. BEENDEN beendet die Ausführung des Programm-Codes. Wenn die Anwendung mit der Laufzeitversion von Access läuft, wird sie beendet und der Benutzer kehrt zu Windows zurück. Wenn die Fehlerbehandlung aktiv ist, können Sie versuchen, den Fehler, falls möglich, auf geeignetere Weise zu behandeln.

Abbildung 14.1: Die Standardmeldung zur Fehlerbehandlung

Mit Fehlerereignissen arbeiten

577

Sie können Code zur Fehlerbehandlung in die Fehlerereignisprozedur eines Formulars oder Berichts integrieren. Außerdem können Sie solchen Code in jede Unterroutine, Funktion oder Ereignisroutine von VBA einfügen. Der Code in Listing 14.1 lässt sich leicht so ändern, dass der Fehler elegant abgefangen wird. Der Code in Listing 14.2 zeigt eine einfache Fehlerbehandlungsroutine. Listing 14.2:

Eine einfache Fehlerbehandlungsroutine

Sub TestError2(Numerator As Integer, Denominator As Integer) On Error GoTo TestError2_Err Debug.Print Numerator / Denominator MsgBox "I am in Test Error" Exit Sub TestError2_Err: If Err = 11 Then MsgBox "Variable 2 Cannot Be a Zero", , "Custom Error Handler" End If Exit Sub End Sub

Dieser Code steht im Modul basError, das Sie in der Datenbank CHAP14EX.MDB auf der Begleit-CD finden.

Die Routine ruft jetzt die Fehlerbehandlung auf. Wenn ein Fehler wegen Division durch Null auftritt, warnt ein Meldungsfeld den Benutzer vor dem Problem, wie Abbildung 14.2 zeigt.

Abbildung 14.2: Eine Meldung der beutzerdefinierten Fehlerbehandlungsroutine

14.3

Mit Fehlerereignissen arbeiten

Jedes Formular und jeder Bericht enthält eine Fehlerereignisprozedur. Dieses Ereignis wird von jedem Fehler der Schnittstelle oder der Jet-Datenbank-Engine ausgelöst, nicht jedoch von einem Programmierfehler des Access-Entwicklers.

578

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Fehler treten häufig in der Schnittstelle eines Formulars oder Berichts oder in der JetDatenbank-Engine auf. Ein Benutzer könnte zum Beispiel versuchen, eine Bestellung für einen nicht vorhandenen Kunden einzugeben. Anstatt die Access-Standardfehlermeldung auszugeben, wollen Sie den Fehler vielleicht abfangen und auf bestimmte Weise behandeln. Nachdem in einem Formular ein Fehler aufgetreten ist, wird dessen Fehlerereignis ausgelöst. In Listing 14.3 sehen Sie die Routine Sub Form_Error. Diese enthält zwei Parameter. Der erste ist die Fehlernummer, der zweite die Methode, mit der Sie auf den Fehler reagieren wollen. Die Fehlernummer wird von Access erzeugt. Dieser Code, den Sie im Formular frmOrders in der Datenbank CHAP14EX.MDB finden, prüft auf einen Fehler im Zusammenhang mit referentieller Integrität. Falls ein solcher aufgetreten ist, fragt ein Meldungsfeld, ob der Benutzer den Kunden hinzufügen will. Wenn dieser mit yes antwortet, wird das Kundenformular angezeigt. Listing 14.3:

Die Routine Sub Form_Error aus dem Formular frmOrders

Private Sub Form_Error(DataErr As Integer, Response As Integer) Dim intAnswer As Integer If DataErr = 3201 Then 'Referential Integrity Error intAnswer = MsgBox("Customer Does Not Exist... _ Would You Like to Add Them Now", vbYesNo) If intAnswer = vbYes Then DoCmd.OpenForm "frmCustomer", , , , acAdd, acDialog End If End If Response = acDataErrContinue End Sub

Denken Sie daran, dass das Beispiel in Listing 14.3 nur Fehler in Bezug auf referentielle Integrität abfängt, keine Fehler anderer Art.

Sehr wichtig ist die Zeile Response = acDataErrContinue. Sie bringt Access dazu, die Code-Ausführung fortzusetzen, ohne die Standardfehlermeldung anzuzeigen. Die andere Option für Response lautet acDataErrDisplay. Sie weist Access an, die Standardfehlermeldung auszugeben. Wenn Sie gern eine Liste aller Fehler, die in Ihrem VBA-Code auftreten können, sowie eine Erläuterung der Fehlernummern hätten, wählen Sie im VBE ?|MICROSOFT VISUAL BASIC-HILFE. Klicken Sie auf die Registerkarte INDEX und geben Sie als Schlüsselwort Fehler ein. Klicken Sie auf SUCHEN. Markieren Sie im Listenfeld THEMA AUSWÄHLEN den Eintrag ERMITTELN DER VON VISUAL BASIC RESERVIERTEN

On Error-Anweisungen

579

FEHLERCODES. Der Code, der erforderlich ist, um eine Tabelle mit VBA-Fehlernummern und -beschreibungen zu erstellen, erscheint im rechten Feld des Hilfefensters. Sie können ihn in ein beliebiges Modul kopieren und starten. Dann wird eine Tabelle mit Fehlernummern und -beschreibungen erstellt.

14.4

On Error-Anweisungen

On Error-Anweisungen aktivieren die Fehlerbehandlung. Jede Routine muss eine eigene On Error-Anweisung enthalten, wenn Sie wollen, dass sie eine eigene Fehler-

behandlung betreibt. Andernfalls wird zur Fehlerbehandlung der Aufrufstack durchsucht. Wenn auch dort keine On Error-Anweisungen zu finden sind, wird die VBAeigene Fehlerbehandlung aufgerufen. Nehmen wir an, dass Func1 Func2 aufruft und Func2 Func3. Nur in Func1 gibt es eine Fehlerbehandlung. In Func3 tritt nun ein Fehler auf. Func3 gibt die Steuerung an Func2 weiter. Func2 besitzt keine Fehlerbehandlung und übergibt daher die Steuerung an Func1. Func1 behandelt den Fehler. Ein Hinweis darauf, dass die Fehlerbehandlungsroutine in Func1 nicht zwangsläufig geeignet ist, um den in Func3 aufgetretenen Fehler abzufangen, erübrigt sich. Mit Hilfe einer On Error-Anweisung können Sie die Anwendung veranlassen, zum Fehlerbehandlungs-Code zu verzweigen, in der Zeile, die unmittelbar auf den Fehler folgt, weiterzumachen oder zu versuchen, die problematische Code-Zeile erneut auszuführen. Sie müssen entscheiden, welche Reaktion sich für einen bestimmten Fehler am besten eignet. Manchmal ist es am günstigsten, wenn die Anwendung als Reaktion auf einen Fehler einfach angehalten wird. In anderen Fällen ist das Überspringen der störenden Zeile die beste Lösung. Durch Kombinieren der Anweisungen On Error GoTo, On Error Resume Next und Resume lässt sich jeder Fehler angemessen behandeln.

14.4.1

On Error GoTo

Die Anweisung On Error GoTo sagt VBA, dass es von dieser Stelle in der Unterroutine oder Funktion zur in der Anweisung genannten Sprungmarke gehen soll, falls ein Fehler auftritt. Das ist die häufigste Form der Fehlerbehandlung. Die in der On Error-Anweisung angegebene Sprungmarke muss sich in der aktuellen Prozedur befinden und innerhalb des Moduls eindeutig sein. Listing 14.4 zeigt ein einfaches Beispiel für Fehlerbehandlung. Listing 14.4:

Ein Beispiel für Fehlerbehandlung mit der Anweisung On Error GoTo

Sub SimpleErrorHandler(iVar1 As Integer, iVar2 As Integer) On Error GoTo SimpleErrorHandler_Err

580

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Dim sngResult As String sngResult = iVar1 / iVar2 Exit Sub SimpleErrorHandler_Err: MsgBox "Oops!" Exit Sub End Sub

Aus dieser einfachen Routine können Sie einige wichtige Dinge lernen. Sie übernimmt zwei Integer-Werte. Dann ruft sie die Fehlerbehandlungsroutine auf. Wenn ein Fehler auftritt, wird die Ausführung an der Sprungmarke fortgesetzt. Beachten Sie, dass die Routine zwei Exit Sub-Anweisungen enthält. Wenn Sie die erste entfernen, wird der Code auch ohne Auftreten eines Fehlers bis zur Sprungmarke ausgeführt. Die Exit Sub-Anweisung am Ende schließt die Prozedur elegant ab und setzt den Fehler-Code auf 0 zurück. Fehlernummer und -beschreibung in die Fehlerbehandlungsroutine integrieren Der Fehlerbehandlungs-Code in Listing 14.4 hat dem Benutzer keine sehr aussagekräftige Meldung geliefert. Die Eigenschaften DESCRIPTION und NUMBER des Objekts Err bieten uns bedeutungsvollere Fehlermeldungen. Das Objekt Err wird weiter hinten in diesem Kapitel im Abschnitt »Das Objekt Err« ausführlich behandelt. Sehen Sie sich zunächst die Eigenschaften DESCRIPTION und NUMBER an, um zu erfahren, wie Sie diese zur Erweiterung einer Fehlerbehandlungsroutine einsetzen können. Um mit ihm Fehlernummer und -beschreibung anzuzeigen, müssen Sie den Fehlerbehandlungs-Code folgendermaßen ändern: SimpleErrorHandler_Err: MsgBox "Error #" & ErrNumber & ": " & Err.Description Exit Sub

Diesmal geben Sie, anstatt die Fehlermeldung hart zu kodieren, die Fehlernummer und den internen VBA-Fehlertext aus. Abbildung 14.3 zeigt die sich daraus ergebende Fehlermeldung. Die Routine SimpleErrorHandler und alle folgenden Beispiele finden Sie im Modul basError der Datenbank CHAP14EX.MDB.

Abbildung 14.3: Eine Fehlermeldung mit Fehlernummer und -beschreibung

On Error-Anweisungen

581

On Error GoTo 0 On Error GoTo 0 wird für zwei Dinge verwendet:

 Wenn Access zu seiner standardmäßigen Fehlerbehandlungsroutine zurückkehren soll

 Wenn Access zur Fehlerbehandlung einer Routine zurückkehren soll, die oberhalb der aktuellen Routine liegt Im Allgemeinen wollen Sie nicht, dass Access zu seiner standardmäßigen Fehlerbehandlung zurückkehrt. Aber vielleicht ist es dann der Fall, wenn Sie den Fehler nicht abfangen können oder wenn Sie sich in der Testphase befinden und noch nicht so weit sind, eine eigene Fehlerbehandlungsroutine zu implementieren. Der Grund dafür, dass Access den Fehler an eine weiter oben angesiedelte Routine weiterleiten soll, ist wesentlich klarer. Sie tun dies, wenn Sie die Fehlerbehandlung »zentralisieren« wollen, was bedeutet, dass eine Routine mehrere andere aufrufen könnte. Anstatt in jede aufgerufene Routine eine Fehlerbehandlung zu integrieren, ist es in bestimmten Situationen günstiger, die Fehlerbehandlung in der aufrufenden Routine zu erledigen.

14.4.2

On Error Resume Next

On Error Resume Next setzt die Programmausführung in der Zeile fort, die unmittelbar auf den Fehler folgt. Dieses Konstrukt wird im Allgemeinen verwendet, wenn das Ignorieren eines Fehlers und die Fortsetzung der Code-Ausführung akzeptabel ist. Listing 14.5 zeigt ein Beispiel für eine derartige Situation. Listing 14.5:

Einen Fehler ignorieren und die Ausführung fortsetzen

Sub TestResumeNext() On Error Resume Next Kill "AnyFile" MsgBox "We Didn't die, But the Error Was: " & Err.Description End Sub

Die Kill-Anweisung wird verwendet, um eine Datei von der Festplatte zu löschen. Wenn die angegebene Datei nicht gefunden wird, tritt ein Fehler auf. Die Datei wird nur gelöscht, wenn sie vorhanden ist, und deshalb brauchen Sie sich nicht um den Fehler zu kümmern. On Error Resume Next ist für diese Situation gut geeignet, weil die Wiederaufnahme der Ausführung nach der störenden Code-Zeile keinen Schaden anrichtet.

582

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

14.5

Resume-Anweisungen

Während Sie sich im Fehlerbehandlungs-Code befinden, können Sie die Anweisungen Resume, Resume Next und Resume verwenden, um anzugeben, wie VBA auf den Fehler reagieren soll. Resume versucht, die fehlerhafte Code-Zeile erneut auszuführen, Resume Next nimmt die Ausführung nach dieser Zeile wieder auf, und Resume setzt die Ausführung an einer genannten Zeilensprungmarke fort. Die folgenden Abschnitte behandeln die Anweisungen im Einzelnen.

14.5.1

Die Anweisung Resume

Die Anweisung Resume nimmt die Ausführung des Codes in der Zeile wieder auf, die zu dem Fehler geführt hat. Sie müssen sie mit äußerster Vorsicht verwenden, weil sie den Code unwiderruflich in eine Endlosschleife führen kann. Listing 14.6 zeigt ein Beispiel für die falsche Verwendung der Anweisung Resume. Listing 14.6:

Falsche Verwendung von Resume

Function BadResume(strFileName As String) On Error GoTo BadResume_Err Dim strFile As String strfile = Dir(strFileName) If strFile = "" Then BadResume = False Else BadResume = True End If Exit Function BadResume_Err: MsgBox Error Resume End Function

Dieser Funktion wird ein Dateiname übergeben. Die Funktion Dir sucht nach dem Dateinamen und gibt True oder False zurück, abhängig davon, ob sie den Dateinamen findet. Das Problem tritt auf, wenn das angefragte Laufwerk nicht verfügbar oder nicht vorhanden ist. Dieser Code bringt den Rechner in eine endlose Schleife. Um das Problem zu beheben, sollten Sie den Code so ändern, dass er aussieht wie in Listing 14.7. Listing 14.7:

Bedingte Verwendung von Resume auf der Grundlage von Benutzerrückmeldungen

Function GoodResume(strFileName As String) On Error GoTo GoodResume_Err Dim strFile As String

583

Resume-Anweisungen

strfile = Dir(strFileName) If strFile = "" Then GoodResume = False Else GoodResume = True End If Exit Function GoodResume_Err: Dim intAnswer As Integer intAnswer = MsgBox(Error & "Would You Like to Try Again?", vbYesNo) If intAnswer = vbYes Then Resume Else ExitFunction End If End Function

In diesem Beispiel überlässt die Fehlerbehandlungsroutine dem Benutzer die Entscheidung, ob er es noch einmal versuchen will. Resume kommt nur ins Spiel, wenn der Benutzer mit Ja antwortet.

14.5.2

Die Anweisung Resume Next

Genauso, wie Sie die Fehlerbehandlung mit der Anweisung On Error Resume Next starten können, können Sie, wie Listing 14.8 zeigt, auch eine Resume Next-Anweisung in Ihre Fehlerbehandlungsroutine einbauen. Listing 14.8:

Aufnehmen einer Resume Next-Anweisung in die Fehlerbehandlungsroutine

Sub TestResumeNextInError() On Error GoTo TestResumeNextInError_Err Kill "AnyFile" MsgBox "We Didn't Die!" Exit Sub TestResumeNextInError_Err: ResumeNext End Sub

In

diesem

Beispiel

wird

der

Code

angewiesen,

die

Sprungmarke

TestResumeNextInError_Err anzusteuern, wenn ein Fehler auftritt. Diese führt eine Resume Next-Anweisung aus, welche den Fehler behebt und veranlasst, dass die Aus-

führung in der Zeile nach dem Fehler wieder aufgenommen wird.

584

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

14.5.3

Die Anweisung Resume

Mit der Anweisung Resume können Sie eine Code-Zeile angeben, in der die Ausführung nach dem Auftreten eines Fehlers wieder aufgenommen werden soll. Dies ist eine gute Möglichkeit, die beiden Exit Sub- bzw. Exit FunctionAnweisungen zu beseitigen, die in den bisher vorgestellten Fehlerbehandlungsroutinen erforderlich waren. Listing 14.9 zeigt ein Beispiel. Listing 14.9:

Mit Hilfe der Anweisung Resume angeben, wo die Ausführung nach dem Auftreten eines Fehlers fortgesetzt werden soll

Sub TestResumeLineLabel(intVar1 As Integer, intVar2 As Integer) On Error GoTo TestResumeLineLabel_Err Dim sngResult As String sngResult = intVar1 / intVar2 TestResumeLineLabel_Exit: Exit Sub TestResumeLineLabel_Err: MsgBox "Error #" & Err.Number & ": " & Err.Description Resume TestResumeLineLabel_Exit End Sub

Beachten Sie, dass diese Routine nur eine einzige Exit Sub-Anweisung enthält. Wenn kein Fehler auftritt, läuft Access bis zur Sprungmarke TestResumeLineLabel_Exit hindurch bis zur Anweisung Exit Sub. Wenn jedoch ein Fehler auftritt, wird der Code in TestResumeLineLabel_Err ausgeführt. Beachten Sie, dass die letzte Zeile der Fehlersprungmarke die Ausführung an der Sprungmarke TestResumeLineLabel_Exit wieder aufnimmt. Diese Methode der Fehlerbehebung ist sinnvoll, weil der gesamte Code, der beim Verlassen der Routine ausgeführt werden muss, an einer Stelle untergebracht werden kann. Es könnte zum Beispiel nötig sein, alle Objektvariablen auf Nothing zu setzen, wenn die Routine verlassen wird. Sie können die entsprechenden Code-Zeilen in die Routine zum Verlassen einbauen.

14.6

Fehlerinformationen löschen

Wenn ein Fehler auftritt, bleiben die Fehlerinformationen im Objekt Err erhalten, bis sie auf eine der folgenden Arten gelöscht werden:

 mit Resume, Resume Next oder Resume  mit Exit Sub, Exit Function oder Exit Property

Verschachtelte Fehlerbehandlungsroutinen

585

 mit einer beliebigen GoTo-Anweisung  durch explizite Verwendung der Methode Clear für das Objekt Err Bis die Informationen gelöscht sind, bleiben sie im Objekt Err erhalten. Nach dem Löschen sind im Objekt Err keine Informationen mehr vorhanden.

14.7

Verschachtelte Fehlerbehandlungsroutinen

Wie bereits im Abschnitt »On Error-Anweisungen« erwähnt, sucht Access im Aufruf-Stack nach einer früheren Fehlerbehandlungsroutine, wenn es in einer Unterroutine oder Funktion keine Fehlerbehandlung findet. Listing 14.10 zeigt ein Beispiel für diesen Vorgang. Listing 14.10: Im Aufruf-Stack nach einer früheren Fehlerbehandlungsroutine suchen Sub Func1() On Error GoTo Func1_Err Debug.Print "I am in Function 1" Call Func2 Debug.Print "I am back in Function 1" Exit Sub Func1_Err: MsgBox "Error in Func1" Resume Next End Sub Sub Func2() Debug.Print "I am in Function 2" Call Func3 Debug.Print "I am still in Function 1" End Sub Sub Func3() Dim sngAnswer As Single Debug.Print "I am in Function 3" sngAnswer = 5 / 0 Debug.Print "I am still in Function 3" End Sub

In dieser Situation tritt der Fehler in Func3 auf. Da Func3 keine eigene Fehlerbehandlung besitzt, wendet sie sich an Func2. Auch Func2 hat keine Fehlerbehandlung und deshalb übergibt sie die Steuerung an Func1. VBA führt den Fehler-Code in Func1 aus. Das wirkliche Problem tritt wegen der Resume Next-Anweisung auf. Die Anwendung fährt mit der Ausführung in Func1 bei der Anweisung Debug.Print "I am in Function 1" fort. Diese Art der Fehlerbehandlung ist gefährlich und verwirrend. Des-

586

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

halb ist es am besten, eine allgemeine Fehlerbehandlungsroutine zu entwickeln, auf die aus der gesamten Anwendung zugegriffen werden kann. Dies wird im Abschnitt »Eine allgemeine Fehlerbehandlungsroutine erstellen« behandelt.

14.8

Das Objekt Err

Das Objekt Err enthält Informationen über den zuletzt aufgetretenen Fehler. Wie alle Access-Objekte besitzt es Eigenschaften und Methoden. Tabelle 14.1 fasst die Eigenschaften des Objekts Err zusammen. Eigenschaft

Beschreibung

Description

Beschreibung des aufgetretenen Fehlers

HelpContext

Kontext-ID für die Hilfedatei

HelpFile

Pfad und Name der Hilfedatei

LastDLLError

Letzter in einer 32-Bit-DLL aufgetretener Fehler

Number

Nummer des aufgetretenen Fehlers

Source

System, in dem der Fehler aufgetreten ist (was äußerst sinnvoll ist, wenn Sie über OLE-Automatisierung eine weitere Anwendung, z.B. Excel, steuern)

Tabelle 14.1: Eigenschaften des Objekts Err

Das Objekt Err besitzt nur zwei Methoden: Clear und Raise. Mit der Methode Clear können Sie eine Fehlerbedingung explizit löschen. Sie wird in erster Linie eingesetzt, wenn Sie Code schreiben, der die Anweisung On Error Resume Next verwendet. Diese Anweisung löscht die Fehlerbedingung nicht. Denken Sie daran, dass es keinen Grund gibt, die Methode Clear mit irgendeiner der folgenden Anweisungen explizit aufzurufen: Resume, Exit Sub, Exit Function, Exit Property oder On Error GoTo. Wenn diese Konstrukte verwendet werden, wird die Methode Clear implizit ausgeführt. Die Methode Raise des Objekts Err wird im nächsten Abschnitt behandelt.

14.9

Einen Fehler auslösen

Die Methode Raise des Fehlerobjekts wird in folgenden Situationen eingesetzt:

 wenn Sie einen Fehler mit Absicht erzeugen wollen (zum Beispiel beim Testen)  wenn Sie einen benutzerdefinierten Fehler erzeugen wollen

Einen Fehler auslösen

587

 wenn der aktuelle Fehler von der Fehlerroutine nicht behandelt wird und Sie anderen Teilen des Aufruf-Stacks erlauben wollen, eine Fehlerbehandlung zu versuchen

 wenn Sie eine Fehlerbehandlungsroutine verschachteln wollen Die Verwendung der Methode Raise zum absichtlichen Erzeugen eines Fehlers und die Erstellung eines benutzerdefinierten Fehlers werden in den folgenden Abschnitten besprochen.

14.9.1

Einen Fehler absichtlich erzeugen

Häufig wollen Sie beim Testen einen Fehler erzeugen, um Ihre Fehlerbehandlung auszuprobieren. Anstatt zu suchen, wie ein bestimmter Fehler ausgelöst wird, können Sie die Methode Raise des Objekts Err für diese Aufgabe einsetzen, wie Listing 14.11 zeigt. Listing 14.11: Auslösen eines Fehlers Sub TestRaiseError() On Error GoTo TestRaiseError_Err Dim sngResult As String Err.Raise 11 Exit Sub TestRaiseError_Err: MsgBox "Error #" & Err.Number & ": " & Err. Description Exit Sub End Sub

Dieser Code verursacht einen error 11 (Division durch 0). Durch Erzeugen dieses Fehlers können Sie die Effizienz Ihrer Fehlerbehandlungsroutine testen.

14.9.2

Benutzerdefinierte Fehler erstellen

Eine weitere wichtige Verwendung der Methode Raise des Objekts Err ist das Erzeugen einer benutzerdefinierten Fehlerbedingung. Das ist sinnvoll, wenn Sie etwas brauchen, das keinen Access-Fehler, sondern einen benutzerdefinierten Fehler verursacht, den Sie der normalen Fehlerbehandlung unterziehen können. Da Sie mit der Methode Raise alle Eigenschaften des Objekts Err festlegen können, können Sie einen vollständig benutzerdefinierten Fehler mit einer Nummer, einer Beschreibung, einer Quelle usw. erstellen, wie Sie ihn in Listing 14.12 finden.

588

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Listing 14.12: Einen benutzerdefinierten Fehler erstellen Sub TestCustomError() On Error GoTo TestCustomErr_Err Dim strName As String strName = InputBox("Please Enter Your Name") If Len(strName) < 5 Then ErrRaise Number:=11111, _ Description:="Length of Name is Too Short" Else MsgBox "You Entered " & strName End If Exit Sub TestCustomErr_Err: MsgBox "Error # " & Err.Number & _ " – " & Err.Description Exit Sub End Sub

Dieses Beispiel ist zwar sehr einfach, illustriert jedoch eine wesentliche Verwendungsweise benutzerdefinierter Fehler. Der Code testet darauf, ob der eingegebene Wert aus weniger als fünf Zeichen besteht. Falls ja, wird ein benutzerdefinierter Fehler (Nummer 11111) ausgegeben und die Routine macht mit der normalen Fehlerbehandlung weiter. Der Abschnitt »Eine allgemeine Fehlerbehandlungsroutine erstellen« weiter hinten in diesem Kapitel untersucht, wie man eine allgemeine Fehlerbehandlungsroutine aufbaut. Durch das Behandeln Ihrer benutzerdefinierten Fehler mit Hilfe der allgemeinen Fehlerbehandlungsroutine werden alle Fehler – nicht nur die benutzerdefinierten – auf dieselbe Weise abgearbeitet.

14.10

Die Auflistung Errors

Die Auflistung Errors ist Teil der Jet-Engine von Access und speichert die zuletzt aufgetretenen DAO-Fehler. Das ist bei der Verwendung von DAO und ODBC wichtig, wo eine Operation zu mehreren Fehlern führen kann. Wenn Sie mit jedem einzelnen Fehler zu tun haben, der von einer Operation verursacht wurde, müssen Sie in die Auflistung Errors schauen. Diese verfügt über dieselben Eigenschaften wie das Objekt Err. Wenn Sie sich die in der Auflistung Errors gespeicherten Fehler ansehen wollen, müssen Sie diese in einer Schleife durchlaufen und sich die Eigenschaften jedes Err-Objekts ansehen. Listing 14.13 zeigt den Code, den Sie dazu verwenden können. Listing 14.13: Die Fehler in der Auflistung Errors ansehen Sub TestErrorsCollection() On Error GoTo TestErrorsCollection_Err

Eine allgemeine Fehlerbehandlungsroutine erstellen

589

Dim db As DAO.Database Set db = CurrentDb db Execute ("qryNonExistent") Exit Sub TestErrorsCollection_Err: Dim ErrorDescrip As Error For Each ErrorDescrip In Errors Debug.Print ErrorDescrip.Description Next ErrorDescrip Exit Sub End Sub

Diese Routine durchläuft jedes Error-Objekt in der Auflistung Errors und gibt die Beschreibung aller enthaltenen Fehler aus.

14.11

Eine allgemeine Fehlerbehandlungsroutine erstellen

Eine »allgemeine« Fehlerbehandlungsroutine lässt sich von einer beliebigen Stelle in Ihrer Anwendung aus aufrufen und ist in der Lage, auf Fehler jeden Typs zu reagieren. Eine allgemeine Fehlerbehandlungsroutine verhindert, dass Sie in jede Unterroutine oder Funktion eine eigene Fehlerbehandlung aufnehmen müssen. Sie ermöglicht es, in der gesamten Anwendung Fehlerbehandlung auf die denkbar effizienteste Art einzuleiten. Für die Erstellung einer allgemeinen Fehlerbehandlungsroutine gibt es viele Ansätze. Sie sollte dem Benutzer Informationen über den Fehler liefern, die Ausgabe dieser Informationen ermöglichen und diese in einer Datei protokollieren. Außerdem sollte sie sich von jeder Prozedur in der Anwendung aus aufrufen lassen. Die Routine On Error (in diesem Fall die Sprungmarke AnySub_Err) jeder Prozedur, die Fehlerbehandlung durchführt, sollte so aussehen wie die Fehlerbehandlungsroutine, die Sie in der Unterroutine von Listing 14.14 sehen. Listing 14.14: Eine allgemeine Fehlerbehandlungsroutine für alle Funktionen und Unterroutinen Sub AnySub() Const SUBNAME = "ANYSUB" On Error GoTo AnySub_Err MsgBox "This is the rest of your code...." Err.Raise 11 MsgBox "We are Past the Error!!"

590

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Exit Sub AnySub_Err: Dim intAction As Integer intAction = ErrorHandler(intErrorNum:=ErrNumber, _ strErrorDescription:=Err.Description, _ strModuleName:=MODULENAME, _ strRoutineName:_SUBNAME) Select Case intAction Case ERR_CONTINUE Resume Next Case ERR_RETRY Resume Case ERR_EXIT Exit Sub Case ERR_QUIT Quit End Select End Sub

Diese Fehlerbehandlungsroutine in AnySub erzeugt eine Variable vom Typ Integer, welche den Rückgabewert des Fehlersystems aufnimmt. Die Variable intAction enthält eine für den aufgetretenen Fehler passende Reaktion. Die Fehlerroutine ruft die allgemeine Fehlerbehandlungsfunktion ErrorHandler auf, übergibt ihr die Fehlernummer (Err.Number), eine Beschreibung des Fehlers (Err.Description), den Namen des Moduls und den Namen der Unterroutine oder Funktion, in denen der Fehler enthalten ist. Der Name des Moduls wird in der privaten Konstanten MODULENAME abgelegt, die im Abschnitt Allgemein des Moduls deklariert wurde und die Sie für jedes erstellte Modul anlegen müssen. Der Name der Unterroutine oder Funktion wird in einer lokalen Konstanten SUBNAME gespeichert. Bei diesem Ansatz erstellen Sie am Beginn jeder Prozedur eine lokale Konstante und weisen ihr den Namen der Unterroutine zu. Dies erfordert Aktualisierungsaufwand, weil sich Prozedurnamen ändern können und Sie daran denken müssen, auch Ihre Zeichenfolge zu ändern. Leider ist diese Art roher Gewalt erforderlich, falls Ihre Fehlerbehandlungsroutine Unterroutine und Modul nennen soll, weil die VBA-Umgebung beim Auftreten eines Fehlers die Namen von Unterroutine und Modul verschweigt. Wenn der Code aus der Funktion ErrorHandler zurückkehrt, wird ein Rückgabewert in die Variable intAction geschrieben, aus dem sich das Schicksal der Routine ergibt. Nachdem Sie jetzt gesehen haben, wie Sie in Ihren Prozeduren Fehlerbehandlung implementieren können, sollten Sie einen Blick auf die Funktion werfen, die beim Auftreten eines Fehlers aufgerufen wird. Sie finden diese in Listing 14.15.

Eine allgemeine Fehlerbehandlungsroutine erstellen

591

Listing 14.15: Deklaration einer Typstruktur für allgemeine Fehlerbehandlung Type typErrors intErrorNum As Integer strMessage As String strModule As String strRoutine As String strUserName As String datDateTime As Variant End Type Public gtypError As typErrors Public Public Public Public

Const Const Const Const

ERR_CONTINUE = 0 'Resume Next ERR_RETRY = 1 'Resume ERR_QUIT = 2 'End ERR_EXIT = 3 'Exit Sub or Func

Dieser Code befindet sich im Abschnitt Allgemein von basGenericErrorHandler. Die deklarierte Typstruktur enthält alle fortdauernden Informationen über den Fehler. Typstrukturen werden in Kapitel 24 behandelt. Für den Augenblick reicht es aus, wenn Sie verstehen, dass eine Typstruktur eine spezielle Art Variable darstellt, die mehrere Teile umfasst. Jeder davon enthält eine andere Information. Die öffentliche Variable gtypError enthält alle Informationen aus der Typstruktur. Die Konstanten dienen dazu, das Schicksal der Anwendung nach dem Auftreten eines Fehlers festzulegen. Listing 14.16 zeigt die Funktion ErrorHandler. Listing 14.16: Die Funktion ErrorHandler Function ErrorHandler(intErrorNum As Integer, _ strErrorDescription As String, _ strModuleName As string, _ strRoutineName As String) As Integer gtypError.intErrorNum = intErrorNum gtypError.strMessage = strErrorDescription gtypError.strModule = strModuleName gtypError.strRoutine = strRoutineName gtypError.strUserName = CurrentUser() gtypError.datDateTime = Now Call LogError Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.Open "Select Response from tblErrors Where ErrorNum = " _ & inErrorNum, CurrentProject.Connection, adOpenStatic If rstEOF Then DoCmd.OpenForm "frmError", WindowMode:=acDialog, _ OpenArgs:="ErrorHandler"

592

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

ErrorHandler = ERR_QUIT Else Select Case rst!Response Case ERR_QUIT DoCmd.OpenForm "frmError", WindowMode:=acDialog, _ OpenArgs:="Critical Error: Application will Terminate" ErrorHandler = ERR_QUIT Case ERR_RETRY ErrorHandler = ERR_RETRY Case ERR_EXIT DoCmd.OpenForm "frmError", WindowMode:=acDialog, _ OpenArgs:="Severe Error: Processing Did Not Complete" ErrorHandler = ERR_EXIT Case ERR_CONTINUE ErrorHandler = ERR_CONTINUE End Select End If End Function

Die Funktion ErrorHandler übernimmt die Fehlernummer, die Fehlerbeschreibung sowie den Namen des Moduls und der Unterroutine bzw. Funktion als Parameter. Dann schreibt sie diese Informationen sowie den aktuellen Benutzer und das Datum in die Typstruktur gtypError. Als nächstes ruft sie eine Routine auf, die den Fehler in einer Access-Tabelle protokolliert. Diese Routine schlägt die Schwere des Fehlers in der Access-Tabelle tblErrors nach, um zu entscheiden, welche Art der Fehlerbehandlung am besten passt. Wenn sich der Fehler-Code nicht in der Fehlertabelle findet, wird ein Fehlerformular angezeigt und ein Rückgabewert an die aufrufende Funktion gesendet, der angibt, dass die Ausführung der Anwendung beendet werden muss. Wenn der Fehler-Code in der Fehlertabelle ermittelt wird und sich der Fehler als schwer oder kritisch erweist, wird ein Fehlerformular eingeblendet, bevor die Steuerung an die aufrufende Routine zurückgegeben wird. In jedem Fall bekommt die aufrufende Routine den Schwere-Code für den Fehler. Im folgenden Abschnitt werden die einzelnen Schritte dieses Vorgangs detailliert behandelt.

14.11.1

Protokollieren des Fehlers

Die Routine LogError ist für die Protokollierung der Fehlerinformationen in einer Access-Tabelle verantwortlich. Da sich Benutzer häufig entschließen, das Fehlerformular nicht auszugeben oder Ihnen nicht zutreffende Informationen darüber liefern, was beim Auftreten des Fehlers geschah (bzw. Sie gar nicht über den Fehler informieren), ist es wichtig, jeden Fehler zu protokollieren, so dass Sie das Fehlerprotokoll jederzeit einsehen können. Man kann Fehler in einer Textdatei oder in einer Datentabelle festhalten. Dieser Abschnitt zeigt Ihnen beide Methoden der Fehlerprotokollierung. Beginnen Sie mit einer Fehlertabelle. Listing 14.17 zeigt die Routine LogError.

Eine allgemeine Fehlerbehandlungsroutine erstellen

593

Listing 14.17: Die Routine LogError Sub LogError() Dim cnn As ADODB.Connection Dim strSQL As String Set cnn = CurrentProject.Connection strSQL = "INSERT INTO tblErrorLog ( ErrorDate, ErrorTime, " _ "UserName, ErrorNum, ErrorString, ModuleName, RoutineName) " strSQL = strSQL & "Select #" & gtypError.datDateTime & "#, #" _ & gtypError.datDateTime & "#, '" _ & gtypError.strUserName & "', " _ & gtypError.intErrorNum & ", '" _ & gtypError.strMessage & "', '" _ & gtypError.strModule & "', '" _ & gtypError.strRoutine & "'" cnnExecute strSQL, , adExecuteNoRecords End Sub

Diese Routine verwendet die Methode Execute des ADO-Objekts Connection, um Ihrer Fehlertabelle einen Datensatz hinzuzufügen. Dieser enthält alle Informationen aus der Struktur gtypError, die schließlich in einer Tabelle mit dem Namen tblErrorLog abgelegt werden. Abbildung 14.4 zeigt die Struktur dieser Tabelle.

Abbildung 14.4: Die Struktur der Tabelle tblErrorLog

Die Alternative wäre, die Informationen in einer Fehlerprotokolldatei in Textform abzulegen, wie es in Listing 14.18 gezeigt wird. Listing 14.18: Informationen in eine Fehlerprotokolldatei in Textform schreiben Sub LogErrorText() Dim intFile As Integer intFile = FreeFile

594

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Open CurDir & "\ErrorLog.Txt" For Append Shared As intFile Write #intFile, "LogErrorDemo", Now, Err, Error, CurrentUser() Close intFile End Sub

Dieser Code verwendet die systemnahen Dateifunktionen Open und Write, um eine ASCII-Textdatei zu öffnen und zu schreiben. Alle fehlerrelevanten Informationen werden in dieser Textdatei abgelegt. Dann wird die Datei mit dem Befehl Close geschlossen. Der potentielle Vorteil dieser Routine liegt darin, dass der Vorgang der Fehlerprotokollierung auch noch funktioniert, wenn das Problem seine Ursache in der Datenbank hat.

14.11.2 Die passende Reaktion auf einen Fehler ermitteln Nachdem der Fehler protokolliert ist, können Sie ermitteln, wie Sie am Besten auf den Fehler reagieren. Indem Sie Ihr Fehlersystem datengesteuert gestalten, können Sie jeden Fehler ein wenig anders behandeln. Abbildung 14.5 zeigt die Struktur der Tabelle tblErrors. Diese sollte eine Liste aller Fehlernummern enthalten, die Sie abfangen wollen. Sie besitzt drei Felder: ErrorNum, ErrorDescription und Response. Wenn ein Fehler auftritt, sucht die Funktion ErrorHandler einen Datensatz, dessen Wert im Feld ErrorNum mit der Nummer des aufgetretenen Fehlers übereinstimmt. Die Funktion ErrorHandler, die Sie in Listing 14.16 finden, lokalisiert mit Hilfe des Codes in Listing 14.19 den Fehler-Code in der Tabelle tblErrors. Listing 14.19: Den Fehler-Code in der Tabelle tblErrors lokalisieren Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset rst.Open "Select Response from tblErrors Where ErrorNum = " _& intErrorNum, CurrentProject.Connection, adOpenStatic If rst.EOF Then DoCmd.OpenForm "frmError", WindowMode:= acDialog, _ OpenArgs:="ErrorHandler" ErrorHandler = ERR_QUIT Else Select Case rst!Response Case ERR_QUIT DoCmd.OpenForm "frmError", WindowMode:=acDialog, _ OpenArgs:="Critical Error: Application will Terminate" ErrorHandler = ERR_QUIT Case ERR_RETRY ErrorHandler = ERR_RETRY Case ERR_EXIT DoCmd.OpenForm "frmError", WindowMode:=acDialog, _ OpenArgs:="Severe Error: Processing Did Not Complete" ErrorHandler = ERR_EXIT Case ERR_CONTINUE

Eine allgemeine Fehlerbehandlungsroutine erstellen

595

ErrorHandler = ERR_CONTINUE End Select End If

Abbildung 14.5: Die Struktur der Tabelle tblErrors

Dieser Teil der Funktion ErrorHandler erstellt eine ADO-Objektvariable des Typs Recordset. Mit Hilfe einer Select-Anweisung öffnet sie eine Datensatzgruppe. Die Select-Anweisung durchsucht eine Tabelle mit dem Namen tblErrors. Wenn sie einen passenden Eintrag findet, bestimmt sie mit Hilfe der Spalte Response die Reaktion auf den Fehler. Beachten Sie in Listing 14.19, dass die Standardfehlerbehandlung verwendet wird, wenn die Fehlernummer in tblErrors nicht gefunden wird, was bedeutet, dass der Code alle weiteren Fehler als Gruppe behandelt. (Das ist meine Standardfehlerbehandlung, nicht die von Access.) Ist die Fehlernummer vorhanden, wird das Formular frmError geöffnet, das Feld Response ausgewertet und die entsprechende Aktion gestartet (mit Hilfe der case-Anweisung); wenn nicht, wird das Formular frmError geöffnet und die Funktion ErrorHandler gibt den Konstantenwert ERR_QUIT zurück. Bei dieser Methode brauchen Sie nur spezielle Fehler, die Sie abfangen wollen, in die Tabelle einzufügen. Wenn in tblErrors keine Datensätze gefunden werden, die zur SQL-Anweisung passen, wird das Formular frmErrors geöffnet und der Rückgabewert für die Funktion wird auf den Konstantenwert ERR_QUIT gesetzt. Bei vorhandener Fehlernummer wird das Feld Response des Datensatzes ausgewertet. Wenn dieses den Konstantenwert ERR_QUIT oder ERR_EXIT enthält, erscheint das Formular frmError, bevor dieser Wert an die fehlerhafte Funktion oder Unterroutine zurückgegeben wird. Wenn das Feld den Konstantenwert ERR_RETRY oder ERR_CONTINUE enthält, wird dieser ohne Anzeige des Formulars zurückgegeben.

596

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

Die Tabelle tblErrors finden Sie in CHAP14EX.MDB auf der CD-ROM mit dem Beispiel-Code. Um sie voll zu nutzen, müssen Sie alle abzufangenden Fehler sowie die Aktionen hinzufügen, welche die Fehlerbehandlungsroutine beim Auftreten eines Fehlers einleiten soll. Der Rückgabewert der Funktion ErrorHandler wird so verwendet, wie es Listing 14.20 zeigt. Listing 14.20: Verwendung des Rückgabewerts der Funktion ErrorHandler SUB ANYSUB()

CONST SUBNAME AS STRING = "ANYSUB" O N ERROR GOTO ANYSUB_ERR M SGBOX "THIS IS THE E RR.RAISE 11 M SGBOX "WE ARE PAST

REST OF YOUR CODE...." THE

ERROR!!"

Exit Sub AnySub_Exit: Exit Sub AnySub_Err: Dim intAction As Integer intAction = ErrorHandler(intErrorNum:=Err.Number, _ strErrorDescription:=Err.Description, _ strModuleName:=MODULENAME, _ strRoutineName:=SUBNAME) Select Case intAction Case ERR_CONTINUE Resume Next Case ERR_RETRY Resume Case ERR_EXIT Resume AnySub_Exit Case ERR_QUIT Quit End Select End Sub

In diesem Beispiel erzeugt die Routine AnySub einen Fehler mit der Nummer 11 (Division durch 0). Da in der Spalte Response von tblErrors die Zahl 3 steht und die Konstante ERR_CONTINUE diese Nummer trägt, wird das Fehlerformular angezeigt und die Routine AnySub mit einer Exit Sub-Anweisung verlassen.

Eine allgemeine Fehlerbehandlungsroutine erstellen

597

Um herauszufinden, was passiert, wenn der Fehler-Code in der Tabelle tblErrors nicht gefunden wird, starten Sie die Routine SubWithUnknownError, die Sie in basError finden. Um zu testen, was geschieht, wenn der Code ERR_CONTINUE zurückgegeben wird, führen Sie die Routine SubWithContinue aus.

14.11.3 Ein Fehlerformular erstellen Der Code im Ladeereignis des Fehlerformulars ruft, wie hier gezeigt, zwei Unterroutinen auf, nämlich GetSystemInfo und GetErrorInfo: Private Sub Form_Load() Call GetSysInfo(Me) Call GetErrorInfo(Me) Me!lblAction.Caption = Me.OpenArgs End Sub

Die erste Unterroutine heißt GetSystemInfo. Sie führt mehrere Windows-API-Aufrufe aus, um die Systeminformationen in Ihr Formular einzusetzen. Den Code finden Sie in Listing 14.21, besprochen wird er in Kapitel 27. Listing 14.21: Mit Hilfe von Code Systeminformationen abfragen Sub GetSysInfo (frmAny As Form) 'Freien Speicher besorgen Dim MS As MEMORYSTATUS MS.dwLength = Len (MS) GlobalMemoryStatus MS frmAny!lblMemoryTotal.Caption = Format(Ms.dwTotalPhys, "Standard") frmAny!lblMemoryAvail.Caption = Format(Ms.dwAvailPhys, "Standard") 'Versionsinformationen holen DImOSINfo As OSVERSIONINFO OSInfo.dwOSVersionInfoSize = Len(OSInfo) If GetVersionEx(OSInfo) Then frmAny!lblOSVersion.Caption = OSInfo.dwMajorVersion & "." _ & OSInfo.dwMinorVersion frmAny!lblBuild.Caption = OSInfo.dwBuildNumber And &HFFFF& If OSInfo.dwPlatformID = 0 Then frmAny!lblPlatformCaption = "Windows 95" Else frmAny!lblPlatformCaption = "Windows NT" End If End If 'Systeminformationen holen Dim SI As SYSTEM_INFO

598

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

GetSystemInfo SI frmAny!lblProcessor.Caption = SI.dwProcessorType End Sub

Diese API-Aufrufe erfordern die Declare-Anweisungen und -Konstanten, die Sie in Listing 14.22 finden. Sie sind in einem Modul mit dem Namen basAPI gespeichert. Listing 14.22: Windows-API-Aufrufe deklarieren Option Compare Database Option Explicit Private Declare Sub GlobalMemoryStatus Lib "Kernel32"_ (lpBuffer As MEMORYSTATUS) Private Type MEMORYSTATUS dwLength As Long dwMemoryLoad As Long dwTotalPhys As Long dwAvailPhys As Long dwTotalPageFile As Long dwAvailPagefile As Long dwTotalVirtual As Long dwAvailVirtual As Long End Type Private Declare Function GetVersionEx Lib "Kernel32" _ Alias "GetVersionExA" (lpOSInfo AS OSVERSIONINFO) As Boolean Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformID As Long strReserved AsString * 128 End Type Private Declare Sub GetSystemInfo Lib "Kernel32"_ (lpSystemInfo As SYSTEM_INFO) Private Type SYSTEM_INFO dwOemID As Long dwPageSize As Long lpMinimumApplicationAddress As Long lpMaximumApplicationAddress As Long dwActiveProcessorMask As Long dwNumberOfProcessors As Long dwProcessorType As Long

Eine allgemeine Fehlerbehandlungsroutine erstellen

599

dwAllocationGranularity As Long dwReserved As Long End Type

Die zweite Unterroutine GetErrorInfo füllt die Bezeichnungsfelder des Fehlerformulars mit den Informationen aus der Struktur aus, wie in Listing 14.23 gezeigt. Listing 14.23: Die Unterroutine GetErrorInfo Sub GetErrorInfo(frmAny As Form) frmAny!lblErrorNumber.Caption = gtypError.intErrorNum frmAny!lblErrorString.Caption = gtypError.strMessage frmAny!lblUserName.Caption = gtypError.strUserName frmAny!lblDateTime.Caption = Format(gtypError.datDateTime, "c") frmAny!lblModuleName.Caption = gtypError.strModule frmAny!lblRoutineName.Caption = gtypError.strRoutine End Sub

Schließlich wird die Art des Fehlers, welche von der Funktion ErrorHandler als OpenArg gesendet wurde, in einem Bezeichnungsfeld im Formular angezeigt. Abbildung 14.6 zeigt das Fehlerformular.

Abbildung 14.6: Das Formular frmErrors zeigt wichtige Informationen über den aufgetretenen Fehler an

14.11.4 Das Fehlerformular ausdrucken Benutzer arbeiten bei der Beschreibung eines Fehlers und der entsprechenden Fehlermeldung häufig nicht sehr genau. Deshalb ist es wichtig, ihnen die Möglichkeit zu geben, die Fehlermeldung auszudrucken. Der Code in Listing 14.24 druckt das Feh-

600

Kapitel 14: Fehlerbehandlung: Vorbereitung auf das Unvermeidliche

lerformular. Er befindet sich hinter dem Klick-Ereignis der Schaltfläche mit dem Druckersymbol im Fehlerformular. Listing 14.24: Das Fehlerformular ausdrucken Sub cmdPrint_Click() On Error GoTo Err_cmdPrint_Click

DoCmd.PrintOut Exit_cmdPrint_Click: Exit Sub Err_cmdPrint_Click: MsgBox Err.Description Resume Exit_cmdPrint_Click End Sub

14.12

Verhindern, dass die eigene Fehlerbehandlung aufgerufen wird

Beim Testen Ihrer Anwendung soll nicht die eigene, sondern die Fehlerbehandlung von VBA aktiviert werden. Um dies zu erreichen, verwenden Sie das Dialogfeld OPTIONEN des VBE. Wählen Sie dazu EXTRAS|OPTIONEN und klicken Sie auf die Registerkarte ALLGEMEIN. Aktivieren Sie im Abschnitt UNTERBRECHEN BEI FEHLERN die Option BEI JEDEM FEHLER. Solange diese Option aktiv ist, wird Ihre Fehlerbehandlung ignoriert und die Access-Standardfehlerbehandlung aufgerufen. Mit Hilfe dieser Einstellung können Sie die Fehlerbehandlung an einer zentralen Stelle einund ausschalten.

14.12.1 Für die Praxis Fehlerbehandlung integrieren Code zur Fehlerbehandlung sollte in das gesamte Zeit- und Abrechnungssystem integriert werden. Das folgende Beispiel zeigt Ihnen, wie Sie die allgemeine Fehlerbehandlung in diese Anwendung einbauen. Unsere Beispielanwendung enthält eine Routine mit dem Namen GetCompanyInfo, die sämtliche Informationen über die Firma aus der Tabelle tblCompanyInfo einliest. Diese Daten werden nach Bedarf während des Betriebs der Anwendung aus der Typstruktur entnommen. Wie jede Routine besitzt auch diese ein Fehlerpotential. Die Originalroutine wurde so geändert, dass sie jetzt die allgemeine Fehlerbehandlungsroutine enthält (siehe Listing 14.25).

Verhindern, dass die eigene Fehlerbehandlung aufgerufen wird

601

Listing 14.25: Integration der allgemeinen Fehlerbehandlungsroutine in den Programm-Code Sub GetCompanyInfo() On Error GoTo GetCompanyInfo_Err Dim strSubName As String Dim rst As ADODB.Recordset strSubName = "GetCompanyInfo" Set rst = New ADODB.Recordset rst.ActiveConnection = CurrentProject.Connection rst.Open "Select * from tblCompanyInfo", Options:=adCmdText typCompanyInfo.SetUpID = rst!SetUpID typCompanyInfo.CompanyName = rst!CompanyName typCompanyInfo.Address = rst!Address typCompanyInfo.City = rst!City typCompanyInfo.StateProvince = rst!StateProvince typCompanyInfo.PostalCode = rst!PostalCode typCompanyInfo.Country = rst!Country typCompanyInfo.PhoneNumber = rst!PhoneNumber typCompanyInfo.FaxNumber = rst!PhoneNumber rst.Close Exit Sub GetCompanyInfo_Err: Dim intAction As Integer intAction = ErrorHandler(lngErrorNum:=Err.Number, _ strErrorDescription:=Err.Description, _ strModuleName:=mstrModuleName, _ strRoutineName:=strSubName) Select Case intAction Case ERR_CONTINUE Resume Next Case ERR_RETRY Resume Case ERR_EXIT Exit Sub Case ERR_QUIT Quit End Select End Sub

Beachten Sie die Anweisung On Error GoTo am Anfang der Routine und den Umstand, dass die lokale Variable strSubName deklariert und auf GetCompanyInfo gesetzt wurde. Die allgemeine Fehlerbehandlungsroutine verwendet die lokale Variable, um die Routine anzuzeigen, in der der Fehler aufgetreten ist. Die Fehlerbehandlungsroutine GetCompanyInfo_Err ruft die Funktion ErrorHandler auf und wertet dann deren Rückgabewert aus.

Optimieren Ihrer Anwendung

Kapitel Hier lesen Sie:

 Mehr Leistung  Einführung in die Optimierung  Hard- und Software-Konfiguration modifizieren  Was bringt Jet 4.0 für die Verbesserung der Leistung?  Mit Hilfe der Leistungsanalyse Problembereiche ermitteln  Tabellen mit dem Ziel optimaler Leistung gestalten  Abfragen mit dem Ziel optimaler Leistung gestalten  Anders programmieren, um die Leistung zu optimieren  Formulare und Berichte mit dem Ziel optimaler Leistung gestalten

15.1

Mehr Leistung

In einer Welt, in der die Hardware häufig kaum mit der Software Schritt halten kann, ist es wichtig, dass Sie alles tun, um die Leistung Ihrer Anwendung zu optimieren. Dieses Kapitel hilft Ihnen, Ihre Anwendungen in Hinblick auf die Geschwindigkeit zu optimieren und die Anforderungen an den Arbeitsspeicher und den Platz auf der Festplatte zu reduzieren.

15.2

Einführung in die Optimierung

»Optimierung« ist die Überarbeitung der Betriebsumgebung, des VBA-Codes, der Anwendungsobjekte und der Datenstrukturen mit dem Ziel, optimale Leistung zu gewährleisten. Kurz gesagt: Optimierung besteht darin, die Anwendung schlanker und anspruchsloser zu machen.

604

Kapitel 15: Optimieren Ihrer Anwendung

Benutzer sind frustriert, wenn eine Anwendung nur langsam läuft. Wenn ein Benutzer nicht gewarnt wird, dass ein Prozess langsam ausgeführt wird, wird er häufig einen Neustart des Rechners versuchen oder ihn ausschalten, während der Prozess noch läuft. Das kann die Datenintegrität erheblich beeinträchtigen. Um das Risiko zu reduzieren, dass der Benutzer den Rechner während eines langwierigen Prozesses neu startet, ist es meistens zu empfehlen, ihm in irgendeiner Form Informationen darüber zu geben, wie lange es dauert. Das kann in Form einer Meldung geschehen, die vor dem Start des Prozesses eingeblendet wird, oder durch eine Fortschrittsanzeige, die den Verlauf des Prozesses wiedergibt. Um die Leistung einer Anwendung zu optimieren, gibt es viele Möglichkeiten – von der Verwendung eines Front-End-Werkzeugs wie der Leistungsanalyse bis hin zur strengen Einhaltung bestimmter Programmiertechniken. Dieses Kapitel beleuchtet die wichtigsten Methoden, die Ihnen zur Leistungsoptimierung zur Verfügung stehen.

15.3

Hard- und Software-Konfiguration modifizieren

Mit Access-»Umgebung« ist die Kombination aus Hard- und Software-Konfiguration gemeint, unter der Microsoft Access betrieben wird. Diese Umgebungseinstellungen können die Leistung einer Access-Anwendung erheblich beeinflussen. Die einfachste Möglichkeit, die Leistung einer Access-Anwendung zu verbessern, besteht in der Aktualisierung der Hard- und Software-Konfiguration, unter der sie läuft. Diese Art von Optimierung erfordert keinen direkten Eingriff des Entwicklers. Eine positive Nebenwirkung der meisten möglichen Umgebungsveränderungen besteht darin, dass Verbesserungen der Umgebung dem Benutzer in allen WindowsAnwendungen Vorteile bringen. Zur Verbesserung der Umgebung gehört mehr, als nur den Arbeitsspeicher auszubauen. Damit ist auch die optimale Konfiguration des Betriebssystems und der Access-Anwendung gemeint.

15.3.1

Hardware, mehr Hardware!

Windows 95, Windows 98, Windows NT und Access 2000 betteln geradezu um Hardware – je mehr, desto besser. Je schneller der Rechner ist und je mehr Arbeitsspeicher er besitzt, desto besser. Zusätzliche Hardware ist vielleicht nicht die billigste Lösung, aber mit Sicherheit die schnellste und einfachste, um die Leistung der Anwendung zu erhöhen.

Hard- und Software-Konfiguration modifizieren

605

Alles, was ich brauche, ist RAM! In erster Linie bettelt Access um Arbeitsspeicher, egal, ob Sie die vollständige Microsoft Access-Version oder die Laufzeitversion des Programms einsetzen. Microsoft Access benötigt schon unter Windows 95 und 98, seinen Standardbetriebsumgebungen, 12 MB RAM, nur um zu laufen. Das ist das unbedingt Nötige; empfohlen werden von Microsoft sogar 16 MB. Unter Windows NT benötigt Access mindestens 16 MB RAM. Beide Anforderungen können dramatisch steigen, wenn der Benutzer noch andere Anwendungen in Betrieb hat oder wenn Ihre Anwendung über OLEAutomatisierung mit anderen Anwendungen kommuniziert. Sehr direkt ausgedrückt: Je mehr RAM Sie und die Benutzer Ihrer Anwendung besitzen, desto besser ist es. 64 MB ist für Access 2000 hervorragend. Wenn jeder Ihrer Benutzer über mindestens 64 MB RAM verfügt, können Sie eigentlich aufhören, dieses Kapitel zu lesen, weil alles, was hier noch gesagt wird, im Vergleich zur Bereitstellung von mehr Arbeitsspeicher nur geringe Vorteile bringt. Wenn Sie jedoch in derselben Lage sind wie die meisten von uns, dass nicht alle Ihre Benutzer einen Pentium II mit 450 MHz und 64 MB RAM besitzen, lesen Sie weiter. Entwickler sollten einen Rechner mit mindestens 64 MB RAM zur Verfügung haben. Denken Sie daran: das ist das Minimum! Die meisten Entwickler sind sich einig, dass 128 MB für ernsthafte Entwicklungsarbeit ideal sind, insbesondere wenn Sie Client-Server-Anwendungen oder solche für Intranets oder das Internet entwickeln wollen. Defragmentieren Sie die Festplatte des Benutzers Beim Schreiben auf die Festplatte versucht der Rechner, zusammenhängenden Speicherplatz für Datendateien zu finden. Wenn sich die Festplatte füllt, werden Dateien in fragmentierter Form abgelegt. Bei jedem Versuch Ihrer Anwendung, Daten und Programme zu lesen, müssen die über die Platte verstreuten Informationen gesucht werden, was sehr zeitaufwendig ist. Deshalb ist das Defragmentieren der Festplatte, auf der die Anwendung und die Datentabellen gespeichert sind, mit Hilfe eines Programms wie des mit Windows 95, Windows 98 und Windows NT 5.0 gelieferten Defragmentierers hilfreich. Der Vorgang des Defragmentierens einer Festplatte lässt sich mit dem System Agent aus dem Microsoft Plus! Pack leicht automatisieren. Dieses Paket wird als Add-On für Windows 95 verkauft. Der System Agent ist ein nützliches Werkzeug, mit dem Sie planen können, wann und wie oft defragmentiert wird. Windows 98 wird mit dem Taskplaner ausgeliefert, der verwendet wird, um die automatische Ausführung verschiedener Systemaufgaben wie Defragmentieren (Defragmentierung) und Überprüfen des Dateisystems (Scandisk) zeitlich zu planen.

606

Kapitel 15: Optimieren Ihrer Anwendung

Komprimieren Sie Ihre Datenbank Genauso wie das Betriebssystem Ihre Dateien mit der Zeit fragmentiert, bringt auch Access eigene Formen der Fragmentierung mit sich. Bei jedem Hinzufügen und Modifizieren von Daten wächst die Datenbank. Das Problem liegt darin, dass die Datenbank nicht kleiner wird, wenn Sie Daten oder Objekte löschen. Access hinterlässt nämlich leere Seiten, auf die neue Daten geschrieben werden können. Diese werden jedoch nicht zwangsläufig mit Daten gefüllt. Der freie Platz lässt sich mit dem Dienstprogramm Compact freigeben, das zu Microsoft Access gehört. Es gibt überschüssigen Speicherplatz frei und versucht alle Datenseiten zusammenhängend abzulegen. Sie sollten Ihre Datenbank häufig komprimieren, insbesondere wenn regelmäßig Datensätze oder Datenbankobjekte (z.B. Formulare und Berichte) hinzugefügt bzw. gelöscht werden. Auf das Dienstprogramm Compact haben Sie nur Zugriff, wenn keine Datenbank geöffnet ist. Sie erreichen es über EXTRAS|DATENBANK-DIENSTPROGRAMME. Wählen Sie dann die Option DATENBANK KOMPRIMIEREN UND REPARIEREN. Es ist der Erwähnung wert, dass es günstig ist, eine Methode zur Komprimierung der Datenbank mitzuliefern, wenn Sie vorhaben, eine Access-Anwendung – möglicherweise über das Laufzeitmodul – an andere Benutzer weiterzugeben. Häufig ermöglicht das Laufzeitmodul keinen Zugriff auf den Menüpunkt KOMPRIMIEREN. Mit der Methode CompactDatabase können Sie eine Datenbank aus einer Access-Datenbank heraus komprimieren, aber dieser Befehl lässt sich nicht aus der aktuellen Anwendung aufrufen. Man muss eine zweite Anwendung erstellen, um die Methode CompactDatabase auf die Originalanwendung anwenden zu können. Verwenden Sie keine komprimierten Laufwerke Unabhängig davon, welches Komprimierungsprogramm Sie verwenden, senkt die Komprimierung von Laufwerken die Leistung von Access 2000 deutlich. Dieser Umstand ist in der Datei README dokumentiert. Bringen Sie den virtuellen Speicher auf Trab Obwohl Windows 95 und 98 versuchen, den virtuellen Speicher selbstständig zu verwalten, halten Sie es vielleicht für sinnvoll, ihnen einige zusätzliche Informationen zu geben. Um die physische Speicherstelle der Auslagerungsdatei zu verändern, klicken Sie mit der rechten Maustaste auf ARBEITSPLATZ und wählen dann im Kontextmenü den Eintrag EIGENSCHAFTEN. Wechseln Sie anschließend auf die Registerkarte LEISTUNGSMERKMALE und klicken Sie auf die Schaltfläche VIRTUELLER ARBEITSSPEICHER. Es könnte sinnvoll sein, die Auslagerungsdatei auf ein schnelleres Laufwerk oder auf ein Laufwerk mit eigener Controller-Karte zu verschieben. Alle Änderungen können sich aber auch negativ auf die Leistung auswirken. Es ist wichtig zu prüfen, ob vorgenommene Änderungen die Situation verbessern oder sie vielleicht ver-

Hard- und Software-Konfiguration modifizieren

607

schlechtern. Im Allgemeinen ist es ratsam, Windows die Größe der Auslagerungsdatei dynamisch verwalten zu lassen, es sei denn, das System verfügt nur über sehr wenig Platz auf der Festplatte. Wenn Access 2000 oder Windows auf einem komprimierten Laufwerk betrieben wird, können Sie die Leistung durch Verschieben der Auslagerungsdatei auf ein nicht komprimiertes Laufwerk steigern. Falls möglich, sollte sich die Auslagerungsdatei auf einem Laufwerk oder einer Partition befinden, das/die für sie reserviert ist, oder auf einem Laufwerk/einer Partition, auf welche(s) andere Anwendungen nur selten zugreifen. Das trägt dazu bei, dass sie zusammenhängend abgelegt wird. Betreiben Sie Access und Ihre Anwendung lokal In Kapitel 17 erfahren Sie, dass Sie sowohl das Programm Access als auch Ihre Anwendungsobjekte am besten auf dem lokalen Rechner jedes Benutzers installieren. Nur die Datentabellen sollten auf einem Datei-Server im Netzwerk abgelegt werden. Andernfalls senden Sie DLLs, OLE-Objekte, Hilfedateien, Typbibliotheken, ausführbare Dateien und Datenbankobjekte über die Leitung. Wenn Sie bei einer Access-Anwendung die geringste mögliche Leistung erzielen wollen, installieren Sie diese auf einer Arbeitsstation ohne Festplatte mit 16 MB RAM. Tun Sie alles, was möglich ist, um Windows schneller zu machen Es amüsiert mich immer wieder, dass die Benutzer mit den langsamsten Rechnern und dem wenigsten Arbeitsspeicher das meiste Zubehör in Betrieb haben. Dazu gehören Multimedia, prächtige Hintergründe und andere raffinierte Dienstprogramme. Wenn Leistung ein Problem darstellt, können Sie ausprobieren, ob der Verzicht auf einige der frivolen Nettigkeiten die Leistung Ihrer Anwendung verbessert. Falls ja, sollten Sie den Benutzer ermutigen, die Kinkerlitzchen zu beseitigen, mehr Arbeitsspeicher zu beschaffen oder aber die Leistung der Anwendung zu akzeptieren. Außerdem sollten Sie andere Anwendungen, z.B. Microsoft Excel, schließen, wenn Sie damit fertig sind. Ein weiterer Tipp, um Windows 95 und 98 schneller zu machen, ist das regelmäßige Herunterfahren und Neustarten. Ein Arbeitsspeicher tendiert zur Fragmentierung, und Anwendungen laufen dann langsamer. Windows NT kann Wochen oder Monate laufen, ohne dass ein Neustart erforderlich ist, aber bei Windows 95 und 98 habe ich festgestellt, dass es vorteilhaft ist, mehrmals täglich neu zu starten.

15.3.2

Ändern Sie die Software-Einstellungen von Access

Neben den auf der Hand liegenden Maßnahmen, die ich gerade skizziert habe, können einige kleinere Software-Kniffe viel für die Verbesserung der Leistung bringen. Die Anpassung verschiedener Einstellungen in der Windows-Registry kann die Leis-

608

Kapitel 15: Optimieren Ihrer Anwendung

tung deutlich steigern. Alle betreffen den Registry-Abschnitt ISAM. Zu den Eigenschaften, die Sie möglicherweise ändern wollen, gehören MaxBufferSize und ReadAheadPages. Beide legen fest, wie die Jet-Engine Speicher einsetzt. Die Option MaxBufferSize steuert die Maximalgröße des internen Cache der JetEngine. Standardmäßig ist sie so eingestellt, dass auf den meisten Rechnern die optimale Leistung erreicht wird. Die Daten werden in Seiten von 2 KB eingelesen und in einem Zwischenspeicher abgelegt. Die Daten im Cache sind für Formulare, Berichte, Tabellen und Abfragen mühelos erreichbar. Die Herabsetzung des Wertes von MaxBufferSize macht Speicher für andere Aufgaben frei. Das kann auf einem Rechner mit minimaler Speicherausstattung hilfreich sein. Die Option ReadAheadPages steuert die Anzahl der 2-KB-Datenseiten, welche die JetEngine bei sequentiellen Lesevorgängen im voraus liest. Sie kann von 0 bis 31 reichen; der Standard liegt bei 16. Je höher diese Zahl ist, desto effizienter liest Access im Voraus, so dass die Daten verfügbar sind, wenn Sie sie benötigen. Je niedriger diese Zahl ist, desto mehr Speicher steht für andere Aufgaben zur Verfügung. Denken Sie beim Konfigurieren dieser Einstellungen daran, dass Werte, die für einen Rechner günstig sind, für den nächsten nicht zwangsläufig auch gut sind. Die Einstellungen müssen für jeden Rechner mit Rücksicht auf die jeweilige Hardware-Konfiguration optimiert werden.

15.4

Was bringt Jet 4.0 für die Verbesserung der Leistung?

An der Jet 4.0-Engine wurden Verbesserungen vorgenommen, um die Leistung gegenüber den Vorgängern deutlich zu steigern. Einige davon gab es schon in der Jet 3.0-Engine von Access 95 oder in der Jet 3.5-Engine von Access 97, aber viele sind in Jet 4.0 neu hinzugekommen. Die gesamte Engine ist ein 32-Bit-Programm. Sie nutzt mehrere Ausführungs-Threads, was deutliche Leistungsvorteile bietet. Zu den Vorzügen, die mit Jet 3.5 (Access 97) kamen, gehört Folgendes:

 Schnelleres Löschen. Teile einer Seite lassen sich als Ganzes löschen anstatt die Daten zeilenweise zu entfernen.

 Verbesserte gleichzeitige Nutzung indizierter Spalten durch mehrere Benutzer. Indizierte Spalten lassen sich von mehreren Benutzern lesen und aktualisieren, ohne dass Sperrkonflikte auftreten. Indizierte Spalten enthalten keine Lesesperren mehr.

 Implizite Transaktionsverarbeitung. Zwar haben viele Benutzer bereits in früheren Access-Versionen Verarbeitungsschleifen in das Konstrukt BeginTrans... CommitTrans verpackt, um die Anzahl der Schreibvorgänge zu begrenzen, aber Jet 3.5 handhabt dies auch von sich aus recht gut.

Was bringt Jet 4.0 für die Verbesserung der Leistung?

609

 Umfangreiche Abfragen werden schneller erledigt. Ursache sind Verbesserungen am Transaktionsverhalten für SQL-Anweisungen in DML (Data Manipulation Language) sowie neue Einstellungen in der Registry, die den Commit von Transaktionen erzwingen, wenn eine bestimmte Sperrschwelle erreicht ist.

 Abfragen mit dem Ungleichheitsoperator () werden schneller abgearbeitet.  Das sequentielle Lesen geht schneller. Es können bis zu 64 KB Speicherplatz auf der Platte auf einmal zugewiesen werden.

 Temporäre Abfragen laufen schneller.  Eine Tabelle lässt sich mit SQL DROP oder SQL DELETE schneller löschen.  Indizes belegen weniger Speicherplatz.  Beim Komprimieren einer Datenbank werden aus Gründen der Leistung alle Indizes optimiert.

 Der Seitenzuweisungsmechanismus wurde verbessert. Dadurch wird eher gewährleistet, dass Tabellendaten auf nebeneinander liegenden Seiten abgelegt werden, und die Fähigkeit, im Voraus zu lesen, wird verbessert.

 Der Cache wird dynamisch konfiguriert. Beim Start erfolgt die Konfiguration anhand des verfügbaren Systemspeichers. Der Cache enthält dann die zuletzt verwendeten Daten und das verbessert die Leistung.

 Es gibt ISAM-Unterstützung für HTML-Dateien.  Mit der Registry-Einstellung MaxLocksPerFile lässt sich ein Commit für Datensätze erzwingen, wenn eine bestimmte Sperrschwelle erreicht ist. Das beschleunigt den Abschluss umfangreicher Abfragen, wenn die Daten auf Windows NTund NetWare-Servern gespeichert werden. Folgende Verbesserungen sind in Jet 4.0 neu:

 Die Datenseiten enthalten jetzt nicht mehr 2 KB sondern 4 KB. Dadurch erhöht sich die maximale Datenbankgröße von 1,07 auf 2,14 GB und für viele Operationen bringt es höhere Leistung, weil weniger Plattenzugriffe erforderlich sind.

 Der native OLEDB Provider bietet im Vergleich zu ODBC-Daten höhere Leistung.

 Die ersten 255 Zeichen von Memo-Feldern lassen sich indizieren. Das steigert die Leistung beim Durchsuchen und Sortieren von Memo-Feldern beträchtlich.

610

15.5

Kapitel 15: Optimieren Ihrer Anwendung

Mit Hilfe der Leistungsanalyse Problembereiche ermitteln

Sie können viel tun, um die Leistung einer Anwendung zu steigern. Die meisten Maßnahmen fordern von Ihnen viel Aufmerksamkeit und Fachwissen. Die Leistungsanalyse ist ein Werkzeug, das Ihnen einen Teil der Arbeit abnimmt. Sie analysiert die Architektur der Access-Anwendung und schlägt Techniken zur Steigerung der Leistung vor. Viele der vorgeschlagenen Techniken lassen sich automatisch implementieren. Um die Leistungsanalyse einzusetzen, wählen Sie EXTRAS|ANALYSE|LEISTUNG. Dann erscheint das Dialogfeld in Abbildung 15.1.

Abbildung 15.1: Das Dialogfeld Leistungsanalyse

Markieren Sie die einzelnen Tabellen, Abfragen, Formulare, Berichte, Makros, Module und Beziehungen, welche die Leistungsanalyse untersuchen soll. Wenn Access die Beziehungen untersuchen soll, müssen Sie auf die Registerkarte AKTUELLE DATENBANK klicken und dann BEZIEHUNGEN wählen. Nachdem Sie Ihre Wahl getroffen und auf OK geklickt haben, werden die markierten Objekte analysiert. Nach dem Abschluss des Analyseprozesses wird das Dialogfeld ASSISTENT ZUR LEISTUNGSANALYSE eingeblendet, das Sie in Abbildung 15.2 sehen. Es liefert Ihnen eine Liste von Verbesserungsvorschlägen für die markierten Objekte. Diese sind in Empfehlungen, Vorschläge, Ideen und automatisch behobene Dinge unterteilt. Zu den vorgeschlagenen Verbesserungen zählt beispielsweise das Hinzufügen eines Index oder die Konvertierung eines OLE-Objekts. Nach der Analyse der mit Access gelieferten Nordwind-Datenbank schlug die Leistungsanalyse beispielsweise vor, im Formular Personal weniger Steuerelemente unterzubringen.

611

Tabellen mit dem Ziel optimaler Leistung gestalten

Abbildung 15.2: Der zweite Teil des Dialogfeldes Assistent zur Leistungsanalyse

15.6

Tabellen mit dem Ziel optimaler Leistung gestalten

Nachdem Sie jetzt gesehen haben, welche Veränderungen Sie an Ihrer Umgebung vornehmen können, um die Leistung zu steigern, sollten Sie nun einen Blick auf die Veränderungen werfen, die Sie zu diesem Zweck an Ihren Datenstrukturen vornehmen können. Dazu gehört das Beseitigen redundanter Daten, die Verwendung von Indizes, die Auswahl geeigneter Datentypen für Felder und die Verwendung unterschiedlicher Abfragetechniken. Die Optimierung der Leistung durch ausgefeilte Datenstrukturen ist geboten. Schlechtes Daten-Design kann die Leistung Ihrer Anwendung erheblich verschlechtern, was Sie auch sonst zur Leistungsverbesserung tun mögen. Alle weiteren Optimierungsversuche sind ohne angemessene Berücksichtigung dieses Bereichs sinnlos. Die Optimierung Ihrer Daten kann Tage dauern. Derartige Veränderungen müssen gut durchdacht und sorgfältig analysiert werden. Veränderungen werden häufig im Lauf der Zeit vorgenommen, wenn sich Probleme zeigen. Dazu können auch die in den folgenden Abschnitten genannten gehören.

15.6.1

Warum »normal«?

Damit ist im Grunde gemeint: Bringen Sie Ihre Tabellen in die Normalform. Daten, die an mehreren Stellen vorkommen, können Ihre Anwendung deutlich verlangsamen. Ursache dafür ist sowohl die Menge der erzeugten Daten als auch die Notwendigkeit, bei Änderungen sämtliche Exemplare der Daten zu aktualisieren. Nehmen

612

Kapitel 15: Optimieren Ihrer Anwendung

wir an, eine Firmenadresse erscheint sowohl in der Tabelle Kunden als auch in der Tabelle Bestellungen. Wenn sich die Adresse ändert, muss sie in beiden Tabellen geändert werden. Die Information sollte nur in der Tabelle Kunden stehen. Adressund Bestelldaten sollten, falls erforderlich, mit Hilfe von Abfragen verknüpft werden.

15.6.2

Denormalisierung?

Wenn es um Leistung geht, gibt es leider keine schnellen, unumstößlichen Regeln. Obwohl Sie durch die Umstellung der Datenstruktur auf die Normalform meistens Leistung gewinnen, kann manchmal auch die Denormalisierung sinnvoll sein. Das gilt im Allgemeinen, wenn Sie feststellen, dass eine bestimmte Verknüpfung immer wieder erstellt wird. Ein weiteres Beispiel ist eine Buchhaltungsanwendung, in der die Gesamtschuld eines Kunden schnell erkennbar sein muss. Anstatt bei jedem Wechsel in einen Kundendatensatz alle offenen Rechnungen auszuwerten, können Sie die Gesamtschuld des Kunden im Kundendatensatz ablegen. Das setzt natürlich voraus, dass die Summe bei jeder Rechnungsausstellung oder Zahlung aktualisiert wird. Allgemein können Sie versuchen, die Daten zu denormalisieren, um zu sehen, ob sich deutliche Leistungsverbesserungen ergeben. Denken Sie daran, dass die Denormalisierung in Bezug auf Datenintegrität und -pflege deutliche Nachteile besitzt.

15.6.3

Index für gute Leistung

Es ist erstaunlich, in welchem Maß ein Index die Leistung verbessern kann. Alle Felder oder Feldkombinationen, anhand derer Sie suchen, sollten in einen Index aufgenommen werden. Sie sollten Indizes für alle Spalten anlegen, die in Abfrageverknüpfungen, Such- und Sortieroperationen verwendet werden. Primärschlüsselindizes sind gegenüber eindeutigen Indizes und eindeutige Indizes gegenüber nicht eindeutigen Indizes zu bevorzugen. Die Erstellung eines Index für das Fremdschlüsselfeld in einer 1:n-Beziehung ist nicht erforderlich. Dieser wird bei der Einrichtung der Beziehung von Access automatisch erstellt. Auch die Erstellung eines Index für ein Feld mit sich häufig wiederholenden Daten bringt keinen Vorteil. Ein Beispiel dafür ist ein Bundesstaatenfeld in einer Kundentabelle, in der alle Kunden in einem von zwei Staaten wohnen. Die Leistungssteigerungen durch Indizes sind gewaltig, obwohl sich Indizes auch überstrapazieren lassen. Obwohl Indizes die Leistung erheblich verbessern können, sollten Sie nicht für jedes Feld einer Tabelle einen Index anlegen. Indizes haben auch Nachteile. Neben dem Verbrauch von Speicherplatz verlangsamen sie das Hinzufügen, Bearbeiten und Löschen von Daten.

Abfragen mit dem Ziel optimaler Leistung gestalten

613

Indizieren Sie in einem Mehrfeldindex möglichst wenige Felder. Mehrfeldindizes können die Leistung erheblich beeinträchtigen.

Strategien für die Optimierung von Client-Server-Anwendungen werden in Kapitel 20 behandelt.

15.6.4

Wählen Sie den richtigen Datentyp

Wählen Sie bei der Definition eines Feldes den kürzesten Datentyp, den es für die Speicherung der Daten gibt. Wenn Sie beispielsweise einen Code zwischen 1 und 10 ablegen wollen, gibt es keinen Grund, für ein numerisches Feld den Typ Double zu wählen.

15.7

Abfragen mit dem Ziel optimaler Leistung gestalten

Die Optimierung Ihrer Abfragen erfordert ziemlich viel Übung und Experimente. Einige Abfragen, die eine 1:n-Beziehung betreffen, laufen beispielsweise effizienter, wenn das Kriterium auf die 1-Seite der Beziehung verlegt wird – bei anderen ist es umgekehrt. Wenn Sie einige grundlegende Dinge verstanden haben, sind Sie in bezug auf die Optimierung Ihrer Abfragen und Ihrer Anwendung insgesamt ein ganzes Stück weitergekommen, wie die folgende Liste zeigt:

 Nehmen Sie möglichst wenige Spalten in die Ergebnismenge auf.  Versuchen Sie, die Anzahl der komplexen Ausdrücke in der Abfrage zu reduzieren. Obwohl durch einen komplexen Ausdruck die Notwendigkeit entfällt, den Ausdruck in jedes einzelne Formular und jeden Bericht aufzunehmen, sind die Leistungsvorteile manchmal den Aufwand wert.

 Verwenden Sie den Operator Zwischen anstelle von größer als (>) und kleiner als (5", _ Options:=adCmdText) Do Until rst.EOF Debug.Print rst!Stor_id, rst!Qty rst.MoveNext Loop End Sub

19.12

Gespeicherte Prozeduren erstellen und ausführen

Auf einem Back-End-Datenbank-Server lassen sich auch gespeicherte Prozeduren ausführen. Eine gespeicherte Prozedur entspricht einer Abfrage oder einem Programm, das auf dem Back-End gespeichert ist, und führt eine Aktion aus. Ein Beispiel ist die in SQL Server 7.0 gespeicherte Prozedur sp_columns, die Informationen über die Felder einer bestimmten Tabelle zurückgibt. Abbildung 19.33 zeigt, wie Sie diese gespeicherte Prozedur vom Abfrage-Entwurfsfenster aus ausführen würden. Sie geben einfach den Namen der gespeicherten Prozedur und die erforderlichen Parameter ein. Sehen Sie sich das Fenster ABFRAGEEIGENSCHAFTEN in Abbildung 19.33 genau an. Wenn Sie eine gültige Verbindungszeichenfolge eingeben, wird der

Gespeicherte Prozeduren erstellen und ausführen

751

Benutzer zur Laufzeit nicht aufgefordert, sich anzumelden. Die Eigenschaft Liefert Datensätze ist ebenfalls wichtig. In diesem Fall setzen Sie den Wert der Eigenschaft auf Ja, damit Sie die Ergebnisse der gespeicherten Prozedur sehen können. Wenn diese keine Datensätze zurückgibt, wie es bei der im Abschnitt »Mit Sichten anstelle von Tabellen verknüpfen« erstellten Create-View-Pass-Through-Abfrage der Fall ist, ist es wichtig, die Eigenschaft auf Nein zu setzen; sonst bekommen Sie eine Fehlermeldung, die besagt, dass keine Zeilen zurückgegeben wurden. Abbildung 19.34 zeigt die Ergebnisse der Ausführung der gespeicherten Prozedur.

Abbildung 19.33: Ausführung einer gespeicherten Prozedur durch Eingabe des Prozedurnamens und der erforderlichen Parameter vom Abfragefenster aus

Abbildung 19.34: Die Ergebnisse der Ausführung der gespeicherten Prozedur sp_columns

Listing 19.4 zeigt eine Prozedur, welche mittels Code die gespeicherte Prozedur sp_columns ausführt. Listing 19.4:

Ausführen der gespeicherten Prozedur sp_columns

Sub StoredProcedure() Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim strConnectString As String strConnectString = "ODBC" & _ ";DATABASE=Pubs" & _ ";UID=SA" & _ ";PWD=" & _ ";DSN=PubsData"

752

Kapitel 19: Client-Server-Techniken

Set cnn = New ADODB.Connection cnn.ConnectionString = strConnectString cnn.Open Set rst = cnn.Execute("sp_columns('sales')", _ Options:=adCmdStoredProc) Do While Not rst.EOF Debug.Print rst!Column_Name rst.MoveNext Loop End Sub

Und so funktioniert sie: Zunächst wird ein Connection-Objekt angelegt und geöffnet, dann wird ein Recordset-Objekt erstellt, das die Ergebnisse der Ausführung der gespeicherten Prozedur aufnehmen soll. Beachten Sie, dass die gespeicherte Prozedur sp_columns einen Parameter übernimmt, der in Klammern steht. Die Konstante adCmdStoredProc teilt, wenn sie als Parameter Options übergeben wird, ADO mit, dass der Befehlstext für die Anweisung Execute der Name einer gespeicherten Prozedur ist.

19.12.1 Eine gespeicherte Prozedur schreiben Wenn Ihre Anwendung eine ADP-Datei ist, können Sie direkt aus der AccessUmgebung gespeicherte Prozeduren schreiben. Folgende Schritte sind dazu erforderlich: 1. Wählen Sie in der Objektliste des Datenbankfensters die Option GESPEICHERTE PROZEDUREN. 2. Doppelklicken Sie auf ERSTELLT EINE GESPEICHERTE PROZEDUR UNTER VERWENDUNG DES DESIGNERS. Dies ruft das Fenster GESPEICHERTE PROZEDUR auf (siehe Abbildung 19.35). 3. Geben Sie den Text für die gespeicherte Prozedur ein. 4. Klicken Sie auf das Werkzeug SPEICHERN in der Symbolleiste. 5. Geben Sie den Namen für die gespeicherte Prozedur ein und klicken Sie auf OK.

753

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

Abbildung 19.35: Im Dialogfeld Gespeicherte Prozedur können Sie auf einem DatenbankServer eine gespeicherte Prozedur erstellen

19.13

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

Wie in diesem Kapitel bereits erwähnt, können Sie mit Hilfe von Access-Projekten (ADP-Dateien) mit SQL Server-Datenbanken arbeiten, ohne die Microsoft JetDatenbank-Engine zu laden. Access-Projekte besitzen gegenüber den anderen in diesem Kapitel behandelten Zugriffsmethoden für Client-Server-Daten folgende Vorteile:

 Sie bieten Ihnen direkten Zugriff auf eine Microsoft SQL Server-Datenbank.  Sie können mühelos SQL Server-Tabellen, -Sichten, -Datenbankdiagramme und gespeicherte Prozeduren erstellen und zwar in der Access-Entwicklungsumgebung.

 Sie können Formulare, Berichte, Datenzugriffsseiten und Module entwickeln, die auf SQL Server zugreifen, ohne Jet zu benutzen.

 Auf der Client-Seite sind geringere Ressourcen erforderlich.  Der Server ist für die gesamte Abfrageverarbeitung zuständig.  Sie können auf Funktionen zugreifen, die beim Zugriff auf ODBC über Jet nicht verfügbar sind.

 Sie können asynchrone Abfragen ausführen, d.h. Sie brauchen nicht darauf zu warten, dass die Ausführung einer Abfrage abgeschlossen ist, bevor Sie eine andere Operation beginnen.

754

Kapitel 19: Client-Server-Techniken

 Sie können Batch-Aktualisierungen durchführen, d.h. Sie haben die Möglichkeit, Änderungen lokal zwischenzuspeichern und sie dem Server dann als Stapel zu liefern.

 Sie können Abfragen ausführen, die mehrere Ergebnisgruppen liefern.  Die Anzahl der Datensätze, die in einer Ergebnisgruppe zurückgegeben wird, lässt sich mühelos begrenzen.

 Meldungen und Fehler, die von der entfernten Datenquelle erzeugt werden, lassen sich einfach überwachen. Nun die Nachteile der Access-Datenprojektdateien:

 Sie können keine lokalen Tabellen anlegen.  Sie können keine lokalen Abfragen erstellen.  Das Erstellen von Tabellen, Sichten, Datenbankdiagrammen und gespeicherten Prozeduren erfordert Lernaufwand.

19.13.1 Ein Access-Datenprojekt (ADP) erstellen Mit Access 2000 werden Access-Datenprojekte (ADPs) eingeführt. Während eine Access-Datenbank über die Jet-Engine und ODBC auf Client-Server-Daten zugreift, verwenden ADPs zu diesem Zweck OLE DB. Dadurch bekommen Sie bei der Nutzung von Client-Server-Daten deutlich mehr Funktionen und höhere Leistung. Der einzige Nachteil liegt darin, dass die Client-Server-Daten in einer Microsoft SQL Server 7.0-Datenbank, in der MSDE oder in einer Microsoft SQL Server 6.5-Datenbank mit installiertem Service Pack 5 gespeichert werden müssen. Die

MSDE

finden

Sie

auf

der

Office-2000-CD-ROM

im

Ordner

\sql\x86\setup.

Wenn Sie mit Hilfe einer Access-Datenbank auf Client-Server-Daten zugreifen, müssen Sie verknüpfte Tabellen, Pass-Through-Abfragen und ODBC zur Bearbeitung der Daten benutzen. Wenn Sie die Strukturen der Client-Server-Tabellen verändern wollen, muss das in der SQL Server-Umgebung stattfinden. Bei einem Access-Datenprojekt können Sie Tabellen, Sichten, Datenbankdiagramme und gespeicherte Prozeduren direkt aus der Access-Umgebung erstellen und modifizieren.

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

755

Um ein Access-Datenprojekt zu erstellen, ist Folgendes erforderlich: 1. Klicken Sie auf die Schaltfläche NEU in der Symbolleiste.

Abbildung 19.36: Im Dialogfeld Neu können Sie auf der Basis einer neuen oder bereits vorhandenen SQL Server-Datenbank ein ADP erstellen

2. Es gibt zwei Optionen, um ein ADP zu erstellen. Mit der ersten können Sie eine vorhandene SQL Server-Datenbank als Grundlage für das ADP verwenden, mit der zweiten eine neue SQL Server-Datenbank. Wenn Sie doppelklicken, um ein Projekt auf der Basis einer vorhandenen Datenbank zu erstellen, wird das Dialogfeld NEUE DATENBANKDATEI eingeblendet. Geben Sie Namen und Speicherort der ADP-Datei ein und klicken Sie auf ERSTELLEN. Daraufhin erscheint das Dialogfeld DATENLINKEIGENSCHAFTEN (siehe Abbildung 19.37). 3. Geben Sie den Namen des Servers, Sicherheitsinformationen und den Namen der Datenbank ein, mit der Sie Verbindung aufnehmen wollen. 4. Klicken Sie auf die Registerkarte WEITERE, um weitere Optionen einzugeben, oder auf die Registerkarte ALLE, um Verbindungsoptionen einzusehen oder zu ändern. 5. Wenn Sie mit der Angabe von Optionen fertig sind, klicken Sie auf die Registerkarte VERBINDUNG und dann auf VERBINDUNG TESTEN, um sicherzustellen, dass alle Einstellungen korrekt vorgenommen wurden. 6. Klicken Sie auf OK, um das Access-Datenprojekt zu erstellen. Abbildung 19.38 zeigt eine ADP-Datei auf der Grundlage des Zeit- und Abrechnungssystems. Beachten Sie, dass die Tabellen so erscheinen, als wären sie in der ADP-Datei enthalten. Tatsächlich sind sie aber in der SQL Server-Datenbank gespeichert. Wichtig ist hier, dass die Tabellen nicht verknüpft sind! Deshalb sehen sie aus, als ob sie Teil des ADP wären, und lassen sich entsprechend bearbeiten.

756

Kapitel 19: Client-Server-Techniken

Abbildung 19.37: Im Dialogfeld Datenlinkeigenschaften können Sie Verbindungsinformationen in Bezug auf die SQL Server-Datenbank eingeben, mit der die ADP-Datei verknüpft ist

Abbildung 19.38: Die ADP-Datei zeigt Ihnen die in der SQL ServerDatenbank enthaltenen Tabellen, Sichten, Datenbankdiagramme und gespeicherten Prozeduren

Wie Sie in Abbildung 19.38 sehen können, sieht das Datenbankfenster für eine ADP-Datei anders aus als das für eine MDB-Datei. Die Objektliste enthält Tabellen,

757

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

Sichten, Datenbankdiagramme und gespeicherte Prozeduren statt Tabellen und Abfragen. Tatsächlich lassen sich weder lokale Tabellen noch Abfragen in einer ADP-Datei speichern.

19.13.2 Mit SQL Server-Tabellen arbeiten Einer der wesentlichen Vorteile eines ADP besteht darin, dass man SQL ServerTabellen direkt aus der Access-Umgebung erstellen, verändern, umbenennen und löschen kann. Es ist wichtig, daran zu denken, dass alle Änderungen, die aus Access heraus vorgenommen werden, in der verknüpften SQL Server-Datenbank unmittelbar zum Tragen kommen. Eine SQL Server-Tabelle anlegen Mit dem SQL Server Table Designer können Sie aus Access heraus SQL ServerTabellen anlegen. Dazu unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste den Eintrag TABELLEN. 2. Doppelklicken Sie auf ERSTELLT EINE TABELLE IN DER ENTWURFSANSICHT. 3. Geben Sie einen Namen für die SQL Server-Tabelle ein und klicken Sie auf OK. Sie gelangen in den SQL Server-Tabellen-Designer, wo Sie die Felder und Attribute definieren können (siehe Abbildung 19.39).

Abbildung 19.39: Im SQL ServerTabellenDesigner können Sie Namen und Attribute der Spalten eingeben

4. Geben Sie im SQL Server-Tabellen-Designer die Namen und Attribute der Spalten ein. 5. Schließen Sie das Fenster und speichern Sie Ihre Änderungen, wenn Sie fertig sind.

758

Kapitel 19: Client-Server-Techniken

Eine SQL Server-Tabelle verändern Um die Struktur einer vorhandenen SQL Server-Tabelle zu verändern, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste den Eintrag TABELLEN. 2. Markieren Sie die Tabelle, deren Struktur Sie verändern wollen. 3. Klicken Sie auf ENTWURF. Die Struktur der Tabelle wird eingeblendet. Abbildung 19.40 zeigt die Tabelle tblClients in der Entwurfsansicht.

Abbildung 19.40: Die Tabelle tblClients in der Entwurfsansicht

4. Verändern Sie Namen und Attribute der gewünschten Spalten. 5. Schließen Sie das Fenster und speichern Sie Ihre Änderungen, wenn Sie fertig sind. Das Erstellen von und die Arbeit mit Tabellen, Sichten, Datenbankdiagrammen und gespeicherten Prozeduren in SQL Server wird in »Microsoft SQL Server 7.0 in 21 Tagen« oder »Microsoft SQL Server 7.0 Kompendium«, beide als Markt&Technik-Bücher erschienen, ausführlich behandelt. Eine SQL Server-Tabelle löschen Das Löschen einer SQL Server-Tabelle ist ganz einfach: 1. Wählen Sie in der Objektliste den Eintrag TABELLEN. 2. Klicken Sie mit der rechten Maustaste auf die zu löschende Tabelle.

759

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

3. Wählen Sie im Kontextmenü LÖSCHEN. Sie müssen daran denken, dass die Tabelle durch das Löschen über den ADP aus der SQL Server-Datenbank entfernt wird. Die Einfachheit des Löschens einer SQL Server-Tabelle über ein ADP macht es außerdem notwendig, dass für die SQL ServerDatenbank eine angemessene Absicherung eingerichtet ist.

19.13.3 Mit SQL Server-Sichten arbeiten SQL Server-Sichten entsprechen Access-Auswahlabfragen. Der wesentliche Unterschied besteht darin, dass SQL Server-Sichten die Verwendung von Parametern nicht unterstützen. Eine SQL Server-Sicht erstellen 1. Wählen Sie in der Objektliste den Eintrag SICHTEN. 2. Doppelklicken Sie auf ERSTELLT EINE SICHT UNTER VERWENDUNG NERS. Danach wird das Sichtenfenster eingeblendet.

DES

DESIG-

3. Definieren Sie die Spalten, Kriterien und die übrigen Attribute der Sicht, wie im Abschnitt »Mit Sichten anstelle von Tabellen verknüpfen« dieses Kapitels beschrieben. Eine SQL Server-Sicht modifizieren Das Modifizieren einer Sicht verläuft ähnlich wie das Modifizieren einer Tabelle: 1. Wählen Sie in der Objektliste den Eintrag SICHTEN. 2. Markieren Sie die Sicht, deren Attribute Sie verändern wollen. 3. Klicken Sie auf ENTWURF. Der Entwurf der vorliegenden Sicht erscheint. 4. Modifizieren Sie die Attribute der Sicht. 5. Schließen Sie das Fenster und speichern Sie Ihre Änderungen, wenn Sie fertig sind. Eine SQL Server-Sicht löschen Das Löschen einer SQL Server-Sicht ist sehr einfach: 1. Wählen Sie in der Objektliste den Eintrag SICHTEN. 2. Klicken Sie mit der rechten Maustaste auf die zu löschende Sicht. 3. Wählen Sie im Kontextmenü LÖSCHEN. Wie bei Tabellen müssen Sie daran denken, dass die Sicht mit dem Löschen aus dem ADP auch aus der SQL Server-Datenbank entfernt wird. Dies unterstreicht wiederum, dass für die SQL Server-Datenbank eine angemessene Absicherung erforderlich ist.

760

Kapitel 19: Client-Server-Techniken

19.13.4 Mit Datenbankdiagrammen arbeiten Datenbankdiagramme bieten Ihnen eine visuelle Methode zum Entwerfen und Verwalten Ihrer Datenbanktabellen. Mit Hilfe eines Datenbankdiagramms lassen sich Tabellenbeziehungen einrichten und ändern und Tabellenstrukturen bearbeiten. Ein Datenbankdiagramm erstellen Um ein Datenbankdiagramm zu erstellen, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste den Punkt DATENBANKDIAGRAMME. 2. Doppelklicken Sie auf EIN DATENBANKDIAGRAMM UNTER VERWENDUNG DESIGNERS ERSTELLEN. Ein leeres Diagrammfenster erscheint.

DES

3. Klicken Sie auf TABELLE ANZEIGEN, um die Tabellen zu sehen, die in der mit dem ADP verknüpften SQL Server-Datenbank enthalten sind (siehe Abbildung 19.41).

Abbildung 19.41: Beim Anlegen eines Datenbankdiagramms beginnen Sie mit dem Einfügen von Tabellen in das leere Diagrammfenster

4. Klicken Sie auf die gewünschten Tabellen und ziehen Sie sie in das Datenbankdiagramm. 5. Um die Struktur einer Tabelle zu ändern, klicken Sie im Designer mit der rechten Maustaste auf die Tabelle und wählen SPALTENEIGENSCHAFTEN. Die im Datenbank-Designer geänderten Eigenschaften werden unmittelbar in der SQL Server-Datenbank geändert.

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

761

6. Um eine Beziehung zu verändern, klicken Sie mit der rechten Maustaste auf die Beziehungslinie und wählen EIGENSCHAFTEN. Dies ruft das Dialogfeld EIGENSCHAFTEN auf (siehe Abbildung 19.42). Dort können Sie alle Attribute einer bestehenden Beziehung verändern. 7. Um eine Beziehung hinzuzufügen, klicken Sie auf den Feldmarkierer und ziehen diesen von der einen Tabelle in die andere. Im Anschluss daran wird das Dialogfeld BEZIEHUNG ERSTELLEN eingeblendet (siehe Abbildung 19.43).

Abbildung 19.42: Im Fenster Eigenschaften können Sie die Attribute einer bestehenden Beziehung verändern

Ein Datenbankdiagramm verändern Um ein vorhandenes Datenbankdiagramm zu verändern, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste den Eintrag DATENBANKDIAGRAMME. 2. Markieren Sie das Datenbankdiagramm, dessen Attribute Sie verändern wollen. Abbildung 19.44 zeigt das mit dem Datenprojekt NorthwindCS verknüpfte Datenbankdiagramm, das zusammen mit Microsoft Access geliefert wurde. 3. Klicken Sie auf ENTWURF. Der Entwurf des Datenbankdiagramms erscheint. 4. Verändern Sie die Attribute des Datenbankdiagramms.

762

Kapitel 19: Client-Server-Techniken

Abbildung 19.43: Im Dialogfeld Beziehung erstellen können Sie die Eigenschaften einer neuen Beziehung festlegen

Abbildung 19.44: Im Datenbankdiagrammfenster können Sie Beziehungen zwischen Tabellen einrichten und die Struktur von Tabellen verändern

5. Schließen Sie das Fenster und speichern Sie Ihre Änderungen, wenn Sie fertig sind.

19.13.5 Mit gespeicherten Prozeduren arbeiten Das Erstellen und Verändern gespeicherter Prozeduren wird im Abschnitt »Gespeicherte Prozeduren erstellen und ausführen« dieses Kapitels erläutert. Sie sollten unbedingt beachten, dass gespeicherte Prozeduren zwar Sichten ähnlich sind, aber

Über ein Microsoft Access-Datenprojekt auf Client-Server-Daten zugreifen

763

zwei weitere Funktionsmerkmale besitzen, die in Sichten nicht zur Verfügung stehen: Gespeicherte Prozeduren können Parameter enthalten und deshalb zur Laufzeit Kriterien übernehmen und außerdem lassen sie sich so entwerfen, dass sie Tabellendaten bearbeiten können. Zwischen dem Ausführen einer Access-Aktionsabfrage für eine verknüpfte Tabelle und dem Ausführen einer gespeicherten Prozedur besteht ein wichtiger Unterschied. Bei einer Aktionsabfrage müssen alle von der Abfrage betroffenen Daten über die Netzwerkleitung transportiert werden, um mit Hilfe der Abfrage auf der Arbeitsstation aktualisiert zu werden. Eine gespeicherte Prozedur aktualisiert Daten dagegen direkt auf dem Server, ohne dass ein Transport der Daten über das Netzwerk erforderlich ist. Das kann zu größeren Leistungsunterschieden führen, insbesondere wenn es um große Datenmengen geht.

19.13.6 Formulare, Berichte, Makros und Module erstellen und damit arbeiten Das Erstellen von und die Arbeit mit Formularen, Berichten, Makros und Modulen in einer ADP-Datei ist der Arbeit mit entsprechenden Objekten in einer AccessDatenbank sehr ähnlich. Wichtig ist jedoch Folgendes: während die Tabellen, Sichten, Datenbankdiagramme und gespeicherten Prozeduren auf dem Server gespeichert sind, werden die Formulare, Berichte, Makros und Module als OLE-Dokumentteil in der ADP-Datei abgelegt. ADP-Dateien sind im Allgemeinen kleiner als MDB-Dateien und weniger anfällig für Beschädigungen!

19.13.7 Andere im Zusammenhang mit Access-Datenprojekten verfügbare Funktionen Neben der Möglichkeit, SQL Server-Tabellen, -Sichten, -Datenbankdiagramme und gespeicherte SQL Server-Prozeduren aus der Access-Umgebung heraus zu pflegen, bringen ADP-Dateien Ihnen weitere Vorteile. Von einer ADP-Datei aus lassen sich folgende Aufgaben erledigen:

 Anlegen von Sicherungskopien der SQL Server-Datenbank  Wiederherstellen der SQL Server-Datenbank  Replikation der SQL Server-Datenbank einschließlich der Möglichkeit, neue SQL Server-Publikationen zu erstellen, Replikate zu synchronisieren und Konflikte zu lösen.

 Pflege der SQL Server-Sicherheit

Client-Server-Strategien

Kapitel

Hier lesen Sie:

 Effizientes Vorgehen  Den günstigsten Typ für eine Datensatzgruppe wählen  Pass-Through-Abfragen und gespeicherte Prozeduren  Access-Datenprojekte  Den Umgang mit Daten optimieren  Abfragen und Formulare optimieren

20.1

Effizientes Vorgehen

Wie Sie im vorigen Kapitel gesehen haben, passiert es leicht, Client-Server-Strategien ineffizient zu implementieren. Das kann dazu führen, dass die Leistung schlechter statt besser wird. Es ist die Aufgabe des Entwicklers, die Techniken intelligent anzuwenden, mit der Client-Server-Systeme wirkungsvoll zum Einsatz kommen. Dieses Kapitel behandelt Strategien, die Ihnen bei der Entwicklung eleganter ClientServer-Anwendungen helfen.

20.2

Den günstigsten Typ für eine Datensatzgruppe wählen

Welchen Typ Sie für eine Datensatzgruppe wählen, wirkt sich deutlich auf die Leistung aus. Sowohl die Eigenschaften CursorType und LockType als auch der Parameter Options der Methode Open des Objekts Recordset bestimmen, welcher Typ Datensatzgruppe zurückgegeben wird.

766

20.2.1

Kapitel 20: Client-Server-Strategien

Die Eigenschaft CursorType

Die Eigenschaft CursorType bestimmt, welcher Cursor-Typ vom Objekt Recordset zurückgegeben wird. Folgende Optionen stehen zur Verfügung:

 adOpenForwardOnly  adOpenStatic  adOpenKeyset  adOpenDynamic Jeder dieser Cursor-Typen bietet eine andere Funktionalität und unterschiedliche Leistung. Was die Leistung betrifft, ist der Vorwärts-Cursor am besten geeignet, bietet jedoch die geringste Funktionalität. Es folgen der statische Cursor, der KeysetCursor und der dynamische Cursor. Was die Funktionalität betrifft, liegt der Vorwärts-Cursor auf dem letzten Platz. Es folgen der statische, der Keyset- und der dynamische Cursor. Wie bereits erwähnt, bietet der Vorwärts-Cursor die beste Leistung, aber die geringste Funktionalität. Wie der Name schon sagt, erlaubt er nur Vorwärtsbewegungen durch die Datensätze der Datensatzgruppe. Er eignet sich nur für Situationen, in der ein einziger Durchgang durch die Datensätze angemessen ist. Ein statischer Cursor erlaubt sowohl Vorwärts- als auch Rückwärtsbewegungen durch die Datensätze der Datensatzgruppe. Seine größte Einschränkung liegt darin, dass Änderungen durch andere Benutzer im Netzwerk (einschließlich Hinzufügen, Bearbeiten und Löschen) in der Datensatzgruppe nicht wiedergegeben werden. Obwohl ein statischer Cursor weniger effizient ist als ein Vorwärts-Cursor, liegt seine Effizienz deutlich über der eines Keyset- oder eines dynamischen Cursors. Das liegt daran, dass er sich nicht um die ständige Aktualisierung der Datenanzeige vom Server kümmern muss. Ein Keyset-Cursor bietet alles, was der statische Cursor auch hat. Außerdem sind Änderungen durch andere Benutzer in der Datensatzgruppe sichtbar. Von anderen Benutzern hinzugefügte Datensätze stehen aber in der Datensatzgruppe nicht zur Verfügung. Von anderen Benutzern gelöschte Datensätze erscheinen als »Löcher« in der Datensatzgruppe und der Zugriff ist nicht mehr möglich. Ein dynamischer Cursor bietet die größte Funktionalität, aber die niedrigste Leistung. Der Datensatzgruppe stehen nicht nur die Änderungen zur Verfügung, die andere Benutzer an den Daten vorgenommen haben, sondern auch hinzugefügte Datensätze und Löschungen. Es gibt eine sehr einfache Regel, die man bei der Auswahl eines Cursor-Typs befolgen sollte: Sie sollten den Cursor-Typ mit der höchsten Leistung wählen, der die benötigte Funktionalität bietet. Sie müssen sich wirklich überlegen, wie wichtig es ist, dass Sie die Änderungen sehen, die andere Benutzer vornehmen, und ob es erforderlich ist, sich vorwärts und rückwärts durch die Datensatzgruppe zu bewegen.

Den günstigsten Typ für eine Datensatzgruppe wählen

20.2.2

767

Die Eigenschaft LockType

Auch die Eigenschaft LockType kann die Leistung beeinflussen. Sie bestimmt, ob und wie sich die Daten der Datensatzgruppe aktualisieren lassen. Die Optionen lauten:

 adLockReadOnly  adLockPessimistic  adLockOptimistic  adLockBatchOptimistic Die wichtigste Differenzierung besteht zwischen der Schreibschutz-Option und den übrigen Optionen. Standardmäßig wird ein Datensatz nur zum Lesen geöffnet. Diese Option liefert die beste Leistung, weil die Aktualisierbarkeit der Datensatzgruppe kein Problem darstellt. Als wichtigstes müssen Sie sich merken, dass Sie die Schreibschutz-Option wählen sollten, wenn die Datensatzgruppe nicht aktualisiert werden muss.

20.2.3

Der Parameter Options der Methode Open

Der Parameter Options der Methode Open bestimmt, wie der Provider das Argument Source der Methode Open des Objekts Recordset auswerten soll. Folgende Wahlmöglichkeiten stehen für den Parameter Options zur Verfügung:

 adCmdText  adCmdTable  adCmdTableDirect  adCmdStoredProc  adCmdUnknown  adCmdFile  adAsyncExecute  adAsyncFetch  adAsyncFetchNonBlocking Es ist wichtig, dass schon die Angabe des Parameters Options Leistungsverbesserungen bewirkt. Das liegt daran, dass ADO nicht ermitteln muss, was im Argument Source steht. Bei der Auswahl des Parameters Options haben die Werte adCmdTable, adCmdTableDirect, adCmdStoredProc, adAsyncExecute, adAsyncFetch und adAsyncFetchNonBlokking den größten Einfluss auf die Leistung. Die Optionen adCmdTable und adCmdTableDirect wirken sich negativ aus, weil beide alle Zeilen der im Argument Source genannten Tabelle zurückgeben. Das kann bei umfangreichen Tabellen in einer Client-Server-Umgebung direkte Konsequenzen haben. Diese Werte unterminieren genau

768

Kapitel 20: Client-Server-Strategien

genommen den wesentlichen Grund dafür, warum eine Anwendung in einer ClientServer-Umgebung installiert wurde. Die Option adCmdStoredProc stellt einfach deshalb eine ausgezeichnete Wahl dar, weil sie vorschreibt, dass die Quelle ausgewertet und als gespeicherte Prozedur auf dem Server ausgeführt wird. Die Option adAsyncExecute gibt an, dass die Quelle asynchron ausgeführt wird, d.h. dass andere Operationen weiterlaufen können, während die Datensätze geholt werden. Die Option adAsyncFetch kann je nach Situation die Leistung steigern oder verringern. Sie legt fest, dass Zeilen, die verbleiben, nachdem die in der Eigenschaft Initial Fetch Size angegebene Anzahl Datensätze geholt wurde, asynchron geholt werden. Das Problem liegt darin, dass der Haupt-Thread, wenn eine angeforderte Zeile nicht verfügbar ist, blockiert wird, bis diese Zeile geholt ist. Die Option adAsyncFetchNonBlocking schließlich stellt sicher, dass der Haupt-Thread in keinem Fall blockiert wird. Wenn die angeforderte Zeile nicht verfügbar ist, rückt die aktuelle Zeile an das Dateiende.

20.3

Pass-Through-Abfragen und gespeicherte Prozeduren

Sie sollten unbedingt daran denken, dass die Ausführung von Pass-Through-Abfragen und gespeicherten Prozeduren erheblich effizienter ist als die Rückgabe einer Datensatzgruppe zur Verarbeitung in Access. Pass-Through-Abfragen und die Einzelheiten ihrer Implementierung werden in Kapitel 19 behandelt. Pass-ThroughAbfragen unterscheiden sich durch den Ort der Verarbeitung. Bei Pass-ThroughAbfragen und gespeicherten Prozeduren findet die gesamte Verarbeitung auf dem Server statt. Wenn Operationen mit Hilfe von VBA-Code ausgeführt werden, müssen alle von diesem Vorgang betroffenen Datensätze auf die Arbeitsstation des Benutzers übertragen, verändert und dann an den Server zurückgegeben werden. Dadurch wird eine erhebliche Menge Netzwerkverkehr erzeugt und die Verarbeitung gewaltig gebremst.

20.4

Access-Datenprojekte

»Access-Datenprojekte« (.ADP-Dateien) ermöglichen den Zugriff auf Microsoft SQL Server-Daten, ohne die Jet-Datenbank-Engine von Microsoft Jet zu laden. Sie liefern durch Beseitigung der Engpässe, welche die Jet-Engine verursacht, eindrucksvolle Leistungssteigerungen. Datenanforderungen gehen direkt an Microsoft SQL Server, anstatt von Jet analysiert und übersetzt zu werden. Access-Datenprojekte werden in Kapitel 19 ausführlich beschrieben. Die durch sie gewonnene Leistung ist möglicherweise erforderlich, damit Sie in einer Anwendung, die Microsoft SQL ServerDaten verwendet, eine zufriedenstellende Leistung erzielen. Außerdem können Sie mit Hilfe von Access-Datenprojekten die mit einer Microsoft SQL Server-Datenbank verknüpften Tabellen, Ansichten, Datenbankdiagramme und gespeicherten

Den Umgang mit Daten optimieren

769

Prozeduren mühelos verwalten. Der wesentliche Nachteil der Datenprojekte liegt darin, dass sie nur zum Zugriff auf Microsoft SQL Server-Datenbanken eingesetzt werden können.

20.5

Den Umgang mit Daten optimieren

Das beste, was Sie zur Optimierung des Umgangs mit Daten – z.B. Bearbeiten, Einfügen und Löschen – tun können, ist das Einfügen eines Versionsfeldes (einer Zeitmarke) in jede entfernte Tabelle. Dieses Versionsfeld wird genutzt, wenn Benutzer die Daten der entfernten Tabelle aktualisieren, um Überschreibkonflikte zu vermeiden. Wenn es nicht vorhanden ist, vergleicht der Server alle Felder, um festzustellen, ob sie sich verändert haben, nachdem der Benutzer mit der Bearbeitung des Datensatzes begonnen hat. Das ist ziemlich ineffizient und wesentlich langsamer als die Auswertung einer Zeitmarke.

20.6

Abfragen und Formulare optimieren

Im Großen und Ganzen verbessert der Umstieg auf die Client-Server-Technologie die Leistung. Wenn Sie beim Entwurf Ihrer Abfragen, Formulare und Berichte nicht sorgfältig arbeiten, kann er die Leistung jedoch vermindern. Sie können einiges tun, um sicherzustellen, dass der Umstieg vorteilhaft ausfällt. Die zur Verfügung stehenden Techniken gliedern sich in abfragebezogene und formularbezogene Verfahrensweisen.

20.6.1

Abfragen optimieren

Server können viele der Funktionen, die der Access-Abfrage-Editor bietet, nicht ausführen. Die Funktionen, die auf dem Server nicht verfügbar sind, werden auf der Arbeitsstation erledigt. Das führt häufig dazu, dass große Datenmengen über das Netzwerk transportiert werden. Sie können diesen zusätzlichen Verkehr ausschalten, indem Sie Ihre Abfragen so gestalten, dass sie vom Server allein bewältigt werden. Es folgen einige Beispiele für problematische Abfragen, die sich auf dem Server nicht ausführen lassen:

 Top-N-Prozentabfragen  Abfragen mit benutzerdefinierten oder Access-Funktionen  Abfragen, die Tabellen aus zwei unterschiedlichen Datenquellen betreffen – z.B. eine Abfrage, die Tabellen von zwei Servern oder eine Access- und eine ServerTabelle verknüpft (einen Join aus diesen Tabellen bildet)

770

Kapitel 20: Client-Server-Strategien

Sowohl Top-N-Abfragen als auch heterogene Verknüpfungen werden von Microsoft SQL Server 7.0 unterstützt.

20.6.2

Formulare optimieren

Sie können die Techniken dieses Abschnitts verwenden, um Formulare zu entwerfen, die die Vorteile der Client-Server-Architektur nutzen. Die Idee besteht darin, Formulare so zu entwerfen, dass sie die minimal erforderliche Datenmenge vom Server anfordern und nur dann zusätzliche Daten bekommen, wenn der Benutzer dies verlangt. Das bedeutet, dass Sie möglichst wenige Datensätze und Felder vom Server anfordern. Sie können das erreichen, indem Sie als Grundlage für Formulare Abfragen anstelle der Tabellen selbst verwenden. Außerdem lässt sich der Prozess dadurch weiter verfeinern, dass Sie Ihre Formulare mit einem speziellen Blick auf die Datenbeschaffung entwerfen. Ein Formular lässt sich beispielsweise zunächst auch ohne Datenquelle öffnen. Es kann verlangen, dass der Benutzer die Kriterien einschränkt, bevor überhaupt Datensätze angezeigt werden. Statische Tabellen, wie zum Beispiel eine Tabelle der Bundesstaaten, sollten lokal gespeichert werden. Dadurch werden Netzwerkverkehr und Anforderungen beim Server reduziert. Außerdem sollten Sie Kombinations- und Listenfelder nicht auf der Grundlage von Server-Daten einrichten. Die Zeilenquelle für Kombinations- und Listenfelder sollte, wo immer möglich, auf lokalen statischen Tabellen basieren. Wenn dies nicht möglich ist, können Sie ein Textfeld mit einem Kombinationsfeld verwenden. Die Zeilenquelle des Kombinationsfeldes bleibt zunächst leer. Der Benutzer muss die ersten Buchstaben in das Textfeld eingeben. Dann wird die Zeilenquelle des Kombinationsfeldes auf eine Select-Anweisung aufgebaut, welche die eingegebenen Zeichen verwendet. Auch OLE-Objekt- und Memo-Felder sind umfangreich und vermehren den Netzwerkverkehr deshalb beträchtlich. Am besten wird der Inhalt dieser Felder nur angezeigt, wenn er vom Benutzer ausdrücklich verlangt wird. Sie erreichen dies, indem Sie die Eigenschaft Sichtbar von OLE- und Memo-Feldern auf False setzen oder diese Felder auf eine andere Seite des Formulars verlegen. Sie können eine Schaltfläche hinzufügen, über die die Benutzer die Anzeige der zusätzlichen Daten erreichen können. Abbildung 20.1 zeigt ein Formular, das die Implementierung einiger der genannten Methoden veranschaulicht. Der Detailbereich des Formulars ist zunächst nicht sichtbar. Das Formular hat keine Datenherkunft und die Daten, die dem im Formular angezeigten Kombinationsfeld zu Grunde liegen, sind in einer lokalen Tabelle gespeichert.

771

Abfragen und Formulare optimieren

Das Ereignis AfterUpdate des Kombinationsfeldes sieht folgendermaßen aus: Private Sub cboBookType_AfterUpdate() Me.RecordSource = "Select * From dbo_titles Where Type Like '" & _ cboBookType.Value & "*';" Me.Detail.Visible = True End Sub

Abbildung 20.1: Ein Formular, das mit Hilfe des Ereignisses AfterUpdate des Kombinationsfeldes die Datenherkunft (RecordSource) festlegt und Details sichtbar macht

Die Eigenschaft Sichtbar (Visible) des Detailbereichs des Formulars ist auf False gesetzt. Nachdem der Benutzer im Kombinationsfeld einen Eintrag ausgewählt hat, wird die Eigenschaft RecordSource des Formulars auf eine Select-Anweisung gesetzt, die aus der Datenbanktabelle dbo_titles bestimmte Titel auswählt. Dann wird der Detailbereich des Formulars sichtbar gemacht, wie in Abbildung 20.2 gezeigt. Schließlich wollen Sie möglicherweise ungebundene Formulare verwenden. Das schließt das Erstellen eines Formulars ein, dessen RecordSource-Eigenschaft dann gelöscht wird. Die Benutzer sehen ein Kombinationsfeld, in dem sie einen Datensatz auswählen können. Aus den Client-Server-Daten wird eine Datensatzgruppe mit dem ausgewählten Datensatz erstellt. Bei dieser Methode des Formularentwurfs muss alles im Code festgelegt werden. Ihr Formular muss alle Hinzufüge-, Bearbeitungs- und Löschoperationen erledigen. Abbildung 20.3 zeigt ein Beispiel eines solchen Formulars. Bei keinem der dort vorhandenen Steuerelemente ist die Steuerelementquelle ausgefüllt. Der Name der einzelnen Steuerelemente entspricht einem Feld in der Datenbanktabelle auf dem Server.

772

Kapitel 20: Client-Server-Strategien

Abbildung 20.2: Ein Formular, das bei sichtbarem Detailbereich mit Hilfe des Ereignisses AfterUpdate des Kombinationsfeldes die Datenherkunft festlegt

Abbildung 20.3: Ein ungebundenes Formular

Das Ereignis Open des Formulars sieht folgendermaßen aus: Private Sub Form_Open(Cancel As Integer) Set mrst = New ADODB.Recordset Me.txtTitle.SetFocus End Sub

Abfragen und Formulare optimieren

773

Dieser Code setzt eine Datenbankvariable auf Modulebene auf die aktuelle Datenbank und übergibt den Fokus an das Textfeld txtTitle. Das Ereignis AfterUpdate des Textfeldes sieht folgendermaßen aus: Private Sub txtTitle_AfterUpdate() Me!cboTitle.RowSource = "SELECT DISTINCTROW [dbo_titles].[title_id] " _ & "FROM [dbo_titles] " _ & "WHERE [dbo_titles].[title_id] Like '" & Me!txtTitle.Text & "*';" End Sub

Dieser Code setzt die Eigenschaft RowSource des Kombinationsfeldes auf eine SelectAnweisung, die alle Datensätze der Titeltabelle auswählt, deren Feld Title_ID mit den Buchstaben beginnt, die der Benutzer eingegeben hat. Auf diese Weise erscheinen im Kombinationsfeld nicht alle Titel vom Server. Das Ereignis AfterUpdate des Kombinationsfeldes sieht folgendermaßen aus: Private Sub cboTitle_AfterUpdate() Dim boolSuccess As Boolean mrst.ActiveConnection = CurrentProject.Connection mrst.Open "Select * From dbo_Titles " _ & "WHERE Title_ID = '" & Me!cboTitle.Value & "';" boolSuccess = PopulateForm(Me, mrst) If Not boolSuccess Then MsgBox "Record Not Found" End If End Sub

Mit Hilfe der Methode Open wird eine Datensatzgruppe auf der Grundlage der verknüpften Tabelle dbo_titles geöffnet. Beachten Sie, dass nur die Datensätze mit der passenden Title_ID geholt werden. Da dieses Feld den Primärschlüssel darstellt, wird nur ein Datensatz zurückgegeben. Dann wird die Funktion PopulateForm aufgerufen, wie Sie hier sehen: Function PopulateForm(frmAny As Form, rstAny As ADODB.Recordset) Dim fld As ADODB.Field If rstAny.EOF Then PopulateForm = False Else For Each fld In rstAny.Fields frmAny(fld.Name) = fld Next fld PopulateForm = True End If End Function

774

Kapitel 20: Client-Server-Strategien

Die Funktion PopulateForm prüft, ob die übergebene Datensatzgruppe Datensätze enthält. Dann geht sie jedes Feld des Formulars durch und vergleicht die Feldnamen mit den Steuerelementen im Formular. Der Wert der einzelnen Steuerelemente wird auf den Wert des Feldes in der Datensatzgruppe gesetzt, das denselben Namen wie das Steuerelement trägt. Beachten Sie, dass diese Änderungen an den Daten des Formulars nicht die Daten auf dem Datenbank-Server aktualisieren. Außerdem sieht das Formular weder Einfügungen noch Löschungen vor. Sie müssen Code schreiben, um aktualisieren, einfügen und löschen zu können, und Sie müssen Schaltflächen bereitstellen, um Ihren Benutzern Zugriff auf diese Funktionalität zu gewähren. Beide Techniken lassen sich sowohl in Verbindung mit verknüpften Tabellen als auch in Verbindung mit Access-Datenprojekten einsetzen. Die Vorteile sind bei Access-Datenprojekten am größten.

20.6.3

Für die Praxis

Client-Server-Strategien anwenden Nehmen Sie an, dass die Tabelle Employees voraussichtlich in Kürze auf einen Datenbank-Server verschoben werden soll, weil sie vertrauliche Daten enthält. Deshalb müssen Sie das Formular Employees mit Rücksicht auf die Client-Server-Architektur entwerfen. Das Formular beschränkt die darin angezeigten Daten. Es wird mit nur einer Optionsgruppe geöffnet, welche die Buchstaben des Alphabets enthält, wie in Abbildung 20.4 gezeigt. Nachdem der Benutzer einen Buchstaben ausgewählt hat, wird der Detailbereich des Formulars eingeblendet und die RecordSource-Eigenschaft des Formulars mit einer Select-Anweisung gefüllt, wie Abbildung 20.5 zeigt.

Das Ereignis Open des Formulars sieht folgendermaßen aus: Private Sub Form_Open(Cancel As Integer) Me.Detail.Visible = False End Sub

Abbildung 20.4: Das Formular Employees mit einer Optionsgruppe zur Auswahl des Nachnamens des Beschäftigten

775

Abfragen und Formulare optimieren

Abbildung 20.5: Die Vollansicht des Formulars Employees

Die Eigenschaft VISIBLE des Detailbereichs des Formulars wird auf False gesetzt. Das Ereignis AfterUpdate der Optionsgrupe sieht folgendermaßen aus: Private Sub optEmpName_AfterUpdate() Me.RecordSource = "Select * from tblEmployees Where LastName Like '" _ & Chr$(Me![optEmpName].Value) & "*';" Me.NavigationButtons = True Me.Detail.Visible = True DoCmd.DoMenuItem acFormBar, 7, 6, , acMenuVer70 End Sub

Dieser Code legt die RecordSource-Eigenschaft des Formulars mit Hilfe einer SelectAnweisung fest und macht die Schaltflächen zum Bewegen und den Detailbereich des Formulars sichtbar. Schließlich passt es die Fenstergröße der Formulargröße an.

Eine Client-ServerAnwendung in Aktion

Kapitel

Hier lesen Sie:

 Zum Gesamtzusammenhang  Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen  Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

21.1

Zum Gesamtzusammenhang

Häufig ist es schwierig, die in einem Buch dargestellten Techniken in einem Gesamtzusammenhang zu sehen. Dieses Kapitel zeigt Ihnen, wie viele der in Kapitel 19 und Kapitel 20 behandelten Client-Server-Techniken angewandt werden.

21.2

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

Eine Möglichkeit für die Erstellung einer Client-Server-Anwendung ist die Verwendung verknüpfter Tabellen. Dies kann, wenn es richtig gemacht wird, eine sehr gute Lösung sein. Ein Überblick über die zum Aufbau einer Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erforderlichen Schritte enthält folgende Punkte: 1. Stellen Sie eine Verknüpfung mit den in der SQL Server-Datenbank enthaltenen Tabellen her. 2. Erstellen Sie ein Formular, welches Registerkarten für Kunden, Bestellungen und Bestelldetails enthält. 3. Fügen Sie ein Kombinationsfeld hinzu, mit dem der Benutzer Daten einer bestimmten Firma suchen kann.

778

Kapitel 21: Eine Client-Server-Anwendung in Aktion

4. Erstellen Sie eine Abfrage, mit deren Hilfe der Detailbereich des Formulars ausgefüllt wird. Die Abfrage holt nur Daten für den ausgewählten Kunden. 5. Erstellen Sie eine Abfrage, mit deren Hilfe der Detailbereich des Unterformulars für Bestellungen ausgefüllt wird. 6. Erstellen Sie eine Abfrage, mit deren Hilfe der Detailbereich des Unterformulars für Bestelldetails ausgefüllt wird. 7. Blenden Sie die Unterformulare für Bestellungen und Bestelldetails aus, bis die entsprechende Registerkarte ausgewählt wird. 8. Geben Sie für die Unterformulare leere Datenquellen an. 9. Bestimmen Sie die Datensatzquelle für die Unterformulare und machen Sie die Unterformulare nur dann sichtbar, wenn die entsprechende Registerkarte gewählt wird. Die folgenden Abschnitte liefern Ihnen die Einzelheiten der einzelnen Schritte zur Erstellung der Anwendung.

21.2.1

Eine Verknüpfung mit Dateien in der SQL Server-Datenbank erstellen

Da diese Version der Anwendung verknüpfte Tabellen enthält, besteht der erste Schritt darin, eine Verknüpfung zu den Tabellen einzurichten, welche die Anwendung verwendet. Das Beispiel benutzt die SQL Server-Version der Datenbank Northwind. (In Access liegt diese Datenbank in der deutschen Version vor.) Unternehmen Sie Folgendes, um Verknüpfungen mit den Tabellen der Datenbank Northwind einzurichten: 1. Klicken Sie mit der rechten Maustaste im Datenbankfenster und wählen Sie TABELLEN VERKNÜPFEN. Dadurch wird das Dialogfeld VERKNÜPFEN aufgerufen. 2. Wählen Sie in der Liste DATEITYP den Eintrag ODBC-DATABASES (). Sie gelangen in das Dialogfeld DATENQUELLE AUSWÄHLEN. 3. Klicken Sie auf die Registerkarte COMPUTERDATENQUELLE (siehe Abbildung 21.1). 4. Klicken Sie auf NEU, um eine neue Datenquelle zu erstellen. Es erscheint das Dialogfeld NEUE DATENQUELLE ERSTELLEN (siehe Abbildung 21.2). 5. Wählen Sie SYSTEMDATENQUELLE und klicken Sie auf WEITER. 6. Wählen Sie in der Treiberliste den Treiber für SQL Server (siehe Abbildung 21.3). Klicken Sie auf WEITER. 7. Klicken Sie auf FERTIG STELLEN. Sie gelangen jetzt in das Dialogfeld NEUE DATENQUELLE FÜR SQL SERVER ERSTELLEN (siehe Abbildung 21.4).

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

779

Abbildung 21.1: Auf der Registerkarte Computerdatenquelle können Sie eine Datenquelle für den Rechner wählen

Abbildung 21.2: Der Assistent zum Erstellen neuer Datenquellen führt Sie durch die einzelnen Schritte der Erstellung

8. Geben Sie einen Namen und optional eine Beschreibung für die Datenquelle ein. 9. Wählen Sie den SQL-Server aus, zu dem Sie eine Verbindung erstellen wollen. Klicken Sie auf WEITER. 10. Markieren Sie die gewünschten Sicherheitsoptionen und klicken Sie auf WEITER (siehe Abbildung 21.5).

780

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.3: Wählen Sie in der Liste der verfügbaren Treiber den Treiber für SQL Server

Abbildung 21.4: Das Dialogfeld Neue Datenquelle für SQL Server erstellen führt Sie durch die einzelnen Schritte der Erstellung einer neuen SQL Server-Datenquelle

11. Wählen Sie die passenden Datenbankoptionen. Dazu gehört, wie gespeicherte Prozeduren ausgeführt und wie Anführungszeichen und Nullwerte behandelt werden sollen. Klicken Sie auf WEITER (siehe Abbildung 21.6). 12. Ändern Sie die übrigen Optionen und klicken Sie auf FERTIG STELLEN. 13. Eine Liste der gewählten Optionen wird angezeigt (siehe Abbildung 21.7). Klicken Sie auf DATENQUELLE TESTEN, um die neue Datenquelle zu testen. Sie sollten die Meldung bekommen, dass der Test erfolgreich abgeschlossen wurde. 14. Klicken Sie auf OK, um das Testdialogfeld zu schließen. Klicken Sie noch einmal auf OK, um das Dialogfeld ODBC MICROSOFT SQL SERVER-SETUP zu schließen. Damit kehren Sie zum Dialogfeld DATENQUELLE AUSWÄHLEN zurück.

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

781

Abbildung 21.5: Geben Sie die gewünschten Absicherungsoptionen für die Datenbank ein

15. Markieren Sie die Datenquelle, die Sie gerade erstellt haben, und klicken Sie auf OK. Sie werden aufgefordert, sich beim SQL-Server anzumelden (siehe Abbildung 21.8). Geben Sie eine gültige Anmelde-ID und ein Kennwort ein, und klicken Sie auf OK. Daraufhin wird das Dialogfeld TABELLEN VERKNÜPFEN eingeblendet (siehe Abbildung 21.9).

Abbildung 21.6: Wählen Sie die passenden Datenbankoptionen

16. Klicken Sie auf jede Tabelle, die Sie in die Verknüpfung einbeziehen wollen, um sie zu markieren. Wenn Sie fertig sind, klicken Sie auf OK. Das Datenbankfenster wird mitsamt den eingerichteten Verknüpfungen eingeblendet, wie Sie in Abbildung 21.10 sehen.

782

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.7: Klicken Sie auf Datenquelle testen, um die Datenquelle mit den aufgeführten Optionen zu testen

Abbildung 21.8: Im Dialogfeld SQL Server-Login können Sie sich beim SQL-Server anmelden

Abbildung 21.9: Im Dialogfeld Tabellen verknüpfen können Sie die SQL ServerTabellen bestimmen, zu denen eine Verknüpfung eingerichtet werden soll

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

783

Abbildung 21.10: Das Datenbankfenster mit Verknüpfungen zur Datenbank Northwind

21.2.2

Das Kundenformular

Das Formular, das Sie aufbauen sollen, sehen Sie in Abbildung 21.11. Beachten Sie, dass zunächst keine Daten erscheinen. Das Formular wurde so gestaltet, dass es nur jeweils einen Datensatz anzeigt. Dies wird dadurch erreicht, dass es auf einer Abfrage basiert, die nur Daten für den Kunden holt, der im Kombinationsfeld SELECT A COMPANY ausgewählt wurde. Außerdem werden die Daten für die Registerkarten ORDERS und ORDER DETAILS erst geholt, wenn diese gewählt werden. Dadurch wird gewährleistet, dass Datensätze auf der n-Seite der 1:n-Beziehung erst geholt werden, wenn dies tatsächlich erforderlich wird.

Abbildung 21.11: Das vollständige Kundenformular erscheint zunächst ohne Daten

784

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Um mit dem Entwurf des Formulars frmCustomer zu beginnen, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste des Datenbankfensters den Eintrag FORMULARE. 2. Doppelklicken Sie auf ERSTELLT EIN FORMULAR IN DER ENTWURFSANSICHT. 3. Wählen Sie ANSICHT|FORMULARKOPF/-FUSS, um eine Kopf- und eine Fußzeile in das Formular einzufügen. Ein Kombinationsfeld zum Suchen in das Formular einfügen Der erste zum Aufbau des Formulars erforderliche Schritt ist das Einfügen eines Kombinationsfeldes, mit dessen Hilfe der Benutzer die Firma auswählen kann, deren Informationen er einsehen möchte. Dieses wird mit der CustomerID und dem CompanyName aller Firmen aus der Firmentabelle gefüllt. Wenn im Kombinationsfeld eine Firma markiert wird, wird das Formular durch eine neue Abfrage aktualisiert, so dass es die Daten für den gewählten Kunden anzeigt. Erstellen Sie das Kombinationsfeld mit Hilfe des Assistenten für Kombinationsfelder, indem Sie wie folgt vorgehen: 1. Achten Sie darauf, dass das Werkzeug STEUERELEMENT-ASSISTENTEN in der Toolbox aktiviert ist. 2. Wählen sie in der Toolbox das Werkzeug KOMBINATIONSFELD und klicken Sie dann auf die Stelle in der Kopfzeile des Formulars, an der das Kombinationsfeld erscheinen soll. Dies startet den Kombinationsfeld-Assistenten. 3. Markieren Sie die Option DAS KOMBINATIONSFELD SOLL DIE WERTE EINER TABELLE ODER ABFRAGE ENTNEHMEN. Klicken Sie anschließend auf WEITER. 4. Wählen Sie in der Liste der Tabellen die (verknüpfte) Tabelle dbo_Customers (siehe Abbildung 21.12). Klicken Sie auf WEITER.

Abbildung 21.12: Wählen Sie in der Liste der verfügbaren Tabellen die Tabelle dbo_Customers aus

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

785

5. Wählen Sie aus der Liste der verfügbaren Felder die Felder CustomerID und CompanyName aus (siehe Abbildung 21.13). Klicken Sie dann auf WEITER.

Abbildung 21.13: Wählen Sie die Felder CustomerID und CompanyName als Felder für das Kombinationsfeld aus

6. Doppelklicken Sie an der rechten Seite der Spalte CompanyName, um die Spalte an den längsten Eintrag anzupassen (siehe Abbildung 21.14). Lassen Sie die Option SCHLÜSSELSPALTE AUSBLENDEN aktiviert. Klicken Sie auf WEITER.

Abbildung 21.14: Doppelklicken Sie an der rechten Seite der Spalte CompanyName, um die Spalte an den längsten Eintrag anzupassen

7. Geben Sie als Beschriftung für das Kombinationsfeld »Select a Company« ein. Klicken Sie auf FERTIG STELLEN. Das Kombinationsfeld wird in das Formular eingefügt (siehe Abbildung 21.15).

786

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.15: Das Kombinationsfeld wird in das Formular eingefügt

8. Wählen Sie das hinzugefügte Kombinationsfeld aus, indem Sie es anklicken. 9. Ändern Sie den Namen des Kombinationsfeldes in cboSelectCompany. 10. Speichern Sie das Formular als frmCustomer. 11. Testen Sie das Formular, um sicherzustellen, dass das Kombinationsfeld eine Liste aller Kunden anzeigt (siehe Abbildung 21.16). Die Abfrage für das Kundenformular erstellen Der nächste Schritt ist der Entwurf der Abfrage, die dem Formular frmCustomer zu Grunde liegt. Die Abfrage verweist auf das Feld CustomerID des Kunden, der im Kombinationsfeld cboSelectCompany ausgewählt ist. Es folgen die einzelnen Schritte: 1. Kehren Sie in die Entwurfsansicht zurück, falls nötig. 2. Markieren Sie das Formular. 3. Klicken Sie im Eigenschaftenfenster auf die Registerkarte DATEN. 4. Klicken Sie in das Eigenschaftsfeld DATENHERKUNFT (siehe Abbildung 21.17). 5. Klicken Sie auf die Schaltfläche mit den drei Punkten. Dadurch wird das Dialogfeld TABELLE ANZEIGEN eingeblendet. 6. Markieren Sie in der Liste der Tabellen die Tabelle dbo_Customers (siehe Abbildung 21.18). Klicken Sie auf HINZUFÜGEN. 7. Klicken Sie auf SCHLIESSEN.

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

787

Abbildung 21.16: Das vollständige Kombinationsfeld zeigt eine Liste aller Kunden an

8. Fügen Sie die Felder CustomerID, CompanyName, ContactName, ContactTitle, Address, City, Region, PostalCode, Phone und Fax in die Abfrage ein (siehe Abbildung 21.19).

Abbildung 21.17: Die Eigenschaft Datenherkunft ermöglicht das Festlegen der Datensatzquelle für das Formular

788

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.18: Markieren Sie im Dialogfeld Tabellen anzeigen die Tabelle dbo_Customers

Abbildung 21.19: Fügen Sie die gewünschten Felder in die Abfragetabelle ein

9. Geben

Sie

für

das

Feld

CUSTOMERID

als

Kriterium

Forms!frmCusto-

mer!CBOSELECTCOMPANY ein (siehe Abbildung 21.20).

Abbildung 21.20: Auswahlkriterien für das Feld CustomerID

10. Schließen Sie den SQL-Anweisungseditor.

789

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

11. Klicken Sie auf Ja, weil Sie die Änderungen an der SQL-Anweisung speichern und die Eigenschaft aktualisieren wollen. Bevor Sie die Felder in das Formular einfügen können, müssen Sie die Registerkarten für das Formular entwerfen. Unternehmen Sie dazu Folgendes: 1. Klicken Sie auf das Registersteuerelement in der Toolbox. 2. Klicken Sie auf die Stelle im Formular frmCustomers, an der das Steuerelement erscheinen soll, um es einzufügen. 3. Ändern Sie die Eigenschaft Beschriftung der ersten Registerkarte auf Customers. 4. Ändern Sie die Eigenschaft Name der ersten Registerkarte auf pagCustomers. 5. Ändern Sie die Eigenschaft Beschriftung der zweiten Registerkarte auf Orders. 6. Ändern Sie die Eigenschaft Name der zweiten Registerkarte auf pagOrders. 7. Klicken Sie mit der rechten Maustaste auf das Registersteuerelement und wählen Sie SEITE EINFÜGEN. Eine dritte Seite erscheint. 8. Ändern Sie die Eigenschaft Beschriftung der dritten Registerkarte auf Order Details. 9. Ändern Sie die Eigenschaft Name der dritten Registerkarte auf pagOrderDetails. 10. Ändern Sie die Eigenschaft Name des Registersteuerelements auf tabDataEntry. 11. Fügen Sie die Felder wie in Abbildung 21.21 gezeigt in die Registerkarte CUSTOMERS des Formulars ein. Die Abfrage für das Unterformular Orders erstellen Der nächste Schritt ist die Erstellung der Abfrage, die dem Unterformular Orders zu Grunde liegt. Diese wählt alle Bestellungen aus, bei denen die CustomerID die des Kunden ist, der im Kombinationsfeld cboSelectCompany markiert ist. Um die Abfrage zu erstellen, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste des Datenbankfensters den Eintrag ABFRAGEN. 2. Doppelklicken Sie auf ERSTELLT EINE NEUE ABFRAGE IN DER SICHT. Das Dialogfeld TABELLEN ANZEIGEN wird eingeblendet.

ENTWURFSAN-

3. Markieren Sie in der Liste der Tabellen die Tabelle dbo_Orders und klicken Sie auf HINZUFÜGEN. 4. Klicken Sie auf SCHLIESSEN. 5. Fügen Sie die Felder OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia und Freight in die Abfrage ein. 6. Geben Sie für das Feld CustomerID als Kriterium Forms!frmCustomer!cboSelectCompany ein.

790

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.21: Die Registerkarte Customers nach dem Einfügen der ausgewählten Felder

7. Speichern Sie die Abfrage unter dem Namen qryOrders. Die vollständige Abfrage erscheint in Abbildung 21.22.

Abbildung 21.22: Die vollständige Abfrage qryOrders

Die Abfrage für das Unterformular OrderDetails erstellen Der nächste Schritt ist die Erstellung der Abfrage, die dem Unterformular OrderDetails zu Grunde liegt. Diese wählt alle Bestelldetails aus, bei denen die OrderID die ID der Bestellung ist, die im Unterformular fsubOrders markiert wurde. Um die Abfrage zu erstellen, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste des Datenbankfensters den Eintrag ABFRAGEN. 2. Doppelklicken Sie auf ERSTELLT EINE NEUE ABFRAGE IN DER SICHT. Das Dialogfeld TABELLEN ANZEIGEN wird eingeblendet.

ENTWURFSAN-

3. Markieren Sie in der Liste der Tabellen die Tabelle dbo_OrderDetails und klicken Sie auf HINZUFÜGEN.

791

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

4. Klicken Sie auf SCHLIESSEN. 5. Fügen Sie die Felder OrderID, ProductID, UnitPrice, Quantity und Discount in die Abfrage ein. 6. Geben Sie für das Feld ORDERID als Kriterium Forms!frmCustomer.Form!fsubOrders!OrderID ein. 7. Speichern Sie die Abfrage unter dem Namen qryOrderDetails. Die vollständige Abfrage erscheint in Abbildung 21.23.

Abbildung 21.23: Die vollständige Abfrage qryOrderDetails

Das Unterformular fsubOrders erstellen Das Unterformular fsubOrders dient zur Anzeige der mit den ausgewählten Kunden verknüpften Bestellungen. Unternehmen Sie Folgendes, um das Unterformular zu erstellen und es in die Seite ORDERS des Registerkartensteuerelements einzufügen: 1. Aktivieren Sie das Formular frmCustomer in der Entwurfsansicht. 2. Markieren Sie mit einem Klick die Seite ORDERS des Registersteuerelements. 3. Vergewissern Sie sich, dass das Werkzeug STEUERELEMENT-ASSISTENTEN aktiv ist. 4. Wählen Sie das Steuerelement UNTERFORMULAR/UNTERBERICHT. 5. Klicken Sie an der Stelle auf die Registerkarte ORDERS, an der Sie das Steuerelement einfügen möchten. Dadurch gelangen Sie in den Unterformular-Assistenten (siehe Abbildung 21.24). 6. Markieren Sie BEREITS VORHANDENE TABELLEN und klicken Sie auf WEITER.

UND

ABFRAGEN

VERWENDEN

7. Markieren Sie im aufklappbaren Listenfeld TABELLEN/ABFRAGEN den Eintrag qryOrders. 8. Fügen Sie alle Felder der Abfrage in die Liste AUSGEWÄHLTE FELDER ein (siehe Abbildung 21.25). 9. Klicken Sie auf WEITER.

792

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.24: Der Unterformular-Assistent hilft Ihnen beim Einfügen des Unterformulars Orders in die Registerkarte Orders

10. Wählen Sie KEINE als Verknüpfung zwischen Haupt- und Unterformular (siehe Abbildung 21.26) und klicken Sie auf WEITER. 11. Geben Sie fsubOrders als Namen des Unterformulars ein und klicken Sie auf FERTIG STELLEN. 12. Legen Sie die Größe des Unterformulars so fest, dass es aussieht wie in Abbildung 21.27. Das Unterformular fsubOrderDetail erstellen Das Unterformular fsubOrderDetails wird verwendet, um die mit der markierten Bestellung verknüpften Bestelldetails anzuzeigen. Unternehmen Sie Folgendes, um das Unterformular fsubOrderDetails zu erstellen und es in die Seite ORDER DETAILS der damit verknüpften Registerkarte einzufügen: 1. Aktivieren Sie das Formular frmCustomer in der Entwurfsansicht. 2. Markieren Sie mit einem Klick die Seite ORDER DETAILS des Registerkartensteuerelements. 3. Vergewissern Sie sich, dass das Werkzeug STEUERELEMENT-ASSISTENTEN aktiv ist. 4. Klicken sie auf das Steuerelement UNTERFORMULAR/UNTERBERICHT. 5. Klicken Sie auf die Stelle auf der Registerkarte ORDER DETAILS, an der das Unterformular erscheinen soll, um es einzufügen. Der Assistent für Unterformulare erscheint.

793

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

Abbildung 21.25: Fügen Sie alle Felder von qryOrders in die Liste der ausgewählten Felder ein

Abbildung 21.26: Wählen Sie als Verknüpfung zwischen dem übergeordneten und dem Unterformular Keine

6. Markieren Sie BEREITS VORHANDENE TABELLEN und klicken Sie auf WEITER.

UND

ABFRAGEN

VERWENDEN

7. Markieren Sie in der Dropdown-Liste TABELLEN/ABFRAGEN den Eintrag qryOrderDetails. 8. Fügen Sie alle Felder der Abfrage in die Liste AUSGEWÄHLTE FELDER ein. 9. Klicken Sie auf WEITER.

794

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.27: Das Unterformular fsubOrders nach dem Einfügen in die Registerkarte Orders

10. Sie werden aufgefordert, Verknüpfungen zwischen Haupt- und Unterformular zu definieren (siehe Abbildung 21.28). Klicken Sie auf WEITER, ohne Verknüpfungen zu definieren.

Abbildung 21.28: Es werden keine Verknüpfungen zwischen Haupt- und Unterformular erstellt

11. Geben Sie fsubOrderDetails als Namen des Unterformulars ein und klicken Sie auf FERTIG STELLEN.

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

795

12. Wählen Sie die Größe des Unterformularsteuerelements so, dass es aussieht wie in Abbildung 21.29.

Abbildung 21.29: Das Unterformular fsubOrderDetails nach dem Einfügen in die Registerkarte Order Details

Die Unterformulare Order und OrderDetails verbergen, bis die entsprechende Registerkarte gewählt wurde Wahrscheinlich das wichtigste Ziel der Entwicklung von Client-Server-Anwendungen ist die Begrenzung der Daten, die vom Datenbank-Server zur Arbeitsstation übertragen werden. Häufig muss der Benutzer die Hauptinformationen eines Kunden sehen, ohne dass er Informationen über Bestellungen oder Bestelldetails braucht. Deshalb ist es unnötig, diese Informationen zu holen, wenn der Benutzer sie nicht ausdrücklich durch einen Klick auf die Registerkarte ORDER bzw. ORDER DETAILS anfordert. Der in Listing 21.1 abgedruckte Code erledigt das Verbergen und Anzeigen des jeweiligen Unterformulars, wenn der Benutzer auf die verschiedenen Registerkarten im Formular klickt. Wenn die Unterformulare angezeigt werden, wird die Eigenschaft RecordSource des Unterformulars mit den passenden Daten gefüllt. Listing 21.1:

Das Change-Ereignis des Steuerelements tabDataEntry erledigt das Verbergen und Anzeigen des jeweiligen Unterformulars

Private Sub tabDataEntry_Change() Select Case Me.tabDataEntry.Pages. _ Item(Me.tabDataEntry.Value).Name Case "pagCustomers" Me.fsubOrders.Visible = False Me.fsubOrderDetails.Visible = False

796

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Case "pagOrders" Me.fsubOrders.Form.RecordSource = "qryOrders" Me.fsubOrders.Visible = True Me.fsubOrderDetails.Visible = False

Case "pagOrderDetails" Me.fsubOrderDetails.Form.RecordSource = "qryOrderDetails" Me.fsubOrders.Visible = False Me.fsubOrderDetails.Visible = True

End Select End Sub

Der Code wertet zunächst aus, welche Seite ausgewählt wurde. Wenn es sich um die Seite pagCustomers handelt, wird die Eigenschaft Visible (bzw. Sichtbar) der Unterformularsteuerelemente fsubOrders und fsubOrderDetails auf False gesetzt. Wenn die Seite pagOrders ausgewählt wurde, wird die Eigenschaft RecordSource des Unterformulars (die Datenherkunft) auf die Abfrage qryOrders gesetzt. Die Eigenschaft Visible des Unterformularsteuerelements fsubOrders wird auf True, die Eigenschaft VISIBLE des Unterformularsteuerelements fsubOrderDetails auf False festgelegt. Wenn die Seite pagOrderDetails ausgewählt wurde, wird die Eigenschaft RecordSource des Unterformulars auf die Abfrage qryOrderDetails gesetzt. Die Eigenschaft Visible des Unterformularsteuerelements fsubOrders wird auf False, die Eigenschaft Visible des Unterformularsteuerelements fsubOrderDetails auf True festgelegt. Die Datenherkunft der Unterformulare leer lassen Alles trifft zusammen, wenn der Benutzer im Kombinationsfeld cboSelectCompany eine Firma auswählt. Dann wird das Ereignis AfterUpdate des Kombinationsfeldes behandelt. Die entsprechende Routine finden Sie in Listing 21.2. Listing 21.2:

Die Behandlungsroutine für das Ereignis AfterUpdate des Kombinationsfeldes cboSelectCompany legt die Datenherkunft der Unterformulare korrekt fest und aktualisiert das Hauptformular

Private Sub cboSelectCompany_AfterUpdate() Select Case Me.tabDataEntry.Pages. _ Item(Me.tabDataEntry.Value).Name Case "pagCustomers" Me.fsubOrders.Form.RecordSource = "" Me.fsubOrderDetails.Form.RecordSource = ""

Eine Client-Server-Anwendung mit Hilfe verknüpfter Tabellen erstellen

797

Case "pagOrders" Me.fsubOrderDetails.Form.RecordSource = "" End Select Me.Requery End Sub

Die Routine wertet zunächst aus, welche Seite ausgewählt wurde. Wenn es sich um die Seite pagCustomers handelt, wird die Eigenschaft RecordSource der Unterformulare fsubOrders und fsubOrderDetails auf eine leere Zeichenfolge gesetzt. Wenn die Seite pagOrders heißt, wird die Eigenschaft RecordSource der Seite fsubOrderDetails auf eine leere Zeichenfolge gesetzt. Im Grunde gewährleistet der Code, dass bei der Auswahl eines anderen Kunden der Bestell- und der Bestelldetaildatensatz erst geholt werden, wenn die jeweilige Seite angeklickt wurde. Das dient dazu, eine große Menge unnötigen Netzwerkverkehr zu verhindern. Die Datenherkunft für die Unterformulare festlegen Da die Datenquellen der Unterformulare auf eine leere Zeichenfolge gesetzt werden, wenn ein anderer Kunde ausgewählt wird, muss die Eigenschaft RecordSource neu ausgefüllt werden, wenn die Seite aktiviert wird. Die in Listing 21.3 gezeigte Behandlungsroutine für das Ereignis Change des Registerkartensteuerelements tabDataEntry erledigt dies. Listing 21.3:

Die Behandlungsroutine für das Ereignis Change des Registerkartensteuerelements tabDataEntry legt die Eigenschaft RecordSource neu fest, wenn eine Seite aktiviert wird

Private Sub tabDataEntry_Change() Select Case Me.tabDataEntry.Pages. _ Item(Me.tabDataEntry.Value).Name Case "pagCustomers" Me.fsubOrders.Visible = False Me.fsubOrderDetails.Visible = False Case "pagOrders" Me.fsubOrders.Form.RecordSource = "qryOrders" Me.fsubOrders.Visible = True Me.fsubOrderDetails.Visible = False

Case "pagOrderDetails" Me.fsubOrderDetails.Form.RecordSource = "qryOrderDetails" Me.fsubOrders.Visible = False Me.fsubOrderDetails.Visible = True

798

Kapitel 21: Eine Client-Server-Anwendung in Aktion

End Select End Sub

Beachten Sie, dass die Datenherkunft des Unterformulars fsubOrders festgelegt wird, wenn die Seite pagOrders ausgewählt wird, und die Datenherkunft des Unterformulars fsubOrderDetails, wenn die Seite pagOrderDetails ausgewählt wird.

21.3

Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

Die eine Alternative für unsere Client-Server-Lösung stellen verknüpfte Tabellen, die andere ein Access-Datenprojekt dar. Wiederum wird die Anwendung um die Client-Server-Datenbank Northwind herum konstruiert. Um die ADP-Datei zu erstellen, unternehmen Sie Folgendes: 1. Klicken Sie auf DATEI|NEU. 2. Wählen Sie PROJEKT (VORHANDENE DATENBANK) und klicken Sie auf OK. 3. Wählen Sie einen Namen und einen Speicherort für das Access-Datenprojekt (.ADP). Klicken Sie auf ERSTELLEN und Sie gelangen in das Dialogfeld DATENLINKEIGENSCHAFTEN. 4. Geben Sie im Textfeld GEBEN SIE EINEN SERVERNAMEN EIN ODER WÄHLEN SIE EINEN AUS den Namen des Servers ein, auf dem sich die Datenbank Northwind befindet. 5. Geben Sie an, wie Sie sich beim Server anmelden wollen. 6. Markieren Sie die Datenbank Northwind als Datenbank auf dem Server. Das vollständige Dialogfeld sollte aussehen wie in Abbildung 21.30. 7. Klicken Sie auf VERBINDUNG TESTEN, um die Verbindung zu Server und Datenbank zu testen. Dann sollte ein Dialogfeld eingeblendet werden, das besagt, dass die Testverbindung erfolgreich war. Klicken Sie auf OK, um fortzufahren. 8. Klicken Sie auf OK, um das Dialogfeld DATENLINKEIGENSCHAFTEN zu schließen. Die ADP-Datei ist jetzt erstellt. Das Datenbankfenster sollte aussehen wie in Abbildung 21.31.

Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

799

Abbildung 21.30: Geben Sie im Dialogfeld Datenlinkeigenschaften Informationen über den Speicherort der Daten an

Abbildung 21.31: Das Datenbankfenster nach dem Erstellen der ADP-Datei

800

21.3.1

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Das Kundenformular entwerfen

Das Formular, welches Sie erstellen sollen, sehen Sie in Abbildung 21.32. Um mit dem Entwurf des Formulars frmCustomer zu beginnen, unternehmen Sie Folgendes: 1. Wählen Sie in der Objektliste den Eintrag FORMULARE. 2. Doppelklicken Sie auf ERSTELLT EIN FORMULAR IN DER ENTWURFSANSICHT. 3. Wählen Sie ANSICHT|FORMULARKOPF/-FUSS, um eine Kopf- und eine Fußzeile in das Formular einzufügen.

Abbildung 21.32: Das vollständige Formular frmCustomer

Ein Kombinationsfeld zum Suchen in das Formular einfügen Wie bei der Anwendung mit verknüpften Tabellen ist der erste Schritt das Einfügen eines Kombinationsfeldes in das Formular, mit dessen Hilfe der Benutzer die Firma auswählen kann, deren Informationen er einsehen möchte. Dieses wird mit den Feldern CustomerID und CompanyName aller Firmen aus der Firmentabelle gefüllt. Erstellen Sie das Kombinationsfeld mit Hilfe des Kombinationsfeld-Assistenten. Unternehmen Sie dazu Folgendes: 1. Klicken Sie, falls erforderlich, auf das Werkzeug STEUERELEMENT-ASSISTENT in der Toolbox, um die Steuerelementassistenten zu aktivieren. 2. Klicken Sie in der Toolbox auf KOMBINATIONSFELD und dann auf die Stelle im Formularkopf, an der das Steuerelement eingefügt werden soll. Dies startet den Kombinationsfeld-Assistenten (siehe Abbildung 21.33). 3. Markieren Sie DAS KOMBINATIONSFELD SOLL SICHT ENTNEHMEN. Klicken Sie auf WEITER.

DIE

WERTE

EINER

TABELLE

ODER

Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

801

Abbildung 21.33: Mit Hilfe des Kombinationsfeld-Assistenten wird ein Kombinationsfeld in das Formular eingefügt

4. Markieren Sie die Tabelle Customers und klicken Sie auf WEITER. 5. Markieren Sie die Felder CustomerID und CompanyName und klicken Sie auf WEITER (siehe Abbildung 21.34). 6. Passen Sie die Spalte für das Feld CompanyName falls nötig, in der Größe an und klicken Sie auf WEITER. 7. Geben Sie als Beschriftung für das Kombinationsfeld »Select a Company« ein und klicken Sie auf FERTIG STELLEN. 8. Nennen Sie das Kombinationsfeld cboSelectCompany. Seiten und Steuerelemente in das Formular einfügen Bevor Sie die Felder in das Formular einfügen können, müssen Sie die Registerkarten für das Formular entwerfen. Unternehmen Sie dazu Folgendes: 1. Klicken Sie auf das Registersteuerelement in der Toolbox. 2. Klicken Sie auf die Stelle im Formular frmCustomer, an der das Steuerelement erscheinen soll, um es einzufügen. 3. Ändern Sie die Eigenschaft Beschriftung der ersten Registerkarte auf Customers. 4. Ändern Sie die Eigenschaft Name der ersten Registerkarte auf pagCustomers. 5. Ändern Sie die Eigenschaft Beschriftung der zweiten Registerkarte auf Orders. 6. Ändern Sie die Eigenschaft Name der zweiten Registerkarte auf pagOrders. 7. Klicken Sie mit der rechten Maustaste auf das Seitensteuerelement und wählen Sie SEITE EINFÜGEN. Eine dritte Seite erscheint.

802

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Abbildung 21.34: Die Felder CustomerID und CompanyName werden in das Kombinationsfeld eingefügt

8. Ändern Sie die Eigenschaft Beschriftung der dritten Registerkarte auf Order Details. 9. Ändern Sie die Eigenschaft Name der dritten Registerkarte auf pagOrderDetails. 10. Ändern Sie die Eigenschaft Name des Registersteuerelements auf tabDataEntry. 11. Ändern Sie die Eigenschaft RecordSource des Formulars (die Datenherkunft) vorübergehend auf die Tabelle Customers. Damit können Sie Steuerelemente in das Formular einfügen. 12. Fügen Sie die Felder wie in Abbildung 21.35 gezeigt in die Registerkarte CUSTOMERS des Formulars ein. 13. Löschen Sie die Datenherkunft aus dem Formular. Die Datenherkunft des Formulars festlegen Dann ist es Zeit, die Datenherkunft für das Formular einzurichten. Das wird am Anfang innerhalb der Behandlungsroutine zum Ereignis Load des Formulars erledigt. Den Code sehen Sie in Listing 21.4. Listing 21.4:

Die Behandlungsroutine für das Ereignis Load des Formulars legt die Datenherkunft für das Formular fest

Private Sub Form_Load() Set mrstCustomers = New ADODB.Recordset With mrstCustomers .ActiveConnection = CurrentProject.Connection .CursorLocation = adUseClient

Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

803

Abbildung 21.35: Die Registerkarte Customers nach dem Einfügen der markierten Felder .CursorType = adOpenDynamic .LockType = adLockOptimistic .Source = "Select * from Customers Where CustomerID = '" & _ Me.cboSelectCompany & "'" .Open End With Set Me.Recordset = mrstCustomers End Sub

Der Code instanziiert zunächst eine ADODB-Datensatzgruppe, die im Abschnitt Allgemeine Deklarationen als privat deklariert wurde. Dann legt er einige Eigenschaften der Datensatzgruppe fest. Beachten Sie, dass als CursorType die Option adOpenDynamic und als LockType die Option adLockOptimistic gewählt wurde. Die Kombination dieser Eigenschaften macht das Formular aktualisierbar. Die Eigenschaft Source der Datensatzgruppe wird auf eine SQL-Anweisung gesetzt, die auf dem im Kombinationsfeld cboSelectCompany gewählten Kunden basiert. Dann wird die Datensatzgruppe geöffnet. Zum Schluss wird die mit dem Formular frmCustomer verknüpfte Datensatzgruppe auf der Grundlage der Datensatzgruppe eingerichtet, die den einen Kundendatensatz enthält. Das Ereignis AfterUpdate des Kombinationsfeldes cboSelectCompany Wenn im Kombinationsfeld cboSelectCompany ein neuer Kunde ausgewählt wird, muss die dem Formular zu Grunde liegende Datensatzgruppe mit den Informationen dieses Kunden neu erstellt werden. Sie sehen die Behandlungsroutine für das Ereignis AfterUpdate des Kombinationsfeldes in Listing 21.5.

804

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Listing 21.5:

Die Routine für das Ereignis AfterUpdate des Kombinationsfeldes cboSelectCompany erstellt die mit dem Formular frmCustomers verknüpfte Datensatzgruppe

Private Sub cboSelectCompany_AfterUpdate() mrstCustomers.Close mrstCustomers.Source = "Select * from Customers Where CustomerID = '" & _ Me.cboSelectCompany & "'" mrstCustomers.Open Set Me.Recordset = mrstCustomers Select Case Me.tabDataEntry.Pages. _ Item(Me.tabDataEntry.Value).Name Case "pagCustomers" Set Me.fsubOrders.Form.Recordset = Nothing Set Me.fsubOrderDetails.Form.Recordset = Nothing Case "pagOrders" Set Me.fsubOrderDetails.Form.Recordset = Nothing Call CreateOrdersRecordset Case "pagOrderDetails" Call CreateOrdersRecordset Call CreateOrderDetailsRecordset End Select End Sub

Zuerst schließt der Code die Datensatzgruppe mrstCustomers. Das ist nötig, damit die Eigenschaften der Datensatzgruppe geändert werden können. Die Herkunft der Datensatzgruppe wird so geändert, dass sie jetzt auf dem gerade im Kombinationsfeld ausgewählten Kunden basiert. Dann wird die Datensatzgruppe geöffnet und die Datensatzgruppeneigenschaft des Formulars wird mit einem Zeiger auf die gerade erstellte Datensatzgruppe versehen. Die case-Anweisung wertet aus, welche Registerkarte des Formulars ausgewählt wurde. Wenn es die Registerkarte CUSTOMERS ist, werden die mit den Unterformularen Order und OrderDetails verknüpften Datensatzgruppen entfernt. Wenn es die Registerkarte ORDERS ist, wird die mit dem Unterformular OrderDetails verknüpfte Datensatzgruppe entfernt und die Routine CreateOrdersRecordset aufgerufen. Diese Routine legt die mit dem Formular fsubOrders verknüpfte Datensatzgruppe an. Wenn die Registerkarte ORDER DETAILS aktiviert wurde, wird zuerst die Routine CreateOrdersRecordset und dann die Routine CreateOrderDetailsRecordset aufgerufen. Die Routine CreateOrderDetailsRecordset ist für das Anlegen der mit dem Unterformular fsubOrderDetails verknüpften Datensatzgruppe zuständig. Beide Routinen werden weiter hinten in diesem Kapitel behandelt.

805

Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

Das Unterformular fsubOrders erstellen Das Unterformular fsubOrders dient zur Anzeige der mit den ausgewählten Kunden verknüpften Bestellungen. Unternehmen Sie Folgendes, um das Unterformular zu erstellen und es in die Seite ORDERS des Registersteuerelements einzufügen: 1. Aktivieren Sie in der Entwurfsansicht das Formular frmCustomer. 2. Markieren Sie mit einem Klick die Seite ORDERS des Registersteuerelements. 3. Vergewissern Sie sich, dass das Werkzeug STEUERELEMENT-ASSISTENTEN aktiv ist. 4. Wählen Sie das Steuerelement UNTERFORMULAR/UNTERBERICHT. 5. Klicken Sie auf die Stelle auf der Registerkarte ORDERS, an der das Steuerelement eingefügt werden soll. Dadurch gelangen Sie in den Unterformular-Assistenten. 6. Markieren Sie BEREITS VORHANDENE TABELLEN und klicken Sie auf WEITER.

UND

ABFRAGEN

VERWENDEN

7. Wählen sie im Listenfeld TABELLEN/ABFRAGEN den Eintrag tblOrders. 8. Fügen Sie alle Felder der Abfrage in die Liste AUSGEWÄHLTE FELDER ein. 9. Klicken Sie auf WEITER. 10. Geben Sie fsubOrders als Namen des Unterformulars ein und klicken Sie auf FERTIG STELLEN. 11. Passen Sie ggf. die Größe des Unterformularsteuerelements an. 12. Öffnen Sie das Formular fsubOrders und löschen Sie seine Datenherkunft. Die Datenherkunft des Formulars wird dann vom Programm gesteuert. Das Unterformular fsubOrderDetails erstellen Das Unterformular fsubOrderDetails wird verwendet, um die mit der ausgewählten Bestellung verknüpften Bestelldetails anzuzeigen. Unternehmen Sie Folgendes, um das Unterformular zu erstellen und es in die Seite ORDER DETAILS des Registersteuerelements einzufügen: 1. Aktivieren Sie das Formular frmCustomer in der Entwurfsansicht. 2. Markieren Sie mit einem Klick die Seite ORDER DETAILS des Registersteuerelements. 3. Vergewissern Sie sich, dass das Werkzeug STEUERELEMENT-ASSISTENTEN aktiv ist. 4. Wählen Sie das Steuerelement UNTERFORMULAR/UNTERBERICHT. 5. Klicken Sie auf die Stelle der Registerkarte ORDER DETAILS, an der das Steuerelement eingefügt werden soll. Der Assistent für Unterformulare erscheint.

806

Kapitel 21: Eine Client-Server-Anwendung in Aktion

6. Markieren Sie BEREITS VORHANDENE TABELLEN und klicken Sie auf WEITER.

UND

ABFRAGEN

VERWENDEN

7. Wählen Sie in der Liste TABELLEN/ABFRAGEN den Eintrag qryOrderDetails. 8. Fügen Sie alle Felder der Abfrage in die Liste AUSGEWÄHLTE FELDER ein. 9. Klicken Sie auf WEITER. 10. Geben Sie fsubOrderDetails als Namen des Unterformulars ein und klicken Sie auf FERTIG STELLEN. 11. Ändern Sie ggf. die Größe des Unterformularsteuerelements. 12. Öffnen Sie das Formular fsubOrderDetails und entfernen Sie seine Datenherkunft. Die Datenherkunft des Formulars wird dann vom Programm gesteuert. Die Unterformulare mit Daten füllen Da die Eigenschaft RecordSource der Formulare fsubOrders und fsubOrderDetails leer ist, müssen beide Formulare per Programm ausgefüllt werden. Der Code in Listing 21.6, den Sie im Formular frmCustomers finden, ist dafür zuständig, das Formular fsubOrders mit Daten zu füllen. Listing 21.6:

Die Routine CreateOrdersRecordset erstellt die Datensatzgruppe, die zum Füllen des Unterformulars fsubOrders mit Daten verwendet wird

Sub CreateOrdersRecordset() Set mrstOrders = New ADODB.Recordset With mrstOrders .ActiveConnection = CurrentProject.Connection .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .Source = "Select * from Orders Where CustomerID = '" & _ Me.cboSelectCompany & "'" .Open End With Set Me.fsubOrders.Form.Recordset = mrstOrders End Sub

Zunächst wird eine Datensatzgruppenvariable auf Modulebene instanziiert, dann werden ihre Eigenschaften festgelegt. Beachten Sie, dass die Eigenschaft CursorType auf adOpenDynamic und die Eigenschaft LockType auf adLockOptimistic gesetzt wird. Die Kombination dieser beiden Eigenschaften macht die entstehende Datensatzgruppe aktualisierbar. Die Eigenschaft Source der Datensatzgruppe basiert auf einer SQL-Anweisung, die alle Datensätze der Tabelle Orders auswählt, bei denen das Feld CustomerID mit der Kundennummer des im Kombinationsfeld cboSelectCompany aus-

Eine Client-Server-Anwendung mit Hilfe eines Access-Datenprojekts erstellen

807

gewählten Kunden übereinstimmt. Dann wird die Datensatzgruppe geöffnet und zum Ausfüllen der mit dem Unterformular fsubOrders verknüpften Datensatzgruppe verwendet. Der Code in Listing 21.7, der sich ebenfalls im Formular frmCustomers befindet, ist für das Füllen des Formulars fsubOrderDetails mit Daten zuständig.

Listing 21.7:

Die Routine CreateOrderDetailsRecordset erstellt die Datensatzgruppe, die zum Füllen des Unterformulars fsubOrderDetails mit Daten verwendet wird

Sub CreateOrderDetailsRecordset() Set mrstOrderDetails = New ADODB.Recordset With mrstOrderDetails .ActiveConnection = CurrentProject.Connection .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .Source = "Select * from [Order Details] Where OrderID = " & _ Me.fsubOrders!OrderID .Open End With Set Me.fsubOrderDetails.Form.Recordset = mrstOrderDetails End Sub

Diese Routine ist mit der Routine CreateOrdersRecordset bis auf die Eigenschaft Source identisch. Die Eigenschaft Source wählt alle Datensätze der Tabelle OrderDetails aus, bei denen das Feld OrderID mit der Bestellnummer des im Unterformular fsubOrders markierten Datensatzes übereinstimmt. Die daraus resultierende Datensatzgruppe wird dann zum Ausfüllen des Unterformulars fsubOrderDetails verwendet. Auf das Anklicken der verschiedenen Formularseiten reagieren Den Schlussstein des Puzzles bildet der Code, der darauf reagiert, dass der Benutzer verschiedene Formularseiten per Mausklick auswählt. Sie sehen ihn in Listing 21.8. Listing 21.8:

Die Behandlungsroutine für das Ereignis Change des Steuerelements tabDataEntry reagiert darauf, dass der Benutzer per Mausklick verschiedene Formularseiten auswählt

Private Sub tabDataEntry_Change() Select Case Me.tabDataEntry.Pages. _ Item(Me.tabDataEntry.Value).Name Case "pagCustomers" Me.fsubOrders.SourceObject = "" Me.fsubOrderDetails.SourceObject = ""

808

Kapitel 21: Eine Client-Server-Anwendung in Aktion

Case "pagOrders" Me.fsubOrders.SourceObject = "fsubOrders" Call CreateOrdersRecordset Me.fsubOrderDetails.SourceObject = ""

Case "pagOrderDetails" Me.fsubOrderDetails.SourceObject = "fsubOrderDetails" Call CreateOrderDetailsRecordset End Select End Sub

Der Code beginnt mit dem Auswerten der ausgewählten Seite. Wenn es sich um die Seite CUSTOMERS handelt, wird die Eigenschaft SourceObject der Unterformularsteuerelemente fsubOrders und fsubOrderDetails auf "" gesetzt. Wenn es sich um die Seite ORDERS handelt, wird die Eigenschaft SourceObject des Unterformularsteuerelements fsubOrders auf "fsubOrders" gesetzt und anschließend die Routine CreateOrdersRecordset aufgerufen, um das Formular fsubOrders mit den passenden Daten zu füllen. Die Eigenschaft SourceObject des Unterformularsteuerelements fsubOrderDetails wird auf "" gesetzt. Wenn es sich um die Seite ORDER DETAILS handelt, wird die Eigenschaft SourceObject des Unterformularsteuerelements fsubOrderDetails auf "fsubOrderDetails" gesetzt. Dann wird die Routine CreateOrderDetailsRecordset aufgerufen, um das Unterformular fsubOrderDetails mit den passenden Daten zu füllen.

Transaktionsverarbeitung

Kapitel

Hier lesen Sie:

 Von Atomarität bis Konsistenz  Die Vorteile  Das Standardverhalten verändern  Explizite Transaktionsverarbeitung implementieren  Einige Bemerkungen zur Transaktionsverarbeitung  Transaktionsverarbeitung in einer Mehrbenutzerumgebung  Transaktionsverarbeitung in einer Client-Server-Umgebung

22.1

Von Atomarität bis Konsistenz

Mit »Transaktionsverarbeitung« ist die Zusammenfassung mehrerer Änderungen zu einem Batch gemeint. Der gesamte Änderungs-Batch wird als Gruppe durchgeführt oder verworfen. Zu den häufigsten Implementierungen der Transaktionsverarbeitung zählen Transaktionen bei Geldautomaten. Stellen Sie sich vor, dass Sie zum Geldautomaten gehen, um Ihr Gehalt einzuzahlen. Mitten in der Verarbeitung kommt es zu einem Stromausfall. Unglücklicherweise hat die Bank den eingehenden Betrag vor dem Stromausfall vermerkt, aber er war Ihrem Konto noch nicht gutgeschrieben worden, als der Stromausfall kam. Transaktionsverarbeitung hätte dies verhindert. Bei Transaktionsverarbeitung wäre der gesamte Prozess als Einheit erfolgreich oder nicht erfolgreich. Eine Gruppe von Operationen gilt als Transaktion, wenn sie folgende Kriterien erfüllt:

 Atomarität – Die Gruppe von Operationen sollte entweder als Einheit oder überhaupt nicht ausgeführt werden.

810

Kapitel 22: Transaktionsverarbeitung

 Konsistenz – Wenn die Gruppe von Operationen als Einheit ausgeführt wird, bleibt die Konsistenz der Anwendung erhalten.

 Isolation – Die Gruppe von Operationen ist von anderen Vorgängen im System unabhängig.

 Dauerhaftigkeit – Nachdem die Gruppe von Operationen übernommen wurde, bleiben die Änderungen bestehen, selbst wenn das System zusammenbricht. Wenn Ihre Anwendung eine Gruppe von Operationen enthält, die atomar und isoliert ist und wenn alle Änderungen weiterbestehen müssen, um die Konsistenz der Anwendung zu erhalten, auch wenn das System zusammenbricht, sollten Sie diese Gruppe von Operationen in eine Transaktionsschleife einbinden. Bei Access 2000 liegt der wesentliche Vorteil der Transaktionsverarbeitung in der Datenintegrität. Wie Sie im nächsten Abschnitt sehen werden, brachte die Transaktionsverarbeitung auch schon in älteren Versionen als Access 95 Leistungsvorteile.

22.2

Die Vorteile

In Access 2.0 ergab die zusätzliche Transaktionsverarbeitung viele geringfügige Vorteile, weil Access 2.0 selbst keine implizite Transaktionsverarbeitung durchführte. Listing 22.1 zeigt Code, der beim Betrieb unter Access 2.0 jedesmal Daten auf die Platte schreibt, wenn die Schleife die Methode Update erreicht. Diese Schreibvorgänge waren in Hinblick auf die Leistung kostspielig, insbesondere wenn sich die Tabellen nicht auf einem lokalen Rechner befanden. Listing 22.1:

Transaktionsverarbeitung mit Hilfe von Access Basic wie in Access 2.0

Sub IncreaseQuantity() On Error GoTo IncreaseQuantity_Err Dim db As DAO.DATABASE Dim rst As DAO.Recordset Set db = CurrentDb Set rst = db.OpenRecordset("Select OrderId, Quantity From tblOrderDetails", _ dbOpenDynaset) 'Datensatzgruppe durchlaufen und das Mengenfeld um 1 erhöhen Do Until rst.EOF rst.Edit rst!Quantity = rst!Quantity + 1 rst.UPDATE rst.MoveNext Loop IncreaseQuantity_Exit:

Die Vorteile

811

Set db = Nothing Set rst = Nothing Exit Sub IncreaseQuantity_Err: MsgBox "Error # " & Err.Number & ": " & Error.Description Resume IncreaseQuantity_Exit End Sub

Dieser und der gesamte Code des Kapitels befindet sich im Modul basTrans der Datenbank CHAP22EX.MDB auf der CD-ROM mit dem Beispiel-Code.

Derselbe Code wie in Listing 22.1 verhält sich bei der Ausführung in Access 2000 wesentlich anders. Neben der expliziten Transaktionsverarbeitung, die Sie möglicherweise aus Gründen der Datenintegrität implementieren, führt Access 2000 hinter den Kulissen eine eigene Transaktionsverarbeitung durch. Diese implizite Transaktionsverarbeitung geschieht allein zur Verbesserung der Leistung Ihrer Anwendung. Während die Verarbeitungsschleife in der Routine IncreaseQuantity ausgeführt wird, schreibt Access die Daten in einen Pufferspeicher und dann in bestimmten Abständen auf die Festplatte. In einer Mehrbenutzerumgebung führt Jet (implizit) standardmäßig alle 50 Millisekunden eine Übernahme aus. Diese Zeitspanne ist auf Parallelität optimiert, nicht auf Leistung. Wenn Sie es für nötig erachten, Parallelität zugunsten von Leistung zu opfern, können Sie einige Einstellungen in der Windows-Registry ändern, um die gewünschten Ergebnisse zu erzielen. Diese Einstellungen werden im nächsten Abschnitt behandelt. Obwohl implizite Transaktionsverarbeitung zusammen mit den veränderbaren Einstellungen der Windows-Registry im Allgemeinen höhere Leistung liefert als explizite Transaktionsverarbeitung, ist diese Situation nicht festgeschrieben. Die Leistungsvorteile durch implizite und explizite Transaktionsverarbeitung werden von zahlreichen Faktoren beeinflusst:

 von der Menge freien Speichers  von der Anzahl der zu aktualisierenden Spalten und Zeilen  von der Länge der zu aktualisierenden Zeilen  vom Netzwerkverkehr Falls Sie vorhaben, Transaktionsverarbeitung nur zum Zweck der Leistungssteigerung zu implementieren, sollten Sie darauf achten, dass Sie die Leistung sowohl bei impliziter als auch bei expliziter Transaktionsverarbeitung messen. Es kommt darauf an, dass Ihre Testumgebung der Produktionsumgebung, in der die Anwendung laufen soll, so ähnlich wie möglich ist.

812

22.3

Kapitel 22: Transaktionsverarbeitung

Das Standardverhalten verändern

Bevor Sie erfahren, wie Transaktionsverarbeitung implementiert wird, sollten Sie einen Blick darauf werfen, was Sie tun können, um das Standardverhalten der in Access 2000 integrierten Transaktionsverarbeitung zu verändern. Implizite Transaktionen werden in Access 2000 von drei Registry-Einstellungen beeinflusst: ImplicitCommitSync, ExclusiveAsyncDelay und SharedAsyncDelay. Diese Schlüssel befinden sich im Registry-Ordner \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Jet 4.0. Sie können mit dem Dienstprogramm RegEdit auf die Windows-Registry zugreifen. Dazu wählen Sie im Startmenü die Option AUSFÜHREN und geben dann RegEdit ein. Die Einstellung ImplicitCommitSync bestimmt, ob das System wartet, bis eine Übernahme durchgeführt ist, bevor es die Ausführung der Anwendung fortsetzt. Die Standardeinstellung ist No, d.h., das System fährt fort, ohne auf das Ende der Übernahme zu warten. Im Allgemeinen werden Sie diese Einstellung nicht ändern wollen, weil dadurch die Leistung enorm erhöht wird. Die Gefahr beim Bestätigen dieses Wertes liegt in der längeren Zeitspanne, in der die Daten verletzbar sind. Bevor die Daten auf die Platte geschrieben sind, könnte der Benutzer den Rechner abschalten und die Integrität der Daten beeinträchtigen. Die Einstellung ExclusiveAsyncDelay gibt die maximale Anzahl Millisekunden an, die vergehen, bevor Jet eine implizite Transaktion übernimmt, wenn eine Datenbank für exklusive Nutzung geöffnet wurde. Die Standardeinstellung beträgt 2 000 Millisekunden. Dieser Wert hat keinen Einfluss auf Datenbanken, die für gemeinsame Nutzung geöffnet wurden. Die Einstellung SharedAsyncDelay ähnelt der Einstellung ExclusiveAsyncDelay. Sie gibt die maximale Anzahl Millisekunden an, die vergehen, bevor Jet eine implizite Transaktion übernimmt, wenn eine Datenbank für gemeinsame Nutzung geöffnet wurde. Die Standardeinstellung beträgt 50 Millisekunden. Je höher dieser Wert liegt, desto größer sind die Leistungsvorteile durch implizite Transaktionen, aber auch das Risiko von Parallelitätsproblemen. Parallelitätsprobleme werden im Abschnitt »Transaktionsverarbeitung in einer Mehrbenutzerumgebung« weiter hinten in diesem Kapitel ausführlich behandelt. Neben den Einstellungen, die die implizite Transaktionsverarbeitung in Access 2000 beeinflussen, gibt es noch eine Registry-Einstellung für die explizite Transaktionsverarbeitung mit dem Namen UserCommitSync, die steuert, ob explizite Transaktionen synchron oder asynchron durchgeführt werden. Bei der Standardeinstellung Yes gibt eine CommitTrans-Anweisung die Kontrolle erst zurück, wenn die Transaktionen tatsächlich auf die Platte geschrieben wurden, d.h., es handelt sich um synchrone

Explizite Transaktionsverarbeitung implementieren

813

Transaktionen. Wenn der Wert auf No geändert wird, bilden mehrere Änderungen eine Warteschlange und die Steuerung wird zurückgegeben, bevor die Änderungen abgeschlossen sind. Sie können die Werte dieser Registry-Einstellungen und anderer Jet-Einstellungen für Windows 95/98 mit Hilfe des Registry-Editors (Regedit.exe) bzw. für Windows NT mit RegEdt32.exe verändern. Änderungen in diesem Abschnitt der Registry betreffen alle Anwendungen, welche die Jet 4.0-Engine benutzen. Wenn nur Ihre Anwendung betroffen sein soll, können Sie den Microsoft Jet betreffenden Teil des Registry-Verzeichnisbaums in den Registry-Verzeichnisbaum Ihrer Anwendung importieren. Dann können Sie die Registry-Einstellungen an Ihre Anwendung anpassen. Um in Ihrer Anwendung das Laden des richtigen Registry-Verzeichnisbaums zu erzwingen, müssen Sie die Eigenschaft INIPath des Objekts DBEngine entsprechend angeben. Ein wesentlich einfacherer Ansatz besteht darin, die Eigenschaften des ADOObjekts Connection festzulegen: Sie können zur Laufzeit neue Einstellungen für alle zuvor erwähnten Registry-Einstellungen sowie zusätzliche Einträge angeben. Ein weiterer Vorteil dieses Ansatzes liegt darin, dass die Registry-Einträge für alle Rechner (temporär) geändert werden, auf denen Ihre Anwendung läuft. Alle Werte, die Sie zur Laufzeit temporär ändern, überschreiben die festgelegten Registry-Werte und ermöglichen die einfache Steuerung und Pflege bestimmter Einstellungen für jede Anwendung. Der folgende Code veranschaulicht, wie die Einstellungen ExclusiveAsyncDelay und SharedAsyncDelay mit Hilfe der Eigenschaften eines ConnectionObjekts verändert werden: Sub ChangeOptions() Dim cnn As ADODB.Connection Set cnn = CurrentProject.Connection cnn.Properties("Jet OLEDB:Exclusive Async Delay") = 1000 cnn.Properties("Jet OLEDB:Shared Async Delay") = 50 End Sub

22.4

Explizite Transaktionsverarbeitung implementieren

Nachdem Sie jetzt die Einstellungen kennen, welche die Transaktionsverarbeitung beeinflussen, können Sie lernen, wie Transaktionsverarbeitung implementiert wird. Die Transaktionsverarbeitung wird von drei Methoden des Objekts Connection (siehe Kapitel 12) gesteuert:

 BeginTrans  CommitTrans  RollbackTrans

814

Kapitel 22: Transaktionsverarbeitung

Die Methode BeginTrans des Objekts Connection eröffnet die Transaktionsschleife. Sobald Access auf BeginTrans trifft, werden alle Änderungen in eine Protokolldatei im Arbeitsspeicher geschrieben. Solange die Methode CommitTrans für das Objekt Connection nicht ausgeführt wird, werden sie nicht in die Datenbankdatei aufgenommen. Nach dem Aufrufen der Methode CommitTrans werden die Änderungen dann dauerhaft in das Datenbankobjekt geschrieben. Wenn die Methode RollbackTrans für das Objekt Connection in Aktion tritt, wird das Protokoll im Arbeitsspeicher gelöscht. Listing 22.2 zeigt ein Beispiel für die Funktionsweise der Transaktionsverarbeitung in Access 2000. Vergleichen Sie es mit Listing 22.1! Listing 22.2:

Transaktionsverarbeitung in Access 2000 mit Hilfe von BeginTrans, Protokollierung, CommitTrans und RollbackTrans

Sub IncreaseQuantityTrans() On Error GoTo IncreaseQuantityTrans_Err Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim boolInTrans As Boolean boolInTrans = False Set rst = New ADODB.Recordset Set cnn = CurrentProject.Connection rst.ActiveConnection = cnn rst.CursorType = adOpenKeyset rst.LockType = adLockOptimistic rst.Open "Select OrderId, Quantity From tblOrderDetails"

'Anfang der Transaktionsschleife cnn.BeginTrans boolInTrans = True 'Schleife durch die Datensatzgruppe, Mengenfeld um 1 erhöhen Do Until rst.EOF rst!Quantity = rst!Quantity + 1 rst.UPDATE rst.MoveNext Loop 'Transaktion übernehmen; alles ist planmäßig verlaufen cnn.CommitTrans boolInTrans = False IncreaseQuantityTrans_Exit: Set cnn = Nothing Set rst = Nothing Exit Sub IncreaseQuantityTrans_Err:

Einige Bemerkungen zur Transaktionsverarbeitung

815

MsgBox "Error # " & Err.Number & ": " & Err.Description 'Transaktion zurücksetzen; ein Fehler ist aufgetreten If boolInTrans Then cnn.RollbackTrans End If Resume IncreaseQuantityTrans_Exit End Sub

Dieser Code verwendet eine Transaktionsschleife, um sicherzustellen, dass alles wie geplant beendet oder überhaupt nicht ausgeführt wird. Beachten Sie, dass die Schleife, die sich durch die Datensatzgruppe bewegt und das Mengenfeld der einzelnen Datensätze um 1 erhöht, in einer Transaktionsschleife platziert wurde. Wenn die gesamte Verarbeitung innerhalb der Schleife erfolgreich abgeschlossen ist, wird die Methode CommitTrans ausgeführt. Im Falle eines Fehlers wird die Methode RollbackTrans ausgelöst, die sicherstellt, dass keine der Änderungen auf die Platte geschrieben wird. Mit Hilfe der Variablen boolInTrans wird ermittelt, ob sich der Code in der Transaktionsschleife befindet. Damit wird gewährleistet, dass die Fehlerbehandlungsroutine nur dann ein Zurücksetzen ausführt, wenn ein Fehler innerhalb der Transaktionsschleife auftritt. Wenn die Methode CommitTrans oder RollbackTrans gestartet wird, ohne dass eine offene Transaktion vorliegt, zieht dies einen Fehler nach sich.

22.5

Einige Bemerkungen zur Transaktionsverarbeitung

Bevor Sie beschließen, dass Transaktionsverarbeitung die beste Erfindung seit fertig geschnittenem Brot ist, sollten Sie einige Aspekte der Transaktionsverarbeitung bedenken, die in diesem Abschnitt umrissen werden.

22.5.1

Transaktionen finden in einem Arbeitsbereich statt

Transaktionen existieren im Kontext eines Connection-Objekts. Die Methoden BeginTrans, CommitTrans und RollbackTrans beeinflussen alle Operationen an der betreffenden Verbindung. Wenn Sie wollen, dass gleichzeitige unverbundene Transaktionen wirksam werden, müssen Sie einzelne Connection-Objekte anlegen, in denen die Transaktionen ablaufen. Während DAO Transaktionen unterstützte, die über mehrere Datenbanken liefen, sind ADO-Transaktionen auf eine konkrete Datenquelle beschränkt, weil sie im Kontext einer Verbindung bestehen.

22.5.2

Sicherstellen, dass die Datenquelle Transaktionen unterstützt

Nicht alle Datenquellen unterstützen Transaktionsverarbeitung, wie beispielsweise Excel- und dBase-Dateien und auch einige Back-End-ODBC-Datenbank-Server. Im Zweifelsfall können Sie mit Hilfe der Eigenschaft Transaction DDL des Objekts Con-

816

Kapitel 22: Transaktionsverarbeitung

nection ermitteln, ob die Datenquelle Transaktionsverarbeitung unterstützt. Wenn die Eigenschaft vorhanden und nicht mit einem Nullwert versehen ist, trifft dies zu. Um festzustellen, ob die Eigenschaft vorhanden ist, fragen Sie ihren Wert ab. Wenn sie nicht vorhanden ist, wird ein Fehler ausgelöst. Listing 22.3 zeigt ein Beispiel dafür, wie man ermittelt, ob ein Objekt Transaktionsverarbeitung unterstützt. Listing 22.3:

Bestimmen, ob eine Verbindung Transaktionsverarbeitung unterstützt

Sub SupportsTransCurrentDB() On Error GoTo SupportsTrans_Err Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim boolSupportsTrans As Boolean Dim vntValue As Variant boolSupportsTrans = False Set cnn = CurrentProject.Connection Set rst = New ADODB.Recordset rst.ActiveConnection = cnn rst.CursorType = adOpenKeyset rst.LockType = adLockOptimistic rst.Open "tblOrderDetails" 'Transaktionsschleife nur beginnen, wenn 'Datensatzgruppe Transaktionen unterstützt On Error Resume Next vntValue = cnn.Properties.Item("Transaction DDL") If Not Err.Number And _ cnn.Properties.Item("Transaction DDL").Value 0 Then boolSupportsTrans = True cnn.BeginTrans End If On Error GoTo SupportsTrans_Err 'Schleife durch Datensatzgruppe, Mengenfeld um 1 erhöhen Do Until rst.EOF rst!Quantity = rst!Quantity + 1 rst.UPDATE rst.MoveNext Loop 'CommitTrans starten, wenn alles nach Plan verlaufen ist 'und Datensatzgruppe Transaktionen unterstützt If boolSupportsTrans Then cnn.CommitTrans End If

Einige Bemerkungen zur Transaktionsverarbeitung

817

SupportsTrans_Exit: Set cnn = Nothing Set rst = Nothing Exit Sub SupportsTrans_Err: MsgBox "Error # " & Err.Number & ": " & Err.Description 'Transaktion zurücksetzen, wenn Fehler aufgetreten ist 'und Datensatzgruppe Transaktionen unterstützt If boolSupportsTrans Then cnn.RollbackTrans End If Resume SupportsTrans_Exit End Sub

Der Code verwendet eine Boolesche Variable mit dem Namen boolSupportsTrans, um zu verfolgen, ob die Verbindung Transaktionen unterstützt. Beachten Sie die Anweisung On Error Resume Next. Die Eigenschaft Transaction DDL des Objekts Connection wird ausgewertet. Wenn sie nicht vorhanden ist, wird ein Fehler ausgelöst. Die nächste Anweisung prüft auf eine Fehlernummer und einen Eigenschaftswert ungleich 0. Nur wenn die Eigenschaft Transaction DDL für das Objekt Connection vorhanden und ungleich 0 ist, wird die Methode BeginTrans aufgerufen und die Variable boolSupportsTrans auf True gesetzt. Die Variable wird im weiteren Verlauf der Routine zweimal ausgewertet. Die Methode CommitTrans wird nur ausgelöst, wenn boolSupportsTrans mit True belegt ist. Bei der Fehlerbehandlung wird die Methode RollbackTrans ebenfalls nur ausgeführt, wenn boolSupportsTrans gleich True ist. Listing 22.4 zeigt ein Beispiel, in dem die Datenquelle, ein Excel-Arbeitsblatt, keine Transaktionen unterstützt. Beachten Sie, dass eine Datenquelle verwendet wird, die auf das Excel-Arbeitsblatt verweist. Mit Hilfe des Connection-Objekts wird eine Datensatzgruppe geöffnet. Der übrige Code entspricht dem in Listing 22.3. gezeigten. Listing 22.4:

Bestimmen, ob eine auf einer anderen Datenquelle als Access basierende Verbindung Transaktionsverarbeitung unterstützt

Sub SupportsTransOtherDB() On Error GoTo SupportsTrans_Err Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim boolSupportsTrans As Boolean Dim vntValue As Variant boolSupportsTrans = False

818

Kapitel 22: Transaktionsverarbeitung

Set cnn = New ADODB.Connection cnn.Open "DSN=TestXLS;UID=;PWD=;" Set rst = New ADODB.Recordset With rst .ActiveConnection = cnn .CursorType = adOpenKeyset .LockType = adLockOptimistic .Open "tblCustomers" End With 'Transaktionsschleife nur beginnen, wenn 'Datensatzgruppe Transaktionen unterstützt On Error Resume Next vntValue = cnn.Properties.Item("Transaction DDL") If Not Err.Number And _ cnn.Properties.Item("Transaction DDL").Value 0 Then boolSupportsTrans = True cnn.BeginTrans End If On Error GoTo SupportsTrans_Err

'Schleife durch Datensatzgruppe, Mengenfeld um 1 erhöhen Do Until rst.EOF rst!City = "Thousand Oaks" rst.UPDATE rst.MoveNext Loop 'CommitTrans starten, wenn alles nach Plan verlaufen ist 'und Datensatzgruppe Transaktionen unterstützt If boolSupportsTrans Then cnn.CommitTrans End If SupportsTrans_Exit: Set cnn = Nothing Set rst = Nothing Exit Sub SupportsTrans_Err: MsgBox "Error # " & Err.Number & ": " & Err.Description

Einige Bemerkungen zur Transaktionsverarbeitung

819

'Transaktion zurücksetzen, wenn Fehler aufgetreten ist 'und Datensatzgruppe Transaktionen unterstützt If boolSupportsTrans Then cnn.Rollback End If Resume SupportsTrans_Exit End Sub

Wenn es bei einer Anwendung um eine Verknüpfung mit einer Datenquelle geht, die keine Transaktionen unterstützt, wird die Eigenschaft Transaction DDL nicht korrekt ausgewertet. Weil beim Umgang mit verknüpften Tabellen die Verbindung der Access-Datenbank verwendet wird, scheint es, als ob die Eigenschaft Transaction DDL Transaktionen unterstütze. Dasselbe Verhalten zeigt sich, wenn für die Verbindung der Datenquelle der Jet Provider eingesetzt wird. In beiden Fällen wird beim Aufrufen der Methoden BeginTrans, CommitTrans und RollbackTrans kein Fehler ausgelöst, sondern der Vorgang scheint erfolgreich abgeschlossen zu werden. Wenn die Methode RollbackTrans aufgerufen wird, findet keine Rücknahme statt und alle Änderungen bleiben erhalten.

22.5.3

Transaktionen verschachteln

Ein weiterer Punkt, den Sie in Bezug auf Transaktionen kennen sollten, ist die Möglichkeit, Transaktionen zu verschachteln. Die Hierarchie richtet sich nach dem FIFO-Prinzip. Die inneren Transaktionen müssen immer vor den äußeren übernommen oder zurückgesetzt werden. Nachdem für eine Transaktion ein CommitTrans ausgeführt wurde, können Sie Änderungen an dieser nur vornehmen, wenn sie in eine andere Transaktion verschachtelt ist, die ihrerseits zurückgesetzt wurde. Die Methode BeginTrans gibt einen Wert zurück, der die Verschachtelungsebene angibt. Mit 1 wird eine Transaktion auf höchster Ebene, mit 2 eine Transaktion auf der nächst niedrigen Ebene bezeichnet usw.

22.5.4

Die explizite Übernahme von Transaktionen vergessen

Wenn sich eine Transaktionsschleife in der Ausführung befindet, werden alle Änderungen in eine Protokolldatei im Arbeitsspeicher geschrieben. Wenn es niemals zu einem CommitTrans kommt, werden die Änderungen praktisch zurückgesetzt. Anders gesagt: es gibt ein implizites Zurücksetzen, wenn die Änderungen nicht mit der Methode CommitTrans explizit auf die Platte geschrieben werden. Das geschieht im Allgemeinen zu Ihrem Vorteil. Wenn die Stromzufuhr unterbrochen wird oder der Rechner sich aufhängt, bevor der CommitTrans ausgeführt wird, werden alle Änderungen zurückgenommen. Dieses Verhalten kann Sie jedoch in Schwierigkeiten stürzen, wenn Sie die Methode CommitTrans vergessen. Wenn die Verbindung geschlossen wird, ohne dass die Methode CommitTrans ausgeführt wurde, wird das Protokoll im Speicher gelöscht und die Transaktion implizit zurückgesetzt.

820

22.5.5

Kapitel 22: Transaktionsverarbeitung

Den verfügbaren Arbeitsspeicher prüfen

Ein weiteres Problem bei Transaktionen tritt auf, wenn das Transaktionsprotokoll den physischen Arbeitsspeicher des Rechners verbraucht hat. Access 2000 versucht zunächst, virtuellen Speicher zu nutzen. Das Transaktionsprotokoll wird in das Verzeichnis geschrieben, das in der Umgebungsvariablen TEMP des Rechners genannt ist. Diese Methode verlangsamt den Transaktionsprozess erheblich. Wenn das Transaktionsprotokoll den gesamten Arbeitsspeicher und den virtuellen Speicher auf der Festplatte aufgebraucht hat, wird ein Fehler mit der Nummer 2004 gemeldet. An dieser Stelle müssen Sie ein Zurücksetzen einleiten, da Sie sonst in Gefahr geraten, die Integrität der Datenbank zu verletzen. Wenn Ihr Code versucht, die Transaktion zu übernehmen, nachdem ein Fehler mit der Nummer 2004 aufgetreten ist, übernimmt die Jet-Engine so viele Änderungen wie möglich und lässt die Datenbank in einem inkonsistenten Zustand zurück. Der Fehler 2004 lässt sich mit Hilfe der Eigenschaft SQLSTATE der Auflistung Errors des Objekts Connection feststellen.

22.5.6

Formulare und Transaktionen

Bei gebundenen Formularen setzt Access seine eigene Transaktionsverarbeitung ein, über die Sie keinerlei Kontrolle besitzen. Wenn Sie selbst im Zusammenhang mit Formularen Transaktionsverarbeitung betreiben wollen, müssen Sie ungebundene Formulare erstellen oder Code ohne Formularschnittstelle ausführen.

22.6

Transaktionsverarbeitung in einer Mehrbenutzerumgebung

In einer Mehrbenutzerumgebung hat Transaktionsverarbeitung Konsequenzen, die über den Schutz von Daten hinausgehen. Indem Sie einen Prozess in eine Transaktionsschleife einbetten, stellen Sie sicher, dass Sie die Kontrolle über alle Datensätze besitzen, die von dem Prozess betroffen sind. Der Preis für diese zusätzliche Kontrolle besteht in geringerer Parallelität für die übrigen Benutzer der Anwendung. Listing 22.5 veranschaulicht dieses Szenario. Listing 22.5:

Ein sicherer Weg, in einer Mehrbenutzerumgebung Transaktionen durchzuführen, der jedoch zu Parallelitätseinbußen führt

Sub MultiPessimistic() On Error GoTo MultiPessimistic_Err Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim intCounter As Integer

Transaktionsverarbeitung in einer Mehrbenutzerumgebung

821

Dim intChoice As Integer Dim intTry As Integer Dim boolInTrans As Boolean boolInTrans = False Set rst = New ADODB.Recordset Set cnn = CurrentProject.Connection rst.ActiveConnection = cnn rst.CursorType = adOpenKeyset rst.CursorLocation = adUseServer rst.LockType = adLockPessimistic rst.Open "Select OrderId, ProductID, UnitPrice " & _ "From tblOrderDetails Where ProductID > 50" 'Transaktionsschleife beginnen cnn.BeginTrans boolInTrans = True 'Schleife durch die Datensatzgruppe, dabei UnitPrice erhöhen Do Until rst.EOF 'Hier Sperre für jeden Datensatz innerhalb der Schleife rst!UnitPrice = rst!UnitPrice * 1.1 rst.UPDATE rst.MoveNext Loop 'Transaktion übernehmen; alles ist nach Plan verlaufen 'Alle Sperren für alle am Prozess beteiligten Datensätze werden aufgehoben cnn.CommitTrans boolInTrans = False Set cnn = Nothing Set rst = Nothing Exit Sub MultiPessimistic_Err: Select Case cnn.Errors(0).SQLState Case 3260 intCounter = intCounter + 1 If intCounter > 2 Then intChoice = MsgBox(Err.Description, vbRetryCancel + vbCritical) Select Case intChoice Case vbRetry intCounter = 1 Case vbCancel 'Benutzer hat Abbruch gewählt, zurücksetzen Resume TransUnsuccessful End Select End If

822

Kapitel 22: Transaktionsverarbeitung

DoEvents For intTry = 1 To 100: Next intTry Resume Case Else MsgBox "Error # " & Err.Number & ": " & Err.Description End Select TransUnsuccessful: If boolInTrans Then cnn.RollbackTrans End If MsgBox "Warning: Entire Process Rolled Back" Set cnn = Nothing Set rst = Nothing Exit Sub End Sub

Die Routine MultiPessimistic wendet pessimistisches Sperren an, d.h., dass der betroffene Datensatz bei jeder Bearbeitung der Daten gesperrt wird. Wenn alles klappt und kein Fehler auftritt, wird die Sperre aufgehoben, wenn die Methode CommitTrans erreicht ist. Ein Fehler mit der Nummer 3260, welcher besagt, dass der Datensatz von einem anderen Benutzer gesperrt wurde, wird von der Fehlerbehandlungsroutine abgefangen. Derjenige, der die Transaktionsverarbeitung ausführt, kann zwischen erneutem Versuch und Abbruch wählen. Wenn er sich für einen neuen Versuch entscheidet, versucht der Code noch einmal, Daten im betreffenden Datensatz zu bearbeiten. Wenn er sich für den Abbruch entscheidet, wird die Transaktion zurückgesetzt. Damit werden die Änderungen an allen am Prozess beteiligten Datensätzen zurückgenommen. Zwei wichtige Bemerkungen zur Routine MultiPessimistic: Erstens wird bei der Ausführung dieser Routine jeder am Prozess beteiligte Datensatz gesperrt. Das kann bedeuten, dass alle anderen Benutzer einen großen Teil oder sogar alle Datensätze erst bearbeiten können, wenn der Transaktionsprozess abgeschlossen ist. Das ist unter dem Aspekt der Datenintegrität wundervoll, aber es könnte in einer Umgebung, in der Daten häufig aktualisiert werden müssen, undurchführbar sein. Deshalb ist es günstig, Transaktionsschleifen zeitlich möglichst kurz zu halten. Zweitens muss die gesamte Transaktion abgebrochen werden, wenn ein einziger Sperrversuch misslingt. Dies könnte wiederum unter dem Aspekt der Datenintegrität Ihren Wünschen entsprechen, aber möglicherweise erfordern, dass alle Benutzer auf Datenbearbeitung verzichten, während ein wichtiger Prozess abläuft. Im optimistischen Sperrmodus findet der Sperrversuch nicht beim Beginn der Datenbearbeitung, sondern beim Aufruf der Methode Update statt. Das macht allerdings keinen großen Unterschied; alle an der Transaktion beteiligten Datensätze bleiben gesperrt, bis CommitTrans oder RollbackTrans ausgeführt sind. Der Hauptun-

Transaktionsverarbeitung in einer Mehrbenutzerumgebung

823

terschied liegt in den Fehlern, die Sie abfangen müssen. Listing 22.6 zeigt den Code für optimistisches Sperren in einer Mehrbenutzerumgebung. Listing 22.6:

Optimistisches Sperren in einer Mehrbenutzerumgebung

Sub MultiOptimistic() On Error GoTo MultiOptimistic_Err Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim intCounter As Integer Dim intChoice As Integer Dim intTry As Integer Dim boolInTrans As Boolean boolInTrans = False Set rst = New ADODB.Recordset Set cnn = CurrentProject.Connection rst.ActiveConnection = cnn rst.CursorType = adOpenKeyset rst.CursorLocation = adUseServer rst.LockType = adLockOptimistic rst.Open "Select OrderId, ProductID, UnitPrice " & _ "From tblOrderDetails Where ProductID > 50" 'Transaktionsschleife beginnen cnn.BeginTrans boolInTrans = True 'Schleife durch die Datensatzgruppe, dabei UnitPrice erhöhen Do Until rst.EOF rst!UnitPrice = rst!UnitPrice * 1.1 'Hier Sperre für jeden Datensatz innerhalb der Schleife rst.UPDATE rst.MoveNext Loop 'Transaktion übernehmen; alles ist nach Plan verlaufen 'Alle Sperren für alle am Prozess beteiligten Datensätze werden aufgehoben cnn.CommitTrans boolInTrans = False Set cnn = Nothing Set rst = Nothing Exit Sub MultiOptimistic_Err: Select Case Err.Number Case 3197 'Data Has Changed-Fehler If rst.EditMode = adEditInProgress Then intChoice = MsgBox("Overwrite Other User's Changes?", _

824

Kapitel 22: Transaktionsverarbeitung

vbYesNoCancel + vbQuestion) Select Case intChoice Case vbCancel, vbNo MsgBox "Update Canceled" Resume TransNotSuccessful Case vbYes rst.UPDATE Resume End Select End If Case 3186, 3260 'Gesperrt oder Läßt sich nicht sichern intCounter = intCounter + 1 If intCounter > 2 Then intChoice = MsgBox(Err.Description, vbRetryCancel + vbCritical) Select Case intChoice Case vbRetry intCounter = 1 Case vbCancel 'Benutzer hat Abbruch gewählt, zurücksetzen Resume TransNotSuccessful End Select End If DoEvents For intTry = 1 To 100: Next intTry Resume Case Else MsgBox "Error # " & Err.Number & ": " & Err.Description End Select TransNotSuccessful: If boolInTrans Then cnn.RollbackTrans End If MsgBox "Warning: Entire Process Rolled Back" Set cnn = Nothing Set rst = Nothing Exit Sub End Sub

Beachten Sie, dass die Sperre in der Routine MultiOptimistic bei jedem Aufruf der Methode Update verhängt wird. Alle Sperren werden aufgehoben, wenn die Methode CommitTrans ausgeführt wird. Außerdem prüft die Fehlerbehandlung auf einen Fehler mit der Nummer 3197 (Datenänderung), der auftritt, wenn die Daten von einem anderen Benutzer zwischen dem Start der Methode Edit und unmittelbar vor dem Start der Methode Update geändert werden.

Transaktionsverarbeitung in einer Client-Server-Umgebung

22.7

825

Transaktionsverarbeitung in einer Client-Server-Umgebung

Wenn es um Transaktionen in einer Client-Server-Umgebung geht, müssen Sie einige weitere Punkte beachten: wann und wie die Transaktionen stattfinden, welche Transaktionstypen unterstützt werden und welcher Art die potentiellen Probleme sind.

22.7.1

Implizite Transaktionen

Wenn keine expliziten Transaktionen verwendet werden, hängt die Art der Übernahme von Transaktionen auf dem Datenbank-Server davon ab, welche Art Befehle ausgeführt werden. Im Allgemeinen ist jede Code-Zeile von einer impliziten Transaktion umschlossen, d.h., es gibt keine Möglichkeit, eine Aktion zurückzusetzen, weil sie unmittelbar auf dem Datenbank-Server übernommen wird. Ausnahmen von dieser Regel bilden SQL-Anweisungen, die Daten verändern. Diese (UPDATE, INSERT und APPEND) werden im Batch ausgeführt; implizit wird eine Transaktionsschleife um die gesamte Anweisung gelegt. Wenn sich nur ein an der SQL-Anweisung beteiligter Datensatz nicht erfolgreich aktualisieren lässt, wird die gesamte UPDATE-, INSERT- oder APPEND-Aktion zurückgesetzt.

22.7.2

Explizite Transaktionen

Bei expliziten Transaktionen übersetzt ODBC die Methoden BeginTrans, CommitTrans und RollbackTrans in die passende Syntax des Back-End-Servers und die Transaktion wird erwartungsgemäß ausgeführt. Die wesentliche Ausnahme von dieser Regel liegt vor, wenn das von Ihnen benutzte Back-End keine Transaktionen unterstützt. Listing 22.7 zeigt ein Beispiel für Transaktionsverarbeitung mit einem SQL ServerBack-End. Listing 22.7:

Transaktionsverarbeitung mit einem SQL Server-Back-End

Sub TransSQLServer() Dim cnn As ADODB.Connection Dim cmd As ADODB.Command Dim boolInTrans As Boolean boolInTrans = False Set cnn = New ADODB.Connection Set cmd = New ADODB.Command cnn.ConnectionString = "Provider=SQLOLEDB; Data Source=Alexis; Initial _ Catalog=Pubs; User ID=SA; Password=" cnn.Open

826

Kapitel 22: Transaktionsverarbeitung

cnn.BeginTrans boolInTrans = True cmd.ActiveConnection = cnn cmd.CommandText = "UPDATE sales Set qty = qty + 1 " & _ "Where Stor_ID = '7067';" cmd.CommandType = adCmdText cmd.Execute cmd.CommandText = "Update titles Set price = price + 1 " & _ "Where Type = 'Business'" cmd.CommandType = adCmdText cmd.Execute cnn.CommitTrans boolInTrans = False TransSQLServer_Exit: Set cnn = Nothing Set cmd = Nothing Exit Sub TransSQLServer_Err: MsgBox "Error # " & Err.Number & ": " & Err.Description If boolInTrans Then cnn.RollbackTrans End If Resume TransSQLServer_Exit End Sub

Die Routine TransSQLServer beginnt mit dem Anlegen der beiden Objektvariablen der Typen Connection und Command. Als nächstes wird die Methode BeginTrans für die Verbindung ausgeführt. Sie erstellt eine temporäre Abfragedefinition. Die Eigenschaft ConnectionString des Connection-Objekts wird mit einem Zeiger auf eine SQL Server-Datenbank mit dem Namen Pubs versehen. Mit der Methode Open des Connection-Objekts wird die Verbindung geöffnet und mit der Methode BeginTrans desselben Objekts beginnt die Transaktionsschleife. Für das Command-Objekt werden u.a. die Eigenschaften ActiveConnection, CommandText und CommandType festgelegt. Danach wird die temporäre Abfrage ausgeführt. Die Eigenschaft CommandText der Abfragedefinition wird verändert und die Abfrage noch einmal ausgeführt. Wenn beide ExecuteMethoden erfolgreich verlaufen, wird die Methode CommitTrans des ConnectionObjekts gestartet. Falls während der Verarbeitung ein Fehler auftritt, wird die Methode RollbackTrans aufgerufen. Listing 22.7 bietet ein Beispiel für die Verwendung von Transaktionen bei der Verarbeitung von Daten, die in Microsoft SQL Server gespeichert wurden. Die Verwendung von ADO-Datensatzgruppen zur Aktualisierung von Client-ServerDaten ist sehr ineffizient. Wie in Kapitel 19 erläutert, ist die Aktualisierung von Client-Server-Daten mit Hilfe gespeicherter Prozeduren meistens vorzuziehen.

Transaktionsverarbeitung in einer Client-Server-Umgebung

22.7.3

827

Sperrbeschränkungen

Ein potentielles Problem im Zusammenhang mit Client-Server-Datenbanken betrifft Sperrbeschränkungen. Viele Datenbank-Server stellen strenge Grenzen dafür auf, wie viele Datensätze gleichzeitig gesperrt werden dürfen. Wie Sie in den Listings 22.2 und 22.3 gesehen haben, kann eine Transaktionsschleife u.U. eine erhebliche Zahl von Datensätzen sperren. Wenn Sie in Ihrem VBA-Code Transaktionsschleifen verwenden, müssen Sie unbedingt an die maximale Anzahl der Sperren denken, die Ihr Back-End unterstützt. Das Problem entfällt, wenn Sie zur Aktualisierung von ClientServer-Daten gespeicherte Prozeduren verwenden.

22.7.4

Negative Interaktionen mit Server-spezifischen Transaktionsbefehlen

Beim Erstellen von Pass-Through-Abfragen sollten Sie keinesfalls die Server-spezifischen Transaktionsbefehle verwenden. Diese können mit den Methoden BeginTrans, CommitTrans und RollbackTrans in Konflikt geraten und Verwirrung und sogar Schäden an Daten verursachen.

22.7.5

Für die Praxis

Die Integrität des Zeit- und Abrechnungssystems mit Hilfe der Transaktionsverarbeitung steigern Bei der Weiterentwicklung des Zeit- und Abrechnungssystems halten Sie es möglicherweise für notwendig, bestimmte Aufgaben mit Hilfe von VBA-Code zu erledigen. Diese Aufgaben erfordern vielleicht, dass mehrere Prozesse entweder erfolgreich oder überhaupt nicht abgeschlossen werden. Wenn solche Situationen entstehen, sollten Sie erwägen, sie in eine Transaktionsschleife einzubetten. Ein Beispiel für eine derartige Situation stellt das Formular frmArchivePayments dar, das Sie in Abbildung 22.1 sehen. Dieses Formular ermöglicht dem Benutzer, einen Datumsbereich anzugeben, der als Kriterium dafür verwendet wird, welche Daten an die Tabelle tblPaymentsArchive gesendet und aus der Tabelle tblPayments gelöscht werden. Wenn dieser Prozess ausgeführt wird, soll sichergestellt werden, dass er entweder in seiner Gesamtheit oder überhaupt nicht stattfindet. Listing 22.8 zeigt den Code der für die Beispielanwendung passenden Transaktionsschleife.

Abbildung 22.1: Im Formular frmArchivePayments kann der Benutzer einen Datumsbereich für zu archivierende Zahlungen angeben

828

Kapitel 22: Transaktionsverarbeitung

Listing 22.8:

Eine für die Beispielanwendung geeignete Transaktionsschleife

Sub cmdArchivePayments_Click() On Error GoTo Err_cmdArchivePayments_Click Dim cnn As ADODB.Connection Dim strSQL As String Dim boolInTrans As Boolean boolInTrans = False If MsgBox("Archives Payments in Selected Date Range, Proceed?", _ vbYesNo, "Please Respond") = vbYes Then Set cnn = CurrentProject.Connection cnn.BeginTrans boolInTrans = True strSQL = "INSERT INTO tblPaymentsArchive" & _ " SELECT DISTINCTROW tblPayments.* " & _ " FROM tblPayments " & _ " WHERE tblPayments.PaymentDate Between #" & _ Me!txtStartDate & _ "# And #" & _ Me!txtEndDate & "#;" cnn.Execute strSQL strSQL = "DELETE DISTINCTROW tblPayments.PaymentDate " & _ "FROM tblPayments " & _ " WHERE tblPayments.PaymentDate Between #" & _ Me!txtStartDate & _ "# And #" & _ Me!txtEndDate & "#;" cnn.Execute strSQL cnn.CommitTrans boolInTrans = False End If MsgBox "Process Completed Successfully!", vbInformation Exit_cmdArchivePayments_Click: Exit Sub Err_cmdArchivePayments_Click: MsgBox Err.Description If boolInTrans Then cnn.RollbackTrans End If Resume Exit_cmdArchivePayments_Click End Sub

Transaktionsverarbeitung in einer Client-Server-Umgebung

829

Diese Routine startet mit Hilfe der Methode BeginTrans des Connection-Objekts eine Transaktionsschleife. Es wird eine SQL-Anweisung erstellt, welche die Werte der Steuerelemente txtStartDate und txtEndDate im Formular als Kriterien verwendet und alle Datensätze im angegebenen Datumsbereich in die Tabelle tblPaymentsArchive einfügt. Die Methode Execute wird auf das Connection-Objekt angewandt und verwendet die SQL-Zeichenfolge als Argument. Die Zeichenfolge wird dann verändert, um eine Anweisung zu bilden, die alle Datensätze im angegebenen Datumsbereich aus der Tabelle tblPayments löscht. Wenn beide SQL-Anweisungen erfolgreich verlaufen, wird die Methode CommitTrans ausgeführt, die beide Transaktionen übernimmt. Im Fehlerfall wird die gesamte Transaktion zurückgesetzt.

Replikation leicht gemacht

Kapitel

Hier lesen Sie:

 Datenänderungen weiterreichen  Einsatzmöglichkeiten für Replikation  Replikation implementieren  Die Architektur der Replikation  Replikationstopologien  Eine Datenbank replikationsfähig machen  Zusätzliche Replikate erstellen  Replikate synchronisieren  Replikationskonflikte lösen  Der Replikations-Manager  Replikation per Programm

23.1

Datenänderungen weiterreichen

Access 95 war die erste Einzelplatzdatenbank, die integrierte Replikationsfähigkeiten besaß. Die Replikation ist mit der Einführung von Access 2000 ausgereifter geworden. Sie ist eine leistungsfähige Funktion, die in der heutigen Welt der mobilen und verteilten Informationsverarbeitung immer wichtiger wird. Dieses Kapitel stellt Ihnen die Replikation und ihre Implementierung mit Hilfe der Benutzerschnittstelle und mittels Code vor.

832

23.2

Kapitel 23: Replikation leicht gemacht

Einsatzmöglichkeiten der Replikation

Als »Datenreplikation« wird die Fähigkeit eines Systems bezeichnet, automatisch Kopien seiner Daten und Anwendungsobjekte an entfernten Standorten anzulegen. Alle Änderungen am Original oder Datenänderungen an den Kopien werden an alle anderen Kopien weitergegeben. Datenreplikation ermöglicht die Offline-Veränderung von Daten an entfernten Standorten. Änderungen am Original oder an den entfernten Daten werden mit anderen Instanzen der Datenbank synchronisiert. Die Ausgangsdatenbank wird als »Hauptentwurf (Designmaster)« bezeichnet. Änderungen an Definitionen von Tabellen oder anderen Datenbankobjekten können nur im Designmaster vorgenommen werden. Dieser wird zur Anfertigung spezieller Kopien mit der Bezeichnung »Replikate« verwendet. Es gibt zwar nur einen Designmaster, aber Replikate können auch von anderen Replikaten angelegt werden. Der Vorgang der Weitergabe von Änderungen vom Designmaster an die Replikate wird als »Synchronisierung« bezeichnet. Der Designmaster und die Replikate, die am Synchronisierungsvorgang beteiligt sind, werden als »Replikatgruppe« zusammengefasst. Stellen Sie sich, um ein Beispiel für Datenreplikation in Funktion zu sehen, ein Verkaufsteam vor, das den ganzen Tag unterwegs ist. Am Ende des Arbeitstages meldet sich jeder Verkäufer über DUN (Dial-Up Networking) oder RAS (Remote Access Services) bei einem der Windows NT-Server der Firma an. Die Transaktionen aller Verkäufer werden an den Server gesendet. Falls nötig, werden Änderungen an den Server-Daten zum Verkäufer gesendet. Wenn sich die Benutzer beim System anmelden, werden außer den zu replizierenden Daten auch die Änderungen an den Komponenten der Anwendung aktualisiert, wenn die Entwickler der Organisation fleißig Formulare, Berichte und Module in das Master-Exemplar der Datenbank einfügen. Dieses Beispiel veranschaulicht nur eine der vielen sinnvollen Einsatzmöglichkeiten der Replikation. Kurz gesagt: Datenreplikation dient zur Verbesserung der Verfügbarkeit und Integrität der Daten innerhalb einer Organisation oder eines Unternehmens. Die praktischen Einsatzmöglichkeiten der Datenreplikation sind zahlreich. Sie lassen sich in fünf allgemeine Bereiche gliedern, die in den folgenden Abschnitten erläutert werden.

23.2.1

Gemeinsame Nutzung von Daten in mehreren Büros

In der globalen Wirtschaft von heute ist es für Firmen normal, mehrere überall im Land oder sogar weltweit verteilte Büros zu besitzen. Vor Access 95 war es schwierig, eine Access-Anwendung zu implementieren, welche die gemeinsame Nutzung von Daten in mehreren Büros unterstützte. Mit Replikation kann jedoch jedes Büro über ein Replikat der Datenbank verfügen. Im Lauf des Tages kann jedes Büro seine Änderungen in gewissen Abständen mit dem Hauptsitz der Firma synchronisieren. Wie oft synchronisiert wird, hängt davon ab, wie häufig die Daten an den einzelnen Standorten aktualisiert werden müssen, um sie aktuell zu halten.

Einsatzmöglichkeiten der Replikation

23.2.2

833

Gemeinsame Nutzung von Daten durch Einzelpersonen an unterschiedlichen Standorten

Die gemeinsame Nutzung von Daten durch Einzelpersonen an unterschiedlichen Standorten wird durch das bereits genannte Beispiel des Verkaufsteams veranschaulicht. Diese Implementierung von Replikation betrifft meistens mobile Benutzer, die nach der Änderung von Daten unterwegs Verbindung zum Netzwerk aufnehmen. Da nur inkrementelle Änderungen vom Designmaster (dem Original) zu den Replikaten (den Kopien) und von den Replikaten zum Designmaster übertragen werden, ist diese Form der Replikation ökonomisch praktikabel.

23.2.3

Die Netzwerkbelastung reduzieren

Replikation kann bei der Reduzierung der Netzwerkbelastung sehr effizient sein. Der Designmaster kann auf einen oder mehrere zusätzliche Server repliziert werden. Dann können verteilte Benutzer Änderungen auf einem der zusätzlichen Server vornehmen und die Leistung im Netzwerk wird durch die Verteilung der Arbeitslast deutlich gesteigert. Datenänderungen auf den zusätzlichen Servern lassen sich in gewissen Abständen während des Tages mit dem Haupt-Server synchronisieren. Wie häufig synchronisiert wird, hängt davon ab, wie wichtig die ständige Aktualität der Daten ist.

23.2.4

Anwendungsaktualisierungen verteilen

Replikation stellt ein hervorragendes Transportmittel für die Verteilung von Aktualisierungen der Anwendung dar. Entwurfsänderungen können nur am Designmaster vorgenommen werden. Deshalb werden alle strukturellen Änderungen an der Anwendung zu den Benutzer gesendet, wenn sie sich organisationsweit zur Synchronisierung mit dem Designmaster anmelden. Dies ist wesentlich effizienter und wirkungsvoller, als jedem Benutzer ein völlig neues Exemplar der Anwendungsdatenbank zu übermitteln, sobald eine kleine Änderung am Schema vorgenommen wird.

23.2.5

Die Daten in der Anwendung durch Kopien sichern

Viele Leute halten Replikation nicht für ein Mittel zur Sicherung von Anwendungsdaten, aber sie eignet sich für diese Aufgabe hervorragend. Normalerweise müssen sich alle Benutzer beim System abmelden, damit eine Sicherungskopie einer AccessDatenbank erstellt werden kann, aber mit Replikation ist das nicht nötig. Der Synchronisierungsprozess kann in gewissen Abständen während des Tages stattfinden, obwohl die Benutzer beim System angemeldet sind, und alle Änderungen werden repliziert. Das ist nicht nur effizienter, als die gesamte Datenbank zu sichern, sondern gewährleistet auch, dass der Betrieb auf einem Sicherungs-Server reibungslos weitergeführt werden kann, wenn auf einem Server Probleme auftreten.

834

23.3

Kapitel 23: Replikation leicht gemacht

Wann ist Replikation nicht geeignet?

Trotz der vielen positiven Aspekte der Replikation ist sie in einigen Situationen ungeeignet, wie z.B. wenn die Datenkonsistenz von wesentlicher Bedeutung ist. Wenn eine Anwendung verlangt, dass die Daten jederzeit aktuell sind, ist sie kein guter Kandidat für Replikation. Replikation ist auch nicht wirkungsvoll, wenn bestehende Datensätze in großer Menge im Lauf des Tages von vielen verschiedenen Benutzern geändert werden. In einer solchen Situation wäre die Lösung von Konflikten, die auftreten, wenn mehrere Benutzer denselben Datensatz modifizieren, nicht praktikabel. Außerdem können Sie Replikation nicht nutzen, wenn Sie den Entwicklungsprozess mit Visual SourceSafe verwalten. Schließlich lassen sich Designmaster weder umbenennen noch verschieben und ein beschädigter Designmaster ist schwierig wiederherzustellen.

23.4

Replikation implementieren

Der Replikationsprozess setzt sich aus folgenden Schritten zusammen: 1. Replizierbarkeit der Datenbank herstellen 2. Replikate anlegen und verteilen 3. Replikate mit dem Designmaster synchronisieren 4. Konflikte lösen Diese Schritte lassen sich folgendermaßen erledigen:

 mit Hilfe der Access-Benutzerschnittstelle,  mit Hilfe des Windows-Aktenkoffers,  mit Hilfe des Replikations-Managers,  mittels ADO-Code. Die für den Replikationsprozess erforderlichen Schritte und die Alternativen für deren Ausführung werden in diesem Kapitel behandelt. Einen Überblick über die Alternativen finden Sie in den folgenden Abschnitten.

23.4.1

Die Access-Benutzerschnittstelle

Die Access-Benutzerschnittstelle stellt einige Menüpunkte bereit, mit deren Hilfe Sie die einzelnen Schritte des Replikationsprozesses ausführen können. Das Menü EXTRAS|REPLIKATION umfasst folgende Optionen: JETZT SYNCHRONISIEREN, DATENBANK IN REPLIKAT KONVERTIEREN, TEILREPLIKATIONS-ASSISTENT, DESIGNMASTER WIEDERHERSTELLEN und KONFLIKTE LÖSEN. Diese werden im Verlauf des Kapitels erläutert.

Replikation implementieren

23.4.2

835

Aktenkoffer-Replikation

Der Windows-Aktenkoffer liefert die Grundlage, die Access für den Replikationsprozess benötigt. Die Benutzer können eine Datenbankdatei einfach in den Aktenkoffer ziehen, um sie zu replizieren bzw. um unterwegs Änderungen an der Datei vorzunehmen und um das Replikat mit dem Designmaster zu synchronisieren, wenn sie erneut Verbindung zum Netzwerk aufnehmen. Das funktioniert, weil Access 2000 bei der Installation eine spezielle Klassen-ID beim Windows-Aktenkoffer registrieren lässt. Wenn eine Datenbank in den Aktenkoffer gezogen wird, wird der Synchronisierungs-Code des Aktenkoffers aufgerufen. Sobald der Benutzer im Aktenkoffermenü AUSWAHL AKTUALISIEREN oder ALLES AKTUALISIEREN wählt, wird eine Aktualisierungsroutine aufgerufen. Aktenkoffer-Replikation ist als Installationsoption für Windows 95, seine Nachfolger und Windows NT 4.0 verfügbar.

23.4.3

Der Replikations-Manager

Der Replikations-Manager ist ein ausgefeiltes Werkzeug, das zu Microsoft Office 2000 Developer gehört. Im Replikationsprozess ist er ein Pflichtbestandteil, wenn Sie viele Replikate verwalten. Er stellt nicht nur die Grundfunktionalität bereit, sondern mit Hilfe des Replikations-Managers können Sie alle Aspekte des Replikationsprozesses verwalten und feinfühlig steuern. Er wird im Abschnitt »Den ReplikationsManager verwenden« ausführlicher behandelt.

23.4.4

ADO-Code

Die meisten Teile des Replikationsprozesses lassen sich auch mittels ADO-Code erledigen, der eingesetzt werden kann, um eine Datenbank replikationsfähig zu machen, um Replikate zu erstellen und zu synchronisieren und um Eigenschaften einer replizierbaren Datenbank abzufragen und festzulegen. ADO lässt sich mühelos in die übrigen Replikationsmethoden integrieren. ADO-Code verlangt von Ihnen zwar am meisten Zeitaufwand und Anstrengung, aber die Replikation lässt sich auf Ereignisse anstelle von Zeitangaben aufbauen und Sie können den Benutzern eine individuelle Schnittstelle für den Replikationsprozess zur Verfügung stellen.

23.4.5

Programme, die Replikation mittels Datenzugriffsobjekten unterstützen

Visual Basic ab Version 4.0, Excel ab der Version für Windows 95 und Visual C++ unterstützen die Replikation mit Hilfe von Datenzugriffsobjekten (ADO). Mit diesen Produkten können Sie Replikation jedoch nicht mit Hilfe des Aktenkoffers oder von Microsoft Office Developer durchführen und deshalb ist es einfacher, die Replikation auf einem Rechner zu erledigen, auf dem Access installiert ist.

836

23.5

Kapitel 23: Replikation leicht gemacht

Die Architektur der Replikation: Was setzt die Replikation in Bewegung?

Nachdem Sie jetzt wissen, was Replikation ist und welche Alternativen Sie für die Implementierung haben, sind Sie bereit, etwas darüber zu erfahren, was die Replikation in Bewegung setzt. Für den Replikationsprozess sind sechs Komponenten zuständig:

 die Verfolgungsschicht  der Microsoft Replikations-Manager  der Synchronizer  der Dateisystemtransport  die Aktenkoffer-Synchronisierung  Registry-Einträge

23.5.1

Die Verfolgungsschicht

Mit der Verfolgungsschicht ist derjenige Teil der Jet-Engine gemeint, der alle Änderungen am Designmaster und an einzelnen Replikaten verfolgen und aufzeichnen kann. Die Verfolgungsschicht ist dafür zuständig, dass die Änderungen mit Sicherheit für die Übermittlung an andere Replikate verfügbar sind.

23.5.2

Der Microsoft Replikations-Manager

Der Microsoft Replikations-Manager stellt Ihnen die Werkzeuge zur Verfügung, die zur Unterstützung des Replikationsprozesses benötigt werden. Außerdem lässt er sich zum Erstellen von Berichten über Synchronisierungsaktivitäten einsetzen.

23.5.3

Der Synchronizer

Wenn Sie den Aktenkoffer oder die Access-Benutzerschnittstelle zum Verwalten des Replikationsprozesses einsetzen, erledigt Jet den Austausch von Informationen zwischen den Replikaten. Wenn Sie den Replikationsprozess mit Hilfe des ReplikationsManagers durchführen, ist der Synchronizer für die Überwachung der Änderungen und die Erledigung des Datenaustausches zwischen den Replikaten zuständig. Wenn Sie den Replikations-Manager einsetzen, wird jedem Replikat ein Synchronizer zugewiesen, der entweder direkte oder indirekte Synchronisierung zwischen den Mitgliedern einer Replikatgruppe durchführt. Beim Start der Synchronisierung versucht er, eine direkte Verbindung zum Zielmitglied der Replikatgruppe herzustellen. Wenn er beide Mitglieder der Replikatgruppe gleichzeitig öffnen kann, findet direkte

Die Architektur der Replikation: Was setzt die Replikation in Bewegung?

837

Synchronisierung statt, d.h., Änderungen durch ein Mitglied der Replikatgruppe werden direkt an das andere übermittelt. Wenn der Synchronizer feststellt, dass das Zielmitglied der Replikatgruppe nicht verfügbar ist, kommt es zu indirekter Replikation. Es gibt viele Gründe für eine Nichterreichbarkeit. Im Folgenden mögliche Gründe, warum keine direkte Verbindung hergestellt werden kann:

 Der Netzwerk-Server, auf dem das Replikat liegt, ist ausgefallen.  Der Rechner mit dem anderen Replikat ist nicht beim Netzwerk angemeldet.  Das andere Mitglied nimmt gerade an einer anderen Replikation teil.  Das andere Mitglied befindet sich nicht in einem gemeinsam genutzten Ordner. Unabhängig vom Grund für eine indirekte Synchronisierung hinterlässt der Synchronizer für das erste Mitglied des Replikats eine Nachricht für den Synchronizer des Mitgliedes der unerreichbaren Replikatgruppe. Diese wird in einem gemeinsam genutzten Ordner in dem Netzwerk abgelegt, der als Ablagestelle für das Zielmitglied dient. Alle während der Unerreichbarkeit eines Mitgliedes einer Replikatgruppe gesendeten Nachrichten werden an dieser Ablagestelle gespeichert. Wenn Sie feststellen müssen, dass eine direkte oder eine indirekte Synchronisierung stattgefunden hat, können Sie die Systemtabelle MSysExchangeLog durchsehen. Diese nur in replizierten Datenbanken vorkommende Tabelle wird im Abschnitt »Zur Datenbank hinzugefügte Systemtabellen« dieses Kapitels behandelt. Der Synchronizer wird über die Benutzerschnittstelle des Replikations-Managers konfiguriert und im Abschnitt »Den Replikations-Manager verwenden« ausführlicher besprochen.

23.5.4

Der Dateisystemtransport

Der Dateisystemtransport ist für die Bereitstellung von Messaging-Diensten für den Synchronizer zuständig.

23.5.5

Die Aktenkoffer-Synchronisierung

Eine weitere wesentliche Komponente der Replikationsarchitektur ist die Aktenkoffer-Synchronisierung. Wie bereits erwähnt, stellt sie sicher, dass eine Datenbank replizierbar ist und verwaltet das Zusammenführen von Änderungen zwischen dem Aktenkoffer- und dem Desktop-Replikat.

838

23.5.6

Kapitel 23: Replikation leicht gemacht

Die Registry-Einträge

Beim Replikationsprozess helfen mehrere Windows-Redistry-Einträge, von denen Sie einige in Abbildung 23.1 sehen. Beachten Sie den Teilschlüssel Transporter unter dem Schlüssel \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0, der wichtige Pfadinformationen enthält, welche der Replikations-Manager und der Synchronizer nutzen. Die Aktenkoffer-Synchronisierung verwendet Einträge unter \HKEY_CLASSES_ROOT\CLSID. Beachten Sie, dass der Registry-Schlüssel weiterhin Transporter heißt, obwohl der Name in Synchronizer geändert wurde.

Abbildung 23.1: Replikation und die WindowsRegistry

23.6

Replikationstopologien

Die Topologie der Datensynchronisierung bestimmt, welche Replikate mit welchen anderen Replikaten synchronisiert werden. Die »Topologie« ist eigentlich ein Plan dafür, wie die Änderungen zwischen den Mitgliedern der Replikatgruppe zusammengeführt werden. Für unterschiedliche Situationen setzt man unterschiedliche Topologien ein und welche Topologie Sie wählen, hängt von den Erfordernissen Ihres Geschäfts und vom Aufbau Ihrer Organisation ab. Es gibt folgende Synchronisierungstopologien: Stern, Ring, Vollverbindung, Linear und Hybrid.

23.6.1

Die Sterntopologie

Bei der Sterntopologie wird ein einziger Verteiler in gewissen Abständen mit den übrigen Replikaten synchronisiert. Der größte Vorteil dieser Topologie ist ihre Ein-

Replikationstopologien

839

fachheit und leichte Programmierbarkeit. Ein weiterer Vorteil liegt in der Kürze der Wege, welche die Daten zurücklegen müssen. Jedes Replikat wird mit nur einer anderen Datenbank, dem Verteiler, synchronisiert. Das ist jedoch nicht besonders zuverlässig. Wenn das steuernde Replikat beschädigt oder unerreichbar ist, kann keine Synchronisierung stattfinden. Ein weiterer Nachteil der Sterntopologie liegt darin, dass das Replikat, welches als erstes mit dem Verteiler synchronisiert wird, keine, das letzte jedoch alle Daten von den anderen Replikaten bekommt. Mit zwei Replikationsrunden lässt sich dieses Problem beseitigen. Schließlich lässt sich die Sterntopologie nicht bei einer großen Anzahl von Replikaten einsetzen, weil die Gesamtbelastung auf dem Verteiler liegt.

Stern

Ring

Linear

Vollständig verbunden

Hybrid

Abbildung 23.2: Beispiele für Replikationstopologien

Der Designmaster darf niemals Verteiler sein. Wenn Sie ihn als Verteiler bestimmen, kann es vorkommen, dass Teiländerungen am Entwurf versehentlich mit den übrigen Replikaten synchronisiert werden. Verlegen Sie den Designmaster lieber auf einen der äußeren Rechner und synchronisieren Sie Entwurfsänderungen mit dem steuernden Replikat, sobald sie abgeschlossen und vollständig getestet sind.

23.6.2

Ringtopologie

Bei einer Ringtopologie wird jeder Rechner mit dem nächsten Rechner in der Replikationskette synchronisiert. Es gibt in diesem Szenario keinen Synchronisierungsmittelpunkt. Der wesentliche Vorteil der Ringtopologie liegt darin, dass die Belastung auf die Umgebungsrechner verteilt wird. Der wichtigste Nachteil besteht darin,

840

Kapitel 23: Replikation leicht gemacht

dass es möglicherweise lange dauert, bis Änderungen an alle Teilnehmer weitergegeben sind, weil es keinen Mittelpunkt gibt. Außerdem wird die Synchronisierung gestoppt, wenn eines der Replikate in der Kette beschädigt oder unerreichbar ist, aber das lässt sich mit Hilfe von Code abfangen, der das Problem bemerkt und den nicht erreichbaren Rechner umgeht.

23.6.3

Die vollständig verbundene Topologie

Wenn die Topologie der Vollverbindung eingesetzt wird, wird jedes Replikat mit jedem anderen Replikat synchronisiert. Dies bietet mehrere Vorteile. Der stärkste Punkt ist die Garantie, dass die Daten in einem gegebenen Augenblick so aktuell wie möglich sind, weil sie von jedem Replikat direkt an alle anderen Replikate der Replikatgruppe gesendet werden. Deshalb ist diese Lösung die beste, wenn größtmögliche Aktualität nötig ist. Ein weiterer Vorteil der vollständig verbundenen Topologie ist der hohe Redundanzgrad, d.h., dass an mehreren Stellen dieselben Daten vorhanden sind. Wegen des niedrigen »Latenz grades« (d.h. der Wahrscheinlichkeit, dass die Daten in einem gegebenen Augenblick nicht aktuell sind) sind außerdem die Folgen bei einem Ausfall eines Replikats minimal. Auch die vollständig verbundene Topologie hat jedoch Nachteile. Sie erfordert von allen Topologien wegen des Netzwerkverkehrs, der erzeugt wird, wenn jedes Replikat mit allen anderen der Gruppe synchronisiert wird, den höchsten Aufwand. Außerdem müssen die Zeitpläne für die Replikation gestaffelt werden, da sonst mit großer Wahrscheinlichkeit Kollisionen auftreten, wenn mehr als ein Replikat versucht, sich mit ein und demselben Replikat zu synchronisieren.

23.6.4

Die lineare Topologie

Die lineare Topologie entspricht bis auf den Umstand, dass die Kette nicht geschlossen wird, der Ringtopologie. Deshalb besitzt sie den höchsten Latenzgrad. Der größte Vorteil der linearen Topologie ist das geringe Maß an Netzwerkverkehr; sie ist jedoch für die meisten Anwendungen nicht einsetzbar, weil es länger dauert, bis Änderungen alle Replikate der Gruppe erreicht haben.

23.6.5

Die Hybridtopologie

Eine Hybridtopologie besteht aus einer beliebigen Kombination der anderen Topologien. In einer komplexen Anwendung ist es normalerweise nicht sinnvoll, nur eine einzige Topologie einzusetzen. Durch Kombination von Topologien können Sie genau die Ergebnisse erzielen, die Sie benötigen. Abbildung 23.2 stellt nur ein Beispiel für eine Hybridtopologie vor – einen Ring, der mit einem Stern verbunden ist. Sie sollten mit verschiedenen Konfigurationen experimentieren, um herauszufinden, welche Topologie Prozessorbelastung, Netzwerkverkehr und Latenz der Daten am besten ausbalanciert.

Änderungen an Ihrer Datenbank durch Replikation

23.7

841

Änderungen an Ihrer Datenbank durch Replikation

Die Replikation führt zu einigen Änderungen an Ihrer Datenbank, aber diese sind notwendig, um die Erfordernisse des Replikationsprozesses zu erfüllen. Es handelt sich um Folgendes:

 In jede replizierte Tabelle werden Felder eingefügt.  In die Datenbank werden mehrere Systemtabellen eingefügt.  In die Datenbankdokumentobjekte werden Eigenschaften eingefügt.  Sequentielle Felder des Typs AutoWert werden in zufällige Felder des Typs AutoWert umgewandelt.

 Die Datenbankgröße nimmt zu.

23.7.1

Felder, die in jede replizierte Tabelle eingefügt werden

Während der Replikation ermittelt die Jet-Engine, ob jede Tabelle ein Feld des Typs AutoWert und der Feldgröße ReplicationID besitzt. Wenn sie kein Feld findet, das diese Kriterien erfüllt, fügt sie ein Feld mit dem Namen s_Guid in die Tabelle ein, welches jeden Datensatz eindeutig kennzeichnet. Dieses ist für alle Replikate identisch. Außerdem fügt die Jet-Engine drei weitere Felder in jede Tabelle der Datenbank ein: s_Lineage, s_ColLineage und s_Generation. Im Feld s_Lineage werden die IDs von

Replikaten, die einen Datensatz aktualisiert haben, und die letzte von diesen Replikaten angelegte Version gespeichert, im Feld s_Generation Informationen über mehrere Änderungen. Diese Felder sind nur sichtbar, wenn Sie die Anzeige von Systemobjekten aktiviert haben (mit EXTRAS|OPTIONEN).

23.7.2

Systemtabellen, die in die Datenbank eingefügt werden

Außerdem fügt die Jet-Engine einige Systemtabellen in Ihre Datenbank ein, die Konflikte, Fehler und Austauschaktionen zwischen den Replikatdatenbanken aufzeichnen. MSysSideTables und MSysExchangeLog sind die wichtigsten; Sie können sie ansehen, wenn Sie die Anzeige von Systemobjekten aktiviert haben (mit EXTRAS|OPTIONEN). Die Tabelle MSysSideTables verfolgt Tabellen, bei denen während der Synchronisierung ein Konflikt aufgetreten ist. Sie hält den Namen der Nebentabelle fest, in der die konfliktverursachenden Datensätze stehen. Die Tabelle MSysErrors verfolgt alle nicht behobenen Synchronisierungsfehler. Sie ist leer, wenn alle Fehler abgearbeitet sind. Sie finden diese Tabelle in allen Replikaten.

842

Kapitel 23: Replikation leicht gemacht

Die Tabelle MSysSchemaProb stellt Fehler fest, die beim Synchronisieren des Entwurfs eines Replikats aufgetreten sind. Sie ist nur sichtbar, wenn zwischen dem Replikat des Benutzers und einem anderen Replikat in der Gruppe ein Entwurfskonflikt aufgetreten ist. Die Tabelle MSysExchangeLog ist eine lokale Tabelle, die Informationen über Synchronisierungen aufnimmt, welche zwischen dem lokalen Replikat und anderen Mitgliedern der Replikatgruppe ausgeführt wurden.

23.7.3

Eigenschaften, die den Datenbankobjekten hinzugefügt werden

Einer replikationsfähigen Datenbank werden mehrere Eigenschaften hinzugefügt, von denen einige nur im VBA-Code zur Verfügung stehen. Die Eigenschaft Replicable der Datenbank wird auf True gesetzt und kann danach nicht mehr verändert werden. Die Eigenschaft ReplicaID ist eine eindeutige ID, welche jedem Replikat zugewiesen wird. Die Eigenschaft DesignMaster kann den Status Designmaster an eine andere Datenbank übertragen. Das geschieht im Allgemeinen, wenn der ursprüngliche Designmaster irreparabel beschädigt ist. Außer den Eigenschaften, die für die Datenbank gelten, können noch zwei Eigenschaften auf die Tabellen, Abfragen, Formulare, Berichte, Makros und Module in der Datenbank angewandt werden: KeepLocal und Replicable. Die Eigenschaft KeepLocal, die einem Objekt vor dem Replizieren der Datenbank zugewiesen wird, verhindert das Kopieren des Objekts in die übrigen Replikate der Gruppe. Die Eigenschaft Replicable, die nach dem Replizieren einer Datenbank angewandt wird, besagt, dass das Objekt repliziert werden soll.

23.7.4

Änderungen an sequentiellen Feldern des Typs AutoWert

Eine weitere wichtige Änderung an Ihren Tabellen beim Replizieren der Datenbank ist die Umwandlung aller Felder des Typs AutoWert von sequentieller in zufällige Nummerierung. Bestehende Datensätze sind davon nicht betroffen, aber neue Schlüssel werden nach dem Zufallsprinzip erzeugt, weil dadurch Konflikte beim Synchronisieren der Datenbank verringert werden. Wenn alle Kopien sequentielle Schlüssel erzeugen, können Sie vorhersehen, dass es zu Konflikten kommen wird, wenn Sie versuchen, die Änderungen zusammenzuführen. Durch die Erzeugung zufälliger Primärschlüssel sinkt die Wahrscheinlichkeit solcher Konflikte.

23.7.5

Änderung der Datenbankgröße

Wenn eine Datenbank repliziert wird, wird sie wegen der hinzugefügten Felder und Tabellen größer. Dies stellt im Allgemeinen kein Problem dar. Wenn Platz auf der Festplatte sehr gefragt ist, sollten Sie diesen Aspekt der Replikation jedoch bedenken, bevor Sie Replikation in Ihre Anwendungen integrieren.

843

Eine Datenbank replikationsfähig machen

23.8

Eine Datenbank replikationsfähig machen

Eine replikationsfähige Datenbank ist nichts weiter als eine Datenbank, deren Eigenschaft Replicable auf True gesetzt wurde. Wenn eine Datenbank nicht als replizierbar markiert ist, kann sie nicht repliziert werden. Wenn eine Datenbank jedoch als replizierbar gekennzeichnet wird, nimmt die Jet-Engine einige Veränderungen an ihr vor, um sie replizierbar zu machen. Bevor diese vollzogen sind, wird die Datenbank nicht als Teil einer Replikationsgruppe erkannt und lässt sich nicht mit anderen Datenbanken synchronisieren. Wenn Sie eine Datenbank replizieren wollen, sollten Sie Folgendes unternehmen: 1. Kennzeichnen Sie alle Objekte in der Datenbank, die nicht repliziert werden sollen, als lokal, indem Sie die Eigenschaft KeepLocal der Objekte auf True setzen. 2. Legen Sie einen Designmaster für die Replikation an, indem Sie die Eigenschaft Replicable der Datenbank auf True setzen. 3. Legen Sie Kopien (Replikate) des Designmasters an. Sie können eine Datenbank mit Hilfe der Access-Benutzerschnittstelle, des Windows-Aktenkoffers, des Replikations-Managers oder mittels Code replizierbar machen. Die beiden folgenden Abschnitte behandeln die Access-Benutzerschnittstelle und den Windows-Aktenkoffer. Die Verwendung des Replikations-Managers wird im Abschnitt »Den Replikations-Manager verwenden«, die Verwendung von Code im Abschnitt »Replikation mittels Code implementieren« besprochen.

23.8.1

Eine Datenbank mit Hilfe der Access-Benutzerschnittstelle replizierbar machen

Wählen Sie EXTRAS|REPLIKATION|DATENBANK IN REPLIKAT KONVERTIEREN. Microsoft Access übermittelt Ihnen eine Warnmeldung, dass die Datenbank vor der Verarbeitung geschlossen wird (siehe Abbildung 23.3). Abbildung 23.3: Dieses Dialogfeld warnt Sie davor, dass Access die Datenbank schließen muss, bevor sie zum Designmaster erklärt werden kann

844

Kapitel 23: Replikation leicht gemacht

Nachdem Sie JA gewählt haben, sehen Sie ein weiteres Dialogfeld, in dem Sie gefragt werden, ob Access eine Sicherungskopie der Datenbank anlegen soll, bevor es fortfährt (siehe Abbildung 23.4). Vor der Replikation eine Sicherungskopie anzulegen, ist immer günstig, weil sich eine Datenbank nach der Markierung als replizierbar nicht in den nicht replizierbaren Zustand zurückversetzen lässt.

Abbildung 23.4: Dieses Dialogfeld fordert Sie auf, Access vor der Replikation der Datenbank eine Sicherungskopie anlegen zu lassen

Als nächstes werden Sie im Dialogfeld SPEICHERORT DES NEUEN REPLIKATS nach Namen und Speicherort des neuen Replikats gefragt (siehe Abbildung 23.5). Nachdem Sie auf OK geklickt haben, wird das neue Replikat angelegt und der Vorgang ist abgeschlossen. Ihre Ursprungsdatenbank wird in einen Designmaster umgewandelt; das Replikat bekommt den im Dialogfeld SPEICHERORT DES NEUEN REPLIKATS angegebenen Namen und Speicherort. Wenn der Replikationsvorgang erfolgreich beendet wurde, erscheint das in Abbildung 23.6 gezeigte Dialogfeld. Beachten Sie, dass nur der Designmaster Änderungen an der Datenbankstruktur (dem Schema) entgegennehmen kann.

Abbildung 23.5: Im Dialogfeld Speicherort des neuen Replikats können Sie Speicherort und Namen für das Replikat angeben

845

Verhindern, dass Objekte repliziert werden

Abbildung 23.6: Dieses Dialogfeld erscheint nach der erfolgreichen Replikation einer Datenbank

23.8.2

Eine Datenbank mit Hilfe des Windows-Aktenkoffers replizierbar machen

Anstelle der Access-Benutzerschnittstelle können Sie zur Replikation einer Datenbank auch den Windows-Aktenkoffer verwenden. Sie brauchen die Datenbankdatei lediglich vom Windows-Explorer auf das Aktenkoffersymbol in Ihrem Arbeitsplatz zu ziehen, um in das in Abbildung 23.7 gezeigte Dialogfeld zu gelangen.

Abbildung 23.7: Dieses Dialogfeld erscheint, nachdem Sie eine Datenbank zum Zweck der Replikation in den Aktenkoffer gezogen haben

Bis auf die letzte Meldung sehen Sie dieselbe Folge von Meldungen, die sie erhalten, wenn Sie im Menü EXTRAS in der Access-Benutzerschnittstelle REPLIKATION wählen. Nur eine Datenbank kann für Änderungen am Entwurf, z.B. für die Modifikation von Tabellenstrukturen, verwendet werden. Das in Abbildung 23.8 gezeigte Aktenkoffer-Dialogfeld fragt, welche Datenbank Sie gern als Designmaster hätten. Im Allgemeinen wählen Sie das Original, nicht die Aktenkofferkopie, weil letztere normalerweise nur unterwegs als Mittel zum Hinzufügen, Bearbeiten und Löschen von Daten verwendet wird.

23.9

Verhindern, dass Objekte repliziert werden

Möglicherweise möchten Sie verhindern, dass bestimmte Objekte einer replikationsfähigen Datenbank repliziert werden, falls beispielsweise bestimmte Daten vertraulich sind oder die meisten Benutzer bestimmte Daten nicht zu sehen brauchen. Möglicherweise wird im Designmaster zum Beispiel eine Gehaltstabelle der Mitarbeiter unterhalten und verwendet, die aber für keines der Replikate erforderlich ist. Je weniger Objekte repliziert werden, desto wirkungsvoller ist der Replikationsvorgang.

846

Kapitel 23: Replikation leicht gemacht

Abbildung 23.8: Die letzte Dialogfeld, das Sie bei der Aktenkoffer-Replikation sehen, lässt Ihnen die Wahl, welches Exemplar als Designmaster verwendet werden soll

In der Access-Benutzerschnittstelle können Sie beim Erstellen eines neuen Objekts das Kontrollkästchen DIESES OBJEKT REPLIZIEREN aktivieren, wie in Abbildung 23.9 gezeigt (ohne Aktivierung bleibt das neue Objekt lokal), oder die Eigenschaft Replizierbar eines vorhandenen Objekts auf dessen Eigenschaftenseite ändern (siehe Abbildung 23.10). Replizierte Objekte sind in der Objektliste des Access-Datenbankfensters durch ein Globussymbol mit rotierenden Pfeilen gekennzeichnet.

Abbildung 23.9: Ein neues Objekt im Dialogfeld Speichern unter replizierbar machen

Abbildung 23.10: Die Eigenschaft Replizierbar eines Objekts auf dessen Eigenschaftenseite ändern

Zusätzliche Replikate erstellen

847

Außerdem können Sie die Eigenschaft Replizierbar mittels VBA-Code oder mit Hilfe des Replikations-Managers ändern. Dazu setzen Sie die Eigenschaft KeepLocal des Objekts auf True. Wenn Sie versuchen, dies mittels VBA-Code zu erreichen, bekommen Sie eine Fehlermeldung, falls Sie die Eigenschaft noch nicht an das Objekt angefügt haben. Deshalb müssen Sie in Ihren Code eine entsprechende Fehlerbehandlung einbauen. Die Verwendung des Replikations-Managers, um ein Objekt nicht replizierbar zu machen, wird im Abschnitt »Eine Datenbank mit Hilfe des Replikations-Managers replizieren« behandelt. Den erforderlichen Code, um ein Objekt mit der Eigenschaft KeepLocal zu versehen und den Wert der Eigenschaft auf True zu setzen, finden Sie in Abschnitt »Replikation mittels Code implementieren«.

23.10 Zusätzliche Replikate erstellen Nachdem Sie ein Replikat angelegt haben, wollen Sie vermutlich noch weitere erstellen. Diese zusätzlichen Replikate sind Kopien, welche in der gesamten Organisation verteilt werden können. Sie lassen sich mit Hilfe der Access-Benutzerschnittstelle, des Windows-Aktenkoffers, des Replikations-Managers oder mittels VBA-Code erstellen. Eine Verkaufsorganisation zum Beispiel braucht vielleicht mehrere Replikate für Verkaufsmitarbeiter, die Kopien der Datenbank auf ihren Notebooks mitnehmen. Jede davon muss ein durch Replikation erzeugtes Replikat sein, keine vom Betriebssystem angelegte Kopie, sonst lässt sich die Arbeit der Verkaufsmitarbeiter nicht mit der der anderen Mitarbeiter synchronisieren. Replikate lassen sich mit allen vier genannten Methoden anlegen, aber zusätzliche Replikate können auch von jedem Mitglied der Replikatgruppe angefertigt werden. Jede Replikatgruppe ist von den anderen Replikatgruppen unabhängig. Replikate aus unterschiedlichen Replikatgruppen lassen sich nicht miteinander synchronisieren.

23.10.1 Zusätzliche Replikate mit Hilfe der Benutzerschnittstelle anlegen Um mit Hilfe der Benutzerschnittstelle zusätzliche Replikate anzulegen, unternehmen Sie Folgendes: 1. Öffnen Sie die Datenbank, die Sie replizieren wollen. 2. Wählen Sie EXTRAS|REPLIKATION|DATENBANK IN REPLIKAT KONVERTIEREN. 3. Geben Sie, wenn Sie dazu aufgefordert werden, einen Namen für das neue Replikat ein.

848

Kapitel 23: Replikation leicht gemacht

23.10.2 Zusätzliche Replikate mit Hilfe des Windows-Aktenkoffers anlegen Außerdem können Sie weitere Replikate anlegen, indem Sie den Designmaster – oder eines der Replikate – in den Aktenkoffer ziehen und dort ablegen. Wenn Sie den Designmaster wählen, werden Sie von einem Dialogfeld gefragt, ob der Designmaster oder das Replikat im Aktenkoffer abgelegt werden soll.

23.11

Replikate synchronisieren

Replikate zu »synchronisieren« bedeutet, alle Änderungen miteinander in Einklang zu bringen. Modifizierte Datensätze werden in allen Kopien geändert, gelöschte Datensätze werden aus allen Replikaten entfernt und hinzugefügte Datensätze werden an alle Replikate angehängt. Die Synchronisationsfähigkeit ist das, was die Replikation von Daten nützlich macht. Ergänzungen, Modifikationen und Löschungen werden an alle Replikate einer Gruppe weitergegeben und die Benutzer bekommen zu sehen, was andere Benutzer geändert haben. Wie beim Erstellen eines Replikats stellt Access Ihnen zum Synchronisieren der Replikate vier Methoden zur Verfügung: die Access-Benutzerschnittstelle, den Windows-Aktenkoffer, den Replikations-Manager und VBA-Code.

23.11.1 Datenbanken mit Hilfe der Access-Benutzerschnittstelle synchronisieren Um die Synchronisierung mit Hilfe der Access-Benutzerschnittstelle durchzuführen, unternehmen Sie Folgendes: 1. Wählen Sie EXTRAS|REPLIKATION|JETZT SYNCHRONISIEREN. 2. Das Dialogfeld DATENBANK SYNCHRONISIEREN wird eingeblendet (siehe Abbildung 23.11). Markieren Sie die zu synchronisierende Datenbank und klicken Sie auf OK. 3. Sie werden aufgefordert, Access die Datenbank vor der Synchronisierung schließen zu lassen (siehe Abbildung 23.12). Wenn Sie JA wählen, schließt Access die Datenbank und öffnet sie dann erneut.

23.11.2 Datenbanken mit Hilfe des Windows-Aktenkoffers synchronisieren Die zweite Möglichkeit, Replikate zu synchronisieren, bietet der Windows-Aktenkoffer. Öffnen Sie einfach das Aktenkofferfenster und wählen Sie die Datenbankdatei aus. Klicken Sie im Aktenkoffermenü auf AUSWAHL AKTUALISIEREN. Wenn Sie alle

Replikate synchronisieren

849

Abbildung 23.11: Im Dialogfeld Datenbank synchronisieren können Sie die zu synchronisierende Datenbank auswählen Abbildung 23.12: Dieses Dialogfeld bestätigt, dass Sie Access erlauben, die Datenbank vor der Synchronisierung zu schließen

im Aktenkoffer befindlichen Replikate synchronisieren wollen, klicken Sie auf ALLES AKTUALISIEREN, um das Dialogfeld AKTENKOFFER AKTUALISIEREN zu öffnen (siehe Abbildung 23.13). Klicken Sie auf AKTUALISIEREN und die Synchronisierung wird abgeschlossen.

Abbildung 23.13: Das Dialogfeld Aktenkoffer aktualisieren erscheint, wenn Sie die Synchronisierung vom Aktenkoffer aus vornehmen

850

23.12

Kapitel 23: Replikation leicht gemacht

Replikationskonflikte beheben

Wenn die Jet-Engine versucht, zwei Datenbanken zu synchronisieren, stellt sie möglicherweise fest, dass dieselbe Zeile in beiden Datenbanken geändert wurde, so dass sich ein Konflikt ergibt, der bearbeitet werden muss. In der Regel gewinnt meistens die Datenbank, in der die Zeile am häufigsten geändert wurde. Wenn sich beide Zeilen genauso oft geändert haben, entscheidet der Zufall. Das klingt möglicherweise erschreckend, ist aber nicht so schlimm, wie es scheint, weil Sie dem Benutzer mitteilen können, welche Änderungen nicht berücksichtigt wurden. Sie müssen erfahren, ob zwei Mitglieder der Replikatgruppe widersprüchliche Informationen enthalten. Möglicherweise haben zwei Benutzer im Außendienst unterschiedliche Informationen über einen Verkauf oder einen Kunden eingegeben. Deshalb ist es wichtig, dass das Programm diese Inkonsistenzen erkennt und eine Methode für die Behandlung solcher Fälle besitzt. Wenn es Konflikte gibt, werden Sie darüber informiert, wenn Sie versuchen, die Datenbank, welche die Konflikte enthält, zu öffnen (siehe Abbildung 23.14). Sie haben dann die Möglichkeit, die Konflikte zu lösen (oder auch nicht). Abbildung 23.14: Dieses Dialogfeld warnt vor Synchronisierungskonflikten

Wenn der Benutzer JA wählt, versucht die Jet-Engine, die Konflikte zu identifizieren. Danach wird das Dialogfeld MICROSOFT-REPLIKATIONSKONFLIKT-VIEWER eingeblendet (siehe Abbildung 23.15). Beachten Sie, dass die Jet-Engine in diesem Fall einen Konflikt in der Tabelle tblClients festgestellt hat. Der Benutzer kann diesen entweder beheben oder die Konfliktlösung aufschieben. Wenn der Benutzer auf ANZEIGEN klickt, erscheint ein weiteres Dialogfeld MICRO(siehe Abbildung 23.16), welches jeden Datensatz mit einem Konflikt anzeigt und die Möglichkeit bietet, vorhandene oder korrigierte Daten beizubehalten bzw. mit Konfliktdaten oder mit korrigierten Daten zu überschreiben.

SOFT-REPLIKATIONSKONFLIKT-VIEWER

Der Benutzer kann die Details des Konflikts zum späteren Nachlesen aufzeichnen und die Lösung der einzelnen Konflikte sofort vornehmen oder aufschieben. Nachdem alle Konflikte abgearbeitet sind, kehrt er zum Dialogfeld MICROSOFT-REPLIKATIONSKONFLIKT-VIEWER zurück.

Replikationskonflikte beheben

851

Abbildung 23.15: Verwenden Sie das Dialogfeld MicrosoftReplikationskonflikt-Viewer zur Lösung von Konflikten zwischen Tabellen

Abbildung 23.16: In diesem Dialogfeld Microsoft-ReplikationskonfliktViewer sehen Sie sich bestimmte Konflikte an und beheben sie

852

Kapitel 23: Replikation leicht gemacht

Wenn Ihre Benutzer kein so hohes Maß an Kontrolle über die Lösung von Konflikten bekommen sollen, können Sie Code schreiben, der Konflikte auf jede von Ihnen gewünschte Weise behebt. Dies wird im Abschnitt »Eine Datenbank mit Hilfe von Code synchronisieren« behandelt.

23.13

Den Replikations-Manager verwenden

Der Replikations-Manager ist ein leistungsfähiges Werkzeug, mit dessen Hilfe Sie die Vorteile der Replikation in Access 2000 vollständig ausnutzen können. Er wird nur zusammen mit Microsoft Office 2000 Developer als Entwicklungswerkzeug geliefert und bietet im Wesentlichen folgende Vorteile:

 Datenbanken lassen sich mühelos replizieren.  Zusätzliche Replikate sind einfach zu erstellen.  Er gibt Ihnen die Möglichkeit, alle Replikate der Gruppe zu synchronisieren.  Er ermöglicht automatisches Synchronisieren nach Zeitplan.  Der Replikationsverlauf eines Objekts kann eingesehen werden.  Replikationseigenschaften sind einfach zu verwalten.  Er ermöglicht das Synchronisieren mit Replikaten an entfernten Standorten.  Er erlaubt das Synchronisieren über ein lokales Netzwerk, ein Intranet oder das Internet.

23.13.1 Den Replikations-Manager zum ersten Mal ausführen Der Replikations-Manager lässt sich über eine Desktop-Verknüpfung oder über das Windows-Startmenü (Programmgruppe MICROSOFT OFFICE 2000 DEVELOPER) öffnen. Wenn Sie den Replikations-Manager zum ersten Mal ausführen, erscheint der Configure Replication Manager Wizard. (siehe Abbildung 23.17). 1. Klicken Sie auf NEXT, um den Konfigurationsprozess und den Configure Replication Manager Wizard zu starten. 2. Dieser Schritt des Configure Replication Manager Wizard fragt, ob Sie indirekte Synchronisierung unterstützen wollen (siehe Abbildung 23.18). Dabei öffnet jeweils ein Synchronizer für jedes der beiden Replikate sein Replikat lokal. Ein stationärer Rechner hinterlässt Änderungen in einem Ablagefeld im Netzwerk. Wenn das Notebook Verbindung zum Netzwerk aufnimmt, findet sein Synchronizer die Änderungen in seinem Ablageordner vor und wendet sie auf das Replikat an. Es hinterlässt seine Änderungen seinerseits in einem Ablageordner des Synchronizers für den stationären Rechner, welcher die Änderungen vorfindet

Den Replikations-Manager verwenden

853

Abbildung 23.17: Der Configure Replication Manager Wizard

und anwendet. Dies ist die bevorzugte Synchronisierungsmethode für entfernte Benutzer, die nicht ständig beim Netzwerk angemeldet sind. Treffen Sie Ihre Wahl und klicken Sie auf NEXT.

Abbildung 23.18: Auswahl einer Synchronisierungsmethode

3. Wenn Sie sich für indirekte Synchronisierung entscheiden, informiert Sie der nächste Schritt des Assistenten über Synchronisierungsarten. Klicken Sie nach dem Lesen auf NEXT. Dann fragt der Assistent nach einem Speicherort für den Ablageordner (siehe Abbildung 23.19). Wählen Sie einen Ordner aus und klicken Sie auf NEXT.

854

Kapitel 23: Replikation leicht gemacht

Abbildung 23.19: Auswahl eines Speicherortes, an dem der Synchronizer Änderungen ablegen kann

4. Dann werden Sie gefragt, ob der Rechner, auf dem der Assistent läuft, ein Internetserver ist. Treffen Sie Ihre Wahl und klicken Sie auf NEXT. 5. Wenn Sie diese Frage bejahen, werden Sie gefragt, ob Sie ihn zur Synchronisierung replizierter Datenbanken einsetzen wollen. Wenn Sie mit YES antworten und auf NEXT klicken, werden Sie nach seinem Namen gefragt. Geben Sie den Namen ein und klicken Sie auf NEXT (siehe Abbildung 23.20). Im nächsten Schritt sollen Sie einen gemeinsam genutzten Ordner und einen Freigabenamen angeben, der bei der Synchronisierung über das Internet verwendet wird. Klicken Sie auf NEXT. Sie werden nach einem FTP-Aliasnamen gefragt. Wählen Sie einen und klicken Sie auf NEXT.

Abbildung 23.20: Wenn Ihr Rechner ein Internetserver ist, können Sie dem Assistenten hier seinen TeilURL nennen

Den Replikations-Manager verwenden

855

6. Der nächste Schritt des Assistenten für die Konfiguration des ReplikationsManagers fordert Sie auf, den Ordner zu nennen, in dem die Synchronisierungsversuche stattfinden sollen. Das Beispiel in Abbildung 23.21 zeigt, dass indirekte Synchronisierung versucht werden soll. Wenn dies nicht gelingt, wird direkte Synchronisierung versucht und dann als letzte Möglichkeit Synchronisierung über das Internet. 7. Wählen Sie einen Speicherort für die Protokolldatei, die zum Aufzeichnen wichtiger Vorkommnisse während der Synchronisierung dient (siehe Abbildung 23.22) und klicken Sie auf NEXT.

Abbildung 23.21: Wählen Sie die Reihenfolge, in der die Synchronisierungsmethoden versucht werden sollen

8. Im nächsten Schritt fragt der Assistent nach einem Namen für den Synchronizer, der für ein Symbol und als aussagekräftige Bezeichnung für diesen verwendet werden soll. Außerdem wird gefragt, ob der Synchronizer automatisch beim Start von Windows gestartet werden soll (siehe Abbildung 23.23). Der Synchronizer muss in Betrieb sein, damit Synchronisierung nach Zeitplan stattfinden kann; möglicherweise wollen Sie also diese Option aktivieren. Geben Sie einen Namen für den Synchronizer und Ihre Wahl in bezug auf den automatischen Start ein und klicken Sie auf NEXT. 9. Klicken Sie auf FINISH, um den Vorgang abzuschließen. Nachdem Sie mit dem Assistenten für die Konfiguration des Replikations-Managers fertig sind, können Sie entweder eine Datenbank in einen Designmaster umwandeln oder ein neues Replikat anlegen (siehe Abbildung 23.24). Diese Aufgaben können Sie jederzeit durchführen. Deshalb sollten Sie auf CLOSE klicken.

856

Kapitel 23: Replikation leicht gemacht

Abbildung 23.22: Auswahl eines Namens und eines Speicherortes für die Protokolldatei

Abbildung 23.23: Auswahl eines Namens für den Synchronizer

Wenn Sie sich dafür entschieden haben, den Synchronizer bei jedem WindowsStart zu laden, jedoch ohne ihn automatisch auszuführen, müssen Sie das Synchronizer-Symbol aus dem Windows-Startordner entfernen.

23.13.2 Eine Datenbank mit Hilfe des Replikations-Managers replizieren Außer mit Hilfe der Access-Benutzerschnittstelle oder des Windows-Aktenkoffers können Sie eine Datenbank auch mit Hilfe des Replikations-Managers replizierbar

Den Replikations-Manager verwenden

857

Abbildung 23.24: Der Microsoft ReplikationsManager wird zum ersten Mal gestartet.

machen. Dieser bietet zusätzliche Optionen wie z.B. die Kennzeichnung eines Objekts als lokal. Folgende Schritte sind erforderlich: 1. Klicken Sie im Replikations-Manager auf die Schaltfläche CONVERT DATABASE TO THE DESIGN MASTER in der Symbolleiste oder wählen Sie DATEI|CONVERT DATABASE TO DESIGN MASTER. Das Dialogfeld DATABASE TO CONVERT TO THE DESIGN MASTER wird eingeblendet (siehe Abbildung 23.25).

Abbildung 23.25: Wählen Sie die Datenbank aus, die Designmaster werden soll

2. Wählen Sie eine zu konvertierende Datei und klicken Sie auf OK. 3. Sie gelangen in den Convert Database to Design Master Wizard. Klicken Sie auf NEXT, nachdem Sie die einführenden Informationen gelesen haben. 4. Geben Sie an, ob Sie eine Sicherungskopie der Datenbank anlegen wollen, bevor Sie sie zum Designmaster konvertieren. Klicken Sie auf NEXT. Es ist immer günstig, eine Kopie der noch nicht replizierten Datenbank aufzubewahren.

858

Kapitel 23: Replikation leicht gemacht

5. Geben Sie eine Beschreibung der neuen Replikatgruppe ein und klicken Sie auf NEXT. Alle von diesem Designmaster angefertigten Replikate sind Mitglieder der Replikatgruppe, die Sie anlegen (siehe Abbildung 23.26).

Abbildung 23.26: Eingabe einer Beschreibung für die Replikatgruppe

6. Dann werden Sie gefragt, ob Sie alle Objekte für die Replikatgruppe verfügbar machen oder einige als lokal kennzeichnen wollen (siehe Abbildung 23.27). Wenn Sie auf MAKE ALL OBJECTS AVAILABLE TO THE ENTIRE REPLICA SET und danach auf die Schaltfläche CHOOSE OBJECTS klicken, wird das Dialogfeld SELECT REPLICATED OBJECTS eingeblendet, damit Sie die ausgewählten Objekte als lokal kennzeichnen können (siehe Abbildung 23.28). Um ein Objekt als lokal zu kennzeichnen, entfernen Sie die Markierung aus dem Kontrollkästchen. Klicken Sie auf OK, wenn Sie fertig sind. 7. Als nächstes geben Sie an, ob die Replikate schreibgeschützt sein sollen (Abbildung 23.29). Der Designmaster ist die einzige Stelle, an der Sie Schemaänderungen vornehmen können. Wenn Sie auch Datenänderungen auf den Designmaster beschränken wollen, aktivieren Sie die Option, die alle Replikate mit Schreibschutz versieht. Im Allgemeinen sollten Sie die Standardoption I WANT TO BE ABLE TO CREATE READ/WRITE REPLICAS beibehalten. Klicken Sie nach der Auswahl auf NEXT. 8. Im nächsten Schritt des Assistenten werden Sie gefragt, ob Sie die Synchronisierung des Designmasters mit dem auf dem aktuellen Rechner vorliegenden Synchronizer verwalten wollen. Wenn Sie mit NO antworten, muss die Synchronisierung von einem anderen verwalteten Mitglied der Replikatgruppe ausgehen. Treffen Sie Ihre Wahl und klicken Sie auf NEXT.

Den Replikations-Manager verwenden

859

Abbildung 23.27: Sollen alle oder nur einige Objekte repliziert werden?

Abbildung 23.28: Objekte als lokal oder repliziert kennzeichnen

9. Klicken Sie auf FINISH, um den Assistenten zu beenden. Anschließend werden Sie über den Erfolg bzw. etwaige Probleme während der Konvertierung informiert.

860

Kapitel 23: Replikation leicht gemacht

Abbildung 23.29: Sollen Replikate mit Leseund Schreibzugriff erstellt werden können?

Eine Tabelle kann nicht als lokal gekennzeichnet werden, wenn sie in Beziehung zu einer replizierten Tabelle steht.

Wenn Sie mehr als eine Replikatgruppe besitzen, müssen Sie das Symbol MANAGED REPLICAS in der Symbolleiste REPLICATION MANAGER verwenden, um eine andere Replikatgruppe anzuzeigen. Es kann jeweils nur eine Replikatgruppe angezeigt werden.

23.13.3 Replikate mit Hilfe des Replikations-Managers erstellen Genauso, wie Sie Replikate mit Hilfe der Access-Benutzerschnittstelle oder des Windows-Aktenkoffers erstellen können, können Sie dazu auch den Replikations-Manager verwenden. Dazu unternehmen Sie Folgendes: 1. Klicken Sie in der Symbolleiste auf NEW REPLICA und dann auf NEXT. 2. Wählen Sie eine Quelle und ein Ziel für das Replikat aus. Die Quelle ist der Name der zu replizierenden Datenbank, das Ziel der Name des Replikats. Klicken Sie auf NEXT. 3. Geben Sie an, ob es möglich sein soll, im Replikat Daten zu ändern. Klicken Sie auf NEXT. 4. Geben Sie an, ob das Replikat vom Synchronizer auf dem aktuellen Rechner verwaltet werden soll. Klicken Sie auf NEXT. 5. Klicken Sie auf FINISH.

Den Replikations-Manager verwenden

861

Wenn Sie ein Replikat einer Datenbank anlegen, die von einem anderen Synchronizer verwaltet wird, müssen Sie diesen Synchronizer mit dem ReplikationsManager auf dem anderen Rechner konfigurieren.

23.13.4 Replikate mit Hilfe des Replikations-Managers synchronisieren Genauso, wie Sie Replikate mit Hilfe der Access-Benutzerschnittstelle oder des Windows-Aktenkoffers synchronisieren können, können Sie dazu auch den Replikations-Manager verwenden, wenn Sie Folgendes unternehmen: 1. Klicken Sie in der Symbolleiste des Replikations-Managers auf SYNCHRONIZE NOW. 2. Das Dialogfeld SYNCHRONIZE NOW wird eingeblendet (siehe Abbildung 23.30). Dort können Sie Einzelheiten der Synchronisierung festlegen. Wenn Sie fertig sind, klicken Sie auf OK, um den Synchronisierungsvorgang abzuschließen.

Abbildung 23.30: Im Dialogfeld Jetzt synchronisieren können Sie Einzelheiten der Synchronisierung festlegen

Entfernte Synchronisierung Möglicherweise sind Sie überrascht, dass das Topologiefenster des ReplikationsManagers nur einen Rechner anzeigt, obwohl Sie viele Replikate besitzen. Für jeden Synchronizer der Replikatgruppe erscheint ein Symbol. Abbildung 23.31 zeigt zwei an der Replizierung beteiligte Synchronizer: ALEXIS und DELL. Der zweite Standort wurde durch Installation des Replikations-Managers auf dem zweiten Rechner eingerichtet. Dann kann jedes Replikat vom lokalen Standort an den entfernten Standort verschoben werden, indem man eine Verbindung zu diesem errichtet und FILE|MOVE REPLICA wählt. Sie können den verwalteten Ordner am entfernten Standort suchen und das Replikat in diesen verschieben. Wenn beide Standorte im Topologiefenster der Replikation erscheinen, können Sie die Synchronisierung mit Hilfe der Verknüpfungslinie erledigen, die sie verbindet.

862

Kapitel 23: Replikation leicht gemacht

Abbildung 23.31: Das Topologiefenster des Replikations-Managers zeigt zwei Synchronizer

Sie können auf die Linie doppelklicken und SYNCHRONIZE NOW wählen oder mit EDIT SCHEDULE einen Zeitplan für die Synchronisierung einrichten. Synchronisierung nach Zeitplan wird im nächsten Abschnitt behandelt. Synchronisierung nach Zeitplan Synchronisierung zwischen Replikaten, die vom selben Synchronizer oder von zwei unterschiedlichen Synchronizern verwaltet werden, lässt sich nach Zeitplan durchführen. Um Synchronisierung zwischen Replikaten mit demselben Synchronizer zeitlich geplant zu erledigen, klicken Sie mit der rechten Maustaste auf das Symbol für den lokalen Synchronizer und wählen EDIT LOCALLY MANAGED REPLICA SCHEDULE (siehe Abbildung 23.32). Dort können Sie Tag und Uhrzeit für die Synchronisierung wählen. Um die Synchronisierung zwischen zwei verschiedenen Synchronizern nach Zeitplan durchzuführen, klicken Sie mit der rechten Maustaste auf die Verbindungslinie und wählen EDIT SCHEDULE, um das gleichnamige Dialogfeld zu öffnen. Dort können Sie die Einzelheiten der Synchronisierung zwischen den beiden Standorten zeitlich festlegen. Die Schattierung der beiden Felder zeigt an, welcher Synchronizer den Austausch anstößt. Wenn beim Start des Austausches keine Verbindung hergestellt werden kann, speichert der Ablageordner ein temporäres Protokoll der Änderungen. Alle 15 Minuten wird ein neuer Versuch unternommen, bis die Verbindung steht.

Den Replikations-Manager verwenden

863

Abbildung 23.32: Im Dialogfeld Edit Schedule können Sie Tag und Uhrzeit für die Synchronisierung der Replikate auswählen

23.13.5 Den Synchronisierungsverlauf untersuchen Der Synchronisierungsverlauf kann sehr hilfreich sein. Er liefert Ihnen nicht nur eine Spur für die Prüfung, sondern trägt auch zur Analyse der Wirksamkeit der Topologie und des Synchronisierungszeitplans bei, die Sie gewählt haben. Der Replikations-Manager unterhält drei Arten von Protokollen:

 Den lokalen Synchronisierungsverlauf  Den entfernten Synchronisierungsverlauf  Das Synchronizer-Protokoll Um den lokalen Synchronisierungsverlauf zu sehen, klicken Sie mit der rechten Maustaste auf das Symbol des lokalen Rechners und wählen View Local Synchronization History. Damit wird das Dialogfeld Synchronization History angezeigt (siehe Abbildung 23.33), das Ihnen Einzelheiten über den Informationsaustausch zwischen den lokalen Replikaten aufzeigt. Um den entfernten Synchronisierungsverlauf anzuzeigen, markieren Sie die Verbindungslinie, die zwei Synchronizer verbindet und wählen VIEW|SYNCHRONIZATION HISTORY, um das Dialogfeld SYNCHRONIZATION HISTORY zu öffnen. Wenn Sie mehr Informationen über einen der Protokolleinträge wünschen, klicken Sie auf DETAILS, um das Dialogfeld SYNCHRONIZATION DETAILS einzublenden (siehe Abbildung 23.34).

23.13.6 Mit Synchronisierungseigenschaften arbeiten Sie können sich auch Eigenschaften des gewählten Synchronizers ansehen. Dazu doppelklicken Sie auf den Synchronizer und das Fenster REPLICA PROPERTIES wird eingeblendet. Dieses mit Registerkarten versehene Dialogfeld übermittelt interessante Informationen über den gewählten Synchronizer.

864

Kapitel 23: Replikation leicht gemacht

Abbildung 23.33: Der lokale Synchronisierungsverlauf

Abbildung 23.34: Das Dialogfeld Synchronization Details zeigt Einzelheiten eines Synchronisierungsverlaufs

Partielle Replikation

865

Jet 4.0 und Access 2000 unterstützen Synchronisierung über das Internet oder ein Intranet. Sie legen ein Replikat auf einem Server ab und synchronisieren mit Hilfe des Replikations-Managers über eine übliche HTTP-Verbindung. Dieser Vorgang wird in Kapitel 31 behandelt.

23.14 Partielle Replikation Jet 3.5 und Access 97 haben die »partielle Replikation« eingeführt, d.h., dass nur eine Teilmenge der Daten repliziert wird. Das ist sinnvoll, wenn beispielsweise mehrere Verkäufer vorhanden sind und jeder nur seine eigenen Daten haben soll. Alle Verkäufer sollen jedoch ihre Änderungen mit anderen Datenbanken im Netzwerk synchronisieren können. Partielle Replikate lassen sich mit Hilfe des Assistenten für partielle Replikation erstellen, der über die Access-Benutzerschnittstelle oder VBACode zu erreichen ist. Die Prozedur der Erstellung eines Teilreplikats mittels VBACode wird im Abschnitt »Ein partielles Replikat mittels Code erstellen« dargestellt, der Assistent für partielle Replikation in diesem Abschnitt. Um ein Teilreplikat zu erstellen, unternehmen Sie Folgendes: 1. Wählen Sie in Microsoft Access, während die zu replizierende Datenbank geöffnet ist, EXTRAS|REPLIKATION|TEILREPLIKATIONS-ASSISTENT. Dies startet den Teilreplikations-Assistenten. 2. Legen Sie fest, ob ein neues Teilreplikat angelegt oder ein bestehendes modifiziert werden soll (siehe Abbildung 23.35). Klicken Sie auf WEITER.

Abbildung 23.35: Legen Sie fest, ob ein neues Teilreplikat angelegt oder ein bestehendes modifiziert werden soll

866

Kapitel 23: Replikation leicht gemacht

3. Geben Sie Namen und Speicherort für das Teilreplikat an. Klicken Sie auf WEITER. 4. Erstellen Sie einen Filterausdruck, der die im Teilreplikat enthaltenen Daten einschränkt. Dazu markieren Sie die Tabelle, deren Daten gefiltert werden sollen, das Feld, das Sie als Kriterium verwenden wollen und den Operator für den Ausdruck. Klicken Sie auf EINFÜGEN. Um den Ausdruck zu vervollständigen, geben Sie den Wert ein, den Sie zur Einschränkung der im Teilreplikat enthaltenen Daten verwenden wollen. Sie können die Auswahl mit AND und OR nach Bedarf erweitern oder verfeinern. Abbildung 23.36 zeigt einen Filterausdruck, der ein Teilreplikat mit Daten nur für Kunden im Staat Kalifornien erstellt. Klicken Sie auf WEITER.

Abbildung 23.36: Legen Sie den Filterausdruck für die Einschränkung der im Teilreplikat enthaltenen Daten fest

5. Der nächste Schritt des Assistenten für Teilreplikate ist sehr wichtig. Er ermöglicht die Angabe weiterer Tabellen, die in das Teilreplikat aufgenommen werden sollen. Tabellen in fetter Schrift besitzen eine Beziehung zu der Tabelle, deren Kriterien Sie für die Erstellung des Teilreplikats verwenden. Sie müssen die Markierung dieser Tabellen aufheben, damit nur Datensätze mit einer Beziehung zu den Datensätzen in Ihrem Filter in das Teilreplikat aufgenommen werden. Tabellen, die nicht in fetter Schrift dargestellt werden, besitzen keine Beziehung zu der gefilterten Tabelle und es wird keine referentielle Integrität erzwungen. Es ist Ihre Sache, ob die Daten in diesen Tabellen ohne Beziehung in das Replikat aufgenommen werden sollen. In Abbildung 23.37 wurden die Markierungen bei allen verknüpften Tabellen entfernt, nicht aber für die nicht verknüpfte Tabelle, d.h., dass verknüpfte Daten für alle Tabellen aufgenommen werden, für die refe-

Replikation mittels Code implementieren

867

rentielle Integrität eingerichtet wurde, während die Tabelle tblCompanyInfo als ganze aufgenommen wird. 6. Zuletzt können Sie noch festlegen, ob Access einen Bericht mit allen Eigenschaftseinstellungen anfertigen soll, die für das Teilreplikat gelten. Treffen Sie Ihre Wahl und klicken Sie auf FERTIG STELLEN.

Abbildung 23.37: Legen Sie fest, welche weiteren Daten in das Teilreplikat aufgenommen werden

23.15

Replikation mittels Code implementieren

Die meisten Replikationsfunktionen lassen sich auch mittels Code implementieren, aber dies ist nicht die einfachste Möglichkeit, Replikation durchzuführen. Vielleicht wollen Sie aber gelegentlich bestimmte Aspekte des Replikationsvorgangs mittels Code implementieren, damit Sie den Vorgang und die Schnittstelle besser aus der Anwendung heraus steuern können. Alle folgenden Beispiele setzen die Objektbibliothek Jet Replication Objects (JRO) voraus. Um auf diese zuzugreifen, müssen Sie die Microsoft Jet and Replication Objects 2.1 Library über EXTRAS|VERWEISE im VBE auswählen. Die Datenbank, welche die JRO-Bibliothek benötigt, muss geöffnet sein.

868

Kapitel 23: Replikation leicht gemacht

23.15.1 Eine Datenbank mittels Code replizierbar machen Die in Listing 23.1 gezeigte Routine, welche sich in der Datenbank Chap23Ex befindet, macht eine Datenbank mittels Code replizierbar.

Listing 23.1:

Eine Datenbank replizierbar machen

Sub MakeReplicable(strMaster As String) Dim rep As JRO.Replica Set rep = New JRO.Replica rep.MakeReplicable strMaster, True Set rep = Nothing End Sub

Diese Routine übernimmt den Pfad zu einer beliebigen Datenbank als Parameter. Zuerst legt sie ein JRO-Objekt Replica an. Mit Hilfe der Methode MakeReplicable des Objekts Replica wird die Datenbank in einen Designmaster konvertiert. Die Methode übernimmt den Namen der Datenbank, die konvertiert werden soll und einen optionalen Parameter, mit dessen Hilfe Sie angeben können, ob der Master Verfolgung auf Spaltenebene anwenden soll (siehe Hinweis). Vor Access 2000 entstanden Konflikte auf Datensatzebene, d.h., dass ein Konflikt entstand, wenn zwei Benutzer unterschiedliche Felder desselben Datensatzes änderten. Access 2000 führt Verfolgung auf Spaltenebene ein, d.h., dass kein Konflikt entsteht, wenn zwei Benutzer unterschiedliche Felder desselben Datensatzes ändern. Konflikte treten nur auf, wenn zwei Benutzer dasselbe Feld eines Datensatzes ändern. Verfolgung auf Spaltenebene ist ein optionales Merkmal, das standardmäßig aktiv ist und nur bei replikationsfähigen Datenbanken zur Verfügung steht.

23.15.2 Ein Objekt als lokal kennzeichnen Normalerweise werden alle Objekte einer Datenbank in den Replikationsvorgang eingeschlossen. Der Code in Listing 23.2 veranschaulicht, wie man ein Datenbankobjekt als lokal kennzeichnet und zwar in diesem Fall die Tabelle tblEmployee. Listing 23.2:

Ein Objekt als lokal kennzeichnen

Sub MakeLocal(strDatabase As String, _ strName As String, _ strObjType As String)

Replikation mittels Code implementieren

869

Dim rep As New JRO.Replica rep.ActiveConnection = strDatabase rep.SetObjectReplicability strName, strObjType, False Set rep = Nothing End Sub

Zuerst wird ein JRO-Replica-Objekt deklariert. Die Eigenschaft ActiveConnection dieses Objekts wird mit einem Zeiger auf die Datenbank versehen, deren Objekt als lokal gekennzeichnet werden soll. Mit der Methode SetObjectReplicability des Replica-Objekts wird ein Datenbankobjekt als lokal gekennzeichnet. Sie übernimmt den Namen und den Typ des betreffenden Objekts. Da der Code die Replizierbarkeit auf False setzt, ist das Objekt als lokal gekennzeichnet.

23.15.3 Ein Replikat mittels Code erstellen Ein neues Replikat lässt sich mit Hilfe der Methode CreateReplica des Objekts Replica erstellen. Sie sehen den Code dafür in Listing 23.3. Listing 23.3:

Ein Replikat anlegen

Sub MakeReplica(strMaster As String, strReplica As String) Dim rep As JRO.Replica Set rep = New JRO.Replica rep.ActiveConnection = strMaster rep.CreateReplica strReplica, "Replica of " & strMaster End Sub

Er übernimmt zwei Parameter. Der erste enthält Pfad und Dateinamen für den Designmaster, der zweite Pfad und Dateinamen für das Replikat. Dann wird die Methode CreateReplica für das Objekt Replica ausgeführt. Der erste Parameter für diese Methode ist der Name des zu erstellenden Replikats, der zweite der Name des Designmasters. Weitere optionale Parameter betreffen den Typ, die Sichtbarkeit, die Priorität und die Aktualisierbarkeit des zu erstellenden Replikats. Replikattypen Beim Erstellen eines Replikats dient der Parameter ReplicaType dazu, den Typ des zu erstellenden Replikats festzulegen. Ein Replikat kann als Designmaster, vollständiges Replikat, Teilreplikat oder nicht replizierbares Replikat angelegt werden. Sichtbarkeit von Replikaten Access 2000 und JRO führen eine neue Eigenschaft ein, die dazu dient, die Sichtbarkeit des Replikats anzugeben. Die Sichtbarkeit bestimmt, welche Replikate mit einem bestimmten Replikat synchronisiert werden können. Sie lässt sich nur bei der Erstellung des Replikats festlegen. Ein Replikat kann global, lokal oder anonym sein. Ein

870

Kapitel 23: Replikation leicht gemacht

globales Replikat kann mit allen Replikaten der Replikatgruppe synchronisiert werden. Standardmäßig sind alle Replikate global. Ein lokales Replikat kann nur mit seinem übergeordneten Replikat synchronisiert werden und ein übergeordnetes Replikat kann die Synchronisierung mit einem lokalen Replikat nach Zeitplan vornehmen. Es erledigt Replikationskonflikte und Fehler im Auftrag des lokalen Replikats. Ein lokales Replikat kann nur weitere lokale Replikate erstellen. Diese haben das übergeordnete Replikat mit dem lokalen Replikat gemeinsam. Alle anderen Replikate kennen das lokale Replikat nicht. Ein anonymes Replikat kann nur mit seinem übergeordneten Replikat synchronisiert werden. Anonyme Replikate sind angebracht, wenn ein Replikat selten an der Synchronisierung teilnimmt. Das anonyme Replikat gibt seine Identität für Aktualisierungen dem veröffentlichenden Replikat bekannt. Anonyme Replikate können nur weitere anonyme Replikate erstellen. Diese haben das übergeordnete Replikat mit dem anonymen Replikat gemeinsam. Priorität für Replikate Eine weitere neue Eigenschaft von Replikaten gibt die Priorität während der Synchronisierung an. Wenn während der Synchronisierung Konflikte auftreten, siegt das Replikat mit der höchsten Priorität. Aktualisierbarkeit von Replikaten Die Aktualisierbarkeit eines Replikats bestimmt, ob die in ihm enthaltenen Daten aktualisierbar sind. Das ist standardmäßig der Fall. Wenn die Eigenschaft auf den konstanten Wert jrRepUpdReadOnly gesetzt ist, ist nur Lesezugriff auf die Daten möglich.

23.15.4 Ein partielles Replikat mittels Code erstellen Auch ein Teilreplikat lässt sich mittels VBA-Code erstellen, wie Sie in Listing 23.4 sehen. Listing 23.4:

Ein Teilreplikat anlegen

Sub CreatePartialReplica() Dim repFull As New JRO.Replica Dim repPartial As New JRO.Replica repFull.ActiveConnection = "c:\My Documents\MyMaster.mdb" repFull.CreateReplica "c:\My Documents\CA Clients.mdb", _ "Partial Replica of MyMaster", _ jrRepTypePartial Set repFull = Nothing repPartial.ActiveConnection = "c:\My Documents\CA Clients.mdb"

Replikation mittels Code implementieren

871

repPartial.Filters.Append "tblClients", jrFilterTypeTable, _ "State = 'CA'" repPartial.Filters.Append "tblProjects", jrFilterTypeRelationship, _ "ClientProjects" repPartial.PopulatePartial "c:\My Documents\MyMaster.mdb" Set repPartial = Nothing End Sub

Zuerst stellt der Code eine Verbindung zum Master her. Mit Hilfe der Methode CreateReplica des Replica-Objekts wird ein Teilreplikat erstellt. Dann wird eine Verbindung zum Replikat eingerichtet. An das Replica-Objekt werden zwei Filter angehängt. Der erste füllt die Tabelle tblClients im Replikat mit allen Kunden, die im Staat Kalifornien wohnen, der zweite die Tabelle tblProjects mit allen Projekten, die mit Kunden im Staat Kalifornien verknüpft sind. Mit Hilfe der Methode PopulatePartial wird das Replikat mit den in den Filtern ermittelten Daten gefüllt.

23.15.5 Eine Datenbank mittels Code synchronisieren Gelegentlich wollen Sie die Synchronisierung vielleicht mittels VBA-Code durchführen. Die in Listing 23.5 gezeigte Routine synchronisiert die beiden als Parameter genannten Datenbanken. Die Konstante jrSyncTypeImpExp gibt an, dass Sie eine Synchronisierung in zwei Richtungen vornehmen wollen. Die Konstante jrSyncModeDirect legt fest, dass indirekte Synchronisierung stattfinden soll. Listing 23.5:

Zwei Datenbanken synchronisieren

Sub Synchronize(strDB1 As String, strDB2 As String) Dim rep As JRO.Replica rep.ActiveConnection = strDB1 rep.Synchronize strDB2, jrSyncTypeImpExp, jrSyncModeDirect Set rep = Nothing End Sub

23.15.6 Konflikte mittels Code beheben Mittels Code lassen sich auch Konflikte beheben (siehe Listing 23.6). Was Sie tun, wenn ein Konflikt festgestellt wird, richtet sich nach den geschäftlichen Bedürfnissen der Benutzer. Listing 23.6:

Konflikte mittels Code feststellen

Sub IdentifyConflicts(strConflictDB) Dim rep As New JRO.Replica Dim rst As ADODB.Recordset rep.ActiveConnection = strConflictDB Set rst = rep.ConflictTables

872

Kapitel 23: Replikation leicht gemacht

If rst.BOF And rst.EOF Then MsgBox "No Conflicts!!!" Else Do Until rst.EOF Debug.Print rst.Fields(0) rst.MoveNext Loop End If

End Sub

Diese Routine geht alle Tabellen durch und ermittelt, ob in der Tabelleneigenschaft ConflictTable etwas festgehalten ist. Wenn ja, wird von dort aus eine Datensatzgruppe geöffnet. Die Routine geht alle Datensätze der Konflikttabelle durch und zeigt den Wert des ersten Feldes im Testfenster an.

23.15.7 Für die Praxis Das Zeit- und Abrechnungssystem mit Replikation verwalten Sie müssen entscheiden, ob es erforderlich ist, Replikation in das Zeit- und Abrechnungssystem zu integrieren. Das könnte sehr sinnvoll sein, wenn Sie beispielsweise viele Berater haben, die im Außendienst tätig sind und unterwegs Informationen über Kunden, Projekte, Rechnungen und Ausgaben eingeben müssen. Mit dem, was Sie in diesem Kapitel gelernt haben, können Sie sicherstellen, dass alle Änderungen an den Datenbankexemplaren der einzelnen Berater jedesmal, wenn sich diese ins Büro einwählen, an die Datenbank auf dem Haupt-Server übermittelt werden. Replikation kann auch eingesetzt werden, um die von der Anwendung verwalteten Daten im Lauf des Tages zu aktualisieren, was das Risiko von Datenverlust und Ausfallzeiten minimiert. Schließlich wollen Sie vielleicht Replikation in die Anwendung integrieren, um die Arbeitsbelastung in Ihrer Organisation auf mehrere Server zu verteilen. Die möglichen Vorteile des Einsatzes von Replikation innerhalb der Beispielanwendung sind zahlreich. Mit dem, was Sie in diesem Kapitel gelernt haben, müssen Sie entscheiden, ob Replikation für Ihre Anwendung das Richtige ist und wie sie sich in Ihrer Organisation am besten einsetzen lässt.

Fortgeschrittene Programmierung

Teil IV

24 Fortgeschrittene VBA-Techniken 25 ActiveX-Steuerelemente 26 Automatisierung: Mit anderen Anwendungen kommunizieren 27 Die Leistungsfähigkeit des Windows-API ausschöpfen 28 Die Leistungsfähigkeit von Klassenmodulen nutzen 29 Eigene Bibliotheken erstellen 30 Generatoren, Assistenten und Menü-Add-Ins verwenden 31 Access und das Internet 32 Datenzugriffsseiten

Fortgeschrittene VBA-Techniken

Kapitel

Hier lesen Sie:

 Für erfahrene Programmierer  Was sind benutzerdefinierte Typen und wozu können sie verwendet werden?  Mit Konstanten arbeiten  Mit Datenfeldern arbeiten  Fortgeschrittene Methoden der Verwendung von Funktionen  Mit Empty und Null arbeiten  Benutzerdefinierte Auflistungen erstellen und verwenden  Kompilieroptionen verstehen und effektiv nutzen  Code-Module im- und exportieren  Mit Projekteigenschaften arbeiten

24.1

Für erfahrenere Programmierer

Die Programmiersprache Visual Basic for Applications (VBA) ist äußerst umfassend und leistungsfähig. In diesem Buch wird überall mit VBA gearbeitet, da die Sprache diverse Anwendungsmöglichkeiten bietet, doch dieses Kapitel konzentriert sich auf einige fortgeschrittene Techniken der Anwendungsentwicklung. Zu den behandelten Themen gehören Typen, Datenfelder, fortgeschrittene Techniken des Erstellens von Funktionen und Optionen für das Kompilieren von VBA-Programmen. Das Beherrschen dieser Themen hilft Ihnen dabei, erfolgreich als VBA-Programmierer zu arbeiten.

876

24.2

Kapitel 24: Fortgeschrittene VBA-Techniken

Was sind benutzerdefinierte Typen und wozu können sie verwendet werden?

Auf benutzerdefinierte Typen wurde bereits in Kapitel 14 kurz eingegangen. In Kapitel 14 wurde ein benutzerdefinierter Typ verwendet, um Informationen über aufgetretene Fehler zu speichern. Ein benutzerdefinierter Typ, der auch als struct oder record bezeichnet wird, ermöglicht Ihnen das Erstellen von Variablen für jeweils mehrere Informationen. Benutzerdefinierte Typen werden häufig verwendet, um die Informationen eines oder mehrerer Datensätze im Hauptspeicher abzulegen. Außerdem werden sie eingesetzt, um zusammengehörige Informationen zu speichern, die ansonsten in mehreren unabhängigen Variablen gespeichert werden würden. Da jedem Element eines benutzerdefinierten Typs ein eigener Datentyp zugewiesen werden kann, können die Datentypen solcher Elemente beispielsweise mit den Datentypen spezieller Felder einer Tabelle übereinstimmen. Ein benutzerdefinierter Typ könnte beispielsweise folgendermaßen strukturiert sein: Die nachfolgenden Code-Fragmente entstammen dem Modul basDataHandling. Public Type TimeCardInfo TimeCardDetailID As Long TimeCardID As Long DateWorked As Date ProjectID As Long WorkDescription As String * 255 BillableHours As Double BillingRate As Currency WorkCodeID As Long End Type

Beachten Sie, dass der jeweilige Datentyp der einzelnen Elemente explizit deklariert ist. Das Element, welches die Zeichenkette WorkDescription enthält, wurde mit einer Länge von 255 angegeben. Benutzerdefinierte Typen erhöhen die Übersichtlichkeit der Programmstruktur, da zusammengehörige Daten als Einheit gespeichert werden können. Sie existieren ausschließlich im Hauptspeicher und sind somit rein temporär. Besonders für Informationen, die vorübergehend zur Laufzeit verarbeitet werden sollen, sind benutzerdefinierte Typen deshalb hervorragend geeignet. Da sie sich bereits im Hauptspeicher befinden, können ihre Werte äußerst effizient ausgelesen und verändert werden.

Was sind benutzerdefinierte Typen und wozu können sie verwendet werden?

24.2.1

877

Deklarieren benutzerdefinierter Typen

Ein benutzerdefinierter Typ wird mit Hilfe einer Type-Anweisung deklariert, die im Deklarationsteil des entsprechenden Moduls anzugeben ist. In Standardmodulen können Typen als öffentlich oder privat deklariert werden, während dies in Formular- bzw. Berichtsmodulen nicht möglich ist. Dort lassen sich benutzerdefinierte Typen lediglich verwenden.

24.2.2

Erstellen einer Typvariablen

Eine Typvariable ist eine Instanz eines Typs im Hauptspeicher. Vor seiner Verwendung muss ein Typ deklariert werden. Um eine Typvariable zu deklarieren, erstellen Sie basierend auf dem Typ eine Local-, Private-, Module-Level- oder Public-Variable. Der Gültigkeitsbereich einer Typvariablen ergibt sich aus der Stelle, an der Sie die Deklaration vornehmen, und aus der Art der Deklaration (Dim, Private oder Public). Ansonsten gelten für Typvariablen die gleichen Regeln wie für alle sonstigen Arten von Variablen. Mit Hilfe der Dim-Anweisung wird im nachfolgend dargestellten Code eine Variable mtypTimeCardData erzeugt. Wenn Sie diese Dim-Anweisung im Allgemeinen Abschnitt des Moduls einfügen, steht die Variable für sämtliche Routinen dieses Moduls zur Verfügung. (Beachten Sie das m, welches darauf hinweist, dass die Deklaration auf Modulebene erfolgte.) Wenn Sie die Anweisung in eine Unterroutine oder Funktion einfügen, bleibt ihr Gültigkeitsbereich auf diese spezielle Routine beschränkt: Dim mtypTimeCardData As TimeCardInfo

24.2.3

Informationen eines Datensatzes in einem Formular in einer Variablen speichern

Nachdem eine Typvariable deklariert wurde, können Sie in jedem ihrer Elemente Daten ablegen. Der folgende Code des Formulars frmTimeCardHours speichert Informationen des Formulars in einer Typvariablen mtypTimeCardData. Diese Typvariable wurde im Abschnitt für allgemeine Deklarationen des Formulars als privat deklariert. Die Type-Struktur finden Sie im Modul basDataHandling. Private Sub cmdWriteToType_Click() mtypTimeCardData.TimeCardDetailID = Me.txtTimeCardDetailID mtypTimeCardData.TimeCardID = Me.txtTimeCardID mtypTimeCardData.DateWorked = Me.txtDateWorked mtypTimeCardData.ProjectID = Me.cboProjectID mtypTimeCardData.WorkDescription = Me.txtWorkDescription mtypTimeCardData.BillableHours = Me.txtBillableHours mtypTimeCardData.BillingRate = Me.txtBillingRate mtypTimeCardData.WorkCodeID = Me.cboWorkCodeID End Sub

878

Kapitel 24: Fortgeschrittene VBA-Techniken

Den in diesem Kapitel dargestellten Code finden Sie auf der diesem Buch beiliegenden CD-ROM in der Datenbank CHAP24EX.MDB. Der Vorteil dieses Codes besteht darin, dass für diese acht Elemente zusammengehöriger Informationen nicht acht Variablen erstellt werden, sondern lediglich eine, in der alle acht Elemente gespeichert werden können. Auf diese Weise bleibt alles klar und übersichtlich.

24.2.4

Informationen aus den Elementen einer Typvariablen abrufen

Um die in Ihrer Typvariablen enthaltenen Informationen abzurufen, verwenden Sie einfach den Variablennamen, gefolgt von einem Punkt und dem Namen des jeweiligen Elements. Der folgende Code stellt eine Meldung dar, welche sämtliche auf einer Stempelkarte enthaltenen Informationen umfasst: Private Sub cmdDisplayFromType_Click() MsgBox "Timecard Detail ID Is " & _ mtypTimeCardData.TimeCardDetailID & Chr(13) & _ "Timecard ID Is " & mtypTimeCardData.TimeCardID & Chr(13) & _ "Date Worked Is " & mtypTimeCardData.DateWorked & Chr(13) & _ "Project ID Is " & mtypTimeCardData.ProjectID & Chr(13) & _ "Work Description Is " & _ Trim(mtypTimeCardData.WorkDescription) & Chr(13) & _ "Billable Hours Is " & mtypTimeCardData.BillableHours & Chr(13) & _ "Billing Rate Is " & mtypTimeCardData.BillingRate & Chr(13) & _ "Workcode ID Is " & mtypTimeCardData.WorkCodeID End Sub

24.3

Mit Konstanten arbeiten

Eine »Konstante« ist ein sinnvoller Name, mit dem eine wenig aussagekräftige Zahl oder eine Zeichenkette versehen wurde. Konstanten können ausschließlich für Werte verwendet werden, die zur Laufzeit unverändert bleiben. Dabei könnte es sich im Rahmen unserer Beispielanwendung beispielsweise um einen Steuersatz oder um einen Rabatt handeln. In Access gibt es drei Arten von Konstanten:

 symbolische  integrierte  systemdefinierte Symbolische Konstanten werden unter Verwendung des Schlüsselworts Const erstellt, um den Code lesbarer und besser handhabbar zu gestalten. Statt beispielsweise immer die Zahl .0875 anzugeben, wenn Sie den Steuersatz meinen, benutzen Sie die Konstante MTAXRATE. Sobald sich der Steuersatz ändert und Ihr Code deshalb geändert werden muss, brauchen Sie die Änderung nur noch an einer einzigen Stelle vorzunehmen. Außerdem ist die Bezeichnung MTAXRATE erheblich aussagekräftiger als die Zahl .0875.

Mit Konstanten arbeiten

879

Integrierte Konstanten sind feste Bestandteile von Microsoft Access und gehören unmittelbar zur Sprache selbst. Als Access-Programmierer können Sie die zu Microsoft Access, Visual Basic und die zu den ActiveX-Datenobjekten (ADO) gehörigen Konstanten verwenden. Außerdem haben Sie die Möglichkeit, Konstanten beliebiger im Rahmen Ihrer Anwendung genutzter Objektbibliotheken zu benutzen. Es sind lediglich drei systemdefinierte Konstanten für sämtliche Anwendungen auf Ihrem Computer verfügbar: True, False und Null.

24.3.1

Eigene Konstanten definieren

Es wurde bereits erwähnt, dass symbolische Konstanten mit Hilfe des Schlüsselworts Const deklariert werden. Die Konstantendeklaration kann innerhalb einer Unterroutine oder Funktion oder auch im Allgemeinen Abschnitt eines Formular-, Berichtsoder Klassenmoduls erfolgen. Im Gegensatz zu früheren Versionen von Access können Konstanten in Access 97 und Access 2000 sogar strikt typisiert werden. Für Konstanten gibt es einige Namenskonventionen. Beispielsweise sollte der erste Buchstabe des Namens einer Konstanten auf deren Gültigkeitsbereich hinweisen und der nachfolgende Buchstabe c signalisiert, dass es sich nicht um eine Variable handelt. Danach folgt die eigentliche Bezeichnung des Datentyps. Eine private Konstante könnte folgendermaßen deklariert und verwendet werden: Private Const mccurTaxRate As Currency = .0875

Ich bevorzuge eine Namenskonvention, bei welcher der Name einer Konstanten mit einem Präfix für den Gültigkeitsbereich beginnt und vollständig in Großbuchstaben geschrieben wird. Das soeben angegebene Beispiel sieht dann so aus: Private Const MTAXRATE as Currency = .0875

Wenn dieser Code im Deklarationsteil eines Moduls eingefügt wird, sorgt er dafür, dass eine private Konstante mit dem Namen MTAXRATE und dem Wert .0875 erstellt wird. Innerhalb des Codes wird die Konstante wie folgt verwendet: Function TotalAmount(curSaleAmount As Currency) TotalAmount = curSaleAmount * MTAXRATE End Function

Diese Routine multipliziert die als Parameter übernommene Variable curSaleAmount mit der Konstanten MTAXRATE. Das Ergebnis der Multiplikation dieser beiden Werte wird dem Namen der Funktion zugewiesen und dient somit als Rückgabewert. In diesem Beispiel besteht der Vorteil der Verwendung einer Konstanten in der besseren Lesbarkeit. Der Ausdruck TotalAmount = curSaleAmount * .0875 ist sicherlich weniger aussagekräftig.

880

Kapitel 24: Fortgeschrittene VBA-Techniken

Den Gültigkeitsbereich symbolischer Konstanten festlegen Analog zu herkömmlichen Variablen verfügen auch benutzerdefinierte Konstanten über einen Gültigkeitsbereich. Im vorherigen Beispiel haben Sie eine private Konstante erstellt. Wird der folgende Ausdruck im Deklarationsteil eines Moduls eingefügt, zieht dies das Erstellen einer öffentlichen Konstanten nach sich: Public Const GTAXRATE As Currency = 0.0875

Da diese Konstante als öffentlich deklariert wurde, kann sie von jeder Unterroutine bzw. Funktion (einschließlich der Ereignisroutinen) innerhalb Ihrer Anwendung benutzt werden. Um die Vorteile einer öffentlichen Konstanten besser zu verstehen, stellen Sie sich bitte vor, dass Sie mit zahlreichen Funktionen und Unterroutinen arbeiten, welche alle die Konstante GTAXRATE verwenden. Was wäre zu tun, wenn der Steuersatz geändert werden müsste? Wenn Sie keine Konstante benutzt hätten, müssten Sie Ihre gesamte Anwendung durchsuchen, um überall den alten Steuersatz durch den neuen zu ersetzen. Da Sie jedoch eine öffentliche Konstante verwendet haben, brauchen Sie lediglich die eine Code-Zeile zu ändern, in der die Konstante deklariert wurde. Der Wert einer Konstanten darf zur Laufzeit grundsätzlich nicht verändert werden. Falls Sie es trotzdem versuchen, verursachen Sie den folgenden VBA-Kompilierfehler: Fehler beim Kompilieren: Zuweisung zu einer Konstanten nicht zulässig.

Die entsprechende Meldung ist in Abbildung 24.1 dargestellt. Der Kompilierfehler wurde durch den Versuch ausgelöst, den Wert der Konstanten GTAXRATE zu verändern. Falls ein Verändern des Werts zur Laufzeit erforderlich ist, sollten Sie erwägen, den Wert in einer Tabelle zu speichern, statt ihn als Konstante zu deklarieren. Dann können Sie den Wert in eine Variable einlesen, sobald die Anwendung gestartet wird, und ihn bei Bedarf ändern. Außerdem haben Sie die Möglichkeit, den neuen Wert in der Tabelle abzulegen.

Abbildung 24.1: Diese Fehlermeldung ergibt sich aus dem Versuch, den Wert einer Konstanten zu verändern

Mit Konstanten arbeiten

24.3.2

881

Mit integrierten Konstanten arbeiten

Microsoft Access deklariert einige integrierte Konstanten, die in Code-, Formularund Berichtsmodulen verwendet werden können. Da diese Konstanten für Microsoft Access reserviert sind, haben Sie weder die Möglichkeit, deren Wert zu ändern, noch ihre Namen anderweitig zu benutzen. Konstanten dieser Art können jedoch jederzeit verwendet werden, ohne zuvor deklariert worden zu sein. In Ihrem Code sollten Sie so oft wie möglich von integrierten Konstanten Gebrauch machen. Auf diese Weise sorgen Sie nicht nur für eine bessere Lesbarkeit des Codes, sondern erreichen zusätzlich eine bessere Por