LoginSignup
11
13

More than 5 years have passed since last update.

VBA標準機能で作成できる要素数0の配列

Last updated at Posted at 2018-08-25

前提

この記事における「要素数0の配列」は
UBound()LBound()に渡してもエラーが発生せず、UBound() - LBound() + 1を評価すると0となる一次元配列』とします。

はじめに

VBAでは、変数宣言などの記述で要素数0の配列を作成できません。

'Option Base 0

Dim myArray() As Variant
ReDim myArray(0) ' 要素数0ではなく添え字が0~0の要素数1個の配列

しかし、一部の型の配列に関してはVBA標準機能・組み込み関数の組み合わせで作成できます。
この記事では、その作成方法を記載しています。

また、この記事の方法はWindows環境でしか動作を確認していません。

動作確認環境
Windows 7   Microsoft Excel 2010 32bit
Windows 8.1 Microsoft Excel 2013 32bit
Windows 10  Microsoft Excel 2016 64bit

備考

以下のページのようにSAFEARRAY操作用のWindows APIを使用すれば、汎用的に要素数0の配列を作成できます。

[Excel VBA] 空の配列を管理する - くろねこ研究所

VBA ほぼタイプセーフなコレクション - Qiita

使用されているWindows API
SafeArrayAllocDescriptor function | Microsoft Docs

使用例

'引数1 :作成したい配列の次元数(VBAなら基本1でいいはず)
'引数2 :任意の型の配列
'返り値:成功・失敗(0なら成功)
Private Declare PtrSafe Function SafeArrayAllocDescriptor Lib "oleaut32" ( _
        ByVal cDims As Long, _
        ByRef ppsaOut() As Any _
    ) As Long

Property Get EmptyLongArray() As Long()
    Dim apiResult As Long
    apiResult = SafeArrayAllocDescriptor(1, EmptyLongArray)
    If apiResult <> 0 Then Err.Raise 5
End Property

要素数0の配列を取得する記述

VBAの標準機能では以下の型の要素数0の配列を作成できます。

  • Variant
  • String
  • Byte
  • オブジェクト

また記述の都合上、それぞれの配列を取得するプロシージャとして紹介します。

Variant型

比較的有名な方法だと思われますが、Array 関数に引数を渡さず実行すると得られます。

ヘルプにも記載されていますが、Option Base 1が設定されているかつArray()と記述するとVariant(1 To 0)の配列となるため注意が必要です。

Property Get EmptyVariantArray() As Variant()
    Let EmptyVariantArray = VBA.Array()
End Property

String型

Split 関数に長さ0の文字列を渡して実行すると得られます。

Property Get EmptyStringArray() As String()
    Let EmptyStringArray = VBA.Split(VBA.vbNullString)
End Property

Byte型

VBAのString型は内部的にはByte型の配列として扱われており、相互に代入が可能です。
長さ0の文字列をByte型の配列に代入すると、要素数0の配列が得られます。

Property Get EmptyByteArray() As Byte()
    Let EmptyByteArray = VBA.vbNullString
End Property

オブジェクト型

正直なぜこのような動作になるのかわかっていませんが、初期化していないObject型の動的配列を変数に代入すると、要素数0の配列になります。

また、返り値をObject()とするとObject()型の変数にしか代入できなくなるためVariantとしています。

Property Get EmptyObjectArray() As Variant '= Object()
    Dim o() As Object '-> Object()
    Let EmptyObjectArray = o
End Property '-> Object(0 To -1)

動作確認用コード

上記プロシージャのTypeNameとUBoundLBoundの結果を出力します。

Sub SampleEmptyArray()

    Dim v() As Variant
    v = EmptyVariantArray

    Debug.Assert (UBound(v) = -1) And (LBound(v) = 0)

    Debug.Print TypeName(v)
    Debug.Print "UBound="; UBound(v)
    Debug.Print "LBound="; LBound(v)


    Dim s() As String
    s = EmptyStringArray

    Debug.Assert (UBound(s) = -1) And (LBound(s) = 0)

    Debug.Print TypeName(s)
    Debug.Print "UBound="; UBound(s)
    Debug.Print "LBound="; LBound(s)

    Dim b() As Byte
    b = EmptyByteArray

    Debug.Assert (UBound(b) = -1) And (LBound(b) = 0)

    Debug.Print TypeName(b)
    Debug.Print "UBound="; UBound(b)
    Debug.Print "LBound="; LBound(b)


    Dim c() As VBA.Collection
    c = EmptyObjectArray

    Debug.Assert (UBound(c) = -1) And (LBound(c) = 0)

    Debug.Print TypeName(c)
    Debug.Print "UBound="; UBound(c)
    Debug.Print "LBound="; LBound(c)

End Sub
11
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13