|
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:
- 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.
- 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'.
- 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.
- 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.
- 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).
|