我正在使用VBA将粘贴内容从Excel复制到PowerPoint。它正在工作,但是我需要清理代码。问题是我不知道在多个过程中使用的变量(或对象)有什么好的做法。我认为我在这方面缺乏一些基本的了解。
将变量从一个过程传递到另一个过程时,在两个过程中使用相同的名称是一个坏主意吗?例如
Sub 1()
Dim a As Long, b As Long
Call Sub2(a, b)
'...
End Sub
Sub2(a As Long, b As Long)
'...
End Sub
Sub2
是否应以不同的方式调用变量,例如x和y?如果没有,我将回到问题1):将这些变量直接从Sub1
传递到Sub2
而不在全局进行声明的原因是什么?当我打算在调用a
之后使用b
中的Sub1
和Sub2
的原始值时得到它(因此基本上将它作为ByVal
传递给{{ 1}}),但我的情况并非如此。
是否有理由限制全局变量的使用?我在代码中将其保留为本地,但是应该全局定义Sub2
,lRowAn
等吗?
何时应将变量从子变量传递给另一个?在下面的代码中,用lRowData
做到这一点对我来说很有意义,但对iSlides
而言却没有意义。
以下是我的实际代码的一部分。子wsEm
和EmData
非常相似,我将看看是否可以合并它们,但是它们很好地说明了我的问题,因为它们使用了许多相同的变量。
EmDataAn
这与代码功能无关,而是在一般情况下如何使用变量。
答案 0 :(得分:3)
首先,将每个变量声明为局部变量。例如,如果仅在一个过程/函数中需要它,则在那里声明它。
如果您需要通过多个过程/函数访问变量,则最好将其作为参数传递给下一个函数。可以ByRef
(默认)或ByVal
来完成。
Sub ProcedureA()
Dim ParamA As String
ParamA = "AAA"
Dim ParamB As String
ParamB = "BBB"
ProcedureB ParamA, ParamB
Debug.Print ParamA 'returns 111
Debug.Print ParamB 'returns BBB
End Sub
Sub ProcedureB(ByRef Param1 As String, ByVal Param2 As String)
Param1 = "111" 'this will change ParamA in ProcedureA too
Param2 = "222" 'this value will only be changed in ProcedureB
End Sub
虽然使用ByRef
(通过引用)可以更改ProcedureB
中的参数,也可以在ProcedureA
中对其进行更改,但是传递的参数ByVal
(按值)在ProcedureA
中保持不变。
如果您以不同的方式命名变量或使用相同的名称,从技术上讲,这没有什么区别。最好在每个过程中使用最有意义的名称(请参见下面的标题变量名称)。
实际上,我认为始终指定它是ByRef
还是ByVal
而不使用默认值也是一种好习惯。使用默认值时,您始终必须记住,在VBA中默认值是ByRef
,但在VB.NET中默认值是ByVal
,这很容易引起混淆(至少是我)。
ProcedureA
结束后,变量不再可用(数据丢失)。
如果您希望数据具有持久性并且可以通过多个函数进行访问,请使用全局变量(尽可能少使用)。
Dim GlobalVarA As String
Sub ProcedureA()
GlobalVarA = "AAA"
End Sub
Sub ProcedureB()
Debug.Print GlobalVarA 'return AAA (if ProcedureA was run before)
End Sub
请注意,在这种情况下,任何过程都可以更改GlobalVarA
的值。如果如上所述将其作为参数传递,则只有将变量传递给的过程才能访问该变量。
Excel VBA结束(或文件关闭)时,全局变量将丢失其数据。
在过程中使用全局变量的缺点是,您始终需要在首次使用它之前检查它的值。因为如果尚未初始化,它是Empty
或Nothing
。例如(上),在运行ProcedureB
时,您不能依靠ProcedureA
已经运行过。因此,在GlobalVarA
中使用ProcedureB
之前,您需要检查Nothing
的值,特别是如果它是一个对象,则必须测试是否不发声Dim VarA As String 'global
Sub ProcedureA()
Dim VarA As String 'same name local
VarA = "AAA" 'this uses always the local variable!
End Sub
Sub ProcedureB()
Debug.Print VarA 'this uses the global variable and it is empty (after ProcedureA is run)
End Sub
,否则很容易出错。
因此我们可以总结一下,尽可能限制对变量的访问将使您的代码更安全,更可靠(如果仅在本地声明,则其他任何函数都不会意外更改它)。仅在确实需要时使用全局变量。
如果在本地声明变量名,那么重用变量名通常是没有问题的。但是,如果您对全局变量和局部变量使用相同的名称,则会变得很棘手(然后VBA会首选局部变量!)
rng1
通常,仅使用有意义的变量名是一个很好的做法。这意味着要调用变量rng2
和InputRange
,而不是调用变量OutputRange
和i
。另外,如果您需要计数器(例如遍历行和列),通常会使用j
和iRow
,但是如果使用例如iCol
和{{1} }作为变量名。
为了强制执行正确的变量声明,我建议始终激活Option Explicit
:在VBA编辑器中,转到工具› 选项› { {3}} 。这样可以防止您错误键入变量名称并意外引入新变量。
答案 1 :(得分:1)
1) When passing a variable from one procedure to another, is it a bad idea to use the same name in both procedures?
有两种方法可以将参数传递到另一个过程ByVal
和ByRef
。
默认情况下,VBA使用ByRef
,所以这样做:
Option Explicit
Sub Test()
Dim i As Long
For i = 0 To 1000
Call Tested(i)
Next i
End Sub
Sub Tested(i As Long)
i = i + 1
End Sub
将使您发疯,因为从第一个循环起,i = 0
将跳到i = 2
。为什么?因为Tested()
将1加到i
上,而Next i
中的Test()
又加上一个。
如何避免这种情况并且仍然使用相同的变量?使用ByVal
,以便为Tested()
赋予i
的值,并且对Tested()
进行的更改不会影响您的初始循环。
全局变量?尽可能不要使用它们。
何时根据我的经验使用它们?
例如,在工作簿中使用许多工作表以及将调用它们的不同过程,然后只需对所有工作表进行子设置并将其声明为全局。
其他情况下,我认为没有必要,因为像QHarr所说的那样,对于优化将参数传递给过程的速度更快。