VBA Makro in einem Modul löschen

Hallo,
da mit die Beitragsfolgen von Ludwig (weidag) zu dem Thema zu lang geworden sind und ich da längst den Überblick verloren habe was jetzt da alles so drinsteht beginne ich eine neue Folge.

Auf XL97 habe ich jetzt folgenden Code gebastelt, der eine Makroprozedur aufgrund des Makronamens löscht, dabei werden alle Module aller offenen Arbeitsmappen (auch die der Preson(a)l.xls!) durchlaufen und bei Auffinden des Makros wird dieses gelöscht und die Sub abgebrochen.

In einigen Tests lief es fehlerfrei, nur warum es bei „Exit For“ in eine Endlosschleife rennt weiß ich noch nicht. Nun gut, als workaround nahm ich halt Exit Sub.
Das hat den Nachteil, wenn „MeinMakro“ in verschiedenen Modulen/Mappen steht, wird es nur einmal entfernt. Dies muß noch verbessert werden.

Angepasst muß ggfs auch noch, falls der Code auskommentiert ist mittels Hochkomma.

Option Explicit

Sub MeinMakro() 'Dieses Testmakro soll entfernt werden
'jkhjhh
End Sub

Sub Loesch()
Call Makro_Loeschen(„MeinMakro“)
End Sub

Sub Makro\_Loeschen(Makroname As String)
Dim CMdl, wb As Workbook, Vorhanden As Boolean, Zeile As Long
Dim Von As Long, Fehlermldg As String, Teil As String
 For Each wb In Workbooks
 For Each CMdl In wb.VBProject.VBComponents
 With CMdl.codemodule
 For Zeile = 1 To .countoflines
 On Error Resume Next
 Teil = Left(.Lines(Zeile, 1), InStr(.Lines(Zeile, 1), "(") - 1)
 On Error GoTo 0
 If InStr(Teil, Makroname) \> 0 Then
 Vorhanden = True
 Von = Zeile
 While .Lines(Zeile, 1) "End Sub"
 Zeile = Zeile + 1
 Wend
 .deletelines Von, Zeile - Von + 1
 'Exit For 'ergibt Endloschleife???
 Exit Sub
 End If
 Next Zeile
 End With
 Next CMdl
 Next wb
If Vorhanden = False Then
 Fehlermldg = "Makro " & Makroname & " nicht gefunden "
 GoTo Fehler
End If
Exit Sub
Fehler:
MsgBox Fehlermldg
End Sub

Gruß
Reinhard

Die Lösung?
Hallo Reinhard,

in der entsprechenden Folge von Beiträgen hab ich’s gepostet. Aber du hast Recht, es ist unübersichtlich geworden. Daher hier nochmals die Lösung, die ich in einem Forum fand. Und die funktioniert tatsächlich wie lange gewünscht:

Public Sub LoescheModule()
With Workbooks(„DeineVorlage.xls“)
With .VBProject.VBComponents
.Remove .Item(„Modul3“)
.Remove .Item(„Modul4“)
End With
End With
End Sub

Deses Nakro wird in der „Oberdatei“ gestartet und löscht alle Makros in allen 28 „Unterdateien“. Ich musste nur die Zeile

.Remove .Item(„Modul3“)

natürlich anpassen und entsprechend „vermehren“.

Vielen Dank für deine vielfältige Hilfe,

Ludwig

Per Makro ein Modul löschen

in der entsprechenden Folge von Beiträgen hab ich’s gepostet.
Aber du hast Recht, es ist unübersichtlich geworden. Daher
hier nochmals die Lösung, die ich in einem Forum fand. Und die
funktioniert tatsächlich wie lange gewünscht:

Hallo Ludwig,
ja, ich sah die Lösung, sie betrifft das Löschen von kompletten Modulen. Bei mir funtionierten auch die anderen Codes zum Löschen kompletter Module und ich weiß wie Marion nicht warum dies bei dir nicht klappte.
Aber dieser Code scheint ja jetzt bei dir zu laufen, insofern ist ja das Problem gelöst.
Ich habe mich darauf konzentriert, einzelne Makros in einem Modul zu löschen oder einzufügen, siehe mein Posting was gleich kommt.
Gruß
Reinhard

