2016-11-21 20 views
4

Excel VBAコードエディタで行番号を有効にするにはどうすればよいですか。私はExcel 2013のバージョンを使用しています。Excel VBA - コードエディタで行番号を有効にする方法

ありがとうございます。

+1

私が知っている限り、あなたはいくつかのコード筋肉鍛錬をしないと、 –

+1

あなたはMZ Tools(それはとにかく価値がある)のようなものをダウンロードすることなくできるとは思わない。 – SJR

+3

ヘルプの下のリボンにはすでにあります。エディタでカーソルを動かすと、現在入っている行番号が表示されます。 – Rockstar

答えて

4

ここに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 ActiveSheet30: ActiveSheetとして再インデントされます
  • [WIP]直接パラメータ
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 
として、現在のモジュールの/ procで電話をかけることがVBE IDEコマンドの追加

あなたはこのような呼び出しを行うことができます。

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の
  • の外で許可されていない前に許可されていませんコード行ごとに1つのラベル/行番号~~>行番号以外の既存のラベルをテストする必要があります。そうしないと、行番号を強制しようとしてコンパイルエラーが発生します。
  • 既に特殊なVBA意味を持つ文字を使用することはできません~~>許可される文字は[aZ]、[0-9]、é、è、ô、ù、€、£、§、 !
  • コンパイラはラベルの前のスペースをトリミングします~~>ラベルがある場合、ラインの最初の文字はラベルの最初の文字です。スペースにすることはできません。
  • コロンで行番号を追加すると、 ":"と拳の次の文字の間にスペースが挿入されます。
  • タブ/スペースで行番号を追加する場合、少なくとも最後の桁と最初の次のcharの間に1つのスペースがあり、コンパイラーはコロン区切り記号の付いたラベルと同じように追加しません。
  • 。ReplaceLineメソッドは、新しい行を選択するとき、または手動でコンパイルを再起動するときにデザインモードと同じようにコンパイルエラーを表示せずに、コンパイルルールをオーバーライドします。
  • コンパイラが「VBA環境/システムより速い」 .Linesプロパティが呼び出されて新しい文字列が取得された場合、空白(コロン文字と文字列の最初の文字の間)が既にその文字列に追加されています。
  • .ReplaceLineが呼び出された後(編集中のモジュールの内部または外部から)、コードが実行されて実行がリセットされるまでデバッグモードに入ることはできません。
+0

それは価値がありますが、[別のMicrosoft Excel MVP](https://mvp.microsoft.com/en-us/PublicProfile/5002943) ?fullName = Mathieu%20%20Guindon)は、VBAで 'Erl'と行番号を使用することにしっかりと反対しています。 1) 'Erl'は'整数 'の解像度を持っていますが、 'Long'の行番号は完全に正当なものであり、' Erl'は定義によって壊されます(どの行が-12345ですか?)、そして2) 'Erl'は、最後に見つかった行番号*を返します。これは、行番号*が必要であることを意味します。*それを使用するために、Commodore-64の爆風のように見えるコード。 –

関連する問題