使用VBA操作文件(11):处理文件、文件夹和驱动器的VBA技术和技巧

 

如果希望处理文件或文件系统,有几种选择可用。最好的选择取决于您希望完成什么任务。可用的选择包括使用VBA函数、Microsoft Scripting Runtime对象库、FileSearch对象,以及与文件系统相关的Windows API函数。
使用VBA函数
可以使用许多VBA函数处理文件系统,下表对这些函数进行了总结。

VBA函数或语句说明
Dir返回与指定的格式或文件属性相匹配的文件、目录或文件夹的名称。
GetAttr返回文件、目录或文件夹的属性。
SetAttr指定文件、目录或文件夹的属性。
CurDir返回当前目录。
ChDir修改当前目录。
ChDrive修改当前驱动器。
MkDir创建一个新目录。
RmDir移除一个现有的目录。
Kill删除一个或多个文件。
FileLen以字节返回磁盘中文件的长度。
LOF以字节返回一个打开文件的长度。
FileCopy复制磁盘中的文件。
FileDateTime返回文件创建或最后修改的日期和时间。
Name重命名文件并将其移动到磁盘中另一个位置。
Open打开磁盘中的文件来读取或写入。
Input从打开的文件中读取字符。
Print写文本到顺序文件中。
Write写文本到顺序文件中。
Close关闭使用Open语句打开的文件。

 

 


如何使用Dir函数判断某文件是否存在?
Dir函数返回在pathname参数中指定的文件的名称。通常使用Dir函数来判断是否指定的文件存在,例如下面的DoesFileExist函数:

Function DoesFileExist(strFileSpec As String) As Boolean
' 如果参数strFileSpec指定的文件存在则返回True.
' 如果strFileSpec不是有效的文件或者是一个目录则返回False.
Const INVALID_ARGUMENT As Long = 53
On Error GoTo DoesfileExist_Err
  If (GetAttr(strFileSpec) And vbDirectory) <> vbDirectory Then
 DoesFileExist = CBool(Len(Dir(strFileSpec)) > 0)
  Else DoesFileExist = False
  End If
DoesfileExist_End:
  Exit Function DoesfileExist_Err:
DoesFileExist = False
  Resume DoesfileExist_End
  End Function
 
  

本例中,GetAttr函数用于确保strFileSpec参数中的值不是一个目录。这是因为,如果向Dir函数中传递一个有效的目录名称,那么将返回在该目录中找到的第一个文件。
如何使用Dir函数获取文件夹中所有文件的名称?
如果pathname参数包含文件夹的路径而不是文件夹中某文件的名称,那么Dir函数返回在该文件夹中找到的第一个文件的名称。接着,再调用Dir函数而无需任何参数,获取文件夹中后面每一个文件的名称。例如,下面的过程返回一个数组,包含在strDirPath参数中指定的目录内所有文件的名称:

Function GetAllFilesInDir( ByVal strDirPath As String) As Variant ' 遍历strDirPath中指定的目录并在数组中保存每个文件名 ' 然后返回该数组到调用过程. ' 如果strDirPath不是一个有效的目录则返回False. Dim strTempName As String Dim varFiles() As Variant Dim lngFileCount As Long   On Error GoTo GetAllFiles_Err   ' 确保strDirPath以"\"字符结尾. If Right$(strDirPath, 1) <> "\" Then strDirPath = strDirPath & "\" End If   ' 确保strDirPath是一个目录. If GetAttr(strDirPath) = vbDirectory Then strTempName = Dir(strDirPath, vbDirectory) Do Until Len(strTempName) = 0 ' 排除 ".", "..". If (strTempName <> ".") And (strTempName <> "..") Then ' 确保没有子目录名称. If (GetAttr(strDirPath & strTempName) _ And vbDirectory) <> vbDirectory Then ' 增加数组的大小以适应发现的文件名并将其添加到数组. ReDim Preserve varFiles(lngFileCount) varFiles(lngFileCount) = strTempName lngFileCount = lngFileCount + 1 End If End If ' 使用Dir函数查找下一个文件名. strTempName = Dir() Loop ' 返回包含已找到的文件名称的数组. GetAllFilesInDir = varFiles End If GetAllFiles_End: Exit Function GetAllFiles_Err: GetAllFilesInDir = False Resume GetAllFiles_End End Function
 
  

