ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 1895|回复: 12

[求助] 求助大神,遍历文件夹的问题

[复制链接]

TA的精华主题

TA的得分主题

发表于 2020-10-30 21:35 | 显示全部楼层 |阅读模式
我想要搜索文件夹下(还有子文件夹)包含特定字段的word文件,然后打开它,如何写程序?、比如:我要寻找C:\Users\Administrator\Desktop\哈哈    文件夹下(包含子文件夹)的所有包含“不动产”三个字的word文档,并打开它。

网上研究了几天了,还没有搞定,望大神指点。






360截图18720124609952.jpg

TA的精华主题

TA的得分主题

发表于 2020-10-31 13:06 | 显示全部楼层
* 请 楼主 备份后试用如下宏:
  1. Sub LoopFolder_duquancai()
  2.     Dim pPath$, f As Object, fd As Object, fso As Object, Stack$(), top&, n&, stxt$, doc As Document, x&
  3.     pPath = "C:\Users\Administrator\Desktop\哈哈"
  4.     Set fso = CreateObject("Scripting.FileSystemObject")
  5.     top = 1
  6.     ReDim Stack(0 To top)
  7.     Do While top >= 1
  8.         For Each f In fso.getfolder(pPath).Files
  9.             n = n + 1
  10.             stxt = f.Path
  11.             If stxt Like "*.doc*" Then
  12.                 Set doc = Documents.Open(FileName:=stxt)
  13.                 If doc.Content Like "*不动产*" Then doc.Content.Font.ColorIndex = wdRed
  14.                 doc.Close SaveChanges:=wdSaveChanges
  15.                 x = x + 1
  16.             End If
  17.         Next
  18.         For Each fd In fso.getfolder(pPath).SubFolders
  19.             Stack(top) = fd.Path
  20.             top = top + 1
  21.             If top > UBound(Stack) Then ReDim Preserve Stack(0 To top)
  22.         Next
  23.         If top > 0 Then pPath = Stack(top - 1): top = top - 1
  24.     Loop
  25.     Set f = Nothing
  26.     Set fd = Nothing
  27.     Set fso = Nothing
  28.     MsgBox "文件夹包含 " & n & " 个文件!" & vbCr & "共处理 Word 文档(*.docx/*.doc) " & x & " 个!", 0 + 48
  29. End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-10-31 15:21 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-10-31 15:35 | 显示全部楼层
413191246se 发表于 2020-10-31 13:06
* 请 楼主 备份后试用如下宏:

大神,您的word VBA是哪里学的? 我在网上买了些课程,发现都是教了一些很基础的东西。我都找不到相关的深度课程。   

TA的精华主题

TA的得分主题

发表于 2020-11-1 01:42 | 显示全部楼层
微软官方有个帮助文档,学好它就可以了。请将光标放在代码中,按 F1 键试试是否会出来帮助。

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-11-1 17:44 | 显示全部楼层
413191246se 发表于 2020-11-1 01:42
微软官方有个帮助文档,学好它就可以了。请将光标放在代码中,按 F1 键试试是否会出来帮助。

多谢了,大神!

TA的精华主题

TA的得分主题

发表于 2020-11-29 21:14 | 显示全部楼层
413191246se 发表于 2020-10-31 13:06
* 请 楼主 备份后试用如下宏:

If top > 0 Then pPath = Stack(top - 1): top = top - 1
这句不太明白,想请教下大神是什么意思

TA的精华主题

TA的得分主题

发表于 2020-11-29 22:21 | 显示全部楼层
楼上朋友,此宏是 杜老师(duquancai)所写,其实我也不明白。

TA的精华主题

TA的得分主题

发表于 2020-11-30 06:48 | 显示全部楼层
前不久看到的,看有不有用!


VBA 7种遍历方法:


Sub 简单遍历测试()
    For Each F In Dir遍历 'Office2003遍历、FSO遍历、双字典遍历、CMD遍历、栈遍历、管道遍历、Dir遍历。
    '-------------------------此处加入文件处理代码即可。
        Selection.InsertAfter F & Chr(13)
        i = i + 1
    Next
    Selection.InsertAfter i
