Standard-Lookupformulare

Lookuptabellen speichern meist Werte, die zum Vermeiden von Redundanzen und Inkonsistenzen aus einer anderen Tabelle ausgelagert wurden. Die Formulare für ihre Bearbeitung sehen meist gleich aus: Ein Hauptformular mit einer OK-Schaltfläche, ein Unterformular mit den Daten – das war es. Solche Formulare braucht man nicht für jede dieser Tabellen einzurichten: Es reicht ein einziges, dem Sie nur noch mitteilen, aus welcher Tabelle oder Abfrage die angezeigten Felder stammen sollen.

Wie ein solches Formular aussieht, entnehmen Sie Bild 1: Es zeigt lediglich die vorhandenen Einträge der Lookuptabelle an und bietet die Möglichkeit, diese zu bearbeiten. Solch ein Formular ist schnell hergestellt: Schnell ein Haupt- und ein Unterformular erstellen, Datenherkunft des Unterformulars einstellen, Felder aus der Feldliste hinzufügen, Unterformular ins Hauptformular einfügen, OK-Schaltfläche unterbringen – fertig!

pic001.png

Bild 1: Ein typisches Lookupformular

Was aber, wenn man eine ganze Reihe solcher Formulare benötigt Dann kommt schon ein wenig mehr Arbeit auf einen zu. Außerdem steigt der Aufwand für änderungen wie etwa das Hinzufügen einer Fehlerbehandlungen oder Wartungsarbeiten proportional zur Anzahl der Formulare.

Aus x mach 1

Was tun Sie, wenn Sie die gleiche Abfolge identischer Codezeilen in einer oder mehreren VBA-Funktionen verwenden Sie erzeugen natürlich eine Prozedur oder Funktion, welche die enthaltenen Anweisungen an nur einer Stelle versammelt und rufen diese Anweisungen dann über die entsprechende Prozedur beziehungsweise Funktion auf – gegebenenfalls unter Einbeziehung eines oder mehrerer Parameter, welche die Prozedur oder Funktion individualisieren.

Genau das gleiche machen wir jetzt mit den Lookupformularen. Wenn Sie in einer Anwendung eine Reihe ähnlich aufgebauter Formulare verwenden, denken Sie einmal darüber nach, ob Sie deren Aufbau nicht genau gleich gestalten können (oder zumindest so, dass dieser über Parameter im gewünschten Maße variiert werden kann).

Wir zeigen, wie das mit einem Lookupformular wie aus Bild 1 funktioniert. Als einzigen Parameter verwenden wir dabei den Namen der Tabelle oder Abfrage, deren Daten angezeigt werden sollen beziehungsweise eine entsprechende SQL-Anweisung. Diese soll mit dem Parameter OpenArgs übergeben werden, sodass der Aufruf unseres Formulars beispielsweise so aussieht:

DoCmd.OpenForm "frmLookup", OpenArgs:="tblVerbrauchsarten"

Das aufgerufene Formular wertet diese Datenherkunft dann aus und füllt die Felder des Formulars entsprechend.

Hauptformular

Das Hauptformular übernimmt die Hauptarbeit des Lookupformulars – zumindest, was den Code angeht. Ansonsten enthält es lediglich das Unterformular sfmLookup, das wir im Anschluss beschreiben, sowie eine Schaltfläche mit der Beschriftung OK, die das Formular schließen soll (siehe Bild 2). Diese Schaltfläche löst die folgende Ereignisprozedur aus:

pic002.png

Bild 2: Das Formular frmLookup samt Unterformular in der Entwurfsansicht

Private Sub cmdOK_Click()
    DoCmd.Close
End Sub

Das Unterformular enthält drei ungebundene Textfelder samt Bezeichnungsfeldern. Die Textfelder heißen txtValue1, txtValue2 und txtValue3, die Bezeichnungsfelder lblValue1, lblValue2 und lblValue3. Wie Sie die Felder anordnen, ist egal – hauptsache, Sie stellen die Eigenschaft Standardansicht des Unterformulars auf Datenblatt ein.

Formular öffnen

Kommen wir zum Aufrufen des Formulars. Dies geschieht, wie bereits erwähnt, über die DoCmd-OpenForm-Anweisung mit dem Namen der Datenherkunft als OpenArgs-Parameter. Diesen muss das Formular beim Öffnen auswerten, was in einer Prozedur geschieht, die durch das Ereignis Beim Öffnen geschieht.

Diese Prozedur prüft, ob der OpenArgs-Parameter einen Wert enthält und bricht das Öffnen des Formulars ab, wenn dies nicht der Fall ist:

Private Sub Form_Open(Cancel As Integer)
    If Len(Nz(Me.OpenArgs, "")) = 0 Then
        Cancel = True
    End If
End Sub

