ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] 请各位老师指教:《循环遍历文件夹》宏(通用)

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-6-9 14:17 | 显示全部楼层 |阅读模式
* 据网文称,VBA遍历文件夹常用有三种方法,这三种方法中,filesearch不适合2007和2010版本,而且速度比较慢;递归法FSO速度也慢;只有用DIR加循环(+双字典+数组)的方法,速度飞快。
* 我决定抛弃 Word2003 的 FileSearch 法,FSO法也慢也不用,采用 Dir + 循环 + 双字典 + 数组 的方法。
* 从网上找了一段代码,原作者是 kiddragon,在此表示感谢!虽然不懂字典、数组,但我仍做了一些修改。
* 下面的代码在 Word2007/2003 中测试通过,运行正常(测试了包含 25 个文件和 62 个文件的文件夹)!
——请各位老师、朋友指教,是否还有更好、更快的方法?
  1. Sub LoopDir循环遍历文件夹()
  2.     On Error Resume Next

  3.     Dim objShell As Object
  4.     Dim objFolder As Object
  5.     Dim SearchPath As String

  6.     Set objShell = CreateObject("Shell.Application")
  7.     Set objFolder = objShell.BrowseForFolder(0, "请选择文件夹!", 0, 0)

  8.     SearchPath = objFolder.self.Path & ""

  9.     If MsgBox("请确认!是否处理文件夹 " & SearchPath & " ?", 4 + 16) = vbNo Then Exit Sub

  10.     Set objShell = Nothing
  11.     Set objFolder = Nothing

  12.     Dim DicList As Object
  13.     Dim FileList As Object
  14.     Dim Key
  15.     Dim NowDic As String
  16.     Dim NowFile As String
  17.     Dim i As Long
  18.     Dim FileName, FilePath

  19.     Set DicList = CreateObject("Scripting.Dictionary")
  20.     Set FileList = CreateObject("Scripting.Dictionary")

  21.     DicList.Add SearchPath, ""

  22.     i = 0
  23.     Do While i < DicList.Count
  24.         Key = DicList.keys
  25.         NowDic = Dir(Key(i), vbDirectory)
  26.         Do While NowDic <> ""
  27.             If (NowDic <> ".") And (NowDic <> "..") Then
  28.                 If (GetAttr(Key(i) & NowDic) And vbDirectory) = vbDirectory Then DicList.Add Key(i) & NowDic & "", ""
  29.             End If
  30.             NowDic = Dir()
  31.         Loop
  32.         i = i + 1
  33.     Loop

  34.     For Each Key In DicList.keys
  35.         NowFile = Dir(Key)
  36.         Do While NowFile <> ""
  37.             FileList.Add NowFile, Key
  38.             NowFile = Dir()
  39.         Loop
  40.     Next

  41.     Dim doc As Document
  42.     Dim x&
  43.     i = 0
  44.     FileName = FileList.keys
  45.     FilePath = FileList.Items
  46.     Do While i < FileList.Count
  47.         If FilePath(i) & FileName(i) Like "*.doc*" Then
  48.             Set doc = Documents.Open(FileName:=FilePath(i) & FileName(i), Visible:=False)
  49.             doc.Content.Font.Color = wdColorRed '单个文档处理
  50.             doc.Close SaveChanges:=wdSaveChanges
  51.             x = x + 1
  52.         End If
  53.         i = i + 1
  54.     Loop

  55.     Set DicList = Nothing
  56.     Set FileList = Nothing

  57.     MsgBox "文件夹包含 " & i & " 个文件!" & vbCr & "共处理 Word 文档(*.docx/*.doc) " & x & " 个!", 0 + 48
  58. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-6-9 14:19 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
* 原作者 kiddragon 代码:
  1. Sub 循环遍历文件夹及子文件夹_显示所有文件的文件名()
  2. 'Code by kiddragon
  3. 'TEST-OK/2019-6-8
  4.     Dim Key, NowDic, NowFile
  5.    
  6.     Const SearchPath = "E:\LoopDir"
  7.       
  8.     Dim DicList, FileList, i, FileName, FilePath
  9.    
  10.     Set DicList = CreateObject("Scripting.Dictionary")
  11.     Set FileList = CreateObject("Scripting.Dictionary")
  12.       
  13.     DicList.Add SearchPath, ""  '初始化目录
  14.       
  15.     '遍历所有目录并添加到DicList
  16.     i = 0
  17.     Do While i < DicList.Count
  18.         Key = DicList.keys '本次要遍历的目录
  19.         NowDic = Dir(Key(i), vbDirectory) '开始查找
  20.         Do While NowDic <> ""
  21.             If (NowDic <> ".") And (NowDic <> "..") Then
  22.                 If (GetAttr(Key(i) & NowDic) And vbDirectory) = vbDirectory Then
  23.                     '找到子目录,则添加
  24.                     DicList.Add Key(i) & NowDic & "", ""
  25.                 End If
  26.             End If
  27.             NowDic = Dir() '再找
  28.         Loop
  29.         i = i + 1
  30.     Loop

  31.     '遍历目录中的所有文件并将其添加到FileList中,FileList.Key=文件名,FileList.Item=目录
  32.     For Each Key In DicList.keys '查找所有目录中的文件
  33.         'MsgBox key
  34.        NowFile = Dir(Key)
  35.        Do While NowFile <> ""
  36.             'MsgBox NowFile
  37.             FileList.Add NowFile, Key 'Add(Key,Item)  FileList.Key=文件名,FileList.Item=目录
  38.             NowFile = Dir()
  39.        Loop
  40.     Next
  41.    
  42.     i = 0
  43.     FileName = FileList.keys
  44.     FilePath = FileList.Items
  45.     Do While i < FileList.Count
  46.         '弹出所有查询到的文件字符串
  47.         MsgBox FilePath(i) & FileName(i)
  48.         i = i + 1
  49.     Loop
  50.    
  51. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-6-9 14:23 | 显示全部楼层
