web-dev-qa-db-de.com

Excel VBA - Aktivieren von Zeilennummern im Code-Editor

Bitte helfen Sie mir: Wie kann ich die Zeilennummern im Excel VBA-Code-Editor aktivieren? Ich benutze Excel 2013-Version.

Vielen Dank.

8
Sohel

Hier ist mein Code zum Hinzufügen von Zeilennummern in der VBE-IDE. Es ist eine Verbesserung der angebotenen Lösung hier von Excel MVP mikerickson. Ich habe daran gearbeitet, weil in einigen seltenen Fällen, die ich bereits getroffen habe, VBE nicht in den Debug-Modus gelangen kann, zum Beispiel, wenn Sie eine .ReplaceLine-Methode in Ihrem Code haben. In der Tat können Sie nicht in den Debug-Modus wechseln, sobald er ausgeführt wurde. Erl ist daher möglicherweise für Debugger (anstelle von Debug.Print) nützlich. Ich habe mehrere Funktionen hinzugefügt wie: 

  • möglichkeit, entweder Zeilennummern als Beschriftungen hinzuzufügen: 10: Dim foo as bar oder als Einzelnummern, die durch eine Registerkarte vom Code getrennt sind: 10 Dim foo as bar
  • möglichkeit zum Hinzufügen von Zeilennummern zu den Anweisungen "Ende von Prozeduren" und zum Anpassen des Einzugs der Prozedurdeklarationszeilen an ihre "End" -Anweisungszeile. Oder nicht.
  • möglichkeit, Zeilennummern zu leeren Zeilen hinzuzufügen oder nicht
  • [WIP] Möglichkeit, Zeilennummern zu einer bestimmten Prozedur in einem Modul hinzuzufügen
  • [WIP] ordnet alle Einrückungen von Codezeilen den Zeilennummern zu, damit sie dem Einzug der letzten eingerückten Zeile entsprechen. Wenn die letzte Zeile 200: End Sub ist, wird die Zeile 30: With ActiveSheet wieder als 30: ActiveSheet eingerückt.
  • [WIP] add eines VBE IDE -Befehls, um die Aufrufe direkt mit dem aktuellen Modul/proc als Parameter auszuführen
Public Enum vbLineNumbers_LabelTypes
    vbLabelColon    ' 0
    vbLabelTab      ' 1
End Enum

Public Enum vbLineNumbers_ScopeToAddLineNumbersTo
    vbScopeAllProc  ' 1
    vbScopeThisProc ' 2
End Enum

Sub AddLineNumbers(ByVal wbName As String, _
                   ByVal vbCompName As String, _
                   ByVal LabelType As vbLineNumbers_LabelTypes, _
                   ByVal AddLineNumbersToEmptyLines As Boolean, _
                   ByVal AddLineNumbersToEndOfProc As Boolean, _
                   ByVal Scope As vbLineNumbers_ScopeToAddLineNumbersTo, _
                   Optional ByVal thisProcName As String)

' USAGE RULES
' DO NOT MIX LABEL TYPES FOR LINE NUMBERS! IF ADDING LINE NUMBERS AS COLON TYPE, ANY LINE NUMBERS AS VBTAB TYPE MUST BE REMOVE BEFORE, AND RECIPROCALLY ADDING LINE NUMBERS AS VBTAB TYPE

    Dim i As Long
    Dim j As Long
    Dim procName As String
    Dim startOfProcedure As Long
    Dim lengthOfProcedure As Long
    Dim endOfProcedure As Long
    Dim strLine As String

    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
        .CodePane.Window.Visible = False

