Hour 12


During this hour you will learn

Handling Large Amounts of Information with Arrays

This hour, you'll learn how to store many occurrences of data in your Visual Basic programs. Most of the code you've seen so far has worked with very little data. Up to this point, you were learning about variables and controlling statements; lots of data would have hindered your learning how to program, especially if you were unfamiliar with programming languages before learning Visual Basic.

This hour's topics teach about arrays. An array isn't much more than a list of variables. You see in this topic how the naming conventions for array variables vary a little (but not much) from the naming conventions for regular non-array variables. With arrays, you can store many occurrences of data. With non-array variables, each piece of data has a different name, and it's difficult to track many occurrences of data.

Before you learn how to read and process table data with Visual Basic, you must have a way to store the many data items that you read from a table into your programs. Arrays provide the containers for several data values, such as those you get when reading from a table into your program.

Conquering arrays is your next step toward understanding advanced uses of Visual Basic. This hour's examples are some of the longest programs you've seen in the book. Arrays aren't difficult, but their power lends them to advanced programming.

Topic 1: Arrays and Non-Array Variables

Although arrays vary from variables, they vary only in the way you declare and access them. Arrays contain multiple occurrences of variable data, and your program can treat an array's variable contents as though those array variables were regular non-array variables. The only requirement is that you properly declare and reference the array variables.

FAST TRACK
Have you programmed with arrays in other programming languages? If you've worked with COBOL tables or BASIC matrixes, you've worked with arrays. You now only need to know how to declare and access arrays. After you read this topic section, skim the remaining topics for follow-up and then move onto Hour 13's lesson, where you'll learn how Visual Basic subroutines and functions really work.

Overview

An array is a list of more than one variable with the same name. Not every list of variables is an array. The following list of four variables doesn't count as an array:

curSales sngbonus98 strFirstName intCtr

This list doesn't define an array because each variable has a different name. You may wonder how more than one variable can have the same name; this convention seems to violate the rules of variables. If two variables have the same name, how does Visual Basic know which one you want when you use its name?

In this topic section, you'll learn that you distinguish array variables from each other by a subscript. A subscript is a number, inside parentheses, that differentiates one element of an array from another. (You first saw the concept of subscripts in Hour 11's final topic.) Elements are the individual variables in an array.

Good Array Candidates

Suppose that you want to process 35 people's names and monthly dues from your local neighborhood association. The dues are different for each person. All this data fits nicely in a table of data, but suppose that you also want to hold, at one time, all the data in variables so that you can perform calculations and print various statistics about the members by using Visual Basic.

Without arrays, you find yourself having to store each of the 35 names in 35 different variables, and each of their dues in 35 different variables. But doing so makes for a complex and lengthy program. To enter the data, you have to store the data in variables with names such as the following:

strFamilyName1 curFamilyDues1 strFamilyName2 curFamilyDues2

strFamilyName3 curFamilyDues3 strFamilyName4 curFamilyDues4

The list continues until you use different variable names for all the 35 names and dues.

Every time you use Visual Basic to display a list of members, calculate average dues, or use this data in any other way, you have to scan sets of 35 different variable names. The steps required in this procedure are why arrays were developed; it's too cumbersome for similar data to have different variable names. The time and typing required to process more than a handful of variables with different names is too much. Not only that, imagine if the neighborhood grew to 500 households!

With arrays, you can store similar data, such as the neighborhood data, in a single variable. In effect, each data value has the same name. You distinguish the values (elements in the array) from each other by a numeric subscript. For instance, instead of a different variable name (strFamilyName1, curFamilyDues1, strFamilyName2, curFamilyDues2, and so on), give the similar data the same variable name (strFamilyName and curFamilyDues) and differentiate them with subscripts as shown in Table 12.1.

Table 12.1 Using Arrays to Store Similar Data

Old Names

Array Names

strFamilyName1, curFamilyDues1

strFamilyName(1), curFamilyDues(1)

strFamilyName2, curFamilyDues2

strFamilyName(2), curFamilyDues(2)

strFamilyName3, curFamilyDues3

strFamilyName(3), curFamilyDues(3)

: :

:

: :

:

strFamilyName35, curFamilyDues35

strFamilyName(35), curFamilyDues(35)

Many Visual Basic programmers like to use an additional variable name prefix for array names, such as strar for a string array or curar for a currency array.

"Where's the improvement?" you might ask. The column of array names has a major advantage over the old variable names. The number inside the parentheses is the subscript number of the array. Subscript numbers are never part of an array name; they're always enclosed in parentheses and serve to distinguish one array element from another.

How many arrays are listed in Table 12.1? If you said two, you're correct. There are 35 elements in each of the two arrays. How many non-array variables are in Table 12.1? Seventy-35 family name variables and 35 dues variables. The difference is very important when you consider how you process them.

