Access Anfänger: RecordCount liefert falsche Werte

Aus DBWiki
Wechseln zu: Navigation, Suche

Problem

Wenn ich einen Recordset öffne, liefert die Eigenschaft RecordCount falsche - viel zu niedrige - Werte.

Lösung

Recordsets vom Typ Dynaset oder Snapshot werden von Access dynamisch nach Bedarf aufgebaut, enthalten also beim Öffnen noch nicht alle Zeilen. Um mit Recordcount die richtige Datensatzzahl zu bekommen, ist erst ein MoveLast erforderlich (das steht zwar auch in der Hilfe, wird aber leicht überlesen):

Dim RS As DAO.Recordset
Set RS = CurrentDB.OpenRecordset("qryMeineAbfrage",dbOpenDynaset)
If Not RS.EOF then
  RS.MoveLast
  Debug.Print RS.Recordcount
  RS.MoveFirst
  Do Until RS.EOF
    ' z.B. den Recordset durchlaufen
    RS.MoveNext
  Loop
End If
RS.Close
Set RS = Nothing

Anmerkung

Wenn nicht ohnehin der gesamte Recordset gelesen oder durchlaufen werden soll, ist es oft effizienter, an dieser Stelle mit den folgenden Konstruktionen zu arbeiten:

Dim RS As DAO.Recordset
Dim strSQL as String
strSQL = "SELECT Count(*) As Anz FROM qryMeineAbfrage"
Set RS = CurrentDB.OpenRecordset(strSQL,dbOpenSnapshot)
Debug.Print RS!Anz
RS.Close
Set RS = Nothing

oder - kurz und knapp:

Debug.Print DCount("*","qryMeineAbfrage")

Hierbei muss man sich aber im Klaren sein, dass DCount wie alle DomainFunktionen (Faustregel: alle mit einem extra D vorn) leider wenig effizient sind. Daher ist erste Variante zu bevorzugen.

Wenn man lediglich die Anzahl von Datensätzen in einer Tabelle ermitteln will, so funktioniert auch das Folgende ohne Recordset (aber nicht bei verknüpften Tabellen!):

Debug.Print CurrentDb.TableDefs("MeineTabelle").RecordCount


Gerade bei Anfängern sieht man häufig (für das Durchlaufen eines Recordsets) die folgende Konstruktion. Sie ist zwar nicht direkt falsch, aber stilistisch eher unschön und auf Grund des MoveLast auch leicht ineffizient:

Dim RS As DAO.Recordset, I As Long, C As Long
Set RS = CurrentDB.OpenRecordset("qryMeineAbfrage",dbOpenDynaset)
 
If Not RS.EOF then
  RS.MoveLast
  C = RS.RecordCount
  RS.MoveFirst
  For I = 1 to C
   'den Recordset durchlaufen
   RS.MoveNext
  Next I
End If
 
RS.Close
Set RS = Nothing

Das schreibt man besser und einfacher so:

Dim RS As DAO.Recordset
Set RS = CurrentDB.OpenRecordset("qryMeineAbfrage",dbOpenDynaset)
Do Until RS.EOF
  ' den Recordset durchlaufen
  RS.MoveNext
Loop
RS.Close
Set RS = Nothing