MsgBox "OKOK!!!", vbOKOnly, "OKKO"
End Sub


Sub 单个文档处理(F)
    Dim pa As Paragraph, c As Range
    With Documents.Open(F, Visible:=False)
        For Each pa In .Paragraphs
            For Each c In pa.Range.Characters
                If c.Font.Name = "仿宋" And Abs(Asc(c)) > 128 Then
                    c.Font.Name = "仿宋_GB2312"
                ElseIf c.Font.Name = "仿宋" And Abs(Asc(c)) < 128 Then
                    c.Font.Name = "Times New Roman"
                End If
            Next
        Next
        .Close True
    End With
End Sub


' 遍历文件夹
Function CMD遍历()
    Dim arr
    Dim t: t = Timer
    With Application.FileDialog(msoFileDialogFolderPicker)
'        .InitialFileName = "D:\"   '若不加这句则打开上次的位置
        If .Show <> -1 Then Exit Function
        fod = .InitialFileName
    End With
    CMD遍历文件 arr, fod, "*.doc*"
    arr = Filter(arr, "*", False, vbTextCompare)
    CMD遍历 = arr
End Function


Function 栈遍历()
    Dim arr() As String
    Dim t: t = Timer
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show <> -1 Then Exit Function
        fod = .InitialFileName
    End With
    遍历栈 arr, CStr(fod), "doc*", True '这种方式就不用使用Function在函数中返回了
    栈遍历 = arr
End Function


Function 管道遍历()
    Dim t: t = Timer
    Dim a As New DosCMD
    Dim arr
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show <> -1 Then Exit Function
        fod = .InitialFileName
    End With
    a.DosInput Environ$("comspec") & " /c dir " & Chr(34) & fod & "\*.doc*" & Chr(34) & " /s /b /a:-d"
    arr = a.DosOutPutEx        '默认等待时间120s
    arr = Split(arr, vbCrLf)   '分割成数组
    arr = Filter(arr, ".doc", True, vbTextCompare) '仅保留doc文件
    arr = Filter(arr, "*", False, vbTextCompare)
    arr = Filter(arr, "$", False, vbTextCompare)
    管道遍历 = arr
    'For Each F In arr
    '   If InStr(F, "$") = 0 And F <> "" Then
    '   Debug.Print F
    '   单个文档处理代码 (F)'-------------------------------------------------------
    '   End If
    'Next
    'MsgBox "已完成!!!", vbOKCancel, "代码处理"
End Function


Function AllName()    '遍历获得文件名,交给数组,不变的部分;'选定的所有word文档
    With Application.FileDialog(msoFileDialogFilePicker)
        .Filters.Add "选择03版word文档", "*.doc", 1
        .Filters.Add "所有文件", "*.*", 2
        If .Show <> -1 Then Exit Function
        For Each F In .SelectedItems
            If InStr(F, "$") = 0 Then
                str0 = str0 & F & Chr(13)
            End If
        Next
    End With
    AllName = Left(str0, Len(str0) - 1)
End Function


