Get Excel-Style Column Names from Column Number

匿名 (未验证) 提交于 2019-12-03 01:10:02

问题:

This is the code for providing the COLUMN name when the row and col ID is provided but when I give values like row = 1 and col = 104, it should return CZ, but it returns 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 

What is wrong with what I am doing?

(This code is in reference for EXCEL Columns, where I provide the Row,Column ID value and expect the ALPHABETIC value for the same.)

回答1:

EDIT: I feel I must admit, as pointed out by a few others―who never left me comments―that the previous version of my answer (which you accepted) had a bug that prevented it from properly handling column numbers greater than 702 (corresponding to Excel column 'ZZ'). So, in the interests of correctness, that's been fixed in the code below, which now contains a loop just like many of the other answers do.

It's quite likely you never used the previous version with large enough column numbers to have encountered the issue. FWIW, the MS specs for the current version of Excel say it supports worksheets with up to 16,384 columns (Excel column 'XFD').

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

Output:

(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' 


回答2:

You have a couple of index issues:

So to fix your problem, you need to make all your indices match:

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 


回答3:

I love maritineau's answer since its code looks plain and easy to follow. But it can't handle the column number which is greater than 26**2 + 26. So I modify part of it.

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

Results

excel_col(1) -> A excel_col(26) -> Z excel_col(27) -> AA excel_col(18278) -> ZZZ 


回答4:

I think it is something like this :

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

Some 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' 


回答5:

I think i figured it out. divmod(104,26) gives mod=0 which makes chr(0+64) = 64 ie '@'.

if i add this line before column_label "mod=26 if mod==0 else mod" i think it should work fine

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 


回答6:

use this 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]) 


回答7:

def ColNum2ColName(n):    convertString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    base = 26    i = n - 1     if i 

EDIT: Right, right zondo.

I just approached A, B, .. AA, AB, ... as a numeric base with digits A-Z.

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

It's an easy way without any while loop etc. and works for any number > 0.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!