TUI Spreadsheet in Python
This is a complete tiny spreadsheet in plain Python.
Quick Run (from repo root)
1cd Site/static/code/examples/python
2python tui_spreadsheet.pyIt supports:
- setting and reading cells (
A1,B3, etc.) - simple formulas like
=A1+B1 - showing all stored cells
- saving and loading from a file
Code (Pythonic + Short)
1from dataclasses import dataclass, field
2from pathlib import Path
3
4
5@dataclass
6class Spreadsheet:
7 cells: dict[str, str] = field(default_factory=dict)
8
9 def set(self, cell: str, raw: str) -> None:
10 key = normalize_cell(cell)
11 if key is None:
12 print("Cell must look like A1, B2, C10...")
13 return
14 self.cells[key] = raw.strip()
15 print(f"Stored {key}.")
16
17 def value(self, cell: str) -> str:
18 key = normalize_cell(cell)
19 if key is None:
20 return "#INVALID_CELL"
21 raw = self.cells.get(key, "")
22 if not raw.startswith("="):
23 return raw
24 return self._evaluate(raw[1:])
25
26 def _evaluate(self, expr: str) -> str:
27 clean = expr.replace(" ", "")
28 if "+" not in clean:
29 return "#BAD_FORMULA"
30 left, right = clean.split("+", maxsplit=1)
31 a = self._number_value(left)
32 b = self._number_value(right)
33 if a is None or b is None:
34 return "#VALUE"
35 return str(a + b)
36
37 def _number_value(self, token: str) -> float | None:
38 try:
39 return float(token)
40 except ValueError:
41 try:
42 return float(self.value(token))
43 except ValueError:
44 return None
45
46 def show(self) -> None:
47 if not self.cells:
48 print("(sheet is empty)")
49 return
50 print("Cell | Raw | Value")
51 print("------------------------")
52 for cell in sorted(self.cells):
53 raw = self.cells[cell]
54 print(f"{cell} | {raw} | {self.value(cell)}")
55
56 def save(self, file_name: str) -> None:
57 path = Path(file_name)
58 lines = [f"{cell}\t{self.cells[cell]}" for cell in sorted(self.cells)]
59 path.write_text("\n".join(lines) + ("\n" if lines else ""))
60 print(f"Saved {len(self.cells)} cell(s) to {path}.")
61
62 def load(self, file_name: str) -> None:
63 path = Path(file_name)
64 if not path.exists():
65 print("File not found.")
66 return
67 self.cells.clear()
68 for line in path.read_text().splitlines():
69 if "\t" not in line:
70 continue
71 cell, raw = line.split("\t", maxsplit=1)
72 self.cells[cell] = raw
73 print(f"Loaded {len(self.cells)} cell(s).")
74
75
76def normalize_cell(raw: str) -> str | None:
77 cell = raw.strip().upper()
78 if not cell:
79 return None
80 letters = ""
81 digits = ""
82 for ch in cell:
83 if ch.isalpha() and not digits:
84 letters += ch
85 elif ch.isdigit():
86 digits += ch
87 else:
88 return None
89 if not letters or not digits or digits.startswith("0"):
90 return None
91 return f"{letters}{digits}"
92
93
94def main() -> None:
95 sheet = Spreadsheet()
96 print("Commands: set, get, show, save, load, quit")
97 print("Example set: set A1 42")
98 print("Formula: set C1 =A1+B1")
99
100 while True:
101 line = input("> ").strip()
102 if not line:
103 continue
104
105 parts = line.split(maxsplit=2)
106 command = parts[0].lower()
107
108 if command == "set":
109 if len(parts) < 3:
110 print("Use: set CELL VALUE")
111 else:
112 sheet.set(parts[1], parts[2])
113 elif command == "get":
114 if len(parts) < 2:
115 print("Use: get CELL")
116 else:
117 cell = parts[1]
118 print(f"{cell.upper()} = {sheet.value(cell)}")
119 elif command == "show":
120 sheet.show()
121 elif command == "save":
122 if len(parts) < 2:
123 print("Use: save FILE")
124 else:
125 sheet.save(parts[1])
126 elif command == "load":
127 if len(parts) < 2:
128 print("Use: load FILE")
129 else:
130 sheet.load(parts[1])
131 elif command == "quit":
132 break
133 else:
134 print("Use: set, get, show, save, load, quit")
135
136
137if __name__ == "__main__":
138 main()Run It
1python tui_spreadsheet.pyWhy this is pythonic
dataclasskeeps state clean.dictstores only cells you touch.- Functions are small and easy to trace.