如何使用行号自动填充VBA编辑器?

时间:2016-12-06 17:10:37

标签: vba basic

出于调试原因,我希望在我的VBA代码中包含行号。这将使我知道发生特定错误的位置。

是否有自动功能(例如设置中的选项)?或者我需要编写自己的宏吗?

如果我需要编写自己的宏来完成这项任务,我该如何做这样的事情呢?

8 个答案:

答案 0 :(得分:14)

您不想要行号。

不是"调试原因",不是为了什么。行号被弃用是因为:在程序存在之前,它们是古代的遗物,而GOTO是获得任何地方的唯一途径。

Erl仅在引发错误之前返回上次遇到的行号。如果您记录错误,这可能意味着误导性错误日志:

Sub DoSomething()
10 On Error GoTo 50
   Debug.Print 42 / 0
30 Exit Sub

50 Debug.Print "Error raised on line " & Erl 'returns 10
End Sub

此外,行号只有Integer分辨率(VBA模块最多可以有65,535行,这是分辨率的两倍),如果你不这样做,它会默默地失败并愉快地报告错误的行号牢记这一点:

Sub DoSomething()
99997 On Error GoTo 99999
99998 Debug.Print 42 / 0
99999
      Debug.Print Erl   'Prints 34462 - and which line is that?
End Sub

任何严肃的VBA应用程序都将使用结构化错误处理

编写小型的专业程序(即遵循现代最佳实践的编写代码),行号变得毫无意义。

行号是颈部疼痛的维持;它们使代码混乱并使其整体难以阅读(因此也需要调试)。

也就是说,IIRC MZ-Tools 3具有这样的功能。

请记住,当行号是一个东西时BASIC看起来像这样:

10 GOSUB 100
20 GOSUB 1000
99 END
100 REM CLEAR SCREEN
110 PRINT CHR$(147)
120 RETURN
200 REM MODULO
210 LET MOD% = V%-INT(V%/FB%)*FB%
220 RETURN
1000 REM INIT VARIABLES
1010 LET FIZZ$ = "FIZZ"
1011 LET BUZZ$ = "BUZZ"
1020 LET FIZZ% = 3
1021 LET BUZZ% = 5
1030 LET MIN% = 1
1031 LET MAX% = 15
1100 PRINT FIZZ$ + ":" + STR$(FIZZ%)
1101 PRINT BUZZ$ + ":" + STR(BUZZ%)
1102 PRINT FIZZ$ + BUZZ$ + ":" + STR$(FIZZ%*BUZZ%)
1105 PRINT
2000 REM ACTUAL FIZZBUZZ LOOP
2010 FOR X = MIN% TO MAX%
2015 LET RESULT$ = STR$(X)
2020 LET FB% = FIZZ%*BUZZ%
2021 LET V% = X
2024 GOSUB 200
2025 IF MOD%=0 THEN LET RESULT$=FIZZ$+BUZZ$ : GOTO 2050
2030 LET FB% = FIZZ%
2031 GOSUB 200
2035 IF MOD%=0 THEN LET RESULT$=FIZZ$ : GOTO 2050
2040 LET FB% = BUZZ%
2041 GOSUB 200
2045 IF MOD%=0 THEN LET RESULT$=BUZZ$ : GOTO 2050
2050 PRINT RESULT$
2090 NEXT X
2099 RETURN

以上是一个有效的Commodore 64 BASIC 2.0 程序。 VBA具有出色的向后兼容性。只需稍加修改,它就可以在VBA中运行:

