Преобразуйте букву столбца excel или электронной таблицы в его номер в Pythonic
есть ли более питонический способ преобразования столбцов в стиле excel в числа (начиная с 1)?
рабочий код до двух букв:
def column_to_number(c):
"""Return number corresponding to excel-style column."""
number=-25
for l in c:
if not l in string.ascii_letters:
return False
number+=ord(l.upper())-64+25
return number
код:
>>> column_to_number('2')
False
>>> column_to_number('A')
1
>>> column_to_number('AB')
28
три буквы не работает.
>>> column_to_number('ABA')
54
>>> column_to_number('AAB')
54
ссылки: ответ на вопрос в C#
13 ответов
есть способ сделать это более подходящие для Python (работает с тремя или более буквами и использует меньше магических чисел):
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
и в качестве однострочного использования reduce (не проверяет ввод и менее читаем, поэтому я не рекомендую его):
col2num = lambda col: reduce(lambda x, y: x*26 + y, [ord(c.upper()) - ord('A') + 1 for c in col])
вот один из способов сделать это. Это вариация кода в XlsxWriter модуль:
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
С помощью openpyxl
import openpyxl
(column_string, row) = openpyxl.cell.coordinate_from_string(address)
column = openpyxl.cell.column_index_from_string(column_string)
Это должно сделать в VBA то, что вы ищете:
Function columnNumber(colLetter As String) As Integer
Dim colNumber As Integer
Dim i As Integer
colLetter = UCase(colLetter)
colNumber = 0
For i = 1 To Len(colLetter)
colNumber = colNumber + (Asc(Mid(colLetter, Len(colLetter) - i + 1, 1)) - 64) * 26 ^ (i - 1)
Next
columnNumber = colNumber
End Function
вы можете использовать его как формулу Excel--введите столбец буквами в виде строки (например, "AA") и должен работать независимо от длины столбца.
ваш код прерывается при работе с тремя буквами из-за того, как вы делаете подсчет-вам нужно использовать базу 26.
прочитав это, я решил найти способ сделать это непосредственно в ячейках Excel. Он даже учитывает столбцы после Z.
просто вставьте эту формулу в ячейку любой строки, любого столбца, и он будет давать вам соответствующий номер.
=IF(LEN(SUBSTITUTE(ADDRESS(ROW(),COLUMN(),4),ROW(),""))=2,
CODE(LEFT(SUBSTITUTE(ADDRESS(ROW(),COLUMN(),4),ROW(),""),1))-64*26)+
CODE(RIGHT(SUBSTITUTE(ADDRESS(ROW(),COLUMN(),4),ROW(),""),1)-64),
CODE(SUBSTITUTE(ADDRESS(ROW(),COLUMN(),4),ROW(),""))-64)
тема здесь заключалась в том, чтобы захватить букву столбца, получить Code()
из него и вычесть 64, исходя из того, что код символа ASCII для буквы A
- это 64.
Я сделал этот однострочный:
colNameToNum = lambda cn: sum([((ord(cn[-1-pos]) - 64) * 26 ** pos) for pos in range(len(cn))])
он работает, повторяя Буквы в обратном порядке и умножая на 1, 26, 26 * 26 и т. д., а затем суммируя список. Этот метод также будет совместим с более длинными строками букв.
Я называю это:
print (colNameToNum ("AA")) # 27
или
print (colNameToNum ("XFD")) # самый высокий разрешенный столбец, я считаю. Результат = 16384
Я не уверен, что правильно понимаю, вы хотите "перевести" ссылочный код C# на python? Если это так, вы были на правильном пути, просто изменить его так:
def column_to_number(c):
"""Return number corresponding to excel-style column."""
sum = 0
for l in c:
if not l in string.ascii_letters:
return False
sum*=26
sum+=ord(l.upper())-64
return sum
так же :
print ws.Range("E2").Column
вызов пример :
from win32com import client
xl = client.Dispatch("Excel.Application")
wb = xl.Workbooks.Open("c:/somePath/file.xls")
xl.Visible = 1
ws = wb.Sheets("sheet 1")
print ws.Range("E2").Column
результат :
>>5
Coincise и элегантных Рубин версия:
def col_num(col_name)
col_name.split(//).inject(0) { |n, c| n * 26 + c.upcase.ord - "A".ord + 1 }
end
для индекса, который начинается с нуля (например, A = 0, B = 1 и т. д.):
def col_to_index(col):
A = ord('A')
return sum(i * 26 + (ord(c) - A) for i, c in enumerate(col[::-1].upper()))
вы можете использовать этот oneliner, используя понимание и строку, которая довольно проста в использовании:
sum([string.ascii_lowercase.index(c) + 26 ** i for i,c in enumerate(col_letters)])
One-liners протестированы в Python 2.7.1 и 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'))
мульти-вкладышами также
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 name
def 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 n
def 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)
все тесты 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 ok
1110829947 COLUMNS ok
вы можете просто добавить следующее в консоль после установки модуля openpyxl:
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'))
просто измените буквы и номер в соответствии с вашими потребностями или создайте for-loop для выполнения работы для всего проекта. Надеюсь, это поможет. Овации.