VSTO中Excel数字和列名相互转换

Excel的列名是字母。但有时候,需要通过数字得到列名或者通过列名得到第几列。

这里有两种方法。一种是通过列名或数字计算;一种通过Range对象转换。

方法1:

Excel列名命名是用字母命名。从A到Z,Z之后是AA,变成两个字母。一共有26个字母,相当于26进制。

我们使用的数字是10进制,数字和列名转换相当于10进制和26进制互转。

不过,这里的26进制有点奇怪。不是普通意义上的26进制。

假如A代表0,而AA应该对应10。这里两个A代表的数字不同。十位上的A是1,个位上的A是0。这个对计算造成不少麻烦。我看过网上其他代码,对这个问题处理不是很好,计算繁琐。

需要对可以整数的部分进行处理,看如下代码:

//数字转列名
public string GetColumnNameByNum(int intColNum, string col = "")
{
    if(intColNum > 26)
    {
        int mod = intColNum % 26;    //余数
        int rel = intColNum / 26;    //除数结果
        
        //处理整除的数字
        if(mod == 0)
        {
            mod = 26; //0对应26,即为Z
            rel -= 1; //高位的数字退1位
        }
        
        //递归转换
        return GetColumnNameByNum(rel, ((char)(mod + 64).ToString() + col);
    }
    else
    {
        return ((char)(intColNum + 64).ToString() + col;
    }
}

测试的时候,测试1,26,27,52,53能否转成对应的A,Z,AA,AZ,BA等列名。

列名转数字就相对简单很多,直接利用进制转换原理计算即可。

//列名转数字
public int GetColumnNumByName(string strColumnName)
{
    strColumnName = strColumnName.ToUpper();
    int length = strColumnName.Length;
    int colNum = 0;
    
    for (int i = 0; i < length; i++)
    {
        colNum += (strColumnName[i] - 64) * 26 ^ (length - i - 1);
    }
    return colNum;
}

其中,字符串索引得到char字符。char字符可以直接参与计算。

同样再测试A,Z,AA,AZ,BA等列名能否转成对应的1,26,27,52,53。

方法2:

还有一种方法可以直接通过Range对象的Address属性和Column属性获取。

先导入引用:

using Excel = Microsoft.Office.Interop.Excel;

数字转列名相互转换的代码如下:

//数字转列名
public string GetColumnNameByNum(int intColNum)
{
    //获取单元格
    string address = Globals.ThisAddIn.Application.Cells.get_Address(1, intColNum);
    
    //找到第2个$的位置
    int find = address.IndexOf('$', 1);
    return address.Substring(1, find - 1);
}

//列名转数字
public int GetColumnNumByName(string strColumnName)
{
    Excel.Range rng = Globals.ThisAddIn.Application.Range[strColumnName + "1"];
    return rng.Column; //直接返回对应列
}

这两种方法看起来第2中方法代码比较少。

建议用第1种,因为第1种方法计算比较快。第2种方法,需要当前工作簿有打开一个文件才可以使用,且计算慢。

评论列表

暂无评论,欢迎来抢沙发!

新的评论

清空