如何在VBA编辑器中跳转到指定行号?

12

我正在使用Office 2010中的VBA。在顶部有一个框,显示着当前行号和列号,例如:

Ln 1480, Col 17

有没有一种方法可以直接跳转到代码编辑器中的另一行号(而不是执行),就像我在记事本中使用 Ctrl+G 一样?这个MSDN回答表明这是不可能的,但我希望有人已经找到了这种编辑器导航的方法。

我知道只需在下拉菜单中点击过程名称即可,但不幸的是,我正在处理一些数百行长的程序,直到我对它们进行重构,能够在我的错误跟踪器中包含行号并在解决问题时跳转到该行就会很好。


你可以在这里看看,看看它是否是一个合适的解决方案:http://www.mrexcel.com/forum/excel-questions/576449-code-line-numbers-visual-basic-applications.html 还有这里:http://www.mztools.com/v3/mztools3.aspx - sous2817
6个回答

11

为VBA IDE创建自己的JumpToLine过程

创建一个名为mdlJumpToLine的新模块,并添加以下方法:

Public Sub JumpToLine(line As Long)
    Application.VBE.ActiveCodePane.SetSelection line, 1, line, 1
End Sub
如果你想跳转到代码模块或类中的第1,234行(前提是该模块或类已经在当前代码窗格中打开),请在立即窗口中输入JumpToLine 1234并按回车键。如果该行已在视图中,则不会执行任何操作,但如果该行超出了屏幕范围,则它将自动滚动到屏幕的中央。
信任对VBA项目对象模型的访问
如果你遇到这个错误:“对象'_Application' 的方法“VBE” 失败”,你需要让程序可以访问VBE。你可以这样做(在Excel 2007中):转到主Excel窗口(而不是VBA IDE),然后点击“文件”--->“选项”--->“信任中心”--->“信任中心设置”--->“宏设置”,并勾选“信任对VBA项目对象模型的访问”复选框。从那时起,“JumpToLine”方法应该可以使用了。

我愿意打赌,将一个按钮和窗口添加到VBA IDE工具栏并将其打包为Addin不会太困难...请参见http://www.cpearson.com/excel/vbemenus.aspx获取提示。 - Blackhawk
对我来说,这只是输出我用于X的行号。 - Johnny Bones
@JohnnyBones 你能否调试一下,找出它是如何打印到即时窗口的吗?考虑到没有明确使用“debug.print”,这似乎是一种奇怪的行为。 - Blackhawk
我认为这是我的最佳选择,当我从即时命令行使用它时,它似乎运行得非常好。 - sigil

6
没有这样的功能。您可以使用编辑工具栏中的书签。如果您的编辑工具栏未显示,请转到“视图”下拉菜单,选择“工具栏”,然后选择“编辑”。
书签工具位于菜单的右侧。

enter image description here

这将允许您在代码中随意放置书签,然后通过单击前进或后退书签箭头在它们之间跳转。

这个答案对于那些无法更改被管理员禁用的TrustCenter设置的人特别有用。 - bluelDe
我怎么从来没有注意到这个功能?这肯定比记住行号或滚动条位置要好。谢谢。 - dra_red

2

这个过程会提示您输入行号,然后(有点)带您到该行所属的程序中。两件事情:它没有错误检查,所以需要一些工作; 如果您输入的数字大于总行数,它只会带您到下一个程序。但是,如果您输入30,它将带您到当前程序的第30行,而不仅仅是模块的第30行。

Public Sub GotoLine()

    Dim lLine As Long, lActiveLine As Long
    Dim sProc As String
    Dim ProcType As Long
    Dim vbaModule As CodeModule
    Dim vbaPane As CodePane

    lLine = Application.InputBox("Enter Line", "Go to Line", , , , , , 1)
    Set vbaPane = Application.VBE.ActiveCodePane
    Set vbaModule = vbaPane.CodeModule

    If lLine > 0 Then
        vbaPane.GetSelection lActiveLine, 0, 0, 0
        sProc = vbaModule.ProcOfLine(lActiveLine, vbext_pk_Proc)

        With vbaModule
            .CodePane.SetSelection .ProcStartLine(sProc, ProcType) + lLine, 1, .ProcStartLine(sProc, ProcType) + lLine + 1, 1
        End With
    End If

End Sub

1
如果您需要进行错误跟踪的帮助,为什么不使用“GoTo标签”呢?
我敢打赌您的错误跟踪工具会为您提供错误的ID或类似的信息。只需找到错误所在的部分并添加一行即可:
Bug1234: 'you may even add comments on the issue/bug

这行代码在执行时会被忽略,你可以使用Ctrl+F查找标签名称。

优点是,如果您重构或更改代码中的任何内容,引用将保持有效,而如果您仅使用行号,则任何修改都将使引用无效。


是的,这比行号更稳定,我一直在使用它,但对于那些只有只读访问权限的工作簿并想要报告已发布版本中的错误(因此行号不会受到开发版本更改的影响)的人来说,这不是一个可行的解决方案。 - sigil
我明白了,那很有道理。在这种情况下,“JumpToLine”函数似乎更合适。 - Paulo Avelar

0
迪克的解决方案非常出色,但是这个版本可以从即时窗口调用。

`

Public Sub IDEGotoLine()

Dim lLine As Long, lActiveLine As Long
Dim sProc As String
Dim ProcType As Long
Dim thisModule As CodeModule
Dim thisPane As CodePane

Set thisPane = Application.VBE.ActiveCodePane
Set thisModule = thisPane.CodeModule
Application.VBE.Windows(thisModule & " (Code)").SetFocus
With thisModule
    thisPane.GetSelection lActiveLine, 0, 0, 0
    sProc = thisModule.ProcOfLine(lActiveLine, vbext_pk_Proc)
    Dim newline As String
    newline = LCase(InputBox("Enter the desired line." _
                & vbLf & "    20 means line 20 in " & sProc _
                & vbLf & " m20 means line 20 in " & thisModule _
                & vbLf & "The current line is  m" & lActiveLine))
                Select Case Left(newline, 1)
    Case "m"hh
        On Error GoTo exit_function
        lLine = Mid(newline, 2)
        Application.VBE.ActiveCodePane.SetSelection lLine, 1, lLine + 1, 1
    Case Else
        On Error GoTo exit_function
        lLine = newline
        .CodePane.SetSelection .ProcStartLine(sProc, ProcType) + lLine, 1, .ProcStartLine(sProc, ProcType) + lLine + 1, 1
    End Select
    If IsError(Application.Caller) Then SendKeys "{f7}" ' if called from immediate window protect highlight from being erased.

' see https://www.experts-exchange.com/dashboard/#/questions/my/29262416
' see https://dev59.com/ulwY5IYBdhLWcg3wpJE-
End With
 exit_function: End Sub

`


0
唯一的方法是在您的代码中物理标记您的行。这有点麻烦,但您可以使用以下代码来添加它们:
Sub AddLineNumbers(wbName As String, vbCompName As String)
    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

然后,您需要添加一个函数来跳转到您需要到达的任何行:

Function JumpToLine(LnNum as String)
  GoTo LnNum
End Function

来源:http://www.mrexcel.com/forum/excel-questions/576449-code-line-numbers-visual-basic-applications.html


VBA 在技术上内部确实会跟踪行号 - 请参见 SetSelection - Blackhawk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接