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 AddInsMsgBox myAddin.FullNameNextEnd 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) ThenApplication.Sheets(iSheet).PrintOut copies:=1End If
Next iSheet
Application对象相关的属性
在Excel 2007应⽤程序中,有⼤量的属性⽤来访问不同的对象。这⾥,只探讨经常使⽤的属性。
ActiveCellActiveChartActiveSheet
ActiveWindowActiveWorkbookRangeSelectionScreenUpdatingSelectionStatusBar
ThisWorkbookActiveCell属性
Application对象的ActiveCell属性返回Range对象,代表活动⼯作簿的活动⼯作表中的活动单元格。如果没有指定对象限定,那么该属性返回活动窗⼝中的活动单元格。
注意区分活动单元格和单元格选区。活动单元格是当前选区⾥的单个单元格,选区可能包含很多单元格,但仅有⼀个单元格是活动单元格。下⾯的⽰例改变活动单元格的字体格式。注意确保正在处理正确的单元格,Worksheets集合的Activate⽅法使⼯作表Sheet1为活动⼯作表。
Worksheets(\"Sheet1\").ActivateWith ActiveCell.Font.Bold = True.Italic = TrueEnd 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 WithEnd 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\")NextEnd Sub
ActiveWindow属性
ActiveWindow属性返回Window对象,代表活动窗⼝(在顶部的窗⼝)。下⾯的⽰例显⽰活动窗⼝的名称(Caption属性):
MsgBox \"活动窗⼝的名称是\" & ActiveWindow.Caption
Caption属性返回活动窗⼝的名称,允许使⽤名称⽽不是索引号来更清楚地访问该窗⼝。下⾯的⽰例选择并打印⼯作表,然后对第⼆个⼯作表重复这⼀过程:
Sub PrintWorksheet()
Application.ScreenUpdating = FalseSheets(\"Sales\").Select
ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=TrueSheets(\"Expenses\").Select
ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=TrueEnd 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.Worksheetswks.CalculateNext
Set wks = NothingEnd 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\").ActivateSelection.Clear
下⾯的⽰例在变量NumRows中存储所选⾏的总数:
numrows = 0
For Each area In Selection.Areas
numrows = numrows + area.Rows.CountNext area
下⾯的⽰例统计所选区域中单元格的数量,并在消息框中显⽰结果:
Sub Count_Selection()Dim cell As ObjectDim count As Integercount = 0
For Each cell In Selectioncount = count + 1Next cell
MsgBox count & \"项被选择\"End Sub
下⾯的⽰例确保在输⼊数据之前选择的是⼯作表:
Sub EnterDataInWorksheet()
If TypeName(ActiveSheet) <> \"Worksheet\" _Or TypeName(Selection) <> \"Range\" ThenMsgBox \"本程序仅⽤于单元格区域\Exit SubEnd If
Range(\"A1\").Value = 20
End Sub
StatusBar属性
StatusBar属性返回或设置状态栏中的⽂本。该属性允许改变显⽰在Excel窗⼝底部的状态栏中的信息,这特别有助于使⽤户了解需要花时间完成的操作处理的进度。因此,状态栏是⼀种告知⽤户当前程序信息的极好⽅式,并且状态栏不会⼲扰⽤户,也易被开发者利⽤。如果Excel控制状态栏,则StatusBar属性返回False。此外,要恢复缺省的状态栏⽂本,只需设置该属性为False,即使隐藏了状态栏。例如,下⾯的⽰例将现在正在处理的⽂件赋值给状态栏:
Sub test()
Dim FileNum As IntegerFileNum = 0
For Each file In Files
Application.StatusBar = \"现在正在处理⽂件\" & FileNumFileNum = FileNum + 1NextEnd Sub
然后,当程序结束时,使⽤下⾯的语句将状态栏恢复为正常:
Application.StatusBar = False
这是通知Excel并清空状态栏的最简单的⽅式。除⾮重新启动Excel,否则状态栏中会⼀直保持着使⽤Application.StatusBar所显⽰的⽂本,因此应该在合适的地⽅使⽤Application.StatusBar = False语句,尤其是应该考虑发⽣错误时如何恢复状态栏。另外,在使⽤状态栏时,需要选择⼀个合适的更新间隔,使之既不会影响程序性能⼜能为⽤户提供有⽤的信息。可以创建⾃已的过程来使⽤StatusBar属性,以显⽰宏或其它过程的进度:
Sub ShowStatusBarProgress()Dim i As Long
Dim pctDone As DoubleDim numSquares As Long
Const MAXSQR As Long = 15
For i = 1 To 30pctDone = i / 30
numSquares = pctDone * MAXSQR
Application.StatusBar = Application.WorksheetFunction.Rept(Chr(60), numSquares)Application.Wait Now + TimeSerial(0, 0, 1)Next i
Application.StatusBar = FalseEnd Sub
本⽰例随着程序的运⾏逐渐显⽰由常量MAXSQR定义的15个⼩于符号,⼩于符号使⽤ASCⅡ字符60⽣成。本⽰例没有指⽰过程执⾏多长时间,只是显⽰了执⾏的进度。Wait⽅法摸拟宏占⽤的执⾏时间。
要在VBA代码中使⽤状态栏,⾸先确定在⽤户界⾯中是否显⽰了状态栏(因为⽤户极有可能关闭了显⽰状态栏的选项),并且在状态栏使⽤完毕后,应将其恢复到⽤户原先的设置,因此在程序开始前,将状态栏的信息保存到⼀个变量中:
bStatusBarInfo=Application.DisplayStatusBar
然后,将DisplayStatusBar属性设置为True,以确保显⽰状态栏。在程序结束前,将状态栏恢复到原先的设置:
Application.DisplayStatusBar=bStatusBarInfoThisWorkbook属性
ThisWorkbook属性返回Workbook对象,代表当前正运⾏的宏所在的⼯作簿。该属性允许加载项引⽤包含代码的⼯作簿。 ActiveWorkbook属性在该实例中不会⼯作,因为活动⼯作簿可能不是包含加载项代码的⼯作簿。换句话说,ActiveWorkbook属性不会 返回加载项⼯作簿,它返回调⽤加载项的⼯作簿。如果从VB代码创建了⼀个加载项,应该使⽤ThisWorkbook属性限定必须在编译到该加载项的⼯作簿 中运⾏的语句。
下⾯的⽰例关闭包含⽰例代码的⼯作簿,如果修改了该⼯作簿,则不会保存修改。
ThisWorkbook.Close SaveChanges:=False
下⾯的⽰例遍历每个打开的⼯作簿并将其关闭,然后关闭包含该代码的⼯作簿。
Private oExcel As Excel.ApplicationPrivate wbk As Excel.Workbook
Sub CloseOpenWrkBks()Dim wrkb As Workbook
For Each wbk In Application.WorkbooksIf wrkb.Name <> ThisWorkbook.Name Thenwbk.Close TrueEnd IfNext wbk
ThisWorkbook.Close TrueEnd Sub
----------------------------------------Application对象相关的⽅法
下⾯探讨Application对象经常使⽤的⼀些⽅法。FindFile⽅法和Dialogs集合
与GetOpenFilename⽅法不同,FileFind⽅法显⽰“打开”对话框并允许⽤户打开⽂件。如果成功打开⽂件,那么该⽅法返回True;如果⽤户取消了该对话框,那么该⽅法返回False。
下⾯的⽰例显⽰⼀条消息,告诉⽤户打开⼀个指定的⽂件,然后显⽰“打开”对话框。如果⽤户不能够打开该⽂件,则显⽰⼀条消息。
Sub OpenFile1()
Dim bSuccess As Boolean
MsgBox \"请定位到MonthlySales.xls⽂件.\"bSuccess = Application.FindFileIf Not bSuccess Then
MsgBox \"该⽂件没有打开.\"End IfEnd 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 \"打开\" & fileToOpenEnd If
下⾯的⽰例获取多个⼯作簿:
'作者:Steven M. HansenSub TestGetFiles()Dim nIndex As IntegerDim vFiles As Variant
Dim strFileName As String'获取多个Excel⽂件
vFiles = GetExcelFiles(\"测试GetExcelFiles函数\")'确保没有取消对话框.
'如果⽤户取消对话框,函数返回False,⽽不是数组
If Not IsArray(vFiles) ThenMsgBox \"没有选择⽂件.\"Exit SubEnd If
'如果没有取消对话框,则遍历⽂件 For nIndex = 1 To UBound(vFiles)
strFileName = strFileName & vbCrLf & vFiles(nIndex)Next nIndex
'显⽰⽤户所选择的⽂件名称
MsgBox \"⽤户已选择的⽂件如下:\" & vbCrLf & strFileNameEnd Sub
'允许选择多个⽂件
'返回含有⽂件名称的数组
Function GetExcelFiles(sTitle As String) As VariantDim 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 StringDim sName As StringDim sFileName As StringDim sMsg As String
sFileName = Application.GetSaveAsFilenameBreakdownName sFileName, sName, sPathsMsg = \"⽂件名是:\" & sName & vbCrLfsMsg = sMsg & \"⽂件路径是:\" & sPathMsgBox sMsg, vbOKOnlyEnd Sub
Function GetShortName(sLongName As String) As StringDim sPath As String
Dim sShortName As String
BreakdownName sLongName, sShortName, sPathGetShortName = sShortNameEnd 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 IfEnd Sub
'返回提供的完整⽂件名中⽂件名的位置或⾸字符索引值'完整⽂件名包括路径和⽂件名
'例如:FileNamePosition(\"C:\\Testing\\Test.xlsx\")=11
Function FileNamePosition(sFullName As String) As IntegerDim bFound As BooleanDim nPosition As IntegerbFound = False
nPosition = Len(sFullName)Do While bFound = False'确保不是零长度字符串
If nPosition = 0 Then Exit Do'从右开始查找第⼀个\"\\\"
If Mid(sFullName, nPosition, 1) = \"\\\" ThenbFound = TrueElse
'从右⾄左
nPosition = nPosition - 1End IfLoop
If bFound = False ThenFileNamePosition = 0Else
FileNamePosition = nPositionEnd 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/A64 值列表
Set myRange = Application.InputBox(Prompt:=\"⽰例\
如果希望允许输⼊多种数据类型,那么可以使⽤上表中的任意数值组合。例如,如果要显⽰⼀个可以接受⽂本或数值的输⼊框,则可以将type的值设置为3(即 1+2的结果)。如果输⼊了错误类型的数据,则显⽰错误消息并提⽰再次输⼊数据。如果单击“取消”按钮,则返回False。
下⾯的⽰例提⽰⽤户输⼊希望打印活动⼯作表的份数(注意,type指定希望输⼊的是⼀个数值):
Sub PrintActiveSheet()
Dim TotalCopies As Long, NumCopies As LongDim sPrompt As String, sTitle As String
sPrompt = \"您想要多少副本?\"sTitle = \"打印活动⼯作表\"
TotalCopies = Application.InputBox(Prompt:=sPrompt, Title:=sTitle, Default:=1, Type:=1)
For NumCopies = 1 To TotalCopiesActiveSheet.PrintOut
Next NumCopiesEnd Sub
如果将InputBox⽅法的返回值赋给⼀个Variant型变量,则可以检测该值是否为False。如果要返回单元格区域,则使⽤像下⾯的代码会更好:
Sub GetRange()Dim rng As RangeOn Error Resume Next
Set rng = Application.InputBox(Prompt:=\"输⼊单元格区域\If rng Is Nothing ThenMsgBox \"操作取消\"Else
rng.SelectEnd IfEnd 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 WorksheetDim rng As Range
Set wks = Worksheets(\"Sheet2\")Set rng = wks.Range(\"A1:A10\")Application.Run \"MyProc\
'也能够使⽤下⾯的语句完成相同的任务 'Call MyProc(rng)
End Sub
Sub MyProc(rng As Range)With rng.Font.Bold = TrueEnd WithEnd 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 = ApplicationEnd Sub
10、保存并关闭该⼯作簿。
11、现在,测试代码。打开该⼯作簿,将触发Appl_WorkbookOpen事件,显⽰相应的信息框。12、关闭该⼯作簿,将触发Appl_WorkbookBeforeClose事件,显⽰相应的信息框。
13、切换回AppEventClass类模块并单击过程列表显⽰能够⽤于监控应⽤程序⾏为的⼀系列事件。
理解这些事件如何被触发以及事件的顺序对理解应⽤程序是重要的。在类模块中添加其他的事件并插⼊消息框,然后试验不同的⾏为来看看何时触发某特定的事件。----------------------------------使⽤Application对象执⾏其它任务
除了Application对象中最常⽤的对象外,您可能希望在Excel应⽤程序中执⾏⼀些其他任务。下⾯我们就来探讨这⽅⾯的内容。删除⼯作表⽽显⽰提⽰信息(DisplayAlerts属性)
下⾯的⽰例⾸先关闭询问是否保存⼯作表的任何消息,接着删除⼯作表并打开警告消息。Sub DeleteSheet()
Application.DisplayAlerts = FalseActiveSheet.Delete
Application.DisplayAlerts = TrueEnd Sub
上述⽰例代码中使⽤了DisplayAlerts属性,将其值设置为False以⾃动执⾏Excel警告对话框中默认按钮相关的操作。
设置DisplayAlerts属性的意图在于,运⾏宏时不必响应系统出现的警告⽽使执⾏过程中断。当然,在过程结束前,最好将DisplayAlerts属性设置为True。
⽆须提⽰⽤户⽽保存⼯作表(DisplayAlerts属性)下⾯的⽰例保存⼯作表,⽽没有通知⽤户是否保存。
Sub SaveWorksheet()
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs \"C:\\MonthlySales.xls\"Application.DisplayAlerts = TrueEnd Sub
此时,如果现有⽂件与要保存的⽂件名相同,那么会覆盖该⽂件⽽不会弹出任何警告消息。使⽤SendKeys⽅法发送信息到记事本
SendKeys⽅法允许发送按键到当前活动窗⼝,⽤来控制不⽀持任何其他交互形式的应⽤程序,例如DDE(动态数据交换)或OLE。下⾯的⽰例使⽤SendKeys命令从Excel中复制数据区域到记事本,然后保存该⽂件。
Sub SKeys()
Range(\"A1:D15\").Copy '复制单元格区域 SendKeys \"% n\最⼩化Excel
Shell \"notepad.exe\开启记事本 SendKeys \"^V\将数据粘贴到记事本 SendKeys \"�\指定另存为
SendKeys \"SalesData.txt\提供⽂件名 SendKeys \"%S\保存⽂件End Sub
本⽰例⾸先复制数据区域到剪贴板,然后最⼩化Excel,开启记事本,接着从剪贴板复制数据到记事本,最后指定⽂件名并保存⽂件。下⾯的⽰例打开了“记事本”应⽤程序(不⽀持DDE或OLE),并将数据⾏写⼊记事本⽂档:
Sub SKeys()
Dim dReturnValue As Double
dReturnValue = Shell(\"NOTEPAD.EXE\AppActivate dReturnValue
Application.SendKeys \"Copy Data.xlsx c:\\\Application.SendKeys \"~\
Application.SendKeys \"�BATCH%S\End Sub
注意,应该在Excel应⽤程序窗⼝执⾏上述程序。
下⾯的过程清除VBE⽴即窗⼝中的内容。如果在⽴即窗⼝中进⾏过试验或者使⽤Debug.Print语句在⽴即窗⼝输出数据,那么旧的信息将产⽣混乱。该过程将焦点转移到⽴即窗⼝,发送选择该窗⼝中的所有⽂本,然后发送Del键删除⽂本:
Sub ImmediateWindowClear()
Application.VBE.Windows.Item(\"⽴即窗⼝\").SetFocusApplication.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\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 minutesPublic Const cRunWhat = \"The_Sub\"
为开始这个过程,使⽤⼀个名为 StartTimer的⼦程序。代码如下:
Sub StartTimer()
RunWhen = Now + TimeSerial(0, 0, cRunIntervalSeconds)
Application.OnTime earliesttime:=RunWhen, procedure:=cRunWhat, _schedule:=TrueEnd Sub
将⽐当前时间多两分钟的⽇期和时间存放在RunWhen变量中,然后调⽤OnTime⽅法指令Excel何时运⾏cRunWhat过程。“The_Sub”是⼀个字符串变量,Excel将在合适的时间运⾏该过程。下⾯是该过程代码⽰例:
Sub The_Sub()'
'这⾥放置代码 '
StartTimerEnd 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:=FalseEnd 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\").ClearContentsEnd 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 SubApplication.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 LongPublic Declare Function KillTimer Lib \"user32\" ( _
ByVal HWnd As Long, ByVal nIDEvent As Long) As LongPublic TimerID As Long
Public TimerSeconds As SingleSub StartTimer()
TimerSeconds = 1 ' 指定计时器的间隔.
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)End Sub
Sub EndTimer()
On Error Resume NextKillTimer 0&, TimerIDEnd 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
因篇幅问题不能全部显示,请点此查看更多更全内容