Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 2/2003.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Eigene Controls mit Access entwickeln

Christoph Spielmann, Düsseldorf

Zu einer guten Entwicklungsumgebung gehört normalerweise die Möglichkeit, dass sich die zur Verfügung gestellten Bausteine wie Klassen, Objekte und Steuerelemente mit den Bordmitteln beliebig erweitern und ergänzen lassen. Leider ist Access hier insbesondere im Bereich der Steuerelemente gravierend eingeschränkt. Dieser Artikel zeigt Ihnen, wie Sie trotzdem neue Controls mit Access entwickeln und einsetzen können.

Unterformulare, Klassen und Objekte

Eine besondere Eigenschaft von Steuerelementen ist, dass Sie ein einziges Mal programmiert bzw. definiert werden und dann in unterschiedlichen Formularen beliebig oft eingesetzt werden können.

Eine weitere Eigenschaft ist, dass sie universell einsetzbar sind und sich je nach Einsatzgebiet ggf. an die besonderen Bedingungen anpassen lassen. Solche Eigenschaften stellen unter Access im Prinzip alle eingebauten Steuerelemente zur Verfügung, jedoch bietet nur ein Steuerelement die Möglichkeit zur individuellen Programmierung. Hierbei handelt es sich um das Unterformular-Steuerelement.

Die Besonderheit dieses Steuerelements ist, dass Sie hier ein beliebiges Formular innerhalb eines anderen Formulars anzeigen können. Dies funktioniert natürlich auch mehrfach.

So kann beispielsweise ein Unterformular innerhalb eines Formulars auch mehrmals angezeigt werden.

Das Unterformular-Steuerelement sorgt hierbei automatisch dafür, dass von dem betreffenden Formular mehrere Instanzen erzeugt werden, die zwar auf der gleichen Formulardefinition basieren, aber ansonsten unabhängig sind. Beispielsweise kann der Wert einer privaten Variablen in den unterschiedlichen Instanzen auch unterschiedliche Werte annehmen, obwohl diese Variable nur ein einziges Mal definiert ist.

In diesem Zusammenhang verwendet man häufig die beiden Begriffe Klasse und Objekt. Eine Klasse ist eine Schema-Definition, also quasi eine Bauanleitung. Auf der Basis einer Klasse können dann mehrere Objekte (oder Objektinstanzen) erzeugt werden.

Bei einem Formular innerhalb des Datenbankfensters von Access handelt es sich immer um eine Klasse. Erst wenn Sie das Formular öffnen, wird ein entsprechendes Objekt erzeugt.

Mit Hilfe von VBA-Programmcode ist es sogar möglich, mehrere Objektinstanzen eines Formulars zu erzeugen.

Das Formular erscheint in diesem Fall mehrfach auf dem Bildschirm, was zum Beispiel bei der gleichzeitigen Bearbeitung mehrerer Datensätze Sinn machen könnte.

Einen ähnlichen Effekt erzielen Sie, wenn Sie ein Formular mehrmals als Unterformular in ein Hauptformular einbetten.

Um die Anlage der einzelnen Objektinstanzen kümmert sich in diesem Fall Access selbst.

Abb. 1: Die PickList im Einsatz

Abb. 2: Aufbau der Tabelle tblAdressen

Abb. 3: Das Formular frmTest in der Entwurfsansicht

Einsatz eines
Unterformulars als Steuerelement

Das hier vorgestellte Beispiel zeigt Ihnen, wie Sie eine so genannte "Pick-List" als Steuerelement realisieren. Hierbei handelt es sich um zwei Listenfelder, zwischen denen Sie Einträge durch Doppelklicks von links nach rechts übernehmen können (s. Abb. 1).

Solche Steuerelemente werden z. B. dann eingesetzt, wenn Sie aus einer Tabelle mehrere Einträge selektieren möchten.

Eine wichtige Anforderung an dieses Steuerelement ist, dass es möglichst universell und ohne viel Programmieraufwand eingesetzt werden kann.

Dementsprechend greift das Steuerelement nicht direkt auf eine bestimmte Access-Tabelle zu, sondern erwartet die Angabe der Tabelle als Konfigurationsparameter. Einzige Anforderung ist, dass die zugrunde liegende Tabelle ein aktualisierbares Ja/Nein-Feld enthält.

In der Beispieldatenbank Control.mdb finden Sie eine entsprechende Tabelle namens tblAdressen (s. Abb. 2). Das Ja/Nein-Feld IstAusgewählt bestimmt hierbei, ob die Adresse (z. B. für einen Serienbrief) selektiert ist.