Sub Main()
10     GoSub 100
20     GoSub 1000
99     End
100     Rem CLEAR SCREEN
110     'Debug.Print Chr$(147) 'Chr$(147) was a special character on C64
120     Return
200     Rem MODULO
210     Let Modulo% = V% - Int(V% / FB%) * FB%
220     Return
1000     Rem INIT VARIABLES
1010     Let FIZZ$ = "FIZZ"
1011     Let BUZZ$ = "BUZZ"
1020     Let FZZ% = 3
1021     Let BZZ% = 5
1030     Let Min% = 1
1031     Let Max% = 15
1100     Debug.Print FIZZ$ + ":" + Str$(FZZ%)
1101     Debug.Print BUZZ$ + ":" + Str(BZZ%)
1102     Debug.Print FIZZ$ + BUZZ$ + ":" + Str$(FZZ% * BZZ%)
1105     Debug.Print
2000     Rem ACTUAL FIZZBUZZ LOOP
2010     For X = Min% To Max%
2015     Let RESULT$ = Str$(X)
2020     Let FB% = FZZ% * BZZ%
2021     Let V% = X
2024     GoSub 200
2025     If Modulo% = 0 Then Let RESULT$ = FIZZ$ + BUZZ$: GoTo 2050
2030     Let FB% = FZZ%
2031     GoSub 200
2035     If Modulo% = 0 Then Let RESULT$ = FIZZ$: GoTo 2050
2040     Let FB% = BZZ%
2041     GoSub 200
2045     If Modulo% = 0 Then Let RESULT$ = BUZZ$: GoTo 2050
2050     Debug.Print RESULT$
2090     Next X
2099     Return
End Sub

不要写出1980年的代码,我们已经30年了。

Commodore-64 BASIC 2.0 FIZZBUZZ

答案 1 :(得分:2)

我使用此代码为我的Excel项目添加行号。我在网上发现了一段时间,我不记得我从哪里得到它,所以归功于最初写这篇文章的人:

Sub AddLineNumbers(wbName As String, vbCompName As String)
    'See MakeUF
    Dim i As Long, j As Long, lineN As Long
    Dim procName As String
    Dim startOfProceedure As Long
    Dim lengthOfProceedure As Long
    Dim newLine As String

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

        For i = 1 To .CountOfLines
            procName = .ProcOfLine(i, vbext_pk_Proc)

            If procName <> vbNullString Then
                startOfProceedure = .ProcStartLine(procName, vbext_pk_Proc)
                lengthOfProceedure = .ProcCountLines(procName, vbext_pk_Proc)

                If startOfProceedure + 1 < i And i < startOfProceedure + lengthOfProceedure - 1 Then
                    newLine = RemoveOneLineNumber(.Lines(i, 1))
                    If Not HasLabel(newLine) And Not (.Lines(i - 1, 1) Like "* _") Then
                        .ReplaceLine i, CStr(i) & ":" & newLine
                    End If
                End If
            End If

        Next i
        .CodePane.Window.Visible = True
    End With
End Sub

Sub RemoveLineNumbers(wbName As String, vbCompName As String)
    'See MakeUF
    Dim i As Long
    With Workbooks(wbName).VBProject.VBComponents(vbCompName).CodeModule
        For i = 1 To .CountOfLines
            .ReplaceLine i, RemoveOneLineNumber(.Lines(i, 1))
        Next i
    End With
End Sub

Function RemoveOneLineNumber(aString)
    RemoveOneLineNumber = aString
    If aString Like "#:*" Or aString Like "##:*" Or aString Like "###:*" Then
        RemoveOneLineNumber = Mid(aString, 1 + InStr(1, aString, ":", vbTextCompare))
    End If
End Function

Function HasLabel(ByVal aString As String) As Boolean
    HasLabel = InStr(1, aString & ":", ":") < InStr(1, aString & " ", " ")
End Function

你必须修改它以满足你的需求,因为你在Access工作,但我确信它的主要部分仍然适用。在Excel中,有一个userform用于启动您指定的模块的代码,但您应该只能传入模块名称(vbCompName)来指定模块。我不熟悉Access VBA,因此我不确定您在代码中替换Workbooks(wbName)的内容。

答案 2 :(得分:2)

VBA编辑器在“标准”工具栏下有一个查看行号的内置方式:

enter image description here

当您选择一行代码时,行号将在“Ln”旁边显示。

答案 3 :(得分:1)

MZ-Tools for VBA具有向单个函数,模块或整个项目添加和删除行号的功能。

请参阅http://www.mztools.com/v8/onlinehelp/index.html?add_remove_line_numbers.htm

注意1:我发现将行号增量配置为1而不是10更好。您永远不会在中间手动添加行号 - 每当您编辑代码时,首先删除行号,然后在您添加时将它们添加回来已经完成了。

注意2:直到几年前,MZ-Tools还有3.0版的免费版本,但很难找到副本。但这是一项很好的投资 - 还有许多其他有用的功能(例如自动添加错误处理程序)。

答案 4 :(得分:1)

