Vba 如何测试数组中不同位置的空元素?即,我如何测试位置是否已在锯齿阵列中标注尺寸?

Vba 如何测试数组中不同位置的空元素?即,我如何测试位置是否已在锯齿阵列中标注尺寸?,vba,Vba,我有一个形式为(j,0)(I,0)的数组Cdo。有两种例外情况:地址(j,0)或(j,0)(0)通常为空,可能包含带有错误消息的字符串[决不能同时包含这两个地址] 要在不生成超出范围的下标的情况下通过这些错误,同时还要将其记录到已清理的数组中,请断开(在二维(j,i)中) j=0至符号的 如果TypeName(Cdo(j,0))“String”,那么 如果TypeName(Cdo(j,0)(0))“String”,那么 对于i=0到UBound(Cdo(j,0)) 断裂(j,i)=Cdo(j,0

我有一个形式为(j,0)(I,0)的数组Cdo。有两种例外情况:地址(j,0)或(j,0)(0)通常为空,可能包含带有错误消息的字符串[决不能同时包含这两个地址]

要在不生成超出范围的下标的情况下通过这些错误,同时还要将其记录到已清理的数组中,请断开(在二维(j,i)中)

j=0至符号的

如果TypeName(Cdo(j,0))“String”,那么
如果TypeName(Cdo(j,0)(0))“String”,那么
对于i=0到UBound(Cdo(j,0))
断裂(j,i)=Cdo(j,0)(i,0)
接下来我
如果结束
中断(j,1)=“不适用”
如果结束
中断(j,1)=“#TrancheDef”
下一个j
我尝试了IsEmpty并查找字符串(如图所示),但在查找未标注维度的位置时,它们都会抛出错误。我无法在数组进入时更改它-如何测试一个位置,例如(403)(0)(0)“存在”可以这么说

或者:
我可以检查Cdo(j,0)(I,0)是否存在——如果不存在,那么它应该是另外两种情况之一。仍然围绕着相同的基本问题。

如果要检查数组是否已初始化,必须使用dll函数:

Option Explicit

Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" (ByRef saArray() As Any) As Long

Private Sub Form_Load()
  Dim Cdo() As String
  'Cdo = Split("a,b,c", ",")

  If SafeArrayGetDim(Cdo) <> 0 Then
    MsgBox "Array has been Initialized"
  End If

End Sub
问候托马斯

function ItExists(byval j as integer) as boolean

  On Error Resume Next
  if lenb((j,0)(0)) then
  'Nothing
  end if
  ItExists=(err.number=0)
  On Error Goto 0

end function

像上面这样的东西应该会起作用。玩它,让它做你想做的事。

我为这个问题找到了另一个解决方案

    Option Base 0
    Option Compare Binary
    Option Explicit

    Private Const VT_BYREF = &H4000
    Private Const VARIANT_DATA_OFFSET As Long = 8

    Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" _
        (ByVal pSA As Long) _
        As Long

    Private Declare Function SafeArrayGetLBound Lib "oleaut32.dll" _
        (ByVal pSA As Long, _
         ByVal nDim As Long, _
         ByRef plLbound As Long) _
        As Long

    Private Declare Function SafeArrayGetUBound Lib "oleaut32.dll" _
        (ByVal pSA As Long, _
         ByVal nDim As Long, _
         ByRef plUbound As Long) _
        As Long

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (ByRef lpDest As Any, _
         ByRef lpSource As Any, _
         ByVal lByteLen As Long)
    '


    Public Function LBoundEx(ByRef vArray As Variant, _
                             Optional ByVal lDimension As Long = 1) As Long

        Dim iDataType As Integer
        Dim pSA As Long

        'Make sure an array was passed in:
        If IsArray(vArray) Then

            'Try to get the pointer:
            CopyMemory pSA, ByVal VarPtr(vArray) + VARIANT_DATA_OFFSET, 4

            If pSA Then

                'If byref then deref the pointer to get the actual pointer:
                CopyMemory iDataType, vArray, 2
                If iDataType And VT_BYREF Then
                    CopyMemory pSA, ByVal pSA, 4
                End If

                If pSA Then
                    If lDimension > 0 Then
                        'Make sure this is a valid array dimension:
                        If lDimension <= SafeArrayGetDim(pSA) Then
                            'Get the LBound:
                            SafeArrayGetLBound pSA, lDimension, LBoundEx
                        Else
                            LBoundEx = -1
                        End If
                    Else
                        Err.Raise vbObjectError Or 10000, "LBoundEx", "Invalid Dimension"
                    End If
                Else
                    LBoundEx = -1
                End If
            Else
                LBoundEx = -1
            End If
        Else
            Err.Raise vbObjectError Or 10000, "LBoundEx", "Not an array"
        End If

    End Function


    Public Function UBoundEx(ByRef vArray As Variant, _
                             Optional ByVal lDimension As Long = 1) As Long

        Dim iDataType As Integer
        Dim pSA As Long

        'Make sure an array was passed in:
        If IsArray(vArray) Then

            'Try to get the pointer:
            CopyMemory pSA, ByVal VarPtr(vArray) + VARIANT_DATA_OFFSET, 4

            If pSA Then

                'If byref then deref the pointer to get the actual pointer:
                CopyMemory iDataType, vArray, 2
                If iDataType And VT_BYREF Then
                    CopyMemory pSA, ByVal pSA, 4
                End If

                If pSA Then
                    If lDimension > 0 Then
                        'Make sure this is a valid array dimension:
                        If lDimension <= SafeArrayGetDim(pSA) Then
                            'Get the UBound:
                            SafeArrayGetUBound pSA, lDimension, UBoundEx
                        Else
                            UBoundEx = -1
                        End If
                    Else
                        Err.Raise vbObjectError Or 10000, "UBoundEx", "Invalid Dimension"
                    End If
                Else
                    UBoundEx = -1
                End If
            Else
                UBoundEx = -1
            End If
        Else
            Err.Raise vbObjectError Or 10000, "UBoundEx", "Not an array"
        End If

    End Function



    Private Function test()
    Dim Cdo() As Variant
    Dim a() As String
    Dim b() As String

    ReDim Cdo(1 To 5, 1 To 2)
    ReDim a(1 To 2)
    ReDim b(1 To 3, 1 To 2)

    Cdo(1, 2) = a
    Cdo(2, 2) = b

    '- test
    Dim x As Long
    Dim y As Long
    Dim z As Long
    Dim q As Long
    Dim ok As Boolean

    x = 2
    y = 2
    z = 2
    q = 2 '- set to -1 for Cdo(x, y)(z) and to >=0 for Cdo(x, y)(z,q)

    ok = False

    If (UBoundEx(Cdo, 1) >= x) Then
      If (UBoundEx(Cdo, 2) >= y) Then
        If (Not IsEmpty(Cdo(x, y))) Then
          If (UBoundEx(Cdo(x, y), 1) >= z) Then
            If (q >= 0) Then
              If (UBoundEx(Cdo(x, y), 2) >= q) Then
                Debug.Print Cdo(x, y)(z, q)
                ok = True
              End If
            Else
              If (UBoundEx(Cdo(x, y), 2) = -1) Then
                Debug.Print Cdo(x, y)(z)
                ok = True
              End If
            End If
          End If
        End If
      End If
    End If

    if (ok) then
      debug.print "OK"
    end it
  End Function
选项库0
选项比较二进制
选项显式
私人Const VT_BYREF=&H4000
专用常量变量数据偏移量,长度=8
专用声明函数SafeArrayGetDim Lib“oleaut32.dll”_
(ByVal pSA尽可能长)_
只要
私有声明函数safeArrayGetlbund Lib“oleaut32.dll”_
(ByVal pSA,只要_
拜瓦尔·恩迪姆,只要_
ByRef plLbound(长度相同)_
只要
专用声明函数SafeArrayGetUBound Lib“oleaut32.dll”_
(ByVal pSA,只要_
拜瓦尔·恩迪姆,只要_
ByRef plUbound(尽可能长)_
只要
私有声明子CopyMemory Lib“kernel32”别名“rtlmovemory”_
(ByRef lpDest,如有)_
ByRef lpSource作为任何_
ByVal lByteLen(长度相同)
'
公共函数LBoundEx(ByRef vArray作为变体_
可选的ByVal尺寸长度=1)长度
Dim iDataType为整数
尽可能长
'确保传入了一个数组:
如果是艾萨瑞(瓦雷)那么
'尝试获取指针:
CopyMemory pSA,ByVal VarPtr(vArray)+变量数据偏移量,4
如果是pSA那么
'如果是byref,则取消引用指针以获取实际指针:
CopyMemory iDataType,vArray,2
如果iDataType和VT_BYREF
CopyMemory pSA,ByVal pSA,4
如果结束
如果是pSA那么
如果尺寸>0,则
'确保这是一个有效的数组维度:
如果维数为0,则
'确保这是一个有效的数组维度:

如果我对ldiDimension感到好奇,是否有任何方法可以执行类似Cdo.size()的操作?数组绝对是初始化的-它是一个带有两个二维数组的锯齿数组。问题是,(403,0)(0)可能存在,而(403,0)(0,0)可能不存在。或者(404,0)(0,0)存在,而其父(404,0)(0)不存在。更准确地说,不是存在/不存在,而是下标超出范围错误。抱歉。。。我很困惑。。。如何创建阵列?在VBA中,通常没有像XX(a,b)(c,d)数组那样的“多”数组-只有XX(a,b,c,d…)?!但如果出现错误,则表示您访问的位置未验证=>未初始化,因为您使用的数组XX(a,b)包含未初始化的数组(c,d)。您可以使用锯齿数组,即子数组中具有异构长度的数组中的数组。引用它们就像我在上面展示的那样,例如,(1,2)(2,2)是第一个数组中的第1行第2列,第2行第2列是第一个数组中的第1行第2列。我引用的数组有5、3和1维,中间的一个是锯齿状的。我无法理解为什么Nanex在只有两个真实变量的情况下决定这个虐待狂结构。谢谢!我希望有一种在元素级别通过布尔值进行测试的方法,不过,出错恢复下一步让我害怕。不用担心,大男孩们一直在使用它,不使用它很好,但你必须做你有时必须做的事情!
function ItExists(byval j as integer) as boolean

  On Error Resume Next
  if lenb((j,0)(0)) then
  'Nothing
  end if
  ItExists=(err.number=0)
  On Error Goto 0

end function
    Option Base 0
    Option Compare Binary
    Option Explicit

    Private Const VT_BYREF = &H4000
    Private Const VARIANT_DATA_OFFSET As Long = 8

    Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" _
        (ByVal pSA As Long) _
        As Long

    Private Declare Function SafeArrayGetLBound Lib "oleaut32.dll" _
        (ByVal pSA As Long, _
         ByVal nDim As Long, _
         ByRef plLbound As Long) _
        As Long

    Private Declare Function SafeArrayGetUBound Lib "oleaut32.dll" _
        (ByVal pSA As Long, _
         ByVal nDim As Long, _
         ByRef plUbound As Long) _
        As Long

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (ByRef lpDest As Any, _
         ByRef lpSource As Any, _
         ByVal lByteLen As Long)
    '


    Public Function LBoundEx(ByRef vArray As Variant, _
                             Optional ByVal lDimension As Long = 1) As Long

        Dim iDataType As Integer
        Dim pSA As Long

        'Make sure an array was passed in:
        If IsArray(vArray) Then

            'Try to get the pointer:
            CopyMemory pSA, ByVal VarPtr(vArray) + VARIANT_DATA_OFFSET, 4

            If pSA Then

                'If byref then deref the pointer to get the actual pointer:
                CopyMemory iDataType, vArray, 2
                If iDataType And VT_BYREF Then
                    CopyMemory pSA, ByVal pSA, 4
                End If

                If pSA Then
                    If lDimension > 0 Then
                        'Make sure this is a valid array dimension:
                        If lDimension <= SafeArrayGetDim(pSA) Then
                            'Get the LBound:
                            SafeArrayGetLBound pSA, lDimension, LBoundEx
                        Else
                            LBoundEx = -1
                        End If
                    Else
                        Err.Raise vbObjectError Or 10000, "LBoundEx", "Invalid Dimension"
                    End If
                Else
                    LBoundEx = -1
                End If
            Else
                LBoundEx = -1
            End If
        Else
            Err.Raise vbObjectError Or 10000, "LBoundEx", "Not an array"
        End If

    End Function


    Public Function UBoundEx(ByRef vArray As Variant, _
                             Optional ByVal lDimension As Long = 1) As Long

        Dim iDataType As Integer
        Dim pSA As Long

        'Make sure an array was passed in:
        If IsArray(vArray) Then

            'Try to get the pointer:
            CopyMemory pSA, ByVal VarPtr(vArray) + VARIANT_DATA_OFFSET, 4

            If pSA Then

                'If byref then deref the pointer to get the actual pointer:
                CopyMemory iDataType, vArray, 2
                If iDataType And VT_BYREF Then
                    CopyMemory pSA, ByVal pSA, 4
                End If

                If pSA Then
                    If lDimension > 0 Then
                        'Make sure this is a valid array dimension:
                        If lDimension <= SafeArrayGetDim(pSA) Then
                            'Get the UBound:
                            SafeArrayGetUBound pSA, lDimension, UBoundEx
                        Else
                            UBoundEx = -1
                        End If
                    Else
                        Err.Raise vbObjectError Or 10000, "UBoundEx", "Invalid Dimension"
                    End If
                Else
                    UBoundEx = -1
                End If
            Else
                UBoundEx = -1
            End If
        Else
            Err.Raise vbObjectError Or 10000, "UBoundEx", "Not an array"
        End If

    End Function



    Private Function test()
    Dim Cdo() As Variant
    Dim a() As String
    Dim b() As String

    ReDim Cdo(1 To 5, 1 To 2)
    ReDim a(1 To 2)
    ReDim b(1 To 3, 1 To 2)

    Cdo(1, 2) = a
    Cdo(2, 2) = b

    '- test
    Dim x As Long
    Dim y As Long
    Dim z As Long
    Dim q As Long
    Dim ok As Boolean

    x = 2
    y = 2
    z = 2
    q = 2 '- set to -1 for Cdo(x, y)(z) and to >=0 for Cdo(x, y)(z,q)

    ok = False

    If (UBoundEx(Cdo, 1) >= x) Then
      If (UBoundEx(Cdo, 2) >= y) Then
        If (Not IsEmpty(Cdo(x, y))) Then
          If (UBoundEx(Cdo(x, y), 1) >= z) Then
            If (q >= 0) Then
              If (UBoundEx(Cdo(x, y), 2) >= q) Then
                Debug.Print Cdo(x, y)(z, q)
                ok = True
              End If
            Else
              If (UBoundEx(Cdo(x, y), 2) = -1) Then
                Debug.Print Cdo(x, y)(z)
                ok = True
              End If
            End If
          End If
        End If
      End If
    End If

    if (ok) then
      debug.print "OK"
    end it
  End Function