Export von Makros in Excel und Vergleich mit Basis-Makros

gehtnetgibtsnet

Cadet 4th Year
Registriert
März 2019
Beiträge
103
Hallo VBA-Profis,

für häufig genutzte eigene Funktionen habe ich mir ein Verzeichnis erstellt, in welchem ich solche Funktionen bereitstelle. Benötige ich eine solche Funktion nun in einem anderen Projekt, so kann ich diese problemlos aus dem Verzeichnis importieren. Das funktioniert schon seit Jahren problemlos.

Um die Übersicht nicht zu verlieren, habe ich mir nun ein Tool erstellt, dass alle meine XLSM-Files ermittelt, die jeweils darin enthaltenen Makros exportiert und - bei Namensgleichheit - mit der bereitgestellten Version vergleicht. Ist zwar der Name identisch, der Inhalt aber unterschiedlich, wird mir die Möglichkeit angeboten, das ermittelte Makro "per Knopfdruck" auszutauschen.

Problem habe ich, wenn es sich um Formluar-Files handelt, Beim Export werden diese als xxx.frm und xxx.frx gespeichert. Allerdings habe ich festgestellt, dass beim Import eines Formulars in den Code noch zusätzlich eine Leerzeile eingefügt wird. Dadurch wird die exportierte Files 2 Bytes länger. Die zusätzluche Zeile könnte ich bei manueller Arbeitsweise zwar wieder löschen, aber bei einem automatisierten Update ist dies nicht möglich.

Wesentlich mehr Probleme gibt es bei den eigentlichen Formular-Daten (xxx.frx). Obwohl die exportierte File die gleiche Länge hat, wie die einstmals importierte File, gibt es sehr viele Unterschiede an verschiedenen Stellen. Selbst 2 exportierte Files aus verschiedenen Mappen sind unterschiedlich. Trotzdem können diese Formulare problemlos ausgetauscht werden. Hier scheinen temporäre Informationen im Code gespeichert zu sein; für mich ist deshalb ein Vergleich nicht möglich.

Meine Frage: hat sich schon jemand mit diesen Problemen beschäftigt? Und ggf. eine Lösung dafür gefunden?
 
Ich baue gerade einen Dokumentengenerator in Word, der Userforms und Module aus verschiedenen Dokumenten importiert und das funktioniert soweit gut. Ob da zusätzliche Zeilen eingefügt werden, weiß ich nicht, weil das für den Generator irrelevant ist. Was genau ist denn das Problem? Ich hab es leider nicht genau verstanden. Die .frx Datei wird glaub ich garnicht benötigt (bin mir aber gerade nicht 100% sicher)
 
Hallo 7HOMAS,

Danke für Deine Antwort.

Mein Problem ist, dass ich nicht feststellen kann, ob das in einer "gefundenen" Mappe enthaltene Makro (inkl. Formular) identisch mit meiner Basis-Version ist. Damit verbunden ist die Frage, ob die Basis-Version eingesetzt werden soll.

Die frx-File ist das eigentliche Formular, während die frm-File der Code ist. Es ist also durchaus denkbar, dass am Formular eine Änderung vorgenommen wurde, nicht jedoch am Code. Deshalb ist ein Austausch sinnvoll, wenn sich mind. eine der beiden Komponenten verändert hat.

Ich hoffe, dass es nun verständlich ist.
 
Woran machst du fest ob es identisch ist? Daran ob der Code exakt gleich ist oder gibt es andere Merkmale?
 
Hallo 7HOMAS,

nur daran, dass beide Files 100% identisch sind.
 
Wenn es die gleichen Dateien sind, wäre zB. die MD5 Checksumme gleich. Alternativ könntest du das Codemodul öffnen und die Zeilen vergleichen. Wenn die Forms gleich sein sollen kannst du dort auch die Controls durchlaufen und auf verschiedene Eigenschaften prüfen.

Davon abgesehen, warum erstellst du dir nicht diese Funktionen als verschiedene AddIns und bindest diese dann ein. Das sind dann alles Referenzen. Wenn du den Code im AddIn anpasst ist der dann überall verfügbar.
 
Hallo 7H0M45. Sorry, dass ich das bisher immer falsch geschrieben habe; das Hirn war weiter als die Augen!!

Zum Thema. Mein Problem ist nicht: "wie stelle ich fest, ob zwei Files identisch sind". Mein Problem ist, dass durch den Import eine zusätzliche Zeile in den Code eingefügt wird. Dadurch ist diese File nach einem temporären Export nicht mehr identisch mit der Original-File. Bei den FRX-Files (also dem eigentlichen Formular) habe ich die Vermutung, dass in den Daten auch temporäre Informationen enthalten sind. Auch hier bringt ein Vergleich (mit welcher Methode auch immer) das Ergebnis: nicht gleich.

