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.

Bitte teilen Sie uns Ihre Anrede, Ihren Namen und Ihre E-Mail-Adresse mit:

Anrede:
Vorname:
Nachname:
E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 5/2018.

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

ODBCDirect durch die Hintertür

Haben Sie Ihr Backend in ein DBMS ausgelagert, also die Tabellen auf einen SQL-Server migriert, so steht Ihnen ab Access 2007 nur noch die Schnittstelle ADODB zur Verfügung, um unter VBA auf sie zuzugreifen, falls Sie sich nicht nur auf verknüpfte Tabellen beschränken möchten. Denn die Technologie ODBCDirect, mit der man direkt eine Verbindung zum Server aufbauen konnte, wurde ersatzlos gestrichen. Mit einem Trick schlagen Sie Microsoft jedoch ein Schnippchen!

ODBCDirect

Es handelt sich dabei eine Datenschnittstelle, die in der Bibliothek DAO untergebracht ist. Dort finden Sie ein Connection-Objekt, welches allein für die Kommunikation mit einem SQL-Server über ODBC zuständig ist (s. Bild 1). Doch offenbar enthält die Bibliothek diese Klasse nur noch aus Kompatibilitätsgründen, denn jeglicher Methodenaufruf auf sie endet mit einer Fehlermeldung 3827: ODBCDirect wird nicht mehr unterstützt. Schreiben Sie den Code so um, dass ADO anstelle von DAO verwendet wird. Das können Sie tun, denn etwas anderes bleibt Ihnen nun auch nicht übrig.

Die ODBCDirect-Klasse Connection im Objektkatalog von VBA

Bild 1: Die ODBCDirect-Klasse Connection im Objektkatalog von VBA

Der Sachverhalt stellt sich in der Praxis nicht selten ein. Haben Sie etwa eine ältere Access 2003-Datenbank im Einsatz, die ODBCDirect nutzt, und auf den Rechnern soll Office 2010 installiert werden, so kommen Sie um Anpassungen leider nicht herum. Statt der DAO-Connection verwenden Sie nun überall eine ADODB-Connection, deren Methoden aber deutlich abweichen! Hier ist einiges an Arbeit für die Migration angesagt.

Warum Microsoft die Schnittstelle entfernte, ist nicht nachzuvollziehen. Einerseits wurden die sogenannten Access-Projekte (ADP) in welchen Sie Formulare unmittelbar an einen MSSQL-Server binden konnten, ab Access 2007 komplett entfernt und stattdessen wurden ODBC-verknüpfte Tabellen empfohlen. Gleichzeitig aber strich man ODBCDirect. Ich habe dafür nur eine Erklärung: Einst waren SQL-Server ziemlich teuer, weshalb sie häufig für Low Budget-Lösungen mit Access nicht infrage kamen. Zudem scheuten viele Entwickler den Einsatz des SQL-Servers, weil hier eine Menge zusätzliches Knowhow zu erwerben war. In der Folge fanden Sie in den einschlägigen Foren und Newsgroups nur selten Fragen zum Thema ODBCDirect. Für Microsoft offenbar Grund genug, sich dieser Schnittstelle zu entledigen.

Inzwischen aber stellt nicht nur Microsoft selbst einen kostenlosen leistungsfähigen Server (SQL Server Express) zur Verfügung, sondern auch andere Größen der Branche, wie IBM mit DB2 Express oder Oracle mit Express 11g, von den OpenSource-Lösungen MySQL, MariaDB, Postgres und Firebird ganz zu schweigen, sodass der Einsatz dieser DBMS als Backend, die der Access Engine klar den Rang ablaufen, naheliegt.

Wollen Sie hier ADODB verwenden, so hat dies einen Haken: Viele der genannten DBMS stellen keinen OLEDB-Provider zur Verfügung. Manche sind instabil oder wenig performant, bei manchen finden Sie gar keinen. Dann müssen Sie den ODBC-Provider MSDASQL nehmen, der aber eine zusätzliche Ebene einzieht und deshalb in der Performance das Nachsehen hat.

