Section 8.3. A Case Study: Recording Checks and Deposits


[Page 442 (continued)]

8.3. A Case Study: Recording Checks and Deposits

The purpose of this section is to take you through the design and implementation of a quality program for personal checkbook management. Nothing in this chapter shows off the power of Visual Basic better than the program in this section. That a user-friendly checkbook management program can be written in less than seven pages of code clearly shows Visual Basic's ability to improve the productivity of programmers. It is easy to imagine an entire finance program, similar to programs that have generated millions of dollars of sales, being written in only a few weeks by using Visual Basic!

Design of the Program

Though there are many commercial programs available for personal financial management, they include so many bells and whistles that their original purposeskeeping track of transactions and reporting balanceshave become obscured. The program in this section was designed specifically as a checkbook program. It keeps track of expenditures and deposits and produces a report. Adding a reconciliation feature would be easy enough, although we did not include one.

The program is supposed to be user friendly. Therefore, it showcases many of the techniques and tools available in Visual Basic.

The general design goals for the program included the following abilities:

  • Automatically enter the user's name on each check and deposit slip.

  • Automatically provide the next consecutive check or deposit slip number. (The user can override this feature if necessary.)

  • Automatically provide the date. (Again, this feature can be overridden.)

  • For each check, record the payee, the amount, and optionally a memo.

  • For each deposit slip, record the source, the amount, and optionally a memo.

  • Display the current balance at all times.

  • Produce a report detailing all transactions.


[Page 443]

User Interface

With Visual Basic, we can place a replica of a check or deposit slip on the screen and let the user supply the information as if actually filling out a check or deposit slip. Figure 8.6 shows the form in its check mode. At the bottom of the check are a label and a check box for the current balance and four buttons.

Figure 8.6. Template for entering a check.


The first time the program is run, the user is asked for his or her name, the starting balance, and the numbers of the first check and deposit slip. Suppose the user's name is David Schneider, the starting balance is $1000, and both the first check number and deposit slip number are 1. Figure 8.6 shows the form after the four pieces of input. The upper part of the form looks like a check. The form has a color of light turquoise blue (or cyan) when in check mode. The Date box is automatically set to today's date, but can be altered by the user. The user fills in the payee, amount, and optionally a memo. When the user pushes the Record This Check button, the information is written to a file, the balance is updated, and check number 2 appears.

To record a deposit, the user pushes the Switch to Deposits button. The form then appears as in Figure 8.7. The form's title bar now reads Deposit Slip, the words Pay To change to Source, and the color of the form changes to yellow. Also, in the buttons at the bottom of the slip, the words Check and Deposit are interchanged. A deposit is recorded in much the same way as a check. When the Report button is pushed, a report similar to the one in Figure 8.8 is displayed below the buttons.

Figure 8.7. Template for entering a deposit.
(This item is displayed on page 444 in the print version)


Figure 8.8. Sample transaction report.
(This item is displayed on page 444 in the print version)

Name:David Schneider

Starting balance:$1,000.00

 

5/6/2006

Date

Transaction

Amount

Balance

4/21/2006


Check #: 1
Paid to: Land's End
Memo: shirts

$75.95

$924.05

4/29/2006


Check #: 2
Paid to: Bethesda Coop
Memo: groceries

$125.00

$799.05

5/5/2006


Deposit #: 1
Source: Prentice Hall
Memo: typing expenses

$245.00

$1,044.05

 

Ending Balance: $1,044.05

  


The common design for the check and deposit slip allows one set of controls to be used for both items. The text of the label lblName is set to the user's name, while the text of the label lblToFrom will change back and forth between Pay To and Source.


[Page 444]

Table 8.3 lists the objects and their initial property settings. Because the program will always begin by displaying the next check, all the text for the labels and the BackColor property of the form could have been set at design time. We chose instead to leave these assignments to the SetupCheck method, which is normally used to switch from deposit entry to check entry, but also can be called by the form's Load event procedure to prepare the initial mode (check or deposit) for the form.


[Page 445]

Table 8.3. Objects and initial property settings for the checkbook management program.

Object

Property

Setting

frmAccount

  

lblName

Font Size

10pt

lblNum

Text

#

txtNum

  

lblDate

Text

Date:

txtDate

  

lblToFrom

  

txtToFrom

  

lblAmount

Text

Amount $

txtAmount

  

lblMemo

Text

Memo

txtMemo

  

btnRecord

Text

&Record This Check

btnMode

Text

&Switch to Deposits

btnReport

Text

&Report

btnQuit

Text

&Quit

lblCurBal

Text

Current Balance

txtBalance

ReadOnly

True

lstTransactions

Font

Courier New


The transactions are stored in CSV format in a text file named CHECKBOOK.TXT. The first line of the file contains four entries: the name to appear on the check and deposit slip, the starting balance, the number of the first check, and the number of the first deposit slip. After that, each transaction is recorded on one line as a sequence of eight items: the type of transaction, the contents of txtToFrom, the current balance, the number of the last check, the number of the last deposit slip, the amount of money, the memo, and the date.

Coding the Program

The second row of Figure 8.9 identifies the different events to which the program must respond. Table 8.4 lists the corresponding event procedures and the general procedures they call.

Figure 8.9. Hierarchy chart for checkbook management program.
(This item is displayed on page 446 in the print version)


Table 8.4. Tasks and their procedures.
(This item is displayed on page 446 in the print version)
 

Task

Procedure

1.

Set up text file and form

frmAccount_Load

 

1.1 Create text file

InitializeData

 

1.2 Read text file

InitializeData

 

1.3 Set up check

SetupCheck

 

1.4 Reset input fields

ResetInput

2.

Record check or deposit slip

btnRecord_Click

 

2.1 Validate input

DataValid

 

2.2 Reset input fields

ResetInput

3.

Toggle between check & deposit slip

btnMode_Click

 

3.1 Set up check

SetupCheck

 

3.2 Set up deposit slip

SetupDeposit

 

3.3 Reset input fields

ResetInput

4.

Display transaction report

btnReport_Click

5.

Quit

btnQuit_Click


Let's examine each event procedure:

  1. frmAccount_Load first calls the InitializeData Sub procedure to process the text file. This procedure first looks to see if the file CHECKBOOK.TXT exists. The function IO.File.Exists returns True if the file exists and False otherwise. If CHECKBOOK.TXT does exist, the procedure reads through the entire file to determine all information needed to proceed. If CHECKBOOK.TXT does not exist, the Sub procedure prompts the user for the name to appear on the checks and deposit slips, the starting balance, and the numbers of the first check and deposit slip and then writes these items to the text file. The event procedure calls the SetupCheck Sub procedure next to set the transaction type to Check and sets the appropriate text and background color for a check. The event procedure then calls ResetInput, which initializes all the text boxes.


    [Page 446]

    The InitializeData Sub procedure employs structured exception handling to protect the code from four possible failures: The text file cannot be read, the text file has an invalid format, the user's input cannot be stored in a new file, and the user's input is invalid. In the first two situations, the program works around the exception by creating a new text file. In the third and fourth situation, the program displays an error message and terminates.

  2. btnRecord_Click first confirms that the required fields contain valid entries. This is accomplished by calling the function DataValid. If the value returned is True, then btnRecord_Click updates the current balance, opens the text file in append mode, writes eight pieces of data to the file, and then closes the file. When DataValid returns False, the function itself pops up a message box to tell the user where information is needed or invalid. The user must type in the information and then press the Record button again. Both procedures employ structured exception handling to protect their code from failures. The btnRecord_Click procedure ensures that the new data can be stored in the file. If it can't, then an error message is displayed and the program terminates. The DataValid function ensures that the user's input is valid. If either the amount or number field is not a number, the InvalidCastException is thrown. The Catch block handles this exception by displaying an appropriate message asking the user to reenter the information.


    [Page 447]

  3. btnMode_Click toggles back and forth from a check to a deposit slip. It calls SetupCheck, or its analog SetupDeposit, and then calls ResetInput.

  4. btnReport_Click displays a complete history of all transactions as shown in Figure 8.8. This procedure reads the text file and displays each entry along with the beginning and ending balances. This procedure employs structured exception handling to protect its code from IO failures when the text file cannot be read correctly or has an invalid format.

  5. btnQuit_Click ends the program.

