Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

VBA Projekt als Klassenbibliothek

Begonnen von Milvus, Oktober 23, 2018, 16:33:17

⏪ vorheriges - nächstes ⏩

Lachtaube

Externen COM-Bibliotheken lassen sich auch Reg-Free einbinden, indem man ein Manifest in die Bibliothek einbindet (ist bei Dot Net vermutlich sogar Pflicht) und für Access selbst ein externes Manifest verwendet. In VBA muss dann ein Aktivierungskontext (eine Instanz von Microsoft.Windows.ActCtx) verwendet werden. Mehr dazu unter Reg-Free COM at runtime via Microsoft.Windows.ActCtx. Alternativ sollte sich auch Olaf Schmidts DirectCOM.dll, die ohne Manifest-Gedöns auskommt, verwenden lassen.
Grüße von der (⌒▽⌒)

Josef P.

#31
Hallo!

Vorab: Ich selbst würde eine accda auch nicht für fix in der Anwendung benötigte Klassen verwenden. Trotzdem muss ich diese Methode ein wenig verteidigen, da man auch damit ordentlich programmieren kann. Der Aufwand ist allerdings größer als mit in der Anwendung enthaltenen Codemodulen.

Zitat von: markus888 am November 17, 2018, 12:17:52
Run und CallbyName brauchen ein vielfaches der Zeit wie direkte Aufrufe.
Was aber bei einem einmaligem Aufruf (je Anwendungsstart) ziemlich egal sein wird.

ZitatRun gibt keinen Error weiter.
Die daraus erzeugten Instanzen aber schon.

ZitatBei Klassen müsste alles per LateBinding funktionieren.
Im Frontend müsste man immer als Objekt deklarieren, da die Klasse unbekannt ist.
Der Compiler kann also keine Änderungen der Schnittstellen feststellen.
Man kann aber die Entwicklung Early binding durchführen und zur Anwendungserstellung auf Latebinding umstellen.

Im Anhang ist noch ein Beispiel, wie ich eine accda als Bibliothek einsetzen würde.
Anm.: TestLib.accda ist nicht komplliert, könnte aber auch als accde (umbenannt auf accda) verwendet werden.

mfg
Josef

markusxy

Na bitte, warum nicht  ;D ;D ;D
Ein kleiner Mehraufwand beim Codieren und bei Änderungen, aber es geht.
Man könnte einfache Funktionen und Prozeduren natürlich auch noch in eine Klasse packen, dann müsste man da auch kein Run verwenden.

Milvus

Zitat von: Josef P. am November 17, 2018, 19:33:17

Man kann aber die Entwicklung Early binding durchführen und zur Anwendungserstellung auf Latebinding umstellen.

Im Anhang ist noch ein Beispiel, wie ich eine accda als Bibliothek einsetzen würde.

JA, zu 90% hab ich das so gemacht. Ich habe derzeit 4 cls, die ich über 4 PUblic funciton initialisiere. Die Idee mit der übergestülpten Factory cls... cool!

Also Fazit wäre, ist schon machbar, besser wäre eine COM-DLL.
Dafür brauche ich .Net bzw. Visual Stuido, richtig?

Lachtaube

#34
COM ist in vielen Programmiersprachen integriert und nicht auf Dot Net beschränkt. Mit Visual Studio (die Community Version dürfte ausreichen) lässt sich jedoch auch ohne große Kenntnis der Funktionsweise von COM schnell ein Resultat erzielen.

Ich hänge nachträglich noch ein kleines Beispiel für eine Regfree COM-Lösung an, das der Translate-Funktion einiger DB-Server nachempfunden ist. Es nutzt Olaf Schmidts DirectCOM.dll. Die DLL wurde mit Power-BASIC 10.04 erstellt (Quell-Code liegt bei) und ist um ein vielfaches schneller als VBA-Implementierungen des gleichen Codes. Registriert man die DLL, ist mit weiterem Geschwindigkeitszuwachs zu rechnen. Die DLLs sowie das Frontend müssen für das Regfree-Funktionieren in dem selben Ordner verweilen.
Grüße von der (⌒▽⌒)

Milvus

Tach in die Runde,

neue erweiterte Fragestellung zu dem Thema.

Ich habe nun eine Hand voll Klassenmodule, die ich zentral hoste und wie oben besprochen aufrufe (Appli.Run).