Weiterhin enthält die Beispieldatenbank das Formular ctlPickList, also das eigentliche Steuerelement sowie das Formular frmTest (s. Abb. 3) als Test-Container für das Steuerelement. Innerhalb des Formulars frmTest befindet sich ein Unterformular-Steuerelement, das ebenfalls den Namen ctlPickList trägt.

Private Sub Form_Load()

    Me.ctlPickList.Form.SetDataSource "tblAdressen", _
        "Nachname", "AdresseID", "IstAusgewählt", ""

End Sub

Quellcode 1

Public Sub SetDataSource(DataSource As String, _
    DisplayField As String, KeyField As String, _
    SelectionField As String, Condition As String)

    m_DataSource = DataSource

    m_DisplayField = DisplayField

    m_KeyField = KeyField

    m_SelectionField = SelectionField

    m_Condition = Condition

    RefreshData

End Sub

Quellcode 2

Option Compare Database

Option Explicit

Private m_DataSource As String

Private m_DisplayField As String

Private m_KeyField As String

Private m_SelectionField As String

Private m_Condition As String

Quellcode 3

Hier ist das gleichnamige Formular als Unterformular untergebracht. Damit das Steuerelement nicht als Unterformular erkennbar ist, sind sämtliche Rahmen und Navigationselemente des Unterformulars ausgeblendet.

Wie bereits angedeutet, ist eine wesentliche Anforderung an das Steuerelement eine einfache Benutzung. Dementsprechend erfolgt die Initialisierung des Steuerelements durch nur eine Programmzeile im Load-Ereignis des Formulars frmTest (s. Quellcode 1).

Die Initialisierung erfolgt mit Hilfe der SetDataSource-Funktion, der lediglich einige Daten zu der Tabelle übergeben werden, auf der die PickList basieren soll. Dazu gehören beispielsweise der Tabellenname, der Name des Anzeigefeldes, der Name des Primärschlüsselfeldes sowie der Name des Ja/Nein-Feldes.

Nach der Initialisierung ist das Steuerelement bereits voll einsatzfähig.

... und so
funktioniert’s

Die komplette Logik zur Anzeige sowie Aktualisierung der Daten ist in dem Klassenmodul des Formulars ctlPickList untergebracht.

Die Hauptprozedur SetDataSource haben Sie bereits kennen gelernt. Sie dient der Initialisierung des Steuerelements (s. Quellcode 2).

Diese Prozedur macht nichts anderes als die übergebenen Parameter an private Variablen des Klassenmoduls zu übergeben.

Diese Variablen werden auch als "Member"-Variablen der Klasse bezeichnet, weswegen ihnen häufig das Präfix "m_" vorangestellt wird. Die Member-Variablen sind im Kopf des Klassenmoduls deklariert (s. Quellcode 3).

Als letzte Anweisung wird von der SetDataSource-Methode die RefreshData-Methode aufgerufen. Sie ist für die Aktualisierung der linken und der rechten Liste zuständig (s. Quellcode 4). In der linken Liste werden nur Einträge aufgelistet, bei denen das Ja/Nein-Feld den Wert False hat. Alle übrigen Einträge werden in der rechten Liste aufgeführt.

Public Sub RefreshData()

    Dim SQLBase As String

    Dim SQLAll As String

    Dim SQLSelected As String

    SQLBase = "SELECT " + m_DisplayField + ", _
        " + m_KeyField + " FROM " + m_DataSource

    If Len(m_Condition) > 0 Then

        SQLBase = SQLBase + " WHERE " + m_Condition

    Else

        SQLBase = SQLBase + " WHERE True"

    End If

    SQLAll = SQLBase

    SQLAll = SQLAll + " AND " + m_SelectionField _
        + "=False"

    SQLAll = SQLAll + " ORDER BY " + m_DisplayField

    SQLSelected = SQLBase

    SQLSelected = SQLSelected + " AND " _
        + m_SelectionField + "=True"

    SQLSelected = SQLSelected + " ORDER BY " _
        + m_DisplayField

    Me.lstAll.RowSource = SQLAll

    Me.lstSelected.RowSource = SQLSelected

    Me.lstAll.Requery

    Me.lstSelected.Requery

End Sub

Quellcode 4

Private Sub btnSelect_Click()

    Dim ID As Integer

    Dim SQL As String

    If IsNull(Me.lstAll.Value) Then Exit Sub

    Cancel = False

    ID = Me.lstAll.Value

    SQL = "UPDATE " + m_DataSource + " SET " _
        + m_SelectionField + "=True WHERE " _
        + m_KeyField + "=" + CStr(ID)

    On Error Resume Next

    CurrentProject.Connection.Execute SQL

    If Err.Number = 0 Then

        Me.RefreshData

    Else

        Err.Raise vbObjectError + 1, _
            "Datensatz konnte nicht ausgewählt werden"

    End If

