将电子表格中的数字转换为列字母

57

你在Python中试过了吗? - sundar nataraj
@sundar nataraj 我确实试过了。我在这里尝试了这段代码:http://bytes.com/topic/python/answers/45129-convert-numbers-letters 。我试了其中的几个例子。但由于该网站组织得如此混乱,我无法弄清哪些代码有效,哪些无效。即使是那个页面上得到答案的人也无法弄清楚。 - jason
18个回答

111
start_index = 1   #  it can start either at 0 or at 1
letter = ''
while column_int > 25 + start_index:   
    letter += chr(65 + int((column_int-start_index)/26) - 1)
    column_int = column_int - (int((column_int-start_index)/26))*26
letter += chr(65 - start_index + (int(column_int)))

1
有没有想过如何将这个例子修改为基于0而不是1的解决方案?A-> 0,B-> 1 .... 到目前为止我的修改:在while循环之前加上n += 1 - RandomDude
从n += 1开始可能是最简单的方法。没有“0”的符号,因此它不是正常的26进制系统。在十进制中,“20”表示2 * 10 + 0 * 1。在电子表格中,您无法表示2 * 26 + 0 * 1。您必须使用1 * 26 + 26 * 1,即“AZ”。请参见https://paradise.caltech.edu/ist4/lectures/foster%201947%20decimal%20no%20zero%20number%20system.pdf。 - Jonathan Richards
3
字符串是不可变的,因此,在字符串前面添加内容是很昂贵的,因为所有内容都必须移动。考虑使用可变的替代方案,如 list 并转换为字符串 "".join(lst) - Brayoni
1
对于 column_int = 4000,它给了我 ÙV,这相当不寻常 :) - Piotr Wasilewicz
是的,这个只能工作到ZZ,然后就会出问题。 - egor83
我建议避免使用这个方法,因为它只能处理两个字母以内的列(例如,ZZ是可以的,但对于AAA就会失败)。如果你确定你的列数不会超过700列,那么使用这个方法是可以的,但是使用xlsxwriter.utility.xl_col_to_name更加通用。 - Marc Stogaitis

59

xlsxwriter库包括一个转换函数xlsxwriter.utility.xl_col_to_name(index),并且在github上。下面是一个工作示例:

>>> import xlsxwriter 
>>> xlsxwriter.utility.xl_col_to_name(10)
'K'
>>> xlsxwriter.utility.xl_col_to_name(1)
'B'
>>> xlsxwriter.utility.xl_col_to_name(0)
'A'

需要注意的是,它使用了从零开始的索引。


7
这个库很棒,使用一个已经被广泛应用的库比自己写代码是一个好主意。 - rebrec
+1,但是 xlsxwriter.utility.xl_col_to_name(28) 给出的是 AC 而不是 AB,通过将输入数字减去 1 可以得到预期输出 AB,但您知道为什么会发生这种情况吗? - akash karothiya
4
xlsxwriter使用基于0的索引(Python也是如此)。 - Dnaiel
1
此外,xlrd 库有一个 conversion function: xlrd.formula.colname(0) 返回 'A' - Giancarlo Sportelli

37

openpyxl库包括您正在寻找的转换函数(以及其他函数),get_column_letter:

>>> from openpyxl.utils.cell import get_column_letter
>>> get_column_letter(1)
'A'
>>> get_column_letter(10)
'J'
>>> get_column_letter(3423)
'EAQ'

19

