Dim Result() As Variant
私の時計ウィンドウでは、これは次のように表示されます
Expression | Value | Type
Result | | Variant/Variant()
以下を確認するにはどうすればよいですか。
if Result is nothing then
または
if Result is Not Set then
これは基本的に私が達成しようとしていることですが、最初のものは機能せず、2番目のものは存在しません。
Chip Pearsonは、このようなことをテストするための一連の関数を含む modArraySupport という便利なモジュールを作成しました。あなたの場合、あなたはIsArrayAllocated
を使いたいでしょう。
Public Function IsArrayAllocated(Arr As Variant) As Boolean
この関数は、指定された配列が割り当てられている(空ではない)かどうかを示すTRUEまたはFALSEを返します。配列のTRUEを返します。静的配列、またはRedimステートメントで割り当てられた動的配列です。配列がまだReDimでサイズ設定されていない動的配列であるか、Eraseステートメントで割り当てが解除されている場合はFALSEを返します。この関数は基本的にArrayIsEmptyの反対です。例えば、
Dim Result() As Variant
Dim R As Boolean
R = IsArrayAllocated(Result) ' returns false
ReDim V(1 To 10)
R = IsArrayAllocated(Result) ' returns true
使用される手法は、基本的に配列の境界をテストすることです(@Tim Williamsによって提案されています)が、追加の落とし穴があります。
すぐにウィンドウでテストするには:
?IsArrayAllocated(Result)
ウォッチウィンドウでのテスト:これを行う方法はいくつかあります。たとえば、R
に時計を追加し、[時計の種類]で[値が変更されたときに中断]を選択します。
エラー処理を回避するために、私はこれを使用しました。これはずっと前にフォーラムで見られ、それ以来成功裏に使用されています。
If (Not Not Result) <> 0 Then 'Means it is allocated
または代わりに
If (Not Not Result) = 0 Then 'Means it is not allocated
私はこれを主にこの方法で未設定の配列から配列サイズを拡張するために使用しました
'Declare array
Dim arrIndex() As Variant
'Extend array
If (Not Not Result) = 0 Then
ReDim Preserve Result(0 To 0)
Else
ReDim Preserve Result(0 To UBound(Result) + 1)
End If
イミディエイトウィンドウで以下を使用できます。
_?Result Is Nothing
?IsNull( Result )
?IsEmpty( Result )
?IsMissing( Result )
_
1つ目は、完全を期すためのものです。 Resultはオブジェクトではないため、_Result Is Nothing
_はエラーをスローします。 Empty
は、初期化されていないバリアント用です ディメンション化されていない配列を含みます。。
(更新)いくつかの追加チェックを行ったところ、1つの例外を除いて、IsEmptyが宣言された配列(Redimされているかどうかに関係なく)でtrueを返すことは決してないことがわかりました。私が見つけた唯一の例外は、配列がパブリックとしてではなくモジュールレベルで宣言されている場合と、イミディエイトウィンドウでチェックした場合のみです。
Missing
関数またはサブに渡されるオプションの値の場合。 Optional Foo() As Variant
を宣言することはできませんが、ParamArray Foo() As Variant
のようなものを使用できます。その場合、何も渡されない場合、IsMissing
はtrueを返します。
したがって、配列が初期化されているかどうかを判断する唯一の方法は、以下をチェックするプロシージャを作成することです。
_Public Function IsDimensioned(vValue As Variant) As Boolean
On Error Resume Next
If Not IsArray(vValue) Then Exit Function
Dim i As Integer
i = UBound(Bar)
IsDimensioned = Err.Number = 0
End Function
_
ところで、このルーチン(またはJean-FrançoisCorbettによって投稿されたライブラリ)は、配列のサイズが決定されてから消去されるとfalseを返すことに注意してください。
(Not Array) = -1
のような言語アーティファクトを使用して初期化をチェックすることは読みにくく、メンテナンスの頭痛の種になると思うので、少し異なるアプローチをお勧めします。
配列の割り当てを確認する必要がある場合は、独自の「ベクトル」タイプを作成しようとしていることが原因である可能性があります。これは、データが追加されるときにデータに対応するために実行時に大きくなる配列です。型システムを利用すれば、VBAを使用するとベクトル型をかなり簡単に実装できます。
Type Vector
VectorData() As Variant
VectorCount As Long
End Type
Dim MyData As Vector
Sub AddData(NewData As Variant)
With MyData
' If .VectorData hasn't been allocated yet, allocate it with an
' initial size of 16 elements.
If .VectorCount = 0 Then ReDim .VectorData(1 To 16)
.VectorCount = .VectorCount + 1
' If there is not enough storage for the new element, double the
' storage of the vector.
If .VectorCount > UBound(.VectorData) Then
ReDim Preserve .VectorData(1 To UBound(.VectorData) * 2)
End If
.VectorData(.VectorCount) = NewData
End With
End Sub
' Example of looping through the vector:
For I = 1 To MyData.VectorCount
' Process MyData.VectorData(I)
Next
VectorCount
変数をチェックするだけなので、このコードで配列の割り当てをチェックする必要がないことに注意してください。 0の場合、ベクトルにはまだ何も追加されていないため、配列は割り当てられていません。
このコードは単純で単純であるだけでなく、ベクトルには配列のすべてのパフォーマンス上の利点があり、要素を追加するための償却コストは実際にはO(1)であり、これは非常に効率的です。唯一のトレードオフは、ベクターのスペースが不足するたびにストレージが2倍になるため、最悪の場合、ベクターのストレージの50%が無駄になることです。
受け入れられた回答の4行目は次のように言うべきだと思います。
ReDim Result(1 To 10)
の代わりに:
ReDim V(1 To 10)
5行目:
R = IsArrayAllocated(Result) ' returns true
3行目と同じようにFALSEを返します。
R = IsArrayAllocated(Result) ' returns false
結果は4行目で再ディメンション化されたものではないためです。
4行目では、Vという配列の再ディメンション化が試みられていますが、宣言されていません。
配列のLBound
を確認してください。エラーが発生した場合は、初期化されていません。