【问题标题】:Calling an xll UDF from VBA从 VBA 调用 xll UDF
【发布时间】:2018-05-23 13:35:37
【问题描述】:

我想从 VBA 调用我的用户定义函数之一。

我的用户定义函数是在 C++ 中声明的:

XLOPER12*WINAPI HelloWorld()noexcept{
    THROWS();
    static XLOPER12 res=[](){
        static std::array<wchar_t,13>str={
            11,'H','e','l','l','o',' ','W','o','r','l','d','\0'};
        XLOPER12 tmp;
        tmp.xltype=xltypeStr;
        tmp.val.str=str.data();
        return tmp;}();
    return &res;}

这是来自字段的真实函数的简化版本,可以返回字符串或双精度甚至数组。当然在这里我只返回一个字符串,但这将我的 UDF 的返回类型限制为LPXLOPER12

我可以使用xlfRegister 成功注册我的函数,指定pxTypeText"U$"。然后我可以从 Excel 调用我的 UDF:

=HelloWorld()

而且它有效!


如果我尝试按照 here 的建议从 VBA 调用我的函数:

Sub macro_test()
    Dim hw As Variant
    hw = Application.Run("D:\Path\MyAddIn.xll!HelloWorld")
End Sub

我从 Application.run 收到一条错误消息:

运行时错误“1004”:应用程序定义或对象定义错误


如果我尝试按照 here 的建议从 VBA 调用我的函数:

Private Declare PtrSafe Function HelloWorld Lib "C:\Path\MyAddIn.xll" () As Variant

Sub macro_test()
    Dim hw As Variant
    hw = HelloWorld()
End Sub

我得到一个空结果而不是"Hello World"


我做错了什么?

其他信息:

  • 使用 Excel 2013
  • 使用 VS 2017 15.5
  • 使用第一种方法 (Application.Run),VBA 不会调用我的函数(我无法使用调试器单步执行我的函数)。
  • 使用第二种方法,VBA 调用我的函数(我可以使用调试器单步执行我的函数)。
  • 使用第二种方法,当我将xlbitDLLFree添加到我的xltype时,函数xlAutoFree12没有被调用,这让我觉得VBA无法正确理解返回值。

【问题讨论】:

  • 使用 VBA 时,您必须坚持使用该语言编写的程序。但是,我相信您可以编译您的 C++ 过程并创建一个可执行文件,您可以从 VBA 的 Shell 函数调用它。看看这个线程:- stackoverflow.com/questions/20917355/…
  • @Variatus 我不想调用可执行文件,我想调用库中的函数。这绝对是 VBA 的part
  • 您是否尝试过“将硬件设置为字符串”(并使用函数原型...作为字符串)?
  • @Malick 是:Excel 崩溃。
  • $ 似乎不正确,您的函数不是 线程安全的。否则,Declare 方法将永远无法工作,因为 Variant 结构与 XLOPER12 结构不同。 Application.Run 应该可以工作。你检查路径是否正确且不包含特殊字符:stackoverflow.com/questions/2136768/…

标签: c++ vba excel xll


【解决方案1】:

如果您的 XLL 已加载且其 UDF 已注册,因此单元格中的 =HelloWord() 可以正常工作,那么您应该能够像这样从 VBA 调用它(除非无参数字符串函数存在问题)

var=Application.run("HelloWorld")

你也可以使用评估

var=Application.Evaluate("=HelloWorld()")

我像这样测试了我的 REVERSE.TEXT XLL 函数,它工作正常。

Sub testing()
Dim var As Variant
var = Application.Run("REVERSE.TEXT", "Charles")
var = Application.Evaluate("=REVERSE.TEXT(""Charles"")")
End Sub

Reverse.Text 使用 UQQ$ 注册(有两个参数,文本和字符数)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 2011-01-29
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    相关资源
    最近更新 更多