好的,我会以艰难的方式做到这一点,因为我会假设您不想必须从我的存储库中下载 VBE 类以使其更易于使用,但它们是有一个例子说明无论如何都是可能的。
首先,您需要添加对 Microsoft Visual Basic for Applications Extensibility 5.3 Library的引用,并允许 VBA 通过执行以下步骤访问编辑器。(假设 Office 2010)
- 文件
- 选项
- 信托中心
- 信任中心设置
- 宏设置
- 选中“信任对 VBA 项目对象模型的访问”。
现在我们已准备好探索工作簿中的代码,但首先,需要记住一些关于我们在此处查找的内容的事项。
- 功能
- 更具体地说,公共职能
- 在标准 *.bas 模块中(类函数不能是 UDF)。
- 没有选项私有模块
下面的代码适用于活动的 vba 项目,但可以修改为将其作为参数。它适用于我在子下方提供的快速测试用例Run
,但我不能保证它适用于所有极端情况。解析很难。这也只是存储和打印集合中的函数签名results
。我想实际上你会想要一个返回它们的函数,这样你就可以遍历集合在工作簿中寻找它们。
Option Explicit
Private Sub Run()
Dim results As New Collection
Dim component As VBIDE.VBComponent
For Each component In Application.VBE.ActiveVBProject.VBComponents
If component.Type = vbext_ct_StdModule Then
' find public functions with no arguments
Dim codeMod As CodeModule
Set codeMod = component.CodeModule
If InStr(1, codeMod.Lines(1,codeMod.CountOfDeclarationLines), "Option Private Module") = 0 Then
Dim lineNumber As Long
lineNumber = codeMod.CountOfDeclarationLines + 1
Dim procName As String
Dim procKind As vbext_ProcKind
Dim signature As String
' loop through all lines in the module
While (lineNumber < codeMod.CountOfLines)
procName = codeMod.ProcOfLine(lineNumber, procKind) 'procKind is an OUT param
Dim lines() As String
Dim procLineCount As Long
procLineCount = codeMod.ProcCountLines(procName, procKind)
lines = Split(codeMod.lines(lineNumber, procLineCount), vbNewLine)
Dim i As Long
For i = 0 To UBound(lines)
If lines(i) <> vbNullString And Left(Trim(lines(i)), 1) <> "'" Then
signature = lines(i)
Exit For
End If
Next
' this would need better parsing, but should be reasonably close
If InStr(1, signature, "Public Function", vbTextCompare) > 0 Then 'first make sure we have a public function
results.Add signature
End If
lineNumber = lineNumber + procLineCount + 1 ' skip to next procedure
Wend
End If
End If
Next component
Dim str
For Each str In results
Debug.Print str
Next
End Sub
Public Function foo()
End Function
Private Function bar()
End Function
Public Function qwaz(duck)
End Function