打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
一、VB语句获取文件夹、文件路径

(一)Dir 函数

该函数返回一个 String(字符串),用以表示一个文件名、目录名或文件夹名称,它必须与指定的模式或文件属性、或磁盘卷标相匹配。

语法:

Dir[(pathname[, attributes])]

Dir 函数的语法具有以下几个部分:

部分

描述

pathname

用来指定文件名的字符串表达式,可能包含目录或文件夹、以及驱动器。如果没有找到 pathname,则会返回零长度字符串 ("")

Microsoft Windows 中, Dir 支持多字符 (*) 和单字符 (?) 的通配符来指定多重文件。

attributes

可选参数。常数或数值表达式,其总和用来指定文件属性。如果省略,则会返回匹配 pathname 但不包含属性的文件。

Dir函数的两个参数都是可选的,pathname是文件或文件夹名称,对于参数attributes本教程只介绍常用的 vbDirectory 属性。

 

接下来,以遍历下图文件夹数据的过程为例来演示一下Dir函数的用法。

 

该文件夹的树形结构如下。

 

C:\Users\Administrator\Desktop\vba\demo

│  01 (1).xlsx

│  01 (2).xlsx

│  文件夹改名.xls

│  新建文本文档.txt

1601

│     430Forbidden.png

1603

│     1.txt

└─1605

       添加字段属性表.xlsx

 

1.遍历文件夹下的文件

