Vba 如何获取Excel工作簿中定义的宏

Vba 如何获取Excel工作簿中定义的宏,vba,excel,vsto,Vba,Excel,Vsto,用VBA或C#代码有没有办法获得工作簿中定义的现有宏的列表 理想情况下,这个列表将有一个方法定义签名,但仅仅获得一个可用宏的列表就好了 这是可能的吗?我很久没有使用vba for Excel了,但是如果我记得清楚的话,代码的对象模型是无法通过脚本访问的 当您尝试访问它时,您会收到以下错误 尝试: 现在您可以访问VB IDE了,您可以导出模块并在其中进行文本搜索,使用vba/c#,使用正则表达式查找子声明和函数声明,然后删除导出的模块 我不确定是否有其他方法可以做到这一点,但这应该是可行的 您可以

用VBA或C#代码有没有办法获得工作簿中定义的现有宏的列表

理想情况下,这个列表将有一个方法定义签名,但仅仅获得一个可用宏的列表就好了


这是可能的吗?

我很久没有使用vba for Excel了,但是如果我记得清楚的话,代码的对象模型是无法通过脚本访问的

当您尝试访问它时,您会收到以下错误

尝试:

现在您可以访问VB IDE了,您可以导出模块并在其中进行文本搜索,使用vba/c#,使用正则表达式查找子声明和函数声明,然后删除导出的模块

我不确定是否有其他方法可以做到这一点,但这应该是可行的

您可以查看以下链接,开始导出模块。


这是我获得有关授予对VB IDE的强制访问权限的信息的地方。

基于Martin的回答,在您信任对VBP的访问之后,您可以使用这组代码获取Excel工作簿VB项目中所有公共子例程的数组。您可以将其修改为仅包含子函数、函数、私有函数或公共函数

Private Sub TryGetArrayOfDecs()
    Dim Decs() As String
    DumpProcedureDecsToArray Decs
End Sub

Public Function DumpProcedureDecsToArray(ByRef Result() As String, Optional InDoc As Excel.Workbook) As Boolean
    Dim VBProj As Object
    Dim VBComp As Object
    Dim VBMod As Object

    If InDoc Is Nothing Then Set InDoc = ThisWorkbook

    ReDim Result(1 To 1500, 1 To 4)
   DumpProcedureDecsToArray = True
    On Error GoTo PROC_ERR

    Set VBProj = InDoc.VBProject
    Dim FuncNum As Long
    Dim FuncDec As String
    For Each VBComp In VBProj.vbcomponents
        Set VBMod = VBComp.CodeModule
        For i = 1 To VBMod.countoflines
            If IsSubroutineDeclaration(VBMod.Lines(i, 1)) Then
                FuncDec = RemoveBlanksAndDecsFromSubDec(RemoveAsVariant(VBMod.Lines(i, 1)))
                If LCase(Left(VBMod.Lines(i, 1), Len("private"))) <> "private" Then
                    FuncNum = FuncNum + 1
                    Result(FuncNum, 1) = FindToLeftOfString(InDoc.Name, ".")    '
                    Result(FuncNum, 2) = VBMod.Name
                    Result(FuncNum, 3) = GetSubName(FuncDec)
                    Result(FuncNum, 4) = VBProj.Name
                End If
            End If
        Next i
    Next VBComp
 PROC_END:
    Exit Function
 PROC_ERR:
    GoTo PROC_END
End Function

Private Function RemoveCharFromLeftOfString(TheString As String, RemoveChar As String) As String
    Dim Result As String
    Result = TheString
    While LCase(Left(Result, Len(RemoveChar))) = LCase(RemoveChar)
        Result = Right(Result, Len(Result) - Len(RemoveChar))
    Wend
    RemoveCharFromLeftOfString = Result
End Function

Private Function RemoveBlanksAndDecsFromSubDec(TheLine As String) As String
    Dim Result As String
    Result = TheLine
    Result = RemoveCharFromLeftOfString(Result, " ")
    Result = RemoveCharFromLeftOfString(Result, "   ")
    Result = RemoveCharFromLeftOfString(Result, "Public ")
    Result = RemoveCharFromLeftOfString(Result, "Private ")
    Result = RemoveCharFromLeftOfString(Result, " ")
    RemoveBlanksAndDecsFromSubDec = Result
End Function

Private Function RemoveAsVariant(TheLine As String) As String
    Dim Result As String
    Result = TheLine
    Result = Replace(Result, "As Variant", "")
    Result = Replace(Result, "As String", "")
    Result = Replace(Result, "Function", "")
    If InStr(1, Result, "( ") = 0 Then
        Result = Replace(Result, "(", "( ")
    End If
    RemoveAsVariant = Result
End Function

Private Function IsSubroutineDeclaration(TheLine As String) As Boolean
    If LCase(Left(RemoveBlanksAndDecsFromSubDec(TheLine), Len("Function "))) = "function " Or LCase(Left(RemoveBlanksAndDecsFromSubDec(TheLine), Len("sub "))) = "sub " Then
        IsSubroutineDeclaration = True
    End If