这适用于我......将其添加到自己的模块中。调用代码将打开或关闭行号。在引号中添加模块标题和/或过程标题将仅更新名为的模块或过程。

    Option Compare Database
    Option Explicit

    Sub AddLineNumbers(Optional vbCompName As String, Optional vbCompSubName As String)
    On Error Resume Next

        DoCmd.Hourglass True
        Application.VBE.ActiveVBProject.References.AddFromGuid "{0002E157-0000-0000-C000-000000000046}", 5, 0
        Call ExecuteAddLineNumbers(vbCompName, vbCompSubName)
        DoCmd.Hourglass False

    End Sub

    Sub ExecuteAddLineNumbers(Optional vbCompName As String, Optional vbCompSubName As String)
    On Error GoTo Err_Handler

        'create a reference to the Microsoft Visual Basic for Applications Extensibility library
        Dim i As Long, j As Long, lineN As Long
        Dim procName As String
        Dim startOfProceedure As Long
        Dim lengthOfProceedure As Long
        Dim newLine As String
        Dim objComponent As Object
        Dim lineNumber As Long
        Dim HasLineNumbers As Boolean

        For Each objComponent In Application.VBE.ActiveVBProject.VBComponents
            If (vbCompName = vbNullString Or objComponent.Name = vbCompName) And objComponent.Name <> _
            Application.VBE.ActiveCodePane.CodeModule.Name) Then
                Debug.Print objComponent.Name
                With objComponent.CodeModule
                    .CodePane.Window.Visible = False
                    For i = 1 To .CountOfLines
                        'Debug.Print .ProcOfLine(i, vbext_pk_Proc)
                        If procName = "" And .ProcOfLine(i, vbext_pk_Proc) <> "" Then
                            procName = .ProcOfLine(i, vbext_pk_Proc)
                            'vbext_pk_Get    Specifies a procedure that returns the value of a property.
                            'vbext_pk_Let    Specifies a procedure that assigns a value to a property.
                            'vbext_pk_Set    Specifies a procedure that sets a reference to an object.
                            'vbext_pk_Proc   Specifies all procedures other than property procedures.
                            'type=vbext_ct_ClassModule
                            'type=vbext_ct_StdModule
                            'type=vbext_ct_Document
                            If objComponent.Type = vbext_ct_ClassModule Then
                                If InStr(.Lines(i + 1, 1), " Let ") > 0 Then
                                    startOfProceedure = .ProcStartLine(procName, vbext_pk_Let)
                                    lengthOfProceedure = .ProcCountLines(procName, vbext_pk_Let)
                                ElseIf InStr(.Lines(i + 1, 1), " Get ") > 0 Then
                                    startOfProceedure = .ProcStartLine(procName, vbext_pk_Get)
                                    lengthOfProceedure = .ProcCountLines(procName, vbext_pk_Get)
                                ElseIf InStr(.Lines(i + 1, 1), " Set ") > 0 Then
                                    startOfProceedure = .ProcStartLine(procName, vbext_pk_Set)
                                    lengthOfProceedure = .ProcCountLines(procName, vbext_pk_Set)
                                Else
                                    startOfProceedure = .ProcStartLine(procName, vbext_pk_Proc)
                                    lengthOfProceedure = .ProcCountLines(procName, vbext_pk_Proc)
                                End If
                            Else
                                startOfProceedure = .ProcStartLine(procName, vbext_pk_Proc)
                                lengthOfProceedure = .ProcCountLines(procName, vbext_pk_Proc)
                            End If
                            lineNumber = 10
                            HasLineNumbers = .Find("##  ", startOfProceedure + 1, 1, startOfProceedure + lengthOfProceedure - 1, 1, _
                            False, False, True)
                        End If

                        If (vbCompSubName = vbNullString And procName <> vbNullString) Or _
                           (vbCompSubName <> vbNullString And procName = vbCompSubName) Then

                            If startOfProceedure + 1 < i And i < startOfProceedure + lengthOfProceedure - 1 Then
                                newLine = RemoveOneLineNumber(.Lines(i, 1), HasLineNumbers)
                                If Trim(newLine) <> vbNullString Then
                                    If Not HasLabel(newLine) And Not (.Lines(i - 1, 1) Like "* _") Then
                                        If HasLineNumbers = False Then newLine = CStr(lineNumber) & vbTab & newLine
                                        .ReplaceLine i, newLine
                                        lineNumber = lineNumber + 10
                                    ElseIf Not HasLineNumbers Then
                                        .ReplaceLine i, vbTab & newLine
                                    Else
                                        .ReplaceLine i, newLine
                                    End If
                                End If
                            ElseIf i = startOfProceedure + lengthOfProceedure - 1 Then
                                procName = ""
                            End If
                        Else
                            procName = ""
                        End If

                    Next i
                    .CodePane.Window.Visible = True
                End With
            End If
        Next objComponent

    Exit Sub

    Err_Handler:
        MsgBox (Err.Number & ": " & Err.Description)

    End Sub

    Function RemoveOneLineNumber(aString As String, HasLineNumbers As Boolean)
        Dim i As Double
        RemoveOneLineNumber = aString
        i = ((Len(Trim(Str(Val(aString)))) / 4) - Int(Len(Trim(Str(Val(aString)))) / 4)) * 4
        If aString Like "#*" Then
            RemoveOneLineNumber = Space(i) & Mid(aString, InStr(1, aString, " ", vbTextCompare))
            RemoveOneLineNumber = Right(aString, Len(aString) - 4)
        ElseIf HasLineNumbers And aString Like "    *" Then
            RemoveOneLineNumber = Right(aString, Len(aString) - 4)
        End If
    End Function

    Function HasLabel(ByVal aString As String) As Boolean
        HasLabel = False
        If Right(Trim(aString), 1) = ":" Or _
            Left(Trim(aString), 3) = "Dim" Or _
            Left(Trim(aString), 3) = "ReDim" Or _
            Left(Trim(aString), 1) = "'" Or _
            Left(Trim(aString), 6) = "Option" Or _
            Left(Trim(aString), 5) = "Debug" Or _
            Left(Trim(aString), 3) = "Sub" Or _
            Left(Trim(aString), 11) = "Private Sub" Or _
            Left(Trim(aString), 10) = "Public Sub" Or _
            Left(Trim(aString), 8) = "Function" Or _
            Left(Trim(aString), 12) = "End Function" Or _
            Left(Trim(aString), 8) = "Property" Or _
            Left(Trim(aString), 12) = "End Property" Or _
            Left(Trim(aString), 7) = "End Sub" Then HasLabel = True

    End Function

