【原创】VBA学习笔记(16)VBA的变量的声明, 作用域(生效范围),赋值(默认值)

目的:整理VBA变量相关的3个问题

  • 变量的声明  (变量的定义)----对比常量的定义
  • 变量的作用域(生效范围)
  • 变量的赋值 和 变量的默认值(如果没有赋值,那么默认值就是初值)

0 要讲变量,先讲常量 常量定义用 const

0.1 常量的定义

  • 常量英文 constant
  • 常量关键字 const
  • 常量定义的语句   
  • const a1 =1
  • const a2 as string = "hello"

0.2 常量和变量的区别:声明时马上赋值

  • 常量必须定义的时候,马上赋值 ( 而变量不能这样)
  • 常量关键字 const  as 
  • 变量 关键字 dim   as (类似的还有  static private public)
  • dim 比较特殊,可以作为 模块级的声明,也可以作为过程级的声明

0.3 常量可以定义在模块内或过程内

如果时模块级,也可以用 public  private等关键字,声明作用域

  • 常量的声明可以在 模块的第一个sub 前,也可以在sub内

比如

  Public Const a5 As String = "hello"

0.4 常量的测试


  Const a1 = 1
  Const a2 As Integer = 2
'   dim Const a3 As Integer = 3  '语法报错,常量定义 只用 const 和 dim是对应的!
  Dim a4 As Integer
  Public Const a5 As String = "hello"
 
  
  

Sub testa101()
   Const b1 = 10
   
   Debug.Print "a1=" & a1
   Debug.Print "a2=" & a2
   Debug.Print "a5=" & a5
   Debug.Print "b1=" & b1
   
End Sub

1 变量的声明 (就是变量的定义)

变量的声明就是变量的定义,先定义好变量,再使用是个好习惯

1.1 先声明好变量类型

  • 初学时,可以先不管,不定义变量类型
  • 但要明白,dim a 这种没声明的,其实都时隐式声明为了 dim a as variant (通用型变量)
  • 初学之后,一定要先声明变量,加option explicit,不加这个遇到变量赋值问题不会报错。
  • 声明语句   dim  a  as integer
  • 特殊问题;   dim i , j as integer 只有j 是int ,而i 是 variant

1.2 变量分类

  • 基本型变量:   integer string double float date
  1. Boolean
  2. Byte
  3. Integer
  4. Long
  5. Currency
  6. Single
  7. Double
  8. Date
  9. String 
  • 通用性变量:   variant ,默认就是通用变量,可以随时改变变量的类型
  • 数组变量:       dim arr1() as string
  • 对象变量:       如 dictionary  worksheet 等等,dim dict1 as object ,对象变量的赋值要用set

1.3 变量定义时不指定类型,默认都是  variant 通用型变量,很灵活,但是也很费

  •  dim a1 
  • dim a1 as variant

1.4 动态变量和静态变量,猜想英文原意?

  • dim 是 dynamic? 动态变量?
  • static 静态变量

1.5 不能在声明的变量同时赋值。变量需要先声明,后赋值。

Dim i As Integer   
Dim j As Integer: j = 1     '错误代码,不能再模块最上面给变量赋值


Sub test100()    
Debug.Print i
Debug.Print j

i = i + 1
j = j + 1


Debug.Print i
Debug.Print j

End Sub

1.5.1 特殊用法:相当于合并语句 (意义不大)

  • 只能在过程内,因为变量只能在过程内赋值!

  • 过程级变量,声明和赋值,可以用 :链家,相当于合并语句而已

  • 声明+ 赋值语法   dim  a  as integer :a=1
  • 声明后 赋值的标准语法 
  • dim  a  as integer
  • a=1
Const k1 As Double = 3.1415926


Sub test100()

Dim i As Integer
Dim j As Integer: j = 1
Const k As Double = 3.1415926

Debug.Print i
Debug.Print j
Debug.Print k
Debug.Print k1

i = i + 1
j = j + 1


Debug.Print i
Debug.Print j

End Sub

2  变量初值与默认值

2.1 变量的初值

  • 初值:是变量最初被赋予的值
  • 一般要求变量赋值后才可以表达式运算
  •  如python 会在表达式运算时,把变量  代换为 值,所以没赋值会报错!

2.2 变量的默认值

  • 默认值:变量没被赋值时,默认的值(有的语言没有,会报错)
  • VBA看起来是给变量赋予了默认值。
  • 比如变量一般默认值为 “”

2.3  不同类型的变量,其默认值不同

