一、Excel事件介紹
Excel事件就是一個能被對象識別的操作。
當某個事件發生后自動運行的過程稱為事件過程。事件過程也是Sub過程。
實踐過程必須寫在特定對象所在的模塊中,而且只有過程所在的模塊里的對象才能觸發這個事件。
事件過程名由Excel自動設置,以“對象名稱_事件名稱”的形式存在,不能更改。
二、Worksheet事件
Worksheet事件是發生在Worksheet對象里的事件。事件過程必須寫在對應的Worksheet對象里,只有過程所在的Worksheet對象里的操作才能觸發該事件。
1、Worksheet_Change事件:自動提示更改的內容
Private Sub Worksheet_Change(ByVal Target As Range) '入參中Target代表被選中的單元格 Application.EnableEvents = False '禁用事件 If Target.Column = 1 Then MsgBox Target.Address & "單元格的值被修改為:" & Target.Value End If Application.EnableEvents = True '啟用事件 End Sub
2、Worksheet_SelectionChange事件:你選中了誰
可以用此事件來記錄Excel單元格修改前的舊值。
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim oldvalue As String MsgBox "當前選中的單元格區域為:" & Target.Address oldvalue = Target.Value If Target.Column <> 1 Then Cells(Target.Row, "A").Select End If End Sub
3、Worksheet_Activate事件:自動提示工作表名
Private Sub Worksheet_Activate() MsgBox "當前活動工作表為:" & ActiveSheet.Name End Sub
4、Worksheet_Deactivate事件:禁止選中其他工作表
Private Sub Worksheet_Deactivate() MsgBox "不允許選中" & ActiveSheet.Name & "工作表外的其他工作表" Worksheets("Sheet1").Select End Sub
5、Worksheet事件列表
Worksheet對象一共有9個事件可供使用。
三、Workbook事件
Workbook事件是發生在Workbook對象里的事件,進入VBE后可以看到ThisWorkbook模塊。這個模塊專門用來保存Workbook對象的事件過程,Workbook對象的事件過程只有保存在這個模板里才能被Excel識別

1、OPen事件
Workbook_Open事件告訴Excel,當打開工作簿時自動運行程序。
Private Sub Workbook_Open() Worksheets(1).Select End Sub
2、BeforeClose事件
每次關閉工作簿都會自動運行程序
Private Sub Workbook_BeforeClose(Cancel As Boolean) '判斷用戶單擊對話框中的哪個按鈕,如果按下的是【否】,則修改參數的值為True If MsgBox("你確定要關閉工作簿嗎?", vbYesNo) = vbNo Then '變量Cancel是程序參數,如果為True,則取消關閉工作簿 Cancel = True '取消關閉 End If End Sub
3、Workbook_SheetChange事件
當工作簿里任意一個單元格被更改時,自動運行程序。
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) '這里入參Sh代表發生更改的單元格所在的工作表,Target表示被更改的單元格 MsgBox "當前更改的工作表為:" & Sh.Name & Chr(13) & _ "發生更改的單元格地址為:" & Target.Address End Sub
4、Workbook事件列表
四、其他事件
1、MouseMove事件
當鼠標指針移動到按鈕上時,按鈕迅速閃開。鼠標和按鈕就像老鷹捉小雞游戲,這樣的效果可以用MouseMove實現。
添加一個按鈕:通過“視圖”——“工具欄”——“控件工具箱”添加,或者通過“開發人員選項”——“插入”——“ActiveX控件”——“命令按鈕”
右鍵按鈕查看代碼(修改按鈕上文字通過Caption屬性修改),編輯按鈕和完成事件邏輯
'MouseMove事件告訴Excel,當鼠標指針在cmd按鈕上移動是自動運行程序 Private Sub CommandButton1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) Dim l As Integer, t As Integer l = Int(Rnd() * 10 + 125) * (Int(Rnd() * 3 + 1) - 2) '生成隨機數 t = Int(Rnd() * 10 + 30) * (Int(Rnd() * 3 + 1) - 2) CommandButton1.Top = CommandButton1.Top + t '重新設置改按鈕的top屬性值 CommandButton1.Left = CommandButton1.Left + l '重新設置改按鈕的left屬性值 End Sub
如果按鈕跑遠了,可以通過另外按鈕Click事件設置參數
Private Sub CommandButton2_Click() CommandButton1.Top = 15 CommandButton1.Left = 160 End Sub

