C#中 EXCEL的使用(转载资料)
Excel Application对象应用大全
[完美Excel]本文以MSDN中的技术文章《Developers Guide to the Excel 2007 Application Object》为线条,参考了一系列相关技术文章和图书资料,全面整理和总结了Application对象应用知识。
Application对象是Excel对象模型中最高层级的对象,代表Excel应用程序自身,也包含组成工作簿的许多部分,包括工作簿、工作表、单元格集合以及它们包含的数据。
Application对象包含:
- 应用程序设置和选项,许多选项与“选项”对话框中的选项相同。
- 返回顶级对象的方法,例如ActiveCell、ActiveSheet,等等。
本文使用VBA代码示例简要介绍了与Application对象相关的经常使用的对象、方法和属性,其中一些成员能够改变用户与Excel应用程序交互的方式,还能够改变应用程序的外观和式样。熟悉Application对象能够让您扩展和调整Excel的功能,以满足自已的需求。
本文主要介绍的内容如下:
从Application对象中引用对象
Application对象相关的集合
- AddIns集合
- Columns集合和Rows集合
- Dialogs集合
- Sheets集合
Application对象相关的属性
- ActiveCell属性
- ActiveChart属性
- ActiveSheet属性
- ActiveWindow属性
- ActiveWorkbook属性
- RangeSelection属性
- ScreenUpdating属性
- Selection属性
- StatusBar属性
- ThisWorkbook属性
Application对象相关的方法
- FindFile方法和Dialogs集合
- GetOpenFilename方法
- GetSaveAsFilename方法
- InputBox方法
- Run方法
Application对象相关的事件
- 激活Application事件监视
使用Application对象执行其它任务
- 删除工作表而显示提示信息(DisplayAlerts属性)
- 无须提示用户而保存工作表(DisplayAlerts属性)
- 使用SendKeys方法发送信息到记事本
- 安排宏在指定的时间和间隔运行(OnTime方法)
Application对象的其它一些属性和方法
- Caller属性
- CutCopyMode属性
- Evaluate方法
- OnKey方法
- ThisCell属性
- WorksheetFunction属性
- 改变光标显示(Cursor属性)
- 获取或改变Excel窗口的状态或大小(WindowState属性)
- 获取系统信息
- 自动隐藏公式栏(DisplayFormulaBar属性)
- 将Excel全屏显示(DisplayFullScreen属性)
- 获取Excel启动文件夹的路径(StartupPath属性)
- 检测Excel的版本(Version属性)
- 打开最近使用过的文档(RecentFiles属性)
- 文件对话框操作(FileDialog属性)
- 改变Excel工作簿的名称(Caption属性)
- 调用Windows的计算器(ActivateMicrosoftApp方法)
- 暂时停止宏运行(Wait方法)
- 重新计算工作簿(Calculate方法)
- 控制函数重新计算(Volatile方法)
- 获取重叠区域(Intersect方法)
- 获取路径分隔符(PathSeparator属性)
- 快速移至指定位置(Goto方法)
- 关闭Excel(Quit方法)
从Application对象中引用对象
使用Application属性返回Application对象。在引用应用程序之后,要访问Application对象下面的对象,则依次下移对象模型层级。例如,下面的代码设置第一个工作簿的第一个工作表中的第一个单元格的值为20:
Application.Workbooks(1).Worksheets(1).Cells(1, 1) = 20
要引用该单元格,上述代码以Application对象开始,移至第一个工作簿,然后到第一个工作表,最后到达单元格。
下面的示例代码在另一个应用程序中创建一个Excel工作簿,然后打开该工作簿:
Set xl = CreateObject("Excel.Sheet")
xl.Application.Workbooks.Open "newbook.xls"
可以使用许多属性和方法返回最常用的用户界面对象,例如活动工作表(ActiveSheet属性),而无须Application对象限定。例如,下面的代码:
Application.ActiveSheet.Name = "Monthly Sales"
可以替换为:
ActiveSheet.Name = "Monthly Sales"
然而,在使用简短的引用时必须小心,必须已经选择了正确的对象。如果已经使用诸如Worksheet对象的Activate方法选择了合适的工作簿和工作表,那么能够使用下面的代码引用第一个单元格:
Cells(1, 1) = 20
有一些实例必须使用Application限定引用。例如,OnTime方法、应用程序窗口的Width和Height属性。通常,处理Excel窗口外观的属性或者影响应用程序全部行为的属性需要Application限定,例如DisplayFormulaBar属性用于显示或隐藏公式栏。Calculation方法也需要限定。
Application对象相关的集合
本节介绍与Application对象相关的一些集合。
AddIns集合
AddIns集合代表当前在Excel中装载的所有加载项。就像遍历任何其它集合一样,可以列出应用程序中关于加载项的不同类型的信息。下面的示例列出当前在Excel中装载的加载项的路径和名称:
Sub ListAddIns()
Dim myAddin As AddIn
For Each myAddin In AddIns
MsgBox myAddin.FullName
Next
End Sub
Columns集合和Rows集合
这些集合代表当前工作簿中的列和行,可以使用它们分别选择指定的列和行。
Application.Columns(4).Select
上述语句选择D列,就像在工作表中单击该列的标题一样。
Application.Rows(5).Select
上述语句选择第5行,就像在工作表中单击该行的行边一样。
Dialogs集合
Dialogs集合由应用程序中所有的对话框组成。本文后面将详细介绍该集合。
Sheets集合
Sheets对象返回指定工作簿或活动工作簿中所有工作表的集合。Sheets集合包含Chart对象或Worksheet对象。下面的示例打印活动工作簿中所有工作表:
Application.Sheets.PrintOut
下面的示例遍历工作簿中所有的工作表,并打印包含有数据的工作表:
For iSheet = 1 To Application.Sheets.Count
If Not IsEmpty(Application.Sheets(iSheet).UsedRange) Then
Application.Sheets(iSheet).PrintOut copies:=1
End If
Next iSheet
Application对象相关的属性
在Excel 2007应用程序中,有大量的属性用来访问不同的对象。这里,只探讨经常使用的属性。
- ActiveCell
- ActiveChart
- ActiveSheet
- ActiveWindow
- ActiveWorkbook
- RangeSelection
- ScreenUpdating
- Selection
- StatusBar
- ThisWorkbook
ActiveCell属性
Application对象的ActiveCell属性返回Range对象,代表活动工作簿的活动工作表中的活动单元格。如果没有指定对象限定,那么该属性返回活动窗口中的活动单元格。
注意区分活动单元格和单元格选区。活动单元格是当前选区里的单个单元格,选区可能包含很多单元格,但仅有一个单元格是活动单元格。
下面的示例改变活动单元格的字体格式。注意确保正在处理正确的单元格,Worksheets集合的Activate方法使工作表Sheet1为活动工作表。
Worksheets("Sheet1").Activate
With ActiveCell.Font
.Bold = True
.Italic = True
End With
ActiveChart属性
ActiveChart属性返回Chart对象,代表活动图表,无论该图表是嵌入式图表还是图表工作表。当嵌入式图表被选择或者被激活时,该图表是活动图表。下面的示例使用ActiveChart属性在工作表Monthly Sales中添加一个三维柱形图:
Sub AddChart()
Charts.Add
With ActiveChart
.ChartType = xl3DColumn
.SetSourceData Source:=Sheets("Sheet1").Range("B3:H15")
.Location Where:=xlLocationAsObject, Name:="Monthly Sales"
.HasTitle = True
.ChartTitle.Characters.Text = "Monthly Sales by Category"
End With
End Sub
ActiveSheet属性
ActiveSheet属性返回Worksheet对象,代表当前所选择的工作表(在顶部的工作表)。在一个工作簿中仅仅有一个工作表是活动工作表。下面的示例显示活动工作表的名字:
MsgBox "活动工作表的名字是" & ActiveSheet.Name
下面的示例由用户指定复制活动工作表的次数并复制活动工作表,将复制的工作表放置到工作表Sheet1的前面:
Sub CopyActiveSheet()
Dim x As Integer, numtimes As Integer
x = InputBox("请输入复制活动工作表的次数")
For numtimes = 1 To x
'在工作表Sheet1的前面放置工作表副本
ActiveWorkbook.ActiveSheet.Copy _
Before:=ActiveWorkbook.Sheets("Sheet1")
Next
End Sub
ActiveWindow属性
ActiveWindow属性返回Window对象,代表活动窗口(在顶部的窗口)。下面的示例显示活动窗口的名称(Caption属性):
MsgBox "活动窗口的名称是" & ActiveWindow.Caption
Caption属性返回活动窗口的名称,允许使用名称而不是索引号来更清楚地访问该窗口。
下面的示例选择并打印工作表,然后对第二个工作表重复这一过程:
Sub PrintWorksheet()
Application.ScreenUpdating = False
Sheets("Sales").Select
ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True
Sheets("Expenses").Select
ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True
End Sub
在该示例中,您可能奇怪为什么将ScreenUpdating属性设置为False。当Excel执行一系列操作任务时,屏幕被更新并且被刷新许多次,这导致屏幕闪烁。设置ScreenUpdating属性为False消除这些闪烁。此外,因为计算机处理器无须为刷新屏幕而暂停,这能使大的应用程序运行得更快。
ActiveWorkbook属性
ActiveWorkbook属性返回Workbook对象,代表活动窗口中的工作簿。下面的示例显示活动工作簿的名称:
MsgBox "活动工作簿的名称是" & ActiveWorkbook.Name
下面的示例设置计算模式为手动,然后遍历并计算活动工作簿中的每个工作表:
Sub CalcBook()
Dim wks As Worksheet
Application.Calculate = xlManual
For Each wks In ActiveWorkbook.Worksheets
wks.Calculate
Next
Set wks = Nothing
End Sub
RangeSelection属性
RangeSelection属性返回Range对象,代表在指定的窗口的工作表中所选择的单元格,即使是工作表中激活或选择的图形对象。下面的示例显示活动窗口的工作表中所选择的单元格的地址:
MsgBox Application.ActiveWindow.RangeSelection.Address
当选择单元格区域时,RangeSelection属性和Selection对象代表相同的单元格区域。当选择图形时,RangeSelection属性返回以前的单元格选区。关于Selection属性的更多介绍参见下节。
下面的示例显示单元格中头三个字符:
Range("A1").Select
MsgBox Left(ActiveWindow.RangeSelection, 3)
下面的示例显示单元格名称的头三个字符:
Range("A1").Select
MsgBox Left(ActiveWindow.RangeSelection.Name.Name, 3)
命令RangeSelection.Name.Name返回单元格名称。
ScreenUpdating属性
ScreenUpdating属性用于控制屏幕刷新,可将其值设置为True或False。通常,Excel开启了屏幕刷新(即该属性值为True),因此在代码执行时,Excel会随着代码的操作而不断更新屏幕显示,这样在运行处理涉及到多个工作表或单元格中的大量数据的代码(选择或激活对象)时,屏幕会不停闪烁,并且会占用CPU的处理时间,从而降低程序的运行速度。
可以在程序代码的开始部分设置ScreenUpdating属性为False,即Application.ScreenUpdating=False,以关闭屏幕刷新,这样不仅能够使代码运行更快,而且使得界面对用户更为友好。在程序结束前,将该属性设置为True,以恢复Excel对屏幕更新的控制。
然而,在宏运行的过程中,如果需要显示用户窗体或者内置对话框,建议先恢复屏幕刷新,否则拖动用户窗体时,会在屏幕上产生橡皮擦的效果。当然,在显示该对象后,可以重新关闭屏幕刷新。
Selection属性
Selection属性返回活动窗口中所选择的对象。例如,对于单元格,该属性返回Range对象;对于图表,该属性返回Chart对象。如果使用该属性时没有限定引用,则等价于Application.Selection。
下面的示例清除工作表Sheet1中的选区(假设选区是单元格区域):
Worksheets("Sheet1").Activate
Selection.Clear
下面的示例在变量NumRows中存储所选行的总数:
numrows = 0
For Each area In Selection.Areas
numrows = numrows + area.Rows.Count
Next area
下面的示例统计所选区域中单元格的数量,并在消息框中显示结果:
Sub Count_Selection()
Dim cell As Object
Dim count As Integer
count = 0
For Each cell In Selection
count = count + 1
Next cell
MsgBox count & "项被选择"
End Sub
下面的示例确保在输入数据之前选择的是工作表:
Sub EnterDataInWorksheet()
If TypeName(ActiveSheet) <> "Worksheet" _
Or TypeName(Selection) <> "Range" Then
MsgBox "本程序仅用于单元格区域", vbCritical
Exit Sub
End If
Range("A1").Value = 20
End Sub
StatusBar属性
StatusBar属性返回或设置状态栏中的文本。该属性允许改变显示在Excel窗口底部的状态栏中的信息,这特别有助于使用户了解需要花时间完成的操作处理的进度。因此,状态栏是一种告知用户当前程序信息的极好方式,并且状态栏不会干扰用户,也易被开发者利用。
如果Excel控制状态栏,则StatusBar属性返回False。此外,要恢复缺省的状态栏文本,只需设置该属性为False,即使隐藏了状态栏。
例如,下面的示例将现在正在处理的文件赋值给状态栏:
Sub test()
Dim FileNum As Integer
FileNum = 0
For Each file In Files
Application.StatusBar = "现在正在处理文件" & FileNum
FileNum = FileNum + 1
Next
End Sub
然后,当程序结束时,使用下面的语句将状态栏恢复为正常:
Application.StatusBar = False
这是通知Excel并清空状态栏的最简单的方式。除非重新启动Excel,否则状态栏中会一直保持着使用Application.StatusBar所显示的文本,因此应该在合适的地方使用Application.StatusBar = False语句,尤其是应该考虑发生错误时如何恢复状态栏。另外,在使用状态栏时,需要选择一个合适的更新间隔,使之既不会影响程序性能又能为用户提供有用的信息。
可以创建自已的过程来使用StatusBar属性,以显示宏或其它过程的进度:
Sub ShowStatusBarProgress()
Dim i As Long
Dim pctDone As Double
Dim numSquares As Long
Const MAXSQR As Long = 15
For i = 1 To 30
pctDone = i / 30
numSquares = pctDone * MAXSQR
Application.StatusBar = Application.WorksheetFunction.Rept(Chr(60), numSquares)
Application.Wait Now + TimeSerial(0, 0, 1)
Next i
Application.StatusBar = False
End Sub
本示例随着程序的运行逐渐显示由常量MAXSQR定义的15个小于符号,小于符号使用ASCⅡ字符60生成。本示例没有指示过程执行多长时间,只是显示了执行的进度。Wait方法摸拟宏占用的执行时间。
要在VBA代码中使用状态栏,首先确定在用户界面中是否显示了状态栏(因为用户极有可能关闭了显示状态栏的选项),并且在状态栏使用完毕后,应将其恢复到用户原先的设置,因此在程序开始前,将状态栏的信息保存到一个变量中:
bStatusBarInfo=Application.DisplayStatusBar
然后,将DisplayStatusBar属性设置为True,以确保显示状态栏。在程序结束前,将状态栏恢复到原先的设置:
Application.DisplayStatusBar=bStatusBarInfo
ThisWorkbook属性
ThisWorkbook属性返回Workbook对象,代表当前正运行的宏所在的工作簿。该属性允许加载项引用包含代码的工作簿。ActiveWorkbook属性在该实例中不会工作,因为活动工作簿可能不是包含加载项代码的工作簿。换句话说,ActiveWorkbook属性不会返回加载项工作簿,它返回调用加载项的工作簿。如果从VB代码创建了一个加载项,应该使用ThisWorkbook属性限定必须在编译到该加载项的工作簿中运行的语句。
下面的示例关闭包含示例代码的工作簿,如果修改了该工作簿,则不会保存修改。
ThisWorkbook.Close SaveChanges:=False
下面的示例遍历每个打开的工作簿并将其关闭,然后关闭包含该代码的工作簿。
Private oExcel As Excel.Application
Private wbk As Excel.Workbook
Sub CloseOpenWrkBks()
Dim wrkb As Workbook
For Each wbk In Application.Workbooks
If wrkb.Name <> ThisWorkbook.Name Then
wbk.Close True
End If
Next wbk
ThisWorkbook.Close True
End Sub
Application对象相关的方法
下面探讨Application对象经常使用的一些方法。
FindFile方法和Dialogs集合
与GetOpenFilename方法不同,FileFind方法显示“打开”对话框并允许用户打开文件。如果成功打开文件,那么该方法返回True;如果用户取消了该对话框,那么该方法返回False。
下面的示例显示一条消息,告诉用户打开一个指定的文件,然后显示“打开”对话框。如果用户不能够打开该文件,则显示一条消息。
Sub OpenFile1()
Dim bSuccess As Boolean
MsgBox "请定位到MonthlySales.xls文件."
bSuccess = Application.FindFile
If Not bSuccess Then
MsgBox "该文件没有打开."
End If
End Sub
也可以使用Dialogs集合打开特定的对话框来完成相同的操作。使用Dialogs集合的优势之一是使用Show方法,可以传递参数修改内置对话框的缺省行为。例如,xlDialogOpen的参数为:file_text、update_links、read_only、format、prot_pwd、write_res_pwd、ignore_rorec、file_origin、custom_delimit、add_logical、editable、file_access、notify_logical、converter。
注:要找到特定对话框的参数,在Excel帮助的“内置对话框参数列表”中查找相应的对话框常量。
下面的示例显示在文件名框中带有Book1.xlsm的“打开”对话框,允许用户显示缺省文件而不必选择文件。
Sub OpenFile2()
Application.Dialogs(XlBuiltInDialog.xlDialogOpen).Show arg1:="Book1.xlsm"
End Sub
Dialogs集合的优点在于,可以使用它来显示任何的Excel对话框(大约有250个)。通过下述步骤可以找到对话框完整列表。
(查找对话框集合的成员列表)
1、打开VBE。
2、单击“查看——对象浏览器”或者按F2键,显示“对象浏览器”。
3、在搜索框中输入xlDialog。
4、单击“搜索”按钮。
对Excel 2007而言,可以使用CommandBar对象来执行功能区中的命令,例如,下面的语句显示“定位”对话框:
Application.CommandBars.ExecuteMso ("GoTo")
ExecuteMso方法执行由idMso参数标识的控件。idMso参数的取值可以查找网上资源。
下面的语句显示“设置单元格格式”对话框中的“字体”选项卡:
Application.CommandBars.ExecuteMso ("FormatCellsFontDialog")
GetOpenFilename方法
GetOpenFilename方法显示标准的“打开”对话框并从用户处获取文件名称,但不真正打开任何文件,而是以字符串返回用户选择的文件名及其路径。那么,您可以利用该字符串完成所需要的操作,例如可以传递返回的结果到OpenText方法。下面是GetOpenFilename方法的语法(所有参数都是可选的):
GetOpenFilename(FileFilter,FilterIndex,Title,ButtonText,MultiSelect)
参数FileFilter是一个字符串,规定筛选条件(例如,*.txt,*.xla),在“打开”文件对话框中只显示与筛选条件相匹配的文件,默认为“所有文件(*.*),*.*”。参数FilterIndex指定缺省的文件筛选条件的索引值,从1到参数FileFilter中指定的筛选数,默认使用索引值为1的文件筛选条件。参数Title指定对话框的标题,默认显示“打开”。参数ButtonText仅用于Macintosh计算机。参数MultiSelect是一个Boolean值,指定能否选择多个文件,默认仅能够选择单个文件。
下面的示例显示在文件类型中设置为文本文件(*.txt)的“打开”对话框,然后显示带有用户选择的信息的消息框。注意,文件并没有被打开。
Dim fileToOpen As String
fileToOpen = Application.GetOpenFilename("文本文件(*.txt),*.txt")
If fileToOpen <> "" Then
MsgBox "打开" & fileToOpen
End If
下面的示例获取多个工作簿:
'作者:Steven M. Hansen
Sub TestGetFiles()
Dim nIndex As Integer
Dim vFiles As Variant
Dim strFileName As String
'获取多个Excel文件
vFiles = GetExcelFiles("测试GetExcelFiles函数")
'确保没有取消对话框.
'如果用户取消对话框,函数返回False,而不是数组
If Not IsArray(vFiles) Then
MsgBox "没有选择文件."
Exit Sub
End If
'如果没有取消对话框,则遍历文件
For nIndex = 1 To UBound(vFiles)
strFileName = strFileName & vbCrLf & vFiles(nIndex)
Next nIndex
'显示用户所选择的文件名称
MsgBox "用户已选择的文件如下:" & vbCrLf & strFileName
End Sub
'允许选择多个文件
'返回含有文件名称的数组
Function GetExcelFiles(sTitle As String) As Variant
Dim sFilter As String
Dim bMultiSelect As Boolean
sFilter = "Excel工作簿(*.xlsx),*.xlsx"
bMultiSelect = True
GetExcelFiles = Application.GetOpenFilename(FileFilter:=sFilter, _
Title:=sTitle, MultiSelect:=bMultiSelect)
End Function
当将GetOpenFilename方法的参数MultiSelect设置为True时,如果用户选择了文件,那么将返回一个变体类型的数组,且数组索引值基于1而不是0;如果用户取消了选择文件,那么返回False。在TestGetFiles过程的代码中,使用IsArray函数测试返回值是否是数组。如果使用vFiles=False来判断的话,当用户选择了文件时,由于返回的值为数组,则会导致运行时错误:类型不匹配。
GetSaveAsFilename方法
GetSaveAsFilename方法显示“另存为”对话框,允许用户指定一个文件名和需要保存文件的位置,但是实际上并没有保存文件。GetSaveAsFilename方法的语法如下(所有参数都是可选的):
Application.GetSaveAsFilename(InitialFilename,FileFilter,FilterIndex,Title,ButtonText)
参数InitialFilename为指定文件名的字符串,默认为活动工作簿的名称,若不需要指定初始文件名,则将其设置为空字符串(”");参数FileFilter是表示筛选条件的字符串,在“另存为”对话框只显示与筛选条件相匹配的文件,默认为“所有文件(*.*),*.*”;参数FilterIndex用来指定缺省的文件筛选条件的索引值,默认使用索引值为1的文件筛选条件;参数Title指定显示对话框标题的字符串文本,默认显示“另存为”;参数ButtonText仅用于Macintosh计算机。
下面介绍一个综合示例,是Steven M. Hansen编写的,从完整的文件名字符串中分解出文件路径和文件名。
Sub TestBreakdownName()
Dim sPath As String
Dim sName As String
Dim sFileName As String
Dim sMsg As String
sFileName = Application.GetSaveAsFilename
BreakdownName sFileName, sName, sPath
sMsg = "文件名是:" & sName & vbCrLf
sMsg = sMsg & "文件路径是:" & sPath
MsgBox sMsg, vbOKOnly
End Sub
Function GetShortName(sLongName As String) As String
Dim sPath As String
Dim sShortName As String
BreakdownName sLongName, sShortName, sPath
GetShortName = sShortName
End Function
Sub BreakdownName(sFullName As String, _
ByRef sName As String, _
ByRef sPath As String)
Dim nPos As Integer
'找出文件名从哪里开始
nPos = FileNamePosition(sFullName)
If nPos > 0 Then
sName = Right(sFullName, Len(sFullName) - nPos)
sPath = Left(sFullName, nPos - 1)
Else
'无效的文件名
End If
End Sub
'返回提供的完整文件名中文件名的位置或首字符索引值
'完整文件名包括路径和文件名
'例如:FileNamePosition("C:\Testing\Test.xlsx")=11
Function FileNamePosition(sFullName As String) As Integer
Dim bFound As Boolean
Dim nPosition As Integer
bFound = False
nPosition = Len(sFullName)
Do While bFound = False
'确保不是零长度字符串
If nPosition = 0 Then Exit Do
'从右开始查找第一个"\"
If Mid(sFullName, nPosition, 1) = "\" Then
bFound = True
Else
'从右至左
nPosition = nPosition - 1
End If
Loop
If bFound = False Then
FileNamePosition = 0
Else
FileNamePosition = nPosition
End If
End Function
除了运行TestBreakdownName过程获取文件名和文件路径外,还可以使用GetShortName函数仅获取文件名。此外,在Sub过程BreakdownName中使用了ByRef参数,即通过引用传递参数,这样传递给子过程的参数改变后,调用子过程的主过程中相应的参数也随之改变。
InputBox方法
InputBox方法提供了一种程序与用户之间进行简单的交互的方式,允许我们从用户处获得信息。该方法将显示一个对话框,提示用户输入某值。通过指定希望用户输入的数据类型,InputBox方法能够进行数据验证。InputBox方法的语法如下:
InputBox(Prompt,Title,Default,Left,Top,HelpFile,HelpContextID,Type)
其中:参数Prompt是在对话框中显示的消息。这里,可以提示用户您希望用户输入的数据类型。该参数是唯一的必需参数。
参数Title是对话框顶部显示的标题。缺省使用应用程序名称。
参数Default是对话框最初显示时的缺省值。
参数Left和Top用于指定对话框的位置,这些值相对于屏幕的左上角且以磅为单位。如果忽略,则对话框将水平居中且距屏幕顶约1/3处。
参数HelpFile和HelpContextId指定帮助文件,如果使用了这两个参数,那么在对话框中将出现帮助按钮。
参数Type指定需要返回的数据类型。缺省为文本,允许的类型列于表1。
表1:InputBox方法返回的数据类型 |
|
值 |
类型 |
0 |
公式。公式作为字符串被返回。这是仅有的必需的参数。 |
1 |
数值。也可以包括返回值的公式。 |
2 |
文本(字符串) |
4 |
逻辑值(True或False) |
8 |
单元格引用,作为Range对象 |
16 |
错误值,例如#N/A |
64 |
值列表 |
注意,如果Type为8,那么必须使用Set语句将结果赋值给Range对象,如下面的代码所示:
Set myRange = Application.InputBox(Prompt:="示例", Type:=8)
如果希望允许输入多种数据类型,那么可以使用上表中的任意数值组合。例如,如果要显示一个可以接受文本或数值的输入框,则可以将type的值设置为3(即1+2的结果)。如果输入了错误类型的数据,则显示错误消息并提示再次输入数据。如果单击“取消”按钮,则返回False。
下面的示例提示用户输入希望打印活动工作表的份数(注意,type指定希望输入的是一个数值):
Sub PrintActiveSheet()
Dim TotalCopies As Long, NumCopies As Long
Dim sPrompt As String, sTitle As String
sPrompt = "您想要多少副本?"
sTitle = "打印活动工作表"
TotalCopies = Application.InputBox(Prompt:=sPrompt, Title:=sTitle, Default:=1, Type:=1)
For NumCopies = 1 To TotalCopies
ActiveSheet.PrintOut
Next NumCopies
End Sub
如果将InputBox方法的返回值赋给一个Variant型变量,则可以检测该值是否为False。如果要返回单元格区域,则使用像下面的代码会更好:
Sub GetRange()
Dim rng As Range
On Error Resume Next
Set rng = Application.InputBox(Prompt:="输入单元格区域", Type:=8)
If rng Is Nothing Then
MsgBox "操作取消"
Else
rng.Select
End If
End Sub
此时,必须使用Set语句将Range对象赋值给某对象变量,如果用户单击“取消”按钮则返回值False,Set语句将失败并提示运行时错误。使用On Error Resume Next语句避免运行时错误,然后检查是否产生了一个有效的区域。如果用户单击“确定”按钮,那么InputBox方法检查内置类型以确保将返回有效的区域,因此空区域表明单击了“取消”按钮。
Run方法
Run方法执行一个宏或调用一个函数。可以使用该方法运行由VBA或Excel宏语言编写的宏,或者运行动态链接库(DLL)里的函数或Excel加载项(XLL)。XLL是使用任何支持创建DLLs的编译器为Excel创建的加载项。Run方法的语法为:
Run(Macro,Arg1,…,Arg30)
参数Macro是要执行的宏或函数的名称,参数Arg1至Arg30是需要传递给宏或函数的一些参数。
下面的示例使用Run方法调用一个过程,设置单元格区域中单元格的字体为粗体。当然,也可以使用Call方法获得相同的结果。
Sub UseRunMethod()
Dim wks As Worksheet
Dim rng As Range
Set wks = Worksheets("Sheet2")
Set rng = wks.Range("A1:A10")
Application.Run "MyProc", rng
'也能够使用下面的语句完成相同的任务
'Call MyProc(rng)
End Sub
Sub MyProc(rng As Range)
With rng.Font
.Bold = True
End With
End Sub
Application对象相关的事件
Application对象也有一些事件,能够用于监视整个Excel应用程序的行为。要使用Application事件,必须启用事件监视。
激活Application事件监视
1、单击“插入——类模块”,创建一个类。
2、在属性中,将类的名称改为AppEventClass。
3、在类的代码窗口,添加下面的代码:
Public WithEvents Appl As Application
现在,能够在应用程序中运用应用程序级事件。
4、在代码窗口顶部左侧的对象列表中,选择Appl。
5、在代码窗口顶部右侧的过程列表中,选择WorkbookOpen。此时,将为Appl_WorkbookOpen过程插入一对占位符。
6、在过程中添加下面的语句:
Private Sub Appl_WorkbookOpen(ByVal Wb As Workbook)
MsgBox "已打开工作簿."
End Sub
7、重复上面的步骤插入Appl_WorkbookBeforeClose事件,并添加下面的语句:
Private Sub Appl_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
MsgBox "关闭工作簿."
End Sub
8、接下来,创建一个变量用于引用类模块中创建的Application对象。在工程资源管理器中,双击ThisWorkbook打开代码窗口。
9、添加下面的语句。
Dim ApplicationClass As New AppEventClass
通过在ThisWorkbook代码窗口添加下面的语句,创建所声明的对象对Application对象的连接:
Private Sub Workbook_Open()
Set ApplicationClass.Appl = Application
End Sub
10、保存并关闭该工作簿。
11、现在,测试代码。打开该工作簿,将触发Appl_WorkbookOpen事件,显示相应的信息框。
12、关闭该工作簿,将触发Appl_WorkbookBeforeClose事件,显示相应的信息框。
13、切换回AppEventClass类模块并单击过程列表显示能够用于监控应用程序行为的一系列事件。
理解这些事件如何被触发以及事件的顺序对理解应用程序是重要的。在类模块中添加其他的事件并插入消息框,然后试验不同的行为来看看何时触发某特定的事件。
使用Application对象执行其它任务
除了Application对象中最常用的对象外,您可能希望在Excel应用程序中执行一些其他任务。下面我们就来探讨这方面的内容。
删除工作表而显示提示信息(DisplayAlerts属性)
下面的示例首先关闭询问是否保存工作表的任何消息,接着删除工作表并打开警告消息。
Sub DeleteSheet()
Application.DisplayAlerts = False
ActiveSheet.Delete
Application.DisplayAlerts = True
End Sub
上述示例代码中使用了DisplayAlerts属性,将其值设置为False以自动执行Excel警告对话框中默认按钮相关的操作。
设置DisplayAlerts属性的意图在于,运行宏时不必响应系统出现的警告而使执行过程中断。当然,在过程结束前,最好将DisplayAlerts属性设置为True。
无须提示用户而保存工作表(DisplayAlerts属性)
下面的示例保存工作表,而没有通知用户是否保存。
Sub SaveWorksheet()
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs "C:\MonthlySales.xls"
Application.DisplayAlerts = True
End Sub
此时,如果现有文件与要保存的文件名相同,那么会覆盖该文件而不会弹出任何警告消息。
使用SendKeys方法发送信息到记事本
SendKeys方法允许发送按键到当前活动窗口,用来控制不支持任何其他交互形式的应用程序,例如DDE(动态数据交换)或OLE。
下面的示例使用SendKeys命令从Excel中复制数据区域到记事本,然后保存该文件。
Sub SKeys()
Range("A1:D15").Copy '复制单元格区域
SendKeys "% n", True '最小化Excel
Shell "notepad.exe", vbNormalFocus '开启记事本
SendKeys "^V", True '将数据粘贴到记事本
SendKeys "%FA", True '指定另存为
SendKeys "SalesData.txt", True '提供文件名
SendKeys "%S", True '保存文件
End Sub
本示例首先复制数据区域到剪贴板,然后最小化Excel,开启记事本,接着从剪贴板复制数据到记事本,最后指定文件名并保存文件。
下面的示例打开了“记事本”应用程序(不支持DDE或OLE),并将数据行写入记事本文档:
Sub SKeys()
Dim dReturnValue As Double
dReturnValue = Shell("NOTEPAD.EXE", vbNormalFocus)
AppActivate dReturnValue
Application.SendKeys "Copy Data.xlsx c:\", True
Application.SendKeys "~", True
Application.SendKeys "%FABATCH%S", True
End Sub
注意,应该在Excel应用程序窗口执行上述程序。
下面的过程清除VBE立即窗口中的内容。如果在立即窗口中进行过试验或者使用Debug.Print语句在立即窗口输出数据,那么旧的信息将产生混乱。该过程将焦点转移到立即窗口,发送选择该窗口中的所有文本,然后发送Del键删除文本:
Sub ImmediateWindowClear()
Application.VBE.Windows.Item("立即窗口").SetFocus
Application.SendKeys "^a"
Application.SendKeys "{Del}"
End Sub
注意,要使上述代码运行,必需编程访问Visual Basic工程。从Excel功能区中选择“开发工具”选项卡,选择“宏安全性”,然后勾选“信任对VBA工程对象模型的访问”。
其中,百分比符号(%)用于代表Alt键,波形符号(~) 代表回车键,^符号代表Ctrl键。在花括号{}里放置名称指定其它特别的键,例如{Del}代表Delete键。
安排宏在指定的时间和间隔运行(OnTime方法)
可以使用Application对象的OnTime方法在指定的时间或者在有规律的时间间隔运行某过程。OnTime方法的语法如下:
Application.OnTime(EarliestTime,Procedure,LastestTime,Schedule)
参数EarliestTime指明希望何时运行由参数Procedure指定的过程,可选的参数LastestTime和Schedule指明过程运行的最迟时间,以及是否安排运行一个新过程或者删除已经存在的过程。当开始调用某过程而Excel正忙时,则需要使用参数LastestTime指定希望调用该过程的时间区间。如果使用Application对象的Wait方法暂停某宏,所有的Excel行为,包括手工交互操作,都将被挂起。OnTime方法的优势在于,当等待运行安排的宏时,允许返回正常的Excel交互操作,包括运行其他的宏。
下面的示例指定每隔5分钟运行一次名为YourProc的过程:
Application.OnTime EarliestTime:=Now + TimeValue("00:05:00"), Procedure:="YourProc"
下面的示例在每天中午运行过程YourProc:
Application.OnTime EarliestTime:=TimeValue("12:00:00"), Procedure:="YourProc"
下面的示例安排每隔5分钟调用一次AutoSave过程。如果关闭该工作簿,则调用CleanUp过程来执行可能希望的清理以及删除任何额外的调用。
Private Sub Workbook_Open()
Application.OnTime Now + TimeValue("00:05:00"), "AutoSave"
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Application.OnTime Now + TimeValue("00:05:00"), "CleanUp", , False
End Sub
注意,Workbook_Open事件和Workbook_BeforeClose事件包含在工作簿代码模块中,而AutoSave过程和CleanUp过程则存在于标准代码模块中。
当使用OnTime方法安排在将来的某个时间运行宏时,必须确保Excel一直在内存中运行直至到达安排的时间。但不需要一直打开包含OnTime宏的工作簿。如果需要,Excel将打开该工作簿。
通过上述简介,我们已经了解了OnTime方法的基本用法。下面再详细介绍OnTime方法。
有时,我们可能需要设计Excel工作簿定期并自动地运行一个过程。例如,可能希望每隔几分钟从数据源中更新数据,此时执行Excel应用程序的OnTime方法指令Excel在给定的时间去运行某过程。通过编写代码使程序自已调用OnTime方法,能使VBA代码定期自动执行。
OnTime方法要求指定日期和时间以及要运行的过程作为参数,重要的是要记住具体地告诉Excel什么时候运行这个过程而不是从当前时间开始的偏差。为了取消一个未执行的OnTime过程,必须经过该过程计划要运行的确切的时间,不能够告诉Excel取消下一个计划执行的过程。因此,建议将安排过程开始运行的时间存放在一个公共的(或全局)变量中,该变量作用于所有的代码。然后,能够使用所存储时间的变量去安排运行或取消事件。下面的示例代码在公共的常量中存储了所运行过程的名称和重复执行的时间间隔,当然这不是必需的。
Public RunWhen As Double
Public Const cRunIntervalSeconds = 120 ' two minutes
Public Const cRunWhat = "The_Sub"
为开始这个过程,使用一个名为 StartTimer的子程序。代码如下:
Sub StartTimer()
RunWhen = Now + TimeSerial(0, 0, cRunIntervalSeconds)
Application.OnTime earliesttime:=RunWhen, procedure:=cRunWhat, _
schedule:=True
End Sub
将比当前时间多两分钟的日期和时间存放在RunWhen变量中,然后调用OnTime方法指令Excel何时运行cRunWhat过程。
“The_Sub”是一个字符串变量,Excel将在合适的时间运行该过程。下面是该过程代码示例:
Sub The_Sub()
'
'这里放置代码
'
StartTimer
End Sub
注意,The_Sub过程的最后一行调用了StartTimer过程,再次重复运行这个过程。并且当下次使用OnTime调用The_Sub过程时,将再次调用StartTimer来重复执行它自已。这就是如何执行周期循环的方法。
有时,当关闭工作簿时或者满足某个条件时需要停止定时执行的过程。由于OnTime方法是Application对象的一部分,简单地关闭已创建事件的工作簿不会取消对OnTime的调用。一旦Excel自身保持运行,它将执行OnTime过程,并且在必要时会自动打开该工作簿。
为了停止OnTime过程,必须对OnTime方法指定确切的时间,这就是我们将时间作为公共的变量存放在RunWhen中的原因。否则,没办法知道过程计划执行的确切时间。(所计划的时间像OnTime方法中的一把“钥匙”,如果没有它,就没有通往事件的入口)
下面是一个名为StopTimer的子过程,它将停止要执行的OnTime过程。
Sub StopTimer()
On Error Resume Next
Application.OnTime earliesttime:=RunWhen, _
procedure:=cRunWhat, schedule:=False
End Sub
这个过程使用了和StartTimer过程相同的OnTime语法,将schedule参数设置为False告诉Excel取消该过程的执行。可能希望在Auto_Close宏或Workbook_BeforeClose事件中包括一个对该过程的调用。在StopTimer过程中,使用On Error Resume Next语句忽略当你企图删除一个不存在的过程时可能产生的任何错误。
下面的示例演示当在单元格B1中输入一个值后,如果A1单元格中不为空,那么将在10秒后自动清除单元格A1和B1中的内容。示例代码如下:
在标准模块中输入如下代码:
Sub DeleteContents()
Worksheets("Sheet1").Range("A1:B1").ClearContents
End Sub
Sub MyEntry()
Range("B1").Value = "Goodbye"
End Sub
在工作表sheet1代码模块中输入如下代码:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address <> "$B$1" Then Exit Sub
If IsEmpty(Target) Or IsEmpty(Target.Offset(0, -1)) Then Exit Sub
Application.OnTime Now + TimeSerial(0, 0, 10), "DeleteContents"
End Sub
扩展话题一:
在VBA帮助系统的OnTime方法介绍中,只对其参数EarliestTime, Procedure, LatestTime, Schedule进行了说明,并列举了定时运行某过程和撤销OnTime设置的三个代码示例。对OnAction属性的介绍中,也只简要介绍了单击某图形或菜单项时运行指定宏的示例。均没有介绍当OnTime方法或OnAction属性中设置的所要运行的宏带有参数时,如何传递参数到这些宏程序中。下面是自已总结的一些参数的传递方法,供分享。
因为运用Application.OnTime或Object.OnAction调用宏程序的语法基本相似,因此下面介绍的OnTime方法所使用的语法同样适用于OnAction属性。
为了便于理解,以下介绍均使用一段相似的代码,只不过传递给所调用宏程序MyProcedure的参数不同而已,以此来讲解传递给宏程序不同参数的方法。例如,下面的代码将使MyProcedure宏程序在从现在起的2秒后运行:
Application.OnTime Now + TimeValue("00:00:02"), "MyProcedure"
问题1:假设MyProcedure宏程序接受参数,如何传递参数到该宏程序中?有下面几种情形:
(1)所调用的宏程序接受一个参数
如果是在正常代码过程中传递参数给宏程序,可以使用” MyProcedure (42)”,其中“42”为传递给MyProcedure程序的参数。但如果这样的传递参数方法用在OnTime方法中,该程序将不会运行。
正确的语法是外层为双引号,内层再加上一组单引号,里面是程序名和程序所接受的参数。如下所示:
'MyProcedure宏程序接受一个数值参数
Application.OnTime Now + TimeValue("00:00:02"), "' MyProcedure 42'"
(2)所调用的宏程序接受多个参数
如果所调用的宏程序接受几个参数,那么在这些参数之间应该用逗号分隔。如下所示:
'MyProcedure宏程序接受两个数值参数
Application.OnTime Now + TimeValue("00:00:02"), "'MyProcedure 42, 13'"
(3)所调用的宏程序接受字符串参数
如果所调用的宏程序所接受的参数是字符串,因为字符串已经带有一对双引号,因此应该将字符串包含在双层双引号中,即字符串参数周围有两对双引号。如下所示:
'MyProcedure宏程序接受一个字符串Hello!作为其参数
Application.OnTime Now + TimeValue("00:00:02"), "'MyProcedure ""Hello!""'"
问题2:当MyProcedure宏程序所接受的参数是变量,如何传递参数到该宏程序中?
(1)该变量为局部变量,用如下所示的方式。
'MyProcedure宏程序接受一个字符串变量strText参数,该变量为局部变量
strText = "Hello!"
Application.OnTime Now + TimeValue("00:00:02"), "'MyProcedure """ & strText & """'"
(2)该变量为全局变量,用如下所示的方式,即不必加双层双引号。
'MyProcedure宏程序接受一个字符串变量g_strText参数,该变量必须声明为公有的
g_strText = "Hello!"
Application.OnTime Now + TimeValue("00:00:02"), "'MyProcedure g_strText'"
注意,在这种情况下变量必须声明为公共变量,否则MyProcedure宏程序将不能找到该变量参数。
扩展话题二:
除了Excel的OnTime方法外,还能使用Windows API库提供的Timer函数。在某些情况下,使用API过程比使用OnTime方法更容易:第一,告诉Windows需要计时器发生的时间间隔而不是某天的特定时间;第二,API过程将自动更新,计时器将每隔一段时间发生直到你告诉它停下来为止。
这些过程需要在Office2000或更新的版本中运行,因为我们使用了AddressOf函数,他们不会在Excel97或更早的版本中运行。
为了使用Windows计时器,将下面的代码放在一个标准代码模块中。
Public Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, ByVal nIDEvent As Long, _
ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
Public TimerID As Long
Public TimerSeconds As Single
Sub StartTimer()
TimerSeconds = 1 ' 指定计时器的间隔.
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub
Sub EndTimer()
On Error Resume Next
KillTimer 0&, TimerID
End Sub
Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _
ByVal nIDEvent As Long, ByVal dwTimer As Long)
'
'由Windows调用的过程.
' 将与计时器相关的代码放置于此.
'
End Sub
执行StartTimer过程开始计时。变量TimerSeconds指明计时器之间间隔有多少秒。这个值可能少于1。注意SetTimer过程在毫秒范围内取值,于是当我们调用SetTimer时我们通过将TimerSeconds乘以1000来增加间隔值。Windows每隔一段计时器发生的时间来调用TimerProc过程。可以将这个过程命名为想要的名字,但必须如示例中所示声明这些参数变量。如果变换了过程的名称,那么要确保也变换了SetTimer中的名字。Windows将传递下面的值到TimerProc过程:
HWnd Excel应用程序的Windows句柄。一般可忽略这个参数。
uMsg 值为275。一般可忽略这个参数。
nIDEvent 这个值通过SetTimer获得TimerID变量返回。如果不止一次调用SetTimer,那么能检查nIDEvent参数确定哪次调用SetTimer导致调用该过程。
dwTimer 计算机运行的毫秒数。相同的值通过GetTickCount Windows过程被返回。
调用EndTimer过程来停止计时器循环,这个过程调用KillTimer,通过SetTimer返回的值传递给它。
API计时器和Excel的OnTime方法间有两个重要的区别:第一,API计时器有着更精确的时间间隔(达到1秒或更少);第二,即便Excel处在编辑模式(也就是说,当正在编辑单元格时),API计时器也将执行。注意,当Excel处于编辑模式时,如果TImerProc企图修改工作表单元格,Excel将会立即退出。
Application对象的其它一些属性和方法
Caller属性
Application对象的Caller属性返回调用或执行宏过程的对象的引用,适用于窗体工具栏控件、指定宏的绘图对象和用户自定义函数。在确定调用用户自定义函数的单元格时特别有用,例如下面的示例使用自定义函数WorksheetName函数显示调用该函数的工作表的名称。
Function WorksheetName()
Application.Volatile
WorksheetName = Application.Caller.Parent.Name
End Function
在工作表单元格中输入“=WorksheetName()”,将显示该工作表的名称。Application.Caller作为一个Range对象返回对调用该函数的单元格的引用,然后使用Range对象的Parent属性产生对包含该Range对象的Worksheet对象的引用,最后将Worksheet对象的Name属性赋给该函数的返回值。当每次重新计算工作表时,Appliaction对象的Volatile方法强制Excel重新计算该函数。因此,如果改变了工作表的名称,那么该函数将显示新的工作表名称。
在WorksheetName函数中,使用下面的代码是错误的:
WorksheetName = ActiveSheet.Name
如果激活的工作表不是包含该公式的工作表并发生重新计算,则将在原单元格中返回错误的名称。例如,如果在工作表Sheet1中已使用该函数,那么在工作表Sheet2中再次使用该函数时工作表Sheet1中将返回错误的名称,即工作表Sheet2的名称。
CutCopyMode属性
当我们在Excel工作表中使用剪切或复制时,在单元格区域周边会出现连续移动的虚线,即使执行完复制操作,原单元格区域周边的虚线框仍存在,直到您按Esc键或者开始单元格中输入操作。如果需要在执行完复制操作后,不要在Excel中看到复制时产生的虚线框,那么可以将Excel剪切复制模式关闭,即设置CutCopyMode属性为False:
Application.CutCopyMode=False
Evaluate方法
Evaluate方法用于将名称转换为一个对象或者一个值,其语法如下:
Evaluate("表达式")
也可以使用简写格式:
[表达式]
表达式可以是任何有效的工作表计算,在其左边有或者没有等号均可,或者是对单元格区域的引用,包括定义的名称或外部引用,或者是图表对象。工作表计算包含在VBA中不能使用的工作表函数,或者是工作表数组公式。
例如,可以在工作表中使用ISBLANK函数,但不能在VBA中使用该函数,因为VBA的等效函数IsEmpty提供了相同的功能。然而,如果需要,仍然可以使用ISBLANK函数。下面的二个示例是等价的,如果单元格A1为空,则返回 True;如果单元格A1不为空,则返回False。
MsgBox Evaluate("=ISBLANK(A1)")
MsgBox [ISBLANK(A1)]
第一个示例用法的好处是能够非常灵活地使用代码产生字符串值。第二个示例用法更简短,但仅通过编辑代码来修改表达式。下面的过程显示True或者False表明活动单元格是否为空,同时演示了第一个示例用法的灵活性。
Sub IsActiveCellEmpty()
Dim sFunctionName As String, sCellReference As String
sFunctionName = "ISBLANK"
sCellReference = ActiveCell.Address
MsgBox Evaluate(sFunctionName & "(" & sCellReference & ")")
End Sub
注意,使用第二个示例用法不能计算包含变量的表达式。
下面的两行代码演示使用Evaluate方法引用Range对象的两种方式,并且给该对象赋值:
Evaluate("A1").Value = 10
[A1].Value = 10
第一个表达式是不实用的并且极少使用,而第二个表达式虽然极不灵活,却是引用Range对象更简便的方式。通过省略Value属性进一步简化表达式,因为该属性是Range对象的默认属性:
[A1] = 10
总之,使用方括号的优点在于代码简短,而使用Evaluate方法的优点在于参数是字符串,这样即可以在代码中构造该字符串,也可以使用变量。再举一个示例,下面的代码将工作表Sheet1中单元格A1的字体加粗:
Worksheets("Sheet1").Activate
boldCell = "A1"
Application.Evaluate(boldCell).Font.Bold = True
此外,Evaluate方法能够返回工作簿名称集合的内容以及有效地产生数组值。下面的代码创建一个隐藏的名称用来保存密码。在“插入”→“名称”→“定义”对话框中不能看到隐藏的名称,因此这是在工作簿里存储信息的便利方式,不会弄乱用户界面:
Names.Add Name:= "PassWord", RefersTo:= "Bazonkas", Visible:=False
然后,像下面的代码一样在表达式里使用隐藏的数据:
sUserInput = InputBox("Enter Password")
If sUserInput = [PassWord] Then
...
End If
Evaluate方法同样适用于数组。下面的表达式产生一个二维的Variant型数组,100行1列,包含从101 到 200的值。执行该过程比使用For…Next循环更有效率。
vRowArray = [ROW(101:200)]
下面的代码将101至200的值赋给单元格区域B1:B100,同样比For…Next循环更有效率:
[B1:B100] = [ROW(101:200)]
OnKey方法
使用OnKey方法按特定的键或组合键运行指定的过程,也可以禁用内置的组合键。其语法为:
Application.OnKey(Key,Procedure)
参数Key指定要按的键的字符串。参数Procedure指定要运行的过程名称的字符串,如果为空(”"),则按参数Key指定的键时将不发生任何操作;如果省略该参数,则恢复参数Key指定的键在Excel中的正常操作,同时清除先前使用OnKey方法所做的操作设置。
参数Key可以指定任何与Alt、Ctrl或Shift组合使用的键,还可以指定这些键的任何组合。每一个键可以由一个或多个字符表示,比如”a”表示字符a,”{ENTER}”表示Enter(回车)。若要指定按对应的键(例如Enter或Tab)时的非显示字符,可以使用下表2所列出的代码。表2中的每个代码表示键盘上的一个对应键,按键代码放置在花括号{}中。
表2:OnKey方法的按键代码 |
|
按键 |
代码 |
Backspace |
{Backspace}或{BS} |
Break |
{BREAK} |
Caps Lock |
{CAPSLOCK} |
Clear |
{CLEAR} |
Delete或Del |
{DELETE}或{DEL} |
向下箭头 |
{DOWN} |
End |
{END} |
Enter(在数字小键盘中) |
{ENTER} |
Enter |
~(波形符) |
Esc |
{ESCAPE}或{ESC} |
Help |
{HELP} |
Home |
{HOME} |
Ins |
{INSERT} |
向左箭头 |
{LEFT} |
Num Lock |
{NUMLOCK} |
Page Down |
{PGDN} |
Page Up |
{PGUP} |
Return |
{RETURN} |
向右箭头 |
{RIGHT} |
Scroll Lock |
{SCROLLLOCK} |
Tab |
{TAB} |
向上箭头 |
{UP} |
F1到F15 |
{F1}到{F15} |
还可以指定与Shift和/或Ctrl和/或Alt组合使用的键。若要指定与其他键组合使用的键,可使用下表3。
表3:组合按键代码 |
|
要组合的键 |
在按键代码之前添加 |
Shift |
+(加号) |
Ctrl |
^(插入符号) |
Alt |
%(百分号) |
若要为特定字符指定处理过程(如 +、^、% 等等),可以将此字符用花括号括起。
下面的示例为键序列Ctrl+加号分配“InsertProc”过程,并为键序列Shift+Ctrl+向右键分配“SpecialPrintProc”过程。
Application.OnKey "^{+}", "InsertProc"
Application.OnKey "+^{RIGHT}", "SpecialPrintProc"
下面的示例将Shift+Ctrl+向右键恢复正常操作。
Application.OnKey "+^{RIGHT}"
下面的示例将Shift+Ctrl+向右键键序列设为不发生任何操作。
Application.OnKey "+^{RIGHT}", ""
又如,下面的代码忽略Alt+F4组合键的操作:
Application.OnKey "%{F4}",""
即按下Alt+F4组合键后,Excel没有任何反应,不执行任何操作。
注意,OnKey方法使用的按键将应用到所有打开的工作簿,且仅在当前的Excel会话期间起作用。
下面的示例代码禁用工作表右键快捷菜单:
Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, _
ByVal Target As Range, Cancel As Boolean)
Cancel = True
MsgBox "对不起!已禁用右键菜单!"
End Sub
'禁用Shift+{F10}显示快捷菜单
Sub SetupNoShiftF10()
Application.OnKey "+{F10}", "NoShiftF10"
End Sub
'恢复Shift+F10组合键的功能
Sub TurnOffNoShiftF10()
Application.OnKey "+{F10}"
End Sub
Sub NoShiftF10()
MsgBox "对不起!已禁用右键菜单!"
End Sub
ThisCell属性
ThisCell属性返回一个单元格,作为Range对象在此调用用户定义的函数。下面的示例在调用函数时将函数所在单元格的地址通知给用户。
Function UseThisCell()
MsgBox "该单元格的地址为: " & _
Application.ThisCell.Address
End Function
在用户定义的函数中,用户不能访问Range对象上的属性或方法。当完成了重新计算后,用户可以为今后的使用和执行附加操作而存储Range对象。
WorksheetFunction属性
在Excel中可以直接使用两组内置函数,一组函数是VBA语言的组成部分,另一组函数是Excel工作表函数的子集。可以使用Application对象的WorksheetFunction属性来使用VBA中没有相同功能的工作表函数。
通常,如果一个VBA函数与一个Excel函数有着相同的用途,那么该Excel函数就不能直接用于VBA宏(虽然本文前面介绍过可以使用Evalute方法访问任何Excel函数)。但还有一种特殊的情形,关于Excel的Mod函数。Mod函数不能直接用于VBA,但是VBA提供了相同用途的Mod操作符。下面的代码使用Evaluate方法的简洁格式,运用Excel的Mod函数和Today函数以数字显示星期几:
MsgBox [MOD(TODAY(),7)]
使用VBA的Date函数和Mod操作符,更简单地获得相同的结果:
MsgBox Date Mod 7
Excel的Concatenate 函数同样也不能用于VBA,但可以使用连接操作符(&)代替,就像在Excel工作表公式里一样。如果一定要在VBA中使用Concatenate函数,可以编写如下的代码:
Sub ConcatenateExample1()
Dim s1 As String, s2 As String
s1 = "Jack "
s2 = "Smith"
MsgBox Evaluate("CONCATENATE(""" & s1 & """,""" & s2 & """)")
End Sub
但下面的代码更简单且结果相同:
Sub ConcatenateExample2()
Dim s1 As String, s2 As String
s1 = "Jack "
s2 = "Smith"
MsgBox s1 & s2
End Sub
VBA函数,例如Date、DateSerial和IsEmpty能够自由地使用,因为它们是<全局>的成员。例如,可以使用下面的代码:
StartDate = DateSerial(1999, 6, 1)
Excel函数,例如VLookup和SUM是WorksheetFuncion对象的方法,可以使用下面的代码:
Total = WorksheetFunction.Sum(Range("A1:A10"))
为了与Excel 5和Excel 95兼容,可以直接使用Application而无需WorksheetFunction:
Total = Application.Sum(Range("A1:A10"))
在VBE编辑器中,输入下面的代码:
application.WorksheetFunction.
将自动显示出能够在VBA中使用的所有工作表函数列表。
改变光标显示(Cursor属性)
通过Cursor属性来设置光标在Excel界面中的显示形状,可以将其设置为xlIBeam(条状)、xlNorthwestArrow(西北向箭头)、xlWait(等待)、xlDefault(恢复为默认值)。
获取或改变Excel窗口的状态或大小(WindowState属性)
通过WindowState属性来获取或改变Excel窗口的状态,包括xlMaximized(最大化)、xlMinimized(最小化)、xlNormal(正常)。
通过Height属性和Width属性改变或获取Excel主应用程序的高度和宽度。注意,只有当Application.WindowState=xlNormal时,才能改变Height属性和Width属性。
通过UsableHeight属性和UsableWidth属性获取主应用程序窗口中一个窗口可用的最大高度和最大宽度。
获取系统信息
下面的示例程序使用了多个Application对象的属性以获取系统信息:
Sub GetSystemInfo()
MsgBox "Excel版本信息为:" & Application.CalculationVersion
MsgBox "Excel当前允许使用的内存为:" & Application.MemoryFree
MsgBox "Excel当前已经使用的内存为:" & Application.MemoryUsed
MsgBox "Excel可以使用的内存为:" & Application.MemoryTotal
MsgBox "本机操作系统的名称和版本为:" & Application.OperatingSystem
MsgBox "本产品所登记的组织名称为:" & Application.OrganizationName
MsgBox "当前用户名为:" & Application.UserName
MsgBox "当前使用的Excel版本为:" & Application.Version
End Sub
自动隐藏公式栏(DisplayFormulaBar属性)
在Excel 2003及以前版本的Excel中,当单元格中输入的数据超过一定数量时,公式栏会自动向下扩展,从而遮盖住了工作表区域。下面的示例代码当单元格中的字符数小于50时,显示公式栏,否则隐藏公式栏。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.count > 1 Then Exit Sub
If Len(Target.Text) > 50 Or Len(Target.Formula) > 50 Then
Application.DisplayFormulaBar = False
Else
Application.DisplayFormulaBar = True
End If
End Sub
当然,上述代码在Excel 2007中仍然有用,但Excel 2007已经改进了公式栏的特性,即使输入大量的数据,也不会遮盖工作表区域。
将Excel全屏显示(DisplayFullScreen属性)
Sub testFullScreen()
MsgBox "运行后将Excel的显示模式设置为全屏幕"
Application.DisplayFullScreen = True
MsgBox "恢复原来的状态"
Application.DisplayFullScreen = False
End Sub
获取Excel启动文件夹的路径(StartupPath属性)
Sub ExcelStartFolder()
MsgBox "Excel的启动文件夹的路径为:" & Chr(10) & Application.StartupPath
End Sub
检测Excel的版本(Version属性)
Sub CheckVersion()
If Val(Application.Version) < 12 Then
MsgBox "只在Excel 2007或更高版本中有效"
ThisWorkbook.Close
End If
End Sub
Application对象的Version属性返回一个代表当前运行的Excel的版本的字符串,使用Val函数返回该字符串内的数值。该属性通常用于判断当前Excel是否满足程序运行要求。
打开最近使用过的文档(RecentFiles属性)
Sub OpenRecentFiles()
MsgBox "显示最近使用过的第三个文件的名称,并打开该文件"
MsgBox "最近使用过的第三个文件的名称为:" & Application.RecentFiles(3).Name
Application.RecentFiles(3).Open
End Sub
文件对话框操作(FileDialog属性)
Sub UseFileDialogOpen()
Dim lngCount As Long
'开启"打开文件"对话框
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = True
.Show
'显示所选的每个文件的路径
For lngCount = 1 To .SelectedItems.count
MsgBox .SelectedItems(lngCount)
Next lngCount
End With
End Sub
本示例显示“打开文件”对话框,当用户在其中选择一个或多个文件后,将依次显示每个文件的路径。其中FileDialog属性返回打开和保存对话框中一系列对象的集合,可以对该集合对象的属性进行进一步的设置,例如上例中的AllowMultiSelect属性设置为True将允许用户选择多个文件。
改变Excel工作簿的名称(Caption属性)
Sub SetCaption()
Application.Caption = "我的工作簿"
End Sub
将工作簿中的Microsoft Excel列改为“我的工作簿”。
调用Windows的计算器(ActivateMicrosoftApp方法)
Sub CallCalculate()
Application.ActivateMicrosoftApp Index:=0
End Sub
运行上述过程后,将调用Windows的计算器。
暂时停止宏运行(Wait方法)
Sub Stop5sMacroRun()
Dim SetTime As Date
MsgBox "按下「确定」,5秒后执行程序「testFullScreen」"
SetTime = DateAdd("s", 5, Now())
Application.Wait SetTime
Call testFullScreen
End Sub
运行本程序后,按下弹出的提示框中的“确定”按钮,等待5秒后执行另一程序testFullScreen。
重新计算工作簿(Calculate方法)
当工作簿的计算模式被设置为手动模式后,运用Calculate方法可以重新计算所有打开的工作簿、工作簿中特定的工作表或者工作表中指定的单元格区域,如下面的代码:
Sub CalculateAllWorkbook()
Application.Calculate
End Sub
下面的代码先将当前Microsoft Excel的版本与上次计算该工作簿的Excel版本进行比较,如果两个版本不同,则对所有打开工作簿中的数据进行一次完整计算。其中,CalculationVersion属性返回工作簿的版本信息。
Sub CalculateFullSample()
If Application.CalculationVersion <> Workbooks(1).CalculationVersion Then
Application.CalculateFull
End If
End Sub
控制函数重新计算(Volatile方法)
Function NonStaticRand()
'当工作表中任意单元格重新计算时本函数更新
Application.Volatile True
NonStaticRand = Rnd()
End Function
本示例摸仿Excel中的Rand()函数,当工作表单元格发生变化时,都会重新计算该函数。在例子中,使用了Volatile方法,强制函数进行重新计算,即无论何时重新计算工作表,该函数都会重新计算。
获取重叠区域(Intersect方法)
Sub IntersectRange()
Dim rSect As Range
Worksheets("Sheet1").Activate
Set rSect = Application.Intersect(Range("rg1"), Range("rg2"))
If rSect Is Nothing Then
MsgBox "没有交叉区域"
Else
rSect.Select
End If
End Sub
本示例在工作表Sheet1中选定两个命名区域rg1和rg2的重叠区域,如果所选区域不重叠,则显示一条相应的信息。其中,Intersect方法返回一个Range对象,代表两个或多个范围重叠的矩形区域。
获取路径分隔符(PathSeparator属性)
Sub GetPathSeparator()
MsgBox "路径分隔符为" & Application.PathSeparator
End Sub
本示例使用PathSeparator属性返回路径分隔符(”\”)。
快速移至指定位置(Goto方法)
Sub GotoSample()
Application.Goto Reference:=Worksheets("Sheet1").Range("A154"), _
scroll:=True
End Sub
本示例运行后,将当前单元格移至工作表Sheet1中的单元格A154。可以将本技巧运用到工作簿事件中,即当打开某工作簿时,快速定位到上一次退出时的单元格位置。
关闭Excel(Quit方法)
Sub 关闭Excel()
MsgBox "Excel将会关闭"
Application.Quit
End Sub
运行本程序后,若该工作簿未保存,则会弹出对话框询问是否保存。
Excel 对象模型概述
Microsoft.Office.Interop.Excel.Application 对象表示 Excel 应用程序本身。
Microsoft.Office.Interop.Excel.Workbook 对象表示 Excel 应用程序内的单个工作簿。
Microsoft.Office.Interop.Excel.Worksheet 对象是 Worksheets 集合的成员。
Microsoft.Office.Interop.Excel.Range
Application 对象表示整个应用程序,每个 Workbook 对象都包含 Worksheet 对象的一个集合。 因此,表示单元格的主要抽象是 Range 对象,使用该对象可 以处理单个单元格或成组的单元格。
1. 添加 Excel引用:
Using Excel; //using Excel = Microsoft.Office.Interop.Excel;
2. 建立一个新的Excel表格:
Excel.Application xlapp = new Excel.Application();
Xlapp.Application.Workbooks.add(true); //新建一张excel工作簿
Xlapp.Visible=true;
3. 给 Excel单元格中赋值:
Xlapp.cells[1,2]=”第一行,第二列单元格”
4. 打开一个 Excel
Excel.Workbook wbook=xlapp.Workbooks._Open(@"d:\1.xls",Missing.Value,Missing.Value,Missing.Value,Missi
ng.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.
Value,Missing.Value,Missing.Value); //打开一个文件作为工作簿.
5. 新建一个工作簿
Excel.WorkBook wbook = xlapp.WorkBooks.Add(Missing.Value);
6. 新建一个工作表
Excel.Worksheet wsheet = (Excel.Worksheet)wbook.Sheets[1]; //两种赋值方式
Excel.Worksheet wsheet = (Excel.Worksheet)xlapp.ActiveSheet;
7. 添加一个工作表
Worksheet workSheet = (Worksheet)workBook.Worksheets.Add(System.Type.Missing,
System.Type.Missing, System.Type.Missing, System.Type.Missing)
8. 在单元格中写入数值
Excel.Range rng = wsheet.get_Range("C6", "D7"); //设定一片区域的值
rng.Value2 = "Hello!";
rng.Interior.ColorIndex = 6; //设置颜色
9. 读取单元格中的值
Excel.Range rng1 = wsheet.get_Range("c6",Missing.Value); //读取区域的值,并显示
MessageBox.Show(rng1.Value2.ToString());
Excel.Range rng2=(Excel.Range)wsheet.Cells[6,3]; //读取单元格的值,转化为range后赋值并显示
MessageBox.Show(rng2.Value2.ToString());
10. 保存 Excel
wbook.Save();
wbook.SaveAs(@"D:\a.xls", Missing.Value, Missing.Value, Missing.Value, Missing.Value,
Missing.Value,Excel.XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value);
wsheet.SaveAs(@"d:\3.xls", Missing.Value, Missing.Value, Missing.Value, Missing.Value,
Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value);
xBook.Close(true, @"D:\Book1.xlsx", Missing.Value);
11. 关闭 Excel程序
wbook = null; //删除引用
wsheet = null;
xlapp.Quit(); //此步关闭
xlapp = null;
12. 设置单元格格式为文本
range.NumberFormatLocal = "@"; //设置单元格格式为文本
13. 获取多个单元格区域
range = (Range)worksheet.get_Range("A1", "E1");
14. 合并单元格
range.Merge(0);
15. 给单元格赋值
worksheet.Cells[1, 1] = "Excel单元格赋值";
16.设置字体大小
range.Font.Size = 15;
17.设置字体是否有下划线
range.Font.Underline=true;
18.设置字体的种类
range.Font.Name="黑体";
19.设置字体在单元格内的对齐方式
range.HorizontalAlignment=XlHAlign.xlHAlignCenter;
20.设置单元格的宽度
range.ColumnWidth=15;
21.设置单元格的背景色
range.Cells.Interior.Color=System.Drawing.Color.FromArgb(255,204,153).ToArgb();
22.设置单元格边框的粗细,颜色,样式
range.Borders.LineStyle=1;
excelRange.Borders.get_Item(XlBordersIndex.xlEdgeBottom).Weight =
Excel.XlBorderWeight.xlMedium;
excelRange.Borders.get_Item(XlBordersIndex.xlEdgeBottom).ColorIndex =3;
excelRange.Borders.get_Item(XlBordersIndex.xlEdgeTop).LineStyle =
Excel.XlLineStyle.xlContinuous;
23.给单元格加边框
range.BorderAround(XlLineStyle.xlContinuous,XlBorderWeight.xlThick,XlColorIndex.xlColorI
ndexAutomatic,System.Drawing.Color.Black.ToArgb());
24.设置单元格上边框为无边框
range.Borders.get_Item(Microsoft.Office.Interop.Excel.XlBordersIndex.xlEdgeTop).LineStyl
e = Microsoft.Office.Interop.Excel.XlLineStyle.xlLineStyleNone;
25.自动调整列宽
range.EntireColumn.AutoFit();
26.文本水平居中方式
Range.HorizontalAlignment= xlCenter;
27.文本垂直居中方式
Range.VerticalAlignment= xlCenter
28.文本自动换行
Range.WrapText=true;
29.填充颜色为淡紫色
Range.Interior.ColorIndex=39;
30.设置字体颜色
Range.Interior.ColorIndex=39;
31.保存 Excel是,不弹出是否保存的窗口直接进行保存.
xlsApp.DisplayAlerts=false;
32.设置行高
((Excel.Range)wSheet.Rows["1:1", System.Type.Missing]).RowHeight = 100;
//RowHeight "1:1"表示第一行, "1:2"表示,第一行和第二行
33.设置列宽
((Excel.Range)wSheet.Columns["A:B", System.Type.Missing]).ColumnWidth = 10;
//ColumnWidth "A:B"表示第一列和第二列, "A:A"表示第一列
34.常用颜色对照表
public enum ColorIndex
{
无色 = -4142, 自动 = -4105, 黑色 = 1, 褐色 = 53, 橄榄 = 52, 深绿 = 51, 深
青= 49, 深蓝 = 11, 靛蓝 = 55, 灰色80 = 56, 深红 = 9, 橙色= 46, 深黄 = 12, 绿
色= 10, 青色 = 14, 蓝色 = 5, 蓝灰 = 47, 灰色 50 = 16, 红色 = 3, 浅橙色 =
45, 酸橙色= 43, 海绿 = 50, 水绿色 = 42, 浅蓝 = 41, 紫罗兰= 13, 灰色40 =
48, 粉红= 7, 金色 = 44, 黄色 = 6, 鲜绿 = 4, 青绿 = 8, 天蓝 = 33, 梅红 =
54, 灰色 25 = 15, 玫瑰红 = 38, 茶色 = 40, 浅黄 = 36, 浅绿 = 35, 浅青绿=
34, 淡蓝 = 37, 淡紫 = 39, 白色 = 2
}
35. range 的值读取方式:
rng.Value2 = "Hello!";
string str = rng.Value2;
string str2 = rng.Text;