Access bietet von Haus aus eine komfortable Datenbindung für Formulare: Man trägt eine Tabelle oder Abfrage als Datensatzquelle ein, bindet die Steuerelemente über ihren Steuerelementinhalt an Felder – und Access erledigt den Rest. Wer jedoch sicherstellen möchte, dass seine Tabellen nicht von außen ausgelesen werden können, darf keine Tabellen oder Tabellenverknüpfungen mehr im Frontend haben. Wir müssen uns also nach einer Alternative umsehen. Dazu entfernen wir alle kritischen Elemente aus dem Frontend und bauen die Formulare um. Aber wie greifen wir auf die Daten zu? Dazu nutzen wir die Recordset-Eigenschaft von Formularen und Steuerelementen. Diese können ein per VBA zusammengestelltes Recordset nutzen. In diesem ersten Teil zeigen wir, wie das mit einfachen Detailformularen und in der Datenblattansicht funktioniert. Danach bauen wir unser Wissen aus und beschäftigen uns mit Haupt- und Unterformularen und Steuerelementen wie dem Kombinations- und dem Listenfeld.
ADODB statt DAO
Warum nutzen wir in diesem Artikel ADODB statt DAO? Weil es flexibler ist, gerade wenn wir die vorgestellten Techniken auch für den Zugriff auf SQL Server-Datenbanken nutzen wollen.
Beispieldatenbank: Frontend mit kennwortgeschütztem Backend
Als Beispiel nutzen wir eine Frontend-Datenbank, die aktuell noch über Tabellenverknüpfungen auf die Tabellen eines Backends zugreift. Dieses ist wiederum per Kennwort geschützt.
Das ist ein wichtiger Baustein im Hinblick auf die Sicherheit der Daten, denn wenn der Benutzer Zugriff auf das Backend hat, kann er dieses theoretisch auch einfach kopieren. In diesem Fall wären die geplanten Sicherheitsmaßnahmen im Frontend nutzlos.
Unser Frontend enthält zu Beginn noch die Verknüpfungen zu den Tabellen im Backend, die wir mit dem Bordmitteln von Access hinzugefügt haben (siehe Bild 1).

Bild 1: Datenbank mit Tabellenverknüpfungen
ADODB-Bibliothek referenzieren
Wir können mit Early Binding oder Late Binding auf die Elemente der ADODB-Bibliothek zugreifen.
Zum Programmieren nutzen wir allerdings Early Binding, da wir so IntelliSense verwenden können. Dazu fügen wir dem VBA-Projekt einen entsprechenden Verweis hinzu (siehe Bild 2).

