Defekte Verweise: Ursachen und Lösungen

In diesem dritten Teil der Beitrags-Reihe rund um das Thema „Verweise“ steigen wir tiefer in die Materie ein: Wie löst Access beziehungsweise VBA Verweise überhaupt auf Was läuft bei defekten Verweisen schief Und welche manuellen und welche VBA-Techniken gibt es, um solche Probleme zu lösen All dies erfahren Sie im vorliegenden Beitrag.

Um die von Verweisen ausgehenden Probleme zu verstehen, sollten Sie wissen, wie Access, genauer VBA, vorgeht, um die Bibliothek eines Befehls zu finden.

Disambiguation

VBA verwendet Disambiguation, um die passende Bibliothek für ein Objekt oder eine Methode zu finden. Wenn VBA (unbekannte) Objekte im Code findet, erfolgt die Suche in der folgenden Reihenfolge:

  • im eigenen Modul,
  • in anderen Standardmodulen des VBA-Projekts,
  • in den Verweisen in der Reihenfolge ihrer Priorität
  • und in den eingebauten Verweisen (VBA und Access).

Woher weiß VBA beispielsweise, was sich hinter dem Befehl Left$ verbirgt VBA prüft als Erstes, ob es in dem Modul, in dem es diese Codezeile findet, eine private oder öffentliche Funktion mit dem Namen Left$ gibt. Wenn eine Funktion mit dem Namen Left$ in diesem Modul vorhanden ist, verwendet es diese Funktion. Wenn das Modul kein passende Funktion enthält, prüft Access, ob in den anderen Standardmodulen der Datenbank eine öffentliche Funktion mit dem Namen Left$ vorhanden ist.

Offenbart das gesamte VBA-Projekt keine Funktion mit dem Namen Left$, durchsucht Access als Nächstes alle nicht eingebauten Verweise der Datenbank (also alle außer Access und VBA) in der Reihenfolge ihrer Priorität. Findet Access auch in diesen Verweisen nichts, untersucht es die eingebauten Verweise VBA und Access nach diesem Befehl. Im Fall von Left$ führt dies im Modul Strings der Bibliothek VBA zum Erfolg.

Sie können diesen Prozess mit der Beispieldatenbank Demo.Disambiguation.mdb nachvollziehen. Sorgen Sie vor dem Start dafür, dass die Bibliotheksdatenbank mit dem Namen Lib.Disambiguation.mdb im selben Verzeichnis wie die Beispieldatenbank liegt.

In der Beispieldatenbank können Sie über eine Schaltfläche zum VBA-Code wechseln. Setzen Sie dort den Cursor in den Befehl Left$. Wählen Sie den Eintrag Definition aus dem Kontextmenü aus und schauen Sie, wo sich der Befehl befindet.

Kommentieren Sie nun die gefundene Funktion aus und wählen Sie erneut Definition. Wiederholen Sie diese Schritte so lange, bis der Objektkatalog am Ende den Befehl Left$ anzeigt.

Disambiguation vermeiden

Sie können vermeiden, dass VBA auf der Suche nach der passenden Bibliothek den Prozess der Disambiguation durchläuft. Stellen Sie dazu dem Befehlswort den Namen der zu verwendenden Bibliothek und/oder des zu verwendenden Moduls voran. Im Fall von Left$ würden Sie dann Folgendes schreiben:

If VBA.Left$(Me!txtName,1)="M" Then

Wenn Sie einen Befehl aus der Access-Bibliothek verwenden wollen, schreiben Sie beispielsweise:

    Access.Application.Run

Für den Aufruf einer Funktion mit dem Namen MyFunction aus dem Modul basMyModul schreiben Sie:

    basMyModul.MyFunction

Wenn sich das Modul in einer als Verweis eingebundenen Bibliothek befindet, stellen Sie den Namen der Bibliothek zusätzlich voran. Bezogen auf das vorherige Beispiel haben Sie nun folgende Möglichkeiten:

    MyLib.MyFunction
    MyLib.basMyModul.MyFunction

Sie können VBA die Arbeit abnehmen und die Befehle vollständig qualifiziert ausschreiben, Sie müssen es aber nicht. Wenn Sie es tun, nehmen Sie VBA nicht nur die Suche nach der richtigen Bibliothek ab. Sie legen auch definitiv fest, welche Bibliothek verwendet wird. Das ist insbesondere dann von Bedeutung, wenn ein Objekt oder eine Methode in mehreren Bibliotheken zugleich vorhanden ist.

