我在特定行之间的 VBA 宏体内找到一些文本,并且 .find 重置行详细信息

问题描述 投票:0回答:1

基于上一篇文章的成功:在 MS Project 中,我如何列出所有子例程及其模块名称
我正在使用 http://www.cpearson.com/excel/vbe.aspx 中的代码来搜索宏中的文本。 我目前正在搜索一些简单的文本,但最终我将循环一组文本(子函数名称)并在每个模块中的每个子函数和函数中搜索它们,以便我可以报告哪些宏和函数调用其他子函数和函数。 代码是:

'.vbVisual Basic
'---------------------------------------------------------------------------------------
' Purpose   :       Prints all subs and functions in a project
' Prerequisites:    Microsoft Visual Basic for Applications Extensibility 5.3 library
'                   CreateLogFile
' How to run:       Run GetFunctionAndSubNames, set a parameter to blnWithParentInfo
'                   If ComponentTypeToString(vbext_ct_StdModule) = "Code Module" Then
'
' Used:             ComponentTypeToString from -> http://www.cpearson.com/excel/vbe.aspx
'---------------------------------------------------------------------------------------

'taken from https://www.vitoshacademy.com/vba-listing-all-procedures-in-all-modules/
'slight modiications to display the module names and customise for MS Project rather than Excel
'changed CreateLogFile to Debug.print
'added choice of how to display the modules

Option Explicit

Private strSubsInfo As String
Public Sub X_GetFunctionAndSubNames()
 
    Dim item            As Variant
    strSubsInfo = ""
    Dim displaychoice As Integer
    
    displaychoice = InputBox("How do you want to display the module names?:" & vbCrLf & "1 = In line with the Procedure Names, seperated by a ':'" & vbCrLf & "2 = The Module name: and then the Procedure names under the Module")
    If Not (displaychoice = 1 Or displaychoice = 2) Then
        MsgBox ("Only 1 or 2 can be chosen, the code will now exit")
        Exit Sub
    End If
    
    For Each item In ThisProject.VBProject.VBComponents 'ThisWorkbook.VBProject.VBComponents
        
        If ComponentTypeToString(vbext_ct_StdModule) = "Code Module" Then
            ListProcedures item.Name, displaychoice, False
            'Debug.Print item.CodeModule.Lines(1, item.CodeModule.CountOfLines)
        End If
        
    Next item
    Debug.Print strSubsInfo
    Chain_slack.Clipboard (strSubsInfo)
    MsgBox ("The procedure and module names have been printed to the Immediate window and has been saved to the Clipboard")
    'CreateLogFile strSubsInfo
End Sub

Private Sub ListProcedures(strName As String, displaychoice As Integer, Optional blnWithParentInfo = False)

    'Microsoft Visual Basic for Applications Extensibility 5.3 library is needed for this to run.

    Dim VBProj          As VBIDE.VBProject
    Dim VBComp          As VBIDE.VBComponent
    Dim CodeMod         As VBIDE.CodeModule
    Dim LineNum         As Long
    Dim ProcName        As String
    Dim ModuleName As String
    Dim ProcKind        As VBIDE.vbext_ProcKind
    Dim Start_row As Long
    Dim End_row As Long
    Dim FindThis As String
    

    Set VBProj = ThisProject.VBProject  'ActiveWorkbook.VBProject
    Set VBComp = VBProj.VBComponents(strName)
    Set CodeMod = VBComp.CodeModule
    ModuleName = VBComp.CodeModule.Name
    FindThis = "find this here"
    
    If displaychoice = 2 Then strSubsInfo = strSubsInfo & IIf(strSubsInfo = vbNullString, vbNullString, vbCrLf) & "Module - " & ModuleName
    
    With CodeMod
        LineNum = .CountOfDeclarationLines + 1
        
        Do Until LineNum >= .CountOfLines
            ProcName = .ProcOfLine(LineNum, ProcKind)
            Start_row = LineNum
            End_row = Start_row + .ProcCountLines(ProcName, ProcKind) + 1
           
            If blnWithParentInfo Then
                If displaychoice = 2 Then strSubsInfo = strSubsInfo & IIf(strSubsInfo = vbNullString, vbNullString, vbCrLf) & strName & "." & ProcName
                If displaychoice = 1 Then strSubsInfo = strSubsInfo & IIf(strSubsInfo = vbNullString, vbNullString, vbCrLf) & strName & "." & ProcName & " : " & ModuleName
            Else
                If displaychoice = 2 Then strSubsInfo = strSubsInfo & IIf(strSubsInfo = vbNullString, vbNullString, vbCrLf) & ProcName
                If displaychoice = 1 Then strSubsInfo = strSubsInfo & IIf(strSubsInfo = vbNullString, vbNullString, vbCrLf) & ProcName & " : " & ModuleName
            End If

            LineNum = .ProcStartLine(ProcName, ProcKind) + .ProcCountLines(ProcName, ProcKind) + 1
            'within this loop can I use the search sub (turned into a functon) from http://www.cpearson.com/excel/vbe.aspx to look from the start line to the end line of this proc
            'and loop thorugh an array or string (easier to transfer fom the starting function?) to see if the proc contains any of the names in the string/array?
