проверить, есть ли у массива значения, и обойти, если он пуст - PullRequest
0 голосов
/ 15 сентября 2018

Итак, мой код настроен на отправку электронного письма со всеми строками, которые соответствуют определенному имени ячейки (отсутствует текст). если в поиске нет ни одного из них, я хочу, чтобы он обошел и ввел «None». Если есть ячейки, у которых он есть, он прекрасно работает, но если их нет, я получаю Подстрочный индекс o Ошибка диапазона.

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, когда происходит ошибка. любая помощь была бы хороша, спасибо.

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

Как отмечено в комментариях, нет собственного способа определить, не является ли массив неинициализированным в 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
0 голосов
/ 15 сентября 2018

Я буду использовать строковую переменную и split() it.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...