Access-FAQ: Rund um Access

Zusammenfassung

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

Techniken

VBA, DAO, ADO, SQL

Voraussetzungen

Access 97 und höher

Beispieldateien

FAQ12_A97.mdb (Access 97)FAQ12_A00.mdb (Access 2000 und höher)

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 zwölften Teil werden Lösungen für die häufigsten Probleme in VBA vorgestellt.

Jahrelang war eine der häufigsten Fragen zum Thema Access-Programmierung, ob nun DAO oder ADO als Datenzugriffstechnik zu lernen und zu verwenden sei. Heute kommt die Frage etwas seltener, auch, weil das Match inzwischen entschieden ist. Microsoft hat von cirka 1999 bis 2001/2002, das heißt, ab der Veröffentlichung von Access 2000 bis in die Zeit von Access XP hinein, versucht, das althergebrachte DAO loszuwerden und durch ADO und ADOX zu ersetzen. Viele Buchautoren sind dem MS-Marketingwirbel erlegen und haben dieses Anliegen freudig weiterpropagiert. Allein, die überwältigende Mehrheit der Access-Programmierer ist MS hier nicht gefolgt, sondern bei DAO geblieben. ADO konnte sich nur in Nischen durchsetzen, etwa bei ADPs und beim Zugriff auf JET-Dateien im klassischen ASP.

Bei der reinen Entwicklungsarbeit mit Access, JET und MDBs hatte ADO keine Chance, weil DAO und JET als Duo gewachsen, besser integriert und meist performanter sind und waren. Da half es auch nichts, dass der Zugriff auf manche Erweiterungen in JET 4.0 nur für ADO ermöglicht wurde, während DAO von MS bewusst vernachlässigt wurde. Bei der täglichen Brotarbeit war und ist DAO einfach beliebter. Microsoft hat diese Realität spät, aber doch akzeptiert. Wenn man in Access 2000 oder XP eine neue Datenbank anlegt, ist standardmäßig nur der Verweis auf ADO vorhanden. Das führte zu millionenfachen Verweisproblemen und ebenso vielen Fragen in Access-Foren. Bei einer neuen Datenbank in Access 2003 hingegen ist nicht nur der DAO-Verweis wieder vorhanden, sondern er steht in der Reihenfolge über dem ADO-Verweis. In der nächsten Version von Access gibt es sogar zum ersten Mal nach vielen Jahren wieder Anpassungen und Neuerungen in DAO.