GetAllFilesInDir函数通过遍历目录中的每一项,并且对于发现的文件,将其名称添加到数组。第一次调用Dir时,使用目录名作为其参数。每增加一次调用都使用不带参数的Dir函数。该过程使用GetAttr函数来确保strDirPath参数包含一个有效的目录,也避免任何子目录的名称被添加到数组中。注意,该过程筛选出“.”和“..”,代表当前目录和父目录。
可以使用下面的过程测试GetAllFilesInDir过程。可以对strDirName参数试不同的值,然后使用F8逐行运行代码,看该过程是如何工作的。

Sub TestGetAllFiles() Dim varFileArray As Variant
  Dim lngI As Long Dim strDirName As String 
  Const NO_FILES_IN_DIR As Long = 9
  Const INVALID_DIR As Long = 13  
  On Error GoTo Test_Err  
strDirName = "c:\my documents"
varFileArray = GetAllFilesInDir(strDirName)
For lngI = 0 To UBound(varFileArray)
 Debug. Print varFileArray(lngI)
Next lngI  
 Test_Err:
Select Case Err.Number
Case NO_FILES_IN_DIR MsgBox "The directory named '" & strDirName _ & "' contains no files."
Case INVALID_DIR MsgBox "'" & strDirName & "' is not a valid directory."
Case 0 Case Else MsgBox "Error #" & Err.Number & " - " & Err.Description
End Select
End Sub
 
  

使用Microsoft Scripting Runtime Object Library
Microsoft Scripting Runtime对象库包含可以用于操作文件和目录的对象,并且比前面讲述的VBA函数更容易使用。
在使用该对象库之前,必须设置对该对象库的引用。如果在“引用”对话框中没有找到该对象库,那么应该可以在C:\Windows\System子文件夹中找到它(Scrrun.dll)。
下表描述了Scripting Runtime对象库是的对象。

对象集合描述
Dictionary 顶层对象,与VBA Collection集合对象相似。
DriveDrives引用系统中的驱动器或驱动器的集合。
FileFiles引用文件系统中的文件或文件集合。
FileSystemObject 顶层对象,用于访问驱动器、文件夹、文件。
FolderFolders引用文件系统中的文件夹或文件夹集合。
TextStream 引用读取、写入或追加到文本文件中的一系列文本。

 

 


在Scripting Runtime对象库中的顶层对象是Dictionary对象和FileSystemObject对象。要使用Dictionary对象,则需创建一个Dictionary类型的对象变量,然后设置其为Dictionary对象的新实例。

Dim dctDict As Scripting.Dictionary Set dctDict = New Scripting.Dictionary
 
  

要在代码中使用Scripting Runtime库中的其它对象,必须首先创建FileSystemObject类型的变量,然后使用New关键词创建该FileSystemObject对象的新实例,如下面的代码所示:

Dim fsoSysObj As Scripting.FileSystemObject Set fsoSysObj = New Scripting.FileSystemObject
 
  

接着使用这个引用FileSystemObject对象的变量来处理Drive、Folder、File和TextStream对象。
如何使用FileSystemObject对象来处理文件和文件夹?
一旦创建了FileSystemObject对象的新实例,就能够使用它来处理驱动器、文件夹和文件了。
下面的过程返回特定文件夹中的文件到Dictionary对象里。GetFiles过程接受三个参数:目录路径、Dictionary对象、一个可选的布尔参数,指定是否应该递归调用该过程。该过程返回一个布尔值,指明是否过程运行成功。
该过程首先使用GetFolder方法返回对Folder对象的引用,然后遍历该文件夹的Files集合,添加每个文件的文件名称和路径到Dictionary对象中。如果blnRecursive参数设置为True,那么GetFiles过程被递归调用以返回每个子文件夹中的文件。

