在 VB/VBA 中使用“CallByName”调用模块中包含的 Sub 或 Function
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2695198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling a Sub or Function contained in a module using "CallByName" in VB/VBA
提问by Kratz
It is easy to call a function inside a classModule using CallByName How about functions inside standard module?
使用 CallByName 很容易调用 classModule 中的函数 标准模块中的函数如何?
''#inside class module
''#classModule name: clsExample
Function classFunc1()
MsgBox "I'm class module 1"
End Function
''#
''#inside standard module
''#Module name: module1
Function Func1()
MsgBox "I'm standard module 1"
End Function
''#
''# The main sub
Sub Main()
''# to call function inside class module
dim clsObj as New clsExample
Call CallByName(clsObj,"ClassFunc1")
''# here's the question... how to call a function inside a standard module
''# how to declare the object "stdObj" in reference to module1?
Call CallByName(stdObj,"Func1") ''# is this correct?
End Sub
回答by David Horowitz
I think jtolle's response addressed the question best - the small reference to Application.Run may be the answer. The questioner doesn't want to use simply func1 or Module1.func1 - the reason one would want to use CallByName in the first place is that the desired function.sub name is not known at compile time. In this case, Application.Run does work, e.g.:
我认为 jtolle 的回答最好地解决了这个问题——对 Application.Run 的小参考可能就是答案。提问者不想简单地使用 func1 或 Module1.func1 - 首先要使用 CallByName 的原因是所需的 function.sub 名称在编译时未知。在这种情况下, Application.Run 确实有效,例如:
Dim ModuleName As String
Dim FuncName As String
Module1Name = "Module1"
FuncName = "func1"
Application.Run ModuleName & "." & FuncName
You can also prepend the Project Name before the ModuleName and add another period ".". Unfortunately, Application.Run does not return any values, so while you can call a function, you won't get its return value.
您还可以在 ModuleName 之前添加项目名称并添加另一个句点“.”。不幸的是,Application.Run 不返回任何值,因此虽然您可以调用函数,但不会获得它的返回值。
回答by mechanical_meat
CallByName works only with class objects.
CallByName 仅适用于类对象。
If your subroutine is in a standard module, you can do this:
如果您的子程序在标准模块中,您可以这样做:
Sub Main()
Module1.Func1
End Sub
If it's a function, then you'll probably want to capture the return value; something like this:
如果它是一个函数,那么您可能想要捕获返回值;像这样:
Sub Main()
Dim var
var = Module1.Func1
End Sub
回答by Hans-Gerd Theunissen
Modules in VB6 and VBA are something like static classes, but unfortunately VB doesn't accept Module1 as an object. You can write Module1.Func1 like C.Func1 (C being an instance of some Class1), but this is obviously done by the Compiler, not at runtime.
VB6 和 VBA 中的模块类似于静态类,但不幸的是 VB 不接受 Module1 作为对象。您可以像 C.Func1 一样编写 Module1.Func1(C 是某个 Class1 的实例),但这显然是由编译器完成的,而不是在运行时完成的。
Idea: Convert the Module1 to a class, Create a "Public Module1 as Module1" in your Startup-module and "Set Module1 = New Module1" in your "Sub Main".
想法:将 Module1 转换为一个类,在您的启动模块中创建一个“Public Module1 as Module1”,并在您的“Sub Main”中创建一个“Set Module1 = New Module1”。
回答by Marcelo Scofano
Although it is an old question and OP asked for CallByName in a standard module, the correct pieces of advice are scattered through answers and comments, and some may not be that accurate, at least in 2020. As SlowLearner stated, Application.run DOES return a Variant, and in that way both branchs below are equivalent, except by handling errors, as commented around Horowitz's answer:
尽管这是一个老问题并且 OP 在标准模块中要求 CallByName,但正确的建议散布在答案和评论中,有些可能不那么准确,至少在 2020 年是这样。正如 SlowLearner 所说,Application.run 确实会返回一个变体,这样下面的两个分支是等效的,除了处理错误,正如围绕霍洛维茨的回答所评论的那样:
Dim LoadEnumAndDataFrom as Variant
'FunctionName returns a Variant Array
if fCallByName then
LoadEnumAndDataFrom = CallByName(ClassObj, "FunctionNameAtClass", VbMethod)
else
'After moving back function for a standard module
LoadEnumAndDataFrom = Application.Run("StandardModuleName" & "." & "FunctionNameAtStandard")
endif
I actually just did this above and had no errors at all, tested in Word, Excel and Access, and both return the same Array.
我实际上只是在上面这样做并且完全没有错误,在 Word、Excel 和 Access 中进行了测试,并且都返回了相同的数组。
Unfortunately, there is an exception: Outlook's object Model is too protected and it does not have the Run method.
不幸的是,有一个例外:Outlook 的对象模型过于受保护,它没有 Run 方法。
回答by Tozi T
Unfortunately it is not possible to prepend the ProjectNamebefore the ModuleNameand add another period "." In MS Word this throws a runtime error 438. The call is restricted to the use of simply ModuleName.ProcName.
不幸的是,不可能在ProjectName之前ModuleName加上另一个句点“.”。在 MS Word 中,这会引发运行时错误 438。该调用仅限于使用 simple ModuleName.ProcName。

