[英]Call a function from sub in vba
我编写了此函数,该函数应该从选定的范围内获取用户定义的单元格,并将其值与用户定义的数字相加或相乘。 输出应为具有一个已更改单元格的数组。
我能够编译它; 但是,我不能这样称呼。
Function Macro1(cellref As Range, row_number As Long, column_number As Long, x As Double, method As Integer) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition
If method = 1 Then
Cells(row_number, column_number) = Cells(row_number, column_number) * x
ElseIf method = 2 Then
Cells(row_number, column_number) = Cells(row_number, column_number) + x
End If
Result = Macro1
End Function
Sub try()
Macro1(Range("A1:AX3").Select, 2, 2, 0.5, 1) = Result
End Sub
运行此代码时,出现错误消息“运行时错误424,所需对象”。 行Macro1(Range("A1:AX3").Select, 2, 2, 0.5, 1) = Result
突出显示为红色
然后我尝试
Function Macro1(cellref As Range, row_number As Long, column_number As Long, x As Double, method As Integer) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition
If method = 1 Then
Cells(row_number, column_number) = Cells(row_number, column_number) * x
ElseIf method = 2 Then
Cells(row_number, column_number) = Cells(row_number, column_number) + x
End If
Result = Macro1
End Function
Sub try()
Macro1(Worksheets("Macro1").Range("A1:AX3"), 2, 2, 0.5, 1)
End Sub
但是我收到“类型不匹配错误13”消息。 Sub try()
行以黄色突出显示,其下面的行为红色
我看到几个问题:
一 ,行
Result = Macro1
在Macro1
是对Macro1
的递归调用。 即Macro1
正在尝试自我调用。
因为Macro1
需要参数(第一个参数是Object
( Range
是Object
)),并且没有提供对象参数,所以会出现错误。 实际上,您没有在此调用中提供任何必需的参数。
二 ,代码:
<functionName> = value
是倒退。 该行尝试将Macro1
(赋值运算符=
左侧的<functionName>
)设置为Result
的值。 这是不可能的(至少在VBA中没有)。 我相信您想要的是:
result = Macro1(Worksheets("Macro1").Range("A1:AX3"), 2, 2, 0.5, 1)
将执行Macro1
使用指定的参数,然后将返回的值( Variant
如你定义它)的Variant
变量(因为你没有Dim
配有它) result
。
第三 ,您已经将Macro1
声明为Function
,但是没有必要-它不返回值,而是将其设置为已传递的Range
的单元格。 最好将其更改为Sub
,因为这是它正在做的工作。 我认为您可能已经打算让它在Result = Macro1
行中返回一个值,但是如上所述,它不会这样做。 VBA通过将要返回的值分配给Function
名称来工作,而不是像某些其他语言那样使用return
函数。 如果确实有想要返回的某种结果,则可以使用以下代码为其分配:
Macro1 = <the value to be returned>
但是,我不确定您从Function
实际返回的内容是什么,因为它可以在一个Range
而不是单个Cell
第四 ,我不确定您为什么要接受整个Range
作为Macro1
的参数,然后在其中指定单个Cell
。 传递...Range("A1:AX3")
然后指定我想column 2
和Row 2
的那个范围是太多的认知努力挑选出你是什么细胞后。 为什么不仅仅传递...Range("B2")
并完成它呢? 好处是
1) Macro1
直接与所需的单元格一起使用,并且仅与所需的单元格一起使用
2)呼叫者仅指定所需的单元格和所需的单元格
3)从参数列表中消除其他不必要的参数。
第五,您的Macro1
收到一个Range
参数以供处理,但从未引用它。 您接受cellref As Range
,但是在代码体中,您正在使用Cells()
并且从未引用过cellref
。 有两个问题:
1)您有一个未指定的Cells()
,它将自动引用ActiveSheet
,无论您的意图与否。
2)您根本不使用调用Macro1
时传递的内容(它可以在Worksheet
Workbook
任何 Worksheet
上)。
通过指定Worksheets("Macro1").Range("A1:AX3")
以便VBA 确切知道要在哪个单元格上,您在对 Macro1
的调用中非常具体。 但是,如果您恰巧在调用时正在查看Sheet2
,则Macro1
将与Worksheets("Sheet2").Range("B2")
因为此时Activesheet
= Worksheets("Sheet2")
而不是Worksheets("Macro1")
。
第六,您不对输入值做任何检查。 如果传递的单元格中的值恰好是red
而不是17.256
会发生什么。 red * 2
的值是多少? 为什么,这是Runtime error #13. Type mismatch
Runtime error #13. Type mismatch
。 您需要某种形式的健全性检查或错误处理,以确保您使用的是数字数据。
最后,我将通过执行前的健全性检查来建议这样的事情:
Function Macro1(cellref As Range, x As Double, method As Long) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition
Dim Result As Double
If Not IsNumeric(cellref.Value) Then
MsgBox ("The cell does not contain a numeric value")
Exit Function
End If
If method = 1 Then
Result = cellref.Value * x
ElseIf method = 2 Then
Result = cellref.Value + x
End If
Macro1 = Result
End Function
Sub try()
With Worksheets("Sheet1")
.Range("B2") = Macro1(.Range("B2"), 0.5, 1)
End With
End Sub
或者,您可以进行错误处理并按以下方式进行操作:
Option Explicit
Function Macro1(cellref As Range, x As Double, method As Long) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition
On Error GoTo ErrorHandler
Dim Result As Double
If method = 1 Then
Result = cellref.Value * x
ElseIf method = 2 Then
Result = cellref.Value + x
End If
CleanExit:
Macro1 = Result
ErrorHandler:
MsgBox ("The cell does not contain a numeric value")
Result = vbNull
Resume CleanExit
End Function
Sub try()
With Worksheets("Sheet1")
.Range("B2") = Macro1(.Range("B2"), 0.5, 1)
End With
End Sub
请注意, Option Explicit
的包含要求您在使用它们之前声明所有变量( Dim
)。 这将有助于消除其他可能的错误,因为您会错误地将Variable1
拼写为Varaible1
而VBA“有帮助”地为您创建了一个全新的变量,从而创建了一个很难发现的错误。
根据其他一些评论,我认为您正在尝试为范围内的许多单元格调用此方法。 在这种情况下,您可以向Try()
过程添加一些简单的循环,以遍历所有需要应用的单元格。 如果不是,并且您正试图基于该范围内的其他值将其应用于“ Range
的一个单元格,则需要修改它的某些部分以执行后续操作。 我希望这篇文章中有足够的信息供您了解如何做到这一点。 如果没有,那么一旦您完全理解了更改此单元格的过程后,可能会提出一个很大的后续问题。
附带说明一下,有一个很棒的OSS VBE附加软件,名为Rubberduck ,可帮助您发现和修复许多此类错误。 我是该工具的忠实拥护者,每天都会使用它,我也为该项目做出了贡献。
首先,不需要不需要的cellref参数。
就像@nacorid和@Jnevill所说的那样,结果= Macro1不执行任何操作,代码只是跳过了它。 如果要返回函数,则为Macro1 = result。 但是,您不分配任何结果,因此它仍然不会做任何事情。 您还需要在sub try()
创建一个分配以捕获返回值。
我不确定您期望的输出是一个具有一个已更改单元格的数组,您正在更改一个单元格,但它不是一个数组,您只是在此行直接更改其值: Cells(row_number, column_number) = Cells(row_number, column_number) * x
编辑:这是您加载阵列,修改并将其粘贴到其他位置的方式。
您将需要添加一些错误处理,以免类型不匹配。
您可能还希望使用pasterange的偏移量使其更具动态性。
sub macro1()
Dim rngarr() As Variant
Dim divisor As Double
Dim targetcol As Long
Dim targetrow As Long
Dim pasterange As Range
rngarr = Range("A1:AX3").Value
'Remember that your array starts at index 1
'A range that starts at row 2 will still have an index 1
targetcol = 2
targetrow = 2
divisor = 0.5
rngarr(targetrow, targetcol) = rngarr(targetrow, targetcol) * divisor
Set pasterange = Range("A5:AX7")
pasterange = rngarr
end sub
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.