Function GetFiles(strPath As String, _ dctDict As Scripting.Dictionary, _ Optional blnRecursive As Boolean) As Boolean   ' 本过程返回目录中的所有文件到Dictionary对象中. ' 如果递归调用则同时返回子文件夹中的所有文件. Dim fsoSysObj As Scripting.FileSystemObject Dim fdrFolder As Scripting.Folder Dim fdrSubFolder As Scripting.Folder Dim filFile As Scripting.File   ' 返回新的FileSystemObject. Set fsoSysObj = New Scripting.FileSystemObject   On Error Resume Next ' 获取文件夹. Set fdrFolder = fsoSysObj.GetFolder(strPath) If Err <> 0 Then ' 不正确的路径. GetFiles = False GoTo GetFiles_End End If On Error GoTo 0   ' 遍历Files集合,添加到字典. For Each filFile In fdrFolder.Files dctDict.Add filFile.Path, filFile.Path Next filFile   ' 如果Recursive标志为真,则递归调用. If blnRecursive Then For Each fdrSubFolder In fdrFolder.SubFolders GetFiles fdrSubFolder.Path, dctDict, True Next fdrSubFolder End If   ' 如果没有错误发生则返回True. GetFiles = True   GetFiles_End: Exit Function End Function   ' 如果没有错误发生则返回True. GetFiles = True   GetFiles_End: Exit Function End Function
 
  

可以使用下面的过程来测试GetFiles过程。该过程创建一个新Dictionary对象,将其传递到GetFiles过程,然后在立即窗口中打印在strDirPath目录及其子目录中的每个文件。

Sub TestGetFiles() ' 测试GetFiles函数. Dim dctDict As Scripting.Dictionary Dim varItem As Variant Dim strDirPath As String   strDirPath = "c:\my documents\" ' 创建新的字典. Set dctDict = New Scripting.Dictionary ' 递归调用, 返回文件到Dictionary对象. If GetFiles(strDirPath, dctDict, True) Then ' 打印字典中的项目. For Each varItem In dctDict Debug. Print varItem Next End If End Sub
 
  

可以对strDirPath参数试验不同的值,看看该过程是如何工作的。
如何使用FileSystemObject来处理文件属性?
File对象和Folder对象提供了Attributes属性,可用来读取或设置文件或文件夹的属性,如下面的示例。
ChangeFileAttributes过程接受四个参数:文件夹的路径、指定要设置的属性的可选的常量、指定要移除的属性的可选常量、指定是否递归调用过程的可选的参数。
如果传递的文件夹路径是有效的,那么该过程返回Folder对象。接着检查是否提供了lngSetAttr参数,如果是,那么该过程遍历文件夹中的所有文件,追加新的属性到每个文件现有的属性中。对于lngRemoveAttr参数做同样的事情,在本例中,如果指定的属性存在于集合中的文件内则移除。
最后,该过程检查blnRecursive参数是否被设置为True,如果是则为strPath参数指定的每个子文件夹中的每个文件调用该过程。

Function ChangeFileAttributes(strPath As String, _ Optional lngSetAttr As FileAttribute, _ Optional lngRemoveAttr As FileAttribute, _ Optional blnRecursive As Boolean) As Boolean  
' 本函数接受一个目录路径, 一个指定文件属性设置的值
' 一个指定文件属性移除的值
' 一个指明是否递归调用的标志
' 如果没有发生错误则返回True.
Dim fsoSysObj As Scripting.FileSystemObject
Dim fdrFolder As Scripting.Folder
Dim fdrSubFolder As Scripting.Folder
Dim filFile As Scripting.File  
' 返回新的FileSystemObject.
Set fsoSysObj = New Scripting.FileSystemObject  
  On Error Resume Next
' 获取文件夹.
Set fdrFolder = fsoSysObj.GetFolder(strPath)
If Err <> 0 Then ' 不正确的路径.
ChangeFileAttributes = False
  GoTo ChangeFileAttributes_End
  End If On Error GoTo 0   ' 如果调用者传递属性去设置则设置所有的.
