【问题标题】:Pass data of arbitrary type between VBA and dll在 VBA 和 dll 之间传递任意类型的数据
【发布时间】:2012-07-15 12:50:51
【问题描述】:

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

所以这些步骤可能涉及:

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

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

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

我的问题:

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

更新:

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

【问题讨论】:

    标签: dll com excel variant vba


    【解决方案1】:

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

    1. 您拥有庞大的数据集,并希望尽可能避免复制。
      在这种情况下,您可能希望通过调用Range.Value 传递相同的Variant 数组。为此,您必须编写一个小 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 端,在Longs 上分配一个数组,并将Range.Value 数组中的元素复制到其中。

    【讨论】:

    • 谢谢!如果我没记错的话,写 TLB 涉及到 COM 编程,对吧?那么这是否会限制应用程序的可移植性(尤其是在 linux 机器上)?
    • @SMir 不,它本身不涉及 COM 编程。您编写 TLB 只是为了让 VB 理解您的 C++ 函数签名。除此之外,该函数是一个普通的、非 COM 的、经典风格的导出函数。
    • 感谢您的及时回复。使用 Variant 是否允许我将混合类型传递给 DLL?或者它只允许使用单一类型(字符串或数字等)。
    • @SMir 数组的每个元素都是VARIANT,所以它们都具有相同的类型——VARIANT。每个变体包含的是完全不同的问题,是的,它们都可以包含不同的实际数据。您决定是否要在 C++ 端处理它。
    • 感谢您的帮助!对此,我真的非常感激。我将尝试实施(可能需要几天时间),如果我遇到任何进一步的问题,我会回复您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    相关资源
    最近更新 更多