diff options
author | Matthew Lemon <lemon@matthewlemon.com> | 2019-12-03 17:11:52 +0000 |
---|---|---|
committer | Matthew Lemon <lemon@matthewlemon.com> | 2019-12-03 17:11:52 +0000 |
commit | 30d510fc62ed7aec90820835926a784744c51d7f (patch) | |
tree | 12dbe08033673153308351f81e4e66566548a9cf |
initial commit
-rw-r--r-- | coords.go | 68 | ||||
-rw-r--r-- | coords_test.go | 99 |
2 files changed, 167 insertions, 0 deletions
diff --git a/coords.go b/coords.go new file mode 100644 index 0000000..ee13dba --- /dev/null +++ b/coords.go @@ -0,0 +1,68 @@ +/* +coords calculates coordinates for spreadsheets. +*/ +package coords + +import ( + "errors" + "fmt" +) + +const ( + maxCols = 16384 + maxAlphabets = (maxCols / 26) - 1 +) + +// ColAlpha returns an alpha representation of a column index. +// index is an integer - ColAlpha(0) returns "A", etc. +func ColIndexToAlpha(index int) (string, error) { + max := len(colstream) - 1 + if index <= max { + return colstream[index], nil + } else { + msg := fmt.Sprintf("cannot have more than %d columns", max) + return "", errors.New(msg) + } +} + +var colstream = cols(maxAlphabets) + +// ColLettersToIndex converts an alpha column +// reference to a zero-based numeric column identifier. +func ColAlphaToIndex(letters string) (int, error) { + max := len(colstream) - 1 + for i, v := range colstream { + if i > max { + msg := fmt.Sprintf("Cannot exceed maximum of %d", max) + return 0, errors.New(msg) + } + if v == letters { + return i, nil + } + } + return 0, errors.New("Cannot find requested string.") +} + +//alphabet generates all the letters of the alphabet. +func alphabet() []string { + letters := make([]string, 26) + for idx := range letters { + letters[idx] = string('A' + byte(idx)) + } + return letters +} + +//cols generates the alpha column component of Excel cell references +//Adds n alphabets to the first (A..Z) alphabet. +func cols(n int) []string { + out := alphabet() + alen := len(out) + tmp := make([]string, alen) + copy(tmp, out) + for cycle := 0; cycle < n; cycle++ { + for y := 0; y < alen; y++ { + out = append(out, out[(cycle+2)-2]+tmp[y]) + } + } + return out +} diff --git a/coords_test.go b/coords_test.go new file mode 100644 index 0000000..8f8f865 --- /dev/null +++ b/coords_test.go @@ -0,0 +1,99 @@ +package coords + +import ( + "testing" +) + +func TestAlphaStream(t *testing.T) { + if colstream[26] != "AA" { + t.Errorf("The test expected AA, got %v.", colstream[26]) + } + if len(colstream) > maxCols { + t.Errorf(`Number of columns in alphastream exceeds Excel maximum. + alphastream contains %d, maxCols is %d`, len(colstream), maxCols) + } +} + +func TestAlphaSingle(t *testing.T) { + ab := alphabet() + if ab[0] != "A" { + t.Errorf("The test expected A, got %v.", ab[0]) + } + if ab[1] != "B" { + t.Errorf("The test expected B, got %v.", ab[1]) + } + if ab[25] != "Z" { + t.Errorf("The test expected Z, got %v.", ab[25]) + } +} + +func TestAlphas(t *testing.T) { + a := 2 // two alphabets long + ecs := cols(a) + cases := []struct { + col int + val string + }{ + {0, "A"}, + {25, "Z"}, + {26, "AA"}, + {52, "BA"}, + } + for _, c := range cases { + // we're making sure we can pass that index + r := 26 * a + if c.col > r { + t.Fatalf("Cannot use %d as index to array of %d", c.col, r) + } + if got := ecs[c.col]; got != c.val { + t.Errorf("The test expected ecs[%d] to be %s - got %s.", + c.col, c.val, ecs[c.col]) + } + } +} + +func TestCollectLetters(t *testing.T) { + cases := []struct { + alpha string + index int + }{ + {"XEZ", 16379}, + {"XEY", 16378}, + {"XEX", 16377}, + {"A", 0}, + {"B", 1}, + {"C", 2}, + {"AA", 26}, + } + for _, c := range cases { + s, err := ColAlphaToIndex(c.alpha) + if err != nil { + t.Fatal(err) + } + if s != c.index { + t.Errorf("Expected %d to return %s, instead it returned %d", c.index, c.alpha, s) + } + + } +} + +func TestGetColApha(t *testing.T) { + cases := []struct { + index int + alpha string + }{ + {0, "A"}, + {1, "B"}, + {2, "C"}, + {16377, "XEX"}, + } + for _, c := range cases { + s, err := ColIndexToAlpha(c.index) + if err != nil { + t.Fatal(err) + } + if s != c.alpha { + t.Errorf("Expected %s, got %s\n", c.alpha, s) + } + } +} |