excel - VBA 中引用/指针的良好替代品?

标签 excel vba ms-access ms-word powerpoint

你能推荐我一个很好的替代 VBA 中引用或指针类型的方法吗?我一直在为这样的表达而苦苦挣扎:

dblMyArray( i * lngDimension0 + j * lngDimension1 + k * lngDimension2, l * lngDimension3 + m * lngDimension4 ) = dblMyArray( i * lngDimension0 + j * lngDimension1 + k * lngDimension2, l * lngDimension3 + m * lngDimension4 ) + 1

如果我想在多维数组中累积值,例如C++,我可以这样写:
double& rElement = dblMyArray[ i * lngDimension0 + j * lngDimension1 + k * lngDimension2 ][ l * lngDimension3 + m * lngDimension4 ];
rElement += 1;

或者
double* pElement = &dblMyArray[ i * lngDimension0 + j * lngDimension1 + k * lngDimension2 ][ l * lngDimension3 + m * lngDimension4 ];
*pElement += 1;

我正在寻找这样的东西。

我不想重复赋值右侧的元素,也不想调用带有 ByRef 参数的函数,因为这会使代码的维护变得更加困难。

有任何想法吗?

最佳答案

VBA 支持指针,但仅限于非常有限的范围,并且主要用于需要它们的 API 函数(通过 VarPtr、StrPtr 和 ObjPtr)。你可以做一些hackery来获取数组内存区域的基地址。 VBA 将数组实现为 SAFEARRAY结构,所以第一个棘手的部分是获取数据区域的内存地址。我发现这样做的唯一方法是让运行时将数组放入 VARIANT 中,然后将其分开:

Public Declare Sub CopyMemory Lib "kernel32" Alias _
    "RtlMoveMemory" (Destination As Any, Source As Any, _
    ByVal length As Long)

Private Const VT_BY_REF = &H4000&

Public Function GetBaseAddress(vb_array As Variant) As Long
    Dim vtype As Integer
    'First 2 bytes are the VARENUM.
    CopyMemory vtype, vb_array, 2
    Dim lp As Long
    'Get the data pointer.
    CopyMemory lp, ByVal VarPtr(vb_array) + 8, 4
    'Make sure the VARENUM is a pointer.
    If (vtype And VT_BY_REF) <> 0 Then
        'Dereference it for the variant data address.
        CopyMemory lp, ByVal lp, 4
        'Read the SAFEARRAY data pointer.
        Dim address As Long
        CopyMemory address, ByVal lp, 16
        GetBaseAddress = address
    End If
End Function

第二个棘手的部分是 VBA 没有取消引用指针的 native 方法,因此您需要另一个辅助函数来执行此操作:
Public Function DerefDouble(pData As Long) As Double
    Dim retVal As Double
    CopyMemory retVal, ByVal pData, LenB(retVal)
    DerefDouble = retVal
End Function

然后你可以像在 C 中一样使用指针:
Private Sub Wheeeeee()
    Dim foo(3) As Double
    foo(0) = 1.1
    foo(1) = 2.2
    foo(2) = 3.3
    foo(3) = 4.4

    Dim pArray As Long
    pArray = GetBaseAddress(foo)
    Debug.Print DerefDouble(pArray) 'Element 0
    Debug.Print DerefDouble(pArray + 16) 'Element 2
End Sub

这是否是 好主意或者比你现在做的更好,留给读者作为练习。

关于excel - VBA 中引用/指针的良好替代品?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39143998/

相关文章:

c# - 列计数与第 1 行的值计数不匹配 C#

vba - 为什么我会遇到 "Type Mismatch"错误?

excel - 自动将 Excel 文件转换为 Google 表格

string - 在 Crystal Reports XI 中设置文本字段中的字符串格式

sql - 在 SQL 语句中使用 VBA 数组

Excel 白类和夜类时间表

VBA替换功能问题

sqlite - 安排规划程序

asp.net - 使用 Microsoft Access 和 VB.NET 预防 SQL 注入(inject)

c# - 什么是 "obfuscate"数值的简单但有些有效的方法?