从vba中的sub调用函数

时间:2019-07-15 13:15:11

标签: excel vba function

我编写了此函数,该函数应该从选定的范围内获取用户定义的单元格,并将其值与用户定义的数字相加或相乘。输出应为具有一个已更改单元格的数组。

我能够编译它;但是,我不能称呼它。

我试图复制thisthis,但是失败了。

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()行以黄色突出显示,而其下方的行则显示为红色

2 个答案:

答案 0 :(得分:6)

我看到了几个问题:

第一

Result = Macro1

Macro1中是对Macro1的递归调用。即Macro1正在尝试自我调用。

由于Macro1需要参数,而第一个参数是ObjectRangeObject),因此会出现错误提供一个对象参数。事实上,您没有在此调用中提供任何必需的参数。


第二,代码:

<functionName> = value

倒退。该行试图将Macro1(赋值运算符<functionName>左侧的=)设置为Result的值。这是不可能的(至少在VBA中没有)。我相信您想要的是:

result = Macro1(Worksheets("Macro1").Range("A1:AX3"), 2, 2, 0.5, 1)

这将使用指定的参数执行Macro1,然后将返回值(如您所定义的Variant)分配给Variant变量(因为您没有{ {1}}({1}}。


第三,您已经将Dim声明为result,但是没有必要-它不是 返回值,它是在Macro1中设置单元格已通过。最好将其更改为Function,因为这是它所做的工作。我认为您可能打算让它在行Range中返回一个值,但是如上所述,这是不行的。 VBA的工作原理是将要返回的值分配给Sub名称,而不像其他某些语言那样使用Result = Macro1函数。如果确实要返回某种结果,则可以使用以下代码为其分配代码:

Function

但是,我不确定您作为return会从中实际得到什么,因为它可以在Macro1 = <the value to be returned> 而不是单个Function上工作


第四,我不确定您为什么接受整个Range作为Cell的参数,然后在其中指定一个Range它。传递Macro1,然后指定我想要该范围的Cell...Range("A1:AX3") way 太多的认知努力,无法理清您要跟踪的单元格。为什么不仅仅传递column 2并完成它呢?好处是

1)Row 2直接与所需的单元格一起使用,并且仅与所需的单元格一起使用

2)呼叫者仅指定所需的单元格,并且仅指定所需的单元格

3)您可以从参数列表中删除其他不必要的参数。


第五,您的...Range("B2")收到一个Macro1参数,但从未引用过。您接受Macro1,但是在代码体中,您正在使用Range,并且从未引用过cellref As Range。有两个问题:

1)您有未指定的Cells(),无论您的意图是什么,它都会自动引用cellref

2)您根本不使用em呼叫Cells()时传递的内容(可能在 any ActiveSheet中的Macro1)。

通过指定Worksheet,您在做给 Workbook的电话时非常具体,以使VBA准确地知道 哪个单元格。你在追。但是,如果您在通话时正看着Macro1,则Worksheets("Macro1").Range("A1:AX3")将与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 )个 all 变量,然后再使用它们。这将有助于消除其他可能的错误,因为您将Option Explicit拼错为Dim,而VBA“有帮助”地为您创建了一个全新的变量,从而创建了一个很难发现的错误。


基于其他一些评论,我认为您正在尝试为范围内的许多单元格调用此方法。在这种情况下,您可以向Variable1过程添加一些简单的循环,以遍历所有需要应用的单元格。如果不是,并且您正在基于该范围内的其他值尝试将其应用于Varaible1中的一个单元格,则需要修改其中的一部分以执行后续操作。我希望这篇文章中有足够的信息供您了解如何做到这一点。如果没有,一旦您完全了解了更改此单元格的过程,那可能会引起一个很大的后续问题。


作为旁注,有一个很棒的OSS VBE插件,名为Rubberduck,可帮助您发现和修复许多此类错误。我是该工具的忠实拥护者,每天都会使用它,我也为该项目做出了贡献。

答案 1 :(得分:0)

首先,您不需要不需要的cellref参数。

@nacorid和@Jnevill表示结果= Macro1不执行任何操作,代码只是跳过了它。如果要返回函数,则为Macro1 = result。但是,您不分配任何结果,因此它仍然不会做任何事情。您还需要在sub try()中创建一个分配以获取回报。

我不确定您的期望输出是一个具有一个已更改单元格的数组,您正在更改一个单元格,但它不是一个数组,您只是通过以下这一行直接更改其值:{{1 }}

编辑: 这是加载数组,修改并将其粘贴到其他地方的方法。

您将需要添加一些错误处理,以免类型不匹配。

您可能还想使用粘贴范围的偏移量使其更具动态性。

Cells(row_number, column_number) = Cells(row_number, column_number) * x