【问题标题】:Iterating through files in folder via FileSystemObject通过 FileSystemObject 遍历文件夹中的文件
【发布时间】:2017-04-12 10:58:37
【问题描述】:

好的,所以我认为自己是 Excel VBA 专家(尽管我已经有一段时间没有做太多事情了)但我对这个问题感到困惑 - 这显然意味着它非常简单,但我忽略了由于我的傲慢:D

我正在使用分配给全局变量的 FileSystemObject(称为“myFSO” - 原始的,我知道...)并使用另外两个全局变量 - xFolder 和 xFile - 来遍历文件夹中的所有文件,并且对文件夹中的每个文件执行操作。

这是代码:

Global myFSO As FileSystemObject
Global xFolder As Scripting.Folder
Global xFile As Scripting.File

Public Sub GetData()

Set bgd = ThisWorkbook.Sheets("BGD")
Set myFSO = New FileSystemObject
Set xFolder = myFSO.GetFolder(bgd.Range("C4").Value)

For Each xFile In xFolder.Files
          <do stuff here>
Next xFile

End Sub

因此,当我单步执行代码时,我可以看到 xFolder 已正确分配。如果我添加手表或插入

Debug.Print xFolder.Files.Count

在代码中,它会返回正确的文件数,所以一切似乎都设置得很好,可以进入 For 循环并做它需要做的事情。

一旦我越过 For Each... 语句行,代码就会运行到例程的末尾,完全忽略了嵌套在 For Each... Next 代码中的整个代码。它甚至没有进入“Next xFile”行。如果我将循环修改为

For i = 1 to xFolder.Files.Count

并以这种方式执行该过程,它可以正常工作。所以,这不是生死攸关的问题,因为我可以做我想做的事,我只是想知道是否有人能说出为什么“For Each”方法不起作用。

【问题讨论】:

  • 你可以在你的For Each xFile In xFolder.Files 中发布你的代码吗,当我用bgd.Range("D" &amp; i).Value = xFile.Name 测试它时,它会在“D”列中显示我所有的文件名。
  • 只是很生气,为什么你将这些变量声明为 global,至少对于 Global xFile As Scripting.File 来说,拥有这个 global 没有任何意义?
  • 你的错误设置是什么?如果它直接转到End Sub,则可能意味着生成了一个被设置掩盖的错误。检查 Err 对象。
  • @peh - 老实说,没有理由为什么它们是全局的,通常我在更大的项目中使用这些相同的变量名,其中变量在单个例程之外使用......我想我只是这样做是出于习惯:)
  • @VincentG - 代码中没有错误处理,总体思路是我过去成功使用了 100 次。如果我添加一个错误处理程序,它不会被调用,表明没有实际错误

标签: vba excel


【解决方案1】:

这是一个有效的最小示例:

  1. 创建一个新文件
  2. 参考 Microsoft 脚本运行时
  3. 创建一个名为BGD 的工作表并将现有路径写入C4,例如C:\Windows
  4. 将以下代码粘贴到模块中并运行它

这会列出调试窗口中的路径和所有文件名。

Public Sub GetData()
    Dim bgd As Worksheet
    Dim myFSO As FileSystemObject
    Dim xFolder As Scripting.Folder
    Dim xFile As Scripting.File


    Set bgd = ThisWorkbook.Sheets("BGD")
    Set myFSO = New FileSystemObject
    Set xFolder = myFSO.GetFolder(bgd.Range("C4").Value)

    Debug.Print xFolder.Path
    For Each xFile In xFolder.Files
        Debug.Print xFile.Name
    Next xFile

End Sub

如果您需要本地变量,则在本地而不是全局声明它们。其他任何做法都是非常糟糕的做法,会导致错误。

【讨论】:

  • 谢谢@Peh - 你在全局变量的主题上绝对正确,只是我在其他情况下出于必要将这些变量用作全局变量,所以我最终只是输入它们自然就这样出来了!
  • 您的帖子在另一种意义上非常有帮助 - 在不同文件夹上测试代码时,它按预期工作,所以它一定与我试图访问的(网络)文件夹有关 - 可能是一个案例安全/文件夹权限等等。
  • 因此,我总是从一个尽可能简单的最小示例开始。如果它有效,那么您就在正确的轨道上,并且可以更详细地介绍。如果它失败了,你会立即发现你的问题。否则,如果您从错误的方面开始调试,您会在几个小时的搜索后分析细节并最终发现一些根本性的错误。
  • 我没想过要更改文件夹 tbh,因为变量 xFolder 已正确分配,但你又一次完全正确,我应该考虑测试它。尽管如此,没关系,我终于在这个查询的后面加入了 StackOverflow,经过多年的访问,所以一件好事发生了! :)
【解决方案2】:

好的 - 问题实际上出在文件夹而不是代码上。正如@Peh 所指出的,我应该使用另一个文件夹测试代码,以及测试代码本身的变体。使用另一个文件夹时,For Each 代码运行良好。如 OP 中所述,我只是使用 For i = 1 to xFolder.Files.Count 而不是 For Each 并得到了我需要的结果,但我更喜欢 For Each 的对象主导方法而不是使用整数/长变量来检查项目计数,并想知道为什么该方法不起作用。

为了让For Each 代码正常工作,我将所需的文件复制到另一个文件夹,它运行良好。由于原始文件夹是一个网络位置,因此可能存在一些文件夹权限或安全设置阻止我使用我想要的代码。

【讨论】:

    【解决方案3】:

    我认为您想列出所有文件夹和所有子文件夹中的所有文件。看看这个链接。

    http://www.learnexcelmacro.com/wp/2011/11/how-to-get-list-of-all-files-in-a-folder-and-sub-folders/

    下载文件;这就是要走的路。在 Excel 工作表中列出所有路径和所有文件名后,您就可以进行各种比较、操作等。

     Sub GetFilesInFolder(SourceFolderName As String)  
    
        '--- For Example:Folder Name= "D:\Folder Name\"  
    
        Dim FSO As Scripting.FileSystemObject  
        Dim SourceFolder As Scripting.folder, SubFolder As Scripting.folder  
        Dim FileItem As Scripting.File  
    
            Set FSO = New Scripting.FileSystemObject  
            Set SourceFolder = FSO.GetFolder(SourceFolderName)  
    
            '--- This is for displaying, whereever you want can be configured  
    
            r = 14  
            For Each FileItem In SourceFolder.Files  
                Cells(r, 2).Formula = r - 13  
                Cells(r, 3).Formula = FileItem.Name  
                Cells(r, 4).Formula = FileItem.Path  
                Cells(r, 5).Formula = FileItem.Size  
                Cells(r, 6).Formula = FileItem.Type  
                Cells(r, 7).Formula = FileItem.DateLastModified  
                Cells(r, 8).Formula = "=HYPERLINK(""" & FileItem.Path & """,""" & "Click Here to Open" & """)"  
    
                r = r + 1   ' next row number  
            Next FileItem  
    
            Set FileItem = Nothing  
            Set SourceFolder = Nothing  
            Set FSO = Nothing  
        End Sub  
    
    
    Sub GetFilesInFolder(SourceFolderName As String, Subfolders As Boolean)  
    
    '--- For Example:Folder Name= "D:\Folder Name\" and Flag as Yes or No  
    
    Dim FSO As Scripting.FileSystemObject  
    Dim SourceFolder As Scripting.folder, SubFolder As Scripting.folder  
    Dim FileItem As Scripting.File  
    'Dim r As Long  
        Set FSO = New Scripting.FileSystemObject  
        Set SourceFolder = FSO.GetFolder(SourceFolderName)  
    
        '--- This is for displaying, whereever you want can be configured  
    
        r = 14  
        For Each FileItem In SourceFolder.Files  
            Cells(r, 2).Formula = r - 13  
            Cells(r, 3).Formula = FileItem.Name  
            Cells(r, 4).Formula = FileItem.Path  
            Cells(r, 5).Formula = FileItem.Size  
            Cells(r, 6).Formula = FileItem.Type  
            Cells(r, 7).Formula = FileItem.DateLastModified  
            Cells(r, 8).Formula = "=HYPERLINK(""" & FileItem.Path & """,""" & "Click Here to Open" & """)"  
    
            r = r + 1   ' next row number  
        Next FileItem  
    
        '--- This is the Function to go each and Every Folder and get the Files. This is a Nested-Function Calling.  
    
        If Subfolders = True Then  
            For Each SubFolder In SourceFolder.Subfolders  
                ListFilesInFolder SubFolder.Path, True  
            Next SubFolder  
        End If  
    
        Set FileItem = Nothing  
        Set SourceFolder = Nothing  
        Set FSO = Nothing  
    End Sub 
    

    【讨论】:

    • 嗨@ryguy72,我不想列出文件夹内容;嵌套在 For Each 语句中的代码会打开文件并对这些文件中的工作表执行操作。真的,问题不是嵌套代码,而是这个 For Each 循环的特定实例不起作用。事实证明,这可能与文件夹的安全设置或权限有关,因为另一个文件夹使用相同的代码可以正常工作。
    猜你喜欢
    • 2017-04-03
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2023-01-20
    • 2014-09-28
    • 2019-05-08
    • 2018-08-06
    相关资源
    最近更新 更多