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

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

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:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 2/2006.

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

Zusammenfassung

Lernen Sie die Lösung zu den häufigsten VBA-Problemen kennen.

Techniken

VBA, Komprimieren, MsgBox, MDE, Diagramme

Voraussetzungen

Access 97 und höher

Beispieldateien

FAQ13_A97_FE.mdb, FAQ13_A97_BE.mdb
FAQ13_A00_FE.mdb, FAQ13_A00_BE.mdb

Access-FAQ

Karl Donaubauer, Wien

In der Access-FAQ von Karl Donaubauer (www.donkarl.com) finden Sie die meistgestellten Fragen und Anworten zum Thema Microsoft Access. In dieser Beitragsreihe stellt Karl Donaubauer die wichtigsten Einträge im Detail vor und zeigt Ihnen entsprechende Lösungen anhand praxisnaher Beispiele. Im dreizehnten Teil werden Lösungen für weitere häufige Probleme und Bugs bei der VBA-Programmierung vorgestellt.

Datensätze zählen

In vielen Situationen muss man ermitteln, ob und wie viele Datensätze eine Tabelle oder Abfrage oder ein Recordset enthält. Dafür existieren mehrere Ansätze mit unterschiedlichen Vor- und Nachteilen. Kurz und schnell geschrieben ist die Domänenaggregatfunktion DomAnzahl (DCount in VBA):

DCount("*", "Tabelle")

Domänenaggregatfunktionen sind allgemein als langsam verschrieen. Das stimmt auch in manchen Fällen, vor allem bei der Verwendung in Abfragen, weil die JET-Datenbank-Engine solche Zugriffe nicht optimieren kann, keinen Ausführungsplan verwenden kann und daher alle Datensätze der Domäne ziehen muss. In vielen Fällen lassen sie sich allerdings durchaus brauchbar einsetzen. Testen Sie am besten in der konkreten Anwendung und Umgebung und vor allem mit den zu erwartenden Datenmengen. Ein großer Vorteil der D-Funktionen ist die relativ einfache und kurze Syntax. Ein anderer ist ihre universelle Einsetzbarkeit, sowohl in Steuerelementinhalten wie in Abfragen oder in VBA.

Eine andere Möglichkeit ist die Verwendung der SQL-Aggregatfunktion Count. Der SQL-String einer Abfrage könnte so aussehen:

SELECT Count(*) AS [AnzahlDS] FROM Tabelle;

Diese Methode ist schneller als DCount. Wenn Sie das Ergebnis allerdings außerhalb der Abfrage benötigen, müssen Sie es zum Beispiel mit einem DAO-Recordset abrufen.

DAO bietet zum Zählen der Datensätze die Eigenschaft RecordCount. Der Code im Beispielformular frmDSZaehlen sieht so aus:

Dim db As DAO.Database

Dim rs As DAO.Recordset

Set db = CurrentDb

Set rs = db.OpenRecordset("SELECT * FROM tblArtikel", dbOpenDynaset)

If Not rs.BOF Then

    rs.MoveLast

    Me!txtRecordCountMit = rs.RecordCount

End If

Vor der Verwendung von RecordCount ist es unbedingt notwendig, mit der MoveLast-Methode zum letzten Datensatz des Recordsets zu springen, damit die richtige Anzahl von Datensätzen ermittelt wird. Der Wechsel zum letzten Datensatz braucht bei großen Recordsets natürlich einige Zeit und sollte deshalb nur durchgeführt werden, wenn Sie wirklich sofort die genaue Datensatzanzahl brauchen. Ohne MoveLast ergibt RecordCount 1, wenn Datensätze vorhanden sind, und 0, wenn keine vorhanden sind (s. Abb. 1).

Abb. 1: Varianten zum Zählen von Datensätzen

Wenn das Recordset leer ist, erzeugt MoveLast den Laufzeitfehler 3021 "Kein Aktueller Datensatz". Deshalb wird im Beispielcode vor dem MoveLast auf BOF geprüft.

Wenn ein DAO-Recordset geöffnet wird, gibt es zwei mögliche Positionen: Falls Datensätze vorhanden sind, steht der Zeiger zuverlässig auf dem ersten Datensatz. Die OpenRecordset-Methode hat nämlich ein MoveFirst eingebaut. Ein anfängliches, ausdrückliches MoveFirst im Code, wie man es oft sieht, ist daher nicht notwendig. Falls hingegen keine Datensätze vorhanden sind, sind sowohl die Eigenschaften BOF als auch EOF True. Sie können also wahlweise das eine oder das andere prüfen. Die beliebte Prüfung auf beides ist daher wiederum nicht notwendig.

Wenn es nur darum geht, zu erfahren, ob ein Recordset überhaupt Datensätze hat, und andernfalls zum Beispiel das Durchlaufen des Recordsets ganz zu unterlassen, dann reicht:

If rs.BOF Then Exit Sub

Seek bei eingebundenen
Tabellen

Die schnellste Suche in DAO ist mit der Seek-Methode möglich. Der Grund ist, dass anders als bei FindFirst ein Index verwendet werden kann, der die Suche wesentlich beschleunigt. Je größer die Tabelle, desto größer der Geschwindigkeitsvorteil. Die Seek-Methode hat jedoch den Nachteil, dass sie nur bei Recordsets vom Typ Table anwendbar ist. Dieser ist wiederum nur für Tabellen verfügbar, die sich in der aktuellen Datenbank befinden.

