2016-04-15 204 views
0

我在一個文件夾中有大約100個宏,而且我正在尋找一個特別的包含VBA模塊的函數,名爲addGBE - 我忘記了它是在哪個文件中。是否有任何軟件程序允許我在特定文件夾中的VBA代碼中搜索文件?在多個Excel文件中搜索VBA代碼

+0

它們都是.bas文件嗎?如果是這樣,你可以複製/重命名爲'.txt',然後搜索文件夾。這可能是最快的方法。您甚至可以使用VBA來複制/重命名每個文件。 – BruceWayne

+0

如果所有代碼都位於'.bas','.txt','.doc'文件(或包含搜索字詞未加密文本格式的其他文件)中,則可以使用Windows搜索來查找代碼(不需要重命名)。有很多網站解釋如何做到這一點http://answers.microsoft.com/en-us/windows/forum/windows_7-files/in-windows-7-i-want-to-search-for-all-files/ aadfe1f1-4a33-406b-8e72-bb920efa4f30?AUTH = 1。如果你不喜歡Windows搜索,你也可以使用這些工具,比如這些http://stackoverflow.com/questions/317944/tools-to-search-for-strings-inside-files-without-indexing。 – Ralph

回答

0

我發現了一些我更新的舊代碼(2006)。它會打開一個框來輸入搜索字符串,然後打開一個dir對話框來選擇文件夾。然後,它將搜索所有模塊,並顯示msgbox顯示文件名和表單/模塊名稱,其中找到字符串。我沒有這樣做,只是更新。原始發現here。有關檢查64位並正確聲明數據類型的Microsoft文檔,請參閱here

Option Explicit 


#If VBA7 And Win64 Then ' VBA7 
Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" _ 
    Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long 

Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" _ 
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long 


Public Type BROWSEINFO 
    hOwner As LongPtr 
    pidlRoot As Long 
    pszDisplayName As String 
    lpszTitle As String 
    ulFlags As Long 
    lpfn As LongPtr 
    lParam As LongPtr 
    iImage As Long 
End Type 

#Else ' Downlevel when using previous version of VBA7 

Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" _ 
    Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long 

Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" _ 
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long 


Public Type BROWSEINFO 
    hOwner As Long 
    pidlRoot As Long 
    pszDisplayName As String 
    lpszTitle As String 
    ulFlags As Long 
    lpfn As Long 
    lParam As Long 
    iImage As Long 
End Type 
#End If 


Function GetDirectory(Optional Msg) As String 

Dim bInfo As BROWSEINFO 
Dim Path As String 
Dim R As Long 
Dim x As Long 
Dim pos As Integer 

'Root folder (&H0 for Desktop, &H11 for My Computer) 
bInfo.pidlRoot = &H0 

'Title in the dialog 
If IsMissing(Msg) Then 
bInfo.lpszTitle = "Select a folder." 
Else 
bInfo.lpszTitle = Msg 
End If 

'Type of directory to return 
bInfo.ulFlags = &H1 

'Display the dialog 
x = SHBrowseForFolder(bInfo) 

'Parse the result 
Path = Space$(512) 
R = SHGetPathFromIDList(ByVal x, ByVal Path) 
If R Then 
pos = InStr(Path, Chr$(0)) 
GetDirectory = Left(Path, pos - 1) 
Else 
GetDirectory = "" 
End If 

End Function 

Function RecursiveFindFiles(strPath As String, _ 
strSearch As String, _ 
Optional bSubFolders As Boolean = True, _ 
Optional bSheet As Boolean = False, _ 
Optional lFileCount As Long = 0, _ 
Optional lDirCount As Long = 0) As Variant 

'adapted from the MS example: 
'http://support.microsoft.com/default.aspx?scid=kb;en-us;185476 
'--------------------------------------------------------------- 
'will list all the files in the supplied folder and it's 
'subfolders that fit the strSearch criteria 
'lFileCount and lDirCount will always have to start as 0 
'--------------------------------------------------------------- 

Dim strFileName As String 'Walking strFileName variable. 
Dim strDirName As String 'SubDirectory Name. 
Dim arrDirNames() As String 'Buffer for directory name entries. 
Dim nDir As Long 'Number of directories in this strPath. 
Dim i As Long 'For-loop counter. 
Dim n As Long 
Dim arrFiles 
Static strStartDirName As String 
Static strpathOld As String 

On Error GoTo sysFileERR 

