Convert an excel or spreadsheet column letter to its number in Pythonic fashion
There is a way to make it more pythonic (works with three or more letters and uses less magic numbers):
def col2num(col): num = 0 for c in col: if c in string.ascii_letters: num = num * 26 + (ord(c.upper()) - ord('A')) + 1 return num
And as a one-liner using reduce (does not check input and is less readable so I don't recommend it):
col2num = lambda col: reduce(lambda x, y: x*26 + y, [ord(c.upper()) - ord('A') + 1 for c in col])
One-liners tested in Python 2.7.1 and 3.5.2
excel_col_num = lambda a: 0 if a == '' else 1 + ord(a[-1]) - ord('A') + 26 * excel_col_num(a[:-1])excel_col_name = lambda n: '' if n <= 0 else excel_col_name((n - 1) // 26) + chr((n - 1) % 26 + ord('A'))
Multi-liners likewise
def excel_column_name(n): """Number to Excel-style column name, e.g., 1 = A, 26 = Z, 27 = AA, 703 = AAA.""" name = '' while n > 0: n, r = divmod (n - 1, 26) name = chr(r + ord('A')) + name return namedef excel_column_number(name): """Excel-style column name to number, e.g., A = 1, Z = 26, AA = 27, AAA = 703.""" n = 0 for c in name: n = n * 26 + 1 + ord(c) - ord('A') return ndef test (name, number): for n in [0, 1, 2, 3, 24, 25, 26, 27, 702, 703, 704, 2708874, 1110829947]: a = name(n) n2 = number(a) a2 = name(n2) print ("%10d %-9s %s" % (n, a, "ok" if a == a2 and n == n2 else "error %d %s" % (n2, a2)))test (excel_column_name, excel_column_number)test (excel_col_name, excel_col_num)
All tests print
0 ok 1 A ok 2 B ok 3 C ok 24 X ok 25 Y ok 26 Z ok 27 AA ok 702 ZZ ok 703 AAA ok 704 AAB ok 2708874 EXCEL ok1110829947 COLUMNS ok
Here is one way to do it. It is a variation on code in the XlsxWriter module:
def col_to_num(col_str): """ Convert base26 column string to number. """ expn = 0 col_num = 0 for char in reversed(col_str): col_num += (ord(char) - ord('A') + 1) * (26 ** expn) expn += 1 return col_num>>> col_to_num('A')1>>> col_to_num('AB')28>>> col_to_num('ABA')729>>> col_to_num('AAB')704