Как получить число столбцов рабочего листа как целое (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;
}