2、不是事件的事件-Application對象的OnKey方法
除了對象的事件,Application對象還有兩種方法,可以像事件一樣讓程序自動運行,分別是OnKey和OnTime
OnKey方法告訴Excel,當在鍵盤上按下指定鍵或組合鍵時自動運行程序。
運行ok過程,返回工作表按下Shift+e組合鍵即可自動運行Test
Sub ok() Application.OnKey "+e", "test" '當按下Shift+e組合鍵時,運行參test過程 End Sub Sub Test() MsgBox "你好,我在學習OnKey方法" End Sub
3、不是事件的事件-Application對象的OnTime方法
OnTime方法告訴Excel,當到指定的時間時自動運行程序(可以是指定的某個時間,也可以是指定的某個時間之后)
Sub ot() '一個小時后,自動運行Test過程 Application.OnTime Now() + TimeValue("01:00:00"), "test" End Sub Sub Test() MsgBox "你好,你已經連續工作一個小時了,請注意休息!" End Sub
無論是OnKey還是OnTime想要讓指定程序自動運行,都必須先運行該方法所在的程序,如果不運行ok或ot過程,指定的Test都不會自動運行。
如果想省去手動執行ok和ot的步驟,可以在ThisWorkbook增加如下事件過程:
Private Sub Workbook_Open() Call ok '運行ok過程 Call ot '運行ot過程 End Sub
五、事件實例
1、一舉多得,快速錄入數據
邏輯說明:
1、通過工作表的Change事件觸發
2、如果C3:C65536為空,或者修改單元格數量大於1,則退出事件
3、讀取“I”列數據,從第3行開始循環,讀取非空數值
4、如果輸入的值等於I列里的值,則進入處理邏輯
5、禁止事件,防止將字母更改為商品名稱時,再次執行程序
6、目標單元格寫入“產品名稱”
7、目標單元格向左移動一格,寫入“銷售日期”
8、目標單元格向右移動一格,寫入“商品代碼”
9、目標單元格向右移動二格,寫入“商品單價”
10、目標單元格向右移動三個,獲取焦點(選中),等待輸入“銷售數量”
11、重啟事件並退出事件
12、循環遞增
Private Sub Worksheet_Change(ByVal Target As Range) '如果更改的單元格不是C列第3行以下的單元格或更改的單元格個數大於1時退出程序 If Application.Intersect(Target, Range("C3:C65536")) Is Nothing Or Target.Count > 1 Then Exit Sub End If Dim i As Integer i = 3 '參照表中第1條記錄在第3行,所以初始值設置為3 Do While Cells(i, "I").Value <> "" If UCase(Target.Value) = Cells(i, "I").Value Then Application.EnableEvents = False '禁用事件,防止將字母改為商品名稱時,再次執行程序 Target.Value = Cells(i, "i").Offset(0, 1).Value '寫入產品名稱 Target.Offset(0, -1).Value = Date '設置銷售日期 Target.Offset(0, 1) = Cells(i, "I").Offset(0, 2).Value '寫入商品代碼 Target.Offset(0, 2) = Cells(i, "I").Offset(0, 3).Value '寫入商品單價 Target.Offset(0, 3).Select '選中銷售數量列,等待輸入銷售數量 Application.EnableEvents = True '重新啟用事件 Exit Sub End If i = i + 1 Loop End Sub
功能:在C列錄入內容對應I列內容時,自動匹配其相關信息,更新銷售日期,並把光標選中F列,等待輸入銷售數量。

2、我該監考哪一場
邏輯說明:
1、使用SelectionChange事件。
2、清除B3:Q22區域內所有單元格底紋顏色。
3、如果同時選中多個單元格,將選中區域內的第一個單元格賦值給Targer。
4、當選中的單元格不在區域B3:Q22時,退出事件。
5、遍歷區域B3:Q22如果有值等於選中的單元格值,則突出顯示。
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Range("B3:Q22").Interior.ColorIndex = xlNone '清除單元格里原有底紋顏色 '當選中的單元格個數大於1時,重新給Target賦值 If Target.Count > 1 Then Set Target = Target.Cells(1) End If '當選中的單元格不包含指定區域的單元格時,退出程序 'Intersect方法返回參數指定的多個單元格的公共區域。參數至少是兩個Range對象 If Application.Intersect(Target, Range("B3:Q22")) Is Nothing Then Exit Sub End If Dim rng As Range For Each rng In Range("B3:Q22") If rng.Value = Target.Value Then rng.Interior.ColorIndex = 39 End If Next End Sub
功能:光標選中單元格時,區域內跟單元格值一樣的都會突出顯示。
邏輯說明:
1、使用SelectionChange事件。
2、清除B3:Q22區域內所有單元格底紋顏色。
3、如果同時選中多個單元格,將選中區域內的第一個單元格賦值給Targer。
4、當選中的單元格不在區域B3:Q22時,退出事件。
5、突出(底紋)標志選中的單元格的行和列
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Range("B3:Q22").Interior.ColorIndex = xlNone '清除單元格里原有底紋顏色 '當選中的單元格個數大於1時,重新給Target賦值 If Target.Count > 1 Then Set Target = Target.Cells(1) End If '當選中的單元格不包含指定區域的單元格時,退出程序 'Intersect方法返回參數指定的多個單元格的公共區域。參數至少是兩個Range對象 If Application.Intersect(Target, Range("B3:Q22")) Is Nothing Then Exit Sub End If ' Dim rng As Range ' For Each rng In Range("B3:Q22") ' If rng.Value = Target.Value Then ' rng.Interior.ColorIndex = 39 ' End If ' Next '添加底紋顏色 Range(Cells(Target.Row, "B"), Cells(Target.Row, "Q")).Interior.ColorIndex = 39 Range(Cells(3, Target.Column), Cells(22, Target.Column)).Interior.ColorIndex = 39 End Sub
功能:
選中單元格時,會自動表示對應的行和列。

3、讓文件每個一分鍾自動保存一次
新增模塊並寫入如下程序
Sub otime() '一分鍾后自動運行WbSave過程 Application.OnTime Now() + TimeValue("00:01:00"), "WbSave" End Sub Sub WbSave() ThisWorkbook.Save '保存本工作簿 Call otime '再次運行otime過程 End Sub
為了在打開工作簿時就運行如上程序,需要增加Workbook事件(在ThisWorkbook中)
Private Sub Workbook_Open() Call otime '打開工作簿后自動運行otime過程 End Sub
六、Interior.ColorIndex說明
使用.Range("").Interior.ColorIndex的方法獲取對應單元格的ColorIndex值,參照下表。
'用代碼就可以獲取顏色列表了 Sub 顏色代碼() For i = 1 To 56 Cells(i, 1) = i Cells(i, 1).Interior.ColorIndex = i Next End Sub