#Region "Class-level variables"   'Text file that stores information   Dim fileName As String = "CHECKBOOK.TXT"   'Variables used for each entry   Dim mode As Boolean        'Mode: check = True, deposit slip = False   Dim nameOnChk As String   'Name to appear on checks   Dim lastCkNum As Integer  'Number of last check written   Dim lastDpNum As Integer  'Number of last deposit slip processed   Dim curBal As Double       'Current balance in account #End Region Private Sub frmAccount_Load(...) Handles MyBase.Load   'Sets the class variables from a new or existing text file   InitializeData()   'Set name and balance labels   lblName.Text = nameOnChk   txtBalance.Text = FormatCurrency(curBal)   'Set the date field to the current date   'The value of CStr(Now) is a string consisting of the current   'date (m/d/yr) followed by a space and the current time. The current   'date is the substring consisting of the characters preceding the space   Dim curDateTime As String = CStr(Now)   txtDate.Text = curDateTime.Substring(0, curDateTime.IndexOf(" "))   'Setup the form for a check   SetupCheck()   'Reset the input fields   ResetInput() End Sub Private Sub InitializeData()   'Reads or creates the file and sets the class-level variables   Dim sr As IO.StreamReader   Dim exists As Boolean = False  'Set to True if text file exists 
[Page 448]
Try 'If text file exists, then read it. If IO.File.Exists(fileName) Then Dim data() As String 'Holds the data read from the file sr = IO.File.OpenText(fileName) 'Split the first line of the text file using the separator data = sr.ReadLine.Split(","c) 'Recover name to appear on checks, current balance, number of 'last check written and number of last deposit slip processed nameOnChk = data(0) curBal = CDbl(data(1)) lastCkNum = CInt(data(2)) lastDpNum = CInt(data(3)) Do While (sr.Peek <> -1) data = sr.ReadLine.Split(","c) curBal = CDbl(data(2)) lastCkNum = CInt(data(3)) lastDpNum = CInt(data(4)) Loop exists = True End If Catch exc As IO.IOException 'Display error message and set flag to False MsgBox("Could not read " & fileName & _ ", will create a new file.", 0, "Error") exists = False Catch 'Display error message and set flag to False MsgBox("File " & fileName & _ " is invalid, will create a new one.", 0, "Error") exists = False Finally 'Close the reader no matter what happens above Try sr.Close() Catch End Try End Try 'If the file doesn't exist, then create one. If Not exists Then Dim sw As IO.StreamWriter Try 'Text file does not exist, so get initial data from user nameOnChk = InputBox("Name to appear on checks:") curBal = CDbl(InputBox("Starting Balance:"))
[Page 449]
'Get numbers of last check and deposit slip lastCkNum = CInt(InputBox("Number of first check:")) - 1 lastDpNum = CInt(InputBox("Number of first deposit slip:")) - 1 'First record in text file records name to appear on checks 'plus initial data for account Dim outputLine() As String = {nameOnChk, CStr(curBal), _ CStr(lastCkNum), CStr(lastDpNum)} sw = IO.File.CreateText(fileName) sw.WriteLine(Join(outputLine, ",")) Catch exc As IO.IOException 'If an exception occurs then display message and quit MsgBox("Cannot store data into file " & fileName & _ ". Program terminating.", 0, "Error") End Catch 'If a number cannot be converted then display message and quit MsgBox("Invalid number. Program terminating.", 0, "Error") End Finally 'Close the writer no matter what happens above Try sw.Close() Catch End Try End Try End If End Sub Private Sub btnRecord_Click(...) Handles btnRecord.Click 'Store the input into the text file Dim amt As Double Dim transType As String 'Only store if all required fields are filled and valid If DataValid() Then amt = CDbl(txtAmount.Text) 'Adjust balance by amount depending on check or deposit slip mode If mode Then curBal = curBal - amt lastCkNum = CInt(txtNum.Text) transType = "Check" Else curBal += amt lastDpNum = CInt(txtNum.Text) transType = "Deposit" End If txtBalance.Text = FormatCurrency(curBal)
[Page 450]
'String array contains info to be stored Dim transOutput() As String = {transType, txtToFrom.Text, _ CStr(curBal), CStr(lastCkNum), CStr(lastDpNum), CStr(amt), _ txtMemo.Text, txtDate.Text} Dim sw As IO.StreamWriter Try 'Append the info to the text file, separated by the separator sw = IO.File.AppendText(fileName) sw.WriteLine(Join(transOutput, ",")) Catch 'Display error message and quit MsgBox("Could not store data into file " & fileName & _ ". Program terminating.", 0, "Error") End Finally 'Close writer no matter what happens above Try sw.Close() Catch End Try End Try 'Reset input controls to blank for next entry ResetInput() End If End Sub Function DataValid() As Boolean 'Returns True if all data are valid, or displays a message if not Dim errorMessage As String 'If one of the four required pieces of information 'is missing, assign its name to errorMessage errorMessage = "" If txtToFrom.Text.Trim = "" Then If mode Then errorMessage = "Pay To" Else errorMessage = "Source" End If txtToFrom.Focus() ElseIf txtAmount.Text.Trim = "" Then errorMessage = "Amount" txtAmount.Focus() End If 'If no errors yet then check syntax of the two numerical fields If errorMessage = "" Then 'Check syntax of the amount field (Double) Try If CDbl(txtAmount.Text) <= 0 Then errorMessage = "The amount must be greater than zero."
[Page 451]
txtAmount.Focus() End If Catch exc As InvalidCastException errorMessage = "The amount " & txtAmount.Text & " is invalid." txtAmount.Focus() End Try Else errorMessage = "The '" & errorMessage & "' field must be filled." End If 'Display error message if available If errorMessage = "" Then 'All required data fields have been filled; recording can proceed Return True Else 'Advise user of invalid data MsgBox(errorMessage & " Please try again.", 0, "") Return False End If End Function Private Sub btnMode_Click(...) Handles btnMode.Click 'Toggle mode between Check and Deposit Slip If mode Then SetupDeposit() Else SetupCheck() End If 'Set fields for next entry ResetInput() End Sub Sub SetupCheck() 'Prepare form for the entry of a check mode = True Me.Text = "Check" 'Sets the title bar of the form lblToFrom.Text = "Pay To" btnRecord.Text = "&Record This Check" btnMode.Text = "&Switch to Deposits" Me.BackColor = Color.Cyan End Sub Sub SetupDeposit() 'Prepare form for the entry of a deposit mode = False Me.Text = "Deposit Slip" 'Sets the title bar of the form lblToFrom.Text = "Source" btnRecord.Text = "&Record This Deposit" btnMode.Text = "&Switch to Checks" Me.BackColor = Color.Yellow End Sub
[Page 452]
Sub ResetInput() 'Reset report listing lstTransactions.Items.Clear() 'Reset all text entry fields except date txtToFrom.Clear() txtAmount.Clear() txtMemo.Clear() If mode Then 'Make txtNum reflect next check number txtNum.Text = CStr(lastCkNum + 1) Else 'Make txtNum reflect next deposit slip number txtNum.Text = CStr(lastDpNum + 1) End If 'Set focus on to/from control for the next entry txtToFrom.Focus() End Sub Private Sub btnReport_Click(...) Handles btnReport.Click 'Display report of all transactions in the text file Dim fmtStr As String = "{0, -18} {1, -35} {2, -12} {3, -12}" Dim data() As String 'Holds the data for each entry Dim balance As String Dim sr As IO.StreamReader Dim curDateTime As String = CStr(Now) curDateTime = curDateTime.Substring(0, curDateTime.IndexOf(" ")) lstTransactions.Items.Clear() Try 'Display headings for the transaction data sr = IO.File.OpenText(fileName) data = sr.ReadLine().Split(","c) balance = data(1) 'Display the name, starting balance, and today's date lstTransactions.Items.Add(String.Format(fmtStr, data(0), _ "Starting Balance: "& FormatCurrency(balance), "", curDateTime)) lstTransactions.Items.Add("") lstTransactions.Items.Add(String.Format(fmtStr, "Date", _ "Transaction", "Amount", "Balance")) fmtStr = "{0,-18} {1,-35} {2,-12:C} {3,-12:C}" 'Loop until the end of file is reached Do While (sr.Peek <> -1) 'Add a blank line in between entries lstTransactions.Items.Add("")
[Page 453]
'Fields are separated by a separator on one line for each entry data = sr.ReadLine.Split(","c) If data(0) = "Check" Then 'The entry is a check lstTransactions.Items.Add(String.Format(fmtStr, data(7), _ "Check #: " & data(3), CDbl(data(5)), CDbl(data(2)))) lstTransactions.Items.Add(String.Format(fmtStr, "", _ "Paid to: " & data(1), "", "")) lstTransactions.Items.Add(String.Format(fmtStr, "", _ "Memo: " & data(6), "", "")) Else 'The entry is a deposit lstTransactions.Items.Add(String.Format(fmtStr, data(7), _ "Deposit #: " & data(4), CDbl(data(5)), CDbl(data(2)))) lstTransactions.Items.Add(String.Format(fmtStr, "", _ "Source: " & data(1), "", "")) lstTransactions.Items.Add(String.Format(fmtStr, "", _ "Memo: " & data(6), "", "")) End If balance = data(2) Loop 'Display the ending balance lstTransactions.Items.Add("") lstTransactions.Items.Add(String.Format(fmtStr, "", _ "Ending Balance: " & FormatCurrency(balance), "", "")) Catch exc As IO.IOException 'Any IO error reading the text file 'Display an error message MsgBox("Could not read file " & fileName & ".", 0, "Error") Catch 'Any non-IO error encountered. The two possibilities are: '1) The entry did not have 8 fields separated by the separator, or '2) The numeric data could not be displayed by FormatCurrency 'Display an error message MsgBox("File " & fileName & " has invalid format.", 0, "Error") Finally 'Close the reader no matter what happens above Try sr.Close() Catch End Try End Try End Sub Private Sub btnQuit_Click(...) Handles btnQuit.Click 'Exit the program End End Sub





An Introduction to Programming Using Visual Basic 2005
Introduction to Programming Using Visual Basic 2005, An (6th Edition)
ISBN: 0130306541
EAN: 2147483647
Year: 2006
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net