Dir(“Pathname”) 参数为文件夹路径,路径以 ”\” 结尾,例:Dir("C:\Users\Administrator\Desktop\vba\demo\")

执行Dir函数返回文件夹下的第一个文件名:01 (1).xlsx

继续执行Dir(不需要加参数),会返回第23……序列的文件名,直到遍历结束返回一个空字符串(””)。

在本例中执行Dir函数4次即返回所有文件名,在第5次执行时便返回空字符串并销毁对象,如果继续执行第6次则程序报错。

1.1构造循环体实现自动遍历

根据Dir函数返回文件名的逻辑我们可以构造一个循环体来自动遍历文件,取文件名。

使用 Do While(文件名不等于””)……Loop的循环结构正合适。

 

1.2使用通配符匹配文件

Microsoft Windows 中, Dir 支持多字符(*) 和单字符 (?) 的通配符来指定多重文件。

*匹配多字符

匹配出demo文件夹下的3Excel文件。将Dir的参数稍加改动,使用一个(*)匹配文件名,使用一个(*)匹配扩展名中的sx或者x

  fileName =Dir("C:\Users\Administrator\Desktop\vba\demo\*.xl*")

 

Sub DirTestLoop_Star()

    DimfileName As String

    DimrowIndex As Integer

    Columns(1).Clear  '清空A列,便于观察程序执行结果

    fileName = Dir("C:\Users\Administrator\Desktop\vba\demo\*.xl*")

    rowIndex = 1

    Do While fileName <> ""

        Cells(rowIndex,1).Value =fileName

        rowIndex =rowIndex + 1

        fileName = Dir

    Loop

End Sub

 

返回结果:

?匹配单字符

      匹配01(1).xlsx 01 (2).xlsx

fileName = Dir("C:\Users\Administrator\Desktop\vba\demo\01(?).xlsx")

返回结果:

1.3获取文件全路径

实际操作中操作目的往往是获取文件全路径,然后对其进行改名、移动、复制、删除等的操作,那么如何获取文件的全路径呢?很简单,我们已经获取了文件名,在前面加上文件夹路径便是全名了。在代码中一般先声明一个变量folderPath存储文件夹路径,然后加上文件名(fileName)组成文件的全路径(fullPath)。

继续在上一例的基础上稍加改动——fullPath=folderPath &filename

 

Sub DirTestLoop_QuestionMark_GetFullPath()

    DimfolderPath, fileName, fullPath As String

    DimrowIndex As Integer

    Columns(1).Clear

    folderPath = "C:\Users\Administrator\Desktop\vba\demo\"

    fileName = Dir(folderPath &"01 (?).xlsx")

    rowIndex = 1

    Do While fileName <> ""

        fullPath =folderPath & fileName

        Cells(rowIndex,1).Value =fullPath

        rowIndex =rowIndex + 1

        fileName = Dir

    Loop

End Sub

 

返回结果:

ThisWorkbook对象的Path 属性与NameFullName属性

VBA的文件路径,了解ThisWorkbook对象的Path属性与NameFullName属性是必要的。至于什么是ThisWorkbook对象,理解为本工作簿就可以,Path 属性返回工作簿所在的文件夹路径,Name 属性返回工作簿的名称,FullName则返回工作簿的全路径。

Chr(10)的效果是换行,Chr函数将一个ASCII码转为相应的字符,此处不做展开。

不难看出,使用ThisWorkbook.Path & “\”& ThisWorkbook.Name即可拼接出当前工作簿的全路径,而这种拼接的结果等于ThisWorkbook.FullName的返回值。

实际操作中操作对象文件夹难免有可能会改名、移动,此时代码中写死的文件夹路径便指向了一个错误的或者不存在的路径。需要考虑这种情况的时候ThisWorkbook.Path的好处便凸显了,一般的会将代码所在的Excel工作簿放到操作对象文件夹内,用ThisWorkbook.Path& “\”便取到了folderPath的值。

folderPath = ThisWorkbook.Path &"\"

 

2.遍历子文件夹

2.1遍历子文件夹路径

接上节,在本节的开始我将代码所在的Excel工作表放入了要操作的文件夹,此时文件夹的树形结构如下:

该文件夹的树形结构如下C:\Users\Administrator\Desktop\vba\demo

  01 (1).xlsx

  01 (2).xlsx

 VBAdemo.xls

  文件夹改名.xls

  新建文本文档.txt

├─1601

     430Forbidden.png

├─1603

     1.txt

└─1605

       添加字段属性表.xlsx

 

在代码中文件夹路径(folderPath)采用ThisWorkbook.Path& "\"的方式来获取;Dir函数的第2参文件属性设置为vbDirectory,设定该参数后Dir函数会返回无属性文件、目录或文件夹名。

Dir(folderPath,vbDirectory)遍历一下,然后分析结果。

 

 

※在上图左侧的结果中“.”、“..”是DOS中用到的虚拟目录,此处不展开。

红色框中是我们要获得的子文件夹,其与另外的目录或者文件的明显辨识符号就是“.”——文件扩展名与目录中都存在.符号。

 

Sub DirTest_Directory()

    DimfolderPath, fileName As String

    DimrowIndex As Integer

    Columns(1).Clear

    folderPath = ThisWorkbook.Path &"\"

    fileName = Dir(folderPath,vbDirectory)

    rowIndex = 1

    Do While fileName <> ""

        If InStr(fileName, ".") =0 Then '如果fileName中不包含.则执行If语句块内代码

           Cells(rowIndex, 1).Value = fileName

           rowIndex = rowIndex + 1

        End If

        fileName = Dir

    Loop

End Sub

 

InStr(fileName, ".") = 0并不能做到“万无一失”,因为会有文件夹名字包含.的情况。

做到这样仍不能确保返回的结果一定是文件夹,举一例——万一有人把“新建文本文档.txt”改成了“新建文本文档”,你可以猜得到结果。

为了避免这样的结果,我们可以继续对结果做一个判断,使用GetAttr函数返回文件、文件夹或目录的属性(为一个整型值),然后使其与vbDirectory(是指代“目录或文件夹”的属性值,值为16,与Dir的第2参有所不相同)属性值进行 And 运算,在下式成立的时候输出结果。

GetAttr(folderPath& fileName) And vbDirectory)= vbDirectory

这样if语句块的判断逻辑就是下面的样子了。

 

If InStr(fileName, ".") = 0 Then '如果fileName中不包含.则执行If语句块内代码

   If (GetAttr(folderPath& fileName) AndvbDirectory) = vbDirectory Then

       Cells(rowIndex,1).Value =fileName

       rowIndex = rowIndex +1

   End If

End If

 

