草稿
'1.1 参数的传递,应该还是要以
'Public index1 '传不过去,擦, 这是之前,想把一个form里的变量,传递给其他form 不管用
'怀疑,可能只能public private 只再模块间是这样的
'测试下
'但好方法?,确实先把东西存再excel表,也就是数据库,之后在读,这样安全?
感觉存在数据库表里,是个好思路
0 名词解释:
0.1 作用域
- 常量/变量的作用域
- 作用域是指这个变量允许在什么地方 使用/ 调用变量。
- ( 反过来说就是那些程序可以访问到这些变量)
- 作用域有各种说法
- 公有变量/全局变量/跨模块变量 public
- 模块级变量 private 或 dim
- 私有变量/ 过程级变量 dim 或 static
- 声明变量的作用域,一定要在模块最开始声明
- 如果只在模块中间声明,比如某些过程后面,会有问题。因为代码是顺序执行的,没执行到那,那个变量在之前还不是全局变量等,所以要在模块最开始声明
0.2 生存周期:(声明作用域会影响生命周期)
- 常量/变量的生存周期
- 变量保留其值的时间,称为生存周期。
- 生存周期的 start : 赋值的过程,开始生效(也就是即使声明为public,赋值所在的过程,不允许,变量的值还是没被改变,可能还是"")
- 比如public a1 在模块开始声明时其实已经创建了,但没赋值,还是为空
- 生存周期的 end : 赋值的过程,已经结束,回收变量,消灭了。(但是声明public private的变量,在过程结束后,并不回收,而是整个模块(其实是整个workbook关闭了)关闭才会回收)
- if 常量在模块开头定义和赋值,生存周期就是整个模块加载期间。
- if 常量定义在过程/函数里,就是过程/函数 生命期内。
- VBA里一般变量(非静态static变量)都在过程内,赋值,生命期也是,离开这个过程,除非已经调用到内存,否则过程外是不生效的,因为已经回收消灭了。
- 静态变量与动态变量 动态变量是指被过程调用时均重新初始化的变量,而静态变量在初始化后,下一次调用时仍保留上次的值的变量。
声明变量作用域会影响变量的生命周期的关系
- 模块级的变量,只要不关表(模块一直在加载)就一直在生效,不会被消灭!。比如public private dim 定义在模块最开始的地方的( dim定义在过程内的不算模块级变量)
- 过程级变量,过程运行结束马上消灭,变量每次重置计算,特殊的static记住之前的
下面是网上查的资料
这个 https://blog.csdn.net/qq_25582033/article/details/117427865
比方说你在一个xls文件中有两个工程(应该1个EXCEL表都只有1个工程吧),那么在某个工程中的模块如果不写这个语句,那么两个工程都可以用这个模块的内容。如果写上Option Private Module,那么另外那个工程就不能使用这个模块的内容。
下面表格里有几个地方是错的,private声明的变量,因为必须在模块顶部(只要是声明在模块顶部的,即使是 dim 或 public private都一样,因为都是模块级变量了),所以一旦过程内运行赋值后,其声明周期不是过程有效期内,而是模块/整个EXCEL的 workbook 文件有效期内都在生效,而并没有被释放消灭。
下面的代码可以证明
Private Sub tf2()
Debug.Print "x= " & X
Debug.Print "y= " & y
Debug.Print "z= " & z
Debug.Print "z1= " & z1
End Sub
'模块级的,只要不关表就一直在
'过程级马上没,一般变量每次重置计算, static记住之前的
Private Sub tf3()
X = 1
y = 111
z = 222
z1 = 333
End Sub
0.3 即使写了参数调用 和 声明作用域,也得先运行那个程序
因为即使是一个public变量,作用域是全局,但是没有被其他程序赋值改变前,值为空
- VBA 并不会,自动运行这个变量的相关的其他 block,
- VBA 和其他代码一样,都是顺序执行的
- 即使声明了某模块级变量,但是如果还未运行赋值过程给这个 模块级变量,那么这个 模块级变量仍然还是 "" none null nothing 等等,运行了赋值过程后,虽然赋值过程本身消灭了,但是这个模块级变量的值会一直保留,且可以被修改到,这个模块结束(被关闭)之前。
0.4 特殊的静态变量 Static (很适合用来计数--因为模块内不清除)
- static 变量 特殊性:生命周期效果类模块级变量,但是作用域还是过程级的变量。这么特殊,可能时比public等更安全点
- VB允许你通过改变声明方式延长当地变量的存活期,这种就是 static 静态变量
- 很特殊,首先是变量,不是常量 (可改变)
- 而且仍然是过程级,外部程序无法访问
- 但是可以在模块结束之前,一直都存在, 生命周期效果类 模块级变量,但是作用域还是过程及的变量。
Const aaa1 = 2
Public Const aaa2 As Integer = 111
Public y
Private z
Dim z1
Sub tf1()
Const aaa5 = 555
'Public Const aaa6 = 666
Debug.Print "aaa1= " & aaa1
Debug.Print "aaa2= " & aaa2
Debug.Print "aaa5= " & aaa5
'Debug.Print "aaa6= " & aaa6
End Sub
Private Sub tf2()
'没法调用过程了里得变量的!只能调用过程。
' 函数特殊,有返回值的函数可以当变量调用,但本质还是 调用函数,只是函数返回值是这样
Debug.Print "x= " & X
Debug.Print "y= " & y
Debug.Print "z= " & z
Debug.Print "z1= " & z1
Debug.Print "z2= " & z2
End Sub
Private Sub tf3()
X = 1
y = 111
z = 222
z1 = 333
Static z2
z2 = z2 + 1
Debug.Print "内部X= " & X
Debug.Print "内部z2= " & z2
End Sub
1第1部分,模块内和模块之间的 直接使用和调用
1.1 常量的 直接使用和调用
- 常量的直接使用,非传递的话,想直接使用只能靠声明
- 常量一般都是声明了直接使用吧,本身不变,没有什么调用的必要了吧?得查查后以后看
1.2 常量的定义,赋值和生命周期
- 常量的声明和定义 (声明和定义一般是一块儿,但赋值一般是在计算时才赋值)
- 常量可以声明,声明在模块开始
- 常量的赋值
- 赋值在哪儿,决定了常量的生命周期
- 如果常量赋值在模块开始,整个模块内都生效,在本模块内常量不会被释放(变量是不允许在 过程外赋值的!)
- 赋值在过程内,只能在过程内生命周期内有效,过程结束就释放了
Const aaa1 = 2
Public Const aaa2 As Integer = 111
Sub tf1()
Const aaa5 = 555
'Public Const aaa6 = 666
Debug.Print "aaa1= " & aaa1
Debug.Print "aaa2= " & aaa2
Debug.Print "aaa5= " & aaa5
'Debug.Print "aaa6= " & aaa6
End Sub
1.2.1 直接使用常量
- 直接使用常量,靠常量本身的声明的使用域的范围
- private 不能跨模块,这个级别声明,只能在本模块内的,不同过程/函数之间用
- public可跨模块,本模块内所有,其他模块的都能直接使用
- 本例中,因为取不到其他模块的private内容,a1会被识别为本模块的 过程级变量名,而且因为没定义没赋值,就为空
'----------------此处是模块5,下面是模块6的内容------------------
'1常量
Private Const a1 = 5
Public Const a2 = 5
Public b5
'----------------此处是模块6,下面是模块6的内容------------------
Private Const a3 = 777
Private Const a4 = 778
Private b7
Public b8
Sub test0001()
Debug.Print "调用常量" & "private 不能跨模块,public可跨模块,取不到其他模块的private内容,a1只能识别为本模块的 过程级变量名"
Debug.Print "其他模块的 a1=" & a1
Debug.Print "其他模块的 a2=" & a2
Debug.Print "a3=" & a3
Debug.Print "a4=" & a4
Debug.Print
End Sub
1.3 常量的调用
常量一般都是声明了直接使用吧,本身不变,没有什么调用的必要了吧?
2 变量的使用 和调用
2.1 代码的封装,无法访问 封装内部的变量,只能整体调用
- 也就是外部代码无法访问封装部分内部的内容,但是可以访问其外部整体调用
- 那些东西是封装的:过程/函数等完整的block,而不是那种顺序流的
- 过程/函数封装的内部到底有啥:变量,一些处理逻辑表达式
- 不能直接调用其他过程内的变量,而只能根据作用域,调用这些过程,并且只能执行这些过程这个动作,并不能引用 那些过程的结果"
2.2 整体调用方式
- 怎么叫 整体调用,就是调用,过程名,call t1() 这种 整体调用。
- 特殊的
- 但是函数特殊,有返回值的函数可以当变量调用,把 特殊变量 = 函数名(代表函数)
- 但本质还是 调用函数,只是函数返回值是这样
function t2
t2=XXXX
end function
- t2= XXXX 相当于return ,只有函数function 可以这样返回,sub 过程不能这样return
2.3 调用过程,也需要看 过程本身的作用域,比如private sub 无法被跨过程调用
- sub / function 因为本身就存在于模块级,不存在在过程中的可能,所以默认是全局的 public
- (默认 public ) sub
- 可以主动声明为 private sub
- Option Private Module ,写在模块开头,会设置下面的所有的 过程/函数都是private的
2.4 过程/函数的 作用域和 变量本身作用域 完全无关! 独立的
3 函数和变量的调用
- 函数包括带返回值,和不带返回值的情况
- 函数如果不带返回值时,类 sub,基本和sub一样的处理
- 但是function 带返回值,的情况是不同的
3.1 不带返回值的function 被调用参数时
- 直接无法访问,其他代码内部的变量,无论时本模块,还是其他模块的
- 因为访问其他变量的代码,本身是在 过程/函数内,所以,在本过程内,没有这些变量。就会认为是未定义的空变量
- 如果内存里已经有 其他过程内的变量,声明为 非过程级,比如 整个模块开始处定义的 public private dim,而且已经运行过其对应赋值过程,内存里变量已经生成,且因为 声明的作用域一直还处于生效期,则可以访问到其值。
- 特殊情况,如果不是在整个模块开始处定义的 public private dim,比如下面例子的 public d3 只是在过程前声明,而不是在整个模块开始处声明,则声明无意义。
- 如果 访问作为整体的 过程,则要i看过程/ 函数本身是否声明为 public private. 一般来说,默认过程/函数 默认都是 public ,也就是可以各个模块都访问。
- 但是可以强制声明为 private 只让本模块内的其他程序,call 调用他
- 但是至少最小的调用范围就是private了
'----------------此处是模块5,下面是模块6的内容------------------
'4函数,和变量 函数(函数名)可以作为变量用,有无返回值时
'函数,无返回值
Private Function e1()
d1 = 6
Debug.Print "内部 d1= " & d1
End Function
Public Function e2()
d2 = 6
Debug.Print "内部d2= " & d2
End Function
'----------------此处是模块6,下面是模块6的内容------------------
Public d3
Sub test03()
d3 = 5
d4 = 6
d5 = 7
Debug.Print "内部d3= " & d3
Debug.Print "内部d4= " & d4
Debug.Print "内部d5= " & d5
End Sub
Sub test0004()
Debug.Print "d1= " & d1
Debug.Print "d2= " & d2
Debug.Print "d3= " & d3
Debug.Print "d4= " & d4
Debug.Print "d5= " & d5
End Sub
Sub test0005()
'Call e1 '会报错,子过程 sub 或函数 function 未定义!
Call e2
End Sub
3.2 如果函数带返回值了,是一种特殊处理, 变量名= 函数名= 函数返回值return
- 核心就是特殊处理 :变量名= 函数名= 函数返回值return
sub内的代码,声明周期也是过程级,应该不影响其他吧
- Application.DisplayAlerts = False
- 这个声明的生命周期也应该在sub内,有啥必要非在sub结尾前关闭掉?多此一举把
2.2
'----------------此处是模块5,下面是模块6的内容------------------
'1常量
Private Const a1 = 5
Public Const a2 = 5
Public b5
'2变量
'VBA 变量的声明可以在 过程/函数的内/外,但是赋值只能在过程/函数的 内
'bbb = 555 '报错,无效的外部过程
'3过程和变量,调用过程只能用call
Private Sub t1()
b1 = 61
' t1 = 61 '报错,缺少函数/或变量,相当于return ,只有函数可以这样返回,sub 过程不能这样return
Debug.Print "内部b1= " & b1
End Sub
Public Sub t2()
b2 = 62
' t2 = 62 '相当于return ,只有函数可以这样返回,sub 过程不能这样return
Debug.Print "内部b2= " & b2
End Sub
Sub t3()
b9 = 69
' t3 = 63 '相当于return ,只有函数可以这样返回,sub 过程不能这样return
Debug.Print "内部b9= " & b9
End Sub
'----------------此处是模块6,下面是模块6的内容------------------
Private Const a3 = 777
Private Const a4 = 778
Private b7
Public b8
Sub test0001()
Debug.Print "调用常量" & "private 不能跨模块,public可跨模块,取不到其他模块的private内容,a1只能识别为本模块的 过程级变量名"
Debug.Print "其他模块的 a1=" & a1
Debug.Print "其他模块的 a2=" & a2
Debug.Print "a3=" & a3
Debug.Print "a4=" & a4
Debug.Print
End Sub
Public Sub test01()
b7 = 111
Debug.Print "内部b7= " & b7
End Sub
Private Sub test02()
b8 = 222
Debug.Print "内部b8= " & b8
End Sub
Sub test0002()
Debug.Print "直接调用其他函数过程里的变量是不行的!封闭性,程/函数 内部的内容都是封装的,外部不能访问,只能整体调用"
Debug.Print "b1=" & b1
Debug.Print "b2=" & b2
Debug.Print "b7=" & b7
Debug.Print "b8=" & b8
Debug.Print "b9=" & b9
End Sub
Sub test0003()
Debug.Print "调用过程/函数,也要看 过程/函数本身的 作用域声明,这个和变量的作用域完全独立"
Debug.Print "一般默认过程/函数,都是模块级的,public 公有的"
Debug.Print "不能直接调用其他过程内的变量,而只能根据作用域,调用这些过程,并且只能执行这些过程这个动作,并不能引用 那些过程的结果"
'Call t1 '非public 过程,无法被这么调用
Call t2
Call t3
Call test01
Call test02
End Sub
'没法调用过程了里得变量的!只能调用过程。
' 函数特殊,有返回值的函数可以当变量调用,但本质还是 调用函数,只是函数返回值是这样
Private Sub tf2()
'没法调用过程了里得变量的!只能调用过程。
' 函数特殊,有返回值的函数可以当变量调用,但本质还是 调用函数,只是函数返回值是这样
Debug.Print "x= " & X
End Sub
Private Sub tf3()
X = 1
End Sub
1.2.1 变量的直接使用
1.2.2 变量的调用
第2是调用
而传递,可以绕开声明,也可以跨过程
形式和实际
传递方法
位置参数
名称参数
混合的,名称的在后,好像是
---------
'在模块里试下,在form里试下,在workbook和sheet里试下
'然后再试下,能不能跨这几个
'VBA的一个BUG,修改函数,变量的声明范围后,比如去掉加上public 有时候,需要关掉重开,运行代码才会正常,还按老的,
'VBA,甚至跨模块调用时,赋值也有这种滞后的问题
'调用,常量,变量/函数
'call 过程/函数
-------
然后 form内呢
然后三者互相呢
'在模块里试下,在form里试下,在workbook和sheet里试下
'然后再试下,能不能跨这几个
'VBA的一个BUG,修改函数,变量的声明范围后,比如去掉加上public 有时候,需要关掉重开,运行代码才会正常,还按老的,
'VBA,甚至跨模块调用时,赋值也有这种滞后的问题
'调用,常量,变量/函数
'call 过程/函数
1 先在模块里做了实验
'常量
Private Const a1 = 5
Public Const a2 = 5
Public b5
'过程和变量
Private Sub t1()
b1 = 6
t1 = 6
End Sub
Public Sub t2()
b2 = 6
' t2 = 6 '相当于return ,只有函数可以这样返回,sub 过程不能这样return
End Sub
'函数和变量
Private Function f1()
b3 = 55
c1 = 6
f1 = 6
End Function
Public Function f2() '过程/函数 不是默认public吗?
b4 = 66
c2 = 6
f2 = 6 '相当于return
b5 = 777
'Public b6 'vba,声明跨过程/函数级的参数,必须在 过程/函数 外部声明,一般是最开始(理论上使用前声明就行,但放最前面最安全)
' b6 = 777
End Function
'函数,无返回值
Private Function e1()
d1 = 6
End Function
Public Function e2()
d2 = 6
End Function
'在模块里试下,在form里试下,在workbook和sheet里试下
'然后再试下,能不能跨这几个
'VBA的一个BUG,修改函数,变量的声明范围后,比如去掉加上public 有时候,需要关掉重开,运行代码才会正常,还按老的,
'VBA,甚至跨模块调用时,赋值也有这种滞后的问题
'调用,常量,变量/函数
'call 过程/函数
Private Const a3 = 777
Private Const a4 = 778
Private b7
Public b8
Public Sub test01()
b7 = 111
End Sub
Public Function test02()
b8 = 222
End Function
Sub test001()
Debug.Print "调用常量" & "private 不跨模块,public可跨模块,取不到其他模块的private内容,a1只能识别为本模块的 过程级变量名"
Debug.Print "a1=" & a1
Debug.Print "a2=" & a2
Debug.Print "a3=" & a3
Debug.Print "a4=" & a4
Debug.Print
Debug.Print "调用其他函数过程里的变量" & "都不行,过程/函数 内部的内容()都是封装的,除非return拿到,否则只能靠声明变量拿到"
Debug.Print "b1=" & b1
Debug.Print "b2=" & b2
Debug.Print "b3=" & b3
Debug.Print "b4=" & b4
Debug.Print "b5=" & b5 '参数声明public还不够,还需要函数/过程也 public ?
Debug.Print "b6=" & b6
Debug.Print "b7=" & b7
Debug.Print "b8=" & b8
Debug.Print
Debug.Print "t1=" & t1
'Debug.Print "t2=" & t2 '过程名不能当 变量/函数 这样直接使用,只能call 调用?
'这样是变量,不是函数,但是无参数的不是默认自动去掉括号吗?
'Debug.Print "t2=" & t2()
'Call t1
Call t2
Debug.Print "f1=" & f1
Debug.Print "f2=" & f2
'Call f1
Call f2
Debug.Print "e1=" & e1
Debug.Print "e2=" & e2
'Call e1
Call e2
End Sub
'传递参数的几个思路
'存下来传递,存储,文件中,中转
'方法,按位置,按名称
'中转