TUI Spreadsheet in Java
This is a complete tiny spreadsheet that runs in a terminal.
Quick Run (from repo root)
1cd Site/static/code/examples/java
2javac TuiSpreadsheet.java
3java TuiSpreadsheetIt supports:
- setting and reading cells (
A1,B3, etc.) - simple formulas like
=A1+B1 - showing all stored cells
- saving and loading from a file
Code (Single Public Class)
1import java.io.IOException;
2import java.nio.file.Files;
3import java.nio.file.Path;
4import java.util.HashMap;
5import java.util.Map;
6import java.util.Scanner;
7
8public class TuiSpreadsheet {
9 public static void main(String[] args) {
10 Scanner scanner = new Scanner(System.in);
11 Sheet sheet = new Sheet();
12
13 System.out.println("Commands: set, get, show, save, load, quit");
14 System.out.println("Example set: set A1 42");
15 System.out.println("Formula: set C1 =A1+B1");
16
17 while (true) {
18 System.out.print("> ");
19 String line = scanner.nextLine().trim();
20 if (line.isEmpty()) {
21 continue;
22 }
23
24 String[] parts = line.split("\\s+", 3);
25 String command = parts[0].toLowerCase();
26
27 switch (command) {
28 case "set":
29 if (parts.length < 3) {
30 System.out.println("Use: set CELL VALUE");
31 break;
32 }
33 sheet.set(parts[1], parts[2]);
34 break;
35 case "get":
36 if (parts.length < 2) {
37 System.out.println("Use: get CELL");
38 break;
39 }
40 System.out.println(parts[1].toUpperCase() + " = " + sheet.value(parts[1]));
41 break;
42 case "show":
43 sheet.show();
44 break;
45 case "save":
46 if (parts.length < 2) {
47 System.out.println("Use: save FILE");
48 break;
49 }
50 sheet.save(Path.of(parts[1]));
51 break;
52 case "load":
53 if (parts.length < 2) {
54 System.out.println("Use: load FILE");
55 break;
56 }
57 sheet.load(Path.of(parts[1]));
58 break;
59 case "quit":
60 return;
61 default:
62 System.out.println("Use: set, get, show, save, load, quit");
63 }
64 }
65 }
66
67 private static class Sheet {
68 private final Map<String, String> cells = new HashMap<>();
69
70 private void set(String cell, String raw) {
71 String key = normalizeCell(cell);
72 if (key == null) {
73 System.out.println("Cell must look like A1, B2, C10...");
74 return;
75 }
76 cells.put(key, raw.trim());
77 System.out.println("Stored " + key + ".");
78 }
79
80 private String value(String cell) {
81 String key = normalizeCell(cell);
82 if (key == null) {
83 return "#INVALID_CELL";
84 }
85 String raw = cells.getOrDefault(key, "");
86 if (!raw.startsWith("=")) {
87 return raw;
88 }
89 return evaluate(raw.substring(1));
90 }
91
92 private String evaluate(String expr) {
93 String clean = expr.replace(" ", "");
94 int plusIndex = clean.indexOf('+');
95 if (plusIndex < 0) {
96 return "#BAD_FORMULA";
97 }
98 String left = clean.substring(0, plusIndex);
99 String right = clean.substring(plusIndex + 1);
100 Double a = numberValue(left);
101 Double b = numberValue(right);
102 if (a == null || b == null) {
103 return "#VALUE";
104 }
105 return String.valueOf(a + b);
106 }
107
108 private Double numberValue(String token) {
109 try {
110 return Double.parseDouble(token);
111 } catch (NumberFormatException ignore) {
112 String fromCell = value(token);
113 try {
114 return Double.parseDouble(fromCell);
115 } catch (NumberFormatException e) {
116 return null;
117 }
118 }
119 }
120
121 private void show() {
122 if (cells.isEmpty()) {
123 System.out.println("(sheet is empty)");
124 return;
125 }
126 System.out.println("Cell | Raw | Value");
127 System.out.println("------------------------");
128 cells.keySet().stream().sorted().forEach(cell -> {
129 String raw = cells.get(cell);
130 String val = value(cell);
131 System.out.println(cell + " | " + raw + " | " + val);
132 });
133 }
134
135 private void save(Path file) {
136 StringBuilder builder = new StringBuilder();
137 cells.keySet().stream().sorted().forEach(cell -> {
138 builder.append(cell)
139 .append("\t")
140 .append(cells.get(cell))
141 .append("\n");
142 });
143 try {
144 Files.writeString(file, builder.toString());
145 System.out.println("Saved " + cells.size() + " cell(s) to " + file + ".");
146 } catch (IOException e) {
147 System.out.println("Could not save file.");
148 }
149 }
150
151 private void load(Path file) {
152 if (!Files.exists(file)) {
153 System.out.println("File not found.");
154 return;
155 }
156 try {
157 cells.clear();
158 for (String line : Files.readAllLines(file)) {
159 String[] parts = line.split("\\t", 2);
160 if (parts.length == 2) {
161 cells.put(parts[0], parts[1]);
162 }
163 }
164 System.out.println("Loaded " + cells.size() + " cell(s).");
165 } catch (IOException e) {
166 System.out.println("Could not load file.");
167 }
168 }
169
170 private String normalizeCell(String raw) {
171 String cell = raw.trim().toUpperCase();
172 if (cell.matches("[A-Z]+[1-9][0-9]*")) {
173 return cell;
174 }
175 return null;
176 }
177 }
178}Run It
1javac TuiSpreadsheet.java
2java TuiSpreadsheetWhy this is beginner-friendly
- One public class, one nested class.
- Formula handling is intentionally tiny and readable.
- You get immediate feedback on every command.