PHPEXCEL get formatted date as is visible in excel

2019-01-14 14:26发布

I am trying to import a excel file using PhpExcel lib for all other fields the getValue() function works but when it encounters a field with format date as set in ms-excel2013 the date field in exel file is in format d-m-Y like 16-11-2014 but when I try to import it's value the getValue() returns 11-16-14 which when passed to strtotime further returns false in turn causing the date('Y-m-d',strtotime($date)) to return 1970-01-01.

I searched whole of web and stackoverflow but none solution fixed my problem. In excel file i see the date as 16-11-2014 and want it to be imported as is.

Here's the code

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;
}

标签: php phpexcel
3条回答
▲ chillily
2楼-- · 2019-01-14 14:51

A getValue() call on a field containing a date should return a value like 41959.00 if that field really does contain an MS Excel date value.... that is, an MS Excel serialized datetime stamp based on the number of days since 1st January 1900 (or 1st January 1904 if the file was created using the Mac version of MS Excel)

To get a formatted date string, you need to call getFormattedValue() instead; and PHPExcel then uses the number format mask for that cell to format the date according to that mask.

To identify if a cell contains an MS serialized datetime stamp, you can use a call to PHPExcel_Shared_Date::isDateTime() first.

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;
                }
            }
        }
    }
}

Rather than returning a formatted data value, you can also ask PHPExcel to return the date as a Unix timestamp, or as a PHP DateTime object instead; and then you'll be able to format it however you want using PHP's built-in date functions or DateTime methods.

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

or

if (PHPExcel_Shared_Date::isDateTime($cell)) {
    $dateTimeObject = PHPExcel_Shared_Date::ExcelToPHPObject($cell->getValue());
    echo $dateTimeObject->format('d-M-Y H:i:s'), PHP_EOL;
}
查看更多
乱世女痞
3楼-- · 2019-01-14 14:52

I've checked the file that you provided, looking at your date issue.

The format that you're using for those dates in your spreadsheet is a locale-aware date format, flagged by MS Excel with an asterisk (*) if you look at the cell format

This means (quoting from Excel's notes on the format mask display):

Date formats that begin with an asterisk (*) respond to changes in regional date and time settings that are specified for the Operating System.

Because PHPExcel is not locale-aware, but does recognise the format mask as a date value, it uses a generic formatting.


Running the following code

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());

gives

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

So (as long as you've removed that setReadDataOnly(true) call from the Reader, call from the Reader, you can still identify date cells as dates, and format them manually, overriding the default locale-formatting

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;
}
查看更多
狗以群分
4楼-- · 2019-01-14 14:57

I have found out the solution:

Method _formatAsDate in the file PHPExcel/Style/NumberFormat.php

The method _formatAsDate in NumberFormat.php

if the date is like 16/11/2014, when passed to strtotime will result in false as the date is supposed to be in format m/d/Y by strtotime. So if you change the format to m/d/Y if it's d/m/Y then the solution will always be correct.

Earlier:

  1. 16/11/2014==1970-01-01 (Row: 1)
  2. 16/11/2014==1970-01-01 (Row: 2)
  3. 23/12/2014==1970-01-01 (Row: 3).

Now:

  1. 11/16/2014==2014-11-16 (Row: 1)
  2. 11/16/2014==2014-11-16 (Row: 2)
  3. 12/23/2014==2014-12-23 (Row: 3)

Code is still the same and simple to import the file:

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;
}
查看更多
登录 后发表回答