Wenn Sie OpenRecordset auf eine Tabelle in der aktuellen Datenbank anwenden und dabei den Parameter für den Typ nicht angeben, wird automatisch der Typ Table verwendet.

Bei eingebundenen Tabellen hingegen, die der Regelfall in professionell gestalteten Anwendungen sind, ist der Standardtyp Dynaset und der Typ Table nicht verfügbar. Wie die Seek-Methode im Normalfall funktioniert, zeigt der Code der ersten Schaltfläche im Beispielformular frmSeek:

Dim db As dao.Database

Dim rs As dao.Recordset

Set db = CurrentDb

Set rs = db.OpenRecordset("tblArtikel", dbOpenTable)

rs.Index = "PrimaryKey"

rs.Seek "=", "13"

If Not rs.NoMatch Then

    Me!txtSeekIntern = rs!Bezeichnung

End If

Es wird also ein Recordset vom Typ Table geöffnet, die Index-Eigenschaft des Recordsets auf den Namen eines in der Tabelle vorhandenen Indexes gesetzt und dann bei Seek der Operator und der Vergleichsausdruck angegeben.

Wenn man den gleichen Code für eine eingebundene Tabelle verwendet, erzeugt das den Laufzeitfehler "3219: unzulässige Operation", weil hier der Typ Table eben nicht zulässig ist. Lässt man die Typangabe dbOpenTable weg, erzeugt der Code wegen des Seek den etwas aussagekräftigeren Laufzeitfehler "3251: Operation wird für diesen Objekttyp nicht unterstützt!".

Die Lösung ist, als Database nicht Currentdb zu verwenden, sondern mit Opendatabase die externe Datenbank für den Zugriff zu öffnen und dann wieder ein Recordset vom Typ Table zu verwenden:

Set db = DBEngine.Workspaces(0). _
    OpenDatabase("externe DB")

Set rs = db.OpenRecordset _
    ("externe Tabelle", dbOpenTable)

Auch diese Methode wird in der Beispieldatenbank demonstriert.

Aktuelle MDB komprimieren

JET-Datenbanken haben leider die Tendenz, sich auch ohne Datenzuwachs aufzublähen. Die Ursachen sind vielfältig: Bewusst gelöschte Datensätze und Objekte, temporäre Objekte, die Access zur Verarbeitung braucht, diverse Bugs und Probleme von DAO und schlecht kompilierter Code. Bei den meisten dieser Gründe hilft das Komprimieren der Datenbank. Wenn Sie das Komprimieren automatisch durchführen lassen möchten, so haben Sie mit Access 97 schlechte Karten. Das einzig einfache automatisierte Komprimieren ist in Access 97 mit der Sendkeys-Methode möglich:

SendKeys "%xdk"

Mit diesem Code wird die Tastenkombination aufgerufen, die den normalen Menüpunkt zum Komprimieren aufruft: Extras/Datenbank-Dienstprogramme/Datenbank komprimieren.

Leider hat Sendkeys den bekannten Bug, dass es gerne, wenn auch nicht immer, die NumLock-Taste deaktiviert. Zudem ist es oft unmöglich, die Umgebung beim Anwender zu kontrollieren und daher zu wissen, ob der Menüpunkt gerade sichtbar und zugänglich ist und was eine bestimmte Tastenkombination bei den gerade offenen Programmen und Einstellungen am Arbeitsplatz auslöst. Deshalb ist eine grundsätzliche Skepsis gegenüber Sendkeys-Notlösungen angebracht.

Eine andere Möglichkeit in Access 97 ist die Verwendung des TSI SOON (Shut One, Open New) database add-in von Michael Kaplan (http://www.trigeminal.com/utility.asp). Dieses Add-In muss natürlich installiert, weitergegeben und aufgerufen werden.

Mit Access 2000 hat Microsoft endlich eine Möglichkeit zum automatisierten Komprimieren eingebaut. Im Menü/Extras/Optionen/Allgemein lässt sich einstellen, dass die Datenbank beim Schließen komprimiert werden soll.

Wenn Sie die Datenbank hingegen während des laufenden Betriebes komprimieren lassen wollen, so gibt es ebenfalls ab Access 2000 eine wesentlich stabilere und sicherere Methode, um den Menüpunkt für das Komprimieren per VBA aufzurufen, nämlich über die Standardaktion des entsprechenden Commandbar-Objektes (in einer Zeile):

CommandBars("MenuBar").Controls("Extras")
.Controls("Datenbank-Dienstprogramme")
.Controls("Datenbank komprimieren und reparieren...").accDoDefaultAction

Andere MDB komprimieren

Völlig unterschiedlich ist das Vorgehen zum automatisierten Komprimieren einer anderen Datenbank. Meist geht es darum, das Daten-Backend der aktuellen Frontend-mdb zu komprimieren. Die wichtigste Voraussetzung dafür ist, dass die andere MDB nicht geöffnet ist. Das heißt, Sie müssen dafür sorgen, dass beim Komprimieren nicht durch offene Formulare oder andere Datenbankobjekte auf Daten aus eingebundenen Tabellen zugegriffen wird. Ebenso dürfen keine Codeobjekte wie etwa Recordsets geöffnet sein, die auf Tabellen der zu komprimierenden Datenbank basieren. Quellcode 1 zeigt den für das Komprimieren nötigen Code.

Quellcode 1: Komprimieren einer Datenbank

Public Sub procCompactOtherDB(strPath As String)

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

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:

© 2003-2015 André Minhorst Alle Rechte vorbehalten.