If lFileCount = 0 Then 
Static collFiles As Collection 
Set collFiles = New Collection 
Application.Cursor = xlWait 
End If 

If Right$(strPath, 1) <> "\" Then 
strPath = strPath & "\" 
End If 

If lFileCount = 0 And lDirCount = 0 Then 
strStartDirName = strPath 
End If 

'search for subdirectories 
'------------------------- 
nDir = 0 

ReDim arrDirNames(nDir) 

strDirName = Dir(strPath, _ 
vbDirectory Or _ 
vbHidden Or _ 
vbArchive Or _ 
vbReadOnly Or _ 
vbSystem) 'Even if hidden, and so on. 

Do While Len(strDirName) > 0 
'ignore the current and encompassing directories 
'----------------------------------------------- 
If (strDirName <> ".") And (strDirName <> "..") Then 
'check for directory with bitwise comparison 
'------------------------------------------- 
If GetAttr(strPath & strDirName) And vbDirectory Then 
arrDirNames(nDir) = strDirName 
lDirCount = lDirCount + 1 
nDir = nDir + 1 
DoEvents 
ReDim Preserve arrDirNames(nDir) 
End If 'directories. 
sysFileERRCont1: 
End If 
strDirName = Dir() 'Get next subdirectory 

DoEvents 
Loop 

'Search through this directory 
'----------------------------- 
strFileName = Dir(strPath & strSearch, _ 
vbNormal Or _ 
vbHidden Or _ 
vbSystem Or _ 
vbReadOnly Or _ 
vbArchive) 

While Len(strFileName) <> 0 

'dump file in sheet 
'------------------ 
If bSheet Then 
If lFileCount < 65536 Then 
Cells(lFileCount + 1, 1) = strPath & strFileName 
End If 
End If 

lFileCount = lFileCount + 1 

collFiles.Add strPath & strFileName 

If strPath <> strpathOld Then 
Application.StatusBar = " " & lFileCount & _ 
" " & strSearch & " files found. " & _ 
"Now searching " & strPath 
End If 

strpathOld = strPath 

strFileName = Dir() 'Get next file 

DoEvents 
Wend 

If bSubFolders Then 
'If there are sub-directories.. 
'------------------------------ 
If nDir > 0 Then 
'Recursively walk into them 
'-------------------------- 
For i = 0 To nDir - 1 
RecursiveFindFiles strPath & arrDirNames(i) & "\", _ 
strSearch, _ 
bSubFolders, _ 
bSheet, _ 
lFileCount, _ 
lDirCount 

DoEvents 
Next 
End If 'If nDir > 0 

'only bare main folder left, so get out 
'-------------------------------------- 
If strPath & arrDirNames(i) = strStartDirName Then 
ReDim arrFiles(1 To lFileCount) As String 
For n = 1 To lFileCount 
arrFiles(n) = collFiles(n) 
Next 
RecursiveFindFiles = arrFiles 
Application.Cursor = xlDefault 
Application.StatusBar = False 
End If 

Else 'If bSubFolders 
ReDim arrFiles(1 To lFileCount) As String 
For n = 1 To lFileCount 
arrFiles(n) = collFiles(n) 
Next 
RecursiveFindFiles = arrFiles 
Application.Cursor = xlDefault 
Application.StatusBar = False 
End If 'If bSubFolders 

Exit Function 
sysFileERR: 

Resume sysFileERRCont1 

End Function 

Function FileFromPath(ByVal strFullPath As String, _ 
Optional bExtensionOff As Boolean = False) _ 
As String 

Dim FPL As Long 'len of full path 
Dim PLS As Long 'position of last slash 
Dim pd As Long 'position of dot before exension 
Dim strFile As String 

On Error GoTo ERROROUT 