Because the subscript number (the only thing that differentiates one array element from another) isn't part of the array name, you can use a For...Next loop or any other counter variable to input, process, and output any and all elements of arrays.

To input every single family name and their dues into the two arrays by using a loop, for instance, you don't need 70 statements as you do when each variable has a different name. You need only four statements, as shown here:

For intSub = 1 To 35

strFamilyName(intSub) =

[ccc]InputBox("What is the family member's name?")

curFamilyDues(intSub) = InputBox("What are their dues?")

Next intSub

This code offers a major advantage over using non-array variables. Notice that the For...Next loop keeps incrementing intSub throughout the data input of all 70 values. The first time through the loop, users enter a value into strFamilyName(1) and in curFamilyDues(1) with the InputBox() function (intSub is then equal to 1). The loop then increments intSub to 2, and the input process starts again for the next two variables.

These four lines of code are much easier to write and maintain than a set of 70 individual InputBox() function calls, and the For...Next loop does exactly the same thing. You can't use the For...Next loop to process a bunch of differently named variables, even if they have numbers in their names, as they do with strFamilyName1, curFamilyDues1, and so on.

Any time you're working with a list of data with similar meanings, an array works best. Arrays make your input, process, and output routines much easier to write. Most importantly to Visual Basic, you can read table data into large arrays if needed and work with the data in memory.

Visual Basic supports two kinds of arrays: static and dynamic. This book discusses static arrays, which are fixed in size and can't be changed at runtime. (You can change dynamic array sizes during the program's execution.) If you want to learn more about dynamic arrays, check out Que's advanced Visual Basic book, Special Edition Using Visual Basic 5.

