简体   繁体   English

将电子表格编号转换为列字母

[英]Convert spreadsheet number to column letter

I'm looking for the opposite to this Q&A: Convert an excel or spreadsheet column letter to its number in Pythonic fashion .我正在寻找与此问答相反的内容: Convert an excel or spreadsheet column letter to its number in Pythonic fashion

or this one but in python How to convert a column number (eg. 127) into an excel column (eg. AA)或这个但在 python 如何将列号(例如 127)转换为 excel 列(例如 AA)

def colnum_string(n):
    string = ""
    while n > 0:
        n, remainder = divmod(n - 1, 26)
        string = chr(65 + remainder) + string
    return string

print(colnum_string(28))
#output:AB

The xlsxwriter library includes a conversion function, xlsxwriter.utility.xl_col_to_name(index) and is on github xlsxwriter库包含一个转换函数xlsxwriter.utility.xl_col_to_name(index)并且在github 上

here is a working example:这是一个工作示例:

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

Notice that it's using zero-indexing.请注意,它使用零索引。

The openpyxl library includes the conversion function (amongst others) which you are looking for, get_column_letter : 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'

My recipe for this was inspired by another answer on arbitrary base conversion ( https://stackoverflow.com/a/24763277/3163607 )我的配方灵感来自另一个关于任意基础转换的答案( https://stackoverflow.com/a/24763277/3163607

import string

def n2a(n,b=string.ascii_uppercase):
   d, m = divmod(n,len(b))
   return n2a(d-1,b)+b[m] if d else b[m]

Example:例子:

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

outputs产出

23 X
24 Y
25 Z
26 AA
27 AB
28 AC
29 AD

Edited after some tough love from Meta在 Meta 的一些艰难的爱之后编辑

The procedure for this involves dividing the number by 26 until you've reached a number less than 26, taking the remainder each time and adding 65, since 65 is where 'A' is in the ASCII table .此过程涉及将数字除以 26,直到达到小于 26 的数字,每次取余数并添加 65,因为 65 是 'A' 在ASCII 表中的位置 Read up on ASCII if that doesn't make sense to you.如果这对您没有意义,请阅读 ASCII。

Note that like the originally linked question , this is 1-based rather than zero-based, so A -> 1 , B -> 2 .请注意,与最初链接的 question 一样,这是基于 1 而不是基于零的,因此A -> 1 , B -> 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))

Example output:示例输出:

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

Just for people still interest in this.只是为了人们仍然对此感兴趣。 The chosen answer by @Marius gives wrong outputs in some cases, as commented by @jspurim.正如@jspurim 所评论的那样,@Marius 选择的答案在某些情况下会给出错误的输出。 Here is the my answer.这是我的答案。

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]

Recursive one line solution w/o libraries没有库的递归单行解决方案

def column(num, res = ''):
   return column((num - 1) // 26, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[(num - 1) % 26] + res) if num > 0 else res
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(50)
print _column(100)
print _column(260)
print _column(270)

Output: A AX CV IZ JJ输出:A AX CV IZ JJ

This simple Python function works for columns with 1 or 2 letters.这个简单的 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

Here is a recursive solution:这是一个递归解决方案:

def column_num_to_string(n):
    n, rem = divmod(n - 1, 26)
    char = chr(65 + rem)
    if n:
        return column_num_to_string(n) + char
    else:
        return char

column_num_to_string(28)
#output: 'AB'

The inverse can also be defined recursively, in a similar way:逆也可以以类似的方式递归定义:

def column_string_to_num(s):
    n = ord(s[-1]) - 64
    if s[:-1]:
        return 26 * (column_string_to_num(s[:-1])) + n
    else:
        return n
    
column_string_to_num("AB")
#output: 28

Just to complicate everything a little bit I added caching, so the name of the same column will be calculated only once.只是为了使一切复杂化,我添加了缓存,因此同一列的名称将只计算一次。 The solution is based on a recipe by @Alex Benfica该解决方案基于@Alex Benfica 的食谱

import string


class ColumnName(dict):
    def __init__(self):
        super(ColumnName, self).__init__()
        self.alphabet = string.uppercase
        self.alphabet_size = len(self.alphabet)

    def __missing__(self, column_number):
        ret = self[column_number] = self.get_column_name(column_number)
        return ret

    def get_column_name(self, column_number):
        if column_number <= self.alphabet_size:
            return self.alphabet[column_number - 1]
        else:
            return self.alphabet[((column_number - 1) / self.alphabet_size) - 1] + self.alphabet[((column_number - 1) % self.alphabet_size)]

Usage example:用法示例:

column = ColumnName()

for cn in range(1, 40):
    print column[cn]

for cn in range(1, 50):
    print column[cn]
import math

num = 3500
row_number = str(math.ceil(num / 702))
letters = ''
num = num - 702 * math.floor(num / 702)
while num:
    mod = (num - 1) % 26
    letters += chr(mod + 65)
    num = (num - 1) // 26
result = row_number + ("".join(reversed(letters)))
print(result)

Recursive Implementation递归实现

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)

