PHP:数字转Excel列头
转自我的个人博客:阔野飞花 http://www.rexcao.net/archives/169
前段时间升级一个项目的Excel导出功能,这次的列数大概有60多条,在处理过程中发现一个问题,原先做好的数字转Excel列头功能现在只到 AZ列就结束了,那显然是不够用啊,后来再仔细查看,发现,原来AZ列之后的内容显示到AAA列上面了,然后看了看原来的代码才发现,原来的逻辑错了!
我原来的错误逻辑是这样的:A-Z,Z下来是AA,AA-AZ,AZ下来是AAA,下来是AAAA依次类推...但是Excel中AZ下来是BZ!意识到这一点之后,就着手开始修改自己原先的代码。
阶段一
数字转Excel列头,目标是提供任意一个数字,将其通过一个固定的方法转为Excel的列头,在此,我准备通过26位数作为临界值取整,取余来判断,后来发现有些绕,就干脆当作26进制来处理了。
阶段二
当 作26进制来处理之后,折腾了一会又发现一个新的问题,对于Excel列头来说,它的计算单位是A-Z,用十进制来类比,十进制数字的计算单位是 0-9,Excel列头Z的下一位是AA,而十进制9的下一位是10,如果A代表0的话,Excel列头Z就相当于是最大的十进制单位9,但是十进制的 10的上位是1,它代表尚未是有值的,而看看Excel列头AA的上位,是A,A代表0,那意思是上位没有值?显然不合理,所以我发现,这里也不能纯粹地 当作26进制来处理。
阶段三
经过上面两个阶段的折腾后,我决定采用另外一种办法,大体思路如下:
1、不再固定计算每个数字对应的列头字母,而是计算指定数字个列头(例如2个就是A、B,3个就是A、B、C等等)。
2、每次加1后,当前字母也加1(相当于1+1=2,A+1=B)。
3、计算结果是多个字母的拼接结果(A拼接A=AA,A拼接B=AB)。
4、低位加1的结果大于Z的话,向上位进一,进一之后的这个上位如果还大于Z的话,继续向上进一...(向上冒泡)
结果
既然思路已经清晰了,那么可以看看实现了。
header('Content-Type:text/html; charset=utf-8');
echo 'Convert number to title of excel.<br>';
function showarr($arr){
echo '<pre>';
print_r($arr);
echo '</pre><br>';
}
$ea = new ExcelAssistant();
$test1 = $ea->GetExcelTit(27);
showarr($test1);
/**
* Excel助手
* @author RexCao 2015-01-08
*/
class ExcelAssistant{
private $carr = array();//结果数组,初始值为A
private $curlet = 'A';//当前末尾字母,初始化为A
private $curletpi = 0;//当前字符串从右向左的位数,用来上位递归加1处理(从0开始)
private $tmpar = array('A');//临时数组,存储结果字符串上每位的字符。初始值为'A'
private static $a = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
private static $b = array('A'=>0,'B'=>1,'C'=>2,'D'=>3,'E'=>4,'F'=>5,'G'=>6,'H'=>7,'I'=>8,'J'=>9,'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25);
/**
* 获取excel列头
* @param $num 列数总计
*/
public function GetExcelTit($num){
$i = 0;
while($i<$num){
$this->curletpi = 0;//没有处理上位的时候,只处理当前位
$this->tmpar[count($this->tmpar)-1] = $this->curlet;
$this->carr[] = implode('',$this->tmpar);
$this->curlet = $this->GetNextLetter($this->curlet);
if($this->curlet == 'A'){
//说明过了一圈,该向上位递归加1了
$this->curletpi++;//从当前位左边的那位开始处理
$this->RecursiveAddUp();
}
$i++;
}
return $this->carr;
}
/**
* 根据字母获取下位字母
* A-Z循环
*/
public function GetNextLetter($l){
$k = self::$b[$l];//当前字母索引
$k++;//下位字母索引
if($k == 26){
$l = 'A';//反转
}else{
$l = self::$a[$k];
}
return $l;
}
/**
* 递归向上位加一
* 在这里,只有一次计算结果为A后,才会向上加1,
* 但不是每个位加了之后都要往上位冒泡,所以不能遍历每个位
* @author RexCao
*/
public function RecursiveAddUp(){
//先更新最右位的字母
$this->tmpar[count($this->tmpar)-1] = 'A';
if($this->curletpi+1>count($this->tmpar)){
$this->tmpar = array_merge(array('A'),$this->tmpar);
}else{
$cl = $this->tmpar[count($this->tmpar)-$this->curletpi-1];//当前位的字母
$cl = $this->GetNextLetter($cl);
if($cl == 'A'){
$this->tmpar[count($this->tmpar)-$this->curletpi-1] = 'A';//要去处理更上位了,先更新本位
$this->curletpi++;//再上一位
$this->RecursiveAddUp();
}else{
//更新当前位的字母为新字母即可
$this->tmpar[count($this->tmpar)-$this->curletpi-1] = $cl;
}
}
}
}
有兴趣看运行结果的,可以去我的个人博客瞧瞧咯(●'◡'●)。阔野飞花 http://www.rexcao.net/archives/169
PHP:数字转Excel列头的更多相关文章
- JAVA获取EXCEL列头
FileInputStream fileInputStream = new FileInputStream(rootPath + path + "/" + fileName); L ...
- 转载: 黄聪:C#中 Excel列字母与数字的转换
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- C#导入Excel遇到数字字母混合列数据丢失解决
错误重现: ----------------------------------------------------------------------- 在导入Excel读取数据时,其中的一个字段保 ...
- 把EXCEL列号数字变成字母
把Excel 列号数字变成字母 private static string ToName(int index) { if (index < 0) { throw new Exception(&q ...
- [No0000107]C#中 Excel列字母与数字的转换
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- NPOI操作Excel时使用列头来读取数据的方法
首先定义扩展方法: public static ICell GetCell(this IRow row, string clounmName) { IRow firstRow = row.Sheet. ...
- C# listview 单击列头实现排序 <二>
单击列头实现排序,首先在羡慕中添加下面的帮助实现的类:具体的代码: using System; using System.Collections; using System.Windows.Forms ...
- datatable的部分问题处理(动态定义列头,给某行添加事件,初始显示空数据)
一.动态定义列头 在ajax中,用datatable再去重新配置列头,当然传回的数据中,要有对应放列头的键值对 我自定义了Mock数据,用于前端自己交互. 其中,rowdata用于存放传回的数据,co ...
- 【转】silverlight telerik RadGridView 列头显示其他控件
<telerik:GridViewDataColumn DataMemberBinding="{Binding target_id}" IsFilterable=" ...
随机推荐
- 使用Swagger生成简单接口文档
使用swagger通过简单的配置可以生成简单的接口文档: 依赖包: // Swagger2 compile 'io.springfox:springfox-swagger2:2.8.0' compil ...
- mysql 查询库中有几张表
SELECT COUNT(*) TABLES, table_schemaFROM information_schema.TABLESWHERE table_schema = '999*999' 999 ...
- FTP 两种连接模式
简介 FTP协议要用到两个TCP连接, 一个是命令连接,用来在FTP客户端与服务器之间传递命令:另一个是数据连接,用来上传或下载数据.通常21端口是命令端口,20端口是数据端口.当混入主动/被动模式的 ...
- matlab中的linkage和cluster函数
Linkage: Agglomerative hierarchical cluster tree(凝聚成层次聚类树) 语法: 解释: Z=linkage(x),返回Z,是一个X矩阵中行的分层聚类树(用 ...
- 2.16 关于python/numpy
- UVA - 10125 哈希
题意:求集合中最大的\(d\)使得\(a+b=d-c\) 学习一下哈希的姿势(原来所谓链地址法就是直接跑个图啊) 哈希真有趣,全靠xjb乱搞 就叫这套hash为xjb-fibonacci-lpy-ha ...
- hdu 1754 I Hate It 线段树基础题
Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求, ...
- 小问题总结:鼠标点击到输入框(input)里的时候,输入框的提示消失,鼠标再移开,输入框提示出现
问题如标题: 鼠标点击到输入框(input)里的时候,输入框的提示消失,鼠标再移开,输入框提示出现.如图所示: 做法如下: <input type="text" name ...
- PIE SDK同态滤波
1.算法功能简介 同态滤波是减少低频增加高频,从而减少光照变化并锐化边缘或细节的图像滤波方法. 同态滤波的流程为:空间域图像→对数运算→傅里叶正变换→同态滤波――傅里叶逆变换→指数运算→同态滤波结果. ...
- groovy——运行方式、基本语法、引入方式、metaClass
jvm运行groovy类有两种方式: 1.使用groovyc编译所有的*.groovy为java的*.class文件,把这些*.class文件放在java类路径中,通过java类加载器来加载这些类. ...