Not all of your Visual Basic data is stored in arrays. You still use variables (like those you've seen throughout this course) for loop control and user input. When you have multiple occurrences of data that you must track within Visual Basic-such as fields from a table that you read into memory-an array is the perfect holder for that data.

Using Public and Dim to Set Up Arrays

As you do with non-array variables, you tell Visual Basic that you're going to use an array; you have to declare the array, just as you have to declare other variables. You use the Public or Dim statements to declare arrays; your choice of statements depends on the kind of array you need and where you want to declare the array.

Declare with a Public statement to create a public array that can be used throughout the entire application (across all modules). The Public statement must appear in the standard module's Declarations section.

If you use a Dim statement in a module's Declarations section, you create a module-level array that can be used throughout the module.

You can declare local static variables and arrays with the Static keyword. A static array retains its values and when execution returns to the procedure, Visual Basic remembers and uses their values.

For declaring arrays, the format of the Public and Dim statements varies only in the keyword of the command and its placement in the module. Here are the syntaxes of the two statements:

Public arName(intSub) [As dataType][, arName(intSub) [As dataType]]...

Dim arName(intSub) [As dataType][, arName(intSub) [As dataType]]...

You name arrays (arName) just as you do regular variables. You can create an array of any data type, so dataType can be Integer, Single, or any of the data types with which you're familiar. The intSub portion of the commands describes the number of elements and how you refer to those array elements. In the preceding statement formats, intSub can take on the following format:

[intLow To] intHigh

You can have more than one set of subscripts, as you learn in this lesson's final topic section.

Unlike other programming languages, Visual Basic's Variant data type lets you specify arrays that hold several different kinds of data. All elements of non-Variant arrays must have the same data type.

Using Option Base

Declaring an array is easiest when you specify only the upper subscript bound. All array subscripts begin at 0 unless the following statement appears in the module's Declarations section:

Option Base 1

The Option Base command is rather outdated. (If you want to change the lower bounds of an array, you should consider using the more advanced Low To option.)

The following Dim statement declares seven elements of an Integer array named intAges:

Dim intAges(6) ' Reserves 7 elements

The subscript, 6, is the upper subscript, and the lower subscript is 0 (without an Option Base 1 appearing elsewhere, which would force the beginning subscript to 1). Figure 12.1 illustrates just what's declared with this statement. An array of seven Integer values, all with the same name (intAges), is reserved for use. Each variable is distinguished by its subscript number; intAges(2) is a completely different variable from intAges(6).

FIG. 12.1

The intAges array contains seven elements.

Often, programmers ignore the zero subscript. Unless you use Option Base 1 or a Low To High subscript, Visual Basic reserves an element for the zero subscript but you don't have to use that zero subscript.

Example

Based on the previous discussion, you can declare the strFamilyName and curFamilyDues arrays as follows:

Dim strFamilyName(35) As String ' Reserves 36 names

Dim curFamilyDues(35) As Currency ' Reserves 36 dues

Actually, the subscript 35 is the upper bound, and the subscript 0 is automatically the lower bound. Therefore, these statements each dimension 36 elements in each array. The previous discussion mentioned 35 members in the neighborhood association, so the 0 subscript isn't used.

Because Dim was used here, the arrays have procedure-level scope. Only the code within the procedure that contains these two statements can use the two arrays unless the procedure passes the arrays to other procedures, as explained in Hour 13's lesson.

Sometimes, specifying the lower and upper bounds of the array subscripts makes sense. As you've seen, if you specify Option Base 1, the lower array subscript is 1. If you specify Option Base 0 or nothing at all, the lower array subscript bounds are zero. By using the expanded array declaration statements with the To keyword, however, you can specify the upper and lower bounds of your array subscripts.

You may find that your data fits within different subscripts than those that default (such as starting at 0 or 1). Suppose that you're storing customer information, and your lowest customer number is 200. It therefore makes sense to begin the array subscripts at 200 and store the first customer at his or her array subscript number 200.

The following statements reserve global storage for three customer-related arrays. The first subscript is 200, and the highest subscript is 999.

Public varCustNumber(200 To 999) As Variant

Public strCustName(200 To 999) As String

Public curCustBalance(200 To 999) As Currency

The high subscript no longer specifies the number of array elements. These three arrays have a total of 800 elements each (subscripted from 200 to 999).

Next Step

These Dim statements each do the same thing:

Dim Amounts(0 To 50) ' Subscripts 0 to 50

Dim Amounts(50) ' Subscripts 0 to 50

And so do these pairs:

Option Base 1

Dim Balances(75) ' Subscripts 1 to 75

Option Base 0

Dim Balances(1 To 75) ' Subscripts 1 to 75

You can see how the Option Base statement affects the arrays you declare. Now that you can declare arrays, you'll now learn how to use them.

Topic 2: Using Arrays

You may see arrays used in calculations, just as non-array variables are, like the following:

curFamilyDues(5) = curFamilyDues(4) * 1.5

To use data in an array, you have to use only the subscript of the array element you want to work with.

In one respect, accessing an array value works like a set of boxes in a post office. The address of all the boxes is the same (they're all located in the same building), but mail is inserted into the appropriate box number.

Overview

The rest of this topic uses some code examples to clarify how arrays work. The earlier examples use arrays to gather and work with user data. After you understand better how to work with arrays, the later examples in this topic use arrays with forms.

The Subscript in Use

The best way to learn how to use subscripts is to see examples. Although the following example shows array elements being filled up by an InputBox() function, most programs get most of their input data from files and forms. Because arrays can store very large amounts of data, you don't want to have to type that data into the variables every time you run a program. Assignment statements don't suffice either, because they aren't good statements to use for extremely large amounts of data and interactive programs.

In Listing 12.1 is the full program that declares two arrays for the neighborhood association's 35 family names and their dues. The program prompts for the input and then prints the data.

If you run this program, you may want to change the number from 35 down to 5 or so to keep from having to type so much input.

Listing 12.1 Assoc.bas: Arrays Simplify Data Storage

Private Sub association ()

' Procedure to gather and print 35 names and dues

Dim strFamilyName(35) As String ' Reserve the array elements

Dim curFamilyDues(35) As Currency

Dim intSub As Integer

Dim msg As Integer ' MsgBox() return

' Loop getting all of the data

For intSub = 1 To 35

strFamilyName(intSub) = InputBox("What is the next family's name")

curFamilyDues(intSub) = InputBox("What are their dues?")

Next intSub

' You now can display all the data

' This example uses a series of message boxes simply

' because that's what you know at this point

intSub = 1 ' Initialize the first subscript

Do

msg = MsgBox("Family" & intSub & "is " & strFamilyName(intSub))

msg = MsgBox("Their dues are " & curFamilyDues(intSub))

intSub = intSub + 1

Loop Until (intSub > 35)

End Sub

Notice that the program can input and print all the names and dues with simple routines. The input routine uses a For...Next loop, and the printing routine uses a Do...Loop. The method you use to control the loop isn't critical. The important thing to see at this point is that you can input and print a great deal of data without having to write lots of code. The array subscripts and loop controlling statements make the printing possible.

This example illustrates parallel arrays-two arrays working side by side. Each element in each array corresponds to one in the other array. Parallel arrays work in memory like joined fields work together in tables.

The neighborhood association program is fine for an illustration, but it works only if there are exactly 35 families. What if the association grows? If it were to grow, you would have to change the program. Therefore, most programs don't have a set limit size for data, as the preceding program did. Most programmers declare more than enough array elements to handle the largest array ever needed. The program then allows users to control how many of those elements are really used.

After you master the fixed-length static arrays discussed here, you may want to learn about dynamic arrays, whose size can change at runtime. If you find that you need more array elements when the program runs, you can get more when using dynamic arrays.

The program in Listing 12.2 is similar to the one in Listing 12.1, except that it declares 500 elements for each array. This number reserves more than enough array elements for the association. Users then input only the actual number (from 1 to 500 maximum). The program is very flexible, allowing a variable number of members input and printed each time it's run. It does need an eventual limit, however, but that limit is reached only when there are 500 members.

Declare enough array space for your estimated needs, but don't declare more array space than you can possibly use. For every extra array element that you reserve but don't use, memory is wasted.

Listing 12.2 Varynumb.bas: Reserving More Elements Than You Currently Need

Private Sub varyNumb ()

' Procedure to gather and print names and dues

Dim strFamilyName(500) As String ' Reserve enough array elements

Dim curFamilyDues(500) As Currency

Dim intSub As Integer, intNumFam As Integer

Dim msg As Integer ' MsgBox() return

intNumFam = 1

' The following loop asks for family names and dues until the

' user presses Enter without typing a name. Whenever a zero-length

' string is entered (just an Enter keypress), the Do-Loop exits

' early with sub holding the number input to that point.

Do

strFamilyName(intNumFam) = InputBox("What is next family's name?")

If (strFamilyName(intNumFam) = "") Then Exit Do ' Exits early

curFamilyDues(intNumFam) = InputBox("What are their dues?")

intNumFam = intNumFam + 1 ' Add one to the subscript variable

Loop Until (intNumFam > 500)

' When the last loop finishes, intSub holds one

' more than the actual number input

' Displays all the input data

For intSub = 1 To intNumFam - 1

msg = MsgBox("Family" & intSub & "is " & strFamilyName(intSub))

msg = MsgBox("Their dues are " & curFamilyDues(intSub))

Next intSub

End Sub

The empty Enter keypress is a good way to trigger the early exit of the loop. Just because 500 elements are reserved for each array doesn't mean that you have to use all 500 of them.

Alternatively, if users are familiar with the data, you can ask them how many values they want to enter. You then loop until that value is reached. Because users are rarely familiar enough with their data to know how many values they will input, asking for the number of values to enter isn't as common as this example, which allows users to trigger the end of input when finished.

Randomly Accessing Elements

You don't have to access an array in the same order as it was entered. An array works like a table because you can access any element in any order, just like reading a record from file by knowing a record number. You use the subscript to "pick out" items from an array of values.

The program in Listing 12.3 requests salary data for the last 12 months. It then waits until another user types the month he or she wants to see. That month's sales are then printed, without the surrounding months getting in the way. This is how you begin to build a search program to find requested data that's stored in arrays; store the data in an array, and then wait for a request from the users to see only specific pieces of that data.

Listing 12.3 Salary.bas: Using Arrays for Data-Searching Code

Private Sub salary ()

' Store 12 months of salaries, and print selected ones

Dim curSal(1 To 12) As Currency ' Reserve elements for 12 salaries

Dim intSub As Integer ' Loop subscript

Dim intNum As Integer ' User's month number

Dim msg As Integer ' MsgBox() return

Dim strAns As String

For intSub = 1 To 12

curSal(intSub) = InputBox("What is salary for month" & Str(intSub) & "?")

Next intSub

' Request the month number

Do

intNum = InputBox("For what month (1-12) do you want a salary?")

msg = MsgBox("The salary for month" & Str(intNum) & " is " & curSal(intNum))

strAns = InputBox("Do you want to see another (Y/N)?")

Loop While (strAns = "Y")

End Sub

After users enter the 12 salaries into the array, they can request any or all of them one at a time simply by supplying the month number (the number of the subscript).

The program in Listing 12.4 shows some of the math operations you can perform on arrays. The program asks for a list of temperatures and keeps asking for them until users enter -99 to signal that there are no more temperatures. The program then computes the average temperature by adding them and dividing by the total number.

Listing 12.4 Tempavg.bas: Letting Users Tell Your Program When No More Data Remains

Private Sub tempAvg ()

' Prompt the user for a list of temperatures and average them

Dim sngTemp(1 To 100) As Single ' Up to 100 temps

Dim sngTotalTemp As Single ' Holds totals as user enters temps

Dim sngAvgTemp As Single

Dim intSub As Integer ' Subscript

Dim msg As Integer ' MsgBox() return

' Prompt user for each temperature

For intSub = 1 To 100 ' Maximum limit

sngTemp(intSub) = InputBox("What is next temperature (-99 ends)?")

' If user wants to stop, decrease count by 1 and exit loop

If (sngTemp(intSub) = -99) Then

intSub = intSub - 1 ' Adjust for early exit

Exit For

End If

sngTotalTemp = sngTotalTemp + sngTemp(intSub) ' Add to total

Next intSub

' Compute average

sngAvgTemp = sngTotalTemp / intSub

msg = MsgBox("The average temperature was " & sngAvgTemp)

End Sub

Visual Basic's MsgBox() function can convert numeric values to strings when you concatenate numeric values to a string message.

Example

In Hour 10's lesson, you learned how to use the Select Case statement with the VarType() function. VarType() returns a number that represents the data type of its argument. Any time your programs use lists of data, you can almost always use arrays to improve on the code.

Listing 12.5 shows the routine as you saw it in Hour 10's lesson.


Listing 12.5 Seldata2.bas: Determining Data Types with Select Case

Private Sub PrntType(varA) ' Variant if you don't specify otherwise

Dim msg As Integer ' MsgBox() return

Select Case VarType(varA) ' VarType() returns an integer

Case 0

msg = MsgBox("The argument is Empty")

Case 1

msg = MsgBox("The argument is Null")

Case 2

msg = MsgBox("The argument is Integer")

Case 3

msg = MsgBox("The argument is Long")

Case 4

msg = MsgBox("The argument is Single")

Case 5

msg = MsgBox("The argument is Double")

Case 6

msg = MsgBox("The argument is Currency")

Case 7

msg = MsgBox("The argument is Date")

Case 8

msg = MsgBox("The argument is String")

Case 9

msg = MsgBox("The argument is an Object")

Case 10

msg = MsgBox("The argument is an Error")

Case 11

msg = MsgBox("The argument is Boolean")

Case 12

msg = MsgBox("The argument is a Variant array")

Case 13

msg = MsgBox("The argument is a Data Access Object")

Case 14

msg = MsgBox("The argument is Decimal")

Case 17

msg = MsgBox("The argument is Byte")

Case Else

msg = MsgBox("The argument is an Array")

End Select

End Sub

Listing 12.6 shows the same routine, using arrays.

Listing 12.6 Arraytst.bas: Using VarType() to Test an Array's Data Type

Private Sub PrntType(varA) ' Variant if you don't specify otherwise

' varA comes from another routine

' Prints data type names using an array

Dim strTypeNames(17) As String ' Will use 18 subscripts, 0 to 17

Dim msg As Integer

' Fill the array with data type names

strTypeNames(0) = "Empty"

strTypeNames(1) = "Null"

strTypeNames(2) = "Integer"

strTypeNames(3) = "Long"

strTypeNames(4) = "Single"

strTypeNames(5) = "Double"

strTypeNames(6) = "Currency"

strTypeNames(7) = "Date"

strTypeNames(8) = "String"

strTypeNames(9) = "Object"

strTypeNames(10) = "Error"

strTypeNames(11) = "Boolean"

strTypeNames(12) = "Variant Array"

strTypeNames(13) = "Data Access Object"

strTypeNames(14) = "Decimal"

strTypeNames(15) = "N/A" ' No VarType value matches

strTypeNames(16) = "N/A" ' these

strTypeNames(17) = "Byte"

If (VarType(varA) <= 17) Then ' An array

msg = MsgBox("The argument is " & strTypeNames(VarType(varA)))

Else

msg = MsgBox("The argument is an array of type " &

[ccc]strTypeNames(VarType(varA-8192)))

End If

End Sub

Shorter code doesn't always mean better code. Your goal should always be writing easy-to-read code, not short, tricky code that works but is hard to maintain later. Nevertheless, many times shorter code does produce easier maintenance because you have fewer lines to understand when you have to make changes later.

The code in Listing 12.6 first stores all the data type names in a string array. The array's subscripts match those of the data types. Therefore, the VarType() function's return value can be used as the subscript to print the appropriate data type title. Although Listing 12.6 doesn't seem to be a big improvement over Listing 12.5, Listing 12.6 doesn't contain all the Case statements that Listing 12.5 contains. Although the code in Listing 12.6 is, therefore, more efficient, the goal of this code wasn't efficiency but just to show you the capability of an array subscript to select data from an array.

If VarType() returns a value that's greater than or equal to 8,192, VarType() is testing an array. To determine the array's data type, subtract 8,192 from VarType()'s return value to find the data type.

Next Step

In Hour 11's lesson, you learned how forms and controls can be referenced by subscripts. Hour 11 introduced the concept of arrays to you without your knowing about arrays. By using the Forms collection, you can refer to all the forms inside an application by its subscript number. Within an individual form, you can refer to controls on that form with a subscript as well, just as you do with array variables.

The procedure in Listing 12.7 stores all open form names in an array called strOpenForms and then prints the contents of that array in the immediate window.

Listing 12.7 Storefrm.bas: Using an Array to Store Form Names

Private Sub storeForms ()

' Function that stores all form names in an array

Dim intSub As Integer

Dim strOpenForms(10) As String

Dim msg As Integer ' MsgBox()'s return

' Save all open forms in the array

For intSub = 0 To Forms.Count - 1

strOpenForms(intSub) = Forms(intSub).Name

Next intSub

' Display the names of the open forms

For intSub = 0 To Forms.Count - 1

msg = MsgBox(strOpenForms(intSub))

Next intSub

End SubScx

If you have four forms open when this procedure executes, the code displays four message boxes that display those form names. The most important things to study about Listing 12.7 are that the open form names are stored in an array and the array's contents are displayed, one at a time, in message boxes.

After you master arrays, the next topic section is easy. It shows how you can keep track of arrays in a different format from the format you saw here. Not all lists of data lend themselves to multidimensional arrays, but you should be prepared for them when you do need them.

Topic 3: Multidimensional Arrays

Some data fits in array lists like those you saw in the first two topic sections; other data is better suited to a table of data. The second topic section introduced single-dimensioned arrays, which are arrays that have only one subscript. Single-dimensioned arrays represent a list of values. This topic section explains how to use arrays of more than one dimension, called multidimensional arrays. Multidimensional arrays, sometimes called tables or matrices, have rows and columns.

Overview

This topic section introduces the following:

What Multidimensional Arrays Are

A multidimensional array is an array with more than one subscript. A single-dimensional array is a list of values, whereas a multidimensional array simulates a table of values or even multiple tables of values. The most commonly used table is a two-dimensional table (an array with two subscripts).

Suppose that a softball team wants to keep track of its players' hits. The team played eight games, and 10 players are on the team.

Table 12.2 shows the team's hit record.

Table 12.2 A Softball Team's Hit Record

Player

Game1

Game2

Game3

Game4

Game5

Game6

Game7

Game8

Adams

2

1

0

0

2

3

3

1

Berryhill

1

0

3

2

5

1

2

2

Edwards

0

3

6

4

6

4

5

3

Grady

1

3

2

0

1

5

2

1

Howard

3

1

1

1

2

0

1

0

Powers

2

2

3

1

0

2

1

3

Smith

1

1

2

1

3

4

1

0

Townsend

0

0

0

0

0

0

1

0

Ulmer

2

2

1

1

2

1

1

2

Williams

2

3

1

0

1

2

1

1

Do you see that the softball table is a two-dimensional table? It has rows (the first dimension) and columns (the second dimension). Therefore, you call it a two-dimensional table with 10 rows and eight columns. (Generally, the number of rows is specified first.)

Each row has a player's name, and each column has a game number associated with it, but these headings aren't part of the data. The data consists of only 80 values (10 rows times eight columns). The data in a table, like the data in an array, always is the same type of data (in this case, every value is an integer). If the table contains names, it's a string table, and so on.

The number of dimensions-in this case, two-corresponds to the dimensions in the physical world. The first dimension represents a line. The single-dimensional array is a line, or list, of values. Two dimensions represent both length and width. You write on a piece of paper in two dimensions; two dimensions represent a flat surface. Three dimensions represent width, length, and depth. You may have seen three-dimensional movies; not only do the images have width and height, but they also (appear to) have depth.

It's difficult to visualize more than three dimensions. You can, however, think of each dimension after three as another occurrence. In other words, you can store a list of one player's season hit record in an array. The team's hit record (as shown in Table 12.2) is two-dimensional. Their league, made up of several teams' hit records, represents a three-dimensional table. Each team (the depth of the table) has rows and columns of hit data. If there's more than one league, you can consider leagues another dimension.

Visual Basic lets you work with up to 60 dimensions, although real-world data rarely requires more than two or three dimensions.

Dimensioning Multidimensional Arrays

As you do with single-dimension arrays, use the Dim or Public statement to reserve storage for multidimensional arrays. Rather than put one value in the parentheses, you put a value for each dimension in the table. The basic syntaxes for reserving multidimensional arrays are as follows:

Public taName(intSub) [As dataTtype][, taName(intSub) [As dataType]]...

Dim taName (intSub) [As dataType][, taName (intSub) [As dataType]]...

The table's intSub values can take on this general syntax:

[intLow To] intHighRow[, [intLow To] intHighColumn][, [intLow To] intHighDepth][,...]

As with single-dimensions, actually reserving storage for tables is easier than the formats lead you to believe. To declare the team data from Table 12.2, for example, you can use the following Dim statement:

Dim intTeams(1 To 10, 1 To 8) As Integer

This statement reserves a two-dimensional table in memory with 80 elements. Each element's subscript looks like the ones shown in Figure 12.2.

FIG. 12.2

The softball team table requires two sets of subscripts.

If you have an entire league of 15 teams to track, you add yet another subscript,

Dim intTeams(1 To 15, 1 To 10, 1 To 8) As Integer

where the first subscript indicates the team, the second subscript indicates the number of players in each team, and the third subscript indicates the number of games each player plays.

The following statement reserves enough memory elements for a television station's shows for one week:

Dim strShows(1 To 7, 1 To 48) As String

This statement reserves 7 days (the rows) of 30-minute shows (because there are 24 hours in a day, this table holds up to 48 30-minute shows).

Every element in a table is always the same type. In this case, each element is a string variable. You can initialize some of the elements with the following assignment statements, for example:

strShows(3, 12) = "As the Hospital Turns"

strShows(1, 5) = "Guessing Game Show"

strShows(7, 20) = "Raspberry Iced Tea Infomercial"

Reserving space for several multidimensional arrays quickly consumes memory space. The following statements reserve a lot of space:

Public ara1(10, 20) As Single

Dim ara2(4, 5, 5) As Double

Public ara3(6, 10, 20, 30) As Integer

ara1 consumes 200 single-precision memory locations, ara2 consumes 100 double-precision memory locations, and ara3 consumes 36,000 memory locations. As you can see, the number of elements adds up quickly. Be careful that you don't reserve so many array elements that you run out of memory in which to store them.

By reading table data into multidimensional arrays and working with the data in the arrays instead of in database tables, you can speed your program's running times. Anything you can do in memory is faster than doing the same thing reading and writing to disk every time you access values. However, you have much more disk space than memory space. When you're working with large files, you have to forsake the efficiency of memory for the disk capacity.

Tables and For...Next Loops

As you see in some of the next few program samples, nested For...Next loops are good candidates for looping through every element of a multidimensional table. For instance, the section of code

For intRow = 1 To 2

For intCol = 1 To 3

MsgBox("Row: " & intRow & ", Col: " & intCol)

Next intCol

Next intRow

produces the following output in the message boxes (you'll learn better ways to display lists of data shortly):

Row: 1, Col: 1


Row: 1, Col: 2

Row: 1, Col: 3

Row: 2, Col: 1

Row: 2, Col: 2

Row: 2, Col: 3

If you were to print the subscripts, in row order, for a two-row by three-column table dimensioned with the following Dim statement, you'd see the subscript numbers shown by this program's nested loops.

Dim intTable(1 To 2, 1 To 3)

Notice that there are as many For...Next
statements as there are subscripts in the Dim statement (two). The outside loop represents the first subscript (the rows), and the inside loop represents the second subscript (the columns).

For now, you can use InputBox() statements to fill tables, although you rarely fill tables this way. Most multidimensional array data comes from forms or-more often-from disk file data. Regardless of what method actually stores values in multidimensional arrays, nested For...Next loops are excellent control statements to step through the subscripts. The following examples further illustrate tables and also show how nested For...Next loops work with multidimensional arrays.

Example

So many of these past few topic sections have needed to display lists of data, but message boxes simply aren't enough to do the job. I've used message boxes simply as vehicles to teach a concept.

Hour 16's lesson teaches you about a special Visual Basic command called Print. Print sends output to an object that you associate Print with. For example, frmMyForm.Print sends output to a form (form output is taught fully in Hour 16's lesson). Visual Basic also contains a special window named the Immediate window to which you can send variables and strings by using Print. The syntax is

Debug.Print dataToPrint

Therefore, if a procedure contained the statement

Debug.Print "Hello"

Visual Basic prints Hello
in the special Immediate window that appears when the code executes. The following example will use Debug.Print to display a small table of information.

Don't worry too much about the Debug.Print statement. I'm using it just to get past the tedious message boxes that just don't work well to show tables of data. You'll see the Immediate window's figure following the code to describe exactly what the debug window will look like when the procedure terminates. To see the Immediate window, you may have to close some of your development environment's windows or possibly choose Immediate Window from the View menu to show the window if it's hidden.

Suppose that a computer company sells two diskette sizes: 3 1/2 inch and 5 1/4 inch. Each diskette comes in one of four capacities: single-sided low-density, double-sided low-density, single-sided high-density, and double-sided high-density. The diskette inventory is well suited for a two-dimensional table. The company determined that the diskettes have the following retail prices:

Single-Sided Double-Sided Single-Sided Double-Sided
Low-Density Low-Density High-Density High-Density

The procedure in Listing 12.8 stores the price of each diskette in a table and prints the values to the debug window by using a nested For...Next loop. You can put this procedure in a standard module or event procedure to trigger its execution.

Listing 12.8 Disks.bas: Inventory Items Often Appear in a Table

Private Sub disks ()

' Assigns and prints diskette prices

Dim curDisks(1 To 2, 1 To 4) As Currency

Dim intRow As Integer, intCol As Integer

' Assign each element the price

curDisks(1, 1) = 2.3 ' Row 1, Column 1

curDisks(1, 2) = 2.75 ' Row 1, Column 2

curDisks(1, 3) = 3.2 ' Row 1, Column 3

curDisks(1, 4) = 3.5 ' Row 1, Column 4

curDisks(2, 1) = 1.75 ' Row 2, Column 1

curDisks(2, 2) = 2.1 ' Row 2, Column 2

curDisks(2, 3) = 2.6 ' Row 2, Column 3

curDisks(2, 4) = 2.95 ' Row 2, Column 4

' Print the prices in table format

Debug.Print " Single-sided, Double-sided, ";

Debug.Print "Single-sided, Double-sided"

Debug.Print " Low-density Low-density ";

Debug.Print "High-density High-density"

For intRow = 1 To 2

If (intRow = 1) Then

Debug.Print "3-1/2 inch ";

Else

Debug.Print "5-1/4 inch ";

End If

For intCol = 1 To 4

Debug.Print curDisks(intRow, intCol) & " ";

Next intCol

Debug.Print ' Moves the cursor to the next line

Next intRow

End Sub

This procedure produces the output shown in Figure 12.3's Immediate window after you resize the window to show the entire table.

FIG. 12.3

The table of diskette prices appears in a table form.

Next Step

Visual Basic includes a special built-in function called Array(). The Array() function lets you declare and initialize an array quickly.

The Array() function works somewhat like the old BASIC READ and DATA statements. You can quickly initialize small arrays if you know the array data values at programming time.

A Variant can contain any other data type including arrays. Suppose that you want to store the number of days in each month (ignoring leap year) in an array named Days. You can declare a Variant variable like this:

Dim Days As Variant

Remember that if you omit As Variant, Visual Basic assumes Variant. Typing the data type makes your code as clear as possible, however.

You can then initialize the array in one step (rather than use a For...Next loop) like this:

Days = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

If the Option
Base 1 statement appears in the module's Declarations section, the first subscript of Array() is 1 and 0 otherwise. You can declare and initialize strings and dates as well by using the simple Array() function assignment to a Variant value.

Summary

This lesson covered a lot of ground. You learned about arrays, which are a more powerful way to store lists of data than using individual variable names. By stepping through arrays with subscripts, your procedures can quickly scan, print, and calculate with a list of values.

You also know how to create, initialize, and process multidimensional arrays. Although not all data fits in the compact format of tables, much does. Using nested For...Next loops makes stepping through a multidimensional array straightforward.

In Hour 13 you learn how to call procedures from other procedures. You also learn the detailed differences between function procedures and subroutine procedures.

Hour 12 Quiz

  1. True or false: Arrays hold more than one variable with the same name.
  2. How do Visual Basic programs tell one array element (value) from another if the elements have identical names?
  3. Can array elements within the same array be different types?
  4. How many array elements are reserved in the following dimension statement? (Assume an Option Base of 0.)
Dim varAra(78) As Variant

  1. What's the preferred way to specify the beginning subscript in an array-using Option Base or using the To keyword?
  2. How many elements are reserved by the following Dim statement?
Dim varStaff(-18 To 4) As Variant

  1. Given the statement
Dim strNames(5, 10) As String

  1. which subscript (first or second) represents rows and which represents columns?
  2. How many elements are reserved with the following statements?
Option Base 1

Dim ara(4, 7)

  1. Given the table of integers called ara

    4 1 3 5 9
    10 2 12 1 6
    25 43 2 91 8

    what values do the following elements contain? (Assume that no Option Base statement appears in the program.)

    1. ara(1, 1)
    2. ara(1, 2)
    3. ara(2, 3)

  1. Given the code

    Dim intGrades(1 To 3, 1 To 5) As Integer
    For intRow = 1 To 3
    For intCol = 1 To 5
    intGrades(intRow, intCol) = intRow + intCol
    Next intCol
    Next intRow

    what values do the following elements contain?

    1. intGrades(2, 3)
    2. intGrades(3, 5)
    3. intGrades(1, 1)

Hour 12 Homework Exercises

  1. Write a procedure to store six of your friends' names in a single string array. Use InputBox() to initialize the arrays with the names. Print the names on-screen inside message boxes.
  2. Write a simple program to track the names of a radio station's top 10 hits. After you store the array, print the songs in reverse order (to get the top 10 countdown) in message boxes.
  3. Write a Dim statement that dimensions enough string space for the names in a women's basketball league of five teams, 25 players, and six games per player.
  4. Write a procedure that reserves storage for three years of sales data for five salespeople. Use assignment statements to fill the matrix with data and display the table one value per message box.


© 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.