Public Sub LoescheModule()
With Workbooks(„DeineVorlage.xls“)
With .VBProject.VBComponents
.Remove .Item(„Modul3“)
.Remove .Item(„Modul4“)
End With
End With
End Sub

Deses Nakro wird in der „Oberdatei“ gestartet und löscht alle
Makros in allen 28 „Unterdateien“. Ich musste nur die Zeile

.Remove .Item(„Modul3“)

natürlich anpassen und entsprechend „vermehren“.

Makro in einem Modul löschen oder einfügen
Hallo Interessierte,

mit Makro_loeschen2(Makroname As String)
löscht man ein Makro in allen Modulen aller offenen Mappen.
Danke an Nepumuk für den Tipp mit der .Find-Routine.

Mit Makro_Einfuegen(Makrotext As String, Optional Modulname As String, Optional Mappenname As String)
fügt man ein Makro, was aus den einzelnen Zeilen in „Makrotetext“ besteht in ein Modul ein.
Läßt man den Modulnamen weg, wird Modul1 angenommen, ggfs erzeugt. Läßt man den Arbeitsmappennamen weg wird Thisworkbook angenommen.
Man sieht an den verschiedenen Calls wie das gehandhabt wird.

Getestet auf XL97 und XL2002.

Option Explicit

Sub Loesch()
Call Makro_loeschen2(„Sub Test“)
End Sub

Sub Einfuegen()
Dim Makrotext As String
Makrotext = "Sub Test()" & Chr(13)
Makrotext = Makrotext & "'blabla" & Chr(13)
Makrotext = Makrotext & "End Sub" & Chr(13)
'Call Makro\_Einfuegen(Makrotext, "Modul4", "ListeAllerMakros.xls")
'Call Makro\_Einfuegen(Makrotext, "Modul4", "Mappe3")
Call Makro\_Einfuegen(Makrotext, "Modul3")
Call Makro\_Einfuegen(Makrotext)
'Call Makro\_Einfuegen(Makrotext, , "Mappe3")
Call Makro\_Einfuegen(Makrotext, "Tabelle2")
End Sub


Sub Makro\_loeschen2(Makroname As String)
Dim CMdl, wb As Workbook, lngStartLine As Long, lngSearchLine As Long
Dim Finden
 For Each wb In Workbooks
 For Each CMdl In wb.VBProject.VBComponents
 lngStartLine = 1
 With CMdl.codemodule
 While .Find(Makroname & "(", lngStartLine, 1, -1, -1, False, False, True)
 If InStr(.Lines(lngStartLine, 1), Makroname & "(") = 1 Then
 lngSearchLine = lngStartLine + 1
 .Find "End Sub", lngSearchLine, 1, -1, -1, False, False, True
 .DeleteLines lngStartLine, lngSearchLine - lngStartLine + 1
 End If
 lngStartLine = lngStartLine + 1
 Wend
 End With
 Next CMdl
 Next wb
End Sub



Sub Makro\_Einfuegen(Makrotext As String, Optional Modulname As String, Optional Mappenname As String)
Dim wb As Workbook, Vorh As Boolean, Fehlermeldung As String, Mdl
If Mappenname "" Then
 For Each wb In Workbooks
 If wb.Name = Mappenname Then
 Vorh = True
 Exit For
 End If
 Next wb
Else
 Mappenname = ThisWorkbook.Name
 Vorh = True
End If
If Vorh = False Then
 Fehlermeldung = "Mappe " & Mappenname & " nicht gefunden"
 GoTo Fehler
End If
Vorh = False
If Modulname = "" Then Modulname = "Modul1"
For Each Mdl In Workbooks(Mappenname).VBProject.VBComponents
 If Mdl.Name = Modulname Then
 Vorh = True
 Exit For
 End If
Next Mdl
If Vorh = False Then
 Workbooks(Mappenname).VBProject.VBComponents.Add(1).Name = Modulname
End If
With Workbooks(Mappenname).VBProject.VBComponents(Modulname).codemodule
 .insertlines .CountOfLines + 2, Makrotext
End With
Exit Sub
Fehler:
MsgBox Fehlermeldung
End Sub

Gruß
Reinhard

Makros in einem Modul
Hallo,
In einer Mitteilung weiter unten vom 24.7. „Moduleund Makros“ habe ich eine Literaturstelle genannt, die mir nach wie vor fuer euch alle leesenswert scheint.
Erich

Antwort und Frage
Hallo Reinhard

mit Makro_loeschen2(Makroname As String)
löscht man ein Makro in allen Modulen aller offenen Mappen.

Geht bei mir euf Excel 2003 problemos
Aber ich *dumm* verstehe den Code nicht ganz:

Dim CMdl, wb As Workbook, lngStartLine As Long, lngSearchLine

Was ist CMdl? warum kein Variablentyp engegeben?
Kann ich den momentanen Wert von CMdl anzeigen? wie?
Ich habe ein Makro im gleichen Modul erstellt, das richtig geloescht wird, aber die Schleife wird zuerst etwa 20-30 Mal durchlaufen. Was macht das Makro genau?

Eine Erklaerung wuerde mir sehr weiterhelfen
Danke
Erich

Hallo Erich,

mit Makro_loeschen2(Makroname As String)
löscht man ein Makro in allen Modulen aller offenen Mappen.

Geht bei mir euf Excel 2003 problemos

Schön.

Aber ich *dumm* verstehe den Code nicht ganz:

Dim CMdl, wb As Workbook, lngStartLine As Long, lngSearchLine

Was ist CMdl? warum kein Variablentyp engegeben?

Normal müßte man schreiben
Dim CMdl as CodeModule
das geht aber schief. Erst wenn man den Verweis auf
MS Visual Basic for Applications Extensibility 5.3
setzt, wird das vom Debugger anerkannt, deshalb habe ich das weggelassen.

Kann ich den momentanen Wert von CMdl anzeigen? wie?

ungetestet, warum nicht nicht mit Cmdl.name, .value oder sowas?

Ich habe ein Makro im gleichen Modul erstellt, das richtig
geloescht wird, aber die Schleife wird zuerst etwa 20-30 Mal
durchlaufen. Was macht das Makro genau?

Das Makro schaut in alle Module aller offenen Mappen, also auch personl.xls, schaut nach der Prozedur „MeinMakro“ o.ä. und löscht genau das, also diese Prozedur (also Codezeilen einees Makros in einem Modul), das Modul bleibt bestehen.

Eine Erklaerung wuerde mir sehr weiterhelfen

Ich hoffe ich konnte dir weiterhelfen, wenn nicht, frag nochmal nach.

Gruß
Reinhard

Hallo Reinhard
Danke fuer rasche Antwort!
Ich habe jetzt einiges begriffen, dann kommen jedoch wieder neue Fragen.

Die FIND-funktion mit ihren Parametern ist mir nicht klar und die Hilfe sagt auch nichts ueber „find“ in Modulen.

Ich moechte das Makro so erweitern, dass es nicht ein bestimmtes Makro sucht und loescht, sondern in allen Modulen, die es brav aufsucht, alle darin enthaltenen Makros auflsitet.
Kannst du mir nochmal einen Tipp geben?
Vielen Dank
Erich

Hallo Erich,

Ich habe jetzt einiges begriffen, dann kommen jedoch wieder
neue Fragen.

*Kicher*, geht mir laufend so.

Die FIND-funktion mit ihren Parametern ist mir nicht klar und
die Hilfe sagt auch nichts ueber „find“ in Modulen.

Auch mir ist das Find in diesem Fall noch ein bisschen unklar, es sind die üblichen Find-Parameter, aber so ganz durchblicke ich da wie du nicht so genau warum das klappt.

Ich moechte das Makro so erweitern, dass es nicht ein
bestimmtes Makro sucht und loescht, sondern in allen Modulen,
die es brav aufsucht, alle darin enthaltenen Makros auflsitet.

Das kriege ich hin.

Gruß
Reinhard

Prozeduren auflisten

