From 3f807a1c01186d8e70e615ab6532cb00e6c44a98 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 10 Sep 2010 14:57:07 +0000 Subject: [PATCH] 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 --- Classes/PHPExcel/Cell/AdvancedValueBinder.php | 26 +++---- Classes/PHPExcel/Shared/Date.php | 33 ++++----- Tests/29advancedvaluebinder.php | 72 +++++++++++++++---- changelog.txt | 1 + 4 files changed, 83 insertions(+), 49 deletions(-) diff --git a/Classes/PHPExcel/Cell/AdvancedValueBinder.php b/Classes/PHPExcel/Cell/AdvancedValueBinder.php index 6d0423fa..5bee95d7 100644 --- a/Classes/PHPExcel/Cell/AdvancedValueBinder.php +++ b/Classes/PHPExcel/Cell/AdvancedValueBinder.php @@ -54,14 +54,18 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder // Style logic - strings 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 if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { // Convert value to number $cell->setValueExplicit( (float)str_replace('%', '', $value) / 100, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE ); - 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)) { list($h, $m) = explode(':', $value); $days = $h / 24 + $m / 1440; - // Convert value to number $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 ); - 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)) { list($h, $m, $s) = explode(':', $value); $days = $h / 24 + $m / 1440 + $s / 86400; - // Convert value to number $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 ); - return true; } // 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) { - // Convert value to Excel date - $cell->setValueExplicit($v, PHPExcel_Cell_DataType::TYPE_NUMERIC); - - // Set style. Either there is a time part or not. Look for ':' + if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { + // Convert value to number + $cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Determine style. Either there is a time part or not. Look for ':' if (strpos($value, ':') !== false) { $formatCode = 'yyyy-mm-dd h:mm'; } else { $formatCode = 'yyyy-mm-dd'; } $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode($formatCode); - return true; } @@ -113,10 +109,8 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder if (strpos($value, "\n") !== false) { $value = PHPExcel_Shared_String::SanitizeUTF8($value); $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); - // Set style $cell->getParent()->getStyle( $cell->getCoordinate() )->getAlignment()->setWrapText(true); - return true; } } diff --git a/Classes/PHPExcel/Shared/Date.php b/Classes/PHPExcel/Shared/Date.php index 6bcca9b6..01695392 100644 --- a/Classes/PHPExcel/Shared/Date.php +++ b/Classes/PHPExcel/Shared/Date.php @@ -273,31 +273,22 @@ class PHPExcel_Shared_Date * @return float|false Excel date/time serial value */ public static function stringToExcel($dateValue = '') { - // restrict to dates and times like these because date_parse accepts too many strings - // '2009-12-31' - // '2009-12-31 15:59' - // '2009-12-31 15:59:10' - if (!preg_match('/^\d{4}\-\d{1,2}\-\d{1,2}( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/', $dateValue)) { + $dateValueNew = PHPExcel_Calculation_Functions::DATEVALUE($dateValue); + + if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) { return false; + } else { + if (strpos($dateValue, ':') !== false) { + $timeValue = PHPExcel_Calculation_Functions::TIMEVALUE($dateValue); + if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) { + return false; + } + $dateValueNew += $timeValue; + } + return $dateValueNew; } - // now try with date_parse - $PHPDateArray = date_parse($dateValue); - 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; } } diff --git a/Tests/29advancedvaluebinder.php b/Tests/29advancedvaluebinder.php index 3e28fcdd..d486c108 100644 --- a/Tests/29advancedvaluebinder.php +++ b/Tests/29advancedvaluebinder.php @@ -69,19 +69,67 @@ $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(14); // Add some data, resembling some different data types echo date('H:i:s') . " Add some data\n"; $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('B2', 12); +$objPHPExcel->getActiveSheet()->setCellValue('A2', 'Numeric value #1:'); +$objPHPExcel->getActiveSheet()->setCellValue('B2', 12345); -$objPHPExcel->getActiveSheet()->setCellValue('A3', 'Boolean value:'); -$objPHPExcel->getActiveSheet()->setCellValue('B3', true); +$objPHPExcel->getActiveSheet()->setCellValue('A3', 'Numeric value #2:'); +$objPHPExcel->getActiveSheet()->setCellValue('B3', -12.345); -$objPHPExcel->getActiveSheet()->setCellValue('A4', 'Percentage value:'); -$objPHPExcel->getActiveSheet()->setCellValue('B4', '10%'); +$objPHPExcel->getActiveSheet()->setCellValue('A4', 'Numeric value #3:'); +$objPHPExcel->getActiveSheet()->setCellValue('B4', .12345); -$objPHPExcel->getActiveSheet()->setCellValue('A5', 'Date/time value:'); -$objPHPExcel->getActiveSheet()->setCellValue('B5', '21 December 1983'); +$objPHPExcel->getActiveSheet()->setCellValue('A5', 'Numeric value #4:'); +$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 echo date('H:i:s') . " Rename sheet\n"; @@ -93,9 +141,9 @@ $objPHPExcel->setActiveSheetIndex(0); // Save Excel 2007 file -echo date('H:i:s') . " Write to Excel2007 format\n"; -$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); -$objWriter->save(str_replace('.php', '.xlsx', __FILE__)); +echo date('H:i:s') . " Write to Excel5 format\n"; +$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); +$objWriter->save(str_replace('.php', '.xls', __FILE__)); // Echo memory peak usage diff --git a/changelog.txt b/changelog.txt index 6eeae22e..ce8b91ef 100644 --- a/changelog.txt +++ b/changelog.txt @@ -36,6 +36,7 @@ Fixed in SVN: - 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 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):