An array is a data structure in which similar elements of data are arranged in an indexed structure-for example, a column of names or a table of numbers . See Table 8 . An array allows you to store many different values in a single variable, and uses parentheses to define and access array elements. OOo Basic does not support the use of square brackets as used by other languages such as C and Java.
Definition | Elements | Description |
---|---|---|
Dim a(5) As Integer | 6 | From 0 through 5 inclusive. |
Dim b(5 To 10) As String | 6 | From 5 through 10 inclusive. |
Dim c(-5 to 5) As String | 11 | From -5 through 5 inclusive. |
Dim d(5, 1 To 6) As Integer | 36 | Six rows with six columns from 0 through 5 and 1 through 6. |
Dim e(5 To 10, 20 To 25) As Long | 36 | Six rows with six columns from 5 through 10 and 20 through 25. |
Array variables are defined using the Dim statement. Think of a one-dimensional array as a column of values and a two-dimensional array as a table of values. Higher dimensions are supported but difficult to visualize. An array index may be any Integer value from -32,768 through 32,767.
Tip | You must declare array variables before using them, even if you don't use "Option Explicit." |
If the lower dimension of an array is not specified, the default lower bound of an array is zero. (Programmers call these arrays " zero-based .") Thus, an array with five elements will have elements numbered a(0) through a(4). Use the keywords "Option Base 1" to change the default lower bound of an array to start at 1 rather than 0. This must be done before any other executable statement in the program.
Option Base { 0 1 }
Tip | Specify the lower bound of an array rather than relying on the default behavior. This is more portable and it will not change when the Option Base statement is used. |
Dim a(3) allows for four elements: a(0), a(1), a(2), and a(3). Option Base does not change the number of elements that an array can store; it only changes how they are indexed. Using Option Base 1, the same statement still allows for four elements: a(1), a(2), a(3), and a(4). I consider this behavior unintuitive and recommend against using Option Base. If you want specific array bounds, the preferred option is to explicitly declare the array bounds. For example, Dim a(1 To 4). Option Base has risks in terms of communicating clear documentation and ensuring portability.
Compatibilty | Visual Basic handles Option Base 1 differently than OOo Basic. VB changes the lower bound to 1 but does not change the upper bound. Visual Basic .NET no longer supports Option Base. When OOo Basic supports "Option Compatible," then "Option Base 1" will not increase the upper bound by 1. In other words, OOo Basic will act like VB. |
Accessing and changing the values in an array is easy (see Listing 18 ). Initializing an array this way is tedious .
Sub ExampleSimpleArray1 Dim a(2) As Integer, b(-2 To 1) As Long Dim m(1 To 2, 3 To 4) REM Did you know that multiple statements can be placed REM on a single line if separated by a colon? a(0) = 0 : a(1) = 1 : a(2) = 2 b(-2) = -2 : b(-1) = -1 : b(0) = 0 : b(1) = 1 m(1, 3) = 3 : m(1, 4) = 4 m(2, 3) = 6 : m(2, 4) = 8 Print "m(2,3) = " & m(2,3) Print "b(-2) = " & b(-2) End Sub
To quickly fill a Variant array, use the Array function (see Listing 19 ), which returns a Variant array with the included data (see Figure 2 ). The functions LBound and Ubound return the lower bound and upper bound of an array. Routines supported by OOo Basic are summarized in Table 9 and discussed thoroughly later.
Function | Description |
---|---|
Array(args) | Return a Variant array that contains the arguments. |
DimArray(args) | Return an empty Variant array. The arguments specify the dimension. |
IsArray(var) | Return True if this variable is an array, False otherwise . |
Join(array) Join(array, delimiter ) | Concatenate the array elements separated by the optional string delimiter and return as a String. The default delimiter is a single space. |
LBound(array) LBound(array, dimension) | Return the lower bound of the array argument. The optional dimension specifies which dimension to check. The first dimension is 1. |
ReDim var(args) As Type | Change the dimension of an array using the same syntax as the DIM statement. The keyword Preserve keeps existing data intact. |
Split(str) Split(str, delimiter) Split(str, delimiter, n) | Split the string argument into an array of strings. The default delimiter is a space. The optional argument "n" limits the number of strings returned. |
UBound(array) UBound(array, dimension) | Return the upper bound of the array argument. The optional dimension specifies which dimension to check. The first dimension is 1. |
Sub ExampleArrayFunction Dim a, i%, s$ a = Array("Zero", 1, Pi, Now) Rem String, Integer, Double, Date For i = LBound(a) To UBound(a) s$ = s$ & i & " : " & TypeName(a(i)) & " : " & a(i) & CHR$(10) Next MsgBox s$, 0, "Example of the Array Function" End Sub
A variable defined as an array but not dimensioned, such as Dim a(), is called an empty array. Test for an empty array by comparing the upper bound of the array to the lower bound. If the upper bound is less than the lower bound, you have an empty array for which no dimensions have been set. An array that has been dimensioned, such as Dim a (5), is not empty.
It is possible to reference an entire array. For example, in Listing 19, the statement "Lbound(a)" returns the lower bound of the array a(). An array declared with the dimensions specified must always be followed by parentheses "()". For example, the variable b() in Listing 20 must be used as "b()". An array declared without the dimensions specified may be written with, or without, the trailing parenthesis. For example, the variable a() in Listing 20 may be used as either "a" or "a()".
Sub ArrayDimensionError Dim a(), b(1 To 2), c REM Valid constructs LBound(a()) : LBound(a) : LBound(b()) : LBound(c()) : Lbound(c) REM Invalid use of LBound(b) yields the run-time error REM Dimension specifications do not match LBound(b) End Sub
The desired dimension of an array is not always known ahead of time. Sometimes the dimension is known but it changes periodically and the code must be changed. An array variable can be declared with or without specifying the dimensions. OOo Basic provides a few different methods to set or change the dimensions of an array.
The Array function generates a Variant array that contains data. This is a quick way to initialize an array. You are not required to set the dimension of the array, but if you do, it will change to become the array returned by Array.
Dim a() a = Array(3.141592654, "PI", 9.81, "Gravity")
The arguments passed to the Array function become data in the returned Variant array. The DimArray function, on the other hand, interprets the arguments as the dimensions of an array to create (see Listing 21 ). The arguments can be expressions, so a variable can be used to set the dimension.
Sub ExampleDimArray Dim a(), i% a = Array(10, 11, 12) Print "" & LBound(a()) & " " & UBound(a()) Rem 0 2 a() = DimArray(3) REM the same as Dim a(3) a() = DimArray(2, 1) REM the same as Dim a(2,1) i = 4 a = DimArray(3, i) Rem the same as Dim a(3,4) Print "" & LBound(a() ,1) & " " & UBound(a() ,1) Rem 0, 3 Print "" & LBound(a() ,2) & " " & UBound(a() ,2) Rem 0, 4 a() = DimArray() REM an empty array End Sub
The Array and DimArray functions both return an array of Variants. The ReDim statement changes the dimension of an existing array. This can change both individual dimensions and the number of dimensions. The arguments can be expressions because the ReDim statement is evaluated at run time.
Dim e() As Integer, i As Integer i = 4 ReDim e(5) As Integer REM 0 To 5 is valid ReDim e(3 To 10) As Integer REM 3 To 10 is valid ReDim e(3, i) As Integer REM (0 To 3, 0 To 4) is valid
Tip | Although neither LBound nor UBound works on an empty array returned from DimArray(), because the array has no dimensions, both methods will work with empty arrays in OOo 2.0. An empty array has one dimension, but the lower bound is zero and the upper bound is -1. Use ReDim to cause an existing array to become empty. |
The ReDim statement supports the keyword Preserve. This attempts to save the data when the dimensions of an array are changed. Increasing the dimension of an array should preserve all of the data, but decreasing the dimension causes data to be lost by truncation . Data can be truncated at either end. If an element in the new array existed in the old array, the value is unchanged. Unlike some variants of BASIC, OOo Basic allows all dimensions of an array to be changed while still preserving data.
Dim a() As Integer ReDim a(3, 3, 3) As Integer a(1,1,1) = 1 : a(1, 1, 2) = 2 : a(2, 1, 1) = 3 ReDim preserve a(-1 To 4, 4, 4) As Integer Print "(" & a(1,1,1) & ", " & a(1, 1, 2) & ", " & a(2, 1, 1) & ")"
ReDim specifies both the dimensions and the type. The type specified with the ReDim statement must match the type specified when the variable is declared. If the types differ , you'll see the compile-time error "Variable already defined."
Listing 22 is a utility function that accepts a simple array and returns a string with all of the elements in the array. The ReDim example code, also in Listing 22, uses ArrayToString.
REM ArrayToString accepts a simple array and places the value REM of each element in the array into a string. Function ArrayToString(a() As Variant) As String Dim i%, s$ For i% = LBound(a()) To UBound(a()) s$ = s$ & i% & " : " & a(i%) & CHR$(10) Next ArrayToString = s$ End Function Sub ExampleReDimPreserve Dim a(5) As Integer, b(), c() As Integer a(0) = 0 : a(1) = 1 : a(2) = 2 : a(3) = 3 : a(4) = 4 : a(5) = 5 Rem a is dimensioned from 0 to 5 where a(i) = i MsgBox ArrayToString(a()), 0 , "a() at start" Rem a is re-dimensioned from 1 to 3 where a(i) = i ReDim Preserve a(1 To 3) As Integer MsgBox ArrayToString(a()), 0 , "a() after ReDim" Rem Array() returns a Variant type Rem b is dimensioned from 0 to 9 where b(i) = i+1 b = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) MsgBox ArrayToString(b()), 0 , "b() at initial assignment" Rem b is dimensioned from 1 to 3 where b(i) = i+1 ReDim Preserve b(1 To 3) MsgBox ArrayToString(b()), 0 , "b() after ReDim" Rem The following is NOT valid because the array is already dimensioned Rem to a different size Rem a = Array(0, 1, 2, 3, 4, 5) Rem c is dimensioned from 0 to 5 where a(i) = i Rem If "ReDim" had been done on c, then this would NOT work c = Array(0, 1, 2, "three", 4, 5) MsgBox ArrayToString(c()), 0 , "Integer array c() Assigned to a Variant" Rem Ironically, this is allowed but c will contain no data! ReDim Preserve c(1 To 3) As Integer MsgBox ArrayToString(c()), 0 , "ReDim Integer c() after assigned Variant" End Sub
Compatibility | Visual Basic has different rules for changing the dimensions of an array, and these rules change between versions of Visual Basic. As a general rule, OOo Basic is more flexible. |
Assigning one Integer variable to another copies the value, and the variables are not related in any other way. See Listing 23 . In other words, if you change the first variable's value, the second variable's value does not change. This is not true for array variables. Assigning one array variable to another makes a reference to the first array rather than copying the data. All changes made to either are automatically seen by the other. It doesn't mater which one is changed; they are both affected. This is the difference between "pass by value " (integers) and "pass by reference" (arrays).
Sub ExampleArrayCopylsRef Dim a(5) As Integer, c(4) As Integer, s$ c(0) = 4 : c(1) = 3 : c(2) = 2 : c(3) = 1 : c(4) = 0 a() = c() a(1) = 7 c(2) = 10 s$ = "**** a() *****" & CHR$(10) & ArrayToString(a()) & CHR$(10) &_ CHR$(10) & "**** c() *****" & CHR$(10) & ArrayToString(c()) MsgBox s$, 0 , "Change One, Change Both" End Sub
If array a() is assigned to array b(), then a() and b() both reference the same data. If b() is then assigned to a completely different array c(), b() and c() both reference the same data but array a() is left unchanged. In other words, the statement a() = b() does not cause a() to reference the variable b(), but rather to reference the same data. To illustrate this, start by creating three arrays-a(), b(), and c()-as shown in Figure 3 . Internally, OOo Basic creates three arrays that are referenced by a(), b(), and c().
The next step is to assign the variable a() to the variable b(). These are array variables so a() references the same array that b() references (see Figure 4 ). The original array referenced by a() is no longer referenced.
If I modify a(), this change is seen by b() because they reference the same array. If I then assign b() to array c(), array b() references the same array that c() references. The variable a(), however, remains unchanged, as shown in Figure 5 .
Bug | No type checking is performed when an array is assigned to another array. Do not assign arrays of different types to each other. |
Because no type checking is performed when an array is assigned to another array, unexpected and obscure problems can occur. The Array function returns a Variant array and is the quickest method to assign multiple values to an array variable. An obvious problem is that an Integer array may contain String values if it references a Variant array. A less obvious problem is that the ReDim statement works based on the declared type. The statement "ReDim Preserve" on an Integer array assigned to a Variant array fails to preserve the data.
Dim a() As Integer REM Declare a() as an Integer() a() = Array(0, 1, 2, 3, 4, 5, 6) REM Assign a Variant() to an Integer() ReDim Preserve a(l To 3) As Integer REM This wipes the array
To safely assign arrays while maintaining the correct data type, another method is required. Copy each element in the array individually. This also prevents two array variables from referencing the same array. See Listing 24 .
Sub ExampleSetIntArray Dim iA() As Integer SetIntArray(iA, Array(9, 8, "7", "six")) MsgBox ArrayToString(iA), 0, "Assign a Variant to an Integer" End Sub REM Dimension the first array to have the same dimensions as the second. REM Perform an element-by-element copy of the array. Sub SetIntArray(iArray() As Integer, v() As Variant) Dim i As Long ReDim iArray(LBound(v()) To UBound(v())) As Integer For i = LBound(v) To UBound(v) iArray(i) = v(i) Next End Sub