Excel-VBA操作文件的四大方法

Posted janicemvidal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Excel-VBA操作文件的四大方法相关的知识,希望对你有一定的参考价值。

在我们日常使用Excel的时候,不仅会用到当前Excel文件的数据,还经常需要访问其他的数据文件。这些数据文件可能是Excel文件、文本文 件或数据库文件等。经常有朋友会问如何在vba代码里操作这些数据文件?本文就系统地介绍一下在Excel中应用VBA操作数据文件的方法。

本文主要介绍四种常用的方法:
1、利用Excel对象来处理文件;
2、利用VBA文件处理语句来处理文件;
3、利用FileSystemObject对象来处理文件;
4、利用API函数来处理文件。

当然对于数据库文件,还可以利用ADO+SQL的方法操作,不过论坛已经有前辈详细介绍过此类方法,本文就不再重复了。

一、利用Excel对象来处理文件

利用Excel对象自带的方法来操作文件是最方便,也是最简单的。
我们主要利用Workbooks集合和Workbook对象的方法来操作文件。

1、打开Excel文件

我们可以用Workbooks.Open方法打开一个Excel工作簿。
Workbooks.Open(FileName, UpdateLinks, ReadOnly, Format, Password, WriteResPassword, IgnoreReadOnlyRecommended, Origin, Delimiter, Editable, Notify, Converter, AddToMru, Local, CorruptLoad)
其中FileName是必选的参数,表示要打开的工作簿名,如果没有指定路径,则代表当前路径。另外14个是可选参数,除了密码参数,其他的一般很少用。具体的含义可以参看VBA的帮助。
例:
Workbooks.Open "F:\test.xls"
可以打开F盘的test.xls文件。

2、打开文本文件

使用Open方法也可以打开文本文件,但建议使用OpenText方法。此方法是载入一个文本文件,并将其作为包含单个工作表的工作簿进行分列处理,然后在此工作表中放入经过分列处理的文本文件数据。完整语法如下:
Workbooks.OpenText(FileName, Origin, StartRow, DataType, TextQualifier, ConsecutiveDelimiter, Tab, Semicolon, Comma, Space, Other, OtherChar, FieldInfo, TextVisualLayout, DecimalSeparator, ThousandsSeparator, TrailingMinusNumbers, Local)

关于以上参数的具体含义可以参看VBA的帮助,这里就不重复了。在实际的编程中,一般无需对这些复杂的参数进行处理。可以通过录制宏来得到打开一个 文本文件的VBA代码。具体方法就是选择“文件——打开”,然后选择打开文本文件,就会出现文本导入向导,一步一步执行完,直到文本打开后,停止录制。
以下是录制宏得到的代码:
Sub Macro1()

‘ Macro1 Macro
‘ 宏由 MC SYSTEM 录制,时间: 2007-3-29


Workbooks.OpenText Filename:="F:\CallWindowProc.txt", Origin:=xlWindows, _
StartRow:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, Comma:=False _
, Space:=False, Other:=False, FieldInfo:=Array(1, 1), _
TrailingMinusNumbers:=True
End Sub

在实际编程中只要做相应的修改就可以使用了。

3、打开其他文件

利用Excel对象还可以打开XML文件和一些数据库(如Access)文件,对应XML文件,需要Excel2003以上的版本。

OpenXML方法的语法如下:
Workbooks.OpenXML(Filename, Stylesheets, LoadOption)
FileName String 类型,必需。要打开的文件名。

Stylesheets Variant 类型,可选。单个值或值的数组,用于指定要应用哪些 XSL 转换 (XSLT) 样式表处理指令。

LoadOption Variant 类型,转换。指定 Excel 打开 XML 数据文件的方式。可为 XlXmlLoadOption 常量之一。

XlXmlLoadOption 可为以下 XlXmlLoadOption 常量之一: 
xlXmlLoadImportToList 将 XML 数据文件的内容置于 XML 列表中。 
xlXmlLoadMapXml 在“XML 结构”任务窗格中显示 XML 数据文件的架构。 
xlXmlLoadOpenXml 打开 XML 数据文件。文件的内容将展开。 
xlXmlLoadPromptUser 提示用户选择打开文件的方式。


示例
下面的代码打开了 XML 数据文件“customers.xml”并在 XML 列表中显示了此文件的内容。

Sub UseOpenXML()
Application.Workbooks.OpenXML _
Filename:="customers.xml", _
LoadOption:=xlXmlLoadImportToList
End Sub

OpenDatabase 方法语法如下:
Workbooks.OpenDatabase(FileName, CommandText, CommandType, BackgroundQuery, ImportDataAs)

FileName String 类型,必需。连接字符串。

CommandText Variant 类型,可选。查询的命令文本。

CommandType Variant 类型,可选。查询的命令类型。以下是可用的命令类型:Default、SQL 和 Table。

BackgroundQuery Variant 类型,可选。查询的背景。

ImportDataAs Variant 类型,可选。确定查询的格式。

示例
本示例中,Excel 打开了“northwind.mdb”文件。

Sub OpenDatabase()

Workbooks.OpenDatabase FileName:="C:\northwind.mdb"

End Sub

4、保存文件

文件的保存使用Workbook对象的Save或SaveAs方法。
Save方法使用简单,语法为
expression.Save,expression是某个Workbook对象。
如:ActiveWorkbook.Save
即保存当前活动工作簿。

如果是第一次保存工作簿或要另存为,请使用 SaveAs 方法为该文件指定文件名。
其语法为:
expression.SaveAs(FileName, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AccessMode, ConflictResolution, AddToMru, TextCodepage, TextVisualLayout, Local)

具体参数含义可参看VBA帮助,使用都比较简单。
示例
本示例新建一个工作簿,提示用户输入文件名,然后保存该工作簿。

Set NewBook = Workbooks.Add
Do
fName = Application.GetSaveAsFilename
Loop Until fName <> False
NewBook.SaveAs Filename:=fName

Application.GetSaveAsFilename为调出标准的“另存为”对话框,获取用户文件名,但并不真正保存任何文件,然后使用代码保存文件。还有Application.GetOpenFileName可以调出标准的“打开”对话框。

5、关闭文件

关闭文件可以使用Workbooks集合或Workbook对象的 Close 方法。前者是关闭所有打开的工作簿,后者关闭特定的工作簿。
Workbook对象的 Close 方法语法为:
expression.Close(SaveChanges, Filename, RouteWorkbook)

SaveChanges参数表示是否保存更改,对许多不需要更改的操作,可设置为False以免弹出保存更改提示的对话框。
FileName 可选。以此文件名保存所做的更改。
RouteWorkbook 可选。如果指定工作簿不需要传送给下一个收件人(没有传送名单或已经传送),则忽略该参数。

示例
本示例关闭 Book1.xls,并放弃所有对此工作簿的更改。

Workbooks("BOOK1.XLS").Close SaveChanges:=False

本示例关闭所有打开的工作簿。如果某个打开的工作簿有改变,Microsoft Excel 将显示询问是否保存更改的对话框和相应提示。

Workbooks.Close

6、综合实例

假如F盘有一个Excel文件test.xls,现在有另一个Excel文件要访问test.xls的数据,我们来看用VBA代码如何操作。代码如下:
Public Sub test()
Application.ScreenUpdating = False
Workbooks.Open "f:\test.xls"
ThisWorkbook.Sheets(1).Range("b1") = ActiveWorkbook.Sheets(1).Range("a2")
ActiveWorkbook.Close
Application.ScreenUpdating = True
End Sub
首先关闭屏幕刷新,是为了防止test.xls在打开时被看见(有时候还是看的见)。打开后,见test.xls的Sheet1的单元格A2中的值赋给当前工作簿的Sheet1的单元格B2,然后关闭test.xls。
当要打开的工作簿不确定的时候,可以通过调用打开对话框来让用户自己选择。
可改为如下:
Public Sub test()
Application.ScreenUpdating = False
Dim Filename as String
Filename = Application.GetOpenFileName
Workbooks.Open Filename
ThisWorkbook.Sheets(1).Range("b1") = ActiveWorkbook.Sheets(1).Range("a2")
ActiveWorkbook.Close
Application.ScreenUpdating = True
End Sub