本帖最后由 413191246se 于 2019-6-9 14:26 编辑

* 各位朋友们,如果有想循环遍历文件夹及子文件夹的要求,可以使用 1 楼代码,但请注意:第 60 行代码要自行修改(单个文档处理,自定义单个文档的格式处理即可,其它的不用管)。
* 如果采用 1 楼代码,请事先做好文件备份,以免造成损失,谢谢!


TA的精华主题

TA的得分主题

发表于 2019-6-9 14:49 来自手机 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 duquancai 于 2019-6-9 20:37 编辑

编程不学function,真是悲哀!不学class,当然也是悲哀!
话说:“只有用DIR加循环(+双字典+数组)的方法,速度飞快。”请问:这个结论从何而来?

TA的精华主题

TA的得分主题

发表于 2019-6-9 19:59 | 显示全部楼层
作者阿杜:
Sub FSO_提取全路径文件()
    Dim f As Object, fd As Object, fso As Object, Stack$(), top&
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show Then pPath$ = .SelectedItems(1) Else MsgBox "请选目标文件夹": Exit Sub
    End With
    Set fso = CreateObject("Scripting.FileSystemObject")
    top = 1: ReDim Stack(0 To top)
    Do While top >= 1
        For Each f In fso.GetFolder(pPath).Files
            n = n + 1
            stxt = stxt & f.Path & Chr(13)
        Next
        For Each fd In fso.GetFolder(pPath).SubFolders
            Stack(top) = fd.Path: top = top + 1
            If top > UBound(Stack) Then ReDim Preserve Stack(0 To top)
        Next
        If top > 0 Then pPath = Stack(top - 1): top = top - 1
    Loop
    ActiveDocument.Content.Text = Empty
    ActiveDocument.Content.Text = stxt
    MsgBox "已提取:" & n & "个包含选择路径下的所有文件!"
End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-6-9 20:46 | 显示全部楼层
本帖最后由 413191246se 于 2019-6-9 21:05 编辑

    杜老师:我不会的很多,如:函数、数组、字典、FSO、类……等,好多好多,关键是,本人天资还很愚笨。“DIR + 循环”速度飞快,是网文上说的,我就信了,反正我也不会。现在,我用 VBA 查找和替换,还算有些心得,其它的真不会。虽然我常常幻想能达到微软软件工程师那个水平,想编啥编啥。

    小花鹿 老师:谢谢提供代码,我要做一下比较(VS),和我 1 楼代码比比。FSO 也好,DIR 循环也好,都不懂,我只好凭实际测试结果来采纳。

    两位老师,现在我一维数组,都不大会,也会一点,反正稀里糊涂的。

    *******************
    前几天,安装上了 Office2007,仍然保留 Office2003,现在可以两个都使用,但我现在偏爱 Word2007(我也只用 Word,其它组件均不使用)。以前也安装过几次 Office2007,但都卸载了;另外,发现 Word2007 其实也经常崩溃,和 Word2003 没啥大区别。

    昨晚我想,Word2007 是不是在 Word2003 的基础上,多了一个 Ribbon 界面而已呢?

    我过去曾经安装过 VB6.0,但没怎么学会编程,连《计算器》都不会编。后来在会录制宏的基础上,在2011年6月间突然开窍,知道进 VBE 编辑代码了!以前不会,其实在 VB6.0 中我已经见过 VBE。在 2011年7月进本坛,直到现在已有 8 年了,有些进步,但进步不大。这两年,跟 杜老师 学习了一些《方法/属性》及代码简写的一些知识,进步较大。

    谢谢两位老师回复! 并请时常指教。——杜老师,我今晚就要学一学 Function。



TA的精华主题

TA的得分主题

 楼主| 发表于 2019-6-10 01:21 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2019-6-10 08:43 来自手机 | 显示全部楼层
不懂function,不懂class,不懂数据结构与算法,去谈效率纯属扯淡!

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-6-10 10:09 | 显示全部楼层
谢谢 杜老师 批评指正!有空我要学学函数,但现在我还是想把自动排版宏(通用模板宏)重新搞一搞。
搞一个通用于 2007和 2003 之间的唯一的一个。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-24 20:33 , Processed in 0.035715 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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