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 LetProperty Setproperty 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可以有返回值。由FunctionEnd 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编写

SubEnd 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为其设置引用。

如果在SubFunction前使用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 数组
posted @ 2020-09-15 20:20  九梦岛主  阅读(1223)  评论(0编辑  收藏  举报