7、总结

利用Excel对象的方法进行文件操作是最简单,也是最方便的,适合初学者。对于Excel文件格式,如果我们仅仅是读取其表格中的内容,这种方法也是首选。对于文本文件的操作,使用第二种方法比较方便,若要将文本转换成表格,那么使用此方法也是合适的。
 
 

如何在d:\test.xls已打开的情况下不让以下的语句再去创建一个test.xls的实例(虽然它标识为只读),

并给出文件已打开的提示.

先做一个判断!判断该工作簿是否打开了?

例如:

Set xlexcel = CreateObject("excel.application")

dim wb as object

set wb = xlexcel.workbooks("test.xls")

if wb is nothing then

msgbox "工作簿未打开!"

xlexcel.Workbooks.Open "d:\test.xls"
xlexcel.Visible = True

end if

 

Excel-VBA操作文件四大方法之二

 

二、利用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 String
Dim 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 ‘ 在立即窗口中显示数据。
Loop
Close #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 TextLine
Open "TESTFILE" For Input As #1 ‘ 打开文件。
Do While Not EOF(1) ‘ 循环至文件尾。
Line Input #1, TextLine ‘ 读入一行数据并将其赋予某变量。
Debug.Print TextLine ‘ 在立即窗口中显示数据。
Loop
Close #1 ‘ 关闭文件。

11、Input 函数

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

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

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