Nun will ich auch einige Formulare und ggf. weitere Access-Objekte dort hosten, da die in mehreren Anwendungen laufen und ich die ebenfalls nicht duplizieren will.

Das hat nun mit einem Formular auch wunderbar geklappt. Ich referenziere über das Hauptobjekt der Libery (ein Klassenmodul), in welchem dann über eine Funktion das Formular-Klassenmodul initialisiert wird.

Alles OK, klappt soweit!!!

Nun verfügt dieses Formular-Klassenmodul über eine öffentliche Sub, mit der bestimmte Aktionen ausgeführt werden sollen. Die ist extra dafür bebaut, um sie von außen anzustoßen. Und da liegt der Hase im Getreide,...

Ich kann die Prozedur zwar von außen anstoßen, bekomme an der Stelle also keinen Fehler, sie wird aber nicht ausgeführt.

Befindet sich das Formular im Forntend selbst, geht es!


Jemand eine Idee?


Wurliwurm

Zitat von: Milvus am November 21, 2018, 13:02:14
Das hat nun mit einem Formular auch wunderbar geklappt. Ich referenziere über das Hauptobjekt der Libery (ein Klassenmodul), in welchem dann über eine Funktion das Formular-Klassenmodul initialisiert wird.

Alles OK, klappt soweit!!!

Nun verfügt dieses Formular-Klassenmodul über eine öffentliche Sub, mit der bestimmte Aktionen ausgeführt werden sollen. Die ist extra dafür bebaut, um sie von außen anzustoßen. Und da liegt der Hase im Getreide,...

Ich kann die Prozedur zwar von außen anstoßen, bekomme an der Stelle also keinen Fehler, sie wird aber nicht ausgeführt.

Ceterum censeo...  ;) Ich habe ja weiter oben schon ausgeführt, daß ich diese Architektur als sehr provisorisch halte und selbst solche Konstruktionen irgendwann aufgegeben habe, weil es keine wirkliche objektorientierte Programmierung mit VBA geben kann.

Für den konkreten Fall fällt mir ein, daß Du evtl. ein Form-Objekt zurückbekommst. Was Du bräuchtest, wäre aber eine Instanz von dem ganz speziellen Formular, mit seinen ganzen Controls und Ereignissen. Indiz dafür ist, wenn Du alle Standardmethoden des Form-Objekts aufrufen kannst, aber keine eigenen Routinen. Wenn das der Fall wäre, gäbe es wahrscheinlich Möglichkeiten, hier etwas zu kapseln, aber das sind alles Workarounds, wo Du immer tiefer in den Wald kommst.

markusxy

Zitat von: Milvus am November 21, 2018, 13:02:14
Ich kann die Prozedur zwar von außen anstoßen

Wie machst du das?
Ich vermute mal, dass das Form nicht in der Auflistung der geöffneten Forms des Frontends, sondern in der zweiten Application geführt wird.

Also müsste es mit Appli!Forms!FormName.Methode funktionieren.
Da sollte es dann spätestens klingeln, wenn man vorhat, dass mehrere Anwendungen die gleiche "Bibliothek" gleichzeitig verwenden wollen. Das würde gelinde gesagt ins Chaos führen.

Du könntest aber mal eine MusterDatei - Frontend und Bibliothek hochladen, dann könnte man sich das ansehen.

Josef P.

#38
Hallo!
ZitatIch kann die Prozedur zwar von außen anstoßen, bekomme an der Stelle also keinen Fehler, sie wird aber nicht ausgeführt.
Wie hast du festgestellt, dass die Prozedur nicht ausgeführt wird?
Wenn du sie ohne Fehlermeldung aufrufen kannst, ist es für mich schwer vorstellbar, dass der Code darin nicht ausgeführt wird.

BTW: Formulare in die Lib einbauen, wir besonders lästig, wenn du so ein Formular als Unterformular verwenden willst .. das ist nämlich nicht möglich.

mfg
Josef

markusxy

Zitat von: Josef P. am November 22, 2018, 07:57:51

BTW: Formulare in die Lib einbauen, wir besonders lästig, wenn du so ein Formular als Unterformular verwenden willst .. das ist nämlich nicht möglich.

