Excel列字母A-Z/AA-ZZ/AAA-ZZZ实现的几种方法

  1. while循环
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);
    }

  1. 递归
    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];
        }
    }
  1. do/while
	//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];
    }

  1. 测试
    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,避免多次计算

你可能感兴趣的:(PHP)