Lektionen/Datenzugriff

Domänenfunktionen: DLookup, DCount, DSum

Einsteiger10 Min. Lesezeit

Manchmal brauchst du nur einen Wert aus einer Tabelle: den Preis eines Artikels, die Anzahl offener Bestellungen, die Summe aller Rechnungen eines Kunden. Dafür ein komplettes Recordset zu öffnen, ist umständlich. Die Domänenfunktionen erledigen das in einer einzigen Zeile — direkt im Code, in Formularen oder in Abfragen.

Der Aufbau: DLookup

DLookup holt einen einzelnen Feldwert aus einer „Domäne" (Tabelle oder Abfrage). Die Signatur:

DLookup(Ausdruck, Domäne, [Kriterien])
  • Ausdruck – das Feld (oder eine Berechnung), das du zurückbekommst, als String.
  • Domäne – Name der Tabelle oder Abfrage, ebenfalls als String.
  • Kriterien – optional, eine WHERE-Bedingung ohne das Wort WHERE.
Dim preis As Variant
preis = DLookup("Preis", "Artikel", "ArtikelID = 42")
Debug.Print preis

Ohne Kriterium liefert DLookup den Wert des ersten gefundenen Datensatzes — bei mehreren Treffern ist das nicht vorhersagbar, also grenze sinnvoll ein.

Kriterien richtig quoten

Der häufigste Fehler steckt in den Kriterien. Je nach Feldtyp musst du den Wert anders einfassen:

FeldtypSchreibweiseBeispiel
Zahlohne Anführungszeichen"ArtikelID = 42"
Textin einfachen Hochkommas '…'"Ort = 'Berlin'"
Datumin Rauten, US-Format #mm/dd/yyyy#"Datum = #07/01/2026#"

Bei Textwerten aus Variablen verkettest du den Inhalt zwischen zwei Hochkommas:

Dim ort As String
ort = "Berlin"
preis = DLookup("Umsatz", "Kunden", "Ort = '" & ort & "'")

Bei Datumswerten musst du das US-Format mm/dd/yyyy erzwingen — sonst interpretiert Access den 07.01. je nach Systemeinstellung falsch. Format hilft:

Dim datum As Date
datum = Date                              ' heute
Dim n As Long
n = DCount("*", "Bestellungen", _
           "Bestelldatum = #" & Format(datum, "mm/dd/yyyy") & "#")

Enthält ein Textwert selbst ein Hochkomma (z. B. O'Brien), bricht die '…'-Variante. Nutze dann doppelte Anführungszeichen per Chr(34): "Name = " & Chr(34) & name & Chr(34).

Null behandeln mit Nz

Findet DLookup keinen Datensatz, gibt es Null zurück — nicht 0 und nicht einen leeren String. Rechnest oder verkettest du direkt damit, kracht es oder das Ergebnis wird selbst Null. Fange das mit Nz ab, das Null in einen Ersatzwert wandelt:

Dim preis As Currency
preis = Nz(DLookup("Preis", "Artikel", "ArtikelID = 999"), 0)
' Kein Treffer -> preis = 0 statt Fehler

Willst du unterscheiden, ob wirklich kein Datensatz existiert, prüfe explizit:

Dim ergebnis As Variant
ergebnis = DLookup("Preis", "Artikel", "ArtikelID = 999")
If IsNull(ergebnis) Then
    MsgBox "Artikel nicht gefunden."
Else
    MsgBox "Preis: " & ergebnis
End If

Die ganze Familie: DCount, DSum, DMin, DMax, DAvg

Alle Domänenfunktionen haben denselben Aufbau Funktion(Ausdruck, Domäne, Kriterien). Sie unterscheiden sich nur darin, was sie berechnen:

FunktionErgebnis
DCountAnzahl der Datensätze
DSumSumme eines Feldes
DMinkleinster Wert
DMaxgrößter Wert
DAvgDurchschnitt
' Wie viele offene Bestellungen gibt es?
Debug.Print DCount("*", "Bestellungen", "Status = 'offen'")

' Gesamtumsatz eines Kunden
Debug.Print Nz(DSum("Betrag", "Rechnungen", "KundenID = 7"), 0)

' Höchste vergebene Belegnummer (für die nächste ID)
Dim naechste As Long
naechste = Nz(DMax("BelegNr", "Belege"), 0) + 1

' Durchschnittspreis der Kategorie
Debug.Print DAvg("Preis", "Artikel", "Kategorie = 'Werkzeug'")

Bei DCount ist "*" als Ausdruck am schnellsten — es zählt einfach Datensätze, ohne ein bestimmtes Feld auszuwerten. Ein Feldname würde Null-Werte auslassen.

Bequemlichkeit vs. Geschwindigkeit

Domänenfunktionen sind praktisch, aber nicht kostenlos. Jeder Aufruf baut intern eine kleine Abfrage auf, öffnet sie und wertet sie aus. Für einen einzelnen Wert ist das völlig in Ordnung. In einer Schleife wird es teuer:

' LANGSAM: DLookup pro Durchlauf – öffnet jedes Mal neu
Dim i As Long
For i = 1 To 10000
    Debug.Print DLookup("Name", "Artikel", "ArtikelID = " & i)
Next i

Läuft eine Domänenfunktion über eine Tabelle ohne Index auf dem Kriterienfeld, muss Access im schlimmsten Fall die ganze Tabelle durchsuchen — und das bei jedem Schleifendurchlauf. Öffne dann lieber einmal ein Recordset:

' SCHNELL: ein Recordset, einmal durchlaufen
Dim db As DAO.Database, rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT ArtikelID, Name FROM Artikel", dbOpenSnapshot)
Do Until rs.EOF
    Debug.Print rs!ArtikelID, rs!Name
    rs.MoveNext
Loop
rs.Close

Wann was?

  • Domänenfunktion – für Einzelwerte, Steuerelement-Herkunft in Formularen, Berechnungen in Abfragen, gelegentliche Prüfungen. Kurz und lesbar.
  • Recordset / SQL – sobald du viele Werte brauchst, in Schleifen arbeitest oder große Tabellen ohne passenden Index abfragst. Deutlich schneller.

Ein einzelner DCount-Aufruf ist übrigens fast immer schneller, als ein Recordset nur zum Zählen zu öffnen und MoveLast aufzurufen. Der Nachteil zeigt sich erst bei der Wiederholung.

Zusammengefasst

  • DLookup(Ausdruck, Domäne, Kriterien) holt einen Einzelwert; DCount, DSum, DMin, DMax, DAvg folgen demselben Muster.
  • Kriterien richtig quoten: Zahlen ohne, Text mit '…', Datum mit #mm/dd/yyyy# im US-Format (per Format(datum, "mm/dd/yyyy")).
  • Kein Treffer bedeutet Null — mit Nz(..., Ersatzwert) abfangen oder mit IsNull explizit prüfen.
  • DCount("*", ...) ist zum Zählen am schnellsten; ein Feldname überspringt Null.
  • In Schleifen oder auf großen, nicht indizierten Tabellen sind Domänenfunktionen langsam — dann lieber ein Recordset einmal öffnen und durchlaufen.
Nächste Lektion
ADO-Grundlagen