vba在文件夹及其子文件夹内的所有文件中searchstring

我有一个巨大的脚本,使我已经部分完成(parsingxml文件到vba和删除某些不想要的孩子),但我一炮打响。

我有我的工作表中的单元格A1:A1500中的string(从我以前的输出获得),我有一个名为“模型”的文件夹在我的工作簿放置在相同的path(该文件夹有许多子文件夹和子文件夹内有很多.c ,.h,.xml文件types存在)。

我需要一个脚本,将采取A1中的string,并search文件夹“模型”及其子文件夹中的所有文件,如果该string是存在于任何文件我必须打印/放在单元格B1“findstring如果string不在任何文件中,我必须在单元格B1中打印/放置“未find”。 以同样的方式,我需要在文件夹“model”中的所有文件中searchA2:A1500中的所有string,并在单元格B2:B1500中打印/放置“findstring”/未find。

下面是我在工作表A1列中的一些string:A4:

vel_gradient

D_speed_20

AGB_router_1

F10_35_XS

我有点熟悉vba,但我不知道如何实现这一点。

任何关于脚本的帮助都被接受。 有人可以帮我弄这个吗。

正如在问题的评论中指出的那样,这个问题的答案涉及到recursion,这意味着一个或多个子例程或函数自我调用一遍又一遍,等等。幸运的是,Excel将为您保留所有这些。 我的解决scheme还利用了Excel技巧,允许您创build或卸载数组,而无需使用Range.Value属性进行迭代。 还包括一个string缩进variables,以帮助可视化如何发生recursion。 不再需要时,只需注释掉Debug.Print语句即可。

解决scheme涉及3个步骤。

  1. 创build一个可以与2个并行数组一起匹配的所有string的数组,以保存find/未find的string以及匹配string的第一个文件

  2. 将3个数组ByRef传递给处理给定文件夹的所有子文件夹和文件的子例程。 任何子文件夹recursion到文件夹子例程中,而文件由单独的文件例程处理。

  3. 所有的子文件夹和文件都被处理后,find的/未find的列将从关联的数组中填充。

请享用

步骤1 – 主要方法

' The main sub routine. Public Sub FindStrings(strFolder As String, Optional wksSheet As Worksheet = Nothing) ' Used examples given, better to convert to variables and calculate at run time. Const lngFirstRow As Long = 1 Const lngLasstRow As Long = 1500 Const strStringsCol As String = "A" Const strMatchesFoundCol As String = "B" Const strFileNamesCol As String = "C" Dim lngIndex As Long, lngFolderCount As Long, lngFileCount As Long Dim strIndent As String Dim varStrings As Variant, varMatchesFound As Variant, varFileNames As Variant If wksSheet Is Nothing Then Set wksSheet = ActiveSheet End If With wksSheet ' Create the strings array from the given range value. varStrings = .Range(.Cells(lngFirstRow, strStringsCol), .Cells(lngLasstRow, strStringsCol)).Value ' Transpose the strings array into a one dimentional array. varStrings = Application.WorksheetFunction.Transpose(varStrings) End With ' Initialize file names array to empty strings. ReDim varFileNames(LBound(varStrings) To UBound(varStrings)) For lngIndex = LBound(varFileNames) To UBound(varFileNames) varFileNames(lngIndex) = vbNullString Next ' Initialize matches found array to empty strings. ReDim varMatchesFound(LBound(varStrings) To UBound(varStrings)) For lngIndex = LBound(varMatchesFound) To UBound(varMatchesFound) varMatchesFound(lngIndex) = vbNullString Next ' Process the main folder. Call ProcessFolder(strFolder, strIndent, varStrings, varMatchesFound, varFileNames, lngFolderCount, lngFileCount) ' Finish setting up matches found array. For lngIndex = LBound(varMatchesFound) To UBound(varMatchesFound) If Len(Trim$(varMatchesFound(lngIndex))) = 0 Then varMatchesFound(lngIndex) = "Not found" End If Next ' Transpose the associated arrays so we can use them to load found / not found and file names columns. varFileNames = Application.WorksheetFunction.Transpose(varFileNames) varMatchesFound = Application.WorksheetFunction.Transpose(varMatchesFound) ' Set up the found / not found column data from the matches found array. With wksSheet .Range(.Cells(lngFirstRow, strFileNamesCol), .Cells(lngLasstRow, strFileNamesCol)).Value = varFileNames .Range(.Cells(lngFirstRow, strMatchesFoundCol), .Cells(lngLasstRow, strMatchesFoundCol)).Value = varMatchesFound End With Debug.Print "Folders: "; lngFolderCount, "Files: "; lngFileCount End Sub 

