从 vba 中的 sub 调用函数
Posted
技术标签:
【中文标题】从 vba 中的 sub 调用函数【英文标题】:Call a function from sub in vba 【发布时间】:2019-07-15 13:15:11 【问题描述】:我编写了这个函数,它应该从选定的范围中获取用户定义的单元格,并将其值与用户定义的数字相加或相乘。输出应该是一个包含一个已更改单元格的数组。
我能够编译它;但是,我不能调用它。
我尝试复制 this 和 this 的内容,但失败了。
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()
行以黄色突出显示,其下方的行以红色突出显示
【问题讨论】:
在Cells(row_number, column_number) * "x"
中,"x"
是文本而不是变量。将其更改为 Cells(row_number, column_number) * x
与 + "x"
相同
@Pᴇʜ 完成,但我仍然收到相同的错误消息
请告诉您在哪几行中出现错误。
Range("A1:AX3").Select
应该只更改为 Range("A1:AX3")
该函数要求将 Range
类型传递给它。相反,您将传递 .Select
方法的输出在范围内(变体,而不是范围),而不仅仅是传递范围本身。所以:Macro1(Range("A1:AX3"), 2, 2, 0.5, 1) = Result
在这段代码中,什么是“原始数组”。您正在调用一个函数,但从该函数中什么也得不到。 Result = Macro1
没有意义,因为 Result
一个你没有声明的变量被设置为空,因为 Macro1
从未在它的函数中设置。我在这里看不到任何数组,只是对单元格和范围的操作。我相信这里存在层层误解。
【参考方案1】:
我发现了几个问题:
首先,行
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
med它)@ 987654340@.
第三,您已将 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
(可能在 any @987654368 @ 在Workbook
)。
通过指定Worksheets("Macro1").Range("A1:AX3")
,您在调用到Macro1
时做得非常具体,以便VBA 知道准确您要查找的单元格.但是,如果您在通话时碰巧正在查看Sheet2
,则Macro1
将使用Worksheets("Sheet2").Range("B2")
,因为此时Activesheet
= Worksheets("Sheet2")
而不是Worksheets("Macro1")
。
第六您没有对输入值进行完整性检查。如果传递的单元格中的值恰好是red
而不是17.256
,会发生什么情况。 red * 2
的值是多少?为什么,它是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“有用地”为您创建了一个全新的变量,为您创建了一个很难找到的错误。
基于其他一些 cmets,我认为您正试图为一个范围内的许多单元格调用它。如果是这种情况,您可以在Try()
过程中添加一些简单的循环,以遍历需要应用它的所有单元格。如果不是,并且您正试图根据该范围内的其他值将其应用于Range
中的一个单元格,您将需要修改其中的某些部分来完成您所追求的工作。我希望这篇文章中有足够的信息让你弄清楚如何做到这一点。如果不是这样,一旦您完全了解了更改此单元格的过程,这可能会成为一个很好的后续问题。
附带说明一下,有一个很棒的 OSS VBE 插件,名为 Rubberduck,它可以帮助您找到并修复许多此类错误。我是这个工具的忠实粉丝,我每天都在使用它,我也为这个项目做出了贡献。
【讨论】:
很高兴你发现它有帮助,@Maria【参考方案2】:首先,你不需要不使用的 cellref 参数。
正如@nacorid 和@Jnevill 所说,结果 = Macro1 没有做任何事情,代码只是跳过它。如果你想返回你的函数,那就是 Macro1 = result。但是,您没有为结果分配任何内容,因此它仍然不会做任何事情。您还需要在 sub try()
中创建一个分配以获取回报。
我不确定您的预期输出是什么意思是一个已更改单元格的数组,您正在更改一个单元格,但它不是一个数组,您只是直接使用以下行更改它的值:Cells(row_number, column_number) = Cells(row_number, column_number) * x
编辑: 以下是加载数组、修改并粘贴到其他位置的方法。
您需要添加一些错误处理以避免类型不匹配。
您可能还希望使用粘贴范围的偏移量使其更具动态性。
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
【讨论】:
我正在更改一个单元格,这是真的,但是这个单元格位于一个单元格数组中,其中每个单元格都有一个值。预期输出 = 包含所有原始值和一个更改值的整个数组 那么您需要将单元格值分配给数组,使用要更改的单元格的数组中的索引修改值,然后返回数组。如果您尝试将新值与数组的其余部分一起粘贴,则需要将数组转储到新范围中。 这正是我的意思并尝试(但失败)了。能具体说明一下吗?以上是关于从 vba 中的 sub 调用函数的主要内容,如果未能解决你的问题,请参考以下文章