7

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

所以这些步骤可能涉及:

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

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

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

我的问题:

  • 一个善良的灵魂可以为我提供如何进行的指导吗?(例如,通过提供 C++ 原型,以及如何处理变体的简单示例)
  • 有谁知道有关使用 C++ 变体(可能与 VBA 联合使用)的任何好的文档/教程?
  • 如果速度是一个问题,使用 COM 是否比使用 VARIANTS 更可取?
  • 使用 C API 是一种选择吗?

更新:

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

1 回答 1

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

    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 端,在 s 上分配一个数组Long并将元素从Range.Value数组中复制到其中。

于 2012-07-16T17:04:46.880 回答