※如果对GetAttr(“文件(夹)全路径”)And运算的逻辑有兴趣可以查查资料,没兴趣直接抄代码就可以。如果对自己的文件规整程度有信心,这一个判断可以省去。Dir(folderPath, vbDirectory)遍历的结果是目录、文件夹、文件都存在的,我们仍将Dir返回的结果赋值给变量fileName,只是为了写代码的时候方便(也便于阅读)而不去声明太多的变量,如果觉得别扭你可以将该变量声明为name或其他便于自己识别的变量名。

 

2.2遍历所有文件夹路径

教程的初衷是面向实际操作的,编写中也在尽可能的秉持这一点。

基于这一点我们就不得不考虑“多层文件结构”的情况,如下,案例文件夹被改造成多级:

C:\Users\Administrator\Desktop\vba\demo

├─1601

  └─3

├─1603

  └─3

      └─4

└─1605

    └─3

遍历所有层级文件夹路径的代码如下:

 

Sub DirTest_GetAllDirectory()

    DimfolderName As String

    Dim i,k As Integer

    Columns(1).Clear

    Cells(1, 1).Value = ThisWorkbook.Path &"\"

    i = 1

    k = 1

    Do While i <= k

        folderName = Dir(Cells(i,1).Value,vbDirectory)

        Do

           If InStr(folderName, ".") = 0 And  _

           (GetAttr(Cells(i, 1).Value & folderName) And vbDirectory) = vbDirectory Then

                  k = k + 1

                  Cells(k, 1).Value = Cells(i, 1).Value & folderName & "\"

           End If

           folderName = Dir

        Loop Until folderName = ""

        i = i + 1

    Loop

End Sub

 

※空格+下划线+回车 将一行代码换行

 

先将主路径ThisWorkbook.Path & "\"(父节点)放入单元格Cells(1, 1),进入外层循环Do While i <= k ……Loop 指定要遍历的父节点,内层循环Do……Loop Until folderName = ""遍历子节点存入A列(作为外层循环的父节点),遍历完成后进入外层循环继续获取父节点……如此往复,当i=k时外层循环进入某一层的最后一个“父节点”的遍历,如果该“父节点”没有子目录则循环到此终止。

PS.

Do……Loop Until folderName = "" 效果等同于Do While folderName <> "" ……Loop 可以自行了解一下。

 

3.遍历文件夹下所有层级的文件

在第1节“遍历文件夹下的文件”中讲述了如何获取一个路径下的文件,在第2节“遍历子文件夹”中讲述了如何获取一个路径下(包括本层)的所有层级目录路径。

3.1工作表遍历行

获取所有子文件夹路径放入A列,然后逐个遍历取文件夹路径遍历其下的文件即可实现本节的操作目的。前面两节都是在向工作表存入数据,本节需要从工作表遍历每行获取数据了,由此便会引入for循环

For i = 1 To 5 Step 1 '如果step(循环步数)为1可省略

   循环体

Next i

通过设定行索引为变量可以操作工作表某列单元格的读取或写入。

上图中使用for语句对C列的前8个单元格分别进行赋值,但是循环的终止行索引往往是不固定的,尤其是在读取数据的时候,不可能每次都在代码中将最后一行的索引“手动写入”。获取最后一行的索引值需要使用Rows.Count属性获取本表最大行索引值maxRow,然后使用End(xlUp).Row在某列的maxRow单元格向上找到最后一个非空的单元格取其行号lastRow

具体代码见下图:

 

3.2遍历文件路径

为了使代码看起来简单,遍历分为逐个遍历取文件夹路径遍历其下的文件两个过程

1、获取所有文件夹路径到A

获取所有层级文件夹路径到A列,这个过程直接用2.2节“遍历所有文件夹”的代码即可。

 

