Excel 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:TestingTest.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。
 
注意,如果Type为8,那么必须使用Set语句将结果赋值给Range对象,如下面的代码所示:
 
表1:InputBox方法返回的数据类型
值 类型
0 公式。公式作为字符串被返回。这是仅有的必需的参数。
1 数值。也可以包括返回值的公式。
2 文本(字符串)
4 逻辑值(True或False)
8 单元格引用,作为Range对象
16 错误值,例如#N/A
64 值列表
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 "�", 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 "�BATCH%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将会立即退出。
 
原文://http://blog.sina.com.cn/s/blog_5067ef490100slsy.html
原文地址:https://www.cnblogs.com/dingfangbo/p/5765037.html