Bugfix: Workitem 14223 - Advanced Value Binder Not Working?

Fixed AdvancedValueBinder date handling (with support for a wider range of date formats), and added support for strings containing numeric values in scientific format (e.g. "-1.234e+5")

git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@60740 2327b42d-5241-43d6-9e2a-de5ac946f064
This commit is contained in:
Mark Baker 2010-09-10 14:57:07 +00:00
parent 25526aa3ea
commit 3f807a1c01
4 changed files with 83 additions and 49 deletions

View File

@ -54,14 +54,18 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
// Style logic - strings // Style logic - strings
if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) { if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) {
// Check for number in scientific format
if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER.'$/', $value)) {
$cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
return true;
}
// Check for percentage // Check for percentage
if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) {
// Convert value to number // Convert value to number
$cell->setValueExplicit( (float)str_replace('%', '', $value) / 100, PHPExcel_Cell_DataType::TYPE_NUMERIC); $cell->setValueExplicit( (float)str_replace('%', '', $value) / 100, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style // Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE ); $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE );
return true; return true;
} }
@ -69,13 +73,10 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) {
list($h, $m) = explode(':', $value); list($h, $m) = explode(':', $value);
$days = $h / 24 + $m / 1440; $days = $h / 24 + $m / 1440;
// Convert value to number // Convert value to number
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style // Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 ); $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 );
return true; return true;
} }
@ -83,29 +84,24 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) {
list($h, $m, $s) = explode(':', $value); list($h, $m, $s) = explode(':', $value);
$days = $h / 24 + $m / 1440 + $s / 86400; $days = $h / 24 + $m / 1440 + $s / 86400;
// Convert value to number // Convert value to number
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style // Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 ); $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 );
return true; return true;
} }
// Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' // Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10'
if (($v = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) {
// Convert value to Excel date // Convert value to number
$cell->setValueExplicit($v, PHPExcel_Cell_DataType::TYPE_NUMERIC); $cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Determine style. Either there is a time part or not. Look for ':'
// Set style. Either there is a time part or not. Look for ':'
if (strpos($value, ':') !== false) { if (strpos($value, ':') !== false) {
$formatCode = 'yyyy-mm-dd h:mm'; $formatCode = 'yyyy-mm-dd h:mm';
} else { } else {
$formatCode = 'yyyy-mm-dd'; $formatCode = 'yyyy-mm-dd';
} }
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode($formatCode); $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode($formatCode);
return true; return true;
} }
@ -113,10 +109,8 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
if (strpos($value, "\n") !== false) { if (strpos($value, "\n") !== false) {
$value = PHPExcel_Shared_String::SanitizeUTF8($value); $value = PHPExcel_Shared_String::SanitizeUTF8($value);
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING);
// Set style // Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getAlignment()->setWrapText(true); $cell->getParent()->getStyle( $cell->getCoordinate() )->getAlignment()->setWrapText(true);
return true; return true;
} }
} }

View File

@ -273,31 +273,22 @@ class PHPExcel_Shared_Date
* @return float|false Excel date/time serial value * @return float|false Excel date/time serial value
*/ */
public static function stringToExcel($dateValue = '') { public static function stringToExcel($dateValue = '') {
// restrict to dates and times like these because date_parse accepts too many strings $dateValueNew = PHPExcel_Calculation_Functions::DATEVALUE($dateValue);
// '2009-12-31'
// '2009-12-31 15:59' if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) {
// '2009-12-31 15:59:10' return false;
if (!preg_match('/^\d{4}\-\d{1,2}\-\d{1,2}( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/', $dateValue)) { } else {
if (strpos($dateValue, ':') !== false) {
$timeValue = PHPExcel_Calculation_Functions::TIMEVALUE($dateValue);
if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) {
return false; return false;
} }
$dateValueNew += $timeValue;
// now try with date_parse }
$PHPDateArray = date_parse($dateValue); return $dateValueNew;
if ($PHPDateArray['error_count'] == 0) {
$year = $PHPDateArray['year'] !== false ? $PHPDateArray['year'] : self::getExcelCalendar();
$month = $PHPDateArray['month'] !== false ? $PHPDateArray['month'] : 1;
$day = $PHPDateArray['day'] !== false ? $PHPDateArray['day'] : 0;
$hour = $PHPDateArray['hour'] !== false ? $PHPDateArray['hour'] : 0;
$minute = $PHPDateArray['minute'] !== false ? $PHPDateArray['minute'] : 0;
$second = $PHPDateArray['second'] !== false ? $PHPDateArray['second'] : 0;
$excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year, $month, $day, $hour, $minute, $second);
return $excelDateValue;
} }
return false;
} }
} }

View File

