Random Access
Up

There are two ways to read and write information to the hard disk, called sequential access and random access. Sequential access implies that all the information has to be read in order, starting at the beginning, whereas random access means that information can be retrieved from anywhere in the file. The disadvantage of random access is that it requires data to be stored in blocks (called 'records') of equal size. Some people would say that it is barely worth learning about random access because VB's database control gives more power and is easy to use. However I have included this project anyway since it gives a useful introduction to the concept of random access and since one of the limitations of VB5 CCE is that it does not include the database control.

The project described on this page uses random access to score data for a high score table. It is absolutely the simplest random access project I could make and it therefore has many limitations: it always stores data in the same file, the data always consists of 10 records, it does not use 'arrays' as a more professional project might... oh, and it does not handle the scores of the high scorers, only their names...

Make a new EXE project and save it immediately (File>Save Project) into a new folder called random_access - save both the form file and the project file inside the new folder in the usual way, giving them the same name as the folder.

On the new form, add a listbox and a textbox as shown here, setting the colors and text properties as indicated. You may not have used a listbox before so let me tell you that its most imortant property is its LIST property which can be set at design time to include many items, as long as you use Ctrl-Enter to move from one line to the next. In our project however, we will be importing the data from a separate file, using random access, so we simply need to remove the contents of the LIST property to make the list box appear empty now. Set the names of the controls to lstNames and txtReplace. I'm using a textbox in this project because list boxes are not designed to be typed into directly like a text box is. However, you will realize later that the project works just as well, or even better, if the text book is placed outside the form, making it invisible.

The Plan

