Data Files 2

advertisement
Data Files
• In all your projects so far, the user has
entered information through text-boxes
• This input method is unsatisfactory for large
quantities of data
• Many computer applications require data to
be saved from one run to the next e.g.
inventory records, customer files etc.
File Organisation
• The manner in which data are
organised,stored and retrieved.
• 2 Common file organisations:
– Sequential
– Random
Opening and Closing Data Files
• Open the file. Before any data may be
placed on the disk or read from the disk, the
file must be opened. Generally done in
Form_Load procedure.
• Read or Write the data records.
• Close the file.
Open Statement
Open “Filename” For {Input/Output/Append/Random} As
#FileNumber
• The Open statement elements shown in the chain brackets
are the file mode, indicating the way that you will access
the file. This is a required entry, so one of the modes must
be chosen.
• The first three choices are used for sequential files.
Open Statement
• The FileNumber may be from 1 to 511
• Record Length may be up to 32,767
characters
Open “A:\DataFile.dat” For Output As #1
Open “C:\VB6\Names.txt” For Input As #2
File Mode
Description
Output
Data are output from the project and written on the
disk. New data is written at the beginning of the file,
overwriting any existing data
Input
Data are input into the project from the disk. This mode
reads data previously stored on the disk.
Append
Data are output from the project and written on the
disk. The new data are added to the end of the file.
Random
Data can be input or output, and records may be
accessed in any order.
FreeFile and Close Statements
• FreeFile function returns the next unused
file number
– intFileNumber = FreeFile
– In large projects, file numbers are hard to track
and allocate
• Close issued automatically when you end
• Issue Close statement before leaving prog.
– Close #1 or
Close #1, #2
• To locate an available file number for a
large project, always use the FreeFile
function to locate an unused file number.
• You don’t care what number is chosen—
only that it is available.
• Store the retrieved file number in a module
or global variable so other forms can
manipulate the files, if necessary.
• Obtain an available file number this way:
– Dim intFileNumb As Integer
– intFileNumb = FreeFile
‘Obtain next
available file number
– Open “File.dat” For Output As
#intFileNumb
• Whenever you reference the preceding file,
you do so with the intFileNumb variable
rather than a literal (number).
Example:
Private Sub cmdCreateFile_Click()
Dim name1 As String, name2 As String
' Demonstrate use of Write # statement
Reference number
Open "PIONEER.TXT" For Output As #1
Write #1, "ENIAC"
File name
Write #1, 1946
Write #1, "ENIAC", 1946
Write to the file
name1 = "Eckert"
name2 = "Mauchly"
Write #1, 14 * 139, "J.P. " & name1, name2, "John"
Close #1
Close the file
End Sub
Sequential File Organization
• Sequential file records are stored one after
another
• Use Write to output data
• Use Input to read data
• File must be opened prior to first use
• Form: Write #fn, item1, item2,…, itemn
Input #fn, item1, item2,…, itemn
• EOF function signals end of file
• Output fields are placed one after another and end
with <CR>
• If you create a form to add records to a file, the
Open statement is commonly placed in the form
Load event procedure, whereas the write statement
is placed in the click procedure of an Add button.
• Input statement reads sequential data
– Input #1, lblName.Caption, lblStreet.Caption
– Input #2, stAccount, stDescription, cPrice
• When reading a sequential file, the EOF (End Of
File) condition is raised when you attempt to read
the n+1st record (n records total).
• The EOF function is used to determine when EOF
occurs
• EOF form: EOF(filenumber)
• Example reading sequential data file and
populating two list boxes:
Do Until EOF(intFileNumb)
Input #intFileNumb, stName, stPhone
lstName.AddItem stName
‘add name to
a list box
lstPhone.AddItem stPhone ‘add phone
to a list box
Loop
Close #intFileNumb
‘close
the input file
Writing to a Sequential File
• Write statement places data in output
• Form: Write #file, o1, o2, …, on
• You can separate fields with commas or
semicolons
• Output fields are separated with commas,
and strings are quoted.
• <Cr>/<Lf> ends each record
• Write #1, txtLname.Text, 54.89
Example (Adding a player to a BASEBALL1.TXT file)
Private Sub Form_Load()
Open App.Path & "\BASEBALl.TXT" For Append As #1
End Sub
Opening the file in append mode
Private Sub cmdAddRec_Click()
Write #1, txtPlayer.Text, txtTimes.Text, txtHits.Text
txtPlayer.Text = “ “
txtTimes.Text =“ ”
txtHits.Text=“ ”
txtPlayer.SetFocus
End Sub
Private Sub cmdQuit_Click()
Close #1
End
End Sub
Reading Data in a Sequential File
•
•
•
•
Form: Input #fn, item1,…,itemn
Separate fields items with commas
File number must be that of an open file
When you read the last record, end-of-file
signals
• You detect end of file with the EOF
function: EOF(FileNumber)
• EOF returns false until end of file is
reached.
• Typical read loop:
– Do Until EOF(1)
– Input #1, strCofFlavor,
strRoastName, strRoastCity
– Loop
• If the file contains five records, then EOF is
raised on the fifth input execution, not on
the sixth Input.
Trapping Program Errors
• Errors may be trapped asynchronously
• Visual Basic generates an error number
whenever an error occurs
• To handle errors, you must
– Turn on error handling feature: On Error...
– Create error handling code
– Determine what is to be done after processing
the error (continue, end program,…)
• Place On Error in any procedure that is to traps
and processes errors
• Example:
– Private Sub Form_Load()
– On Error GoTo HandleErrors
'Turn on
error trapping
– Open "A:\Testdata.dat" For Input As #1
– … (more code here)
– Exit Sub 'exit to avoid executing error
routine
– HandleErrors:
– ‘some code to handle error
– Resume
– End Sub
• A line label is a name followed by a colon
on a line by itself
• HandleErrors is a line label
• Forms of On Error statement:
– On Error GoTo linelabel transfer control to
label in module
– On Error Resume Next skip error line &
continue with next
– On Error GoTo 0
handling
turns off error
The Err Object
• The Err object holds information about
error that just occurred
• Err.Source holds the source of the error
• Err.Number holds the error number
• Err.Description contains error description
• You can raise an error condition—turn on
an error—with: Err.Raise Number:=xx
• Err.Number
– 7
– 9
– 11
– 13
– 52
– 53
– 54
– 58
– 61
– 67
– 68
– 70
– 71
– 75
– 76
– 482
Err.Description
Out of memory
Subscript out of range
Division by zero
Type mismatch
Bad filename or number
File not found (fnf)
Bad file mode
File already exists
Disk full
Too many files
Device unavailable
Permission denied
Disk not ready
Path/file access error
Path not found
Printer error
• Raise error 76 in program code: Err.Raise
Number:=76
Coding Error-Handling Routines
• On Error statement designates error handler
• Code to handle errors follows line label
• Line label appears on line by itself and ends
with a colon
• A Case statement works well to sort out
errors with a "switchboard"
• Continue execution with Resume statement
• Using Case to handle errors with a
"Switchboard":
–
–
–
–
–
–
Select Case Err.Number
Case 53
'Handle error # 53 here
…
Case 71
'Handle error # 71 here
...
Case Else 'Handle all other errors
here
–
…
– End Select
• Resume statement forms:
– Resume
continues with line causing error
(careful!)
– Resume Next continues with line following one
that caused error
– Resume linelabel continues at line label,
which must be in same proc
• Exit statement jumps out of structure--a
function, subroutine, or loop
• Exit should be placed before line label of
error handling routine so normal program
flow doesn't drop through the error code.
Exit and Exit Sub Statements
• Exit Sub immediately exits current sub
procedure
• Exit Function immediately exits current
function
• Exit is used to prematurely halt execution
of sub procedure or function when
extraordinary conditions occur
• Place Exit Sub above error handling label
Saving Changes to a File
• When data changes, ask users if they want
to save the changes before program ends
• Changed data is known as “dirty” data
• Keep track of data changes with a global
boolean flag
• Any procedure that allows data to change
should set the flag to True—indicating
“dirty” data file
• Check file just before ending program
• You should Unload all forms before executing an
End statement.
• This triggers each form’s Unload event (and each
Class’s Terminate event), giving you control at
that point to check for “dirty” data files.
• The best way to ask the user if they want to save
changes is in the QueryUnload event procedure.
• The QueryUnload event procedure obtains control
when the (what else!) QueryUnload event occurs.
• QueryUnload occurs when the user:
– clicks an Exit button or menu command to exit
– clicks on a window’s Close button
– or exits Windows altogether
QueryUnload procedure example:
Private Sub Form_QueryUnload(Cancel As
Integer, UnloadMode As Integer)
Dim intResponse As Integer
If mblnIsDirty Then
IntResponse = MsgBox(“Data has
changed. Save it?”, _
vbYesNo + vbQuestion,
“Coffee List Changed Warning”)
If intResponse = vbYes Then
mnuFileSave_Click
End If
End If
End Sub
Sequential File Prog. Example
• You can load a combo box by reading from
a data file and executing the AddItem
method
• Reading file & list filling halts when EOF
occurs on input file
Random Access Files
•A Random Access file is like an array of records stored
on a disk.
•The records are numbered 1,2,3, and so on, and can be
referred to by their numbers.
•Therefore, a Random Access File resembles a box of
index cards, each having a numbered tab. Any card can
be selected from the box without first reading every
index card preceding it; similarly any record of a
random access file can be read without having to read
every record preceding it.
Random File Organization
• Records are fixed length and have a record
number (data type=long integer) for
reference
• Fields are fixed length and position
– Less data then length will be padded with
spaces
– More data than length will be truncated
Random File Example
• Read or written in any order
• Think of the structure being "like a
table"
Lynne
Jim
Tom
Weldon
Buckner
Thumb
803-649-9999
803-652-1111
803-593-1234
Defining the Record Structure
•
•
•
•
Must be done before reading or writing
Use Type/End Type statements
Code in General Declarations
Use fixed length strings
– Specify length in Dim statement
– Ex: Dim strFName as String * 20
• Number variables do not require explicit
length
Type/End Type
Private Type Person
intEmpNum As Integer
strFName
As String * 20
strLName
As String * 30
strPhone
As String * 12
curRate
As Currency
End Type
Dim mudtPersonRecord As Person
Open App.Path & "\Names.dat" For Random as #1
Len=Len (mudtPersonRecord)
Note: mudt prefix for User Defined Type
Open Statement
• Once the random file is opened it can be
used for both input and output unlike
sequential files!
• If you open a file that does not exist, VB
will create it as an empty file
• Once opened, data are available for
read/write operations one record at a time
Reading a Random File
• Open an existing file for Random
• Use Get Statement to read the records
Get Statement
• Usually coded in Form_Load
• If populating a listbox or combo use a Do
Until reach last record to read data
Get #FileNumber, [RecordNumber], RecordName
Get #2, 4, mudtPersonRecord
Get #2, intRecordNumber, mudtPersonRecord
[ ] indicates optional, if RecordNumber is omitted, the next record is read
Put Statement
• Use to place/save data in a random file
• File must already be opened "For Random"
• Place code in mnuFileSave, mnuFileClose
or Form_QueryUnload
• Follow with a Close statement
Put Statement Example
Put #FileNumber, [RecordNumber], RecordName
Put #2, 4, mudtPersonRecord
Put #2, intRecordNumber, mudtPersonRecord
[ ] indicates optional, if RecordNumber is omitted, the next
record is read
Accessing the Fields
• Get and Put operate on an entire record
• Reference the individual fields using dot
notation for the User Defined Type
Accessing the Fields (cont.)
• Read using Get then update textbox
Get #2, 1, mudtPersonRecord
txtLName.Text = mudtPersonRecord.strLName
• Update field from textbox the Write using Put:
mudtPersonRecord.strPhone = txtPhone.Text
Put #2, 1, mudtPersonRecord
LOF Function
• Length of File function returns the size of the file
in bytes
• Use instead of EOF used for sequential files
• To determine the highest record number in the file
divide LOF by the size of one record
LOF(FileNumber)
LOF(3)
intNumRecords=LOF(3)/Len(mudtPersonRecord)
Seek Function
• Returns the current location of the pointer =
the next record in the file to be processed
Seek(FileNumber)
intNextRecord=Seek(3)
Trim Functions
•
•
•
•
Remove extra blank spaces in a string
Trim ==> removes spaces from both ends
LTrim==> removes spaces at left end
RTrim ==> removes spaces at right end
Trim(String)
LTrim(String)
RTrim(String)
txtLName.Text=RTrim(mudtPersonRecord.strLName)
Reading/Retrieving Records –
Sample Code
Sub GetRecord(lngRecNum as Long)
Get #1, lngRecNum, mudtPersonRecord
With mudtPhoneRecord
txtEmpNum.Text = .intEmpNum
txtFName.Text = RTrim(.strFName)
txtLName.Text = Rtrim(.strLName)
txtPhone.Text = Rtrim(.strPhone)
txtRate.Text = .curRate
End With
End Sub
Writing Records –Sample Code
Sub PutRecord(lngRecNum as Long)
With mudtPhoneRecord
.intEmpNum=Val(txtEmpNum.Text)
.strFName = txtFName.Text
.strLName = txtLName.Text
.strPhone = txtPhone.Text
.curRate = Val(txtRate.Text)
End With
Put #1, lngRecNum, mudtPersonRecord
End Sub
Using ListBox to Store Random
File Key Field (p 413)
• When you Get or Put a record you need to
know the record number
• To keep track of record numbers store them
in ItemData property of ListBox
• When user selects a value from the list, read
its ItemData property to retrieve the desired
record
Updating a Random File
• Create routines to
– Edit existing records
– Add new records
– Delete existing records
Edit Existing Records
• Display the record
• Disable all command buttons except Save
and Cancel
• Lock text boxes for fields containing data
you do not want the user to modify
Add New Records
• Clear all text boxes on form
• Disable all command buttons except Save
and Cancel
• When user clicks Save write the new record
at the end of the file
• If using a list box to store record numbers,
update listbox by adding new data and
record number
Delete Existing Records
• A common way to delete a record from a random file is to
mark it as deleted rather than actually remove it
• If you were to remove the record you would have to move
forward all the remaining records and change their record
numbers
• Various methods are used to indicate that a record is to be
treated as "deleted"
– Write a special character in an existing field to indicate deleted
– Include a "Delete Flag or Delete Code" field in the record
description and mark it True to indicate deleted
– “Y” and “N” or “A” and “D” (Yes/No, Active/Deleted)
• If using a list box to store record numbers, update listbox
by deleting the record's associated data and record number
Deleting Existing Records
Private Type udtEmployee
strLastName As String * 15
strFirstName As String * 10
strAddress As String * 50
strEmployeeNumber strEmployeeNumber As Long
strDeleteCode As String * 1
End Type
Private mudtEmployee As udtEmployee
mudtEmployee.strDeleteCode = “D” ‘marks record as deleted
‘when you add records to the collection, only add those without the
“d”
Get #mintFileNumber, , mudtEmployee
With mudtEmployee
If .strDeleteCode <> “D” Then
Add .strLastName, _
.strFirstName, _
.strAddress, _
.strEmployeeNumber, _
Trim(.strEmployeeCode)
End If
End With
Random data files
• You can read/write data in any order
• Open “filename” For Random As #1 LEN=x
• Get #filenumber, [record#], RecordName
• RecordName is a user-defined data type:
Type FullName
strLastName As String * 20
strFirstName As String * 15
End Type
Random data files
• Output: Put
Put #filenumber, [recordnumber], Recordname
• Put #1, iRecordNo, pCustomerRecord
• Get & Put statements read an entire record
• You refer to fields in user-defined structure
by recordname.fieldname
• lstName.AddItem mRec.LastName
• end of file is calculated via record lengths
• LOF function used to locate end of file for a
random file
• LOF(filenumber)
• To find out how many records a file has, divide
the file length by the record length
– iNumberRecords = LOF(1) / Len(mMemberRecord)
• where mMemberRecord is a user defined record
type and the Len function returns the length of a
single record
• The number of records in a random file can be
used to drive a For/Next loop
• Remember, a random file DOES NOT have
an end of file mark in the traditional sense
• Next record number (at end of file) is also
calculated:
– iRecordNumber = LOF(1) /
Len(mMemberRecord) + 1
• The Seek function returns the current
location of the file pointer—which record is
the current record.
• Form: Seek(filenumber)
Random Access Files
• One statement suffices to open a randomaccess file for all purposes: creating,
appending, writing, and reading.
• Suppose a record type has been defined with a
Type block and a record variable, called recVar,
has been declared with a Dim Statement. Then,
after the following statement…
Open “filespec” For Random As #n = Len(recVar)
…is executed, records may be written, read, added,
and changed. The file is referred to by the number
n. Each record will have as many characters as
alotted to each value of recVar.
Comments
• Random Access Files are also known as
direct-access or relative files. Because each
record has the same number of characters,
the computer can calculate
Download