Language: Deutsch English















Last Update: 2017 - 09 - 05





Eine AccDE/MDE/ADE-Datei mit VB-Script erstellen

von Philipp Stiefel, ursprünglich veröffentlicht 23. November 2015


Mann im Nebel, article header image

Ich habe heute über eine Stunde damit verbracht, ein VB-Script zu debuggen, das, unter anderem, aus einer Microsoft Access Data Project (ADP) Datei eine kompilierte ADE-Datei erzeugen sollte. (Dieser Artikel gilt für AccDB zu AccDE und MDB zu MDE genauso.)

Ich verstehe jetzt endlich das Problem und habe eine fast schon triviale Lösung dafür gefunden. – Aber da ich keine Beschreibung dieses Sachverhalts im Internet finden konnte, schreibe ich nun eine hier.

AccDE/MDE/ADE-Datei mit SysCmd 603 erstellen

Um eine Access Anwendung mit VBA zu einer AccDE (MDE/ ADE) zu kompilieren, kannst du die SysCmd-Funktion von Access verwenden, wenn du sie mit der undokumentierten AcSysCmdAction ‘603’ aufrufst. Diese Aktion ist zwar undokumentiert, aber sie ist bereits sei Access 97 vorhanden und sie funktioniert sehr zuverlässig.

Es gibt auch keine weitere Möglichkeit, um eine kompilierte Access Datei per VB(A) Code zu erstellen, außer die Access-Benutzeroberfläche mit SendKeys oder ähnlichem zu automatisieren.

Verwende diese Syntax, um eine kompilierte Access Anwendung mit einem SysCmd-Aufruf zu erstellen:

SysCmd 603, strInputFile, strOutputFile

Wenn du das so machst, brauchst du nur ein paar einfache und ziemlich naheliegende Regeln zu beachten, damit die Funktion funktioniert, wie erwartet.

  • Das Access-Datenbankformat muss von der Version von Access, die du dazu benutzt, unterstützt werden.
  • Der komplette VBA Code deiner Anwendung muss sich fehlerfrei kompilieren lassen.
  • Die Quelldatenbank darf nicht in der aktuellen oder einer anderen Access Instanz geöffnet sein.

So weit, so gut. Nun zu dem Problem.

Das problematische Script

Hier ist ein vereinfachter Auszug aus meinem Script um die kompilierte Access Datei zu erzeugen.

Dim app Dim strDBName Dim strADEName Set app = CreateObject("Access.Application") strDBName = "D:\Source\AccFile.adp" strADEName = "D:\Target\AccFile.ade" app.SysCmd 603, strDBName, strADEName Set app = Nothing

Das sieht so aus, als sollte es funktionieren, oder?

Es funktioniert aber nicht. Der Funktionsaufruf löst einen Laufzeitfehler aus.

Laufzeitfehler 7952 - Sie haben einen ungültigen Funktionsaufruf angegeben.

Natürlich habe ich alle oben angegebenen Voraussetzungen geprüft. Ich habe mich überzeugt, dass die Pfade zu den Dateien korrekt sind und Lese- bzw. Schreibrechte bestehen. Dann habe ich danach recherchiert, was diese Fehlermeldung genau heißen könnte.

Problemanalyse

Das diese Verwendung der SysCmd-Funktion nicht dokumentiert ist, wird sie auch nicht so häufig verwendet. Ich habe folglich keine Erklärung für dieses Phänomen oder eine Lösung dafür im Internet gefunden.

Aus den erfolgreichen Lösungen für andere Probleme mit Aufrufe der SysCmd-Funktion mit dokumentierten AcSysCmdActions, die die gleiche Fehlermeldung ausgelöst hatten, konnte ich ableiten, dass die Funktion uns mit der Meldung sagen will: „Ich mag deine Parameter nicht!“.

Also schauen wir uns die SysCmd-Funktion und ihre Parameter einmal genauer an:

So let’s look at the parameter definition of the SysCmd-Function

Function SysCmd(Action As AcSysCmdAction, [Argument2], [Argument3]) Member of Access.Application