'start with a simple term which has been seeded through the project in known places before starting to loop through the various search terms
            
            If SearchCodeModule(ModuleName, Start_row, End_row, FindThis) = True Then Debug.Print ModuleName & ": " & ProcName & " contains " & FindThis & "  " & Start_row & "-" & End_row
                    
        Loop
    End With
End Sub

Function ComponentTypeToString(ComponentType As VBIDE.vbext_ComponentType) As String
    'ComponentTypeToString from http://www.cpearson.com/excel/vbe.aspx
    Select Case ComponentType
    
        Case vbext_ct_ActiveXDesigner
            ComponentTypeToString = "ActiveX Designer"
            
        Case vbext_ct_ClassModule
            ComponentTypeToString = "Class Module"
            
        Case vbext_ct_Document
            ComponentTypeToString = "Document Module"
            
        Case vbext_ct_MSForm
            ComponentTypeToString = "UserForm"
            
        Case vbext_ct_StdModule
            ComponentTypeToString = "Code Module"
            
        Case Else
            ComponentTypeToString = "Unknown Type: " & CStr(ComponentType)
            
    End Select
    
End Function

Function SearchCodeModule(module_name As String, SL As Long, EL As Long, FindWhat As String)
'from http://www.cpearson.com/excel/vbe.aspx
'should be returning a true or false 

    Dim VBProj As VBIDE.VBProject
    Dim VBComp As VBIDE.VBComponent
    Dim CodeMod As VBIDE.CodeModule
    'Dim FindWhat As String
    'Dim SL As Long ' start line
    'Dim EL As Long ' end line
    Dim SC As Long ' start column
    Dim EC As Long ' end column
    Dim Found As Boolean
    
    Set VBProj = ThisProject.VBProject
    Set VBComp = VBProj.VBComponents(module_name)
    Set CodeMod = VBComp.CodeModule
    
    'FindWhat = "findthis"
    
    With CodeMod
        'SL = 1
        'EL = .CountOfLines
        SC = 1
        EC = 255
        Found = .Find(target:=FindWhat, StartLine:=SL, StartColumn:=SC, _
            EndLine:=EL, EndColumn:=EC, _
            wholeword:=True, MatchCase:=False, patternsearch:=False)
        'Do Until Found = False
        '    Debug.Print "Found at: Line: " & CStr(SL) & " Column: " & CStr(SC)
        '    EL = .CountOfLines
        '    SC = EC + 1
        '    EC = 255
        '    Found = .Find(target:=FindWhat, StartLine:=SL, StartColumn:=SC, _
        '        EndLine:=EL, EndColumn:=EC, _
        '        wholeword:=True, MatchCase:=False, patternsearch:=False)
        'Loop
    End With  'why are SL and EL set to equal the location of the string and also the values for StartLine and EndLine are set to the same; how can I keep these for the next loop?
    SearchCodeModule = Found  'Debug.Print Found