Thema AddIns: das hatte ich testweise versucht. Doch es macht wenig Sinn, meine derzeit mehr als 50 Funktionen in jede Mappe über das Addin einzubetten.
 
Mh. Der Inhalt einer *.frm ist in klartext. Unteranderem wird auch der eigene Dateiname in der Datei gespeichert.
Wenn beide Name also uebereinstimmen, ist auch der Hash gleich.

Bei der *.frx ist das leider etwas schwieriger. Keine Ahnung wie man das dekompilieren kann.
Ich vermute, dass der Zeitpunkt des exports mitgespeichert wird.
Damit wird es schwierig.
Was spricht dagegen diese immer zu aktualisieren?
Der Export dauert jetzt ja nicht ewig.


Edit:
Wuerde eine Versionsangabe im Namen deinem Vorhaben in die Quere kommen?
So muesstest du nur noch den Dateinamen vergleichen.
 
Zuletzt bearbeitet:
Hallo Scientist,

Danke für Deine Antwort.

Der Aufbau einer *.frm-File ist mir bekannt. Dumm nur - und diese Aussage treffe ich jetzt zum x. mal -, dass beim Import in eine Arbeitsmappe eine zusätzliche Leerzeile in den Code eingefügt wird.

Das mit der Versions-Nummer wird sehr schwierig: der File-Name in meinem Basis-Verzeichnis ist nicht Bestandteil des importierten Codes. Lediglich der im VB-Editor vergebene Name ist verfügbar. Im Code ist er als OleObjectBlob gespeichert. Wenn ich jetzt anfange, hier noch eine Versions-Nummer einzuführen - und dies bei jeder kleinsten Änderung beachte - müsste ich meine Vergleichslogik (gleicher Name) umstellen. Echt: das lohnt sich nicht.

Bei dieser Art von Files könnte ich mir notfalls einen Vergleich in der Weise vorstellen, dass ich eine Zeile nach den (immer vorhandenen) Header-Lines eine Leerzeile aus der temporär exportierten File lösche. Damit unterstelle ich, dass beim Import einer *.frm-File immer eine Leerzeile eingefügt wird.

VERSION 5.00
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} UF_TimeMsg1
Caption = "Hier dein Titel"
ClientHeight = 1890
ClientLeft = 45
ClientTop = 330
ClientWidth = 4710
OleObjectBlob = "UF_TimeMsg1.frx":0000
StartUpPosition = 1 'Fenstermitte
End
Attribute VB_Name = "UF_TimeMsg1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

Wenn man eine *.fmx-File aus dem Funktions-Ordner (also: die Basis-Version) mit der aus einer Arbeitsmappe exportierten Version derselben *.frm-File vergleicht, so gibt es sehr viele Unterschiede an den unterschiedlichsten Stellen. Das ist nicht nur ein Timestamp. Ich habe in einer solchen File 8 Unterschiede (unterschiedlicher Länge) gefunden; siehe beigefügte PDF-Files. In anderen Vergleichen waren es mehr als 8 Unterschiede.

Mir geht es auch nicht um das Dekompilieren. Wenn ich die Logik dieser Bereiche kennen würde, könnte ich sie beim Vergleichen ausklammern. Die meisten Unterschiede sehe ich im Zusammenhang mit "meinen" Namen und deren Attribute im Formular.

Natürlich wäre mir eine andere Lösung wesentlch lieber, als mich durch den Code durchhangeln zu müssen.

Grundsätzlich einen Update bei den ".fr"-Files (es werden automatisch beide importiert) zu machen halte ich für keinen guten Ansatz; den Update möchte ich nur machen, wenn sich auch tatsächlich etwas verändert hat.
 

Anhänge

  • frx-Vergleich 1.pdf
    26,2 KB · Aufrufe: 334
  • frx-Vergleich 2.pdf
    64,9 KB · Aufrufe: 326
Kannst du vlt. dein Problem mal irgendwie Skizzieren, Beispieldateien oder so liefern. Ich verstehe ehrlich gesagt dein Problem nicht und auch nicht was du mit der .frx datei willst. Wenn du ein Formular irgendwo importierst wird doch immer die .frm Datei verwendet. Und da kannst du zur Not automatisiert den Code vergleichen. Wenn dir irgendwo noch Zeilen eingefügt werden, dann berücksichtigst du das halt im Algorithmus, wobei mir zumindest noch nicht aufgefallen ist, dass soetwas passiert.
 
Die Zeile wird bei mir nur beim Export hinzugefuegt, wenn ich auch die letzte Zeile bearbeite (sowohl bei *.frm, als auch bei *.bas).
Ansonsten bleibt es bei einer leeren Zeile.
Wenn du also Leerzeilen am Ende vermeidest bzw. diese nicht bearbeitest, bleibt es bei einer automatisch hinzugefuegten leeren Zeile.

