Office VBA从新手到高手
上QQ阅读APP看书,第一时间看更新

第4章 VBA对象和事件

本章视频教学录像:44分钟

高手指引

对象模型用来描述对象之间的关系,使用VBA在Office环境下开发应用程序,实质就是访问和控制Office各对象的过程,因此使用VBA进行编程时,必须先了解对象模型。本章以Excel环境为例介绍对象模型,帮大家逐步熟悉和了解VBA的对象、属性和方法,同时介绍一些常用的对象及其使用方法。此外还将介绍事件的概念和作用,以及事件的编写和使用。

重点导读

VBA的对象、属性和方法

VBA的常用对象

VBA对象的使用

VBA事件的使用

4.1 VBA的对象、属性和方法

本节视频教学录像:4分钟

VBA是一门特殊的程序语言,它既拥有VB的强大功能,也拥有Office强大的办公数据处理能力。在使用VBA进行程序设计之前,需要掌握常用概念和术语,例如对象、方法、属性等,通过对这些术语和概念的了解,在进行程序编写时,可以更为方便、直接地调用相应的功能。

4.1.1 什么是对象

客观世界是由各种各样的对象组成,每种对象都有各自内部状况和运动规律,对象之间通过一定渠道相互联系,构成各种不同的系统。在现实生活中,每个实体都是对象,例如电视机等,每个对象又有它的属性和方法,例如电视机有颜色、外形等属性,此外电视还有改变音量、切换频道等操作,电视的属性值表示了电视机所处的状态,而状态只能通过对电视机属性的操作来改变。

Office软件中包含有非常多的对象,以Excel为例,它包含有上百种统一通过不同方式操作的对象,例如Excel窗口、工作薄、工作表和单元格等都是对象。在Excel中,对象是指一组属性及这组属性上的专用操作的封装体。所有的VBA对象都是通过层次组织起来的,一些对象可能包含其他对象。例如,Excel是一个Application对象,该对象包含其他对象,如工作薄对象,工作薄对象又包含其他对象,诸如工作表对象或图表对象。

每个对象都有它的属性值,属性值表示对象的状态,对象的属性只能通过该对象所提供的操作来存取和修改。操作也称为方法或服务,它规定了对象的行为,表示对象所提供的服务,一个对象通常由对象名、属性和操作3部分组成。

4.1.2 对象的属性

属性定义了对象的特征,诸如大小、颜色或屏幕位置等;或者某一方面的行为,诸如对象激活或者可见,可以通过修改对象的属性值来改变对象的特征。

1. 设置属性值

在代码中设置属性的语法格式为:

        Object.property=expression

其中,object是对象名,property是对象的某个属性。

例如,下面的过程可以设置窗体中的caption属性来更改窗体的标题:

        Sub change(newTitle)
        myForm.caption=newTitle
        end sub

另外也可以在VBE环境下使用“属性”窗口进行。选择菜单【视图】➣【属性窗口】命令。

在弹出的属性窗口中即可设置不同对象的不同属性,如下图所示,首先在【对象名】下拉列表中选择指定对象,然后在属性列表中选择要设置的属性,在属性值列中设置具体值。

2. 读取属性值

可以通过属性的返回值来查看对象的信息,读取属性的语法为:

       Variable=object.property

下面这个例题读取当前活动窗口的标题,并用消息框显示。

       Sub getName()
       Dim wName as String
       wName=ActiveWindow.caption
       MsgBox wName
       End sub

4.1.3 对象的方法

方法是对象能执行的动作,对象可以使用不同的方法。例如,区域(Range)对象有清除单元格内容ClearContents方法;清除格式的ClearFormats方法;以及同时清除内容和格式的Clear方法等。在调用方法的时候,使用点操作符引用对象,如果有参数,在方法后加上参数值,参数之间用空格隔开。在代码中使用方法的格式如下。

        Object.method

例如下面程序使用add方法添加一个新工作簿或者工作表。

        Sub addsheet()
        ActiveWorkbook.Sheets.Add
        End sub

下面的代码选中工作表Sheet1中“A1单元格”,然后再清除其中内容。

        Sheet1.range("A1").Select
        Sheet1.range("A1").clear

上一章介绍过VBA的变量和数组的知识,变量和数组除了能够保存简单的数据类型外,还可以保存和引用对象。与普通变量类似,使用对象变量也要声明和赋值。

对象变量的声明如下。

和普通变量的定义类似,对象变量也使用Dim语句或其他的声明语句(Public、Private或Static)来声明对象变量,引用的对象变量必须是Variant、Object或是一个对象的指定类型。例如:

        Dim MyObject
        Dim MyObject AS Object
        Dim MyObject As Font

其中第一句“Dim MyObject”声明MyObject为Variant数据类型,此时因为没有声明数据类型,则默认是Variant数据类型;第二句“Dim MyObject AS Object”声明MyObject为Object数据类型,第三句“Dim MyObject As Font”声明MyObject为Font类型。

给对象变量赋值如下。

