繁体   English   中英

从vba中的sub调用函数

[英]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需要参数(第一个参数是ObjectRangeObject )),并且没有提供对象参数,所以会出现错误。 实际上,您没有在此调用中提供任何必需的参数。


,代码:

<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 2Row 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM