Ein Access-Skriptum für Fortgeschgrittene

Transcription

Ein Access-Skriptum für Fortgeschgrittene
Pädagogisches Institut
des Bundes
in Oberösterreich
Die VBA-Programmierung
mit MS-Access 7.0
Prof. Otmar Haring
Access 7.0 - Programmierung
INHALTSÜBERSICHT
1. Vorbereitung...................................................................................................... 4
2. Die Entwicklungsumgebung ............................................................................. 6
3. Eigenschaften und Ereignisse............................................................................ 6
Ereignisse und ihr Auftreten ............................................................................................. 6
Ereignisprozedur und Veränderung von Eigenschaften ................................................... 7
Entscheidungen im Programmcode .................................................................................. 8
Aufruf einer allgemeinen Prozedur................................................................................... 9
Einstellungen für Programmcode ..................................................................................... 9
Programmtechnisches Öffnen eines Formulars .............................................................. 11
Datenübergabe in ein anderes Formular ......................................................................... 11
MsgBox-Befehl und Funktion ........................................................................................ 12
Abbrechen von Ereignissen ............................................................................................ 13
Filter-Ereignisse.............................................................................................................. 13
4. Auflistungen .................................................................................................... 14
5. Programmstrukturen........................................................................................ 15
DO WHILE - LOOP ....................................................................................................... 15
FOR - NEXT - FOR EACH - NEXT........................................................................ 15
6. Objekttypen ..................................................................................................... 16
Festlegen von Objektvariablen ....................................................................................... 16
Mehrere Instanzen eines Objektes öffnen....................................................................... 17
7. Variablendeklaration ....................................................................................... 17
8. Variablentypen ................................................................................................ 18
9. Globale Funktionen ......................................................................................... 18
Function - Sub................................................................................................................. 18
Optionale Argumente...................................................................................................... 19
Lokale und globale Variablendeklaration....................................................................... 19
ByVal und ByReference - Variablenübergabe ............................................................... 19
Haltepunkte, Schrittweise Programmverfolgung, Anzeige der Variableninhalte .......... 20
Array-Übergabe an Funktion .......................................................................................... 21
Otmar Haring
Seite 1
Access 7.0 - Programmierung
10. Anwendung vervollständigen........................................................................ 21
Übersichtsmanager.......................................................................................................... 21
Startoptionen einstellen .................................................................................................. 21
Menü-Editor.................................................................................................................... 22
11. Fehlerbehandlung .......................................................................................... 23
Arten von Fehlern und ihre Behandlung ........................................................................ 23
Bedingte Kompilierung................................................................................................... 24
12. Data-Access-Object (DAO) .......................................................................... 25
Das Recordset-Objekt ..................................................................................................... 25
Move-Methode und RecordCount-Eigenschaft .............................................................. 26
Move-Methode und EOF-Eigenschaft............................................................................ 27
Datensatz hinzufügen (Edit- und Update-Methode)....................................................... 27
Find-Methode.................................................................................................................. 27
Einen bestimmen Datensatz im Formular „Kunden“ suchen ......................................... 28
Hinzufügen von Daten, die in einem Kombinationsfeld eingegeben werden ................ 28
Abfrage dynamisch erstellen und Ergebnis im Testfenster ausgeben ............................ 29
Transaktionen.................................................................................................................. 30
Datenbank erstellen, Laufwerk und Verzeichnis wechseln............................................ 31
Container- und Document-Objekte................................................................................. 32
Objekte in andere Datenbank kopieren........................................................................... 33
13. Datenbank replizieren.................................................................................... 34
Desingn-Master erstellen ................................................................................................ 34
Replika erstellen ............................................................................................................. 34
Synchronisation von Datenbanken ................................................................................. 34
Konfliktlösung bei Replikation....................................................................................... 35
Abfrage der benutzerdefinierten Datenbankeigenschaften............................................. 36
14. OLE-Programmierung................................................................................... 37
OLE-Objekt im Formular ............................................................................................... 37
Datenaustausch mit Word über OLE .............................................................................. 38
Berechnungen in Excel über OLE durchführen.............................................................. 39
15. Zugriffsberechtigungen ................................................................................. 41
Grundüberlegungen ........................................................................................................ 41
Datenbank sichern, Berechtigungen vergeben ............................................................... 42
Otmar Haring
Seite 2
Access 7.0 - Programmierung
Protokollieren von Benutzeraktionen ............................................................................. 43
Erstellen einer eigenen WorkSpace ................................................................................ 43
16. Eigene Statuszeile.......................................................................................... 44
Timer-Eigenschaft von Formularen (Uhrzeit in der Statuszeile) ................................... 45
Statuszeile mit Fortschrittsanzeige ................................................................................. 45
Statusanzeige in einem eigenen Formular ...................................................................... 46
17. Liste mit Mehrfachauswahl ........................................................................... 48
Die Eigenschaft „Mehrfachauswahl“.............................................................................. 48
VBA-Eigenschaften von Multiple Choice-Listfeldern:.................................................. 48
18. VBA-Programmierung in Berichten ............................................................. 52
Seitensumme eines Feldes berechnen............................................................................. 52
19. Zusätzliche Anregungen................................................................................ 53
VB-Control-Arrays simulieren ....................................................................................... 53
Kontrollkästchen mit drei Auswahlmöglichkeiten ......................................................... 53
Unterbrechung des AUTOEXEC-Makros verhindern.................................................... 54
Otmar Haring
Seite 3
Access 7.0 - Programmierung
1. Vorbereitung
Folgende fünf Tabellen sind Grundlage für dieses Skriptum. Die Tabelle „Titel“ ist
normalerweise nicht sichtbar.
Aufträge
Name
Auf-ID
Reise-ID
Datensatzherkunft:
Gebundene Spalte:
Herkunftstyp:
Spaltenanzahl:
Spaltenbreiten:
Spaltenreihenfolge:
Steuerelement anzeigen:
Kunden-ID
Datensatzherkunft:
Gebundene Spalte:
Herkunftstyp:
Spaltenanzahl:
Spaltenbreiten:
Steuerelement anzeigen:
gebucht am
fällig
Preis
bezahlt
Kunden
Name
ID
Nachname
Vorname
Titel
Datensatzherkunft:
Gebundene Spalte:
Herkunftstyp:
Spaltenanzahl:
Steuerelement anzeigen:
Geschlecht
Straße
PLZ
Ort
Telefon 1
Telefon 2
Anrede
Reiseziele
Name
ID
Reiseziel
Dauer
Datum
Reisemittel
Preis
Otmar Haring
Typ
AutoWert
Zahl (Long)
Größe
4
4
Index
Primärschlüssel
Ja (mit Duplikaten)
SELECT DISTINCTROW Reiseziele.ID, Reiseziele.Reiseziel FROM Reiseziele;
1
Tabelle/Abfrage
2
0;1440
Standard
Kombinationsfeld
Zahl (Long)
4
Ja (mit Duplikaten)
SELECT DISTINCTROW Kunden.ID, Kunden.Nachname, Kunden.Vorname
FROM Kunden;
1
Tabelle/Abfrage
3
0;1440;1440
Kombinationsfeld
Datum/Zeit
Datum/Zeit
Währung
Ja/Nein
Typ
AutoWert
Text
Text
Text
8
8
8
1
Nein
Nein
Nein
Nein
Größe
4
50
50
20
Index
Primärschlüssel
Nein
Nein
Nein
SELECT DISTINCTROW Titel from Titel order by Titel;
1
Tabelle/Abfrage
1
Kombinationsfeld
Zahl (Integer)
Text
Text
Text
Text
Text
Text
Typ
AutoWert
Text
Zahl (Long)
Datum/Zeit
Text
Währung
2
100
10
50
50
50
50
Nein
Nein
Nein
Nein
Nein
Nein
Nein
Größe
4
50
4
8
20
8
Index
Primärschlüssel
Nein
Nein
Nein
Nein
Nein
Seite 4
Access 7.0 - Programmierung
Titel
Name
Titel
Typ
Text
Größe
20
Index
Nein
Protokolltabelle
Name
ID
Benutzer
Änderungsdatum
Änderungsart
bearbeitete ID
Typ
AutoWert
Text
Datum/Zeit
Text
Zahl (Long)
Größe
4
20
8
50
4
Index
Primärschlüssel
Nein
Nein
Nein
Ja (mit Duplikaten)
Die Beziehungen der Tabellen sehen folgendermaßen aus:
Um die OLE-Verknüpfung mit WinWord durchführen zu können, ist noch eine Datei
erforderlich, die zwei Textmarken „Adresse“ und „Anrede“ enthält, wie nachfolgendes Beispiel
zeigt:
Adresse
Anrede
Otmar Haring
Seite 5
Access 7.0 - Programmierung
2. Die Entwicklungsumgebung
VBA-Code in Access kann in zwei Bereichen erstellt werden. Wenn der
Programmcode direkt mit dem Formular oder Bericht in Zusammenhang steht,
wird er meist im Formular oder Bericht abgelegt. Allgemeine Prozeduren oder
Funktionen stehen hingegen in eigenen Modulen. Egal, ob man nun den Modulteil
eines Formulars/Berichts oder ein eigenes Modul betrachtet - beide besitzen einen
Deklarationsteil und einen Bereich, in dem der Programmcode abgelegt ist.
Deklarationen
Funktion1
Prozedur1
Prozedur2
Funktion2
Funktion3
Prozedur3
Funktion4
Zusätzlich besitzen Formular-/Berichtsmodule noch einen Bereich, in dem die
Ereignisprozeduren zu den einzelnen Objekten abgelegt werden.
Deklarationen
Ereignisproz.1
Ereignisproz.2
Ereignisproz.3
Ereignisproz.4
Ereignisproz.5
Ereignisproz.6
Ereignisproz.7
Ereignisproz.8
Funktion1
Prozedur1
Prozedur2
Funktion2
Funktion3
Prozedur3
Zusammen mit dem Modulfenster erscheint eine Symbolleiste, die den schnellen
Zugang auf die wichtigsten Fähigkeiten der Entwicklungsumgebung gestattet.
Aufrufe
Prozedur
einfügen
Modul
einfügen
Objekt- Programm Haltepunkt
katalog beenden
setzen
Testfenster
Programm
fortsetzen
Prozedurschritt
Wert
anzeigen
Neu
initialisieren
Einziehen
Kompilieren
Ausrücken
Editor
Einzelschritt
3. Eigenschaften und Ereignisse
Ereignisse und ihr Auftreten
Wenn mit Formularen oder Berichten gearbeitet wird, interpretiert Access
bestimmte Vorgänge in diesen Datenbankobjekten als Ereignisse. Das Wechseln
von einem Steuerelement zum nächsten oder von einem Datensatz zum anderen im
Formular ist zum Beispiel ein solches Ereignis.
Otmar Haring
Seite 6
Access 7.0 - Programmierung
Auf welche Ereignisse ein Objekt reagieren kann, ist in der Eigenschaftsliste des
Objektes im Registerblatt „Ereignis“ ersichtlich. Die Ereignisse treten in einer
bestimmten Reihenfolge auf:
Öffnen und Schließen eines Formulars:
Öffnen
Entladen
Laden
Größenänderung
Deaktivierung
Aktivierung
Anzeigen
Schließen
Hingehen zu und Verlassen von Steuerelementen:
Hingehen
Fokuserhalt
Verlassen
Fokusverlust
Wechsel zwischen Steuerelementen in verschiedenen Formularen:
Fokusverlust (Element1)
Aktivierung (Formular2)
Deaktivierung (Formular1)
Fokuserhalt (Element2)
Ereignisprozedur und Veränderung von Eigenschaften
Klick-Prozedur für Button „Datum“ erstellen:
Zum Testen zuerst mehrere Eigenschaften von Objekten verändern
Zwei Möglichkeiten zum Eintragen des Fälligkeitsdatums:
- Ungebundenes Feld mit einer Berechnungsformel
(=[gebucht am] + 7)
- Buchungsdatum und Fälligkeitsdatum automatisch durch
Programmcode eintragen lassen
(Vorteil: Feldinhalte können jederzeit verändert werden!)
Private Sub Datum_Click()
'1. Eigenschaft "aktiviert" definieren
'
fällig.Enabled = False
'2. Umschalten
'
fällig.Enabled = Not (fällig.Enabled)
'3. zugreifen auf gebundenes Formularfeld mit Leerzeichen
'
im Namen []
'
-> Me![feldname]
'
Me![gebucht am].Visible = Not (Me![gebucht am].Visible)
'4. Hintergrundfarbe -> RGB()
'
-> QBColor()
'
Me!Preis.BackColor = RGB(255, 0, 0)
'5. Datum-gebucht und Fälligkeitsdatum eintragen
Me![gebucht am].Value = Date
Me!fällig = DateAdd("d", 7, Date)
End Sub
Otmar Haring
Seite 7
Access 7.0 - Programmierung
Entscheidungen im Programmcode
Das Objekt „Mahnen“ soll nur sichtbar sein, wenn der Betrag noch nicht bezahlt
wurde und das Fälligkeitsdatum bereits überschritten ist.
NOT
Mit Hilfe dieses Befehls kann sehr schnell eine bestimme Eigenschaft
invertiert werden.
IF - THEN
Mit der „IF-THEN“-Abfrage können Entscheidungen während des
Programmablaufes getroffen werden. Es gibt mehrere Formen, den Befehl
anzuwenden:
a) IF Bedingung THEN Aktion
b) IF Bedingung THEN
Aktion(en)
ELSE
Aktion(en)
END IF
c) IF Bedingung THEN
Aktion(en)
ELSEIF Bedingung THEN
Aktion(en)
ELSE
Aktion(en)
END IF
SELECT CASE
Mit dieser Abfragemöglichkeit kann auf unterschiedlichste Inhalte einer
bestimmten Variablen reagiert werden.
SELECT CASE Variable
CASE Wert
Aktion(en)
CASE Wert
Aktion(en)
END SELECT
Otmar Haring
Seite 8
Access 7.0 - Programmierung
Aufruf einer allgemeinen Prozedur
Da die Überprüfung der Anzeige des Feldes „Mahnen“ mehrmals stattfinden muß
(bei jedem Anzeigen eines neuen Datensatzes, bei jeder Änderung des „Bezahlt“Feldes, bei Änderung des Fälligkeitsdatums, ...), empfiehlt sich der Einsatz einer
allgemeinen Prozedur.
PRIVATE - PUBLIC:
Prozeduren bzw. Funktionen, die nur im Formular Gültigkeit haben, werden
mit PRIVATE deklariert. Sollte eine Prozedur aber auch von einem anderen
Formular oder Modul aufgerufen werden können, muß sie mit PUBLIC
deklariert werden.
Private Sub Form_Current()
'1. NOT
'
mahnen.Visible = Not bezahlt
'2. IF - Then
'
Abfrage, ob neuer Datensatz (Preis=0)
'
If Not bezahlt And Preis > 0 Then
'
mahnen.Visible = True
'
Else
'
mahnen.Visible = False
'
End If
'3. Allgem. Proz. Aufrufen
TestMahnen
End Sub
Public Sub TestMahnen()
If Not bezahlt And Preis > 0 And fällig < Date Then
mahnen.Visible = True
Else
mahnen.Visible = False
End If
End Sub
Private Sub bezahlt_AfterUpdate()
'1. Aufruf der allgem. Prozedur
TestMahnen
End Sub
Private Sub fällig_AfterUpdate()
TestMahnen
End Sub
Einstellungen für Programmcode
Grundeinstellung der Farben für Programmcode, Kommentarzeilen, Haltepunkte, ..
(Extras - Optionen - Modul)
Volle Modulansicht (Extras - Optionen - Modul)
Variablen-Deklaration erforderlich
AutoSyntaxüberprüfung anzeigen
Seitenansicht der Module (Datei - Seitenansicht)
Otmar Haring
Seite 9
Access 7.0 - Programmierung
Übung:
Formular „Kunden“ öffnen und folgende Aufgaben erledigen:
- Optionsgruppe mit der Geschlechtsauswahl hinzufügen
- Eine allgemeine Prozedur für die Briefanrede erstellen:
In das Feld „Anrede“ soll je nach Geschlecht „Sehr geehrte Frau“ oder
„Sehr geehrter Herr“ gefolgt vom Titel (falls vorhanden) und dem
Familiennamen eingetragen werden.
- Diese allgemeine Prozedur muß beim Klick auf den Button und - nur wenn
schon eine Anrede besteht - bei jeder Änderung des Geschlechts aufgerufen
werden.
Private Sub Brief_Click()
SetAnrede
End Sub
Private Sub Geschlechtswahl_Click()
If Not IsNull(Briefanrede) Then
SetAnrede
End If
End Sub
Public Sub SetAnrede()
If Geschlecht = 1 Then
Briefanrede = "Sehr geehrter Herr "
Else
Briefanrede = "Sehr geehrte Frau "
End If
If Not IsNull(Titel) Then
Briefanrede = Briefanrede & Titel & " "
End If
Briefanrede = Briefanrede & [Nachname]
End Sub
Otmar Haring
Seite 10
Access 7.0 - Programmierung
Programmtechnisches Öffnen eines Formulars
Ein Formular kann programmtechnisch auf drei Arten geöffnet werden:
- durch einen Makrobefehl
- durch den VBA-Befehl „DoCmd.OpenForm“, der die gleiche Argumentreihenfolge wie der Makrobefehl benötigt
(siehe in der Hilfe „OpenForm-Methode“)
- durch den VBA-Befehl „DoCmd.OpenForm“, bei dem Argumente in beliebiger
Reihenfolge eingegeben werden können.
(Im Objektkatalog die Bibliothek „Access“ auswählen, das Modul „DoCmd“
suchen und die Methode „OpenForm“ einfügen)
ACHTUNG: Die zur Trennung eingefügten Strichpunkte durch Beistriche
ersetzen!!!
Datenübergabe in ein anderes Formular
Sollte im Formular „Aufträge“ ein Kunde benötigt werden, der in der
Kundentabelle noch nicht erfaßt wurde, muß durch Klick auf den Button „Neu“ das
Kundenformular automatisch geöffnet werden. Dieses Formular muß zur Eingabe
eines neuen Datensatzes bereit sein und die Navigationsschaltflächen müssen
ausgeblendet sein.
Beim Schließen des Kundenformulars muß der eben eingegebene Datensatz in das
Auftragsformular übergeben werden.
Damit kein Fehler beim Schließen des Kundenformulars auftritt, darf die
Aktualisierung des Auftragsformulars nur dann stattfinden, wenn dieses auch
tatsächlich offen ist.
Um diese Aufgabe zu lösen, wird die benutzerdefinierte Eigenschaft „Tag“ im
Kundenformular so verändert, daß der Formularname des aufrufenden Formulars
eingetragen wird.
Private Sub Neu_Click()
'Argumentreihenfolge festgelegt
'
DoCmd.OpenForm "kunden", , , , acAdd
'benannte Argumente über Objektkatalog
DoCmd.OpenForm Formname:="Kunden", DataMode:=acAdd
'ausblenden der Navigationsschaltflächen
Forms!Kunden.NavigationButtons = False
'Eigenschaft "Tag" in Kundenformular verändern
Forms!Kunden.Tag = "Aufträge"
End Sub
Beim Schließen des Kundenformulars wird das vorherige Formular wieder
aktiviert:
Private Sub Form_Close()
If Me.Tag <> "" Then
Forms(Me.Tag)![Kunden-ID].Requery
Forms(Me.Tag)![Kunden-ID].Value = Me.ID
End If
End Sub
Otmar Haring
Seite 11
Access 7.0 - Programmierung
MsgBox-Befehl und Funktion
Um dem Anwender Mitteilungen vom Programm her zu geben, wird der Befehl
oder die Funktion „MsgBox“ eingesetzt. Die Funktion „MsgBox“ muß mit
mindestens einem und maximal fünf Parametern versorgt werden und liefert einen
Rückgabewert. In der einfachsten Form erhält die Funktion nur den ersten
Parameter, der den Meldungstext festlegt. Die allgemeine Syntax sieht
folgendermaßen aus:
MsgBox (prompt [, buttons] [, title] [, helpfile,
context] )
Der Befehl „MsgBox“ liefert im Gegensatz zur Funktion keinen Rückgabewert.
Der zweite Unterschied ist formaler Art: Die Argumente werden nicht in
Klammern gesetzt.
Das Argument „buttons“ beeinflußt die Art der Schaltflächen und der Icons im
Meldungsfenster. Eine Summierung der Werte liefert das gewünschte Ergebnis:
Konstante
vbOKOnly
vbOKCancel
vbAbortRetryIgnore
vbYesNoCancel
vbYesNo
vbRetryCancel
Konstante
vbCritical
vbQuestion
vbExlamation
vbInformation
Konstante
vbDefaultButton1
vbDefaultButton2
vbDefaultButton3
Otmar Haring
Inhalt
0
1
2
3
4
5
Schaltfläche(n)
OK
OK, Abbrechen
Beenden, Wiederholen, Ignorieren
Ja, Nein, Abbrechen
Ja, Nein
Wiederholen, Abbrechen
Inhalt
16
32
48
64
Icon
Stop-Schild
Fragezeichen
Ausrufezeichen
Buchstabe „i“
Inhalt
0
256
512
Bevorzugte Schaltfläche
1. Schaltfläche
2. Schaltfläche
3. Schaltfläche
Seite 12
Access 7.0 - Programmierung
Der Rückgabewert gibt Auskunft über die gedrückte Schaltfläche:
Konstante
vbOK
vbCancel
vbAbort
vbRetry
vbIgnore
vbYes
vbNo
Inhalt
1
2
3
4
5
6
7
Gedrückte Schaltfläche
OK
Abbrechen
Beenden
Wiederholen
Ignorieren
Ja
Nein
Abbrechen von Ereignissen
Manchen Ereignisprozeduren werden Parameter übergeben. Sollte in der
Argumentliste der Parameter „Cancel“ aufscheinen, kann dieses Ereignis
abgebrochen werden.
Zwei Beispiele:
- Wenn der Nachname vor dem Vornamen eingegeben wird, soll das Feldupdate
nicht durchgeführt werden.
- Das Schließen des Formulars „Kunden“ soll durch eine Abfrage bestätigt werden
Private Sub Nachname_BeforeUpdate(Cancel As Integer)
If IsNull(Vorname) Then
MsgBox "Bitte erst Vorname eingeben!"
Cancel = True
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
If MsgBox("Wollen Sie das Formular wirklich schließen?", _
vbYesNo + vbQuestion) = vbNo Then
Cancel = True
End If
End Sub
Filter-Ereignisse
Access 7.0 bietet eine neue Art der Datenfilterung: Den formularbasierten Filter.
Mit zwei neuen Ereignissen („Bei Filter“ und „Bei angewendetem Filter“) kann auf
die Filterung von Daten reagiert werden.
Um dem Formular „Kunden“ ein neues Aussehen zu geben, wenn der
formularbasierte Filter angewendet wird, sollen der Hintergrund neu eingefärbt und
die Telefonfelder ausgeblendet werden, sowie die Filterung nach der PLZ nicht
möglich sein. Das Fenster soll auch noch eine neue Beschriftung bekommen.
Das Filterfenster kann auf zwei Arten beendet werden:
- durch Anwenden des Filters
- durch Abbrechen der Filtereinstellungen
Beim Schließen sollen alle vorgenommenen Änderungen des Formularaussehens
wieder zurückgenommen werden. Zusätzlich soll bei Abbrechen des Filterfensters
eine Meldung am Bildschirm erscheinen.
Otmar Haring
Seite 13
Access 7.0 - Programmierung
Private Sub Form_Filter(Cancel As Integer, _
FilterType As Integer)
'FilterType gibt die Art des Filters an
'-> Formularfilter oder erweiterter Filter
If FilterType = acFilterByForm Then
Detailbereich.BackColor = RGB(255, 255, 0)
Telefon_1.Visible = False
Telefon_2.Visible = False
'Liste für PLZ ausschalten
PLZ.FilterLookup = False
'Überschrift für Formular
Me.Caption = "Suchen"
End If
End Sub
Private Sub Form_ApplyFilter(Cancel As Integer, _
ApplyType As Integer)
'ApplyType gibt das Beenden des Filterfensters an
'z.B. Abbrechen oder Anwenden
If ApplyType = acCloseFilterWindow Then
MsgBox "Warum haben Sie nichts ausgewählt?"
Me.Filter = Null
End If
Detailbereich.BackColor = QBColor(7)
Telefon_1.Visible = True
Telefon_2.Visible = True
'Überschrift für Formular
Me.Caption = "Kunden"
End Sub
4. Auflistungen
Auflistungen enthalten Objekte, die alle denselben Typ haben. Ein Objekt kann entweder direkt
über seinen Namen oder manchmal nur über seine Auflistung angesprochen werden. Da mit einer
Auflistung ein Objekt angesprochen wird, besitzt dieses natürlich auch Eigenschaften.
Folgende Beispiele sind im Textfenster auszuprobieren!
Beispiele von Auflistungen:
Forms.Auflistung:
? Forms(0).Name
? Forms(1).Name
? Forms.Count
?
?
?
?
?
Otmar Haring
Forms(0).CurrentView
(0 = Entwurf,
Forms!Aufträge.CurrentView
Forms("Aufträge").CurrentView
Forms(Variable).CurrentView
Form_Aufträge.CurrentView
1 = Formular, 2 = Datenblatt)
Seite 14
Access 7.0 - Programmierung
Controls.Auflistung:
? Forms(0).Controls.Count
? Forms(0).Controls(0).Name
? Forms(0)(0).Name
? Forms("Aufträge").Controls("fällig").ControlSource
5. Programmstrukturen
Mit Hilfe von Schleifen kann manchmal sehr elegant mit Auflistungen gearbeitet werden. Dies ist
vor allem dann nötig, wenn mit wenig Programmcode Eigenschaften von mehreren Objekten
verändert oder aufgelistet werden sollen.
DO WHILE - LOOP
DO WHILE Bedingung
Aktion(en)
LOOP
FOR - NEXT - FOR EACH - NEXT
Sub Listforms1()
Dim i As Integer
For i = 0 to Forms.Count-1
Debug.Print Forms(i).Name
Next
End Sub
Sub Listforms2()
Dim i As Variant
For Each i In Forms
Debug.Print i.Name
Next
End Sub
Sub ListControls()
Dim ctrl
For Each ctrl In Forms("Aufträge").Controls
Debug.Print ctrl.Name
Next
End Sub
Sub ListProps()
Dim Prop
Debug.Print Forms(0).Controls(0).Name
For Each Prop In Forms(0).Controls(0).Properties
Debug.Print Prop.Name, Prop.Value
Next
End Sub
Otmar Haring
Seite 15
Access 7.0 - Programmierung
6. Objekttypen
Um in einer Auflistung von Objekten nur bestimmte Typen herauszufiltern, kann mit der Abfrage
„TYPEOF“ der Type des Objekts bestimmt werden.
Folgende Objekttypen sind gültig:
CheckBox
CommandButton
Label
ListBox
OptionGroup
SubForm
TextBox
ComboBox
Image
Line
OptionButton
Rectangle
SubReport
ToggleButton
Sub Listfelder()
Dim ctrl
Dim vari
vari = InputBox("Welches Formular?")
For Each ctrl In Forms(vari)
If TypeOf ctrl Is TextBox Then
Debug.Print ctrl.Name
End If
Next
End Sub
Sub ctrlÄndern()
Dim ctrl
For Each ctrl In Forms("Aufträge").Controls
'Alle Buttons werden aktiviert oder deaktiviert
If TypeOf ctrl Is CommandButton Then
If ctrl.Enabled = True Then
ctrl.Enabled = False
Else
ctrl.Enabled = True
End If
End If
Next
End Sub
Festlegen von Objektvariablen
Um nicht immer den gesamten Objektbezug angeben zu müssen, kann einer
Variablen ein Objektverweis zugewiesen werden. Dies geschieht mit dem Befehl
„SET Variable = “.
Sollte mit einem Objekt längere Zeit gearbeitet werden (z.B. weil mehrere
Eigenschaften definiert werden müssen), können mit dem Befehl „WITH“, der auf
dieses Objekt verweist, mehrere Anweisungen für dieses Objekt durchgeführt
werden.
Otmar Haring
Seite 16
Access 7.0 - Programmierung
Public Sub KundenObjekt()
Dim frm As Form
'neues Objekt definieren
'-> gesamter Name braucht nicht mehr angegeben werden
Set frm = Forms!Kunden
'Schnelles Setzen von Eigenschaften eines Objektes
With frm.Nachname
.Visible = True
.Enabled = True
.BackColor = QBColor(10)
End With
End Sub
Mehrere Instanzen eines Objektes öffnen
Mit dem Befehl „NEW“ ist es möglich, eine weitere Instanz eines Objektes zu
öffnen. Dies wird zum Beispiel benötigt, wenn in einem Formular Daten bearbeitet
werden, und zur gleichen Zeit mit dem gleichen Formular neue Datensätze
eingegeben werden sollen.
Auf dem Kunden-Formular wird ein Button erstellt, der die allgemeine Prozedur
„OpenKundenNeu“ aufruft.
Public Sub OpenKundenNeu()
'Kundenformular als neue Instanz öffnen
'z.B. zum Eingeben eines neuen Kunden,
'ohne im ersten Formular etwas zu ändern
Set frm = New Form_Kunden
'Im Hinzufügemodus öffnen
frm.DataEntry = True
'Neue Instanz anzeigen
frm.Visible = True
'um es programmtechnisch zu schließen:
'-> set frm = Nothing
End Sub
7. Variablendeklaration
In Funktion oder Prozedur:
Dim VarName[(Dimension)][As [New] Typ]
Static VarName[(Dimension)][As [New] Typ]
ReDim [Preserve] VarName(Dimension) [As Type]
Otmar Haring
Seite 17
Access 7.0 - Programmierung
In Moduldeklaration (allgemein)
Public VarName[(Dimension)][As [New] Typ]
Private VarName[(Dimension)][As [New] Typ]
[Private | Public] Type Varname
Elementname[(Dimension)] As Typ
[Elementname[(Dimension)] As Typ]
...
End Type
8. Variablentypen
Byte
1 Byte
0 bis 255
Boolean
2 Bytes
True oder False
Integer
2 Bytes
-32.768 bis 32.767
Long
4 Bytes
-2.147.483.648 bis 2.147.483.647
Single
4 Bytes
-3,402823E38 bis -1,401298E-45 für negative Werte
1,401298E-45 bis 3,402823E38 für positive Werte
Double
8 Bytes
-1,79769313486232E308 bis -4,94065645841247E-324 (neg.)
4,94065645841247E-324 bis 1,79769313486232E308 (pos.)
Currency
8 Bytes
-922.337.203.685.477,5808 bis 922.337.203.685.477,5807
Date
8 Bytes
1. Januar 100 bis 31. Dezember 9999
Object
4 Bytes
Beliebiger Verweis auf ein Objekt vom Typ Object
String
(variable Länge)
10 Bytes + 2^31 = 0 bis ca. 2 Mrd. unter Win95,
Textlänge 2^16 = 0 bis ca. 65.400 unter Windows 3.x
String
Textlänge
2^31 = 0 bis ca. 2 Mrd. unter Win95,
2^16 = 0 bis ca. 65.400 unter Windows 3.x
16 Bytes
Numerische Werte im Bereich des Datentyps Double
(feste Länge)
Variant)
(mit Zahlen)
Variant
(mit Zeichen)
22 Bytes + Wie bei String mit variabler Länge
Textlänge
9. Globale Funktionen
Funktionen bzw. Prozeduren, die nicht nur in einem Formular oder Bericht benötigt werden,
programmiert man in globalen Modulen. Diese bestehen genauso wie der Programmteil in einem
Formular (Bericht) aus Deklarationsteil und Programmcode (Funktionen oder Prozeduren). Es
gibt allerdings in globalen Modulen keine Ereignisprozeduren.
Function - Sub
Der Unterschied zwischen einer Prozedur (Sub) und einer Funktion (Function) ist
der, daß die Funktion einen Wert zurückliefert (z.B. SIN, MOD, INSTR, ...). Dies
bedeutet, daß das Ergebnis einer Funktion immer weiterbehandelt werden muß
(z.B. Zuweisen an eine Variable, Ausgeben in ein Feld, ...).
An Funktionen oder Prozeduren können auch Argumente übergeben werden. Dabei
werden die Argumente beim Aufruf von Funktionen in Klammer und bei
Prozeduren nicht in Klammer übergeben.
Otmar Haring
Seite 18
Access 7.0 - Programmierung
Public Function MWSt()
MWST = 0.2
End Function
Public Function MWSt(Betrag)
MWSt = Betrag * 0.2
End Function
Public Function MWSt(Betrag, MWStSatz)
MWSt = Betrag * MWStSatz
End Function
Optionale Argumente
Wenn Argumente nur manchmal gebraucht werden, kann man sie als „Optional“
deklarieren:
Public Function MWSt(Betrag, Optional MWStSatz)
If IsMissing(MWStSatz) Then MWStSatz = 0.2
MWSt = Betrag * MWStSatz
End Function
Public Function EndPreis(Betrag, Optional Zuschlag, _
Optional MWStSatz)
If IsMissing(Zuschlag) Then
Zuschlag = 0.5
End If
Betrag = Betrag * (1 + Zuschlag)
If IsMissing(MWStSatz) Then
MWStSatz = 0.2
End If
EndPreis = Betrag + MWSt(Betrag, MWStSatz)
End Function
Lokale und globale Variablendeklaration
Abhängig vom Ort der Variablendeklaration, hat die Variable nur einen
bestimmten Gültigkeitsbereich (nur in der Funktion (Prozedur), im gesamten
Modul, in der gesamten Anwendung).
Public Function Test()
Dim vari
vari = InputBox("Bitte Betrag eingeben!")
ShowVari
Test = EndPreis(vari)
ShowVari
End Function
Public Sub ShowVari()
MsgBox "Vari := " & vari
End Sub
-> liefert Fehlermeldung, da nicht dekl.
ByVal und ByReference - Variablenübergabe
Variablen belegen im Speicher einen bestimmten Speicherplatz. Je nachdem, ob an
eine Funktion nur der Wert der Variablen oder die Adresse des Speicherplatzes der
Otmar Haring
Seite 19
Access 7.0 - Programmierung
Variablen übergeben wird, kann sich der jeweilige Inhalt der Ursprungsvariablen
ändern.
Bei der Übergabe „ByReference“ (Standard) wird die Adresse der Variablen
übergeben. Verändert die Funktion den Wert der Variablen, so ändert sich auch der
Wert der Ursprungsvariablen.
Bei der Übergabe „ByVal“ wird nur der Wert der Variablen übergeben. Die
Funktion legt sich eine neue Variable an einem anderen Speicherplatz an. Bei
Veränderung des Variableninhaltes in der Funktion wird daher der Inhalt der
Ursprungsvariablen nicht verändert.
Haltepunkte, Schrittweise Programmverfolgung, Anzeige der Variableninhalte
Um die folgenden Beispiele genau verfolgen zu können, sind Debuging-Tools
notwendig.
gleiche Proz wie oben, aber mit globaler Dekl. der Variablen
Vari
Private Vari
2 verschiedene Aufrufe der Function Endpreis:
Public Function EndPreis(Betrag, Optional Zuschlag, _
Optional MWStSatz)
Public Function EndPreis(ByVal Betrag, Optional _
Zuschlag, Optional MWStSatz)
Otmar Haring
Seite 20
Access 7.0 - Programmierung
Array-Übergabe an Funktion
Wenn die Anzahl der Argumente für eine bestimmte Funktion (z.B. Summieren
von Zahlen) sehr unterschiedlich sein kann, kann mit der Übergabe eines Arrays
(Feldes) diese Aufgabe gelöst werden.
Public Function Summiere(ParamArray Werte())
Dim x
Dim erg
For Each x In Werte
erg = erg + x
Next
Summiere = erg
End Function
10. Anwendung vervollständigen
Übersichtsmanager
Mit Hilfe des Übersichts-Managers wird automatisch ein Startformular erstellt.
Startoptionen einstellen
Unter diesem Menüpunkt, der im „Extras“-Menü zu finden ist, können die
Startparameter der Applikation eingestellt werden. Neben der Angabe des
Startformulars können auch noch ein Anwendungstitel und ein Symbol
(Grafikdatei) vergeben werden.
Otmar Haring
Seite 21
Access 7.0 - Programmierung
Menü-Editor
DerApplikation kann ein eigenes Menü zugewiesen werden, das am leichtesten mit
dem Menü-Editor erstellt wird. Dabei kann ein bestehendes Menü verändert oder
ein neues erstellt werden. In diesem Beispiel wird beim Anklicken eines
Menüpunktes die Funktion „OpenForm“ aufgerufen, die verschiedene Formulare in
unterschiedlichem Modus öffnet (0 = hinzufügen; 1 = editieren).
Otmar Haring
Seite 22
Access 7.0 - Programmierung
Public Function OpenForm(Formular, Modus)
Dim frm
For Each frm In Forms
If frm.Name = Formular Then
DoCmd.Close A_FORM, Formular
End If
Next
DoCmd.OpenForm Formular, , , , Modus
End Function
11. Fehlerbehandlung
Arten von Fehlern und ihre Behandlung
Syntaxfehler:
Kompilierfehler:
Laufzeitfehler:
Tritt bei der Programmeingabe auf:
Fehlermeldung bestätigen und Fehler ausbessern
Tritt beim Kompilieren des Programms auf:
Fehlermeldung bestätigen und Fehler ausbessern
Tritt erst beim Programmlauf auf:
„On Error“-Fehlerbehandlung im Programm
Art des Fehler mit den Access-Objekten „Err.Number“
und „Err.Description“ erkennbar
In den Optionen (Extras - Optionen - Modul) kann eingestellt werden, daß trotz
„On Error“-Behandlung im Code bei jedem Fehler angehalten wird.
Public Sub FormÖffnen()
Dim Fn
Fn = InputBox("Bitte geben Sie den Namen des zu " _
& " öffnenden Formulares ein", "Formularname")
If Fn <> "" Then
On Error Resume Next
DoCmd.OpenForm Fn
Forms(Fn).Detailbereich.BackColor = RGB(200, 200, 0)
Debug.Print Err.Number, Err.Description
End If
End Sub
Public Sub FormÖffnen()
Dim Fn
Fn = InputBox("Bitte geben Sie den Namen des zu " _
& " öffnenden Formulares ein", "Formularname")
If Fn <> "" Then
On Error Resume Next
DoCmd.OpenForm Fn
Forms(Fn).Detailbereich.BackColor = RGB(200, 200, 0)
Forms(Fn).Controls(2).ForeColor = RGB(0, 100, 100)
If Err.Number <> 0 Then
MsgBox "Fehler: " & Err.Number & vbCrLf & _
"Formular " & Fn & " ist nicht vorhanden!"
End If
End If
End Sub
Otmar Haring
Seite 23
Access 7.0 - Programmierung
Public Sub FormÖffnen()
Dim Fn
On Error GoTo Err_Zeile
Fn = InputBox("Bitte geben Sie den Namen des zu " _
& " öffnenden Formulares ein", "Formularname")
If Fn <> "" Then
DoCmd.OpenForm Fn
Forms(Fn).Detailbereich.BackColor = RGB(200, 200, 0)
Forms(Fn).Controls(2).ForeColor = RGB(0, 100, 100)
End If
Exit Sub
Err_Zeile:
Fn = InputBox("Bitte geben Sie den Namen des zu " _
& " öffnenden Formulares ein", "Bitte neu eingeben!")
If Fn <> "" Then
Resume
Else
Exit Sub
End If
End Sub
Bedingte Kompilierung
Access 7.0 bietet die Möglichkeit, Programmteile nur unter Zutreffen einer
bestimmten Bedingung kompilieren zu lassen. Diese Möglichkeit wird
angewendet, wenn Teile des Programmcodes auf Grund verschiedener
Systemvoraussetzungen anders aussehen, und daher anders kompiliert werden
müssen.
Diese Möglichkeit kann aber auch angewendet werden, wenn ein Programmteil
noch nicht fertig programmiert wurde, und man trotzdem einen Kompilierlauf
starten möchte. Für diesen Fall setzt man eine Bedingung ein, die nicht zutreffen
kann und klammert dadurch den noch fehlerhaften Programmteil von der
Kompilierung aus.
Voraussetzungen für die bedingte Kompilierung:
Variable muß im allgemeinen Teil mit „#Const“ deklariert werden
Bedingte Kompilierung mit „#If - #End If“
#Const Version = 2
Public Sub Kompilierung()
Dim x
'Bedingte Kompilierung:
'Variable muß mit #Const deklariert werden!
#If Version = 1 Then
If x = 4 Then
x=
End If
#End If
End Sub
Otmar Haring
Seite 24
Access 7.0 - Programmierung
12. Data-Access-Object (DAO)
Folgende Abbildung zeigt die Hierarchie von Datenzugriffsobjekten (Data-Access-Object). In
dieser Abbildung werden allerdings nur Auflistungen (mit Ausnahme des Objekts DBEngine auf
der obersten Ebene) dargestellt. Jede Auflistung enthält jedoch wiederum Objekte. Nicht
dargestellt in dieser Abbildung ist lediglich die Property-Auflistung.
Das Recordset-Objekt
Das Recordset-Objekt wird zum Bearbeiten der Daten in der Datenbank verwendet.
Um ein Recordset zu öffnen, wird die Methode „Openrecordset“ verwendet:
Set Variable = Datenbank.OpenRecordSet(Herkunft, Typ,
Optionen)
Herkunft: Name der Tabelle/Abfrage oder SQL-Befehl
Typ:
dbOpenTable:
Verweist auf eine Tabelle. Einige Operationen
(Sortieren, Verwenden der Methode „Seek“)
sind nur für diesen Typ verfügbar.
dbOpenDynaset:
Verweist auf eine Tabelle oder das Ergebnis
einer Abfrage. Ermöglicht das Extrahieren und
Aktualisieren von Daten aus mehreren
Tabellen.
dbOpenSnapshot: Gleicht dem Typ Dynaset, ist allerdings nur
eine statische Kopie der Daten zum Zeitpunkt
der Erstellung. Ein Snapshot kann nicht
aktualisiert werden.
Otmar Haring
Seite 25
Access 7.0 - Programmierung
Optionen: dbAppendOnly: Es können nur neue Datensätze hinzugefügt
werden (Dynaset)
dbSeeChanges: Es wird ein Laufzeitfehler ausgelöst, wenn ein
anderer Benutzer Daten ändert, die ich
bearbeite
dbDenyWrite: Andere Benutzer können keine Datensätze
ändern oder hinzufügen
Auf das Recordset-Objekt können mehrere Methoden angewendet werden und es
besitzt auch einige Eigenschaften.
Methoden:
AddNew
CancelUpdate
Delete
Edit
Find-Methoden
Move-Methoden
Requery
Update
Eigenschaften:
BOF, EOF
Bookmark
EditMode
NoMatch
RecordCount
Move-Methode und RecordCount-Eigenschaft
Die folgenden zwei Beispiele liefern jeweils die Anzahl von Datensätzen. Im ersten
Fall soll die Anzahl der Datensätze in der Tabelle „Kunden“ bestimmt werden, im
zweiten ist die Anzahl der in Wien lebenden Kunden gefragt.
Public Function RecCountTab()
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("Kunden", dbOpenTable)
rs.MoveLast
Debug.Print rs.RecordCount
rs.Close
End Function
Public Function RecCountSQL()
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM " & _
"Kunden WHERE Ort='Wien'", dbOpenDynaset)
rs.MoveLast
Debug.Print rs.RecordCount
rs.Close
End Function
Otmar Haring
Seite 26
Access 7.0 - Programmierung
Move-Methode und EOF-Eigenschaft
Im Testfenster sollen die Nachnamen der Kunden der Reihe nach ausgegeben
werden.
Function ReadInfo()
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("Kunden", dbOpenDynaset)
While Not rs.EOF
Debug.Print rs![Nachname]
rs.MoveNext
Wend
rs.Close
End Function
Datensatz hinzufügen (Edit- und Update-Methode)
In der Tabelle „Aufträge“ soll ein Datensatz hinzugefügt werden. Der Kunde ist
dabei zufällig aus der Tabelle „Kunden“ und das Reiseziel aus der Tabelle
„Reiseziele“ zu wählen. Das Buchungsdatum soll ein beliebiges Datum im ersten
Halbjahr 1996 sein.
Public Function RecAdd()
Dim rs1 As Recordset, rs2 As Recordset, rs3 As Recordset
Set rs1 = CurrentDb.OpenRecordset("Aufträge", _
dbOpenTable)
Set rs2 = CurrentDb.OpenRecordset("Kunden", _
dbOpenSnapshot)
Set rs3 = CurrentDb.OpenRecordset("Reiseziele", _
dbOpenSnapshot)
rs2.MoveLast
rs3.MoveLast
rs1.AddNew
rs1![Kunden-ID] = Int(Rnd * rs2.RecordCount) + 1
rs1![Reise-ID] = Int(Rnd * rs3.RecordCount) + 1
rs1![gebucht am] = DateSerial(96, Int(Rnd * 6) + 1, _
Int(Rnd * 27) + 1)
rs1![fällig] = rs1![gebucht am] + 14
rs1.UPDATE
rs1.Close
rs2.Close
rs3.Close
End Function
Find-Methode
Nachdem im Formular „Aufträge“ eine Reise ausgewählt wurde (Ereignis
„AfterUpdate“ des Feldes „Reise-ID“), soll der Preis der Reise aus der Tabelle
„Reiseziele“ übernommen und in der Tabelle „Aufträge“ eingetragen werden.
Um diese Aufgabe lösen zu können, muß der gleiche Datensatz in der Tabelle
„Reiseziele“ gesucht werden, der im Feld „Reise-ID“ ausgewählt wurde.
Otmar Haring
Seite 27
Access 7.0 - Programmierung
Private Sub Reise_ID_AfterUpdate()
Dim rs As Recordset
Dim kriterium As String
Set rs = CurrentDb.OpenRecordset("Reiseziele", _
dbOpenDynaset)
kriterium = "[ID] = " & Me![Reise-ID]
rs.FindFirst kriterium
If Not rs.NoMatch Then
Me![Preis] = rs!Preis
End If
rs.Close
End Sub
Einen bestimmen Datensatz im Formular „Kunden“ suchen
Im Formular „Kunden“ ist im Formularkopf ein Kombinationsfeld zu erstellen, mit
dessen Hilfe ein Datensatz gesucht werden kann. Das Kombinationsfeld beinhaltet
alle Kunden-Datensätze. Durch Auswahl eines bestimmten Kunden soll auch im
Detailbereich des Formulars dieser Kunde aufscheinen.
Private Sub Suchname_AfterUpdate()
Dim rs As Recordset
Dim fm As Form
Set fm = Me
Set rs = Me.RecordsetClone
rs.FindFirst "ID = " & Me!Suchname
fm.Bookmark = rs.Bookmark
rs.Close
End Sub
Hinzufügen von Daten, die in einem Kombinationsfeld eingegeben werden
Der akademischen Grad wird in der Tabelle „Kunden“ mit Hilfe eines
Kombinationsfeldes erfaßt. Dieses Kombinationsfeld erhält seine Daten aus der
unsichtbaren Tabelle „Titel“. Wenn ein neuer Titel eingegeben wird, der noch nicht
in der Tabelle gespeichert ist, soll dieser nach einer Sicherheitsabfrage hinzugefügt
werden. Auch im Kombinationsfeld soll der neu dazugekommene Titel sofort
aufscheinen.
Wenn Daten eingegeben werden, die nicht in der Liste vorkommen, wird die
gleichnamige Ereignisprozedur („NotInList“) aufgerufen, der zwei StandardOtmar Haring
Seite 28
Access 7.0 - Programmierung
parameter übergeben werden:
NewData: Enthält den Eintrag, der nicht in der Liste vorgekommen ist.
Response: Ist eine eingebaute Konstante, die angibt, wie auf das Ereignis
„NotInList“ reagiert wurde. Das Argument kann folgende
Konstanten annehmen:
acDataErrDisplay
(Voreinstellung) Zeigt dem Benutzer
die Standardmeldung an. Wird verwendet,
um den Benutzer zu hindern, einen neuen
Wert zum Listenfeld hinzuzufügen.
acDataErrContinue Unterdrückt die Standardmeldung. Nimmt
den neuen Eintrag nicht in die Liste auf.
acDataErrAdded
Unterdrückt die Standardmeldung. Nimmt
den neuen Eintrag in die Liste auf und
vergleicht durch erneutes Abfragen das
Kombinationsfeld mit den Herkunftsdaten.
Private Sub Titel_NotInList(NewData As String, _
Response As Integer)
If MsgBox("Titel ist nicht in der Liste!" & vbCrLf & _
"Möchten Sie ihn eintragen?", vbYesNo + vbQuestion) = _
vbYes Then
AddTitel NewData
Response = acDataErrAdded
Else
Response = acDataErrContinue
End If
End Sub
Public Function AddTitel(sTitel)
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("Titel")
rs.AddNew
rs!Titel = sTitel
rs.UPDATE
rs.Close
End Function
Abfrage dynamisch erstellen und Ergebnis im Testfenster ausgeben
Durch Aufruf einer Funktion („Selgruppe“) im Testfenster sollen die
Monatssummen der Aufträge als Ergebnis tabellarisch dargestellt werden.
Otmar Haring
Seite 29
Access 7.0 - Programmierung
Dazu ist vorerst eine neue Abfrage zu erstellen, bei der die Argumente mit einer
SQL-Anweisung definiert werden. Das Ergebnis dieser Abfrage wird anschließend
im Testfenster ausgegeben.
Function SelGruppe()
Dim rs As Recordset
Dim q As QueryDef
On Error GoTo Abfragefehler
Set q = CurrentDb.QueryDefs("Test")
q.SQL = "SELECT DISTINCTROW Format([gebucht am], " & _
"'mmmm yy') as Monat, Sum(Aufträge.Preis) AS " & _
"[Summe von Preis] FROM Aufträge GROUP BY " & _
"Format([gebucht am],'mmmm yy') " & _
"ORDER BY First(Aufträge.[gebucht am]);"
Set rs = q.OpenRecordset
While Not rs.EOF
Debug.Print rs.Fields(0), rs.Fields(1)
rs.MoveNext
Wend
rs.Close
Exit Function
Abfragefehler:
Set q = CurrentDb.CreateQueryDef("Test")
Resume Next
End Function
Transaktionen
In der Regel werden Transaktionen verwendet, um die Integrität der Daten zu
gewährleisten, wenn Datensätze in zwei oder mehr Tabellen aktualisiert werden
müssen, und sichergestellt sein muß, daß alle Änderungen in allen Tabellen
vollständig durchgeführt wurden.
Wenn zum Beispiel Geld von einem Konto auf ein anderes überwiesen werden soll,
wird ein Betrag von einem Kontostand abgezogen und zum anderen Kontostand
hinzuaddiert. Wenn eine der beiden Aktualisierungen fehlschlägt, stimmt die
Bilanz der Konten nicht mehr.
Mit der „BeginTrans“-Methode wird die Transaktion eingeleitet. Um alle
Änderungen zu übernehmen, bedient man sich anschließend der „CommitTrans“Methode. Möchte man die Änderungen rückgängig machen, kann dies mit der
„RollBack“-Methode durchgeführt werden.
Die Änderungen werden im Temp-Verzeichnis der Arbeitsstation
zwischengespeichert. Dabei ist zu achten, daß genügend Festplattenspeicher frei
ist, da sonst das Jet-Datenbankmodul einen Fehler auslöst.
Übung:
Otmar Haring
Durch Aufruf einer Funktion sollen in der Tabelle „Aufträge“ zehn neue
Datensätze mit Zufallsdaten hinzugefügt werden (siehe „Datensatz hinzufügen“ auf
Seite 27 und „Find-Methode“ auf Seite 27). Nach jeweils 5 hinzugefügten
Datensätzen soll der Anwender entscheiden können, ob die Datensätze wirklich
angefügt werden sollen oder nicht.
Seite 30
Access 7.0 - Programmierung
Public Function RecAddTrans()
Dim rs1 As Recordset, rs2 As Recordset, rs3 As Recordset
Dim ws As Workspace
Dim kriterium As String
Dim i As Integer
Set ws = DBEngine.Workspaces(0)
Set rs1 = CurrentDb.OpenRecordset("Aufträge", _
dbOpenTable)
Set rs2 = CurrentDb.OpenRecordset("Kunden", _
dbOpenSnapshot)
Set rs3 = CurrentDb.OpenRecordset("Reiseziele", _
dbOpenDynaset)
rs2.MoveLast
rs3.MoveLast
ws.BeginTrans
For i = 1 to 10
rs1.AddNew
rs1![Kunden-ID] = Int(Rnd * rs2.RecordCount) + 1
rs1![Reise-ID] = Int(Rnd * rs3.RecordCount) + 1
rs1![gebucht am] = DateSerial(96, Int(Rnd * 6) + 1, _
Int(Rnd * 27) + 1)
rs1![fällig] = rs1![gebucht am] + 14
kriterium = "[ID] = " & rs1![Reise-ID]
rs3.FindFirst kriterium
If Not rs3.NoMatch Then
rs1![Preis] = rs3![Preis]
End If
rs1.UPDATE
Next
If i = 5 or i = 10 Then
If MsgBox("5 Sätze angefügt, Bestätigen?", _
vbYesNo) = vbYes Then
ws.CommitTrans
Else
ws.Rollback
End If
ws.BeginTrans
End If
ws.Rollback
rs1.Close
rs2.Close
rs3.Close
ws.Close
End Function
Datenbank erstellen, Laufwerk und Verzeichnis wechseln
Im Verzeichnis „C:\Eigene Dateien\Access95\Programmierung“ soll eine neue
Datenbank mit dem Namen „ReisebüroCopy.mdb“ erstellt werden. (Diese
Datenbank wird für anschließende Übungen mit Datenbank-Repliaktionen
benötigt.)
Otmar Haring
Seite 31
Access 7.0 - Programmierung
Sollte das aktuelle Verzeichnis nicht das obengenannte sein, muß dorthin
gewechselt werden. Anschließend wird nach einer Sicherheitsabfrage (ob die Datei
schon besteht) die neue Datenbank mit der Methode „CreateDatabase“ angelegt,
die zwei Argumente benötigt:
Datenbankname: Name der neuen Datenbank
Gebietsschema:
Ein Zeichenfolgeausdruck, mit dem die Sortierreihenfolge zum Erstellen der Datenbank angegeben
wird.
Nähere Hinweise in der Access-Hilfe.
Function CreateDB()
Dim db As DATABASE
Dim ws As Workspace
Set ws = DBEngine.Workspaces(0)
ChDrive "C:"
If CurDir <> _
"C:\Eigene Dateien\Access95\Programmierung" Then
ChDir "C:\Eigene Dateien\Access95\Programmierung"
End If
If Dir("ReisebüroCopy.mdb") <> "" Then
Kill ("ReisebüroCopy.mdb")
End If
Set db = ws.CreateDatabase("ReisebüroCopy", _
dbLangGeneral)
db.Close
ws.Close
End Function
Container- und Document-Objekte
Jedes Database-Objekt besitzt eine Containers-Auflistung, die aus integrierten
Container-Objekten besteht (Databases, Forms, Tables, ...). Jedes Container-Objekt
wiederum besitzt eine Documents-Auflistung, die ein Document-Objekt für jedes
Vorkommen des Objekttyps enthält. Die Eigenschaften der einzelnen Objekte sind
in der Hilfe von Access beschrieben.
Die Namen der Container mit den Namen der darin enthaltenen Dokumente und
deren letztes Änderungsdatum sollen in einer Liste im Testfenster ausgegeben
werden.
Otmar Haring
Seite 32
Access 7.0 - Programmierung
Function ObjName()
Dim db As DATABASE
Dim cont As Container
Dim obj As Document
Dim i As Integer
Set db = CurrentDb
For i = 0 To db.Containers.Count - 1
Set cont = db.Containers(i)
Debug.Print cont.Name
For Each obj In db.Containers(i).Documents
Debug.Print , obj.Name, obj.LastUpdated
Next
Next
db.Close
End Function
Objekte in andere Datenbank kopieren
Alle Tabellen (mit Ausnahme der Systemtabellen) sollen in die vorhin angelegte
Datenbank „ReisebüroCopy“ kopiert werden.
Function CopyObj()
Dim db As DATABASE
Dim doc As Document
Set db = CurrentDb
For Each doc In db.Containers("Tables").Documents
If Left(doc.Name, 4) <> "MSys" Then
DoCmd.CopyObject "ReisebüroCopy.mdb", , acTable, _
doc.Name
End If
Next
db.Close
End Function
Otmar Haring
Seite 33
Access 7.0 - Programmierung
13. Datenbank replizieren
Desingn-Master erstellen
Die Datenbank „ReisebüroCopy“ soll die Eigenschaft „Design-Master“ in einem
Replica-Set bekommen. Dazu wird die Datenbank im Hintergrund exklusiv
(zweiter Parameter auf „true“) geöffnet und die Eigenschaft „replizierbar“
(„Replicable“) auf „true“ („T“) gesetzt.
Function RepliDB()
Dim db As DATABASE
Dim prop As Property
Set db = DBEngine.OpenDatabase("ReisebüroCopy.mdb", True)
Set prop = db.CreateProperty("Replicable", dbText, "T")
db.Properties.Append prop
db.Close
End Function
Replika erstellen
Programmtechnisch gibt es zwei Möglichkeiten, eine Replika zu erstellen.
a) Von der Datenbank „Reisebüro“ ausgehend, wird eine Replika der Datenbank
„ReisebüroCopy“ mit dem Namen „ReisebüroCopy R1“ erstellt. Der zweite
Parameter „Beschreibung“ ist ein String, der das zu erstellende Replikat
beschreibt und ist zwingend vorgeschrieben.
Function Replica1()
Dim db As DATABASE
Set db = DBEngine.OpenDatabase("ReisebüroCopy.mdb", True)
db.MakeReplica "ReisebüroCopy R1.mdb", "Beschreibung"
db.Close
End Function
b)
Von einer replizierbaren Datenbank (Design-Master „ReisebüroCopy“ oder
der Replika „ReisebüroCopy R1“) aus wird die Replika erstellt. Dazu ist ein
Wechsel in eine der vorher angelegten Datenbanken notwendig!
Function Replica2()
Dim db As DATABASE
Set db = CurrentDb
db.MakeReplica "ReisebüroCopy R2.mdb", "Beschreibung"
db.Close
End Function
Synchronisation von Datenbanken
Der zweite optionale Parameter gibt die Richtung an, in die synchronisiert werden
soll:
dbRepImpExpChanges:
dbRepImportChanges:
dbRepExportChanges:
Otmar Haring
Austausch in beide Richtungen (Voreinstellung)
Änderung empfangen
Änderung senden
Seite 34
Access 7.0 - Programmierung
Function Synch()
Dim db As DATABASE
Set db = CurrentDb
db.Synchronize "ReisebüroCopy R1.mdb", dbRepExportChanges
db.Close
End Function
Konfliktlösung bei Replikation
Wenn bei einer Synchronisation in einem Replica-Set ein Konflikt auftritt, wird
automatisch der Konfliktmanager von Access aufgerufen, mit dessen Hilfe der
Konflikt gelöst werden kann.
Möchte man diesen Konfliktmanager durch eine eigene Funktion ersetzen, die
vielleicht die Konflikte automatisch löst, muß über den Menüpunkt
„Datenbankeigenschaften“ im Datei-Menü eine neue Datenbankeigenschaft
(„ReplicationConflictFunction“) hinzugefügt werden, die angibt, welche Funktion
(z.B. „MyConf()“) ausgeführt werden soll, wenn ein Konflikt auftritt.
Name:
Typ:
Wert:
ReplicationConflictFunction
Text
MyConf()
Diese Eigenschaft kann auch programmtechnisch gesetzt werden:
Otmar Haring
Seite 35
Access 7.0 - Programmierung
Function SetConflictProp()
Dim db As DATABASE
Dim doc As Document
Dim prop As Property
Set db = CurrentDb
Set doc = _
db.Containers("Databases").Documents("UserDefined")
On Error GoTo Err_Handler
Set prop = _
doc.CreateProperty("ReplicationConflictFunction", & _
dbText, "MyConf()")
doc.Properties.Append prop
On Error GoTo 0
Weiter:
'Eigenschaft könnte umbenannt werden
doc.Properties("ReplicationConflictFunction") = _
"MyConf()"
Exit Function
Err_Handler:
MsgBox "Property existiert schon, ist aber egal!"
Resume Weiter
End Function
Abfrage der benutzerdefinierten Datenbankeigenschaften
Function DBProps()
Dim db As DATABASE
Dim doc
Dim prop As Property
Set db = CurrentDb
Set doc = _
db.Containers("Databases").Documents("UserDefined")
For Each prop In doc.Properties
Debug.Print prop.Name, prop.Value
Next
db.Close
End Function
Die Funktion liefert folgendes Ergebnis:
Otmar Haring
Seite 36
Access 7.0 - Programmierung
Sollte ein Konflikt auftreten, wird die Tabelle Tabellenname_Conflict erzeugt.
Beim nächsten Öffnen der Datenbank wird dann automatisch die KonfliktProzedur angesprungen, die in den Eigenschaften definiert wurde.
Hier kann der Konflikt programmtechnisch gelöst werden.
Function MyConf()
MsgBox "Hier sollte die Konflikt-Prozedur stehen"
End Function
14. OLE-Programmierung
OLE-Objekt im Formular
Im Formular „Aufträge“ wird ein ungebundenes Objektfeld (EXCEL-Tabelle)
eingefügt. Durch Klick auf den Button „cmdOLE“ werden in der Tabelle die
Monatsumsätze eingetragen.
Die Eigenschaft „Klasse“ des Objektfeldes muß in der Prozedur „cmdOLE_Click“
im Programmcode angepaßt werden:
Function InsExcel(obj As Object)
Dim rs As Recordset
Dim cell As Integer
Set rs = CurrentDb.OpenRecordset("SELECT DISTINCTROW " & _
"Format([gebucht am],'mmm yy') as Monat, " & _
"Sum(Aufträge.Preis) AS [Summe] FROM Aufträge " & _
"GROUP BY Format([gebucht am],'mmm yy') ORDER BY " & _
"First(Aufträge.[gebucht am])")
cell = 1
While Not rs.EOF
obj.Cells(cell, 1).Value = "" & rs.Fields(0)
obj.Cells(cell, 2).Value = "" & rs.Fields(1)
cell = cell + 1
rs.MoveNext
Wend
rs.Close
End Function
Otmar Haring
Seite 37
Access 7.0 - Programmierung
Private Sub cmdOLE_Click()
If OLE1.Class = "Excel.Sheet.5" Then
InsExcel OLE1
Else
MsgBox "Falsche Klasse"
End If
End Sub
Datenaustausch mit Word über OLE
Im Formular „Kunden“ soll ein Button erstellt werden, mit dem die Kundendaten
in ein vorbereitetes Word-Dokument geschrieben werden. Anschließend soll das
Dokument gespeichert und gedruckt und das im Hintergrund geöffnete Word
wieder geschlossen werden.
Das ausgefüllte Word-Dokument „Reisebüro.doc“, das anschließend unter dem
Namen „Test0.doc“ gespeichert wird:
Otmar Haring
Seite 38
Access 7.0 - Programmierung
Dim obj As Object
Dim pfad As String
'
On Error GoTo Pfadfehler
pfad = "C:\Eigene Dateien\Access95\Programmierung\"
Set obj = CreateObject("Word.Basic")
obj.DateiÖffnen pfad & "Reisebüro.doc"
obj.BearbeitenGeheZu "Adresse"
If Me.Geschlecht = 1 Then
obj.Einfügen "Herrn"
Else
obj.Einfügen "Frau"
End If
obj.Einfügen " " & Titel
obj.Einfügen Chr$(11)
obj.Einfügen Vorname & " " & Nachname & Chr$(11)
obj.Einfügen Straße & Chr$(11)
obj.Einfügen PLZ & " " & Ort
obj.BearbeitenGeheZu "Anrede"
obj.Einfügen "" & Briefanrede
obj.DateiSpeichernUnter pfad & "Test0.doc"
obj.DateiDrucken
Set obj = Nothing
Exit Sub
Pfadfehler:
Debug.Print Err.Number, Err.Description
If Err.Number = 177 Or Err.Number = 78 Then
pfad = InputBox("Die Pfadangabe für die Datei" & _
Chr$(13) & Chr$(10) & "'REISEBÜRO.DOC' ist " & _
"falsch!" & Chr$(13) & Chr$(10) & Chr$(13) & _
Chr$(10) & "Wie lautet der richtige Pfad?", _
"Pfadfehler")
If IsNull(pfad) Or pfad = "" Then Exit Sub
End If
Resume
End Sub
Berechnungen in Excel über OLE durchführen
Im Formular „Reiseziele“ werden zwei ungebundene Textfelder und ein Button
eingefügt. Durch Klick auf diesen Button sollen der Tagesdurchschnittspreis der
aktuellen Formularseite sowie der Tagesdurchschnittspreis von allen Angeboten
berechnet werden. Dazu müssen die jeweiligen Datenfelder „Dauer“ und „Preis“
sowie die Berechnungsformeln nach Excel geschrieben werden. Die Ergebnisse der
Berechnungen sollen in den ungebundenen Textfeldern ausgegeben werden.
Otmar Haring
Seite 39
Access 7.0 - Programmierung
Private
Dim
Dim
Dim
Dim
Sub cmdOLEExcel_Click()
obj As Object
rs As Recordset
i As Integer
anz As Integer
Set obj = CreateObject("Excel.Sheet")
obj.Cells(1, 1).Value = Me!Dauer.Value
obj.Cells(1, 2).Value = Me!Preis.Value
obj.Cells(2, 1).Value = "Durchschnitt:"
obj.Cells(2, 2).Value = "=B1/A1"
Me!OLE1.Value = obj.Cells(2, 2).Value
Set rs = CurrentDb.OpenRecordset("Reiseziele")
rs.MoveLast
rs.MoveFirst
anz = rs.RecordCount
For i = 1 To anz
obj.Cells(i, 4).Value = rs!Dauer.Value
obj.Cells(i, 5).Value = rs!Preis.Value
rs.MoveNext
Next
obj.Cells(anz
obj.Cells(anz
obj.Cells(anz
obj.Cells(anz
anz + 1
Me!OLE2.Value
'
'
'
+
+
+
+
1,
1,
2,
2,
4).Value
5).Value
4).Value
5).Value
=
=
=
=
"=Sum(D1:D" & anz & ")"
"=Sum(E1:E" & anz & ")"
"Durchschnitt:"
"=E" & anz + 1 & "/D" & _
= obj.Cells(anz + 2, 5).Value
obj.Application.Visible = True
Stop
obj.Application.Visible = False
Set obj = Nothing
End Sub
Otmar Haring
Seite 40
Access 7.0 - Programmierung
15. Zugriffsberechtigungen
Grundüberlegungen
Access bietet die Möglichkeit, die Datenbank vor unberechtigten Zugriffen zu
schützen. Die Informationen über Benutzer, Gruppen und Paßwörter werden dabei
in einer eigenen Arbeitsgruppen-Datei (*.mdw) gespeichert. Standardmäßig
verwendet Access die Datei „SYSTEM.MDW“. Da es sinnvoll ist, jede zu
schützende Datenbank mit einer eigenen Arbeitsgruppen-Datei zu versehen, um
unterschiedliche Benutzer und Gruppen für diese Datenbank definieren zu können,
muß vorerst eine neue Arbeitsgruppe erstellt werden.
Dies geschieht mit dem Programm „WRKGADM.EXE“, das sich im AccessVerzeichnis befindet. Anschließend können für diese Arbeitsgruppe die Benutzer
und die Gruppen erstellt werden. Bei der Vergabe von Rechten ist zu beachten, daß
der Eigentümer der Datenbank (standardmäßig der Administrator) alle Rechte
besitzt. Dies bedeutet, daß eine Datenbank nur dann sicher geschützt werden kann,
wenn dem Administrator als Standarduser alle Rechte genommen werden.
Otmar Haring
Seite 41
Access 7.0 - Programmierung
Nach dem Start von Access wird über den Befehl „Extras - Zugriffsrechte Benutzer- und Gruppenkonten...“ vorerst das Anmeldeverfahren aktiviert, indem
dem Administrator (dies ist der Standard-User) ein Kennwort zugewiesen wird.
Anschießend ist ein neuer Benutzer einzufügen, der später die Datenbank
administrieren wird. Er muß der Gruppe der „Administratoren“ hinzugefügt
werden. Der Benutzer „Administrator“ muß aus der Gruppe der „Administratoren“
entfernt werden! Wenn anschließend Access neu gestartet wird, ist das
Anmeldeverfahren bereits aktiv.
Um als neuer Eigentümer eine Datenbank erstellen zu können, muß man sich nun
mit dem vorhin definierten Namen anmelden. Da dieser neue Benutzer (der
zukünftige Administrator der Datenbank) noch über kein Kennwort verfügt, muß
ihm dies auf die gleiche Weise zugewiesen werden wie vorher dem Administrator.
Erstellt der nun angemeldete Benutzer eine Datenbank, ist er Eigentümer und
besitzt somit alle Rechte. Muß eine bereits bestehende Datenbank gesichert
werden, ist diese zu laden, und mit dem Menüpunkt „BenutzerDatensicherheitsassistent...“ eine neue Datenbank zu erstellen. Dieser Assistent
weist dem neuen Benutzer alle Rechte zu und entzieht sie zugleich allen anderen.
Nun können andere Benutzer und Gruppen definiert und ihnen Rechte auf die
einzelnen Objekte zugewiesen werden. Wichtig bei der Vergabe der
Berechtigungen ist , daß der Benutzer „Administrator“ und die Gruppe „Benutzer“
über keinerlei Rechte verfügen.
Datenbank sichern, Berechtigungen vergeben
Im folgenden Beispiel sollen alle Änderungen im Formular „Kunden“ in einer
eigenen Tabelle protokolliert werden. Dazu ist eine neue Gruppe „Demogruppe“
und ein neuer Benutzer „Demo“ anzulegen, der Mitglied dieser Gruppe ist. Die
neue Gruppe erhält auf alle Formulare die Berechtigung „Öffnen/Ausführen“ und
auf alle Tabellen mit Ausnahme der „Protokolltabelle“ alle Rechte außer „Entwurf
ändern“ und „Verwalten“. Versucht nun der Demo-User die „Protokolltabelle“ zu
öffnen oder den Entwurf anzusehen, erscheint eine der folgenden
Fehlermeldungen:
Otmar Haring
Seite 42
Access 7.0 - Programmierung
Protokollieren von Benutzeraktionen
Wenn ein Datenbankbenutzer in der Kundentabelle Datensätze neu eingibt,
verändert oder löscht, sollen diese Aktionen in der „Protokolltabelle“ aufgezeichnet
werden. Dazu wird auf die einzelnen Ereignisse mit je einer Prozedur reagiert,
indem eine globale Prozedur mit der Art der Tätigkeit und der betroffenen
Satznummer aufgerufen wird. Beim Löschen eines Datensatzes muß die
Satznummer vor der Löschbestätigung gesichert werden.
Dim Satznummer As Long
Private Sub Form_AfterDelConfirm(Status As Integer)
Protokoll "gelöscht", Satznummer
End Sub
Private Sub Form_AfterInsert()
Satznummer = Me.ID
Protokoll "eingegeben", Satznummer
End Sub
Private Sub Form_AfterUpdate()
Satznummer = Me.ID
Protokoll "geändert", Satznummer
End Sub
Private Sub Form_Delete(Cancel As Integer)
Satznummer = Me.ID
End Sub
Erstellen einer eigenen WorkSpace
Da außer dem Eigentümer der Datenbank die „Protokolltabelle“ niemand öffnen
darf, muß die Datenbank im Hintergrund ein zweites Mal mit einer anderen
WorkSpace geöffnet werden. Das Modul, in welchem der folgende Programmcode
steht, muß auf alle Fälle gegen Zugriffe von anderen Benutzern geschützt werden,
da hier das Kennwort des Eigentümers eingetragen sein muß.
Da bei Anlegen eines neuen Datensatzes zwei Ereignisse (zuerst „AfterUpdate“
und anschließend „AfterInsert“) eintreten, muß im Programmcode darauf
entsprechend reagiert werden.
Otmar Haring
Seite 43
Access 7.0 - Programmierung
Private Const UserName = "Otmar"
Private Const Kennwort = "password"
Sub Protokoll(Tätigkeit As String, Satznummer As Long)
Dim db As DATABASE
Dim db1 As DATABASE
Dim rs As Recordset
Dim ws As Workspace
Dim pfad As String
Set ws = DBEngine.CreateWorkspace("OH-Arbeitsbereich", _
UserName, Kennwort)
DBEngine.Workspaces.Append ws
Set db1 = CurrentDb()
pfad = db1.Name
db1.Close
Set db = ws.OpenDatabase(pfad)
Set rs = db.OpenRecordset("Protokolltabelle")
If Tätigkeit = "eingegeben" Then
rs.MoveLast
rs.Edit
rs.Änderungsart = Tätigkeit
rs.UPDATE
Else
rs.AddNew
rs.Benutzer = CurrentUser()
rs.Änderungsdatum = Now
rs.Änderungsart = Tätigkeit
rs.[bearbeitete ID] = Satznummer
rs.UPDATE
End If
rs.Close
db.Close
ws.Close
End Sub
16. Eigene Statuszeile
In manchen Fällen ist es notwendig, den Benutzer über den Fortschritt von
bestimmten Aktionen zu informieren oder ihn mit laufenden Informationen zu
versorgen. Diese Informationen können in der Statuszeile untergebracht werden.
Mit Hilfe der Funktion „SysCmd“ kann der Statusanzeiger oder ein beliebiger Text
in der Statuszeile abgelegt werden. Weiters liefert diese Funktion auch noch
Informationen über Access und seine dazugehörigen Daten (z.B. Versionsnummer
von Access, Name der verwendeten INI-Datei, ...).
Die Funktion hat folgendes Aussehen. Weitere Informationen sind in der Hilfe
nachzulesen.
Rückgabewert = SysCmd(Aktion[, Text][, Wert])
Otmar Haring
Seite 44
Access 7.0 - Programmierung
Timer-Eigenschaft von Formularen (Uhrzeit in der Statuszeile)
Setzt man den Parameter „Aktion“ auf „acSysCmdSetStatus“ kann ein beliebiger
Text in der Statuszeile abgelegt werden. Der Parameter „acSysCmdClearStaus“
löscht die Statuszeile wieder.
Im folgenden Beispiel sollen Uhrzeit und Datum in der Statuszeile angezeigt
werden, wenn das Formular „Reiseziele“ geöffnet ist. Da sich der Zustand der
Statuszeile ständig ändert, muß jede Sekunde eine Funktion aufgerufen werden, die
den Inhalt der Statuszeile ändert. Die Eigenschaft „Zeitgeberintervall“ („Timer“)
legt eine bestimmte Zeitspanne in Millisekunden fest, nach deren Ablauf das
Ereignis „Bei Zeitgeber“ („OnTimer“) eintritt.
Private Sub Form_Open(Cancel As Integer)
Me.OnTimer = "= StatusDatumZeit"
Me.TimerInterval = 1000
End Sub
Private Sub Form_Close()
Dim r
Me.OnTimer = ""
Me.TimerInterval = 0
r = SysCmd(acSysCmdClearStatus)
End Sub
Function StatusDatumZeit()
Dim r
r = SysCmd(acSysCmdSetStatus, Format$(Time, _
"hh:mm:ss") & "
" & Format$(Date, "dd.mm.yy"))
End Function
Statuszeile mit Fortschrittsanzeige
Wenn Access längere Operationen durchführen muß, kann in der Statuszeile der
Fortschritt der Aktion angezeigt werden.
Im folgenden Beispiel sollen im Kundenformular alle Datensätze durch Klick auf
einen Button durchlaufen und angezeigt werden. In der Statuszeile ist der Benutzer
über den Fortschritt der Aktion zu informieren.
Für diese Aufgabe müssen die Parameter „acSysCmdInitMeter“ (Initialisiert den
Statusanzeiger), „acSysCmdUpdateMeter“ (Aktualisiert den Statusanzeiger) und
„acSysCmdRemoveMeter“ (Entfernt den Statusanzeiger) verwendet werden.
Otmar Haring
Seite 45
Access 7.0 - Programmierung
Private
Dim
Dim
Dim
Dim
Dim
Sub cmdFortschrittSysCmd_Click()
rs As recordset
fm As Form
i As Integer
r As Integer
anz As Long
Set fm = Me
Set rs = fm.RecordsetClone
rs.movelast
anz = rs.recordcount
rs.movefirst
r = SysCmd(acSysCmdInitMeter, "Datensätze anzeigen", anz)
For i = 1 To anz - 1
r = SysCmd(acSysCmdUpdateMeter, i)
rs.movenext
fm.Bookmark = rs.Bookmark
Next
r = SysCmd(acSysCmdRemoveMeter)
rs.Close
End Sub
Statusanzeige in einem eigenen Formular
Da der Statuszeile manchmal zu wenig Aufmerksamkeit geschenkt wird, ist oft
eine Statusanzeige in einem eigenen Formular sinnvoller. In diesem Formular
werden keine Daten verwaltet, deshalb können alle zusätzlichen Bildelemente (wie
Bildlaufleisten, Datensatzmarkierer, Navigationsschaltflächen, usw.) ausgeblendet
werden.
Otmar Haring
Seite 46
Access 7.0 - Programmierung
Durch Klick auf einen Button im Kundenfenster soll eine allgemeine Prozedur
„Fortschrittsfenster“ aufgerufen werden, die das Fenster mit der Fortschrittsanzeige
öffnet. Die Funktion soll so allgemein geschrieben werden, daß sie von jedem
beliebigen Fenster gestartet werden könnte. Der Prozedur werden zwei Parameter
mitgegeben: Der Prozentwert und optional der Titel. Ist der Prozentwert Null, wird
das Fenster geöffnet und initialisiert, beim Wert 100 wird das Fenster wieder
geschlossen.
Private
Dim
Dim
Dim
Dim
Dim
Sub cmdFortschrittFenster_Click()
rs As recordset
fm As Form
i As Integer
r As Integer
anz As Long
Set fm = Me
Set rs = fm.RecordsetClone
rs.movelast
anz = rs.recordcount
rs.movefirst
'Initialisieren der Fortschrittsanzeige
Fortschrittsfenster 0, "Datensätze anzeigen"
For i = 1 To anz - 1
Fortschrittsfenster Int(i / anz * 100 + 0.5)
rs.movenext
fm.Bookmark = rs.Bookmark
Next
Fortschrittsfenster 100
rs.Close
End Sub
Sub Fortschrittsfenster(wert As Integer, Optional Titelzeile)
Static fm1 As Form
Static fm2 As Form
If wert = 0 Then
Set fm1 = Screen.ActiveForm
DoCmd.OpenForm "Fortschrittsanzeige"
Set fm2 = Screen.ActiveForm
fm2.TeilRechteck.Left = fm2.GesamtRechteck.Left
fm2.TeilRechteck.Top = fm2.GesamtRechteck.Top
fm2.TeilRechteck.Height = fm2.GesamtRechteck.Height
If Not IsMissing(Titelzeile) Then
fm2.txtTitel.Caption = Titelzeile
End If
fm2.SetFocus
End If
If wert = 100 Then
DoCmd.Close A_FORM, "Fortschrittsanzeige"
Exit Sub
End If
fm2.TeilRechteck.Width = Int(wert / 100 * _
fm2.GesamtRechteck.Width)
fm2.txtProzent.Caption = Str$(wert) & " %"
DoCmd.RepaintObject A_FORM, "Fortschrittsanzeige"
End Sub
Otmar Haring
Seite 47
Access 7.0 - Programmierung
17. Liste mit Mehrfachauswahl
Die Eigenschaft „Mehrfachauswahl“
Die Eigenschaft „Mehrfachauswahl“ in einem Listenfeld gibt an, ob ein Benutzer
mehrere Zeilen in der Liste auswählen kann oder nicht. Dabei gibt es drei
Einstellungen:
Keine:
Mehrfachauswahl ist nicht möglich
Einzeln:
Mehrere Elemente können durch Mausklick oder Leertaste
ausgewählt werden.
Erweitert:
Mehrere Elemente können durch Mausklick mit „Shift“- bzw.
„Strg“-Taste markiert werden.
Im folgenden Beispiel soll das Kombinationsfeld zur Auswahl des Reisemittels in
eine Multi-Select-Liste umgewandelt werden. Die Bindung an das Tabellenfeld
„Reisemittel“ wird dabei aufgehoben. Ein weiteres Textfeld
„txtReisemittelGesamt“ wird angelegt und an das Tabellenfeld gebunden. Die
Zeichenlänge vom Tabellenfeld sollte entsprechend erhöht werden, da der Inhalt
länger werden kann.
VBA-Eigenschaften von Multiple Choice-Listfeldern:
Selected:
Mit dieser Eigenschaft kann die Auswahl eines Listenfeldes
abgefragt oder gesetzt werden.
Beispiel:
Me!Listbox.Selected(4) = True
wählt das fünfte Element aus
ItemsSelected: Diese Auflistung beinhaltet nur die Indexzahlen der ausgewählten
Zeilen in einem Listenfeld.
Column:
Diese Eigenschaft identifiziert eindeutig einen Eintrag in einem
mehrspaltigen Listenfeld:
Beispiel:
= Me!Listbox.Column(0, 3)
wählt das Element in Spalte 1 (Parameter 0) und
Zeile 4 (Parameter 3) aus
Im folgenden Beispiel wird nach dem Update der Reisemittelliste das Textfeld
„txtReisemittelgesamt“ aus den einzelnen Reisemitteln zusammengestellt. Die
Funktion, die diese Arbeit übernimmt, soll dabei so universell programmiert sein,
daß eine beliebige Liste, ein beliebiges Trennzeichen und eine beliebige Spalte (bei
mehrspaltigen Listen) ausgewertet werden können.
Otmar Haring
Seite 48
Access 7.0 - Programmierung
Private Sub Reisemittelliste_AfterUpdate()
txtReisemittelGesamt = ListeAuswerten _
(Me!Reisemittelliste, ", ", 0)
End Sub
Function ListeAuswerten(Liste As Control, _
Trennzeichen As String, Spalte As Integer) As Variant
'Liste:
Gibt den Namen der Liste an
'Trennzeichen: Gibt das/die Zeichen an, mit dem/denen _
die einzelnen Inhalte getrennt werden
'Spalte:
Gibt die Spalte an, aus der der Inhalt _
genommen werden soll
Dim varReturn As Variant
Dim Zeile As Variant
varReturn = Null
For Each Zeile In Liste.ItemsSelected
If IsNull(varReturn) Then
varReturn = Liste.Column(Spalte, Zeile)
Else
varReturn = varReturn & Trennzeichen & _
Liste.Column(Spalte, Zeile)
End If
Next
ListeAuswerten = varReturn
End Function
Beim Anzeigen eines neuen Datensatzes soll zuerst von allen Zeilen im Listenfeld
die Markierung entfernt werden. Anschließend wird das Feld
„txtReisemittelGesamt“ ausgewertet und die entsprechenden Zeilen im Listenfeld
wieder markiert.
Der Funktion „ListeEinzelnAuswählen“ werden folgende Parameter übergeben:
- der Listenname als Control
- ein Boolescher Wert, der angibt, ob das Feld markiert werden soll oder
nicht
- ein Array von Variantfeldern, die den Inhalt der auszuwählenden Zeilen
beinhalten. Da das Array unterschiedlich groß sein kann, wird dieser
Parameter in der Funktion als „ParamArray“ definiert.
Private Sub Form_Current()
Dim ret As Boolean
ret = ListeAllesAuswählen(Me!Reisemittelliste, False)
ret = ListeEinzelnAuswählen(Me!Reisemittelliste, True, _
WerteBestimmen(Me!txtReisemittelGesamt, ", ", 1), _
WerteBestimmen(Me!txtReisemittelGesamt, ", ", 2), _
WerteBestimmen(Me!txtReisemittelGesamt, ", ", 3), _
WerteBestimmen(Me!txtReisemittelGesamt, ", ", 4))
End Sub
Otmar Haring
Seite 49
Access 7.0 - Programmierung
Function ListeAllesAuswählen(Liste As Control, _
Wert As Boolean) As Boolean
'Liste: Gibt den Namen der Liste an
'Wert: Bestimmt, ob Zeilen ausgewählt oder nicht _
ausgewählt werden sollen
On Error GoTo ListeAllesAuswählen_Fehler
Dim i As Integer
For i = 0 To Liste.ListCount - 1
Liste.Selected(i) = Wert
Next
ListeAllesAuswählen = True
Exit Function
ListeAllesAuswählen_Fehler:
ListeAllesAuswählen = False
Exit Function
End Function
Function ListeEinzelnAuswählen(Liste As Control, Wert As _
Boolean, ParamArray Inhalte()) As Boolean
'Liste:
'Wert:
Gibt den Namen der Liste an
Bestimmt, ob Zeilen ausgewählt oder nicht _
ausgewählt werden sollen
'Inhalte: Array von Inhalten, die ausgewählt werden _
sollen
On Error GoTo ListeEinzelnAuswählen_Fehler
Dim i As Integer
Dim Element As Variant
For i = 0 To Liste.ListCount - 1
For Each Element In Inhalte
If Element = Liste.ItemData(i) Then
Liste.Selected(i) = Wert
Exit For
End If
Next Element
Next i
ListeEinzelnAuswählen = True
Exit Function
ListeEinzelnAuswählen_Fehler:
ListeEinzelnAuswählen = False
Exit Function
End Function
Otmar Haring
Seite 50
Access 7.0 - Programmierung
Die Funktion „WerteBestimmen“ soll ebenfalls so allgemein programmiert werden,
daß sie mehrfach eingesetzt werden kann. Dazu werden ihr drei Parameter
übergeben:
- der Name des Textfeldes als Control
- das Trennzeichen mit dem die Einträge getrennt wurden
- eine Zahl, die angibt, der wievielte Eintrag im Textfeld gefiltert werden
soll. Existiert dieser Eintrag nicht, muß der Wert „Null“ zurückgeliefert
werden.
Function WerteBestimmen(Textfeld As Control, Trennzeichen _
As Variant, Index As Integer) As Variant
'Textfeld:
Gibt den Namen des Textfeldes an, das _
die Werte beinhaltet
'Trennzeichen: Gibt das/die Zeichen an, mit dem/denen _
die einzelnen Inhalte getrennt werden
'Index:
Gibt die an, der wievielte Eintrag _
genommen werden soll
Dim
Dim
Dim
Dim
varReturn As Variant
Position1 As Variant
Position2 As Variant
i As Integer
If IsNull(Textfeld) Then Exit Function
Position2 = 1
For i = 1 To Index
Position1 = Position2
Position2 = InStr(Position1 + 1, Textfeld, _
Trennzeichen)
If Position1 = 0 Then
Exit For
End If
Next
If Position1 = 0 Then
varReturn = Null
ElseIf Position2 = 0 Then
varReturn = Mid(Textfeld, Position1)
Else
varReturn = Mid(Textfeld, Position1, _
Position2 - Position1)
End If
If InStr(varReturn, Trennzeichen) > 0 Then
varReturn = Mid(varReturn, 1 + Len(Trennzeichen))
End If
WerteBestimmen = varReturn
End Function
Otmar Haring
Seite 51
Access 7.0 - Programmierung
18. VBA-Programmierung in Berichten
Seitensumme eines Feldes berechnen
Um im Seitenfuß die Gesamtsumme des Preises darzustellen, müssen die einzelnen
Preise beim Ereignis „Drucken“ in einer Variablen summiert werden. Beim
Ausdrucken des Seitenfußes wird einem ungebundenen Feld der Inhalt der
Variablen zugewiesen.
Dim Gesamt As Double
Private Sub Detailbereich_Print(Cancel As Integer, _
PrintCount As Integer)
Gesamt = Gesamt + Me.Preis
End Sub
Private Sub Seitenfuß_Print(Cancel As Integer, _
PrintCount As Integer)
Me.Gesamtsumme = Gesamt
End Sub
Private Sub Seitenkopf_Print(Cancel As Integer, _
PrintCount As Integer)
If Gesamt = 0 Then
Me.Übertrag = ""
Me.Übertragtext.Caption = ""
Else
Me.Übertrag = Gesamt
Me.Übertragtext.Caption = "Übertrag:"
End If
End Sub
Otmar Haring
Seite 52
Access 7.0 - Programmierung
19. Zusätzliche Anregungen
VB-Control-Arrays simulieren
Visual Basic bietet mit Arrays (Feldern) die Möglichkeit, gleiche Objekttypen in
einer Schleife zu behandeln. Da in Access keine Möglichkeit besteht, solche
Arrays zu definieren, kann man diese mit einem kleinen Trick simulieren.
Angenommen auf einem Formular befinden sich einige Kontrollkästchen
(Checkboxes), die alle bei Eintreten eines bestimmten Ereignisses (z.B. Öffnen des
Formulars, Klick auf einen Button, ...) auf den Wert 0 gesetzt werden sollen.
Um ein Array zu simulieren, müssen alle Objekte den gleichen Namen mit einer
fortlaufenden Nummer haben (z.B. „Schultyp1“, „Schultyp2“, ...). zusätzlich muß
ein unsichtbares Bezeichnungsfeld (z.B. „AnzahlCheckBoxes“) mit der Anzahl der
Objekte als Beschriftung auf dem Formular plaziert werden.
Der folgende Programmcode löscht alle Häkchen in den Kontrollkästchen:
Private Sub cmdClear_Click()
Dim i As Integer
For i = 1 To Val(AnzahlCheckboxes.Caption)
Me("Schultyp" & i).Value = 0
Next
End Sub
Kontrollkästchen mit drei Auswahlmöglichkeiten
Normalerweise bietet ein Kontrollkästchen zwei Auswahlmöglichkeiten
(ausgewählt oder nicht ausgewählt). Unter manchen Umständen ist es aber
notwendig, eine dritte Auswahlmöglichkeit zuzulassen (z.B.: Teilnahme an einer
Schulveranstaltung: „Macht mit“, „Macht nicht mit“, „Ist noch unschlüssig“). Die
dritte Möglichkeit wird durch ein graues Kästchen repräsentiert.
Otmar Haring
Seite 53
Access 7.0 - Programmierung
Um dies zu erreichen, darf das Kontrollkästchen nicht mit einem „Ja/Nein“-Feld
belegt sein, sondern mit einem Zahlenfeld vom Typ „Integer“. Die dritte Option
(graues Kästchen) wird dann angezeigt, wenn das Datenfeld den Inhalt „Null“
besitzt.
Um bei jedem Klick auf das Kästchen einen anderen Inhalt zu erzeugen, muß als
erstes der aktuelle Inhalt in einer Variablen („Alterwert“) gesichert werden.
Daraufhin wird der Inhalt zyklisch gewechselt.
Dim Alterwert As String
Private Sub Teilnahme_Enter()
If IsNull(Teilnahme.Value) Then
Alterwert = ""
Else
Alterwert = Trim$(Str$(Teilnahme.Value))
End If
End Sub
Private Sub Teilnahme_Click()
If Alterwert = "-1" Then
Me!Teilnahme.Value = 0
Alterwert = "0"
ElseIf Alterwert = "0" Then
Me!Teilnahme.Value = Null
Alterwert = ""
Else
Me!Teilnahme.Value = -1
Alterwert = "-1"
End If
End Sub
Unterbrechung des AUTOEXEC-Makros verhindern
Normalerweise kann die Ausführung eines AUTOEXEC-Makros durch Drücken
der „Shift“-Taste beim Laden der Applikation verhindert werden. Diese
Möglichkeit kann in Access 7.0 durch Setzen einer entsprechenden
Datenbankeigenschaft mit dem Namen „AllowByBassKey“ verhindert werden. Die
Eigenschaft kann die Werte „True“ oder „False“ annehmen. Ist
„AllowByBassKey“ auf „True“ gesetzt, ist die Unterbrechung mit der „Shift“Taste möglich, bei „False“ nicht möglich.
Otmar Haring
Seite 54
Access 7.0 - Programmierung
Im folgenden Beispiel soll eine Funktion „Start“ vom „Autoexec“-Makro
aufgerufen werden. Nach Überprüfung des momentanen Benutzers soll nur der
Datenbankeigentümer die Möglichkeit haben, die Startoption zu ändern.
Es ist auch darauf zu achten, daß beim ersten Start (wenn die Eigenschaft noch
nicht besteht) kein Programmfehler auftritt.
Function Start()
Dim db As DATABASE
Dim antwort As Integer
Dim Zustand As Boolean
Dim Startzustand As String
On Error GoTo Start_Error
If CurrentUser() = "otmar" Then
Set db = CurrentDb()
Zustand = db.Properties!AllowBypassKey
If Zustand Then
Startzustand = "IST MÖGLICH"
Else
Startzustand = "IST NICHT MÖGLICH"
End If
antwort = MsgBox("Die momentane Starteinstellung" & _
" lautet: " & vbCrLf & vbCrLf & _
"Unterbrechung des 'AUTOEXEC-Makros' " & _
vbCrLf & Startzustand & vbCrLf & vbCrLf & _
"Soll diese Einstellung geändert werden?" _
, 4 + 32, "Startoption einstellen!")
If antwort = 6 Then
SetByPass Not Zustand
End If
End If
Start_Exit:
Exit Function
Start_Error:
If Err = 3270 Then
'Eigenschaft existiert nicht
db.Properties.append _
db.Createproperty("AllowByPassKey", _
dbBoolean, True)
Resume
Else
'Ein anderer Fehler ist aufgetreten
MsgBox "Unerwarteter Fehler: " & Error$ _
& " (" & Err & ")"
Resume Start_Exit
End If
End Function
Otmar Haring
Seite 55
Access 7.0 - Programmierung
Sub SetByPass(Flag As Boolean)
Dim db As DATABASE
Set db = CurrentDb()
db.Properties!AllowBypassKey = Flag
End Sub
Otmar Haring
Seite 56