window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-TCJTE9L38H');

Verweise beim Start prüfen

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Beim Einsatz von Access-Anwendungen gibt es manchmal Probleme, weil die Verweise auf Bibliotheken nicht korrekt gesetzt sind. Dann werden plötzlich VBA-Funktionen wie “Left” oder “Right” als fehlerhaft bewertet. Der Benutzer steht dann dumm da, weil er nicht weiß, was zu tun ist. Dieser Beitrag zeigt, wie Sie das Problem nachstellen können und welche Lösungsmöglichkeiten es gibt – von der manuellen Variante bis zur automatischen Korrektur des Verweises beim Start der Anwendung.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1904_VerweiseBeimStart.accdb.

Fehlerhafter Verweis

Probleme wie die oben genannten treten meist auf, wenn Sie eine Anwendung auf Ihrem Rechner entwickeln und diese dann an einen Benutzer weitergeben, auf dessen Rechner nicht alle per Verweis referenzierten Bibliotheken vorliegen – oder diese nicht in der richtigen Version vorliegen.

Verweise finden Sie grundsätzlich im Verweise-Dialog, den Sie vom VBA-Editors aus (zu öffnen mit Strg + G oder Alt + F11) mit dem Menübefehl Extras|Verweise anzeigen. Dieser Dialog zeigt die Liste der eingebundenen Bibliotheken, die bei einer neuen, leeren Access-Anwendung auf Basis von Access 2016 etwa wie in Bild 1 aussieht. Die Bibliotheken hinter diesen vier Einträge sollten überall, wo Access 2016 installiert ist, auch vorhanden sein.

Der Verweise-Dialog von Access

Bild 1: Der Verweise-Dialog von Access

Bei umfangreicheren Anwendungen kommen meist noch Verweise auf weitere Bibliotheken hinzu, zum Beispiel um Word, Excel oder Outlook zu automatisieren, die Datenzugriffs-Bibliothek ADODB zu nutzen oder auch um die Befehle für die Verarbeitung von XML hinzuzufügen.

Wenn Sie nun einen Verweis auf Outlook hinzufügen, die Datenbank auf den Zielrechner übertragen und dann aber Outlook gar nicht auf dem Zielrechner vorliegt, gibt es Probleme wegen des fehlenden Verweises.

Manchmal gibt es auch Probleme, wenn Sie mit einem Verweis auf die Objektbibliothek von Outlook 2016 programmieren und auf dem Zielrechner ist eine ältere Version von Outlook vorhanden.

Manuelle Lösung

Vorausgesetzt, die Bibliothek, auf die der Verweis zeigen soll, ist auf dem Zielrechner installiert und registriert, können Sie wie folgt vorgehen, um den Verweis zu erneuern:

  • öffnen Sie den Verweise-Dialog.
  • Entfernen Sie den mit NICHT VORHANDEN markierten Verweis.
  • Fügen Sie den Verweis auf die gewünschte Bibliothek zur Liste der Verweise hinzu, indem Sie den entsprechenden Eintrag per Haken selektieren.
  • Schließen Sie den Verweise-Dialog.

Danach sollte die Anwendung dann wie gewohnt funktionieren. Eine Ausnahme könnte sein, dass Sie in Ihrer Anwendung tatsächlich Funktionen einer neueren Bibliothek verwenden, die in der älteren, auf dem Zielrechner vorhandenen Version noch nicht verfügbar ist.

Wenn Sie eine Anwendung beim Kunden laufen haben, für die Sie regelmäßig neue Versionen liefern, dann ist es für den Kunden natürlich mühselig, immer die Verweise zu aktualisieren – daher stellen wir nun eine Alternative vor.

Verweise automatisch beim Start aktualisieren

Die Alternative lautet, beim Start einer Anwendung die Verweise zu prüfen und diese gegebenenfalls zu erneuern. Wenn ein Verweis nicht gesetzt werden kann, weil die entsprechende Bibliothek nicht verfügbar ist, soll eine Meldung erscheinen, die den Benutzer darüber informiert, damit dieser mit dem Entwickler der Software herausfinden kann, wo das Problem in diesem Fall liegt.

Zu Beispielzwecken nehmen wir an, dass wir Verweise auf die Bibliotheken für den Zugriff auf die Office-Anwendungen Excel, Outlook und Word hinzufügen sowie einen auf die Bibliothek Microsoft XML, v6.0 (siehe Bild 2).

Verweise-Dialog mit zusätzlichen Verweisen

Bild 2: Verweise-Dialog mit zusätzlichen Verweisen

Bei den mit diesen Verweisen referenzierten Bibliotheken handelt es sich sämtlich um registrierte Bibliotheken, für die es eine GUID gibt. Diese wollen wir nun zunächst ermitteln, indem wir diese per VBA-Routine im Direktbereich des VBA-Editors ausgeben:

