|
楼主 |
发表于 2021-11-28 21:21
|
显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用 · 内置多项VBA编程加强工具 ★ 免费下载 ★ ★ 使用手册★
感谢只点,确实有一个函数我认为处理数据少而懒得写了,直接无限用了ReDim Preserve
程序应该严紧,我会将他改正
关于WindowsAPI方法也考虑用过,但是WindowsAPI方法针对不同的数据类型的内存偏移都不一致,类型处理起来很麻烦,最后也不采用了
我就分享下我曾经放弃的API方法吧,就刚才所言只支持Variant类型数组,其他类型还要修改代码
多维数组转一维,支持任意维度,这个想法是突发奇想的,
可以想一想,在不知道数组维度的情况下如何不用foreach遍历整个数组,我只想到了这个api方法?
- Private Type SAFEARRAY
- cDims As Integer
- fFeatures As Integer
- cbElements As Long
- cLocks As Long
- pvData As LongPtr
- End Type
- Private Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
- ByRef Destination As Any, _
- ByRef Source As Any, _
- ByVal Length As Long)
- Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias _
- "VarPtr" (ByRef Var() As Any) As LongPtr
- '支持任意维度
- Private Function 多维转一维(arr()) As Variant()
- Dim v1 As LongPtr
- Dim s As SAFEARRAY
- Dim psa As LongPtr
- '得到数组信息地址
- CopyMemory psa, ByVal VarPtrArray(arr), 4
- '读取数组信息
- #If Win64 Then
- CopyMemory s, ByVal psa, 20
- #Else
- CopyMemory s, ByVal psa, 16
- #End If
- v1 = s.pvData '数组真实地址
- '取得数组元素总个数
- Dim cc As Long
- cc = 1
- For i = 1 To s.cDims
- cc = cc * (UBound(arr, i) - LBound(arr, i) + 1)
- Next
- Dim arr1
- '构造一维数组
- ReDim arr1(1 To cc)
- '将多维复制地址到一维
- CopyMemory arr1(1), ByVal v1, s.cbElements * cc
- 多维转一维 = arr1
- '最后释放掉 arr1 以内出现崩溃
- CopyMemory arr1, 0&, 4
- End Function
- Sub 测试二维()
- Dim v(2 To 8, 2 To 8)
- For i = 2 To 8
- For j = 2 To 8
- v(i, j) = i & "," & j
- Next
- Next
- arr = 多维转一维(v)
- End Sub
- Sub 测试三维()
- Dim v(2 To 8, 2 To 8, 1 To 10)
- For i = 2 To 8
- For j = 2 To 8
- For k = 1 To 10
- v(i, j, k) = i & "," & j & "," & k
- Next
- Next
- Next
- arr = 多维转一维(v)
- End Sub
复制代码
|
|