VBA基本语法规范
数据类型
Variant、 Byte 、 Boolean 、 Integer 、 Long 、 Single 、 Double 、 Currency 、 Decimal 、 Date 、 Object 和 String 。
定义对象变量
使用Dim、Private、Static、Public声明对象,(用Dim声明的模块级变量都默认为Private的)
' Declare MyObject as Variant data type.
Dim MyObject
' Declare MyObject as Object data type.
Dim MyObject As Object
' Declare MyObject as Font type.
Dim MyObject As Font
如果使用对象变量却没有实现声明,则默认是Variant(多样变量)
使用Set将对象变量分配给变量
Set MyObject = YourObject ' Assign object reference.
Set MyObject = Nothing ' Discontinue association.
可以通过New关键词与Set语句结合使用,可以将声明变量与为其分配对象
Set MyObject = New Object ' Create and Assign
引用对象的当前实例
使用Me关键词,带边引用在其上运行的代码的当前实例
Sub ChangeObjectColor(MyObjectName As Object)
MyObjectName.BackColor = RGB(Rnd * 256, Rnd * 256, Rnd * 256)
End Sub
ChangeObjectColor Me
数组
数组的声明方式和其他对象是一样的,即Dim、Private、Static、Public
通常我们需要制定固定大小的数组, 数组是否以0或1开始,可以根据Option Base语句设置,默认为0
声明固定大小的数组
在下面的代码行中,一个固定大小的数组声明为具有11 行和 11 列的 Integer 数组:
Dim MyArray(10, 10) As Integer
第一个参数代表行、第二个参数代表列
声明动态数组
Dim sngArray() As Single
在数组范围内的过程中,使用 ReDim 语句可更改维度数、定义元素数,以及定义每个维度的上限和下限。 可以根据需要使用 ReDim 语句更改动态数组。 但是,每次这么做时,数组中的现有值都会丢失。 使用 ReDim Preserve 可在保留数组中现有值的情况下扩展数组。
例如,下面的语句将数组扩增了 10 个元素,而未丢失原始元素的当前值。
ReDim Preserve varArray(UBound(varArray) + 10)
在对动态数组使用 Preserve 关键字时,仅能更改最后一个维度的上限,而不能更改维度数。
声明常量
Const关键词
Public Const conAge As Integer = 34
可在一个语句中声明多个常量。 若要指定数据类型,必须为每个常量包括数据类型。
在下面的语句中, 常量conAge和conWage声明为Integer。
Const conAge As Integer = 34, conWage As Currency = 35000
声明变量
通常使用Dim来声明。过程中声明为过程级变量,模块顶部声明为模块级变量。
Dim strName As String
可以使用Type语句创建用户定义的类型。
在一个数据中声明多个变量
Dim intX As Integer, intY As Integer, intZ As Integer
声明变量类型缩写格式
类型的缩写是:% -integer; & -long; @ -currency; # -double; ! -single; $ -string
以下语句将intX、intY声明成整数
Dim intX%, intY%, intZ as Integer
隐式声明变量(Option Explicit)
通过在赋值语句中使用一个变量,即可在 Visual Basic 中隐式声明此变量。 隐式声明的所有变量都是 Variant 类型。 相比大多数其他变量,Variant 类型变量需要更多的内存资源。
如果不希望VB进行隐式声明,可在过程之前添加Option Explicit语句置于模块中。 此语句要求显式声明模块内的所有变量。
Option Explicit ' Force explicit variable declaration.
Dim MyVar ' Declare variable.
MyInt = 10 ' Undeclared variable generates error.
MyVar = 10 ' Declared variable does not generate error.
设置属性改变时的执行代码(Let、Get、Set)
可以创建具有相同名称的Property Let、 Property Set 和property Get 过程。
Private IsInverted As Boolean
Property Let Inverted(X As Boolean)
IsInverted = X
If IsInverted Then
…
(statements)
Else
(statements)
End If
End Property
通过以上设置了IsInverted为私有类型,要改变这个数据只能通过Inverted来改变
Form1.Inverted = True
Get程序用于返回属性的当前状态
Property Get Inverted() As Boolean
Inverted = IsInverted
End Property
条件语句
If...Then...Else
Sub FixDate()
myDate = #2/13/95#
If myDate < Now Then myDate = Now
End Sub
以上是一行代码的情况,如果要多行代码,则需要使用End If语句结尾
Sub AlertUser(value as Long)
If value = 0 Then
AlertLabel.ForeColor = "Red"
AlertLabel.Font.Bold = True
AlertLabel.Font.Italic = True
End If
End Sub
Select Case
Function Bonus(performance, salary)
Select Case performance
Case 1
Bonus = salary * 0.1
Case 2, 3
Bonus = salary * 0.09
Case 4 To 6
Bonus = salary * 0.07
Case Is > 8
Bonus = 100
Case Else
Bonus = 0
End Select
End Function
循环语句
Do...Loop
Do While
当条件为True则一直循环
Sub ChkFirstWhile()
counter = 0
myNum = 20
Do While myNum > 10
myNum = myNum - 1
counter = counter + 1
Loop
MsgBox "The loop made " & counter & " repetitions."
End Sub
Sub ChkLastWhile()
counter = 0
myNum = 9
Do
myNum = myNum - 1
counter = counter + 1
Loop While myNum > 10
MsgBox "The loop made " & counter & " repetitions."
End Sub
Do Until
一直循环到条件为True
Sub ChkFirstUntil()
counter = 0
myNum = 20
Do Until myNum = 10
myNum = myNum - 1
counter = counter + 1
Loop
MsgBox "The loop made " & counter & " repetitions."
End Sub
Sub ChkLastUntil()
counter = 0
myNum = 1
Do
myNum = myNum + 1
counter = counter + 1
Loop Until myNum = 10
MsgBox "The loop made " & counter & " repetitions."
End Sub
退出Do循环体
在代码中使用Exit Do声明,以跳出/离开循环
Sub ExitExample()
counter = 0
myNum = 9
Do Until myNum = 10
myNum = myNum - 1
counter = counter + 1
If myNum < 10 Then Exit Do
Loop
MsgBox "The loop made " & counter & " repetitions."
End Sub
For...Next
类似于常见的for循环体,该循环体使用一个定义的数值变量的增减来执行相应的循环。
以下代码片段使得计算机Beep 50次,Next声明对x变量自增
Sub Beeps()
For x = 1 To 50
Beep
Next x
End Sub
使用Step关键词,你可以定义Next的步幅。
Sub TwosTotal()
For j = 2 To 10 Step 2
total = total + j
Next j
MsgBox "The total is " & total
End Sub
自减步幅
Sub NewTotal()
For myNum = 16 To 2 Step -2
total = total + myNum
Next myNum
MsgBox "The total is " & total
End Sub
For Each ... Next
For Each...Next 语句会为集合中的每个 对象并为数组中的每个元素重复语句块。
例如,下面的过程将关闭所有窗体(包含正在运行的过程的窗体除外)。
Sub CloseForms()
For Each frm In Application.Forms
If frm.Caption <> Screen. ActiveForm.Caption Then frm.Close
Next
End Sub
下面的代码将循环访问数组中的每个元素,并将每个元素的值设置为索引变量 I 的值。
Dim TestArray(10) As Integer, I As Variant
For Each I In TestArray
TestArray(I) = I
Next I
使用Exit For退出For循环体
Sub TestForNumbers()
For Each myObject In MyCollection
If IsNumeric(myObject.Value) = False Then
MsgBox "Object contains a non-numeric value."
Exit For
End If
Next c
End Sub
使用"For Each...Next"循环来循环访问VBA类
For Each...Next 循环不会仅循环访问 Collection对象的数组和实例。 For Each...Next 循环还可以循环访问你已编写的 VBA 类。
With语句
With语句可以为整个语句块指定一次对象或用户定义类型。
下面的示例在一系列单元格中填入数字 30,应用粗体格式,并将单元格的内部颜色设置为黄色。
Sub FormatRange()
With Worksheets("Sheet1").Range("A1:C10")
.Value = 30
.Font.Bold = True
.Interior.Color = RGB(255, 255, 0)
End With
End Sub
条件编译
可以使用条件编译有选择地运行代码块,例如,调试将不同与同一编程任务的速度进行比较的语句,或者用不同的语言对应用程序进行本地化。
你可以通过使用#Const
来定义一个编译器常量,通过使用#If...Then...#Else
来根据常量执行相应的代码。
' Declare public compilation constant in Declarations section.
#Const conDebug = 1
Sub SelectiveExecution()
#If conDebug = 1 Then
. ' Run code with debugging statements.
.
.
#Else
. ' Run normal code.
.
.
#End If
End Sub
函数
Function编写
和Sub类似,但Function可以有返回值。由Function
和End Function
组成。
Sub Main()
temp = Application.InputBox(Prompt:= _
"Please enter the temperature in degrees F.", Type:=1)
MsgBox "The temperature is " & Celsius(temp) & " degrees C."
End Sub
Function Celsius(fDegrees)
Celsius = (fDegrees - 32) * 5 / 9
End Function
Sub编写
由Sub
和End Sub
组成。可执行操作,但不返回值。
' Declares a procedure named GetInfo
' This Sub procedure takes no arguments
Sub GetInfo()
' Declares a string variable named answer
Dim answer As String
' Assigns the return value of the InputBox function to answer
answer = InputBox(Prompt:="What is your name?")
' Conditional If...Then...Else statement
If answer = Empty Then
' Calls the MsgBox function
MsgBox Prompt:="You did not enter a name."
Else
' MsgBox function concatenated with the variable answer
MsgBox Prompt:="Your name is " & answer
' Ends the If...Then...Else statement
End If
' Ends the Sub procedure
End Sub
命名参数和可选参数
你可以按照参数顺序赋值给相应的Sub和Function函数,也可以指定名称,则不用按照特定顺序。
Sub PassArgs(strName As String, intAge As Integer, dteBirth As Date)
Debug.Print strName, intAge, dteBirth
End Sub
' 你可以使用指定顺序赋值相应的语句
PassArgs "Mary", 29, #2-21-69#
' 也可以使用名称指定数据
PassArgs intAge:=29, dteBirth:=#2/21/69#, strName:="Mary"
传递指定名字参数,需要使用:=
指定值。
当你使用可选参数的时候,命名参数非常有用。可以不必使用逗号来只是缺失位置的参数。
可选参数的声明需要以Optional(可选的)
修饰,并对其赋值操作。
Sub OptionalArgs(strState As String, Optional strCountry As String = "USA")
. . .
End Sub
以下代码中,存在varRegion
以及varCountry
两个可选参数。使用IsMissing()
可以判断参数是否已将可选的Variant参数传递给该过程。
Sub OptionalArgs(strState As String, Optional varRegion As Variant, _
Optional varCountry As Variant = "USA")
If IsMissing(varRegion) And IsMissing(varCountry) Then
Debug.Print strState
ElseIf IsMissing(varCountry) Then
Debug.Print strState, varRegion
ElseIf IsMissing(varRegion) Then
Debug.Print strState, varCountry
Else
Debug.Print strState, varRegion, varCountry
End If
End Sub
数组参数
数组参数可以将多个参数作为一个数组对象传递给一个程序。你无需在定义前就知道这个数组里面存在多少个元素。
使用ParamArray
关键词来修饰数组参数。
Sub AnyNumberArgs(strName As String, ParamArray intScores() As Variant)
Dim intI As Integer
Debug.Print strName; " Scores"
' Use UBound function to determine upper limit of array.
For intI = 0 To UBound(intScores())
Debug.Print " "; intScores(intI)
Next intI
End Sub
AnyNumberArgs "Jamie", 10, 26, 32, 15, 22, 24, 16
AnyNumberArgs "Kelly", "High", "Low", "Average", "High"
作用域及可见性
作用范围是指供另一个过程使用的变量、常量或过程的可用性。 有三种范围级别:过程级、私有模块级和公共模块级。
过程级作用域
在一个过程内定义的变量或常量在该过程外不可见。 只有包含变量声明的过程可以使用它。 在以下示例中,第一个过程显示一个包含字符串的消息框。 第二个过程显示一个空白消息框,因为该变量对于第一个过程而言是局部变量。
Sub LocalVariable()
Dim strMsg As String
strMsg = "This variable can't be used outside this procedure."
MsgBox strMsg
End Sub
Sub OutsideScope()
MsgBox strMsg
End Sub
私有模块级作用域
可以在模块的声明部分定义模块级变量和常量。 模块级变量可以是公共的,也可以是私有的。 公共变量可以在项目中所有模块中使用。默认情况下,使用Dim
声明的变量作用范围默认是Private的。
在下面的示例中, 字符串变量strMsg
可用于模块中定义的任何过程。 当调用第二个过程时, 它会在对话框中显示字符串strMsg
变量的内容。
' Add following to Declarations section of module.
Private strMsg As String
Sub InitializePrivateVariable()
strMsg = "This variable can't be used outside this module."
End Sub
Sub UsePrivateVariable()
MsgBox strMsg
End Sub
公共模块级作用域
如果使用Public
,则声明了一个公共变量。
变量生存期
初始化变量操作如下:
-
数值变量初始化为零,
-
可变长度字符串初始化为零长度字符串 ("")
-
固定长度的字符串用 ASCII 字符代码0或Chr(0) 表示的字符填充
-
Variant 变量初始化为空
-
用户定义类型变量的每个元素都像单独变量一样初始化。
-
Object对象类型变量初始化较为特殊,会为其保留控件,但是将其初始化为Nothing,直到使用
Set
为其设置引用。
如果在Sub
及Function
前使用Static
声明,则其中的所有过程级变量将在两次调用之间保留其值。
理解Variants(变体)
如果你声明常量、变量或者参数时未指定类型,则默认会设置其为Variant类型的对象。数值类型的Variant对象需要使用16字节来存储,同时他们的引用也比显示声明类型的变量更慢(仅在较大较复杂的程序中较为重要),而字符串类型的Variant对象则需要22字节。
Dim myVar
Dim yourVar As Variant
theVar = "This is some text."
最后一个语句不显式声明变量, 而是隐式或自动声明该变量。 隐式声明的变量将被指定为 Variant 数据类型。
如果为变量或参数指定数据类型,而使用了错误的数据类型,则会发生数据类型错误。 若要避免数据类型错误,只使用隐式变量( Variant 数据类型)或者明确声明所有变量并指定数据类型。 后一种方法是首选方法。
使用括号
Sub过程、内置语句和一些方法不带有返回值,不必将参数括在括号中。
MySub "stringArgument", integerArgument
函数过程、内置函数和一些方法带有返回值,如果你不需要,你可以不必使用括号。而如果需要将其赋值给另一个对象,则需要带上括号。
Answer3 = MsgBox("Are you happy with your salary?", 4, "Question 3")
赋值语句
Let
语句一般会被忽略,如
Let yourName = InputBox("What is your name?").
Set
语句用于将对象分配给已声明为对象的变量。该关键词是必须的。
Sub ApplyFormat()
Dim myCell As Range
Set myCell = Worksheets("Sheet1").Range("A1")
With myCell.Font
.Bold = True
.Italic = True
End With
End Sub
vbType常量
常量 | 值 | 说明 |
---|---|---|
vbEmpty | 0 | 未初始化(默认) |
vbNull | 1 | 不包含有效数据 |
vbInteger | 双面 | Integer |
vbLong | 第三章 | 长整型 |
vbSingle | 4 | 单精度浮点数 |
vbDouble | 5 | 双精度浮点数 |
vbCurrency | 型 | Currency |
vbDate | 步 | Date |
vbString | utf-8 | String |
vbObject | 第 | 对象 |
vbError | 10 | Error |
vbBoolean | 11x17 | Boolean |
vbVariant | 12 | Variant(仅用于变量数组) |
vbDataObject | 13 | 数据访问对象 |
vbDecimal | 日 | Decimal |
vbByte | × | Byte |
vbLongLong | 20 | LongLong整数 (仅在64位平台上有效) |
vbUserDefinedType | 36 | 包含用户定义类型的变量 |
vbArray | 8192 | 数组 |