Excel VBA - VBA-gesteuerte Manipulation von VBA-Co

Informationen und Beispiele zu den hier genannten Dialog-Elementen:
MsgBox
Bild

Betrifft: Excel VBA - VBA-gesteuerte Manipulation von VBA-Co
von: Harry
Geschrieben am: 31.10.2015 15:38:30

Hallo VBA-Experten,
habe ein Problem mit der VBA-gesteuerten Manipulation von VBA-Code in einem VBA-Modul.
Hierzu habe ich das Problem auf ein möglichst einfaches Beispiel reduziert:
Per VBA-Code verändere ich eine Funktion (erste Änderung).
Der erste Aufruf dieser Funktion liefert dann das erwartete Ergebnis.
Dann verändere ich die Funktion (zweite Änderung).
Der zweite Funktionsaufruf liefert das erste Ergebnis, die zweite Änderung in wird ignoriert.
Was muss ich tun, damit die zweite Änderung berücksichtigt wird?
Muss nach der Änderung eventuell irgendein Update/Refresh erfolgen?
Weitere Hinweise: Das Problem tritt auch bei Excel 2010 auf.
Habe auch mal testweise den Virusscanner deaktiviert - ohne Erfolg.
Grüße und vielen Dank im Voraus!
Harry


Function myTest() As Variant ' wichtig: dies ist die erste Zeile im VBA-Modul!
' diese Zeile wird durch den VBA-Code ersetzt ...
End Function

Sub Start() ' Start-Prozedur
Dim Result As Double: Result = 0

Application.VBE.ActiveCodePane.CodeModule.replaceline 2, "myTest = 2"
MsgBox myTest ' ergibt 2, wie erwartet

' sind an dieser Stelle eventuell weitere Schritte erforderlich? (Update/Recompile)

Application.VBE.ActiveCodePane.CodeModule.replaceline 2, "myTest = 3"
MsgBox myTest ' ergibt 2 anstelle von 3

End Sub

Bild

Betrifft: AW: Excel VBA - VBA-gesteuerte Manipulation von VBA-Co
von: Tino
Geschrieben am: 31.10.2015 16:09:49
Hallo,
ich denke nach dem ersten Aufruf der Funktion ist diese zur Laufzeit gesperrt und
wird erst nach Abschluss aktualisiert.
Wo liegt eigentlich der Sinn in solch einer Aktion?
Gruß Tino

Bild

Betrifft: AW: Excel VBA - VBA-gesteuerte Manipulation von VBA-Co
von: Harry
Geschrieben am: 31.10.2015 19:16:30
Hallo Tino, hallo Luschi,
vielen Dank für die Antwort(en).
Zweck der Funktion myTest: Auswertung eines beliebigen String-Ausdrucks (Parser).
myTest() soll Strings auswerten und das Ergebnis zurückgeben,
z. B. Zahlen
"(2*3)-8*3"
oder z. B. Bool'sche Auswertung (True/False)
"a=1 and b=2"
Es geht mir also nicht darum, die Zahlen durch numerische Vorgaben zu beeinflussen (so wie im Lösungsvorschlag), sondern nur durch den String (der z. B. aus einer Datei stammt).
Würde die Funktion sich also zur Laufzeit aktualisieren lassen, könnte ich darauf verzichten, einen externen Parser einzubinden oder selbst einen zu schreiben.
Gibt es irgendeine Möglichkeit, die Sperre zur Laufzeit aufzuheben bzw. eine programmgesteuerte Aktualisierung zu machen?
Gruß
Harry

Bild

Betrifft: wenn nicht zur Laufzeit, dann danach
von: Tino
Geschrieben am: 31.10.2015 19:42:27
Hallo,
bin mir sicher man könnte das was du machen möchtest bestimmt auch ander lösen.
Dazu kenne ich aber dein vorhaben zu wenig.

Option Explicit
 
Function myTest() As Variant ' wichtig: dies ist die 3. Zeile im VBA-Modul! 
myTest = 3
End Function

Sub Start()
Start_ 0
End Sub

Sub Start_(intIndex%)
Dim Result As Double: Result = 0
   
With Application.VBE.ActiveCodePane.CodeModule
    If intIndex = 0 Then
        .replaceline 4, "myTest = 2"
    ElseIf intIndex = 1 Then
        .replaceline 4, "myTest = 3"
    End If
End With

MsgBox myTest ' ergibt 2, wie erwartet 
If intIndex < 1 Then _
    Application.OnTime Now + TimeSerial(0, 0, 1), "'Start_ 1'"
End Sub
Gruß Tino

Bild

Betrifft: AW: Excel VBA - VBA-gesteuerte Manipulation von VBA-Co
von: Luschi
Geschrieben am: 31.10.2015 16:12:11
Hallo Harry,
Du mußt Vba zwingen das Ergebnis der Funktion neu zu berechnen:


Option Explicit
Function myTest(i As Integer) As Variant ' wichtig: dies ist die erste Zeile im VBA-Modul!
    'Ersetzungszeile
