A cell address has two directions - parsing it in and printing it back out. Today you build the inverse of yesterday's function so a column index becomes its letters again, which we will need every time the engine reports a cell address.
Convert a zero-based column index back into its column label, the exact inverse of yesterday.
Going the other way is the same one-based quirk in reverse. If you try to treat
the index as ordinary base-26 you get an off-by-one that breaks exactly at the
Z-to-AA boundary. The fix mirrors yesterday: add one to move back into
one-based counting, then peel off letters from the right, subtracting one before
each modulo so that the value 0 maps to A rather than to a nonexistent zero
digit.
The pair colToIndex and indexToCol should be exact inverses: feeding a label
through one and then the other returns the original. That round-trip is worth
checking at the boundaries - Z (25), AA (26), ZZ (701) - because those are
where the naive base-26 version goes wrong. With both directions working, a column
is just an integer to the rest of the engine, and we can always render it back.
// undo the one-based folding: add 1, then peel off letters// from the right, decrementing before each modulo.func indexToCol(i int) string {i++out := ""for i > 0 {i--out = string(rune('A'+i%26)) + outi /= 26}return out}