40

鉴于:

$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']);

我可以像这样遍历行,但速度很慢,即在一个 3MB Excel 文件中,工作表具有“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”)?

4

7 回答 7

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

从“A”的 $colString 返回 1,从“Z”返回 26,从“AA”返回 27,等等。

和(几乎)相反的

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

从 0 的 $colNumber 返回“A”,从 25 返回“Z”,从 26 返回“AA”,等等。

编辑

几个有用的技巧:

工作表类有一个 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 Style

$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 相对于 $row++ 的性能改进

于 2010-12-30T21:30:29.427 回答
1
    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) //返回一个

于 2012-11-14T04:37:23.633 回答
1

我建议将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;
    }
于 2014-12-23T09:33:21.727 回答
1

不确定您的类是否具有内置方法,但您始终可以对列索引字符串的每个字母使用 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 是 'A' 的 ord() 值减 1,$decimal_value 是 A0 的值。应该适用于任何数字列。已经测试过了。希望这可以帮助。

于 2010-12-30T16:38:17.863 回答
1

这是 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 次幂。

于 2014-01-15T22:44:57.747 回答
0

由于这个问题已有 10 年历史,并且此处引用的软件包不再是最新的:

以下是使用phpspreadsheet 的方法

$colNumber = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($colString); // e.g. 5

来源: https ://phpspreadsheet.readthedocs.io/en/latest/topics/accessing-cells/

于 2021-01-08T10:37:51.573 回答
0
/**
 * 
 */
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;
}
于 2017-10-15T02:15:48.317 回答