Programmierung der KVA

Im Beitrag Kunden, Verträge und Anschreiben verwalten lernen Sie eine komplette Anwendung kennen. Der vorliegende Beitrag beschreibt die Technik, die sich hinter dieser Anwendung verbirgt – angefangen mit dem Datenmodell über die Abfragen, Formulare und Berichte bis hin zu den verwendeten VBA-Prozeduren. Spezielle Themen werden in weiteren Beiträgen vertieft, auf die wir an geeigneter Stelle verweisen.

Datenmodell

Das Datenmodell umfasst einige Tabellen, welche die Daten für die eigentliche Anwendung liefern – nämlich die Verwaltung von Kunden, Verträgen und Anschreiben bezüglich dieser Kunden und Verträge. Zusätzlich gibt es noch eine Optionen-Tabelle, eine Tabelle, welche Informationen über Laufzeitfehler speichert sowie eine zum Speichern temporärer Daten beim Erstellen eines Word-Dokuments.

Wir durchlaufen das Datenmodell etwa in der Reihenfolge, in der wir die Elemente der Benutzeroberfläche im Beitrag Kunden, Verträge und Anschreiben verwalten (www.access-im-unternehmen.de/854) beschrieben haben. Dort beginnen wir mit dem Übersichtsformular zur Anzeige der Kunden, welches als Datenherkunft die Tabelle tblKunden verwendet. Zumindest steht dies in der entsprechenden Eigenschaft des Unterformulars sfmKundenuebersicht – tatsächlich gibt es in der Datenbank aber gar keine Tabelle namens tblKunden. Diese Tabelle gab es aber im ersten Entwurf der Datenbank – und sie sah genau so aus wie die Tabelle, die jetzt tblKundenBase heißt (s. Bild 1). Warum der Name dieser Tabelle geändert wurde, erfahren Sie weiter unten.

pic002.png

Bild 1: Entwurf der Tabelle tblKundenBase (früher tblKunden)

Die Tabelle enthält alle für die Kommunikation mit einem Kunden notwendigen Daten wie die Kundennummer (die manuell vergeben wird und vom Wert des Primärschlüsselfeldes KundeID abweichen kann), AnredeID, Vorname, Nachname und weitere Felder.

Felder, die auf ID enden, deuten normalerweise auf das Vorhandensein von Beziehungen zu anderen Tabellen hin, die als Lookup-Tabellen zur Auswahl von Werten für das betroffene Feld dienen können. So ist es auch bei der Tabelle tblKundenBase im Fall der Felder AnredeID und PersoenlicheAnredeID. Beide Felder sind mit entsprechenden Lookup-Tabellen verknüpft, die Sie in Bild 2 vorfinden.

pic003.png

Bild 2: Die Tabellen tblAnreden und tblPersoenlicheAnreden

Verträge speichern

Die Verträge zu jedem Kunden werden in der Tabelle tblVertraege gespeichert. Diese enthält Felder zum Eintragen der wesentlichen Vertragsdaten, die selbst nicht in der Datenbank verwaltet werden (s. Bild 3).

pic004.png

Bild 3: Entwurf der Tabelle tblVertraege

Ein sehr wichtiges Feld dieser Tabelle heißt KundeID und dient zum Eintragen des Wertes des Feldes KundeID der Tabelle tblKundenBase für den Kunden, dem der Vertrag zugeordnet ist.

Weitere Fremdschlüsselfelder dieser Tabelle heißen ZahlweiseID, GesellschaftID, VertragsartID und BankverbindungID.

