我需要为定义Properties,Functions和Subs的所有行扫描Application.VBE.ActiveProject.VBComponent.CodeModule。我想检索作用域,类型,名称和返回变量类型(如果可用)。
匹配行例如是
Private Property Get Attribute() As String
Public Sub calculateTotal()
Friend Function getIdentifier() As Long
我迭代地开发了一个应该与
匹配的正则表达式Public
,Friend
或Private
Property
,Sub
或Function
Get
或Set
(如果是属性)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构建和调试正则表达式,但无法使其正常工作。我显然缺乏安全地包含所需部分并排除表达式的可选部分的知识。
答案 0 :(得分:3)
您可以使用
(Public|Friend|Private)\s+(Property|Sub|Function)(\s+[GS]et)?\s+(\w+)\s*(\([^()]*\))(\s+As\s+\w+)?
说明:
(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 ]*
,G
,e
,空格,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项目。