已经发现更有效的算法,请参考《Excel中列数字与字母的转换(JAVA实现)》
如果您有兴趣,可以继续阅读!
最近的一个专案中客户有这么一个需求:读取EXCEL档案的时候,需要做一些处理,但当处理某个单元格时如果发生异常需要记录是哪个单元格导致的异常,并且以列标题(字母+数字的)形式表示是哪个单元格 比如是 第7行第6列的单元格出错,则会记录 “F7 XXXX”.
我们都知道JAVA 中有很多工具类可以处理很多类型的文档,比如 Workbook 类。但我发现 该类并没有获取EXCEL中对应的列英文字母标题(字母序号/列标题)的方法 如果我要获取第7行第6列的单元格编号”F7″是行不通的,只能记录 “第7行第6列 XXX” 这样的信息,不直观。所以最后还是决定自己动手实现。目前最主要的任务就是获取 第N列对应的字母序列.
过程:因为字母是26位的,所以我第一印象采取的方式就是,类似10进制转16进制的方法。后来发现,这样行不通,总有些字母序列表示不出来. 最主要是因为 0 这个特殊的数字 0 和 00等同,假设 A代表0 那么 AA代表00 这样在数值上 A和AA相等,但在Excel中 A标识第一列 AA标识的是第27列。
后来我把这些字母序号写在纸上,发现了一个规律,他们都是以26n为一个区块,这样的话,我就看是否能采用类似计算文件系统偏移地址的方式来计算出来。后来成功了!
首先 确定字母有几位
A以0开始的,如果从1开始 则Z为26,给后面两位时计算带来麻烦
因为 A=0 时Z=25 A/26=0 Z/26=0 在一个范围内,
而A=1 时 Z=26 A/26=0 Z/26=1 在两个范围内。
然后我们以26n为一个区块,找出每个区块的 起始地址(应该是对应出现的个数-1) 和 结束地址
发现 N个字母的起始地址为
A0=0 大小26
AA0=26 大小262
AAA0=26*26+26 大小263
AAAA0=26*26*26+26*26+26 大小26n
A(n)A0=26n-1+26n-2…+26=26*(26n-1)/25 (等比数列求和)大家可以在纸上按以上的分法画出区块图!
这样便可以计算出有几个字母了-》公式: n= (log25*num/26+1)/log26的整数部分+1
然后我们找出num对应最大区块的偏移(多出字母标题的个数)sub= num-26*(26n-1-1)/25;
这时便可以算出第一个字母是什么 An=sub/26n-1 因为多出来的部分会包含若干个前面的区块
对于求后面的An-1 也要先算出偏移 这里用求余也可以算出 sub=sub%26n-1 (26n-1是这个区块的大小)
然后求出 包含了多少前面的区块 An-1=sub/26n-2
依次类推 直到求出 最后一个字母。
JAVA源码:
//get the Label of Excel Column,parameter num is which num,it start from ‘0’
public static String getExcelColumnLabel(int num){
String temp=””;
//make sure how many letters are there
double i=Math.floor(Math.log(25.0*(num)/26.0+1)/Math.log(26))+1;
if(i>1){
double sub=num-26*(Math.pow(26, i-1)-1)/25;
for(double j=i;j>0;j–){
temp= temp+(char)(sub/Math.pow(26, j-1)+65);
sub=sub%Math.pow(26, j-1);
}
}else{
temp= temp+(char)(num+65);
}
return temp;
}
测试:
public static void main(String[] args){
for(int i=1;i<=26*26*26*26+26*26*26+26*26+26;i++){
if((i)%26==0){
System.out.print(“[“+getExcelColumnLabel(i-1)+”]/n”);
}else{
System.out.print(“[“+getExcelColumnLabel(i-1)+”]”);
}
}
}
注意:我的起始列是从 0 开始,
如果你是从1开始,需要把输入参数减去1
比如你要输出第27列对应的 字母标题
那么输入参数 是27-1=26
调用如下
System.out.print(“[“+getExcelColumnLabel(26)+”]”);
好了 大家可以把代码copy下来 测试下,这是我第一次在CSDN上发表技术类的文章,有什么错误或不理解的还请大家指出。另外我的方法应该不是最好的,最高效的,如果哪位高手还有更好的方法,欢迎跟帖指出!TKS