如何在VBA布尔/ LongLong数组中处理"类型不匹配"?

Ron*_*onk 3 arrays vba long-long

当尝试执行下面的代码时,我得到VBA错误:类型不匹配.任何人都知道原因(和解决方案?:-))

我将数据类型从Long更改为LongLong,以便能够处理更大的数字.在此之前,代码(摘录)工作正常.

Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long

Public Sub TestScreenResolution()
    Debug.Print ScreenResolution
End Sub
Private Function ScreenResolution() As Double
     Dim hDC As Long
     hDC = GetDC(0)
     ScreenResolution = GetDeviceCaps(hDC, 88)
     ReleaseDC 0, hDC
End Function

Public Sub TestMySub()
    Call MySub(999999999)
End Sub
Private Sub MySub(ByVal x As LongLong)

Dim y As LongLong
Dim Max As LongLong
Dim Min As LongLong

Max = x * x
Min = (x - 1) * (x - 1)

Dim Arr() As Boolean   'Default Boolean type is False
ReDim Arr(Min To Max) ''<<< "Type Mismatch" compile error

For y = Max To Min Step -2
    Arr(y) = True
Next y

End Sub
Run Code Online (Sandbox Code Playgroud)

当然,这段代码没有任何结果,仅用于测试这段代码.

Com*_*ern 6

tldr;

你不能"处理"它 - LongLong与你的ReDim陈述不兼容.(虽然999999999技术上适合a Long,但编译器不允许在那里进行缩小转换).


VBA中任何数组的最大大小由内部支持的SAFEARRAY结构(在OLE自动化协议规范的2.2.30.10节中定义)确定.C++中结构的定义是这样的:

typedef struct tagSAFEARRAY {
  USHORT         cDims;
  USHORT         fFeatures;
  ULONG          cbElements;
  ULONG          cLocks;
  PVOID          pvData;
  SAFEARRAYBOUND rgsabound[1];
}
Run Code Online (Sandbox Code Playgroud)

请注意,cbElements数组项的大小(以字节为单位).这有效地将每个项目限制为~4GB.


您遇到的问题是存储有关数组维度的信息的SAFEARRAYBOUND结构:

typedef struct tagSAFEARRAYBOUND {
  ULONG cElements;
  LONG  lLbound;
} SAFEARRAYBOUND, *LPSAFEARRAYBOUND;
Run Code Online (Sandbox Code Playgroud)

这意味着无论编程语言如何,您可以填入任何维度的最大项目总数SAFEARRAYULONG_MAX(4,294,967,295).因此,以下编译(虽然它在我的机器上分配时内存不足):

Dim foo(-2147483646 To 2147483647) As Byte
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的示例中,下限是负数,因为VBA也不支持无符号类型,这是调整数组大小的VBA代码的另一个障碍.从技术上讲,你可以通过oleaut32.dll导出0 To 4294967294SafeArrayCreate函数来获取一个带有边界的数组,但是我怀疑你会遇到类似的索引问题.


将图层进一步剥离,您开始触及一些更有趣的限制.例如,回顾SAFEARRAYBOUND上面的结构,您会注意到虽然您可以拥有ULONG_MAX 元素,但数组的下限受签名 限制LONG.这种限制被延续到处理SAFEARRAYs的大多数其他OLE自动化中,包括SafeArrayGetLBound和其他(有趣的SafeArrayGetUBound是,签名,这让我想知道你是否可以溢出它......).


那么为什么MS在添加64位支持时不更新呢?好吧,它几乎可以打破一切.除此之外,真的没有任何迫切需要-一旦你超越ULONG的元素,你就开始运行与在对数据区的存储记忆非常现实的问题,必须在创建结构时进行分配-否则它是不可能的通过COM使用它,因为在该结构的根部是一个指针,并且合同表明调用代码(不管客户端)必须能够使用属于数据区域的任何地址,包括VBA.

  • 好吧,鉴于一个大小需要197,582,278GB RAM的阵列,我在想******将是你的限制. (4认同)
  • meh ...朋友之间几百PB的内存是多少? (3认同)