QBasic - Step By Step :: Section 8
Author: Mike Ware
Website: [warebiz] :: "The Programmer's Domain" - http://warebiz.tripod.com
Email: warebiz@yahoo.com
Copyright © 2002 Michael Shawn Ware, All Rights Reserved.


You are here --> [Section 8 :: Working With Records and Data Files]

"Jump To Articles"
    --> What is a Record?
    --> Arrays of Records
    --> What is a File?
    --> Sequential Files
    --> Random Files


What is a Record?

While arrays are only capable of storing data that is of the same type, a record allows the programmer to store a group of related data that is not necessarily of the same type. In some other programming languages such as C++, a record is called a structure. A record is composed of data items which should be related to each other in some way; each individual data item in the record is referred to as a field and each field has a distinct type associated with it. The general form of a record definition is as follows:


    TYPE recordName
        field1 AS TYPE1
        field2 AS TYPE2
        field3 AS TYPE3
        fieldN AS TYPEN
    END TYPE

where recordName is the name of the record type and field1, ..., fieldN are fields of the record type. For example, if a company needs to generate a report displaying the name, identification number, position, and annual salary of each employee, a record could be used to store this information for each employee. Consider the following record type definition which would take care of our company problem:


    TYPE employeeInfo
        name AS STRING * 25
        idNum AS INTEGER
        position AS STRING * 30
        salary AS DOUBLE
    END TYPE


The record type's name is employeeInfo, and it has four fields. We now have our definition ready, but in order to use it, we must first declare a variable of the record type. After a variable has been declared of the record type, the variable will have all of the record's characteristics and will then be able to store data in each field. Declaration can be done using the DIM statement much like we do when dimensioning "ordinary" variables [see, Dimensioning Variables (section 1)]. Since the record definition is considered to be a user-defined "type", we can dimension a variable as being of that particular type. For example, consider the following statement which will dimension a variable of our previous employeeInfo type:


    DIM employee AS employeeInfo

Now we have a variable declared by the record type, and we can begin to store values in each field of the variable. We can accomplish this by using the dot "." operator. The dot "." operator provides a way to access a particular field of the record type. For example, the following statement would access and assign a value to the name field of our previous employee record variable:


    employee.name = "Joe Smoe"


Notice that our employee record variable is only capable of storing data for one person or record because we dimensioned it as being a single variable. In most cases, a record type will be used with arrays so each element in the array can be associated with its own record. This allows for the storage and access of many records. Arrays of records are covered in the next section. For now, study the following complete program which makes use of a single variable of a record type definition:


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

REM This program uses a simple record to store data for one variable
REM declared by the record type.
REM
REM PROGRAMMER: Mike Ware
REM DATE LAST UPDATE: 4-1-00

CLS

TYPE stuRecord
   name AS STRING * 25
   id AS INTEGER
   gpa AS SINGLE
END TYPE

DIM student AS stuRecord

INPUT "Enter the name of the student: ", student.name
INPUT "Enter the id number of the student: ", student.id
INPUT "Enter the gpa of the student: ", student.gpa

PRINT
PRINT "STUDENT: "; student.name
PRINT "     ID:"; student.id
PRINT "    GPA:"; student.gpa

END

////////////////////////////////////////////////////////////////////////////////////////////////////////

Arrays of Records

You are also able to use arrays to store groups of records or structures. Each element in the array would therefore contain a record. For example, consider the following declaration of an array of records using our previous employeeInfo record type:


    DIM employeeList( 1 TO 25 ) AS employeeInfo

This would declare an array of 25 elements defined by the employeeInfo record type. You can then access a specific field of a specific array record by using the record's corresponding array element subscript and dot "." operator with field name as usual. For example, consider the following statement which would access and assign a value to the idNum field of the fifth element in the employeeList array:


    employeeList( 5 ).idNum = 2132


When needing to access elements in an array that contains records, a loop should be used. For example, consider the following piece of code:


