PHPEXCEL 获取 excel 文件中可见的格式化日期
PHPEXCEL get formatted date as is visible in excel file
我正在尝试使用 PhpExcel 库导入 excel 文件
对于所有其他字段,getValue()
函数有效,但当它遇到格式为 ms-excel2013 中设置的日期的字段时
exel 文件中的日期字段格式为 d-m-Y,如 16-11-2014
但是当我尝试导入它时,它的值 getValue()
returns 11-16-14
当进一步传递给 strtotime
时 returns false
又导致 date('Y-m-d',strtotime($date))
到return 1970-01-01
.
我搜索了整个网络和 Whosebug,但 none 解决方案解决了我的问题。
在 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;
}
对包含日期的字段的 getValue()
调用应该 return 类似 41959.00
的值,如果该字段确实包含 MS Excel 日期值... . 也就是说,一个 MS Excel 序列化日期时间戳基于自 1900 年 1 月 1 日以来的天数(如果文件是使用 MS Mac 版本创建的,则为 1904 年 1 月 1 日)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;
}
}
}
}
}
除了 return 格式化数据值,您还可以要求 PHPExcel 将日期 return 作为 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;
}
我已经检查了你提供的文件,查看你的日期问题。
您在电子表格中用于这些日期的格式是区域设置感知日期格式,如果您查看单元格格式[=15],MS Excel 会用星号 (*) 标记=]
这意味着(引用Excel关于格式掩码显示的注释):
Date formats that begin with an asterisk (*) respond to changes in regional date and time settings that are specified for the Operating System.
由于 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;
}
我找到了解决方案:
方法_formatAsDate 文件PHPExcel/Style/NumberFormat.php
如果日期类似于 16/11/2014
,当传递给 strtotime
时将导致 false
,因为日期应该采用 m/d/Y
格式 [=12] =].因此,如果您将格式更改为 m/d/Y
如果它是 d/m/Y
那么解决方案将始终是正确的。
早些时候:
- 16/11/2014==1970-01-01(行:1)
- 16/11/2014==1970-01-01(行:2)
- 23/12/2014==1970-01-01(行:3)。
现在:
- 11/16/2014==2014-11-16(行:1)
- 11/16/2014==2014-11-16(行:2)
- 12/23/2014==2014-12-23(行:3)
导入文件的代码仍然相同且简单:
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;
}
我正在尝试使用 PhpExcel 库导入 excel 文件
对于所有其他字段,getValue()
函数有效,但当它遇到格式为 ms-excel2013 中设置的日期的字段时
exel 文件中的日期字段格式为 d-m-Y,如 16-11-2014
但是当我尝试导入它时,它的值 getValue()
returns 11-16-14
当进一步传递给 strtotime
时 returns false
又导致 date('Y-m-d',strtotime($date))
到return 1970-01-01
.
我搜索了整个网络和 Whosebug,但 none 解决方案解决了我的问题。
在 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;
}
对包含日期的字段的 getValue()
调用应该 return 类似 41959.00
的值,如果该字段确实包含 MS Excel 日期值... . 也就是说,一个 MS Excel 序列化日期时间戳基于自 1900 年 1 月 1 日以来的天数(如果文件是使用 MS Mac 版本创建的,则为 1904 年 1 月 1 日)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;
}
}
}
}
}
除了 return 格式化数据值,您还可以要求 PHPExcel 将日期 return 作为 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;
}
我已经检查了你提供的文件,查看你的日期问题。
您在电子表格中用于这些日期的格式是区域设置感知日期格式,如果您查看单元格格式[=15],MS Excel 会用星号 (*) 标记=]
这意味着(引用Excel关于格式掩码显示的注释):
Date formats that begin with an asterisk (*) respond to changes in regional date and time settings that are specified for the Operating System.
由于 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;
}
我找到了解决方案:
方法_formatAsDate 文件PHPExcel/Style/NumberFormat.php
如果日期类似于 16/11/2014
,当传递给 strtotime
时将导致 false
,因为日期应该采用 m/d/Y
格式 [=12] =].因此,如果您将格式更改为 m/d/Y
如果它是 d/m/Y
那么解决方案将始终是正确的。
早些时候:
- 16/11/2014==1970-01-01(行:1)
- 16/11/2014==1970-01-01(行:2)
- 23/12/2014==1970-01-01(行:3)。
现在:
- 11/16/2014==2014-11-16(行:1)
- 11/16/2014==2014-11-16(行:2)
- 12/23/2014==2014-12-23(行:3)
导入文件的代码仍然相同且简单:
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;
}