我错过了什么或者这个用于计算excel列字符的Microsoft算法不正确?

时间:2013-12-12 16:27:37

标签: python excel vba

我正在尝试用Python编写一个函数,它接受一个列号并输出相应的Excel列代码(例如:5 - >“E”,27 - >“AA”)。我尝试实现这里给出的算法:http://support.microsoft.com/kb/833402,这是以下的视觉基础:

Function ConvertToLetter(iCol As Integer) As String
   Dim iAlpha As Integer
   Dim iRemainder As Integer
   iAlpha = Int(iCol / 27)
   iRemainder = iCol - (iAlpha * 26)
   If iAlpha > 0 Then
      ConvertToLetter = Chr(iAlpha + 64)
   End If
   If iRemainder > 0 Then
      ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64)
   End If
End Function

我的python版本:

def excelcolumn(colnum):
    alpha = colnum // 27
    remainder = colnum - (alpha*26)
    out = ""
    if alpha > 0:
        out = chr(alpha+64) 
    if remainder > 0:
        out = out + chr(remainder+64) 
    return out

这可以正常工作,直到第53列,这导致“A [”,alpha = 53 // 27 == 1,因此remainder = 53 - 1*26 == 27意味着第二个字符chr(64+27)将为“[”。我错过了什么吗?我的VBA技能非常低迷,因此可能是问题所在。

编辑:我正在使用Python 3.3.1

3 个答案:

答案 0 :(得分:1)

我将回答您的具体问题:

...这个用于计算excel列字符的Microsoft算法不正确吗?

即可。 一般来说,当你想要两个数的整数除法(通常称为DIV)和其余的(通常称为MOD)时,你应该使用与分母相同的值。因此,你应该在两个地方使用26或27。

因此,算法不正确(很容易看到iCol=27iAlpha=1iRemainder=1,而iRemainder=0}。

在这种特殊情况下,数字应为26.因为这会给你从零开始的数字,你应该添加ascii("A")(= 65),一般来说,而不是64.双重错误使它工作对于某些情况。

(几乎不可接受)混淆可能源于这样一个事实:从AZ有26列,从AZZ有26 * 27从AZZZ的列有26 * 27 * 27列,依此类推。

适用于任何列的代码,非递归

def excelcolumn(colnum):
    if colnum < 1:
        raise ValueError("Index is too small")
    result = ""
    while True:
        if colnum > 26:
            colnum, r = divmod(colnum - 1, 26)
            result = chr(r + ord('A')) + result
        else:
            return chr(colnum + ord('A') - 1) + result

(摘自here)。

答案 1 :(得分:1)

Microsoft公式不正确。我敢打赌,他们从来没有测试过超过53.当我在Excel中自己测试时,它给出了与你相同的错误答案。

我是这样做的:

def excelcolumn(colnum):
    alpha, remainder = colnum // 26, colnum % 26
    out = "" if alpha == 0 else chr(alpha - 1 + ord('A'))
    out += chr(remainder + ord('A'))
    return out

这不是假定基于0的列号,而VBA代码假设从1开始。

如果您需要延伸到701列以外,您需要一些略有不同的内容,如评论中所述:

def excelcolumn(colnum):
    if colnum < 26:
        return chr(colnum + ord('A'))
    return excelcolumn(colnum // 26 - 1) + chr(colnum % 26 + ord('A'))

答案 2 :(得分:1)

这是一种方法:

def xl_col_to_name(col_num):
    col_str = ''

    while col_num:
        remainder = col_num % 26

        if remainder == 0:
            remainder = 26

        # Convert the remainder to a character.
        col_letter = chr(ord('A') + remainder - 1)

        # Accumulate the column letters, right to left.
        col_str = col_letter + col_str

        # Get the next order of magnitude.
        col_num = int((col_num - 1) / 26)

    return col_str

给出了:

>>> xl_col_to_name(5)
'E'
>>> xl_col_to_name(27)
'AA'
>>> xl_col_to_name(256)
'IV'
>>> xl_col_to_name(1000)
'ALL'

这取自XlsxWriter模块中的utility functions