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

时间:2012-07-16 16:12:22

标签: excel dll com excel-vba variant vba

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

所以步骤可能涉及:

  1. 在VBA中加载dll
  2. 将excel范围发送到dll(范围可能包含数字和/或字符串列)
  3. 操纵dll文件中的excel数据
  4. 我正在考虑使用excel变体和C ++变体。但我不清楚如何使用C ++变体,因为我无法在其上找到任何好的文档。

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

    我的问题:

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

    更新

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

1 个答案:

答案 0 :(得分:2)

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

  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;
    }
    

    TLB描述看起来像这样:

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

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

    LIBRARY "TestSafearray"
    
    EXPORTS
        ReturnArrLowerBound
    
  2. 您的数据集大小合理,您不必介意一点点复制 然后使您的C ++函数接受仅仅int[]并在VB中将其声明为接受arr() as Long。在VB端,在Long上分配一个数组,并从Range.Value数组中将元素复制到其中。