End Function

Private Function GetSubName(DecLine As String) As String
    GetSubName = FindToRightOfString(FindToLeftOfString(DecLine, "("), " ")
End Function

Function FindToLeftOfString(FullString As String, ToFind As String) As String
    If FullString = "" Then Exit Function
    Dim Result As String, ToFindPos As Integer
    ToFindPos = InStr(1, FullString, ToFind, vbTextCompare)
    If ToFindPos > 0 Then
        Result = Left(FullString, ToFindPos - 1)
    Else
        Result = FullString
    End If
    FindToLeftOfString = Result
End Function

Function FindToRightOfString(FullString As String, ToFind As String) As String
    If FullString = "" Then Exit Function
    Dim Result As String, ToFindPos As Integer
    ToFindPos = InStr(1, FullString, ToFind, vbTextCompare)
    Result = Right(FullString, Len(FullString) - ToFindPos + 1 - Len(ToFind))
    If ToFindPos > 0 Then
        FindToRightOfString = Result
    Else
        FindToRightOfString = FullString
    End If
End Function
Private Sub-TryGetArrayOfDecs()
Dim Decs()作为字符串
DumpProceduredeCostoarray Decs
端接头
公共函数dumpProceduredeCostoarray(ByRef Result()作为字符串,可选InDoc作为Excel.工作簿)作为布尔值
作为对象的Dim VBProj
作为对象的Dim VBComp
将VBMod设置为对象
如果InDoc为空,则设置InDoc=ThisWorkbook
重拨结果(1到1500,1到4)
dumpproceduredeCostoarray=True
关于错误转到程序错误
设置VBProj=InDoc.VBProject
Dim FuncNum尽可能长
作为字符串的Dim FuncDec
对于VBProj.vbcomponents中的每个VBComp
设置VBMod=VBComp.CodeModule
对于i=1到VBMod.countofline
如果发出错误的声明(VBMod.行(i,1)),则
FuncDec=removesblanks和decsfromsubdec(removesvariant(VBMod.line(i,1)))
如果LCase(左(VBMod.行(i,1),Len(“private”))“private”,则
FuncNum=FuncNum+1
结果(FuncNum,1)=FindToLeftOfString(InDoc.Name,“.””
结果(FuncNum,2)=VBMod.Name
结果(FuncNum,3)=获取子名称(FuncDec)
结果(FuncNum,4)=VBProj.Name
如果结束
如果结束
接下来我
下一个VBComp
程序结束:
退出功能
过程错误:
转到程序结束
端函数
私有函数RemoveCharFromLeftOfString(字符串为String,RemoveChar为String)作为String
将结果变暗为字符串
结果=字符串
而LCase(左(结果,Len(RemoveChar))=LCase(RemoveChar)
结果=右(结果,Len(结果)-Len(RemoveChar))
温德
RemoveCharFromLeftOfsString=结果
端函数
私有函数移除blanks和decsfromsubdec(作为字符串的行)作为字符串
将结果变暗为字符串
结果=直线
结果=从LeftOfsString(结果“”)中删除共享
结果=从LeftOfsString(结果“”)中删除共享
结果=从LeftOfsString中删除共享(结果为“公共”)
结果=从LeftOfsString中删除共享(结果为“私有”)
结果=从LeftOfsString(结果“”)中删除共享
RemoveBlanks和DecsFromSubDec=结果
端函数
私有函数将变量(行作为字符串)移除为字符串
将结果变暗为字符串
结果=直线
结果=替换(结果,“作为变量”、“”)
结果=替换(结果,“作为字符串”,“作为字符串”)
结果=替换(结果,“函数”、“”)
如果InStr(1,结果,“(”)=0,则
结果=替换(结果,“(”,“(”)
如果结束
RemoveAsVariant=结果
端函数
私有函数IsubroutineDeclaration(线作为字符串)作为布尔值
如果LCase(左)(删除空格和从子行删除),Len(“函数”))=函数或LCase(左)(删除空格和从子行删除),Len(“子”)=子行,则
IsSubroutineDeclaration=真
如果结束
端函数
私有函数GetSubName(作为字符串拒绝)作为字符串
GetSubName=FindToRightOfString(FindToLeftOfString(拒绝)(“”“”)
端函数
函数FindToLeftOfString(FullString作为字符串,ToFind作为字符串)作为字符串
如果FullString=“”,则退出函数
Dim结果作为字符串,ToFindPos作为整数
ToFindPos=InStr(1,FullString,ToFind,vbTextCompare)
如果ToFindPos>0,则
结果=左(完整字符串,ToFindPos-1)
其他的
结果=完整字符串
如果结束
FindToLeftOfString=结果
端函数
函数FindToRightOfString(FullString作为字符串,ToFind作为字符串)作为字符串
如果FullString=“”,则退出函数
Dim结果作为字符串,ToFindPos作为整数
ToFindPos=InStr(1,FullString,ToFind,vbTextCompare)
结果=右(完整字符串,Len(完整字符串)-ToFindPos+1-Len(ToFind))
如果ToFindPos>0,则
FindToRightOfsString=结果
其他的
FindToRightOfsString=FullString
如果结束
端函数

是。此链接介绍了使用VBA代码可以对VBA代码执行的几项操作,包括“列出模块中的所有过程”。
Tools | Macro | Security |Trusted Publisher Tab
[x] Trust access to Visual Basic Project
Private Sub TryGetArrayOfDecs()
    Dim Decs() As String
    DumpProcedureDecsToArray Decs
End Sub

Public Function DumpProcedureDecsToArray(ByRef Result() As String, Optional InDoc As Excel.Workbook) As Boolean
    Dim VBProj As Object
    Dim VBComp As Object
    Dim VBMod As Object

    If InDoc Is Nothing Then Set InDoc = ThisWorkbook

    ReDim Result(1 To 1500, 1 To 4)
   DumpProcedureDecsToArray = True
    On Error GoTo PROC_ERR

    Set VBProj = InDoc.VBProject
    Dim FuncNum As Long
    Dim FuncDec As String
    For Each VBComp In VBProj.vbcomponents
        Set VBMod = VBComp.CodeModule
        For i = 1 To VBMod.countoflines
            If IsSubroutineDeclaration(VBMod.Lines(i, 1)) Then
                FuncDec = RemoveBlanksAndDecsFromSubDec(RemoveAsVariant(VBMod.Lines(i, 1)))
                If LCase(Left(VBMod.Lines(i, 1), Len("private"))) <> "private" Then
                    FuncNum = FuncNum + 1
                    Result(FuncNum, 1) = FindToLeftOfString(InDoc.Name, ".")    '
                    Result(FuncNum, 2) = VBMod.Name
                    Result(FuncNum, 3) = GetSubName(FuncDec)
                    Result(FuncNum, 4) = VBProj.Name
                End If
            End If
        Next i
    Next VBComp
 PROC_END:
    Exit Function
 PROC_ERR:
    GoTo PROC_END
End Function

Private Function RemoveCharFromLeftOfString(TheString As String, RemoveChar As String) As String
    Dim Result As String
    Result = TheString
    While LCase(Left(Result, Len(RemoveChar))) = LCase(RemoveChar)
        Result = Right(Result, Len(Result) - Len(RemoveChar))
    Wend
    RemoveCharFromLeftOfString = Result
End Function

Private Function RemoveBlanksAndDecsFromSubDec(TheLine As String) As String
    Dim Result As String
    Result = TheLine
    Result = RemoveCharFromLeftOfString(Result, " ")
    Result = RemoveCharFromLeftOfString(Result, "   ")
    Result = RemoveCharFromLeftOfString(Result, "Public ")
    Result = RemoveCharFromLeftOfString(Result, "Private ")
    Result = RemoveCharFromLeftOfString(Result, " ")
    RemoveBlanksAndDecsFromSubDec = Result
End Function

Private Function RemoveAsVariant(TheLine As String) As String
    Dim Result As String
    Result = TheLine
    Result = Replace(Result, "As Variant", "")
    Result = Replace(Result, "As String", "")
    Result = Replace(Result, "Function", "")
    If InStr(1, Result, "( ") = 0 Then
        Result = Replace(Result, "(", "( ")
    End If
    RemoveAsVariant = Result
End Function

Private Function IsSubroutineDeclaration(TheLine As String) As Boolean
    If LCase(Left(RemoveBlanksAndDecsFromSubDec(TheLine), Len("Function "))) = "function " Or LCase(Left(RemoveBlanksAndDecsFromSubDec(TheLine), Len("sub "))) = "sub " Then
        IsSubroutineDeclaration = True
    End If
End Function

Private Function GetSubName(DecLine As String) As String
    GetSubName = FindToRightOfString(FindToLeftOfString(DecLine, "("), " ")
End Function

Function FindToLeftOfString(FullString As String, ToFind As String) As String
    If FullString = "" Then Exit Function
    Dim Result As String, ToFindPos As Integer
    ToFindPos = InStr(1, FullString, ToFind, vbTextCompare)
    If ToFindPos > 0 Then
        Result = Left(FullString, ToFindPos - 1)
    Else
        Result = FullString
    End If
    FindToLeftOfString = Result
End Function

Function FindToRightOfString(FullString As String, ToFind As String) As String
    If FullString = "" Then Exit Function
    Dim Result As String, ToFindPos As Integer
    ToFindPos = InStr(1, FullString, ToFind, vbTextCompare)
    Result = Right(FullString, Len(FullString) - ToFindPos + 1 - Len(ToFind))
    If ToFindPos > 0 Then
        FindToRightOfString = Result
    Else
        FindToRightOfString = FullString
    End If
End Function