web-dev-qa-db-ja.com

VBAマクロで空の配列を確認する方法

空の配列を確認したい。 Googleはさまざまなソリューションを提供してくれましたが、何も機能しませんでした。たぶん私はそれらを正しく適用していません。

_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は空なので。それを避ける方法はありますか?

56
Vicky

文字列配列を処理しているときに、結合を検討しましたか?

If Len(Join(FileNamesList)) > 0 Then
73
Fionnuala

トリプルネガティブで行く:

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 myArrayはSafeArrayポインターを返します。初期化されていない配列の場合、-1を返します。 Not thisをXOR -1で指定できます。したがって、必要に応じてゼロを返します。

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

ソース

62
ahuth

配列関数でテストすると、すべての境界で機能します。

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
28
Lance Roberts

私はここで同じような答えを見る...しかし私のものではない...

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
6
Perposterer

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
5
BBQ Chef

このコードはあなたが期待することをしません:

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

空の文字列("")またはvbNullStringDirに渡すと、現在のディレクトリパス(CurDir$によって返されるパス)の最初のファイルの名前が返されます。したがって、SigStringが空の場合、If条件はTrueに評価されます。これは、Dirが空でない文字列(現在のディレクトリの最初のファイルの名前)、およびGetBoilerが呼び出されます。 SigStringが空の場合、fso.GetFileの呼び出しは失敗します。

条件を変更してSigStringが空でないことを確認するか、Dirの代わりにFileSystemObject.FileExistsメソッドを使用して、ファイルが存在するかどうかを確認する必要があります。 Dirは、予期しない動作を行うため、正確に使用するのは困難です。個人的には、面白いビジネスがないので、DirではなくScripting.FileSystemObjectを使用します(ファイルが存在する場合はFileExistsTrueを返し、そうでない場合はFalseを返します)。さらに、FileExistsは、コードのintentDirよりも明確に表します。

方法1:SigStringが最初に空でないことを確認する

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
4
Mike Spross

偉大なチップピアソンによるコードの下に貼り付けているだけです。それは魅力的です。
ここに彼の 配列関数のページ があります。

これがお役に立てば幸いです。

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
4
sancho.s

Authは最も近いものでしたが、彼の答えは型の不一致エラーをスローします。

他の回答については、可能な場合はエラーを使用して条件をテストすることは避けてください。少なくともデバッグが複雑になるためです(他の何かがそのエラーを引き起こしている場合)。

シンプルで完全なソリューションを次に示します。

option explicit
Function foo() As Variant

    Dim bar() As String

    If (Not Not bar) Then
        ReDim Preserve bar(0 To UBound(bar) + 1)
    Else
        ReDim Preserve bar(0 To 0)
    End If

    bar(UBound(bar)) = "it works!"

    foo = bar

End Function
2
Mike Bethany

空の配列の簡易チェック:

Dim exampleArray() As Variant 'Any Type

If ((Not Not exampleArray) = 0) Then
      'Array is Empty
Else
      'Array is Not Empty
End If
2
Robert S.

Ahuthの answer ;に基づく

_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

2
user425678

Byte配列が空かどうかを確認するには、VBA関数StrPtr()を使用するのが最も簡単な方法です。

バイト配列が空の場合、StrPtr()0;それ以外の場合は、ゼロ以外の値を返します(ただし、 じゃない 最初の要素へのアドレス)。

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

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

ただし、Byte配列でのみ機能します。

1
Fuzzier

別の方法は、より早くそれを行うことです。ブール変数を作成し、配列にデータを読み込んだらtrueに設定できます。本当に必要なのは、データを配列にロードするときのifステートメントだけです。

1
Tim Boutchia
Public Function IsEmptyArray(InputArray As Variant) As Boolean

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

   ErrHandler:
   IsEmptyArray = True

End Function
1
Zhenya

別の方法があります。私はいくつかのケースでそれを使用しましたが、機能しています。

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
1
Surya
Function IsVarArrayEmpty(anArray As Variant) as boolean
    On Error Resume Next
    IsVarArrayEmpty = true
    IsVarArrayEmpty = UBound(anArray) < LBound(anArray)
End Function

たぶんuboundがクラッシュしてtrueのままになることがあり、ubound < lbound、 空っぽです

1
Pierre

その数を確認できます。

ここでcidは配列です。

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

これがお役に立てば幸いです。ごきげんよう!

0
Mantej Singh

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ミリ秒の初期化が必要なので、10M要素の配列には約3秒かかります。同じ機能をScriptControl ActiveXを介して実装できます(64ビットMS Officeバージョンでは使用できないため、 this のような回避策を使用できます)。

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

意図したとおりに問題と質問を一般化します。配列の割り当てをテストし、最終的なエラーをキャッチします

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より大きい配列が欠落していることは確かです。奇妙な土地で、はい。

0
jpinto3912

個人的には、上記の答えの1つを変更して、配列に内容があるかどうかを確認できると思います。

if UBound(ar) > LBound(ar) Then

これは負の数の参照を処理し、他のオプションのいくつかよりも時間がかかりません。

0
Jim Snyder

以下の関数を使用して、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
0