Here's the plan for how the program will work:

  1. When the program is started (when the form is loaded into the computer's memory) we will run a procedure which opens a file called 'studentscoredata.dat' for random access and then uses a loop to read the 10 names from the file directly into the listbox. We'll add a line that selects the first item in the listbox - we don't want the user to try to replace an item when no item is selected, for it's not clear what should happen in that case.
     
  2. However, the first item may not be the one that the user wants to change, so we now allow the user to select a different item by clicking somewhere else in the list. When this happens a procedure is activated that empties the text box and puts the insertion point in the text box so that anything typed by the user is inserted there and nowhere else. Note that whatever is typed by the user can only be received by ONE control, and whichever control this is is said to have the 'focus'.
     
  3. Now the user will type into the text box the name that is supposed to replace the selected item in the list box. As the user types, a procedure copies the contents of the text box into the selected line of the list box.
     
  4. When the user has finished modifying items (s)he will exit the program, and as the program is unloaded from the computer's memory a final procedure will run - this procedure will use a loop to copy all the names in the listbox back into the file, using random access mode. You may realize that although this program operates in random access mode we are in fact accessing the records in the file in sequence, so we are not yet making full use of the power of random access - that will come later.
     
  5. Later we will add a fifth procedure to sort the contents of the list box using a simple sorting routine called a 'bubble sort'. Sorting routines are an important part of many programmes, so this should be a useful introduction to the concepts involved.

The code in detail

You've learnt in previous projects that nearly all the code in VB projects must be placed inside procedures (between a 'private sub' and an 'end sub') except for DIM statements and the statement that enabled the inclusion of sounds in your projects - these items were placed above all the procedures, in the area known as the General Declarations area. This time we will put into the General Declarations area something new, the declaration of a constant. We have said that our program will store 10 names - that number will not change while the program is running so it's best to call it a constant rather than a variable. (However, we could easily modify the program to handle more names if we wish, just be modifying the constant declaration). In the General Declarations area we will also declare a variable called temp in such a way that it has a fixed length of 20 characters, plenty of space for any normal person's name. In order for random access to work the file must contain data in blocks (called 'records' which have a fixed length, so our program will check the length of the variable called 'temp' and take this to be the length of the records in the random access file. Also, the variable called temp will be used for the temporary storage of names as they are moved between the list box and the random access file. We'll also declare a variable called filename which will be used later to store the name and location of the random access file. Here then are the lines that you can paste into the General Declarations area of your project's code window:

Const numberofrecords = 10
Dim temp As String * 20  ' a fixed length of 20 characters
Dim filename

Now let's have a look at the Form_Load procedure, the procedure that is run as the program starts up, before any other procedures are run:

Private Sub Form_Load()
filename = App.Path & "\studentscoredata.dat"
Open filename For Random As #1 Len = Len(temp)
     For n = 1 To numberofrecords
          Get #1, n, temp
          lstNames.List(n - 1) = Trim(temp) ' TRIM removes leading and trailing spaces
     Next
Close #1
Form1.Show ' if the form is not showing then the next line gives an error
lstNames.ListIndex = 0 ' selects first item in listbox
End Sub

The first line determines the location (path) of our application (our program) on the computer's hard disk, adds a file name to that and then stores the result in the variable called 'filename'. Then the file is opened for random access via channel 1, assuming that the file contains data split into records with a length equal to that of the variable called temp (20 characters). Next we begin a loop which will repeat 10 times, first using n=1, then 2 etc, all the way up to 10, the number stored in the constant called numberofrecords. Inside the loop is an instruction to retrieve the 'nth' record from the file and place it into the variable called temp. The next line copies the contents of temp into the current line of the list box and trims off the spaces at the end (most names are less than 20 characters but we know the records in our file must always be 20 characters long so the records are padded to the right length with extra spaces at the end). Note that the numbering of the lines in the list box begins with zero not one, so it is necessary to subtract one from the record number in order to determine the correct destination line in the listbox (record 1 is copied to line 0 etc). The end of the loop is indicated with the line 'Next' and then the channel used for accessing the is closed, as it always should be. The reason for including the next line is hard to understand unless we look at the line after that first. The final line before 'end sub' selects the first item in the list box, for reasons previously mentioned. The problem is that the form is not normally displayed until the Form_Load procedure has finished running, but we cannot select an item in a list box that is not yet displayed. Now you understand the need to include a line that forces the display of the form 'early' so that the last line can now function properly.

With the listbox displayed and the first item in the listbox already selected we are now waiting for the user to select a different item by clicking somewhere in the listbox - here is the procedure:

Private Sub lstNames_Click()
txtReplace.Text = ""
txtReplace.SetFocus
End Sub

This procedure simply empties the textbox and then gives the textbox the 'focus' so that the insertion point is flashing in the textbox and whatever the user types appears there.

Once the user has clicked on an item in the list to select it then (s)he will begin typing, causing the contents of the listbox to change and triggering this procedure each time (s)he presses a key:

Private Sub txtReplace_Change()
lstNames.List(lstNames.ListIndex) = txtReplace.Text
End Sub

This procedure simply copies the contents of the textbox into the selected line of the listbox. We know that the LIST property of a listbox can contain many lines of data - each line is identified by an index number, so the first line of our listbox will contain the data identified as lstNames.List(0) etc. When a line is selected, VB puts its index number into a special property called ListIndex, so if the first line is selected, for example, then the ListIndex property would contain a 0.

Once the user has finished setting the names as desired then (s)he will end the program, causing the program to be unloaded from the computer's memory. As this happens the final procedure will run:

Private Sub Form_Unload(Cancel As Integer)
Open filename For Random As #1 Len = Len(temp)
     For n = 0 To numberofrecords - 1
          temp = lstNames.List(n)
          Put #1, n + 1, temp
     Next
Close #1
End Sub

This procedure reopens channel 1 for random access, then uses a loop to first copy each line of the listbox into the variable called temp and then to copy temp into the correct location in the file. Most of the names being copied will not be the right length to fill the records in the file, which can each contain 20 characters, so VB will automatically add spaces to the end of them to make them the right length.

Having copied and pasted the declarations and the four procedures into your project's code window, you should now have a working project - try it!

The Bubble Sort

If everything is working you may now want to learn how to add a 'bubble sort' feature to your project. It is also possible to sort the contents of a listbox by setting its SORTED property to true, but that would be much too easy! We want to learn how sorting can be carried out by code, so add a command button, set its caption to "Sort" and its name to cmdSort and then add this procedure to your existing code:

Private Sub cmdSort_Click() ' this is a bubble sort
For n = 0 To numberofrecords - 2   ' we will set item 0 then 1 etc up to 8
     For m = (numberofrecords - 2) To n Step -1  ' will step from 8 down to n
          If lstNames.List(m + 1) < lstNames.List(m) Then ' need to swap them
               temp = lstNames.List(m)
               lstNames.List(m) = lstNames.List(m + 1)
               lstNames.List(m + 1) = temp ' they've been swapped!
          End If
     Next m
Next n
End Sub

Our bubble sort will set each item in the list to contain the correctly sorted value, starting with item 0 and finishing with item 8 (don't forget the numbering of the items starts with 0 not 1). We don't need to set the last value, item 9, because we know that if all the other values are in the right place then the last value must be in the right place too. The 'n loop' keeps track of which item we are trying to set, beginning with 0 and stepping up 8. The inner loop, the m loop, compares the two items at the bottom of the list (items 8 and 9) and then makes sure that the 'smaller' item (the one that would appear first in an alphabetical listing) appears above the larger one, swapping their locations if necessary. Next the m loop compares items 7 and 8 and makes sure that the smaller item appears first, swapping if necessary. This process is repeated within the 'm loop' until item 0 has been compared with item 1 - we can be certain that the smallest word in the list has 'bubbled' its way all the way to the top, into item 0. Now that the m loop has finished looping and we are sure that item 0 contains the correct value, the outer loop, the n loop will step from 0 to 1 and then the m loop will begin again, this time bubbling the correct value into item 1. This process continues until the correct values have been bubbled into items 0 through 8, which means that item 9 must also logically contain its correct value, the 'largest' one or the one that would come last in the alphabet (note that according to the ASCII convention capital letters ALWAYS come before lower case letters in the alphabet, so "a" comes before "z" but after "Z").

If you are having trouble with this project, here is the entire code so that you can copy and paste it in one go if you wish:

Const numberofrecords = 10
Dim temp As String * 20  ' a fixed length of 20 characters
Dim filename

Private Sub Form_Load()
filename = App.Path & "\studentscoredata.dat"
Open filename For Random As #1 Len = Len(temp)
     For n = 1 To numberofrecords
          Get #1, n, temp
          lstNames.List(n - 1) = Trim(temp) ' TRIM removes leading and trailing spaces
     Next
Close #1
Form1.Show ' if the form is not showing then the next line gives an error
lstNames.ListIndex = 0 ' selects first item in listbox
End Sub

Private Sub lstNames_Click()
txtReplace.Text = ""
txtReplace.SetFocus
End Sub

Private Sub txtReplace_Change()
lstNames.List(lstNames.ListIndex) = txtReplace.Text
End Sub

Private Sub Form_Unload(Cancel As Integer)
Open filename For Random As #1 Len = Len(temp)
     For n = 0 To numberofrecords - 1
          temp = lstNames.List(n)
          Put #1, n + 1, temp
     Next
Close #1
End Sub

Private Sub cmdSort_Click() ' this is a bubble sort
For n = 0 To numberofrecords - 2 ' we will set item 0 then 1 etc up to 8
     For m = (numberofrecords - 2) To n Step -1 ' will step from 8 down to n
          If lstNames.List(m + 1) < lstNames.List(m) Then ' need to swap them
               temp = lstNames.List(m)
               lstNames.List(m) = lstNames.List(m + 1)
               lstNames.List(m + 1) = temp ' they've been swapped!
          End If
     Next m
Next n
End Sub

As stated earlier, this project works better if the text box is not visible, so that the user thinks (s)he is typing directly into the list box even though that is not so. However, you cannot simply set the VISIBLE property of the textbox to false, for VB won't let you type into the textbox in that case. Instead, move the textbox outside the visible part of the form (in design mode, not run mode, make the form big, move the textbox, then make the form small again).

Previous Up Next