Ein Beispiel hierfür ist das Recordset-Objekt. Das Recordset-Objekt ist in den Bibliotheken ADODB und DAO zu finden. Wenn Sie bei der Deklaration des Recordset-Objekts keine spezielle Bibliothek angeben und nur eine der beiden Bibliotheken per Verweis eingebunden ist, verwendet Access diese, sonst die mit der höheren Priorität.

Geben Sie hingegen bei der Deklaration des Recordset-Objekts bereits die zu verwendende Bibliothek an, verwendet VBA die „richtige“ Bibliothek. Wenn der zugehörige Verweis fehlt, erhalten Sie bereits beim Kompilieren eine Fehlermeldung.

    'Deklaration ohne Bibliothek
    Dim rst As RecordSet
    'Deklaration mit Bibliothek
    Dim rst As DAO.RecordSet

Prüfen der Verweise

Wenn VBA prüfen will, ob ein Objekt in der Type Library eines Verweises enthalten ist, ermittelt es den intern gespeicherten GUID zu diesem Verweis. Mit dieser Information fragt VBA die Registry ab. Als Ergebnis erhält VBA letztlich den Pfad zur Datei mit der Type Library zurück.

Wenn sich diese Datei am erwarteten Ort befindet, lädt VBA sie in den Speicher und prüft, ob diese Type Library Informationen zu dem gesuchten Objekt enthält. Enthält die Type Library das Objekt nicht, sucht VBA in den anderen Verweisen in der Reihenfolge ihrer Priorität weiter. Als Letztes kommen dabei die eingebauten Verweise Access und VBA zum Zuge.

Wenn VBA den gesuchten Befehl nicht finden konnte, quittiert VBA dies beim Kompilieren mit der Fehlermeldung Sub oder Function nicht definiert.

Den gesamten Prozess können Sie Bild 1 und Abb. 2 nachvollziehen. Aus diesen Schaubildern lassen sich folgende Erkenntnisse ableiten: Aus der Tatsache, dass Access Befehle zuerst im VBA-Projekt der Anwendung sucht, wird deutlich, dass Sie die Befehle, die VBA bereitstellt, durch eine eigene Version ersetzen können. Welche Möglichkeiten sich daraus ergeben und worauf Sie dabei achten sollten, wird in einem gesonderten Beitrag beschrieben.

missing image file

Bild 1: Vom Befehl im VBA-Code …

missing image file

Bild 2: … zur passenden Bibliothek

Wenn VBA beim Versuch, eine Type Library zu laden, auf ein Problem stößt, bricht der Prozess der Disambiguation ab. VBA lässt dann nicht etwa die fehlerhafte Bibliothek aus und sucht in den anderen Bibliotheken weiter, sondern bricht den Prozess komplett ab.

Wenn Sie sich nochmals in Erinnerung rufen, dass VBA die eingebauten Verweise erst am Ende durchsucht, wird deutlich, warum VBA so oft behauptet, der Befehl Left$ könne nicht gefunden werden. Dies liegt wohl ganz einfach daran, dass VBA auf der Suche nach der richtigen Bibliothek auf einen anderen, fehlerhaften Verweis gestoßen ist.

Fehlerhafte Verweise

Nachdem jetzt klar ist, was bei einem defekten Verweis passiert, ist es an der Zeit zu überlegen, wie es zu defekten Verweisen kommen kann.

Ein Verweis ist fehlerhaft, wenn auf dem ausführenden Rechner nicht dieselbe Version einer Bibliothek registriert ist, sie gar nicht registriert ist oder wenn die registrierte Datei nicht gefunden werden kann. Die Gründe dafür sind vielfältig. So kann es zum Beispiel sein, dass auf dem ausführenden Rechner eine ältere oder eine neuere Version einer Bibliothek registriert ist.

Es kann aber auch passieren, dass ein Verweis komplett fehlt. Dies kann dann der Fall sein, wenn die Type Library auf diesem Rechner (noch) nicht registriert worden ist oder wenn die Registrierung aufgehoben wurde, weil beispielsweise eine Komponente vom System entfernt wurde. Zu einem fehlerhaften Verweis kommt es auch, wenn die registrierte Datei umbenannt, verschoben oder gelöscht wurde.

Auch das Durchbrechen der so genannten binären Kompatibilität führt zu einem fehlerhaften Verweis. Dafür, dass dies nicht passiert, ist der Programmierer der Komponente verantwortlich. Leider passieren hier hin und wieder Fehler, auf die Sie keinen Einfluss haben.

Wo erfolgt Disambiguation

