Access Anfänger: RecordCount liefert falsche Werte

Aus DBWiki
Wechseln zu: Navigation, Suche

Problem

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


Wiki hinweis.png

Anmerkung:

Wenn man jedoch nur erfahren will, ob das Recordset generell Zeilen enthält, genügt es, einen Ausdruck wie If rs.RecordCount > 0 Then zu verwenden.


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 erhalten, ist zuerst ein MoveLast erforderlich (das steht zwar auch in der Hilfe, wird aber leicht überlesen), um das Einlesen aller Datensätze zu forcieren.

   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. das Recordset durchlaufen
         rs.MoveNext
      Loop
   End If
   rs.Close

Anmerkung

Wenn nicht ohnehin das 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

oder kürzer:

   Debug.Print CurrentDB.OpenRecordset("SELECT Count(*) FROM qryMeineAbfrage", _
                                       dbOpenSnapshot)(0)

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 bzw. zweite Variante zu bevorzugen.

Wenn man lediglich die Anzahl von Datensätzen in einer Tabelle ermitteln will, so funktioniert auch das Folgende ohne Recordset (jedoch 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
   Dim i As Long
   Dim 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
         'das Recordset durchlaufen
         rs.MoveNext
      Next
   End If
 
   rs.Close

Das schreibt man besser und einfacher so:

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