Previously, with the help of Ms. Ophelia Packerschnozz, we created a Personal Address Book using a random access file to store myContacts.txt. If your contact moves, gets a different phone number, or changes the email address, you can edit the fields in contact information by highlighting and making your change. When you leave the information window, your new data will be saved to the record.
Okay, that's cool, but I've added several contacts, changed several contacts, and just played around a bit, so now I have 50 records in the database, and half of them are nonsense. How do I delete a record?
If you're digitally hip with files, you can open myContacts.txt using word pad and make any changes needed. The address book program reads the file every time you open it and the latest changes will be shown. Many users (like me!) are not file experts and will bum up the entire data base if they attempt to edit manually. That's the reason savvy programmers create backups! Ms. Packerschnozz challenged me to add a delete routine to my address book, and I knew I would make errors before I had the program debugged, so I saved a copy of myContacts.txt as masterContacts.txt before starting. If I mess up the database, I can always reload it from masterContacts.txt while I correct the errors in my program.
Every programmer has a method they prefer to use when performing a given task. This is the method I use to delete a particular record from my random access file. If you don't choose to use this method... that's okay, adapt or invent your own method.
We can set all the fields for the record, name$, addr1$, addr2$, etc, to "" in the User Data window, and they will be blanked out, but we will still have a record with blank fields and it will appear in our list of contacts when we run the program. We want to avoid that.
Take off that dunce cap, Welopez! Put on your thinking cap and ask yourself, "What would a Worble do?" Now come up with a plan for the steps you need to accomplish in your code!
My first need is to add a button to the info form. Ms. Packerschnozz had me put the window parameters for User Data into a GOSUB so I don't have to enter the routine in several different places in my code. Presently we have two buttons, Save and Close, so I only need to add another button one time and it will be used whenever my User Data window is opened.
BUTTON #info.btn1, "Save", [saveRec], UL, 60, 320, 60, 25
BUTTON #info.btn3, "Delete", [delRec], UL 160, 320, 60, 25 '< New button
BUTTON #info.btn2, "Close", [closeInfo], UL, 260, 320, 60, 25
The Delete button branches to [delRec], so now all I need to do is write the code for the branch routine.
Remember, a random access file is one continuous string of characters! From beginning to end, there are no line feeds or carriage returns! The only spaces are used to separate words in the data field, or to pad data to fill the field. Using our "Yellow Brick Road" analogy, what we want to do is remove a brick from the road, then move the remaining bricks to close up the empty spot. We don't want to drive down the road and hit a pot-hole! This is my [delRec] routine:
WAIT
'This routine deletes the selected record from the file using ALT+0153
[delRec]
CONFIRM "Are you sure you want to delete this record?"; answer$
IF answer$="no" THEN [closeInfo]
name$="™" 'Marks the record to be deleted
CALL openBook, msg1$, userNum
PUT #book, userNum 'Puts the marked record into myContacts.txt
'===== Create a temporary file
OPEN "newFile.txt" FOR RANDOM AS #temp LEN=189
FIELD #temp,_
30 AS name$,_
30 AS addr1$,_
30 AS addr2$,_
30 AS city$,_
3 AS state$,_
12 AS zip$,_
14 AS phone$,_
40 AS email$
'==== Read all records in the old file
WHILE oldRec"™" THEN 'If not marked to delete, put to temp file
newRec=newRec+1 'Increment counter for the temp file
PUT #temp, newRec 'Put this record in temp file
END IF
WEND
CLOSE #temp 'Close the temp file
CLOSE #book 'Close the address file
oldRec=0 : newRec=0 'Reset the record counters
KILL "myContacts.txt" 'Kill the old address file
NAME "newFile.txt" AS "myContacts.txt" 'Rename the temp file for future use
GOTO [closeInfo]
When the user presses the Delete button, the first thing we're going to do is popup one of those pesky CONFIRM notices. I hate those things, but they serve a good purpose because some users do not understand the meaning of delete. If the user response is "no," the pesky notice goes away, we branch to [closeInfo] which closes the User Data window, then branches to [again] to update the COMBOBOX and open the main program window. So far, so good!
If the user response is "yes," we run the [delRec] routine. The first thing we do is mark this record so the Worble supervising this program run knows we want to discard this record. In my program, I've used ™ (ALT+0153) as the character to identify records for deletion. It is highly unlikely that any name$ in database will begin with ™.
When the record has been marked, I CALL the subroutine to open the database and put the marked record into the file, replacing the present data for that record. Make sure you understand, the only data for this record which has changed is name$! The rest of the entire database remains unchanged in every way.
Now we're going to create a temporary data file called newFile.txt. It will have the same field names and field lengths as myContacts.txt. A WHILE/WEND loop will GET each record from myContacts.txt and check to determine if the file has been marked for deletion, if not, the current record will be written to newFile.txt and then we check the next record, until we have read every record from myContacts.txt.
If, however, the first character of name$ in the old file is ™, we know this record is supposed to be discarded and we do not PUT the record to newFile.txt. Got that? It's the same as removing every pair of shoes from your closet (myContacts) and finding a really grungy pair of shoes. Instead of putting the old shoes into the closet (newFile), we leave them alone. Later the Worble in Charge of Clean Up Your Room! will make our grungy shoes disappear. (Trust me, you'll see how this works in a moment!)
Because we are deleting a record from the database, we know that newFile.txt will have fewer records than oldFile.txt, and we must use separate counters for this routine. oldRec is the counter to GET a record from myContacts.txt, and newRec is the counter for records as they are PUT into newFile.txt.
By the time our WHILE/WEND has finished reading every record in myContacts.txt, every record has been written into newFile.txt, and in the proper order, except the record which has been marked for deletion (the grungy old pair of shoes). When we've finished cleaning our closet, we CLOSE #book and #temp, and reset oldRec=0 and newRec=0, in the event we need to delete another record from the database.
The last thing this branch routine does is to KILL myContacts.txt (Yes, Virginia, you finally get to use the KILL command!) so it no longer exists on your hard drive, then we rename newFile.txt with the NAME "newFile.txt" AS "myContacts.txt" and return to the main window of the program to see the results of all our work.
Now, I'm going to find Don Juan D'Worble and see if I can borrow a quart of addresses from his little black book