在VBA和dll之间传递任意类型的数据

SMi*_*Mir 6 com dll excel vba variant excel-vba

所以我正在开发一个Excel项目,它将使用VBA加载C++ dll.我想要做的是能够将没有特定类型的Excel范围(数据可以是数字或分类)传递给C++ dll(我可以描述我的Excel范围的最佳方式是类型variant).

所以步骤可能涉及:

  1. 在VBA中加载dll
  2. 将excel范围发送到dll(范围可能包含数字和/或字符串列)
  3. 操纵dll文件中excel的数据

我正在考虑使用excel变体和C++变体.但是我不清楚如何使用C++变体,因为我找不到任何好的文档.

我收到的另一个建议是使用COM编程.

我的问题:

  • 一个善良的灵魂可能会为我提供如何进行的指示吗?(例如,通过提供C++原型,以及如何处理变体的简单示例)
  • 有没有人知道任何关于使用C++ Variants(也许还有VBA)的好文档/教程?
  • 如果速度是一个问题,使用COM优先使用VARIANTS吗?
  • 使用C API是一个选项吗?

更新:

  • 我需要操作的范围的大小可能很大(约500,000行).
  • 速度是一个因素,因此,我希望尽可能避免不必要的复制.

GSe*_*erg 3

如果您只想将数据传递给 dll(而不是指向实际 Excel 对象的指针,例如Range),那么您有两个基本选项:

  1. 您拥有庞大的数据集,并且希望尽可能避免复制。
    在这种情况下,您可能希望传递Variant通过调用 获得的相同数组Range.Value。为了做到这一点,您必须编写一些 TLB 以从 VB 中引用,在其中您将导出的 C++ 函数描述为期望SAFEARRAY(VARIANT)*. 这是因为Declare操作员不会让您实际传递 SAFEARRAY*。
    该函数将如下所示:

    LONG __stdcall ReturnArrLowerBound(SAFEARRAY** ppArr)
    {
        if (ppArr == NULL) return -1;
        SAFEARRAY* pArr = (*ppArr);
    
        LONG res = 0;
        SafeArrayGetLBound(pArr, 1, &res);
    
        return res;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    TLB 描述如下:

    [
        uuid(A686B138-D8CE-462e-AEF2-75DA4DBF1C75)
    ]
    library foo
    {
        [
            dllname("TestSafearray.dll")
        ]
        module vb
        {
            [entry("ReturnArrLowerBound")]
            LONG __stdcall ReturnArrLowerBound(SAFEARRAY(VARIANT)* ppArr);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    你的 C++ 项目显然会包含一个 def 文件:

    LIBRARY "TestSafearray"
    
    EXPORTS
        ReturnArrLowerBound
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您的数据集大小合理,并且您不介意进行一点复制。
    然后让你的 C++ 函数接受一个 mereint[]并在 VB 中将其声明为接受arr() as Long。在VB方面,在s上分配一个数组Long并将元素从Range.Value数组复制到其中。