def column_index_from_string(column, fast=False): """Convert a column letter into a column number (e.g. B -> 2) Excel only supports 1-3 letter column names from A -> ZZZ, so we restrict our column names to 1-3 characters, each in the range A-Z. .. note:: Fast mode is faster but does not check that all letters are capitals between A and Z """ column = column.upper() clen = len(column) if not fast and not all('A' <= char <= 'Z' for char in column): msg = 'Column string must contain only characters A-Z: got %s' % column raise ColumnStringIndexException(msg) if clen == 1: return ord(column[0]) - 64 elif clen == 2: return ((1 + (ord(column[0]) - 65)) * 26) + (ord(column[1]) - 64) elif clen == 3: return ((1 + (ord(column[0]) - 65)) * 676) + ( (1 + (ord(column[1]) - 65)) * 26) + (ord(column[2]) - 64) elif clen > 3: raise ColumnStringIndexException( 'Column string index can not be longer than 3 characters') else: raise ColumnStringIndexException( 'Column string index can not be empty')
def get_column_letter(col_idx): """Convert a column number into a column letter (3 -> 'C') Right shift the column col_idx by 26 to find column letters in reverse order. These numbers are 1-based, and can be converted to ASCII ordinals by adding 64. """ # these indicies corrospond to A -> ZZZ and include all allowed # columns if not 1 <= col_idx <= 18278: msg = 'Column index out of bounds: %s' % col_idx raise ColumnStringIndexException(msg) ordinals = [] temp = col_idx while temp: quotient, remainder = divmod(temp, 26) # check for exact division and borrow if needed if remainder == 0: quotient -= 1 remainder = 26 ordinals.append(remainder + 64) temp = quotient ordinals.reverse() return ''.join([chr(ordinal) for ordinal in ordinals])