Iterative Implementations迭代实现

Version 1 : uses chr , ord版本 1 : 使用chr , ord

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

Version 2 : Uses string.ascii_uppercase版本 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))

Version 3 : Uses divmod , chr , ord版本 3 :使用divmodchrord

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

def letter2num(col_letter: str) -> int:
    row_num, col_num = gspread.utils.a1_to_rowcol(col_letter + '1')
    return col_num


def num2letter(col_num: int) -> str:
    return gspread.utils.rowcol_to_a1(1, col_num)[:-1]


# letter2num('D') => returns 4
# num2letter(4) => returns 'D'

an easy to understand solution:一个易于理解的解决方案:

def gen_excel_column_name(col_idx, dict_size=26):
    """generate column name for excel

    Args:
        col_idx (int): column index, 1 based.
        dict_size (int, optional): NO. of letters to use. Defaults to 26 (A~Z).

    Returns:
        str: column name. e.g. A, B, C, AA, AB, AC
    """
    if col_idx < 1:
        return ''
    
    # determine how many letters in the result
    l = 1  # length of result
    capcity = dict_size  # number of patterns when length is l
    while col_idx > capcity:
        col_idx -= capcity
        l += 1
        capcity *= dict_size

    res = []
    col_idx -= 1 # now col_idx is a dict_size system. when dict_size = 3, l = 2,  col_idx=2 means 02, col_idx=3 means 10 
    while col_idx > 0:
        d = col_idx % dict_size
        res.append(d)
        col_idx = col_idx // dict_size
    # padding leading zeros
    while len(res) < l:
        res.append(0)

    # change digits to letters and reverse
    res = [chr(65 + d) for d in reversed(res)]
    return ''.join(res)

for i in range(1, 42):
    print(i, gen_excel_column_name(i, 3))

part of the output:部分输出:

1 A
2 B
3 C
4 AA
5 AB
6 AC
7 BA
8 BB
9 BC
10 CA
11 CB
12 CC
13 AAA
14 AAB
15 AAC
16 ABA
17 ABB
18 ABC
19 ACA
20 ACB
21 ACC
22 BAA
23 BAB
24 BAC
25 BBA
26 BBB
27 BBC
28 BCA
29 BCB
30 BCC
31 CAA
32 CAB
33 CAC
34 CBA
35 CBB
36 CBC
37 CCA
38 CCB
39 CCC
40 AAAA
41 AAAB

Using xlsxwriter使用 xlsxwriter

import gspread
import numpy as np
import xlsxwriter

.....You code.......

array = np.array(wks.get_all_values())


row_count = 0
col_count = 0
for a in array:
    col_count = 0
    row_count += 1
    for b in a:
        col_count += 1
        print(f"{xlsxwriter.utility.xl_col_to_name(col_count-1)}{row_count} {str(b)}")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM