oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1// Package calc owns everything about formulas: references, lexing, parsing,
2// evaluation and the dependency graph.
3package calc
4
5import (
6 "errors"
7 "strings"
8)
9
10// ColLabel renders a zero-based column position as a spreadsheet label.
11// This is bijective base-26, not ordinary base-26: there is no zero digit,
12// which is why 25 is "Z" and 26 is "AA" rather than "BA".
13func ColLabel(pos int) string {
14 if pos < 0 {
15 return ""
16 }
17 var sb strings.Builder
18 pos++
19 for pos > 0 {
20 pos--
21 sb.WriteByte(byte('A' + pos%26))
22 pos /= 26
23 }
24 b := []byte(sb.String())
25 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
26 b[i], b[j] = b[j], b[i]
27 }
28 return string(b)
29}
30
31// ParseColLabel is ColLabel's inverse.
32func ParseColLabel(s string) (int, error) {
33 if s == "" {
34 return 0, errors.New("calc: empty column label")
35 }
36 n := 0
37 for i := 0; i < len(s); i++ {
38 c := s[i]
39 if c >= 'a' && c <= 'z' {
40 c -= 'a' - 'A'
41 }
42 if c < 'A' || c > 'Z' {
43 return 0, errors.New("calc: bad column label")
44 }
45 n = n*26 + int(c-'A') + 1
46 }
47 return n - 1, nil
48}
49
50// A1 renders zero-based positions as an A1 reference. Positions, not ids:
51// stable ids are the key, A1 is the view.
52func A1(rowPos, colPos int) string {
53 return ColLabel(colPos) + itoa(rowPos+1)
54}
55
56func itoa(n int) string {
57 if n == 0 {
58 return "0"
59 }
60 var b [20]byte
61 i := len(b)
62 for n > 0 {
63 i--
64 b[i] = byte('0' + n%10)
65 n /= 10
66 }
67 return string(b[i:])
68}
69