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。
注意,如果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