TYPE stuRecord
     name AS STRING * 25
     id AS INTEGER
     gpa AS SINGLE
END TYPE

DIM student(1 TO 20) AS stuRecord

FOR index = 1 TO 20
     INPUT "Enter the name of the student: ", student(index).name
     INPUT "Enter the id number of the student: ", student(index).id
     INPUT "Enter the gpa of the student: ", student(index).gpa
NEXT index

PRINT
FOR count = 1 TO 20
     PRINT "STUDENT: "; student(count).name
     PRINT "     ID:"; student(count).id
     PRINT "    GPA:"; student(count).gpa
NEXT count

The following complete program illustrates the use of arrays of records. Study it before moving on to learn about data files.


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

REM This program illustrates the use of an array of records.
REM
REM PROGRAMMER: Mike Ware
REM DATA LAST UPDATE: 4-5-00

CLS

TYPE groupInfo
   name AS STRING * 25
   idNum AS STRING * 5
   location AS STRING * 30
   dataOfReg AS STRING * 8
END TYPE

sizeOfArray = 3

DIM group(1 TO sizeOfArray) AS groupInfo

FOR index = 1 TO sizeOfArray
   PRINT "For member --->"; index
   INPUT "Enter name: ", group(index).name
   INPUT "Enter identification number: ", group(index).idNum
   INPUT "Enter location: ", group(index).location
   INPUT "Enter registration date: ", group(index).dataOfReg
   PRINT
NEXT index

CLS
PRINT
PRINT "GROUP MEMBER LISTING"
PRINT "---------------------"
PRINT

FOR index = 1 TO sizeOfArray
   PRINT "Member: "; group(index).name
   PRINT "ID: "; group(index).idNum
   PRINT "Location: "; group(index).location
   PRINT "Registration Data: "; group(index).dataOfReg
   PRINT
NEXT index

END

////////////////////////////////////////////////////////////////////////////////////////////////////////

What is a File?

Files are scattered everywhere inside your computer and come in many shapes and forms. The most important files are program and data files. Program files are associated with providing access and execution of an actual program that is stored and installed on your computer system. Everytime you create a QBasic source file using an editor, you are actually creating a program file that can be executed with the use of a computer. Data files contain data and information needed for programs to perform execution successfully. Data files are "linked" to or "included" with a certain program file during run-time or compilation time.

There are many advantages to using data files with your programs. In QBasic, records are normally always associated with a file. The records can actually be permanently stored, one-by-one, in a data file, and then the file can later be used as a way to retrieve particular records in the file. This type of storage is called secondary because it makes use of some type of permanent storage device such as a hard drive, a floppy disk drive, a zip drive, or any type of compact storage disc. All other storage in a computer is called primary, which is the active internal short-term computer memory that is lost upon termination of the computer system. Files also make it easier to update data and specific program requirements. Once stored in seconday storage, any program has access to the file unless certain programs only have priviledges of accessing it (this is not covered in this tutorial or is even possible in QBasic).

There are two ways to access a file stored on disk in order to transer the data between secondary storage (disk where file is stored) and primary storage (active internal memory of a computer). These two access methods are called sequential and random.

By definition, sequential means moving from one thing or object to the next. In our case, sequential access means that the data contained in the targetted file will be accessed in the order in which it is physically stored on the disk. In other words, if you want to access the 25th record within a file, files 1 to 24 must be accessed first in order to reach the 25th (target) file.

Random access allows the programmer to directly access a specific record within a particular file. This makes the search for a record contained in a file extremely faster than sequential access.

In QBasic, there are 2 ways to create a file: sequential and random. If creating a sequential file, you must use sequential access when attempting to access data contained in the file. If creating a random file, you may use random access to locate data contained within a file. Let's first talk about sequential files and then move on to random files. Read on for more...

Sequential Files