Public Sub VerweisePruefenUndErneuern()
    Dim objReference As Reference
    Dim strGUID As String
    For Each objReference In References
        Debug.Print objReference.Name
        Debug.Print objReference.FullPath
        Debug.Print objReference.Guid
    Next objReference
End Sub

Das Ergebnis sieht dann so aus:

VBA
C:\Program Files (x86)\...\VBA7.1\VBE7.DLL
{000204EF-0000-0000-C000-000000000046}
Access
C:\Program Files (x86)\...\MSACC.OLB
{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}
stdole
C:\Windows\SysWOW64\stdole2.tlb
{00020430-0000-0000-C000-000000000046}
DAO
C:\Program Files (x86)\...\OFFICE16\ACEDAO.DLL
{4AC9E1DA-5BAD-4AC7-86E3-24F4CDCECA28}
Excel
C:\Program Files (x86)\...\EXCEL.EXE
{00020813-0000-0000-C000-000000000046}
Outlook
C:\Program Files (x86)\...\MSOUTL.OLB
{00062FFF-0000-0000-C000-000000000046}
Word
C:\Program Files (x86)\...\MSWORD.OLB
{00020905-0000-0000-C000-000000000046}
MSXML2
C:\Windows\SysWOW64\msxml6.dll
{F5078F18-C551-11D3-89B9-0000F81FE221}

Nun wollen wir ja gar nicht alle Einträge prüfen, sondern nur diejenigen, die nicht eingebaut sind. Das prüfen wir durch eine If…Then-Bedingung, mit der wir den Wert der Eigenschaft BuiltIn untersuchen. Ist diese True, handelt es sich um eine eingebaute Eigenschaft, die wir nicht ersetzen müssen, da diese meist vorhanden sind. Hat BuiltIn den Wert False, müssen wir handeln: Dann könnte es sein, dass ein falscher Verweis zu Fehlern führt. Mit der folgenden geänderten Version der Prozedur VerweisePruefenUndErneuern geben wir nur noch die Verweise aus, die wir erneuern können:

Public Sub VerweisePruefenUndErneuern()
    Dim objReference As Reference
    Dim strGUID As String
    For Each objReference In References
        If objReference.BuiltIn = True Then
            Debug.Print objReference.Name
            Debug.Print objReference.FullPath
            Debug.Print objReference.Guid
        End If
    Next objReference
End Sub

Damit erhalten wir dann ein ähnliches Ergebnis wie weiter oben, nur dass diesmal die eingebauten Verweise nicht berücksichtigt werden.

Was fangen wir nun damit an Wir könnten direkt in dieser Prozedur ein paar Zeilen unterbringen, die dafür sorgen, dass die Verweise auf Gültigkeit überprüft und gegebenenfalls erneuert werden. Das würde dann etwa wie in Listing 1 aussehen. Hier durchlaufen wir wieder alle Reference-Objekte, schließen aber durch die ersten beiden If…Then-Bedingungen zuerst die eingebauten und dann die vorhandenen Verweise aus.

Public Sub VerweisePruefenUndErneuern()
     Dim objReference As Reference
     Dim objReferenceNew As Reference
     Dim strReference As String
     Dim strGUID As String
     For Each objReference In References
         If objReference.BuiltIn = False Then
             If objReference.IsBroken = True Then
                 strGUID = objReference.Guid
                 strReference = objReference.Name
                 References.Remove objReference
                 Set objReferenceNew = References.AddFromGuid(strGUID, 0, 0)
                 If objReference Is Nothing Then
                     MsgBox "Der Verweis auf die Bibliothek '" & strReference & "' fehlt."
                 End If
             End If
         End If
     Next objReference
End Sub

Listing 1: Fehlende Verweise werden direkt erneuert

Sind beide If…Then-Bedingungen wahr, merken wir uns in den Variablen strGUID und strReference die GUID und den Namen der referenzierten Bibliothek. Dann fügen wir die Referenz auf eine Bibliothek über die Methode AddFromGUID wieder zur Liste References hinzu. Dabei übergeben wir als Parameter die GUID der Bibliothek sowie den Wert 0 für die beiden Parameter Major und Minor.

Eine fehlende Bibliothek sollte damit wieder referenziert werden können.

Diese Prozedur rufen wir am besten beim Start der Anwendung auf, damit keine Fehler durch fehlende Verweis auftreten. Wie das gelingt, zeigen wir am Ende des Beitrags.

Benötigte Verweise an anderer Stelle speichern

