我正在编写一个 VBA 函数,我希望它可以在同一文档中的其他 VBA 模块中公开使用,但是我不希望它作为 UDF(用户定义的函数)提供。
如果我使用公共访问修饰符,那么我的函数也可以作为 UDF 公式使用,可以从工作簿中的单元格调用。我不想要这个。
是否有访问修饰符或其他方式可以帮助我获得这种“仅限 VBA”的行为?
亲切的问候
我正在编写一个 VBA 函数,我希望它可以在同一文档中的其他 VBA 模块中公开使用,但是我不希望它作为 UDF(用户定义的函数)提供。
如果我使用公共访问修饰符,那么我的函数也可以作为 UDF 公式使用,可以从工作簿中的单元格调用。我不想要这个。
是否有访问修饰符或其他方式可以帮助我获得这种“仅限 VBA”的行为?
亲切的问候
如果您Option Private Module
在该函数出现的模块中使用,则该函数可以声明为Public
并在您的 VBA 项目中的任何其他模块中使用,但其他应用程序或项目(包括 Excel 本身)将无法访问该函数。
如果在 Excel 中使用,这将返回 #VALUE 错误。
Function VBAOnly() As Variant
If TypeName(Application.Caller) <> "Range" Then
VBAOnly = 1 'or some other return value
Else
VBAOnly = CVErr(xlErrValue)
End If
End Function
而不是写 a Function
,写 a Sub
,然后通过ByRef
参数设置返回值。这样,您的函数将对 Excel 不可见(通过 Alt F8 或开发人员选项卡 > 宏除外),并且不会出现在 Excel 的智能感知中。
代替
Function Add(Num1 As Double, Num2 As Double)
Add = Num1 + Num2
End Function
利用
Sub AddInvisible(ByRef Result As Double, Num1 As Double, Num2 As Double)
Result = Num1 + Num2
End Sub
笔记
ByRef
不是绝对必要的(因为参数在 VBA 中默认通过引用),但它可以作为一个有用的提示,Result
携带返回值。您需要对代码进行必要的更改,例如:
z = Add(x,y)
会成为
AddInvisible z,x,y
如下所示:
Sub DemoAddInvisible()
Dim Num1 As Double
Dim Num2 As Double
Dim Result As Double 'Result initialises to 0
Num1 = 1
Num2 = 2
AddInvisible Result, Num1, Num2
MsgBox Result ' See that Result has become 3
End Sub
所有这些的缺点是新代码有点难以理解。
答案之间有点混乱,所以这里有一个更全面的解释:
从技术上讲...如果输入了确切的公式,则可以调用标准 VBA 模块中的所有函数。甚至公式在Private Functions
里面Private Modules
例子
Option Private Module
Private Function hiddenEverythingExample() As String
hiddenEverythingExample= "NOPE!!!"
End Function
如果单元格有,仍将返回一个值=hiddenEverythingExample()
但是,我相信 OP 的目标是避免让 itellisense 在 Excel 公式栏中填充这些函数。
我最常用的方法是为所有 VBA-Only 函数创建一个特定Option Private Module
的模块并放入模块定义(函数上方的区域)。
这确保了该模块中的所有功能都不会出现在 itellisense 中,但仍然可以与 itellisense 一起被其他模块访问。
定义 asPrivate Function
也可以完成此操作,但是该功能的范围仅限于该模块,这可能是也可能不是要求。
请注意,YowE3K 推断一个函数必须是Private Function
AND Option Private Module
,但只有一个OR是消除 itellisense 所必需的。
使用Private
修饰符应该只允许在函数所在的模块中执行。
传递一个参数,该参数仅在给定“魔术*”值时才允许该函数运行。
示例 - 这将给出错误#NAME!
,除非您知道密钥是什么:
Function VBAOnly(key As Long)
If key <> 12345 Then
VBAOnly = CVErr(xlErrName)
Exit Function
End If
VBAOnly = True
End Function