适用于属性,函数和子代的VBA RegEx

时间:2016-04-29 22:06:44

标签: regex vba

我需要为定义Properties,Functions和Subs的所有行扫描Application.VBE.ActiveProject.VBComponent.CodeModule。我想检索作用域,类型,名称和返回变量类型(如果可用)。

匹配行例如是

  • Private Property Get Attribute() As String
  • Public Sub calculateTotal()
  • Friend Function getIdentifier() As Long

我迭代地开发了一个应该与

匹配的正则表达式
  • 关键字PublicFriendPrivate
  • 后面跟一个空白
  • 后跟关键字PropertySubFunction
  • 后面跟一个空白
  • 后跟可选关键字GetSet(如果是属性)
  • 后跟名称(由任意文字和下划线组成)
  • 后跟括号,可以包含参数
  • 后跟可选关键字As
  • 后跟可选的变量类型

最后以

结束
  • (Public|Friend|Private)(已捕获)
  • (?: )
  • (Property|Sub|Function)(已捕获)
  • (?: )
  • (?:[Get |Set ]*)(这里它开始变得难看,我猜)
  • (\w+)(已捕获)
  • (?:\([\w\s]+\))
  • (?:[As ]*)
  • (\w*)(已捕获)

或在"字" (Public|Friend|Private)(?: )(Property|Sub|Function)(?: )(?:[Get |Set ]*)(\w+)(?:\([\w\s]+\))(\w*)。我尝试使用Expresso构建和调试正则表达式,但无法使其正常工作。我显然缺乏安全地包含所需部分并排除表达式的可选部分的知识。

2 个答案:

答案 0 :(得分:3)

您可以使用

(Public|Friend|Private)\s+(Property|Sub|Function)(\s+[GS]et)?\s+(\w+)\s*(\([^()]*\))(\s+As\s+\w+)?

请参阅this regex demo

说明:

(Public|Friend|Private)  # keyword
\s+                      # blank
(Property|Sub|Function)  # keyword2
(\s+[GS]et)?             # Optional blank + Get/Set
\s+(\w+)                 # blank + name
\s*(\([^()]*\))          # Optional blank+compulsory parentheses
(\s+As\s+\w+)?           # Optional As +variable type

要点是要使序列成为可选项,您需要在其后应用分组?量词。比方说,要选择性地匹配空白+ As,您需要\s+(1个或多个空格)和As包裹在()?中:{{1} }。您的(\s+As)?匹配零个或多个[Get |Set ]*Ge,空格,t|个字符S字符类,匹配集合/范围中的单个字符。

请注意,[...]\([^()]*\)之类的字符串匹配,因为(no-round-brackets-inside)是与[^()](之外的任何字符匹配的否定字符类。

答案 1 :(得分:1)

正如您所注意到的,正则表达式是“有趣的”。这是一种更简单,更强大的方法。

它仍然处于原型阶段,但是Rubberduck 2.0会(它仍然是alpha ..和buggy)暴露出一个COM API,可以让你编写这样的代码:

Frame f = new Frame();
f.setVisible(true);

假设上面的过程是用Public Sub ListMembers() Dim parser As New Rubberduck.ParserState parser.Initialize Application.VBE parser.Parse Dim i As Variant Dim item As Declaration For Each i In parser.UserDeclarations Set item = i If IsMember(item.DeclarationType) Then Debug.Print item.ParentDeclaration.Name & "." & item.Name & IIf(item.TypeName = vbNullString, vbNullString, " As " & item.TypeName) Dim j As Variant Dim ref As IdentifierReference For Each j In item.References Set ref = j Debug.Print " >> used in '" & ref.ParentScope.Name & "', line " & ref.StartLine Next End If Next End Sub Private Function IsMember(ByVal item As DeclarationType) As Boolean IsMember = item = DeclarationType_Function _ Or item = DeclarationType_Procedure _ Or item = DeclarationType_PropertyGet _ Or item = DeclarationType_PropertyLet _ Or item = DeclarationType_PropertySet End Function 编写的,它会产生这个输出(假设项目中没有其他代码,没有其他加载的项目):

ThisWorkbook

您可以使用该API不仅可以迭代成员,还可以确定谁在调用谁以及在何处。 ThisWorkbook.IsMember As Boolean >> used in 'IsMember', line 28 >> used in 'ListMembers', line 14 ThisWorkbook.ListMembers 不是全部; Rubberduck还会加载所有引用的类型库,因此如果您迭代UserDeclarations,您可以迭代Excel对象模型或VBA标准库的成员,并迭代它们的AllDeclarations

请注意,API仍然非常高,因此仍有可能发生变化。

  

免责声明我直接参与了Rubberduck项目。