赋值,初值,默认值(和类型有关)一般为0!

  • integer    默认值   0
  • string      默认值  ""     
  • long        默认值 0
  • double    默认值 0.0    
  • object     nothing           释放也时 set object = nothing
  • 等等

2.4不同变量类型的默认值查询

https://blog.csdn.net/hpdlzu80100/article/details/80664914

2.5 为什么一般不能在声明变量时赋值呢?

  • 声明时不能给变量赋值。(变量,静态变量都会被初始化,但是而常量并不会被初始化)
  • 因为当过程开始运行时,所有的变量都会被初始化。
  • 一个数值变量会初始化成 0,变长字符串被初始化成零长度的字符串 (""),而定长字符串会被填满 ASCII 字符码 0 所表示的字符或是 Chr(0)。

3 变量的作用域(生效范围)

变量到底能再哪些地方生效,这个由2个因素决定

  1.  变量声明时,声明语句前面的关键字,比如 dim  private  public
  2. 变量声明时,所在的代码的层级。 特别是用  dim 这种灵活而模糊的

3.1 全局级作用域:用 global / public 来声明在模块最前面!(实测不生效!!!)

变量可以跨工作簿/ 工程:

  1. 可以跨多个工作簿生效,有这样的变量吗?据说有
  2. 不能加Option Private Module 用global 和 public
  3. 我实测了不行,但据说是适用一个 EXCEL文件下,有多个工程的情况,没见过,暂时我测试没有看到可以跨工程的变量。

3.2 工程级作用域:用 global /public 来声明在模块最前面(过程外)

变量可以在整个工程内生效,可以跨这个工程内的模块

  1. 用public 关键字在模块的第1个过程之前声明的变量 (public不能用在过程内)
  2. 可以在多个模块内都生效
  3. public 声明的变量,丢失有两种可能,一种是你关闭了excel文件,另一种是你重新编辑了代码,其他情况都会保留的

特殊情况

  1. Option Private Module
  2. 加上这句话后,这个模块内的代码,只能再本工程内使用
  3. 并且,点开EXCEL的菜单宏,将看不见这些宏了。

 

3.3 模块级作用域 :用dim / private 来声明在过程外

  1. 用private 或 dim 在模块的第1个过程之前声明的变量,这时候  private 或 dim 此时等价。
  2. 差别是,dim 很模糊,可以用在过程内/过程外,而private 必须声明在过程外。
  3. 也就是用private a  as string 声明的变量,是模块级变量,不能声明在过程里。
  4. 如果加了这句话 一定只是在模块内生效 !Option Private Module

3.4 过程级变量:用dim / static 来声明在过程内部!

  • 用 static 或 dim 在过程内声明的变量,只在这个过程内生效。但是 static 和dim  声明的变量完全不同
  • 差别是,dim 很模糊,可以用在过程内/过程外,static 声明的变量,只能定义在过程内。
  • static a1 这样定义的变量,虽然一定是定义在过程内的,但是 static定义的变量在过程结束后并不会被释放,而是一直起作用到,过程所在的模块 重置 会重新启动。
  • static a1 静态变量的作用域,还是过程内。但是生命周期在 模块重置/重启 前都一直生效。

   

3.5  变量定义时,VBA的特殊问题

  • 作用域语句,是整行生效
  • 但是  声明语句 dim as 语句不是,对单个变量生效
  • 当相同名称的变量,多次以不同的作用域声明时,出现作用域冲突。这种情况,VBA 会自动以就近原则使用变量,即优先使用最近定义的变量。也就是一般会先使用过程内部的,更近的

  • 比如
  • 例子1: dim i , j as integer 只有j 是int ,而i 是 variant
  • 例子2: Public a6, a7 As Integer ,这2个变量作用域都时public

4 变量生命周期 (生命期不完全等同于范围)

变量的生命周期 和 变量定义时的 作用域定义是 密切相关的,基本就是作用域外,就不再生效。

比如

  • 全局级:excel 程序打开后都生效,除非EXCEL关闭,一直在内存里
  • 工程级:当前的EXCEL表,工程,没有关闭就一直生效。
  • 模块级:当前模块在运行就生效
  •              (反之,没运行 这个模块 就不生效)
  • 过程级,过程执行时才开始生效,给其分配内存空间,过程执行结束就从内存释放
  •                (反之,没运行 这个过程/函数 就不生效,想生效就得调用它! 这就是调用原因!)
  • 过程级的例外:static 在过程执行后还是生效,将保留其值,直到模块重置或重新启动   
  •                    Static]定义的是静态变量,这意味着在过程结束后这个变量所占有的内存不会被回收,数据也不会被破坏,下次再调用该过程的时候,数据就依然存在。