Bild 2: Verweis auf die ADODB-Bibliothek
VBA-Funktionen für den Zugriff auf Connection und Recordset
Wir werden immer wieder den gleichen Code verwenden, um die Recordset-Eigenschaften von Formularen und Steuerelementen mit Daten zu füllen. Daher legen wir gleich ein paar Funktionen an, welche diese Aufgabe erledigen und rufen diese einfach vom Formular aus auf.
Das Modul mdlADODB enthält alle Hilfsfunktionen, die wir für den Zugriff auf die Datenbank benötigen. Wir legen es einmalig an und verwenden es in allen Formularen der Anwendung. Die erste Konstante steuert, welches Backend verwendet wird:
'Art der Verbindung: '1 = CurrentProject.Connection '2 = Access-Backend (.accdb) '3 = SQL Server Private Const cIntConnection As Integer = 2
Mit dem Wert 1 nutzen wir CurrentProject.Connection – also die Verbindung, die Access für das aktuelle Frontend ohnehin offen hält. Das ist sinnvoll, wenn Frontend und Backend dieselbe Datenbank sind oder wenn die Tabellen des Backends per Tabellenverknüpfung eingebunden sind. Mit dem Wert 2 öffnen wir eine eigene ADODB-Verbindung auf eine kennwortgeschützte Access-Backend-Datenbank. Mit dem Wert 3 verbinden wir uns mit einem SQL Server. Der Wechsel des Backends ist damit auf eine einzige Zeile reduziert.
Die Verbindungsstrings für die beiden echten Verbindungen stehen als Konstanten im Modul. Für das Access-Backend ergänzen wir den Provider-String später um den Dateipfad und das Kennwort:
'Verbindungsstring für Access-Backend (ACE-Provider) Private Const strCnnAccess As String = _ "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" 'Verbindungsstring für SQL Server (Windows-Authentifiz.) Private Const strCnnSQLServer As String = _ "Provider=MSOLEDBSQL;Server=amvDesktop2023;" & _ "Database=ADODBRecordsets;Trusted_Connection=Yes;"
Für das Access-Backend benötigen wir zusätzlich den Dateinamen der Backend-Datenbank sowie das Kennwort. Beides steht ebenfalls als Konstante im Modul. Den vollständigen Pfad ermitteln wir zur Laufzeit per GetDBPfad, damit die Anwendung auch nach einem Verschieben von Frontend und Backend in einen anderen Ordner weiterhin funktioniert:
'Dateiname des Access-Backends Private Const strDBName As String = _ "FormulareMitADODBRecordset_BE.accdb" 'Datenbankpasswort des Access-Backends Private Const strDBPasswort As String = "kennwort" Private Function GetDBPfad() As String GetDBPfad = CurrentProject.Path & "\" & strDBName End Function
Nur der Dateiname steht fest im Code – der Ordner wird immer zur Laufzeit aus CurrentProject.Path abgeleitet. Wer Backend und Frontend in getrennten Ordnern betreibt, trägt stattdessen einfach den vollständigen Pfad als Konstante ein.
CurrentProject.Path kann auch durch einen festen Pfad ersetzt werden. Alternativ kann man die Funktion auch so umbauen, dass der Pfad beispielsweise aus der Registry eingelesen wird. Wenn dort kein Pfad gespeichert ist, könnte man diesen per Datei-Dialog abfragen.
Die Funktion GetConnection
Die Funktion GetConnection ist der zentrale Baustein des Moduls. Sie gibt abhängig von cIntConnection eine geöffnete ADODB.Connection zurück.
Alle anderen Funktionen des Moduls – und alle Formulare der Anwendung – rufen ausschließlich diese eine Funktion auf, um eine Verbindung zu erhalten (siehe Listing 1).
Public Function GetConnection() As ADODB.Connection Dim cnn As ADODB.Connection Dim strConn As String Select Case cIntConnection Case 1 'CurrentProject.Connection wiederverwenden Set GetConnection = CurrentProject.Connection Exit Function Case 2 'Access-Backend: Verbindungsstring zusammenstellen strConn = strCnnAccess & GetDBPfad() If strDBPasswort <> "" Then strConn = strConn & ";Jet OLEDB:Database Password=" & strDBPasswort End If Case 3 'SQL Server: Verbindungsstring direkt verwenden strConn = strCnnSQLServer End Select Set cnn = New ADODB.Connection cnn.Open strConn Set GetConnection = cnn End Function
Listing 1: Die Funktion GetConnection
Bei Case 1 verlassen wir die Funktion sofort per Exit Function: CurrentProject.Connection ist bereits offen und gehört Access – wir dürfen sie weder über cnn.Open öffnen noch später schließen.
Bei den Werten 2 und 3 stellen wir zunächst den Verbindungsstring zusammen und öffnen am Ende gemeinsam eine neue Verbindung. Diese neue Verbindung müssen wir später auch wieder schließen – dazu gleich mehr.
Beim Access-Backend ergänzen wir den Provider-String um den Pfad aus GetDBPfad() und, falls vorhanden, um das Kennwort.
Der Schlüssel für das Datenbankpasswort lautet Jet OLEDB:Database Password – dieser Name stammt noch aus der Zeit des Jet-Datenbankmoduls und wird vom neueren ACE-Provider unverändert weiterverwendet.
Die Funktion GetRecordset
Die zweite Hilfsfunktion GetRecordset öffnet ein Recordset auf Basis eines SQL-Strings und gibt es zurück. Sie kapselt die immer gleichen Schritte – Verbindung holen, Recordset anlegen, Cursor konfigurieren, öffnen – so dass wir in den Formularen nur noch den SQL-String übergeben müssen (siehe Listing 2).
Public Function GetRecordset(ByVal strSQL As String, Optional ByVal lngCursorType As Long = adOpenStatic, _ Optional ByVal lngLockType As Long = adLockOptimistic) _ As ADODB.Recordset Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Set cnn = GetConnection() Set rst = New ADODB.Recordset rst.CursorLocation = adUseClient rst.Open strSQL, cnn, lngCursorType, lngLockType Set GetRecordset = rst End Function
Listing 2: Die Funktion GetRecordset
Cursor- und Sperrtyp sind als optionale Parameter mit sinnvollen Standardwerten ausgelegt. adOpenStatic liefert einen statischen Cursor, der alle Daten einmalig in den Arbeitsspeicher lädt. Das ist die Voraussetzung für adUseClient, denn clientseitige Cursor unterstützen nur statische oder Forward-Only-Cursor. adLockOptimistic sperrt den Datensatz erst beim Update-Aufruf kurz, was Konflikte im Mehrbenutzerbetrieb minimiert.
Warum adUseClient fest und nicht als Parameter? Weil wir das Recordset anschließend an die Recordset-Eigenschaft eines Formulars binden wollen – und Access erwartet dafür zwingend einen clientseitigen Cursor. Wer ein Recordset nur lesend durchlaufen möchte, ohne es ans Formular zu binden, kann zwar auch einen serverseitigen Cursor verwenden, aber für den Zweck dieser Beitragsreihe ist adUseClient die richtige Wahl.
Ein wichtiges Detail: cnn ist hier eine lokale Variable. Bei adUseClient ist das kein Problem – ADODB trennt das Recordset nach dem Öffnen intern von der Verbindung, sodass die Connection freigegeben werden kann, ohne das Recordset zu beeinträchtigen.
Das Recordset lebt danach eigenständig im Speicher. Bei einem serverseitigen Cursor wäre das anders: Dort muss die Verbindung so lange offen bleiben, wie das Recordset verwendet wird.
Die Testprozedur
Bevor wir das Modul in Formularen einsetzen, prüfen wir mit einer einfachen Testprozedur, ob Verbindung und Recordset korrekt funktionieren. Test_GetRecordset öffnet ein Recordset mit den ersten zehn Datensätzen der Tabelle tblKunden und gibt KundeID und Firma im Direktbereich aus:
Public Sub Test_GetRecordset() Dim rst As ADODB.Recordset Set rst = GetRecordset( _ "SELECT TOP 10 * FROM tblKunden") Do While Not rst.EOF Debug.Print rst!KundeID, rst!Firma rst.MoveNext Loop End Sub
Wir stellen cIntConnection auf den gewünschten Wert, drücken F5 im VBA-Editor und prüfen im Direktbereich, ob die Daten korrekt ausgegeben werden. Liefert die Prozedur Ergebnisse, sind Verbindungsstring, Pfad und Kennwort korrekt – wir können mit der Implementierung der Formulare beginnen. Voraussetzung ist, dass es eine entsprechende Backend-Datenbank oder SQL Server-Datenbank gibt.
Detailformular mit Recordset füllen
Damit kommen wir zum eigentlich Kern – dem Füllen der Recordset-Eigenschaft eines Formulars mit dem Ergebnis der Funktion GetRecordset.
Um dieses einfach erstellen zu können, ist es wichtig, dass die Tabellen noch in der Datenbank liegen oder entsprechende Tabellenverknüpfungen vorhanden sind. Auf diese Weise können wir das Formular schnell über die Eigenschaft Datensatzquelle mit der Tabelle verknüpfen und die Steuerelemente als gebundene Steuerelemente aus der Feldliste in das Formular ziehen.
Die Bindung der Steuerelemente an die Datensatzquelle funktioniert nämlich nach dem Zuweisen eines Recordsets genauso wie mit einer direkt für die Eigenschaft Datensatzquelle angegebenen Tabelle oder Abfrage.
Dazu legen wir ein neues, leeres Formular namens frmKunden an und fügen Datensatzquelle und Steuerelemente wie in Bild 3 hinzu.