Als Nächstes ist zu überlegen, wann und wo VBA es überall mit Verweisen zu tun haben kann. Daraus ergibt sich dann, wann und wo sich ein Fehler in den Verweisen auswirken kann. Der Prozess der Disambiguation erfolgt zum einen in VBA, zum anderen wird dieser Prozess aber auch vom (Jet) Expression Service genutzt. Der Expression Service ist dafür verantwortlich, dass Ausdrücke ausgewertet werden. Solche Ausdrücke können an folgenden Stellen verwendet werden:

  • Abfragen
  • Steuerelemente
  • Feldeigenschaften

Auch in diesen Ausdrücken können Sie VBA-Befehle verwenden. Der Expression-Service sorgt dann dafür, dass das richtige Ergebnis ermittelt wird, und gibt dieses zurück an die Abfrage oder an das Steuerelement.

Unterschiede in MDB und MDE ()

Lassen Sie uns kurz die Frage betrachten, ob es Unterschiede zwischen einer .mdb-Datei und einer .mde-Datei gibt, wenn es um Verweise geht. In einer nicht kompilierten .mdb-Datei wird der Code modulweise geladen. Das gesamte Modul wird interpretiert. Dabei werden die passenden Klassen gesucht. Wenn dabei ein fehlerhafter Verweis gefunden wird, kommt es zur Fehlermeldung.

In einer kompilierten .mdb-Datei und in einer .mde-Datei ist der Ablauf etwas anders. Dort ist der Code bereits kompiliert. Es erfolgt also keine Suche mehr nach der passenden Klasse. Dies ist bereits bei der Kompilierung erfolgt. Wenn jetzt aber ein fehlerhafter Verweis geladen werden soll, gibt es auch in diesem Fall eine Fehlermeldung. Im Ergebnis unterscheiden sich .mdb-Datei und .mde-Datei also nicht. Wenn fehlerhafte Verweise vorhanden sind, führt dies zu einem Fehler.

Wie löst Access Verweise auf

Als Nächstes sollten Sie sich anschauen, wie Access Verweise auflöst. Dies ist verkürzt etwa bei Microsoft in [1] dokumentiert. Wenn Sie wissen, wie und wo VBA nach Verweisen sucht, können Sie diese Möglichkeiten auch für Ihre Bibliotheksdatenbanken nutzen. Access geht in folgenden drei Schritten vor:

  • Ist der Verweis bereits geladen
  • Verweis in RefLibPaths gefunden
  • Suche gemäß SearchPath API.

Als Erstes wird geprüft, ob der benötigte Verweis bereits geladen ist. Dies ist für Access die beste Situation, weil dann keine Fehler mehr auftreten können. Als Zweites wird geprüft, ob in der Registry ein Schlüssel mit dem Namen RefLibPaths existiert. Dieser Schlüssel wird in folgendem Pfad gesucht:

    HKLM\Software\Microsoft\Office\x.0\Access

Dabei gibt x.0 die Version von Access an. Ein Eintrag im Schlüssel RefLibPaths funktioniert zwar prinzipiell für jede auf einem System registrierte Komponente. Ein solcher Eintrag ist aber generell nur für den Verweis auf andere Datenbanken vorgesehen. Wenn dieser Schlüssel vorhanden ist – er muss vom Entwickler angelegt werden -, wird geprüft, ob dort ein Eintrag mit dem Namen der gesuchten Datenbank vorhanden ist. Wenn dies der Fall ist, wird der Pfad zur Datenbank aus dem Wert des Registry-Keys ausgelesen.

Als Drittes wird bei der Suche nach der zu ladenden Datei die SearchPath API verwendet. Die SearchPath API sucht nacheinander an folgenden Stellen:

  • Anwendungsverzeichnis
  • Aktuelles Verzeichnis
  • Windows System-Verzeichnis
  • Windows-Verzeichnis
  • Umgebungsvariable PATH
  • Datenbankverzeichnis

Das Anwendungsverzeichnis ist das Verzeichnis, in dem die msaccess.exe gespeichert ist. Da dieses Verzeichnis in der Regel im Ordner C:\Programme liegt, kommt es für eine eigene Bibliothek als Speicherort nicht in Frage. Das aktuelle Verzeichnis ist das Verzeichnis, das man erhält, wenn man auf Datei|öffnen klickt. Da Sie nie genau wissen, welches das aktuelle Verzeichnis ist, kommt dieses Verzeichnis als Speicherort für eine eigene Bibliothek ebenfalls nicht in Betracht.

