Hallo zusammen,
kurze Frage in die Runde. Es besteht kein Problem direkt, ich möchte eher Erfahrungswerte tauschen.
Problemstellung: Es gibt mehrere Frontends. Einige enthalten "a lot of" Code, bei anderen gehts so. Der Code hat große Schnittmengen, heißt Funktionen etc. sind gleich (manchmal aber auch nicht, da es sich im ein gewachsenes Objekt handelt). Und da bin ich auch schon am Punkt:
Ich will die Redundanz des Codes vermeiden. Ich habe etliche Module mit untershiedlichen Funktionen, Subs, die extrem kaskadiert sind usw. (Stress!)
Meine Idee: Ich möchte sämtlichen Code in ein VBA-Projekt stecken. Mit den Verweisen sollte es keine Knoflikte bei den unterschiedlichen Forntends geben (außer bei Versionen). Soweit es möglich ist, will ich so viel wie möglich in Klassenmodule verfrachten, und somit eine Art "Klassenbibliothek" aufbauen.
Das Projekt will ich dann in die Frontends per VBA Verweis einbinden.
Also in Richtung 3-Schicht Modell (Formularcode bleibt im Frontend, der Rest des Codes wird zentralisiert)
Habt Ihr Erfahrungen damit?
Geht das und taugt die Idee?
Wäre für jede Rückmeldung von Leuten, die sowas schon mal gemacht haben sehr dankbar.
Hallo,
du kannst alle Prozeduren in eine separate DB-(Datei) einbauen und die DB-Datei als Verweis in das FE einbauen.
Zitat von: Milvus am Oktober 23, 2018, 16:33:17
Also in Richtung 3-Schicht Modell (Formularcode bleibt im Frontend, der Rest des Codes wird zentralisiert)
Habt Ihr Erfahrungen damit?
Geht das und taugt die Idee?
Mit Access und VBA eine 3-Schicht-Anwendung bauen zu wollen ist gelinde gesagt äußerst kreativ, hart gesagt absurd. Wirklich gehen tut es sowieso nicht, weil eine 3-Schicht-Anwendung in der Middleware einen eigenen Prozess hat. Was Du beschreibst, ist ein Zugriff auf Bibliotheken.
Access ist sehr schön intuitiv und man kann viele schnelle Erfolgserlebnisse damit haben. Aber es hat Gründe, warum es nicht für größere Anwendungen benutzt wird.
Zitat von: Wurliwurm
Mit Access und VBA eine 3-Schicht-Anwendung bauen zu wollen ist gelinde gesagt äußerst kreativ, hart gesagt absurd. Wirklich gehen tut es sowieso nicht, weil eine 3-Schicht-Anwendung in der Middleware einen eigenen Prozess hat.
Ich ahne ungefähr, was Du meinst, da wir in VBA keine Vererbung realisieren können. Gut es gibt immerhin Schnittstellen.
Unter 3Schicht meinte ich relativ simpel: Formularlogik ist in den Formularen und alles was sich "als Prozess oder Funktionalität" kapseln lässt kommt in Klassenmodule. Allgemeine Funktionen kommen in normale Module und sind nur in der Peripherie der Architektur. Allgemeine Prozeduren gibt es am besten gar nicht.
Die Daten befinden sich natürlich im Backend.
Die Klassenmodule können voneinander abhängen, was sich beim intitialisieren bereits festlegen lässt.
Somit wäre damit schon ein relativ hoher Grad an eine Klassenarchitektur erreichbar, wenn auch keine echte.
So meinte ich das. Für meine Fälle jedenfalls absolut ausreichend.
Grundsätzlich spricht nichts gegen dein Vorhaben.
Im Detail wird man dann mit zunehmender Erfahrung Konzepte anpassen und verändern.
Bezüglich Klassen in eingebundenen Access Dateien:
Das hat auch diverse Vorteile.
Da es in Access keine Konstruktoren gibt, kann man dann Factory Funktionen einsetzen.
Man kann genau steuern ob Klassen im Frontend mittels New Operator, Factory Funktionen, beiden Methoden oder gar nicht erstellt werden können.
Abgesehen davon - das Friend Schlüsselwort kann man nur in solchen Konstruktionen einsetzen und das bietet dann eine Reihe zusätzlicher Möglichkeiten, wenn Klassengruppen zusammenwirken.
LG Markus
Zitat von: markus888 am Oktober 24, 2018, 08:45:20
Grundsätzlich spricht nichts gegen dein Vorhaben.
Man kann genau steuern ob Klassen im Frontend mittels New Operator, Factory Funktionen, beiden Methoden oder gar nicht erstellt werden können.
Abgesehen davon - das Friend Schlüsselwort kann man nur in solchen Konstruktionen einsetzen und das bietet dann eine Reihe zusätzlicher Möglichkeiten, wenn Klassengruppen zusammenwirken.
LG Markus
Da hab ich meinen Meister gefunden. Keine Idee, wovon Du sprichst. Hört sich aber so an, als dass ich es wissen will. Einen Vorschlag, wo ich mich da einlesen kann?
Ich hab so'n Buch mit >1000 Seiten, da werde ich aber bestimmt nichts finden, sonst wäre ich schon drüber gestolpert.
Ich habe soeben folgendes versucht:
Expernes Projekt einbinden: OK
Ein Klassenmodul aus dem fremden Projekt deklarieren: FAILED!
Hat einer eine Idee, ob/wie man sowas machen kann?
Lege ein Modul in der Library-DB an und erstelle eine Funktion, die eine Klassen-Instanz erzeugt und aus jedem Frontend, das diese Library-DB verknüpft, aufgerufen werden kann.
Public Function CreateMyClass() As MyClass
Set CreateMyClass = New MyClass
'ggf. weiter über Argumente initialisieren
End Function
Zitat von: Milvus am Oktober 24, 2018, 18:58:17
Einen Vorschlag, wo ich mich da einlesen kann?
Nein, aber durch das Forum, das www bzw. eigenes Überlegen sollten sich alle Punkte klären lassen.
Was verstehst du denn konkret nicht?
Um Klassen aus externen Bibliotheken nutzen zu können sollte man die VB Attribute entsprechend ändern.
Bei der Standard Einstellung kann man kein Objekt einer Klasse erstellen.
Dazu erstellst du eine neue Klasse und exportierst sie in ein Textfile.
Das geht per VBA mittels der versteckten Application.SaveAsText Methode - Import dann mittels LoadFromText. Oder eben mittels Datei importieren/exportieren.
Dann musst du die Attribute ändern und die Datei wieder importieren.
Im Prinzip sind die Namen der Attribute schon selbsterklärend.
Ansonsten findet sich alles im www, bzw. teste einfach selbst und schau wie weit du selbst kommst.
Dazu möchte ich noch anfügen, dass man zwar alle Attribute ändern kann, Access beim importieren aber manche Änderungen wieder zurücksetzt. Du wirst also nur durch erneutes exportieren erfahren wie die Einstellungen tatsächlich aussehen.
Lachtaube hat jetzt mal ein Beispiel für eine Factory Methode geliefert.
Zu etwa 60% übergebe ich an eine solche Methode auch Argumente um das Objekt zu initialisieren.
Die Sub erstelle ich nicht Public sondern mit Friend.
Dann kann das Objekt tatsächlich nur über diese Factory Funktion initialisiert werden.
Das geht aber auch ohne Factory Funktion, indem man über die Attribute gleich festlegt, dass ein Objekt erzeugt werden darf. Das kann man nach belieben einsetzen.
Viel Erfolg. Markus
Zitat von: Lachtaube am Oktober 25, 2018, 12:35:57
Lege ein Modul in der Library-DB an und erstelle eine Funktion, die eine Klassen-Instanz erzeugt und aus jedem Frontend, das diese Library-DB verknüpft, aufgerufen werden kann.
Public Function CreateMyClass() As MyClass
Set CreateMyClass = New MyClass
'ggf. weiter über Argumente initialisieren
End Function
Perfekt, ja bestätige läuft. Super, herzliches Dankeschön! :D
Hat jemand Erfahrung mit der Perfomance, wenn >30 Forntends darauf zugreifen? Also alle auf das gleiche Projekt in der gleichen Datei verweisen.
Ich würder erwarten, dass das keine Probleme macht, da ich nur Klassenmodule einbinen will und die dienen ja nach Literatur nur als Vorlage für das jew. Objekt, welches dann ja in dem jew. Frontend erzeugt wird (und nicht im eingebundenen Projekt).
Hi Marcus,
ich glaube das geht schon weiter als das Einbinden eines VBA-Projekts.
Aber das passt ganz gut in mein Konzept. Ich werde erst mal einige Klassenmodule sammeln und die zentral in einem Projekt zur Verfügung stellen. Dann glaube ich, ist der Schritt in eine echte Bibliothek nicht mehr so groß.
Du sprichts von einer "echten" Klassenbibliothek nehme ich an?
Theoretisch sollte keine Behinderung auftreten, wenn mehrere Anwender die Bibliothek parallel nutzen-denn der Code wird ja im jeweiligen Frontend ausgeführt. Einen Mehrwert einer zusätzlichen Bibliothek-Datenbank gegenüber zentralem Code im Frontend sehe ich jedoch nicht. Im Mehrbeutzerbetrieb müsste das Ding ja entweder auf einem Netzwerk-Share liegen oder parallel mit dem Frontend verteilt werden.
Zitat von: Lachtaube am Oktober 26, 2018, 22:39:08
Einen Mehrwert einer zusätzlichen Bibliothek-Datenbank gegenüber zentralem Code im Frontend sehe ich jedoch nicht. Im Mehrbeutzerbetrieb müsste das Ding ja entweder auf einem Netzwerk-Share liegen oder parallel mit dem Frontend verteilt werden.
Es gibt unterschiedliche Frontends und der Code soll nur einmal gepflegt werden. Das ist der Sinn dahinter. Liegt auf dem gleichen Netzwerk, wie die restlichen Frontends auch.
Zitat von: Milvus am Oktober 26, 2018, 20:11:43Du sprichts von einer "echten" Klassenbibliothek nehme ich an?
Es geht um Klassenmodule.
Bei einem Standard-Modul gibt es nichts zu verändern.
Bin auf ein neues Hindernis gestoßen.
Situation:
Ich habe ca. 20 verschiedene Frontends. Jedes dieser Frontends wird an n (n>1) verschiedene Personen in individuelle Nuterzordner verteilt, als mde-Datei!
Ziel: Für cls-Module soll es nur eine zentrale VB-Projekt-Datei geben, an der "Programmiert" wird. Nun gibt es die Möglichkeit, dass alle Frontends (das werden locker über 100 im tägl. Betrieb) auf diese zentrale Datei einen VB-Verweis haben. Das funktioniert soweit auch im Testbetrieb.
Was ich aber lieber machen würde, wäre, dass bei der Verteilung der Frontends auch die zentrale VB-Projekt-Datei mit verteilt wird (in den gleichen Nutzer-Ordner). Damit das dann funktioniert, muss beim Öffnen der Datei, der VB-Verweise einmalig neu gesetzt werden.
Jetzt zum Problem: Das neu Setzen des Verweises zum VB-Projekt funktioniert zwar bei mdb-Dateien, nicht aber bei einer kompilierten mde-Datei. >:(
Kann mir da jemand helfen, einen Tipp geben?
Zitat von: Milvus am November 02, 2018, 10:17:09Kann mir da jemand helfen, einen Tipp geben?
Deinen Verstand benützen - dann findet sich auch eine Lösung. :)
Zitat von: Milvus am Oktober 26, 2018, 20:11:43
Aber das passt ganz gut in mein Konzept. Ich werde erst mal einige Klassenmodule sammeln und die zentral in einem Projekt zur Verfügung stellen. Dann glaube ich, ist der Schritt in eine echte Bibliothek nicht mehr so groß.
An Deiner Stelle würde ich mir wirklich überlegen, ob es sich nicht lohnen würde, sich in Plattformen einzuarbeiten, welche für solche mehrschichtigen Anwendungen konzipiert sind. Ich würde das, was Du vorhast, nicht tun, weil man da irgendwann in den Wald kommt und dann das ganze Access-mdb-mde-Knäuel in die Tonne wandern muß und monatelanges Frickeln dann für die Katz war. Google mal nach "dll hell" und "dependency hell".
Hallo!
Zuerst zur eingebundenen "Bibliothek":
Du könntest die mde-Bibliothek als Add-In (mda/accda) einbinden, dann muss sie nicht als Verweis gesetzt sein. (Für die Entwicklung würde ich den Verweise schon nutzen, damit Intellisense zur Verfügung steht.)
Als Bibliothek könntest du aber auch eine COM-dll verwenden, die du mit .net schreibst.
Eine andere Variante ist der Umweg über eine "Starter-Anwendung" als mdb/accdb, die 2 mde-Biblitheken (eigentliche Anwendung und Bibliothek) nutzt. In einem AEK-Vortrag von Paul Rohorzka ist dieses Konzept erklärt.
Weiters:
Ist das Neusetzen des Pfades einer Bibliotheksdatei überhaupt notwendig, wenn du die Bibliotheks-mde im Anwendungsverzeichnis hast. Ich dachte, Access stellt das dann selbst um.
Nun zu der Variante, die ich in meinen Anwendungen verwende:
Jede Anwendung enthält alle notwendigen Codemodule. In diesem Code sind auch die wiederverwendbaren Module, welche automatisiert aktualisiert werden, falls ich die aktuelle Version in der jeweiligen Anwendung haben will. Verbessere ich in einer meiner Anwendung eines dieser wiederverwendbaren Codemodule, dann wird es aus dieser Anwendung in ein Repository eine Quellcodeverwaltung exportiert und kann (nach Tests) in den anderen Anwendungen wieder importiert werden.
Akutalisierungen gibt es bei dieser Variante natürlich nur durch ein Update der Anwendung. Das kann man als Nachteil aber auch als Vorteil betrachten.
mfg
Josef
Info:
Ich habe eine Lösung im gefunden. Mittels Application.run kann eine Funktion in einem allgemeinen Modul der externen Datei gestartet werden, welche wiederum das Object des Klassenmoduls der externen Datei bildet und in der aufgerufenen Datei zur Verfügung steht.
Zumindest interpretiere ich den Ablauf so.
Zitat von: Wurliwurm am November 09, 2018, 14:58:35
An Deiner Stelle würde ich mir wirklich überlegen, ob es sich nicht lohnen würde, sich in Plattformen einzuarbeiten, welche für solche mehrschichtigen Anwendungen konzipiert sind. Ich würde das, was Du vorhast, nicht tun, weil man da irgendwann in den Wald kommt und dann das ganze Access-mdb-mde-Knäuel in die Tonne wandern muß und monatelanges Frickeln dann für die Katz war. Google mal nach "dll hell" und "dependency hell".
Geht es um den Übergang von Klassenmodulen in eine dll oder den Ansatz eines zentralen Projekts generell (vermute ersteres)?
Das zentrale Projekt verschlankt erst mal das ganze Zeugs, da es nur einmal existiert. SO zumindest mein Ziel.
Zitat von: Milvus am November 14, 2018, 13:07:37
Zitat von: Wurliwurm am November 09, 2018, 14:58:35
An Deiner Stelle würde ich mir wirklich überlegen, ob es sich nicht lohnen würde, sich in Plattformen einzuarbeiten, welche für solche mehrschichtigen Anwendungen konzipiert sind. Ich würde das, was Du vorhast, nicht tun, weil man da irgendwann in den Wald kommt und dann das ganze Access-mdb-mde-Knäuel in die Tonne wandern muß und monatelanges Frickeln dann für die Katz war. Google mal nach "dll hell" und "dependency hell".
Geht es um den Übergang von Klassenmodulen in eine dll oder den Ansatz eines zentralen Projekts generell (vermute ersteres)?
Ob die Bibliothek als VB oder DLL vorliegt, macht prinzipiell keinen großen Unterschied in Bezug zu dem, was ich meine.
Der Unterschied zwischen einer guten verteilten Anwendung und Deiner Lösung ist, daß man bei ersterer Schnittstellen definieren kann und außerdem eine Versionskontrolle hat. Anschaulich:
Wenn der Client ein Objekt vom Typ XY von der zentralen Instanz haben will um darauf Methoden aufzurufen, wird zuerst eine Schnittstelle vom Typ IF_XY definiert mit dem ganzen ("vertraglich vereinbarten") Methoden. Die zentrale Instanz führt eine Registry, reagiert auf die Abfrage des Clients in der Registry nach Interface IF_XY und gibt ein passendes Objekt zurück. Vorteil ist, daß die zentrale Instanz jederzeit die interne Implementierung ändern kann, ohne daß es Änderungsbedarf bei den Clients gibt.
Bei Deiner Lösung sehe ich die Gefahr, daß bei Änderung ständig sowohl die Clients als auch das Programmrepository geändert werden müssen. Und daß es keine Kontrolle darüber gibt, wenn ein Client nicht (mehr) zur Repositorybibliothek passt. Es crasht dann immer erst zur Laufzeit.
Im Ergebnis mußt Du vieles per Hand nachprogrammieren (wie die Verlinkung der Bibliotheken in den Clients), was es alles schon fertig gibt und wo viele Mannjahre Entwicklung dafür investiert wurden.
Zitat von: Milvus am November 02, 2018, 10:17:09
Jetzt zum Problem: Das neu Setzen des Verweises zum VB-Projekt funktioniert zwar bei mdb-Dateien, nicht aber bei einer kompilierten mde-Datei.
Ich hätte jetzt nicht geglaubt, dass diese Kleinigkeit zu so einem Problem wird.
Wenn du eine MDE in eine MDE einbinden willst, kannst du den Pfad der eingebundenen Datei nicht mehr ändern.
Ergo musst also dafür sorgen, dass am Entwicklungsrechner und am Client für die MDE mit den Funktionen der selbe Pfad verwendet wird.
Die Datei ins Netzwerk zu legen, halte ich für keine gute Idee.
Da sollte man an die Folgen bei Änderungen denken.
Wie du aber siehst ändern Programmierer ihre Ansichten im laufe der Zeit, was verschiedene Themen betrifft.
Aus meiner Sicht hat jede Vorgehensweise bestimmte Vorteile, und man soll einfach immer das passende nutzen.
Ich persönliche lege in die eingebundene Datei nur Methoden und Klassen für absolut allgemeine Funktionen rein die ich in jeder DB benötige und mit dadurch mit einem Schlag zur Verfügung stehen. Vor allem für meine viele Test DBs ist das ein großer Vorteil.
Ich mache das jetzt schon einige Zeit so.
Die ganzen Bedenken von Wurliwurm kann ich zwar nachvollziehen - sind aber kein Problem so lange man sich an gewisse Prinzipien hält.
Da kann man dann natürlich nicht einfach die Schnittstelle eines Codes ändern.
Es muss dann halt wie bei jeder Software "Abwärtskompatibilität" gesichert sein.
Gruß Markus
Hallo!
ZitatWenn du eine MDE in eine MDE einbinden willst, kannst du den Pfad der eingebundenen Datei nicht mehr ändern.
Ergo musst also dafür sorgen, dass am Entwicklungsrechner und am Client für die MDE mit den Funktionen der selbe Pfad verwendet wird.
Wenn die Bibliothek-MDE im gleichen Verzeichnis (oder darunter) liegt, muss die Anwendung bzw. Bibliothek nicht im gleichen Ort wie auf dem Entwicklungsrechner liegen.
Der Nachteil bei einer mde-Anwendung mit einer verknüpften mde-Bibilothek ist, dass eine neue Version dieser Biblithek nicht mehr kompatibel zur alten Version ist und somit eine Neuerstellung der mde-Anwendung erforderlich wird. => Wird in der mde-Biblothek eine Funktion verbressert, ohne die Schnittstellen zu ändern, muss trotzdem die Anwendung neu verteilt werden. Daher nehme ich lieber gleich alle erforderlichen Code-Module in die Anwendung auf. Dann weiß ich wenigstens, das das zusammenpasst. ;)
Bei einer eingebundenen COM-dll muss die Anwendung nicht neu kompliert werden, wenn das Interface (inkl. GUID-Kennungen) von der alten Version unverändert bleiben.
mfg
Josef
Zitat von: Josef P. am November 14, 2018, 21:48:33
Wenn die Bibliothek-MDE im gleichen Verzeichnis (oder darunter) liegt, muss die Anwendung bzw. Bibliothek nicht im gleichen Ort wie auf dem Entwicklungsrechner liegen.
Das wäre auf jeden Fall eine Erleichterung.
Muss ich mal testen.
Ich habe aber auch mit dem fixen Ordner kein Problem.
Zitat...Neuerstellung der mde-Anwendung erforderlich wird.
Ich weiß - ein Nachteil.
Es müssen dann beide Dateien neu erstellt werden.
Sollten also bei einem User mehrere Frontends die Datei eingebunden haben, müssen auch alle anderen Frontends neu erstellt werden. ;D
Sollte man so arbeiten, ist man also gut beraten dass per Code erledigen zu lassen. Genauso die Updates beim User.
Bei den Updates müssen dann auch nach alle betroffenen Frontends geschlossen sein. Alles sehr mühsam.
Ich würde mir so was gar nicht anfangen. ;D
Zitat von: markus888 am November 14, 2018, 18:09:13
Ich persönliche lege in die eingebundene Datei nur Methoden und Klassen für absolut allgemeine Funktionen rein die ich in jeder DB benötige und mit dadurch mit einem Schlag zur Verfügung stehen. Vor allem für meine viele Test DBs ist das ein großer Vorteil.
Merci, exakt so!
Gebaut ist das Teil (geerbt) prozedural (Schachteln ohne Ende und das Modulüberbgreifend. Dann sind die Strukturen in unterschiedlichen Frontends (die unterschiedlichen Zwecken diesenen) nachgebaut und zu ca. 70% identisch). D.h. die beschriebene Situation liegt hier eigentlich schon vor. :(
Ich arbeite vorzugsweise mit cls-Modulen, bzw. will die Menge dieser ausbauen. Mein Ziel ist ja genau das, aus dem Wald rauszukommen (zumindest ein Stück weit). Von einer echten Bibliothek sind wir weit entfernt und ich hab schon Mühe, die cls durchzukämpfen. Aber nicht nur das, ich arbeite strickt modular, d.h. ich hab was, das kopiere ich irgendwo rein und das läuft, Punkt! So nutze ich nun z.B. Formulare, die in mehrere Anwendungen gebraucht werden und halte die identisch, diese wiederum nutzen die Libary. D.h., ich kopier ein Formular irgendwo rein und es läuft!
Also ich habe jetzt jedenfalls eine positive Erfahrung: Ich habe eine cls-Libary gebaut, die bei der Verteilung mit in das gleiche Verzeichnis gelegt wird. Aufruf dann der cls über Public Functions über Application run ohne direkren Verweis!
Zitat von: Milvus am November 16, 2018, 16:01:16
Also ich habe jetzt jedenfalls eine positive Erfahrung: Ich habe eine cls-Libary gebaut, die bei der Verteilung mit in das gleiche Verzeichnis gelegt wird. Aufruf dann der cls über Public Functions über Application run ohne direkren Verweis!
Das ist (aus meiner Sicht) die schlechtest mögliche Variante.
Schlechte Performance, ohne die Möglichkeit für den Compiler zu prüfen, Error Handling problematisch.
Run bzw. CallByName sollte man wirklich nur für absolute Notfälle verwenden.
LG M
Hallo!
Auch wenn ich selbst nicht diese Variante verwenden würde, finde ich die Vorgehensweise über ein per VBA aufgerufenes Add-In nicht so kiritisch.
Es ist zumindest bei einer Access-Bibliothek eine Möglichkeit die Bibliothek auszutauschen, ohne die Anwendung (mde) austauschen zu müssen.
Man muss bei mehreren Anwendungen, die diese Bibliothek verwenden, aber sehr sorgfältig prüfen, dass keine Schnittstellenverletzungen gemacht werden.
ZitatSchlechte Performance, ...
Das muss meiner Meinung nach nicht unbedingt sein. Man könnte einmal über Application.Run eine Instanz einer Klasse holen, mit der man dann für alle anderen Klassen aus der Bibliothek Instanzen erstellen kann.
Der Earlybinding vs. Latebinding-Geschwindigkeitsunterschied besteht natürlich. Der dürfte aber vernachlässigbar (vermutlich gar nicht messbar) sein.
Zitat... ohne die Möglichkeit für den Compiler zu prüfen, ...
Zur Entwicklungszeit könnte man mit Verweis auf die Bibliothek arbeiten und diesen erst vor Auslieferung auf die "Add-In"-Technik umstellen.
ZitatError Handling problematisch.
Fehler sollten eigentlich schon nach oben weitergereicht werden.
ZitatRun bzw. CallByName sollte man wirklich nur für absolute Notfälle verwenden.
Da gilt wie immer: Wenn man weiß, was man tut, kann man vieles machen, auch wenn es für "Anfänger" nicht empfehlenswert ist. ;)
@Milvus:
Verwendest du für deinen Code eine Quellcodeverwaltung bzw. hast dich damit schon einmal beschäftigt?
Damit kann man nämlich wiederverwendbaren Code sehr gut verwalten und in die Anwendungen integrieren.
Wenn man dann für den wiederverwendbaren Code automatisierte Tests gestaltet, können auch mögliche Schnittstellenprobleme u. ä. frühzeitig erkannt werden.
mfg
Josef
@Josef
schließen Add-Ins nicht die Nutzung einer Access-Runtime-Umgebung aus?
Ich integriere bis auf wenige Ausnahmen auch immer den kompletten Code ins Frontendend. Ausnahmen sind komplexe oder zeitkritische Methoden, die sich in VBA nur schwierig realisieren lassen. Dafür verwende ich vorzugsweise klassische DLLs, die allerhöchstens als externe Abhängigkeit die auf allen Windows-Rechnern installierte msvcrt.dll aufweisen.
Hallo!
Zitatschließen Add-Ins nicht die Nutzung einer Access-Runtime-Umgebung aus?
Ich bin nicht sicher, ob Application.Run mit einer Access-Runtime-Version läuft, da ich das nur für Entwickler-Aufrufe verwende.
ZitatIch integriere bis auf wenige Ausnahmen auch immer den kompletten Code ins Frontendend.
So mache ich das auch. Die Ausnahmen sind allerdings auch keine Access-Bibliotheken sondern COM-dlls, welche ich mit C# erstelle.
Das Einspielen des wiederverwendbaren Code sieht bei mir so aus:
http://access-codelib.net/videos/ACLib-Import-Wizard/neue-anwendung-erstellen/neue-anwendung-erstellen.mp4
mfg
Josef
@Josef,
ich war wohl unpräzise:
Run und CallbyName brauchen ein vielfaches der Zeit wie direkte Aufrufe.
Run gibt keinen Error weiter.
Diese Punkte sind für mich aber nur bei einfachen Prozeduren und Funktionen von Bedeutung.
Die machen bei mir aber sicher 60% aus.
Bei 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.
Ein absolutes NO GO.
Im Vergleich zum direkten einbinden eine ganze Menge Nachteile, gegenüber praktisch Zero Vorteilen.
Keine gute Bilanz.
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 (http://www.vbforums.com/showthread.php?796881-VB6-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.
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
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.
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?
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.
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?
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.
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.
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
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.
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
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.!
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.
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 (https://web.archive.org/web/20030314223111/http://smsconsulting.spb.ru:80/shamil_s/demos/pages/treestruct1.htm) von Shamil Salakhetdinov nachsehen. Nur Open- und Load-Event benötigen einen proreduralen Ansatz, womit sich aber gut leben lässt.
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. ;)
Zitat von: Lachtaube am November 17, 2018, 09:55:43Ausnahmen sind komplexe oder zeitkritische Methoden, die sich in VBA nur schwierig realisieren lassen. Dafür verwende ich vorzugsweise klassische DLLs, die allerhöchstens als externe Abhängigkeit die auf allen Windows-Rechnern installierte msvcrt.dll aufweisen.
Ich möchte das Thema noch mal aufgreifen und mal etwas mit DLL experimentieren.
Ich frage mich ob besser c++ oder Delphi/Pascal, oder ??
Womit machst du sie?
Kann wer grundsätzliche Tipps zu möglichen Plattformvorteilen nennen - wenn es um VBA im Hintergrund geht.
Vor Jahren habe ich mit C bereits erste Erfahrung gemacht - hätte also C++ genommen.
LG Markus
Zitat von: markus888 am November 28, 2018, 10:16:25
Ich möchte das Thema noch mal aufgreifen und mal etwas mit DLL experimentieren.
Ich frage mich ob besser c++ oder Delphi/Pascal, oder ??
Die erste Frage sollte sein:
COM oder WinAPI?Wenn du nur einzelne Funktionen aus einer DLL aufrufen willst, dann ist WinAPI (Declare...) ausreichend und bringt den geringsten Overhead bei der Distribution einer solchen Anwendung mit sich.
Komplexere Objekte aus einer DLL kann man (
theoretisch!) auf diesem Weg auch nutzen, aber die extrem gesteigerte Komplexität der Anbindung aus VBA verbietet diesen Ansatz faktisch. In diesem Fall ist eine COM-DLL das Mittel der Wahl.
Mit C++ und Delphi kannst du beide Ansätze implementieren. Delphi/Pascal ist mit VB(A)-Vorkenntnissen aus meiner Sicht wesentlich einfacher zu erlernen als C++. Das ist aber primär eine Frage der individuellen Vorkenntnisse und Vorlieben.
Wenn du in Richtung COM gehen willst, ist aus meiner Sicht eine .Net-DLL die erste Wahl. Mit VB.net hast du eine Sprache, die nah bei VBA liegt. Wenn du C-Nähe bevorzugst, hast du C# zur Auswahl. - Beides erfordert aus meiner Sicht und begrenzten Erfahrung mit C++ wesentlich weniger Einarbeitung als die o.g. Alternativen.
Phillip,
es geht vorerst nur um Funktionen mit Standard Aufrufkonvention.
Da geht es zuerst mal um Performance - auch für die Einbindung als UDF in Abfragen.
VBA Code kann ja noch so gut programmieren - die langsame Ausführung (im Vergleich zu c) ist ja zum Weinen.
Com dll wäre dann ein nächster Schritt.
@Markus,
im Prinzip kann jede Programmiersprache verwendet werden, die 32-Bit DLLs für Windows mit der Calling Convention StdCall erzeugen kann.
Der Aufwand, in C++ allgemein verwendbare DLLs zu schreiben (wenn man von Klassen und Templates Gebrauch macht), ist sehr hoch und IMHO deshalb nicht unbedingt empfehlenswert.
Wenn man ohne Install-Routinen leben will, sollte man beim Entwickeln in C darauf achten, möglichst ohne externe Abhängigkeiten anderer Bibliotheken auszukommen. Ausnahmen stellt die msvcrt.dll dar, die auf jedem Windows vorhanden ist. Nimmst Du aber z.B. das neueste Visual Studio, so muss i.d.R. immer die verwendete Runtime der C-Bibliothek mit vertrieben werden - statischen Linken bläht eine DLL doch sehr stark auf.
Ich verwende häufig den GCC oder hin und wieder auch CLang (einen qualitativen Unterschied zwischen beiden Compilern habe ich nicht unbedingt bemerkt) unter MSYS2 (https://www.msys2.org/) zum Kompilieren. Als Editor setze ich GNU-Emacs ein, der entsprechend eingerichtet, allen PiPaPo für eine C-Entwicklungsumgebung bietet, was man so benötigt. Unter C/C++ Development Environment for Emacs (https://tuhdo.github.io/c-ide.html) gibt es Tipps zur Konfiguration. Wenn Du Versuche mit GCC starten willst, sind die beiden Artikel Building Windows DLLs with MinGW (https://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/) und Advanced MinGW DLL Topics (https://www.transmissionzero.co.uk/computing/advanced-mingw-dll-topics/) vielleicht hilfreich.
Pascal ist vom Sprachumfang her nicht ganz so mächtig wie C - dafür aber im Umgang mit Datentypen etwas sicherer und der Code ist leichter verständlich.
Auch FreeBASIC stellt eine interessante Alternative (nicht nur für DLLs - Objektorientierung ist möglich) dar, ohne eine neue Programmiersprache erlernen zu müssen, weil man hier, wie auch unter C und Pascal konstante Datenstrukturen bereits im Code anlegen kann. Es hat auch ein hervorragendes Manual, das ständig auf dem Laufenden gehalten wird. Aktuelle Versionen stellt Dein Landsmann Stefan Wurzinger unter http://office.mv-lacken.at/jenkins/ (http://office.mv-lacken.at/jenkins/) zur Verfügung.
Wenn man nicht mit Zeigern und Strukturen hantieren will, ist eine das Dot-Net unterstützende Programmiersprache sicherlich auch geeignet. Mir persönlich ist das jedoch zu sehr aufgebläht.
Zitat von: Lachtaube am November 28, 2018, 11:47:42Wenn man nicht mit Zeigern un Strukturen hantieren will
Wow, danke für die vielen Infos.
Und nein, auf die Zeiger möchte ich nicht verzichten. :)
Zitat von: PhilS am November 28, 2018, 10:47:05
Wenn du in Richtung COM gehen willst, ist aus meiner Sicht eine .Net-DLL die erste Wahl. Mit VB.net hast du eine Sprache, die nah bei VBA liegt.
Besten Dank,
habe mir bereits ein Buch besorgt, da gehts im Wesentlichen um ADO.Net. Wenn ich das so lese, vergeht mir die Lust an Access Recordsets.
Wie auch immer, kannst Du evtl. ein Buch empfehlen, das fix das Werkzeug von V-Studio einführt?
Ich würde dann einfach mal ein paar Experimente mit der Com machen. Erste cls hab ich ja schon. Die arbeiten aber mit Verweisen u.A. auf Excel. Da Office ja aber installiert ist, müsste das Einbinden in .Net ja auch nöglich sein, import nennt man das dort glaube ich.
Hallo!
Ein Hinweis aus eigener Erfahrung:
Wenn du an die .net-COM-Klassen Referenzen von Access-/Excel-Objekten übergibst, achte auf das saubere Aufräumen. COM und .net passen nämlich bezüglich Freigeben der Referenz und dem Zerstören der Instanzen gar nicht so gut zusammen. In .net gibt der GC (Garbage collector) z. B. Speicher nicht sofort frei, wenn man es nicht expizit anweist.
Ich hatte bei einem COM-Add-In für den VBA-Editor anfangs Probleme, bis ich den GC soweit hatte, dass alles freigegeben wird und es zu keiner "hängengebliebenen" Access-Anwendung kommt.
Diese Probleme gibt es nur, wenn in VBA erzeugte Instanzen in der .net-COM verwendet werden. Instanzen aus .net-COM-Klassen in VBA verwenden ist kein Problem.
Vieleicht etwas OT (passt auch teilweise zu deinem anderen Thread), aber ich schreib mal meine Meinung zu dem ganzen Vorhaben und den damit aufkommenden Problemen.
Mir kommt vor, für dich gibt es derzeit nur einen Lösungsansatz für deine Problemstellung: alle aktuellen Access-Anwendung als Komponenten zu betrachten, die dann wie Microservies zusammenspielen sollen. Ich trau mich zu behaupten, dass du mit Access damit auf Dauer keine Freude haben wirst und vielleicht sogar Schiffbruch erleiden wirst.
Es ist vieles machbar. Aber nicht alles was machbar ist, muss sinnvoll sein. Access ist für mich ein RAD (Rapid Application Development)-System und keine Entwicklungsumgebung für Komponenten-Modelle.
Mit .net zu programmieren ist für mich schöner als in VBA, da man OOP nutzen kann. Es ist auch nett, wenn man eine .net-COM-dll in Access verwenden kann. (Funktioniert übrigens auch per Late binding der dll inkl. Early binding der Typen für Intellisense ohne Eintrag in der Registry.)
Trotzdem nutze ich die Einbindung von .net-COM nur sehr selten, da es eine zusätzliche Abhängigkeit erzeugt.
Den intensiveren Gebrauch von .net-COM in VBA würde ich nur dann verwenden, wenn Access nur als Prototyp dient und die Anwendung später als .net-Anwendung laufen soll. In so einem Szeanrio wäre es Zeitverschwendung Logik in VBA zu schreiben, wenn man sie später in .net benötigt.
Weiters habe ich den Eindruck, dass du dich noch nicht intensiv mit einer Quellcodeverwaltung auseinander gesetzt hast. Damit wäre das Problem des wiederholt vorkommenden Codes auch behoben, da dann zwar der Code mehrmals verwendet wird, aber trotzdem nur an einer Stelle gewartet werden muss. Es mag dir am Anfang vielleicht umständlich vorkommen, in jeder Anwendung den Code eingebaut zu haben und die wiederverwendbaren Klassen nicht aus eine Bibliothek zu nutzen. In meiner (doch schon etwas längeren ;)) Praxis mit Access finde ich diese Variante - für fix in der Anwendung benötigter Klassen - passender für Access.
mfg
Josef
Zitat von: Josef P. am November 30, 2018, 20:54:26
Weiters habe ich den Eindruck, dass du dich noch nicht intensiv mit einer Quellcodeverwaltung auseinander gesetzt hast. Damit wäre das Problem des wiederholt vorkommenden Codes auch behoben, da dann zwar der Code mehrmals verwendet wird, aber trotzdem nur an einer Stelle gewartet werden muss.
Danke, Einschätzung nicht ganz korrekt. Ich neige sehr stark zum Zentralisieren und Standardisieren und setzte mich sogar explizit damit auseinader. Hab ich im Forum hier und da schon mal erwähnt: Ich habe das Teil geerbt und die Situation ist da und ist wie sie ist. Nachträglich da was zusammen zu führen... keine Chance! Setze mich jetzt seit nem Halben Jahr mit der Lösung auseinander und bin zu dem Schluss gekommen:
Beste Lösung ist, dort wo eine gleichsinnige Funktionalität läuft, diese in Klassenmodulen übertragen und nachträglich verwalten.
Noch mal die Situation:
Es laufen ein Dutzend Frontends. Ein Dutzen Backends. Jedes FE hat Code für sich, der bei gleichen Funktionen zu 70% Deckungsgleich ist. Damit eine Funktion läuft, muss sie 5-20 andere Funktionen benutzen, die wuer über die Modulwelt verteilt sind. Das sind nur die Funktionen.
Datenmodell: Kaum aufgelöst, Tabellen mit > 50 Felden, Referentielle Integrität: Netagiv! Formulare: 100 Controls sind nix. Ein Formular arbeitet nicht für sich alleine, ist abhängig von anderen...
Meine erste Aussage war: Neu aufbauen!
Meine zweite Aussage war: Neu aufbauen!
Meine jeztzige Aussage ist: Neu aufbauen!
Zitat von: Milvus am Dezember 03, 2018, 06:41:35
Ich habe das Teil geerbt und die Situation ist da und ist wie sie ist. Nachträglich da was zusammen zu führen... keine Chance!
Liest sich wie der Klassiker: "Ein big ball of mud" und ein armer Mensch, der sich darum kümmern soll. Ich würde an Deiner Stelle da keine Arbeit mehr reinstecken. Access-VBA ist keine Wunderwaffe für Unternehmensanwendungen! Anstelle dessen Einarbeitung in Plattformen für verteilte Anwendungen. Josef hat es im vorigen Post schon gut beschrieben.
https://de.wikipedia.org/wiki/Big_Ball_of_Mud
@Milvus
ZitatMeine erste Aussage war: Neu aufbauen!
Meine zweite Aussage war: Neu aufbauen!
Meine jetzige Aussage ist: Neu aufbauen!
Falls du Hilfe brauchst bei der Argumentation gegenüber dem
Auftraggeber; - meine Meinung: neu aufbauen!
gruss ekkehard
Zitat von: PhilS am November 28, 2018, 10:47:05
Mit C++ und Delphi kannst du beide Ansätze implementieren.
Ich hab jetzt meine ersten Gehversuche mit c und mit Delphi gemacht.
Bleibe jetzt aber vorerst bei Delphi. Hauptsächlich weil die Standard-Datentypen größtenteil mit den in VBA übereinstimmen
und daher viele Funktionen dazu mitgebracht werden. Grade beim Datum.
Bis auf den BSTR ist alles integriert. Wenn ich aus der DLL Arrays oder String zurückgeben muss, dann erzeuge ich eine Variable in VBA und übergebe diese per Referenz an die dll. In der DLL erzeuge ich dann den String oder das Array, dann sorgt VBA am Schluss automatisch für die Freigabe des Speichers.
Zitat von: PhilSKomplexere Objekte aus einer DLL kann man (theoretisch!) auf diesem Weg auch nutzen, aber die extrem gesteigerte Komplexität der Anbindung aus VBA verbietet diesen Ansatz faktisch. In diesem Fall ist eine COM-DLL das Mittel der Wahl.
Das nächste sind jetzt die COM DLL. Aber ich fürchte es geht mir wie dem Milvus und mir vergeht die Lust an VBA. :(
Phillip, wie hast du das gemeint - komplexere Objekte nutzen.
ist es denn theoretisch möglich in einer DLL Objekte im Speicher zu halten und gezielt wieder freizugeben, oder ist da in jedem Fall eine COM Dll notwendig.
Zitat von: markus888 am Dezember 07, 2018, 20:18:20
Phillip, wie hast du das gemeint - komplexere Objekte nutzen.
ist es denn theoretisch möglich in einer DLL Objekte im Speicher zu halten und gezielt wieder freizugeben, oder ist da in jedem Fall eine COM Dll notwendig.
COM ist ein Standard für die Erstellung/Aktivierung der Objekte, die Ermittlung deren (COM-)Interfaces und deren sauberer Entsorgung aus dem Speicher. VBA baut auf COM auf und somit bildet eine Instanz einer Objektvariable in VBA ein COM-Objekt ab.
Was aber eine DLL intern "bei sich zuhause" macht, ist allein deren Entwickler überlassen. Du kannst also in der DLL ein Objekt erstellen und über eine konventionelle (non-COM) API einen "Zeiger" (oder sonstigen Identifikator) des Objektes nach außen reichen. Wenn du in VBA diesen "Zeiger" speicherst und ihn dann an weitere API-Funktionen übergibst, kann die DLL das in Methodenaufrufe auf dem bestehenden Objekt übersetzen.
Folglich ist es nicht nur theoretisch, sondern auch praktisch (die GDI+ ist ein Beispiel) möglich, ohne COM mit Objekten zu arbeiten.
Es ist nur deutlich komplizierter in der Entwicklung.
Darüber hinaus hast du dir automatisch konzeptionell schon ein halbes Memory-Leak gebaut. Nur der Entwickler kennt den Zusammenhang zwischen dem Objekt-"Zeiger" und dem gezielten Freigeben des Objektes. Es gibt keinen definierten, allgemeingültigen Prozess für die Entsorgung obsoleter Objekte.
Zitat von: PhilS am Dezember 09, 2018, 11:30:01
Es gibt keinen definierten, allgemeingültigen Prozess für die Entsorgung obsoleter Objekte.
Davon wäre ich ausgegangen.
Werde jetzt mal com mit Delphi testen.
Hallo zusammen,
ich habe sehr interessiert Euren Gesprächsverlauf beobachtet. Ich möchte dazu folgenden Tip geben:
Exportiert man die Klasse in ACCDA/ACCDE entsteht eine CLS Datei: Hier ist der VB_Exposed Parameter sichtbar und kann per Textedit geändert werden.
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Test_Klasse"
Attribute VB_GlobalNameSpace = True
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Option Compare Database
Public Sub s_test(ByVal zeile As String)
MsgBox "Jawoll dat klappt" & vbCrLf & zeile & vbCrLf & Application.CurrentProject.FullName
End Sub
Danach kann die Klasse importiert werden und die DB als ACCDE gespeichert werden. Dann den Verweis über durchsuchen im Verweise Dialog.
Danach kann man eine Hauptanwendung wie folgt schreiben:
Option Explicit
Private Kl_test As Test_Klasse
Sub test()
Set Kl_test = Test_Klasse 'late Binding wichtig
Call Kl_test.s_test("Huhu") 'Hier der Zugriff !
End Sub
Ich habe die Dateien in ein Paket gepackt. So ging es bei mir. Late Binding ist wichtig. Mit Early Binding und "New" geht es nicht, hatte ich herausgefunden.
mit netten Grüßen
Oliver
Zitat von: oliver3370 am Dezember 10, 2019, 11:06:44
Ich habe die Dateien in ein Paket gepackt. So ging es bei mir. Late Binding ist wichtig. Mit Early Binding und "New" geht es nicht, hatte ich herausgefunden.
Private Kl_test As Test_Klasse ist aber kein Late Binding! Du bindest ja bereits bei der Deklaration an den konkreten Typ.
Eine Instanzierung mit New sollte ebenfalls funktionieren, wenn du die Attribute wie folgt setzt:
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Zitat von: oliver3370 am Dezember 10, 2019, 11:06:44Mit Early Binding und "New" geht es nicht, hatte ich herausgefunden.
New geht schon.
Du könntest dir ja überlegen wofür die übrigen Attribute da sind.
Um dein Konzept gezielt zu nutzen musst du schon die Bedeutung aller Attribute kennen. ;)
Hallo zusammen,
die Möglichkeit mit ACCDE Programmiercode zu kapseln und objektorientiert in VBA aufzurufen (ok, ohne Vererbung) ist immerhin eine Möglichkeit. Bei ACCDE "soll" der programmierte compilierte Code geschützt und sicher sein. Auf jeden Fall braucht man nicht alles in einer etwaigen anderen Sprache umzuschreiben, sondern kann einfach den alten Klassencode weiter verwenden. Man benötigt keine neuen Tools um DLLs zu erstellen. Hier besteht vielleicht auch eine Hürde. Nicht ganz perfekt, aber ... durchaus verwendbar aus meiner Sicht.
Mit netten Grüßen Oliver
Zitat von: oliver3370 am Dezember 10, 2019, 13:06:05durchaus verwendbar aus meiner Sicht.
Das Einbinden hat auch noch zusätzliche Vorteile.
Das Schlüsselwort Friend für Prozeduren/Properties macht ja nur einen Sinn, wenn sich die Klassen in einem anderen Projekt befinden.
Dadurch kann man Prozeduren/Properties einer Klassen vor dem User/Anwendungsentwickler kapseln.
Da VBA Klassen keine Konstruktoren kennen, kann man via Faktory Funktionen diese so simulieren.