VBA
即Visual Basic For Appilication
,属于VB语言的的子集。
无论打开多少EXCEL表格,都会共享一个IDE环境。
每一个Excel文件,对应的VBA工程都有4类对象,包括: Microsoft Excel对象、窗体、模块和类模块。
Microsoft Excel对象 Microsoft Excel对象代表了Excel文件及其包括的工作薄等几个对象,包括所有的 Sheet和一个Workbook,分别表示文件(工作薄)中所有的工作表(包括图表),例如缺省情况下,Excel文件包括3个Sheet,在资源管理器窗口就包括3个 Sheet,名字分别是各Sheet的名字。
ThisWorkbook 代表当前Excel文件。双击这些对象会打开代码窗口,在此窗口中可输入相关的代码,响应工作薄或者文件的一些事件,例如文件的打开、关闭,工作薄的激活、内容修改、选择等有关事件。
窗体 窗体对象代表了自定义对话框或界面。
模块 模块为自定义代码的载体。作用:1.保存过程和函数 2.定义模块内的私有变量或者整个工程的公有变量。
类模块 类模块则是以类或对象的方式编写代码的载体。
插入一个模块,写上如下代码。
Sub MyFirstVBAProgram()
Dim strName As String
Dim strHello As String
strName = InputBox("请输入你的名字:")
strHello = "你好," & strName & " !"
MsgBox strHello
End Sub
----------------
解释:下面我们简单看一下这段代码的组成,代码第1行表示这是一个新的过程,名称为“MyFirstVBAProgram",第2、3行定义了2个变量,其类型为字符串类型,第4行调用InputBox这个内置函数,并将返回值赋给strName这个变量,第5行将几个字符串组合成一个新的字符串,第6行调用MsgBox这个函数,显示一个对话框,第7行表示过程结束。VBA程序由不同的模块组成,在模块内部,可以定义不同的变量、过程或函数,由此组成一个完整的程序。
与其他程序设计语言不同,VBA程序是事件驱动的,没有Main函数之类的入口的概念。本质上,VBA代码应该只是一些完成具体工作的集合,而通过界面元素或者Excel的事件驱动执行,你可以通过自定义按钮、菜单,并指定一个宏(VBA过程,自定义界面也可以通过编程手段完成此类工作),通过单击此按钮即可调用相应的VBA代码。
过程是最基本的运行单位,格式如下:
Sub Test()
...
End Sub
------------
[ Private | Public][Static ] Sub name [ (arglist) ]
[ statements]
[Exit sub]
[ statements]
End sub
部分 | 描述 |
---|---|
Public | 可选的。表示所有模块的所有其它过程都可访问这个Sub过程。如果在包含Option Private的模块中使用,则这个过程在该工程外是不可使用的。 |
Private | 可选的。表示只有在包含其声明的模块中的其它过程可以访问该Sub过程。 |
Static | 可选的。表示在调用之间保留Sub过程的局部变量的值。Static属性对在Sub 外声明的变量不会产生影响,即使过程中也使用了这些变量。 |
name | 必需的。Sub 的名称;遵循标准的变量命名约定。 |
arglist | 可选的。代表在调用时要传递给Sub 过程的参数的变量列表。多个变量则用逗号隔开。 |
statements | 可选的。Sub过程中所执行的任何语句组。 |
从其它过程调用一个过程(Sub)时,必须键入过程名称以及任何需要的参数值。Call语句可有可无,如果使用它,则参数必须以括号括起来。
[ Public | Private] [static] Function name [ (arglist) ] [As type]
[ statements]
[ name = expression]
[Exit Function]
[ statements]
[name = expression]
End Function
下面的示例展示了调用具有多个参数的Sub 过程的两种不同方法。当第二次调用HouseCalc
时,因为使用Call语句(第3行),所以需要利用括号将参数括起来。
sub Main ()
HouseCalc 99800,43100
Call HouseCalc (380950,49500)
End sub
sub HouseCalc (price As single, wage As single)
if 2.5 * wage <= 0.8 * price Then
MsgBox "You cannot afford this house. "
Else
MsgBox "This house is affordable. "
End If
End Sub
Answer3 = MsgBox ("Are you happy?",4, "Question 3")
MsgBox "Task Completed! ", 0,"Task Box"
如果不在意函数的返回值,可以用调用Sub 过程的方式来调用函数。如下面示例所示,可以省略括号,列出参数并且不要将函数指定给变量:
定义变量可以使用Dim语句
Dim 变量名 As 数据类型
-----
变量名命名一般可以这样
change_name
函数命名一般这样
changeName()
数据类型,指变量的特性,用来决定可保存何种数据。数据类型包括 Byte、Boolean、Integer、Long、Currency、Decimal、Single、Double、Date、String、Object、Variant(默认)和用户定义类型等。
VBA的数据类型、存储空间大小、数值范围
数据类型 | 存储空间大小 | 范围 |
---|---|---|
Byte | 1个字节 | 0到255 |
Boolean | 2个字节 | True或False |
Integer | 2个字节 | -32,768到32,767 |
Long(长整型) | 4个字节 | -2,147,483,648 到2,147,483,647 |
Single(单精度浮点型) | 4个字节 | 负数时从-3.402823E38到-1.401298E-45;正数时从1.401298E-45到3.402823E38 |
Double(双精度浮点型) | 8个字节 | 负数时从-1.79769313486231E308 到一4.94065645841247E-324;正数时从4.94065645841247E-324 到1.79769313486232E308 |
Date | 8个字节 | 100 年1月1日到9999年 12月31日 |
object | 4个字节 | 任何0bject引用 |
String(变长) | 10字节加字符串长度 | 到大约20 亿 |
Variant(数字)(字符) | 16 个字节 | 任何数字值,最大可达 Double 的范围 |
用户自定义(利用Type) | 所有元素所需数目 | 每个元素的范围与它本身的数据类型的范围相同。 |
VBA的日期和函数
字符串定义后为空字符串,即没有任何数据的字符串(“”),可以通过以下方式对字符串赋值。字符串在VBA中用双引号表示。
Mystring = "Hello world."
MyFixedstring = "This is a fixed string .
"MyEmptystring = ""
定长字符串必须是其确定的长度,如果赋值时长度过长或过短,则自动以空格添满或截断。
字符串的连接可以使用“&”或者“+”,不过不推荐使用后者,因为容易和数字运算混淆。例如可以使用以下语句连接字符串。
Mystring ="test"
Mystring = Mystring &" Test Added"
Mystring = Mystring + " Added still"
字符串处理的常用函数如表2-6所示,各函数的具体使用方法可参考VBA的帮助文档。
Dim MyTime,MyDate,Mystr
MyTime = #17:04:23#
MyDate = #January 27,1993#
'以系统设置的长时间格式返回当前系统时间。
Mystr =Format ( Time, "Long Time " )
'以系统设置的长日期格式返回当前系统日期。
MyStr = Format (Date, "Long Date")
Mystr = Format (MyTime,"h :m : s")'返回 "17:4:23"。
Mystr = Format (MyTime,"hh : mm : ss AMPM")'返回"05:04:23 PM"。
'如果没有指定格式,则返回字符串。
MyStr = Format (23)'返回 "23"。
'用户自定义的格式。
MyStr = Format (5459.4,"##,##0.00") ’返回"5,459.40"。
Mystr = Format (334.9,"###0.00") '返回 "334.90"。
Mystr = Format (5,"0.00%")'返回"500.00%"。
MyStr = Format ("HELLO","<")'返回"hello"。
Mystr = Format ("This is it", ">")'返回"THIS IS IT"。
要声明常量并设定常量的值,需要使用Const语句。常量声明后,不能对它赋一个新的数值。例如,假设需要声明一个常量来保存书本价格,可以使用如下语句:
Const BOOKPRICE As Long = 23.50
VBA中的运算符有以下几类运算符:
^
运算符:求一个数字的某次方,如A^B;*
运算符:乘法运算;/
运算符:除法运算;\
运算符:对两个数作除法并返回一个整数;+
运算符:加法运算;-
运算符:减法运算;数组是具有相同数据类型并且共享同一个名字的一组变量的集合。数组中的元素通过索引数字加以区分。定义数组的语法如下:
Dim ArrayName (n) A.s Type
Dim ArrayName (a to b) As Type
其中n、a、b是数组中的元素的数目。n表示数组元素为0到n,共n+1个,a表示数组元素最小索引为a,最大为b,元素个数为(b-a+1)个。
例如,如果要创建保存10个学生名字的数组,可以使用如下语句:
Dim strstudents (9) As string
注意,括号中的数字是9而不是10。这是因为在默认情况下,第一个索引数字是0。数组在处理相似信息时非常有用。
Sub MyFirstVBAProgram()
Dim strName As String
Dim strHello As String
strName = InputBox("请输入你的名字:")
strHello = "你好," & strName & " !"
MsgBox strHello
End Sub
如果用户单击O或按下Enter键,则 InputBox函数返回文本框中的内容。如果用户单击Cancel,则此函数返回一个长度为零的字符串 ("")。
顺序语句是最基础的,按照语句一步一步的执行。
If...Then..Else语句
If
表达式是根据表达式的值有条件地执行一组语句,如果条件为真,则执行其后的语句,否则到下一个判断条件。其语法为:
If condition Then [statements][Else elsestatements]
或者,可以使用块形式的语法:
If condition Then
[ statements]
[ElseIf condition-n Then
[elseifstatements] ...
[Else
[ elsestatements ] ]
End If
在使用判断语句时,也会使用到以下逻辑运算符。
例子
Dim Number,Digits,Mystring
Number = 53
'设置变量初始值。
If Number < 10 Then
Digits = l
ElseIf Number < 100 Then
'若判断结果为True,则完成下一行语句。
Digits = 2
Else
Digits = 3
End If
Function Bonus (performance, salary)
select Case performance
case l
Bonus = salary *0.l
Case 2,3
Bonus = salary *0.09
Case 4 To 6
Bonus = salary *0.07
Case Is >8
Bonus = 100
Case Else
Bonus = o
End select
End Function
--------------
Sub Discount3 ()
Dim Quantity As variant
Dim Discount As Double
Quantity = InputBox("Enter Quantity: ")
select Case Quantity
Case ""
Exit Sub
Case 0 To 24
Discount = 0.1
Case 25 To 49
Discount = 0.15
Case 50 To 74
Discount = 0. 2
Case Is >= 75
Discount = 0.25
End select
MsgBox "Discount: " & Discount
End Sub
For Next语句
For I = l To 10
For J = l To 10
For K= l To 10
...
Next K
Next J
Next I
Dim Found,My0bject,MyCollection
Found = False
'设置变量初始值。
For Each Myobject In MyCollection
'对每个成员作一次迭代。
If Myobject.Text = "Hello" Then
Found = True
′将变量 Found的值设成True。
Exit For
’退出循环。
End If
Next
在前面的章节中讲过,“集合”是一组相关的对象。例如,Workbooks集合是所有打开的Workbook 对象的集合,还可以使用很多其他的集合。假设要在集合的所有对象上执行某个动作,或要对集合的所有对象求值并在特定条件下采取动作,这些都是使用For Each-Next结构的好机会,因为在使用For Each-Next结构时,不必知道集合中有多少元素。
For Each-Next结构的语法如下所示:
For Each element In collection
[instructions]
[Exit For]
[instructions]
Next [element]
下面的过程在活动工作簿中的 Worksheets集合上使用For Each-Next结构。在执行这个过程的时候,MsgBox 函数显示出每个工作表的Name属性(如果活动工作簿中有5个工作表,就调用MsgBox函数5次)。
Sub countsheets ()
Dim Item as worksheet
For Each Item In Activeworkbook.worksheets
MsgBox Item.Name
Next Item
End sub
Exit Do
Exit For
Exit Function
Exit Property
Exit sub
循环中可以在任何位置放置任意个Exit For语句,随时退出循环。**Exit For经常在条件判断之后使用,例如 If…Then,并将控制权转移到紧接在 Next 之后的语句。可以将一个For…Next循环放置在另一个For…Next循环中,组成嵌套循环。不过在每个循环中的counter要使用不同的变量名。
With语句可以对某个对象执行一系列的语句,而不用重复指出对象的名称。例如,要改变一个对象的多个属性,可以在With控制结构中加上属性的赋值语句,这时候只是引用对象一次而不是在每个属性赋值时都要引用它。下面的例子显示了如何使用With语句来给同一个对象的几个属性赋值。
with MyLabel
.Height = 2000
.width = 2000
.caption = "This is MyLabel"
End with
程序一旦进入With 块,object就不能改变。因此不能用一个With语句来设置多个不同的对象。可以将一个With块放在另一个之中,而产生嵌套的With语句。但是,由于外层With块成员会在内层的With 块中被屏蔽住,所以必须在内层的With块中,使用完整的对象引用来指出在外层的With块中的对象成员。
With语句经常使用在对一个对象或用户自定义类型需要进行反复引用的情况下,特别是在循环中,如果要反复引用某个对象,那么最好通过With语句来引用该对象。
Debug对象可以在运行时将输出发送到立即(Immediate)窗口
。Debug对象有2个方法: Assert和 Print方法,Assert 判断1条条件语句,如果为False,则挂起执行,暂停在Assert语句的地方,Print语句则向立即窗口输出一段文本,例如以下代码:
Dim i As Long
For i = l To 10 step 1
Debug.Print i
Debug.Assert i <8
Next i
当程序执行到3行Debug.Print时,程序向立即窗口输出i的值,而当i大于等于8时,Debug.Assert判断的表达式为False,程序挂起。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R0fCwsvP-1615651551126)(images/VBA基础教程一/image-20210307123111262.png)]
VBA提供了以下几种调试工具供使用。这些工具包括:
On Error Resume
如果有运行时刻的错误发生,那么程序将从导致错误发生的语句处重新开始执行;
On Error Resume Next
如果有运行时刻的错误发生,那么程序就从导致错误发生的语句的下一句继续执行下去。
Sub debugPrint()
Dim i As Long
For i = l To 10 Step 1
Debug.Print i
On Error Resume Next '暗示下面只要有错误的语句都可以跳过
a = 8 / 0
b = 8 / 0
Debug.Assert i < 8
Next i
End Sub
OnTime事件在一天中的某个特定时刻发生。下面的示例展示了如何进行Excel编程,使其在下午3点发出叫声并显示消息:
Sub SetAlarm ()
Application.onTime Timevalue("15:00:00"),"DisplayAlarm"
End Sub
Sub DisplayAlarm()
Beep
MsgBox "wake up. It's time for your afternoon break ! "
End Sub
该示例中,SetAlarm过程使用Application对象的OnTime方法来设置OnTime事件。该方法使用了两个参数:时间(在示例中为3 pm)和该时间到来时执行的过程(在示例中为DisplayAlarm过程)。执行SetAlarm过程后,DisplayAlarm过程将会在下午3点被调用,弹出如图19-10所示的对话框。
如果想要通过相对于当前时间来确定事件的发生时间,例如,从现在开始的20分钟之后,那么可以这样来编写指令:
Application.onTime Now + TimeValue ( "00:20:00"),"DisplayAlarm"
也可以使用OnTime方法来确定某个特定日期过程发生的时间。下列语句在2010年4月1日上午 12:01运行DisplayAlarm过程。
Application. OnTime DateSerial (2010, 4,1)+TimeValue ("00:00:01"), "DisplayAlarm"
Dim NextTick As Date
Sub UpdateClock()
' Updates cell A1 with the current time
ThisWorkbook.Sheets(1).Range("A1") = Time
' Set up the next event five seconds from now
NextTick = Now + TimeValue("00:00:05")
Application.OnTime NextTick, "UpdateClock"
End Sub
Sub StopClock()
' Cancels the OnTime event (stops the clock)
On Error Resume Next
Application.OnTime NextTick, "UpdateClock", , False
End Sub
窗体是事件驱动类型的。
双击按钮控件,会生成单机代码,函数名称为cmdHello_Click()
(即为按钮控件的名称+事件名称)
Private Sub cmdHello_Click()
Me.txtMsg.Text = "Hello VB!" 'txtMsg即为文本框控件的名称 Me相当于This
End Sub
最关键的就是插入一个图片或者窗体控件,然后制定宏
为其指定宏,就可以点击它控制后面的程序了。