步骤2 – 进程子文件夹方法

 Private Sub ProcessFolder(strFolder As String, ByRef strIndent As String, ByRef varStrings As Variant, ByRef varMatchesFound As Variant, ByRef varFileNames As Variant, ByRef lngFolderCount As Long, lngFileCount As Long) Dim objFileSystemObject As Object, objFolder As Object, objFile As Object ' Use late binding throughout this method to avoid having to set any references. Set objFileSystemObject = CreateObject("Scripting.FileSystemObject") lngFolderCount = lngFolderCount + 1 Debug.Print strIndent & "Dir: " & Format(lngFolderCount, "###,##0 ") & strFolder For Each objFolder In objFileSystemObject.GetFolder(strFolder).SubFolders If objFolder.Name = "history" Then 'Do Nothing Else ' Recurse with the current sub folder. Call ProcessFolder(objFolder.Path, strIndent & " ", varStrings, varMatchesFound, varFileNames, lngFolderCount, lngFileCount) End If Next ' Process any files found in the current folder. For Each objFile In objFileSystemObject.GetFolder(strFolder).Files Call ProcessFile(objFile.Path, strIndent & " ", varStrings, varMatchesFound, varFileNames, lngFileCount) Next Set objFileSystemObject = Nothing: Set objFolder = Nothing: Set objFile = Nothing End Sub 

第3步 – 进程文件方法

 Private Sub ProcessFile(strFullPath As String, ByRef strIndent As String, ByRef varStrings As Variant, ByRef varMatchesFound As Variant, ByRef varFileNames As Variant, ByRef lngFileCount As Long) On Error Resume Next Dim objFileSystemObject As Object Dim strFileContent As String Dim lngIndex As Long lngFileCount = lngFileCount + 1 Debug.Print strIndent & "File: " & Format(lngFileCount, "###,##0 ") & strFullPath ' Use late binding throughout this method to avoid having to set any references. Set objFileSystemObject = CreateObject("Scripting.FileSystemObject") strFileContent = objFileSystemObject.OpenTextFile(strFullPath).Readall() If Err.Number = 0 Then ' Check for matched strings by iterating over the strings array. For lngIndex = LBound(varStrings) To UBound(varStrings) ' Skip zero length strings. If Len(Trim$(varStrings(lngIndex))) > 0 Then ' We have a matched string. If InStr(1, strFileContent, varStrings(lngIndex), vbTextCompare) > 0 Then ' Set up parallel arrays the first time the string is matched. If Len(Trim$(varMatchesFound(lngIndex))) = 0 Then ' Set corresponding array value. varMatchesFound(lngIndex) = "String found" ' Save file name where first match was found. varFileNames(lngIndex) = strFullPath End If End If End If Next Else Err.Clear End If Set objFileSystemObject = Nothing On Error GoTo 0 End Sub 

如果您的文件不是太大,您可以一次读取所有内容:

 Sub Tester() Debug.Print StringInFile("C:\_Stuff\test\File_Val2.txt", "xxx") End Sub Function StringInFile(fPath, txtSearch) As Boolean StringInFile = InStr(CreateObject("scripting.filesystemobject").opentextfile( _ fPath).Readall(), txtSearch) > 0 End Function 

但是,如果您需要testing多个string,则一次读取文件会更有效,然后使用instr()检查每个string