Sometimes I need to perform searches in the VBA code to try and cleanup client databases, and sometimes Mz_tools, although an exceptional add-in, just doesn’t give me enough flexibility to perform the type of searches I need. It is rare, but it does happen.
Below is a generic procedure to search through all your VBA code for a term. As it stands below, it offers little benefit over Mz-Tools, but it allows you the flexibility to modify it as you see fit to do things Mz-Tools simply can’t.
For instance, I needed to search through the VBA code of a database looking for a given term, where the next line included a specific function. There is simply no way to do this with Mz-Tools, but I added one line to my code below and presto I had my listing to work off of. And let me tell you when you are dealing with complex databases with 100’s of forms modules, reports module, modules, class modules, a routine like the one below can make a drastic improvement!
I must also state that I was surprised by the speed of such a search, it is fast considering the quantity of code I was combing through when I last used it. Access & VBA never cease to amaze me sometimes.
'Call findWordInModules("DoCmd.Delete Object acTable")
Public Sub findWordInModules(ByVal sSearchTerm As String)
'object.Find(target, startline, startcol, endline, endcol [, wholeword] [, matchcase] [, patternsearch])
'https://msdn.microsoft.com/en-us/library/aa443952(v=vs.60).aspx
' VBComponent requires reference to Microsoft Visual Basic for Applications Extensibility
' or keep it as is and use Late Binding instead
Dim oComponent As Object 'VBComponent
For Each oComponent In Application.VBE.ActiveVBProject.VBComponents
If oComponent.CodeModule.Find(sSearchTerm, 1, 1, -1, -1, False, False, False) = True Then
Debug.Print "Module: " & oComponent.Name 'Name of the current module in which the term was found (at least once)
'Need to execute a recursive listing of where it is found in the module since it could be found more than once
Call listLinesinModuleWhereFound(oComponent, sSearchTerm)
End If
Next oComponent
End Sub
Sub listLinesinModuleWhereFound(ByVal oComponent As Object, ByVal sSearchTerm As String)
Dim lTotalNoLines As Long 'total number of lines within the module being examined
Dim lLineNo As Long 'will return the line no where the term is found
lLineNo = 1
With oComponent
lTotalNoLines = .CodeModule.CountOfLines
Do While .CodeModule.Find(sSearchTerm, lLineNo, 1, -1, -1, False, False, False) = True
Debug.Print vbTab & "Line No:" & lLineNo & Trim(.CodeModule.Lines(lLineNo, 1)) 'Remove any padding spaces
lLineNo = lLineNo + 1 'Restart the search at the next line looking for the next occurence
Loop
End With
End Sub
As always, be sure to add proper error handling.
I hope this helps.
hi i am trying to use your function but I dont know how to call it …
1) the link for the Library on MSDN refers to Visual Studio 6.0 , but i see in the comment also “VBComponent requires reference to Microsoft Visual Basic for Applications Extensibility” .
In my access 2010 references i have loaded : MS visual basic for application Extensibility 5.3
Is it allright ? or i need to find a Library for visual studio 6 also ?
2) in the execution Windows i typed : findWordInModules(valide)
to find some module code containing the word “valide” but then i got an error 40203 ” the research string should be specified “
1) Follow the instructions given in the function, so what you selected is perfect.
2) it is because you are not supplying a String to the function. The way you coded it, you are supplying a variable (which does not exist). Instead, you’d need to try:
? findWordInModules(“valide”)
Very slick…exactly what I was looking for!
I haven’t dug into the Application.VBE.ActiveVBProject object yet to see what properties/objects/collections are available, but I’m curious if you can also return the procedure name and procedure type (function, sub, property, enum, declaration, etc.) along with the line of code where the search term was found.
If I get a change to work through it, I’ll post what I figure out…
Yes, you can use automation to extract procedure names, module names, …
I found this very useful, and made a couple of changes to ‘listLinesinModuleWhereFound’ that better suited my needs: When word found then find name of function or sub that contains the word searched for. There is probably a better way of doing this, but this got me what I wanted.
Sub listLinesinModuleWhereFound(ByVal oComponent As Object, ByVal sSearchTerm As String) Dim lLineNo As Long 'will return the line no where the term is found Dim PrevLine As Long Dim ProcName As String lLineNo = 1 With oComponent Do While .CodeModule.Find(sSearchTerm, lLineNo, 1, -1, -1, False, False, False) = True If InStr(.CodeModule.Lines(lLineNo, 1), "Sub ") > 0 Or _ InStr(.CodeModule.Lines(lLineNo, 1), "Function ") > 0 Then Debug.Print vbTab & "Mod Ln: " & lLineNo & " " & Trim(.CodeModule.Lines(lLineNo, 1)) ProcName = Trim(.CodeModule.Lines(lLineNo, 1)) Else For PrevLine = lLineNo - 1 To 0 Step -1 'Not a sub - find Sub/Func name If PrevLine = 0 Then 'Not found, must be declaration? Debug.Print vbTab & "Decl Ln: " & lLineNo & " " & Trim(.CodeModule.Lines(lLineNo, 1)) Exit For End If If InStr(.CodeModule.Lines(PrevLine, 1), "Sub ") > 0 Or _ InStr(.CodeModule.Lines(PrevLine, 1), "Function ") > 0 Then If ProcName Trim(.CodeModule.Lines(PrevLine, 1)) Then Debug.Print vbTab & "Mod Ln: " & PrevLine & " " & Trim(.CodeModule.Lines(PrevLine, 1)) ProcName = Trim(.CodeModule.Lines(PrevLine, 1)) End If Debug.Print vbTab & vbTab & "Proc Ln: " & lLineNo - PrevLine & " " & Trim(.CodeModule.Lines(lLineNo, 1)) 'Remove any padding spaces Exit For End If Next End If lLineNo = lLineNo + 1 'Restart the search at the next line looking for the next occurence Loop End With End SubMy needs were quite modest (create a list of Excel and Word files containing a search string). But working through your clever code got me (hardly a professional!) pointed in the right direction to write my own. Many, many thanks!