Mit dem System-Verzeichnis sind die Ordner C:\Windows\System und C:\Windows\System32 gemeint. Das Windows-Verzeichnis bezieht sich auf die Ordner C:\Windows beziehungsweise C:\WinNT. Dateien, die nicht das Betriebssystem betreffen, haben in diesen Ordnern generell nichts zu suchen. Hinzu kommt, dass bei neueren Betriebssystemen der angemeldete Benutzer nicht unbedingt berechtigt ist, in diesen Ordnern Veränderungen vorzunehmen. Die Dateien in diesen Ordnern werden teilweise ausgeblendet, um die Systemstabilität nicht zu gefährden. Als Speicherort für eine eigene Bibliothek sind diese Ordner daher eher ungeeignet.

Bei der Suche mit der Umgebungsvariablen PATH werden alle dort eingetragenen Pfade durchsucht. Um den Pfad zu einer Bibliotheksdatenbank in dieser Umgebungsvariablen einzutragen, müssen Sie für die Weitergabe ein Installationsprogramm verwenden. Dieser zusätzliche Aufwand macht die Umgebungsvariable PATH für eigene Bibliotheken unattraktiv.

Als Letztes wird das Datenbankverzeichnis durchsucht. Das Datenbankverzeichnis ist das Verzeichnis, in dem die Datenbank, die Sie gerade ausführen, gespeichert ist. Bei der Suche werden auch alle Unterordner des Datenbankverzeichnisses berücksichtigt.

Das Datenbankverzeichnis oder eines seiner Unterverzeichnisse bietet sich als Speicherort für eine eigene Bibliothek geradezu an. Der angemeldete User hat auf diesen Ordner auf jeden Fall die notwendigen Berechtigungen. Zusätzlich ist sichergestellt, dass der Ordner im Windows-Explorer sichtbar ist. Wenn Sie den Ordner mit der Anwendung an einen anderen Ort verschieben oder kopieren, wird auch die Bibliothek mit verschoben. Die Wahrscheinlichkeit, dass die Bibliothek an dieser Stelle gefunden wird, ist also sehr hoch.

Es kann Ihnen passieren, dass Sie eine neue Version Ihrer Bibliothek im Datenbankverzeichnis gespeichert haben und trotzdem eine alte Version Ihrer Bibliothek verwendet wird. Prüfen Sie dann alle hier vorgestellten Speicherorte darauf hin, ob dort eine alte Version Ihrer Bibliothek gespeichert ist. Es wird nämlich die Version Ihrer Bibliothek verwendet, die Access zuerst findet.

Fehlermeldungen und Symptome

Als Nächstes werden Fehlermeldungen und Symptome aufgezeigt, die bei Fehlern in den Verweisen auftreten. Wenn Sie die auftretenden Fehler nachvollziehen wollen, starten Sie die Beispieldatenbank mit dem Namen Demo.Fehlermeldungen.mdb.

öffnen Sie als Erstes das Formular frm_Personen. Sie erhalten in Access 2003 einen Hinweis mit dem Text: „Ihr Projekt enthält einen fehlenden oder inkorrekten Verweis auf die Datei „xxx“. Sie haben die Möglichkeit, sich zusätzliche Hilfe zu diesem Fehler anzeigen zu lassen.“ Dieses Hinweisformular zeigt Ihnen deutlich, dass es ein Problem mit den Verweisen gibt, und informiert Sie, was Sie zur Bereinigung dieses Problems tun können. Wenn Sie das Formular öffnen, sehen Sie im Feld Initialen statt des erwarteten Feldinhalts den Text #Name wie in Bild 3. In diesem Feld werden die Initialen mittels der Funktion Links aus den Feldern Vorname und Nachname ermittelt.

missing image file

Bild 3: Der Eintrag #Name in einem Steuerelement deutet auf ein Problem mit den Verweisen hin.

Die Funktion Links beziehungsweise Left ist eine Funktion aus der Bibliothek VBA. Diese Bibliothek wird als Letztes durchsucht. Da vorher eine andere Bibliothek nicht gefunden werden kann, bricht der Prozess der Disambiguation ab und Access reagiert mit einem Fehler.

Wenn Sie als Nächstes eine der beiden Schaltflächen anklicken, wechselt Access in den VBA-Editor. Dort erscheint eine Fehlermeldung mit dem Text Fehler beim Kompilieren: Projekt oder Bibliothek nicht gefunden. Der Befehl Left ist im VBA-Editor gelb markiert.

Wählen Sie nun im VBA-Editor den Befehl Debuggen|Kompilieren von… aus. Sie erhalten dieselbe Fehlermeldung wie vorher. Wieder ist das Schlüsselwort Left gelb markiert. Wenn Sie die Meldung mit OK bestätigen, öffnet sich zusätzlich der Verweis-Dialog.

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar