Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
12
返回列表 发新帖
楼主: Dj_soo

[已解决]如何计算能得到数组的维数?

[复制链接]
发表于 2010-3-30 10:37 | 显示全部楼层

借用一下API:


Option Explicit
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, source As Any, ByVal Length As Long)
Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Ptr() As Any) As Long
Const AppName = "Stanley Pan Hint:"

Public Sub ArrayDimensionTest()
Dim varArray() As Integer 'dim a variables to contain array
ReDim varArray(1) As Integer 'one dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName

ReDim varArray(1, 2) As Integer 'two dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName

ReDim varArray(2, 3, 4) As Integer 'three dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName

ReDim varArray(1, 2, 3, 4) As Integer 'Four dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName
End Sub
Public Function ArrayDims(ByVal lpArray As Long) As Integer
    Dim lAddress As Long
    CopyMemory lAddress, ByVal lpArray, 4
    If lAddress = 0 Then
        ' The array isn't initilized
        ArrayDims = -1
        Exit Function
    End If
    CopyMemory ArrayDims, ByVal lAddress, 2
End Function

还有一个

 'GetArrayInfo - Retreive number of dimensions and the SAFEARRAY memory structure
Type SAFEARRAYBOUND
    cElements As Long ' # of elements in the array dimension
    lLbound As Long ' lower bounds of the array dimension
End Type
Type SAFEARRAY
    cDims As Integer ' Count of dimensions in this array.
    fFeatures As Integer ' Flags used by the SAFEARRAY routines documented
    ' below.
    cbElements As Long ' Size of an element of the array.
    cLocks As Long ' Number of times the array has been
    ' locked without corresponding unlock.
    pvData As Long ' Pointer to the data.
    rgsabound(1 To 60) As SAFEARRAYBOUND ' One bound for each dimension.
    ' An array can have max 60 dimensions, only the first cDims items will be
    ' used
    ' note that rgsabound elements are in reverse order,
    ' e.g. for a 2-dimensional
    ' array, rgsabound(1) holds info about columns, and rgsabound(2) about rows
End Type
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As _
Any, source As Any, ByVal bytes As Long)
Private Const VT_BYREF = &H4000&

' Fills a SAFEARRAY structure for the supplied array.
'
' The information contained in the SAFEARRAY structure allows
' the caller to identify the number of dimensions and the
' number of elements for each dimension (among other things).
' Element information for each dimension is stored in a
' one-based sub-array of SAFEARRAYBOUND structures (rgsabound).
'
' TheArray The array to get information on.
' ArrayInfo The output SAFEARRAY structure.
'
' RETURNS The number of dimensions of the array
' or zero if the array isn't dimensioned

Function GetArrayInfo(TheArray As Variant, ArrayInfo As SAFEARRAY) As Boolean
    Dim lp As Long ' work pointer variable
    Dim VType As Integer ' the VARTYPE member of the VARIANT structure
    ' Exit if no array supplied
    If Not IsArray(TheArray) Then Exit Function
    With ArrayInfo
        ' Get the VARTYPE value from the first 2 bytes of the VARIANT structure
        CopyMemory VType, TheArray, 2
        ' Get the pointer to the array descriptor (SAFEARRAY structure)
        ' NOTE: A Variant's descriptor, padding & union take up 8 bytes.
        CopyMemory lp, ByVal VarPtr(TheArray) + 8, 4
        ' Test if lp is a pointer or a pointer to a pointer.
        If (VType And VT_BYREF) <> 0 Then
            ' Get real pointer to the array descriptor (SAFEARRAY structure)
            CopyMemory lp, ByVal lp, 4
        End If
        ' Fill the SAFEARRAY structure with the array info
        ' NOTE: The fixed part of the SAFEARRAY structure is 16 bytes.
        CopyMemory ArrayInfo.cDims, ByVal lp, 16
        ' Ensure the array has been dimensioned before getting SAFEARRAYBOUND
        ' Information
        If ArrayInfo.cDims > 0 Then
            ' Fill the SAFEARRAYBOUND structures with the array info
            CopyMemory .rgsabound(1), ByVal lp + 16, _
            ArrayInfo.cDims * Len(.rgsabound(1))
            ' So caller knows there is information available for the array in
            ' output SAFEARRAY
            GetArrayInfo = ArrayInfo.cDims
        End If
    End With
End Function
Sub XXX()
    Dim A(1, 2, 3, 4, 5, 6, 7, 100)
    Dim INFO As SAFEARRAY
    GetArrayInfo A, INFO
    MsgBox INFO.cDims
End Sub

回复

使用道具 举报

 楼主| 发表于 2010-3-30 10:38 | 显示全部楼层

这样的话,似乎只能用错误捕捉的方法了..谢谢各位
回复

使用道具 举报

 楼主| 发表于 2010-3-30 10:39 | 显示全部楼层
回复

使用道具 举报

 楼主| 发表于 2010-3-30 10:42 | 显示全部楼层

API真强大,代码看起来也很简单明了,最佳应该是11楼,还好是同一个人呵呵
回复

使用道具 举报

发表于 2010-3-30 11:16 | 显示全部楼层

QUOTE:
以下是引用兰色幻想在2010-3-30 10:37:00的发言:

肯定的回答,没有这样的VBA函数

谢谢兰版!

[em04]
回复

使用道具 举报

发表于 2010-3-30 11:28 | 显示全部楼层

一晃爱疯已经读社士了[em04]
回复

使用道具 举报

发表于 2010-3-30 12:05 | 显示全部楼层

QUOTE:
以下是引用EZD在2010-3-30 11:28:00的发言:
一晃爱疯已经读社士了[em04]

你使劲晃,也可以啊[em04]

回复

使用道具 举报

发表于 2010-3-30 13:23 | 显示全部楼层

QUOTE:
以下是引用amulee在2010-3-30 10:37:00的发言:

借用一下API:


Option
   Explicit
Declare
   Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, source As Any, ByVal Length As
   Long)
Declare
   Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Ptr() As Any) As
   Long
Const AppName = "Stanley Pan Hint:"

Public
   Sub ArrayDimensionTest()
Dim varArray() As
   Integer
   'dim a variables to contain array
ReDim varArray(1) As
   Integer
   'one dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName

ReDim varArray(1, 2) As
   Integer
   'two dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName

ReDim varArray(2, 3, 4) As
   Integer
   'three dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName

ReDim varArray(1, 2, 3, 4) As
   Integer
   'Four dimension
MsgBox ArrayDims(VarPtrArray(varArray)), vbInformation, AppName
End
   Sub
Public
   Function ArrayDims(ByVal lpArray As
   Long) As
   Integer
    Dim lAddress As
   Long
    CopyMemory lAddress, ByVal lpArray, 4
    If lAddress = 0 Then
        ' The array isn't initilized
        ArrayDims = -1
        Exit
   Function
    End
   If
    CopyMemory ArrayDims, ByVal lAddress, 2
End
   Function

还有一个

 'GetArrayInfo - Retreive number of dimensions and the SAFEARRAY memory structure
Type SAFEARRAYBOUND
    cElements As
   Long
   ' # of elements in the array dimension
    lLbound As
   Long
   ' lower bounds of the array dimension
End
   Type
Type SAFEARRAY
    cDims As
   Integer
   ' Count of dimensions in this array.
    fFeatures As
   Integer
   ' Flags used by the SAFEARRAY routines documented
    ' below.
    cbElements As
   Long
   ' Size of an element of the array.
    cLocks As
   Long
   ' Number of times the array has been
    ' locked without corresponding unlock.
    pvData As
   Long
   ' Pointer to the data.
    rgsabound(1 To 60) As SAFEARRAYBOUND ' One bound for each dimension.
    ' An array can have max 60 dimensions, only the first cDims items will be
    ' used
    ' note that rgsabound elements are in reverse order,
    ' e.g. for a 2-dimensional
    ' array, rgsabound(1) holds info about columns, and rgsabound(2) about rows
End
   Type
Private
   Declare
   Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As _
Any, source As Any, ByVal bytes As Long)
Private
   Const VT_BYREF = &H4000&

' Fills a SAFEARRAY structure for the supplied array.
'
' The information contained in the SAFEARRAY structure allows
' the caller to identify the number of dimensions and the
' number of elements for each dimension (among other things).
' Element information for each dimension is stored in a
' one-based sub-array of SAFEARRAYBOUND structures (rgsabound).
'
' TheArray The array to get information on.
' ArrayInfo The output SAFEARRAY structure.
'
' RETURNS The number of dimensions of the array
' or zero if the array isn't dimensioned

Function GetArrayInfo(TheArray As
   Variant, ArrayInfo As SAFEARRAY) As
   Boolean
    Dim lp As
   Long
   ' work pointer variable
    Dim VType As
   Integer
   ' the VARTYPE member of the VARIANT structure
    ' Exit if no array supplied
    If
   Not IsArray(TheArray) Then
   Exit
   Function
    With ArrayInfo
        ' Get the VARTYPE value from the first 2 bytes of the VARIANT structure
        CopyMemory VType, TheArray, 2
        ' Get the pointer to the array descriptor (SAFEARRAY structure)
        ' NOTE: A Variant's descriptor, padding & union take up 8 bytes.
        CopyMemory lp, ByVal VarPtr(TheArray) + 8, 4
        ' Test if lp is a pointer or a pointer to a pointer.
        If (VType And VT_BYREF) <> 0 Then
            ' Get real pointer to the array descriptor (SAFEARRAY structure)
            CopyMemory lp, ByVal lp, 4
        End
   If
        ' Fill the SAFEARRAY structure with the array info
        ' NOTE: The fixed part of the SAFEARRAY structure is 16 bytes.
        CopyMemory ArrayInfo.cDims, ByVal lp, 16
        ' Ensure the array has been dimensioned before getting SAFEARRAYBOUND
        ' Information
        If ArrayInfo.cDims > 0 Then
            ' Fill the SAFEARRAYBOUND structures with the array info
            CopyMemory .rgsabound(1), ByVal lp + 16, _
            ArrayInfo.cDims * Len(.rgsabound(1))
            ' So caller knows there is information available for the array in
            ' output SAFEARRAY
            GetArrayInfo = ArrayInfo.cDims
        End
   If
    End
   With
End
   Function
Sub XXX()
    Dim A(1, 2, 3, 4, 5, 6, 7, 100)
    Dim INFO As SAFEARRAY
    GetArrayInfo A, INFO
    MsgBox INFO.cDims
End
   Sub

到现在看到API还是头大。

有机会阿木开个专题说说API与VBA?

自己也在看API,可是几乎没有进步哦。汗ing .............

回复

使用道具 举报

发表于 2010-3-30 13:23 | 显示全部楼层

QUOTE:
以下是引用兰色幻想在2010-3-30 10:37:00的发言:

肯定的回答,没有这样的VBA函数

学习了,原来这样
回复

使用道具 举报

发表于 2010-3-30 16:14 | 显示全部楼层

某位大虾所说:API不要去学,在需要的时候去查API帮助就足够了,那酱紫我去哪里查API帮助呢[em04]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-6-6 16:29 , Processed in 0.277311 second(s), 7 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表