【问题标题】:Loop through all the directories and sub-directories with intermediate wildcard patterns使用中间通配符模式遍历所有目录和子目录
【发布时间】:2015-12-17 17:59:44
【问题描述】:

我有一个循环遍历所有目录的代码,但我只需要在每个级别循环遍历一些特定目录。例如路径。 C:/主目录/ABC*/Y/XYZ*/*.edf.

此代码通过递归给出每个目录中的每个文件。我无法对其进行编辑,使其仅提供具有单个模式的子目录和具有单个模式的该文件夹的子目录,然后是具有另一个单一模式的子目录,然后仅提供其中的 .edf 文件文件夹。我可以在这段代码中做 .edf 文件的事情

我是通过这两个函数来做的。

Function Recursive(FolderPath As String)
Dim Value As String, Folders() As String
Dim Folder As Variant, a As Long
ReDim Folders(0)
If Right(FolderPath, 2) = "\\" Then Exit Function
Value = Dir(FolderPath, &H10)
Do Until Value = ""
    If Value = "." Or Value = ".." Then
    Else
        If GetAttr(FolderPath & Value) = 16 Then
            Folders(UBound(Folders)) = Value
            ReDim Preserve Folders(UBound(Folders) + 1)
        Else
            If Count = 4 Then
                temp(0, UBound(temp, 2)) = FolderPath
                temp(1, UBound(temp, 2)) = Value
                temp(2, UBound(temp, 2)) = Count ' FileLen(FolderPath & Value)
                ReDim Preserve temp(UBound(temp, 1), UBound(temp, 2) + 1)
                End If
        End If
    End If
    Value = Dir
Loop
For Each Folder In Folders
    Count = Count + 1
    Recursive FolderPath & Folder & "\"
    Count = Count - 1
Next Folder
End Function

Public temp() As String
Public Count As Integer
Function ListFiles(FolderPath As String)
Dim k As Long, i As Long
ReDim temp(2, 0)
Count = 1
If Right(FolderPath, 1) <> "\" Then
    FolderPath = FolderPath & "\"
End If
Recursive FolderPath
k = Range(Application.Caller.Address).Rows.Count
If k < UBound(temp, 2) Then
    MsgBox "There are more rows, extend user defined function"
Else
    For i = UBound(temp, 2) To k
          ReDim Preserve temp(UBound(temp, 1), i)
            temp(0, i) = ""
            temp(1, i) = ""
            temp(2, i) = ""
    Next i
End If
ListFiles = Application.Transpose(temp)
ReDim temp(0)
End Function

【问题讨论】:

  • 您好,欢迎来到 Stack Oberflow。在发布之前,请花时间阅读我们帮助中的mcve 部分。
  • 感谢您的评论。显然这是我的第一个问题。您能否指出问题的问题所在。我已经浏览了帮助部分,但我无法弄清楚。
  • 没有实际问题被问到。您在使用的脚本中报告了哪些错误?
  • @nbayly 此代码用于循环遍历所有目录和文件。我无法对其进行编辑,使其仅提供具有单个模式的子目录和具有单个模式的该文件夹的子目录,然后是具有另一个单一模式的子目录,然后仅提供其中的 .edf 文件文件夹。我可以在这段代码中做 .edf 文件的事情。

标签: vba excel


【解决方案1】:

我对 Scripting.Dictionary 对象采取了不同的方法。在 ABC 和 XYZ 级别创建包含多个文件夹的目录结构(匹配和不匹配)后,我用 *.txt 和 *.edf 文件填充了最终文件夹。

以下过程使用早期绑定加载 Scripting.Dictionary 对象。这需要使用 VBE 的工具 ► 参考将 Microsoft Scripting Runtime 添加到项目中。为了更通用,可以通过最初将 dFNs 变量调暗为对象并使用 CreateObject method 来使用 Late Binding

Sub main()
    Dim fm As Long, sFM As String, vFMs As Variant, sMASK As String
    Dim fn As Variant, dFNs As New Scripting.Dictionary

    sFM = Environ("TMP") & "\Main Directory\ABC*\Y\XYZ*\*.edf"
    If UBound(Split(sFM, Chr(42))) < 2 Then Exit Sub  '<~~possibly adjust this safety
    sFM = Replace(sFM, "/", "\")
    vFMs = Split(sFM, Chr(92))

    sMASK = vFMs(LBound(vFMs))
    For fm = LBound(vFMs) + 1 To UBound(vFMs)
        sMASK = Join(Array(sMASK, vFMs(fm)), Chr(92))
        If CBool(InStr(1, vFMs(fm), Chr(42))) Or fm = UBound(vFMs) Then
            build_FolderLevels dFNs, sFM:=sMASK, iFLDR:=Abs((fm < UBound(vFMs)) * vbDirectory)
            sMASK = vbNullString
        End If
    Next fm

    'list the files
    For Each fn In dFNs
        Debug.Print "from dict: " & fn
    Next fn

    dFNs.RemoveAll: Set dFNs = Nothing
End Sub

Sub build_FolderLevels(dFMs As Scripting.Dictionary, _
                       Optional sFM As String = "", _
                       Optional iFLDR As Long = 0)
    Dim d As Long, fp As String, vFMs As Variant

    If CBool(dFMs.Count) Then
        vFMs = dFMs.Keys
        For d = LBound(vFMs) To UBound(vFMs)
            vFMs(d) = vFMs(d) & sFM
        Next d
    Else
        vFMs = Array(sFM)
    End If
    dFMs.RemoveAll

    For d = LBound(vFMs) To UBound(vFMs)
        fp = Dir(vFMs(d), iFLDR)
        Do While CBool(Len(fp))
            dFMs.Add Key:=Left(vFMs(d), InStrRev(vFMs(d), Chr(92))) & fp, _
                     Item:=iFLDR
            fp = Dir
        Loop
    Next d
End Sub

为了促进递归行为,我将字典键传递给变量数组,然后擦洗字典。使用与新通配符掩码连接的数组元素,我重新填充了字典。冲洗并重复,直到完成所有可能的组合。

以下是 VBE 立即窗口的结果。

main
from dict: t:\TMP\Main Directory\ABC\Y\XYZ\Temp.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ\Temp1.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ\Temp2.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ1\Temp.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ1\Temp1.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ1\Temp2.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ2\Temp.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ2\Temp1.edf
from dict: t:\TMP\Main Directory\ABC\Y\XYZ2\Temp2.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ\Temp.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ\Temp1.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ\Temp2.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ1\Temp.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ1\Temp1.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ1\Temp2.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ2\Temp.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ2\Temp1.edf
from dict: t:\TMP\Main Directory\ABC1\Y\XYZ2\Temp2.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ\Temp.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ\Temp1.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ\Temp2.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ1\Temp.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ1\Temp1.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ1\Temp2.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ2\Temp.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ2\Temp1.edf
from dict: t:\TMP\Main Directory\ABC2\Y\XYZ2\Temp2.edf

我还在您的原始通配符路径上运行了几个变体,并取得了类似的成功。

【讨论】:

  • 感谢您的回答。这似乎很棒。但是我的编译器在 dFNs As New Scripting.Dictionary 处给出用户定义类型未定义错误。我是 vba 的新手。如果你能告诉我如何解决这个问题,我会很高兴。
  • 我真的很抱歉这些愚蠢的问题,但我没时间了。它在 fp = Dir(vFMs(d), iFLDR) 处给出运行时错误。变量 vFMs(d) 给出了以非常不寻常的方式连接的两条路径。我认为这是问题所在,但我不知道如何解决。
  • 恐怕我无法重现它,而且如果不对您的目录树的精确副本进行测试,我也不太可能做到。您可以尝试在原始文件掩码的字符串分配中使用传统的反斜杠,但除此之外,我不确定发生了什么。显然,你已经改变了原来的东西,因为我正在使用我的临时文件夹,而你正在使用 C:
  • 我没有改变任何东西。只是根据代码中的模板替换了链接。但是感谢您的帮助。我会试着从这里弄清楚自己。
  • 如果你有足够的时间,我可以把原始文件夹发给你吗?非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 2018-11-15
  • 2016-01-22
  • 2013-10-09
  • 1970-01-01
  • 2021-12-18
相关资源
最近更新 更多