programing

vba 매크로에서 빈 배열을 확인하는 방법

linuxpc 2023. 4. 26. 23:01
반응형

vba 매크로에서 빈 배열을 확인하는 방법

빈 배열을 확인하고 싶습니다.구글은 저에게 다양한 해결책을 주었지만 아무 것도 작동하지 않았습니다.아마도 제가 그것들을 올바르게 적용하지 않는 것 같습니다.

Function GetBoiler(ByVal sFile As String) As String
'Email Signature
    Dim fso As Object
    Dim ts As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
    GetBoiler = ts.ReadAll
    ts.Close
End Function

Dim FileNamesList As Variant, i As Integer
' activate the desired startfolder for the filesearch
FileNamesList = CreateFileList("*.*", False) ' Returns File names
' performs the filesearch, includes any subfolders
' present the result
' If there are Signatures then populate SigString
Range("A:A").ClearContents
For i = 1 To UBound(FileNamesList)
    Cells(i + 1, 1).Formula = FileNamesList(i)
Next i

SigString = FileNamesList(3)

If Dir(SigString) <> "" Then
    Signature = GetBoiler(SigString)
Else
    Signature = ""
End If

여기서 만약FileNamesList배열이 비어 있습니다.GetBoiler(SigString)전화를 받아서는 안 됩니다.FileNamesList배열이 비어 있습니다.SigString또한 비어 있으며 이 호출이 발생합니다.GetBoiler()빈 문자열로 함수를 지정합니다.라인에서 오류가 발생합니다.

Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)

이래sFile비어 있습니다.그것을 피할 방법은 없습니까?

트리플 네거티브로 진행:

If (Not Not FileNamesList) <> 0 Then
    ' Array has been initialized, so you're good to go.
Else
    ' Array has NOT been initialized
End If

아니면 그냥:

If (Not FileNamesList) = -1 Then
    ' Array has NOT been initialized
Else
    ' Array has been initialized, so you're good to go.
End If

로든 VB 에는어든이유.Not myArraySafeArray 포인터를 반환합니다.초기화되지 않은 어레이의 경우 -1을 반환합니다.넌 할 수 있다.Not이 값을 XOR에 -1로 표시하여 원하는 경우 0을 반환합니다.

               (Not myArray)   (Not Not myArray)
Uninitialized       -1                 0
Initialized    -someBigNumber   someOtherBigNumber

원천

문자열 배열을 다룰 때 참여를 고려해 보셨습니까?

If Len(Join(FileNamesList)) > 0 Then

배열 함수에서 테스트하는 경우 모든 범위에서 작동합니다.

Function IsVarArrayEmpty(anArray As Variant)

Dim i As Integer

On Error Resume Next
    i = UBound(anArray,1)
If Err.number = 0 Then
    IsVarArrayEmpty = False
Else
    IsVarArrayEmpty = True
End If

End Function

여기 비슷한 답이 보입니다...하지만 내 것은...

이런 식으로 처리하게 될 것은 유감스럽게도...나는 len(join(arr) > 0 접근법을 좋아하지만 배열이 빈 문자열 배열이었다면 작동하지 않았을 것입니다...

Public Function arrayLength(arr As Variant) As Long
  On Error GoTo handler

  Dim lngLower As Long
  Dim lngUpper As Long

  lngLower = LBound(arr)
  lngUpper = UBound(arr)

  arrayLength = (lngUpper - lngLower) + 1
  Exit Function

handler:
  arrayLength = 0 'error occured.  must be zero length
End Function

VBA를 쓸 때 머릿속에 다음과 같은 문장이 있습니다. "그렇게 쉬울 수도 있지만...."

제가 채택한 것은 다음과 같습니다.

Private Function IsArrayEmpty(arr As Variant)
  ' This function returns true if array is empty
  Dim l As Long

  On Error Resume Next
  l = Len(Join(arr))
  If l = 0 Then
    IsArrayEmpty = True
  Else
    IsArrayEmpty = False
  End If

  If Err.Number > 0 Then
      IsArrayEmpty = True
  End If

  On Error GoTo 0
End Function

Private Sub IsArrayEmptyTest()
  Dim a As Variant
  a = Array()
  Debug.Print "Array is Empty is " & IsArrayEmpty(a)
  If IsArrayEmpty(a) = False Then
    Debug.Print "  " & Join(a)
  End If
End Sub

이 코드는 사용자가 예상한 대로 작동하지 않습니다.

If Dir(SigString) <> "" Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

문자열을 (으)로 표시됩니다."") 또는vbNullStringDir은 현재 경로에 첫 번째 합니다(" "" "" "" "" "가 ).CurDir$. 그래서 만약에SigString비어 있습니다, 당신의If은 상는다음같평것입다니될가이태로 평가됩니다.TrueDir 않은 문자열의 첫 을 반환하고, " " " " " " " " " " " (" " " " " " " " " ( " " " " " " " " " " " " " " " 을 합니다.GetBoiler호출됩니다.그리고 만약에SigString. 이 은 " 비있다니습"입니다. 호출:fso.GetFile실패합니다.

은 당신의 의 상태를 .SigString비어 있지 않거나 다음을 사용합니다.FileSystemObject.FileExists 대신 Dir파일이 있는지 확인합니다. Dir예상치 못한 일을 하기 때문에 정확하게 사용하기가 어렵습니다. 저는 는개으로적인을 할 것입니다.Scripting.FileSystemObject1파운드가 Dir일이입니다.FileExists아온다를 합니다.True 음, 파이존다면, 음고리, 그일,False그렇지 않으면). 다가게,FileExists코드의 의도를 훨씬 명확하게 표현합니다.Dir.

