在 Symfony2 中使用 PHPExcel 读取 Excel 文件,编辑一个单元格的内容然后保存到数据库

Read Excel file using PHPExcel in Symfony2, edit contents of one cell then save to database

我建立了一个系统,客户端可以使用电子表格向其上传数据。它使用的是 CSV,但其中包含的数据意味着上传不太可靠。因此,我将使用 PHPExcel 和 Symfony2 的 PHPExcel 包来读取上传的 Excel 电子表格并将此数据插入数据库.

我在使用 PHPExcel 时遇到两个问题。首先是上传的文件中有一列包含英国格式的日期 (DD/MM/YYYY)。但是,显然,MySQL 使用美国格式 (YYYY-MM-DD)。所以我想做的是格式化一个特定的单元格以使用 YYYY-MM-DD 格式而不是 DD/MM/YYYY.

我遇到的第二个问题是,我想以最有效的方式将所有这些数据插入到 MySQL 数据库中。我不确定如何最好地做到这一点。我知道在使用大型电子表格时 PHPExcel 会出现内存问题,因此我想确保尽可能高效地保存到数据库。

到目前为止,由于我一直专注于阅读 Excel 文件,这是我的代码:

        $objPHPExcel = $this->get('phpexcel')->createPHPExcelObject($dir.$fileName);

        $objPHPExcel->setActiveSheetIndex(0);
        $row = $objPHPExcel->getActiveSheet()->getHighestRow()+1;

        foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
                echo 'Worksheet - ' , $worksheet->getTitle();
                echo '<table>';
                foreach ($worksheet->getRowIterator() as $row) {
                        //echo '<trRow number - ' , $row->getRowIndex() , EOL;
                        echo '<tr>';

                        $cellIterator = $row->getCellIterator();
                        $cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set
                        foreach ($cellIterator as $cell) {
                                if (!is_null($cell)) {
                                        echo '<td>'.$cell->getFormattedValue().'</td>';
                                }
                        }
                        echo '<tr>';
                }
                echo '</table>';
        }

在尝试格式化单个单元格时,我将代码更改为:

        $objPHPExcel = $this->get('phpexcel')->createPHPExcelObject($dir.$fileName);
        foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
                echo 'Worksheet - ' , $worksheet->getTitle();
                echo '<table>';
                foreach ($worksheet->getRowIterator() as $row) {
                        //echo '<trRow number - ' , $row->getRowIndex() , EOL;
                        echo '<tr>';

                        $cellIterator = $row->getCellIterator();
                        $cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set
                        foreach ($cellIterator as $cell) {
                                if (!is_null($cell)) {
                                        echo '<td>'.$cell[0]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[1]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[2]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[3]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[4]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[5]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[6]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[7]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[8]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[9]->getFormattedValue().'</td>';
                                        echo '<td>'.date('Y-m-d', strtotime($cell[10]->getFormattedValue())).'</td>';
                                        echo '<td>'.$cell[11]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[12]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[13]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[14]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[15]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[16]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[17]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[18]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[19]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[20]->getFormattedValue().'</td>';
                                        echo '<td>'.$cell[21]->getFormattedValue().'</td>';
                                }
                        }
                        echo '<tr>';
                }
                echo '</table>';
        }

但这在 Apache2 日志中给出了以下错误:

PHP Fatal error: Cannot use object of type PHPExcel_Cell as array

如有任何帮助,我们将不胜感激。

是的,$cell不是一个数组,它是一个对象,所以使用$cell[0]是无效的

替换整个代码块:

foreach ($cellIterator as $cell) {
    if (!is_null($cell)) {
        echo '<td>'.$cell[0]->getFormattedValue().'</td>';
        echo '<td>'.$cell[1]->getFormattedValue().'</td>';
        echo '<td>'.$cell[2]->getFormattedValue().'</td>';
        echo '<td>'.$cell[3]->getFormattedValue().'</td>';
        echo '<td>'.$cell[4]->getFormattedValue().'</td>';
        echo '<td>'.$cell[5]->getFormattedValue().'</td>';
        echo '<td>'.$cell[6]->getFormattedValue().'</td>';
        echo '<td>'.$cell[7]->getFormattedValue().'</td>';
        echo '<td>'.$cell[8]->getFormattedValue().'</td>';
        echo '<td>'.$cell[9]->getFormattedValue().'</td>';
        echo '<td>'.date('Y-m-d', strtotime($cell[10]->getFormattedValue())).'</td>';
        echo '<td>'.$cell[11]->getFormattedValue().'</td>';
        echo '<td>'.$cell[12]->getFormattedValue().'</td>';
        echo '<td>'.$cell[13]->getFormattedValue().'</td>';
        echo '<td>'.$cell[14]->getFormattedValue().'</td>';
        echo '<td>'.$cell[15]->getFormattedValue().'</td>';
        echo '<td>'.$cell[16]->getFormattedValue().'</td>';
        echo '<td>'.$cell[17]->getFormattedValue().'</td>';
        echo '<td>'.$cell[18]->getFormattedValue().'</td>';
        echo '<td>'.$cell[19]->getFormattedValue().'</td>';
        echo '<td>'.$cell[20]->getFormattedValue().'</td>';
        echo '<td>'.$cell[21]->getFormattedValue().'</td>';
    }
}

foreach ($cellIterator as $cell) {
    if (!is_null($cell)) {
        if ($cell->getColumn() == 'K') {
            // The 10th column (column K) is a date that needs reformatting
            $cellValue = date('Y-m-d', strtotime($cell->getFormattedValue()));
        } else {
             $cellValue = $cell->getFormattedValue();
        }
        echo '<td>'.$cellValue.'</td>';
    }
}

最好使用 PHPExcel 自己的日期处理方法而不是依赖日期单元格的格式化值,所以

$cellValue = PHPExcel_Shared_Date::ExcelToPHPObject($cell->getValue())
    ->format('Y-m-d');

会比

更清洁、更安全
$cellValue = date('Y-m-d', strtotime($cell->getFormattedValue()));

此外,如果其他列可能包含日期值,而不是检查特定列,请替换

if ($cell->getColumn() == 'K') {
    // The 10th column (column K) is a date that needs reformatting

if (PHPExcel_Shared_Date::isDateTime($cell)) {
    // Cell contains a date value that needs reformatting

所以最终结果应该是这样的:

foreach ($cellIterator as $cell) {
    if (!is_null($cell)) {
        if (PHPExcel_Shared_Date::isDateTime($cell)) {
            // Cell contains a date value that needs reformatting
            $cellValue = PHPExcel_Shared_Date::ExcelToPHPObject($cell->getValue())
                ->format('Y-m-d');
        } else {
             $cellValue = $cell->getFormattedValue();
        }
        echo '<td>'.$cellValue.'</td>';
    }
}

您可能还想考虑通过设置

来消除 if (!is_null($cell)) 测试
$cellIterator->setIterateOnlyExistingCells(true); 

最后一点,当您计划将所有这些行数据插入到 MySQL 数据库中时,在迭代时为行中的每个单元格构建一个数组,并在每个单元格的末尾进行插入排。 但是,由于数值的格式化值可能包含千位分隔符、货币代码等(例如 $ 123,456.789),因此最好使用 [= 获取原始值 (123456.789) 23=] 而不是 getFormattedValue() 用于所有非日期值,否则当您尝试将带有千位分隔符的格式化值插入数据库中的 FLOAT 或 INTEGER 列时,您的 SQL 可能会出错 table