Accounts Receivables

This file is part of Synchro-Sette November 1983 . Download the collection to get this file.
Date: November 1983
Type: Program
Platform(s): TS 1000

This is an Accounts Receivable billing management program that stores up to 100 customer billing records in a two-dimensional string array. Each 32-character record in B$(100,32) packs the due date (bytes 1–6), customer name (bytes 7–22), and amount due (bytes 23–31) into fixed-width fields. The program offers a menu-driven interface with seven functions: entering billings, sorting (using a Shell sort at line 2000), displaying with optional hard-copy LPRINT output, searching and editing individual records, deleting records, saving to tape via SAVE, and clearing all data with RUN. A machine code routine is called at line 50 via RAND USR 16514, likely for screen or system initialisation, and POKE 16418 is used to toggle SLOW/FAST mode programmatically. The deletion routine at line 5400 marks a record with a string of “%Z” characters so it sorts to the end of the file, then immediately re-sorts and decrements the record counter.


Program Analysis

Program Structure

The program is organised around a central menu loop at lines 30–300 and a set of subroutine/module blocks dispatched by a computed GOTO 1000*VAL A$. Each major function occupies a distinct line-number block:

LinesFunction
30–300Initialisation, decorated menu screen, and key dispatch
400–410Subroutine: zero-pad a 1-digit string to 2 characters
500–590Subroutine: prompt for and validate the file date (MM/DD/YY)
600–680Subroutine: ensure a numeric string has a decimal point and two decimal places
1000–1510Module 1 – Enter/add billings
2000–2200Module 2 – Sort billings (Shell sort)
3000–3230Module 3 – Display billings, optional LPRINT
4000–4700Module 4 – Search and edit a billing record
5000–5430Module 5 – Search and delete a billing record
6000–6060Module 6 – Save file to tape
7000–7020Module 7 – Clear file (RUN)
9000–9060Subroutine: “Press ENTER to continue” pause
9998–9999SAVE the program itself, then RUN

Data Storage Layout

All records are stored in B$(100,32), a 100-element array of 32-character strings. Each element is treated as a fixed-width packed record with the following field layout:

BytesFieldFormat
1–2Year2-digit YY
3–4Month2-digit MM
5–6Day2-digit DD
7–22Customer nameUp to 16 characters, space-padded
23–31Amount dueRight-aligned numeric string

Storing the date as YYMMDD at the start of the record is deliberate: it means lexicographic sorting of the whole record automatically sorts by date first, then alphabetically by name — which is exactly what the Shell sort at line 2000 exploits by comparing B$(I) directly with B$(L).

Machine Code Usage

Line 50 calls RAND USR 16514, invoking machine code at address 16514 decimal (0x4082). This falls within the ZX81 system variables / display file area. The exact purpose is not documented in the listing but is typically used for a fast screen clear or hardware initialisation routine. Line 60 follows with POKE 16418,0 (system variable CDFLAG at 0x4022), which forces FAST mode at the hardware level, complementing the FAST / SLOW BASIC keywords used throughout.

Shell Sort Implementation

Lines 2005–2200 implement a classic Shell (diminishing-increment) sort on the B$ array. The gap sequence starts at INT(R1/2) and halves each pass until it reaches zero, at which point the array is fully sorted. The comparison B$(I) <= B$(L) at line 2080 operates on the full 32-character record strings, making the YYMMDD date prefix the primary sort key with no extra code required.

Deletion Technique

When a record is deleted (line 5400), the program does not physically remove the entry. Instead it overwrites the record with a string of 32 %Z characters — the highest printable characters in the ZX81 character set. Calling the sort immediately afterwards (line 5410 GOSUB 2005) bubbles this sentinel record to the end of the array. Decrementing R1 at line 5420 then hides it from all subsequent operations.

Key BASIC Idioms

  • Computed GOTO: GOTO 1000*VAL A$ at line 300 dispatches to the correct module (1000, 2000, … 7000) based on the single-key menu selection, avoiding a chain of IF statements.
  • Zero-padding subroutine: Lines 400–410 prepend “0” to any 1-character string, ensuring all date fields are exactly 2 digits wide for correct lexicographic sorting.
  • Decimal-point normalisation subroutine: Lines 600–680 scan for a decimal point; if absent, “.00” is appended; if only one decimal digit is present, a trailing “0” is added. This ensures monetary values display consistently.
  • FAST/SLOW toggling: The program switches aggressively between FAST (no display, faster execution) and SLOW (display updated) modes. SLOW is set just before INPUT statements so the user can see the prompt; FAST is restored immediately after.
  • Inverse-video menu text: Menu item labels at lines 100–200 use the % character (ZX81 inverse space) to create an alternating inverse-space/character pattern, producing a bold highlighted appearance without needing additional PRINT AT calls.

