Had*_*iJo 0 excel vba excel-vba excel-2016
给出以下代码: 我似乎无法成功地将Range对象变量从一个子函数传递到另一个子函数.我花了整整一天时间研究和试验,然后才吞下骄傲来到这里.
请阅读下面的评论,并回答您有关为什么最后两行不会表现的任何想法.
Public Sub doSomethingToRows(ROI As Range)
*'do Something with the cell values within the supplied range*
End Sub
'
Public Sub testDoAltRows()
Dim RegionOfInterest As Range 'is this an object or not?
'*The following yields: Class doesn't support Automation (Error 430)*
'*Set RegionOfInterest = New Worksheet 'this just gives an error*
Set RegionOfInterest = Worksheets("Sheet1").Range("A1")
RegionOfInterest.Value = 1234.56 '*okay, updates cell A1*
Set RegionOfInterest = Worksheets("Sheet1").Range("B5:D15")
RegionOfInterest.Columns(2).Value = "~~~~~~" '*okay*
'doSomethingToRows (RegionOfInterest) 'why do I get "OBJECT IS REQUIRED" error?
doSomethingToRows (Worksheets("Sheet1").Range("B5:C15")) 'but this executes okay
End Sub
Run Code Online (Sandbox Code Playgroud)
备注
调用过程时,不需要使用Call关键字.但是,如果使用Call关键字调用需要参数的过程,则必须将参数列表括在括号中.如果省略Call关键字,则还必须省略argumentlist周围的括号.如果使用Call语法调用任何内部函数或用户定义函数,则会丢弃函数的返回值.
要将整个数组传递给过程,请使用数组名称后跟空括号.
从实际的角度来看,即使可以使用或不使用"Call"关键字调用Subs,但选择一种方式并坚持使用它作为编码风格的一部分是有意义的.我同意Comintern的观点 - 基于对现代VBA代码的观察,我认为使用"Call"关键字应该被视为已弃用.相反,在参数列表周围调用不带括号的Subs.
现在回答这个重要问题:
为什么你的代码会抛出错误?
以下面的子例程为例:
Public Sub ShowSum(arg1 As Long, arg2 As Long)
MsgBox arg1 + arg2
End Sub
Run Code Online (Sandbox Code Playgroud)
我们已经确定,如果不使用Call关键字,必须像这样调用Subs:
ShowSum 45,37
如果它被称为是什么会发生什么ShowSum(45, 37)?好吧,你甚至无法编译,因为VBA立即抱怨"预期=".这是因为VBA解析器看到括号并确定它必须是一个Function调用,因此它希望您使用"="赋值语句处理返回值.
那只有一个参数的Sub怎么样?例如:
Public Sub ShowNum(arg1 As Long)
MsgBox arg1
End Sub
Run Code Online (Sandbox Code Playgroud)
调用此Sub的正确方法是ShowNum 45.但是如果你在VBA IDE中键入它ShowNum(45)会怎么样?一旦将光标移出线条,您就会注意到VBA在子名称和左括号之间添加了一个空格,为您提供关于如何实际解释代码行的关键线索:
ShowNum (45)
Run Code Online (Sandbox Code Playgroud)
VBA并未将这些括号视为包围参数列表 - 而是将它们视为分组括号.大多数情况下,这都无关紧要,但在具有默认成员的对象中也是如此.
要查看此问题,请尝试运行以下命令:
Dim v As Variant
Set v = Range("A1")
Set v = (Range("A1")) '<--- type mismatch here
Run Code Online (Sandbox Code Playgroud)
请注意,标记的行上出现"类型不匹配".现在将这两个语句添加到监视窗口并查看"类型"列:
+-------------+-----+--------------+
| Expression |Value| Type |
+-------------+-----+--------------+
|Range("A1") | |Object/Range |
|(Range("A1"))| |Variant/String|
+-------------+-----+--------------+
Run Code Online (Sandbox Code Playgroud)
当您使用分组括号包围对象时,将评估其默认属性 - 对于Range对象,它是Value属性.
因此,VBA允许你在"将参数列表括号括起来"中实际上只是巧合 - 实际上,VBA只是将其解释为分组括号并相应地评估该值.您可以通过在Sub上尝试相同的事情来查看它在VBA中无效的多个参数,以调用参数列表周围带括号的Sub.
@PaulG
试试这个:
Public Sub Main()
Debug.Print TypeName(Range("A1"))
Debug.Print TypeName((Range("A1")))
End Sub
Run Code Online (Sandbox Code Playgroud)