阅读(2826) (0)

VBA强制声明变量

2016-11-16 10:27:00 更新

VB使用Option Explicit语句自动提醒你正式地声明你的变量,这个语句必须放在每个模块的最上面。如果你试图运行一个含有未定义的变量的过程时,Option Explicit语句会让VB产生一个错误信息。


1.  返回代码窗口你输入过程CalcCost的地方

2.  在模块的最上面输入Option Explicit并回车,Excel将该语句显示为蓝色

3.  运行过程CalcCost,VB显示错误信息“编译错误:变量未定义”

4.  点击确定关闭信息框。

VB加亮变量名称slsPrice。现在你需要正式声明这个变量。当你声明了变量slsPrice并再次运行该过程时,VB一旦遇到另外一个未声明的变量时,将再次产生同样的错误。


5.  在CalcCost过程的开始部分输入下述声明:

'declaration of variables (声明变量)

Dim slsPrice as Currency

Dim slsTax as Single

Dim Cost as Currency

Dim strMsg as String


6.  按下F5来运行该过程,修改后的程序显示如下“
Option Explicit
Sub CalcCost()
'declaration of variables
             Dim slsPrice As Currency
             Dim slsTax As Single
             Dim Cost As Currency
             Dim strMsg As String
             slsPrice = 35
             slsTax = 0.085
             Range("A1").Formula = "The cost of calculator"
             Range("A4").Formula = "Price"
             Range("B4").Formula = slsPrice
             Range("A5").Formula = "Sales Tax"
             Range("A6").Formula = "Cost"
             Range("B5").Formula = Format((slsPrice * slsTax), "0.00")
             Cost = Format(slsPrice + (slsPrice * slsTax), "0.00")
             With Range("B6").Formula = Cost
             strMsg = "The calculator total is " & "$" & Cost & "."
             Range("A8").Formula = strMsg
End Sub



在模块上面输入的Option Explicit语句强迫你声明变量,因为如果你需要声明变量的话,你必须每次在添加新模块时输入Option Explicit语句,所以你可以让VB帮你输入它。按照下述步骤来自动在新模块里添加Option Explicit语句:


1.  选择“工具”-“选项”


2.  确保选项对话框(编辑器页)上的“要求变量声明”被勾选上了


3.  点击确定关闭对话框


从现在开始,每个新模块都会在第一行添加Option Explicit语句。如果你要在一起创建的模块里
强制声明变量的话,你必须手动输入Option Explicit。


技巧:Option Explicit更多信息
Option Explicit强迫正式(显式)声明模块里的所有变量。使用它的一个重大优点是,输入错误会在编译时(VB试图将源代码翻译为可执行代码)被检测到。Option Explicit语句必须在模块里的任何过程之前出现。


了解变量范围

不同的变量在VBA过程里有不同的影响范围。Scope(范围)这个术语定义某个特定的变量在同一个过程,其它过程,或者其它VBA工程里的可用性。变量在VBA里可以是下面三种级别的范围:

过程级别范围
模块级别范围
工程级别范围

过程级别(当地)变量

你已经知道如何通过关键字Dim来声明变量,在关键字Dim在模块中的位置决定了该变量的范围。在VBA过程中用Dim关键字声明的变量拥有过程级别的范围,过程级别的变量经常被称为当地变量。当地变量只能使用在声明它的过程里面。未声明的变量总是过程级别的变量。在它的范围内,变量的名称必须是唯一的,这意味着你不可以在同一个过程里使用同样的名称来声明两个变量。然而,你可以在不同的过程里面使用同样的变量名称。换句话说,过程CalcCost里可以有slsTax变量,同一个模块里的过程ExpenseRep里页可以有它自己的变量slsTax,两个变量相互独立。

模块级别变量

当地变量有助于节省电脑内存,一旦该过程结束,该变量便立即消失,并且电脑释放该变量占用的内存空间。然而,在编程中,你经常需要变量在本过程结束后仍然在其它过程里可用,这种情形需要你改变变量的范围。你可能就需要定义一个模块级别的变量,而不是过程级别的了。要定义模块级别的变量的话,你必须将关键字Dim放在模块表里任何过程的上面(紧接着在关键字OptionExplicit的下面)。例如,将slsTax设置为任何Variables模块里的过程都可以使用,按照下述方法声明slsTax变量:

Option Explicit
Dim slsTax As Single
Sub CalcCost( )
            <放置过程指令>
End Sub

在上面的例子里,关键字Dim在模块的上面,紧挨着OptionExplicit语句。你需要另外一个过程来使用变量slsTax,这样你才能查看这是如何工作的。

1.在代码窗口里,将变量声明行Dim slsTax As Single从Variables模块的CalcCost过程里剪切,并且粘贴到该模块的上面Option Explicit语句的下面。

2.  在CalcCost过程的同一个模块里输入ExpenseRep过程代码:

Sub ExpenseRep()
         Dim slsPrice As Currency
         Dim Cost As Currency
         slsPrice = 55.99
         Cost = slsPrice + (slsPrice * slsTax)
         MsgBox slsTax
         MsgBox Cost
End Sub