Bei meinem ersten Test hatte ich keine Aenderung durchgefuehrt und bei den *.frx haben sich nur zwei zusammenhaengende Bereiche veraendert (einfache UserForm mit einem Element).
Einmal der Bereich wie bei dir in Datei "frx-Vergleich 1.pdf".
Bei weiteren Tests habe ich aber jetzt gesehen, dass der/die weiteren Bereiche dann doch staerker schwanken.

Auf Basis der exportierten Datei wird das so wohl nichts bzw. jedenfalls wird es komplizierter und man muss erst mal schauen, was sich fuer Infos aendern.
 
Hallo Scientist,

importiere doch einmal eine Userform. Dann wirst Du feststellen, dass beim Import eine zusätzliche Zeile vor dem eigentlichen Code eingefügt wird. Dass beim Export eine Zeile eingefügt wird, habe ich bisher nicht festgestellt.

Dass mein Problem nicht einfach zu lösen ist, habe ich erwartet. Deswegen steht in meiner ersten Fragestellung:

gehtnetgibtsnet schrieb:
hat sich schon jemand mit diesen Problemen beschäftigt? Und ggf. eine Lösung dafür gefunden?
 
  • Gefällt mir
Reaktionen: Scientist
Das Pferd von hinten aufzäumen?

Der Vorschlag den Exporten signifikante Namen zu geben wäre der erste Schritt.

Der zweite wäre zu fragen wie viele… Splitter… es sind mit denen du hantierst.
Vergleichen wir mal z.B. mit Programmen und WIN, dort werden DLLs gehandhabt in denen ganze Sätze von Codeblöcken geschleppt werden von denen teilweise nur wenige benutzt werden.
Stelle also Module [in einer Lager-Mappe] zusammen die du (mit sprechenden Namen) exportierst. Und wenn du an der Quelle was änderst überspeicherst du (oder fügst ein Datum in den Namen ein).
Importiert wird/werden die Module {und Userforms} die man braucht, und es sind immer die aktuellen.

Die Not, Projekte aus einer (sic) Modulsammlung zu bedienen habe ich nicht, da sind ganze Mappen die Quellen die kopiert und angepasst werden. Aber so wie ich deine Lage verstände wäre nur zu fragen wie groß die Häppchen geschnitten werden müssen. Du kennst bestimmt deine Pappenheimer die du immer brauchst, die könntest du integrieren um lieber Überflüssiges mitzunehmen als herumzustochern (ja, OK, das ginge auch mir gegen die Programmiererehre, aber irgendwann beugt man sich der schnöden Praxis).

CN8
 
Hallo cumulonimbus8,

ich werde einmal über verschiedene Antworten in diesem Thread nachdenken.
 
Werte Leser diesen Threads,

um hinter die Geheimnisse der frx-Files zu gelangen, habe ich noch zwei weitere Test gemacht:

1. in zwei "jungfräuliche" Mappen habe ich jeweils dieselbe Userform importiert. Trotzdem war der Inhalt der exportierten frx-Files unterschiedlich.

2. danach habe ich eine der beiden Mappen kopiert. In die Kopie habe ich zusätzlich ein weiteres Modul eingefügt. Trotzdem war die exportierte frx-File der Kopie identisch mit der aus der "Mutterfile".

Fazit: die erkannten Änderungen am frx-Code geschehen beim Import. Danach wird der Code nicht mehr verändert.

Das wollte ich noch nachtragen.
 
Interessant ...
Wenn ich eine UserForm zwei Mal direkt hintereinander exportiert hatte, waren die Dateien nicht identisch.
 
Hallo Scientist,

Danke für den Hinweis. Ich habe es ebenfalls probiert und muss feststellen: es ist so!

Dabei ist es egal, ob der Export über den VB-Editor oder durch ein Makro gemacht wird.

Bei meinem Export-Versuch mit einem Makro habe ich die Mappe erneut geöffnet und dann alle Makros nochmals exporiert. Ein Vergleich hat mir gezeigt, dass die *.frx-Files aus den beiden Exports unterschiedlich sind (und zwar an den bisher schon bekannten Stellen).

Mein Fazit: ein Vergleich von Basis-frx und Export-frx mit dem Hintergrund, zu erkennen, ob eine Änderung gemacht wurde, ist (derzeit) nicht möglich, es sei denn, dass sich die Länge des Moduls verändert hat.

Für mich und mein Problem bleibt dann nur die Lösung über das Code-Modul frm. Und wenn ich zukünftig eine Änderung an einem meiner (wenigen) Formulare mache, dann sollte ich daran denken, gleichzeitig im Code auch eine Änderung zu machen, damit ich über diese Schiene erkenne, dass sich etwas verändert hat. Und das Problem mit der zusätzlich beim Import eingefügten Leerzeile muss ich durch eigene Logik in den Griff bekommen.

Wie heißt mein Motto? "get net gibts net".
 
Zurück
Oben