@ -69,19 +69,67 @@ $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(14);
// Add some data, resembling some different data types // Add some data, resembling some different data types
echo date('H:i:s') . " Add some data\n"; echo date('H:i:s') . " Add some data\n";
$objPHPExcel->getActiveSheet()->setCellValue('A1', 'String value:'); $objPHPExcel->getActiveSheet()->setCellValue('A1', 'String value:');
$objPHPExcel->getActiveSheet()->setCellValue('B1', 'String'); $objPHPExcel->getActiveSheet()->setCellValue('B1', 'Mark Baker');
$objPHPExcel->getActiveSheet()->setCellValue('A2', 'Numeric value:'); $objPHPExcel->getActiveSheet()->setCellValue('A2', 'Numeric value #1:');
$objPHPExcel->getActiveSheet()->setCellValue('B2', 12); $objPHPExcel->getActiveSheet()->setCellValue('B2', 12345);
$objPHPExcel->getActiveSheet()->setCellValue('A3', 'Boolean value:'); $objPHPExcel->getActiveSheet()->setCellValue('A3', 'Numeric value #2:');
$objPHPExcel->getActiveSheet()->setCellValue('B3', true); $objPHPExcel->getActiveSheet()->setCellValue('B3', -12.345);
$objPHPExcel->getActiveSheet()->setCellValue('A4', 'Percentage value:'); $objPHPExcel->getActiveSheet()->setCellValue('A4', 'Numeric value #3:');
$objPHPExcel->getActiveSheet()->setCellValue('B4', '10%'); $objPHPExcel->getActiveSheet()->setCellValue('B4', .12345);
$objPHPExcel->getActiveSheet()->setCellValue('A5', 'Date/time value:'); $objPHPExcel->getActiveSheet()->setCellValue('A5', 'Numeric value #4:');
$objPHPExcel->getActiveSheet()->setCellValue('B5', '21 December 1983'); $objPHPExcel->getActiveSheet()->setCellValue('B5', '12345');
$objPHPExcel->getActiveSheet()->setCellValue('A6', 'Numeric value #5:');
$objPHPExcel->getActiveSheet()->setCellValue('B6', '1.2345');
$objPHPExcel->getActiveSheet()->setCellValue('A7', 'Numeric value #6:');
$objPHPExcel->getActiveSheet()->setCellValue('B7', '.12345');
$objPHPExcel->getActiveSheet()->setCellValue('A8', 'Numeric value #7:');
$objPHPExcel->getActiveSheet()->setCellValue('B8', '1.234e-5');
$objPHPExcel->getActiveSheet()->setCellValue('A9', 'Numeric value #8:');
$objPHPExcel->getActiveSheet()->setCellValue('B9', '-1.234e+5');
$objPHPExcel->getActiveSheet()->setCellValue('A10', 'Boolean value:');
$objPHPExcel->getActiveSheet()->setCellValue('B10', true);
$objPHPExcel->getActiveSheet()->setCellValue('A11', 'Percentage value #1:');
$objPHPExcel->getActiveSheet()->setCellValue('B11', '10%');
$objPHPExcel->getActiveSheet()->setCellValue('A12', 'Percentage value #2:');
$objPHPExcel->getActiveSheet()->setCellValue('B12', '12.5%');
$objPHPExcel->getActiveSheet()->setCellValue('A13', 'Date value #1:');
$objPHPExcel->getActiveSheet()->setCellValue('B13', '21 December 1983');
$objPHPExcel->getActiveSheet()->setCellValue('A14', 'Date value #2:');
$objPHPExcel->getActiveSheet()->setCellValue('B14', '19-Dec-1960');
$objPHPExcel->getActiveSheet()->setCellValue('A15', 'Date value #3:');
$objPHPExcel->getActiveSheet()->setCellValue('B15', '19/12/1960');
$objPHPExcel->getActiveSheet()->setCellValue('A16', 'Date value #4:');
$objPHPExcel->getActiveSheet()->setCellValue('B16', '19-12-1960');
$objPHPExcel->getActiveSheet()->setCellValue('A17', 'Date value #5:');
$objPHPExcel->getActiveSheet()->setCellValue('B17', '1-Jan');
$objPHPExcel->getActiveSheet()->setCellValue('A18', 'Time value #1:');
$objPHPExcel->getActiveSheet()->setCellValue('B18', '01:30');
$objPHPExcel->getActiveSheet()->setCellValue('A19', 'Time value #2:');
$objPHPExcel->getActiveSheet()->setCellValue('B19', '01:30:15');
$objPHPExcel->getActiveSheet()->setCellValue('A20', 'Date/Time value:');
$objPHPExcel->getActiveSheet()->setCellValue('B20', '19-Dec-1960 01:30');
$objPHPExcel->getActiveSheet()->setCellValue('A21', 'Formula:');
$objPHPExcel->getActiveSheet()->setCellValue('B21', '=SUM(B2:B9)');
// Rename sheet // Rename sheet
echo date('H:i:s') . " Rename sheet\n"; echo date('H:i:s') . " Rename sheet\n";
@ -93,9 +141,9 @@ $objPHPExcel->setActiveSheetIndex(0);
// Save Excel 2007 file // Save Excel 2007 file
echo date('H:i:s') . " Write to Excel2007 format\n"; echo date('H:i:s') . " Write to Excel5 format\n";
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save(str_replace('.php', '.xlsx', __FILE__)); $objWriter->save(str_replace('.php', '.xls', __FILE__));
// Echo memory peak usage // Echo memory peak usage

View File

@ -36,6 +36,7 @@ Fixed in SVN:
- Bugfix: (MBaker) Workitem 14146 - Worksheet clone broken for CachedObjectStorage_Memory - Bugfix: (MBaker) Workitem 14146 - Worksheet clone broken for CachedObjectStorage_Memory
- Bugfix: (MBaker) Workitem 12998 - PHPExcel_Reader_Excel2007 fails when gradient fill without type is present in a file - Bugfix: (MBaker) Workitem 12998 - PHPExcel_Reader_Excel2007 fails when gradient fill without type is present in a file
- Bugfix: (MBaker) Workitem 14176 - @ format for numeric strings in XLSX to CSV conversion - Bugfix: (MBaker) Workitem 14176 - @ format for numeric strings in XLSX to CSV conversion
- Bugfix: (MBaker) Workitem 14223 - Advanced Value Binder Not Working?
2010-08-26 (v1.7.4): 2010-08-26 (v1.7.4):