FPL = Len(strFullPath) 
PLS = InStrRev(strFullPath, "\", , vbBinaryCompare) 
strFile = Right$(strFullPath, FPL - PLS) 

If bExtensionOff = False Then 
FileFromPath = strFile 
Else 
pd = InStr(1, strFile, ".", vbBinaryCompare) 
FileFromPath = Left$(strFile, pd - 1) 
End If 

Exit Function 
ERROROUT: 

On Error GoTo 0 
FileFromPath = "" 

End Function 

Sub SearchWBsForCode() 

Dim strTextToFind As String 
Dim strFolder As String 
Dim arr 
Dim i As Long 
Dim strWB As String 
Dim VBProj As VBProject 
Dim VBComp As VBComponent 
Dim lStartLine As Long 
Dim lEndLine As Long 
Dim lFound As Long 
Dim lType As Long 
Dim lSkipped As Long 
Dim oWB As Workbook 
Dim bOpen As Boolean 
Dim bNewBook As Boolean 

strTextToFind = InputBox("Type the text to find", _ 
"finding text in VBE") 

If Len(strTextToFind) = 0 Or StrPtr(strTextToFind) = 0 Then 
Exit Sub 
End If 

strFolder = GetDirectory() 

If Len(strFolder) = 0 Then 
Exit Sub 
End If 

lType = Application.InputBox("Type file type to search" & _ 
vbCrLf & vbCrLf & _ 
"1. Only .xls files" & vbCrLf & _ 
"2. Only .xla files" & vbCrLf & _ 
"3. Either file type", _ 
"finding text in VBE", 1, Type:=1) 

Select Case lType 
Case 1 
arr = RecursiveFindFiles(strFolder, "*.xls", True, True) 
Case 2 
arr = RecursiveFindFiles(strFolder, "*.xla", True, True) 
Case 3 
arr = RecursiveFindFiles(strFolder, "*.xl*", True, True) 
Case Else 
Exit Sub 
End Select 

With Application 
.ScreenUpdating = False 
.EnableEvents = False 
.DisplayAlerts = False 
End With 

For i = 1 To UBound(arr) 

Application.StatusBar = i & "/" & UBound(arr) & _ 
" - Searching " & arr(i) 

strWB = FileFromPath(arr(i)) 

On Error Resume Next 
Set oWB = Workbooks(strWB) 

If oWB Is Nothing Then 
bOpen = False 
Workbooks.Open arr(i) 
Else 
'for preventing closing WB's that are open already 
bOpen = True 
Set oWB = Nothing 
End If 

bNewBook = True 

For Each VBComp In Workbooks(strWB).VBProject.VBComponents 

If Err.Number = 50289 Then 'for protected WB's 
lSkipped = lSkipped + 1 
Err.Clear 
GoTo PAST 
End If 

lEndLine = VBComp.CodeModule.CountOfLines 
If VBComp.CodeModule.Find(strTextToFind, _ 
lStartLine, _ 
1, _ 
lEndLine, _ 
-1, _ 
False, _ 
False) = True Then 

If bNewBook = True Then 
lFound = lFound + 1 
bNewBook = False 
End If 

Application.ScreenUpdating = True 

If MsgBox("Workbook: " & arr(i) & vbCrLf & _ 
"VBComponent: " & VBComp.Name & vbCrLf & _ 
"Line number: " & lStartLine & _ 
vbCrLf & vbCrLf & _ 
"WB's found so far: " & lFound & vbCrLf & _ 
"Protected WB's skipped: " & lSkipped & _ 
vbCrLf & vbCrLf & _ 
"Stop searching?", _ 
vbYesNo + vbDefaultButton1 + vbQuestion, _ 
i & "/" & UBound(arr) & _ 
" - found " & strTextToFind) = vbYes Then 

With Application 
.StatusBar = False 
.EnableEvents = True 
.DisplayAlerts = True 
End With 

With VBComp.CodeModule.CodePane 
.SetSelection lStartLine, 1, lStartLine, 1 
.Show 
End With 

Exit Sub 
End If 

Application.ScreenUpdating = False 

End If 
Next 

PAST: 
If bOpen = False Then 
Workbooks(strWB).Close savechanges:=False 
End If 
On Error GoTo 0 

Next 

On Error Resume Next 
If bOpen = False Then 
Workbooks(strWB).Close savechanges:=False 
End If 

With Application 
.ScreenUpdating = True 
.StatusBar = False 
.EnableEvents = True 
.DisplayAlerts = True 
End With 

MsgBox lFound & " WB's found with " & strTextToFind & " in VBE" & _ 
vbCrLf & vbCrLf & _ 
"protected WB's skipped: " & lSkipped, , _ 
"finding text in VBE" 

End Sub 
+0

您是否介意擴展您的解決方案,並將'#If Win64 Then ...'用於64位系統? – Ralph

+0

根據您的建議更新。我認爲這應該適用於64和32沒有問題。這對我來說有點技術性,但我認爲我明白了,爲什麼。 – mrbungle