したいこと
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; } }