如何从VBA函数中返回结果

341

如何从一个函数中返回结果?

例如:

Public Function test() As Integer
    return 1
End Function

这会产生编译错误。

我该如何使此函数返回一个整数?


12
文档:http://msdn.microsoft.com/zh-cn/library/office/gg264233%28v=office.14%29.aspx(说明:这是一个指向 Microsoft Office 相关文档的链接,提供了详细的开发者参考信息。) - Jean-François Corbett
3个回答

516

对于非对象返回类型,你必须将值分配给函数名称,像这样:

Public Function test() As Integer
    test = 1
End Function

使用示例:

Dim i As Integer
i = test()
如果该函数返回一个对象类型,则必须使用Set关键字,例如:
Public Function testRange() As Range
    Set testRange = Range("A1")
End Function

使用示例:

Dim r As Range
Set r = testRange()

请注意,将返回值分配给函数名称不会终止函数的执行。如果您想退出函数,则需要明确使用Exit Function语句。例如:

Function test(ByVal justReturnOne As Boolean) As Integer
    If justReturnOne Then
        test = 1
        Exit Function
    End If
    'more code...
    test = 2
End Function

文档:Function语句


37
为了完整起见,需要注意当您返回一个对象(例如 Range)时,需要像在常规方法中设置对象变量一样使用 Set。因此,例如,如果“test”是返回 Range 的函数,则返回语句应如下所示:set test = Range("A1") - Jay Carr
为什么是这样的,@JayCarr? - PsychoData
5
之所以通常使用set来设置对象变量,是因为不使用set可能会导致问题。我在没有使用set的情况下遇到了问题,但如果我使用了set就不会出现问题。 - Jay Carr
1
我认为值得一提的是,当您从电子表格中调用函数时,其行为与从另一个VBA函数或Sub中调用它时有所不同。 - Doug Jenkins
5
当在 VBA 中调用该函数时,它会返回一个范围对象,但当从工作表中调用时,它仅会返回该值。因此,set test = Range("A1")test = Range("A1").Value 是完全等同的,其中“test”被定义为 Variant 类型,而不是 Range 类型。 - Doug Jenkins
显示剩余2条评论

89

VBA函数会将函数名称本身视为一种变量。因此,您只需使用一个函数名称即可,而不是使用“return”语句:

test = 1

需要注意的是,这并不会跳出函数。在此语句之后的任何代码也将被执行。因此,你可以有许多赋值语句来分配不同的值给 test,而当你到达函数结尾时,无论其值为何都将成为返回的值。


2
实际上,您提供了更清晰的答案,并提供了额外的信息(这可能会引起新手对VBA的另一个问题)。继续保持好工作。 - Adarsha
抱歉,看起来你的回答和我的回答一样,只是加了一个不会跳出函数的事实。这是一个很好的补充,但我认为将其作为评论更合适。我不确定正确的礼仪是什么,我想仅仅因为这个而投反对票可能有点粗鲁,因为这是一个好答案,但它不会让我撤销投票。 - Dan

49

仅将返回值设置为函数名称仍然不完全等同于Java(或其他)return语句,因为在Java中,return会退出函数,就像这样:

public int test(int x) {
    if (x == 1) {
        return 1; // exits immediately
    }

    // still here? return 0 as default.
    return 0;
}

如果你在VB中没有在函数结尾处设置返回值,则完全等效的方法需要两行代码。因此,在VB中,确切的推论如下:

Public Function test(ByVal x As Integer) As Integer
    If x = 1 Then
        test = 1 ' does not exit immediately. You must manually terminate...
        Exit Function ' to exit
    End If

    ' Still here? return 0 as default.
    test = 0
    ' no need for an Exit Function because we're about to exit anyway.
End Function 

既然情况是这样,那么知道你可以像使用方法中的其他变量一样使用返回变量也是很好的。就像这样:

Public Function test(ByVal x As Integer) As Integer

    test = x ' <-- set the return value

    If test <> 1 Then ' Test the currently set return value
        test = 0 ' Reset the return value to a *new* value
    End If

End Function 

或者,极端的示例来说明返回变量的工作方式(但并不一定是你实际编写代码应该使用的好示例)- 这将使你整晚都睡不好觉:

Public Function test(ByVal x As Integer) As Integer

    test = x ' <-- set the return value

    If test > 0 Then

        ' RECURSIVE CALL...WITH THE RETURN VALUE AS AN ARGUMENT,
        ' AND THE RESULT RESETTING THE RETURN VALUE.
        test = test(test - 1)

    End If

End Function

2
“知道你可以像使用方法中的任何其他变量一样使用返回变量,这是大多数情况下正确的 - 但是例如,如果返回类型为Variant且您的目标是返回一个数组,则类似于ReDim test(1 to 100)的操作将触发错误。此外,即使可以像对待基本类型(如Integers)那样处理它,但这被认为是不太符合惯例的。它会使代码更难阅读。VBA程序员扫描分配给函数名称的行以了解函数的作用。将函数名称用作常规变量会不必要地使其变得模糊。” - John Coleman
它对于小型函数确实有用,是任何VBA程序员应该知道的内容,所以我对你提到它没有任何问题。我只是认为应该包含一个警告。 - John Coleman
感谢解释 Exit Functionreturn 的关系。 - Austin
1
@Gene 我不明白。将变量声明为数组并不是必要的,就可以使用 ReDimDim test As Variant 后跟 ReDim test(1 to 100) 是没有问题的。在函数体中不能使用变量函数的名称来执行此操作,这表明您不能像在函数体中使用其他变量一样使用返回变量,这正是我所说的。顺便说一句,您使用感叹号似乎有些过头了。在互联网上,它似乎有点像喷子,尽管您的评论并没有任何喷子的意思。 - John Coleman
1
@Gene,你只是偶然地说对了。但你的理由是错误的。 - Excel Hero
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接