Ich moechte das Makro so erweitern, dass es nicht ein
bestimmtes Makro sucht und loescht, sondern in allen Modulen,
die es brav aufsucht, alle darin enthaltenen Makros auflsitet.
Kannst du mir nochmal einen Tipp geben?

Hallo Erich,
getestet auf XL2000. Nicht getestet: freigegeben Mappen, Mappen mit
Passwort, gelistete Prozeduren > 65536 Zeielen, ob da der
Spaltenwechsel funktionirt, u.v.m.

Rückmeldung, bei welchen zu öffnenden Dateien oder Prozeduren es
Probleme gibt wäre sehr nett.

In der Statusbar wird der Fortschritt angezeigt.
Auskommentierter Code wird blau angezeigt.

Im Anhang bin ich einen anderen Weg gegangen, Code funktioniert auch,
allerdings kommt Fehler wenn eine Property erkannt wird. Und „On Error“ funktioniert nicht. Also mehr
was zum lernen/üben.

In ein Standardmodul:

Option Explicit
Public Zei As Long, Spa As Integer

Sub ProzedurenAuflisten()
'listet alle Prozeduren aller offenen Workbooks auf
Dim wb As Workbook
ThisWorkbook.Worksheets("Tabelle1").Activate
Zei = 1
Spa = 1
Cells.ClearContents
[A1:smiley:1] = Split("Mappe Modul Prozedur Code")
[A1:smiley:1].Copy Destination:=[E1:IV1]
For Each wb In Workbooks
 MsgBox wb.Name
 'If UCase(wb.Name) "PERSONL.XLS" And wb.Name ThisWorkbook.Name Then
 Call ListProcedures(wb)
 'End If
Next wb
End Sub


Sub MappenOeffnenProzedurenAuflisten()
'Öffnet alle Dateien im Ordner "Pfad" und listet alle Prozeduren auf.
'Code 2007 by Reinhard
Dim wb, Pfad As String, fs, N As Long, ws As Worksheet
Dim oldStatusBar
Application.ScreenUpdating = False
Application.EnableEvents = False
On Error GoTo Fehler
'Pfad = "C:\Download"
Pfad = ThisWorkbook.Path
Set ws = ThisWorkbook.Worksheets("Tabelle1")
Set fs = Application.FileSearch
Call MappenSchliessen
oldStatusBar = Application.DisplayStatusBar
Application.DisplayStatusBar = True
Zei = 1
Spa = 1
With ws
 .Cells.ClearContents
 .Cells.Font.ColorIndex = xlAutomatic
 .[A1:smiley:1] = Split("Mappe Modul Prozedur Code")
 .[A1:smiley:1].Copy Destination:=.[E1:IV1]
