Hallo Forum,
ich bin neu hier und habe mich angemeldet, da ich keine adequate Lösung im Internet gefunden habe.
Kurzfassung:
Ich möchte aus einem Access Frontend (A) eine Abfrage in einer anderen Access Datei (B) öffnen. Also die Daten per ADO Recordset holen. Nun benutzt diese Abfrage (in der fremden Datei B) eine VBA Funktion.
Beim Öffnen des Recordset bekomme ich die Meldung, dass die Funktion nicht definiert ist.
Kopiere ich mir die Funktion von A nach B, geht das Recordset auf. Beim Debuggen kann ich (leider) auch feststellen, dass die Funktion in A ausgeführt wird.
>:(
Ziel der Sache ist aber gerade, dass ich mir die Daten dort holen will, ohne Funktionen zu vervielfältigen.
Mit eingebundenen Tabellen das gleiche!
Die ADO Connection ist bereits curser serverseitig eingestellt, habe auch client probiert, gleiches Drama!
Was will ich?
Ich will, dass die Funktion in B ausgeführt wird (in der Fremden Datenbank, dort wo auch die Abfrage liegt!
Alternativer Ansatz: Ich löse dort einen Code aus, der eine Temp-Tabelle baut und hole mir die Daten dann von hier. Wollte aber erst mal fragen, ob sich das nicht vernüftig lösen lässt.
Ich verstand bisher eine gespeicherte Abfrage wie ein View, scheint aber irgendwie anders zu sein.
Besten Dank in die Runde!
Nur die in der Access/Jet-Engine eingebauten Funktionen können in dieser Szenerie verwendet werden.
Wenn Du die Abfrage als SQL-Text hier postest und ggf. verwendete eigene VBA-Funktionen dazu erklärst, könnte man u.U. einen konkreten Vorschlag machen.
Mit einem Datenbankserver statt einer accdb würde das gehen. Gibt es ganz kostenlos zum Download.
Zitat von: Milvus am Oktober 19, 2018, 15:25:26
Die ADO Connection ist bereits curser serverseitig eingestellt, habe auch client probiert, gleiches Drama!
Das macht bei einer access-Datei als Backend auch gar keinen Unterschied.
Zitat von: Lachtaube am Oktober 19, 2018, 15:55:56
Wenn Du die Abfrage als SQL-Text hier postest und ggf. verwendete eigene VBA-Funktionen dazu erklärst, könnte man u.U. einen konkreten Vorschlag machen.
Ums auf Wesentliche zu bringen:
Feld Standardfunktion VBA Funktion in allgem. Modul (die die Ärger macht)
SELECT StandardFeld, Year([Feld1]) AS YYYY, kalenderwoche([Feld1])
Zitat von: Wurliwurm am Oktober 19, 2018, 16:16:06
Mit einem Datenbankserver statt einer accdb würde das gehen. Gibt es ganz kostenlos zum Download.
Ja das scheint darauf hinaus zu laufen. Hab ich als VIEW schon mal gesehen! Da wird alles Server-Seitig gemacht. Umso größer die Verwirrung, dass ich ADO so einstelle Curser = Server und das Teil das Gegenteil macht.
Menschenskinder! >:(
Hallo Milvus,
Von einer VBA-Funktion ist da nichts zu sehen, nur eine unvollständige
Auswahlabfrage.
Wenn ich nicht völlig daneben liege, kannst du aber im FROM-Teil einer
Abfrage auch den kompletten Pfad zu einer externen DB (B) angeben.
D.h. du kannst die Abfrage direkt in DB A ausführen.
gruss ekkehard
Zitat von: Milvus am Oktober 19, 2018, 16:42:04
Umso größer die Verwirrung, dass ich ADO so einstelle Curser = Server und das Teil das Gegenteil macht.
Das Access ignoriert die Einstellung schlichtweg. Immer bewuß halten: Architekturmäßig gibt es keinen Server(prozess) beim Zugriff auf die externe Access-Datei, sondern einen File-Zugriff über die lokale jet.dll.
Die Kalenderwoche ist also der Störfaktor. Bei in Europa gängigen Kalenderwochen nach ISO 8601 versagt DatePart() in einigen Jahren (2019 z.B.) an Montagen und liefert fälschlich die KW 53 statt KW 1 des Folgejahres. Da aber die KW des darauffolgenden Dienstags immer stimmt und auch immer dieselbe KW betrifft, könnte man ein Datum, das auf einen Montag fällt, immer auf den Dienstag - besser noch auf den Donnerstag verschieben - denn dann stimmt auch die Jahresangabe zur KW.
SELECT DatePart( 'ww', Datumsfeld - Weekday( Datumsfeld, 2 ) + 4 ) AS KW,
Year( Datumsfeld - Weekday( Datumsfeld, 2 ) + 4 ) AS YYYY
FROM EineTabelle;
Persönlich würde ich eine Tabelle mit Zeitdimensionen in der Auflösung von einen Tag bevorzugen, in dem nicht jedesmal bei Verwendung eines Datums die KW neu errechnet werden muss.
Zitat von: Wurliwurm am Oktober 19, 2018, 16:52:58
Das Access ignoriert die Einstellung schlichtweg. Immer bewuß halten: Architekturmäßig gibt es keinen Server(prozess) beim Zugriff auf die externe Access-Datei, sondern einen File-Zugriff über die lokale jet.dll.
Das erklärt alles, der Profi kommt nicht von ungefähr ;D
Mist! Da muss ich basteln.
Danke für Eure Hilfe!
Zitat von: Lachtaube am Oktober 19, 2018, 17:11:14
Die Kalenderwoche ist also der Störfaktor. Bei in Europa gängigen Kalenderwochen nach ISO 8601 versagt DatePart() in einigen Jahren (2019 z.B.) an Montagen und liefert fälschlich die KW 53 statt KW 1 des Folgejahres. Da aber die KW des darauffolgenden Dienstags immer stimmt und auch immer dieselbe KW betrifft, könnte man ein Datum, das auf einen Montag fällt, immer auf den Dienstag - besser noch auf den Donnerstag verschieben - denn dann stimmt auch die Jahresangabe zur KW.
SELECT DatePart( 'ww', Datumsfeld - Weekday( Datumsfeld, 2 ) + 4 ) AS KW,
Year( Datumsfeld - Weekday( Datumsfeld, 2 ) + 4 ) AS YYYY
FROM EineTabelle;
Persönlich würde ich eine Tabelle mit Zeitdimensionen in der Auflösung von einen Tag bevorzugen, in dem nicht jedesmal bei Verwendung eines Datums die KW neu errechnet werden muss.
Hey Lachtaube, danke für den Ansatz! Ja, klar...
Was ich bisher verschwiegen habe, das war nur ein Beispiel. Es gibt noch zahlreiche andere Funktionen, da müsste ich überall ran...
Daher mein Ansatz von Extern auf interne Abfragen zuzugreifen, um das damit zu umgehen!
Merci in die Runde!
Zitat von: Wurliwurm am Oktober 19, 2018, 16:52:58
Zitat von: Milvus am Oktober 19, 2018, 16:42:04
Umso größer die Verwirrung, dass ich ADO so einstelle Curser = Server und das Teil das Gegenteil macht.
Das Access ignoriert die Einstellung schlichtweg. Immer bewuß halten: Architekturmäßig gibt es keinen Server(prozess) beim Zugriff auf die externe Access-Datei, sondern einen File-Zugriff über die lokale jet.dll.
Access ignoriert die Vorgaben keinesfalls. - Abgesehen davon dass wir von der ADO Klasse sprechen.
Nicht jeder Provider unterstützt alle Möglichkeiten, außerdem verstehen die wenigsten, dass man die Optionen nicht beliebig kombinieren kann.
Das ist bei DAO auch nicht anders. Besser wäre es natürlich, das Recordset würde einfach einen Laufzeitfehler erzeugen, wenn im Code Unsinn steht, aber das passiert eben nicht.
Wenn man die Codes in Verbindung mit ADO in diversen Foren ansieht wird man feststellen, dass zu 90% die Angaben nicht umsetzbar sind und daher das Recordset sie ändern muss. Da aber kaum jemand nachsieht, wie Anweisungen umgesetzt werden bleibt das unbemerkt.
Zeig also mal, wie dein Code aussieht.
Unabhängig davon geht das mit den UDF nicht. Die müssen immer im ausführenden Frontend stehen, so wie hier bereits ausgeführt.
LG M
Zitat von: markus888 am Oktober 20, 2018, 11:02:10
Zitat von: Wurliwurm am Oktober 19, 2018, 16:52:58
Zitat von: Milvus am Oktober 19, 2018, 16:42:04
Umso größer die Verwirrung, dass ich ADO so einstelle Curser = Server und das Teil das Gegenteil macht.
Das Access ignoriert die Einstellung schlichtweg. Immer bewuß halten: Architekturmäßig gibt es keinen Server(prozess) beim Zugriff auf die externe Access-Datei, sondern einen File-Zugriff über die lokale jet.dll.
Da aber kaum jemand nachsieht, wie Anweisungen umgesetzt werden bleibt das unbemerkt
Ich könnte mir vorstellen, das Microsoft das bewusst so gemacht hat, um die Zielgruppe nicht zu irritieren mit 'unbegreiflichen' Fehlermeldungen. Wenn einer wie der TE merkt, das hier etwas faul ist, dann ist er schon in einem Erkenntnisprozess.
Die vorgeschlagenen Workarounds halte ich nicht gut. Man muss sich wie gesagt bewusst machen, dass bei einer Access-Datei als Backend sämtliche Clients die Abfragen erst lokal verarbeiten können. Sie kennen nur die Rohdaten, die evtl alle über das Netz müssen, wissen nichts über Code in der Backend-Datei, bei konkurrierendem Schreiben und Lesen müssen Hintergrund ziemliche Tricks gemacht werden und trotzdem wird es unendlich langsam.
Deshalb einen Server (ich meine ein Programm und nicht teure Hardware) einsetzen. Der Umstieg ist erstmal ähnlich wie beim Umstieg von Excel auf Access, wo man auch erst ein leeres Blatt vor sich hat und nicht gleich lostippen kann. Man muss dort in Relationen und nicht in Excel Tapeten denken, Formulare, Funktionen, Recordsets und Routinen verstehen. Beim Umstieg auf den Server muss man halt sich zusätzlich mit Usern, Berechtigungen und Freigaben, Ports und IP-Adressen, Logs etc. vertraut machen. Und mit serverseitigen Funktionen, Stored Procedures und Triggern.
Man sollte sich zudem vor Augen halten, dass der Sprachumfang von Jet-SQL sehr sparsam ist. Sehr stark aufgebessert wird das, indem der Expression Service auch Funktionen der VBA-Bibliothek, Accessfunktionen (Nz, DMax) und eigendefinierte Funktionen verfügbar in der SQL-Anweisung macht, allerdings nur aus dem Access-Frontend heraus.
Hahahaaaa! ;D
Das hilft nicht viel.
Zentrales Problem ist, ich will die Funktionen in anderen Frontents nicht kopieren und vervielfältigen.
Ich habe einen Ansatz gefunden:
SELECT * FROM Abfrage1 IN 'C:\Testing\MitFunktion.accdb'
Läuft!
D.h. in der Datenbankt MitFunktion.accdb habe ich eine Abfrage gepackt die eine VBA Funktion dort benutzt.
Von einer anderen Datei greife ich mit dem SELECT oben zu, und geht.
https://support.microsoft.com/de-de/help/508923
Vielleicht kann der ein oder andere damit was anfangen. 8)
Bin gerne auch an alternativen Ansätzen interessiert. Ich suche mir dann das beste raus.
Ergänzung:
Hab ich vergessen: Damit das funktionert, muss ein Verweis auf das VBA-Projekt gesetzt sein.
Also, im VBA Editor die Verweise öffnen, Durchsuchen, und die Datei auswählen, wo die Abfrage drin ist.
Zitat von: Milvus am Oktober 22, 2018, 08:44:55
Ergänzung:
Hab ich vergessen: Damit das funktionert, muss ein Verweis auf das VBA-Projekt gesetzt sein.
Hoffentlich verstehst du jetzt auch, dass es mit dem In Operator in der Select Anweisung nichts zu tun hat.
ZitatSELECT * FROM Abfrage1 IN 'C:\Testing\MitFunktion.accdb'
Indem du einen Verweis verwendest werden die Funktionen der Anwendung alle direkt in den Speicher geladen.
Deine Vorgehensweise (Abfragen und Codes anderer Frontends zu verwenden) erscheint grundsätzlich einmal sonderbar. Aber wie auch immer jeder soll experimentieren und dazu lernen. So ergeben sich manchmal interessante Ideen.
Ich persönlich verwende einfach eine accde Datei für Funktionen, Klassen und Formulare welche ich per Verweis in die Frontends einbinde, damit die in jeder Anwendung zur Verfügung stehen.
Es wäre konstruktiv, auch einmal darüber nachzudenken, ein aktives DBMS als Backend einzusetzen statt eines Accessfiles. Damit kann man u.a. eine Menge Anwendungslogik (Views scheinen Dir bekannt zu sein) in diesem Backend zentral halten und verwalten, die angesetzten Frontends (beliebiger Art) können sich dann um ihre eigenen Belange kümmern ohne einen Codeaustausch oder gegenseitigen Zugriff.
Ohne die Ergänzung hätte mich das Funktionieren auch sehr verwundert.
.