したいこと
Excelの列で用いられている26進数風の数列(アルファベットのみ)を計算したい。
26進数風の数列(アルファベットのみ)にて、数値→アルファベット、アルファベット→数値の関数が欲しい。
計算したい理由
エクセルのセルの指定では数値指定できるのですが、一方で、表示はアルファベットのみの数列なので分かりにくいからです。下記の記事で数値でとっていますが、それではわかりにくいなぁと感じました。

VSTO エクセルでクリックしたセルの値を取得したい
したいこと
VSTO エクセルでクリックしたセルの値を取得したい
VSTO エクセルで選択したセルの値を取得するには
結論1 イベントハンドラが必要な場合
現在のシートにイベントハンドラを以下のように追加します。
...
この画像のような、列側のアルファベットの数列です。

元ネタ
調査して、”[C#]エクセルの列名のようなアルファベットを返す関数”を参考にさせていただきました。
ソースコードとテスト
今回はただただコードを晒すだけの記事です。試してみてください。
テストコード(数値→アルファベット)
Assert.AreEqual("A", ExcelUtilityClass.GetColumnString(1), "指定したExcel Column値と異なります");
Assert.AreEqual("B", ExcelUtilityClass.GetColumnString(2), "指定したExcel Column値と異なります");
Assert.AreEqual("Z", ExcelUtilityClass.GetColumnString(26), "指定したExcel Column値と異なります");
Assert.AreEqual("AA", ExcelUtilityClass.GetColumnString(27), "指定したExcel Column値と異なります");
Assert.AreEqual("AZ", ExcelUtilityClass.GetColumnString(52), "指定したExcel Column値と異なります");
Assert.AreEqual("BA", ExcelUtilityClass.GetColumnString(53), "指定したExcel Column値と異なります");
Assert.AreEqual("BZ", ExcelUtilityClass.GetColumnString(78), "指定したExcel Column値と異なります");
Assert.AreEqual("ZZ", ExcelUtilityClass.GetColumnString(702), "指定したExcel Column値と異なります");
Assert.AreEqual("AAA", ExcelUtilityClass.GetColumnString(703), "指定したExcel Column値と異なります");
Assert.AreEqual("AAB", ExcelUtilityClass.GetColumnString(704), "指定したExcel Column値と異なります");
Assert.AreEqual("BAA", ExcelUtilityClass.GetColumnString(1379), "指定したExcel Column値と異なります");
Assert.AreEqual("ZAA", ExcelUtilityClass.GetColumnString(17603), "指定したExcel Column値と異なります");
Assert.AreEqual("ZZY", ExcelUtilityClass.GetColumnString(18277), "指定したExcel Column値と異なります");
Assert.AreEqual("ZZZ", ExcelUtilityClass.GetColumnString(18278), "指定したExcel Column値と異なります");
Assert.AreEqual("AAAA", ExcelUtilityClass.GetColumnString(18279), "指定したExcel Column値と異なります");
テストコード(アルファベット→数値)
Assert.AreEqual(475254, ExcelUtilityClass.GetColumnNumber("ZZZZ"), "指定したExcel Column値と異なります");
Assert.AreEqual(18279, ExcelUtilityClass.GetColumnNumber("AAAA"), "指定したExcel Column値と異なります");
Assert.AreEqual(18278, ExcelUtilityClass.GetColumnNumber("ZZZ"), "指定したExcel Column値と異なります");
Assert.AreEqual(18277, ExcelUtilityClass.GetColumnNumber("ZZY"), "指定したExcel Column値と異なります");
Assert.AreEqual(17603, ExcelUtilityClass.GetColumnNumber("ZAA"), "指定したExcel Column値と異なります");
Assert.AreEqual(1379, ExcelUtilityClass.GetColumnNumber("BAA"), "指定したExcel Column値と異なります");
Assert.AreEqual(1353, ExcelUtilityClass.GetColumnNumber("AZA"), "指定したExcel Column値と異なります");
Assert.AreEqual(703, ExcelUtilityClass.GetColumnNumber("AAA"), "指定したExcel Column値と異なります");
Assert.AreEqual(702, ExcelUtilityClass.GetColumnNumber("ZZ"), "指定したExcel Column値と異なります");
Assert.AreEqual(28, ExcelUtilityClass.GetColumnNumber("AB"), "指定したExcel Column値と異なります");
Assert.AreEqual(27, ExcelUtilityClass.GetColumnNumber("AA"), "指定したExcel Column値と異なります");
Assert.AreEqual(2, ExcelUtilityClass.GetColumnNumber("B"), "指定したExcel Column値と異なります");
Assert.AreEqual(1, ExcelUtilityClass.GetColumnNumber("A"), "指定したExcel Column値と異なります");
ソースコード
public class ExcelUtilityClass
{
/// <summary>
/// 数字 ⇒ Column(列・エクセル)変換
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public static string GetColumnString(int index, int limitDigit = 5)
{
string str = "";
int maxDigit = GetCurDigit(index);
double[] maxPow = GetMaxDigitArray();
for (int i = maxDigit; i >= 0; --i)
{
double pow = 0.0;
pow = Math.Pow(26.0, i);
// 26のi乗の商を計算
double quotient = Math.Floor(index / pow);
if (i != 0)
{
if (-0.000001 <= Math.Floor(index % pow) && Math.Floor(index % pow) <= 0.000001)
{
quotient -= 1;
}
else if (quotient > 26)
{
quotient = 26;
}
}
char curDigit = (char)((int)quotient + 0x40);
str = str + curDigit.ToString();
// 上の桁を計算したので、下の桁へ移行
index = index - (int)(quotient * pow);
}
return str;
}
/// <summary>
/// 現在の桁数
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public static int GetCurDigit(int index)
{
int maxDigit = 20;
double[] maxPow = GetMaxDigitArray();
double[] minPow = new double[maxDigit];
// アルファベット26進の桁の最小値 計算
// ( 例. 3桁なら 26*26 + 26 + 1 = AAA )
minPow[0] = 1;
for (int i = 1; i < minPow.Length; ++i)
{
minPow[i] = maxPow[i - 1] + 1;
}
int curDigit = 0;
// indexが26の何乗か分の桁を持っているかを計算する
for (int i = 0; i < maxPow.Length - 1; ++i)
{
if (minPow[i] <= index && index <= maxPow[i])
{
curDigit = i;
break;
}
}
return curDigit;
}
/// <summary>
/// 最大桁の配列
/// </summary>
/// <returns></returns>
private static double[] GetMaxDigitArray()
{
int maxDigit = 20;
double[] maxPow = new double[maxDigit];
// アルファベット26進の桁の最大値 計算 ( 例. 3桁なら 26*26*26 + 26*26 + 26 = ZZZ)
for (int i = 0; i < maxPow.Length; ++i)
{
maxPow[i] = Math.Pow(26.0, i + 1);
for (int j = i; j > 0; --j)
{
maxPow[i] += Math.Pow(26.0, j);
}
}
return maxPow;
}
/// <summary>
/// Column(列・エクセル) ⇒ 数字 変換
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public static int GetColumnNumber(string str)
{
int digit = str.Length;
// 大文字に変換
str = str.ToUpperInvariant();
int result = 0;
for (int i = 0; i < digit; ++i)
{
char c = Convert.ToChar(str.Substring(i, 1));
int curDigit = c - 0x40;
double pow = Math.Pow(26.0, digit - i - 1);
result += curDigit * (int)pow;
}
return result;
}
}

