
在VBA中,join函数可以快速的将一个String类型的数组连接成一个字符串,用的还比较多。
但是这个函数只支持将一维的数组进行连接,如果碰到多维数组的情况,一般都是先用For循环将数组转换为一维的,然后再使用join函数。这样就造成不得不另外使用一个数组的内存空间来保存数据,同时还要进行For循环处理,浪费了时间和空间。
在数据类型Array中,我们知道了数组的底层结构,其中cDims就是指明数组维度的,那么,我们只需要通过修改内存中cDims的值,以及SafeArray中rgsabound记录的元素的个数,那么就可以实现将多维的数组转换为一维数组:

代码:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)Private Type SafeArrayBoundcElements As Long '// 该维的长度lLbound As Long ' 该维的数组存取的下限,一般为0End TypePrivate Type SafeArraycDims As Integer ' 数组的维度fFeatures As Integer 'cbElements As Long ' / 数组元素的字节大小cLocksas As Long 'pvDataas As Long ' // 数组的数据指针rgsabound() As SafeArrayBoundEnd TypeSub TestToOneDim()Dim arr() As StringReDim arr(1, 2, 3) As StringVBA.RandomizeDim i As Long, j As Long, k As LongFor i = 0 To UBound(arr)For j = 0 To UBound(arr, 2)For k = 0 To UBound(arr, 3)arr(i, j, k) = VBA.Format(i, "x0") & VBA.Format(j, "\y0") & VBA.Format(j, "z0=") & VBA.Format(VBA.Rnd() * 100, "0")NextNextNextToOneDim arrDebug.Print VBA.Join(arr, "|")End SubFunction ToOneDim(arr As Variant) As LongIf Not VBA.IsArray(arr) ThenToOneDim = -1Exit FunctionEnd IfDim ptr As LongDim sa As SafeArrayptr = MyArrayPtr(arr)'获取SafeArrayBound之前的数据CopyMemory VarPtr(sa.cDims), ptr, 16If sa.cDims = 1 Then Exit FunctionReDim sa.rgsabound(sa.cDims - 1) As SafeArrayBound'根据维度再读取需要的数据CopyMemory VarPtr(sa.rgsabound(0).cElements), ptr + 16, sa.cDims * 8'修改为一维'修改rgsabound(0)的个数Dim i As LongFor i = 1 To sa.cDims - 1sa.rgsabound(0).cElements = sa.rgsabound(0).cElements * sa.rgsabound(i).cElementsNextsa.cDims = 1'反写到数组CopyMemory ptr, VarPtr(sa), 16CopyMemory ptr + 16, VarPtr(sa.rgsabound(0).cElements), 8End FunctionFunction MyArrayPtr(ByRef v As Variant) As LongDim b(16 - 1) As ByteCopyMemory VarPtr(b(0)), VarPtr(v), 16' Printf "b = 0x% x", bDim ptr As LongCopyMemory VarPtr(ptr), VarPtr(b(8)), 4' - 0x20 8-11存的是数组地址' - 0x60 8-11存的是数组地址的地址If b(1) = &H60 ThenCopyMemory VarPtr(ptr), ptr, 4End IfMyArrayPtr = ptrEnd Function
当然这里要注意看是不是自己需要的输出顺序,如果不是,那么应该只能通过For循环来处理了。

文章转载自VBA 学习,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




