文章背景: 在VBA中,通过Dir函数,可以判断指定路径的文件是否存在等。此外,借助FileSystemObject对象,我们同样可以操作文件和文件夹。
FileSystemObject对象模型,是微软提供的专门用来访问计算机文件系统的,具有大量的属性和方法。其使用面向对象的“object.method”语法来处理文件夹和文件,使用起来十分方便。FileSystemObject并不是VBA的一部分,它是以一个COM组件的形式提供的。因此,使用前要创建FileSystemObject对象。
1 创建FSO对象
1.1 直接创建法
1.2 引用法
2 借助FSO可以获取的对象
3 FSO对象的属性
4 应用示例
4.1 检查文件或文件夹是否存在
4.2 基于给定路径,创建新文件夹
4.3 获取文件夹内所有文件的名称
4.4 获取文件夹内所有子文件夹的名称
4.5 获取文件夹及其子文件夹内所有文件的名称
4.6 拷贝文件
4.7 拷贝文件夹
1 创建FSO对象
1.1 直接创建法
代码语言:javascript复制Sub FSODemo()
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
End Sub
A big downside of using this method is that it would not show an IntelliSense when you work with objects in FSO.
使用直接创建法的缺点是,在VBA代码中,在使用FSO对象时,无法使用自动补全代码的功能。
1.2 引用法
通过VBE编译器里的工具
->引用
,打开引用
对话框,在可使用的引用
中,找到Microsoft Scripting Runtime
选项 ,点击确定
。具体操作如下:
http://mpvideo.qpic.cn/0bc344aacaaav4ajpe3xurrfbz6dahtqaaia.f10002.mp4?dis_k=8acb6ee50c2919d41a387dab6ccb8ba0&dis_t=1663656429&vid=wxv_2389279455514099713&format_id=10002&support_redirect=0&mmversion=false
完成上述步骤之后,接下来就可以在VBA代码中引用FSO对象。
代码语言:javascript复制Sub CreatingFSO()
Dim MyFSO As FileSystemObject
Set MyFSO = New FileSystemObject
End Sub
(1) 通过New
关键字,创建FileSystemObject的实例(Instance)。
(2) 通过Set
关键字,将这个FileSystemObject的新实例赋给MyFSO对象。
如果需要的话,可以将上述的两条代码整合为一条。
代码语言:javascript复制Sub CreatingFSO_1()
Dim MyFSO As New FileSystemObject
End Sub
采用引用法
的好处是,在代码中使用FSO对象时,可以通过代码自动补全的功能,显示FSO对象的属性和方法。
http://mpvideo.qpic.cn/0b2e24aaaaaalyajnx3xurrfbv6dadlqaaaa.f10002.mp4?dis_k=a42b0beb9b84c8710e8028114e1cfb8e&dis_t=1663656429&vid=wxv_2389280549808013313&format_id=10002&support_redirect=0&mmversion=false
2 借助FSO可以获取的对象
下表展示了借助FSO可以获取和修改的几个重要的对象。
3 FSO对象的属性
4 应用示例
假如C盘中有如下的文件结构:
代码语言:javascript复制# a -> b -> 1dog.txt, 2cat.txt
# c -> 3panda.txt
# d -> e
# 4duck.txt
# 5horse.txt
4.1 检查文件或文件夹是否存在
(1)检查指定路径的文件夹是否存在
代码语言:javascript复制Sub CheckFolderExist()
Dim MyFSO As FileSystemObject
Set MyFSO = New FileSystemObject
If MyFSO.FolderExists("C:ab") Then
Debug.Print "The Folder Exists."
Else
Debug.Print "The Folder Does Not Exist."
End If
End Sub
运行后,立即窗口中显示的是:
代码语言:javascript复制The Folder Exists.
VBA中的Dir
函数,可以实现类似的功能,用到的主要代码为:CheckDir = Dir(PathName, vbDirectory)
。
(2)检查指定路径的文件是否存在
代码语言:javascript复制Sub CheckFileExist()
Dim MyFSO As FileSystemObject
Set MyFSO = New FileSystemObject
If MyFSO.FileExists("C:ac3panda.txt") Then
Debug.Print "The File Exists."
Else
Debug.Print "The File Does Not Exist."
End If
End Sub
运行后,立即窗口中显示的是:
代码语言:javascript复制The File Exists.
VBA中的Dir
函数,可以实现类似的功能,用到的主要代码为:FileName = Dir(Path)
。
4.2 基于给定路径,创建新文件夹
代码语言:javascript复制Sub CreateFolder()
Dim MyFSO As FileSystemObject
Set MyFSO = New FileSystemObject
If MyFSO.FolderExists("C:af") Then
Debug.Print "The Folder Already Exist"
Else
MyFSO.CreateFolder ("C:af")
End If
End Sub
由于文件夹f
一开始不存在,因此,运行代码后,创建新的文件夹f
。
(1) 通过MyFSO.FolderExists
判断文件夹是否存在;若不存在,则通过MyFSO.CreateFolder
创建新的文件夹。
(2)也可以通过VBA的Dir
函数判断文件夹是否存在;若不存在,则通过MkDir
函数创建新的文件夹。
4.3 获取文件夹内所有文件的名称
代码语言:javascript复制Sub GetFileNames()
Dim MyFSO As FileSystemObject
Dim MyFile As File
Dim MyFolder As Folder
Set MyFSO = New FileSystemObject
Set MyFolder = MyFSO.GetFolder("C:a")
For Each MyFile In MyFolder.Files
Debug.Print MyFile.Name
Next MyFile
End Sub
运行后,立即窗口中显示的是:
代码语言:javascript复制4duck.txt
5horse.txt
此外,借助VBA中的Dir
函数,以及Do...Loop
循环,也可以实现类似的功能。
4.4 获取文件夹内所有子文件夹的名称
代码语言:javascript复制Sub GetSubFolderNames()
Dim MyFSO As FileSystemObject
Dim MyFile As File
Dim MyFolder As Folder
Dim MySubFolder As Folder
Set MyFSO = New FileSystemObject
Set MyFolder = MyFSO.GetFolder("C:a")
For Each MySubFolder In MyFolder.SubFolders
Debug.Print MySubFolder.Name
Next MySubFolder
End Sub
运行后,立即窗口中显示的是:
代码语言:javascript复制b
c
d
f
此外,借助VBA中的Dir
函数,以及Do...Loop
循环,也可以实现类似的功能。
4.5 获取文件夹及其子文件夹内所有文件的名称
通过递归法,使用FSO对象获取文件夹及其子文件夹内所有文件的名称。
代码语言:javascript复制Sub getAllFileNames()
Dim MyFSO As FileSystemObject
Dim MyFolder As Folder
Set MyFSO = New FileSystemObject
If MyFSO.FolderExists("C:a") Then
Set MyFolder = MyFSO.GetFolder("C:a")
LookupAllFiles MyFolder
Else
Debug.Print "The Folder Does Not Exist."
End If
End Sub
Sub LookupAllFiles(fld As Folder)
Dim fil As File, outFld As Folder
For Each fil In fld.Files
Debug.Print fil.Name
Next
For Each outFld In fld.SubFolders
LookupAllFiles outFld '递归法,调用自身
Next
End Sub
运行getAllFileNames
的代码,立即窗口中显示的是:
4duck.txt
5horse.txt
1dog.txt
2cat.txt
3panda.txt
4.6 拷贝文件
把一个或多个文件从一个地方复制到另一个地方。
object.CopyFile source, destination, [ overwrite ]
- source -- Required. Character string file specification, which can include
wildcard
characters, for one or more files to be copied. - destination -- Required. Character string destination where the file or files from source are to be copied.
Wildcard
characters arenot
allowed. - overwrite -- Optional. Boolean value that indicates if existing files are to be overwritten. If True, files are overwritten; if False, they are not. The default is True. Note that CopyFile will fail if destination has the read-only attribute set, regardless of the value of overwrite. 关于通配符的使用,说明如下: Wildcard characters can only be used in the last path component of the source argument. For example, you can use: FileSystemObject.CopyFile "c:ab*.txt", "c:a" But you can't use: FileSystemObject.CopyFile "c:a**.txt", "c:a" 更多关于object.CopyFile用法的注意事项,参见文末的参考资料[6]。
4.6.1 拷贝单个文件
代码语言:javascript复制Sub CopyFile()
Dim MyFSO As FileSystemObject
Dim Source As String
Dim Destination As String
Set MyFSO = New FileSystemObject
Source = "C:ab1dog.txt"
Destination = "C:a1dog.txt"
MyFSO.CopyFile Source, Destination
End Sub
上述代码仅仅作为示例使用。实际工作中,拷贝前,需要提前判断:1) Source
文件是否存在;2) Destination
路径中是否已存在同名文件。
4.6.2 拷贝多个指定类型的文件
代码语言:javascript复制Sub CopyMoreFile()
Dim MyFSO As FileSystemObject
Dim Source As String
Dim Destination As String
Dim FileName As String
Set MyFSO = New FileSystemObject
Source = "C:ab*.txt"
Destination = "C:a"
FileName = Dir(Source)
If FileName <> "" Then
If MyFSO.FolderExists(Destination) Then
On Error Resume Next
MyFSO.CopyFile Source, Destination, False
If Err.Number <> 0 Then
Debug.Print "目标文件夹中存在同名文件,请确认!"
End If
On Error GoTo 0
Else
Debug.Print "目标文件夹不存在。"
End If
Else
Debug.Print "未找到指定文件。"
End If
Debug.Print "Done."
End Sub
(1)借助通配符,可以实现一次性拷贝多个指定文件到指定文件夹内。
(2)如果 source 中包含通配符或 destination中以路径分隔符()为结尾,则认为 destination 是一个已存在文件夹,在其中复制相匹配的文件。
4.7 拷贝文件夹
Recursively copies a folder from one location to another.
object.CopyFolder source, destination, [ overwrite ]
- source -- Required. Character string folder specification, which can include
wildcard
characters, for one or more folders to be copied. - destination -- Required. Character string destination where the folder and subfolders from source are to be copied.
Wildcard
characters arenot
allowed. - overwrite -- Optional. Boolean value that indicates if existing folders are to be overwritten. If True, files are overwritten; if False, they are not. The default is True. 更多关于object.CopyFolder用法的注意事项,参见文末的参考资料[8]。
4.7.1 拷贝单个文件夹
代码语言:javascript复制Sub CopyFolder()
Dim MyFSO As FileSystemObject
Dim Source As String
Dim Destination As String
Set MyFSO = New FileSystemObject
Source = "C:ab"
Destination = "C:ad"
MyFSO.CopyFolder Source, Destination, False
Debug.Print "Done."
End Sub
(1)上述代码将文件夹b
拷贝到文件夹d
内。
(2) If source contains wildcard characters, or destination ends with a path separator (), it is assumed that destination is an existing folder in which to copy matching folders and subfolders.
4.7.2 拷贝多个文件夹
代码语言:javascript复制Sub CopyMoreFolder()
Dim MyFSO As FileSystemObject
Dim Source As String
Dim Destination As String
Set MyFSO = New FileSystemObject
Source = "C:ad*"
Destination = "C:a"
If Not MyFSO.FolderExists(Destination) Then
Debug.Print "目标文件夹不存在。"
Exit Sub
End If
On Error Resume Next
MyFSO.CopyFolder Source, Destination, False
If Err.Number <> 0 Then Debug.Print "匹配不到文件夹,或者目标文件夹内已存在同名文件夹。"
On Error GoTo 0
Debug.Print "Done."
End Sub
(1)将文件夹d
内所有的子文件夹拷贝到文件夹a
内,本例中文件夹d
内只有一个子文件夹,也就是e
。
(2)如果 source 中包含通配符,则认为 destination 是一个已存在的文件夹。如果destination 文件夹不存在,则运行时会报错:Run-time error '76': Path not found
。
参考资料:
[1] excel VBA 操作文件的主要方法 利用FileSystemObject对象来处理文件(https://www.office26.com/excelhanshu/vba-read-write-files-03.html)
[2] Excel VBA 操作文件(夹)神器--FSO对象(https://zhuanlan.zhihu.com/p/104704524)
[3] FileSystemObject object(https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/filesystemobject-object)
[4] Using VBA FileSystemObject (FSO) in Excel – Easy Overview & Examples(https://trumpexcel.com/vba-filesystemobject/)
[5] How to use the MKDIR Statement (VBA)(https://www.techonthenet.com/excel/formulas/mkdir.php)
[6] CopyFile method(https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/copyfile-method)
[7] VBA中CopyFile 方法的功能及应用(https://blog.csdn.net/kongwei521/article/details/7176558)
[8] CopyFolder method(https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/copyfolder-method)
延伸阅读:
[1] VBA: Dir函数查找指定文件
[2] VBA: 使用递归法将xls文件批量转化为xlsm文件