Empfehlung: Voten Sie auf access.uservoice für die Wiederaufnahme von ODBCDirect! Dort nimmt Microsoft Vorschläge zu zukünftigen Access-Versionen entgegen. Früher einmal gab es das Connect-Programm von Microsoft, wo vornehmlich MVPs ihre Vorschläge einbrachten. Die wurden allerdings nicht wirklich ernst genommen. Offenbar hat sich dies geändert. Nach dem Debakel mit den Access-WebServices, die in der Zukunft deshalb eben entfallen sollen, wendet man sich nun anscheinend vermehrt den Anregungen der Community zu, wie etwa die Wiedergeburt der dBase-Schnittstelle zeigt.

Die Programmierung der ODBCDirect-Schnittstelle ist fast so einfach, wie die von lokalen oder verlinkten Access-Tabellen:

Dim oWrk As DAO.Workspace
Dim oConx As DAO.Connection
Dim sConx As String
Dim rs As DAO.Recordset
Set oWrk = oDbEng.CreateWorkspace("", "", "", dbUseODBC)
sConx = "ODBC;Driver={Microsoft dBase Driver (*.dbf)}" & _
             ";DriverID=533";Dbq=" & CurrentProject.Path
Set oConx = oWrk.OpenConnection("", , , sConx)
Set rs = oConx.OpenRecordset( _
     "SELECT * FROM KUNDENLI.DBF.DBF", dbOpenDynaset)

Hier wird zunächst ein Workspace oWrk angelegt, welches von dem abweicht, das die DBEngine von Access.Application voreingestellt hat, weil die Konstante dbUseODBC angegeben ist. Der Normalfall wäre dbUseJet. Dann wird in sConx der Connect-String zusammengebaut, der mit dem Tag ODBC; beginnen muss.

Mit Driver geben Sie den Namen eines installierten ODBC-Treibers an, in unserem Fall den dBase-Treiber. Daran schließen sich treiberspezifische Optionen an. Hier ist es vor allem der Pfad, unter dem sich die dBase-Dateien befinden, im Schlüssel Dbq.

Mit diesem Connect-String öffnen Sie das Connection-Objekt oConx. Ähnlich, wie bei einem Database-Objekt, können Sie nun ein Recordset über ein SQL-Statement auf die Connection öffnen.

Aber das geht doch gar nicht mehr!

Korrekt. Führen Sie den angeführten Code in einer ACCDB aus, so tritt die erwähnte Fehlermeldung auf.

Sie könnten nun auf die Idee kommen, statt der ACE-Bibliothek die alte zu verwenden. Löschen Sie also den Verweis auf DAO und laden Sie einen auf DAO.36 neu (Microsoft DAO 3.6 Object Library). Tatsächlich ändert dies am Sachverhalt rein gar nichts. Denn der Verweis führt nicht dazu, dass die alte Engine geladen würde.

Da die alte, wie die neue, den Namen DAO trägt, verwendet Access weiterhin die interne ADEDAO.dll, die bereits beim Start von Access geladen wird. Die Bibliothek selbst wird zwar von VBA genutzt, doch quasi nur als Tabelle für die Klassen, die unter beiden Bibliotheken an dieselben GUIDs und Methoden für die Interfaces gebunden sind.

Der nächste Versuch wäre, eine eigene DBEngine anzulegen, die auf die dao360.dll verweist. Das lässt sich über die Methode CreateObject erledigen:

Dim oDBEng As Object
Dim oWrk As Object
Set oDbEng = CreateObject("DAO.DBEngine.36")
Set oWrk = oDbEng.CreateWorkspace("", "", "", dbUseODBC)

Verblüffend, auch dies zeitigt dieselbe Fehlermeldung in der letzten Zeile! Hier ist der Grund der, dass die Office-Installation in der Registry die ProgID- und CLSID-Schlüssel so verbogen hat, dass sie ebenfalls auf die acedao.dll verweisen. Also scheinen wohl alle Wege verbaut zu sein.

Es geht doch!

In der letzten Ausgabe erfuhren Sie, wie Sie COM-Objekte instanziieren können, ohne dass jene im System registriert sein müssen (ActiveX und COM ohne Registrierung verwenden). Dabei kommt ein Modul zum Einsatz (mdlComLoaderASM), das ziemlich komplex ist und auch vor Assembler-Teilen nicht Halt macht. Hier haben Sie nun eine nützliche Anwendung für die Routinen des Moduls: Wir versuchen, eine Instanz der alten JET-Engine über die Funktion GetCOMInstance zu erhalten. Das geht im Prinzip so:

