【问题标题】:check if array has values and bypass if empty检查数组是否有值,如果为空则绕过
【发布时间】:2018-09-14 21:22:25
【问题描述】:

所以我的代码设置为发送一封电子邮件,其中包含符合特定单元格名称的所有行(缺少文本)。如果搜索中没有这些,我希望它绕过并输入“无”。如果有单元格有它,它工作得很好,但如果没有,我会得到一个下标超出范围错误。

Dim MissingText() As Variant
Dim WrongNum() As Variant
Dim BlankText() As Variant
Dim objOutlook As Object
Dim objMsg As Object


Set objOutlook = CreateObject("Outlook.Application")
Erase MissingText, WrongNum, BlankText

Listed = 0
Ending = Cells(Rows.Count, 5).End(xlUp).Row
n = 0
For Listed = 2 To Ending
    If Cells(Listed, 10).Value = "Missing Text" Then
        ReDim Preserve MissingText(n)
        MissingText(n) = Listed
        n = n + 1
    End If

Next Listed
If IsEmpty(MissingText) Then
    MissingTogether = "None"
    GoTo MissingSkip
End If
CountArray = UBound(MissingText, 1) - LBound(MissingText, 1) + 1
CountArray = CountArray - 1
MissingTogether = Join(MissingText, ", ")
MissingSkip:

(继续) 在 CountArray = UBound(MissingText, 1) - LBound(MissingText, 1) + 1 是发生错误的时间。任何帮助都会很好,谢谢。

【问题讨论】:

  • 为什么不测试n>0
  • LOL 我想我是想让它变得更复杂,而且我已经盯着它看了一段时间。谢谢
  • 是的,您可以检查是否n > 0 或使用布尔变量(如果您没有n),或使用this answer 中提到的函数如果您必须检查用于代码中许多地方的初始化数组。
  • 是的,擦除后重新调整变体很好,但测试它是否有用是浪费时间。 IsArray 为真,IsMissing 和 IsEmpty 均为假。 LBound 和 UBound 都抛出错误。

标签: arrays excel vba


【解决方案1】:

正如 cmets 中所指出的,在 VBA 中没有确定数组是否未初始化的本地方法。但是,您可以检查它的内存占用以查看它的变量是否包含空指针。请注意,VarPtr 会引发数组类型不匹配,因此需要先将其包装在 Variant 中:

'In declarations section:
#If VBA7 Then
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias _
        "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, _
        ByVal length As Long)
#Else
    Private Declare Sub CopyMemory Lib "kernel32" Alias _
        "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, _
        ByVal length As Long)
#End If

Private Const VT_BY_REF As Integer = &H4000&
Private Const DATA_OFFSET As Long = 8

Private Function IsUninitializedArray(SafeArray As Variant) As Boolean
    If Not IsArray(SafeArray) Then
        Exit Function
    End If

    Dim vtype As Integer
    'First 2 bytes are the VARENUM.
    CopyMemory vtype, SafeArray, LenB(vtype)
#If VBA7 Then
    Dim lp As LongPtr
#Else
    Dim lp As Long
#End If
    'Get the data pointer.
    CopyMemory lp, ByVal VarPtr(SafeArray) + DATA_OFFSET, LenB(lp)
    'Make sure the VARENUM is a pointer.
    If (vtype And VT_BY_REF) <> 0 Then
        'Dereference it for the actual data address.
        CopyMemory lp, ByVal lp, LenB(lp)
        IsUninitializedArray = lp <> 0
    End If
End Function

使用示例:

Public Sub Example()
    Dim Test() As String
    MsgBox IsUninitializedArray(Test) 'False

    Test = Split(vbNullString)
    MsgBox IsUninitializedArray(Test) 'True

    Erase Test
    MsgBox IsUninitializedArray(Test) 'False
End Sub

【讨论】:

    【解决方案2】:

    我将使用一个字符串变量和split()它。

    dim strMissing as string, aryMissing as variant
    
    For Listed = 2 To Ending
        If Cells(Listed, 10).Value = "Missing Text" Then
            strMissing = Listed & ", " & strMissing
        End If
    Next Listed
    
    If strMissing = "" then 
        MissingTogether = "None"
        GoTo MissingSkip
    else
        aryMissing = split(strMissing, ", ")
        CountArray = UBound(MissingText, 1) - LBound(MissingText, 1) + 1
    End If
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      • 2022-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多