So lange alle Formulare im gleichen Projekt sind, sollte es vermutlich schon funktionieren, nur halt nicht Projekt übergreifend, da man das VB_Exposed Attribut nicht auf True setzen kann.

Josef P.

#40
Hallo!

ZitatSo lange alle Formulare im gleichen Projekt sind, sollte es vermutlich schon funktionieren, nur halt nicht Projekt übergreifend
Genau an das dachte ich. Ein Formular aus der Lib als Unterformular in der Anwendung einbauen.

Zitat.. da man das VB_Exposed Attribut nicht auf True setzen kann.
Zumindest nicht bei einem Formular. Bei einem normalen Klassen-Codemodul könnte man VB_Creatable und VB_Exposed auf True setzen, um ein Instanz mit New (bei Early binding) erzeugen zu können.
Aber auch wenn man das bei einem Formular einstellen könnte, könnte man das Formular in der Lib-Datei nicht als Unterformular in der Anwendung auswählen, weil das in Access nicht vorgesehen ist. ;)

mfg
Josef

Milvus

Guten Morgen liebe Mitstreiter,

also ich finde das Forum hier echt klasse, ein reger Austausch

:D

Also zu meiner Vorgehensweise, Vergleich:

Ich habe eine MDE mit allen Klassenmodulen, die auf public eingestellt sind und ein Master-Klassenmodul, in welchem die Public Funcitons zur Initialisierung der konkreten Klassenmodule eingerichtet wird. Außerdem gibt es noch eine Public Function in einem wilden Codeformular, welches die Masterklasse einleitet.

Der Zugriff aus einer anderen Access Datei folgt einmalig über die Public Function für die Masterklasse, der Rest dann über das Object der Masterklasse.

Das funktioniert alles sauber!!!

Nun habe ich auch ein ungebundenes Formularin der Liary Datei platziert und dieses (genauer gesagt das Klassenmodul des Formulars) ebenfalls unterhalb der Masterklasse initialisierbar gemacht.

Auch dieses kann ich (wie die Klassenmodule auch) über die Libary initialisieren und auf die Collections des Formulars zugreifen. Kann es also laden und benutzen.

Der Unterschied zu den Klassenmodulen:

In einem Klassenmodul platziere ich Publics (Properties, Prozeduren, Functions), die kann ich aus der fremden Anwendung alle anstoßen!!!

In dem Klassenmodul des Formulars habe ich ebenfalls Publics platziert, die kann ich offenbar nicht anstoßen!

Es kann sein, dass mir die MDE da etwas vortäuscht, die kann man ja nicht im Einzelschritt durchlaufen.
Ich melde mich noch mal.

Sorry kann nix hochladen, ist von Firma. Müsste ich was Abspecken, kann ich aber bei Geleg.!



markusxy

Zitat von: Milvus am November 23, 2018, 09:12:45
In einem Klassenmodul platziere ich Publics (Properties, Prozeduren, Functions), die kann ich aus der fremden Anwendung alle anstoßen!!!

In dem Klassenmodul des Formulars habe ich ebenfalls Publics platziert, die kann ich offenbar nicht anstoßen!

Weil du das Klassenmodul eines Formulars im Gegensatz zu einem normalen Klassenmodul nicht "Public" setzen kannst.
Das Attribut VB_Exposed kannst du im Formular nicht auf true setzen. Da musst du dir also einen anderen Weg überlegen.

Lachtaube

Ein Access-Formular benötigt keinen Code im eigenen Klassen-Modul - es muss lediglich ein (leeres) Klassen-Modul bestehen, um VBA-Events anbinden zu können. Eine Realisierung kannst Du in einer dreistufigen Umsetzung von Shamil Salakhetdinov nachsehen. Nur Open- und Load-Event benötigen einen proreduralen Ansatz, womit sich aber gut leben lässt.
Grüße von der (⌒▽⌒)

Josef P.

Hallo!

ZitatIn dem Klassenmodul des Formulars habe ich ebenfalls Publics platziert, die kann ich offenbar nicht anstoßen!
Du kannst diese Prozduren schon starten. Du kannst sie nur nicht per IntelliSense sehen, da nur das Form-Interface nutzbar ist.

mfg
Josef

Anm.: Ich zeige im Anhang nur eine Möglichkeit der Umsetzung. Das bedeutet nicht, dass ich diese Vorgehensweise empfehle. ;)