'Convert a number to Excel’s base 26
OK, I'm stuck on something seemingly simple. I am trying to convert a number to base 26 (ie. 3 = C, 27 = AA, ect.). I am guessing my problem has to do with not having a 0 in the model? Not sure. But if you run the code, you will see that numbers 52, 104 and especially numbers around 676 are really weird. Can anyone give me a hint as to what I am not seeing? I will appreciate it. (just in case to avoid wasting your time, @ is ascii char 64, A is ascii char 65)
def toBase26(x):
x = int(x)
if x == 0:
return '0'
if x < 0:
negative = True
x = abs(x)
else:
negative = False
def digit_value (val):
return str(chr(int(val)+64))
digits = 1
base26 = ""
while 26**digits < x:
digits += 1
while digits != 0:
remainder = x%(26**(digits-1))
base26 += digit_value((x-remainder)/(26**(digits-1)))
x = remainder
digits -= 1
if negative:
return '-'+base26
else:
return base26
import io
with io.open('numbers.txt','w') as f:
for i in range(1000):
f.write('{} is {}\n'.format(i,toBase26(i)))
So, I found a temporary workaround by making a couple of changes to my function (the 2 if statements in the while loop). My columns are limited to 500 anyways, and the following change to the function seems to do the trick up to x = 676, so I am satisfied. However if any of you find a general solution for any x (may be my code may help), would be pretty cool!
def toBase26(x):
x = int(x)
if x == 0:
return '0'
if x < 0:
negative = True
x = abs(x)
else:
negative = False
def digit_value (val):
return str(chr(int(val)+64))
digits = 1
base26 = ""
while 26**digits < x:
digits += 1
while digits != 0:
remainder = x%(26**(digits-1))
if remainder == 0:
remainder += 26**(digits-1)
if digits == 1:
remainder -= 1
base26 += digit_value((x-remainder)/(26**(digits-1)))
x = remainder
digits -= 1
if negative:
return '-'+base26
else:
return base26
Solution 1:[1]
Sorry, I wrote this in Pascal and know no Python
function NumeralBase26Excel(numero: Integer): string;
var
algarismo: Integer;
begin
Result := '';
numero := numero - 1;
if numero >= 0 then
begin
algarismo := numero mod 26;
if numero < 26 then
Result := Chr(Ord('A') + algarismo)
else
Result := NumeralBase26Excel(numero div 26) + Chr(Ord('A') + algarismo);
end;
end;
Solution 2:[2]
Here is a solution :
def get_xl_range_col_nr(rng):
def xl_ord(char):
return ord(char) - ord('@')
return sum([xl_ord(value) * (26 ** key)
for key, value
in enumerate([car for car in rng.upper() if car not in '0123456789'][::-1])])
get_xl_range_col_nr('ABC456') # returns 731
get_xl_range_col_nr('C456') # returns 3
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Leonardo Couto Chueri |
| Solution 2 | Arnaud Desplanche |