Das ist nicht nur die Konsequenz der Beharrlichkeit der Access-Gemeinde. Das MS-Marketing konzentriert sich seit Jahren ausschließlich auf .NET und damit ADO.NET. Der Name ist mehr oder weniger eine Finte, denn diese Zugriffstechnologie hat nicht sehr viel mit dem klassischen ADO zu tun. ADO ist also auch aus Marketingsicht bereits wieder veraltet. Fazit der jahrelangen Schlacht:

  • DAO ist ein Evergreen und Königin für Access/JET/MDBs.
  • ADO regiert bei ADPs, also Access-Projekten mit dem MS SQL Server als Backend.
  • ADOX , die ADO-Erweiterung für JET, war nur eine Episode.
  • ADO.NET könnte die Zukunft in allen MS-Anwendungen sein. MS hat es aber noch nicht geschafft, .NET ernsthaft in die Office-Welt und -Programmierung zu integrieren. Sie sollten auch als vielleicht reiner Access-Entwickler diese interessante Technologie im Auge behalten. Sie ist aber noch nicht mit Access oder VBA nutzbar.
  • Eines der ersten Probleme jedes Access-VBA-Programmierers ist ebenso ein beliebtes Streitthema unter erfahrenen Programmierern: Wann ist bei Bezügen der Punkt, wann das Ausrufezeichen als Trennzeichen voranzusetzen oder ist die Verwendung der String-Schreibweise generell vorzuziehen

    Eine einfache Grundregel ist: vor Objekten ein Ausrufezeichen, vor Auflistungen und Eigenschaften ein Punkt. Eine andere bekannte Merkregel lautet: Wenn nach dem Trennzeichen ein Element folgt, das fix in Access eingebaut ist, dann gehört der Punkt dorthin. Wenn das Element benutzerdefiniert ist, dann verwendet man das Ausrufezeichen. Ein Beispiel (in einer Zeile):

    Application.Forms!frmKunden.Controls!Nachname.Visible

    Die Forms-Auflistung ist von Access vorgegeben, deshalb wird hier der Punkt vorangestellt. Das Formular frmKunden wurde vom Entwickler erstellt, deshalb kommt hier das Ausrufezeichen zum Zuge. Die Controls-Auflistung ist wieder ein eingebautes Element von Access. Nachname ist ein benutzerdefinierter Steuerelementname. Die Eigenschaft Visible stammt wiederum von Access.

    Diese Regel gilt auch für die meistangewandte Kurzform:

    Forms!frmKunden!Nachname.Visible

    So einfach diese Grundregeln sind, so diffizil wird es im Detail, weil VBA sehr variabel ist und oft mehrere Varianten zulässt. Eine Quelle der Unsicherheit und der häufigste Streitpunkt ist dabei Punkt oder Ausrufezeichen nach dem Schlüsselwort Me. Mit Me bezieht man sich auf das Objekt, das heißt die Instanz der Klasse, in der der aktuelle Code ausgeführt wird. In Access ist das meist ein Formular oder ein Bericht. Nach den oben angeführten Regeln müsste man sich auf Steuerelemente mit Ausrufezeichen beziehen, also: Me!MeinSteuerelement.

    Steuerelemente sind in VB und VBA aber nicht nur Objekte, sondern auch Eigenschaften von Formularen. Deshalb funktioniert ebenso: Me.MeinSteuerelement.

    Manche Programmierer bevorzugen diese Schreibweise, weil sie damit im VBA-Editor Intellisense nutzen können, ihnen also automatisch die Liste der im jeweiligen Kontext verfügbaren Objekte und Eigenschaften angezeigt wird (s. Abb. 1).

    Abb. 1: Punkt bringt Intellisense im Kontext.

    Bei Verwendung des Ausrufezeichens tritt Intellisense nicht in Aktion. Sie können zwar mit der Tastenkombination STRG + Leertaste die Auswahlliste erzwingen, diese zeigt dann aber nicht die in diesem Kontext verfügbaren Einträge, sondern alle für den VBA-Code in der aktuellen Anwendung verfügbaren Schlüsselworte und Objekte an (s. Abb. 2).

    Abb. 2: Auswahlliste ohne Kontext

    Die Punkt-Schreibweise hat also einen unbestreitbaren Vorteil. Der Nachteil ist jedoch, dass manchmal unvorhersehbare und von Microsoft nicht dokumentierte Probleme damit auftauchen. So kommt es vor, dass nach einer Konvertierung in eine höhere Access-Version oder auch einfach nach einer Neukompilierung die Bezüge nicht mehr funktionieren. Oft passiert diese Art Korruption, wenn für die Steuerelemente dieselben Namen wie für die Felder der Datenquelle verwendet werden. Das scheint aber nur eine der möglichen Mitverursacher zu sein. Jedenfalls treten derartige Probleme mit Ausrufezeichen nicht auf. Deshalb ist es sicherer, auch hier das Ausrufezeichen zu verwenden, oder die ebenfalls zuverlässige String-Schreibweise mit Klammern:

    Me("MeinSteuerelement")

    oder

    Me.Controls("MeinSteuerelement")

    Für viele Aufgaben in der VBA-Programmieung ist es von Vorteil oder unbedingt notwendig, statt fixer Objektnamen Variablen verwenden zu können. Das betrifft sowohl Steuerelemente in Formularen und Berichten als auch Felder in Recordsets von DAO oder ADO. Die Lösung für diese Anforderung ist die Schreibweise mit runden Klammern.

    Ein Steuerelement können Sie zum Beispiel so ansprechen:

    Forms("Formularname")(StringVariable)

    Ebenso funktioniert es mit einem Feld in einem Recordset:

    rs(StringVariable)

    Die häufigste Verwendung findet die eben behandelte Klammer-Schreibweise in Schleifen zum Durchlaufen von Controls- oder Fields-Auflistungen. Meistens geht es darum, per Code mehrere oder alle Steuerelemente eines Formulares oder Berichtes zu durchlaufen, um eine bestimmte Eigenschaft für diese Elemente in einem Rutsch zu prüfen oder zu ändern.

    Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

    Workplace

    Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

    Schreibe einen Kommentar

    Access-FAQ: Rund um Access

    Roland Grothe, Hanau; André Minhorst, Duisburg

    Zusammenfassung

    Erstellen Sie ein Add-In zum Messen und Vergleichen der Performance von Funktionen.

    Techniken

    Domänenfunktionen

    Voraussetzungen

    Access 97 und höher

    Beispieldateien

    Domaenenfunktionen97.mdb (Access 97)Domaenenfunktionen00.mdb (Access 2000 und höher)

    Dieser Beitrag stellt Ihnen eine Gruppe von Funktionen vor, die einen recht einfachen Zugriff auf Daten in beliebigen Tabellen oder Abfragen einer Access-Datenbank ermöglichen. Mit diesen so genannten Domänenfunktionen ist es möglich, Tabellendaten in Form von Funktionsergebnissen zum Beispiel als Feldinhalte oder als Kriterien in Abfragen zur Verfügung zu stellen. Anhand einiger Praxisbeispiele erfahren Sie, in welchen Fällen der Einsatz von Domänenfunktionen sinnvoll ist und wann es besser ist, auf andere Alternativen zur Datenermittlung zurückzugreifen.

    Domänenfunktionen lassen sich am einfachsten als „in eine Funktion gepackte SQL-Abfragen“ definieren. Mit Domänenfunktionen lassen sich fast alle Abfragen ersetzen, die allerdings eine Bedingung zwingend erfüllen müssen: Sie dürfen lediglich einen einzigen Wert zurückliefern. Die Bezeichnung dieses Funktionstyps erklärt sich aus dem Begriff Domäne (engl.: Domain), eine in Datenbank-Kreisen übliche Bezeichnung für eine Datensatzgruppe. Die insgesamt zwölf von Access zur Verfügung gestellten Domänenfunktionen ermöglichen den schnellen und unkomplizierten Zugriff auf Informationen aus einer Tabelle oder einer gespeicherten Abfrage.

    Sie lassen sich sehr flexibel einsetzen und stellen oft die einzige Möglichkeit dar, das Ergebnis einer Funktionsabfrage in einem Formular- oder Berichtsfeld darzustellen, ohne aufwändigen VBA-Code schreiben zu müssen. Sie sind auch immer dann hilfreich, wenn ein solches Ergebnis zu weiteren Berechnungen benötigt wird, da Sie direkt in dem jeweiligen Ausdruck anstelle eines konkreten Wertes verwendet werden.

    Tab. 1 zeigt alle Domänenfunktionen in Deutsch und Englisch inklusive Beschreibung. Sie können in der deutschen Version von Access fast überall sowohl die deutschen als auch die englischen Funktionsbezeichnungen verwenden. Access wandelt diese automatisch in die deutsche Bezeichnung um. Dies gilt allerdings nicht für VBA-Code. Dort verwendete Funktionen müssen mit der englischen Bezeichnung eingegeben werden. In VBA werden die Funktionsparameter statt mit dem Semikolon mit einem Komma voneinander getrennt.

    Funktion (engl. Bez.)

    Beschreibung

    DomAnzahl (DCount)

    Anzahl der Datensätze aus der Tabellen- bzw. Abfrage-Domäne, bei denen der Inhalt des in Ausdruck definierten Feldes bzw. das Ergebnis dieses Ausdrucks nicht Null ist. Berücksichtigt werden nur Datensätze, die dem in Kriterium festgelegten Kriterium entsprechen (die Syntaxbeschreibung gilt für alle Domänenfunktionen).

    DomSumme (DSum)

    Summe der Feldinhalte

    DomErsterWert (DFirst)

    Feldinhalt des ersten Datensatzes

    DomLetzterWert (DLast)

    Feldinhalt des letzten Datensatzes

    DomMittelwert (DAvg)

    Durchschnittswert des Feldinhaltes. Nullwerte werden ignoriert

    DomVarianz (DVar)

    Varianz eines Feldes, bezogen auf eine Stichprobe

    DomVarianzG (DVarP)

    Varianz eines Feldes, bezogen auf die Gesamtmenge

    DomStdAbw (DStDev)

    Standardabweichung eines Feldes, bezogen auf eine Stichprobe

    DomStdAbwG (DStDevP)

    Standardabweichung eines Feldes, bezogen auf die Gesamtmenge

    DomMin (DMin)

    minimaler Wert eines Feldes

    DomMax (DMax)

    maximaler Wert eines Feldes

    DomWert (DLookup)

    Feldinhalt des ersten Datensatzes

    Tab. 1: Domänenfunktionen von Access

    Der Aufruf einer Domänenfunktion erfolgt immer in dieser Form:

    Funktion(Ausdruck;Domäne[;Kriterium])

    Alle drei Parameter werden in Form einer Zeichenkette übergeben, wobei die ersten beiden zwingend notwendig sind. Der Parameter Kriterium ist optional und kann weggelassen werden, wenn er nicht benötigt wird. Im Prinzip finden Sie in den Parametern die Hauptkomponenten einer SQL-Abfrage wieder, wobei lediglich die entsprechenden Schlüsselwörter weggelassen werden. Fügen Sie diese (in Gedanken) wieder hinzu, erhalten Sie den SQL-Befehl:

    SELECT Ausdruck FROM Domäne WHERE Kriterium

    Tatsächlich baut Access aus den Parametern einen der jeweiligen Domänenfunktion angepassten SQL-Befehl zusammen. Daher müssen Sie bei der Verwendung von Domänenfunktionen alle Bedingungen und Einschränkungen beachten, die auch für „normale“ SQL-Befehle gelten.

    Dies gilt vor allem für die vom SQL-Interpreter vorgeschriebenen amerikanischen Formatierungen, auf die der Beitrag später noch eingehen wird. Für die folgenden Beschreibungen der einzelnen Parameter verwenden Sie als Beispiel die Domänenfunktion DomWert(), die einen einzelnen Wert aus einer Tabelle oder Abfrage ermittelt und die Funktion DomAnzahl(), welche die Anzahl der Datensätze zurückgibt, die einen Eintrag in einem bestimmten Feld enthalten.

    Der Parameter „Ausdruck“

    Bei diesem Parameter handelt es sich normalerweise um den Namen des Feldes, das die benötigte Information enthält. Der Feldname wird als Zeichenkette übergeben, daher müssen Sie ihn in Anführungszeichen setzen. Um etwa das Bestelldatum des ersten Datensatzes der Tabelle Bestellungen zu ermitteln, verwenden Sie folgenden Ausdruck:

    DomWert("[Bestelldatum]";"[Bestellungen]")

    Unter VBA würde dieser Ausdruck so aussehen (in einer Zeile):

    Dlookup("[Bestelldatum]","[Bestellungen]")

    Sie können das Ergebnis dieses Ausdrucks im Direktfenster durch Voranstellen der Anweisung Debug.Print oder dessen Abkürzung, dem Fragezeichen (), ausgeben lassen (s. Abb. 1).

    Abb. 1: Testen einer Domänenfunktion im Direktfenster

    Statt eines einzelnen Feldnamens kann aber auch ein komplexerer Ausdruck übergeben werden, der Informationen aus mehreren Feldern zusammenfasst oder Berechnungen durchführt. In diesem Fall setzen Sie den gesamten Ausdruck in doppelte Anführungszeichen. Der folgende Ausdruck ermittelt beispielsweise die Zeit zwischen der Bestellung und der Lieferung des ersten Datensatzes der Tabelle Bestellungen:

    DomWert("[Lieferdatum] - [Bestelldatum]"; "[Bestellungen]")

    Die VBA-Variante lautet:

    Dlookup("[Lieferdatum] - [Bestelldatum]", "[Bestellungen]")

    Befinden sich innerhalb des Ausdrucks doppelte Anführungszeichen, ersetzen Sie diese durch einfache Anführungszeichen, die vom SQL-Interpreter als Begrenzungszeichen anerkannt werden.

    Der folgende Ausdruck ermittelt die Firmenbezeichnung aus dem ersten Datensatz der Tabelle Kunden und stellt den Ansprechpartner anschließend in Klammern dar:

    DomWert("[Firma] & '' ('' & [Kontaktperson] & '')''";"[Kunden]")

    beziehungsweise

    Dlookup("[Firma] & '' ('' & [Kontaktperson] & '')''","[Kunden]")

    Anstelle eines einfachen Anführungszeichens können Sie auch zwei doppelte Anführungszeichen verwenden, allerdings wird ein solcher Ausdruck sehr schnell unübersichtlich:

    DomWert("[Firma] & "" ("" & [Kontaktperson] & "")""";"[Kunden]")

    Die Zeichenkette kann der Domänenfunktion auch als Bezeichner, als Ergebnis einer Funktion oder (in VBA) als Variable übergeben werden.

    In diesem Fall lassen Sie die Anführungszeichen weg. Es muss jedoch sichergestellt sein, dass die übergebene Zeichenkette die bereits angesprochenen formalen Bedingungen erfüllt, ansonsten erhalten Sie den Ausdruck #Fehler als Ergebnis.

    Der Parameter „Domäne“

    Wie auch der Parameter Ausdruck ist der Parameter Domäne nicht optional und daher unbedingt einzugeben. Als gültige Werte wird der Name jeder Tabelle oder gespeicherten Abfrage der aktuellen Datenbank in Form einer Zeichenkette akzeptiert. Auch für diesen Parameter gelten die gleichen Regeln bezüglich der Anführungszeichen und eckigen Klammern wie beim Parameter Ausdruck. Wird als Domäne der Name einer Abfrage verwendet, kann es sich hierbei nur um eine gespeicherte Abfrage handeln. Es ist nicht möglich, diesen Parameter wie im Ausdruck

    DomWert("[Bestelldatum]";"SELECT * FROM [Bestellungen]")

    Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

    Workplace

    Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

    Schreibe einen Kommentar

    Access-FAQ: Rund um Access

    Zusammenfassung

    Erfahren Sie, wie Sie mit Schlüsseln, Indizes, Beziehungen und Validierungen für konsistente Daten sorgen.

    Techniken

    Tabellen, Indizes, Schlüssel, Beziehungen, Gültigkeitsregeln, Validierung in Formularen

    Voraussetzungen

    Access 97 oder höher

    Beispieldateien

    FAQ10_97.mdb, FAQ10_00.mdb

    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 zehnten Teil werden Lösungen für die häufigsten Probleme mit dem Tastatur-, Cursor- und Mausverhalten in Formularen vorgestellt sowie Probleme, die beim Aufruf von Berichten aus Formularen auftreten.

    Das Register-Steuerelement ist ein besonderes Wesen. Es hat keinen Steuerelementinhalt und kann keine Tabellendaten aufnehmen, besitzt aber eine Value-Eigenschaft. Es ist ein Container für die anderen Steuerelemente, spielt aber bei einem Bezug auf diese Steuerelemente keine Rolle. Es bietet mit den Seiten (Pages) seine eigenen Steuerelemente, die aber ganz anders funktionieren, und vieles mehr. Diese Besonderheiten bereiten mancherlei Probleme auch in Hinblick auf die Navigation.

    Eine häufige Frage ist etwa, wie man per VBA einen Seitenwechsel auslösen kann. Eine Möglichkeit ist, mit SetFocus den Fokus auf ein Steuerelement auf der gewünschten Seite zu setzen. Das bewirkt gleichzeitig einen Seitenwechsel. Ein gezielter Seitenwechsel lässt sich jedoch auch ohne diesen Workaround mit der bereits erwähnten Eigenschaft Value des Register-Steuerelements regeln:

    Me!MeinRegister.Value = 1

    Dieser Code wechselt zur zweiten Seite des Registers. Die Value-Eigenschaft entspricht der Eigenschaft Seitenindex (PageIndex) der einzelnen Registerseiten. Die erste Seite hat immer den Index 0, die zweite Seite 1 und so weiter. Wie bei den meisten anderen Steuerelementen heißt auch beim Register die Standardeigenschaft Value und kann deshalb weggelassen werden. Für den Wechsel zur zweiten Seite reicht also:

    Me!MeinRegister = 1

    Ein anderes häufiges Problem ist, wie man bei einem Register-Steuerelement mitbekommt, dass die Seite gewechselt wird, weil man mit Aktionen oder Einstellungen auf den Wechsel zu einer bestimmten Seite reagieren möchte. Für diesen Zweck besitzt das Register das Ereignis Bei änderung (OnChange). Um die Eigenschaften des Register-Steuerelementes zu sehen, darf nicht eine einzelne Seite, sondern muss das Register komplett markiert sein. Das erreichen Sie in der Entwurfsansicht am besten durch einen Ziehrahmen, der außerhalb des Registers beginnt, oder durch einen Klick auf einen freien Platz neben den Registerzungen. Im Code der Ereignis-Eigenschaft Bei änderung können Sie dann zum Beispiel ein Select-Case-Konstrukt verwenden, um auf die Seitenwechsel individuell reagieren zu können (s. Quellcode 1).

    Quellcode 1: Registerseite wechseln

    Private Sub MeinRegister_Change()
        Select Case Me!MeinRegister.Value
            Case 0
                ''es wurde zur 1. Seite gewechselt
            Case 1
                ''es wurde zur 2. Seite gewechselt
        End Select
    End Sub

    Oft wird eine längere, zusammengehörende Sequenz von Steuerelementen auf verschiedene Registerseiten verteilt, zum Beispiel um die vielen Textfelder von Personal- oder Fragebögen besser zu gliedern. In diesem Fall ist es für Tastatureingaben bequemer, wenn beim Drücken der Eingabetaste im untersten Steuerelement der Registerseite der Wechsel zum ersten Steuerelement der nächsten Seite ausgelöst wird. Diese Funktionalität können Sie mithilfe des Ereignisses Bei Taste Ab des Textfeldes programmieren.

    Abb. 1: Navigation im Register-Steuerelement

    Abb. 1 zeigt das Beispiel-Formular frmRegister, in das alle genannten Funktionalitäten eingebaut sind.

    Der Ereigniscode Bei Taste Ab des letzten Textfelds auf Seite 2 lautet:

    Select Case KeyCode
      Case vbKeyReturn, vbKeyDown, vbKeyTab And (Shift And acShiftMask) = 0
        KeyCode = 0
        Me!Telefon.SetFocus
    End Select

    Es wird damit geprüft, ob die Eingabetaste, die Cursortaste Nach unten oder die Tabulatortaste ohne heruntergedrückte Umschalttaste betätigt wurde. Falls ja, wird der Tastaturanschlag aufgehoben und der Fokus auf das erste Textfeld, Telefon, der dritten Registerseite gesetzt. Wie schon erwähnt, wird dadurch automatisch ein Seitenwechsel bewirkt.

    Komplett ist diese Tastatursteuerung erst mit dem Gegenstück, das heißt, im ersten Steuerelement einer Registerseite sollten die Cursortaste Nach oben oder die Tabulatortaste bei gedrückter Umschalttaste den Wechsel zum letzten Steuerelement der vorherigen Seite bewirken. Im Ereigniscode Bei Taste Ab des Textfeldes Telefon steht daher:

    Select Case KeyCode
        Case vbKeyUp, vbKeyTab And _        (Shift And acShiftMask) = 1
        KeyCode = 0
        Me!Land.SetFocus
    End Select

    Von der Datenblattansicht von Tabellen, Abfragen und Formularen oder auch von Excel her sind viele Anwender gewohnt, die Zeile mit den Cursortasten Nach unten und Nach oben wechseln zu können. In einem Endlosformular hingegen muss der Cursor standardmäßig erst alle Steuerelemente des Datensatzes durchlaufen und wechselt erst nach dem letzten Steuerelement zum nächsten Datensatz beziehungsweise zur nächsten Zeile. Der Weg, um das zu ändern, führt über die Programmierung des Tastaturverhaltens auf Formularebene. Zuerst müssen Sie die Eigenschaft Tastenvorschau des Formulars auf Ja setzen, damit die Tastaturereignisse des Formulars Vorrang vor denen der Steuerelemente haben. Im Ereignis Bei Taste Ab des Formulars können Sie dann folgenden Code verwenden:

    On Error Resume Next
    Select Case KeyCode
        Case vbKeyDown
            KeyCode = 0
            DoCmd.GoToRecord , , acNext
        Case vbKeyUp
            KeyCode = 0
            DoCmd.GoToRecord , , acPrevious
    End Select

    Beim ersten oder letzten Datensatz würde eine Fehlermeldung erscheinen, weil kein weiterer Datensatzwechsel in die gleiche Richtung mehr möglich ist. Diese erwarteten Fehlermeldungen werden zu Beginn des Codes mit Resume Next übergangen. Danach wird geprüft, ob eine der Cursortasten Nach unten oder Nach oben gedrückt wurde. In beiden Fällen werden die Tastaturwerte ausgelesen und es wird zum nächsten beziehungsweise vorherigen Datensatz gewechselt. Bei jedem Drücken dieser beiden Tasten in allen Steuerelementen wird nun ein Datensatzwechsel ausgelöst und das Endlosformular verhält sich wie ein Datenblatt. Allerdings nur fast.

    Falls sich ein Kombinationsfeld im Formular befindet, dessen Auswahlliste gerade aufgeklappt ist, dann findet mit den Cursortasten ebenfalls ein Datensatzwechsel statt. Der Anwender kann also nicht mehr wie gewohnt mit diesen Tasten in der Auswahlliste navigieren. Abb. 2 zeigt dieses Dilemma, beinhaltet aber auch die Lösung. Mit Access-Mitteln gibt es leider keine Möglichkeit zu prüfen, ob die Auswahlliste eines Kombinationsfeldes geöffnet ist oder nicht. Dafür sind relativ umfangreiche API-Codes nötig, die es im Internet zum Beispiel vom bekannten API-Künstler Dev Ashish gibt. Seinen Code habe ich in der Beispiel-Datenbank in das Modul basIsComboOpen eingefügt. Im Formular frmDSWechselCursor ist dann im zuvor beschriebenen Code nur eine zusätzliche Zeile mit dem Aufruf der Funktion nötig, die prüft, ob aktuell ein Kombinationsfeld geöffnet ist:

    If fIsComboOpen Then Exit Sub

    In diesem Fall wird also schlicht die Prozedur verlassen und die Tastatureingabe nicht geändert, damit der Anwender ganz normal in der geöffneten Liste navigieren kann.

    Abb. 2: Kein Datensatzwechsel bei geöffnetem Kombinationsfeld

    In den bisherigen Fällen ging es darum, die Navigation, vor allem per Tastatur, zu erweitern. Der Gegensatz sind Situationen, in denen die eingebauten Navigationsmöglichkeiten von Access unerwünscht sind und eingeschränkt werden müssen.

    Der einfachste Fall ist, den Datensatzwechsel zum vorigen/nächsten Datensatz zu verhindern, wenn im ersten/letzten Steuerelement die Return-, Tabulator- oder eine Pfeiltaste gedrückt wird. Dafür bietet Access die eingebaute Eigenschaft Zyklus, die Sie auf Aktueller Datensatz stellen können.

    Nur wenig aufwändiger ist das Unterbinden des Datensatzwechsels mit den Tasten Bild Auf und Bild Ab, die standardmäßig einen Datensatzsprung um eine komplette Formularinnenhöhe bewirken. Um das zu verhindern, müssen Sie wiederum die Eigenschaft Tastenvorschau des Formulars auf Ja setzen. Im Ereignis Bei Taste Ab des Formulars reicht dann eine einzige Codezeile, um die beiden Tasten zu deaktivieren:

    If KeyCode = vbKeyPageUp Or KeyCode = vbKeyPageDown Then KeyCode = 0

    Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

    Workplace

    Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

    Schreibe einen Kommentar

    Access-FAQ: Rund um Access

    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 fünften Teil lernen Sie die Lösungen zu den meistgenannten Problemen der Teilnehmer der deutschsprachigen Access-Newsgroups im Zusammenhang mit Tabellen kennen.

    Eine professionell aufgebaute Access-Anwendung besteht fast immer aus zwei oder mehr MDBs in der klassischen Frontend/Backend-Struktur. In der Backend-MDB befinden sich nur die Daten, das heißt Tabellen, in der Frontend-MDB sämtliche anderen Datenbankobjekte sowie die eingebundenen Tabellen aus dem Backend. Die wichtigsten Vorteile dieser Struktur sind geringere Korruptionsanfälligkeit und leichtere Wartung.

    Manche Anwendungen besitzen auch mehrere Backends, aus denen Tabellen im Frontend eingebunden sind. Das macht zum Beispiel Sinn, wenn ein einzelnes Backend aufgrund der Datenmenge an die Grenzen von Access stoßen würde (ein Gigabyte bei Access 97, zwei Gigabyte ab Access 2000) oder wenn man „Wegwerf-Backends“ verwendet, in die große Datenmengen aus anderen Formaten importiert werden und die dafür immer wieder neu aufgebaut werden.

    Abb. 1: Tabelleneigenschaft Beschreibung

    Access erlaubt bei eingebundenen Tabellen leider nur die Angabe von absoluten und fixen Herkunftspfaden. Diese sind in der Entwurfsansicht der eingebundenen Tabelle in der Eigenschaft Beschreibung sichtbar. Abb. 1 zeigt ein Beispiel, in dem der Wert dieser Eigenschaft folgendermaßen lautet (ohne Zeilenumbruch):

    DATABASE=D:\\Lager\\ArtikelBE.mdb;TABLE=tblArtikel

    Das bedeutet, dass die Originaltabelle tblArtikel heißt und dass sich das Backend ArtikelBE.mdb im Ordner D:\\Lager befindet.

    Hinweis

    Auf der Begleit-CD finden Sie je zwei Beispiel-Datenbanken im Format von Access 97 und im Format von Access 2000 mit den Quellcodes und Beispielen aus diesem Artikel.

    Function fctReConnect1(strNameBE As String)
        On Error GoTo myError
        Dim db As DAO.Database
        Dim tdf As DAO.Tabledef
        Dim strPathBE As String
        Set db = CurrentDb
        strPathBE = Left(db.Name, Len(db.Name) - _        Len(Dir(db.Name))) & strNameBE
        For Each tdf In db.TableDefs
           If tdf.Connect <> "" Then
                If Mid(tdf.Connect, 11) <> strPathBE Then
                    tdf.Connect = ";database=" & strPathBE
                    tdf.RefreshLink
                End If
           End If
        Next tdf
    myExit:
        Exit Function
    myError:
        Select Case Err.Number
            Case Else
                MsgBox "Ausnahme Nr. " & Err.Number _                & " " & Err.Description
        End Select
        Resume myExit
    End Function

    Quellcode 1

    ändert sich nun der Ordner des Backends, so ist die Verbindung zur Ursprungstabelle verloren, und beim Versuch, die eingebundene Tabelle zu öffnen, erscheint eine Fehlermeldung, die besagt, dass die Backend-MDB nicht gefunden werden kann. Manuell müsste man nun die eingebundene Tabelle löschen und wieder neu mit dem richtigen Pfad verknüpfen.

    Eine andere Möglichkeit ist die Verwaltung der eingebundenen Tabellen über den Tabellenverknüpfungs-Manager im Menüpunkt Extras/Datenbank-Dienstprogramme. Der Tabellenverknüpfungs-Manager hat jedoch einige Schwächen, wie Installationsprobleme und begrenzte Breite für sehr lange Pfade.

    In Access 2003 gibt es zudem den häufigen Bug, dass eingebundene Tabellen nicht im Manager angezeigt werden. Man muss für sein korrektes Funktionieren erst die zuständige accwizz.dll neu registrieren. Bug und Lösung sind im Knowledgebase-Artikel 835519 beschrieben.

    Möchten Sie das Wiedereinbinden selbst kontrollieren und automatisieren, so können Sie per Code beim Starten der Datenbank prüfen, ob die Einbindung noch in Ordnung ist, und falls nicht, die Tabellen neu verknüpfen. Um das komplett ohne Anwender-Eingriff durchzuführen, können Sie als Vorgabe für den Anwender festlegen, dass Backend- und Frontend-MDB immer zusammen in einem gemeinsamen Verzeichnis zu installieren sind. Damit kann der Code automatisch den aktuellen Pfad für die Wiedereinbindung verwenden. Die Funktion aus Quellcode 1 erledigt genau das.

    Sie können die Funktion beim öffnen des Startformulars oder im Autoexec-Makro aufrufen:

    fctReConnect1 "NameDesBackends"

    Im Code wird zuerst die Variable strPathBE auf den aktuellen Ordner des Frontends gesetzt und um den übergebenen Backend-Namen ergänzt. Danach werden alle Tabellen des Frontends durchlaufen und es wird geprüft, ob die Eigenschaft Connect mehr als einen Leerstring erhält. Nur bei eingebundenen Tabellen enthält die Eigenschaft den gleichen Text wie die oben angeführte Tabelleneigenschaft Beschreibung. Es wird geprüft, ob Backendpfad und -name identisch sind mit strPathBE. Falls nicht, wird die Connect-Eigenschaft auf den neuen Pfad geändert und die Verbindung mit der Methode RefreshLink aktualisiert. Das Installieren von Frontend und Backend im selben Ordner ist natürlich nicht immer möglich. In solchen Fällen ist das Wiedereinbinden in der Praxis nur halbautomatisch möglich.

    Function fctReConnect2()
        On Error GoTo myError
        Dim tdf As DAO.Tabledef
        Dim strPathBE As String
        If DLookup("ArtikelId", "tblArtikel") <> "" Then Exit Function
    myExit:
        Exit Function
    myError:
        Select Case Err.Number
            Case 3024, 63725, 3043, 3044
                MsgBox "Der Pfad zu den Daten hat sich geändert. " & _
                       "Bitte wählen Sie im folgenden Dialog die aktuelle Daten-mdb aus."
                strPathBE = fct_Datei_suchen
                If strPathBE <> "" Then
                    Dim db As DAO.Database
                    Set db = CurrentDb
                    For Each tdf In db.TableDefs
                       If tdf.Connect <> "" Then
                            If Mid(tdf.Connect, 11) <> strPathBE Then
                                tdf.Connect = ";database=" & strPathBE
                                tdf.RefreshLink
                            End If
                       End If
                    Next tdf
                End If
                Resume Next
            Case Else
                MsgBox "Bei der Installation ist ein Problem aufgetreten. " & _
                       "Bitte überprüfen Sie den Pfad und versuchen Sie noch " & _
                       "einmal die Daten einzubinden.", _
                       vbCritical, "Problem bei der Installation !"
                Resume myExit
        End Select
    End Function
    Public Function fctDateiSuchen()
        Dim fd As New FileDialog
        With fd
            .DialogTitle = "Datei suchen"
            .InitDir = Left(CurrentDb.Name, Len(CurrentDb.Name) - _            Len(Dir(CurrentDb.Name)))
            .ShowOpen
        End With
        If Len(fd.FileName) > 0 Then fctDateiSuchen = fd.FileName
    End Function

    Quellcode 2

    Der Anwender bekommt dabei am besten einen Dateidialog zur Auswahl des Backends präsentiert. Es gibt verschiedene Varianten von Dateidialogen, die man dafür verwenden kann. Ab Office XP existiert der Office-eigene Dateidialog. Für alle Office-Versionen gibt es das FileDialog-ActiveX von Microsoft. Stabiler im Hinblick auf die Verweisproblematik ist jedoch der Aufruf des Windows-eigenen Dateidialogs mithilfe von API-Aufrufen.

    Quellcode 2 zeigt ein Beispiel für einen relativ einfachen Wiedereinbindungscode.

    Abb. 2: WindowsXP-Dateidialog zur Auswahl des Backends

    Zum Anzeigen des Windows-Dateidialogs (s. Abb. 2) wird das in der Access-Gemeinde sehr bekannte und frei erhältliche Klassenmodul FileDialog von Karsten Pries verwendet.

    Für die anderen genannten Dateidialoge ist die Verwendung im Wiedereinbindungscode nur unwesentlich anders zu gestalten. Alle geben einen String mit dem ausgewählten Pfad und Dateinamen zurück. In der fctReConnect2 in Quellcode 2 wird zuerst ein DLookup auf irgendein Tabellenfeld, das sicher vorhanden ist, ausgeführt. Wenn die Datenverbindung zum Backend nicht mehr stimmt, ergibt dieser versuchte Datenzugriff einen Laufzeitfehler. In der Fehlerbehandlung werden die Fehlernummern abgeprüft, die üblicherweise bei nicht korrekter Backendverbindung auftreten (Daten-MDB nicht gefunden, Netzwerkfehler wegen Laufwerksproblem, kein zulässiger Pfad). Dann wird die Funktion fctDateiSuchen verwendet, die den Dateidialog aufruft und die wichtigsten Einstellungen (Titel und Startordner) für den Dialog vornimmt. Mit dem ausgewählten und zurückgelieferten Pfad und Dateinamen wird dann die Neueinbindung auf die gleiche Weise wie bei Quellcode 1 beschrieben durchgeführt.

    Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

    Workplace

    Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

    Schreibe einen Kommentar