エクセルはセルを「A1」とか「AB10」のように英字の列と数字の行番号で指定するのだけど(A1スタイルと云うのかな)、たまに列番号で指定したいときもある。
ということで、列番号を渡すと列名を返すメソッドを作ってみる。このメソッドがあると、5列目を”E”列のように変換できるので、列番号で指定できるようになる。
この種のメソッドを作るときに間違いやすいのが、1で始まるデータであるところ。上のコードでいえばfor文の3番目の式「c = (c - 1) / 26」を「c /= 26」と書いてしまったりする。そうすると、26が渡されたときにループをもう1回まわってしまって、"AA"に変換されてしまう。正しくは"Z"です。
上のメソッドをテストするのが次のコード。
前の投稿で文字コードのことを調べていたのは、このテストでアルファベット26文字分のテストをループを回して済ませたかったからなのでした。
*
逆に”A”を渡すと1を返すメソッドも作ってみる。
作った時期が違うので、メソッド名も引数もローカル変数名もバラバラですな、なかなか恥ずかしい。
そして単体テストがこちら。
こうしてテストで確認できるようにしてあると、確かに安心。
ということで、列番号を渡すと列名を返すメソッドを作ってみる。このメソッドがあると、5列目を”E”列のように変換できるので、列番号で指定できるようになる。
/// <summary>
/// 列番号からエクセルの列名を得る (例 5 → "E")
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
static public string GetCellA1(int c)
{
string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string s = "";
for (; c > 0; c = (c - 1) / 26 )
{
int n = (c - 1) % 26;
s = alpha.Substring(n, 1) + s;
}
return s;
}
この種のメソッドを作るときに間違いやすいのが、1で始まるデータであるところ。上のコードでいえばfor文の3番目の式「c = (c - 1) / 26」を「c /= 26」と書いてしまったりする。そうすると、26が渡されたときにループをもう1回まわってしまって、"AA"に変換されてしまう。正しくは"Z"です。
上のメソッドをテストするのが次のコード。
[TestMethod()]
public void GetCellA1Test()
{
Assert.AreEqual(ExcelLib.Util.GetCellA1(1), "A");
Assert.AreEqual(ExcelLib.Util.GetCellA1(26), "Z");
Assert.AreEqual(ExcelLib.Util.GetCellA1(27), "AA");
Assert.AreEqual(ExcelLib.Util.GetCellA1(702), "ZZ");
Assert.AreEqual(ExcelLib.Util.GetCellA1(703), "AAA");
for (int i = 1; i <= 26; i++)
{
string s = Convert.ToChar(Convert.ToInt32('A') + i - 1).ToString();
Assert.AreEqual(ExcelLib.Util.GetCellA1(i), s);
}
}
前の投稿で文字コードのことを調べていたのは、このテストでアルファベット26文字分のテストをループを回して済ませたかったからなのでした。
*
逆に”A”を渡すと1を返すメソッドも作ってみる。
/// <summary>
/// エクセルの列名から列番号を得る(例:"A"→1)
/// </summary>
/// <param name="col"></param>
/// <returns></returns>
static public int getExcel列番号(string col)
{
string abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int m = 0;
for (int i = 0; i < col.Length; i++)
{
string c = col.Substring(i, 1);
int n = abc.IndexOf(c) + 1;
m += n * (int)Math.Pow(26, col.Length - i - 1);
}
return m;
}
作った時期が違うので、メソッド名も引数もローカル変数名もバラバラですな、なかなか恥ずかしい。
そして単体テストがこちら。
[TestMethod]
public void Test_getExcel列番号()
{
Assert.AreEqual(mmExcel.getExcel列番号("A"), 1);
Assert.AreEqual(mmExcel.getExcel列番号("B"), 2);
Assert.AreEqual(mmExcel.getExcel列番号("C"), 3);
Assert.AreEqual(mmExcel.getExcel列番号("AA"), 27);
Assert.AreEqual(mmExcel.getExcel列番号("AAA"), 703); // 26 * 27 + 1 = 26 * (26 + 1) + 1
int c = Convert.ToInt32('A');
for (int i = 0; i < 26; i++)
{
string s = Convert.ToChar(c + i).ToString();
Assert.AreEqual(mmExcel.getExcel列番号(s), i + 1);
}
}
こうしてテストで確認できるようにしてあると、確かに安心。

コメント
コメントを投稿