Excel VBA - 如何在代码编辑器中打开行号

时间:2016-11-21 23:17:02

标签: excel-vba vba excel

请帮忙:如何在Excel VBA代码编辑器中打开行号?我使用的是Excel 2013版本。

谢谢。

2 个答案:

答案 0 :(得分:6)

这是我在VBE IDE中添加行号的代码。它是Excel MVP mikerickson提供的here解决方案的改进。我已经解决了这个问题,因为在我遇到过的极少数情况下,VBE无法进入调试模式,例如在代码中有.ReplaceLine方法时。实际上,一旦执行它就无法进入调试模式,因此Erl可能对调试很有用(而不是Debug.Print)。我添加了几个功能,例如:

  
      
  • 可以将行号添加为标签:10: Dim foo as bar或通过标签从代码中分隔的单个数字:10 Dim foo as bar
  •   
  • 可以将行号添加到过程语句的结尾,并将过程声明行的缩进与numberered的End语句行匹配。或者没有。
  •   
  • 是否可以为空行添加行号
  •   
  • [WIP]可以将行号添加到模块中的特定过程
  •   
  • [WIP]匹配代码行的所有缩进与行号以匹配缩进的最后一行的缩进。如果最后一行为200: End Sub,则行30: With ActiveSheet将重新缩进为30: ActiveSheet
  •   
  • [WIP]添加VBE IDE命令直接以当前模块/ proc作为参数进行调用
  •   
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

你可以这样打电话:

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

作为提醒,这里有一些关于行号的编译规则:

    在子/函数声明语句之前不允许
  • 不允许在proc之外
  • 不允许在行继续符“_”(下划线)
  • 之后的行上
  • 每个代码行不允许有多个标签/行号~~&gt;必须测试除行号以外的现有标签,否则将尝试强制使用行号进行编译错误。
  • 不允许使用已经具有特殊VBA含义的字符~~&gt;允许的字符是[a-Z],[0-9],é,è,ô,ù,€,£,§甚至“:”一个人!
  • 编译器将修剪标签之前的任何空格~~&gt;因此,如果有标签,该行的第一个字符是标签的第一个字符,它不能是空格。
  • 使用冒号附加行号将导致在“:”和第一个下一个字符之间插入空格(如果没有)
  • 当附加一个带有制表符/空格的行号时,最后一个数字和第一个下一个字符之间必须至少有一个空格,编译器不会像对带有冒号分隔符的标签那样添加空格
  • .ReplaceLine方法将覆盖编译规则,而不会像在设计模式中选择新行或手动重新启动编译时那样显示任何编译错误
  • 编译器“比VBA环境/系统更快”:例如,在使用.ReplaceLine插入带冒号且没有任何空格的行号之后,如果调用.Lines属性来获取新字符串,空格(冒号字符和字符串的第一个字符之间)已经附加在该字符串中!
  • 在调用.ReplaceLine之后(从编辑的模块内部或外部)进入调试模式是不可能的,直到代码运行并重置执行。

答案 1 :(得分:0)

excel 2016的

简短回答,尚未在2013年尝试过。

