--- title: "General Ledger" id: 56682 type: "computer_media" slug: "general-ledger-2" url: "http://localhost/computer_media/general-ledger-2/" markdown_url: "http://localhost/computer_media/general-ledger-2.md" published_at: "2024-09-22T23:31:42+00:00" modified_at: "2026-04-03T07:58:59+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/09/General-Ledger.jpg" excerpt: "A complete double-entry general ledger system with trial balance and profit-and-loss reporting, fitting 30 accounts and 310 transaction lines into a single BASIC program." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "M. Sieder" slug: "m-sieder" taxonomy: "post_tag" url: "http://localhost/tag/m-sieder/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Max Sieder" slug: "max-sieder" taxonomy: "indiv" url: "http://localhost/indiv/max-sieder/" genre: - name: "Finance" slug: "finance" taxonomy: "genre" url: "http://localhost/type/finance/" media_type: "Program" programmers: - name: "Max Sieder" slug: "max-sieder" taxonomy: "indiv" url: "http://localhost/indiv/max-sieder/" download_url: "https://archive.org/download/timex-sinclair-software-archive/General%20Ledger%20%281983%29%28Sieder%2C%20M.E.%29%28TS1000%29%28CA%29%28Cassette%29.zip" mediadate: "1983" producer_company: - id: 11060 title: "M. Sieder" type: "company" url: "http://localhost/company/m-sieder/" images: - url: "http://localhost/wp-content/uploads/2024/09/General-Ledger.jpg" related_products: - id: 12715 title: "General Ledger" type: "product" url: "http://localhost/product/general-ledger/" media_type_tags: "Finance" --- 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`. 1. Lines 10–60: Main menu and dispatcher 2. Lines 100–500: Register initialisation (option 0) — DIM statements and variable resets, year entry 3. Lines 1001–1050: Open new ledger card (option 1) 4. Lines 2005–2610: Account search and transaction entry (option 2) 5. Lines 3000–3980: Trial balance and P+L statement (option 3) 6. Lines 4000–4215: Subroutines — currency formatting (4000), display transaction row (4100), display balance (4200) 7. Lines 6000–6003: Save to tape (option 4) 8. 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 from `DIM`, 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 name `C`. 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 3200` to skip the page-break prompt if all accounts fit on one page, but the condition should perhaps be `C>14` or similar; the current logic depends on the loop having incremented `C` past `O` naturally. - The P+L thresholds at lines 3620 and 3630 use `>1` and `<1` rather than `>0` and `<0`, meaning accounts with a balance of exactly 1 or -1 are excluded from both totals. - Line 4100 is entered via `GOSUB 4100` but 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 the `GOSUB` target 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. ## 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 ```