Function AllFodName()    '用dos命令遍历选定文件夹下的所有word文档
    Dim fso As Object
    Dim aCollection As New Collection
    Set fso = CreateObject("scripting.filesystemobject")
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "选择文档所在文件夹"
        If .Show <> -1 Then Exit Function
        folder = .SelectedItems(1)
    End With
    Set ws = CreateObject("WScript.Shell")
    '    ws.Run Environ$("comspec") & " /c dir " & folder & "\*.ppt /s /a:-d /b/on|find /v" & Chr(34) & ".pptx" & Chr(34) & "> C:\temp.txt", 0, True
    ws.Run Environ$("comspec") & " /c dir " & Chr(34) & folder & Chr(34) & "\*.doc* /s /a:-d /b/on" & "> C:\temp.txt", 0, True

    Open "C:\temp.txt" For Input As #1
    arr = Split(StrConv(InputB(LOF(1), 1), vbUnicode), vbCrLf)
    Close #1
    ws.Run Environ$("comspec") & " /c del /q /s " & Chr(34) & "C:\temp.txt" & Chr(34), 0, False    '删除临时文件
    Set ws = Nothing
    '    '--------------------------此处是否多此一举?-----------------------
    '    For i = LBound(arr) To UBound(arr) - 1  '使用集合提高效率
    '        aCollection.Add arr(i)
    '    Next
    '    '--------------------------------------------------------------------
    '    For i = 0 To UBound(arr)
    '         aname = CreateObject("Scripting.FileSystemObject").GetBaseName(arr(i))
    '         If InStr(1, aname, "$") = 0 Then
    '         If InStr(1, arr(i), "$") = 0 Then Debug.Print arr(i)
    '         Selection.InsertAfter arr(i)
    '         End If
    '    Next
    AllFodName = arr
End Function


Function FSO遍历()  '我的得意代码之十五!!!文档不引用
    '*------------------------------------------------------------------------------*
    Dim fso As Object, b As Object, arr() As String, F  '注意,这里的as string是必须,否则,filter函数无法使用。因为收集的不是字符串形式的地址
    Set fso = CreateObject("scripting.filesystemobject")
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show <> -1 Then Exit Function
        fod = .InitialFileName
    End With
    For Each F In fso.GetFolder(fod).Files   '目录本身的
        ReDim Preserve arr(i)
        arr(i) = F
        i = UBound(arr) + 1
    Next
    查找子目录 fod, arr, fso
    arr = Filter(arr, ".doc", True, vbTextCompare)  '仅保留doc文件
    arr = Filter(arr, "*", False, vbTextCompare)
    arr = Filter(arr, "$", False, vbTextCompare)  '过滤掉带有$符号的文件
    FSO遍历 = arr
    Set fso = Nothing
End Function
Function 查找子目录(ByVal fod As String, arr, fso)
    If fso.FolderExists(fod) Then
        If Len(fso.GetFolder(fod)) = 0 Then
            Debug.Print "文件夹" & fod & " 是空的!"  '这里似乎用不上
        Else
            For Each zi In fso.GetFolder(fod).SubFolders
                For Each F In zi.Files  '子目录中的
                    i = UBound(arr) + 1
                    ReDim Preserve arr(i)
                    arr(i) = F
                Next
                查找子目录 zi, arr, fso
            Next
        End If
    End If
End Function


Function Dir遍历()
Dim arr() As String
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show <> -1 Then Exit Function
        fod = .InitialFileName
    End With
处理子目录 fod, arr
    arr = Filter(arr, ".doc", True, vbTextCompare) '仅保留doc文件
    arr = Filter(arr, "$", False, vbTextCompare) '过滤掉带有$符号的文件
Dir遍历 = arr
End Function


Sub 处理子目录(p, arr)
On Error Resume Next
    Dim a As String, b() As String, c() As String
    If Right(p, 1) <> "\" Then p = p + "\"
    MY = Dir(p, vbDirectory Or vbHidden Or vbNormal Or vbReadOnly)
    Do While MY <> ""
        If MY <> ".." And MY <> "." Then
            If (GetAttr(p + MY) And vbDirectory) = vbDirectory Then
                n = n + 1
                ReDim Preserve b(n)
                b(n - 1) = MY
            Else
            On Error Resume Next
                i = UBound(arr) + 1
            On Error GoTo 0
                ReDim Preserve arr(i)
                arr(i) = p + MY
            End If
        End If
        MY = Dir
    Loop
    For j = 0 To n - 1
        处理子目录 (p + b(j)), arr
    Next
    ReDim b(0)
End Sub


Function Office2003遍历()    '-------------参考
    Dim sFile As String, arr() As String
    With Application.FileDialog(msoFileDialogFolderPicker)