做一次:

  1. 最终 Module2中的大代码粘贴到工作簿中的此答案中。
  2. 在此工作簿的答案中粘贴最终 Module3的代码。
  3. 在此工作簿的答案中粘贴最终 Module4的代码。
  4. 然后粘贴第Global allow_for_line_addition As String行,这样您就可以自动添加每个第一行上方/的内容 模块。
  5. 删除每个模块末尾的所有空行(因此,在模块的最后end subend functionEnd Property之后不会输入任何内容。
  6. 在VBA编辑器中,虽然没有运行代码,但没有进入&#34;中断&#34; -mode:点击工具&gt;引用&gt;标记:`Microsoft Visual Basic for Applications Extensibility 5.3&#34;
  7. 每次修改代码时都会这样做:

    1. *运行最终 Module3的代码,以删除工作簿中所有模块的行号。
    2. *运行 final Module4的代码,为工作簿中的所有模块添加行号。
    3. (*因为有时候如果你剪掉线或移动它们会出现错误(例如将line 2440:放在line 2303:之上)。通过删除并重新添加它们,行编号会自动更正再次)

      长答案(包括学习步骤和尝试) - 对我而言,实施hymced的答案并不简单,因此我记录了在VBA代码中为行模块添加行号所需的步骤编辑器(*并再次删除它们)。我按照以下步骤使其正常工作。

      1. this link我了解到vbcomponent可以是一个模块。
      2. 我将给出的第一个代码复制到临时 Module2,并将第二个代码复制到临时 Module3
      3. 然后将临时 Module3中第二个代码的第一行修改为:

        AddLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
        
      4. 我收到了错误:

        procName = .ProcOfLine(i, vbext_pk_Proc) ` Type d`argument ByRef incompatible ~~> Requires VBIDE library as a Reference for the VBA Project
        
      5. 所以我读到我必须启用VBIDE库。

      6. 所以我停止了代码,点击了工具&gt;引用,找不到VBIDE库。

      7. this forum上,我发现通过添加引用来启用VBIDE VBA可扩展性库:

      8.   

        单击VBE中的Tools-References,然后向下滚动并勾选   Microsoft Visual Basic for Applications可扩展性5.3。

        的条目

        所以在这样做之后,第一个错误消失了,它没有突出显示任何一行但却给出了错误&#34;无效的过程调用或参数&#34;。

        1. 由于我仍然不确定vbCompName,我认为可能需要知道sub而不是模块,所以我尝试修改临时 {{1转到:

          Module3
        2. 突出了这一行:

          AddLineNumbers wbName:="Book1.xlsm", vbCompName:="learn", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc
          
        3. 说:With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule 。 (所以我也尝试过:subscript out of rangeModule1.learn,产生Module1:learn - 错误。

          事实证明,

          subscript out of range
          如果要提供行号的子号位于名为AddLineNumbers wbName:="Book1.xlsm", vbCompName:="Module1", LabelType:=vbLabelColon, AddLineNumbersToEmptyLines:=True, AddLineNumbersToEndOfProc:=True, Scope:=vbScopeAllProc 的模块中,则

          是调用替换子的正确方法。第一个错误描述发生,但它确实将行号添加到代码中(包含Module1的第一行和包含sub ...的最后一行除外。在名为end sub的{​​{1}}中进行了测试名为Module1的excel 2016工作簿。完整性sub learn()包括:

          Book1.xlsm

          然而,在回来的路上,删除行号,它产生了一个错误,因为它询问了learnSub learn() ThisWorkbook.Worksheets("Sheet1").Activate Range("A1").Activate Range("A1").Select Range("A1").Value = Range("A1").Value + 1 End Sub 的.lines(0,1)

          1. 所以我将其修改为排除.lines(0,1),方法是将更改后的代码放入 final procName

            Sub AddLineNumbers...
          2. 使用下面的代码调用Module2上的替换,粘贴在临时 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

            sub learn()

            现在它可以工作(添加和删除行号,所有4种方法都可以调用在临时 module3中添加/删除行号来为模块中的单个子目录添加/删除行号在示例案例中 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 。所以我试图在同一个模块中放置2个子组件。在这种情况下,代码没有将添加行号更改为第二个子组件。

            1. 所以我在module2上面添加了以下一行:

              module1
            2. 使Module1看起来像:

              Global allow_for_line_addition As String
              

              现在它将行号添加到整个模块,但它没有从整个模块中删除行号,因此我编辑了hymced Module1 Module2`的删除代码。

              注意:如果在子或函数结束后有空白行,则每次运行脚本时都会添加白线以添加行号(在第一次运行后,只需更新行号) )。这些空行号在执行代码时会导致错误,因此您应该删除它们一次。如果sub的末尾没有空行,则此代码也不会添加新行。

              1. 要为工作簿中的所有模块添加行号,请在修改它时将长代码保留在最终 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 中并替换临时代码 s answer as well and already put it in the long code of **final** 最终 Module2

                Module3

                并将以下代码添加到最终 Module3

                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
                
              2. 您可以将Module4替换为您自己的工作簿的名称,或者使用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 替换(注意不是&#34;&#34;),反之亦然。