5  过程得作用域 和 变量作用域

5.1 过程和函数的 默认作用域  public

  • 比如过程和函数默认是 工程级作用域
  • 实测,在sub 前加 public 可以,不加默认也时 public
  • sub  相当于    public  sub                       "在workbook内有效
  • function  相当于    public  function          "在workbook内有效

5.2 过程/函数 也可以用 private 来声明

  • 但是如果加 private 声明,就限制在只在模块内生效,无法被跨模块调用
  • 如果定义为 private sub testsub1()           "只在本模块内有效。

5.3 实测,过程/函数 好像无法 全局作用域?

  • 实测,在sub 前加global 自动消失

5.4 过程/函数  声明为static

  • 如果声明为静态
  • 静态过程  static  sub ,其内部所有变量都是  static 变量

5.5  变量的最终作用域 (两层 作用域 共同作用的结果)

  • 过程/函数的作用域 和变量的作用域是两回事
  • 但是 过程的属性 部分情况下会影响变量的作用域,如static sub

6  变量的调用

6.1 搞清楚,为什么要调用变量? 调用变量就得先调用其他过程/函数?

  • 首先,过程级的变量是无法调用的,即使你调用那个过程。这可以认为是一种对过程级变量的的保护。
  • 一般的过程变量,都是过程,开始运行时才重新分配内存(重新初始化),过程结束就重置了,这也是一般变量都不允许在过程外赋值的原因。因为即时是一个 声明为 public 变量,在某个过程内的赋值,也只有运行这个过程时才生效。
  • 而想要调用这个 public变量,在其他过程中的值,就必须调用那个 给这个 public变量赋值的过程,这就是过程调用。并且,只有1个程序调用另外一个程序过程中,才可以读到其他 程序的变量的值。

6.2 怎么调用? 调用变量的几个条件

变量如果想在多个程序之间调用

  • 首先要声明为 非局部变量。
  • 需要调用变量所在过程/函数,才能调用其他过程内的变量 (变量的赋值都在过程内,虽然变量可以声明在过程外)

6.3 调用常量

和调用变量是一样的,见下面的例子


6.4 变量的传递方式

情况1:为了调用其他程序的变量,而调用其他程序

本程序(主程序)调用其他程序(被调用程序)时,可以取到其他程序的参数

变量的调用,需要声明为非局部变量,且需要调用变量所在的代码,

情况2:为了给其他程序的主动传递变量,而调用其他程序,并获得回调

本程序(主程序)调用其他程序(被调用程序)时,可以把参数传给其他程序,并取得回调。而并调用的程序,被调用时必须传参数给它,否则无法正确调用

  • 被调用的程序,可以设定2种传递方式,进而影响给主程序的回调值。
  • 也就是会不会受影响,不由 主程序 决定!?

  • byref ,被调用程序 按地址传递,传回主程序的参数,回调时会受影响。
  • VBA默认按地址传递,方便管理?

  • byval  ,被调用程序 按值传递,传回主程序的参数,回调时会不受改变。

按地址传递(ByRef),是指主程序直接将数据交给子过程(过程中定义传递方式),在过程中修改、调试、返回给主程序,主程序输出的是修改后的值。

例如:如果我在参数中设为ByRef,那么ByRef的这个变量我可以改变它的值

按值传递(Byval),是指将主程序的值(副本一份)给子过程,过程对副本操作,主程序输出的仍是原值。若想输出值传递后的值,可在子过程中设置输出。

6.5 还有其他各种调用

  • 参数,变量得调用
  • 过程/函数得调用
  • 模块得调用
  • 被调用结束前,是不会释放得. 也就是除非调用它们得 宿主程序释放,否则不会释放

7 实例

7.1 实例:   变量的成功调用(工程级作用域,跨模块调用)

举例:模块1代码

Public t1
Public t2
Global Const t3 As Integer = 777

Sub bbtest1()
Dim k1

t1 = 100
k1 = 1000

End Sub


Private Sub bbtest2()
Dim k2

t2 = 101
k2 = 1001

End Sub

模块2代码

  • 要成功的调用需要满足2个条件
  1. 必须要先调用这个变量的过程/函数
  2. 这个变量,必须是非过程级的,模块级的/工程级的
  • 如果  private 声明了一个过程,则这个过程只能被模块内调用,不能被跨到 模块2调用,这里会报错
