Live-Forum - Die aktuellen Beiträge
Datum
Titel
29.03.2024 13:14:12
28.03.2024 21:12:36
28.03.2024 18:31:49
Anzeige
Archiv - Navigation
936to940
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
936to940
936to940
Aktuelles Verzeichnis
Verzeichnis Index
Verzeichnis Index
Übersicht Verzeichnisse
Inhaltsverzeichnis

Lösung zum Problem beim Einfügen von Code (@Alf)

Lösung zum Problem beim Einfügen von Code (@Alf)
04.01.2008 12:00:00
Code
Hallo Alf und die anderen Interessierten,
erst einmal vielen Dank für Eure Hilfestellungen. Es ging um folgendes Problem:
www.herber.de/forum/archiv/936to940/t936319.htm
Ich habe das Problem nach dem Weihnachtsurlaub nun lokalisieren und lösen können.
Eins vorneweg: es ist relativ egal, wie der Code eingefügt wird (zeilenweise, im Ganzen per .AddFromString oder per Export/Import-Funktion). Das Problem liegt am Was wird eingefügt.
Ich arbeite inzwischen (mnit Unterbrechungen wegen Frust) seit November an dem Problem und habe so ziemlich alles ausprobiert. Mit frischen Ideen im neuen Jahr bin ich gestern rangegangen, noch etwas auszuprobieren.
Mir ist zuvor aufgefallen, daß Excel immer beim Einfügen des Quellcodes in das Modul "DieseArbeitsmappe" abstürzt. Da diese Component in der For...Each- Schleife immer zuerst an der Reihe ist, hatte ich die Vermutung, daß dort irgendwelche Referenzen in die anderen Codeteile (die ja zu diesem Zeitpunkt noch fehlen) fehlerhaft sind. Daher habe ich den Code so umgeschrieben daß zuerst das Standardmodul übertragen wird, dann werden die UserForms importiert, dann alle Document-Codemodule und schliesslich der Code von "DieseArbeitsmappe". Mit dem Erfolg, daß das Standardmodul (Modul1) und die UserForms problemlos eingefügt wurden. Jedoch trat der Fehler schliesslich beim Einfügen eines Arbeitsblatt-Codes auf (nicht "DieseArbeitsmappe"). Daher konnte ich schon einmal einiges ausschliessen, speziell, daß "DieseArbeitsmappe" vom VBE irgendwie "speziell" behandelt wird (meine Vermutung mit den Referenzen war damit natürlich auch nicht stichhaltig).
Um auf den Punkt zu kommen: Ich habe schliesslich entschieden, daß es am einzufügenden Code liegen muß und diesen jeweils in Zeilen zerlegt (per Split-Funktion) und mit .InsertLine in einer Schleife eingefügt und konnte nun beim debuggen genau beobachten, wo er aussteigt. Ergebnis: immer bei Prozedur-Signaturen. Durch einen Geistesblitz und vergleich mit dem Code, der in das Standardmodul eingefügt wird, bin ich darauf gekommen, daß es am Schlüsselwort "Private" liegt, und zwar wenn dieses in Ereignisprozeduren auftaucht!!!
Nachdem ich per Replace-Funktion diese Schlüsselwörter herausgefiltert habe, lief der Code auch in der von mir geposteten Variante anstandslos durch. Mein Code war also die ganze Zeit richtig, der Fehler liegt eindeutig beim VBE, ist aber umgehbar. Zumal die "Private"-Statements beim Speichern wieder automatisch eingefügt werden :-)
Ich hoffe, ich kann Leuten mit ähnlichen Problemen (von denen es freilich nicht viele gibt) mit meinem Erguss helfen.
Beste Grüße,
Kolja

