Excel 欄位編號(A=1, B=2, ..., Z=26, AA=27, AB=28...)本質是 26 進位系統,但無「0」位元。本文實作雙向轉換函式,並分析演算法邏輯與邊界條件。
A=1, B=2, ..., Z=26AA=27, AB=28, ..., AZ=52, BA=53, ..., ZZ=702AAA=703, ...這是一個「不含零的 26 進位」系統,類似 26 進位但每位權重為 26^position,數字範圍 1-26 對應 A-Z。
def col_to_num(col_str):
"""Excel 欄位字母轉數字 (A=1, AA=27...)"""
col_str = col_str.upper().strip()
result = 0
for ch in col_str:
if 'A' <= ch <= 'Z':
result = result * 26 + (ord(ch) - ord('A') + 1)
else:
raise ValueError("無效字元: %s" % ch)
return result
# 測試
print(col_to_num('A')) # 1
print(col_to_num('Z')) # 26
print(col_to_num('AA')) # 27
print(col_to_num('AB')) # 28
print(col_to_num('ZZ')) # 702
print(col_to_num('AAA')) # 703
以 AB 為例:
result = 0result = 0 * 26 + 1 = 1result = 1 * 26 + 2 = 28此即霍納法則(Horner's method)計算多項式:((1)*26 + 2)。
def num_to_col(num):
"""數字轉 Excel 欄位字母 (1=A, 27=AA...)"""
if num < 1:
raise ValueError("數字必須 >= 1")
result = []
while num > 0:
num -= 1 # 關鍵:調整為 0-based
remainder = num % 26
result.append(chr(ord('A') + remainder))
num //= 26
return ''.join(reversed(result))
# 測試
for n in [1, 26, 27, 28, 52, 53, 702, 703, 18278]:
print("%d -> %s" % (n, num_to_col(n)))
# 1 -> A
# 26 -> Z
# 27 -> AA
# 28 -> AB
# 52 -> AZ
# 53 -> BA
# 702 -> ZZ
# 703 -> AAA
# 18278 -> ZZZ
num -= 1因為無「0」位元,1~26 對應 A~Z。標準取模會得到 0~25,故先減 1 再取模:
num=1:0%26=0 → 'A'num=26:25%26=25 → 'Z'num=27:26%26=0 → 'A',num=1 再產生 'A' → AA
# 原文使用字典映射,效率較低且不完整
dict = {'A':1, 'B':2, ...} # 需手動定義 26 個鍵值
def count_(s):
p = len(s) - 1
count = 0
for x in range(len(s)):
count += (26 ** p) * dict[s[p-x]] # 權重計算
p -= 1
return count
缺點:需預建字典、不支援任意長度、程式碼冗長。標準演算法僅需 ord() 運算,O(n) 時間、O(1) 空間。
from openpyxl.utils import column_index_from_string, get_column_letter
# 內建函式
print(column_index_from_string('AA')) # 27
print(get_column_letter(27)) # 'AA'
def col_to_num_robust(col_str):
if not col_str or not isinstance(col_str, basestring):
raise TypeError("輸入必須為非空字串")
col_str = col_str.strip().upper()
if not col_str:
raise ValueError("字串不可為空白")
result = 0
for ch in col_str:
if not 'A' <= ch <= 'Z':
raise ValueError("僅支援 A-Z 字母,發現: %s" % ch)
result = result * 26 + (ord(ch) - 64) # ord('A')=65
return result