Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 如何仅在模块上限制VBA功能_Excel_Vba - Fatal编程技术网

Excel 如何仅在模块上限制VBA功能

Excel 如何仅在模块上限制VBA功能,excel,vba,Excel,Vba,我对VBA知之甚少,并试图学习它。我制作了一个VBA脚本,如下所示: Function doIt() Dim c As int... ............. ............. ............. c = callFunction ............... .............. End Function Function callFunction(byVal num As Int) .......... .......... .......... End Fu

我对VBA知之甚少,并试图学习它。我制作了一个VBA脚本,如下所示:

Function doIt()
Dim c As int...
.............
.............
.............
c = callFunction
...............
..............
End Function

Function callFunction(byVal num As Int)
..........
..........
..........
End Function
正如您所看到的,callFunction是一个从主函数doIt调用的函数。假设callFunction计算一个整数的平方。整个VBA脚本保存在C驱动器中相应加载项文件夹下的加载项模块中。当从excel工作表调用时,函数doIt工作正常。但问题是,如果我从工作表调用函数callFunction,它也可以工作。如何将callFunction仅限于addIn模块,以便只有模块可以使用它,并且如果有人从工作表调用callFunction(2),它将不会在工作表中给出2的平方


注意:即使我将其设置为私有,它仍然可以从工作表中调用。

我认为您不能阻止允许在VBA和Excel单元格中访问它的函数功能

不过,我有一些变通方法,允许您创建函数,当在单元格中调用时,该函数会给出不同的结果,例如,可以返回一些信息(或标准错误),而不是计算结果

下面是展示此功能的代码。我认为这是非常清楚和可以理解的,所以你不需要额外的评论

Function callFunction(ByVal num As Integer)

On Error Resume Next
    Dim tmpAdd
    tmpAdd = Application.ThisCell.Address

    If Err.Number = 0 Then
        If Left(Application.ThisCell.Formula, 13) = "=callFunction" Then
            'called from excel cell, but this function is called!
            'returns any type of standard function error

                callFunction = CVErr(XlCVError.xlErrNull)
                Exit Function
        End If
    End If
    'called from VBA/IDE environment or from other function
    'standard calculation

        callFunction = num ^ num

End Function
编辑受@DanielDusek答案(但有点不完整)的启发,我将丹尼尔和我的解决方案混合在一起。因此,新的、相当完整的代码:

Function callFunction(ByVal num As Integer)

    If TypeName(Application.Caller) = "Range" Then
        If Left(Application.ThisCell.Formula, 13) = "=callFunction" Then
            'called from excel cell, but this function is called!
            'returns any type of standard function error

                callFunction = CVErr(XlCVError.xlErrNull)
                Exit Function
        End If
    End If
    'called from VBA/IDE environment or from other function
    'standard calculation

        callFunction = num ^ num
End Function

如果在任何VBA函数/子例程中使用,无论调用的位置(间接使用),这两种解决方案都将给出
num^num
结果。在Excel单元格中调用时,它将给出
错误
值(直接使用)

使用Application.Caller属性,您可以确定是谁调用了您的函数,如果该函数是从工作表中调用的,则可以引发错误或返回任何您想要的但与计算结果不同的结果

Private Function callFunction(ByVal num As Integer) As Variant
    If (TypeName(Application.Caller) = "Range") Then
        ' function was called from worksheet
        callFunction = "Invalid procedure call" ' or raise error Err.Raise Number:=5
        Exit Function
    End If

    ' continue ...
    callFunction = num * num
End Function

关于应用程序。来电者:

我认为您的解决方案不完整。如果在另一个函数(B)中使用函数(A),然后在工作表单元格中调用函数(B),它将返回
无效过程
,而不是(B)结果。感谢KazJaw提供的解决方案。它运行良好。但我感到惊讶的是,为什么即使将函数声明为私有函数,也可以从模块外部调用它。那么,在VBA中,私有、友元函数类型的用途/作用是什么?这将是我的荣幸,作为一名新手,如果你向我解释函数类型的用法,将有助于学习私有、友元函数类型。你不能使用
friend
关键字,因为根据vba帮助,它是…“仅在类模块中使用”。然而,
private
关键字应该起作用。如果我用
Private
启动任何函数,我无法从其他模块中
function
的任何
sub
调用它。但在这种情况下,Private关键字不起作用。我声明了callFunction private,但它也可以从工作表中调用,并且返回了正确的值。您可以从工作表中调用
private Function
。在这种情况下,
Private
关键字的唯一好处是,在单元格中输入函数名称时,不会列出或建议函数。