'        .InitialFileName = "D:\"   '若不加这句则打开上次的位置
        If .Show <> -1 Then Exit Function
        bc = .InitialFileName
    End With
    Set mySearch = Application.FileSearch    '定义一个Application.FileSearch
        With mySearch
            .NewSearch    '设置一个新搜索
            .LookIn = bc    '在该驱动器盘符下
            .SearchSubFolders = True    '搜索子文件夹
            '    .FileType = msoFileTypeWordDocuments           '以此可以定义文件类型
            .FileName = "*.DOc*"    '搜索一个指定文件,此处为任意WORD模板文件
            If .Execute() > 0 Then    '开始并搜索成功
                For i = 1 To .FoundFiles.Count
                    ReDim Preserve arr(i - 1)
                    arr(i - 1) = .FoundFiles(i)
                Next i
            End If
        End With
Office2003遍历 = arr
End Function

TA的精华主题

TA的得分主题

发表于 2020-11-30 06:49 | 显示全部楼层
Function 双字典遍历()    ' 字典分为word的dictionary和scripting的dictionary,这里的是后者。
    Dim d1, d2    'as Dictionary
    Set d1 = CreateObject("scripting.dictionary")
    Set d2 = CreateObject("scripting.dictionary")
    With Application.FileDialog(msoFileDialogFolderPicker)
        '.InitialFileName = "D:\"   '若不加这句则打开上次的位置
        If .Show <> -1 Then Exit Function
        path1 = .InitialFileName
    End With
    d1.Add path1, ""  '目录最后一个字符必须为"\"
    '*---------------------------第一个字典获取目录总数和名称----------------------------*
    i = 0    '
    Do While i < d1.Count    '第几个i就是进入第几个文件夹!i从0开始。d1.count为找到的文件夹总数。
        ke = d1.keys
        ML = Dir(ke(i), vbDirectory)
        Do While ML <> ""
            'Debug.Print d1.Count
            If ML <> "." And ML <> ".." Then
                If (GetAttr(ke(i) & ML) And vbDirectory) = vbDirectory Then    '第一个括号必须有
                    d1.Add ke(i) & ML & "\", ""
                End If
            End If
            ML = Dir()
        Loop
        i = i + 1
    Loop
    '*---------------------------第二个字典获取各个目录的文件名----------------------------*
    For Each ke In d1.keys
        fa = Dir(ke & "*.doc*")    '也可以是“*.*”,也可以用fso操作这里
        Do While fa <> ""
            '            d2.Add fa, "ite"    'dictionary的item可以相同,可以为空,而key决不可相同,是唯一的!
            d2.Add ke & fa, "ite"    'dictionary的item可以相同,可以为空,而key决不可相同,是唯一的!【加了ke & ,完整路径;】
            fa = Dir  '上面的"ite"可以改成"",或任意其他值。
        Loop
    Next
    '*--------------------------ke在这里可循环利用,打印看看key和item都是什么----------------------------*
    '    For Each ke In d2.keys
    '        Debug.Print ke
    '    Next
    '    For Each ke In d2.Items
    '        Debug.Print ke
    '    Next
    '*---------------------------最后释放字典对象----------------------------*
    双字典遍历 = d2.keys
    Set d1 = Nothing
    Set d2 = Nothing
End Function


Function CMD遍历文件(ByRef arr, ByVal aPath$, ByVal aExtensionName$)
    Dim aNum%
    Dim t: t = Timer
    With CreateObject("WScript.Shell")
        If Right(aPath, 1) <> "\" Then aPath = aPath & "\"
        .Run Environ$("comspec") & " /c dir " & Chr(34) & aPath & aExtensionName & Chr(34) & " /s /b /a:-d > C:\tmpDoc.txt", 0, True    '遍历获取Word文件,并列表到临时文件,同步方式
        aNum = FreeFile()                                     '空闲文件号[上面最后一个参数true的作用是等待cmd语句执行完毕后再执行下面的语句]
        Open "C:\tmpDoc.txt" For Input As #aNum
        arr = Split(StrConv(InputB(LOF(aNum), aNum), vbUnicode), vbCrLf)    '将遍历结果从文件读取到数组中
        Close #aNum
        '.Run Environ$("comspec") & " /c del /q /s " & Chr(34) & "C:\tmpDoc.txt" & Chr(34), 0, False    '删除临时文件,异步方式
    End With
    arr = Filter(arr, "$", False, vbTextCompare)                        '不包含$,即非word临时文件