If Scope = vbScopeAllProc Then

        For i = 1 To .CountOfLines

            strLine = .Lines(i, 1)
            procName = .ProcOfLine(i, vbext_pk_Proc) ' Type d'argument ByRef incompatible ~~> Requires VBIDE library as a Reference for the VBA Project

            If procName <> vbNullString Then
                startOfProcedure = .ProcStartLine(procName, vbext_pk_Proc)
                bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)
                countOfProcedure = .ProcCountLines(procName, vbext_pk_Proc)

                prelinesOfProcedure = bodyOfProcedure - startOfProcedure
                'postlineOfProcedure = ??? not directly available since endOfProcedure is itself not directly available.

                lengthOfProcedure = countOfProcedure - prelinesOfProcedure ' includes postlinesOfProcedure !
                'endOfProcedure = ??? not directly available, each line of the proc must be tested until the End statement is reached. See below.

                If endOfProcedure <> 0 And startOfProcedure < endOfProcedure And i > endOfProcedure Then
                    GoTo NextLine
                End If

                If i = bodyOfProcedure Then InProcBodyLines = True

                If bodyOfProcedure < i And i < startOfProcedure + countOfProcedure Then
                    If Not (.Lines(i - 1, 1) Like "* _") Then

                        InProcBodyLines = False

                        PreviousIndentAdded = 0

                        If Trim(strLine) = "" And Not AddLineNumbersToEmptyLines Then GoTo NextLine

                        If IsProcEndLine(wbName, vbCompName, i) Then
                            endOfProcedure = i
                            If AddLineNumbersToEndOfProc Then
                                Call IndentProcBodyLinesAsProcEndLine(wbName, vbCompName, LabelType, endOfProcedure)
                            Else
                                GoTo NextLine
                            End If
                        End If

                        If LabelType = vbLabelColon Then
                            If HasLabel(strLine, vbLabelColon) Then strLine = RemoveOneLineNumber(.Lines(i, 1), vbLabelColon)
                            If Not HasLabel(strLine, vbLabelColon) Then
                                temp_strLine = strLine
                                .ReplaceLine i, CStr(i) & ":" & strLine
                                new_strLine = .Lines(i, 1)
                                If Len(new_strLine) = Len(CStr(i) & ":" & temp_strLine) Then
                                    PreviousIndentAdded = Len(CStr(i) & ":")
                                Else
                                    PreviousIndentAdded = Len(CStr(i) & ": ")
                                End If
                            End If
                        ElseIf LabelType = vbLabelTab Then
                            If Not HasLabel(strLine, vbLabelTab) Then strLine = RemoveOneLineNumber(.Lines(i, 1), vbLabelTab)
                            If Not HasLabel(strLine, vbLabelColon) Then
                                temp_strLine = strLine
                                .ReplaceLine i, CStr(i) & vbTab & strLine
                                PreviousIndentAdded = Len(strLine) - Len(temp_strLine)
                            End If
                        End If

                    Else
                        If Not InProcBodyLines Then
                            If LabelType = vbLabelColon Then
                                .ReplaceLine i, Space(PreviousIndentAdded) & strLine
                            ElseIf LabelType = vbLabelTab Then
                                .ReplaceLine i, Space(4) & strLine
                            End If
                        Else
                        End If
                    End If

                End If

            End If

NextLine:
        Next i

ElseIf AddLineNumbersToEmptyLines And Scope = vbScopeThisProc Then

End If

        .CodePane.Window.Visible = True
    End With

End Sub

Function IsProcEndLine(ByVal wbName As String, _
                   ByVal vbCompName As String, _
                   ByVal Line As Long) As Boolean

With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
    If Trim(.Lines(Line, 1)) Like "End Sub*" _
    Or Trim(.Lines(Line, 1)) Like "End Function*" _
    Or Trim(.Lines(Line, 1)) Like "End Property*" _
    Then IsProcEndLine = True
End With

End Function

Sub IndentProcBodyLinesAsProcEndLine(ByVal wbName As String, ByVal vbCompName As String, ByVal LabelType As vbLineNumbers_LabelTypes, ByVal ProcEndLine As Long)
    Dim procName As String
    Dim startOfProcedure As Long
    Dim endOfProcedure As Long

    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule

        procName = .ProcOfLine(ProcEndLine, vbext_pk_Proc)
        bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)
        endOfProcedure = ProcEndLine
        strEnd = .Lines(endOfProcedure, 1)

        j = bodyOfProcedure
        Do Until Not .Lines(j - 1, 1) Like "* _" And j <> bodyOfProcedure

            strLine = .Lines(j, 1)

            If LabelType = vbLabelColon Then
                If Mid(strEnd, Len(CStr(endOfProcedure)) + 1 + 1 + 1, 1) = " " Then
                    .ReplaceLine j, Space(Len(CStr(endOfProcedure)) + 1) & strLine
                Else
                    .ReplaceLine j, Space(Len(CStr(endOfProcedure)) + 2) & strLine
                End If
            ElseIf LabelType = vbLabelTab Then
                If endOfProcedure < 1000 Then
                    .ReplaceLine j, Space(4) & strLine
                Else
                    Debug.Print "This tool is limited to 999 lines of code to work properly."
                End If
            End If

            j = j + 1
        Loop

    End With
End Sub