10
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Lösung zum Problem beim Einfügen von Code (@Al
04.01.2008 13:45:00
Code
Hallo Kolja
Toll, dass du das Problem gelöst hast!
Ich habe versucht, deinen ominösen VBE-Fehler anhand eines einfachen Beispiels zu provozieren.
Dazu füge ich per Code zwei Ereignisprozeduren in das Codemodul von "Mappe1!Tabelle1" ein.
Den entsprechenden CommandButton habe ich zuvor manuell in das Blatt eingefügt.

Private Sub TryToProvokeVBEError()
' Alfred Ruf 04.01.2008
Dim CM As VBIDE.CodeModule
Dim Text As String
Set CM = Workbooks("Mappe1").VBProject.VBComponents("Tabelle1").CodeModule
CM.DeleteLines 1, CM.CountOfLines
Debug.Assert False
Text = "Option Explicit" & vbCrLf
Text = Text & "Private Sub CommandButton1_Click()" & vbCrLf
Text = Text & "    Debug.Print ""Clicked...""" & vbCrLf
Text = Text & "End Sub" & vbCrLf
Text = Text & "Private Sub Worksheet_SelectionChange(ByVal Target As Range)" & vbCrLf
Text = Text & "    Debug.Print ""SelectionChanged...""" & vbCrLf
Text = Text & "End Sub"
CM.AddFromString Text
End Sub


Ohne dich nerven zu wollen: bei mir stürzt die VBE trotz den "Private"-Statements nicht ab!
Und was hat mein Beispiel bei dir für Auswirkungen?
Gruss, Alf

Anzeige
AW: Lösung zum Problem beim Einfügen von Code (@Al
04.01.2008 14:23:00
Code
Hallo Alf,
tja, das ist allerdings in der Tat seltsam. Vom Prinzip her habe ich das gestern genauso gemacht wie Du in deinem Beispiel, inkl. Absturz an besagter Stelle. Ohne 'Private' gings dann.
Probier mal in deinem Code, ob der Fehler auftritt, wenn Du in "DieseArbeitsmappe" eine Workbook-Ereignisprozedur einfügst. Möglicherweise ist nur hier der Grund für den Absturz im 'Private'-Statement zu suchen und der Absturz im anderen Codemodul bei mir hatte einen anderen Grund (da waren nämlich noch ein Fehlerchen in meiner Einfügeschleife, der teilw. Leerzeilen produziert hat).
Oder der Fehler tritt nur bei meiner speziellen Konfiguration mit den drei Arbeitsmappen auf.
Gruß,
Kolja

Anzeige
AW: Lösung zum Problem beim Einfügen von Code (@Al
04.01.2008 15:07:42
Code
Hallo Kolja
Auch mit der Manipulation des Arbeitsmappen-Codemoduls kann ich den VBE-Absturz nicht provozieren:

Private Sub TryToProvokeVBEError2()
' Alfred Ruf 04.01.2008
Dim CM As VBIDE.CodeModule
Dim Text As String
Set CM = Workbooks("Mappe1").VBProject.VBComponents("DieseArbeitsmappe").CodeModule
CM.DeleteLines 1, CM.CountOfLines
Debug.Assert False
Text = "Option Explicit" & vbCrLf
Text = Text & "Private Sub Workbook_Open()" & vbCrLf
Text = Text & "    Debug.Print ""Opened...""" & vbCrLf
Text = Text & "End Sub" & vbCrLf
CM.AddFromString Text
End Sub


Jagen wir ein Gespenst?
Gruss Alf

Anzeige
AW: Lösung zum Problem beim Einfügen von Code (@Al
04.01.2008 16:56:00
Code
Hi Alf,
um ehrlich zu sein: mir gehen diesbezüglich langsam die Ideen aus. Eins ist sicher: das Code-Einfügen klappt bei mir jetzt mit der beschriebenen Maßnahme.
Dafür habe ich inzwischen (wieder) ein anderes Problem: Ich lösche ja alle UserForms mit
  • .Remove VBComp

  • Das geht auch meistens, nur eine UserForm wiederstrebt sich da. Beim debuggen bleibt sie einfach drin, erst wenn ich den Code stoppe, verschwindet die Komponente aus dem Projekt-Explorer. Alle anderen sind gleich weg. Ich habe mich heute Nachmittag schon wieder totgesucht nach irgendwelchen Referenzierungen auf das Modul - nichts! Die ganzen VBE-/Codemanipulationsgeschichten sind schlichtweg nicht ausgereift meiner Meinung nach.
    Zum ursprünglichen Phänomen fällt mir aber echt nichts mehr ein. Ich vermute dahinter irgendwelche internen Probleme der Entwicklungsumgebung. Veilleicht liegt bei mir eine ganz spezielle Konstellation vor, die evtl. nicht so leicht wie in deinem Probe-Code nachgestellt werden kann.
    Ich würde inzwischen einiges geben, um ein Buch o.ä. über die Interna des VBA-Editors geben :)
    Gruß,
    Kolja

    Anzeige
    AW: Lösung zum Problem beim Einfügen von Code (@Al
    06.01.2008 11:17:30
    Code
    Hallo Kolja,
    mit dem Thema 'Austausch von Vba-Code habe ich mich auch lange beschäftigt und
    den gesammten Vba-Code aus 1 geöffneten xls/xlt-Datei lösche ich so:
    
    Sub CodeKiller(dateiName As String, cBoxWert As Boolean)
    Dim wb As Workbook, n1 As Long, n2 As Long, s As String, _
    t As Integer, ok As Boolean
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Set wb = Workbooks(dateiName)
    For n1 = wb.VBProject.VBComponents.Count To 1 Step -1
    s = wb.VBProject.VBComponents(n1).Name
    t = wb.VBProject.VBComponents(n1).Type
    ok = False
    Select Case t
    Case vbext_ct_Document
    'Klassenmodule von "DieseArbeitsmappe" kann man nicht löschen
    'deshalb alle Code-Zeilen entfernen
    n2 = wb.VBProject.VBComponents(n1).CodeModule.CountOfLines
    If n2 > 0 Then
    wb.VBProject.VBComponents(n1).CodeModule.DeleteLines 1, n2
    End If
    ok = False
    Case vbext_ct_ClassModule, vbext_ct_StdModule
    'Standard- & die anderen Klassenmodule
    ok = True
    Case vbext_ct_MSForm
    'Formulare nur auch Wunsch löschen
    ok = cBoxWert
    End Select
    If ok Then
    wb.VBProject.VBComponents.Remove wb.VBProject.VBComponents(n1)
    End If
    Next n1
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    End Sub
    

    Wie Du siehst, lösche ich die Vba-Componenten per internen Index und das klappt wunderbar. Dieser Code steht in 1 AddIn und hier wird auch das Exportieren und Wiedereinlesen organisiert.
    Gruß von Luschi
    aus klein-Paris

    Anzeige
    AW: Lösung zum Problem beim Einfügen von Code (@Al
    08.01.2008 14:30:00
    Code
    Hallo Luschi,
    danke für dein Posting. Ich habe den Code gerade mal ausprobiert, macht keinen Unterschied bei mir.
    Bei einem bestimmten Formular läuft zwar die Codezeile "destVBComponents.Remove VBComp" durch, aber das Modul ist danach immer noch da. Bei den anderen Formularen funktioniert dies einwandfrei.
    Wenn die Formulare später alle wieder importiert werden, meckert Excel natürlich, daß ein Formular gleichen Names schon vorhanden ist.
    Gruß,
    Kolja

    AW: Lösung zum Problem beim Einfügen von Code (@Al
    08.01.2008 15:14:00
    Code
    Hallo Kolja,
    diese Vba-Code-Zeile 'destVBComponents.Remove VBComp' gibt es in meinem geposteten Thread nicht.
    Gruß von Luschi
    aus klein-Paris

    Anzeige
    AW: Lösung zum Problem beim Einfügen von Code (@Al
    08.01.2008 15:28:54
    Code
    Hallo Luschi,
    Du hast recht. Ich habe da einiges geändert, vielleicht stelle ich noch mal den aktuellen Code ein:
    
    Public Function transferVBACode(source As Masterlist, dest As Masterlist) As Boolean
    Dim returnValue As Boolean
    Dim FName As String
    Dim VBComp As VBIDE.VBComponent
    Dim VBCompInDest As VBIDE.VBComponent
    Dim restoreScreenUpdating As Boolean
    Dim restoreEvents As Boolean
    Dim destWorkbook As Workbook
    Dim sourceWorkbook As Workbook
    Dim destVBComponents As VBComponents
    Dim sourceVBComponents As VBComponents
    Dim destFolderPath As String
    Dim currentComp_Name As String
    Dim currentComp_Type As Integer
    Dim currentComp_Code As String
    Dim newComp As VBComponent
    Dim comp_match As Boolean
    Dim search_ws_ml As Boolean
    Dim i As Integer
    If Application.ScreenUpdating = False Then
    Application.ScreenUpdating = True
    restoreScreenUpdating = True
    End If
    If Application.enableEvents = True Then
    Application.enableEvents = False
    restoreEvents = True
    End If
    ' Projekte wenn nötig entsperren
    If source.VBAProjectProtected = True Then
    returnValue = source.UnlockVBAProject
    If returnValue = False Then
    transferVBACode = False
    Exit Function
    End If
    End If
    If dest.VBAProjectProtected = True Then
    returnValue = dest.UnlockVBAProject
    If returnValue = False Then
    transferVBACode = False
    Exit Function
    End If
    End If
    ' Workbook- und Component-Objekte initialisieren
    Set destWorkbook = dest.GetMLWorkbook
    Set sourceWorkbook = source.GetMLWorkbook
    Set destVBComponents = destWorkbook.VBProject.VBComponents
    Set sourceVBComponents = sourceWorkbook.VBProject.VBComponents
    ' Ordnerpfad der Zieldatei merken
    destFolderPath = dest.GetFolderPath
    ' ### Code der Zieldatei löschen ###
    For Each VBComp In destVBComponents
    With VBComp.CodeModule
    If VBComp.Type  vbext_ct_MSForm Then
    .DeleteLines 1, .CountOfLines
    End If
    If VBComp.Type = vbext_ct_MSForm Or _
    VBComp.Type = vbext_ct_ClassModule Or _
    VBComp.Type = vbext_ct_StdModule Then
    destVBComponents.Remove VBComp
    End If
    End With
    Next VBComp
    ' ### Module kopieren ###
    ' Hier kommt es darauf an, den Code einer Komponente des Templates der richtigen
    ' Komponente der Zieldatei zuzuordnen. Diese Zuordnung kann eindeutig geschehen, wenn
    ' der Name und der Typ beider Komponenten übereinstimmen.
    ' Wird keine Entsprechung in der Zieltabelle gefunden, wird eine Komponente mit diesem
    ' Namen und Typ generiert und der Code dort eingefügt.
    ' !!!Wichtiger Hinweis!!! Wer über folgendes Fragment stolpert:
    '   .AddFromString String:=Replace(currentComp_Code, "Private ", "")
    ' Wird der Code einer Ereignisprozedur mit dem Schlüsselwort "Private" in der Signatur
    ' eingefügt, stürzt Excel danach komplett ab. Dies ist ein Fehler im VBE und wird durch
    ' oben stehendes Konstrukt umgangen! Das herauszufinden, hat mich viele Arbeitsstunden
    ' gekostet. Falls daher mal beim Aktualisieren einer Masterliste ein Absturz erfolgt,
    ' sollte der Fehler zunächst hier gesucht werden (evtl. tritt das Problem auch bei
    ' anderen Schlüsselwörtern auf)!
    For Each VBComp In sourceVBComponents
    ' Namen (Worksheet-Name), Typ und Code der aktuellen Komponente des Templates auslesen
    currentComp_Type = VBComp.Type
    currentComp_Code = VBComp.CodeModule.Lines(1, VBComp.CodeModule.CountOfLines)
    Select Case currentComp_Type
    Case vbext_ct_StdModule, vbext_ct_Document, vbext_ct_ClassModule
    ' Spezialfall "DieseArbeitsmappe": der Name ist hier nicht in den Properties zu  _
    finden
    If VBComp.Name = "DieseArbeitsmappe" Then
    ' Neuen Code einfügen
    destVBComponents(VBComp.Name).CodeModule.AddFromString String:=Replace
    Else
    comp_match = False
    ' Komponente mit gleichen (Klartext-)Namen der Zieldatei suchen
    For Each VBCompInDest In destVBComponents
    If VBCompInDest.Properties("Name") = VBComp.Properties("Name") Then
    ' Neuen Code einfügen
    VBCompInDest.CodeModule.AddFromString String:=Replace( _
    currentComp_Code, "Private ", "")
    comp_match = True
    Exit For
    End If
    Next VBCompInDest
    ' Komponente ist nicht in der Zieldatei vorhanden
    If comp_match = False Then
    ' Modul ist nicht vorhanden
    ' -> neue Komponente des richtigen Typs erstellen
    Set newComp = destVBComponents.Add(VBComp.Type)
    ' Code einfügen
    newComp.CodeModule.AddFromString String:=Replace(currentComp_Code, " _
    Private ", "")
    ' Nun müssen noch alle Eigenschafts-Werte der Komponente übertragen  _
    werden
    '   For i = 1 To VBComp.Properties.Count
    '       newComp.Properties.Item(i) = VBComp.Properties.Item(i)
    '   Next i
    End If
    End If
    Case vbext_ct_MSForm
    ' Formular-Modul in den Ordner der Zieldatei exportieren ...
    FName = destFolderPath & "\" & VBComp.Name & ".frm"
    VBComp.Export FName
    ' ... und importieren
    destVBComponents.Import FName
    ' temporäre Datei(en) löschen
    Kill FName
    Kill Replace(FName, ".frm", ".frx")
    Case Else
    End Select
    comp_match = False
    Next VBComp     ' nächste Komponente
    ' Operation war erfolgreich, wenn wir bis hierher gekommen sind
    transferVBACode = True
    ' Das aktive Projekt soll nun wieder dieses sein
    Set Application.VBE.ActiveVBProject = ThisWorkbook.VBProject
    Application.VBE.MainWindow.Visible = False
    If restoreScreenUpdating Then
    Application.ScreenUpdating = False
    End If
    If restoreEvents Then
    Application.enableEvents = True
    End If
    ' Objekte freigeben
    Set destWorkbook = Nothing
    Set sourceWorkbook = Nothing
    Set destVBComponents = Nothing
    Set sourceVBComponents = Nothing
    Set VBCompInDest = Nothing
    Set newComp = Nothing
    Set VBComp = Nothing
    End Function
    


    Hier ist die Zeile auf jeden Fall vorhanden. Der Code funktioniert auch bei den meisten Dateien, nur eben nicht dort, wo eines der Formulare nicht gelöscht wird.
    Gruß,
    Kolja

    Anzeige
    AW: Lösung zum Problem beim Einfügen von Code (@Al
    08.01.2008 16:27:00
    Code
    Hallo Kolja,
    Du hast mein System beim Austausch von Vba-Code noch nicht verstanden.
    Die AddFromString-Methode ist leider fehlerbehaftet. Wenn im Orignalcode steht:
    
    MsgBox "Ich habe jetzt " & _
    "keine Lust mehr"
    


    dann steht im eigefügten Code

    
    MsgBox "Ich habe jetzt " & _
    "keine Lust mehr"
    

    Es wird also eine sinnlose Leerzeile eingefügt, die natürlich zu einem Fehler führt.
    Deshalb mache ich Folgendes:
    - aus der Datei mit dem richtigen Vba-Code exportiere ich allen Vba-Code in ein extra dafür angelegtes Verzeichnis
    - alle schon darin vorhandenen Dateien werden zuvor gelöscht
    - die Klassenmodule in 'DieseArbeitsmappe' werden beim Exportieren auch noch umbenannt.
    - statt *.cls heißen sie dann *.clsS, weil beim Importieren alle *.cls-Dateien in ein normales Klassenmodul
      eingefügt werden würde
    - in der anderen Datei werden alle Vba-Module (einschließlich Formulare) gelöscht
    - in diese Datei werden dann alle vorher exportierten Module mit 'AddFromFile' wieder importiert
    - bei den *.clsS-Dateien wird der TabellenIndexName (CodeName)-benutzt und die ersten 4 Vba-Zeilen
      wieder gelöscht
    - bei den Formularen nur die frm-dateien (nicht die frx-Dateien)
    Das alles passiert aus einem AddIn heraus. Nur so ist gewährleistet, daß auch alle Vba-Teile in der Austauch-Datei zuvor gelöscht werden können. Da die Templates/Austauschdatei sicher mit einem Vba-Kennwort versehen sind, habe ich auch hier eine Lösung gefunden, vom AddIn aus den Schutz aufzuheben. Leider sind die Internet-Vorschäge immer nur auf den Sendkeys-Befehl ausgerichtet. Zuvor muß im Projekt-Explorer aber noch das richtige Vba-Projekt selektiert werden und dann kann erst der Sendkeys-Befehl gestartet werden.
    Durch die 'AddFromFile'-Methode werden nicht vorhandene Objekte automatisch in der Austauschdatei von Excel angelegt.
    Gruß von Luschi
    aus klein-Paris

    Anzeige
    AW: Lösung zum Problem beim Einfügen von Code (@Al
    08.01.2008 17:18:00
    Code
    Hallo Luschi,
    danke für deine ausführliche Antwort, aber nichts für ungut: Du hast deine Lösch-Systematik in deinem Posting gar nicht erklärt, außer, daß der Code dafür in einem AddIn steht.
    Bei mir funktioniert die AddFromString-Methode außerdem. Mein momentanes Problem liegt beim Löschen der UserForms. Hier wird ein Formular schlichtweg nicht entfernt, alle anderen funktionieren.
    Gruß,
    Kolja

    300 Forumthreads zu ähnlichen Themen

    Anzeige
    Anzeige
    Anzeige

    Links zu Excel-Dialogen

    Beliebteste Forumthreads (12 Monate)

    Anzeige

    Beliebteste Forumthreads (12 Monate)

    Anzeige
    Anzeige
    Anzeige