1: 방법 1: 확인을 SigString non-empty 먼저있않습다니지비어▁non다▁is▁first니않습

If SigString <> "" And Dir(SigString) <> "" Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

방법 2: 을 사용합니다.FileSystemObject.FileExists방법

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")

If fso.FileExists(SigString) Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

저는 위대한 칩 피어슨의 코드 아래에 간단히 붙여넣고 있습니다.그것은 매력적입니다.
여기 배열 함수에 대한 그의 페이지가 있습니다.

이것이 도움이 되길 바랍니다.

Public Function IsArrayEmpty(Arr As Variant) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsArrayEmpty
' This function tests whether the array is empty (unallocated). Returns TRUE or FALSE.
'
' The VBA IsArray function indicates whether a variable is an array, but it does not
' distinguish between allocated and unallocated arrays. It will return TRUE for both
' allocated and unallocated arrays. This function tests whether the array has actually
' been allocated.
'
' This function is really the reverse of IsArrayAllocated.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    Dim LB As Long
    Dim UB As Long

    err.Clear
    On Error Resume Next
    If IsArray(Arr) = False Then
        ' we weren't passed an array, return True
        IsArrayEmpty = True
    End If

    ' Attempt to get the UBound of the array. If the array is
    ' unallocated, an error will occur.
    UB = UBound(Arr, 1)
    If (err.Number <> 0) Then
        IsArrayEmpty = True
    Else
        ''''''''''''''''''''''''''''''''''''''''''
        ' On rare occasion, under circumstances I
        ' cannot reliably replicate, Err.Number
        ' will be 0 for an unallocated, empty array.
        ' On these occasions, LBound is 0 and
        ' UBound is -1.
        ' To accommodate the weird behavior, test to
        ' see if LB > UB. If so, the array is not
        ' allocated.
        ''''''''''''''''''''''''''''''''''''''''''
        err.Clear
        LB = LBound(Arr)
        If LB > UB Then
            IsArrayEmpty = True
        Else
            IsArrayEmpty = False
        End If
    End If

End Function

빈 어레이에 대한 단순화된 검사:

Dim exampleArray() As Variant 'Any Type

If ((Not Not exampleArray) = 0) Then
      'Array is Empty
Else
      'Array is Not Empty
End If

여기 다른 방법이 있습니다.저는 그것을 사용한 적이 있고 효과가 있습니다.

Function IsArrayEmpty(arr As Variant) As Boolean

Dim index As Integer

index = -1
    On Error Resume Next
        index = UBound(arr)
    On Error GoTo 0

If (index = -1) Then IsArrayEmpty = True Else IsArrayEmpty = False

End Function

ahuth의 대답에 근거하여;

Function AryLen(ary() As Variant, Optional idx_dim As Long = 1) As Long
    If (Not ary) = -1 Then
        AryLen = 0
    Else
        AryLen = UBound(ary, idx_dim) - LBound(ary, idx_dim) + 1
    End If
End Function

배열을 합니다.is_empty = AryLen(some_array)=0

Public Function IsEmptyArray(InputArray As Variant) As Boolean

   On Error GoTo ErrHandler:
   IsEmptyArray = Not (UBound(InputArray) >= 0)
   Exit Function

   ErrHandler:
   IsEmptyArray = True

End Function

아래 기능을 사용하여 vba에서 변형 또는 문자열 배열이 비어 있는지 확인할 수 있습니다.

Function IsArrayAllocated(Arr As Variant) As Boolean
        On Error Resume Next
        IsArrayAllocated = IsArray(Arr) And _
                           Not IsError(LBound(Arr, 1)) And _
                           LBound(Arr, 1) <= UBound(Arr, 1)
End Function

샘플사용량

Public Function test()
Dim Arr(1) As String
Arr(0) = "d"
Dim x As Boolean
x = IsArrayAllocated(Arr)
End Function

또 다른 방법은 그것을 더 빨리 하는 것입니다.데이터를 어레이에 로드하면 부울 변수를 생성하여 true로 설정할 수 있습니다. 따라서 데이터를 어레이에 로드할 때의 간단한 if 문만 있으면 됩니다.

함수 바 배 비 이 있 확 지 는 간 가 하 방 다 것 니 입 는 하 은 용 사 법 이 기 을 능 단 장 인 트 는 한 열 어 ▁the ▁is ▁to ▁is ▁v , ▁way 다 ▁to ▁use ▁the ▁whether 니 ▁a ▁simplest ▁empty ▁check 바 것 ▁byte 입 ▁array ba ba 이 트StrPtr().

바트배비있으면어이열이,StrPtr()아온다를 합니다.0그렇지 않으면 0이 아닌 값을 반환합니다(그러나 첫 번째 요소의 주소는 아닙니다).

Dim ar() As Byte
Debug.Assert StrPtr(ar) = 0

ReDim ar(0 to 3) As Byte
Debug.Assert StrPtr(ar) <> 0

그러나 바이트 배열에서만 작동합니다.

Function IsVarArrayEmpty(anArray As Variant) as boolean
    On Error Resume Next
    IsVarArrayEmpty = true
    IsVarArrayEmpty = UBound(anArray) < LBound(anArray)
End Function

아마도요.ubound충돌하고 그것은 사실로 남아 있습니다, 그리고 만약.ubound < lbound비어있습니다

의도한 대로 문제와 질문을 일반화하겠습니다.어레이에서 할당을 테스트하고 최종 오류를 감지합니다.

Function IsVarArrayEmpty(anArray as Variant)
Dim aVar as Variant

IsVarArrayEmpty=False
On error resume next
aVar=anArray(1)
If Err.number then '...still, it might not start at this index
    aVar=anArray(0)
    If Err.number then IsVarArrayEmpty=True ' neither 0 or 1 yields good assignment
EndIF
End Function

모든 음수 인덱스가 있거나 모두 1보다 큰 배열이 누락된 것은(는)그럴 가능성이 있습니까?이상한 나라에서, 네.

개인적으로 위의 답변 중 하나를 수정하여 배열에 내용이 있는지 확인할 수 있다고 생각합니다.

if UBound(ar) > LBound(ar) Then

이렇게 하면 음수 참조를 처리하고 다른 일부 옵션보다 시간이 적게 걸립니다.

JScript를 사용하여 총 할 수 .VBArray()개체(단일 또는 다차원의 변형 유형 배열과 함께 작동):

Sub Test()

    Dim a() As Variant
    Dim b As Variant
    Dim c As Long

    ' Uninitialized array of variant
    ' MsgBox UBound(a) ' gives 'Subscript out of range' error
    MsgBox GetElementsCount(a) ' 0

    ' Variant containing an empty array
    b = Array()
    MsgBox GetElementsCount(b) ' 0

    ' Any other types, eg Long or not Variant type arrays
    MsgBox GetElementsCount(c) ' -1

End Sub

Function GetElementsCount(aSample) As Long

    Static oHtmlfile As Object ' instantiate once

    If oHtmlfile Is Nothing Then
        Set oHtmlfile = CreateObject("htmlfile")
        oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
    End If
    GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)

End Function

각 요소의 초기화에 약 0.3 mksec + 15 msec이 소요되므로 10M 요소의 배열은 약 3초가 소요됩니다.다음을 통해 동일한 기능을 구현할 수 있습니다.ScriptControlActiveX(64비트 MS Office 버전에서는 사용할 수 없으므로 이와 같은 해결 방법을 사용할 수 있습니다.)

if Ubound(yourArray)>-1 then
 debug.print "The array is not empty"
else
 debug.print "EMPTY"
end if

당신은 그것의 개수를 확인할 수 있습니다.

여기서 cid는 배열입니다.

if (jsonObject("result")("cid").Count) = 0 them
MsgBox "Empty Array"

이것이 도움이 되길 바랍니다.좋은 하루 보내세요!

빈 어레이를 테스트하는 또 다른 솔루션

if UBound(ar) < LBound(ar) then msgbox "Your array is empty!"

또는 LBound가 0인 것을 이미 알고 있는 경우

if -1 = UBound(ar) then msgbox "Your array is empty!"

이것은 join()보다 빠를 수 있습니다. (그리고 나는 부정적인 인덱스로 확인하지 않았습니다.)

2개의 문자열 배열이 동일한 문자열을 공유하지 않도록 필터링하는 샘플입니다.

' Filtering ar2 out of strings that exists in ar1

For i = 0 To UBound(ar1)

    ' filter out any ar2.string that exists in ar1
    ar2 = Filter(ar2 , ar1(i), False)    

    If UBound(ar2) < LBound(ar2) Then
       MsgBox "All strings are the same.", vbExclamation, "Operation ignored":
       Exit Sub

    End If

Next

' At this point, we know that ar2 is not empty and it is filtered 
'
Public Function arrayIsEmpty(arrayToCheck() As Variant) As Boolean
    On Error GoTo Err:
    Dim forCheck
    forCheck = arrayToCheck(0)
    arrayIsEmpty = False
    Exit Function
Err:
    arrayIsEmpty = True
End Function

언급URL : https://stackoverflow.com/questions/206324/how-to-check-for-empty-array-in-vba-macro

반응형