ExpenseRep过程里声明了两个货币类型的变量:slsPrice和Cost。slsPrice变量随后赋值55.99,slsPrice和CalcCost过程里声明的变量slsPrice是独立工作的。ExpenseRep过程计算采购的费用,该费用包括销售税,因为销售税和CalcCost过程里使用的是一样的,所以将slsTax变量声明为模块级别的变量。VB执行CalcCost过程后,变量slsTax的内容等于0.085。如果slsTax是当地变量的话,随着CalcCost过程的终结,变量slsTax的内容将被清空。过程ExpenseRep结束时显示两个信息框来输出变量slsTax和Cost的值。当你运行CalcCost后,VB清空除了slsTax之外的所有变量的内容,因为slsTax以被定义为模块级别的变量。一旦你试图通过运行ExpenseRep来计算价格,VB就会找到slsTax的值,并且将它用到计算中。

技巧:私有变量
当你在模块级别声明变量时,除了关键字Dim之外,你还可以使用关键字Private。例如:

Private slsTax As Single

私有变量仅仅在声明该变量的模块里的过程中可用。私有变量总是在模块的上面Option Explicit语句之后声明。

技巧:保持工程级别的变量为私有
为了避免工程级别的变量内容被工程之外使用,你可以在Option Explicit语句下面,模块的上面输入Option Private Module,例如:

Option Explicit
Option Private Module
Public slsTax As Single
Sub CalcCost( )
            <这里是过程代码>
End Sub


工程级别变量

模块级别的变量用关键字Public(而不是Dim)声明时,拥有工程级别范围。这意味着它们可以在VBA任何模块里使用。当你想要在一个打开的VBA工程的所有过程里使用某个变量时,必须用Public关键字来声明它,例如:

Option Explicit
Public slsTax As Single
Sub CalcCost( )
            <过程代码>
End Sub

注意,变量slsTax在模块上面以Public关键字声明的,它将会在该VBA工程里的任何过程里都可用。

变量的存活期

除了范围之外,变量还有存活期,变量的存活期决定了该变量能保存它的值有多久。一旦该工程打开,模块级别和工程级别的变量就会保留它们的值。然而,如果程序的逻辑需要,VB能够重新初始化这些变量。使用Dim语句声明的当地变量当过程结束时就会丢失值,当地变量的存活期是随着过程的运行的,并且它们在程序每次运行的时候可以被重新初始化。VB允许你通过改变声明方式延长当地变量的存活期。

了解和使用静态变量

用Static关键字声明的变量是特殊的当地变量,静态变量在过程级别声明。和那些用关键字Dim声明的当地变量相反,静态变量在程序已经不在它们的过程里时仍然不会丢失它们的内容。例如,当一个带有静态变量的VBA过程调用另外一个过程时,在VB执行完被调用的过程语句后返回主调过程时,静态变量仍然保留它原来的值。过程CostOfPurchase示范静态变量allPurchase的使用:

Sub CostOfPurchase()
         'declare variables
          Static allPurchase
          Dim newPurchase As String
          Dim purchCost As Single
          newPurchase = InputBox("Enter the cost of a purchase:")
          purchCost = CSng(newPurchase)
          allPurchase = allPurchase + purchCost
          'display results
          MsgBox "The cost of a new purchase is: " & newPurchase
          MsgBox "The running cost is: " & allPurchase
End Sub

上面的过程以一个名为allPurchase的静态变量和两个当地变量newPurchase和purchCost的声明开始。该过程中使用的InputBox函数显示一个对话框并且等着用户输入数值,一旦用户输入数值并且点击确定后,VB就会将该数值赋给变量newPurchase。在第四章中有InputBox函数的讨论。因为InputBox函数的结果总是字符串,变量newOurchase被声明为字符串数据类型了。然而,你不能在数学计算中使用字符串,这就是为什么需要在下一指令中使用一个类型转换函数(CSng)来将字符串值转换为单精度浮点类型的数字。函数CSng只需要一个自变量——你要转换的数值。函数CSng转换的数字结果保存在变量purchCost上。

技巧:类型转换函数
在CSng上的任意地方按下F1,可以查看更多关于函数CSng的信息(也可以查看其它类型转换函数信息)下一行指令:allPurchase = allPurchase + purchCost,将InputBox函数提供的新数值加和到目前的采购数值上。当你第一次运行这个过程的时候,变量allPurchase和变量purchCost的内容是一样的;当你第二次运行它的时候,这个静态变量的值由对话框提供的值增加了。你可以随意多次运行过程CostOfPurchase,只要该工程是开着的,变量allPurchase就会不断的变化。依照下述步骤来试验该过程:

1.  将光标放在过程CostOfPurchase里的任意地方并且按下F5
2.  当对话框出现时,输入一个数字,例如,输入100然后回车。VB显示信息““Thecostofanew
purchase is: 100.”
3.点击确定,VB显示第二个信息“The running cost is: 100.”
4.重新运行该程序,当对话框出现时,输入另外一个数字,例如输入50再回车。VB显示信息“The
cost of a new purchase is 50.”
5.  点击确定,VB显示第二个信息“The running cost is: 150.”
6.  多次运行该程序,看看VB是如何追踪运行的总量的。