【问题标题】:Get the Excel column label (A, B, ..., Z, AA, ..., AZ, BA, ..., ZZ, AAA, AAB, ...)获取 Excel 列标签(A、B、...、Z、AA、...、AZ、BA、...、ZZ、AAA、AAB、...)
【发布时间】:2022-11-18 11:36:06
【问题描述】:

给定 Excel 列标题的字母,我需要输出列号。

它是A-Z,然后是AA-AZ,然后是BA-BZ,依此类推。

我想像以 26 为底数一样通过它,我只是不知道如何实现它。

它适用于像AA这样的简单对象,因为26^0 = 1 + 26^1 = 26 = 27

但是对于ZA,如果我做26 ^ 26(z 是第 26 个字母),输出显然太大了。我错过了什么?

【问题讨论】:

  • 您需要乘以 26,而不是乘以 的幂。
  • 它恰好是一个以 26 为基数的数字。ZZ 为 26 * 26 + 26,即 702。

标签: python excel base


【解决方案1】:

如果我们将“A”解码为 0,“B”解码为 1,...那么“Z”为 25,“AA”为 26。

所以它不是纯 26 基编码,因为前缀“A”对值没有影响,“AAAB”必须与“B”相同,就像在十进制系统中 0001 一样到 1. 但这里不是这种情况。

“AA”的值为1*261个+ 0, "ZA" 为 26*261个+ 0。

我们可以概括地说,“A”的值应为 1,“B”的值应为 2,...等(单个字母编码除外)。所以在“AAA”中,最右边的“A”代表一个系数为0,而其他的“A”代表一个:1*262个+ 1*261个+ 0

这导致以下代码:

def decode(code):
    val = 0
    for ch in code: # base-26 decoding "plus 1"
        val = val * 26 + ord(ch) - ord("A") + 1 
    return val - 1

当然,如果我们希望列号以 1 而不是 0 开头,那么只需将最后的语句替换为:

return val

【讨论】:

    【解决方案2】:

    权力之和

    您可以对 26 的幂的倍数求和:

    def xl2int(s):
        s = s.strip().upper()
        return sum((ord(c)-ord('A')+1)*26**i
                   for i,c in enumerate(reversed(s)))
    
    xl2int('A')
    # 1
    
    xl2int('Z')
    # 26
    
    xl2int('AA')
    # 27
    
    xl2int('ZZ')
    # 702
    
    xl2int('AAA')
    # 703
    

    int内置

    您可以使用字符串转换表和带有 base 参数的内置 int

    因为你有一个破损的基础,你需要为长度为 n 的输入添加 26**n+26**(n-1)+...+26**0,你可以通过 int('11...1', base=26) 获得它与输入字符串的长度一样多的 1。

    from string import ascii_uppercase, digits
    t = str.maketrans(dict(zip(ascii_uppercase, digits+ascii_uppercase)))
    
    def xl2int(s):
        s = s.strip().upper().translate(t)
        return int(s, base=26)+int('1'*len(s), base=26)
    
    xl2int('A')
    # 1
    
    xl2int('Z')
    # 26
    
    xl2int('AA')
    # 27
    
    xl2int('ZZ')
    # 702
    
    xl2int('AAA')
    # 703
    

    翻译工作原理

    它移动每个字符,以便 A -> 0,B -> 1...J -> 9,K -> A...Z -> P。然后使用 int 将其转换为整数。然而,获得的数字是不正确的,因为我们缺少数字中每个数字位置的 26**x,因此我们添加与输入中的数字一样多的 26 次方。

    【讨论】:

      【解决方案3】:

      另一种方法,用 VBA 编写:

      Function nColumn(sColumn As String) As Integer
      
      ' Return column number for a given column letter.
      
      ' 676 = 26^2
      ' 64 = Asc("A") - 1
      
      nColumn = _
          (IIf(Len(sColumn) < 3, 0, Asc(Left(      sColumn    , 1)) - 64) * 676) + _
          (IIf(Len(sColumn) = 1, 0, Asc(Left(Right(sColumn, 2), 1)) - 64) * 26) + _
                                   (Asc(     Right(sColumn    , 1)) - 64)
      
      End Function
      

      或者您可以直接在工作表中进行:

      =(if(len(<clm>) < 3, 0, code(left(      <clm>    , 1)) - 64) * 676) + 
       (if(len(<clm>) = 1, 0, code(left(right(<clm>, 2), 1)) - 64) * 26) + 
                             (code(     right(<clm>    , 1)) - 64)
      

      我还发布了the inverse operation done similarly

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-25
        • 1970-01-01
        • 2018-09-07
        相关资源
        最近更新 更多