Excelの列名(A1, B1, …)を計算する方法

多くのプログラマーが出会う難問「Excelで列番号からA1形式の列名への変換」。VBA なら ConvertFomula メソッドを使ったりして実現できなくもないですが、文字列を切り出したりしなければならず、エレガントな方法とは言えない気がします。かといって、計算だけで求めようとすると頭がこんがらがってしまうことになりかねません。

難しい理由

なぜこの計算が難しいのかというと、列名には 0(ゼロ)の概念がないことに原因があります。Z 列の次が AA 列 であり、 “A” が “1” を表すものだとすると桁が上がった瞬間に 1 の位が “0” ではなく “1” になったようなものです。” “(空白)が “0” とするなら “Z” の次は “A “(エー・空白)になるべきなのです。とはいえ、普通に Excel を使う場合に列名に空白が入るのも不便なので、実用上は今の Excel の仕様が良いのでしょう。

計算方法

分かりやすさのためにループで計算すると、こんな感じのコードでいけるかもしれません。

def get_column_name(column):

    chars = ' ' + string.ascii_uppercase
    idx = [0, 0, 0]

    while column > 0:
        idx[2] += 1
        for i in range(0, 2, 1):
            if idx[2 - i] >= len(chars):
                idx[2 - i - 1] += 1
                idx[2 - i] = 1
        column -= 1

    return ''.join([chars[i] for i in idx]).strip()

Pythonにて恐縮です。必要ならVBAなどに読み替えてもらえればと思います。改行が意味を持っているところなど、Python と VBA にも共通点はあるかなと感じる今日この頃です。

chars = ' ' + string.ascii_uppercase

ここでは、” ” と “A” から “Z” までのアルファベットを一連の文字列として並べて、0 から 26 に対応した文字を取得できるようにしています。

idx = [0, 0, 0]

これは各桁の値を保持します。Excelの列は3桁が最大なので、要素が3つあります。左が上位、右が下位の桁に対応します。

while column > 0:
    idx[2] += 1
    # (中略)
    column -= 1

column は求めたい列の番号として与えられたパラメーターです。この値が 0 になるまで繰り返すことで列名を求めます。idx[2] += 1 は、最下位の桁に 1 を加える処理です。

for i in range(0, 2, 1):
   if idx[2 - i] >= len(chars):
       idx[2 - i - 1] += 1
       idx[2 - i] = 1

ここがポイントの「桁上がり処理」です。下位桁から順に”Z”を超えていないかチェックをします。”Z” を超えている場合、1つ上の桁に 1 を加えて、その桁を “1” に戻します。ここで “0” ではなく “1” に戻すのが算数・数学とは異なるポイントです。

そんなこんなで冒頭紹介したコードを使うと列番号から列名を計算することができます。もっと効率よくするなら、場合分けを使えば除算と剰余算で計算することもできると思います。