Sub RemoveLineNumbers(ByVal wbName As String, ByVal vbCompName As String, ByVal LabelType As vbLineNumbers_LabelTypes)
    Dim i As Long
    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule

        For i = 1 To .CountOfLines

            procName = .ProcOfLine(i, vbext_pk_Proc)

            If procName <> vbNullString Then

                If i = .ProcBodyLine(procName, vbext_pk_Proc) Then InProcBodyLines = True

                LenghtBefore = Len(.Lines(i, 1))
                If Not .Lines(i - 1, 1) Like "* _" Then
                    InProcBodyLines = False
                    .ReplaceLine i, RemoveOneLineNumber(.Lines(i, 1), LabelType)
                Else
                    If IsInProcBodyLines Then
                        ' do nothing
                    Else
                        .ReplaceLine i, Mid(.Lines(i, 1), RemovedChars_previous_i + 1)
                    End If
                End If
                LenghtAfter = Len(.Lines(i, 1))

                LengthBefore_previous_i = LenghtBefore
                LenghtAfter_previous_i = LenghtAfter
                RemovedChars_previous_i = LengthBefore_previous_i - LenghtAfter_previous_i

                If Trim(.Lines(i, 1)) Like "End Sub*" Or Trim(.Lines(i, 1)) Like "End Function" Or Trim(.Lines(i, 1)) Like "End Property" Then

                    LenOfRemovedLeadingCharacters = LenghtBefore - LenghtAfter

                    procName = .ProcOfLine(i, vbext_pk_Proc)
                    bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)

                    j = bodyOfProcedure
                    strLineBodyOfProc = .Lines(bodyOfProcedure, 1)
                    Do Until Not strLineBodyOfProc Like "* _"
                        j = j + 1
                        strLineBodyOfProc = .Lines(j, 1)
                    Loop
                    LastLineBodyOfProc = j
                    strLastLineBodyOfProc = strLineBodyOfProc

                    strLineEndOfProc = .Lines(i, 1)
                    For k = bodyOfProcedure To j
                        .ReplaceLine k, Mid(.Lines(k, 1), 1 + LenOfRemovedLeadingCharacters)
                    Next k

                    i = i + (j - bodyOfProcedure)
                    GoTo NextLine

                End If
            Else
            ' GoTo NextLine
            End If
NextLine:
        Next i
    End With
End Sub

Function RemoveOneLineNumber(ByVal aString As String, ByVal LabelType As vbLineNumbers_LabelTypes)
    RemoveOneLineNumber = aString
    If LabelType = vbLabelColon Then
        If aString Like "#:*" Or aString Like "##:*" Or aString Like "###:*" Then
            RemoveOneLineNumber = Mid(aString, 1 + InStr(1, aString, ":", vbTextCompare))
            If Left(RemoveOneLineNumber, 2) Like " [! ]*" Then RemoveOneLineNumber = Mid(RemoveOneLineNumber, 2)
        End If
    ElseIf LabelType = vbLabelTab Then
        If aString Like "#   *" Or aString Like "##  *" Or aString Like "### *" Then RemoveOneLineNumber = Mid(aString, 5)
        If aString Like "#" Or aString Like "##" Or aString Like "###" Then RemoveOneLineNumber = ""
    End If
End Function

Function HasLabel(ByVal aString As String, ByVal LabelType As vbLineNumbers_LabelTypes) As Boolean
    If LabelType = vbLabelColon Then HasLabel = InStr(1, aString & ":", ":") < InStr(1, aString & " ", " ")
    If LabelType = vbLabelTab Then
        HasLabel = Mid(aString, 1, 4) Like "#   " Or Mid(aString, 1, 4) Like "##  " Or Mid(aString, 1, 4) Like "### "
    End If
End Function

Function RemoveLeadingSpaces(ByVal aString As String) As String
    Do Until Left(aString, 1) <> " "
        aString = Mid(aString, 2)
    Loop
    RemoveLeadingSpaces = aString
End Function

Function WhatIsLineIndent(ByVal aString As String) As String
    i = 1
    Do Until Mid(aString, i, 1) <> " "
        i = i + 1
    Loop
    WhatIsLineIndent = i
End Function

Function HowManyLeadingSpaces(ByVal aString As String) As String
    HowManyLeadingSpaces = WhatIsLineIndent(aString) - 1
End Function

Sie können wie folgt telefonieren:

Sub AddLineNumbers_vbLabelColon()
    AddLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
End Sub

Sub AddLineNumbers_vbLabelTab()
    AddLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelTab, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
End Sub

Sub RemoveLineNumbers_vbLabelColon()
    RemoveLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelColon
End Sub

Sub RemoveLineNumbers_vbLabelTab()
    RemoveLineNumbers wbName:="EvaluateCall.xlsm", vbCompName:="ModLineNumbers_testDest", LabelType:=vbLabelTab
End Sub