答案 5 :(得分:1)

任何体面的错误处理程序将报告的不仅仅是行号。它将报告错误代码、描述和发生错误的模块。不管 ERL 是否在整个应用程序中重复行号,如果您找不到报告的其他线索的问题,也许您需要休假。或者,地狱,添加一个变量来增加模块级 alpha 代码作为行号的附属物,例如“newERL = strProcLevel & ERL”,为您提供“A12345”作为行号。

答案 6 :(得分:0)

这不是100%测试,但使用VBA可扩展性,您可以执行以下操作

Sub line_number(strModuleName As String)

Dim vbProj As VBProject
Dim vbComp As VBComponent
Dim cmCode As CodeModule
Dim intLine As Integer

Set vbProj = Application.VBE.ActiveVBProject
Set vbComp = vbProj.VBComponents(strModuleName)
Set cmCode = vbComp.CodeModule

For intLine = 2 To cmCode.CountOfLines - 1
   cmCode.InsertLines intLine, intLine - 1 &  cmCode.Lines(intLine, 1)
   cmCode.DeleteLines intLine + 1, 1
Next intLine

End Sub

这给出了之前和之后的结果,但不推荐以这种方式改变。

答案 7 :(得分:0)

Arich的答案就像个人模块的魅力一样。如果要为整个工作簿提供(更新的)行号,请应用以下步骤* ^:

做一次:

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

    1. °运行Module3的代码,删除工作簿中所有模块的行号。
    2. °运行Module4的代码,为工作簿中的所有模块添加行号。
    3. <强> 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
      

      <强> 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
      

      <强> 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
      

      您可以将"Book1.xlsm"替换为您自己的工作簿的名称,或者使用thisworkbook(注意不是“”),反之亦然。

      • *请注意这在excel 2016中有效,我还没有在2013年尝试过。
      • ^这是Hemced的回答here.的修改版本,反过来看起来很像Arich的答案。
      • °因为有时候如果你将线条剪掉或移动它们会导致错误(例如将line 2440:放在line 2303:之上)。通过删除和重新添加它们,行号将再次自动更正。