If lngSetAttr Then
  For Each filFile In fdrFolder.Files
     If Not (filFile.Attributes And lngSetAttr) Then
       filFile.Attributes = filFile.Attributes Or lngSetAttr
     End If
  Next
End If   ' 如果调用者传递属性去移除则移除所有的.
If lngRemoveAttr Then
  For Each filFile In fdrFolder.Files
         If (filFile.Attributes And lngRemoveAttr) Then
             filFile.Attributes = filFile.Attributes - lngRemoveAttr End If Next End If
       ' 如果调用者设置blnRecursive参数为True,则递归调用函数.
         If blnRecursive Then
       ' 遍历子文件夹.
         For Each fdrSubFolder In fdrFolder.SubFolders
        ' 调用带有子文件夹路径的函数.
       ChangeFileAttributes fdrSubFolder.Path, lngSetAttr, _ lngRemoveAttr, True
        Next
        End If 
      ChangeFileAttributes = True
      ChangeFileAttributes_End: Exit Function
  End Function
 
  

可以使用下面的过程测试ChangeFileAttributes过程。在本例中,具有隐藏属性设置的“我的文档”文件夹中的所有文件被设置可见:

Sub TestChangeAttributes() If ChangeFileAttributes( "c:\my documents", , _ Hidden, False) = True Then MsgBox "File attributes succesfully changed!" End If End Sub
 
  

可以对ChangefileAttributes过程中的参数试验不同的值,看看该过程是如何工作的。
使用FileSearch对象
FileSearch对象是Microsoft Office 9.0 Object Library中的一个成员,公开了Office文件打开对话框的所有功能的编程接口,包括在高级查找对话框中的功能。可以使用FileSearch对象的对象、方法和属性基于提供的条件来搜索文件或文件集合。
下面的示例展示了如何使用FileSearch驿象查找在strFilespec参数中指定类型的一个和多个文件。注意,通过分号分隔符指定扩展名列表可以搜索多个文件扩展名:

Function CustomFindFile(strFileSpec As String)
  ' 本过程演示一个简单的文件搜索程序
' 显示一个消息框,包含在"C:\"目录中与参数strFileSpec提供的文件规范相匹配的所有文件的名称
' 参数strFileSpec可以包含一个或多个在分号分隔列表中的文件规格.
' 例如,下面的strFileSpec参数返回"c:\"中包含扩展名"*.log;*.bat;*.ini"的包有文件
  Dim fsoFileSearch As Office.FileSearch
Dim varFile As Variant Dim strFileList As String  
' 如果输入有效,那么处理文件搜索.
If Len(strFileSpec) >= 3 And InStr(strFileSpec, "*.") > 0 Then
  Set fsoFileSearch = Application.FileSearch 
  With fsoFileSearch .NewSearch .LookIn = "c:\" .Filename = strFileSpec .SearchSubFolders = False If .Execute() > 0 Then
  For Each varFile In .FoundFiles
 strFileList = strFileList & varFile & vbCrLf
  Next varFile
  End If
  End With
 MsgBox strFileList
Else MsgBox strFileSpec & " is not a valid file specification."
  Exit Function
End If
  End Function
 
  

FileSearch对象有两个方法和一些属性,可用于在自定义的Office解决方案中创建自定义文件搜索功能。上述示例使用NewSearch方法清除任何以前的搜索条件,Execute方法执行搜索特定的文件。Execute方法返回找到的文件数,同时支持可选的参数来指定排序顺序、排序类型、以及是否用来仅保存快速搜索索引来执行搜索。使用FoundFiles属性返回对FoundFiles对象的引用(FoundFiles对象包含搜索中找到的所有匹配文件的名称)。
使用LookIn属性指定搜索的目录,使用SearchSubFolders属性指定是否搜索在LookIn属性指定的目录中的子文件夹。FileName属性支持通配符和文件名或文件类型规范的分号分隔列表。

注:本文初译自MSDN:Working with Files, Folders, and Drives: More VBA Tips and Tricks,辑录于此,作为文件操作应用大全的一部分。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值