Und als Erinnerung, hier einige Regeln über die Zeilennummern:

  • vor einer Sub/Function-Deklarationsanweisung nicht zulässig
  • außerhalb eines proc nicht erlaubt
  • in einer Zeile nach einem Zeilenfortsetzungszeichen "_" (Unterstrich) nicht zulässig
  • es darf nicht mehr als eine Beschriftungs-/Zeilennummer pro Codezeile vorhanden sein. ~~> Vorhandene Beschriftungen, die keine Zeilennummern sind, müssen getestet werden. Andernfalls tritt ein Kompilierungsfehler auf, der versucht, eine Zeilennummer zu erzwingen.
  • zeichen, die bereits eine spezielle VBA-Bedeutung haben, dürfen nicht verwendet werden ~~> Erlaubte Zeichen sind [a-Z], [0-9], é, è, ô, €, £, § und sogar ":" alleine!
  • der Compiler schneidet ein beliebiges Leerzeichen vor einem Label ab. ~~> Wenn also ein Label vorhanden ist, ist das erste Zeichen der Zeile das erste Zeichen des Labels. Es darf kein Leerzeichen sein.
  • wenn Sie eine Zeilennummer an einen Doppelpunkt anhängen, wird ein Leerzeichen zwischen dem ":" und dem nächsten Zeichen eingefügt, wenn keines vorhanden ist
  • wenn Sie eine Zeilennummer mit einem Tabulator/Leerzeichen anfügen, muss sich zwischen der letzten Ziffer und dem nächsten Zeichen mindestens ein Leerzeichen befinden. Der Compiler fügt ihn nicht wie bei einem Label mit Doppelpunkt-Trennzeichen hinzu
  • die .ReplaceLine-Methode überschreibt die Kompilierungsregeln, ohne einen Kompilierfehler anzuzeigen, wie dies im Entwurfsmodus der Fall ist, wenn Sie eine neue Zeile auswählen oder die Kompilierung manuell neu starten
  • der Compiler ist 'schneller als die VBA-Umgebung/das VBA-System': Zum Beispiel wurde unmittelbar nach einer Zeilennummer mit Doppelpunkt und ohne Leerzeichen mit .ReplaceLine eingefügt, wenn die .Lines-Eigenschaft aufgerufen wird, um die neue Zeichenfolge zu erhalten, das Leerzeichen ( zwischen dem Doppelpunkt und dem ersten Zeichen der Zeichenfolge) ist in dieser Zeichenfolge bereits angehängt!
  • es ist nicht möglich, den Debug-Modus aufzurufen, nachdem eine .ReplaceLine aufgerufen wurde (von innerhalb oder außerhalb des Moduls, das gerade bearbeitet wird), nicht bis der Code ausgeführt wird und die Ausführung zurückgesetzt wird.
6
hymced

Kurze Antwort für Excel 2016, habe es 2013 noch nicht ausprobiert.