Bild 3: Ausstatten des Formulars mit gebundenen Steuerelementen
Nun folgen die entscheidenden Schritte:
- Wir leeren die Eigenschaft Datensatzquelle wieder.
- Dann fügen wir für das Ereignis Beim Öffnen die Ereignisprozedur aus Listing 3 hinzu.
Private Sub Form_Open(Cancel As Integer) Set Me.Recordset = GetRecordset("SELECT * FROM tblKunden") End Sub
Listing 3: Das Ereignis Beim Öffnen
Öffnen wir das Formular nun in der Formularansicht, zeigt dieses die Daten wie in einem herkömmlichen gebundenen Formular an. Wir können in den Datensätzen blättern, neue Datensätze anlegen, vorhandene Datensätze bearbeiten und löschen.
Nur für Abonnenten
Ab hier wird’s wirklich spannend – der Rest ist exklusiv für Abonnenten.
Mit dem Abo von Access im Unternehmen bekommst du den kompletten Artikel – inklusive vollständigem Code, Beispieldatenbank und Schritt-für-Schritt-Erklärung.
So sparst du dir stundenlanges Herumprobieren, vermeidest teure Fehler in deiner Access-Anwendung und kannst Lösungen direkt in deinem Unternehmen einsetzen, statt nur darüber zu lesen.
Teste Access im Unternehmen jetzt 4 Wochen lang kostenlos: Voller Zugriff auf alle Artikel, Downloads und Beispieldatenbanken. Kein Risiko – wenn es für dich nicht passt, kündigst du einfach innerhalb der ersten vier Wochen.
Bereits Abonnent? Hier einloggen
Kostenlos & unverbindlich
Oder hast Du eine konkrete Frage zu Deiner eigenen Access-Anwendung?
Vielleicht stellt Deine Anwendung Dich vor eine Herausforderung, zu der Du bisher keine Lösung findest. Schlechte Performance, kein ausreichender Zugriffsschutz, Du bist unsicher über Dein Datenmodell oder Dein Code liefert unerklärliche Fehler?
In unserem kostenlosen Access-Audit schaut sich André Minhorst persönlich gemeinsam mit Dir Deine Lösung per Zoom an – und zeigt Dir, wo Datenmodell, VBA-Code, Ergonomie und Sicherheit Optimierungspotenzial bieten.
Jetzt kostenloses Access-Audit anfordern →