配列の要素と次元の数を実行時まで宣言しない場合、またはアプリケーションの実行中の特定の (複数の) 時点で配列サイズを変える場合には、動的配列を使用します。動的配列を宣言するには、次の例にあるように、空のサブスクリプトリスト (空のカッコ) を付けて Dim ステートメント (またはそのバリエーション) を使用します。
Dim myDynamicArray() As String
Dim ステートメントには配列の次元についての情報は入っていないので、ステートメントは String 型の要素を持つ動的配列の名前として myDynamicArray という名前を単に予約するだけです。
動的配列を宣言する場合、次元や要素はなく、記憶域も割り当てられません。配列は ReDim ステートメントで次元と範囲を指定するまでは使用できません。ReDim ステートメントは、配列のサイズを定義し、要素用に記憶域を割り当てて初期化します。ReDim ステートメントの構文を次に示します。
ReDim [ Preserve ] arrayName ( bounds ) [ As dataType ]
ここで、arrayName は空の範囲リストを使用して宣言した配列の名前、bounds は範囲リストで、この配列に定義する次元の数と範囲を指定します。As dataType は配列で保持される要素のデータ型を指定します。これは Dim ステートメントで定義したデータ型と同じでなければなりません。オプションの Preserve キーワードは、arrayName 内の要素の現在の値を保持するように LotusScript® に指示します。これは、Dim で動的配列を定義し、ReDim でサイズを定義して要素に値を代入した後で、配列を拡張して新たな要素を追加して値を代入する場合に便利です。例えば、次のようになります。
Option Base 1
' Declare a dynamic String array. Later, this is
' defined as a one-dimensional array whose elements
' are assigned values that the user enters.
Dim myNames() As String
Dim ans1 As Integer
Dim ans2 As Integer
Dim counter As Integer
Dim userInput As String
' Ask the user to enter a number and assign it to ans1%.
ans1% = CInt(InputBox$ _
("How many names would you like to enter?"))
' Use ans1% as the upper bound of the array's only dimension.
ReDim myNames(ans1%)
' Elicit ans1% strings from the user, and assign them
' to successive elements in the array.
For counter% = 1 to ans1%
myNames(counter%) = InputBox$("Enter a name: ")
Next
' Print the contents of the array on a single line
' with a space between the value of each element.
For counter% = 1 to ans1%
Print myNames(counter%) " " ;
Next
' Output: a newline
Print ""
' Ask the user for another number and assign it to ans2%.
ans2% = CInt(InputBox$("How many more names?"))
' If the number is greater than 0, resize the
' array, preserving its original values, so that the
' user can enter additional values.
If ans2% > 0 Then
ReDim Preserve myNames(ans1% + ans2%)
' Elicit the new values and assign them to the
' elements that have been allocated after the old ones.
For counter% = 1 to ans2%
myNames(counter% + ans1%) = InputBox$("Enter a name: ")
Next
' Print the contents of the array on a single line
' with a space between the value of each element.
For counter% = 1 to ans1% + ans2%
Print myNames(counter%) " " ;
Next
Print ""
End If
動的配列のサイズを定義するために最初に適用した ReDim ステートメントによって、その配列の次元数が永続的に定義されます。範囲リスト中の上限値または下限値は、使用する ReDim ステートメントに Preserve キーワードが含まれない限り、後で変更できます。範囲を変更すると、LotusScript は範囲リストで指定された量の記憶域を割り当て直し、配列要素をそのデータ型に適切な既定値で初期化します。ReDim ステートメントに Preserve を含めた場合、値を大きくして変更できるのは、配列の最後の次元の上限値だけです。その場合、LotusScript は適切な量の記憶域を追加で割り当て、追加された配列要素を初期化します。ReDim ステートメントで配列の次元数や要素のデータ型を変更することはできません。
Erase ステートメントを使用して、動的配列に現在割り当てられているすべての記憶域を取り戻すことができます。固定長配列に適用された場合、Erase ステートメントは配列要素の初期化だけを行います (配列要素のデータ型に応じて、ゼロ、空の文字列、EMPTY、または NOTHING に初期化します)。
IsArray 関数を使用して識別子が既存配列の名前かどうかを調べることができます。DataType 関数を使用して、配列が固定長配列か動的配列かを判別できます。DataType または TypeName 関数を使用して、配列要素のデータ型を確認できます。スカラー値に対して実行できる任意の LotusScript 組み込み関数を使用して、配列の要素を操作できます。次に例を示します。
' Declare arrays with a base of 1 and containing 10 elements
Dim myDblArray(1 To 10) As Double
Dim anIntArray(1 To 10) As Integer
Dim counter As Integer
' Seed the random number generator.
Randomize
' Populate myDblArray with random numbers
' greater than 0 and less than 1.
For counter% = 1 To 10
myDblArray(counter%) = Rnd()
Next
' Populate anIntArray with the elements of myDblArray
' after rounding to one decimal place, multiplying
' by 10, dividing by 10 and adding 1 to the remainder
' to yield a whole number between 1 and 10.
For counter% = 1 To 10
anIntArray(counter%) = _
((Round(myDblArray(counter%), 1) * 10) Mod 10) + 1
Next
' Test the first element of anIntArray for its data type.
Print TypeName(anIntArray(1))
' Output: INTEGER
' Print the contents of myDblArray and anIntArray.
For counter% = 1 To 10
print myDblArray(counter%) & " " & anIntArray(counter%)
Next
' Output: something like the following:
' .402520149946213 5
' .530154049396515 6
' .309299051761627 4
' 5.76847903430462E-02 2
' 2.41877790540457E-02 1
' .988802134990692 1
' .688120067119598 8
' .493557035923004 6
' .28598952293396 4
' .610387742519379 7
Dim aStringArray(1 to 5, 1 to 2)
aStringArray(1,1) = "Roman"
aStringArray(1,2) = "Minsky"
aStringArray(2,1) = "Sara"
aStringArray(2,2) = "Nala"
aStringArray(3,1) = "Raymond"
aStringArray(3,2) = "Nala"
aStringArray(4,1) = "Sandra"
aStringArray(4,2) = "Brooks"
aStringArray(5,1) = "Simon"
aStringArray(5,2) = "Anders"
' Check to see if the first two characters of each element
' in the first dimension of aStringArray would be SA
' if they were uppercase. If so, print the corresponding
' element in the second dimension of the array, making
' its first character uppercase and the rest lowercase.
For counter% = 1 to 5
If UCase$(Left$(aStringArray(counter%, 1), 2)) = "SA" Then
Print UCase$(Left$(aStringArray(counter%, 2), 1)) _
& LCase$(Mid$(aStringArray(counter%, 2), 2, _
Len(aStringArray(counter%, 2))))
End If
Next
' Output:
' Nala
' Brooks
動的配列が初期化されたかどうかを見分ける組み込み関数はありません。 ただし、配列を使用しようとして生成されたエラー条件をトラップする関数を作成し、その関数を使用して見分けることができます。
IsArrayInitialized(arr As Variant) As Boolean
Dim intTemp As Integer
On Error Goto uninit
intTemp = Ubound(arr)
IsArrayInitialized = True
Exit Function
Function
It is only slightly more efficient to use a specific type for the arr parameter instead of variant (e.g. "arr( ) As String" instead of "arr As Variant").