Dim oDbEng As DAO.DBEngine
Dim oWrk As DAO.Workspace
Set oDbEng = GetCOMInstance(sFile, "DBEngine", True)
Set oWrk = oDbEng.CreateWorkspace("", "", "", dbUseODBC)

Und, siehe da, die Sache klappt, und wir haben Microsoft ausgetrickst! Natürlich muss in der Variablen sFile zuvor der Pfad zur dao360.dll stehen.

Aber gibt es diese Datei überhaupt auf dem Rechner mit Office 2007 ff.? Wir können das nicht für alle Fälle versichern. Doch die dao360.dll wird auch von Windows selbst für seine Zwecke genutzt, weshalb die Datei nach unseren Beobachtungen mit diesem installiert wird. Auch der Pfad scheint immer derselbe zu sein. Sie können ihn vom Pfad der ACEDAO ableiten, wenn auf diese ein Verweis gesetzt ist:

sFile = References("DAO").FullPath
sFile = Replace(sFile, "OFFICE14\ACEDAO.DLL", _
                        "DAO\dao360.dll")

Heraus kommt dabei der String

C:\Program Files (x86)\Common Files\Microsoft Shared\DAO\dao360.dll

Möchten Sie also Ihre alte Access 2003-Datenbank, die ODBCDirect nutzt, nach Access 2010 migrieren, so ersetzen Sie im Code einfach alle Aufrufe auf das Connection-Objekt etwa mit dieser Routine:

Dim oConx As DAO.Connection
Dim oDbEng As DAO.DBEngine
Dim oWrk As DAO.Workspace
Function Connection As DAO.Connection
Dim sFile As String
If oConx Is Nothing Then
   sFile = References("DAO").FullPath
   sFile = Replace(sFile, "OFFICE14\ACEDAO.DLL", _
                        "DAO\dao360.dll")
   Set oDbEng = GetCOMInstance(sFile, "DBEngine", True)
   Set oWrk = oDbEng.CreateWorkspace("", "", "", dbUseODBC)
End If
Set Connection = oConx
End Function

Das Connection-Objekt steht damit generell im VBA-Projekt zur Verfügung. Auf Umgestaltung nach ADO können Sie getrost verzichten.

Ein Anwendungsbeispiel finden Sie in Listing 1. Wie zuvor ausgeführt erzeugt GetCOMInstance hier eine neue DBEngine. Statt der ProgID DBEngine allerdings ist die entsprechende CLSID für das Objekt der Begierde eingesetzt. GetCOMInstance muss nämlich sonst die CLSID aus der ProgID selbst ermitteln, was Sie der Prozedur abnehmen können.

Sub ConnectMysqlODBCDirect()
     Dim oDbEng As DAO.DBEngine
     Dim oWrk As DAO.Workspace
     Dim oConx As DAO.Connection
     Dim sConx As String
     Dim rs As DAO.Recordset
     Dim sFile As String
     
     sFile = Replace(References("DAO").FullPath, "OFFICE14\ACEDAO.DLL", "DAO\dao360.dll")
     
     Set oDbEng = GetCOMInstance(sFile, _
                     "{00000100-0000-0010-8000-00AA006D2EA4}", True)
     'oder statt CLSID: DBEngine ~ DAO.DBEngine.36
     
     Set oWrk = oDbEng.CreateWorkspace("", "", "", dbUseODBC)
     sConx = "ODBC;Driver={MySQL ODBC 5.3 ANSI Driver};" & _
         "DATABASE=mysqlbackend;" & _
         "SERVER=127.0.0.1;PORT=3306;" & _
         "UID=root;PWD=aiupwd;OPTION=18475"
     Set oConx = oWrk.OpenConnection("", dbDriverNoPrompt, , sConx)
     'oder dbDriverCompleteRequired
     Set rs = oConx.OpenRecordset( _
       "SELECT ID,Artikel FROM tblArtikel", dbOpenDynaset)
     Do While Not rs.EOF
         Debug.Print rs(0).Value, rs(1).Value
         rs.MoveNext
     Loop

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.

Bitte teilen Sie uns Ihre Anrede, Ihren Namen und Ihre E-Mail-Adresse mit:

Anrede:
Vorname:
Nachname:
E-Mail:

© 2003-2018 André Minhorst Alle Rechte vorbehalten.