Action ist die Aktion, die durchgeführt werden soll. Ein numerischer Wert aus dem AcSysCmdAction-Enum oder in unserem Fall ein numerischer, undokumentierter Wert. Dieser Parameter sollte in Ordnung sein.

Argument2 und Argument3 haben keinen definierten Datentyp. Also sind sie Variants in VB(A).

In VB-Script sind alle Variablen vom Typ Variant. Die Variablen im Script, die die Pfade zu den Access Dateien enthalten und an die SysCmd-Funktion übergeben werden sind Variants mit dem Subtyp String. Dies sollte also nicht zu einem harten, aber klaren „Laufzeitfehler 13 – Datentypen unverträglich“ führen – Tut es ja auch nicht.

Aber denk darüber nochmal genau nach. Die SysCmd-Funktion hat eine Vielzahl von Aufgaben (schlechtes Design!), immer abhängig von dem Wert des Action-Parameters. Also müssen die Parameter Argument2 und Argument3 vom Typ Variant sein um die vielen verschiedenen Use-Cases der Funktion zu unterstützen. Daher kann in diesem Zusammenhang kaum ein klarer „Datentypen unverträglich“-Fehler auftreten.

Ich vermute das Access Entwicklungsteam bei Microsoft hatte die Absicht, diese Funktion so robust wie möglich gegen ungültige Parameter zu machen, in überprüft wird ob die Datentypen zu dem übergebenen Wert für Action passen. Sie haben eine Validierung der Parameter implementiert, die einen Laufzeitfehler „7952 - Sie haben einen ungültigen Funktionsaufruf angegeben.“ auslöst, um Parameter mit unerwarteten Datentypen zurückzuweisen.

Die Lösung

Nehmen wir einmal an, die Argumente für den Aufruf von SysCmd müssen exakt den richtigen Datentyp für den übergebenen Action Wert haben. Um eine AccDE/MDE/ADE zu kompilieren sind die beiden anderen Argumente die Pfade zu der Input- bzw. Output –Datei. Diese sollten als Strings übergeben werden. – Aber in VB-Script sind die entsprechenden Variablen Variants, wenn auch mit Subtyp String.

Wenn unsere Annahme korrekt ist, sollte das Script funktionieren, wenn wir die Pfade ausdrücklich als Strings anstelle von Variants an die SysCmd-Funktion übergeben. Um das zu erreichen, konvertiere ich die Variablen bei der Übergabe an SysCmd mit der CStr-Funktion jeweils zu einem String.

Dim app Dim strDBName Dim strADEName Set app = CreateObject("Access.Application") strDBName = "D:\Source\AccFile.adp" strADEName = "D:\Target\AccFile.ade" app.SysCmd 603, CStr(strDBName), CStr(strADEName) Set app = Nothing

Und rate mal! – Es funktioniert tatsächlich!

Also ist unsere Annahme korrekt und mein Problem ist gelöst.

Ich habe immerhin das Beste aus dieser ärgerlichen Zeitverschwendung gemacht, indem ich darauf basierend diesen Artikel geschrieben habe und somit hoffentlich anderen Entwicklern helfe, schneller eine Lösung zu finden.

Lektionen

Hier sind zwei Lektionen, die wir aus dieser Geschichte lernen sollten.

  1. Eine Funktion für eine Vielzahl verschiedener Aufgaben ist schlechtes Programmdesign, denn ihre Aufrufschnittstelle wird unscharf und fehlerträchtig sein. Jede Funktion sollte nur eine, klar definierte Aufgabe haben!

  2. Das gleiche gilt für Variablen. Jede Variable einen klaren Zweck und dieser sollte sich in ihrem Datentyp widerspiegeln. Verwende streng typisierte Variablen, wenn das irgendwie möglich ist. – In diesem Beispiel ist es das nicht, weil VB-Script keine typisierten Variablen unterstützt.

Share this article: Share on Facebook Tweet Share on LinkedIn Share on XING

Abonniere meinen Newsletter

*

Ich werde Deine Email-Addresse niemals weitergeben. Du kannst den Newsletter jederzeit abbestellen.



© 1999 - 2017 by Philipp Stiefel