2011-08-31 8 views
6

¿Hay alguna forma más pitónica de convertir columnas de estilo Excel en números (empezando por 1)?Convertir una carta de columna excel o de hoja de cálculo a su número en forma pitónica

Trabajando código de un máximo de dos letras:

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 

código se ejecuta:

>>> column_to_number('2') 
False 
>>> column_to_number('A') 
1 
>>> column_to_number('AB') 
28 

Tres cartas que no trabaja.

>>> column_to_number('ABA') 
54 
>>> column_to_number('AAB') 
54 

Referencia: question answered in C#

Respuesta

18

Hay una manera de hacerlo más Pythonic (funciona con tres o más letras y utiliza números menores de magia):

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 

Y como una sola línea usando reducir (no comprobar la entrada y es menos legible, así que no lo recomiendo):

col2num = lambda col: reduce(lambda x, y: x*26 + y, [ord(c.upper()) - ord('A') + 1 for c in col]) 
+0

¿Y cómo regresas para el otro lado? –

1

Esto debería hacer, en VBA, lo que está buscando:

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 

Usted puede usarlo como lo haría una fórmula de Excel - entrar en la columna, en letras, como una cadena (por ejemplo, "AA") y debería funcionar independientemente de la longitud de la columna.

Se le rompe código cuando se trata de tres letras por la forma en que está haciendo el recuento - es necesario utilizar la base 26.

0

No estoy seguro de haber entendido correctamente, es lo que quiere "traducir "el código de C referenciado a python? Si es así, estabas en el camino correcto; simplemente modificarlo para:

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 
0

acaba de hacer:

print ws.Range("E2").Column 

ejemplo llamada:

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 

resultado:

>>5 
5

Esta es una manera de hacerlo. Es una variante de código en el módulo 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 
1

Después de leer esto, me decidí a encontrar una manera de hacerlo directamente en las celdas de Excel. Incluso representa columnas después de Z.

Simplemente pegue esta fórmula en una celda de cualquier fila de cualquier columna y le dará el número correspondiente.

=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) 

El tema aquí era para agarrar la letra de la columna, obtener la Code() de ella y restar 64, basado en el hecho de que el código de caracteres ASCII para la letra A es 64.

1

Usando openpyxl

import openpyxl 
(column_string, row) = openpyxl.cell.coordinate_from_string(address) 
column = openpyxl.cell.column_index_from_string(column_string) 
0

coincise y elegante versión Rubí:

def col_num(col_name) 
    col_name.split(//).inject(0) { |n, c| n * 26 + c.upcase.ord - "A".ord + 1 } 
end 
+0

La pregunta no tiene nada que ver con Ruby. – arogachev

0

Para índice que comienza a partir de cero (por ejemplo A = 0, B = 1, y así sucesivamente):

def col_to_index(col): 
    A = ord('A') 
    return sum(i * 26 + (ord(c) - A) for i, c in enumerate(col[::-1].upper())) 
1

Hice este delineador:

colNameToNum = lambda cn: sum([((ord(cn[-1-pos]) - 64) * 26 ** pos) for pos in range(len(cn))]) 

Funciona al recorrer las letras en orden inverso y multiplicar por 1, 26, 26 * 26, etc., y luego sumar la lista. Este método también sería compatible con cadenas de letras más largas.

me llaman con:

de impresión (colNameToNum ("AA")) # 27

o

de impresión (colNameToNum ("XFD")) # la columna más alta permitida, creo . Resultado = 16384

0

Usted podría utilizar esta oneliner mediante la comprensión y la cadena que es bastante fácil de usar:

sum([string.ascii_lowercase.index(c) + 26 ** i for i,c in enumerate(col_letters)]) 
0

de una sola línea probados en Python 2.7.1 y 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 asimismo

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) 

todas las pruebas de impresión

  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 
0

sólo podría añadir lo siguiente en la consola después de instalar el módulo 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')) 

basta con cambiar las letras y números que se adaptan a sus necesidades o crear un bucle for para hacer el trabajo para el conjunto proyecto. Espero que esto ayude. Aclamaciones.

Cuestiones relacionadas