Dies sollten Sie bedenken, wenn Sie das Formular frmLookup der Beispieldatenbank per Doppelklick auf den Eintrag im Datenbankfenster beziehungsweise Navigationsbereich öffnen möchten.

Nach dieser Prüfung geht die eigentliche Arbeit los, und zwar in der Ereignisprozedur Beim Laden des Formulars (s. Listing 1).

Listing 1: Beim Laden des Formulars werden auch die Felder angepasst und gefüllt.

Private Sub Form_Load()
    Dim db As DAO.Database
    Dim obj As Object
    Dim strColumnHeader As String
    Dim strOpenArgs As String
    Dim strCaption As String
    Dim i As Integer
    Dim intFieldcount As Integer
    Dim lngWidth As Long
    strOpenArgs = Nz(Me.OpenArgs, "")
    Set db = CurrentDb
    Me!sfmLookup.Form.Recordsource = strOpenArgs
    WizHook.Key = 51488399
    Select Case WizHook.ObjTypOfRecordSource(strOpenArgs)
    Case 0
    On Error Resume Next
    db.QueryDefs.Delete "qdfTemp"
    On Error Goto 0
    Set obj = db.CreateQueryDef("qdfTemp", strOpenArgs)
    Case 1
    Set obj = db.TableDefs(strOpenArgs)
    Case 2
    Set obj = db.QueryDefs(strOpenArgs)
    End Select
    intFieldcount = obj.Fields.Count
    If intFieldcount > 3 Then
        intFieldcount = 3
    End If
    For i = 1 To 3
        If intFieldcount < i Then
            Me!sfmLookup.Form.Controls("txtValue" & i).ColumnHidden = True
        Else
            Me!sfmLookup.Form.Controls("txtValue" & i).ControlSource = obj.Fields(i - 1).Name
            strColumnHeader = obj.Fields(i - 1).Name
            On Error Resume Next
            strColumnHeader = obj.Fields(i - 1).Properties("Caption")
            On Error Goto 0
            Me!sfmLookup.Form.Controls("lblValue" & i).Caption = strColumnHeader
            Me!sfmLookup.Form.Controls("txtValue" & i).ColumnWidth = (Spaltenbreite(db, _
            strOpenArgs, strColumnHeader, Me!sfmLookup.Form.Controls("txtValue" & i)) + 500)
            lngWidth = lngWidth + Me!sfmLookup.Form.Controls("txtValue" & i).ColumnWidth
        End If
    Next i
    Me.InsideWidth = Me.InsideWidth - Me.sfmLookup.Width + lngWidth + 500
    Me!sfmLookup.Width = lngWidth + 500
    strCaption = obj.Name
    On Error Resume Next
    strCaption = obj.Properties("Description")
    On Error Goto 0
    Me.Caption = strCaption
End Sub

Das Öffnungsargument wird hier zunächst in der Variablen strOpenArgs zwischengespeichert und dem Unterformular über die Eigenschaft Recordsource als Datenherkunft zugewiesen. Damit ist das Unterformular an die betroffene Tabelle oder Abfrage gebunden.

Danach benötigten wir ein Objekt, anhand dessen wir die Felder der Datenherkunft durchlaufen können, um die Felder des Unterformulars anpassen und füllen zu können. Da der Benutzer mit dem Öffnungsargument beliebige Datenherkünfte übergeben können soll (also Tabellen, Abfragen oder SQL-Ausdrücke), haben wir zwei Möglichkeiten:

Entweder wir öffnen ein Recordset-Objekt auf Basis der angegebenen Datenherkunft und stellen dies per WHERE-Bedingung so ein, dass es keine Datensätze zurückliefert (denn wir brauchen es ja nur zur Identifikation der Felder), oder wir verwenden eines der Datendefinitions-Objekte wie TableDef oder QueryDef. Diese enthalten keine Daten, sondern nur die Definition der Tabelle beziehungsweise Abfrage.

Die erste Variante übergehen wir diesmal, da wir erst noch prüfen müssten, ob der übergebene Ausdruck eine Tabelle, Abfrage oder ein SQL-Ausdruck ist und ob dieser gegebenenfalls schon eine WHERE-Klausel enthält – sprich: Es würden eine Reihe Zeichenkettenfunktionen aufgerufen, die wir uns diesmal einfach sparen möchten.

Im Falle der TableDef-/QueryDef-Variante wissen wir allerdings ebenfalls nicht, ob strOpenArgs nun eine Tabelle, eine Abfrage oder einen SQL-Ausdruck enthält. Das ist aber kein Problem, denn die nicht dokumentierte WizHook-Klasse liefert uns mit ObjTypOfRecordSource eine kleine Funktion, der wir den Datenherkunftsausdruck einfach übergeben können (vorherige Aktivierung durch WizHook.Key = 51488399 nötig). Heraus kommt eine von drei Zahlen:

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