'=========================================================================== ' Subject: PERSONAL EXPENSE RECORDER Date: 11-25-95 (00:00) ' Author: Dave Gjessing Code: QB, QBasic, PDS ' Origin: dgjess@freenet.columbus.oh.us Packet: MISC.ABC '=========================================================================== 'November 25, 1995 'file PER12QB.BAS '"Personal Expense Recorder" 'Copyright Dave Gjessing 1995 ' 'the README file: ' 'PER is intended to be a quick, simple means to record one's day-to-day 'expenses, and to generate handy reports about same. If you are a 'bean-counter type person, you will find it to be completely inadequate, 'and should not waste your time looking at it. If (on the other hand) you 'are a normal person, you just might find it useful. ' 'To use: ' 'While in the directory where the .BAS file resides, type -> qbasic 'Once it is loaded, press SHIFT+F5 ' 'The program will ask for a passcode. Since you have not yet set up a 'code, you simply press ENTER. The main menu will come up. ' 'Press S, to go to the set-up menu. Press 1, and type in your name and a 'passcode. The passcode must be a number. (From here on out you will need 'to type in your passcode when the program starts). ' 'Back at the set-up menu, press 2, to add expense categories. Category 'names may be up to 16 characters long. Some examples: food, shelter, and 'utilities. You also need to provide a two-character category code. For 'the examples above, these might be fo, sh, and ut. You are given a 'chance to accept or re-do each entry. (You may also edit them later on). ' 'Repeat the process for all your expense categories. Don't get carried 'away with creating categories; each entry also has a note attached to 'it. The note is where you should be specific. (I have been getting along 'fine for three months with 15 categories). ' 'Also at the set-up menu, you may fool around with the screen colors. The 'default colors are 1,15. ' 'Once you have set up your categories, return to the main menu. ' 'Press N, to add new expenses. You will be presented with a data file 'name to either accept or reject. The program creates a new file each 'month. The files are named [MMYY]QPER.DAT. If the filename being 'presented to you is the wrong one for the current month, then you need 'to go to DOS and correct your system's date. You may do this from the 'main menu. You may want to add an entry for the month that just ended; 'in that case press ESCAPE, and tell the program the month and year that 'you wish to work with. In most case though, you will simply press ENTER, 'to accept the file shown (the current month's file). Next, you may 'either accept or change the day. If you are recording an expense from a 'few days ago, type in the new day. (Note that you cannot name a new 'month or year at this point; only a new day). In most cases, you will 'again simply press ENTER to accept the current day. Now you have to pick 'a category. (The reasoning behind the two-character category codes will 'now become apparent to you (if there was any doubt)). Pick one, and then 'you must enter in the dollar amount (dollars and cents). You may then 'enter in a short note (up to 40 characters). Next, your entire new entry 'is presented for your approval. Press Y to accept the entry, N do do it 'all over, or Q to quit back to the main menu and forget all about it. ' 'That's all there is to entering expenses. Now to look at what you have 'done... 'At the main menu, press R for reports, and then A, S, or C. A (All 'Expenses for Month) will give you a complete listing of all the line 'items for all categories for a given month. S (Monthly Summary) will do 'a short report; just totals for each category, and the percentage of the 'grand total that each represents. C (Expenses per Category) will show 'all line items in a given month, for a given category. ' 'With all reports, you are offered a chance to save the report to either 'a file or to a printer. If you save to a file you may import the report 'into any wordprocessing program. ' 'Finally, at the main menu you may press E to edit existing records. You 'have a choice of editing Entries or Categories. You can change anything. 'Be aware that if you eliminate a category code, the program will not be 'able to find prior entries (entered under the old code). I would suggest 'writing down all your category codes. You may need them if you screw up 'whilst editing. ' 'Which brings us to crisis prevention. If you forget your passcode, go to 'DOS and delete the file PERSONAL.DAT. This will allow you to get back 'into the program (but you will have to re-do name, passcode, and 'colors). If you trash your category codes while editing, delete the file 'CATEGORY.DAT, and re-create it at the set-up menu, with the information 'that you wrote down earlier. ' ' *** ' 'This computer programing stuff is great fun. I've been at it in earnest 'for about four months now. This program is written in Visual Basic for 'DOS (although it does not use any of the slick features available in 'VBDOS). This particular version has been converted to run under the QBasic 'interperator. ' 'In the original VB version I used the CURRENCY data type for entry.amount. 'QBasic does not recognise that, so it has been changed to DOUBLE. ' 'I hope that the source code might be helpful to other budding nerds like 'myself. After all, I've spent an absurd amount of time working on this 'thing, gleaning bits of stuff from other people's programs. To all from 'whom I have learned stuff, here is something back! I hope it is useful. ' 'dgjess@freenet.columbus.oh.us ' '************************************************************************* 'start of the program: ' DECLARE SUB editentries () DECLARE SUB editcategories () DECLARE SUB line25 () DECLARE SUB sumfile (sumfilename$) DECLARE SUB sumprint () DECLARE SUB selectcolors () DECLARE SUB calcsubtotal () DECLARE SUB sumscreen () DECLARE SUB perhelp (topic$) DECLARE SUB afmscreen () DECLARE SUB background (character%) DECLARE SUB pcfile (pcfilename$) DECLARE SUB drawborder (UpRow%, LeftCol%, BotRow%, RtCol%, bgc%) DECLARE SUB pcprint () DECLARE SUB afmprint () DECLARE SUB afmfile (afmfilename$) DECLARE SUB pcscreen () DECLARE SUB getamount () DECLARE SUB getnote () DECLARE SUB getcategory () DECLARE SUB addcategories () DECLARE SUB getday () DECLARE SUB displaycategories () DECLARE SUB selectfile () DECLARE SUB getpass () DECLARE SUB getpersonaldat () COMMON SHARED bgc% 'background color - user-defined in setup COMMON SHARED fgc% 'forground color - user-defined in setup DEFINT A-Z '************************************************************************ 'Today's notes... (11/26/95) 'I have moved mass quantities of code from module level to sub level, 'where it belongs, and eliminated tons of SHARED statements. 'I need to work on reporting over a range of months. 'I also plan to make the program multi-user - PERSONAL.DAT will hold any 'number of passcodes; the code entered tells the program who's data files 'to access. Of course, the name of the data files will have to be revised. '************************************************************************ 'define the form of the PERSONAL.DAT file record TYPE personal uname AS STRING * 30 'the user's name passcode AS SINGLE 'a numeric passcode bgc AS INTEGER 'background color fgc AS INTEGER 'forground color END TYPE DIM SHARED userid AS personal '************************************************************************ 'define the form of the CATEGORY.DAT file records TYPE category code AS STRING * 2 'two-character code, easy to remember label AS STRING * 16 'full description, tied to the code END TYPE DIM SHARED whatfor AS category '************************************************************************ 'define the form of the expense record file entries TYPE expenrec day AS STRING * 8 'the date of the expense catcode AS STRING * 2 'taken from whatfor.code amount AS DOUBLE 'the money note AS STRING * 40 'optional note END TYPE DIM SHARED entry AS expenrec '************************************************************************ DIM SHARED workfilename AS STRING 'the data file currently in use DIM SHARED screenfull AS INTEGER 'for report subs - a screenfull of stuff DIM SHARED linenum AS INTEGER 'for printing - a pagefull of stuff screenfull = 18 linenum = 0 '************************************************************************ CLS getpass 'very simple passcode "protection" '************************************************************************ 'OK, the user is in and we are up and running... top: CLS COLOR fgc%, bgc% background (176) 'number in parenthesis is ASCII character code 'can be any one you want CALL drawborder(8, 8, 16, 72, bgc%) 'draw the box around the menu COLOR 14, bgc% 'the main menu... LOCATE 8, 23 PRINT " PERSONAL EXPENSE RECORDER .12(QB) " COLOR fgc%, bgc% LOCATE 10, 29 PRINT "N) Enter New Expenses" LOCATE 11, 29 PRINT "R) Generate Reports" LOCATE 12, 29 PRINT "E) Edit Existing Records" LOCATE 13, 29 PRINT "S) Personal Set-Up" LOCATE 14, 29 PRINT "D) Set System Date" LOCATE 16, 29 COLOR 14, bgc% PRINT " (H)elp - ESC to Quit "; CALL line25 DO 'main menu selection process... mainchoice$ = INKEY$ mainchoice$ = UCASE$(mainchoice$) IF mainchoice$ = "N" THEN CLS : GOTO startnewentry IF mainchoice$ = "R" THEN CLS : GOTO reportsmenu IF mainchoice$ = "S" THEN CLS : GOTO setup IF mainchoice$ = "E" THEN CLS : GOTO editing IF mainchoice$ = "H" THEN CLS : CALL perhelp("main"): GOTO top IF mainchoice$ = "D" THEN CLS : SHELL "date": GOTO top IF mainchoice$ = CHR$(27) THEN : CLOSE : COLOR 7, 0: CLS : END '*SYSTEM '* a little QBasic trick: (excuse me if this is common knowlege) 'If the last command in your program is SYSTEM, you will leave the 'QBasic environment automaticaly upon termination. This can be used 'to make it seem like your un-compiled .BAS program runs as a stand-alone 'program, when you start it with a batch file. For instance, write a 'per.bat file, as follows: 'copy con per.bat 'qbasic /run per12qb ' 'Now replace the END statement above with SYSTEM 'Now, at the DOS command line, type per 'The program will load up and run without any further intervention, 'and when you exit it, you will be puked back onto the command line. '"We don't need no stinking compiler!" 'End of trick. LOCATE 25, 63 PRINT TIME$; 'this is not in line25 because it changes constantly LOOP '************************************************************************ startnewentry: 'begin gathering data for new entry selectfile 'chose the data file to write to getday 'get the day within the selected month displaycategories 'show the available expense categories getcategory 'pick one getamount 'get the amount of money (negetive is OK) getnote 'get the note about the expense CLS 'show the data entered, and find out if it is all OK... COLOR fgc%, bgc% CALL drawborder(9, 8, 15, 72, bgc%) 'draw the box around the menu LOCATE 8, 27 COLOR 12, bgc% PRINT " New Entry Confirmation !" LOCATE 10, 12 COLOR fgc%, bgc% PRINT "Record File..: "; workfilename$ LOCATE 11, 12 PRINT "Date.........: "; entry.day LOCATE 12, 12 PRINT "Category.....: "; entry.catcode; " ("; RTRIM$(whatfor.label); ")" LOCATE 13, 12 PRINT USING "Amount.......: $##,###.##"; entry.amount LOCATE 14, 12 PRINT "Note: "; entry.note LOCATE 16, 27 COLOR 14, bgc% PRINT " Is all this OK? (Y/N/Q) " DO newentryconf$ = INKEY$ newentryconf$ = UCASE$(newentryconf$) IF newentryconf$ = "Y" THEN GOTO recordnewentry IF newentryconf$ = "N" THEN GOTO startnewentry 'start over IF newentryconf$ = "Q" THEN GOTO top 'never mind, forget it LOOP 'if it is all OK, then write it to the selected data file... recordnewentry: OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) numrecords = LOF(3) / LEN(entry) newplace = numrecords + 1 PUT #3, newplace, entry CLOSE 3 PRINT COLOR 14, bgc% LOCATE 18, 25 PRINT " New entry has been recorded ": SLEEP 1 COLOR fgc%, bgc% GOTO top '************************************************************************ reportsmenu: CLOSE linenum = 0 'initialize the number of text lines shown CLS 'on the screen to *0* LOCATE 9 CALL drawborder(9, 8, 15, 72, bgc%) 'draw the box around the menu COLOR 14, bgc% LOCATE 9, 20 PRINT " Personal Expense Recorder Reports Menu " COLOR fgc%, bgc% LOCATE 11, 27 PRINT "A) ALL Expenses for Month" LOCATE 12, 27 PRINT "S) Monthly Summary" LOCATE 13, 27 PRINT "C) Expenses per CATEGORY" COLOR 14, bgc% LOCATE 15, 28 PRINT " ESC return to main menu " COLOR fgc%, bgc% CALL line25 DO reportschoice$ = INKEY$ reportschoice$ = UCASE$(reportschoice$) IF reportschoice$ = "A" THEN CLS : CALL selectfile: GOTO allformonth IF reportschoice$ = "S" THEN CLS : CALL selectfile: GOTO monthsummary IF reportschoice$ = "C" THEN CLS : CALL selectfile: GOTO pcscreen IF reportschoice$ = CHR$(27) THEN CLS : GOTO top LOCATE 25, 63 PRINT TIME$; LOOP '************************************************************************** allformonth: afmscreen PRINT COLOR 13, bgc% PRINT " would you like to save this report?" PRINT COLOR fgc%, bgc% PRINT " to save to a file press F" PRINT " to send the report to your printer press P" PRINT " press ENTER to forget all about it" DO afmchoice$ = INKEY$ afmchoice$ = UCASE$(afmchoice$) IF afmchoice$ = "F" THEN GOTO afmfile IF afmchoice$ = "P" THEN GOTO afmprint IF afmchoice$ = CHR$(13) THEN GOTO reportsmenu LOOP afmfile: CLOSE PRINT LINE INPUT "filename: "; afmfilename$ 'half-assed bad filename detection... IF afmfilename$ = "" THEN BEEP: CLS : PRINT "bad filename": SLEEP 2: GOTO reportsmenu afmfile (afmfilename$) CLS CLOSE LOCATE 12, 20 PRINT "report written to "; afmfilename$ SLEEP 2 GOTO reportsmenu afmprint: afmprint GOTO reportsmenu '*************************************************************************** monthsummary: CLOSE PRINT OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 grandtotal# = 0 'initialize the grand total to 0 'figure the grand total... WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 CALL calcsubtotal grandtotal# = grandtotal# + subtotal# NEXT 'finished with category?, OK, on to the next one... WEND 'no more categories?, OK, finish the report sumscreen PRINT COLOR 13, bgc% PRINT " would you like to save this report?" PRINT COLOR fgc%, bgc% PRINT " to save to a file press F" PRINT " to send the report to your printer press P" PRINT " press ENTER to forget all about it" DO sumchoice$ = INKEY$ sumchoice$ = UCASE$(sumchoice$) IF sumchoice$ = "F" THEN GOTO sumfile IF sumchoice$ = "P" THEN GOTO sumprint IF sumchoice$ = CHR$(13) THEN GOTO reportsmenu LOOP GOTO reportsmenu sumfile: CLOSE PRINT LINE INPUT "filename: "; sumfilename$ 'half-assed bad filename detection... IF sumfilename$ = "" THEN BEEP: CLS : PRINT "bad filename": SLEEP 2: GOTO reportsmenu sumfile (sumfilename$) CLS CLOSE LOCATE 12, 20 PRINT "report written to "; sumfilename$ SLEEP 2 GOTO reportsmenu sumprint: sumprint GOTO reportsmenu '*************************************************************************** pcscreen: displaycategories getcategory pcscreen PRINT COLOR 13, bgc% PRINT " would you like to save this report?" PRINT COLOR fgc%, bgc% PRINT " to save to a file press F" PRINT " to send the report to your printer press P" PRINT " press ENTER to forget all about it" DO pcchoice$ = INKEY$ pcchoice$ = UCASE$(pcchoice$) IF pcchoice$ = "F" THEN GOTO pcfile IF pcchoice$ = "P" THEN GOTO pcprint IF pcchoice$ = CHR$(13) THEN GOTO reportsmenu LOOP pcfile: PRINT LINE INPUT "filename: "; pcfilename$ IF pcfilename$ = "" THEN BEEP: CLS : PRINT "bad filename": SLEEP 2: GOTO reportsmenu pcfile (pcfilename$) CLS CLOSE LOCATE 12, 20 PRINT "report written to "; pcfilename$ SLEEP 2 GOTO reportsmenu pcprint: pcprint GOTO reportsmenu '************************************************************************ editing: CLS LOCATE 9 PRINT " Edit what?" PRINT PRINT " (E)ntries" PRINT " (C)ategories" PRINT " (Q)uit" DO editchoice$ = INKEY$ editchoice$ = UCASE$(editchoice$) IF editchoice$ = "E" THEN CLS : GOTO editentries IF editchoice$ = "C" THEN CLS : GOTO editcategories IF editchoice$ = "Q" THEN CLS : GOTO top LOOP editentries: editentries GOTO top editcategories: editcategories GOTO top '************************************************************************ setup: setupmenu: CLS LOCATE 9 PRINT " Personal Expense Recorder Set-Up Menu " PRINT PRINT " 1) set name, passcode" PRINT " 2) add expense categories" PRINT " 3) set colors" PRINT " M) go back to main menu" DO setupchoice$ = INKEY$ setupchoice$ = UCASE$(setupchoice$) IF setupchoice$ = "1" THEN CLS : GOTO personaldat IF setupchoice$ = "2" THEN CLS : GOTO categories IF setupchoice$ = "3" THEN CLS : CALL selectcolors: GOTO setupmenu IF setupchoice$ = "M" THEN CLS : GOTO top LOOP personaldat: getpersonaldat GOTO setupmenu categories: displaycategories PRINT addcategories GOTO setupmenu GOTO top '************************************************************************ END handler: CLS BEEP LOCATE 12, 30 PRINT "check your printer" SLEEP 2 CLOSE 'quick fix to stop termination upon RESUME top 'off-line printer in the reports sections '************************************************************************ 'end of program DEFSNG A-Z SUB addcategories startaddcategories: INPUT "New Category Name "; newlabel$ INPUT "Two-place abbreviation "; newcode$ IF LEN(newcode$) <> 2 THEN BEEP: GOTO startaddcategories newcode$ = UCASE$(newcode$) whatfor.label = newlabel$ whatfor.code = newcode$ PRINT PRINT "New entry confirmation: "; whatfor.code; " "; whatfor.label PRINT PRINT "press ESCAPE to do over, ENTER if OK" DO verifyaddcategorieschoice$ = INKEY$ IF verifyaddcategorieschoice$ = CHR$(13) THEN GOTO endaddcategories IF verifyaddcategorieschoice$ = CHR$(27) THEN GOTO quitwithoutdoinganything LOOP endaddcategories: OPEN "CATEGORY.DAT" FOR RANDOM AS #2 LEN = LEN(whatfor) numrec = LOF(2) / LEN(whatfor) numrec = numrec + 1 PUT #2, numrec, whatfor CLOSE PRINT quitwithoutdoinganything: END SUB DEFINT A-Z SUB afmfile (afmfilename$) OPEN afmfilename$ FOR OUTPUT AS #5 month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ PRINT #5, "===============================================================================" PRINT #5, " All expenses paid by "; userid.uname; " during: "; monthyear$ PRINT #5, "===============================================================================" PRINT #5, "" 'just about the same as the screen version... OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 grandtotal# = 0 WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 GOTO lineitemsafmfile nextlineitemsafmfile: grandtotal# = grandtotal# + subtotal# NEXT WEND PRINT #5, "===============================================================================" PRINT #5, USING " Total...... $ ##,###.## "; grandtotal#; PRINT #5, " Report Date: "; DATE$ PRINT #5, "===============================================================================" GOTO endafmfile lineitemsafmfile: OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) Inumrec = LOF(3) / LEN(entry) Inumrec = Inumrec + 1 Icounter = 1 subtotal# = 0 WHILE Icounter < Inumrec FOR Y = Icounter TO Icounter GET #3, Y, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundafmfile IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundafmfile codefoundafmfile: PRINT #5, " "; entry.day; " "; entry.catcode; PRINT #5, USING " $ ##,###.##"; entry.amount; PRINT #5, " "; entry.note subtotal# = subtotal# + entry.amount codenotfoundafmfile: Icounter = Icounter + 1 NEXT WEND PRINT #5, "" PRINT #5, " Sub Total "; selectedcatcode$; PRINT #5, USING " $ ##,###.## "; subtotal#; selectedcatlabel$ = RTRIM$(selectedcatlabel$) PRINT #5, " ("; selectedcatlabel$; ")" PRINT #5, "-------------------------------------------------------------------------------" CLOSE 3 GOTO nextlineitemsafmfile endafmfile: END SUB SUB afmprint CLOSE month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ ON ERROR GOTO handler LPRINT "===============================================================================" LPRINT " All expenses paid by "; userid.uname; " during: "; monthyear$ LPRINT "===============================================================================" LPRINT linenum = 4 OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 grandtotal# = 0 WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 linenum = linenum + 1 GOTO afmprintlineitems nextafmprintlineitems: IF linenum > screenfull + 40 THEN LPRINT CHR$(12) linenum = 0 ELSE END IF grandtotal# = grandtotal# + subtotal# NEXT WEND LPRINT "===============================================================================" LPRINT USING " Total...... $ ##,###.## "; grandtotal#; LPRINT " Report Date: "; DATE$ LPRINT "===============================================================================" LPRINT CHR$(12) GOTO endafmprint afmprintlineitems: OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) Inumrec = LOF(3) / LEN(entry) Inumrec = Inumrec + 1 Icounter = 1 subtotal# = 0 WHILE Icounter < Inumrec FOR Y = Icounter TO Icounter GET #3, Y, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundafmprint IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundafmprint codefoundafmprint: LPRINT " "; entry.day; " "; entry.catcode; LPRINT USING " $ ##,###.##"; entry.amount; LPRINT " "; entry.note linenum = linenum + 1 subtotal# = subtotal# + entry.amount codenotfoundafmprint: Icounter = Icounter + 1 IF linenum > screenfull + 40 THEN LPRINT CHR$(12) linenum = 0 ELSE END IF NEXT WEND LPRINT LPRINT " Sub Total "; selectedcatcode$; LPRINT USING " $ ##,###.## "; subtotal#; selectedcatlabel$ = RTRIM$(selectedcatlabel$) LPRINT " ("; selectedcatlabel$; ")" LPRINT "-------------------------------------------------------------------------------" linenum = linenum + 3 CLOSE 3 GOTO nextafmprintlineitems endafmprint: END SUB SUB afmscreen CLOSE month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ PRINT "===============================================================================" PRINT " All expenses paid by "; userid.uname; " during: "; monthyear$ PRINT "===============================================================================" PRINT linenum = linenum + 4 'there are four lines right there... CLOSE 'we will now get each category code in turn, and display all the entries 'that are associated with each code... OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 grandtotal# = 0 'initialize the grand total to 0 WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 GOTO afmslineitems 'go and show the line items... nextafmslineitems: IF linenum > screenfull THEN 'if so many lines have been displayed 'on screen then stop and re-set counter PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) COLOR fgc%, bgc% linenum = 0 '(re-set counter) ELSE 'if linenum is not greater than screenfull END IF 'then never mind grandtotal# = grandtotal# + subtotal# NEXT 'finished with category?, OK, on to the next one... WEND 'no more categories?, OK, finish the report IF linenum > screenfull THEN 'if so many lines have been displayed 'on screen then stop and re-set counter PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) COLOR fgc%, bgc% linenum = 0 '(re-set counter) ELSE 'if linenum is not greater than screenfull END IF 'then never mind PRINT "===============================================================================" PRINT USING " Total...... $ ##,###.## "; grandtotal#; PRINT " Report Date: "; DATE$ PRINT "===============================================================================" PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) GOTO endafms afmslineitems: 'go and show the line items... OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) Inumrec = LOF(3) / LEN(entry) Inumrec = Inumrec + 1 Icounter = 1 subtotal# = 0 WHILE Icounter < Inumrec FOR Y = Icounter TO Icounter GET #3, Y, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundapm IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundapm codefoundapm: PRINT " "; entry.day; " "; entry.catcode; PRINT USING " $ ##,###.##"; entry.amount; PRINT " "; entry.note linenum = linenum + 1 subtotal# = subtotal# + entry.amount codenotfoundapm: Icounter = Icounter + 1 IF linenum > screenfull THEN PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) COLOR fgc%, bgc% linenum = 0 END IF NEXT WEND PRINT selectedcatlabel$ = RTRIM$(selectedcatlabel$) PRINT " Sub Total "; selectedcatcode$; PRINT USING " $ ##,###.## "; subtotal#; PRINT " ("; selectedcatlabel$; ")" COLOR 14, bgc% PRINT "-------------------------------------------------------------------------------" COLOR fgc%, bgc% linenum = linenum + 3 CLOSE 3 GOTO nextafmslineitems endafms: END SUB SUB background (character%) FOR X = 1 TO 25 'these statements LOCATE X, 1 'place a background PRINT STRING$(80, CHR$(character%)); 'of ASCII characters NEXT 'on the screen END SUB SUB calcsubtotal SHARED selectedcatcode$ SHARED selectedcatlabel$ SHARED subtotal# OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) numrec = LOF(3) / LEN(entry) numrec = numrec + 1 counter = 1 subtotal# = 0 WHILE counter < numrec FOR X = counter TO counter GET #3, X, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundct IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundct codefoundct: subtotal# = subtotal# + entry.amount codenotfoundct: counter = counter + 1 NEXT WEND CLOSE #3 END SUB DEFSNG A-Z SUB displaycategories OPEN "CATEGORY.DAT" FOR RANDOM AS #2 LEN = LEN(whatfor) numrec = LOF(2) / LEN(whatfor) numrec = numrec + 1 counter = 1 col = 2 COLOR 14, bgc% PRINT " Code Name Code Name Code Name" COLOR fgc%, bgc% PRINT WHILE counter < numrec FOR X = counter TO counter + 1 GET #2, X, whatfor counter = counter + 1 PRINT TAB(col); whatfor.code; " "; whatfor.label; " "; IF col <= 46 THEN col = col + 22 'does three IF col > 46 THEN col = 2: PRINT " " 'columns of categories NEXT WEND CLOSE PRINT END SUB DEFINT A-Z SUB drawborder (UpRow, LeftCol, BotRow, RtCol, bgc%) 'draw the top of the border LOCATE UpRow, LeftCol PRINT CHR$(213) + STRING$(((RtCol - LeftCol) - 1), CHR$(205)) + CHR$(184) 'draw the sides of the border FOR i = (UpRow + 1) TO (BotRow - 1) LOCATE i, LeftCol PRINT CHR$(179) + STRING$(((RtCol - LeftCol) - 1), CHR$(32)) + CHR$(179) NEXT 'draw the bottom of the border LOCATE BotRow, LeftCol PRINT CHR$(212) + STRING$(((RtCol - LeftCol) - 1), CHR$(205)) + CHR$(190) END SUB SUB editcategories CLOSE OPEN "category.dat" FOR RANDOM AS #3 LEN = LEN(whatfor) numrec = LOF(3) / LEN(whatfor) numrec = numrec + 1 counter = 1 linenum = 0 PRINT WHILE counter < numrec FOR X = counter TO counter GET #3, X, whatfor linenum = linenum + 1 IF linenum > screenfull THEN PRINT linenum = 0 COLOR 13, bgc% INPUT " item # to edit + ENTER, or ENTER to continue ", edit% SELECT CASE edit% CASE IS > numrec BEEP CLS : LOCATE 12, 35 PRINT "no such record": SLEEP 2 CLOSE : GOTO endeditcat CASE IS < 0 BEEP CLS : LOCATE 12, 35 PRINT "no such record": SLEEP 2 CLOSE : GOTO endeditcat 'CASE IS = 0 CASE ELSE GOTO ReplaceOldCat END SELECT COLOR fgc%, bgc% END IF PRINT "#"; counter; TAB(7); whatfor.label; " "; whatfor.code counter = counter + 1 NEXT WEND PRINT COLOR 13, bgc% INPUT " item # to edit + ENTER, or ENTER to forget it ", edit% SELECT CASE edit% CASE IS > numrec BEEP CLS : LOCATE 12, 35 PRINT "no such record": SLEEP 2 CLOSE : GOTO endeditcat CASE IS = 0 CLOSE GOTO endeditcat CASE ELSE GOTO ReplaceOldCat END SELECT COLOR fgc%, bgc% ReplaceOldCat: CLS PRINT GET #3, edit%, whatfor LOCATE 20 COLOR 11, bgc% PRINT " OLD -> "; PRINT " "; whatfor.label; " "; whatfor.code LOCATE 1, 1 COLOR fgc%, bgc% INPUT "New Category Name "; newlabel$ INPUT "Two-place abbreviation "; newcode$ IF LEN(newcode$) <> 2 THEN BEEP PRINT "Bad code": SLEEP 1 GOTO endeditcat END IF newcode$ = UCASE$(newcode$) whatfor.label = newlabel$ whatfor.code = newcode$ LOCATE 21 COLOR 14, bgc% PRINT " NEW -> "; PRINT " "; whatfor.label; " "; whatfor.code PRINT COLOR 14, bgc% PRINT " Is all this OK? (Y/N/Q) " DO newentryconf$ = INKEY$ newentryconf$ = UCASE$(newentryconf$) IF newentryconf$ = "Y" THEN GOTO recordeditedcat IF newentryconf$ = "N" THEN CLOSE : GOTO endeditcat 'start over IF newentryconf$ = "Q" THEN CLOSE : GOTO endeditcat 'never mind, forget it LOOP recordeditedcat: PUT #3, edit%, whatfor CLOSE 3 endeditcat: END SUB SUB editentries selectfile OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) numrec = LOF(3) / LEN(entry) numrec = numrec + 1 counter = 1 linenum = 0 PRINT WHILE counter < numrec FOR X = counter TO counter GET #3, X, entry linenum = linenum + 1 IF linenum > screenfull THEN PRINT linenum = 0 COLOR 13, bgc% INPUT " item # to edit + ENTER, or ENTER to continue ", edit% SELECT CASE edit% CASE IS > numrec BEEP CLS : LOCATE 12, 35 PRINT "no such record": SLEEP 2 CLOSE : GOTO endeditentries CASE IS < 0 BEEP CLS : LOCATE 12, 35 PRINT "no such record": SLEEP 2 CLOSE : GOTO endeditentries CASE IS = 0 CASE ELSE GOTO ReplaceOldEntry END SELECT COLOR fgc%, bgc% END IF PRINT "#"; counter; TAB(7); entry.day; " "; entry.catcode; PRINT USING " $ ##,###.##"; entry.amount; PRINT " "; entry.note counter = counter + 1 NEXT WEND PRINT COLOR 13, bgc% INPUT " item # to edit + ENTER, or ENTER to forget it ", edit% SELECT CASE edit% CASE IS > numrec BEEP CLS : LOCATE 12, 35 PRINT "no such record": SLEEP 2 CLOSE : GOTO endeditentries CASE IS = 0 CLOSE GOTO endeditentries END SELECT COLOR fgc%, bgc% ReplaceOldEntry: CLS PRINT GET #3, edit%, entry LOCATE 20 COLOR 11, bgc% PRINT " OLD -> "; PRINT " "; entry.day; " "; entry.catcode; PRINT USING " $ ##,###.##"; entry.amount; PRINT " "; entry.note; LOCATE 1, 1 COLOR fgc%, bgc% getday 'get the day within the selected month getcategory getamount 'get the amount of money (negetive is OK) getnote 'get the note about the expense LOCATE 21 COLOR 14, bgc% PRINT " NEW -> "; PRINT " "; entry.day; " "; entry.catcode; PRINT USING " $ ##,###.##"; entry.amount; PRINT " "; entry.note PRINT COLOR 14, bgc% PRINT " Is all this OK? (Y/N/Q) " DO newentryconf$ = INKEY$ newentryconf$ = UCASE$(newentryconf$) IF newentryconf$ = "Y" THEN GOTO recordeditedentry IF newentryconf$ = "N" THEN CLOSE : GOTO endeditentries 'start over IF newentryconf$ = "Q" THEN CLOSE : GOTO endeditentries 'never mind, forget it LOOP recordeditedentry: PUT #3, edit%, entry CLOSE 3 endeditentries: END SUB DEFSNG A-Z SUB getamount INPUT " Amount............ : $", entry.amount END SUB SUB getcategory SHARED selectedcat$ startgetcategory: PRINT LINE INPUT " Enter Category Code: "; selectedcat$ selectedcat$ = UCASE$(selectedcat$) entry.catcode = selectedcat$ OPEN "CATEGORY.DAT" FOR RANDOM AS #2 LEN = LEN(whatfor) numrec = LOF(2) / LEN(whatfor) totalrec = numrec numrec = numrec + 1 counter = 1 WHILE counter < numrec FOR X = counter TO counter + 1 GET #2, X, whatfor counter = counter + 1 IF whatfor.code = entry.catcode THEN GOTO goodcat IF counter > totalrec THEN CLOSE 2: BEEP: GOTO startgetcategory NEXT WEND goodcat: CLOSE 2 END SUB SUB getday LOCATE 1 month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "-" + year$ thisday$ = MID$(DATE$, 4, 2) thisday$ = month$ + "-" + thisday$ + "-" + year$ PRINT " Date of Expense..."; thisday$; " type new DAY, or ENTER to accept date shown" LOCATE 1, 23 LINE INPUT newday$ IF newday$ = "" THEN GOTO todayisfine IF VAL(newday$) > 31 THEN BEEP: PRINT "invalid day": GOTO trydayagain IF LEN(newday$) <> 2 THEN BEEP: PRINT "invalid day": GOTO trydayagain entry.day = month$ + "-" + newday$ + "-" + year$ GOTO donewithday trydayagain: SLEEP 2 CLS PRINT " Date of Expense..."; thisday$; " type new DAY, or ENTER to accept date shown" LOCATE 1, 23 LINE INPUT newday$ IF newday$ = "" THEN GOTO todayisfine IF VAL(newday$) > 31 THEN BEEP: PRINT "invalid day": GOTO trydayagain IF LEN(newday$) <> 2 THEN BEEP: PRINT "invalid day": GOTO trydayagain entry.day = month$ + "-" + newday$ + "-" + year$ GOTO donewithday todayisfine: entry.day = thisday$ donewithday: END SUB SUB getnote LINE INPUT " Note...............: "; entry.note END SUB SUB getpass passtry = 0 OPEN "PERSONAL.DAT" FOR RANDOM AS #1 LEN = LEN(userid) GET #1, 1, userid 'get the previously recorded passcode: 'passcode from PERSONAL.DAT LOCATE 12, 26 PRINT "passcode please"; COLOR 0, 0 'hide the code being entered INPUT try IF try = userid.passcode THEN CLOSE : GOTO ok IF try <> userid.passcode THEN BEEP: GOTO notOK notOK: passtry = passtry + 1 LOCATE 14, 10 COLOR 7, 0 PRINT "Invalid passcode. If none has been set yet, try ENTER " SLEEP 3 CLS IF passtry < 3 THEN GOTO passcode CLS COLOR 14, 12 LOCATE 12, 20 PRINT " Sorry. (Three strikes and 'yer OUT!) " COLOR 7, 0 CLOSE SLEEP 3: CLS : END ok: 'if passcode is lost, delete the 'file PERSONAL.DAT, and use the ENTER IF userid.bgc = 0 AND userid.fgc = 0 THEN 'if there is no PERSONAL.DAT bgc% = 1: fgc% = 15 'file, then the colors will be '0,0. This changes them to 1,15 ELSE bgc% = userid.bgc 'if there is a PERSONAL.DAT file fgc% = userid.fgc 'then get *those* colors END IF END SUB SUB getpersonaldat startgpd: CLOSE OPEN "PERSONAL.DAT" FOR RANDOM AS #1 LEN = LEN(userid) PRINT "Current User name: "; userid.uname PRINT "Current passcode : "; userid.passcode PRINT INPUT "New User name : ", userid.uname INPUT "New passcode : ", userid.passcode PUT #1, 1, userid CLOSE END SUB DEFINT A-Z SUB line25 LOCATE 25, 1 PRINT STRING$(80, CHR$(219)); COLOR fgc%, bgc% LOCATE 25, 1: PRINT " "; : PRINT CHR$(16); " For: "; userid.uname; : PRINT " "; DATE$; " "; CHR$(17); : PRINT " "; END SUB SUB pcfile (pcfilename$) SHARED selectedcat$ OPEN pcfilename$ FOR OUTPUT AS #5 month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ OPEN "PERSONAL.DAT" FOR RANDOM AS #4 PRINT #5, "===============================================================================" PRINT #5, " Expenses paid by "; userid.uname; " during: "; monthyear$ PRINT #5, " For category "; selectedcat$; " ONLY" PRINT #5, "===============================================================================" CLOSE 4 OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) CLS numrec = LOF(3) / LEN(entry) numrec = numrec + 1 counter = 1 total# = 0 PRINT #5, WHILE counter < numrec FOR X = counter TO counter GET #3, X, entry IF entry.catcode = selectedcat$ THEN GOTO pcfcodefound IF entry.catcode <> selectedcat$ THEN GOTO pcfcodenotfound pcfcodefound: PRINT #5, " "; entry.day; " "; entry.catcode; PRINT #5, USING " $ ##,###.##"; entry.amount; PRINT #5, " "; entry.note total# = total# + entry.amount pcfcodenotfound: counter = counter + 1 NEXT WEND PRINT #5, PRINT #5, "===============================================================================" PRINT #5, " Total for "; selectedcat$; PRINT #5, USING ": $ ##,###.## "; total#; PRINT #5, " Report Date: "; DATE$ PRINT #5, "===============================================================================" CLOSE 3 END SUB SUB pcprint SHARED selectedcat$ month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ OPEN "PERSONAL.DAT" FOR RANDOM AS #4 ON ERROR GOTO handler LPRINT "===============================================================================" LPRINT " Expenses paid by "; userid.uname; " during: "; monthyear$ LPRINT " For category "; selectedcat$; " ONLY" LPRINT "===============================================================================" CLOSE 4 OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) numrec = LOF(3) / LEN(entry) numrec = numrec + 1 counter = 1 total# = 0 linenumber = 0 LPRINT WHILE counter < numrec FOR X = counter TO counter GET #3, X, entry IF entry.catcode = selectedcat$ THEN GOTO pccodefound IF entry.catcode <> selectedcat$ THEN GOTO pccodenotfound pccodefound: LPRINT " "; entry.day; " "; entry.catcode; LPRINT USING " $ ##,###.##"; entry.amount; LPRINT " "; entry.note total# = total# + entry.amount linenumber = linenumber + 1 IF linenumber = 50 THEN linenumber = 0: LPRINT " continued...": LPRINT CHR$(12) pccodenotfound: counter = counter + 1 NEXT WEND LPRINT LPRINT "===============================================================================" LPRINT " Total for "; selectedcat$; LPRINT USING ": $ ##,###.## "; total#; LPRINT " Report Date: "; DATE$ LPRINT "===============================================================================" CLOSE 3 LPRINT CHR$(12) END SUB SUB pcscreen SHARED selectedcat$ OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) CLS month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ PRINT "===============================================================================" PRINT " Expenses paid by "; userid.uname; " during: "; monthyear$ PRINT " For category "; selectedcat$; " ONLY" PRINT "===============================================================================" linenum = 5 numrec = LOF(3) / LEN(entry) numrec = numrec + 1 counter = 1 total# = 0 PRINT WHILE counter < numrec FOR X = counter TO counter GET #3, X, entry IF entry.catcode = selectedcat$ THEN GOTO codefound IF entry.catcode <> selectedcat$ THEN GOTO codenotfound codefound: PRINT " "; entry.day; " "; entry.catcode; PRINT USING " $ ##,###.##"; entry.amount; PRINT " "; entry.note total# = total# + entry.amount linenum = linenum + 1 IF linenum > screenfull THEN PRINT linenum = 0 COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) COLOR fgc%, bgc% END IF codenotfound: counter = counter + 1 NEXT WEND IF linenum > screenfull THEN PRINT linenum = 0 COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) COLOR fgc%, bgc% END IF PRINT PRINT "===============================================================================" PRINT " Total for "; selectedcat$; PRINT USING ": $ ##,###.## "; total#; PRINT " Report Date: "; DATE$ PRINT "===============================================================================" CLOSE 3 PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) END SUB SUB perhelp (topic$) 'Obviously I was originaly planning on having a lot of on-line help text. 'However, it's a pain in the ass writing all this stuff, and I'm tired of 'fooling with it. I'll do the readme file, but that's it! IF topic$ = "main" THEN PRINT PRINT " The Personal Expense Recorder program is intended as an easy-to-use, simple" PRINT " means to record one's day-to-day expenses. This is the QBasic version .12" PRINT PRINT " See the file README.PER for full instructions." PRINT PRINT " Expenses are recorded in monthly data files, according to category. The " PRINT " files are named in the format [MMYY]QPER.DAT. You should back these files up " PRINT " from time to time." PRINT PRINT " The first thing to do is go to Set-Up from the main menu. I would suggest " PRINT " setting up a few test categories, and then running the program through its" PRINT " various functions to get a feel for it. Once you see how it works, go to " PRINT " DOS and delete all the .DAT files, and then start over for real." PRINT PRINT " Thanks for helping to test this program. All future versions will use" PRINT " the same data files as this prototype version, so go ahead and use it." PRINT PRINT " PER is by Dave Gjessing (dgjess@freenet.columbus.oh.us). It is freeware." PRINT " However, any comercial use is prohibited, without prior written consent" PRINT " from the author. Copyright Dave Gjessing 1995. All rights reserved." PRINT COLOR 13, bgc% PRINT " press any key to continue"; : Halt$ = INPUT$(1) 'COLOR fgc%, bgc% END IF END SUB DEFSNG A-Z SUB selectcolors colortop: CLS PRINT "Currently, your colors are:" PRINT "background "; bgc% PRINT "foreground "; fgc% PRINT PRINT "0 - Black 4 - Red 8 - Dark Grey 12 - Light Red" PRINT "1 - Blue 5 - Magenta 9 - Light Blue 13 - Light Magenta" PRINT "2 - Green 6 - Brown 10 - Light Green 14 - Yellow" PRINT "3 - Cyan 7 - White 11 - Light Cyan 15 - Bright White" PRINT PRINT "To see what the various combinations look like, indicate" PRINT "a foreground and a background number below:" PRINT PRINT "background "; INPUT bgc% PRINT PRINT "foreground "; INPUT fgc% PRINT COLOR fgc%, bgc% IF bgc% = fgc% THEN 'if user screws up, set colors to default BEEP: CLS fgc% = 15 bgc% = 1 COLOR fgc%, bgc% PRINT "You are trying to make the BG the same as the FG! - that's no good." GOTO colortop END IF userid.fgc = fgc% userid.bgc = bgc% OPEN "PERSONAL.DAT" FOR RANDOM AS #1 LEN = LEN(userid) PUT #1, 1, userid CLOSE END SUB SUB selectfile startselectfile: CLS current$ = DATE$ month$ = LEFT$(current$, 2) year$ = RIGHT$(current$, 2) currentfileid$ = month$ + year$ currentfilename$ = currentfileid$ + "QPER.DAT" CALL drawborder(9, 8, 15, 72, bgc%) 'draw the box around the menu LOCATE 10, 20 PRINT "The current month's data file would be... " COLOR 14, bgc% LOCATE 12, 33 PRINT currentfilename$ COLOR fgc%, bgc% LOCATE 14, 13 PRINT "ESCAPE to name another file, ENTER to accept this file" DO selectfilechoice$ = INKEY$ IF selectfilechoice$ = CHR$(13) THEN GOTO current IF selectfilechoice$ = CHR$(27) THEN GOTO other LOOP current: workfilename$ = currentfilename$ GOTO endselectfile other: PRINT INPUT " month and year you want (MMYY) "; otherfile$ IF LEN(otherfile$) <> 4 THEN BEEP: CLS : GOTO startselectfile proposedmonth$ = LEFT$(otherfile$, 2) proposedmonth = VAL(proposedmonth$) IF proposedmonth > 12 THEN BEEP: CLS : GOTO startselectfile workfilename$ = otherfile$ + "QPER.DAT" verifyselectfile: CLS LOCATE 9 PRINT " You have picked..." PRINT COLOR 14, bgc% PRINT " "; workfilename$ PRINT COLOR fgc%, bgc% PRINT " as the working file." PRINT PRINT " ESCAPE to do over, ENTER if OK" DO verifyselectfilechoice$ = INKEY$ IF verifyselectfilechoice$ = CHR$(13) THEN GOTO endselectfile IF verifyselectfilechoice$ = CHR$(27) THEN GOTO startselectfile LOOP endselectfile: CLS END SUB DEFINT A-Z SUB sumfile (sumfilename$) CLOSE SHARED grandtotal# month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ OPEN sumfilename$ FOR OUTPUT AS #5 PRINT #5, "===============================================================================" PRINT #5, " Summary of expenses paid by "; userid.uname; " during: "; monthyear$ PRINT #5, "===============================================================================" PRINT #5, "" OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 GOTO lineitemssumfile nextlineitemssumfile: NEXT 'finished with category?, OK, on to the next one... WEND 'no more categories?, OK, finish the report PRINT #5, "" PRINT #5, "===============================================================================" PRINT #5, USING " Total...... $ ##,###.## "; grandtotal#; PRINT #5, " Report Date: "; DATE$ PRINT #5, "===============================================================================" GOTO endsumfile lineitemssumfile: selectedcatlabel$ = RTRIM$(selectedcatlabel$) OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) Inumrec = LOF(3) / LEN(entry) Inumrec = Inumrec + 1 Icounter = 1 subtotal# = 0 WHILE Icounter < Inumrec FOR Y = Icounter TO Icounter GET #3, Y, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundsumfile IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundsumfile codefoundsumfile: subtotal# = subtotal# + entry.amount codenotfoundsumfile: Icounter = Icounter + 1 NEXT WEND percentage# = subtotal# / grandtotal# percentage# = percentage# * 100 selectedcatlabel$ = RTRIM$(selectedcatlabel$) pad = 16 - LEN(selectedcatlabel$) + 1 PRINT #5, " "; selectedcatlabel$; STRING$(pad, CHR$(46)); " |"; PRINT #5, USING " ###.## %"; percentage#; PRINT #5, " | "; STRING$(33, CHR$(46)); PRINT #5, USING " $ ##,###.## "; subtotal# CLOSE 3 GOTO nextlineitemssumfile endsumfile: END SUB SUB sumprint CLOSE SHARED grandtotal# ON ERROR GOTO handler month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ LPRINT "===============================================================================" LPRINT " Summary of expenses paid by "; userid.uname; " during: "; monthyear$ LPRINT "===============================================================================" LPRINT CLOSE OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 GOTO lineitemssumprint nextlineitemssumprint: linenum = linenum + 1 NEXT 'finished with category?, OK, on to the next one... WEND 'no more categories?, OK, finish the report LPRINT LPRINT "===============================================================================" LPRINT USING " Total...... $ ##,###.## "; grandtotal#; LPRINT " Report Date: "; DATE$ LPRINT "===============================================================================" LPRINT CHR$(12) GOTO endsumprint lineitemssumprint: selectedcatlabel$ = RTRIM$(selectedcatlabel$) OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) Inumrec = LOF(3) / LEN(entry) Inumrec = Inumrec + 1 Icounter = 1 subtotal# = 0 WHILE Icounter < Inumrec FOR Y = Icounter TO Icounter GET #3, Y, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundsumprint IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundsumprint codefoundsumprint: subtotal# = subtotal# + entry.amount codenotfoundsumprint: Icounter = Icounter + 1 NEXT WEND percentage# = subtotal# / grandtotal# percentage# = percentage# * 100 selectedcatlabel$ = RTRIM$(selectedcatlabel$) pad = 16 - LEN(selectedcatlabel$) + 1 LPRINT " "; selectedcatlabel$; STRING$(pad, CHR$(46)); " |"; LPRINT USING " ###.## %"; percentage#; LPRINT " | "; STRING$(33, CHR$(46)); LPRINT USING " $ ##,###.## "; subtotal# CLOSE 3 GOTO nextlineitemssumprint endsumprint: END SUB SUB sumscreen CLOSE SHARED grandtotal# month$ = LEFT$(workfilename$, 2) year$ = MID$(workfilename$, 3, 2) monthyear$ = month$ + "/" + year$ CLOSE PRINT "===============================================================================" PRINT " Summary of expenses paid by "; userid.uname; " during: "; monthyear$ PRINT "===============================================================================" PRINT linenum = 4 'there are four lines right there... CLOSE OPEN "CATEGORY.DAT" FOR RANDOM AS #4 LEN = LEN(whatfor) numrec = LOF(4) / LEN(whatfor) numrec = numrec + 1 counter = 1 WHILE counter < numrec FOR X = counter TO counter GET #4, X, whatfor selectedcatcode$ = whatfor.code selectedcatlabel$ = whatfor.label counter = counter + 1 GOTO lineitemssumscreen nextlineitemssumscreen: linenum = linenum + 1 IF linenum > screenfull THEN PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) COLOR fgc%, bgc% linenum = 0 '(re-set counter) ELSE 'if linenum is not greater than screenfull END IF 'then never mind NEXT 'finished with category?, OK, on to the next one... WEND 'no more categories?, OK, finish the report IF linenum > screenfull THEN SLEEP PRINT PRINT "===============================================================================" PRINT USING " Total...... $ ##,###.## "; grandtotal#; PRINT " Report Date: "; DATE$ PRINT "===============================================================================" PRINT COLOR 13, bgc% PRINT " press any key to continue": Halt$ = INPUT$(1) GOTO endsumscreen lineitemssumscreen: selectedcatlabel$ = RTRIM$(selectedcatlabel$) OPEN workfilename FOR RANDOM AS #3 LEN = LEN(entry) Inumrec = LOF(3) / LEN(entry) Inumrec = Inumrec + 1 Icounter = 1 subtotal# = 0 WHILE Icounter < Inumrec FOR Y = Icounter TO Icounter GET #3, Y, entry IF entry.catcode = selectedcatcode$ THEN GOTO codefoundsum IF entry.catcode <> selectedcatcode$ THEN GOTO codenotfoundsum codefoundsum: subtotal# = subtotal# + entry.amount codenotfoundsum: Icounter = Icounter + 1 NEXT WEND percentage# = subtotal# / grandtotal# percentage# = percentage# * 100 selectedcatlabel$ = RTRIM$(selectedcatlabel$) pad = 16 - LEN(selectedcatlabel$) + 1 PRINT " "; selectedcatlabel$; STRING$(pad, CHR$(46)); " |"; PRINT USING " ###.## %"; percentage#; PRINT " | "; STRING$(33, CHR$(46)); PRINT USING " $ ##,###.## "; subtotal# CLOSE 3 GOTO nextlineitemssumscreen: endsumscreen: END SUB