Das Problem ist nur: Wenn der Benutzer auf irgendeine Weise einen der Verweise entfernt, ohne diesen wieder hinzuzufügen, treten in der Folge Probleme auf an den Stellen, wo im Code Elemente dieser Bibliothek verwendet werden.

Wenn wir dann beim Starten der Anwendung die Prozedur aufrufen, durchläuft diese wieder alle Verweise und prüft die Verweise mit der Eigenschaft IsBroken. Wenn jedoch ein Verweis auf eine Bibliothek gar nicht mehr in der Liste der Verweise enthalten ist, kann er mit der hier vorliegenden Version der Prozedur auch nicht ersetzt werden – die Prozedur erfährt ja gar nicht, das ein Verweis fehlt. Das wird erst später offensichtlich, wenn die Anwendung das erste Mal auf Elemente der mit dem Verweis referenzierten Bibliothek zugreift und dadurch Laufzeitfehler ausgelöst werden.

Also wollen wir, bevor wir die Anwendung an den Benutzer weitergeben, die Verweise, die überprüft werden sollen, in irgendeiner Form speichern. Dabei gibt es zwei Möglichkeiten:

  • Wir speichern die GUIDs fest im Code.
  • Wir legen eine Tabelle an, der wir die Informationen über die Verweise hinzufügen. Diese Tabelle sollte dann im Frontend der Datenbankanwendung liegen, wenn diese in Frontend und Backend aufgeteilt ist.

Die Basis für beide Varianten sieht beispielsweise wie in Listing 2 aus. Diese Funktion nimmt den Parameter strGUID entgegen. Im Direktbereich könnten wir die Funktion wie folgt aufrufen:

Public Function VerweiseErneuern(strGUID As String) As Boolean
     Dim objReference As Reference
     Dim bolReferenceMissing As Boolean
     Dim bolReferenceBroken As Boolean
     bolReferenceBroken = False
     bolReferenceMissing = True
     VerweiseErneuern = True
     For Each objReference In References
         If objReference.Guid = strGUID Then
             bolReferenceMissing = False
             If objReference.IsBroken = True Then
                 bolReferenceBroken = True
             End If
             Exit For
         End If
     Next objReference
     If bolReferenceMissing = True Or bolReferenceBroken = True Then
         On Error Resume Next
         References.Remove objReference
         Set objReference = References.AddFromGuid(strGUID, 0, 0)
         If objReference Is Nothing Then
             VerweiseErneuern = False
         End If
     End If
End Function

Listing 2: Erneuern des Outlook-Verweises

 VerweiseErneuern("{00062FFF-0000-0000-C000-000000000046}")

Die Funktion stellt die Variablen bolReferenceBroken auf False und bolReferenceMissing auf True ein. Dann versucht sie, einen Verweis auf die Bibliothek mit der mit strGUID übergebenen GUID zu finden. Dies geschieht in einer For Each-Schleife über alle Elemente der Auflistung References. Wenn der aktuell mit objReference referenzierte Verweis die gesuchte GUID enthält, können wir die Variable bolReferenceMissing schon einmal auf False einstellen, denn der Verweis ist ja zumindest vorhanden.

Dann prüft die Prozedur mit der Eigenschaft IsBroken noch, ob der Verweis als NICHT VORHANDEN markiert ist. Das ist etwas missverständlich, denn NICHT VORHANDEN gibt ja nicht an, dass der Verweis fehlt, sondern die referenzierte Bibliothek. Jedenfalls stellt die Funktion die Variable bolReferenceBroken auf True ein, wenn IsBroken den Wert True aufweist. Sobald der Verweis passend zu strGUID gefunden wurde, verlassen wir dann auch mit Exit For die Schleife.

objReference enthält somit auch einen Verweis auf das Reference-Objekt. Damit gehen wir in eine If…Then-Bedingung, in der wir prüfen, ob entweder bolReferenceMissing oder bolReferenceBroken den Wert True hat. Das ist nun entweder der Fall, wenn der Verweis gar nicht vorhanden ist oder dieser “broken” ist.

Dann versucht die Funktion, den Verweis mit der Remove-Methode der References-Auflistung zu entfernen und diesen dann über die Methode AddFromGUID erneut hinzuzufügen, wobei ein Verweis auf das neue Reference-Objekt in der Variablen objReference landet – aber auch nur, wenn das Hinzufügen erfolgreich war.

Wenn etwa die Datei hinter der GUID nicht vorhanden ist, gelingt dies nicht und objReference bleibt leer.

Ist objReference danach leer, wird der Wert False mit dem Funktionswert zurückgegeben.

Von einer Prozedur aus könnten wir diese Funktion wie etwa in Listing 3 aufrufen. Dies würde, wenn die Outlook-Bibliothek nicht vorhanden oder fehlerhaft ist, eine Meldung liefern.

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

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar