Dies ist der Code zum Bereitstellen des COLUMN-Namens, wenn die Zeilen- und Spalten-ID angegeben wird. Wenn ich jedoch Werte wie row = 1 and col = 104 gebe, sollte er CZ zurückgeben, aber D@.

row = 1
col = 104
div = col
column_label = str()
while div:
    (div, mod) = divmod(div, 26)
    column_label = chr(mod + 64) + column_label

print column_label

Was ist los mit dem, was ich tue?

(Dieser Code bezieht sich auf EXCEL-Spalten, in denen ich den Wert für Zeile und Spalten-ID gebe und den ALPHABETIC-Wert für denselben erwarte.)

20
saun jean 3 Okt. 2013 im 11:37

8 Antworten

Beste Antwort

BEARBEITEN: Ich muss zugeben, wie einige andere betonten - die mir nie Kommentare hinterlassen haben -, dass die vorherige Version meiner Antwort (die Sie akzeptiert haben) einen Fehler aufwies, der sie daran hinderte, Spaltennummern größer als {{X0 richtig zu behandeln }} (entspricht der Excel-Spalte 'ZZ'). Im Interesse der Korrektheit wurde dies im folgenden Code behoben, der nun wie viele andere Antworten eine Schleife enthält.

Es ist sehr wahrscheinlich, dass Sie die vorherige Version nie mit Spaltennummern verwendet haben, die groß genug sind, um auf das Problem zu stoßen. FWIW, die MS-Spezifikationen Für die aktuelle Version von Excel werden Arbeitsblätter mit bis zu 16.384 Spalten (Excel-Spalte 'XFD') unterstützt.

LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def excel_style(row, col):
    """ Convert given row and column number to an Excel-style cell name. """
    result = []
    while col:
        col, rem = divmod(col-1, 26)
        result[:0] = LETTERS[rem]
    return ''.join(result) + str(row)

if __name__ == '__main__':
    addresses = [(1,  1), (1, 26),
                 (1, 27), (1, 52),
                 (1, 53), (1, 78),
                 (1, 79), (1, 104),
                 (1, 18253), (1, 18278),
                 (1, 702),  # -> 'ZZ1'
                 (1, 703),  # -> 'AAA1'
                 (1, 16384), # -> 'XFD1'
                 (1, 35277039)]

    print('({:3}, {:>10}) --> {}'.format('row', 'col', 'Excel'))
    print('==========================')
    for row, col in addresses:
        print('({:3}, {:10,}) --> {!r}'.format(row, col, excel_style(row, col)))

Ausgabe:

