Is there a more pythonic way of converting excel-style columns to numbers (starting with 1)?
Working code up to two letters:
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])
You could use this oneliner using comprehension and string that is fairly easy to use:
sum([string.ascii_lowercase.index(c) + 26 ** i for i,c in enumerate(col_letters)])
You could just add the following to the console after installing the openpyxl module:
import openpyxl
from openpyxl.utils import get_column_letter, column_index_from_string
workbook = openpyxl.load_workbook('your_workbook.xlsx')
sheet = wb.get_sheet_by_name('your_sheet_from_workbook')
print(get_column_letter(1))
print(column_index_from_string('A'))
Just change the letters and number to suit your needs or create a for-loop to do the job for a whole project. I hope this helps. Cheers.
Here's what I use (wrote before I found this page):
def col_to_index(col):
return sum((ord(c) - 64) * 26**i for i, c in enumerate(reversed(col))) - 1
And some runs:
>>> col_to_index('A')
1
>>> col_to_index('AB')
28
>>> col_to_index('ABCD')
19010
Using openpyxl
import openpyxl
(column_string, row) = openpyxl.cell.coordinate_from_string(address)
column = openpyxl.cell.column_index_from_string(column_string)
Coincise and elegant Ruby version:
def col_num(col_name)
col_name.split(//).inject(0) { |n, c| n * 26 + c.upcase.ord - "A".ord + 1 }
end