End Sub

Quellcode 5

Die Prozedur stellt zu diesem Zweck mit Hilfe der Informationen der Member-Variablen zwei SQL-Anweisungen zusammen und weist diese der RowSource-Eigenschaft der betreffenden Listenfelder zu. Abschließend erfolgt noch eine Aktualisierung mittels Requery-Methode.

Select und
UnSelect

Um einen Eintrag von der linken in die rechte Liste zu befördern, klickt der Benutzer die Schaltfläche ">" an, die sich zwischen den beiden Listenfeldern befindet. Diese Schaltfläche ist mit der Ereignisprozedur aus Quellcode 5 verknüpft.

Auf ähnliche Weise wie bereits bei der Aktualisierung der beiden Listenfelder stellt auch diese Prozedur zunächst eine SQL-Anweisung zusammen. Diesmal handelt es sich allerdings um eine Aktualisierungsabfrage (UPDATE), die den Wert des Ja/Nein-Feldes auf True setzt.

Da bei der Änderung von Daten mit Fehlern zu rechnen ist (z. B. fehlende Schreibrechte oder Datensatzsperren) wird die Ausführung der SQL-Anweisung in eine Fehlerbehandlungsroutine gekapselt. Diese hat die folgende Struktur:

Durch die Resume-Next-Anweisung (s. Quellcode 6) werden zunächst einmal alle Fehler ignoriert. Anschließend wird mit Err.Number geprüft, ob ein Fehler aufgetreten ist. Dieser wird dann ggf. behandelt.

Der Vorteil dieser Struktur ist, dass Fehler immer sofort an der Stelle behandelt werden, an der sie auftreten. Dies ist in vielen Fällen ein deutlicher Vorteil gegenüber den Sprungmarken der On-Error-Goto-Anweisung. Zudem entspricht dies dem Try-Catch-Finally-Konstrukt, das z. B. von VB.NET zur Behandlung von Fehlern eingesetzt wird.

Die btnSelect_Click-Ereignisprozedur nutzt dieses Konstrukt, um im Fehlerfall eine Meldung anzuzeigen und im Erfolgsfall die beiden Listenfelder zu aktualisieren.

Entfernen von Einträgen

On Error Resume Next

    <Anweisungen>    

If Err.Number = 0 Then

    <Anweisungen im Nicht-Fehlerfall>

Else

    <Anweisungen im Fehlerfall>

End If

Quellcode 6

Private Sub lstAll_DblClick(Cancel As Integer)

    btnSelect_Click

End Sub

Private Sub lstSelected_DblClick(Cancel As Integer)

    btnUnSelect_Click

End Sub

Quellcode 7

Zum Entfernen von Einträgen aus der rechten Liste ist die Ereignisprozedur des Buttons "<" zuständig.

Sie hat einen fast identischen Aufbau. Anstatt das Ja/Nein-Feld auf True zu setzen, wird dieses jedoch auf False gesetzt. Außerdem greift sie nicht auf das linke, sondern das rechte Listenfeld zu. Den kompletten Aufbau entnehmen Sie der Beispieldatenbank.

Auswahl per Doppelklick

Um das Hinzufügen und Entfernen von Einträgen weiter zu vereinfachen, kann der Benutzer anstelle eines Klicks auf die beiden Schaltflächen alternativ auch doppelt auf einen Listeneintrag klicken.

Hierzu sind die beiden Doppelklick-Ereignisse der Listenfelder mit den Ereignisprozeduren aus Quellcode 7 verknüpft:

Wie Sie sehen, werden lediglich die betreffenden Ereignisprozeduren der beiden Schaltflächen aufgerufen.

Fazit und Ausblick

Die hier vorgestellte Technik zur Entwicklung von Steuerelementen mit Access bietet sich immer dann an, wenn ein identisches Use-Interface-Element mehrmals in einem Formular oder einer Anwendung auftaucht.

Sie sparen dadurch das Kopieren von Programmcode, was Ihre Anwendung übersichtlicher und damit pflegeleichter macht.

Leider gibt es auch Nachteile. So können mit Hilfe von Unterformularen entwickelte Steuerelemente keine nutzbaren Ereignisse auslösen, was den Einsatzbereich einschränkt.

Sollten Sie darauf nicht verzichten können, bleibt Ihnen leider nur der Einsatz von Visual Basic übrig.

Hier können Sie Steuerelemente entwickeln, die Sie innerhalb von Access genauso wie die fest eingebauten Steuerelemente verwenden können und die sich kaum davon unterscheiden.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Download

Download

Die .zip-Datei enthält folgende Dateien:

Control00.mdb

Beispieldateien downloaden

© 2003-2015 André Minhorst Alle Rechte vorbehalten.