Sub cctest1()

Debug.Print "t1=" & t1
Debug.Print "k1=" & k1

End Sub



Sub cctest2()

Call bbtest1
Debug.Print "t1=" & t1
Debug.Print "k1=" & k1

End Sub



Sub cctest3()

'Call bbtest2    '报错,因为bbtest2 是private 无法被其他模块的程序调用
Debug.Print "t1=" & t2
Debug.Print "k2=" & k2

End Sub

7.2 实例:   静态变量的成功调用

静态变量  static

  • 静态变量,肯定都是过程级变量(局部变量),只能声明在过程内,函数内
  • 静态变量的特点,是只要静态变量所在的模块,工程没关闭,静态变量都不会释放
  • 不会释放是什么意思?也就是说 内存空间不会释放,变量不会被重置掉。
  • 而一般的过程变量,都是过程,开始运行时才重新分配内存(重新初始化),过程结束就重置了,这也是一般变量都不允许在过程外赋值的原因。因为即时是一个 声明为 public 变量,在某个过程内的赋值,也只有运行这个过程时才生效。
  • 而想要调用这个 public变量,在其他过程中的值,就必须调用那个 给这个 public变量赋值的过程,这就是过程调用。并且,只有1个程序调用另外一个程序过程中,才可以读到其他 程序的变量的值。
  • 被调用程序的声明周期,应该和主调程序生命周期一致。
  • 利用这个可以做啥?
  • 静态变量在程序已经不在它们的过程里时仍然不会丢失它们的内容
  • static一个典型的用法,就是可以用来做累计值,反复调用其他程序时,自身的static变量一直在累计。

Private x
Private j

Sub Qtest1()

 Static sum1
' sum1 = 0    '不能加这句, 这相当于循环开始进行了归0,VBA里静态变量就是要利用不赋初值的特性
 Call Qtest2
 sum1 = sum1 + x
 Debug.Print "sum1=" & sum1
End Sub

Sub Qtest2()
 x = 5
End Sub


Sub Qtest10()
 Call Qtest20
 sum1 = sum1 + j + k    '这里的k,是用的本过程的,不是其他过程得k,也没有更高作用于的k
 Debug.Print "sum1=" & sum1
End Sub


Sub Qtest20()
 j = 5
 k = 5    'k是过程变量,是无法传出去的
End Sub

 

7.3 实例:   常量的成功调用

  • 常量基本和变量也是一样
  • 按常量的 声明关键字的,定义在过程内,还是模块外,用的 dim ,private 还是 public global
Const x2 = "hi"


Sub testnew1()
Const x1 = "hello"
End Sub


Sub testnew2()
Call testnew1
Debug.Print "x1=" & x1
Debug.Print "x2=" & x2
End Sub

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常好的问题!让我来回答你的问题。 首先,关于VBA学习笔记(一):自动添加代码,你可以使用VBA的宏来自动添加代码。具体步骤如下: 1. 打开你要添加代码的Excel文件,并按下Alt + F11进入VBA编辑器界面。 2. 在左侧的“项目资源管理器”窗格中,展开你的Workbook,并双击“这台电脑”(或“Microsoft Excel 对象”),打开相应的代码窗口。 3. 在代码窗口的顶部,选择“工具” > “宏” > “录制新宏”。 4. 在弹出的“新建宏”对话框中,为新宏命名,并选择一个快捷键,以便日后调用。 5. 点击“确定”后,VBA会自动开始录制你的操作。 6. 在代码窗口中,添加你需要自动执行的代码。 7. 完成代码添加后,点击“停止录制”按钮,保存你的新宏。 接下来,关于VBA修改注册表,你可以使用VBA的“WshShell”对象来实现。具体步骤如下: 1. 在VBA编辑器中,打开你要修改注册表的代码窗口。 2. 在代码窗口的顶部,添加以下代码: ``` Dim WshShell As Object Set WshShell = CreateObject("WScript.Shell") ``` 这将创建一个名为“WshShell”的对象,用于执行后续的注册表修改操作。 3. 接下来,你可以使用该对象的“RegWrite”方法来修改注册表。例如,以下代码将修改Windows启动时自动运行的程序列表: ``` WshShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\MyApp", "C:\MyApp.exe", "REG_SZ" ``` 该代码将在“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”键下添加一个名为“MyApp”的值,其值为“C:\MyApp.exe”,类型为“REG_SZ”。 4. 完成代码添加后,保存并执行你的代码。 希望这些步骤对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值