Bei der mit dem Feld ZahlweiseID verknüpften Tabelle tblZahlweisen handelt es sich wiederum um eine einfache Lookup-Tabelle, die lediglich die entsprechenden Werte zur Auswahl enthält (s. Bild 5 aussehen.

pic006.png

Bild 4: Datenblattansicht der Tabelle tblZahlweisen

pic007.png

Bild 5: Eigenschaften des Nachschlagefeldes ZahlweiseID

Das Feld VertragsartID soll ebenfalls als Nachschlagefeld eingerichtet werden und die Datensätze der Tabelle tblVertragsarten anzeigen. Dies sieht später so aus wie in Bild 6.

pic008.png

Bild 6: Das Nachschlagefeld VertragsartID

Etwas umfangreicher und nicht mehr als einfache Lookup-Tabelle zu bezeichnen ist die Tabelle tblGesellschaften, welche die für das Feld GesellschaftID zur Verfügung stehenden Einträge anbietet. Diese Tabelle enthält aber nicht nur die im Nachschlagefeld angezeigten Datensätze, sondern auch noch weitere Felder, die Sie in Bild 7 erkennen können.

pic005.png

Bild 7: Entwurf der Tabelle tblGesellschaften

Richtig kompliziert wird es dann beim Fremdschlüsselfeld BankverbindungID. Diese dient zwar letztlich auch wieder nur zur Auswahl von Datensätzen einer verknüpften Tabelle namens tblBankverbindungen, allerdings handelt es sich bei der verknüpften Tabelle um eine Hilfe zur Herstellung einer Beziehung zwischen den Tabellen tblVertraege und tblGeldinstitute – und dabei wird dann auch noch das Fremdschlüsselfeld KundeID einbezogen.

Um dies nachzuvollziehen, werfen wir einen Blick auf die Übersicht des kompletten Datenmodells in Bild 8.

pic001.png

Bild 8: Übersicht über das Datenmodell

Dort wird deutlich, dass die Tabelle tblBankverbindungen zunächst einmal die Tabellen tblKunden und tblGeldinstitute zusammenführt. Eigentlich könnte man dem Kunden auch einfach ein Feld namens BLZ und eines namens Kontonummer zuweisen, aber die Anwendung soll für jeden Kunden mehrere Bankverbindungen speichern können – was ja auch realistisch ist, denn Hausbesitzer mögen beispielsweise alle Verträge bezüglich des Hauses von einem eigenen Konto aus bezahlen und andere, wie etwa eine Lebensversicherung, von einem anderen Konto aus.

Aber dies hätte sich realisieren lassen, indem wir einfach eine Tabelle mit den Feldern BLZ, Kontonummer und KundeID erstellen, der wir dann pro Kunde mehrere Bankverbindungen zuweisen können. Für die Kontonummer ist dies in Ordnung, denn die ist wohl für jede Bankverbindung eindeutig, aber die BLZ kann durchaus bei mehreren Bankverbindungen verschiedener Kunden gleich sein. Also legen wir eine eigene Tabelle an, die tblGeldinstitute heißt und neben dem Namen des Geldinstituts auch noch die Bankleitzahl enthält. Statt eines Feldes BLZ fügen wir der Tabelle tblBankverbindungen also ein Fremdschlüsselfeld namens GeldinstitutID zur Auswahl des Geldinstituts hinzu.

So können Sie also nun die Bankverbindungen für einen Kunden definieren. Um diese Bankverbindungen nun auch den Verträgen zuweisen zu können, damit die Beiträge auch vom richtigen Konto abgebucht werden, wenn ein Kunde mehrere Bankverbindungen angegeben hat, erhält die Tabelle tblVertraege auch noch ein Fremdschlüsselfeld, mit dem die Bankverbindung ausgewählt werden kann. Später, beim Entwurf des Formulars zur Eingabe dieser Daten, zeigt dieses Feld natürlich nur die Bankverbindungen und Geldinstitute zum aktuellen Kunden an.

Beschriftungen für die Tabellenfelder einstellen

Die meisten Tabellenfelder werden auf die eine oder andere Art in einem Formular in der Formular- oder Datenblattansicht landen. Dabei ziehen Sie die Felder am einfachsten direkt aus der Feldliste in den Formularentwurf. Access legt dann automatisch Bezeichnungsfelder an, die sich an den Feldnamen orientieren. Bei Feldnamen wie Strasse der EMail ist hier in der Regel Nacharbeit erforderlich, um die Bezeichnungsfelder mit Texten wie Straße oder E-Mail auszustatten. Um diese Arbeit kommen Sie nicht herum, aber Sie können diese zumindest minimieren – nämlich durch Eintragen entsprechender Texte für die Eigenschaft Beschriftung der Felder im Tabellenentwurf. Wenn nämlich Beschriftungen vorhanden sind, übernimmt Access diese statt der Feldnamen als Text für die Bezeichnungsfelder.

In den folgenden Abschnitten schauen wir uns nun die Formulare der Anwendung an.

Die Kundenübersicht

Das Formular frmKundenuebersicht soll gleich beim Start der Anwendung geöffnet werden und eine Übersichtsliste der Kunden anzeigen. Dabei soll es die Möglichkeit bieten, die Details zu einem Kunden anzuzeigen, einen Kunden zu löschen oder einen neuen Kunden anzulegen.

Die Anzeige der Kundenliste soll in einem Unterformular in der Datenblattansicht erfolgen, da dieses gegenüber einem Listenfeld ausreichend Komfort zur Anpassung von Spaltenbreiten und -anordnung oder auch zur Sortierung der Datensätze bietet. Deshalb legen Sie zuerst ein entsprechendes Unterformular namens sfmKundenuebersicht an. Dieses verwendet die Tabelle tblKunden als Datenherkunft und zeigt all ihre Felder an (s. Bild 9).

pic009.png

Bild 9: Entwurf des Unterformulars sfmKundenuebersicht

Dieses Formular fügen wir nach dem Speichern und Schließen gleich nach dem Anlegen in ein weiteres neues, leeres Formular ein – und zwar wie in Bild 10 in den Detailbereich. Dies erledigen Sie, indem Sie das Unterformular sfmKundenuebersicht aus dem Datenbankfenster beziehungsweise Navigationsbereich in den Formularentwurf ziehen und dann seine Größe anpassen. Unter Access 2007 und jünger stellen Sie außerdem die Eigenschaften Horizontaler Anker und Vertikaler Anker jeweils auf den Wert Beide ein.

pic010.png

Bild 10: Haupt- und Unterformular

Dieses Formular speichern Sie unter dem Namen frmKundenuebersicht. Fügen Sie dem Kopfbereich ein geeignetes Bild und eine Beschriftung hinzu. Legen Sie dort außerdem eine Schaltfläche namens cmdSuche an. Im Formularfuß landen weitere Schaltflächen namens cmdOK, cmdNeu, cmdBearbeiten und cmdLoeschen – die Beschriftungen können Sie der Abbildung entnehmen.

Die Schaltfläche cmdOK soll schlicht das Formular schließen. Dies erreichen Sie durch Anlegen der folgenden Ereignisprozedur:

Private Sub cmdOK_Click()
    DoCmd.Close acForm, Me.Name
End Sub

Zum Anlegen der Prozedur markieren Sie die Schaltfläche cmdOK in der Entwurfsansicht, aktivieren mit F4 das Eigenschaftsfenster, wählen für die Eigenschaft Beim Klicken den Wert [Ereignisprozedur] aus und klicken dann auf die Schaltfläche mit den drei Punkten. Die nun erscheinende Prozedur im VBA-Editor ergänzen Sie wie oben angegeben.

tblKunden und tblKundenBase

Nun kümmern wir uns um die weiteren Schaltflächen, die ja zum Beispiel dem Löschen eines der Kundendatensätze dienen. Wollen wir einen Kunden aber wirklich gleich komplett löschen Und damit auch alle Daten, die mit diesem verknüpft sind Nein, das soll nicht geschehen. Zumal Sie ja Ihre Kommunikation dokumentiert wissen wollen. Wie also löscht man einen Kunden, der nicht mehr aktiv ist Man könnte diesen archivieren und diesen anschließend löschen. Einfacher ist es aber, den Kunden nur als gelöscht zu markieren. Und alle Kunden, die so markiert sind, nicht mehr in den Formularen der Anwendung anzuzeigen. Also kommt nun das Feld GeloeschtAm zum Einsatz, das ja bereits in der Abbildung weiter oben zu sehen war.

Wenn Sie sich nun vorstellen, dass die Anwendung in der Entwicklung schon weiter fortgeschritten ist als es im Rahmen dieses Beitrags beschrieben wurde, müssten Sie alle Stellen, an denen die Anwendung auf die Tabelle tblKunden zugreift, so ändern, dass nur noch die Datensätze angezeigt werden, deren Feld GeloeschtAm den Wert Null hat.

Nun unterscheidet Access an keiner Stelle, die sich auf Datenherkünfte oder Datensatzherkünfte bezieht, zwischen Tabellen oder Abfragen. Es spricht also nichts dagegen, einfach die Tabelle tbKunden in tblKundenBase umzubenennen und eine Abfrage namens tblKunden zu erstellen, die nur noch die Datensätze anzeigt, die noch nicht als gelöscht markiert wurden. Diese Abfrage sieht wie in Bild 11 aus.

pic011.png

Bild 11: Die Abfrage tblKunden liefert alle Kunden, die nicht als gelöscht markiert wurden.

Schaltflächen aktivieren und deaktivieren

Abhängig davon, ob das Unterformular überhaupt einen Datensatz anzeigt, sollen die Schaltflächen mit den Beschriftungen Bearbeiten und Löschen aktiviert oder deaktiviert werden.

Dazu stellen wir eine kleine Funktion namens SchaltflaechenAktivieren bereit, die prüft, ob das Unterformular aktuell Datensätze enthält, und die Schaltflächen cmdBearbeiten und cmdLoeschen entsprechend aktiviert oder deaktiviert:

Private Sub SchaltflaechenAktivieren()
    Dim bolNotNull As Boolean
    bolNotNull = Not (objSfmKundenuebersicht.Recordset.RecordCount = 0)
    Me!cmdBearbeiten.Enabled = bolNotNull
    Me!cmdLoeschen.Enabled = bolNotNull
End Sub

Was aber ist objSfmKundenuebersicht – wir wollen doch das Unterformular sfmKundenuebersicht abfragen, das mit Me!sfmKundenuebersicht.Form referenziert werden kann Nun, wir haben doch einiges mehr mit diesem Unterformular vor und deshalb speichern wir eine Referenz auf dieses Unterformular in einer eigenen Objektvariable, die im Kopf der Klasse des Formulars wie folgt deklariert wird:

Dim WithEvents objSfmKundenuebersicht As Form

Und wo belegen wir dieses Objekt mit dem entsprechenden Verweis auf das im Unterformular-Steuerelement enthaltene Formular In der Prozedur, die durch das Ereignis Beim Laden des Hauptformulars ausgelöst wird (s. Listing 1).

Listing 1: Ereignis beim Laden des Formulars frmKundenuebersicht

Private Sub Form_Load()
    Set objSfmKundenuebersicht = Me!sfmKundenuebersicht.Form
    With objSfmKundenuebersicht
        .OnCurrent = "[Event Procedure]"
    End With
    Set objColumnWidths = New clsColumnWidths
    With objColumnWidths
        Set .DataSheetForm = objSfmKundenuebersicht
        .OptimizeColumnWidths
    End With
    Set objDatasheetSelector = New clsDatasheetSelector
    Set objDatasheetSelector.DataSheetForm = objSfmKundenuebersicht
    SchaltflaechenAktivieren
End Sub

Und dort geschieht noch eine Menge mehr. Zum Beispiel stellen wir die Eigenschaft OnCurrent für die Variable objSfmKundenuebersicht auf den Wert [Ereignisprozedur] ein. Dies sorgt dafür, dass wir im gleichen Klassenmodul eine Ereignisprozedur anlegen können, die ausgelöst wird, wenn das referenzierte Unterformular einen neuen Datensatz anzeigt – und das geschieht auch beim Datensatzwechsel. Alles, was wir tun müssen, damit wir diese Ereignisprozedur im Klassenmodul des Hauptformulars statt im Klassenmodul des Unterformulars anlegen können, sind vier Schritte:

  • Deklarieren einer Objektvariablen auf das Unterformular mit dem Schlüsselwort With-Events (bereits erledigt),
  • Festlegen der Eigenschaft OnCurrent mit dem Wert "[Event Procedure]" (auch schon erledigt),
  • Einstellen der Eigenschaft Hat Modul des Unterformulars auf den Wert Ja und
  • Anlegen der entsprechenden Ereignisprozedur im Klassenmodul des Hauptformulars.

Diese Ereignisprozedur sieht wie folgt aus:

Private Sub objsfmKundenuebersicht_Current()
    SchaltflaechenAktivieren
End Sub

Dies sorgt dafür, dass die Prozedur SchaltflaechenAktivieren bei jedem Datensatzwechsel im Unterformular ausgelöst wird und die beiden dadurch aktivierten oder deaktivierten Schaltflächen immer den richtigen Status haben. Dies gilt auch, wenn der letzte Datensatz im Unterformular gelöscht wird – in diesem Fall werden die beiden Schaltflächen dann deaktiviert.

Spaltenbreite anpassen

Die Prozedur Form_Load erledigt aber noch mehr. Zum Beispiel sorgt sie dafür, dass die Spaltenbreiten entsprechend des Inhalts der einzelnen Spalten optimiert werden.

Die wesentliche Funktionalität hierzu befindet sich in einem Klassenmodul namens clsColumnWidths, das Sie im Kopf des Moduls Form_frmKundendetails wie folgt deklarieren (sollten Sie diese Klasse aus der Beispieldatenbank in eine andere Datenbank übertragen können, öffnen Sie einfach den VBA-Editor beider Anwendungen und ziehen Sie die Klasse von einem VBA-Projekt zum anderen):

Dim objColumnWidths As clsColumnWidths

In der Prozedur Form_Load sorgen diese Zeilen dafür, dass die Klasse instanziert und die Spaltenbreiten optimiert werden:

Set objColumnWidths = New clsColumnWidths
With objColumnWidths
    Set .DataSheetForm = objSfmKundenuebersicht
    .OptimizeColumnWidths
End With

Die erste Anweisung instanziert ein neues Objekt auf Basis der Klasse, die übrigen weisen der Klasse das zu optimierende Formular zu und führen schließlich mit OptimizeColumnWidth die Optimierung durch (mehr zu dieser Klasse erfahren sie im Beitrag Datenblatt-Spaltenbreiten automatisch anpassen, www.access-im-unternehmen.de/752).

Zeile bei Klick komplett markieren

Weitere zwei Zeilen sorgen dafür, dass der Benutzer die Daten nicht direkt im Datenblatt bearbeiten kann. Dazu wird beim Anklicken eines Datensatzes direkt der komplette Datensatz markiert. Die dafür nötige Klasse deklarieren Sie im Modulkopf:

Dim WithEvents objDatasheetSelector As clsDatasheetSelector

Diese Klasse wird wieder mit dem Schlüsselwort WithEvents deklariert. Das bedeutet, dass es wieder die Möglichkeit gibt, auf Ereignisse dieser Klasse zu reagieren – dazu gleich mehr. Zunächst die beiden Zeilen, mit denen Sie die Klasse einrichten und einen Verweis auf das betroffene Unterformular übergeben:

Set objDatasheetSelector = New clsDatasheetSelector
Set objDatasheetSelector.DataSheetForm = objSfmKundenuebersicht

Nun zum Ereignis, das Sie für dieses Objekt implementieren können. Es sieht so aus und wird durch einen Doppelklick auf einen der Datensätze ausgelöst:

Private Sub objDatasheetSelector_DblClick()
    KundeBearbeiten objSfmKundenuebersicht!txtKundeID
End Sub

Die einzige Anweisung ruft die Prozedur KundeBearbeiten auf. Dabei übergibt sie als Parameter den aktuellen Wert im Steuerelement txtKunde-ID des Unterformulars – hierzu später mehr.

Damit die Datensätze nicht nur nicht bearbeitet werden können, sondern auch noch kein neuer Datensatz angezeigt wird, stellen Sie die drei Eigenschaften Anfügen zulassen, Löschen zulassen und Bearbeitungen zulassen jeweils auf den Wert Nein ein.

Schaltflächen aktivieren

Schließlich wird beim Laden des Formulars noch die Prozedur SchaltflaechenAktivieren ausgelöst, damit die Schaltflächen gleich beim Öffnen den richtigen Status aufweisen. Man könnte auch davon ausgehen, dass es ausreicht, wenn dies beim Auswählen eines Datensatzes im Unterformular geschieht – schließlich ist das auch beim Öffnen des Formulars der Fall. Allerdings löst das Unterformular das Ereignis Beim Anzeigen bereits zum ersten Mal aus, bevor das Ereignis Beim Laden im Hauptformular feuert.

Das heißt, dass die im Klassenmodul des Hauptformulars implementierte Ereignisprozedur, die durch den Datensatzwechsel im Unterformular ausgelöst wird, beim Anzeigen des ersten Datensatzes nach dem Öffnen des Unterformulars noch gar nicht zum Einsatz kommt. Also müssen wir die Prozedur SchaltflaechenAktivieren im Ereignis Beim Laden des Hauptformulars einmal auf andere Art und Weise auslösen.

Löschen eines Kundendatensatzes

Einen Kundendatensatz löscht der Benutzer durch einen Mausklick auf die Schaltfläche cmdLoeschen. Dies löst die Prozedur aus Listing 2 aus. Wie oben besprochen, sollen Datensätze der Tabelle tblKundenBase aber gar nicht gelöscht, sondern nur als gelöscht markiert werden.

Listing 2: Löschen eines Kundendatensatzes per Schaltfläche

Private Sub cmdLoeschen_Click()
    Dim db As DAO.Database
    Dim lngKundeID As Long
    Dim strSQL As String
    lngKundeID = objSfmKundenuebersicht!KundeID
    Set db = CurrentDb
    strSQL = "UPDATE tblKundenBase SET GeloeschtAm = " & ISODatum(Now) & " WHERE KundeID = " _
        & lngKundeID
    db.Execute strSQL, dbFailOnError
    objSfmKundenuebersicht.Requery
    SchaltflaechenAktivieren
    Set db = Nothing
End Sub

Genau dies erledigt die Prozedur: Sie ermittelt zunächst den Wert des Feldes KundeID des aktuell im Unterformular markierten Datensatzes und speichert diesen Wert in der Variablen lngKundeID. Dieser wird bei der Formulierung einer UPDATE-Abfrage wieder aufgegriffen. Diese UPDATE-Abfrage soll das Feld GeloeschtAm für den betroffenen Datensatz auf das aktuelle Datum samt Uhrzeit einstellen.

Die Execute-Methode der zuvor deklarierten und mit einem Verweis auf die aktuell verwendete Datenbank gefüllten Objektvariablen db führt die SQL-Aktionsabfrage schließlich aus. Danach wird der Inhalt des Unterformulars mit der Requery-Methode aktualisiert und ein Aufruf der Prozedur SchaltflaechenAktivieren sorgt für die Aktualisierung des Aktiviert-Status der Schaltflächen Löschen und Bearbeiten.

Kundendetails anzeigen

Das Anzeigen des Formulars mit den Kundendetails soll auf zwei Arten möglich sein: erstens durch Auswählen des gewünschten Datensatzes und anschließendes Betätigen der Bearbeiten-Schaltfläche und zweitens durch einen Doppelklick auf den Eintrag im Unterformular.

Da es gleich zwei Wege gibt, einen Kunden im Detailformular anzuzeigen, bringen wir die notwendigen Befehle in einer separaten Prozedur unter. Diese wird beim Anklicken der Schaltfläche cmdBearbeiten über die entsprechende Ereignisprozedur wie folgt aufgerufen:

Private Sub cmdBearbeiten_Click()
    KundeBearbeiten objSfmKundenuebersicht!txtKundeID
End Sub

Den Aufruf über die Prozedur, die durch einen Doppelklick auf einen der Einträge im Unterformular ausgelöst wird, haben Sie ja bereits weiter oben kennengelernt.

Die Prozedur KundeBearbeiten sieht wie in Listing 3 aus.

Listing 3: Öffnen eines weiteren Formulars zum Bearbeiten eines Kunden

Private Sub KundeBearbeiten(lngKundeID As Long)
    Dim strWhereCondition As String
    strWhereCondition = "KundeID = " & lngKundeID
    DoCmd.OpenForm "frmKundenDetails", DataMode:=acFormEdit, WhereCondition:=strWhereCondition
    Set objFrmKundenDetails = Forms!frmKundenDetails
    With objFrmKundenDetails
        .OnClose = "[Event Procedure]"
        .AfterUpdate = "[Event Procedure]"
    End With
End Sub

Sie erwartet die ID des anzuzeigenden Kunden und fügt mit diesem ein Kriterium zusammen, das beispielsweise so aussieht:

KundeID = 123

Dann öffnet sie das Formular frmKundenDetails und übergibt dieses Kriterium mit dem Parameter WhereCondition. Außerdem wird das Formular mit DataMode:=acFormEdit auf den Bearbeitungsmodus eingestellt.

Es ist wichtig, dass eventuelle Ónderungen an dem im Detail geöffneten Datensatz gleich nach dem Schließen des Detailformulars in der Kundenübersicht dargestellt werden. Dies erreicht man meist, indem man die DoCmd.OpenForm-Methode mit dem Parameter WindowMode:=acDialog öffnet. Man kann dann abwarten, bis das Formular geschlossen oder unsichtbar geschaltet wird, und das aufrufende Formular mit den folgenden Anweisungen der zwischenzeitlich angehaltenen Prozedur aktualisieren.

Wir machen es hier etwas anders – auch damit Sie während der Bearbeitung des aktuellen Kunden im Formular frmKundenDetails weiter mit dem Formular frmKundenuebersicht arbeiten können.

Das aufgerufene Formular frmKundenDetails wird dazu mit einer modulweit deklarierten Variablen referenziert:

Dim WithEvents objFrmKundenDetails As Form

Für diese legen wir – wie schon für das Unterformular – Ereignisprozeduren an. Diese besitzen nur eine einzige Anweisung, welche die Funktion SilentRequery mit dem Namen des Feldes KundeID aufruft:

Private Sub frmKundenDetails_AfterUpdate()
    SilentRequery objSfmKundenuebersicht, "KundeID"
End Sub
Private Sub frmKundenDetails_Close()
    SilentRequery objSfmKundenuebersicht, "KundeID"
End Sub

Warum legen wir dazu gleich zwei Ereignisprozeduren an Weil wir so nicht nur beim Schließen des Detailformulars, sondern auch beim Speichern des dort angezeigten Datensatzes die Daten in der Kundenübersicht aktualisieren können.

Theoretisch braucht das Formular frmKundendetails keinen eigenen Code, damit diese Vorgehensweise funktioniert. Allerdings können Sie nur auf Ereignisse dieses Formulars reagieren, wenn dieses auch ein Klassenmodul besitzt.

Normalerweise ist dies reine Formsache, da Sie zumindest Code für die Schaltfläche cmdOK hinterlegen, aber zur Sicherheit: Ist dies nicht der Fall, müssen Sie die Eigenschaft Hat Modul des Formulars frmKundendetails auf Ja einstellen.

Neuen Kunden anlegen

Auch zum Anlegen eines neuen Kunden rufen wir das Formular frmKundenDetails auf. Dies gelingt ausschließlich durch einen Mausklick auf die Schaltfläche cmdNeu. Dies löst die folgende Ereignisprozedur aus:

Private Sub cmdNeu_Click()
    DoCmd.OpenForm "frmKundenDetails", DataMode:=acFormAdd
    Set objFrmKundenDetails = Forms!frmKundenDetails
    With objFrmKundenDetails
        .OnClose = "[Event Procedure]"
        .AfterUpdate = "[Event Procedure]"
    End With
End Sub

Die hier verwendeten Anweisungen arbeiten prinzipiell genau so wie die zum Bearbeiten eines vorhandenen Kunden – mit der Ausnahme, dass das Formular diesmal durch den Parameter Datamode:=acFormAdd gleich einen neuen, leeren Datensatz anzeigt. Auch hier gilt: Der neue Datensatz wird spätestens beim Schließen des Detailformulars, aber auch bereits beim Speichern in der Übersicht angezeigt.

Suche starten

Sie können auch das Suchformular aufrufen, um nach bestimmten Datensätzen in der Kundenübersicht zu suchen. Dies gelingt mit einem Klick auf die Schaltfläche cmdSuche. Dies löst schlicht die folgende Prozedur aus, die das Formular frmKundensuche öffnet:

Private Sub cmdSuche_Click()
    DoCmd.OpenForm "frmKundensuche", OpenArgs:="sfmKundenuebersicht"
End Sub

Die Prozedur übergibt den Namen des zu durchsuchenden Unterformulars als Parameter an das aufgerufene Formular.

Feinheiten

Um das Design der beiden Formulare frmKundenDetails und frmKundensuche kümmern wir uns gleich, vorher noch einige Kleinigkeiten:

Das Hauptformular frmKundenuebersicht zeigt selbst keine Daten an, es besteht also kein Anlass, Elemente wie den Datensatzmarkierer oder die Navigationsschaltflächen einzublenden. Also stellen Sie die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen, Trennlinien und Bildlaufleisten auf den Wert Nein und Automatisch zentrieren auf Ja ein.

Kundensuche

Das Formular frmKundensuche wird durch einen Klick auf die entsprechende Schaltfläche des Formulars frmKundenuebersicht geöffnet. Beim Öffnen sollte mit dem Öffnungsargument, das mit Me.OpenArgs abgefragt wird, der Name des Unterformulars übergeben werden, auf das sich die Suche bezieht. Auf diese Weise können das Suchformular und das Suchergebnis aufeinander abgestimmt werden. Details zur Funktion der Kundensuche finden Sie im Beitrag Kundensuche mit Komfort (www.access-im-unternehmen.de/858).

Kunden im Detail anzeigen

Das Detailformular zur Anzeige eines Kunden sieht im Entwurf wie in Bild 12 aus. Es ist an die Datenherkunft tblKunden gebunden – also an die Abfrage, die den gleichen Namen wie eine Tabelle hat, um die Daten der eigentlichen Tabelle gefiltert und ohne als gelöscht markierte Datensätze zu liefern. Wir hätten hier auch die Tabelle tblKundenBase als Datenherkunft angeben können, da das Formular ohnehin nicht alle Datensätze dieser Tabelle liefert, sondern immer nur einen – und der wird über das Übersichtsformular frmKundenuebersicht ausgewählt, das keine als gelöscht markierten Datensätze anzeigt.

pic019.png

Bild 12: Entwurfsansicht des Formulars frmKundendetails

Das Formular enthält alle Felder der Datenherkunft, wobei einige wegen des für die Suche verwendeten Listenfeldes oben rechts in der Abbildung nicht sichtbar sind. Das Formular enthält außerdem zwei Unterformulare: eines zur Anzeige der Bankverbindungen und ein weiteres für die Vertragsdaten. Außerdem finden sich im Formular noch ein Textfeld und ein Listenfeld, die gemeinsam eine Schnellsuche zum flotten Auffinden und Anzeigen weiterer Kunden liefern. Schließlich sind da noch fünf Schaltflächen. Zwei öffnen das Formular frmAnschreibenErstellen, eine zeigt einen Bericht zur Ausgabe von Adressetiketten in der Vorschau an und eine weitere druckt das Adressetikett schließlich aus.

Die letzte Schaltfläche im Bunde heißt cmdOK und schließt das Formular frmKundendetails wieder.

Öffnen des Formulars

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar