This program implements a general ledger accounting system, providing functions for creating ledger cards, entering transactions, generating trial balances, and producing profit-and-loss statements. Up to 30 accounts are supported, each holding up to 10 transaction entries stored in parallel arrays (date in D$, reference in E$, debit in F, credit in G), with running balances maintained in H(). The currency formatting subroutine at line 4000 uses STR$ with rounding to two decimal places, and includes fixes for leading decimal points such as “.50” becoming “0.50”. A year-end transfer routine at line 7000 clears transaction arrays and posts the closing balance as a brought-forward entry, resetting each card to a single opening entry. Data is saved to tape via a STOP/CONT pattern that allows the user to prepare the recorder before executing the SAVE command.
Program Analysis
Program Structure
The program is organised as a menu-driven shell (lines 10–60) dispatching to six functional modules via GOTO. The main menu loop runs from line 10 and re-enters itself after most operations via GOTO 10.
- Lines 10–60: Main menu and dispatcher
- Lines 100–500: Register initialisation (option 0) — DIM statements and variable resets, year entry
- Lines 1001–1050: Open new ledger card (option 1)
- Lines 2005–2610: Account search and transaction entry (option 2)
- Lines 3000–3980: Trial balance and P+L statement (option 3)
- Lines 4000–4215: Subroutines — currency formatting (4000), display transaction row (4100), display balance (4200)
- Lines 6000–6003: Save to tape (option 4)
- Lines 7002–7150: Year-end account transfer (option 5)
Data Structures
The program uses parallel arrays to simulate a record structure. Each account occupies a fixed block of 10 slots in the transaction arrays. Account C maps to transaction indices (C*10)+1 through C*10+10.
| Array | Size | Purpose |
|---|---|---|
A$(30,10) | 30 × 10 chars | Account names (10-char limit) |
C(30) | 30 | Declared but not actively used (balance stored in H) |
D$(310,5) | 310 × 5 chars | Transaction date |
E$(310,4) | 310 × 4 chars | Transaction reference |
F(310) | 310 | Debit amounts |
G(310) | 310 | Credit amounts |
H(30) | 30 | Running account balance (debit positive, credit negative) |
N(30) | 30 | Next free transaction index per account |
T(30) | 30 | Account type: 0=balance sheet, 1=P+L |
B(1), J(1), K(1) | 1 | Scalar placeholders (single-element arrays) |
The scalar variables B, J, K, etc. are used independently of the single-element arrays of the same letter — a common Sinclair BASIC technique where DIM B(1) does not affect the plain variable B.
Currency Formatting Subroutine (line 4000)
The subroutine at line 4000 converts numeric value P into a formatted two-decimal-place string P$. It handles three edge cases:
- Values between 0 and 1 where
STR$produces".5"— prefixed with"0"at line 4010. - Negative values between -1 and 0 where
STR$produces"-."— corrected to"-0..."at line 4020. - Integers with no decimal point —
".00"appended at line 4060. - Values with only one decimal digit — a trailing
"0"appended at line 4070.
Rounding is achieved via INT (P*100+.5)/100, which is the standard Sinclair BASIC two-decimal rounding idiom.
Transaction Entry Flow
Entry begins at line 2100. The variable X holds C*10, the base offset for the current account’s transaction block. N steps from X+1 up to a maximum of X+10. For each transaction, date (D$), reference (E$), debit (F), and credit (G) are collected sequentially. The running balance H(C) is updated immediately: debits add, credits subtract. A three-option sub-menu (continue, error correction, return) appears after each entry.
The error-correction path (option 2, line 2550) allows the user to reverse the last debit or credit entry by decrementing N and adjusting H(C), then re-entering from line 2320 (which is line 2325 effectively — a minor label off-by-one, jumping into the middle of the entry loop).
Trial Balance (lines 3000–3200)
The trial balance iterates over accounts 1 to O (where O holds the count of opened accounts). Positive balances are accumulated in R (debits) and negative balances in S (credits, stored as negative). The display uses TAB with LEN P$ subtracted to right-align figures in debit (column 21) and credit (column 32) positions. If the account count exceeds 14, the balance is carried forward across two screen pages using STOP/CONT as a pause mechanism (lines 3099 and 3205).
The error line at 3200 prints the difference between debit and credit totals. Ideally this should be zero; the label “ERROR:” is used to indicate any imbalance.
Profit and Loss Statement (lines 3500–3980)
P+L only processes accounts where T(C)=1. Income accounts (credit balance, i.e. H(C)<1) accumulate in S; expense accounts (H(C)>1) in R. The net result is computed as (R+S)*-1 — a negative result indicates a loss, as noted on screen.
Year-End Transfer (lines 7002–7150)
The transfer routine clears the 10-entry transaction block for the chosen account, then writes a single brought-forward ("BFD.") entry using the closing balance. If the balance is positive it is placed in the debit column (F(N)); if negative, in the credit column (G(N)). The account pointer N(C) is reset to the first slot.
Tape Save (lines 6000–6003)
Saving uses the STOP/CONT idiom: execution halts at line 6001, the user starts the tape recorder, then continues. The SAVE "G/%L" at line 6002 saves the program. After saving, GOTO 5 targets a non-existent line, which causes execution to fall through to line 8 (the next line in the program), effectively restarting cleanly from the copyright REM.
Bugs and Anomalies
- Lines 200–235 use plain variables (
LET B=0,LET C=0, etc.) to initialise what are intended to be array elements, but without subscripts these reset the scalar variables only, not the array contents. The arrays themselves are left at their default zero/space values fromDIM, so this is harmless in practice on first run but would not correctly re-initialise arrays if option 0 were selected after data entry. - The trial balance loop at line 3065 uses
FOR C=U TO C, where both the loop variable and the limit share the nameC. The limit is evaluated once at loop start, so this works correctly, but it is unusual style. - Line 3097 checks
IF C>=O THEN GOTO 3200to skip the page-break prompt if all accounts fit on one page, but the condition should perhaps beC>14or similar; the current logic depends on the loop having incrementedCpastOnaturally. - The P+L thresholds at lines 3620 and 3630 use
>1and<1rather than>0and<0, meaning accounts with a balance of exactly 1 or -1 are excluded from both totals. - Line 4100 is entered via
GOSUB 4100but the subroutine body begins at line 4106, with lines 4100–4105 absent. Execution falls through from 4100 to 4106 correctly since there are no intervening lines, but theGOSUBtarget is effectively line 4106. - Line 7080 uses
IF H(C)<1(should be<0) for the credit brought-forward test, meaning a balance of exactly 0 would write a zero to the credit column rather than being skipped.
Content
Source Code
5 REM "G/L" 16-105 (BY NO.)
8 REM COPYRIGHT M.SIEDER 1983
10 CLS
30 PRINT AT 1,10;"GENERAL LEDGER";AT 2,0;Y$
40 PRINT AT 3,2;"ENTER LEAD NO.FOR OPERATION";
41 PRINT AT 5,3;"0)CLEAR REGISTERS";AT 6,3;"1)OPEN NEW LEDGER CARD";AT 7,3;"2)SEARCH FOR ACCT.+ENTRIES";AT 8,3;"3)TRIAL BAL. AND P+L STATEMT.";AT 9,3;"4) SAVE ON TAPE";AT 10,3;"5)TRANSFER OF ACCT.BAL."
45 INPUT I
46 CLS
50 IF I=0 THEN GOTO 100
51 IF I=1 THEN GOTO 1000
52 IF I=2 THEN GOTO 2000
53 IF I=3 THEN GOTO 3000
56 IF I=4 THEN GOTO 6000
58 IF I=5 THEN GOTO 7000
60 IF I>5 THEN GOTO 10
101 DIM B(1)
105 DIM A$(30,10)
110 DIM C(30)
115 DIM D$(310,5)
120 DIM E$(310,4)
125 DIM F(310)
130 DIM G(310)
135 DIM H(30)
140 DIM J(1)
145 DIM K(1)
150 DIM N(310)
155 DIM T(30)
200 LET B=0
202 LET C=0
205 LET F=0
210 LET N=0
212 LET O=0
215 LET G=0
220 LET H=0
225 LET J=0
230 LET K=0
235 LET T=0
240 LET Y$="--------------------------------"
300 PRINT AT 10,11;"ENTER YEAR"
310 INPUT B
320 CLS
500 GOTO 10
1001 LET C=O
1005 LET C=C+1
1010 IF C>30 THEN GOTO 2600
1016 LET O=C
1020 PRINT AT 8,4;"ACCT.NO.";C;AT 9,4;"ENTER""0""FOR BAL.SHEET ACCT.";AT 10,4;"ENTER""1""FOR P+L ACCT."
1021 INPUT T(C)
1022 CLS
1030 PRINT AT 10,4;"ENTER ACCT.NAME";" NO.";T(C);"-";C;AT 12,6;"( 10 DIGITS ONLY )"
1040 INPUT A$(C)
1045 CLS
1050 GOTO 2100
2005 PRINT AT 9,5;"ENTER NO. OF ACCOUNT"
2010 INPUT I
2015 LET C=I
2035 GOTO 2100
2065 CLS
2070 GOTO 10
2100 CLS
2105 LET X=C*10
2110 LET N=X+1
2200 PRINT AT 1,0;"NO.";T(C);"-";C;AT 1,9;A$(C);AT 1,25;"YR:";B
2205 PRINT AT 2,0;Y$
2210 PRINT AT 3,0;"NO.";AT 3,4;"DATE";AT 3,10;"REF.";AT 3,16;"DEBIT";AT 3,25;"CREDIT"
2215 PRINT AT 4,0;Y$
2265 PRINT AT 17,12;"PRES.BAL.:"
2270 GOSUB 4200
2300 FOR N=(X+1) TO N(C)
2305 IF N>10+X THEN GOTO 2500
2306 GOSUB 4100
2310 IF N=N(C) THEN GOTO 2325
2315 NEXT N
2325 IF N>10+X THEN GOTO 2500
2330 PRINT AT 21,19;"DATE ";N
2335 INPUT D$(N)
2340 PRINT AT 21,19;"REF. ";N
2345 INPUT E$(N)
2350 PRINT AT 21,19;"DEBIT ";N
2352 INPUT F(N)
2358 LET H(C)=H(C)+F(N)
2360 PRINT AT 21,19;"CREDIT ";N
2362 INPUT G(N)
2368 LET H(C)=H(C)-G(N)
2370 PRINT AT 17,22;" ";AT 21,19;" "
2380 GOSUB 4100
2382 GOSUB 4200
2385 LET N=N+1
2390 LET N(C)=N
2400 IF N<=10+X THEN GOTO 2520
2500 IF N>10+X THEN PRINT AT 19,6;"FULL ACCT.CARD";AT 20,4;"ENTER""1"" TO RETURN";AT 21,4;"ENTER""0"" TO COPY "
2505 INPUT I
2507 IF I<1 THEN COPY
2508 GOTO 10
2510 IF I>=1 THEN GOTO 10
2520 PRINT AT 19,20;"1)CONT.ENT.";AT 20,20;"2)ERROR ";AT 21,20;"3)RETURN "
2525 INPUT I
2530 PRINT AT 19,20;" ";AT 20,20;" ";AT 21,20;" "
2535 IF I=1 THEN GOTO 2320
2536 IF I=2 THEN GOTO 2550
2537 LET C=O
2538 IF I>2 THEN GOTO 10
2550 PRINT AT 19,20;"1)DEBIT ";AT 20,20;"2)CREDIT"
2555 INPUT I
2560 PRINT AT 19,20;" ";AT 20,20;" "
2565 IF I=1 THEN LET H(C)=H(C)-F(N-1)
2570 IF I=2 THEN LET H(C)=H(C)+G(N-1)
2575 IF I<3 THEN LET N=N-1
2580 IF I<3 THEN GOTO 2320
2600 PRINT AT 11,2;"OUT OF LEDGER CARDS"
2605 PAUSE 50
2610 GOTO 10
3000 REM "TRIAL BALANCE"
3005 PRINT AT 10,2;"ENTER DATE OF TRIAL BALANCE"
3010 INPUT I$
3015 CLS
3020 PRINT AT 1,1;"TRIAL BALANCE AS OF: ";I$
3025 PRINT Y$
3030 PRINT AT 3,0;"NO.";AT 3,3;"ACCOUNT";AT 3,15;"DEBITS";AT 3,23;"CREDITS"
3035 PRINT Y$
3053 LET R=0
3055 LET S=0
3060 LET C=14
3061 LET U=1
3065 FOR C=U TO C
3067 IF H(C)<0 THEN GOTO 3080
3070 LET R=R+H(C)
3071 LET P=H(C)
3072 GOSUB 4000
3074 PRINT TAB 0;C;TAB 3;A$(C);TAB 21-LEN P$;P$
3075 GOTO 3090
3080 LET S=S-H(C)
3081 LET P=H(C)
3082 GOSUB 4000
3085 PRINT TAB 0;C;TAB 3;A$(C);TAB 32-LEN P$;P$
3090 NEXT C
3092 PRINT Y$
3093 LET R$=STR$ R
3094 LET S$=STR$ S
3096 PRINT TAB 0;"TOTALS:";TAB 21-LEN R$;R$;TAB 32-LEN S$;S$
3097 IF C>=O THEN GOTO 3200
3098 PRINT AT 21,0;"ENTER"" CONT "" OR "" COPY """
3099 STOP
3100 LET C=O
3101 LET U=15
3105 CLS
3106 PRINT TAB 2;"BFD.";TAB 21-LEN R$;R$;TAB 32-LEN S$;S$
3110 GOTO 3065
3200 PRINT TAB 0;"ERROR: ";INT ((R-S)*100+.5)/100
3202 LET U=1
3203 LET C=O
3204 PRINT AT 21,0;"ENTER"" CONT "" OR "" COPY """
3205 STOP
3208 PRINT AT 9,4;"ENTER 1)FOR DAILY P+L";AT 10,10;"2)FOR RETURN"
3210 INPUT I
3215 CLS
3220 IF I>1 THEN GOTO 10
3225 IF I=0 THEN GOTO 10
3230 IF I=1 THEN GOTO 3500
3500 PRINT AT 2,2;"P+L AS OF: ";I$;AT 3,0;Y$
3555 LET R=0
3560 LET S=0
3600 FOR C=1 TO O
3610 IF T(C)=0 THEN GOTO 3800
3615 IF T(C)=1 THEN GOTO 3620
3620 IF H(C)>1 THEN LET R=R+H(C)
3630 IF H(C)<1 THEN LET S=S+H(C)
3800 NEXT C
3810 LET P=-S
3815 GOSUB 4000
3820 PRINT AT 4,4;"REVENUES: ";AT 4,32-LEN P$;P$
3825 LET P=-R
3830 GOSUB 4000
3835 PRINT AT 6,4;"EXPENSES: ";AT 6,32-LEN P$;P$
3920 PRINT AT 7,0;Y$
3924 LET P=(R+S)*-1
3926 GOSUB 4000
3930 PRINT AT 8,4;"RESULT: ";AT 8,32-LEN P$;P$
3940 PRINT AT 10,4;"( - MEANS LOSS)"
3950 PRINT AT 20,10;" INPUT ""1"" TO RETURN ";AT 21,10;" INPUT ""0"" TO COPY "
3960 INPUT I
3974 IF I<1 THEN COPY
3975 GOTO 10
3980 IF I>=1 THEN GOTO 10
4000 LET P$=STR$ (INT (P*100+.5)/100)
4010 IF P$(1)="." THEN LET P$="0"+P$
4020 IF LEN P$>1 THEN IF P$(1 TO 2)="-." THEN LET P$="-0"+P$(2 TO )
4030 FOR L=1 TO LEN P$
4040 IF P$(L)="." THEN GOTO 4070
4050 NEXT L
4060 LET P$=P$+".00"
4070 IF L=LEN P$-1 THEN LET P$=P$+"0"
4080 RETURN
4106 LET P=F(N)
4107 GOSUB 4000
4108 PRINT AT 4+(N-X),23-LEN P$;P$
4109 LET P=G(N)
4110 GOSUB 4000
4111 PRINT AT 4+(N-X),32-LEN P$;P$
4114 PRINT AT 4+(N-X),0;N;AT 4+(N-X),4;D$(N);AT 4+(N-X),10;E$(N)
4120 RETURN
4200 LET P=H(C)
4205 GOSUB 4000
4210 PRINT AT 17,31-LEN P$;P$
4215 RETURN
6000 PRINT AT 9,2;"START TAPE IN ""RECORD"" MODE";AT 10,12;" AND ";AT 11,6;"ENTER""CONT""TO SAVE"
6001 STOP
6002 SAVE "G/%L"
6003 GOTO 5
7002 PRINT AT 10,2;"ENTER DATE OF TRANSFER";AT 11,3;"(DAY AND MONTH ONLY)"
7010 INPUT I$
7015 CLS
7017 PRINT AT 6,0;"ENTER 1-30 FOR ACCT.TO TRSF."
7020 INPUT I
7022 CLS
7025 LET C=I
7030 LET N=(C*10)+1
7032 LET N(C)=N
7035 FOR Y=N TO (N+9)
7040 LET D$(Y)=" "
7045 LET E$(Y)=" "
7050 LET F(Y)=0
7055 LET G(Y)=0
7060 NEXT Y
7065 LET D$(N)=I$
7070 LET E$(N)="BFD."
7075 IF H(C)>1 THEN LET F(N)=H(C)
7080 IF H(C)<1 THEN LET G(N)=H(C)
7085 LET C=O
7100 PRINT AT 10,6;"TRANSFER COMPLETED"
7105 PAUSE 50
7150 GOTO 10
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