Border Drawing

Lines 80–88 draw a decorative border around the screen. Lines 80–81 print (inverse space + space) pairs across rows 22 and 23 to create a bottom border. Lines 83–88 then print a block graphic character (▖, from A$="\'.") around the full perimeter — top row, bottom row, left column, and right column — using three separate FOR loops.

Bugs and Anomalies

  • Line 3020 typo: PRINT AT 10,0;"THE BILLINGSS UNPAID…" contains a double “SS” in “BILLINGSS”.
  • Y$ single-character check: At line 3004, Y$ is assigned from INKEY$ (always 0 or 1 character). Line 3105 and 3192 then reference Y$(1), which on a ZX81 would cause an error if Y$=""; however the loop at 3004–3005 ensures Y$ is non-empty before proceeding, so in practice Y$(1) is always valid.
  • Line 1340 accepts 3–4 digit year input: The check IF LEN A$<2 OR LEN A$>4 accepts 2, 3, or 4 character year strings. Line 1350 then takes the last 2 characters (A$(LEN A$-1 TO LEN A$)), so a 4-digit year like “1983” correctly yields “83”, but the upper bound of 4 is unnecessarily generous.
  • Line 260 character code range: The check CODE A$<29 OR CODE A$>35 accepts only ZX81 character codes 29–35, which correspond to the digits “1” through “7”. This is the correct approach for numeric key validation on the ZX81.

Content

Appears On

Cassette to accompany the November 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Accounts Receivables

Source Code

   1 REM Y% \.'\. :%KNOT $TAB \@@RND\: TAB \'.RNDTAN 
   2 FAST 
   3 DIM B$(100,32)
   4 LET R1=0
   5 LET N$=""
  30 FAST 
  40 CLS 
  50 RAND USR 16514
  60 POKE 16418,0
  70 FOR N=0 TO 31
  80 PRINT AT 22,N;"% ";AT 23,N;"% "
  81 NEXT N
  82 LET A$="\'."
  83 FOR N=0 TO 31
  84 PRINT AT 0,N;A$;AT 23,N;A$
  85 NEXT N
  86 FOR N=0 TO 23
  87 PRINT AT N,0;A$;AT N,31;A$
  88 NEXT N
 100 PRINT AT 2,5;"% %A%C%C%O%U%N%T%S% % %R%E%C%E%I%V%A%B%L%E% "
 110 PRINT AT 5,2;"%T%O% %E%N%T%E%R% %O%R% %A%D%D% %B%I%L%L%I%N%G%S";TAB 29;"1"
 120 PRINT AT 7,2;"%T%O% %S%O%R%T% %B%I%L%L%I%N%G%S";TAB 29;"2"
 130 PRINT AT 9,2;"%T%O% %D%I%S%P%L%A%Y% %B%I%L%L%I%N%G%S";TAB 29;"3"
 140 PRINT AT 11,2;"%T%O% %S%E%E% %O%R% %E%D%I%T% %F%I%L%E";TAB 29;"4"
 150 PRINT AT 13,2;"%T%O% %D%E%L%E%T%E% %F%R%O%M% %F%I%L%E";TAB 29;"5"
 160 PRINT AT 15,2;"%T%O% %S%A%V%E% %F%I%L%E% %O%N% %T%A%P%E";TAB 29;"6"
 170 PRINT AT 17,2;"%T%O% %C%L%E%A%R% %F%I%L%E";TAB 29;"7"
 200 PRINT AT 21,6;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E";AT 21,6;"ENTER ONE OF ABOVE";AT 21,6;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E"
 210 SLOW 
 250 LET A$=INKEY$
 260 IF A$="" OR CODE A$<29 OR CODE A$>35 THEN GOTO 200
 270 POKE 16418,2
 300 GOTO 1000*VAL A$
 400 IF LEN A$=1 THEN LET A$="0"+A$
 410 RETURN 
 500 PRINT ,,,,,,"WHAT IS TODAY\ 'S DATE?"
 510 PRINT ,,"FORMAT MUST BE AS IN THIS SAMPLE"
 520 PRINT ,,"OCTOBER 3RD, 1982 WOULD BE:"
 530 PRINT "      10/03/82"
 540 PRINT ,,"JANUARY 31ST, 1983 WOULD BE:"
 550 PRINT "      01/31/83"
 555 SLOW 
 560 INPUT N$
 565 FAST 
 570 IF LEN N$<>8 THEN GOTO 555
 580 PRINT ,,
 590 RETURN 
 600 FAST 
 610 FOR I=1 TO LEN A$
 620 IF A$(I)="." THEN GOTO 670
 630 NEXT I
 640 LET A$=A$+".00"
 660 RETURN 
 670 IF I=LEN A$-1 THEN LET A$=A$+"0"
 680 GOTO 660
\n1000 FAST 
\n1010 CLS 
\n1020 IF N$="" THEN GOSUB 500
\n1025 CLS 
\n1026 PRINT ,,,,,,,,,,,,,,"THE FILE DATE/NAME IS ";N$
\n1030 PRINT ,,,,"  ENTER EACH ITEM OF INFORMATION"
\n1040 PRINT "FOR EACH BILLING. IF YOU HAVE NO"
\n1050 PRINT "MORE TO ENTER, JUST PRESS"
\n1060 PRINT "<ENTER> FOR THE CUSTOMER PROMPT."
\n1070 FOR N=R1+1 TO 100
\n1080 SCROLL 
\n1085 SCROLL 
\n1090 PRINT "CUSTOMER\ 'S NAME (16 CHAR. MAX.)?"
\n1095 SLOW 
\n1100 INPUT A$
\n1101 IF A$="" THEN GOTO 1500
\n1102 IF LEN A$>16 THEN GOTO 1095
\n1103 FAST 
\n1104 LET B$(N,7 TO 22)=A$
\n1106 SCROLL 
\n1108 PRINT ,A$
\n1110 SCROLL 
\n1120 PRINT "NUMBER OF MONTH BILL IS DUE?";
\n1130 SLOW 
\n1140 INPUT A$
\n1145 IF LEN A$<1 OR LEN A$>2 THEN GOTO 1140
\n1150 FAST 
\n1160 GOSUB 400
\n1170 PRINT TAB 32-LEN A$;A$
\n1180 LET B$(N,3 TO 4)=A$
\n1190 SCROLL 
\n1200 PRINT "DATE (NUMBER) BILL IS DUE?";
\n1210 SLOW 
\n1220 INPUT A$
\n1230 FAST 
\n1240 IF VAL A$>31 OR VAL A$<1 THEN GOTO 1210
\n1250 GOSUB 400
\n1260 LET B$(N,5 TO 6)=A$
\n1270 PRINT TAB 32-LEN A$;A$
\n1280 SCROLL 
\n1300 PRINT "WHAT IS THE YEAR (2 DIGITS)?";
\n1310 SLOW 
\n1320 INPUT A$
\n1330 FAST 
\n1340 IF LEN A$<2 OR LEN A$>4 THEN GOTO 1310
\n1350 LET A$=A$(LEN A$-1 TO LEN A$)
\n1360 PRINT TAB 28;"19";A$
\n1370 LET B$(N, TO 2)=A$
\n1380 SCROLL 
\n1390 PRINT "WHAT IS THE AMOUNT DUE?";
\n1400 SLOW 
\n1410 INPUT A$
\n1420 IF VAL A$>99999.99 THEN GOTO 1400
\n1430 FAST 
\n1435 GOSUB 600
\n1440 LET B$(N,23 TO 31)=A$
\n1445 PRINT TAB 32-LEN A$;A$
\n1450 SCROLL 
\n1460 PRINT "................................"
\n1470 NEXT N
\n1500 LET R1=N-1
\n1510 GOTO 30
\n2000 GOSUB 2005
\n2002 GOTO 30
\n2005 FAST 
\n2010 LET N=R1
\n2020 LET N=INT N/2
\n2030 IF N=0 THEN GOTO 2200
\n2040 LET J=1
\n2050 LET K=R1-N
\n2060 LET I=J
\n2070 LET L=I+N
\n2080 IF B$(I)<=B$(L) THEN GOTO 2150
\n2090 LET A$=B$(I)
\n2100 LET B$(I)=B$(L)
\n2110 LET B$(L)=A$
\n2120 LET I=I-N
\n2130 IF I<1 THEN GOTO 2150
\n2140 GOTO 2070
\n2150 LET J=J+1
\n2160 IF J>K THEN GOTO 2020
\n2170 GOTO 2060
\n2200 RETURN 
\n3000 FAST 
\n3001 CLS 
\n3002 PRINT ,,"DO YOU WANT HARD COPY?"
\n3003 SLOW 
\n3004 LET Y$=INKEY$
\n3005 IF Y$="" THEN GOTO 3004
\n3008 LET TB=0
\n3010 CLS 
\n3020 PRINT AT 10,0;"THE BILLINGSS UNPAID ARE AS     FOLLOWS:"
\n3030 SCROLL 
\n3035 IF Y$="Y" THEN LPRINT " "
\n3036 IF Y$="Y" THEN LPRINT " "
\n3040 PRINT "DATE DUE   CUSTOMER       AMOUNT"
\n3042 SCROLL 
\n3044 SCROLL 
\n3046 FOR N=1 TO R1
\n3050 PRINT B$(N,3 TO 4);"/";B$(N,5 TO 6);"/";B$(N, TO 2);TAB 10;B$(N,7 TO 22);
\n3051 DIM O$(32)
\n3060 FAST 
\n3070 LET A=VAL B$(N,23 TO 31)
\n3080 LET A$=STR$ A
\n3090 GOSUB 600
\n3095 LET O$=B$(N,3 TO 4)+"/"+B$(N,5 TO 6)+"/"+B$(N, TO 2)+"  "+B$(N,7 TO 22)+O$( TO 6-LEN A$)+A$
\n3100 PRINT TAB 32-LEN A$;A$
\n3105 IF Y$(1)="Y" THEN LPRINT O$
\n3110 LET TB=TB+A
\n3120 SLOW 
\n3130 SCROLL 
\n3140 NEXT N
\n3150 SCROLL 
\n3160 SCROLL 
\n3170 LET A$=STR$ TB
\n3180 GOSUB 600
\n3190 PRINT "TOTAL MONEY OWED IS";TAB 31-LEN A$;"$";A$
\n3192 IF Y$(1)="Y" THEN LPRINT " "
\n3193 DIM O$(32)
\n3196 LET O$="TOTAL MONEY OWED IS"+O$( TO 12-LEN A$)+"$"+A$
\n3197 IF Y$(1)="Y" THEN LPRINT O$
\n3200 SCROLL 
\n3210 SCROLL 
\n3220 GOSUB 9000
\n3230 GOTO 30
\n4000 FAST 
\n4010 CLS 
\n4020 PRINT ,,"WHAT IS THE CUSTOMER\ 'S NAME?"
\n4030 SLOW 
\n4040 INPUT A$
\n4050 FAST 
\n4060 IF LEN A$>16 THEN GOTO 4030
\n4070 CLS 
\n4080 FOR N=1 TO R1
\n4090 IF B$(N,7 TO 6+LEN A$)=A$ THEN GOTO 4200
\n4100 NEXT N
\n4110 PRINT ,,"THE NAME ";A$
\n4120 PRINT "IS NOT IN THE FILE ::::"
\n4130 GOSUB 9000
\n4140 GOTO 30
\n4200 CLS 
\n4210 PRINT ,,B$(N,7 TO 22)
\n4220 PRINT B$(N,3 TO 4);"/";B$(N,5 TO 6);"/";B$(N, TO 2),B$(N,23 TO 31)
\n4230 PRINT ,,,,"IS THIS THE CORRECT BILLING?"
\n4240 SLOW 
\n4250 LET C$=INKEY$
\n4260 IF C$="" THEN GOTO 4250
\n4270 FAST 
\n4280 IF C$="N" THEN GOTO 4100
\n4300 PRINT ,,"CUSTOMER","1","DATE","2","AMOUNT","3","NONE OF ABOVE","4"
\n4310 PRINT ,,,,"WHICH ONE DO YOU WANT TO CHANGE?"
\n4320 SLOW 
\n4330 LET C$=INKEY$
\n4340 IF C$="" OR CODE C$<29 OR CODE C$>32 THEN GOTO 4330
\n4350 FAST 
\n4360 GOTO 4300+(100*VAL C$)
\n4400 PRINT ,,B$(N,7 TO 22)
\n4410 PRINT "CHANGE TO?",
\n4420 SLOW 
\n4430 INPUT A$
\n4440 FAST 
\n4450 IF LEN A$>16 THEN GOTO 4420
\n4460 LET B$(N,7 TO 22)=A$
\n4470 PRINT A$
\n4480 GOSUB 9000
\n4490 GOTO 30
\n4500 PRINT ,,B$(N,3 TO 4);"/";B$(N,5 TO 6);"/";B$(N, TO 2)
\n4510 PRINT "CHANGE TO (SAME FORMAT)?"
\n4520 SLOW 
\n4530 INPUT A$
\n4540 FAST 
\n4550 IF LEN A$<>8 THEN GOTO 4520
\n4560 IF A$(3)<>"/" AND A$(6)<>"/" THEN GOTO 4520
\n4570 LET B$(N, TO 6)=A$(7 TO 8)+A$( TO 2)+A$(4 TO 5)
\n4580 PRINT ,A$
\n4590 GOSUB 9000
\n4595 GOTO 30
\n4600 LET A=VAL B$(N,23 TO 31)
\n4610 LET A$=STR$ A
\n4620 GOSUB 600
\n4630 PRINT ,,A$
\n4640 PRINT "CHANGE TO?";
\n4650 SLOW 
\n4660 INPUT A
\n4670 FAST 
\n4680 IF A>99999.99 THEN GOTO 4650
\n4685 LET A$=STR$ A
\n4690 GOSUB 600
\n4692 LET B$(N,23 TO 31)=A$
\n4694 PRINT TAB 32-LEN A$;A$
\n4696 GOSUB 9000
\n4700 GOTO 30
\n5000 FAST 
\n5010 CLS 
\n5020 PRINT ,,"WHAT IS THE CUSTOMER\ 'S NAME?"
\n5030 SLOW 
\n5040 INPUT A$
\n5050 FAST 
\n5060 IF LEN A$>16 THEN GOTO 5030
\n5070 CLS 
\n5080 FOR N=1 TO R1
\n5090 IF B$(N,7 TO 6+LEN A$)=A$ THEN GOTO 5200
\n5100 NEXT N
\n5110 PRINT ,,"THE NAME ";A$
\n5120 PRINT "IS NOT IN THE FILE ::::"
\n5130 GOSUB 9000
\n5140 GOTO 30
\n5200 CLS 
\n5210 PRINT ,,B$(N,7 TO 22)
\n5220 PRINT B$(N,3 TO 4);"/";B$(N,5 TO 6);"/";B$(N, TO 2),B$(N,23 TO 31)
\n5230 PRINT ,,,,"IS THIS THE CORRECT BILL?"
\n5240 SLOW 
\n5250 LET C$=INKEY$
\n5260 IF C$="" THEN GOTO 5250
\n5270 FAST 
\n5280 IF C$="N" THEN GOTO 5100
\n5300 PRINT ,,"ENTER <Y> IF YOU WANT TO DELETE."
\n5310 SLOW 
\n5320 INPUT A$
\n5330 IF A$="Y" THEN GOTO 5400
\n5340 GOTO 30
\n5400 LET B$(N)="%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z%Z"
\n5410 GOSUB 2005
\n5420 LET R1=R1-1
\n5430 GOTO 30
\n6000 FAST 
\n6010 CLS 
\n6020 PRINT ,,"PREPARE THE DATA TAPE IN THE    RECORDER AND PRESS ENTER :::"
\n6030 SLOW 
\n6040 INPUT A$
\n6050 SAVE N$
\n6060 GOTO 30
\n7000 FAST 
\n7010 CLS 
\n7020 RUN 
\n9000 FAST 
\n9010 PRINT AT 21,0;"PRESS ENTER TO CONTINUE :::"
\n9020 SLOW 
\n9030 INPUT A$
\n9040 FAST 
\n9050 CLS 
\n9060 RETURN 
\n9998 SAVE "ACORE%C"
\n9999 RUN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top