End Function

在进入 Sub ListProcedures 中的循环时,当前过程的行的开始和结束记录在 Start_row 和 End_row 中。这些值被传递给 Seach 函数以限制每个模块内的搜索区域。 问题是,当搜索函数找到匹配项(即 Found = True)时,SL、EL、Start_Row 和 End_row 的值都会成为找到搜索文本的行。 这是一个问题,因为将来当我循环遍历所有可能的搜索字符串时,我将需要 Start_row 和 End_row 保持不变。 为什么会这样做以及如何修复它? :) 非常感谢您帮助我继续学业。

vba project ms-project
1个回答
0
投票

报告哪些宏和函数调用其他子函数和函数

Public Sub X_GetFunctionAndSubNames()
 
    Dim vbProj As VBIDE.VBProject
    Set vbProj = ThisProject.VBProject
    
    Dim Item As VBIDE.VBComponent
    For Each Item In vbProj.VBComponents
        
        If Item.Type = vbext_ct_StdModule Then
            Dim SubsInfo As String
            SubsInfo = SubsInfo & vbCrLf & ListProcedures(vbProj, Item)
        End If
        
    Next Item
    
    Debug.Print SubsInfo
    'Chain_slack.Clipboard (SubsInfo)
    MsgBox "The procedure and module names have been printed to the Immediate window and has been saved to the Clipboard"
    
End Sub

Function ListProcedures(vbProj As VBIDE.VBProject, module As VBIDE.VBComponent) As String

    Dim modInfo As String
    modInfo = module.Name
    
    Dim ProcKind As VBIDE.vbext_ProcKind
    ProcKind = vbext_pk_Proc
    
    With module.CodeModule
        Dim LineNum As Long
        LineNum = .CountOfDeclarationLines + 1
        
        Do Until LineNum >= .CountOfLines

            Dim procName As String
            procName = .ProcOfLine(LineNum, ProcKind)
           
            modInfo = modInfo & vbCrLf & vbTab & procName & FindCalls(vbProj, procName)
            
            LineNum = .ProcStartLine(procName, ProcKind) + .ProcCountLines(procName, ProcKind) + 1
                    
        Loop
    End With
    
    ListProcedures = modInfo
    
End Function


Function FindCalls(vbProj As VBIDE.VBProject, procName As String) As String

    Dim VBComp As VBIDE.VBComponent
    For Each VBComp In vbProj.VBComponents
    
        If VBComp.Type = vbext_ct_StdModule Then
            With VBComp.CodeModule
                
                Dim callInfo As String
                Dim SL As Long
                SL = 0

                Do Until Not .Find(procName, SL, 0, .CountOfLines, 0, WholeWord:=True)
                    
                    Dim foundIn As String
                    foundIn = .ProcOfLine(SL, vbext_pk_Proc)
                    
                    If procName <> foundIn And Len(foundIn) > 0 Then
                        callInfo = callInfo & vbCrLf & vbTab & vbTab & "called by " & foundIn & " on line " & SL
                    End If
                    SL = SL + 1
                    
                Loop
                
            End With
        End If
    Next VBComp
    
    FindCalls = callInfo
    
End Function

输出

过程名称在模块名称下方缩进显示,然后缩进在模块名称下方是调用它们的列表。

BuildVBAModel
    X_GetFunctionAndSubNames
    ListProcedures
        called by X_GetFunctionAndSubNames on line 14
    FindCalls
        called by ListProcedures on line 42
Module2
    MainProc
    Func1
        called by MainProc on line 6
        called by MainProc on line 11
    ProcB
        called by MainProc on line 8
        called by MainProc on line 13
© www.soinside.com 2019 - 2024. All rights reserved.