Excel VBA 数组在每次调用子程序时都会被清空。

huangapple go评论70阅读模式
英文:

Excel VBA Array is getting cleared every time a Subroutine is called

问题

I am using Excel VBA to sort through a folder and it's subfolder to find the files that start with a specific name (in this case files called BACAPPC.xml). I am looking to save the name of that file to an array. Once I know where the file in located, there is another file in a related folder that I want to grab the name of and add it to the array. The code below finds that two file names and enters them into the array after the first BACAPPC.xml file is found), however when the DoFolder sub gets called again to search a new set of folders, it initializes the array and wipes the previous stored values.


Sub FindAllXMLinAUserSpecifiedFolder2()
' First ask user for the file path to search for the XML files

    Dim fldr As FileDialog
    Dim sItem As String
    ' temp comment out call dialog box and force path name
    sItem = "C:\UserData\hawkib\XXXX\YYYY\Job_10-18-22"
    
    'Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
    'With fldr
    '    .Title = "Select a Folder"
    '    .AllowMultiSelect = False
    '    .InitialFileName = Application.DefaultFilePath
    '    If .Show <> -1 Then GoTo NextCode
    '    sItem = .SelectedItems(1)
    'End With
'NextCode:
    GetFolder = sItem
'    Set fldr = Nothing


' more stuff

    Dim FileSystem As Object
    Dim HostFolder As String
    
    Set FileSystem = CreateObject("Scripting.FileSystemObject")
    HostFolder = GetFolder
        
    DoFolder FileSystem.GetFolder(HostFolder), 1
End Sub
    
