从VBA调用xll UDF

3
我希望能够从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()

它有效!


如果我按照这里所建议的方法从VBA调用我的函数:
Sub macro_test()
    Dim hw As Variant
    hw = Application.Run("D:\Path\MyAddIn.xll!HelloWorld")
End Sub

我从Application.run得到一个错误信息:

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


如果我尝试按照这里建议的方法从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调用了我的函数(我可以通过调试器进入我的函数)。
  • 使用第二种方法,在我的xltype中添加xlbitDLLFree时,函数xlAutoFree12没有被调用,这让我觉得VBA可能没有正确地理解返回值。

当使用VBA时,您必须坚持使用该语言编写的过程。但是,我相信您可以编译C++过程并创建可执行文件,然后可以从VBA的“Shell”函数中调用它。请查看此线程:- https://dev59.com/iWEi5IYBdhLWcg3w0fFR - Variatus
@Variatus 我不想调用一个可执行文件,我想调用库中的一个函数。这绝对是 VBA 的一部分。 - Arnaud
你尝试过使用“Dim hw As String”(以及函数原型... As String)吗? - Malick
@Malick 是的:Excel 崩溃了。 - Arnaud
@S Meaden 在VBA中调用另一种语言编写的过程和从VBA中调用是两个非常不同的概念。我很遗憾你没有理解我在上面的帖子中试图表达的观点,即考虑调用的替代方法。由于我没有预料到Shell会是答案,所以我承认我的动机是为了被通知线程的添加。如果您推荐的解决方案符合答案的要求,我建议您将它们发布为答案,并且我将授予积分,就像我为下面@Charles William的答案所做的那样。 - Variatus
显示剩余5条评论
1个回答

5
如果你的XLL已经被加载并且其UDF已经注册,那么在单元格中使用"HelloWord()"应该是有效的,因此你只需要像下面这样在VBA中调用它就可以了(除非参数为空的字符串函数存在问题)。
var=Application.run("HelloWorld")

您也可以使用Evaluate函数。
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$注册的(有两个参数,文本和字符数)


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