It is important to note that a file position pointer is used by a file to "point to" the next record to be processed in the file. At first, the pointer starts at the very beginning of the file therefore pointing to the first record, and then it is incremented to each next record while "cycling" through the file. This is how sequential access is able to work. As the file is sequentially moved within the file, the imaginary file position pointer is actually sequentially moved to each record within the file until the target record is reached.

Opening a File
When creating or accessing a sequential file, the first thing the programmer must do is open the file using the OPEN statement. The OPEN statement has the following form:


    OPEN "fileName.ext" FOR mode AS #[buffer]

As you can tell, the OPEN statement will provide the name of the file, the way it which it will be used (mode), and the buffer number of the file. The same rules apply for naming data files as they do for naming "regular" QBasic program files, except a data file should normally be given an extension (.ext) of .DAT where as a program file is given an extension of .BAS. This could mean that the program using the data file could have the same name as the data file. The extensions would be the only way to distinguish the files from eachother; this is a customary thing to do when naming program and data files that will only be associated with eachother.

You can use a file as either OUTPUT, INPUT, or APPEND; these are the mode options. OUTPUT means that the program will eventually write data to the file. INPUT means that the data contained in the file will eventually be read into the calling program. APPEND means that the data will be added to an existing file on disk.

A buffer is a reserved section of primary storage used for storing temporary data being written to or read from a file. The programmer specifies the buffer number of a file, and it is used by the program to recognize and identify the file that is attempting to be manipulated. The buffer number of the file must be known by the programmer when attempting to write data to or read data from the file.

If you try to open a file that dosen't exist, a new file will be created. If you try to open a pre-existing file as OUTPUT, the file will be overwritten and lose all of its contents or data. For example, consider the following OPEN statement:


    OPEN "STUDATA.DAT" FOR OUTPUT AS #1

The above OPEN statement would open the file STUDATA.DAT for output using 1 as a buffer number. If STUDATA.DAT pre-existed on disk, then it will be overwritten and created as an empty file. Once you have successfully opened a file, you can either write data to it, read data from it, or append records to the file; this depends on what mode you specified for the file in the OPEN statement.

Writing to a File
Writing to a file that has been previously opened as OUTPUT is accomplished by using the WRITE# statement. The WRITE# statement works much like the PRINT statement, except instead of sending output to the screen, the WRITE# statement will send data to the opened file. Another difference is that when using the WRITE# statement, you must first indicate the buffer number of the file being written to. For example, consider the following WRITE# statement:


    WRITE #1, name, address, phone

The above statement would write the data contained in the name, address, and phone variables to the file using buffer number 1. The WRITE# statement actually only transfers the data into buffer 1's primary storage location. The transfer from primary memory to secondary memory actually occurs when "closing" the file, which is covered further in the article.

Reading From a File
Reading data from a file that has been previously opened as INPUT is accomplished by using the INPUT# statement. The INPUT# statement is similar to the INPUT statement, except instead of the reading user data input from the keyboard, the INPUT# statement reads data from a file on disk. For example, consider the following:


    INPUT #1, stuName, gpa, grade

The above statement would take values associated with the file with buffer number 1, and assign the values to each of the specified variables in the statement one value at a time. It is important to note that the INPUT# statement reads data from the record that is currently being pointed to by the file position pointer. After the INPUT# statement is executed, the file position pointer will be incremented to the next record in the file, and then the process is repeated if trying to read more data in the file.

It is also important to realize that there is an end-of-file character at the end of every file. This allows the program accessing the file to recognize when there is no more data in the file to be read into the program. Any attempt to read past the end of the file will generate an error. The end-of-file character comes in handy when reading data from a file because it will let you know when all data has been read. There is a member function called EOF( ) that is used to check for the end of a file during the reading process. The EOF( ) function will return a value of false ( 0 ) if there are more records in the file, or it will return a value of true ( 1 ) if the end of the file has been reached. Therefore, the EOF( ) function is actually evaluated much like a boolean expression. The argument sent into the EOF( ) function will be the buffer number of the file being manipulated. Because the EOF( ) is a boolean expression that returns a value of true or false, it is an efficient way of controlling the execution of a loop that is reading data from a file. For example, consider:


    DO WHILE NOT EOF( 1 )
        INPUT #1, stuName, gpa, grade
        PRINT "STUDENT: "; stuName; SPC(5); gpa; SPC(5); grade
    LOOP

The above code would read all data and records contained in the file with buffer number 1 and print the data for each record until the end-of-file character is reached. If you wanted to sequentially access and print data contained in a particular record in a file, you would have to read in (but not print) all records precending the "target" record. This can be accomplished by creating a "dummy" variable to keep track of how many records have been read from the file until the record you are trying to access is the next record to be read. This is time consuming, not to mention in-efficient, and a better solution to this problem would be to use a random method file. We dive into the details of random files further in the article.

Appending a File
Firstly, appending a file requires the mode of the OPEN statement to be APPEND. Appending a file is the process of adding records to the end of a file that previously exists on disk. Appending is a process in itself because, as previously mentioned, opening a file by OUTPUT will create a new file or overwrite a file if it previously existed on disk. Thus, there is no way to add records to the end of a file using a mode of OUTPUT. The APPEND mode operation in the OPEN statement moves the file position pointer to the end of the file being opened. Therefore, after opening a file for APPEND, anytime you write data to the file, the data will be "tagged" or inserted onto the end of the file.

Closing a File
After the program is done using the file, the file must be closed. When writing data to a file on disk, the CLOSE statement is actually responsible for transferring the data currently in primary memory to seconday memory (file on disk). So, it is imperative that you close files. This is accomplished by using the CLOSE statement as follows:


    CLOSE #[buffer]

The CLOSE statement actually writes all temporary data that is currently in the corresponding buffer to the file. If we wanted to close our previous STUDATA.DAT file, we could use:


    CLOSE #1

You can also close many opened files using a single CLOSE statement as follows:


    CLOSE #1, #2, #3, ..., #n

You can also close all currently opened files by using a single CLOSE statement with no parameters by simply issuing:


    CLOSE

Study the following complete program illustrating how to write/read data using a sequential file before moving on to learn about random files:


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

REM This program will create a sequential file named INFO.DAT.
REM The file will then be used to store input data supplied
REM by the user and then to retreive the data contained in
REM in the file.
REM
REM PROGRAMMER: Mike Ware
REM DATE LAST UPDATED: 4-28-00

OPEN "INFO.DAT" FOR OUTPUT AS #1

CLS

REM Get input from user
INPUT "Do you wish to enter student information (Y/N)"; answer$

DO WHILE answer$ = "Y" OR answer$ = "y"
   INPUT "Enter student name: ", name$
   INPUT "Enter student id: ", id
   INPUT "Enter student gpa: ", gpa

   REM Write current input to temporary buffer storage 1
   WRITE #1, name$, id, gpa

   INPUT "Do you wish to enter new student information (Y/N)"; answer$
LOOP

REM Transer data from temporary buffer 1 to actual INFO.DAT
CLOSE #1

OPEN "INFO.DAT" FOR INPUT AS #2

PRINT "STUDENT LISTING"
PRINT "----------------------------------------"

DO WHILE NOT EOF(2)
   INPUT #2, name$, id, gpa
   PRINT
   PRINT "STUDENT NAME: "; name$
   PRINT "  STUDENT ID:"; id
   PRINT " STUDENT GPA:"; gpa
LOOP

CLOSE #2

END

////////////////////////////////////////////////////////////////////////////////////////////////////////

Random Files

If the solution to the problem you are working with deals with directly accessing a particular record in a file, then the most efficient algorithm to use would involve using a random file. As previously mentioned in this article, random files have the capability of accessing a record within a file without the need to access all preceding records like a sequential file. Specifying that a file be treated as random uses a form similar to the form used for specifying different mode operations for a sequential file. As with all file types, the first thing the programmer must do before attempting to use the file is open it. The form of opening a random file is as follows:


    OPEN "fileName.ext" FOR RANDOM AS #[buffer] LEN = LEN(recordVariable)