Einmal machen:

  1. Fügen Sie den großen Code aus finalModule2 In diese Antwort in Ihre Arbeitsmappe ein.
  2. Fügen Sie den Code für finalModule3 In diese Antwort in Ihre Arbeitsmappe ein.
  3. Fügen Sie den Code für finalModule4 In diese Antwort in Ihre Arbeitsmappe ein.
  4. Fügen Sie dann die Zeile Global allow_for_line_addition As String Ein, damit Sie über/in die erste Zeile jedes Moduls automatisch die Leinenummern einfügen können.
  5. Löschen Sie alle Leerzeilen am Ende jedes Moduls (damit kein Verlust nach dem letzten end sub, end function Oder End Property Eines Moduls eintritt).
  6. Wenn Sie im VBA-Editor keinen Code ausführen und sich nicht im "break" -Modus befinden, klicken Sie auf tools> references> mark: `Microsoft Visual Basic für Applikationen - Erweiterbarkeit 5.3"

Tun Sie dies jedes Mal, wenn Sie Ihren Code geändert haben:

  1. * Führen Sie den Code für finalModule3 Aus, um Zeilennummern für alle Module in Ihrer Arbeitsmappe zu entfernen.
  2. * Führen Sie den Code für finalModule4 Aus, um Zeilennummern zu allen Modulen in Ihrer Arbeitsmappe hinzuzufügen.

(* weil manchmal ein Fehler auftritt, wenn Sie Zeilen ausschneiden oder verschieben (z. B. line 2440: über line 2303: setzen). Durch Entfernen und erneutes Hinzufügen wird die Zeilennummerierung automatisch wieder korrekt )

Lange Antwort (einschließlich Lernschritten und -versuchen) - Für mich war es nicht einfach, die Antwort von hymced zu implementieren, deshalb habe ich die Schritte dokumentiert, die zum Hinzufügen von Zeilennummern zu einem Modul im VBA-Code-Editor erforderlich sind (* und wieder entfernen). Ich habe die folgenden Schritte ausgeführt, um es zum Laufen zu bringen.

  1. Aus dieser Link Ich habe gelernt, dass eine vb-Komponente ein Modul sein kann.
  2. Ich habe den ersten angegebenen Code in temporärModule2 Kopiert und den zweiten von hymced in temporärModule3.
  3. Dann ändere die erste Zeile des 2. Codes in temporärModule3 Zu:

    AddLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
    
  4. Ich habe einen Fehler in der Zeile:

    procName = .ProcOfLine(i, vbext_pk_Proc) ` Type d`argument ByRef incompatible ~~> Requires VBIDE library as a Reference for the VBA Project
    
  5. Also habe ich gelesen, dass ich die VBIDE-Bibliothek aktivieren musste.

  6. Also habe ich den Code angehalten, auf tools> references geklickt und die VBIDE-Bibliothek nicht gefunden.

  7. Am in diesem Forum habe ich festgestellt, dass VBIDE durch Hinzufügen eines Verweises auf die VBA-Erweiterungsbibliothek aktiviert wird:

Klicken Sie in der VBE auf Extras-Referenzen, scrollen Sie nach unten und markieren Sie den Eintrag für Microsoft Visual Basic für Applikationen - Erweiterbarkeit 5.3.

Danach verschwand der erste Fehler und es wurde keine Zeile markiert, sondern der Fehler "Ungültiger Prozeduraufruf oder ungültiges Argument" ausgegeben.

  1. Da ich mir über den vbCompName immer noch nicht sicher bin, dachte ich, er müsste möglicherweise das Sub anstelle des Moduls kennen, also habe ich versucht, den 2. Code in temporaryModule3 Zu ändern :

    AddLineNumbers wbName:="Book1.xlsm", vbCompName:="learn", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
    
  2. Das hat die Zeile hervorgehoben:

    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule 
    

sprichwort: subscript out of range. (Also habe ich auch versucht: Module1.learn Und Module1:learn, Was den subscript out of range - Fehler ergab.

Wie sich herausstellt,

AddLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc

ist die richtige Methode, um das ersetzende Sub aufzurufen, wenn sich das Sub, das Sie mit Zeilennummern versehen möchten, in einem Modul namens Module1 befindet. Der erste beschriebene Fehler tritt auf, fügt jedoch die Zeilennummern zum Code hinzu (mit Ausnahme der ersten Zeile mit sub ... Und der letzten Zeile mit end sub. Getestet in Module1 Mit dem Namen sub learn() der Excel 2016-Arbeitsmappe mit dem Namen Book1.xlsm. Der Vollständigkeit halber besteht learn aus:

Sub learn()
    ThisWorkbook.Worksheets("Sheet1").Activate
    Range("A1").Activate
    Range("A1").Select
    Range("A1").Value = Range("A1").Value + 1
End Sub

Auf dem Rückweg gab es jedoch beim Entfernen der Zeilennummern einen Fehler, da in Sub AddLineNumbers... .Lines (0,1) von procName abgefragt wurden.

  1. Also habe ich es modifiziert, um die .lines (0,1) auszuschließen, indem ich den geänderten Code unten in finalModule2 Einfügte:

    Public Enum vbLineNumbers_LabelTypes
        vbLabelColon    ' 0
        vbLabelTab      ' 1
    End Enum
    
    Public Enum vbLineNumbers_ScopeToAddLineNumbersTo
        vbScopeAllProc  ' 1
        vbScopeThisProc ' 2
    End Enum
              Sub AddLineNumbers(ByVal wbName As String, _
                                                          ByVal vbCompName As String, _
                                                          ByVal LabelType As vbLineNumbers_LabelTypes, _
                                                          ByVal AddLineNumbersToEmptyLines As Boolean, _
                                                          ByVal AddLineNumbersToEndOfProc As Boolean, _
                                                          ByVal Scope As vbLineNumbers_ScopeToAddLineNumbersTo, _
                                                          Optional ByVal thisProcName As String)
    
    ' USAGE RULES
    ' DO NOT MIX LABEL TYPES FOR LINE NUMBERS! IF ADDING LINE NUMBERS AS COLON TYPE, ANY LINE NUMBERS AS VBTAB TYPE MUST BE REMOVE BEFORE, AND RECIPROCALLY ADDING LINE NUMBERS AS VBTAB TYPE
    
        Dim i As Long
        Dim j As Long
        Dim procName As String
        Dim startOfProcedure As Long
        Dim lengthOfProcedure As Long
        Dim endOfProcedure As Long
        Dim strLine As String
    
        With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
            .CodePane.Window.Visible = False
    
    If Scope = vbScopeAllProc Then
    
            For i = 1 To .CountOfLines - 1
    
                strLine = .Lines(i, 1)
                procName = .ProcOfLine(i, vbext_pk_Proc) ' Type d'argument ByRef incompatible ~~> Requires VBIDE library as a Reference for the VBA Project
    
                If procName <> vbNullString Then
                    startOfProcedure = .ProcStartLine(procName, vbext_pk_Proc)
                    bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)
                    countOfProcedure = .ProcCountLines(procName, vbext_pk_Proc)
    
                    prelinesOfProcedure = bodyOfProcedure - startOfProcedure
                    'postlineOfProcedure = ??? not directly available since endOfProcedure is itself not directly available.
    
                    lengthOfProcedure = countOfProcedure - prelinesOfProcedure ' includes postlinesOfProcedure !
                    'endOfProcedure = ??? not directly available, each line of the proc must be tested until the End statement is reached. See below.
    
                    If endOfProcedure <> 0 And startOfProcedure < endOfProcedure And i > endOfProcedure Then
                        GoTo NextLine
                    End If
    
                    If i = bodyOfProcedure Then inprocbodylines = True
    
                    If bodyOfProcedure < i And i < startOfProcedure + countOfProcedure Then
                        If Not (.Lines(i - 1, 1) Like "* _") Then
    
                            inprocbodylines = False
    
                            PreviousIndentAdded = 0
    
                            If Trim(strLine) = "" And Not AddLineNumbersToEmptyLines Then GoTo NextLine
    
                            If IsProcEndLine(wbName, vbCompName, i) Then
                                endOfProcedure = i
                                If AddLineNumbersToEndOfProc Then
                                    Call IndentProcBodyLinesAsProcEndLine(wbName, vbCompName, LabelType, endOfProcedure)
                                Else
                                    GoTo NextLine
                                End If
                            End If
    
                            If LabelType = vbLabelColon Then
                                If HasLabel(strLine, vbLabelColon) Then strLine = RemoveOneLineNumber(.Lines(i, 1), vbLabelColon)
                                If Not HasLabel(strLine, vbLabelColon) Then
                                    temp_strLine = strLine
                                    .ReplaceLine i, CStr(i) & ":" & strLine
                                    new_strLine = .Lines(i, 1)
                                    If Len(new_strLine) = Len(CStr(i) & ":" & temp_strLine) Then
                                        PreviousIndentAdded = Len(CStr(i) & ":")
                                    Else
                                        PreviousIndentAdded = Len(CStr(i) & ": ")
                                    End If
                                End If
                            ElseIf LabelType = vbLabelTab Then
                                If Not HasLabel(strLine, vbLabelTab) Then strLine = RemoveOneLineNumber(.Lines(i, 1), vbLabelTab)
                                If Not HasLabel(strLine, vbLabelColon) Then
                                    temp_strLine = strLine
                                    .ReplaceLine i, CStr(i) & vbTab & strLine
                                    PreviousIndentAdded = Len(strLine) - Len(temp_strLine)
                                End If
                            End If
    
                        Else
                            If Not inprocbodylines Then
                                If LabelType = vbLabelColon Then
                                    .ReplaceLine i, Space(PreviousIndentAdded) & strLine
                                ElseIf LabelType = vbLabelTab Then
                                    .ReplaceLine i, Space(4) & strLine
                                End If
                            Else
                            End If
                        End If
    
                    End If
    
                End If
    
    NextLine:
            Next i
    
    ElseIf AddLineNumbersToEmptyLines And Scope = vbScopeThisProc Then
    
    End If
    
            .CodePane.Window.Visible = True
        End With
    
    End Sub
              Function IsProcEndLine(ByVal wbName As String, _
                  ByVal vbCompName As String, _
                  ByVal Line As Long) As Boolean
    
    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
    If Trim(.Lines(Line, 1)) Like "End Sub*" _
                Or Trim(.Lines(Line, 1)) Like "End Function*" _
                Or Trim(.Lines(Line, 1)) Like "End Property*" _
                Then IsProcEndLine = True
    End With
    
    End Function
              Sub IndentProcBodyLinesAsProcEndLine(ByVal wbName As String, ByVal vbCompName As String, ByVal LabelType As vbLineNumbers_LabelTypes, ByVal ProcEndLine As Long)
        Dim procName As String
        Dim startOfProcedure As Long
        Dim endOfProcedure As Long
    
        With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
    
            procName = .ProcOfLine(ProcEndLine, vbext_pk_Proc)
            bodyOfProcedure = .ProcBodyLine(procName, vbext_pk_Proc)
            endOfProcedure = ProcEndLine
            strEnd = .Lines(endOfProcedure, 1)
    
            j = bodyOfProcedure
            Do Until Not .Lines(j - 1, 1) Like "* _" And j <> bodyOfProcedure
    
                strLine = .Lines(j, 1)
    
                If LabelType = vbLabelColon Then
                    If Mid(strEnd, Len(CStr(endOfProcedure)) + 1 + 1 + 1, 1) = " " Then
                        .ReplaceLine j, Space(Len(CStr(endOfProcedure)) + 1) & strLine
                    Else
                        .ReplaceLine j, Space(Len(CStr(endOfProcedure)) + 2) & strLine
                    End If
                ElseIf LabelType = vbLabelTab Then
                    If endOfProcedure < 1000 Then
                        .ReplaceLine j, Space(4) & strLine
                    Else
                        Debug.Print "This tool is limited to 999 lines of code to work properly."
                    End If
                End If
    
                j = j + 1
            Loop
    
        End With
    End Sub
              Sub RemoveLineNumbers(ByVal wbName As String, ByVal vbCompName As String, ByVal LabelType As vbLineNumbers_LabelTypes)
        Dim i As Long
        With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
            'MsgBox ("nr of lines = " & .CountOfLines & vbNewLine & "Procname = " & procName)
                'MsgBox ("nr of lines REMEMBER MUST BE LARGER THAN 7! = " & .CountOfLines)
            For i = 1 To .CountOfLines
                procName = .ProcOfLine(i, vbext_pk_Proc)
                If procName <> vbNullString Then
                    If i > 1 Then
                            'MsgBox ("Line " & i & " is a body line " & .ProcBodyLine(procName, vbext_pk_Proc))
                        If i = .ProcBodyLine(procName, vbext_pk_Proc) Then inprocbodylines = True
                            If .Lines(i - 1, 1) <> "" Then
                                'MsgBox (.Lines(i - 1, 1))
                            End If
                        If Not .Lines(i - 1, 1) Like "* _" Then
                            'MsgBox (inprocbodylines)
                            inprocbodylines = False
                                'MsgBox ("recoginized a line that should be substituted: " & i)
                            'MsgBox ("about to replace " & .Lines(i, 1) & vbNewLine & " with: " & RemoveOneLineNumber(.Lines(i, 1), LabelType) & vbNewLine & " with label type: " & LabelType)
                            .ReplaceLine i, RemoveOneLineNumber(.Lines(i, 1), LabelType)
                        Else
                            If IsInProcBodyLines Then
                                ' do nothing
                                    'MsgBox (i)
                            Else
                                .ReplaceLine i, Mid(.Lines(i, 1), RemovedChars_previous_i + 1)
                            End If
                        End If
                    End If
                Else
                ' GoTo NextLine
                End If
    NextLine:
            Next i
        End With
    End Sub
              Function RemoveOneLineNumber(ByVal aString As String, ByVal LabelType As vbLineNumbers_LabelTypes)
        RemoveOneLineNumber = aString
        If LabelType = vbLabelColon Then
            If aString Like "#:*" Or aString Like "##:*" Or aString Like "###:*" Or aString Like "####:*" Then
                RemoveOneLineNumber = Mid(aString, 1 + InStr(1, aString, ":", vbTextCompare))
                If Left(RemoveOneLineNumber, 2) Like " [! ]*" Then RemoveOneLineNumber = Mid(RemoveOneLineNumber, 2)
            End If
        ElseIf LabelType = vbLabelTab Then
            If aString Like "#   *" Or aString Like "##  *" Or aString Like "### *" Or aString Like "#### *" Then RemoveOneLineNumber = Mid(aString, 5)
            If aString Like "#" Or aString Like "##" Or aString Like "###" Or aString Like "####" Then RemoveOneLineNumber = ""
        End If
    End Function
              Function HasLabel(ByVal aString As String, ByVal LabelType As vbLineNumbers_LabelTypes) As Boolean
        If LabelType = vbLabelColon Then HasLabel = InStr(1, aString & ":", ":") < InStr(1, aString & " ", " ")
        If LabelType = vbLabelTab Then
            HasLabel = Mid(aString, 1, 4) Like "#   " Or Mid(aString, 1, 4) Like "##  " Or Mid(aString, 1, 4) Like "### " Or Mid(aString, 1, 5) Like "#### "
        End If
    End Function
              Function RemoveLeadingSpaces(ByVal aString As String) As String
        Do Until Left(aString, 1) <> " "
            aString = Mid(aString, 2)
        Loop
        RemoveLeadingSpaces = aString
    End Function
              Function WhatIsLineIndent(ByVal aString As String) As String
        i = 1
        Do Until Mid(aString, i, 1) <> " "
            i = i + 1
        Loop
        WhatIsLineIndent = i
    End Function
    
              Function HowManyLeadingSpaces(ByVal aString As String) As String
        HowManyLeadingSpaces = WhatIsLineIndent(aString) - 1
    End Function
    

Mit dem Aufruf der Ersetzung für sub learn() mit dem folgenden Code, eingefügt in temporärmodule3:

    Sub AddLineNumbers_vbLabelColon()
    AddLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbscopeallproc
End Sub

Sub AddLineNumbers_vbLabelTab()
    AddLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelTab, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbscopeallproc
End Sub

Sub RemoveLineNumbers_vbLabelColon()
    RemoveLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelColon
End Sub

Sub RemoveLineNumbers_vbLabelTab()
    RemoveLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelTab
End Sub

Jetzt funktionierte es (Hinzufügen und Entfernen von Zeilennummern, wobei alle 4 Methoden zum Aufrufen des Hinzufügens/Entfernens von Zeilennummern in temporärmodule2 Für ein einzelnes Sub in einem Modul ( module1 Im Beispielfall). Also habe ich versucht, 2 U-Boote hintereinander in dasselbe Modul zu setzen. In diesem Fall hat der Code die zusätzlichen Zeilennummern in der zweiten Unterzeile nicht geändert.

  1. Also habe ich die folgende Zeile über Module1 Eingefügt:

    Global allow_for_line_addition As String
    

So sieht Module1 Aus:

Global allow_for_line_addition As String
  Sub learn()
    ThisWorkbook.Worksheets("Sheet1").Activate
    Range("A1").Activate
    Range("A1").Select
    Range("A1").Value = Range("A1").Value + 1
End Sub
Sub learn2()
    ThisWorkbook.Worksheets("Sheet1").Activate
    Range("A1").Activate
    Range("A1").Select
    Range("A1").Value = Range("A1").Value + 1
End Sub

Jetzt wurden die Zeilennummern zum gesamten Modul hinzugefügt, aber nicht die Zeilennummern aus dem gesamten Modul entfernt. Daher habe ich den Entfernungscode von hymced s answer as well and already put it in the long code of **final** Module2` bearbeitet.