我对此的处理方式受到另一个关于任意进制转换的答案的启发(https://dev59.com/kXI95IYBdhLWcg3w_zMN#24763277)

def n2a(n):
    d, m = divmod(n,26) # 26 is the number of ASCII letters
    return '' if n < 0 else n2a(d-1)+chr(m+65) # chr(65) = 'A'

例子:

print (-1,n2a(-1))
print (0,n2a(0))
for i in range(23,30):
    print (i,n2a(i))

输出

-1
0 A
23 X
24 Y
25 Z
26 AA
27 AB
28 AC
29 AD

编辑:我添加了n2a(0)来澄清它是从零开始的。我还稍微修改了函数,以避免在给定负数时出现无限递归。

1
简洁且从零开始! - Wayne
2
请注意,此索引是从零开始的! - Asclepius
我添加了n2a(0)以澄清它是从零开始的。 - Giancarlo Sportelli

10

在 Meta 的狠心敲打下进行了修改

这个过程需要将数字除以 26,直到你得到一个小于 26 的数字为止,每次取余数并加上 65,因为在 ASCII 表 中,65 是 'A' 所在的位置。如果你不明白,请阅读有关 ASCII 的相关知识。

请注意,与原始链接的问题一样,这是基于1的而不是基于0的,因此 A -> 1B -> 2

def num_to_col_letters(num):
    letters = ''
    while num:
        mod = (num - 1) % 26
        letters += chr(mod + 65)
        num = (num - 1) // 26
    return ''.join(reversed(letters))

示例输出:

for i in range(1, 53):
    print(i, num_to_col_letters(i))
1 A
2 B
3 C
4 D
...
25 Y
26 Z
27 AA
28 AB
29 AC
...
47 AU
48 AV
49 AW
50 AX
51 AY
52 AZ

5
num_to_col_letters(26) 的输出结果是错误的,它输出了 "A@" - jspurim
1
我看到了@coldfix提出的编辑 - 这个答案不起作用,一个工作版本被善意地提出作为编辑。为了充分披露:我不确定如何处理这个问题,所以在meta上问了这个问题。无论如何 - 我的建议是将编辑作为新答案添加 - 或者原始答案应该查看那个编辑,并决定是否更改此答案。 - J Richard Snape
1
PS:用户1344186的回答使用类似的方法,在这些边缘情况下可以正常工作。 - J Richard Snape
2
@JRichardSnape 我同意我的答案基本上是错误的,而且编辑更多地提供了一个全新的算法,而不是修复我的一些小问题。 - Marius
2
@jason_cant_code似乎仍在网站上活跃,也许可以说服他们切换接受的答案。 - Marius
显示剩余3条评论

9

对于仍然对此感兴趣的人。由@Marius选择的答案在某些情况下会给出错误的输出,如@jspurim所评论的那样。以下是我的答案。

import string
def convertToTitle(num):
    title = ''
    alist = string.uppercase
    while num:
        mod = (num-1) % 26
        num = int((num - mod) / 26)  
        title += alist[mod]
    return title[::-1]

5

不借助任何库的递归一行解决方案

def column(num, res = ''):
   return column((num - 1) // 26, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[(num - 1) % 26] + res) if num > 0 else res

3

递归实现

import string
def spreadsheet_column_encoding_reverse_recursive(x):
    def converter(x):
        return (
            ""
            if x == 0
            else converter((x - 1) // 26) + string.ascii_uppercase[(x - 1) % 26]
        )

    return converter(x)

迭代实现

第一版本:使用 chrord 函数。

def spreadsheet_column_encoding_reverse_iterative(x):
    s = list()

    while x:
        x -= 1
        s.append(chr(ord("A") + x % 26))
        x //= 26

    return "".join(reversed(s))

版本 2:使用 string.ascii_uppercase

import string
def spreadsheet_column_encoding_reverse_iterative(x):
    s = list()

    while x:
        x -= 1
        s.append(string.ascii_uppercase[x % 26])
        x //= 26

    return "".join(reversed(s))

版本 3: 使用 divmod, chr, ord

def spreadsheet_column_encoding_reverse_iterative(x):
    s = list()

    while x:
        x, remainder = divmod(x - 1, 26)
        s.append(chr(ord("A") + remainder))

    return "".join(reversed(s))

2
def _column(aInt):
    return chr((aInt - 1) // 26 + 64) + chr((aInt - 1) % 26 + 1 + 64) if aInt > 26 else chr(aInt + 64)
    
print _column(1)
print _column(27)
print _column(50)
print _column(100)
print _column(260)
print _column(270)

Output: A AA AX CV IZ JJ


1
这个简单的Python函数适用于只有1或2个字母的列。
def let(num):       

alphabeth = string.uppercase
na = len(alphabeth)

if num <= len(alphabeth):
    letters = alphabeth[num-1]
else:
    letters = alphabeth[ ((num-1) / na) - 1 ] +  alphabeth[((num-1) % na)]            

return letters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接