End Function
Sub Start() ' Start-Prozedur
    Dim Result As Double: Result = 0
    Application.VBE.ActiveCodePane.CodeModule.ReplaceLine 4, "myTest = 2 + i"
    MsgBox myTest(0) ' ergibt 2, wie erwartet
    
    ' sind an dieser Stelle eventuell weitere Schritte erforderlich? (Update/Recompile)
    
    Application.VBE.ActiveCodePane.CodeModule.ReplaceLine 4, "myTest = 2 + i"
    MsgBox myTest(1) ' ergibt 2 anstelle von 3
End Sub
Gruß von Luschi
aus klein-Paris
PS: aber ob die Idee überhaupt gut ist, kiann ich mir nicht vorstellen!!!

Bild

Betrifft: mach für mich überhaupt keinen Sinn?! ;-) oT.
von: Tino
Geschrieben am: 31.10.2015 16:21:04


Bild

Betrifft: AW: mach für mich überhaupt keinen Sinn?! ;-) oT.
von: Luschi
Geschrieben am: 31.10.2015 16:27:32
Hallo Tino,
für mich natürlich auch nicht, aber des Menschen Vba-Wille ist sein ???-Himmelreich.
Gruß von Luschi
aus klein-Paris

Bild

Betrifft: die zweite Wiederholung
von: Tino
Geschrieben am: 31.10.2015 16:32:31
Hallo,
ich meine die zweite Zeile
Application.VBE.ActiveCodePane.CodeModule.ReplaceLine 4, "myTest = 2 + i"
ändert die Funktion nicht.

Dim Result As Double: Result = 0
Application.VBE.ActiveCodePane.CodeModule.ReplaceLine 4, "myTest = 2 + i"
MsgBox myTest(0)
MsgBox myTest(1)
Gruß Tino
Gruß Tino

Bild

Betrifft: Das kann nicht so fktionieren, ...
von: Luc:-?
Geschrieben am: 31.10.2015 20:52:17
…Harry,
wie du's dir vorstellst, da hat Tino recht, denn dazu muss neu kompiliert wdn, was aber erst nach Abschluss des 1.Durchlaufs geschieht. Ich hatte Derartiges noch/schon unter Xl9 ausprobiert und dabei festgestellt, dass man die Initialisierung/Änderung einer Prozedur und ihren Aufruf nicht in derselben Prozedur unterbringen kann. Hier reduziert sich das allerdings auf weitere Aufrufe, der 1.akzeptiert die initialisierende Änderung noch. Das so etwas kontraproduktiv ist, merkt man schon daran, dass sich die SubProz nach der 1.Änderung nicht mehr anhalten lässt.
Du benötigst also für jede Änderung einen eigenen Aufruf, zB so:

Option Explicit
Function myTest()   'Fkt m.WechselZeile
    Rem WechselZeile
End Function
   
Sub RufMTS2()   '1.Start-RufProzedur
    Call MyTestStart("myTest", " = 2", 1)
End Sub
   
Sub RufMTS3()   '2.Start-RufProzedur
    Call MyTestStart("myTest", " = 3", 1)
End Sub
Rem parametrierte Start-Prozedur
Sub MyTestStart(ByVal naRelFkt$, ByVal ErgZuweis$, Optional ByVal prozTyp As Long)
    Const relZlVsatz As Long = 1, txProzArt$ = "Sub Function Property", _
          txWxZl$ = vbTab & "Rem WechselZeile"
    Dim Result As Double, relZl As Long, prozArt As String
    prozArt = Split(txProzArt)(prozTyp)
    With Application.VBE.ActiveCodePane.CodeModule
        relZl = .ProcStartLine(naRelFkt, vbext_pk_Proc)
        While InStr(.Lines(relZl, 1), prozArt) = 0: relZl = relZl + 1: Wend
        .ReplaceLine relZl + relZlVsatz, vbTab & naRelFkt & ErgZuweis
        Result = Evaluate(naRelFkt & "()"): MsgBox CStr(Result)
        .ReplaceLine relZl + relZlVsatz, txWxZl
    End With
End Sub
Da ich nicht davon ausgehe, dass das eigentliche Problem so simpel ist, scheint mir Luschis Lösung hier auszuscheiden und eine generelle Feststellung dazu angebrachter.
Allerdings vermute ich, dass der Hintergrund dieser Frage anders aussieht als es den Anschein hat und das eigentliche Problem eines sein könnte, das besser anders gelöst wdn sollte.
Gruß, Luc :-?

Besser informiert mit …

Bild

Betrifft: AW: Excel VBA - VBA-gesteuerte Manipulation von VBA-Co
von: Harry
Geschrieben am: 01.11.2015 13:52:41
Hallo Tino, hallo Luschi,
vielen Dank für die Antwort(en).
Zweck der Funktion myTest: Auswertung eines beliebigen String-Ausdrucks (Parser).
myTest() soll Strings auswerten und das Ergebnis zurückgeben,
z. B. Zahlen
"(2*3)-8*3"
oder z. B. Bool'sche Auswertung (True/False)
"a=1 and b=2"
Es geht mir also nicht darum, die Zahlen durch numerische Vorgaben zu beeinflussen (so wie im Lösungsvorschlag), sondern nur durch den String (der z. B. aus einer Datei stammt).
Würde die Funktion sich also zur Laufzeit aktualisieren lassen, könnte ich darauf verzichten, einen externen Parser einzubinden oder selbst einen zu schreiben.
Da es anscheinend keine Möglichkeit gibt, die Sperre zur Laufzeit aufzuheben bzw. eine programmgesteuerte Aktualisierung zu machen, muss ich einen anderen Weg gehen.
Gruß und vielen Dank!
Harry

Bild

Betrifft: Das hatte ich mir schon beinahe gedacht, ...
von: Luc:-?
Geschrieben am: 01.11.2015 14:18:56
…Harry;
da du es vorziehst, meine umfangreiche AW zu ignorieren, hiermal nur ein Tipp → vbFkt Evaluate (oder benannte Fml mit XLM-Fkt AUSWERTEN).
Auf dieser Basis kann man auch eine kleine UDF schreiben, die im Ggsatz zur XLM-Fkt auch in ZellFmln eingesetzt wdn könnte, allerdings mit FmlText in US-Original-Notation (was hier aber wohl der lokalen deutschen gleich wäre).
Luc :-?

Bild

Betrifft: AW: Das hatte ich mir schon beinahe gedacht, ...
von: Harry
Geschrieben am: 01.11.2015 21:20:07
Hallo Luc :-?,
sorry, habe Deinen umfangreichen Beitrag natürlich auch gesehen u. möchte mich auch bei Dir herzlich dafür bedanken! Die Möglichkeit über Evaluate oder über Excel-Funktionen hatte ich auch schon geprüft aber verworfen, weil ich ursprünglich eine möglichst direkte Kopplung mit dem VBA-Code wollte.
Z. B. sollte beim String mit dem Bool'schen Ausdruck "Fritz = 1 AND Franz = 2" auf die Public-VBA-Variablen "Fritz" und "Franz" zugegriffen werden. Das wäre möglich, falls sich der VBA-Code dynamisch aktualisieren ließe. Die damit verbundenen Möglichkeiten wären absolut großartig.
Sehr wertvoll für mich ist die Information von Euch, dass ein ReCompile der gleichen Funktion zur Laufzeit nicht mehrfach möglich ist. D. h. ich kann die VBA-Code-Manipulation als Lösungsoption ausschließen u. meine Energie auf andere Möglichkeiten fokussieren.
Nochmals herzlichen Dank!
Harry

Bild

Betrifft: Wenn du 'Evaluate' nicht willst, ...
von: Luc:-?
Geschrieben am: 02.11.2015 02:31:42
…Harry,
musst du das alles selber pgmieren. Ich habe das vor ca 12 Jahren mal gemacht und die daraus resultierende FktsProzedur (UDF) ist bis heute meine mit Abstand längste, musste wg LängenÜberschreitung auch noch geteilt wdn.
Die 1.Versuche in dieser Richtung, nur auf Basis von Xl-Standard­Operatoren, waren allerdings deutlich kürzer. Dazu muss der zu berechnende Text durchgegangen, Zahlen, Namen und Operatoren isoliert und richtig zueinander in Beziehung gesetzt wdn. Evaluate bietet dagegen den Vorteil, eine Notation wie in einer engl Fml benutzen zu können, wobei man dann natürlich keine VBA-Schreibweise mit bspw And als Operator benutzen kann. Pgmierst du das selbst, kannst du natürlich machen, was du willst, nur nicht so wie von dir angedacht.
Mit einem eigenen Programm könnte das evtl so wie mit der o.g. UDF aussehen:

 ABCDE
1VariablenNamenFmlTextErgebnisZellFml
2alphabetaa<25&b>10ƒ(a=25, b=11)=Falsch⇒T2Form(C2;;alpha;beta)
32511a<25|b>10ƒ(a=25, b=11)=Wahr⇒T2Form(C3;;alpha;beta)

Ich vermute aber, dass das auch nicht deinen Intentionen entspricht. Anders geht's nur so wie in der von dir letztlich ebenfalls verworfenen Variante, die auch nicht mittels Ereignissen in Verbindung mit globalen Zählern zu anderem Arbeiten zu bewegen ist. Man bewegt sich hier wohl in einer „Grauzone“ außerhalb des normalen Verlaufs, deren Variablen nach Abschluss der Operation zurückgesetzt wdn. Die einzige Möglichkeit besteht hier darin, Xl wenigstens in Form einer benannten Konstanten in Anspruch zu nehmen. Deren lfd Erhöhung bleibt nämlich erhalten und kann so zur Grundlage eines ereignis­gesteuerten Mehrfach­Aufrufs der Modifi­kation­sprozedur gemacht wdn.
Ansonsten ist auch mit CallByName eher nichts zu machen, denn hierbei geht's, ähnlich wie bei Run,um vbObjekt- und -Eigenschaften­Namen in Textform, nicht um ganze VBA-Kommando­Zeilen-Texte. Dafür gibt's wohl nichts außer der behandelten Möglichkeit.
Luc :-?

 Bild

Beiträge aus den Excel-Beispielen zum Thema "Excel VBA - VBA-gesteuerte Manipulation von VBA-Co"