function getColCode($col) {
$letters = [
'Z', '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'
];
$code = '';
while ($col > 0) {
$ret = intval($col / 26);
$mod = intval($col % 26);
if ($mod == 0) {
$ret -= 1;
}
$code .= $letters[$mod];
$col = $ret;
}
return strrev($code);
}
function getColLetter($col) {
static $letters = [
'Z', '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'
];
$ret = intval($col / 26);
$mod = intval($col % 26);
if ($mod == 0 && $ret == 0) {
return '';
} else {
if ($mod == 0) {
$ret -= 1;
}
return getColLetter($ret) . $letters[$mod];
}
}
//PHPExcel的内部实现
function stringFromColumnIndex($columnIndex)
{
static $indexCache = [];
if (!isset($indexCache[$columnIndex])) {
$indexValue = $columnIndex;
$base26 = null;
do {
$characterValue = ($indexValue % 26) ?: 26;
$indexValue = ($indexValue - $characterValue) / 26;
$base26 = chr($characterValue + 64) . ($base26 ?: '');
} while ($indexValue > 0);
$indexCache[$columnIndex] = $base26;
}
return $indexCache[$columnIndex];
}
foreach (range(1, 10000) as $value) {
var_dump($value .'-'. getColCode($value));
var_dump($value .'-'. getColLetter($value));
var_dump($value .'-'. stringFromColumnIndex($value));
var_dump(getColCode($value) == getColLetter($value));
var_dump(getColCode($value) == getColCode2($value));
var_dump(getColCode($value) == stringFromColumnIndex($value));
var_dump(getColLetter($value) == stringFromColumnIndex($value));
}
总结:
上述的本质是基于base26的算法
方案1,while,难点是字母’Z‘的位置
方案2,递归实现,是while方案的一种转换,letters加了static修饰
方案3,do/while,PHPExcel的内部实现。方法比较讨巧,有很多可以学习的点:ascii值64的基础上加偏移量,从而不用声明letters数组;加了cache,避免多次计算