现在的位置: 首页 > 精选转贴 > 正文

VBA 操作文件的主要方法(2)

2014年09月01日 精选转贴 ⁄ 共 11074字 ⁄ 字号 暂无评论 ⁄ 阅读 1,796 次
上接:VBA 操作文件的主要方法(1)

 

二、利用VBA文件处理语句来处理文件

    VBA包含了许多用于文件操作的语句和函数,可以满足绝大多数情况下的文件操作要求。下面我们按照操作目的进行一 一介绍。

 

(一)文件处理
 
1.Name 语句

语法:Name oldpathname As newpathname

功能:重命名一个文件、目录、或文件夹,移动一个文件。

说明:在一个已打开的文件上使用 Name,将会产生错误。进行文件操作时,一定要注意错误处理。

示例

On Error Resume Next    '错误处理
Name "f:\TEST.xls" As "f:\TEST123.xls"  '重命名
Name "f:\TEST.xls" As "f:\dll\TEST.xls"  '移动文件
Name "f:\TEST.xls" As "d:\TEST123.xls"  '跨驱动器移动并重命名文件

注意:Name不能移动一个目录或文件夹。

2、FileCopy 语句

语法:FileCopy source, destination

功能:复制一个文件。

说明:如果对一个已打开的文件使用 FileCopy 语句,则会产生错误。

示例

FileCopy "f:\TEST.xls", "e:\TEST.xls"  '从F盘复制TEST.xls到E盘

3、Kill 语句

语法:Kill pathname

功能:从磁盘中删除文件。

说明:Kill 支持多字符 (*) 和单字符 (?) 的统配符来指定多重文件。如果使用 Kill 来删除一个已打开的文件,则会产生错误。

示例

Kill "f:\TEST.xls"  ’删除F盘的TEST.xls文件
Kill "f:\*.xls"   ' 删除F盘所有xls文件

4、GetAttr 函数

语法:GetAttr(pathname)

功能:获取一个文件、目录、或文件夹的属性。返回一个 Integer值。

返回值:由 GetAttr 返回的值,是下面这些属性值的总和:

常数    值   描述
vbNormal   0   常规
vbReadOnly   1   只读
vbHidden   2   隐藏
vbSystem   4  系统文件
vbDirectory   16   目录或文件夹
vbArchive   32   存档文件
vbalias   64   指定的文件名是别名。只在Macintosh中可用。

说明:若要判断是否设置了某个属性,在 GetAttr 函数与想要得知的属性值之间使用 And 运算符与逐位比较。如果所得的结果不为零,则表示设置了这个属性值。

示例

Debug.Print GetAttr("F:\test.txt") '若为存档文件,在立即窗口可看到值为32
Debug.Print GetAttr("F:\test.txt") '将属性—高级—可存档文件的勾去掉后,值为0

为判断一个文件是否只读,可用下法:

Debug.Print GetAttr("F:\test.txt") And vbReadOnly

若值非零,说明时只读的。

5、SetAttr 语句

语法:SetAttr pathname, attributes

功能:为一个文件设置属性。

说明:如果想要给一个已打开的文件设置属性,则会产生运行时错误。

示例

SetAttr"F:\test.txt", vbHidden       ' 设置隐藏属性
SetAttr"F:\test.txt", vbHidden + vbReadOnly      ' 设置隐藏并只读

6、FileLen 函数

语法:FileLen(pathname)

功能:获取一个文件的长度,单位是字节。

说明:当调用 FileLen 函数时,不需要打开文件,如果所指定的文件已经打开,则返回的值是这个文件在打开前的大小。

7、FileDateTime 函数

语法:FileDateTime(pathname)

功能:获取一个文件被创建或最后修改后的日期和时间。

示例

Debug.Print FileDateTime("F:\TEST.xls")  '在立即窗口可看到2007-3-29 19:28:27

 

(二)目录处理

 

1、CurDir 函数

语法:CurDir[(drive)]

功能:返回当前的路径。

说明:drive 参数是可选的,它指定一个存在的驱动器。如果没有指定驱动器,或 drive 是零长度字符串 (""),则 CurDir 会返回当前驱动器的路径。

示例

Debug.Print CurDir      ' 返回“C:\Documents and Settings\yc\My Documents”
Debug.Print CurDir("C")     ' 返回“C:\Documents and Settings\yc\My Documents”
Debug.Print CurDir("D")     ' 返回“D:\”。

2、ChDir 语句

语法:ChDir path

功能:改变当前的目录或文件夹。

说明:ChDir 语句改变缺省目录位置,但不会改变缺省驱动器位置。缺省驱动器一般是C。

示例

ChDir "D:\temp"
Debug.Print CurDir      ' 返回“C:\Documents and Settings\yc\My Documents”
Debug.Print CurDir("D")     ' 返回“D:\temp”

与上例比较,此时D盘的当前目录已经变为“D:\temp”,但是缺省驱动器还是C。

3、ChDrive 语句

语法:ChDrive drive

功能:改变当前的驱动器。

说明:如果使用零长度的字符串 (""),则当前的驱动器将不会改变。如果 drive 参数中有多个字符,则 ChDrive 只会使用首字母。

示例

ChDrive "D"
ChDir "D:\temp"Debug.Print CurDir      ' 返回“D:\temp”
Debug.Print CurDir("D")     ' 返回“D:\temp”

与上例比较,用CurDir返回的是“D:\temp”,当前驱动器已经变为D了。

4、Dir 函数

语法:Dir[(pathname[, attributes])]
      两个参数都是可选的,attributes表示文件属性。

功能:返回一个文件名、目录名或文件夹名称,它必须与指定的模式或文件属性、或磁盘卷标相匹配。

说明:在第一次调用 Dir 函数时,必须指定 pathname,否则会产生错误。如果也指定了文件属性,那么就必须包括 pathname。

Dir 会返回匹配 pathname 的第一个文件名。若想得到其它匹配 pathname 的文件名,再一次调用 Dir,且不要使用参数。如果已没有合乎条件的文件,则 Dir 会返回一个零长度字符串 ("")。一旦返回值为零长度字符串,并要再次调用 Dir 时,就必须指定 pathname,否则会产生错误。不必访问到所有匹配当前 pathname 的文件名,就可以改变到一个新的 pathname 上。但是,不能以递归方式来调用 Dir 函数。以 vbDirectory 属性来调用 Dir 不能连续地返回子目录。

示例

Debug.Print Dir("F:\TEST.xls")  ’返回"TEST.xls"
Debug.Print Dir("F:\*.xls")  ’返回按条件第一个找到的文件名
Debug.Print Dir("F:\*.txt",vbReadOnly) ’返回第一个只读的txt文件

以下过程可显示C盘根目录下的所有目录.

Sub DirC()
    MyPath = "c:\"   
    MyName = dir(MyPath, vbDirectory)     ' 找寻第一项。
    Do While MyName <> ""      ' 开始循环。    ' 跳过当前的目录及上层目录。    
        If MyName <> "." And MyName <> ".." Then        ' 使用位比较来确定 MyName 代表一目录。        
            If (GetAttr(MyPath & MyName) And vbDirectory) = vbDirectory Then
                Debug.Print MyName     ' 如果它是一个目录,将其名称显示出来。
            End If
        End If
        MyName = dir    ' 查找下一个目录。
    Loop
End Sub

 以下过程利用递归可以查找目录和子目录下的所有文件。

Public Sub FindFile(mPath As String, Optional sFile As String = "")
    On Error Resume Next
    Dim s As String, sDir() As StringDim, i As Long, d As Long
    If Right(mPath, 1) <> "\" Then
        mPath = mPath & "\"
    End If
    '查找目录下的文件
    s = dir(mPath & sFile, vbArchive + vbDirectory + vbHidden + vbNormal + vbReadOnly + vbSystem)
    Do While s <> ""
        Debug.Print mPath & s
        s = dir
    Loop
    '查找目录下的子目录
    s = dir(mPath, vbArchive + vbDirectory + vbHidden + vbNormal + vbReadOnly + vbSystem)
    Do While s <> ""
        If s <> "." And s <> ".." Then
            If (GetAttr(mPath & s) And vbDirectory) = vbDirectory Then
                d = d + 1
                ReDim Preserve sDir(d)
                sDir(d) = mPath & s
            End If
        End If
        s = dir
    Loop
    '开始递归        
    For i = 1 To d
        FindFile sDir(d) & "\"
    Next
End Sub

5、MkDir 语句

语法:MkDir path

功能:创建一个新的目录或文件夹。

说明:path 可以包含驱动器。如果没有指定驱动器,则 MkDir 会在当前驱动器上创建新的目录或文件夹。

示例

MkDir "MYDIR"    '在当前目录建立新的目录或文件夹。

6、RmDir 语句

语法:RmDir path

功能:删除一个存在的目录或文件夹。

说明:如果想要使用 RmDir 来删除一个含有文件的目录或文件夹,则会发生错误。在试图删除目录或文件夹之前,先使用 Kill 语句来删除所有文件。

示例

RmDir "MYDIR"      ' 将 MYDIR 删除。

  

(三)处理文本文件

 

1、Open 语句

语法:Open pathname For mode [Access access] [lock] As [#]filenumber [Len=reclength]

其中access、lock、reclength为可选参数,一般不用。
mode 指定打开文件的方式。有5种:
Input:以输入方式打开,即读取方式。
Output:以输出方式打开,即写入方式。
Append:以追加方式打开,即添加内容到文件末尾。
Binary:以二进制方式打开。
Random:以随机方式打开,如果未指定方式,则以 Random 方式打开文件。

filenumber  是一个有效的文件号,范围在 1 到 511 之间。可以指定,也可使用 FreeFile 函数可得到下一个可用的文件号。

说明:如果 pathname 指定的文件不存在,那么,在用 Append、Binary、Output、或 Random 方式打开文件时,可以建立这一文件。

示例

Open "F:\TEST.txt" For Input As #1  '以输入方式打开
Open "F:\TEST.xls" For Binary As #1  '以二进制方式打开

2、Close 语句

语法:Close [filenumberlist]
     filenumberlist 参数为一个或多个文件号,若省略 filenumberlist,则将关闭 Open 语句打开的所有活动文件。

说明:打开文件后,必须在使用完后关闭文件。

示例

Dim I, FileName
For I = 1 To 3
    FileName = "TEST" & I    ' 创建文件名。
    Open FileName For Output As #I    ' 打开文件。
    Print #I, "This is a test."    ' 将字符串写入文件。
Next I
Close    ' 将三个已打开的文件全部关闭。

3、Reset 语句

语法:Reset

功能:关闭所有用 Open 语句打开的磁盘文件。

说明:Reset 语句关闭 Open 语句打开的所有活动文件,并将文件缓冲区的所有内容写入磁盘。

示例

Dim FileNumber
For FileNumber = 1 To 5
    Open "TEST" & FileNumber For Output As #FileNumber
    Write #FileNumber, "Hello World"    ' 将数据写入文件。
Next FileNumber
Reset    ' 关闭文件并将缓冲区内的数据写到磁盘中。

4、FreeFile 函数

语法:FreeFile[(rangenumber)]
      参数 rangenumber指定一个范围,以便返回该范围之内的下一个可用文件号。指定 0(缺省值)则返回一个介于 1 – 255 之间的文件号。指定 1 则返回一个介于 256 – 511 之间的文件号。

功能:提供一个尚未使用的文件号。

示例

Dim fnum As Integer
fnum = FreeFile
Open "F:\TEST.txt" For Input As #fnum
Close #fnum

5、EOF 函数

语法:EOF(filenumber)

功能:返回一个 Integer,它包含 Boolean 值 True,表明已经到达为 Random 或顺序 Input 打开的文件的结尾。

6、LOF 函数

语法:LOF(filenumber)

功能:返回一个 Long,表示用 Open 语句打开的文件的大小,该大小以字节为单位。

7、Loc 函数

语法:LOc(filenumber)

功能:返回一个 Long,在已打开的文件中指定当前读/写位置。

8、Input # 语句

语法:Input #filenumber, varlist

功能:从已打开的顺序文件中读出数据并将数据指定给变量。

说明:通常用 Write # 将 Input # 语句读出的数据写入文件。为了能够用 Input # 语句将文件的数据正确读入到变量中,在将数据写入文件时,要使用 Write # 语句而不使用 Print # 语句。使用 Write # 语句可以确保将各个单独的数据域正确分隔开。

示例
本示例使用 Input # 语句将文件内的数据读入两个变量中。本示例假设 TESTFILE文件内含数行以 Write # 语句写入的数据;也就是说,每一行数据中的字符串部分都是用双引号括起来,而与数字用逗号隔开,例如,("Hello", 234)。

Dim MyString, MyNumber
Open "TESTFILE" For Input As #1      ' 打开输入文件。
Do While Not EOF(1)       ' 循环至文件尾。
    Input #1, MyString, MyNumber      ' 将数据读入两个变量。
    Debug.Print MyString, MyNumber      ' 在立即窗口中显示数据。
LoopClose #1         ' 关闭文件。

9、Write # 语句

语法:Write #filenumber, [outputlist]

功能:将数据写入顺序文件。

说明:通常用 Input # 从文件读出 Write # 写入的数据。
如果省略 outputlist,并在 filenumber 之后加上一个逗号,则会将一个空白行打印到文件中。多个表达式之间可用空白、分号或逗号隔开。空白和分号等效。

用 Write # 将数据写入文件时将遵循几个通用的约定,使得无论什么区域都可用 Input # 读出并正确解释数据:

·在写入数值数据时总使用句号作为十进制分隔符。

·对于 Boolean 类型的数据,或者打印 #TRUE# 或者打印 #FALSE#。无论在什么地区,都不将 True 和 False 这两个关键字翻译出来。

·使用通用的日期格式将 Date 类型的数据写入文件中。当日期或时间的部件丢失或为零时,只将现有部分写入文件中。

·如果 outputlist 的数据为 Empty,则不将任何数据写入文件。但对 Null 数据,则要写入 #NULL#。

·如果 outputlist 数据为 Null 数据,则将 #NULL# 写入文件中。

·对于 Error 类型的数据,输出看起来与 #ERROR errorcode# 一样。无论在什么地区,都不将关键字 Error 翻译出来。
与 Print # 语句不同,当要将数据写入文件时,Write # 语句会在项目和用来标记字符串的引号之间插入逗号。没有必要在列表中键入明确的分界符。Write # 语句在将 outputlist 中的最后一个字符写入文件后会插入一个新行字符,即回车换行符,(Chr(13) + Chr(10))。

示例

Open "F:\test.txt" For Output As #1      ' 打开输出文件。
Write #1, "Hello World", 1234      ' 写入以逗号隔开的数据。
Write #1,         ' 写入空白行。
Dim MyBool, MyDate, MyNull, MyError
' 赋值 Boolean、Date、Null 及 Error 等。
MyBool = False : MyDate = #February 12, 1969# : MyNull = Null
MyError = CVErr(32767)
' Boolean 数据以 #TRUE# 或 #FALSE# 的格式写入。
' 日期以通用日期格式写入,例如:#1994-07-13# 代表
' 1994 年 1 月 13 日。Null 数据以 #NULL# 格式写入。 
' Error 数据以 #ERROR 错误代号# 的格式写入。
Write #1, MyBool; " is a Boolean value"
Write #1, MyDate; " is a date"
Write #1, MyNull; " is a null value"
Write #1, MyError; " is an error value"
Close #1    ' 关闭文件。

我们可以看到写入的内容为:
"Hello World",1234
#FALSE#," is a Boolean value"
#1969-02-12#," is a date"
#NULL#," is a null value"
#ERROR 32767#," is an error value"

10、Line Input # 语句

语法:Line Input #filenumber, varname

功能:从已打开的顺序文件中读出一行并将它分配给 String 变量。

说明:通常用 Print # 与 Line Input # 语句配合使用。
Line Input # 语句一次只从文件中读出一个字符,直到遇到回车符 (Chr(13)) 或回车–换行符 (Chr(13) + Chr(10)) 为止。回车–换行符将被跳过,而不会被附加到字符串上。

示例

Dim TextLineOpen "TESTFILE" For Input As #1     ' 打开文件。
Do While Not EOF(1)       ' 循环至文件尾。
    Line Input #1, TextLine      ' 读入一行数据并将其赋予某变量。
    Debug.Print TextLine      ' 在立即窗口中显示数据。
LoopClose #1        ' 关闭文件。

11、Input 函数

语法:Input(number, [#]filenumber)
其中number 指定要返回的字符个数。

功能:返回 String,它包含以 Input 或 Binary 方式打开的文件中的字符。

说明:通常用 Print # 或 Put 将 Input 函数读出的数据写入文件。Input 函数只用于以 Input 或 Binary 方式打开的文件。
与 Input # 语句不同,Input 函数返回它所读出的所有字符,包括逗号、回车符、空白列、换行符、引号和前导空格等。

示例

Dim MyCharOpen "f:\test.txt" For Input As #1
Do While Not EOF(1)       ' 循环至文件尾。
    MyChar = Input(1, #1)      ' 读入一个字符。
    Debug.Print MyChar      ' 显示到立即窗口。
LoopClose #1

下面这个函数可以将文本文件的数据一次读入到一个字符串(但是若包含中文时会出错,因为一个中文字占2个字节)。

Public Function ReadText(FileName As String)
    Dim fnum%, isopen As Boolean
    On Error GoTo erro
    fnum = FreeFile()
    Open FileName For Input As #fnum
    isopen = True
    ReadText = Input(LOF(fnum), fnum)
erro:
    If isopen Then Close #fnum
    If err Then Debug.Print err.Number, err.Description
End Function

12、Print # 语句

语法:Print #filenumber, [outputlist]

outputlist 参数的设置如下:
[{Spc(n) | Tab[(n)]}] [expression] [charpos]

Spc(n) 用来在输出数据中插入空白字符,而 n 指的是要插入的空白字符数。
Tab(n) 用来将插入点定位在某一绝对列号上,这里,n 是列号。使用无参数的 Tab 将插入点定位在下一个打印区的起始位置。
expression 要打印的数值表达式或字符串表达式。
charpos 指定下一个字符的插入点。使用分号将插入点定位在上一个显示字符之后。用 Tab(n) 将插入点定位在某一绝对的列号上,用无参数的 Tab 将插入点定位在下一个打印区的起始处。如果省略 charpos,则在下一行打印下一个字符。

功能:将格式化显示的数据写入顺序文件中。

说明:通常用 Line Input # 或 Input 读出 Print # 在文件中写入的数据。

示例

Open "F:\test.txt" For Output As #1         ' 打开输出文件。
Print #1, "This is a test"                  ' 将文本数据写入文件。
Print #1,                                   ' 将空白行写入文件。
Print #1, "Zone 1"; Tab; "Zone 2"           ' 数据写入两个区(print zones)。
Print #1, "Hello"; " "; "World"             ' 以空格隔开两个字符串。
Print #1, Spc(5); "5 leading spaces "       ' 在字符串之前写入五个空格。
Print #1, Tab(10); "Hello"                  ' 将数据写在第十列。
' 赋值 Boolean、Date、Null 及 Error 等。
Dim MyBool, MyDate, MyNull, MyError
MyBool = False: MyDate = #2/12/1969#: MyNull = Null
MyError = CVErr(32767)
' True、False、Null 及 Error 会根据系统的地区设置自动转换格式。
' 日期将以标准的短式日期的格式显示。
Print #1, MyBool; " is a Boolean value"
Print #1, MyDate; " is a date"
Print #1, MyNull; " is a null value"
Print #1, MyError; " is an error value"
Close #1

以上代码写入的内容如下:
This is a test
Zone 1       
Zone 2
Hello World
5 leading spaces
Hello
False is a Boolean value
1969-2-12  is a date
Null is a null value
Error 32767 is an error value

13、Width # 语句

语法:Width #filenumber, width
width 必要。范围在 0–255 之间的数值表达式,在新的一行开始之前,指出在该行上可出现多少字符。如果 width 等于 0,则行的长度不受限制。width 的缺省值为 0。

功能:将一个输出行的宽度指定给用 Open 语句打开的文件。

示例

Dim IOpen "f:\TESTFILE.txt" For Output As #1
Width #1, 5                                 ' 设置输出行宽为 5。
For I = 0 To 9                              ' 循环 10 次。    
    Print #1, Chr(48 + I);                  ' 每行输出五个字符。
Next I
Close #1

以上代码写入的内容如下:
01234
56789

  

(四)处理二进制文件

 

打开二进制文件可以使用Open语句的Random和Binary方式打开。二进制文件读写使用Get和Put语句。

1、Put 语句

语法:Put [#]filenumber, [recnumber], varname

recnumber 可选。Variant (Long)。记录号(Random 方式的文件)或字节数(Binary 方式的文件),指明在此处开始写入。

说明:通常用 Get 将 Put 写入的文件数据读出来。

示例

Dim num As Long, text As Strin
gnum = 12345text = "a string"
Open "f:\data.bin" For Binary As #1     '打开或创建一个二进制文件
Put #1, , num                           '写入4个字节
Put #1, , text                          '写入8个字节(字符串长为8)
Close #1

2、Get 语句

语法:Get [#]filenumber, [recnumber], varname

recnumber 可选。Variant (Long)。记录号(Random 方式的文件)或字节数(Binary 方式的文件),以表示在此处开始读出数据。

功能:将一个已打开的磁盘文件读入一个变量之中。

说明:通常用 Put 将 Get 读出的数据写入一个文件。

示例:读取以上代码写入的内容

Dim num As Long, text As String
Open "f:\data.bin" For Binary As #1
Get #1, , numtext = Space$(8)                        '准备8个字节的字符串
Get #1, , text                          '读入
Debug.Print num, text
Close #1

在立即窗口可以看到如下内容:
 12345       a string

3、Seek 语句

语法:Seek [#]filenumber, position
其中position 为介于 1~ 2,147,483,647(相当于 2^31 – 1)之间的数字,指出下一个读写操作将要发生的位置。

功能:在 Open 语句打开的文件中,设置下一个读/写操作的位置。

说明:可以用Seek语句指定Get语句的读取位置,但在 Get 及 Put 语句中指定的记录号将覆盖由 Seek 语句指定的文件位置。

示例

Dim MaxSize, NextChar, MyChar
Open "TESTFILE" For Input As #1     
MaxSize = LOF(1)       ' 取得文件的总字符数。' 用循环读入所有记录,但是从最后的记录开始往前读。
For NextChar = MaxSize To 1 Step -1
    Seek #1, NextChar      ' 设置读写位置。
    MyChar = Input(1, #1)      ' 读入一字符。
Next NextChar
Close #1

4、Seek 函数

语法:Seek(filenumber)

功能:返回一个 Long,在 Open 语句打开的文件中指定当前的读/写位置。

说明:在使用Get语句读取文件时,必须用LOF函数来判断是否到达文件末尾,而不是用EOF函数。可以使用Seek函数判断当前位置,然后与LOF的值比较。

示例

Do While Seek(1) < LOF(1)   '继续读取   
   '......
Loop

 

(五)小结

      VBA语句的文件操作涵盖了文件操作的绝大部分内容,很多函数的使用也很简单,一般的文件读写也非常方便,特别是对文本文件。但对于复杂的文件读写,代码的结构和维护性都不好。因此在VB6之后,微软引入了FileSystemObject对象模型,提供了面向对象的类库,来操作驱动器、文件夹和文件。但对于二进制文件的操作,目前还只能用VBA语句。

 

下接: VBA 操作文件的主要方法(3)

给我留言

您必须 [ 登录 ] 才能发表留言!