Я пытаюсь импортировать файл excel, используя PhpExcel lib для всех других полей, getValue()
работает, но когда он встречает поле с датой даты, установленной в ms-excel2013, поле даты в exel-файле находится в формате dmY, например, 16-11-2014
но когда я пытаюсь импортировать его значение, getValue()
возвращает 11-16-14
который при передаче в strtotime
далее returns false
в свою очередь, заставляя date('Ym-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(); // eg 10 $highestColumn = $worksheet->getHighestColumn(); // eg '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; }
Вот файл
заранее спасибо
getValue()
в поле, содержащем дату, должен возвращать значение, например, 41959.00
если это поле действительно содержит значение даты MS Excel …. то есть штамп даты и времени MS Excel, основанный на количестве дней с 1 января 1900 (или 1 января 1904 года, если файл был создан с использованием Mac версии MS Excel)
Чтобы получить форматированную строку даты, вам нужно вместо этого вызвать getFormattedValue()
; и PHPExcel затем использует маску формата номера для этой ячейки для форматирования даты в соответствии с этой маской.
Чтобы определить, содержит ли ячейка MS-сериализованную PHPExcel_Shared_Date::isDateTime()
, вы можете сначала вызвать вызов 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('dMY H:i:s', $unixTimeStamp), PHP_EOL; }
или
if (PHPExcel_Shared_Date::isDateTime($cell)) { $dateTimeObject = PHPExcel_Shared_Date::ExcelToPHPObject($cell->getValue()); echo $dateTimeObject->format('dMY H:i:s'), PHP_EOL; }
Я проверил файл, который вы предоставили, глядя на вопрос о дате.
Формат, который вы используете для этих дат в вашей таблице, представляет собой формат даты, соответствующий значению даты, помеченный 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"
Таким образом (пока вы удалили setReadDataOnly(true)
из Reader, позвоните из Reader, вы все равно можете определить ячейки даты как даты и отформатировать их вручную, переопределяя стандартное языковое форматирование
if (PHPExcel_Shared_Date::isDateTime($objPHPExcel->getActiveSheet()->getCell('I5'))) { $dateTimeObject = PHPExcel_Shared_Date::ExcelToPHPObject($objPHPExcel->getActiveSheet()->getCell('I5')->getValue()); echo $dateTimeObject->format('dm-Y'), PHP_EOL; }
Я нашел решение:
Метод _formatAsDate в файле PHPExcel / Style / NumberFormat.php
если дата подобна 16/11/2014
, при передаче в strtotime
результат будет false
как дата должна быть в формате m/d/Y
по strtotime
. Поэтому, если вы измените формат на m/d/Y
если это d/m/Y
тогда решение всегда будет правильным.
Код все тот же и простой для импорта файла:
protected function importExcel($filePath) { $excelData = array(); if ($filePath) { $objPHPExcel = PHPExcel_IOFactory::load($filePath); foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) { $worksheetTitle = $worksheet->getTitle(); $highestRow = $worksheet->getHighestRow(); // eg 10 $highestColumn = $worksheet->getHighestColumn(); // eg '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; }