End Function


Function FolderSearch(ByRef mlNameArr() As String, pPath As String, pSub As Boolean)  '搜索子目录
'mlNameArr装文件名动态数组,pSub子目录开关,pPath搜索起始路径
    On Error Resume Next
    Dim DirFile, mf&, pPath1$
    Dim workStack$(), top&    'workstack工作栈,top栈顶变量
    pPath = Trim(pPath)
    If Right(pPath, 1) <> "\" Then pPath = pPath & "\"    ' 对搜索路径加 backslash(反斜线)
    pPath1 = pPath
    top = 1
    ReDim Preserve workStack(0 To top)
    Do While top >= 1
        DirFile = Dir(pPath1, vbDirectory)
        Do While DirFile <> ""
            If DirFile <> "." And DirFile <> ".." Then
                If (GetAttr(pPath1 & DirFile) And vbDirectory) = vbDirectory Then
                    mf = mf + 1
                    ReDim Preserve mlNameArr(1 To mf)
                    mlNameArr(mf) = pPath1 & DirFile
                End If
            End If
            DirFile = Dir
        Loop
        If pSub = False Then Exit Function
        DirFile = Dir(pPath1, vbDirectory)    ' 搜索子目录
        Do While DirFile <> ""
            If DirFile <> "." And DirFile <> ".." Then
                If (GetAttr(pPath1 & DirFile) And vbDirectory) = vbDirectory Then
                    workStack(top) = pPath1 & DirFile & "\"    '压栈
                    top = top + 1
                    If top > UBound(workStack) Then ReDim Preserve workStack(0 To top)
                End If
            End If
            DirFile = Dir
        Loop
        If top > 0 Then pPath1 = workStack(top - 1): top = top - 1    '弹栈
    Loop
End Function


Function 遍历栈(ByRef fileNameArr() As String, pPath As String, pMask As String, pSub As Boolean)
'fileNameArr装文件名动态数组,psb子目录开关,pPath搜索起始路径,pMask扩展名(如doc)
    On Error Resume Next
    Dim DirFile, mf&, pPath1$
    Dim workStack$(), top&    'workstack工作栈,top栈顶变量
    pPath = Trim(pPath)
    If Right(pPath, 1) <> "\" Then pPath = pPath & "\"    ' 对搜索路径加 backslash(反斜线)
    pPath1 = pPath
    top = 1
    ReDim Preserve workStack(0 To top)
    Do While top >= 1
        DirFile = Dir(pPath1 & "*." & pMask)
        Do While DirFile <> ""
            mf = mf + 1
            ReDim Preserve fileNameArr(1 To mf)
            fileNameArr(mf) = pPath1 & DirFile
            DirFile = Dir
        Loop
        If pSub = False Then Exit Function
        DirFile = Dir(pPath1, vbDirectory)    ' 搜索子目录
        Do While DirFile <> ""
            If DirFile <> "." And DirFile <> ".." Then
                If (GetAttr(pPath1 & DirFile) And vbDirectory) = vbDirectory Then
                    workStack(top) = pPath1 & DirFile & "\"    '压栈
                    top = top + 1
                    If top > UBound(workStack) Then ReDim Preserve workStack(0 To top)
                End If
            End If
            DirFile = Dir    'next file
        Loop
        If top > 0 Then pPath1 = workStack(top - 1): top = top - 1    '弹栈
    Loop
End Function

评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-25 22:23 , Processed in 0.042468 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表