与普通变量赋值不同,对象变量赋值必须使用Set语句,其语法为:

        Set对象变量=数值或者对象

除了可以赋值一般数值外,还可以把一个集合对象赋值给另一个对象。

例如:

        Set Mycell=WorkSheets(1).Range("C1")

把工作表中C1单元格中的内容赋值给对象变量Mycell。

下面语句同时使用New关键字和Set语句来声明对象变量。

        Dim MyCollection As Collection
        Set MyCollection = New Collection

4.2 VBA的常用对象

本节视频教学录像:10分钟

VBA中有很多对象,这些对象模型在实际编程中使用非常广。这些对象模型之间相互联系,对象模型是通过层次结构有逻辑地组织在一起的,一个对象可以是其他对象的容器,可以包含其他对象,而且这些对象又可以是其他对象的对象。下图是Excel对象中的层次结构图。

其中位于顶层的是Application对象,它包含Excel的其他对象。

尽管Excel的对象模型有数百个,在使用Excel时,有些对象可能会经常用到,而另外一些对象则不常用。本节以Excel为例,给出几个常用的对象模型,这些模型对Excel程序的一些设置、工作簿和工作表的操作、单元格和单元格区域的操作,是经常涉及的。可通过熟悉其相应的属性、方法等内容,来加深对Excel对象模型的认识和理解。

4.2.1 Application对象

Office中所有组件程序都可以使用Application对象,它指应用程序环境,例如Excel环境、Word环境等。在Application中包含众多属性设置,程序通过这些属性值改变Excel环境。下面是常用的几个属性设置。

● Application.Caption: 设置Excel主窗口标题栏。

● Application.DisplayFormulaBar: 如果属性值为True,则显示编辑栏。

● Application. DisplayScrollBars:如果属性值为True,则滚动条在所有工作簿中显示。

● Application.StatusBar: 如果属性值为True,则显示状态栏;通过该属性,还可以设置状态栏上的文字。

● Application.ScreenUpdating: 如果属性值为True,则启用屏幕更新。

● Application.WindowState:查询Excel窗口的状态,也可以设置状态,有3个属性值:xlMaximized(最大化窗口)、xlMinimized(最小化窗口)、xlNormal(正常)。

● Application.UserName:返回或设置当前用户的名称。

● Application.WorkSheetFunction:返回WorkSheetFunction对象,在其中包含了大量的计算公式。

● Application.Dialogs:返回一个Dialogs集合,该集合表示所有内置对话框。

● Application.ActivePrinter:返回或设置活动打印机的名称。

例如:

        Application.Caption="我的程序"

表示把Excel程序主标题栏中显示的名称设置为“我的程序”。

        Application.StatusBar="程序正在运行"

表示在Excel程序的状态栏显示文字“程序正在运行”。

【实例4-1】 计算工作表中单元格A1:A5区域中的最小值。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

        Sub test()
        Dim myrange As Range
        Dim result As Double
        Set myrange =
        Worksheets("sheet1").
        Range("A1:A5")
        result = Application.
        WorksheetFunction.Min(myrange)
        MsgBox result
        End Sub

其中01行定义myrange为Range对象类型,在03行为该对象类型赋值为工作表中的单元格A1:A5区域,06行为使用WorkSheetFunction对象中的VBA内置函数计算单元格区域中的最小值,06行将结果显示出来。

3 按快捷键【F5】,运行结果如下图所示。

在Application中也包括了大量的方法,常使用的方法如下所述。

● Application.FindFile:显示【打开】对话框。

● Application.SaveWorkSpace:保存当前工作区。

● Application.GetOpenFileName:显示标准的【打开】对话框,并获取用户文件名,而不必真正打开任何文件。