Hinweis: Wenn Sie nach dem Ende eines Unterelements oder einer Funktion leere weiße Linien haben, werden bei jeder Ausführung des Skripts weiterhin weiße Linien hinzugefügt, um die Zeilennummern hinzuzufügen (die nach der ersten Ausführung einfach die Zeilennummern aktualisieren). Diese leeren Zeilennummern verursachen beim Ausführen des Codes einen Fehler. Sie sollten sie also einmal entfernen. Wenn am Ende eines Unterzeichens keine Leerzeilen stehen, werden durch diesen Code auch keine neuen hinzugefügt.

  1. Um Zeilennummern zu all Ihren Modulen in Ihrer Arbeitsmappe hinzuzufügen, behalten Sie den langen Code in finalModule2 Bei, während ich ihn änderte, und ersetzen Sie den Code von temporaryModule3 Mit finalModule3:

    Global allow_for_line_addition As String 'this is just so that you can automatically add linenumbers
            Sub remove_line_numbering_all_modules()
    'source: https://stackoverflow.com/questions/36791473/vba-getting-the-modules-in-workbook
    'This code numbers all the modules in your .xlsm
        Dim vbcomp As VBComponent
        Dim modules As Collection
    Set modules = New Collection
        For Each vbcomp In ThisWorkbook.VBProject.VBComponents
            'if normal or class module
            If ((vbcomp.Type = vbext_ct_StdModule) Or (vbcomp.Type = vbext_ct_ClassModule)) Then
                   'V0:
                   RemoveLineNumbers wbName:=ThisWorkbook.name, vbCompName:=vbcomp.name, LabelType:=vbLabelColon
                   'V1:
                   'Call RemoveLineNumbers(ThisWorkbook.name, vbcomp.name)
            End If
        Next vbcomp
    End Sub
    

    Und füge den folgenden Code zu finalModule4 Hinzu:

    Global allow_for_line_addition As String 'this is just so that you can automatically add linenumbers
    'This sub adds line numbers to all the modules after you have added the following line to every module
    'add tools references Microsoft visual basic for applications (5.3) as checked
    'Source httpsstackoverflow.comquestions40731182Excel-vba-how-to-turn-on-line-numbers-in-code-editor50368332#50368332
            Sub add_line_numbering_all_modules()
    'source: https://www.stackoverflow.com/questions/36791473/vba-getting-the-modules-in-workbook
    'This code numbers all the modules in your .xlsm
        Dim vbcomp As VBComponent
        Dim modules As Collection
        Set modules = New Collection
        For Each vbcomp In ThisWorkbook.VBProject.VBComponents
            'if normal or class module
            If ((vbcomp.Type = vbext_ct_StdModule) Or (vbcomp.Type = vbext_ct_ClassModule)) Then
                   'V0:
                   Call AddLineNumbers(ThisWorkbook.name, vbcomp.name, vbLabelColon, True, True, vbScopeAllProc)
                   'v1
                   'Call AddLineNumbers(ThisWorkbook.name, vbcomp.name)
            End If
        Next vbcomp
    End Sub
    

dabei können Sie entweder "Book1.xlsm" durch den Namen Ihrer eigenen Arbeitsmappe oder durch thisworkbook (mit dem Vermerk "") ersetzen oder umgekehrt.

1
a.t.