VBA - 通过模式搜索查找 VBE 模块中的所有编号行

标签 vba excel parsing vbe

任务:

我的目标是找到我的代码模块的过程中的所有编号行。 CodeModule.Find 方法可用于检查搜索词(目标参数)。

语法:

对象。查找(目标、起始行、起始列、结束行、结束列 [、全字] [、匹配大小写] [、模式搜索])

引用帮助网站https://msdn.microsoft.com/en-us/library/aa443952(v=vs.60).aspx状态: 参数patternsearch:可选。一个 bool 值,指定目标字符串是否是正则表达式模式。 如果为 True,则目标字符串是正则表达式模式。默认值为 False。

如上所述,find 方法允许进行正则表达式模式搜索,我想使用它来以精确的方式识别编号行: 数字后跟制表符。因此,下面的示例定义了一个搜索字符串 s 并将 .Find 方法中的最后一个参数 PatternSearch 设置为 True。

问题 AFAIK 有效的正则表达式定义可能是

s = "[0-9]{1,4}[ \t]"

但这没有显示任何内容,甚至没有显示错误。

为了至少显示任何结果,我定义了搜索词

s = "[0-9]*[ \t]*)"

在调用示例过程ListNumberedLines中显示不稳定的结果。

问题

是否有可能在 CodeModule.Find 方法中使用有效的正则表达式模式搜索?

示例代码

Option Explicit

' ==============
' Example Search
' ==============
Sub ListNumberedLines()
'  Declare search pattern string s
   Dim S As String
10  S = "[0-9]*[ \t]*)"     
20  Debug.Print "Search Term: " & S
30  Call findWordInModules(S)

End Sub

Public Sub findWordInModules(ByVal sSearchTerm As String)
' Purpose: find modules ('components') with lines containing a search term
' Method:  .CodeModule.Find with last parameter patternsearch set to True
' Based on https://www.devhut.net/2016/02/24/vba-find-term-in-vba-modulescode/

' VBComponent requires reference to Microsoft Visual Basic for Applications Extensibility
'             or keep it as is and use Late Binding instead
' Declare module variable oComponent
  Dim oComponent            As Object    'VBComponent

  For Each oComponent In Application.VBE.ActiveVBProject.VBComponents
    If oComponent.CodeModule.Find(sSearchTerm, 1, 1, -1, -1, False, False, True) = True Then
        Debug.Print "Module: " & oComponent.Name  'Name of the current module in which the term was found (at least once)
        'Need to execute a recursive listing of where it is found in the module since it could be found more than once
        Call listLinesinModuleWhereFound(oComponent, sSearchTerm)
    End If
  Next oComponent
End Sub

Sub listLinesinModuleWhereFound(ByVal oComponent As Object, ByVal sSearchTerm As String)
' Purpose: list module lines containing a search term
' Method:  .CodeModule.Find with last parameter patternsearch set to True
  Dim lTotalNoLines         As Long   'total number of lines within the module being examined
  Dim lLineNo               As Long   'will return the line no where the term is found
    lLineNo = 1
  With oComponent         ' Module
    lTotalNoLines = .CodeModule.CountOfLines
    Do While .CodeModule.Find(sSearchTerm, lLineNo, 1, -1, -1, False, False, True) = True
        Debug.Print vbTab & "Zl. " & lLineNo & "|" & _
                    Trim(.CodeModule.Lines(lLineNo, 1))  'Remove any padding spaces
        lLineNo = lLineNo + 1    'Restart the search at the next line looking for the next occurence
    Loop
  End With
End Sub

最佳答案

正如 @MatsMug 所说,用正则表达式解析 VBA 是很难不可能的,但行号是一个更简单的情况,应该可以单独使用正则表达式找到。

幸运的是,行号只能出现在过程主体内(包括在 End Sub/Function/Property 语句之前),因此我们知道它们永远不会成为代码的第一行。

不幸的是,您可以在行标签前面添加 0 个或多个行延续:

Sub Foo()
 _
 _
10 Beep
End Sub

此外,行号后面并不总是跟有空格 - 它后面可以跟指令分隔符,使行号具有行标签的外观:

Sub foo()
10: Beep
End Sub

而且如果你的代码是邪恶的,你可能会遇到负行号(使用十六进制表示法输入 - VBE 尽职尽责地漂亮地打印回代码 Pane ,并带有前导空格和负数):

Sub foo()
10 Beep
 -1 Beep
End Sub

我们还需要能够识别出现在连续行上的数字,这些数字不是行号:

Sub foo()
  Debug.Print _
5 & "is not a line-number"
End Sub

所以,这是一些邪恶的行编号,混合了所有这些边缘情况:

Option Explicit

Sub foo()

5: Beep

 _
 _
 _
10 Beep

20 _
'Debug.Print _
30

50: Beep

40 Beep

 _
 -1 _
 Beep 'The "-1" line number is achieved by entering "&HFFFFFFFF"

Debug.Print _
2 & "is not a line-number"

60 End Sub

这是一些标识行号的正则表达式:

(?<! _)\n( _\n)* ?(?<line_number>(?:\-)?\d+)[: ]

这是 regex101 的语法突出显示:

enter image description here

关于VBA - 通过模式搜索查找 VBE 模块中的所有编号行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45743203/

相关文章:

c++ - DLL 导致 "Microsoft Excel has stopped working"但它在 Win32 控制台应用程序中工作正常

xml - 控制 Excel XML 中的打印预览默认值

html - Facebook 如何知道要从文章中解析出什么图像?

vba - Word VBA 代码用于选择单元格中的文本,将特殊剪切并粘贴回同一单元格

vba - 将 .xfdf 保存为 .pdf

VBA Excel For 循环与变体数组导致 Excel 崩溃

excel - 对 Excel 进行编程以根据特定有效期有条件地格式化单元格(跟踪表)

c++ - 将字符串解析为不区分大小写的 protobuf 枚举

iPhone解析XML数据,标签没有出现

excel - 将一张纸的列宽设置为与另一张相同