【实例4-2】显示【打开文件】对话框。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

        Sub test()
        file = Application.
        GetOpenFilename("Text Files(*.txt),
    *.txt")
        If file <> False Then
        MsgBox "open" & file
        End If
        End Sub

其中02行使用Application.GetOpe-nFileName来显示标准的【打开】对话框,当用户选择文件后,所选文件名存放到file中,然后在04行中显示。

3 按快捷键【F5】,运行结果如图所示。

● Application.Wait:暂停运行宏,直到指定的时间才继续运行。

● Application.OnTime:安排一个过程在将来的特定时间运行。

例如:

       Application.OnTime
       TimeValue("08:00:00"), "Test2"

表示在8点整运行过程“Test2”。

4 然后在【文件打开】对话框中选取需要打开的文件,选择完后,单击【打开】按钮,弹出下面对话框。

4.2.2 Workbook对象

Workbook代表一个Excel工作簿,通过Workbook可以对Excel文件进行创建、打开、保存、关闭和删除等操作。

1. Workbook对象声明

在进行操作时,必须指定工作簿,即在VBA中声明一个Workbook对象,经常使用的有如下3个对象。

Workbook对象:表示当前打开的所有Excel文档,可以通过工作簿索引号或工作簿名称访问指定工作簿。例如:当前打开3个工作簿文件,其中第2个文件名为test. xls,可使用下面语句得到第2个文件:

       Workbooks(2).activate
       Workbooks("test.xls").activate

● ActiveWorkbook对象:表示当前处于活动状态的工作簿。

例如保存当前工作簿代码为:

        ActiveWorkbook.Save

● ThisWorkbook对象:表示对包含该语句的工作簿有效。

例如:当前打开3个工作簿,在第一个工作簿中写入代码块,激活第二个工作簿,并关闭当前写有代码的第一个工作簿。

        Workbooks(2).activate
        ThisWorkbook.close

2. 工作簿创建

那么如何创建一个工作簿呢?这需要使用Workbooks集合中Add方法。其语法格式为:

        Workbooks.Add参数/模板参数

其中参数是现有Excel文件名的字符串。

其中模板参数指定工作簿中包含的工作类型,有4个取值,如下所示。

● xlWBATWorkSheet:表示采用只包含一个工作表的工作簿模板。

● xlWBATChart:表示创建工作簿中包含一个图表。

● xlWBATExcel4MarcoSheet:表示创建工作簿中包含一个Excel4的宏表。

● xlWBATExcel4IntMarcoSheet:表示创建一个包含Excel4的国际性宏表。

3.工作簿打开

打开工作簿的语法格式为:

       Workbooks.Open参数

其中参数是要打开的文件名称的字符串。此外,还可以定义以何种方式打开指定的文件,可以通过系统的帮助来了解。

4.工作簿保存

保存工作簿的语法格式为:

       ThisWorkbook.save

如果将文件另存为一个新的文件,或者是首次保存一个新建的工作簿,语法格式为:

       ThisWorkbook.saveAs参数

其中参数指定文件保存的路径和文件名。

5. 关闭工作簿

其语法格式为:

       Workbooks.Close

表示关闭所有的工作簿。

如果关闭特定的工作簿,其格式为:

       Workbooks("工作簿名称").Close

6.设置工作簿密码

其语法格式为:

       Workbooks.Password= 密码

使用该属性可以获取或设置密码。

       Workbooks.add "d:\newfile.xls"

创建一个新的工作簿“d:\newfile. xls”。

Workbooks.Open “d:\newfile.xls”

表示打开文件“d:\newfile.xls”。

4.2.3 Worksheet对象

Worksheet对象代表一个工作表,通过Worksheet对象,可以在程序中完成各种针对工作表的操作,例如设置单元格格式、为单元格赋值、插入工作表等,多个Worksheet对象组成Worksheets集合。

1. 工作表的引用

和工作簿一样,因为工作簿中一般有多个工作表,因此使用工作表时要指定,可以通过索引号或者名称来指定,例如:

        Worksheet(1)
       Worksheet.Item(1)
       Worksheet("sheet1")

都是访问工作表1。在程序中还可以直接使用工作表名称,例如:

       Sheet1.range("A1:A3")

表示第一张工作表中A1到A3单元格。

        Worksheet的属性

常用的属性如下所述。

Name:返回或者设置一个String值,表示对象的名称。

Range:返回一个Range对象,代表一个单元格或者单元格区域。

Cells:返回一个Range对象,代表工作表中的所有单元格。

PageSetup:返回一个PageSetup对象,它包含用于指定对象的所有页面设置。

Visible:返回或设置一个xlSheetVisibility值,表示对象是否可见。

2.新建工作表

其基本语法格式为:

        Worksheets.add(Before,After,
        Count,Type)

其中各参数含义如下。

Before:新建的工作表置于当前工作表之前。

After:新建的工作表置于当前工作表之后。

Count: 新建的工作表数,默认为1。

Type: 新建工作表类型,共有4种类型,和工作簿的选项一样。

例如:

        Worksheets.add before:
        =Worksheet(1)

表示在第一个工作表之前插入一个工作表。如果不指定before或者after,默认插入到活动工作表前。

        Worksheets.add count:=2

表示同时插入两个工作表。

也可以在新建的同时为工作表命名。

例如:

        Worksheets.add.name="学生信息表"

或者先新建工作表,然后再命名。

        Worksheets.add
        Activesheet.name="学生信息表"

因为新建的工作表默认是活动工作表。

3.复制工作表

使用copy的方法可以复制工作表,其基本语法格式为:

        Worksheet.Copy (before,after)

其中参数before、after不能同时使用,它们分别表示把要复制的工作表放到被复制工作表之前或者之后。例如:

        Worksheets("sheet1").Copy
         after:=Worksheets("Sheet2")

表示复制工作表1,并把其放置到工作表2之后。

下面这个实例给出了这个过程,同时把新生成的工作表命名为“学生信息表”。

【实例4-3】 工作表复制。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

        Sub test()
        ThisWorkbook.
        orksheets ("sheet1").Copy
        after:=Worksheets("Sheet2")
        ActiveSheet.Name = "学生信息表"
        End sub

3 过程执行前如下图所示。

4 按快捷键【F5】,运行结果如图所示。

4. 工作表的删除

其基本语法格式为:

        Worksheet.Delete

例如:

       Worksheets("sheet1").delete

实现删除sheet1工作表。

5. 移动工作表

其基本语法格式为:

       Worksheet.Copy (before,after)

其中参数before、after与复制工作表含义一样。例如:

       Worksheets("sheet2").Move
       before:= Worksheets("sheet1")

把工作表sheet2移动到工作表sheet1之前。

4.2.4 Range对象

Range对象代表工作表中的单元格或者单元格区域,包含在Worksheet对象中。在操作Excel任何区域之前,都需要将其定义为一个Range对象,然后使用Range对象的方法和属性对其进行操作。

1. Range对象的引用

其基本语法为:

        Range("名称")

其中名称可以是一个单元格,也可以是一个连续或者不连续单元格区域。例如:

        Worksheets("sheet1").
        Range("A1")

表示单元格A1。

        Worksheets("sheet1").
        Range("A1:C3")

表示单元格A1到C3区域。

        Worksheets("sheet1").
        Range("A1:C3,D4:E5")

表示单元格A1到C3区域,D4到E5区域。

如果单元格被定义了名称,也可以使用名称引用。例如:

       Dim n as String
       n="A1:C2"
       Worksheets("sheet1").Range(n)=3

把单元格A1到C3区域命名为n,然后使用n来访问该区域。

在后面第7章还会详细介绍。

2. Offset属性

该属性返回一个Range对象,表示指定单元格区域具有一定偏移量位置上的区域。其语法格式为:

       Offset(Rowoffset,Columnoffset)

其中Rowoffset,Columnoffset分别表示行偏移量和列偏移量。例如:

       Range("A1").offset(3,4)

表示从单元格A1开始,向下移动3行,再向右移动4列的单元格。

4.2.5 Comment对象

Comment是批注的意思,对单元格做解释或者说明,而且批注并不影响单元格内的数值,也不参与或影响运算。在Excel中,一个批注就是一个Comment对象。

下面给出了如何给单元格添加批注的语法:

        Range("范围").addComment
        Text:="批注内容"

例如:

        Range("A1").addcomment
        text:="这是一个批注"

为单元格A1添加一个批注,内容是“这是一个批注”,其简单实现过程如下。

【实例4-4】添加批注。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

        Sub test()
        Range("A1").AddComment
        Text:="这是一个批注"
        End Sub

3 按快捷键【F5】,运行结果如图所示。

提示

如果某个单元格中已经存在批注,再次添加时会提示错误。

此外,下面语句可以查看Excel工作表中批注的数量。

       Worksheets("sheet").Comments.
        Count

下面语句给出了删除批注的语句。

       Worksheets("sheet").
        Range("A1").delete

下面语句给出了隐藏批注的方法。

       Worksheets("sheet").
        Range("A1").Visible=True

4.3 VBA对象的使用

本节视频教学录像:7分钟

上一节以Excel为例,介绍了一些常用的VBA对象。这一节我们通过一些实例,熟悉这些对象模型在编程中的使用。

4.3.1 创建一个工作簿

下面通过一个实例,详细介绍如何创建一个新的工作簿,并保存到指定位置。

【实例4-5】创建工作簿。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

        Sub test()
        Dim WB As Workbook
        Dim Sht As Worksheet
        Set WB = Workbooks.Add
        Set Sht = WB.Worksheets(1)
        Sht.Name = "学生名册"
       Sht.Range("A1:F1") =
        Array("学号”, "姓名", “性别",
        "出生年月", "入学时间", "是否团员")
       WB.SaveAs "c:\学生花名册
        .xls"
       ActiveWorkbook.Close
       End Sub

代码中在02,03行首先分别定义一个Workbook对象和WorkSheet对象,在04行创建一个工作簿Wb,05行指定工作表,然后分别在06到07行为工作表标签命名,并在单元格“A1:F1”设置表头。最后08行保存新建的工作簿到所指定的位置,并命名文件名,09行关闭新建的工作簿。

其中08行如果修改为:

        WB.SaveAs ThisWorkbook.Path &
    "\学生花名册.xls"

则将文件保存到工作簿所在的文件夹中。

3 按快捷键【F5】,可以在C盘上找到文件学生花名册.xls,打开该文件,如下图所示。

4.3.2 判断工作簿是否存在

上一小节通过实例演示了工作簿、工作表的创建以及单元格内容的定义,并且介绍了文件的保存,在实际使用的时候,由于电脑上已经存在的文件很多,经常需要查询是否存在某个文件,然后进行具体操作,下面这个实例介绍了如何判断工作簿是否存在。

【实例4-6】 判断工作簿是否存在。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

        Sub test()
        Dim file As String
        file = "c:\学生花名册.xlsx"
        If Len(Dir(file)) > 0 Then
        MsgBox "工作簿已经存在"
        Else
        MsgBox "工作簿不存在"
        End If
        End Sub

其中,03行输入要判断的工作薄的文件名(注意要写上文件夹的名字),04行到08行使用一个条件语句来判断,其中调试是利用Dir函数来判断file所指定的文件是否存在,如果存在,Dir函数返回文件名,否则返回空字符串,并使用Len函数判断其长度。当然也可以把03行改为如下形式,例如:

       file = ThisWorkbook.Path & "\学
        生花名册.xlsx"

表示判断的文件位于工作簿所在的文件夹。

3 按快捷键【F5】,程序运行结果如下图所示。

4.3.3 批量新建工作表

如下图所示,在这张表中有若干个院系的学生。

现在需要把不同系的学生单独放到一个工作表中,如下图所示。

我们看一下如何实现这个功能。

【实例4-7】 数据分类到不同工作表。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

该部分代码主要分为两个部分:创建工作表和把数据分到所创建的工作表中。

⑴ 创建工作表

        Set sht = Worksheets("sheet1")
        Do While sht.Cells(i, "C").
    Value <> “”
        On Error Resume Next
        If Worksheets(sht.Cells(i, "C").
    Value) Is Nothing Then
       Worksheets.Add
        after:=Worksheets(Worksheets.Count)
       ActiveSheet.Name = sht.
        Cells(i,"C").Value
       sht.Range("A1:D1").Copy
        Worksheets(sht.Cells(i, "C").
        Value).Range("A1:D1")
       End If
       i = i + 1
       Loop

其中04语句用于判断新建班级工作表时候存在,05语句用于在最后的工作表后插入新建工作表,07语句用于把原表的第一行标题复制到所有新建表中。

⑵ 把数据分到不同工作表中

       i = 2
       bj= Worksheets("sheet1").
        Cells(i, "C").ValueDo While bj<> ""
       Set rng = Worksheets(bj).
        Range("A65536").End(xlUp).
        Offset(1, 0)
       Worksheets("sheet1").
        Rows(i).Copy rng
       i = i + 1
       bj= Worksheets("sheet1").
        Cells(i, "C").Value
       Loop

其中04语句中“Range(“A65536”). End(xlUp)”是代表A列最后一个非空单元格,“Offset(1, 0)”表示非空行的下一行。05语句用于记录复制。

3 按快捷键【F5】,运行程序,实现本节开始要求的效果图。

4.3.4 快速合并多表数据

这一个实例同上一小节的实例恰好相反,是把一个工作簿中若干个表的内容合并成一个新工作表。

【实例4-8】 合并多表数据。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

该部分代码主要分为两个部分:创建工作表和把数据分到所创建的工作表中。

⑴ 新建工作表

        01 Worksheets.Add
    after:=Worksheets(Worksheets.Count)
        02  ActiveSheet.Name = "汇总表"
        03  Worksheets(1).
    Range(“A1:D1”).Copy Worksheets(“汇
    总表”).Range("A1:D1")

其中01语句实现新建工作表,02语句把新建工作表命名为“汇总表”,03语句把原表的第一行标题复制到所建新表中。

⑵ 把数据汇总到新建工作表中

        01  For Each sht In Worksheets
        02  If sht.Name <> ActiveSheet.
    Name Then
        03    Set rng = Range("A65536").
    End(xlUp).Offset(1, 0)
        04    xrow = sht.Range("A1").
    CurrentRegion.Rows.Count -1
        sht.Range("A2"     ).
    Resize(xrow,7).Copy rng
        05 End If
       06 Next

其中01语句遍历所有工作表,02语句通过判断语句除去新建的“汇总表”,其他的工作表内容都要复制,03语句获得新建表的第一个非空单元格,04语句获得各个工作表的记录条数,05语句实现复制记录到新建表。

3 按快捷键【F5】,运行程序,运行前的效果图如下所示。

运行后的效果图如下所示。

4.4 VBA的事件

本节视频教学录像:3分钟

事件是一个对象可以识别的工作,例如单击鼠标、打开文件等,而且可以编写代码响应事件。用户的动作或者程序代码的结果都可能导致事件的产生,事件还可以由系统触发。

4.4.1 事件与行为

在VBA中,事件可以定义为激发对象的操作,例如在Excel中常见的有打开工作簿、切换工作表、选择单元格、单击鼠标等。

而行为可以定义为针对事件所编写的操作过程。针对某个事件发生所编写的过程称为事件过程,也叫Sub过程。事件过程必须写在特定对象所在的模块中,而且只有过程所在的模块中的对象才能触发这个事件。

下面给出几种Excel中常见的事件。

1. 工作簿事件

当特定的工作簿打开(Open)、关闭之前(BeforeClose)或者激活任何一张工作表(SheetActivate)都是工作簿事件。工作簿事件的代码必须在ThisWork对象代码模块中编写。

2. 工作表事件

当特定的工作表激活(Activate)、更改单元格内容(Change)、选定区域发生改变(SelectionChange)等都是工作表事件,工作表事件的代码必须写在对应工作表的代码模块中。

3. 窗体和控件事件

窗体打开或者窗体上的控件也可响应很多事件,例如单击(Click)、鼠标移动(MouseMove)等,这些事件的代码必须编写在相应的用户窗体代码模块中。

4. 不与对象关联的事件

还有两类事件不与任何对象关联,分别是OnTime和OnKey,分别表示时间和用户按键这类事件。

4.4.2 事件过程的编写

如果要对某个事件进行响应,就要编写对应该事件的代码程序,即事件过程,或者行为程序,并把这些程序放到系统规定的位置,此外还要注意,每个事件处理程序的名称要使用系统事先定好的名称,即事件过程的过程名系统自动设置,不能更改。下面给出事件过程编写的步骤(以激活工作表Sheet1为事件作为例子)。

1 打开VBE编辑环境。

2 在左侧的“工程资源管理器”窗口中双击“Sheet1(Sheet1)”对象,将在右侧“代码窗口”中出现代码编辑器。如下图所示。

3 在代码窗口中左侧对象下拉列表框中选择对象,如图所示。

4 然后在右侧下拉列表框中选择事件,如图所示。

5 选择好对象和事件后,系统中自动生成事件过程的名称及结构,此时,就可以在其中编写所需要的行为程序代码。

4.5 VBA常用的事件

本节视频教学录像:8分钟

下面以Excel为例,介绍其中常用的几种事件,让读者加深对事件的使用。

4.5.1 Workbook事件

Workbook事件发生在Workbook对象中,当发生工作簿打开、工作簿中任何工作表更改、激活工作簿等情况,都触发工作簿事件,执行实现编写的行为代码。

编写Workbook事件在上一节介绍的步骤step2中左侧的“工程资源管理器”窗口中双击“ThisWorkbook”对象,其余步骤完全一样。

下面介绍几个常见的Workbook事件。

1. Open事件

表示打开工作簿时将产生的事件,下面看一个实例。

【实例4-9】 工作簿打开事件。

1 打开VBE编辑环境。

2 在左侧的“工程资源管理器”窗口中双击“ThisWorkbook”对象,将在右侧“代码窗口”中出现代码编辑器。

3 在代码窗口中左侧对象下拉列表框中选择“Workbook”对象,如图所示。

4 然后在右侧下拉列表框中选择“Open”事件,如图所示。

5 选择好对象和事件后,系统中自动生成事件过程的名称及结构,此时,就可以在其中编写所需要的行为程序代码。本例书写的代码实现的功能是打开工作簿时,显示欢迎信息。代码如下:

       Private Sub Workbook Open()
       MsgBox "欢迎你使用VBA"
       End Sub

6 保存程序,关闭工作簿。然后重新打开它,可以看到下图效果。

2. BeforeClose事件

在关闭工作簿之前,产生这个事件,若果工作簿已经修改,则询问用户是否保存。

3. Activate事件

激活一个工作簿时发生这个事件。一般包括以下两种情况。

工作簿打开时,在Open事件之后产生该事件。

从另一个工作簿切换到这个工作簿发生该事件。

4. Deactivate事件

当工作簿从活动状态转为非活动状态时产生这个事件,一般包括以下两种情况。

工作簿从活动状态转为非活动状态。

关闭工作簿时,在BeforeClose事件之后发生这个事件。

4.5.2 Worksheet事件

Worksheet事件发生在Worksheet对象中,控制用户在工作表中的操作。下面是常用的Worksheet事件。

1. Change事件

当工作表的单元格发生更改时触发的事件。下面给出一个自动执行的过程。

【实例4-10】 单元格变化自动提示更改内容。

1 重复4.4.2节 14步。

2 然后在右侧下拉列表框中选择事件,如图所示。

3 选择好对象和事件后,系统中自动生成事件过程的名称及结构,此时,就可以在其中编写所需要的行为程序代码,如下所示。

        Private Sub Worksheet
    Change(ByVal Target As Range)
        MsgBox "单元格" & Target.
    Address & "的内容被更改为:" &
    Target.Value
        End Sub

4 返回工作表,在任何单元格改变内容,回车确认即可以看到程序运行结果。

2. SelectionChange事件

当工作表中选定的单元格发生改变时触发这个事件,通过该事件可以为新选定的单元格进行设置。例如选定某一个单元格时,将该单元格底色设为暗灰色。可在上面步骤step5中设置程序如下所示。

       Private Sub Worksheet
        SelectionChange(ByVal Target As
        Range)
       Target.Interior.ColorIndex = 15
       End Sub

3. Activate事件

当激活某个工作表时触发这个事件,例如下面程序。

       Private Sub Worksheet Activate()
       MsgBox "目前活动工作表是:" &
        ActiveSheet.Name
       End Sub

当在其他工作表切换到“sheet1”的时候,就会激活这个事件,程序效果图如下所示。

4.5.3 窗体和控件事件

这一类事件非常多,诸如窗体打开或者窗体上的控件也可响应很多事件,例如单击(Click)、鼠标移动(MouseMove)等,我们将在下一章介绍窗体的时候再讲述这类事件。

4.5.4 OnTime和OnKey事件

前面几种事件都是与具体对象相关联的,此外,有两种特殊的事件:OnTime和OnKey。这两种事件不与具体的对象关联,但可以通过使用Application对象对应的方法来响应事件。

1. OnTime事件

使用Application的OnTime方法可以安排一个过程在将来的特定时间运行(既可以是具体指定的某个时间,也可以是指定的一段时间之后)。其语法格式如下:

        Applicaton.OnTime(EarliestTime,
    Procedure, LatestTime, Schedule)

其中各参数含义如下所述。

⑴ EarliestTime:表示希望此过程运行的时间,是必选项。

⑵ Procedure:表示要运行的过程名,是必选项。

⑶ LatestTime:表示过程开始运行的最晚时间,是可选项。例如,如果LatestTime参数设置为EarliestTime + 30,且当到达EarliestTime时间时,由于其他过程处于运行状态而导致Microsoft Excel不能处于“就绪”、“复制”、“剪切”或“查找”模式,则Microsoft Excel将等待30秒让第一个过程先完成。如果Microsoft Excel不能在30秒内回到“就绪”模式,则不运行此过程。如果省略该参数,Microsoft Excel将一直等待到可以运行该过程为止。

⑷ Schedule:如果为True,则预定一个新的OnTime过程。如果为False,则清除先前设置的过程。默认值为True。是可选项。

提示

使用Now + TimeValue(time) 可安排经过一段时间(从现在开始计时)之后运行某个过程。使用TimeValue(time) 可安排某个过程只运行指定的时间。

【实例4-11】 定时提醒。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

       Sub test()
       Application.OnTime Now() +
        TimeValue("00:00:30"), "hint"
       End Sub
       Sub hint()
       MsgBox "您好!学习VBA很
        有乐趣吧!”
       End Sub

这个实例包含两个过程,其中过程test中就定义了OnTime事件,Now()函数返回当前系统事件,TimeValue("00:00:30”)表示30秒的事件,即在从现在开始30秒后,运行进程hint。在hint进程中使用输出函数显示一句话“您好!学习VBA很有乐趣吧!”

3 按快捷键【F5】,运行程序,30秒后,自动运行进程hint,效果图如下。

2. OnKey事件

是指按下键盘某个键所触发的事件,使用Application对象的OnKey方法可以设置OnKey事件,其基本语法格式为:

Application.OnKey(Key,Procedure)

其中参数Key表示要按下的键的字符串,参数Procedure表示要运行的过程名字的字符串。

Key参数可指定任何与Alt、Ctrl或Shift组合使用的键,还可以指定这些键的任何组合。每一个键可由一个或多个字符表示,比如 "a"表示字符a,"{ENTER}"表示Enter。

若要指定按对应的键(例如,Enter或选项卡)时不显示的字符,请使用下表中列出的代码。表中的每个代码表示键盘上的一个键。

另外,还可以指定键加Shift键、 Ctrl键或Alt键。若要指定键与其他键组合,请使用下表。

提示

要组合的键必须在其他键代码之间。

例如:

       Application.OnKey "^{+}", "test1"
        Application.OnKey "+^{RIGHT}",
        "test2"
       Application.OnKey "a", "teste"

第一句表示为按键序列 “Ctrl+加号”分配"test1"过程;并为按键序列“Shift+Ctrl+向右键”分配"test2"过程;按键“a”分配”test3”进程。当用户按下对应键的时候,VBA将调用对应进程。

【实例4-12】 按键触发提示信息。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

       Sub test1()
       Application.OnKey "^a",
        "test2"
       End Sub
       Sub test2()
       MsgBox "VBA是不是很简单
        易学啊!"
       End Sub

这段代码包含两个进程,进程“test1”定义一个OnKey事件,当按下组合键“Ctrl”和“A”的时候,运行进程“test2”,在运行进程“test2”中显示"VBA是不是很简单易学啊!"输出框。

3 按快捷键【F5】,运行程序,返回工作表区域,按【Ctrl+A】组合键可以运行进程“test2”,如图所示。

4.6 VBA事件的应用

本节视频教学录像:6分钟

前面介绍了事件及行为的概念和基本用法,下面再通过一些基本实例加深对事件使用的认识。

4.6.1 数据的快速录入

假设你现在开一个小型超市,要记录每一笔销售记录,如下图所示。

每次卖出一种商品的时候,都要添加一条记录,例如卖一瓶啤酒,就要写上“啤酒”,“yl-004”、“2.6”、“2014/7/12”、“1”等信息,实际上这些信息许多都可以省略,让系统自动快速录入,自己只需写出商品和数量即可,而且商品也不需要写出完整的商品名,只需写出其快捷代码即可。可以实现为商品把这些基本信息写入Excel表,如图所示。

可以在卖啤酒的时候,输入“pj”即可自动将啤酒的相关信息填入。下面给出具体实现步骤。

初始Excel界面如图所示。

【实例4-13】 快速录入数据。

基本操作步骤和4.4.2节所述步骤几乎一样,只是在step4后选择不一样,如下所示。

然后在右侧下拉列表框中选择事件,如图所示。

选择好对象和事件后,系统中自动生成事件过程的名称及结构,此时,就可以在其中编写所需要的行为程序代码,如下所示。

       Private Sub Worksheet
        Change(ByVal Target As Range)
       If Application.Intersect
        (Target, Range("B2:B65536")) Is
        Nothing Or Target.Count > 1 Then
        Exit Sub
        End If
        Dim i As Integer
        06    i = 3
        07    Do While Cells(i, "I").
    Value <> ""
        08    If UCase(Target.Value) =
    Cells(i, "I").Value Then
        09       Application.
    EnableEvents = False
        10       Target.Value = Cells(i,
    "I").Offset(0, 1).Value
        11       If Target.Offset(-1, -1).
    Value >= 1 Then
        12          Target.Offset(0, -1).
    Value = Target.Offset(-1, -1).Value + 1
        13       End If
        14       Target.Offset(0, 1).Value
    = Cells(i, "I").Offset(0, 2).Value
        Target.Offset(0, 2).Value
    = Cells(i, "I").Offset(0, 3).Value
        Target.Offset(0, 3).Value
    = Date
        17       Target.Offset(0, 4).Select
        18       Application.
    EnableEvents = True
        19       Exit Sub
        20     End If
       21     i = i + 1
       22     Loop
       23     MsgBox "没有这种商品,
        请重新输入!"
       End Sub

其中02~04语句规定必须在B单元格列输入数据,并且更改的单元格数量不大于1;然后在07~22循环中判断录入字符代码是否和实现录入的商品参照表中快捷代码内容一样,如果不一样,则显示“没有这种商品,请重新输入!”如果存在,则将对应信息放到销售商品的响应位置,然后光标停在数量单元格内,等待输入数量。

返回工作表,在商品名称中输入对应代码,回车确认即可以看到程序运行结果,如图所示。

4.6.2 数据的自动保存

在使用Excel的时候,系统每隔一定时间自动保存,那么就不用担心机器断电等情况下所写文件丢失的情况。这个例子的实现很简单,也是使用Application的OnTime事件。

【实例4-14】 数据自动保存。

基本操作如下。

1 打开VBE编辑环境。

2 创建模块,在模块中输入以下代码。

       Sub test()
       Application.OnTime Now()
    + TimeValue("00:01:00"),"save
    test"
        End Sub
        Sub save test()
        ThisWorkbook.Save
        Call test
        End Sub

在这部分中有两个模块,在主模块test中,定义OnTime事件,每隔1分钟调用“saver test”过程,而“saver test”过程保存本工作簿,不过这样还不行,还要再加入过程,让打开工作簿后自动运行所定义的过程test。程序代码是在“ThisWorkbook”模块中加入,如下图所示。

3 保存修改,关闭并且重新打开工作簿,这样你在使用过程中不用操心是否保存,系统每隔1分钟自动保存。

4.7 综合实战—Excel数据范围判断

本节视频教学录像:4分钟

在使用Excel录入数据的时候,经常遇到一些情况,单元格里的内容要求输入有一定范围,例如性别要求是“男”或者“女”,年龄要在0和100之间,等等。现在我们通过一个综合实例看一下如何实现。

在这个实例中,使用了Worksheet对象的Change事件对单元格中录入的数据进行检验,然后使用循环语句依次对不同列进行检验。下面给出具体实现步骤。

基本操作步骤和4.4.2节所述步骤几乎一样,只是在step4后选择不一样,如下所示。

然后在右侧下拉列表框中选择事件,如图所示。

选择好对象和事件后,系统中自动生成事件过程的名称及结构,此时,就可以在其中编写所需要的行为程序代码,如下所示。

        Private Sub Worksheet
        Change(ByVal Target As Range)
       Select Case Target.Column
       Case 3
       If Target <>"男" And Target <>
        "女" Then
       MsgBox "性别输入错误,请重新输
        入 ", vbOKOnly, "注意"
       Target.Select
       End If
       Case 4
       If Target < 0 Or Target >
       100 Then
       MsgBox "请注意年龄是否输入正确",
        vbOKOnly, "注意"
       Target.Select
       End If
       End Select
       End Sub

其中02行判断检查工作表中所操作单元格的列,然后根据所操作的列数值执行“select case”中的Case语句后的代码。例如当操作3列的时候,判断输入的内容是否为“男”或者“女”,如果不是,则提示"性别输入错误,请重新输入",然后让用户重新输入。

返回工作表,当在“性别”单元格所在列输入内容时,如果输入的性别不是“男”或者“女”,回车确认即可以错误提示,如图所示。

同样当年龄输入不符合要求的时候,也会出现错误提示,读者可以自己验证。