Sub DoFolder(folder, RowNum As Integer)
    Dim SubFolder
    Dim ExtSplit As Variant
    Dim NameSplit As Variant
    Dim TempName As String
    Dim TempFileName As String
    Dim file
    Dim AppFileLocs() As Variant
    Dim AppTypeInfoLocation As String
    Dim Split1 As Variant
    Dim Split2 As Variant
    
    For Each SubFolder In folder.SubFolders
    TempName = SubFolder
        If InStr(1, SubFolder, "TPL_", vbTextCompare) > 0 Then
    
    For Each file In SubFolder.Files
        TempFileName = file
        If file Like "*BAAPPC_*.xml" Then
                ' prints file to excel - for testing only
                ActiveSheet.Cells(RowNum, 1) = file
                ReDim Preserve AppFileLocs(RowNum - 1, 2)
                AppFileLocs(RowNum - 1, 0) = file
                 ExtSplit = Split(file, ".")
                 NameSplit = Split(file, "\")

                 Flpath = Left(file, Len(file) - Len(NameSplit(UBound(NameSplit))))
                Spilt1 = Split(Flpth, "\")
                ' find name of parent folder and then append to change directory to parent folder\APPTYPE then include name of file that will be added to the array
                Split1 = Left(SubFolder, InStrRev(SubFolder, "\")) & "\APPTYPE\AppTypeInfo.xml"
                AppFileLocs(RowNum - 1, 1) = Split1
                
                
                RowNum = RowNum + 1
        End If
    Next
        End If
        
        DoFolder SubFolder, RowNum
    Next


End Sub

Any suggestions on how to allow the search to go through all folders and subfolders and add the file names to an array?

英文:

I am using Excel VBA to sort through a folder and it's subfolder to find the files that start with a specific name (in this case files called BACAPPC.xml). I am looking to save the name of that file to an array. Once I know where the file in located, there is another file in a related folder that I want to grab the name of and add it to the array. The code below finds that two file names and enters them into the array after the first BACAPPC.xml file is found), however when the DoFolder sub gets called again to search a new set of folders, it initializes the array and wipes the previous stored values.


Sub FindAllXMLinAUserSpecifiedFolder2()
&#39; First ask user for the file path to search for the XML files

    Dim fldr As FileDialog
    Dim sItem As String
    &#39; temp comment out call dialog box and force path name
    sItem = &quot;C:\UserData\hawkib\XXXX\YYYY\Job_10-18-22&quot;
    
    &#39;Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
    &#39;With fldr
    &#39;    .Title = &quot;Select a Folder&quot;
    &#39;    .AllowMultiSelect = False
    &#39;    .InitialFileName = Application.DefaultFilePath
    &#39;    If .Show &lt;&gt; -1 Then GoTo NextCode
    &#39;    sItem = .SelectedItems(1)
    &#39;End With
&#39;NextCode:
    GetFolder = sItem
&#39;    Set fldr = Nothing


&#39; more stuff

    Dim FileSystem As Object
    Dim HostFolder As String
    
    Set FileSystem = CreateObject(&quot;Scripting.FileSystemObject&quot;)
    HostFolder = GetFolder
        
    DoFolder FileSystem.GetFolder(HostFolder), 1
End Sub
    
Sub DoFolder(folder, RowNum As Integer)
    Dim SubFolder
    Dim ExtSplit As Variant
    Dim NameSplit As Variant
    Dim TempName As String
    Dim TempFileName As String
    Dim file
    Dim AppFileLocs() As Variant
    Dim AppTypeInfoLocation As String
    Dim Split1 As Variant
    Dim Split2 As Variant
    
    For Each SubFolder In folder.SubFolders
    TempName = SubFolder
        If InStr(1, SubFolder, &quot;TPL_&quot;, vbTextCompare) &gt; 0 Then
    
    For Each file In SubFolder.Files
        TempFileName = file
        If file Like &quot;*BAAPPC_*.xml&quot; Then
                &#39; prints file to excel - for testing only
                ActiveSheet.Cells(RowNum, 1) = file
                ReDim Preserve AppFileLocs(RowNum - 1, 2)
                AppFileLocs(RowNum - 1, 0) = file
                 ExtSplit = Split(file, &quot;.&quot;)
                 NameSplit = Split(file, &quot;\&quot;)

                 Flpath = Left(file, Len(file) - Len(NameSplit(UBound(NameSplit))))
                Spilt1 = Split(Flpth, &quot;\&quot;)
                &#39; find name of parent folder and then append to change directory to parent folder\APPTYPE then include name of file that will be added to the array
                Split1 = Left(SubFolder, InStrRev(SubFolder, &quot;\&quot;) - 1) &amp; &quot;\APPTYPE\AppTypeInfo.xml&quot;
                AppFileLocs(RowNum - 1, 1) = Split1
                
                
                RowNum = RowNum + 1
        End If
    Next
        End If
        
        DoFolder SubFolder, RowNum
    Next


End Sub

Any suggestions on how to allow the search to go through all folders and subfolders and add the file names to an array?

答案1

得分: 1

这是一种方法,使用非递归搜索子文件夹,然后处理找到的文件列表:

Option Explicit

Sub Tester()

    Dim xmlFiles As Collection, rootFolder As String, xmlFile, appFileLocs As Collection
    
    rootFolder = "C:\UserData\hawkib\XXXX\YYYY\Job_10-18-22"
    
    Set xmlFiles = GetFileMatches(rootFolder, "*BAAPPC_*.xml")
    Set appFileLocs = New Collection
    
    For Each xmlFile In xmlFiles
        Debug.Print xmlFile.Path
        appFileLocs.Add xmlFile.parentfolder.Path & "\APPTYPE\AppTypeInfo.xml"
    Next xmlFile
    
    '对`appFileLocs`进行某些操作

End Sub

'给定起始文件夹和文件模式,返回文件对象的集合
'例如,"*.txt"
'如果不想检查子文件夹,请将最后一个参数设为False
Function GetFileMatches(startFolder As String, filePattern As String, _
                    Optional subFolders As Boolean = True) As Collection

    Dim fso, fldr, f, subFldr, fpath
    Dim colFiles As New Collection
    Dim colSub As New Collection

    Set fso = CreateObject("scripting.filesystemobject")
    colSub.Add startFolder

    Do While colSub.Count > 0

        Set fldr = fso.getfolder(colSub(1))
        colSub.Remove 1
        '收集任何子文件夹
        If subFolders Then
            For Each subFldr In fldr.subFolders
                colSub.Add subFldr.Path
            Next subFldr
        End If
        '### 仅在文件夹名称包含"TPL_"时收集匹配的文件
        If InStr(1, fldr.Name, "TPL_", vbTextCompare) > 0 Then
            For Each f In fldr.Files
                If f.Name Like filePattern Then colFiles.Add f
            Next f
        End If
    Loop
    Set GetFileMatches = colFiles
End Function

英文:

Here's one way, using a non-recursive search over subfolders, then processing the list of found files:

Option Explicit

Sub Tester()

    Dim xmlFiles As Collection, rootFolder As String, xmlFile, appFileLocs As Collection
    
    rootFolder = &quot;C:\UserData\hawkib\XXXX\YYYY\Job_10-18-22&quot;
    
    Set xmlFiles = GetFileMatches(rootFolder, &quot;*BAAPPC_*.xml&quot;)
    Set appFileLocs = New Collection
    
    For Each xmlFile In xmlFiles
        Debug.Print xmlFile.Path
        appFileLocs.Add xmlFile.parentfolder.Path &amp; &quot;\APPTYPE\AppTypeInfo.xml&quot;
    Next xmlFile
    
    &#39;do something with `appFileLocs`

End Sub

&#39;Return a collection of file objects given a starting folder and a file pattern
&#39;  e.g. &quot;*.txt&quot;
&#39;Pass False for last parameter if don&#39;t want to check subfolders
Function GetFileMatches(startFolder As String, filePattern As String, _
                    Optional subFolders As Boolean = True) As Collection

    Dim fso, fldr, f, subFldr, fpath
    Dim colFiles As New Collection
    Dim colSub As New Collection

    Set fso = CreateObject(&quot;scripting.filesystemobject&quot;)
    colSub.Add startFolder

    Do While colSub.Count &gt; 0

        Set fldr = fso.getfolder(colSub(1))
        colSub.Remove 1
        &#39;collect any subfolders
        If subFolders Then
            For Each subFldr In fldr.subFolders
                colSub.Add subFldr.Path
            Next subFldr
        End If
        &#39;### collect any matching files only if the folder name contains &quot;TPL_&quot;
        If InStr(1, fldr.Name, &quot;TPL_&quot;, vbTextCompare) &gt; 0 Then
            For Each f In fldr.Files
                If f.Name Like filePattern Then colFiles.Add f
            Next f
        End If
    Loop
    Set GetFileMatches = colFiles
End Function

答案2

得分: 0

循环遍历文件夹的文件夹中的文件
- 

- 由于您知道所需文件夹的深度级别可以避免使用递归或其他方法来查找文件夹的所有子文件夹
- 由于您可以访问 *FileSystemObject* 对象也可以访问 *Dictionary* 对象这是一个比数组更合适的数据结构

&lt;!-- language: lang-vb --&gt;

    Sub GetXmlFilePairs()
    
        常量 ROOT_FOLDER_PATH 作为字符串 _
            = &quot;C:\UserData\hawkib\XXXX\YYYY\Job_10-18-22&quot;
        
        Dim fso 作为对象: 设置 fso = CreateObject(&quot;Scripting.FileSystemObject&quot;)
        
        ' 每个键将包含 'baappc...' 文件路径,而每个相应的
        ' 项目将包含 'AppTypeInfo.xml' 文件路径。
        Dim dict 作为对象: 设置 dict = CreateObject(&quot;Scripting.Dictionary&quot;)
        
        Dim fsoFolder 作为对象, fsoSubFolder 作为对象, fsoFile 作为对象
        Dim SubFolderPath 作为字符串, SubFilePath 作为字符串
        
        ' 级别 1:根文件夹的所有文件夹
        对于 每个 fsoFolder 在 fso.GetFolder(ROOT_FOLDER_PATH).Subfolders
            ' 级别 2:根文件夹的所有文件夹的所有文件夹
            对于 每个 fsoSubFolder 在 fsoFolder.Subfolders
                如果 InStr(1, fsoSubFolder.Name, &quot;TPL_&quot;, vbTextCompare) > 0 然后 ' 包含
                '如果 InStr(1, fsoSubFolder.Name, &quot;TPL_&quot;, vbTextCompare) = 1 然后 ' 以...开始
                    SubFolderPath = fsoSubFolder.Path
                    对于 每个 fsoFile 在 fsoSubFolder.Files
                        如果 LCase(fsoFile.Name) Like &quot;baappc_*.xml&quot; 然后 ' 以...开始/以...结束
                        '如果 LCase(fsoFile.Name) Like &quot;*baappc_*.xml&quot; 然后 ' 包含/以...结束
                            SubFilePath = fso _
                                .BuildPath(SubFolderPath, &quot;APPTYPE\AppTypeInfo.xml&quot;)
                            如果 fso.FileExists(SubFilePath) 然后
                                dict(fsoFile.Path) = SubFilePath
                            Else
                                dict(fsoFile.Path) = &quot;&quot;
                            End If
                            ' 如果您正在寻找每个文件夹一个文件
                            ' (看起来是这样),您可以通过以下方式提高效率:
                            'Exit For
                        End If
                    下一个 fsoFile
                End If
            下一个 fsoSubFolder
        下一个 fsoFolder
        
        如果 dict.Count = 0 然后
            MsgBox &quot;未找到文件&quot;, vbExclamation
            退出子程序
        End If
        
        ' 在即时窗口中打印文件配对的路径('Ctrl+G')。
        
        Dim        
        对于 每个 键 在 dict.Keys
            Debug.Print 键, dict(键)
        下一个 键
    
        ' 在工作表中返回文件配对的路径。
        
    '    使用 ActiveSheet.Range(&quot;A2&quot;).Resize(dict.Count)
    '        .Value = Application.Transpose(dict.Keys)
    '        .Offset(, 1).Value = Application.Transpose(dict.Items)
    '    End With
        ' 请注意,如果您使用集合而不是字典,将无法进行此简化。
    
    End Sub
英文:

Loop Through Folders of Folders of a Folder

  • Since you know the depth level of the folders you need, you can avoid using recursion or other methods to find all subfolders of a folder.
  • Since you have access to the FileSystemObject object, you also have access to the Dictionary object. It is a more appropriate data structure to be used instead of an array.

<!-- language: lang-vb -->

Sub GetXmlFilePairs()
Const ROOT_FOLDER_PATH As String _
= &quot;C:\UserData\hawkib\XXXX\YYYY\Job_10-18-22&quot;
Dim fso As Object: Set fso = CreateObject(&quot;Scripting.FileSystemObject&quot;)
&#39; Each key will contain the &#39;baappc...&#39; file path while each corresponding
&#39; item will contain the &#39;AppTypeInfo.xml&#39; file path.
Dim dict As Object: Set dict = CreateObject(&quot;Scripting.Dictionary&quot;)
Dim fsoFolder As Object, fsoSubFolder As Object, fsoFile As Object
Dim SubFolderPath As String, SubFilePath As String
&#39; Level 1: all folders of the root folder
For Each fsoFolder In fso.GetFolder(ROOT_FOLDER_PATH).Subfolders
&#39; Level 2: all folders of all folders of the root folder
For Each fsoSubFolder In fsoFolder.Subfolders
If InStr(1, fsoSubFolder.Name, &quot;TPL_&quot;, vbTextCompare) &gt; 0 Then &#39; contains
&#39;If InStr(1, fsoSubFolder.Name, &quot;TPL_&quot;, vbTextCompare) = 1 Then &#39; begins with
SubFolderPath = fsoSubFolder.Path
For Each fsoFile In fsoSubFolder.Files
If LCase(fsoFile.Name) Like &quot;baappc_*.xml&quot; Then &#39; begins with / ends with
&#39;If LCase(fsoFile.Name) Like &quot;*baappc_*.xml&quot; Then &#39; contains / ends with
SubFilePath = fso _
.BuildPath(SubFolderPath, &quot;APPTYPE\AppTypeInfo.xml&quot;)
If fso.FileExists(SubFilePath) Then
dict(fsoFile.Path) = SubFilePath
Else
dict(fsoFile.Path) = &quot;&quot;
End If
&#39; If you&#39;re looking for a single file per folder
&#39; (looks like it), you could improve efficiency with:
&#39;Exit For
End If
Next fsoFile
End If
Next fsoSubFolder
Next fsoFolder
If dict.Count = 0 Then
MsgBox &quot;No files found.&quot;, vbExclamation
Exit Sub
End If
&#39; Print the paths of the file pairs in the Immediate window (&#39;Ctrl+G&#39;).
Dim Key
For Each Key In dict.Keys
Debug.Print Key, dict(Key)
Next Key
&#39; Return the paths of the file pairs in a worksheet.
&#39;    With ActiveSheet.Range(&quot;A2&quot;).Resize(dict.Count)
&#39;        .Value = Application.Transpose(dict.Keys)
&#39;        .Offset(, 1).Value = Application.Transpose(dict.Items)
&#39;    End With
&#39; Note that this simplification wouldn&#39;t be possible
&#39; if you used a collection instead of the dictionary.
End Sub

huangapple
  • 本文由 发表于 2023年7月18日 05:15:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76708122.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定