Sub GetAllDirectory()

    DimfolderName As String

    Dim i,k As Integer

    Columns(1).Clear

    Cells(1, 1).Value = ThisWorkbook.Path &"\"

    i = 1

    k = 1

    Do While i <= k

        folderName = Dir(Cells(i,1).Value,vbDirectory)

        Do

           If InStr(folderName, ".") = 0 And  _

           (GetAttr(Cells(i, 1).Value & folderName) And vbDirectory) = vbDirectory Then

                  k = k + 1

                  Cells(k, 1).Value = Cells(i, 1).Value & folderName & "\"

           End If

           folderName = Dir

        Loop Until folderName = ""

        i = i + 1

    Loop

End Sub

 

2、遍历A列文件夹,取文件

这个过程可以通过改造1.1节“构造循环体实现自动遍历”的代码实现

在该过程的开始调用上节的GetAllDirectory()过程 将所有文件夹路径放入A列, dir函数的路径参数声明为变量folderPath,然后通过for循环在A列取文件夹路径赋值给该变量。内层Do While……Loop循环取出folderPath下的所有文件放在B列。

 

Sub LoopGetFile()

    CallGetAllDirectory '调用GetAllDirectory()过程

    Columns(2).Clear

    DimfileName, folderPath As String

    DimrowIndexA, rowIndexB, maxRow, lastRowA As Integer

    maxRow = Rows.Count

    lastRowA = Cells(maxRow, 1).End(xlUp).Row

    ForrowIndexA = 1 To lastRowA

        folderPath =Cells(rowIndexA, 1).Value

        fileName = Dir(folderPath)

        rowIndexB =Cells(maxRow, 2).End(xlUp).Row+ 1

        Do While fileName <> ""

           Cells(rowIndexB, 2).Value = folderPath &fileName

           rowIndexB = rowIndexB + 1

           fileName = Dir

        Loop

    NextrowIndexA

End Sub

 

(二)Application.FileDialog属性(番外篇

这是番外篇,有兴趣可读。

使用Excel应用的Application.FileDialog属性打开对话框拾取一个文件夹路径,而不用把路径写入代码或者把代码所在工作簿放入文件夹下取Thisworkbook.Path

定义一个函数GetMainDirectory,用来拾取主文件夹路径。

VBA自定义函数 Function可以自行扩展,在工作表中使用自定义函数可以弥补许多原生函数的不足。

 

'定义一个函数,用来拾取主文件夹路径

'传入msoFileDialogFolderPicker(文件夹拾取对话框),返回字符串类型的文件夹路径

Function GetMainDirectory(ByVal DialogType As MsoFileDialogType) As String

  WithApplication.FileDialog(DialogType)

    If .Show= True Then

        GetMainDirectory =.SelectedItems(1)

    End If

  End With

End Function

 

下面的代码中调用 GetMainDirectory函数打开Excel自带对话框,拾取文件夹路径赋值给数组索引位置为1的元素,然后遍历出所有子文件夹。

※代码中使用了数组、单元格地址的Range表达方式。如果恰好你是有兴趣阅读到这里,尝试把它与Dir函数2.2“遍历所有文件夹”的代码做下对比。

 

'获取主文件夹路径及其所有子文件夹路径

'使用 GetMainDirectory 函数获取主文件夹路径,然后遍历其子夹,取路径放入A

Sub GetFolderList()

    Dim folder(1 To 10000)

    DimfolderName As String

    Dim i,k

    folder(1) = GetMainDirectory(msoFileDialogFolderPicker)+ "\"

    Range("a1") = folder(1)

    i = 1: k = 1

    Do While i <= k

       folderName = Dir(folder(i),vbDirectory)

       Do

        If InStr(folderName, ".") = 0 And folderName <> "" Then

           k =k + 1

          folder(k) = folder(i) &folderName & "\"

           Range("a" & k) =folder(k)

        End If

        folderName = Dir

       Loop Until folderName = ""

       i = i + 1

     Loop

End Sub

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
VBA实用小程序72:遍历文件夹(和子文件夹)中的文件
php 上传文件并对上传的文件进行简单验证(错误信息,格式(防伪装),大小,是否为http上传)
ExcelVBA_047 跨多文件查成绩
ExcelVBA_004 Excel批量插入图片
VBA一键批量设置word页边距
Excel VBA 7.14跨工作薄合并工作表,按照工作表名称分类
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服