Notice that we opened the file as being RANDOM and a buffer file number is used as usual (if this does not look normal, see Sequential Files). The major difference is the LEN = LEN( ) function initialization. The argument, recordVariable, that is sent into the LEN( ) function is a variable of a record type. The LEN( ) function will return the size of recordVariable in order to allocate space for each record to be stored in the file.

Writing or Storing Records
When dealing with random files, you can't send data from each field in a record one-by-one into the file. Instead, random files let you send the contents of the entire record to the file in one statement. This is accomplished by using the PUT statement, and the PUT statement also specifies the location in the file where the record is being sent. The PUT statement has the following form:


    PUT #[buffer], recordNumber, recordVariable

In the above statement, the buffer file number must be first specified, the number of the record or the location of the record to be in the file is next, and finally the actual record variable is specified so the program knows which record to send to the file.

Reading Records
The complete opposite operation of the GET statement would be to retreive or get the data contained in a data file. QBasic has a "built-in" function to handle this situation also. It is called GET and has a form identical to the PUT statement. The form of the GET statement is as follows:


    GET #[buffer], recordNumber, recordVariable

Because of the GET statement, any record can be directly accessed by specifying the record's record number or location file number. This is what makes random files much more powerful than sequential files. The following complete program demonstrates most of the material covered in this article about random files and also gives a great review of most of the material covered in the tutorial up to this point. Be sure to take the time to study and tweak the program code before testing the program. When I created the program, I designed it with a somewhat weak security system and also geared the command prompt to fit my needs. If you can't figure out how to run the program, look at the code. The code will tell you what to enter at the prompts, and then you can change the code to fit your needs.


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

REM PROGRAMMER: MIKE WARE
REM COMPUTERIZED INFORMATION BLACK BOOK
REM Be sure to study and tweak code before
REM testing program.

CLS

TYPE recordInfo
   Gender AS STRING * 1
   FirstName AS STRING * 20
   FirstIni AS STRING * 2
   MiddleIni AS STRING * 2
   LastName AS STRING * 25
   StreetAddress AS STRING * 50
   City AS STRING * 30
   State AS STRING * 30
   ZipCode AS STRING * 5
   TelephoneNumber AS STRING * 12
   CellNumber AS STRING * 12
   PagerNumber AS STRING * 8
   EmailAddress AS STRING * 50
   College AS STRING * 50
END TYPE

DIM record AS recordInfo

OPEN "RECORD.DAT" FOR RANDOM AS #1 LEN = LEN(record)

CALL Begin(record)

SUB Begin (record AS recordInfo)

COLOR 8
divider = (80 - LEN("-------------------------------")) / 2
PRINT TAB(divider); "-------------------------------"
COLOR 3
center = (80 - LEN(">>>>> RESTRICTED AREA <<<<<")) / 2
PRINT TAB(center); ">>>>> RESTRICTED AREA <<<<<"
COLOR 8
PRINT TAB(divider); "-------------------------------"

COLOR 7
LOCATE 6, 23
PRINT "AUTHORIZATION REQUIRED TO PROCEED!"
LOCATE 9, 29
INPUT "ACCESS CODE: ", author$

IF author$ = "123456" THEN
   CALL Welcome(record)
ELSE
   CLS
   BEEP
   COLOR 8
   LOCATE 9, 25
   PRINT STRING$(27, "-")
   LOCATE 10, 28
   COLOR 4
   PRINT "INCORRECT ACCESS CODE"
   LOCATE 11, 25
   COLOR 8
   PRINT STRING$(27, "-")
   COLOR 7
   END
END IF

END SUB

SUB FamilyAddRecord (record AS recordInfo)

CLS
COLOR 8
divider = (80 - LEN("-----------------------------")) / 2
PRINT TAB(divider); "-----------------------------"
COLOR 3
center = (80 - LEN("ADD RECORD INFORMATION")) / 2
PRINT TAB(center); "ADD RECORD INFORMATION"
COLOR 8
PRINT TAB(divider); "-----------------------------"
COLOR 7

PRINT
PRINT
INPUT "ENTER RECORD NUMBER: ", RecNum
PRINT
PRINT "WARNING!"
PRINT
PRINT "YOU WILL LOSE ANY SAVED DATA IN RECORD: "; RecNum
PRINT
INPUT "PROCEED (Y/N)? ", ANS$

IF ANS$ = "Y" THEN
        CLS
        COLOR 8
        divider = (80 - LEN("-----------------------------")) / 2
        PRINT TAB(divider); "-----------------------------"
        COLOR 3
        center = (80 - LEN("ADD RECORD INFORMATION")) / 2
        PRINT TAB(center); "ADD RECORD INFORMATION"
        COLOR 8
        PRINT TAB(divider); "-----------------------------"
        COLOR 7
        PRINT
        PRINT

        INPUT "GENDER: ", record.Gender
        INPUT "FIRST NAME: ", record.FirstName
        INPUT "FIRST NAME (INITIAL): ", record.FirstIni
        INPUT "MIDDLE NAME (INITIAL): ", record.MiddleIni
        INPUT "LAST NAME: ", record.LastName
        INPUT "STREET ADDRESS: ", record.StreetAddress
        INPUT "CITY: ", record.City
        INPUT "STATE: ", record.State
        INPUT "ZIP CODE (#####): ", record.ZipCode
        INPUT "TELEPHONE NUMBER (###-###-####): ", record.TelephoneNumber
        INPUT "CELL-PHONE NUMBER (###-###-####): ", record.CellNumber
        INPUT "PAGER NUMBER: ", record.PagerNumber
        INPUT "EMAIL ADDRESS: ", record.EmailAddress
        INPUT "COLLEGE: ", record.College

        PUT #1, RecNum, record

        PRINT
        INPUT "PRESS  TO RETURN TO MAIN MENU...", go$
        CALL FamilyMenu(record)

ELSE
        CALL FamilyMenu(record)
END IF


END SUB

SUB FamilyDisplayListing (record AS recordInfo)

CLS
COLOR 8
divider = (80 - LEN("------------------------------------")) / 2
PRINT TAB(divider); "------------------------------------"
COLOR 3
center = (80 - LEN("COMPLETE RECORD LISTING")) / 2
PRINT TAB(center); "COMPLETE RECORD LISTING"
COLOR 8
PRINT TAB(divider); "------------------------------------"
COLOR 7
PRINT
PRINT SPC(2); "#"; TAB(15); "|"; SPC(1); "G"; SPC(1); "|"; SPC(3); "NAME"
COLOR 8
PRINT STRING$(80, "-")
COLOR 7

FOR count = 1 TO LOF(1) / LEN(record)
   GET #1, count, Family
   PRINT SPC(1); count; TAB(7); "---->"; SPC(3); "|"; SPC(1); record.Gender; SPC(1); "|"; SPC(3); record.FirstIni; SPC(1); record.MiddleIni; SPC(1); record.LastName
NEXT count

PRINT
PRINT
PRINT
INPUT "PRESS  TO RETURN TO MAIN MENU...", go$
CALL FamilyMenu(record)


END SUB

SUB FamilyMenu (record AS recordInfo)

CLS
COLOR 3
center = (80 - LEN(">>>>> COMPUTERIZED BLACK BOOK <<<<<")) / 2
PRINT TAB(center); ">>>>> COMPUTERIZED BLACK BOOK <<<<<"
PRINT

COLOR 8
PRINT TAB(20); STRING$(39, "-")
COLOR 7
PRINT TAB(22); "1 - ADD A NEW RECORD"
PRINT TAB(22); "2 - OPEN AN EXISTING RECORD"
PRINT TAB(22); "3 - DISPLAY LIST OF CURRENT RECORDS"
PRINT TAB(22); "4 - PRINT LIST OF CURRENT RECORDS"
PRINT TAB(22); "5 - EXIT"
COLOR 8
PRINT TAB(20); STRING$(39, "-")
PRINT
PRINT

COLOR 7
INPUT "SELECT DOMAIN:\ ", Choice

DO WHILE Choice < 1 OR Choice > 5
   PRINT "INVALID CHOICE!"
   PRINT
   INPUT "ENTER A CHOICE (1 - 5): ", Choice
LOOP


SELECT CASE Choice
   CASE 1
      CALL FamilyAddRecord(record)
   CASE 2
      CALL FamilyOpenRecord(record)
   CASE 3
      CALL FamilyDisplayListing(record)
   CASE 4
      CALL FamilyPrintListing(record)
   CASE 5
      CLOSE #1
      CALL Welcome(record)
      END
END SELECT


END SUB

SUB FamilyOpenRecord (record AS recordInfo)

CLS
COLOR 8
divider = (80 - LEN("---------------------------")) / 2
PRINT TAB(divider); "---------------------------"
COLOR 3
center = (80 - LEN("OPEN AN EXISTING RECORD")) / 2
PRINT TAB(center); "OPEN AN EXISTING RECORD"
COLOR 8
PRINT TAB(divider); "---------------------------"
COLOR 7

PRINT
PRINT
INPUT "ENTER RECORD NUMBER: ", RecNum

GET #1, RecNum, record
CLS
COLOR 8
divider = (80 - LEN("-------------------------------")) / 2
PRINT TAB(divider); "-------------------------------"
COLOR 3
center = (80 - LEN("SEARCH STATUS: RECORD FOUND")) / 2
PRINT TAB(center); "SEARCH STATUS: RECORD FOUND"
COLOR 8
PRINT TAB(divider); "-------------------------------"
COLOR 7
PRINT
PRINT
COLOR 3
PRINT "RECORD NUMBER: "; RecNum
COLOR 8
PRINT STRING$(80, "-")
COLOR 7
PRINT
PRINT "GENDER: "; TAB(20); record.Gender
PRINT "FIRST NAME: "; TAB(20); record.FirstName
PRINT "MIDDLE INITIAL: "; TAB(20); record.MiddleIni
PRINT "LAST NAME: "; TAB(20); record.LastName
PRINT "STREET ADDRESS: "; TAB(20); record.StreetAddress
PRINT "CITY: "; TAB(20); record.City
PRINT "STATE: ", TAB(20); record.State
PRINT "ZIP CODE: "; TAB(20); record.ZipCode
PRINT "TELEPHONE NUMBER: "; TAB(20); record.TelephoneNumber
PRINT "CELLPHONE NUMBER: "; TAB(20); record.CellNumber
PRINT "PAGER NUMBER: "; TAB(20); record.PagerNumber
PRINT "EMAIL ADDRESS: "; TAB(20); record.EmailAddress
PRINT "COLLEGE: "; TAB(20); record.College

PRINT
PRINT
INPUT "PRESS  TO RETURN TO MAIN MENU...", go$
CALL FamilyMenu(record)


END SUB

SUB FamilyPrintListing (record AS recordInfo)

CLS
COLOR 8
divider = (80 - LEN("------------------------------------")) / 2
LPRINT
LPRINT
LPRINT
LPRINT
LPRINT TAB(divider); "------------------------------------"
COLOR 3
center = (80 - LEN("COMPLETE RECORD LISTING")) / 2
LPRINT TAB(center); "COMPLETE RECORD LISTING"
COLOR 8
LPRINT TAB(divider); "------------------------------------"
COLOR 7
LPRINT
LPRINT SPC(2); "#"; TAB(16); "|"; SPC(1); "G"; SPC(1); "|"; SPC(3); "NAME"
COLOR 8
LPRINT STRING$(80, "-")
COLOR 7