(row,       col) --> Excel
========================
(  1,         1) --> 'A1'
(  1,        26) --> 'Z1'
(  1,        27) --> 'AA1'
(  1,        52) --> 'AZ1'
(  1,        53) --> 'BA1'
(  1,        78) --> 'BZ1'
(  1,        79) --> 'CA1'
(  1,       104) --> 'CZ1'
(  1,     18253) --> 'ZZA1'
(  1,     18278) --> 'ZZZ1'
(  1,       702) --> 'ZZ1'
(  1,       703) --> 'AAA1'
(  1,     16384) --> 'XFD1'
(  1,  35277039) --> 'BYEBYE1'
23
martineau 6 Dez. 2016 im 17:00
def ColNum2ColName(n):
   convertString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   base = 26
   i = n - 1

   if i < base:
      return convertString[i]
   else:
      return ColNum2ColName(i//base) + convertString[i%base]

BEARBEITEN: Richtig, richtig, Zondo.

Ich habe mich gerade A, B, .. AA, AB, ... als numerische Basis mit den Ziffern A-Z genähert.

A = 1
B = 2
 .
 .
X = 24
Y = 25
Z = 26
 .
 .
 .

Es ist ein einfacher Weg ohne while-Schleife usw. und funktioniert für jede Zahl > 0.

2
user6360292 20 Mai 2016 im 10:57

Ich denke, es ist ungefähr so:

def get_col(col):
    """Get excel-style column names"""
    (div, mod) = divmod(col, 26)
    if div == 0:
        return str(unichr(mod+64))
    elif mod == 0:
        return str(unichr(div+64-1)+'Z')
    else:
        return str(unichr(div+64)+unichr(mod+64))

Einige Tests:

>>> def get_col(col):
...     (div, mod) = divmod(col, 26)
...     if div == 0:
...         return str(unichr(mod+64))
...     elif mod == 0:
...         return str(unichr(div+64-1)+'Z')
...     else:
...         return str(unichr(div+64)+unichr(mod+64))
... 
>>> get_col(105)
'DA'
>>> get_col(104)
'CZ'
>>> get_col(1)
'A'
>>> get_col(55)
'BC'
1
Emil Davtyan 3 Okt. 2013 im 08:43

Hier ist eine andere Möglichkeit, Excel-Spaltennamen ohne Schleife mithilfe eines Pandas-Multiindex-Datenrahmens abzurufen. Dies ist eine Modifikation eines verallgemeinerten Basis-zu-Basis-Konverters, daher ist der Code etwas länger als einige der anderen Optionen, aber ich denke, er ist effektiv:

def xlcolumn(num):
    base = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    baseln = len(base)
    idx = [""]+base
    num = num-1

    # create pandas multiindex using idx, base
    # current excel version has 16384 columns (A --> XFD), so multiindex needs to have a minimum of 3 levels:
    #   (26x26x26 = 17576 > 16384 columns) 

    index = pd.MultiIndex.from_product([idx, idx, idx],names=['level 1', 'level 2', 'level 3'])
    df = pd.DataFrame(index = index)
    df = df.drop("",level = 'level 3')
    df = df.iloc[:baseln].append(df.drop("",level = 'level 2'))
    df['val']=1

    if num < baseln:
        xlcol = str(df.iloc[num].name[2])
    elif num >= baseln and num < baseln**2:
        xlcol = str(df.iloc[num].name[1])+str(df.iloc[num].name[2])
    else:
        xlcol = str(df.iloc[num].name[0])+str(df.iloc[num].name[1])+str(df.iloc[num].name[2])

    return xlcol

0
Viren Desai 22 Juli 2019 im 19:19

Ich liebe Maritineaus Antwort, da der Code einfach und leicht zu befolgen ist. Aber es kann nicht mit der Spaltennummer umgehen, die größer als 26 ** 2 + 26 ist. Also ändere ich einen Teil davon.

def excel_col(col):
    """Covert 1-relative column number to excel-style column label."""
    quot, rem = divmod(col-1,26)
    return excel_col(quot) + chr(rem+ord('A')) if col!=0 else ''



if __name__=='__main__':
    for i in [1, 26, 27, 26**3+26**2+26]:
        print 'excel_col({0}) -> {1}'.format(i, excel_col(i))

Ergebnisse

excel_col(1) -> A
excel_col(26) -> Z
excel_col(27) -> AA
excel_col(18278) -> ZZZ
8
Ken T 21 Juli 2014 im 09:41

Benutze diesen Code:

def xlscol(colnum):
    a = []
    while colnum:
        colnum, remainder = divmod(colnum - 1, 26)
        a.append(remainder)
    a.reverse()
    return ''.join([chr(n + ord('A')) for n in a])
0
Taher Khorshidi 12 März 2016 im 08:40

Sie haben einige Indexprobleme:

Um Ihr Problem zu beheben, müssen alle Indizes übereinstimmen:

def colToExcel(col): # col is 1 based
    excelCol = str()
    div = col 
    while div:
        (div, mod) = divmod(div-1, 26) # will return (x, 0 .. 25)
        excelCol = chr(mod + 65) + excelCol

    return excelCol

print colToExcel(1) # => A
print colToExcel(26) # => Z
print colToExcel(27) # => AA
print colToExcel(104) # => CZ
print colToExcel(26**3+26**2+26) # => ZZZ
13
Nodebody 3 Okt. 2013 im 08:56

Ich glaube, ich habe es herausgefunden. divmod (104,26) ergibt mod = 0, was chr (0 + 64) = 64 bedeutet, dh '@'.

Wenn ich diese Zeile vor column_label "mod=26 if mod==0 else mod" hinzufüge Ich denke, es sollte gut funktionieren

column_label=''
div=104
while div:
    (div, mod) = divmod(div, 26)
    mod=26 if mod==0 else mod
    column_label = chr(mod + 64) + column_label

print column_label
0
saun jean 3 Okt. 2013 im 08:31