在PHP中将Excel列坐标转换为整数位置

时间:2016-05-28 07:24:40

标签: php excel coordinates

我需要将Excel坐标(例如“AD45”)转换为整数的X = 30和Y = 45位置。

我有这段PHP代码:

/**
 * @param  String $coordinates
 *
 * @return array
 */
public function getCoordinatesPositions($coordinates) {
    $letters = preg_replace('/[^a-zA-Z]/', '', $coordinates);
    $numbers = preg_replace('/[^0-9]/', '', $coordinates);

    $letters = strtoupper($letters);

    $columnCoordinate = 0;
    $alphabetIterate = 0;

    $alphabetRange = range('A', 'Z');
    $alphabetCount = count($alphabetRange);

    $splittedLetters = str_split($letters);
    $lettersCount = count($splittedLetters);

    $i = 1;

    if ($lettersCount === 1) {
        $columnCoordinate = array_search($splittedLetters[0], $alphabetRange) + 1;

    } else {
        foreach ($splittedLetters as $letter) {
            if ($i !== $lettersCount) {
                $position = (array_search($letter, $alphabetRange) + 1) * $alphabetCount;
            } else {
                $position = (array_search($letter, $alphabetRange) + 1);
            }

            $columnCoordinate += $position;

            $i++;
        }
    }

    return array('column' => $columnCoordinate, 'row' => $numbers);
}

我的问题是,如果您传递3个或更多字母的坐标(“ABC45”),则此函数不会返回正确的列值。而我的同事说,这个算法性能也很差。

您对更简单,更好的性能算法有什么想法吗?谢谢。

2 个答案:

答案 0 :(得分:2)

原则上算法很好。您可以通过这种方式简化它并使其更加通用:

function getCoordinatesPositions($coordinates) {

    $letters = preg_replace('/[^a-zA-Z]/', '', $coordinates);
    $numbers = preg_replace('/[^0-9]/', '', $coordinates);

    $letters = strtoupper($letters);

    $alphabetRange = range('A', 'Z');
    $alphabetCount = count($alphabetRange);

    $splittedLetters = str_split($letters);
    $lettersCount = count($splittedLetters);

    $columnCoordinate = 0;
    $i = 1;
    foreach ($splittedLetters as $letter) {
       $columnCoordinate += (array_search($letter, $alphabetRange) + 1) * pow($alphabetCount,  $lettersCount - $i);
       $i++;
    }

    return array('column' => $columnCoordinate, 'row' => intval($numbers));
}

var_dump(getCoordinatesPositions("ABC456"));

对于PHPExcel,请参阅PHPExcel how to get column index from cell

答案 1 :(得分:1)

@Axel Richter的回答是一个很好的解决方案并且工作正常,但可以改进为:

  • 防止坐标错误。
  • 减少代码。
  • 可能会提高性能。

以下是建议的版本:

function getCoordinatesPositions($coordinates) {
    if (preg_match('/^([a-z]+)(\d+)$/i', $coordinates, $matches)) {
        $level = strlen($matches[1]);
        $matches[1] = array_reduce(
            str_split(strtoupper($matches[1])),
            function($result, $letter) use (&$level) {
                return $result + (ord($letter) - 64) * pow(26, --$level);
            }
        );
        return array_splice($matches, 1);
    }
    // (returns NULL when wrong $coordinates)
}

使用初始preg_match()可确保避免使用错误的坐标,并直接将列部分提取到$matches['1']

现在主要的改进是使用ord($letter)来计算字母的单个值:它可以避免创建range('A', 'Z')的临时数组,并简化评估。

然后array_reduce()允许对列部件进行更紧凑的处理,该部件被原位修改,因此最终返回也简化为中间人$matches的简单部分