FOR count = 1 TO LOF(1) / LEN(record)
   GET #1, count, record
   LPRINT SPC(1); count; SPC(3); "---->"; SPC(3); "|"; SPC(1); record.Gender; SPC(1); "|"; SPC(3); record.FirstIni; SPC(1); record.MiddleIni; SPC(1); record.LastName
NEXT count

CLS
COLOR 8
divider = (80 - LEN("------------------------------------------")) / 2
PRINT TAB(divider); "------------------------------------------"
COLOR 3
center = (80 - LEN("PRINTING COMPLETE RECORD LISTING")) / 2
PRINT TAB(center); "PRINTING COMPLETE RECORD LISTING"
COLOR 8
PRINT TAB(divider); "------------------------------------------"
COLOR 7
PRINT
PRINT
PRINT "THE LISTING IS BEING PRINTED."
PRINT
INPUT "PRESS  TO RETURN TO MAIN MENU...", go$
CALL FamilyMenu(record)


END SUB

SUB Welcome (record AS recordInfo)

CLS
PRINT "HELLO, MASTER "
PRINT
INPUT "DOMAIN:\ ", MESSAGE$

IF MESSAGE$ = "CALL MENU" THEN
   CALL FamilyMenu(record)
ELSEIF MESSAGE$ = "HELP" OR MESSAGE$ = "help" THEN
   PRINT
   PRINT STRING$(43, "*")
   PRINT "HELP LOG - [commands]"
   PRINT SPC(5); "CALL MENU --> DISPLAYS MENU OF OPTIONS"
   PRINT SPC(5); "EXIT --> TERMINATES AUTHORIZATION"
   PRINT SPC(5); "HELP --> DISPLAYS HELP LOG"
   PRINT STRING$(43, "*")
   PRINT
   INPUT "DOMAIN:\", MESSAGE$

      IF MESSAGE$ = "CALL MENU" THEN
         CALL FamilyMenu(record)
      ELSEIF MESSAGE$ = "HELP" THEN
         PRINT
         PRINT STRING$(43, "*")
         PRINT "HELP LOG - [commands]"
         PRINT SPC(5); "CALL MENU --> DISPLAYS MENU OF OPTIONS"
         PRINT SPC(5); "EXIT --> TERMINATES AUTHORIZATION"
         PRINT STRING$(43, "*")
         PRINT
      ELSEIF MESSAGE$ = "EXIT" THEN
         COLOR 4
         PRINT
         PRINT "\-- AUTHORIZATION TERMINATED --/"
         COLOR 7
         PRINT "GOODBYE, "
         END
      ELSE
         PRINT
         PRINT "INVALID RESPONSE"
         COLOR 4
         PRINT "\-- AUTHORIZATION TERMINATED --/"
         COLOR 7
         END
      END IF
ELSEIF MESSAGE$ = "EXIT" THEN
   COLOR 4
   PRINT
   PRINT "\-- AUTHORIZATION TERMINATED --/"
   COLOR 7
   PRINT "GOODBYE, MASTER "
   END
ELSE
   PRINT
   PRINT "INVALID RESPONSE"
   COLOR 4
   PRINT "\-- AUTHORIZATION TERMINATED --/"
   COLOR 7
   END
END IF

END SUB

////////////////////////////////////////////////////////////////////////////////////////////////////////

You have reached the end of my QBasic tutorial. I hope you found some information in the tutorial to be helpful and worthy of reading. If you found any problems with the tutorial or simply have a question concerning a topic in the tutorial, feel free to contact me at the email address provided above. I'll be sure to get back with you. As always, thanks for supporting [warebiz] and be sure to check back for updates. Happy coding!

NOTE: Updates made to the tutorial as far as adding new articles and program examples will depend on user feedback and suggestions.

Back to Top