我正在尝试用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
答案 0 :(得分:1)
我将回答您的具体问题:
...这个用于计算excel列字符的Microsoft算法不正确吗?
是即可。
一般来说,当你想要两个数的整数除法(通常称为DIV
)和其余的(通常称为MOD
)时,你应该使用与分母相同的值。因此,你应该在两个地方使用26或27。
因此,算法不正确(很容易看到iCol=27
,iAlpha=1
和iRemainder=1
,而iRemainder=0
}。
在这种特殊情况下,数字应为26.因为这会给你从零开始的数字,你应该添加ascii("A")
(= 65),一般来说,而不是64.双重错误使它工作对于某些情况。
(几乎不可接受)混淆可能源于这样一个事实:从A
到Z
有26列,从A
到ZZ
有26 * 27从A
到ZZZ
的列有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。