Как получить число столбцов рабочего листа как целое (28) вместо букв Excel ( "AB" )?

Дано:

$this->objPHPExcelReader = PHPExcel_IOFactory::createReaderForFile($this->config['file']);
$this->objPHPExcelReader->setLoadSheetsOnly(array($this->config['worksheet']));
$this->objPHPExcelReader->setReadDataOnly(true);
$this->objPHPExcel = $this->objPHPExcelReader->load($this->config['file']);

Я могу выполнять итерацию по таким строкам, но очень медленно, т.е. в файле Excel объемом 3 МБ с листом "EL" . 1 секунда на строку:

foreach ($this->objPHPExcel->setActiveSheetIndex(0)->getRowIterator() as $row)
{
    $dataset = array();
    $cellIterator = $row->getCellIterator();
    $cellIterator->setIterateOnlyExistingCells(false);
    foreach ($cellIterator as $cell)
    {
        if (!is_null($cell))
        {
            $dataset[] = $cell->getCalculatedValue();
        }
    }
    $this->datasets[] = $dataset;
}

Когда я повторяю так, это значительно быстрее (примерно 2000 строк за 30 секунд), но мне придется преобразовать буквы, например. "EL" к числу:

$highestColumm = $this->objPHPExcel->setActiveSheetIndex(0)->getHighestColumn(); // e.g. "EL"
$highestRow = $this->objPHPExcel->setActiveSheetIndex(0)->getHighestRow();

$number_of_columns = 150; // TODO: figure out how to get the number of cols as int
for ($row = 1; $row < $highestRow + 1; $row++) {
    $dataset = array();
    for ($column = 0; $column < $number_of_columns; $column++) {
        $dataset[] = $this->objPHPExcel->setActiveSheetIndex(0)->getCellByColumnAndRow($column, $row)->getValue();
    }
    $this->datasets[] = $dataset;
}

Есть ли способ получить максимальный столбец как целое число (например, "28" ) вместо букв в формате Excel (например, "AB" )?

Ответ 1

$colNumber = PHPExcel_Cell::columnIndexFromString($colString);

возвращает 1 из $colString из 'A', 26 из 'Z', 27 из 'AA' и т.д.

и (почти) обратный

$colString = PHPExcel_Cell::stringFromColumnIndex($colNumber);

возвращает 'A' из $colNumber из 0, 'Z' из 25, 'AA' из 26 и т.д.

ИЗМЕНИТЬ

Несколько полезных трюков:

Для класса рабочей таблицы существует метод toArray():

$this->datasets = $this->objPHPExcel->setActiveSheetIndex(0)->toArray();

который принимает следующие параметры:

* @param  mixed    $nullValue          Value returned in the array entry if a cell doesn't exist
* @param  boolean  $calculateFormulas  Should formulas be calculated?
* @param  boolean  $formatData         Should formatting be applied to cell values?
* @param  boolean  $returnCellRef      False - Return a simple array of rows and columns indexed by number counting from zero
*                                      True - Return rows and columns indexed by their actual row and column IDs

хотя он использует итераторы, поэтому будет немного медленнее

ИЛИ

Воспользуйтесь возможностью PHP увеличивать строки символов в стиле Perl

$highestColumm = $this->objPHPExcel->setActiveSheetIndex(0)->getHighestColumn(); // e.g. "EL" 
$highestRow = $this->objPHPExcel->setActiveSheetIndex(0)->getHighestRow();  

$highestColumm++;
for ($row = 1; $row < $highestRow + 1; $row++) {     
    $dataset = array();     
    for ($column = 'A'; $column != $highestColumm; $column++) {
        $dataset[] = $this->objPHPExcel->setActiveSheetIndex(0)->getCell($column . $row)->getValue();
    }
    $this->datasets[] = $dataset;
}

и если вы обрабатываете большое количество строк, вы можете заметить повышение производительности строки ++ $над $row ++

Ответ 2

Не уверен, что ваш класс имеет встроенный метод, но всегда можно использовать функцию ord() для каждой буквы индексной строки столбца. Разумеется, вам придется вычесть базовое значение "A" и умножить на 26 ^ x для каждой позиции из крайнего правого ряда. Что-то вроде:

    $input_string = 'BC';
    $base_value = 64;
    $decimal_value = 26;
    $column_index = 0;
    for ($i = 0; $i < strlen($input_string); $i++) {
        $char_value = ord($input_string[$i]);
        $char_value -= $base_value;
        $char_value *= pow($decimal_value, (strlen($input_string) - ($i + 1)));
        $column_index += $char_value;
    }
    echo $column_index;

В основном это сделало бы "BC" равным (2 * 26 ^ 1) + (3 * 26 ^ 0) = 55.

$input_string, являющаяся строкой индекса столбца, $base_value является значением ord() 'A' минус 1, а $decimal_value является значением A0. Должен работать до любого столбца номера. Протестировали. Надеюсь, это поможет.

Ответ 3

Это несколько упрощенная версия ответа dqhendricks. Я добавил к копиям одну функцию, предполагая, что вы введете полную ссылку на ячейку excel (например, "AB12" ), а другая, если вы введете только ссылку на колонку (например, "AB" ). Оба они возвращают индекс, основанный на нуле.

Входной справочник по полной ячейке

function getIndex ($cell) {
    // Strip cell reference down to just letters
    $let = preg_replace('/[^A-Z]/', '', $cell);

    // Iterate through each letter, starting at the back to increment the value
    for ($num = 0, $i = 0; $let != ''; $let = substr($let, 0, -1), $i++)
        $num += (ord(substr($let, -1)) - 65) * pow(26, $i);

    return $num;
}

Только справочная таблица столбцов

function getIndex ($let) {
    // Iterate through each letter, starting at the back to increment the value
    for ($num = 0, $i = 0; $let != ''; $let = substr($let, 0, -1), $i++)
        $num += (ord(substr($let, -1)) - 65) * pow(26, $i);

    return $num;
}

Функция переходит от задней части строки к фронту, чтобы увеличить значение столбца. Он использует функцию ord(), чтобы получить числовое значение символа, а затем вычитает значение буквы, чтобы дать значение локального столбца. Наконец, он умножается на текущую мощность 26.

Ответ 4

простейшее решение $ getColumnIndexFromString = PHPExcel_Cell:: columnIndexFromString ($ maximumColumn);

Ответ 5

Я предлагаю преобразовать excel в массив, очистить его от пустых элементов и затем подсчитать количество столбцов:

protected function getColumnsCheck($file, $col_number) {
        if (strstr($file, ".xls") != false && strstr($file, ".xlsx") != false) {
            $fileType = PHPExcel_IOFactory::identify($file);
            $objReader = PHPExcel_IOFactory::createReader($fileType);
            $objPHPExcel = $objReader->load($file);
            $columns_empty = $objPHPExcel->getActiveSheet(0)->toArray()[0]; 

            $columns = array_filter($columns_empty);

            return ($col_number==count($columns));
        }
        return false;
    }

Ответ 6

    function getNameFromNumber($num) {//(Example 0 = A, 1 = B)
$numeric = $num % 26;
$letter = chr(65 + $numeric);
$num2 = intval($num / 26);
if ($num2 > 0) {
    return getNameFromNumber($num2 - 1) . $letter;
} else {
    return $letter;
}
}

getNameFromNumber (0)//return A

Ответ 7

/**
 * 
 */
function number_to_alphabet($number) {
    $number = intval($number);
    if ($number <= 0) {
        return '';
    }
    $alphabet = '';
    while($number != 0) {
        $p = ($number - 1) % 26;
        $number = intval(($number - $p) / 26);
        $alphabet = chr(65 + $p) . $alphabet;
    }
    return $alphabet;
}

/**
 * Required PHP 5.6.
 * @see: http://php.net/manual/en/language.operators.arithmetic.php
 */
function alphabet_to_number($string) {
    $string = strtoupper($string);
    $length = strlen($string);
    $number = 0;
    $level = 1;
    while ($length >= $level ) {
        $char = $string[$length - $level];
        $c = ord($char) - 64;        
        $number += $c * (26 ** ($level-1));
        $level++;
    }
    return $number;
}

Тест:

for ($x=1; $x<=1000; $x++) {
    echo 'number_to_alphabet('.$x.') = ',$y = number_to_alphabet($x),'; ';
    echo 'alphabet_to_number('.$y.') = '.alphabet_to_number($y).'; ';
    echo PHP_EOL;
}