PHPEXCEL获取excel文件

时间:2015-07-24 06:15:40

标签: php phpexcel

我正在尝试使用PhpExcel lib导入excel文件 对于所有其他字段getValue()函数有效,但遇到格式为date的字段时,在ms-excel2013中设置 exel文件中的日期字段格式为d-m-Y,如16-11-2014 但是当我尝试导入它的值时,getValue()会返回11-16-14,当strtotime进一步传递returns false时会导致date('Y-m-d',strtotime($date))返回1970-01-01

我搜索了整个网络和stackoverflow,但没有解决方案解决了我的问题。 在excel文件中,我将日期视为16-11-2014,并希望按原样导入。

这里是代码

protected function importExcel($filePath) {
    $excelData = array();
    if ($filePath) {
        $objPHPExcel = PHPExcel_IOFactory::load($filePath);
        $objPHPExcel->setReadDataOnly(true);
        foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
            $worksheetTitle = $worksheet->getTitle();
            $highestRow = $worksheet->getHighestRow(); // e.g. 10
            $highestColumn = $worksheet->getHighestColumn(); // e.g 'F'
            $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
            $nrColumns = ord($highestColumn) - 64;
            $data = array();
            for ($row = 1; $row <= $highestRow; ++$row) {
                $values = array();
                for ($col = 0; $col < $highestColumnIndex; ++$col) {
                    $cell = $worksheet->getCellByColumnAndRow($col, $row);
                    if (PHPExcel_Shared_Date::isDateTime($cell))
                        throw new Exception("is date time"); // just a check
                    $val = $cell->getValue();
                    if (isset($val) && $val)
                        $data[$row][$col] = $val;
                }
            }
            $excelData[$worksheetTitle] = $data;
        }
        return $excelData;
    }
    return FALSE;
}

3 个答案:

答案 0 :(得分:8)

对包含日期的字段进行getValue()调用时,如果该字段确实包含MS Excel日期值,则应返回41959.00之类的值....即MS Excel序列化日期时间戳基于1900年1月1日(或1904年1月1日,如果文件是使用Mac版的MS Excel创建)的天数

要获取格式化的日期字符串,您需要调用getFormattedValue();然后,PHPExcel使用该单元格的数字格式掩码根据该掩码格式化日期。

要确定某个单元格是否包含MS序列化日期时间戳,您可以先使用PHPExcel_Shared_Date::isDateTime()调用。

foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
    echo 'Worksheet - ' , $worksheet->getTitle() , EOL;

    foreach ($worksheet->getRowIterator() as $row) {
        echo '    Row number - ' , $row->getRowIndex() , EOL;

        $cellIterator = $row->getCellIterator();
        $cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set
        foreach ($cellIterator as $cell) {
            if (!is_null($cell)) {
                echo '        Cell - ' , $cell->getCoordinate() , ' - ';
                if (PHPExcel_Shared_Date::isDateTime($cell)) {
                    echo $cell->getFormattedValue() , EOL;
                } else {
                    echo $cell->getValue() , EOL;
                }
            }
        }
    }
}

您可以要求PHPExcel将日期作为Unix时间戳返回,或者作为PHP DateTime对象返回,而不是返回格式化的数据值;然后你就可以使用PHP的内置日期函数或DateTime方法格式化它。

if (PHPExcel_Shared_Date::isDateTime($cell)) {
    $unixTimeStamp = PHPExcel_Shared_Date::ExcelToPHP($cell->getValue());
    echo date('d-M-Y H:i:s', $unixTimeStamp), PHP_EOL;
}

if (PHPExcel_Shared_Date::isDateTime($cell)) {
    $dateTimeObject = PHPExcel_Shared_Date::ExcelToPHPObject($cell->getValue());
    echo $dateTimeObject->format('d-M-Y H:i:s'), PHP_EOL;
}

答案 1 :(得分:3)

我已查看您提供的文件,查看您的日期问题。

您在电子表格中用于这些日期的格式是一种区域设置感知日期格式,如果您查看单元格格式,则由MS Excel标记并带有星号(*)

这意味着(引用Excel关于格式掩码显示的注释):

  

以星号(*)开头的日期格式会响应为操作系统指定的区域日期和时间设置的更改。

由于PHPExcel不支持区域设置,但确实将格式掩码识别为日期值,因此它使用通用格式。

运行以下代码

var_dump($objPHPExcel->getActiveSheet()->getCell('I5')->getValue());
var_dump(PHPExcel_Shared_Date::isDateTime($objPHPExcel->getActiveSheet()->getCell('I5')));
var_dump($objPHPExcel->getActiveSheet()->getCell('I5')->getStyle()->getNumberFormat()->getFormatCode());
var_dump($objPHPExcel->getActiveSheet()->getCell('I5')->getFormattedValue());

给出

float(42062)
bool(true)
string(8) "mm-dd-yy"
string(8) "02-27-15"

所以(只要您从Reader中删除了setReadDataOnly(true)来自Reader的调用,您仍然可以将日期单元格标识为日期,并手动格式化它们,覆盖默认的区域设置格式

if (PHPExcel_Shared_Date::isDateTime($objPHPExcel->getActiveSheet()->getCell('I5'))) {
    $dateTimeObject = PHPExcel_Shared_Date::ExcelToPHPObject($objPHPExcel->getActiveSheet()->getCell('I5')->getValue());
    echo $dateTimeObject->format('d-m-Y'), PHP_EOL;
}

答案 2 :(得分:1)

我找到了解决方案:

文件 PHPExcel / Style / NumberFormat.php

中的方法 _formatAsDate

The method _formatAsDate in NumberFormat.php

如果日期与16/11/2014相同,则传递给strtotime时会生成false,因为m/d/Y的日期应该采用格式strtotime 。因此,如果您将格式更改为m/d/Y,如果它d/m/Y,则解决方案始终是正确的。

早些时候:

  1. 16/11/2014 == 1970-01-01(行:1)
  2. 16/11/2014 == 1970-01-01(第2行)
  3. 23/12/20 2014 == 1970-01-01(第3行)。
  4. 现在:

    1. 11/16/2014 == 2014-11-16(第1行)
    2. 11/16/2014 == 2014-11-16(第2行)
    3. 12/23/2014 == 2014-12-23(第3行)
    4. 导入文件的代码仍然相同且简单:

      protected function importExcel($filePath) {
          $excelData = array();
          if ($filePath) {
              $objPHPExcel = PHPExcel_IOFactory::load($filePath);
              foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
                  $worksheetTitle = $worksheet->getTitle();
                  $highestRow = $worksheet->getHighestRow(); // e.g. 10
                  $highestColumn = $worksheet->getHighestColumn(); // e.g 'F'
                  $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
                  $nrColumns = ord($highestColumn) - 64;
                  $data = array();
                  for ($row = 1; $row <= $highestRow; ++$row) {
                      $values = array();
                      for ($col = 0; $col < $highestColumnIndex; ++$col) {
                          $cell = $worksheet->getCellByColumnAndRow($col, $row);
                          $val = $cell->getValue();
                          if (isset($val) && $val)
                              $data[$row][$col] = $val;
                      }
                  }
                  $excelData[$worksheetTitle] = $data;
              }
              return $excelData;
          }
          return FALSE;
      }