🧮

26進数を使って列番号をExcelの列コードに変換する【C & Python】

2023/06/01に公開

Excelの列コードのような数え方の名前

Excelの列コードのようにA~Zまで行ったらAA~AZ, BA~BZ, ZA~ZZその次はAAA~みたいに増えていく数え方は「辞書式配列法」と呼ぶらしいです。

考え方

C言語

以下のサイトで実際に実行できます
https://paiza.io/projects/firg2mv7z1eQphs3gzIpIA?language=c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(void)
{
    int Line = 702;                     // 列番号。Excelだと 895はAHK, 702はZZ になるはず。
 
    div_t QuotAndRem;                   // 商と余りが入る構造体
    int Remainder[256] = {};            // 余りが計算された順に1文字ずつ格納される配列
    int Quotient = 0;                   // 商
    int ArraySize = 0;                  // 余りが格納された配列Remainderの個数(終端記号は含まない)
    int i = 0;
    int j = 0;
 
    int Num[256] = {};                  // 前後順番を入れ替えられたRemainderが格納される配列
    char Word[256] = {};                // Excelの列ワード
 
 
    QuotAndRem = div(Line, 26);         // 列番号を26で割った商と余りを構造体に入れる
    Remainder[0] = QuotAndRem.rem;      // 構造体から余りを代入
    Quotient = QuotAndRem.quot;         // 構造体から商を代入
 
    // 商が0になるまでループ
    while (Quotient != 0)
    {
        i++;
        QuotAndRem = div(Quotient, 26);     // 列番号を26で割った商と余りを構造体に入れる
        Remainder[i] = QuotAndRem.rem;      // 構造体から余りを配列に追加
        Quotient = QuotAndRem.quot;         // 構造体から商を代入
    }
 
    ArraySize = i + 1;                      // 余りが格納されている配列の数
 
    ///////////////////////////// 余りが0になってしまった時の処理 はじまり /////////////////////////////
    //for (i = 0; i < ArraySize; i++){ fprintf(stdout, "余り0の対策前のRemainder[%d] = %d\n", i, Remainder[i]); }
 
    for (i = 0; i < ArraySize - 1; i++)
    {
        // 余りの桁目が文字に変換できない0だったら
        if (Remainder[i] == 0)
        {
            Remainder[i] = 26;                          // 余りの桁目を26(文字のZ)に変える
            Remainder[i + 1] = Remainder[i + 1] - 1;    // 余りの次の目を1繰り下げる
        }
 
        // 余りの桁目が繰り下げられた-1だったら
        if (Remainder[i] == -1)
        {
            Remainder[i] = 25;                          // 余りの桁目を25(文字のY)に変える
            Remainder[i + 1] = Remainder[i + 1] - 1;    // 余りの次の目を1繰り下げる
        }
 
    }
 
    // もし一番大きい桁の数が0以下だったら
    if (Remainder[ArraySize - 1] <= 0)
    {
        ArraySize--;    // 余りが格納されている配列の数を1減らす
    }
 
    //for (i = 0; i < ArraySize; i++){ fprintf(stdout, "余り0の対策後のRemainder[%d] = %d\n", i, Remainder[i]); }
    ///////////////////////////// 余りが0になってしまった時の処理 おしまい /////////////////////////////
 
 
    // 余りが入れられた配列Remainderを前後入れ替えてNumに格納
    j = ArraySize - 1;
    for (i = 0; i < ArraySize; i++)
    {
        Num[j] = Remainder[i];
        j--;
    }
 
    //for (i = 0; i < ArraySize; i++){ fprintf(stdout, "Num[%d] = %d\n", i, Num[i]); }
 
    // Numをアルファベットに変換してWordに格納 (ASCIIコードでは65がA、66がBになる)
    for (i = 0; i < ArraySize; i++)
    {
        sprintf(&Word[i], "%c", Num[i] + 64);
        fprintf(stdout, "Word[%d] = %c\n", i, Word[i]);
    }
 
    Word[ArraySize] = '\0'; // 配列の終端記号追加
 
    // 答えを表示
    fprintf(stdout, "\nExcelの列番号 %d は %s です!!\n", Line, Word);
 
    return 0;
}

Python

Line = 702
Remainder = []

Remainder.append(int(Line % 26))
Quotient = int(Line // 26)

while 0 != Quotient:
    Remainder.append(int(Quotient % 26))
    Quotient = int(Quotient // 26)

for i in range(0, len(Remainder) - 1):
    # 余りの桁目が文字に変換できない0だったら
    if 0 == Remainder[i]:
        Remainder[i] = 26                           # 余りの桁目を26(文字のZ)に変える
        Remainder[i + 1] = Remainder[i + 1] - 1     # 余りの次の目を1繰り下げる

    # 余りの桁目が繰り下げられた-1だったら
    if -1 == Remainder[i]:
        Remainder[i] = 25                           # 余りの桁目を25(文字のY)に変える
        Remainder[i + 1] = Remainder[i + 1] - 1     # 余りの次の目を1繰り下げる

# もし一番大きい桁の数が0以下だったら要素を消去
if 0 >= Remainder[-1]:
    del Remainder[-1]

# 余りが入れられた配列を逆順にする
Remainder.reverse()
Answer = [chr(Num + 64) for Num in Remainder]

print(Answer)

Discussion