示例:
Dim MyChar
Open "f:\test.txt" For Input As #1
Do While Not EOF(1) ‘ 循环至文件尾。
MyChar = Input(1, #1) ‘ 读入一个字符。
Debug.Print MyChar ‘ 显示到立即窗口。
Loop
Close #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 I
Open "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 String
num = 12345
text = "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, , num
text = 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语句。
Excel文件本身就是二进制文件,它使用的文件格式叫做BIFF(Binary Interchange File Format),即二进制可交换文件格式(但2007开始使用OOXML格式)。关于其内部的结构,本人也在研究中。以二进制结构打开Excel文件,不 但可以读取其表格中的数据,还可以读取其所有的信息(包括密码)。注意,以Open语句打开文件,并不是我们通常的双击一个文件打开显示到屏幕上,而是将 其存放在磁盘上的数据读入到缓冲区,不是可视化的打开。这种打开是不需要密码的,即使你的Excel文件设置了打开密码,还是照打开不误,这也正是 Excel文件不安全的根源所在。我以前发过一篇关于破解的文章,里面破解VBA工程密码的方法就是用二进制替换。由于论坛不让讨论破解的话题,这里就不 再详细分析代码了,感兴趣的请自行研究。当然,Excel的其他密码也是可类似破解的,前提是你必须十分了解Excel的内部结构,知道密码放在哪里,才 能替换。知道的解密的方法,自然可以针对性的改进加密的方法。好了,这里就不再罗嗦了,如果对Excel的内部结构感兴趣,可以先看这篇文章,看懂再说。

 

Excel-VBA操作文件四大方法之三

 


三、利用FileSystemObject对象来处理文件

FileSystemObject对象模型,是微软提供的专门用来访问计算机文件系统的,具有大量的属性、方法和事件。其使 用面向对象的“object.method”语法来处理文件夹和文件,使用起来十分方便(需Office 2000以后版本)。FileSystemObject并不是VBA的一部分,它是以一个COM组件的形式提供的。因此,要使用先要创建 FileSystemObject对象。

FileSystemObject对象模型包含了下面的对象和集合:

·FileSystemObject 主对象,包含用来创建、删除和获得有关信息,以及用来操作驱动器、文件夹和文件的方法和属性。

·Drive 对象,包含用来获得信息的方法和属性,这些信息是关于连接在系统上的驱动器的,如有多少可用空间等。驱动器不一定是硬盘,也可以是CD-ROM、U盘甚至是通过网络在逻辑上连接的硬盘(如公司里部门共享的服务器网络硬盘)。

·Drives 集合,提供驱动器的列表,这些驱动器以实物或在逻辑上与系统相连接。Drives集合包括所有驱动器,与类型无关。

·File 对象,包含用来创建、删除或移动文件的方法和属性。

·Files 集合,提供包含在文件夹内的所有文件的列表。

·Folder 对象,包含用来创建、删除或移动文件夹的方法和属性。

·Folders 集合,提供包含在文件夹内的所有文件夹的列表。

·TextStream 对象,用来读写文本文件。


(一)准备工作

要使用FileSystemObject对象,先要创建它。创建FileSystemObject对象要使用CreatObject函数。CreateObject 函数用来创建并返回一个对 ActiveX 对象的引用。

语法:CreateObject(class,[servername])
class 是要创建的应用程序名称和类。 
servername 要在其上创建对象的网络服务器名称。(如果要在远程计算机上创建对象才用)

class 参数使用 appname.objecttype 这种语法,包括以下部分:

appname 必需的;提供该对象的应用程序名。 
objecttype 必需的;待创建对象的类型或类。

因此,我们用下面的代码创建FileSystemObject对象:

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")

Scripting是类型库的名称,FileSystemObject就是要创建的对象的名字。

同样我们可以创建Dictionary 对象如下:
Dim d
Set d = CreateObject("Scripting.Dictionary")


(二)FileSystemObject对象的方法

FileSystemObject对象模型中有些功能是重复的,如可用FileSystemObject对象的CpoyFile方法,也可用File对象的Copy方法来复制文件。下面先介绍FileSystemObject对象的方法。

1、GetDrive 方法

语法:object.GetDrive drivespec

drivespec参数可以是一个驱动器字符(c)、一个驱动器字符加一个冒号(c:)、一个驱动器字符加冒号和路径分隔符(c:\)或任何网络共享的说明(\\computer2\share1)。

作用:返回一个与指定路径中的驱动器相对应的 Drive 对象。

示例:
Dim d
Set d = fso.GetDrive("D:") ‘变量d就代表了驱动器D对象
如果 drivespec 不符合任何一种可以接受的形式或者不存在,则发生一个错误。

注意:为简洁,示例中都假定fso是已经创建的FileSystemObject对象

2、GetDriveName 方法

语法:object.GetDriveName(path)

作用:返回一个包含指定路径的驱动器名字的字符串。

示例:
Debug.Print fso.GetDriveName("c:\test.txt") ‘立即窗口显示"c:"

3、GetExtensionName 方法

语法:object.GetExtensionName(path)

作用:返回一个包含路径中最后部件扩展名的字符串。

示例:
Debug.Print fso.GetExtensionName("c:\test.txt") ‘立即窗口显示"txt"

4、GetBaseName 方法

语法:object.GetBaseName(path)

作用:返回一个包含路径中最后部件的基本名字(去掉任何文件扩展名)的字符串。

示例:
Debug.Print fso.GetBaseName("c:\abc\test.txt") ‘立即窗口显示"test"

5、GetAbsolutePathName 方法

语法:object.GetAbsolutePathName(pathspec)

作用:从提供的路径说明中返回一个完整、明确的路径。

示例:
如果pathspec为空字符串"",则返回当前路径。假设当前路径为C:\Documents and Settings\yc\My Documents

Debug.Print fs.GetAbsolutePathName("") ‘显示C:\Documents and Settings\yc\My Documents

Debug.Print fs.GetAbsolutePathName("c:..") ‘显示C:\Documents and Settings\yc,即上层目录

Debug.Print fs.GetAbsolutePathName("abc") ‘显示C:\Documents and Settings\yc\My Documents\abc

Debug.Print fs.GetAbsolutePathName("c:\test.txt") ‘显示C:\test.txt

6、GetFile 方法

语法:object.GetFile(filespec)

作用:返回一个和指定路径中文件相对应的 File 对象。

示例:
Dim f
Set f = fso.GetFile("c:\test.txt") ‘变量f就代表了文件test.txt对象
注意:如果指定的文件不存在,则发生一个错误。

7、GetFileName 方法

语法:object.GetFileName(pathspec)

作用:返回指定路径中的最后部件,该路径不是驱动器说明的一部分。

示例:
Debug.Print fso.GetFileName("c:\abc\test.txt") ‘立即窗口显示"test.txt"

8、GetFolder 方法

语法:object.GetFolder(folderspec)

作用:返回一个和指定路径中文件夹相对应的 Folder 对象。

示例:
Dim fd
Set fd = fso.GetFolder("c:\windows") ‘变量f就代表了文件夹windows对象
注意:如果指定的文件夹不存在,则发生一个错误。

9、GetSpecialFolder 方法

语法:object.GetSpecialFolder(folderspec)

作用:返回指定的特殊文件夹。

说明:
folderspec 参数可为任何的下列值:

WindowsFolder 0 Windows 文件夹,包含由 Windows 操作系统安装的文件。 
SystemFolder 1 系统文件夹,包含库、字体、设备驱动程序。 
TemporaryFolder 2 Temp 文件夹,用于存储临时文件。它的路径在 TMP 环境变量中。

10、GetParentFolderName 方法

语法:object.GetParentFolderName(path)

作用:返回一个包含指定路径最后部件父文件夹名字的字符串。

示例:
Debug.Print fso.GetParentFolderName("c:\tmp\test.txt") ‘显示"c:\tmp"

11、GetTempName 方法

语法:object.GetTempName

作用:返回一个随机产生的临时文件或文件夹的名字,该名字在执行需要临时文件或文件夹的操作时有用。

说明:GetTempName 方法不产生一个文件,它仅提供一个临时文件名字,该名字可被 CreateTextFile 用于创建一个文件。

示例:
Debug.Print fso.GetTempName ‘显示"radB0208.tmp",每次都会变。

12、BuildPath 方法

语法:object.BuildPath(path, name)

作用:追加一个名字到一个已经存在的路径。

示例:
Debug.Print fso.BuildPath("c:\tmp", "abc") ‘显示"c:\tmp\abc"

13、CreateFolder 方法

语法:object.CreateFolder(foldername)

作用:创建一个文件夹。

注意:如果指定的文件夹已经存在,则发生一个错误。

示例:
fso.CreateFolder("c:\myfolder") ‘在C盘创建一个myfolder文件夹

14、CopyFolder 方法

语法:object.CopyFolder source, destination[, overwrite]
source 必需的。指明一个或多个被复制文件夹的字符串文件夹说明,可以包括通配符。 
destination 必需的。指明 source 中被复制文件夹和子文件夹的接受端的字符串,不允许有通配符。 
overwrite 可选的。Boolean 值,它表示已存在的文件夹是否被覆盖。如果为 True,文件被覆盖。如果为 False,文件不被覆盖。缺省值为 True。

作用:复制一个文件夹到另一个地方。

说明:
① 通配符仅可用于 source 参数的最后一个路径部件。

例如:fso.CopyFolder "c:\mydocuments\letters\*", "c:\tempfolder\" 这是可以的。
但不能这样:fso.CopyFolder "c:\mydocuments\*\*", "c:\tempfolder\"

② 如果 source 包含通配符或 destination 以路径分隔符(\)为结尾,则认为 destination 是一个已存在的文件夹,在其中复制相匹配的文件夹和子文件夹。否则认为 destination 是一个要创建的文件夹的名字。

例如:fso.copyfolder "c:\tmp", "f:\abc\"
如果F盘没有abc文件夹,将发生错误。如果存在,可看到abc文件夹里有tmp文件夹。
假如写成这样:fso.copyfolder "c:\tmp", "f:\abc"
此时若abc不存在,将创建abc文件夹,且将tmp文件夹里的内容复制到abc文件夹里,而不是tmp文件夹,只有abc是一个已经存在的文件夹时,才复制整个tmp文件夹到abc文件夹里。

③如果 destination 是一个已存在的文件,则发生一个错误。

④如果 destination 是一个目录,它将尝试复制文件夹和它所有的内容。如果一个包含在 source 的文件已在 destination 中存在,当 overwrite 为 False 时发生一个错误,否则它将尝试覆盖这个文件。

⑤如果 destination 是一个只读目录,当尝试去复制一个已存在的只读文件到此目录并且 overwrite为 False 时,则发生一个错误。

⑥如果 source 不存在或使用的通配符不能和任何文件夹匹配,也发生一个错误。

⑦CopyFolder 方法停止在它遇到的第一个错误上,之前所做的操作是不会消失的,所以要注意。

15、MoveFolder 方法

语法:object.MoveFolder source, destination
参数与CopyFolder的前两个一样。

作用:将一个或多个文件夹从一个地方移动到另一个地方。

说明:
①只有在操作系统支持的情况下,这个方法才允许文件夹在卷之间移动。Windows是不允许的,将C盘的文件夹移到D盘是不行的。

②如果 source 包含通配符或 destination 以路径分隔符 (\) 为结尾,则认为 destination 指定了一个已存在的文件夹,在此文件夹中移动相匹配的文件。否则,认为 destination 是一个要创建的目标文件夹名字。这点与CopyFolder是一样的。

③如果 destination 是一个已存在的文件,则发生一个错误。

④如果 destination 是一个目录,则发生一个错误。
例如:
fso.movefolder "c:\tmp", "c:" ‘发生错误。

⑤如果 source 不存在或使用的通配符不能和任何文件夹匹配,也发生一个错误。

⑥MoveFolder 方法停止在它遇到的第一个错误上。不要尝试回卷在错误发生前所做的任何改变。

16、DeleteFolder 方法

语法:object.DeleteFolder folderspec[, force]

folderspec 必需的。要删除的文件夹的名字。 Folderspec 可以在最后的路径部件中包含通配符。 
force 可选的。Boolean 值,如果要删除具有只读属性设置的文件夹,其值为 True,如果值为 False (缺省),则不能删除具有只读属性设置的文件夹。

作用:删除一个指定的文件夹和它的内容。

说明:如果没有发现相匹配的文件夹,则发生一个错误。DeleteFolder 方法停止在它遇到的第一个错误上,不要尝试回卷或撤消错误发生前所做的任何改变。

示例:
fso.DeleteFolder("c:\tmp")

17、FolderExists 方法

语法:object.FolderExists(folderspec)

作用:如果指定的文件夹存在返回 True,不存在返回 False。

18、DriveExists 方法

语法:object.DriveExists(drivespec)

作用:如果指定的驱动器存在,返回 True,如果不存在返回 False。

19、FileExists 方法

语法:object.FileExists(filespec)

作用:如果指定的文件存在,返回 True,若不存在,则返回 False。

20、CreateTextFile 方法

语法:object.CreateTextFile(filename[, overwrite[, unicode]])

overwrite 可选的。Boolean 值,表示一个已存在文件是否可被覆盖。如果可被覆盖其值为 True,其值为 False 时不能覆盖。如果它被省略,则已存在文件不能覆盖。

unicode 可选的。Boolean 值,表示文件是作为一个 Unicode 文件创建的还是作为一个ASCII 文件创建的。如果作为一个 Unicode 文件创建,其值为 True,作为一个 ASCII 文件创建,其值为 False。如果省略的话,则认为是一个 ASCII 文件。

作用:创建一个指定的文件名并且返回一个用于该文件读写的 TextStream 对象。

示例:
Dim f
Set f = fso.CreateTextFile("c:\testfile.txt", True)

21、OpenTextFile 方法

语法:object.OpenTextFile(filename[, iomode[, create[, format]]])

作用:打开一个指定的文件并返回一个 TextStream 对象,该对象可用于对文件进行读、写、追加操作。

说明:
·iomode 参数可为下面设置值中的任何值:

ForReading 1 打开一个只读文件,不能对此文件进行写操作。 
ForWriting 2 打开一个用于写操作的文件。如果和此文件同名的文件已存在,则覆盖以前内容。 
ForAppending 8 打开一个文件并写到文件的尾部。

注意:在VBA帮助里是没有ForWriting的,其实是有的,VBA帮助也是有错误的。另外,这些常数在使用前要先声明,或者直接用数值。

·create 可选的,它表示如果指定的 filename 不存在是否可以创建一个新文件。如果创建新文件,其值为 True。若不创建文件其值为 False。缺省值为 False。

·Format 参数可为下面设置值中的任何值:

TristateUseDefault –2 使用系统缺省打开文件。 
TristateTrue –1 以 Unicode 格式打开文件。 
TristateFalse 0 以 ASCII 格式打开文件。

示例:
Dim f
Set f = fso.OpenTextFile("c:\testfile.txt", 2, True)
或者:
Const ForWriting = 2
Set f = fso.OpenTextFile("c:\testfile.txt", ForWriting, True)
这两者功能是一样的,一个声明了常量,一个直接用数值。都是在C盘创建文件testfile.txt(如不存在),或以写的方式打开(如存在)。

22、CopyFile 方法

语法:object.CopyFile source, destination[, overwrite]

作用:把一个或多个文件从一个地方复制到另一个地方。

说明:需要注意的地方与CopyFolder是完全类似的。

示例:
fso.copyfile "c:\testfile.txt", "f:\abc\" ‘若abc不存在则出错。
fso.copyfile "c:\testfile.txt", "f:\abc" ‘若abc不存在则复制testfile.txt到F盘文件名变为abc,若abc存在,出错,因为是一个目录。

23、MoveFile 方法

语法:object.MoveFile source, destination

作用:将一个或多个文件从一个地方移动到另一个地方。

说明:需要注意的地方与MoveFolder是完全类似的。

24、DeleteFile 方法

语法:object.DeleteFile filespec[, force]

作用:删除一个指定的文件。

说明:force 可选的。如果要删除具有只读属性设置的文件,其值为 True。如果其值为 False (缺省),则不能删除具有只读属性设置的文件。 

(三)处理驱动器

可以利用Drive对象来获取有关各种驱动器的信息,Drive对象的属性有:

TotalSize 属性 驱动器的总容量,以字节为单位。
AvailableSpace 属性 驱动器的可用空间容量,以字节为单位。
FreeSpace 属性 驱动器的剩余空间容量,和 AvailableSpace 属性是相同的。
对于支持限额的计算机系统来说,二者之间可能有所不同。
DriveLetter 属性 驱动器字母,即盘符。
DriveType 属性 驱动器的类型。如"Removable"、"Fixed"、"Network"、"CD-ROM"、"RAM Disk"
SerialNumber 属性 驱动器的序列号。
FileSystem 属性 驱动器所使用的文件系统类型。如FAT、FAT32、NTFS、以及 CDFS。
IsReady 属性 驱动器是否可用。
ShareName 属性 驱动器的网络共享名。
VolumeName 属性 驱动器的卷标名。
Path 属性 驱动器的路径。C 驱动器的路径是 C:,而不是 C:\。
RootFolder 属性 定驱动器的根文件夹。C 驱动器的根文件夹是 C:\。

这些属性的使用都十分简单,直接用“对象.属性”就可以了。在使用前要先用GetDrive获得一个Drive对象,注意不能创建一个驱动器对象。下面举个例子:

Sub ShowFreeSpace(drvPath)
Dim fs, d, s
Set fs = CreateObject("Scripting.FileSystemObject")
Set d = fs.Getdrive(fs.GetDriveName(drvPath))
s = "Drive " & UCase(drvPath) & "-"
s = s & d.VolumeName & vbCrLf
s = s & "Free Space: " & FormatNumber(d.FreeSpace / 1024, 0)
s = s & " Kbytes"
MsgBox s
End Sub

利用Call ShowFreeSpace("c:"),即可获得C盘的卷标名和可用空间。

(四)处理文件夹

1、获取文件夹的信息

可以利用Folder对象来获取有关文件夹的信息,Folder对象的属性有:

Attributes 属性 文件夹的属性。可为下列值中的任意一个或任意的逻辑组合:
Normal 0 一般文件。未设置属性。 
ReadOnly 1 只读文件。属性为读/写。 
Hidden 2 隐藏文件。属性为读/写。 
System 4 系统文件。属性为读/写。 
Volume 8 磁盘驱动器卷标。属性为只读。 
Directory 16 文件夹或目录。属性为只读。 
Archive 32 自上次备份后已经改变的文件。属性为读/写。 
Alias 64 链接或快捷方式。属性为只读。 
Compressed 128 压缩文件。属性为只读。 
Name 属性 文件夹名字。
ShortName 属性 较早的 8.3 命名约定的程序所使用的短名字。
Type 属性 文件夹类型。
Files 属性 所有 File 对象组成的 Files 集合,这些 File 对象包含在指定的文件夹中
──包括设置了隐藏和系统文件属性的那些文件。
Drive 属性 文件夹所在的驱动器符号。
IsRootFolder 属性 文件夹是否是根文件夹。
ParentFolder 属性 文件夹的父文件夹对象。
SubFolders 属性 文件夹的子文件夹集合。
Path 属性 文件夹的路径。
ShortPath 属性 较早的 8.3 文件命名约定的程序所使用的短路径。
Size 属性 文件夹的大小,以字节为单位。
DateCreated 属性 文件夹的创建日期和时间。
DateLastModified 属性 最后一次修改文件夹的日期和时间。
DateLastAccessed 属性 最后一次访问文件夹的日期和时间。

属性的使用和Drive对象是一样的,可以用GetFolder获取一个Folder对象,也可以用FileSystemObject对象的CreateFolder 方法创建一个Folder对象。

2、Folder对象的方法

⑴Copy 方法

语法:object.Copy destination[, overwrite]

作用:把一个指定的文件夹从一个地方复制到另一个地方。

说明:Copy 方法的作用与FileSystemObject对象的CopyFolder 方法是一样的,不同在于后者可一次复制多个文件夹。

⑵Move 方法

语法:object.Move destination

作用:将一个指定的文件夹从一个地方移动到另一个地方。

说明:Move 方法的作用与FileSystemObject.MoveFolder 是一样的。不同在于后者可一次移动多个文件夹。

⑶Delete 方法

语法:object.Delete force

作用:删除一个指定的文件夹。

说明:Delete 方法的作用与FileSystemObject.DeleteFolder 是一样的。

⑷CreateTextFile 方法

语法:object.CreateTextFile(filename[, overwrite[, unicode]])

作用:与FileSystemObject对象的CreateTextFile 方法是一样的。

示例:
Set fd = fs.getfolder("c:\tmp")
Set f = fd.CreateTextFile("testfile.txt", True)
可在C盘tmp文件夹下创建testfile.txt文件。


(五)处理文件

1、获取文件的信息

可以利用File对象来获取有关文件的信息,File对象的属性和Folder的属性是完全一样的,只是少了Files 属性、IsRootFolder 属性、SubFolders 属性这3个属性。这里就不列了。

2、File对象的方法

⑴Copy 方法

⑵Move 方法

⑶Delete 方法

以上三种方法与Folder的是完全类似的,语法也一样,同样也可用FileSystemObject对象相应的方法代替。

⑷OpenAsTextStream 方法

语法:object.OpenAsTextStream([iomode, [format]])

作用:打开一个指定的文件并返回一个 TextStream 对象,该对象可用来对文件进行读、写、追加操作。

说明:此方法与FileSystemObject对象的 OpenTextFile 方法相同的功能。参数也是一致的。


(六)处理文本文件

1、打开或创建文本文件

打开现有的文本文件,可以使用FileSystemObject对象的 OpenTextFile 方法或File对象的OpenAsTextStream 方法。
创建文件可以使用FileSystemObject对象的 CreatTextFile 方法或在OpenTextFile 方法中将iomode参数设为ForWriting=2,create参数设为True。
例如:
Set f = fso.OpenTextFile("c:\test1.xls", 2, True) ‘如果不存在test1.xls将自动创建。

2、读取文件

打开文件后,将返回一个TextStream 对象,我们可以利用TextStream 对象的属性及方法来对文件进行读写操作。

先看TextStream 对象的几个属性。

·AtEndOfLine 属性 文件指针是否正好在行尾标记的前面
·AtEndOfStream 属性 文件指针是否在 TextStream 文件末尾
·Column 属性 TextStream 文件中当前字符位置的列号
·Line 属性 TextStream 文件中的当前行号

利用TextStream 对象读取文件有三种方法。

·Read 方法

语法:object.Read(characters)

功能:从一个 TextStream 文件中读取指定数量的字符并返回得到的字符串。

示例:
Sub du()
Dim fso, a, retstring
Const ForReading = 1
Set fso = CreateObject("Scripting.FileSystemObject")
Set a = fso.OpenTextFile("c:\testfile.txt", ForReading, False)
Do While a.AtEndOfLine <> True ‘是否到行末
retstring = retstring & a.Read(1) ‘读取一个字符
Loop
a.Close
Debug.Print retstring ‘可看到读取了第一行的字符
End Sub

·ReadLine 方法

语法:object.ReadLine

功能:从一个 TextStream 文件读取一整行(到换行符但不包括换行符)并返回得到的字符串。

示例:
Sub du_line()
Dim fso, a, retstring
Const ForReading = 1
Set fso = CreateObject("Scripting.FileSystemObject")
Set a = fso.OpenTextFile("c:\testfile.txt", ForReading, False)
Do While a.AtEndOfStream <> True ‘是否在 TextStream 文件末尾
retstring = a.ReadLine ‘读取一行
Debug.Print retstring ‘显示在立即窗口
Loop
a.Close
End Sub

·ReadAll 方法

语法:object.ReadAll

功能:读取整个的 TextStream 文件并返回得到的字符串。

说明:对于大的文件,使用ReadAll方法浪费内存资源。应使用其它的技术去输入一个文件,比如按行读取文件。

示例:
Sub du_all()
Dim fso, a, retstring
Const ForReading = 1
Set fso = CreateObject("Scripting.FileSystemObject")
Set a = fso.OpenTextFile("c:\testfile.txt", ForReading, False)
retstring = a.Readall ‘全部读取
Debug.Print retstring
a.Close
End Sub

还有两个辅助读取的方法:

·Skip 方法

语法:object.Skip(characters)

功能:当读一个 TextStream 文件时跳过指定数量的字符。

示例:
Sub duskip()
Dim fso, a, retstring
Const ForReading = 1
Set fso = CreateObject("Scripting.FileSystemObject")
Set a = fso.OpenTextFile("c:\testfile.txt", ForReading, False)
Do While a.AtEndOfLine <> True ‘是否到行末
retstring = retstring & a.Read(1) ‘读取一个字符
a.Skip (1) ‘跳过一个字符
Loop
a.Close
Debug.Print retstring ‘可看到读取了第一行的奇数位的字符
End Sub

·SkipLine 方法

语法:object.SkipLine

功能:当读一个 TextStream 文件时跳过下一行。


3、写入数据到文件

写入数据到文件也有三种方法。

·Write 方法

语法:object.Write(string)

功能:写一个指定的字符串到一个 TextStream 文件。

示例:
Sub xie()
Const ForWriting = 2, ForAppending = 8
Dim fs, f
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.OpenTextFile("c:\testfile.txt", ForAppending,TristateFalse)
f.Write "Hello world!" ‘写入字符串
f.Close
End Sub

·WriteLine 方法

语法:object.WriteLine([string])

功能:写入一个指定的字符串和换行符到一个 TextStream 文件中。

示例:
f.WriteLine("Hello world!") ‘写入字符串,加一个换行符。

·WriteBlankLines 方法

语法:object.WriteBlankLines(lines)

功能:写入指定数量的换行符到一个 TextStream 文件中。

示例:
f.WriteBlankLines(3) ‘相当于按3次回车。

4、关闭文件

利用TextStream 对象的Close方法,上面的示例中已经有了,很简单。


(七)总结

从上面的介绍,我们看到使用FileSystemObject对象处理文件、文件夹比使用VBA语句的方法具有更容易存在的特点。这是因为 FileSystemObject对象使用了面向对象的语法。另外FileSystemObject对象处理文本文件毫不逊色于VBA语句,非常值得推 荐。唯一的问题是不能处理二进制文件,微软在有关文档中称计划将来支持二进制文件,不过应该只是计划而已,呵呵。
之四

四、利用API函数来处理文件

通过前面三种方法的介绍,你是否已经觉得足够了?是的,前面的方法完全可以应付几乎所有的文件操作。但是为了普及一下API,展示一下API的魅力,最后向大家介绍一下如何利用API函数来处理文件。另一方面也是本人对API情有独钟,为她做一下广告,呵呵。

大家对API的强大也是有所耳闻了,在文件操作方面,API自然毫不逊色。
说明:为了文章简洁,我们先给出API函数的名称及功能,其完整的声明及常数就不再一一细诉,只在示例中给出其完整用法。

(一)处理驱动器及目录

下面是windows中提供的对于目录进行操作的API函数及其功能:

CreateDirectory,CreateDirectoryEx 创建一个新目录 
GetCurrentDirectory 在一个缓冲区中装载当前目录 
GetDiskFreeSpace,GetDiskFreeSpaceEx 获取与一个磁盘的组织有关的信息,以及了解剩余空间的容量 
GetDriveType 判断一个磁盘驱动器的类型 
GetFullPathName 获取指定文件的完整路径名 
GetLogicalDrives 判断系统中存在哪些逻辑驱动器字母 
GetLogicalDriveStrings 获取一个字串,其中包含了当前所有逻辑驱动器的根驱动器路径 
GetSystemDirectory 这个函数能取得Windows系统目录(System目录)的完整路径名。在这个目录中,包含了所有必要的系统文件。根据微软的标准,其他定制控件和一 些共享组件也可放到这个目录。通常应避免在这个目录里创建文件。在网络环境中,往往需要管理员权限才可对这个目录进行写操作 
GetTempPath 获取为临时文件指定的路径 
GetVolumeInformation 获取与一个磁盘卷有关的信息 
GetWindowsDirectory 这个函数能获取Windows目录的完整路径名。在这个目录里,保存了大多数windows应用程序文件及初始化文件 
RemoveDirectory 删除指定目录 
SetCurrentDirectory 设置当前目录 
SetVolumeLabel 设置一个磁盘的卷标(Label)

下面通过几个例子来详细的了解一下其中主要的几个函数及其用法:

1、GetLogicalDrives

作用:判断系统中存在哪些逻辑驱动器字母

声明:Declare Function GetLogicalDrives Lib "kernel32" Alias "GetLogicalDrives" () As Long

说明:此函数的返回值类型为Long,这个结构中的二进制位标志着存在哪些驱动器。其中,位0设为1表示驱动器A:存在于系统中;位1设为1表示存在B:驱动器;以次类推

示例:
Public Sub Get_LogicalDrives()
Dim LDs As Long, Cnt As Long, sDrives As String
LDs = GetLogicalDrives
sDrives = "Available drives:"
For Cnt = 0 To 25
If (LDs And 2 ^ Cnt) <> 0 Then
sDrives = sDrives + " " + Chr$(65 + Cnt)
End If
Next Cnt
MsgBox sDrives
End Sub

上面的示例中,我们通过二进制运算,将返回值转换成字符。如果你的机上有C,D,E,F,G,H这几个驱动器,那么LDs的值就是252,转成二进制为11111100,从右往左,依次代表A,B,C,D,...,为0的说明没有此驱动器字母。大家可以自己试一试。

2、GetDriveType

作用:判断一个磁盘驱动器的类型

声明:Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long

说明:此函数的返回值类型为Long,如驱动器不能识别,则返回零。如指定的目录不存在,则返回1。如执行成功,则用下述任何一个常数指 定驱动器类型:DRIVE_REMOVABLE(表示磁盘可以从驱动器上移走,通常是软驱), DRIVE_FIXED(磁盘不能从驱动器上移走,通常为本地硬盘), DRIVE_REMOTE(驱动器是远程网络驱动器), DRIVE_CDROM(驱动器是CD-ROM驱动器) 或 DRIVE_RAMDISK(驱动器是RAM驱动器)
参数为String类型,包含了驱动器根目录路径的一个字串
此函数的功能与FSO的Drive对象的DriveType属性是一样的。

示例:
‘定义常数变量

Private Const DRIVE_CDROM = 5 ‘表示光盘驱动器
Private Const DRIVE_FIXED = 3 ‘表示硬盘驱动器
Private Const DRIVE_RAMDISK = 6 ‘表示RAM驱动器
Private Const DRIVE_REMOTE = 4 ‘表示网络驱动器
Private Const DRIVE_REMOVABLE = 2 ‘表示软盘驱动器


Private Sub Get_DriveType()
Dim temp As Long
temp = GetDriveType("d:\") ‘取的d:盘驱动器类型
Select Case temp
Case DRIVE_CDROM
MsgBox "DRIVE_CDROM: 光盘驱动器"
Case DRIVE_FIXED
MsgBox "DRIVE_FIXED: 硬盘驱动器"
Case DRIVE_RAMDISK
MsgBox "DRIVE_RAMDISK: RAM驱动器"
Case DRIVE_REMOTE
MsgBox "DRIVE_REMOTE: 网络驱动器"
Case DRIVE_REMOVABLE
MsgBox "DRIVE_REMOVABLE: 软盘驱动器"
End Select
End Sub

3、GetDiskFreeSpaceEx

作用:获取与一个磁盘的组织以及剩余空间容量有关的信息

声明:Declare Function GetDiskFreeSpaceEx Lib "kernel32" Alias "GetDiskFreeSpaceExA" (ByVal lpRootPathName As String, lpFreeBytesAvailableToCaller As LARGE_INTEGER, lpTotalNumberOfBytes As LARGE_INTEGER, lpTotalNumberOfFreeBytes As LARGE_INTEGER) As Long

说明:此函数的返回值类型为Long,非零表示成功,零表示失败。会设置GetLastError.

在采用FAT16格式的windows95系统中,如一个驱动器(分区)的容量超过了2GB,则不应使用这个函数。此时,这个函数能识别的最大分区容量只有2GB

参数说明:
lpRootPathName String,不包括卷名的磁盘根路径名 
lpFreeBytesAvailableToCaller LARGE_INTEGER,指定一个变量,用于容纳调用者可用的字节数量 
lpTotalNumberOfBytes LARGE_INTEGER,指定一个变量,用于容纳磁盘上的总字节数 
lpTotalNumberOfFreeBytes LARGE_INTEGER,指定一个变量,用于容纳磁盘上可用的字节数

LARGE_INTEGER结构用来代表一个64位带符号的整数值,它的定义如下:

Type LARGE_INTEGER ‘ 8 Bytes
lowpart As Long
highpart As Long
End Type

其中lowpart为 Long,指定低32位,highpart 为 Long,指定高32位。

示例:虽然此函数能识别的最大分区容量只有2GB,但通过调整,对大于2G的仍然能得出正确容量。以下的调整公式是本人通过逆向推算出来的,至于其中的原理也不是很清楚,大家可一测试一下。

Private Sub Get_DiskFreeSpaceEx()
Dim temp As Long, Dms$
Dim tempa, tempb, tempc
Dim RootPathName As String
Dim FreeBytesAvailabletoCaller As LARGE_INTEGER
Dim TotalNumberOfBytes As LARGE_INTEGER
Dim TotalNumberOfFreeBytes As LARGE_INTEGER

RootPathName = "d:"
‘取得磁盘空间
temp = GetDiskFreeSpaceEx(RootPathName, FreeBytesAvailabletoCaller, TotalNumberOfBytes, TotalNumberOfFreeBytes)

Dms = Dms + "磁盘容量:" + vbCrLf
tempa = TotalNumberOfBytes.highpart * 2 ^ 32 + IIf(TotalNumberOfBytes.lowpart > 0, TotalNumberOfBytes.lowpart, TotalNumberOfBytes.lowpart + 2 ^ 32) ‘计算容量
Dms = Dms + CStr(tempa) + "字节" + vbCrLf
tempa = Format(tempa / 1024 / 1024 / 1024, "0.00")
Dms = Dms + tempa + "G" + vbCrLf

‘取得磁盘可用空间

Dms = Dms + "磁盘可用空间:" + vbCrLf
tempb = TotalNumberOfFreeBytes.highpart * 2 ^ 32 + IIf(TotalNumberOfFreeBytes.lowpart > 0, TotalNumberOfFreeBytes.lowpart, TotalNumberOfFreeBytes.lowpart + 2 ^ 32) ‘计算
Dms = Dms + CStr(tempb) + "字节" + vbCrLf
tempb = Format(tempb / 1024 / 1024 / 1024, "0.00")
Dms = Dms + tempb + "G" + vbCrLf

‘取得磁盘已用空间

Dms = Dms + "磁盘已用空间:" + vbCrLf
tempc = tempa - tempb

Dms = Dms + CStr(tempc) + "G" + vbCrLf

MsgBox Dms
End Sub

4、CreateDirectory, CreateDirectoryEx

作用:创建一个新目录

声明:
Declare Function CreateDirectory& Lib "kernel32" Alias "CreateDirectoryA" (ByVal lpNewDirectory As String, lpSecurityAttributes As SECURITY_ATTRIBUTES)

Declare Function CreateDirectoryEx& Lib "kernel32" Alias "CreateDirectoryExA" (ByVal lpTemplateDirectory As String, ByVal lpNewDirectory As String, lpSecurityAttributes As SECURITY_ATTRIBUTES)

说明:此函数的返回值类型为Long,非零表示成功,零表示失败。会设置GetLastError

参数说明:
lpTemplateDirectory String,指定一个模板目录的名字,从中复制默认属性(比如目录中文件的默认压缩方式)。如设为vbNullString,则表示不使用模板 
lpNewDirectory String,新目录的名字 
lpSecurityAttributes SECURITY_ATTRIBUTES,这个结构定义了目录的安全特性——如果操作系统支持的话

示例:
Private Sub Create_Directory()
Dim Security As SECURITY_ATTRIBUTES
‘创建目录
Ret& = CreateDirectory("C:\Directory", Security)
‘若返回0,则失败。
If Ret& = 0 Then MsgBox "Error : 创建失败!", vbCritical + vbOKOnly
End Sub

5、RemoveDirectory

作用:移除一个目录

声明:Declare Function RemoveDirectory Lib "kernel32" Alias "RemoveDirectoryA" (ByVal lpPathName As String) As Long

说明:此函数的返回值类型为Long,非零表示成功,零表示失败。会设置GetLastError.
在调用这个函数前,目录必须为空

参数说明:
lpPathName 为String类型,要删除的那个目录的名字

示例:
Private Sub Remove_Directory()
Dim Security As SECURITY_ATTRIBUTES
CreateDirectoryEx "C:\Windows", "C:\Temp", Security
‘移除目录
RemoveDirectory "C:\Temp"
End Sub

6、SetCurrentDirectory

作用:设置当前目录,与VBA语句ChDir类似。

声明:Declare Function SetCurrentDirectory Lib "kernel32" Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long

说明:此函数的返回值类型为Long,非零表示成功,零表示失败。会设置GetLastError

参数说明:
LpPathName String,新当前目录的路径

示例:
SetCurrentDirectory "d:\" ‘设置D:为当前目录

7、GetSystemDirectory

作用:这个函数能取得Windows系统目录(System目录)的完整路径名。在这个目录中,包含了所有必要的系统文件。根据微软的标 准,其他定制控件和一些共享组件也可放到这个目录。通常应避免在这个目录里创建文件。在网络环境中,往往需要管理员权限才可对这个目录进行写操作

声明:Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long

说明:此函数的返回值类型为Long,装载到lpBuffer缓冲区的字符数量。如lpBuffer不够大,不能容下文件名,则返回要求的缓冲区长度

参数说明:
lpBuffer String,用于装载系统目录路径名的一个字串缓冲区。它应事先初始化成nSize+1个字符的长度。通常至少要为这个缓冲区分配MAX_PATH个字符的长度 
nSize Long,lpBuffer字串的最大长度

示例:
Private Sub Get_SystemDirectory()
Dim sSave As String, Ret As Long
‘创建缓冲区
sSave = Space(255)
‘获取系统目录
Ret = GetSystemDirectory(sSave, 255)
‘移除多余的0
sSave = Left$(sSave, Ret)
‘显示路径
MsgBox "系统目录: " + sSave
End Sub

 
(二)处理文件

下面是windows中提供的对于文件进行操作的API函数及其功能:

CloseHandle 关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。
CompareFileTime 根据FILETIME结构的信息,对比两个文件的时间 
CopyFile 复制文件。注意:只能复制文件,而不能复制目录
CreateFile 这是一个全功能的函数,可打开和创建文件、管道、邮槽、通信服务、设备以及控制台 
DeleteFile 删除指定文件 
FindClose 关闭由FindFirstFile函数创建的一个搜索句柄 
FindFirstFile 根据文件名查找文件 
FindNextFile 根据调用FindFirstFile函数时指定的一个文件名查找下一个文件 
FlushFileBuffers 针对指定的文件句柄,刷新内部文件缓冲区 
GetBinaryType 判断文件是否可以执行 
GetFileAttributes 判断指定文件的属性 
GetFileInformationByHandle 该函数能够获取上面所有函数所能够获取的信息,如大小、属性等,同时还包括一些其他地方无法获取的信息,比如:文件卷标、索引和链接信息。
GetFileSize 判断文件长度 
GetFileTime 取得指定文件的时间信息,有三个文件时间:创建时间、最后访问时间、最后写时间。
GetFileType 在给出文件句柄的前提下,判断文件类型 
GetFileVersionInfo 从支持版本标记的一个模块里获取文件版本信息 
GetFileVersionInfoSize 针对包含了版本资源的一个文件,判断容纳文件版本信息需要一个多大的缓冲区 
GetFullPathName 获取文件路径,该函数获取文件的完整路径名。注意:只有当该文件在当前目录下,
结果才正确。如果要得到真正的路径。应该用GetModuleFileName函数。
GetShortPathName 获取指定文件的短路径名 
GetTempFileName 这个函数包含了一个临时文件的名字,它可由应用程序使用 
GetTempPath 获取Windows临时目录路径
lclose 关闭指定的文件,请参考CloseHandle函数,了解进一步的情况 
lcreat 创建一个文件。如文件已经存在,就会将其缩短成零长度,并将其打开,以便读写 
llseek 设置文件中进行读写的当前位置。该函数与vba的seek语句类似。
LockFile 在windows中,文件可用共享模式打开——在这种情况下,多个进程可同时访问该文件。
利用这个函数,要对文件进行读写的一个应用程序可将文件的某一部分锁定起来,使其
不能由其他应用程序访问。这样便避免了同时读写时发生的冲突 
LockFileEx 与LockFile相似,只是它提供了更多的功能 
lopen 以二进制模式打开指定的文件 
lread 将文件中的数据读入内存缓冲区 
lwrite 将数据从内存缓冲区写入一个文件 
MoveFile, MoveFileEx 移动文件。如dwFlags设为零,则MoveFile完全等价于MoveFileEx 
OpenFile 这个函数能执行大量不同的文件操作。和这个函数相比,请优先考虑CreateFile函数
(它能打开命名管道和控制Unicode文件名,同时不受128个字符的路径名称的限制) 
ReadFile 从文件中读出数据。与lread函数相比,这个函数要明显灵活的多。该函数能够操作
通信设备、管道、套接字以及邮槽 
ReadFileEx 与ReadFile相似,只是它只能用于异步读操作,并包含了一个完整的回调 
SearchPath 查找指定文件 
SetEndOfFile 针对一个打开的文件,将当前文件位置设为文件末尾 
SetFileAttributes 设置文件属性 
SetFilePointer 在一个文件中设置当前的读写位置 
SetFileTime 设置文件的创建、访问及上次修改时间 
UnlockFile 解除对一个文件的锁定 
UnlockFileEx 解除对一个文件的锁定 
WriteFile 将数据写入一个文件。该函数比lwrite函数要灵活的多。也可将这个函数应用于对
通信设备、管道、套接字以及邮槽的处理 
WriteFileEx 与WriteFile类似,只是它只能用于异步写操作,并包括了一个完整的回调


文件的压缩和解压缩

LZOpenFile 打开压缩文件以读取
LZSeek 查找压缩文件中的一个位置
LZRead 读一个压缩文件
LZClose 关闭一个压缩文件
LZCopy 复制压缩文件并在处理过程中展开
GetExpandedName 从压缩文件中返回文件名称。


下面通过几个例子来详细的了解一下其中主要的几个函数及其用法:

1、CreateFile

作用:这是一个全功能的例程,可打开和创建文件、管道、邮槽、通信服务、设备以及控制台

声明:
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

说明:
此函数的返回值类型为Long,如执行成功,则返回文件句柄。INVALID_HANDLE_VALUE表示出错,会设置 GetLastError。即使函数成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS

打开一个通信端口时(如COM1),无论如何都要设置成 OPEN_EXISTING。

这个函数代替了lOpen 和 lCreate函数,应该是我们的首选

参数说明:

·lpFileName String,要打开的文件的名字 
·dwDesiredAccess Long,如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息 
·dwShareMode Long,零表示不共享; FILE_SHARE_READ 和/或 FILE_SHARE_WRITE 表示允许对文件进行共享访问 
·lpSecurityAttributes SECURITY_ATTRIBUTES,指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)

·dwCreationDisposition 
Long,下述常数之一: 
CREATE_NEW 创建文件;如文件存在则会出错 
CREATE_ALWAYS 创建文件,会改写前一个文件 
OPEN_EXISTING 文件必须已经存在。由设备提出要求 
OPEN_ALWAYS 如文件不存在则创建它 
TRUNCATE_EXISTING 讲现有文件缩短为零长度

·dwFlagsAndAttributes 
Long,一个或多个下述常数 
FILE_ATTRIBUTE_ARCHIVE 标记归档属性 
FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式 
FILE_ATTRIBUTE_NORMAL 默认属性 
FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录 
FILE_ATTRIBUTE_READONLY 文件为只读 
FILE_ATTRIBUTE_SYSTEM 文件为系统文件 
FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作 
FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作 
FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块 
FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化 
FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化 
FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件 
也可在Windows NT下组合使用下述常数标记: 
SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY

·hTemplateFile Long,如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性

示例如下:

lngHandle = CreateFile("c:\text.txt", GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0)

‘上面代码以写方法打开文件,如文件不存在则创建它。

2、lcreat

作用:创建一个文件。如文件已经存在,就会将其缩短成零长度,并将其打开,以便读写

声明:Declare Function lcreat Lib "kernel32" Alias "_lcreat" (ByVal lpPathName As String, ByVal iAttribute As Long) As Long

说明:此函数的返回值类型为Long,如执行成功,返回打开文件的句柄。如果出错,则返回HFILE_ERROR

该函数会打开已由其他应用程序打开的文件,所以使用它时要小心。win32的CreateFile函数已取代了这个函数。这个函数与vb的open语句作用相同

参数说明:

lpPathName String,欲创建的文件的名字 
iAttribute Long,下述值之一:

0——文件能够读写
1——创建只读文件
2——创建隐藏文件
3——创建系统文件

示例:
下面的语句打开c:\test.txt文件

lcreat “c:\test.txt”,0

3、lopen

作用:以二进制模式打开指定的文件

声明:Declare Function lopen Lib "kernel32" Alias "_lopen" (ByVal lpPathName As String, ByVal iReadWrite As Long) As Long

说明:此函数的返回值类型为Long,如执行成功,返回打开文件的句柄。HFILE_ERROR表示出错。会设置GetLastError

参数说明:

lpPathName String,欲打开文件的名字 
iReadWrite Long,访问模式和共享模式常数的一个组合,如下所示: 
1、访问模式 
READ 打开文件,读取其中的内容 
READ_WRITE 打开文件,对其进行读写 
WRITE 打开文件,在其中写入内容 
2、共享模式(参考OpenFile函数的标志常数表) 
OF_SHARE_COMPAT, OF_SHARE_DENY_NONE, OF_SHARE_DENY_READ, OF_SHARE_DENY_WRITE, OF_SHARE_EXCLUSIVE

示例:
lopen “c:\test.txt”,READ

4、GetFileTime

作用:取得指定文件的时间信息

声明:Declare Function GetFileTime Lib "kernel32" Alias "GetFileTime" (ByVal hFile As Long, lpCreationTime As FILETIME, lpLastAccessTime As FILETIME, lpLastWriteTime As FILETIME) As Long

说明:Long,非零表示成功,零表示失败。会设置GetLastError

如果不需要特定的信息,那么lpCreationTime,lpLastAccessTime,lpLastWriteTime都可以设置为零(用ByVal As Long)。这个函数返回的文件时间采用UTC格式

参数说明:
hFile Long,文件的句柄 
lpCreationTime FILETIME,用于装载文件的创建时间 
lpLastAccessTime FILETIME,用于装载文件上一次访问的时间(FAT文件系统不支持这一特性) 
lpLastWriteTime FILETIME,用于装载文件上一次修改的时间

示例:

Dim file As Long
Dim CreationTime As FileTime
Dim lastaccesstime As FileTime
Dim lastaccesstime As FileTime
‘定义结构
Private Type FileTime
dwLowDateTime As Long
dwHighDateTime As Long
End Type

 str1 = "c:\text.txt"
file = lopen(str1, READ_WRITE) ‘打开文件
temp = GetFileTime(file, CreationTime, lastaccesstime, lastwritetime)’得到文件相关信息

以上代码获取的时间信息是Long型的,还需要时间转换函数进行转换,完整的示例见附件。

5、CopyFile

作用:复制文件。与vb的filecopy命令相似

声明:Declare Function CopyFile Lib "kernel32" Alias "CopyFileA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Long) As Long

说明:Long,非零表示成功,零表示失败。会设置GetLastError

参数说明:

lpExistingFileName String,源文件名 
lpNewFileName String,目标文件名 
bFailIfExists Long,如果设为TRUE(非零),那么一旦目标文件已经存在,则函数调用会失败。否则目标文件被改写


示例:
CopyFile "c:\test1.txt", "c:\test2.txt", 1

以上代码将c:\test1.txt 拷贝到c:\test2.txt,完整的示例见附件。

6、MoveFile, MoveFileEx

作用:移动文件。如dwFlags设为零,则MoveFile完全等价于MoveFileEx

声明:
Declare Function MoveFile Lib "kernel32" Alias "MoveFileA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String)

Declare Function MoveFileEx Lib "kernel32" Alias "MoveFileExA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal dwFlags As Long)

说明:Long,非零表示成功,零表示失败。会设置GetLastError

这两个函数通常不能将文件从一个卷移动到另一个卷。但如设置了MOVEFILE_COPY_ALLOWED标记,MoveFileEx可以做到这一点.

参数说明:

lpExistingFileName String,欲移动的文件名 
lpNewFileName String,新文件名 
dwFlags Long,一个或多个下述常数 
MOVEFILE_REPLACE_EXISTING 如目标文件存在,则将其替换 
MOVEFILE_COPY_ALLOWED 如移动到一个不同的卷,则复制文件并删除原来的文件 
MOVEFILE_DELAY_UNTIL_REBOOT 移动操作在系统下次重新启动时正式进行。这样便可在Windows NT中改换系统文件

示例:
Private Const MOVEFILE_COPY_ALLOWED = &H2
Private Const MOVEFILE_DELAY_UNTIL_REBOOT = &H4
Private Const MOVEFILE_REPLACE_EXISTING = &H1

 MoveFile "c:\test.txt", "d:\test1.txt" ‘移动文件
MoveFileEx "d:\test1.txt", "c:\test.txt", MOVEFILE_COPY_ALLOWED ‘再一次移动

以上代码实现了文件的移动,两次移动後,文件不变

7、DeleteFile

作用:删除指定文件

声明:Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long

说明:Long,非零表示成功,零表示失败。会设置GetLastError

与vba的kill语句相似,在windows 95下使用这个函数要小心——即使文件当前正由一个应用程序打开,该函数也会将其删除.

参数说明:
lpFileName String,欲删除文件的名字

示例:

DeleteFile "c:\test.txt" ‘删除c:\test.txt文件

完整的示例见附件。

8、ReadFile

作用:从文件中读出数据。与lread函数相比,这个函数要明显灵活的多。该函数能够操作通信设备、管道、套接字以及邮槽

声明:Private Declare Function ReadFile Lib "kernel32" Alias "ReadFile" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long

说明:Long,非零表示成功,零表示失败。会设置GetLastError。如启动的是一次异步读操作,则函数会返回零值,并将 ERROR_IO_PENDING设置成GetLastError的结果。如结果不是零值,但读入的字节数小于nNumberOfBytesToRead 参数指定的值,表明早已抵达了文件的结尾

参数:
hFile ---- Long,文件的句柄
lpBuffer --- Any,用于保存读入数据的一个缓冲区
nNumberOfBytesToRead - Long,要读入的字符数
lpNumberOfBytesRead - Long,从文件中实际读入的字符数
lpOverlapped --- OVERLAPPED,如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须用这个参数引用一个特殊的结构。那个结构定义了一次异步读 取操作。否则,应将这个参数设为NULL(将函数声明成ByVal As Long,并传递零值)

示例:完整的示例见附件。

9、WriteFile

作用:将数据写入一个文件。该函数比lwrite函数要灵活的多。也可将这个函数应用于对通信设备、管道、套接字以及邮槽的处理

声明:Declare Function WriteFile Lib "kernel32" Alias "WriteFile" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long

说明:Long,TRUE(非零)表示成功,否则返回零。会设置GetLastError

参数:
hFile --- Long,一个文件的句柄
lpBuffer --- Any,要写入的一个数据缓冲区
nNumberOfBytesToWrite - Long,要写入数据的字节数量。如写入零字节,表示什么都不写入,但会更新文件的“上一次修改时间”。针对位于远程系统的命名管道,限制在65535个字节以内

lpNumberOfBytesWritten - Long,实际写入文件的字节数量

lpOverlapped --- OVERLAPPED,倘若在指定FILE_FLAG_OVERLAPPED的前提下打开文件,这个参数就必须引用一个特殊的结构。那个结构定义了一次异 步写操作。否则,该参数应置为空(将声明变为ByVal As Long,并传递零值)

示例:完整的示例见附件。


10、SHFileOperation

作用:此函数的功能很强大,能对文件或文件夹进行复制、移动、重命名、删除的全部操作。

声明:Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long

说明:Long,TRUE(非零)表示成功,否则返回零。

参数:
lpFileOp --SHFILEOPSTRUCT类型,指定文件的操作。
Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long ‘对文件的操作指令
pFrom As String ‘源文件或路径
pTo As String ‘目的文件或路径
fFlags As Integer ‘操作标志
fAnyOperationsAborted As Long
hNameMappings As Long
lpszProgressTitle As String
End Type

示例:见附件。


(三)总结

通过以上的介绍,我们可以看到API在文件操作方面功能十分强大,能够完成一些前面方法所不能完成的任务。FileSystemObject对象模 型的内部可能就是用API写的,即便不是我们也可以用API写出一个FSO类来。API是一个巨大的宝库,当你为实现某个功能而愁眉不展的时候,查查 API可能就能找到满意的答案。

写的这么多,希望对大家有所帮助,至少操作文件是没有什么问题了。

以上是关于Excel-VBA操作文件的四大方法的主要内容,如果未能解决你的问题,请参考以下文章

Python文件读写中的四大操作

如果未安装插件,Excel-VBA 会显示警告

Android 四大组件之ContentProvider 访问通讯录进行增删改查操作

Python---MySQL数据库之四大操作(增 删 改 查)

Excel-VBA 工作表拆分和保存以逗号分隔的许多空白列结束

Mysql数据库的四大特性