End With
With fs
 .LookIn = Pfad
 .Filename = "\*.xls"
 .SearchSubFolders = True
 .Execute
 'For N = 1 To .FoundFiles.Count
 For N = 1 To 10
 If InStr(.FoundFiles(N), "\Personl.xls") = 0 And InStr(.FoundFiles(N), "\" & ThisWorkbook.Name) = 0 Then
 Workbooks.Open .FoundFiles(N), 0, True
 Set wb = ActiveWorkbook
 'If UCase(wb.Name) "PERSONL.XLS" And wb.Name ThisWorkbook.Name Then
 Application.StatusBar = "Bearbeite gerade " & N & " / " & .FoundFiles.Count & "Dateien."
 Call ListProcedures2(wb)
 wb.Close savechanges:=False
 'End If
 End If
 Next N
End With
ws.Rows(1).Font.Bold = True
ws.Rows("2:2").Select
ActiveWindow.FreezePanes = True
ws.Range("A1").Select
Fehler:
Application.StatusBar = False
Application.DisplayStatusBar = oldStatusBar
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox "Done"
End Sub


Sub ListProcedures2(ByVal wb As Workbook)
'Code 2007 by Reinhard
Dim VBCodeMod As CodeModule, lngStartLine As Long, strMsg As String
Dim strModName As String, CMdl, Zeile As Long, Spalte As Integer
Dim N As Long, Von As Long, Bis As Long, Prozedur As String
Dim ws As Worksheet
Call ZeileSpalte
Set ws = ThisWorkbook.Worksheets("Tabelle1")
ws.Cells(Zei, Spa) = wb.Name
On Error Resume Next
For Each CMdl In wb.VBProject.VBComponents
 ws.Cells(Zei, Spa + 1) = CMdl.Name
 Set VBCodeMod = wb.VBProject.VBComponents(CMdl.Name).CodeModule
 With VBCodeMod
 'ws.Cells(Zei, Spa + 2) = VBCodeMod.Name
 For N = 1 To .CountOfLines
 If IstProz(.Lines(N, 1)) "" Then ws.Cells(Zei, Spa + 2) = IstProz(.Lines(N, 1))
 ws.Cells(Zei, Spa + 3) = .Lines(N, 1)
 If InStr(.Lines(N, 1), "'") \> 0 Then
 ws.Cells(Zei, Spa + 3).Characters(Start:=InStr(.Lines(N, 1), "'"), Length:=Len(.Lines(N, 1)) - InStr(.Lines(N, 1), "'") + 1).Font.ColorIndex = 5
 End If
 Call ZeileSpalte
 Next N
 End With
Next CMdl
ws.UsedRange.Columns.AutoFit
End Sub


Function ZeileSpalte()
Zei = Zei + 1
If Zei \> ThisWorkbook.Worksheets("Tabelle1").Rows.Count Then
 Zei = 2
 Spa = Spa + 4
End If
End Function


Function IstProz(ByVal Zeile As String)
Dim Vorh As Boolean, N As Byte, Woerter
Woerter = Array("Sub ", "Function ", "Property ")
For N = 0 To UBound(Woerter)
 If InStr(Zeile, Woerter(N)) \> 0 Then
 If InStr(Zeile, "'") = 0 Then
 IstProz = Zeile
 Else
 If InStr(Zeile, "'") \> InStr(Zeile, ")") Then
 IstProz = Left(Zeile, InStr(Zeile, "'") - 1)
 End If
 End If
 Exit For
 End If
Next N
End Function

Gruß
Reinhard

Sub ListProcedures(ByVal wb As Workbook)

'Verweis auf Microsoft Visual basic for Applications Extensibility muß gesetzt sein!!
'Code 2007 by Reinhard

Dim VBCodeMod As CodeModule, lngStartLine As Long, strMsg As String
Dim strModName As String, CMdl, Zeile As Long, Spalte As Integer
Dim N As Long, Von As Long, Bis As Long, Prozedur As String
Dim ws As Worksheet
Call ZeileSpalte
Set ws = ThisWorkbook.Worksheets("Tabelle1")
ws.Cells(Zei, Spa) = wb.Name
For Each CMdl In wb.VBProject.VBComponents
 ws.Cells(Zei, Spa + 1) = CMdl.Name
 Set VBCodeMod = wb.VBProject.VBComponents(CMdl.Name).CodeModule
 With VBCodeMod
 lngStartLine = .CountOfDeclarationLines + 1
 Do Until lngStartLine \>= .CountOfLines
 Prozedur = .ProcOfLine(lngStartLine, vbext\_pk\_Proc)
 ws.Cells(Zei, Spa + 2) = Prozedur
 For N = 1 To lngStartLine - 1
 ws.Cells(Zei, Spa + 3) = .Lines(N, 1)
 Call ZeileSpalte
 Next N
 On Error GoTo Weiter 'Fehler wenn Prozedur keine Sub oder Function sondern Property
 lngStartLine = lngStartLine + .ProcCountLines(.ProcOfLine(lngStartLine, vbext\_pk\_Proc), vbext\_pk\_Proc)
 On Error GoTo 0
 Von = .ProcStartLine(Prozedur, vbext\_pk\_Proc)
 Bis = .ProcCountLines(Prozedur, vbext\_pk\_Proc)
 For N = Von To Von + Bis - 1
 ws.Cells(Zei, Spa + 3) = .Lines(N, 1)
 Call ZeileSpalte
 Next N
 Loop
 End With
Weiter:
Next CMdl
ActiveSheet.UsedRange.Columns.AutoFit
End Sub