[dbohdan] 2015-03-25: The following code is a [Tk] [spreadsheet] inspired, title included, by http://jsfiddle.net/ondras/hYfN3/. Halfway through writing it I found the [tiny spreadsheet] and lifted the idea of tracing variable reads to trigger recalculation from it. One important difference from the tiny spreadsheet is that TEAIPTT does not require a Tcl [expr] patch. **Feature comparison with the JavaScript version** | ✓ Under 30 lines of plain Tcl/Tk (rather than vanilla JS*) | | ✓ Libraries used: none | | ✓ [Excel]-like syntax (formulas start with "=") | | ✓ Support for arbitrary expressions (=A1+B2*C3) | | ✓ Circular reference prevention | | ✗ Automatic persistence | * Lines are assumed to be up to 100 characters long (because the under-30-line JavaScript spreadsheet uses lines longer than 80 characters, 100 is the next common limit and using lines of unlimited length would feel like cheating). The smallest JS spreadsheet is currently this one: http://xem.github.io/sheet/ (227 bytes for the minimal version, 267b if we add automatic persistence). **Screenshot** [under-35-line-spreadsheet-screenshot] **Code** ====== #!/usr/bin/wish package require Tk 8.6 ;# needs lmap foreach row {0 1 2 3 4 5 6} { grid {*}[lmap {column} {"" A B C D E F} { set cell $column$row if {$column eq "" || $row == 0} { ::ttk::label .label$cell -text [expr {$row ? $row : $column}] } else { set ::formula($cell) [set ::$cell ""] trace add variable ::$cell read recalc ::ttk::entry .cell$cell -textvar ::$cell -width 10 -validate focus \ -validatecommand [list ::reveal-formula $cell %V %s] } }] } proc recalc {cell args} { catch {set ::$cell [uplevel #0 [list \ expr [regsub -all {([A-F][1-6])} $::formula($cell) {$\1}]]]} } proc reveal-formula {cell event value} { if {$event eq "focusin"} { if {$::formula($cell) ne ""} { set ::$cell =$::formula($cell) } .cell$cell selection range 0 end .cell$cell icursor end } else { ;# focusout if {![regexp {^=(.*)} $value -> ::formula($cell)]} { set ::formula($cell) "" } foreach otherCell [array names ::formula] { recalc $otherCell } } return 1 } ====== ====== # Demos: proc set-cell {cell value} { .cell$cell delete 0 end .cell$cell insert 0 $value } proc demo1 {} { set-cell A1 "**Demo1**" set-cell A2 "Art.1"; set-cell B2 "123.45" set-cell A3 "Art.2"; set-cell B3 "76.55" set-cell A4 "Sum"; reveal-formula B4 focusout "=B2+B3" set-cell A5 ".16"; reveal-formula B5 focusout "=B4*A5" set-cell A6 " Total:"; reveal-formula B6 focusout "=B4+B5" } proc demo2 {} { set-cell F1 "**Demo2**" set-cell A1 "Art.1"; set-cell B1 "3"; set-cell C1 "50"; reveal-formula D1 focusout "=B1*C1" set-cell A2 "Art.2"; set-cell B2 "1"; set-cell C2 "123.75"; reveal-formula D2 focusout "=B2*C2" set-cell A3 "Art.3"; set-cell B3 "5"; set-cell C3 "25.25"; reveal-formula D3 focusout "=B3*C3" set-cell A4 " Sum:"; reveal-formula B4 focusout "=B1+B2+B3"; #reveal-formula D4 focusout "=sum(D1..D3)" reveal-formula D4 focusout "=D1+D2+D3" set-cell A5 " Tax:"; set-cell B5 ".16"; reveal-formula D5 focusout "=D4*B5" set-cell C6 " Total:"; reveal-formula D6 focusout "=D4+D5" } #demo1; focus -f .cellB2 demo2; focus -f .cellB1; # recalc D4 ====== **Discussion** [AMG]: Exchanged the row and column [foreach] lines so that the tab key moves across rather than down. [dbohdan] 2015-03-28: [xem], it is neat just how much functionality your spreadsheet packs in 0x00-0xE2 but it looks like it only recalculates formulas one step at a time. I.e., if you have A1 set to =B1 and B1 set to =C1 and then put the number 5 into C1 it will take ''two'' `onblur` events before the value propagates back to A1. This also means you can create stable infinite loops that will cycle values and `NaN`s between cells. I wonder how much you could [code golf%|%golf] the Tcl/Tk version if you try to optimize for character count rather than line count and relax the requirement on `recalc`. Any takers? A page like [Golfed spreadsheet] would be appropriate for that. I also wonder what would be the minimal overhead of adding full recalculation with circular reference prevention to [xem]'s JS version. [aspect] 2015-03-29: Fixed deletion of formulas and reduced by using [lmap], taking advantage of `-textvariable` to eliminate the `set-cell` proc and eliminating the test in `recalc` because [expr] will error on an empty expression. Without `set-cell`, some explicit selection management is required on focusin, reducing the saving. This might be improved with some careful event binding, rather than `-validate`. [bsg] 2015-03-30: I've taken this Tiny spreadsheet and tried to make it generally useful as a utility tool: [MINISS - Mini Spread Sheet] [HJG] 2016-01-27 - An empty spreadsheet doesn't look too impressive, so I added some demos. Nothing fancy, just simple calculations like price * amount, tax, sum. The coding uses the original procedure-names, so it looks quite verbose, and I also re-introduced set-cell(). <>Application | GUI | Spreadsheet