From 4d92e77d001ae36357bb992090d0a757415698d8 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sat, 15 Jun 2013 12:15:03 +0100 Subject: [PATCH] Eliminate need for use of money_format() function; various fixes to HLOOKUP, VLOOKUP and DOLLAR functions + unit tests --- Classes/PHPExcel/Calculation/Functions.php | 94 ------------------- Classes/PHPExcel/Calculation/LookupRef.php | 9 +- Classes/PHPExcel/Calculation/TextData.php | 11 ++- .../PHPExcel/Calculation/LookupRefTest.php | 16 ++++ .../PHPExcel/Style/NumberFormatTest.php | 3 + .../Calculation/LookupRef/VLOOKUP.data | 5 + 6 files changed, 37 insertions(+), 101 deletions(-) create mode 100644 unitTests/rawTestData/Calculation/LookupRef/VLOOKUP.data diff --git a/Classes/PHPExcel/Calculation/Functions.php b/Classes/PHPExcel/Calculation/Functions.php index 5de66c4..3004eec 100644 --- a/Classes/PHPExcel/Calculation/Functions.php +++ b/Classes/PHPExcel/Calculation/Functions.php @@ -689,100 +689,6 @@ if (!function_exists('atanh')) { } // function atanh() } -if (!function_exists('money_format')) { - function money_format($format, $number) { - $regex = array( '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?(?:#([0-9]+))?', - '(?:\.([0-9]+))?([in%])/' - ); - $regex = implode('', $regex); - if (setlocale(LC_MONETARY, null) == '') { - setlocale(LC_MONETARY, ''); - } - $locale = localeconv(); - $number = floatval($number); - if (!preg_match($regex, $format, $fmatch)) { - trigger_error("No format specified or invalid format", E_USER_WARNING); - return $number; - } - $flags = array( 'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ? $match[1] : ' ', - 'nogroup' => preg_match('/\^/', $fmatch[1]) > 0, - 'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ? $match[0] : '+', - 'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0, - 'isleft' => preg_match('/\-/', $fmatch[1]) > 0 - ); - $width = trim($fmatch[2]) ? (int)$fmatch[2] : 0; - $left = trim($fmatch[3]) ? (int)$fmatch[3] : 0; - $right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits']; - $conversion = $fmatch[5]; - $positive = true; - if ($number < 0) { - $positive = false; - $number *= -1; - } - $letter = $positive ? 'p' : 'n'; - $prefix = $suffix = $cprefix = $csuffix = $signal = ''; - if (!$positive) { - $signal = $locale['negative_sign']; - switch (true) { - case $locale['n_sign_posn'] == 0 || $flags['usesignal'] == '(': - $prefix = '('; - $suffix = ')'; - break; - case $locale['n_sign_posn'] == 1: - $prefix = $signal; - break; - case $locale['n_sign_posn'] == 2: - $suffix = $signal; - break; - case $locale['n_sign_posn'] == 3: - $cprefix = $signal; - break; - case $locale['n_sign_posn'] == 4: - $csuffix = $signal; - break; - } - } - if (!$flags['nosimbol']) { - $currency = $cprefix; - $currency .= ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']); - $currency .= $csuffix; - $currency = iconv('ISO-8859-1','UTF-8',$currency); - } else { - $currency = ''; - } - $space = $locale["{$letter}_sep_by_space"] ? ' ' : ''; - - if (!isset($locale['mon_decimal_point']) || empty($locale['mon_decimal_point'])) { - $locale['mon_decimal_point'] = (!isset($locale['decimal_point']) || empty($locale['decimal_point'])) ? - $locale['decimal_point'] : - '.'; - } - - $number = number_format($number, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep'] ); - $number = explode($locale['mon_decimal_point'], $number); - - $n = strlen($prefix) + strlen($currency); - if ($left > 0 && $left > $n) { - if ($flags['isleft']) { - $number[0] .= str_repeat($flags['fillchar'], $left - $n); - } else { - $number[0] = str_repeat($flags['fillchar'], $left - $n) . $number[0]; - } - } - $number = implode($locale['mon_decimal_point'], $number); - if ($locale["{$letter}_cs_precedes"]) { - $number = $prefix . $currency . $space . $number . $suffix; - } else { - $number = $prefix . $number . $space . $currency . $suffix; - } - if ($width > 0) { - $number = str_pad($number, $width, $flags['fillchar'], $flags['isleft'] ? STR_PAD_RIGHT : STR_PAD_LEFT); - } - $format = str_replace($fmatch[0], $number, $format); - return $format; - } // function money_format() -} - // // Strangely, PHP doesn't have a mb_str_replace multibyte function diff --git a/Classes/PHPExcel/Calculation/LookupRef.php b/Classes/PHPExcel/Calculation/LookupRef.php index c3a3f07..c3363f1 100644 --- a/Classes/PHPExcel/Calculation/LookupRef.php +++ b/Classes/PHPExcel/Calculation/LookupRef.php @@ -735,7 +735,11 @@ class PHPExcel_Calculation_LookupRef { return PHPExcel_Calculation_Functions::NA(); } else { // otherwise return the appropriate value - return $lookup_array[$rowNumber][$returnColumn]; + $result = $lookup_array[$rowNumber][$returnColumn]; + if ((is_numeric($lookup_value) && is_numeric($result)) || + (!is_numeric($lookup_value) && !is_numeric($result))) { + return $result; + } } } @@ -798,7 +802,8 @@ class PHPExcel_Calculation_LookupRef { return PHPExcel_Calculation_Functions::NA(); } else { // otherwise return the appropriate value - return $lookup_array[$returnColumn][$rowNumber]; + $result = $lookup_array[$returnColumn][$rowNumber]; + return $result; } } diff --git a/Classes/PHPExcel/Calculation/TextData.php b/Classes/PHPExcel/Calculation/TextData.php index d8a98db..90447c0 100644 --- a/Classes/PHPExcel/Calculation/TextData.php +++ b/Classes/PHPExcel/Calculation/TextData.php @@ -208,16 +208,17 @@ class PHPExcel_Calculation_TextData { } $decimals = floor($decimals); + $mask = '$#,##0'; if ($decimals > 0) { - return money_format('%.'.$decimals.'n',$value); + $mask .= '.' . str_repeat('0',$decimals); } else { $round = pow(10,abs($decimals)); if ($value < 0) { $round = 0-$round; } - $value = PHPExcel_Calculation_MathTrig::MROUND($value,$round); - // The implementation of money_format used if the standard PHP function is not available can't handle decimal places of 0, - // so we display to 1 dp and chop off that character and the decimal separator using substr - return substr(money_format('%.1n',$value),0,-2); + $value = PHPExcel_Calculation_MathTrig::MROUND($value, $round); } + + return PHPExcel_Style_NumberFormat::toFormattedString($value, $mask); + } // function DOLLAR() diff --git a/unitTests/Classes/PHPExcel/Calculation/LookupRefTest.php b/unitTests/Classes/PHPExcel/Calculation/LookupRefTest.php index bc63431..454422a 100644 --- a/unitTests/Classes/PHPExcel/Calculation/LookupRefTest.php +++ b/unitTests/Classes/PHPExcel/Calculation/LookupRefTest.php @@ -31,4 +31,20 @@ class LookupRefTest extends PHPUnit_Framework_TestCase return new testDataFileIterator('rawTestData/Calculation/LookupRef/HLOOKUP.data'); } + /** + * @dataProvider providerVLOOKUP + */ + public function testVLOOKUP() + { + $args = func_get_args(); + $expectedResult = array_pop($args); + $result = call_user_func_array(array('PHPExcel_Calculation_LookupRef','VLOOKUP'),$args); + $this->assertEquals($expectedResult, $result); + } + + public function providerVLOOKUP() + { + return new testDataFileIterator('rawTestData/Calculation/LookupRef/VLOOKUP.data'); + } + } diff --git a/unitTests/Classes/PHPExcel/Style/NumberFormatTest.php b/unitTests/Classes/PHPExcel/Style/NumberFormatTest.php index 10b4427..13fc3ed 100644 --- a/unitTests/Classes/PHPExcel/Style/NumberFormatTest.php +++ b/unitTests/Classes/PHPExcel/Style/NumberFormatTest.php @@ -12,6 +12,9 @@ class NumberFormatTest extends PHPUnit_Framework_TestCase define('PHPEXCEL_ROOT', APPLICATION_PATH . '/'); } require_once(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + + PHPExcel_Shared_String::setDecimalSeparator('.'); + PHPExcel_Shared_String::setThousandsSeparator(','); } /** diff --git a/unitTests/rawTestData/Calculation/LookupRef/VLOOKUP.data b/unitTests/rawTestData/Calculation/LookupRef/VLOOKUP.data new file mode 100644 index 0000000..8fefc6c --- /dev/null +++ b/unitTests/rawTestData/Calculation/LookupRef/VLOOKUP.data @@ -0,0 +1,5 @@ +1, {"Density"|"Viscosity"|"Temperature";0.457|3.55|500;0.525|3.25|400;0.616|2.93|300;0.675|2.75|250;0.746|2.57|200;0.835|2.38|150;0.946|2.17|100;1.09|1.95|50;1.29|1.71|0}, 2, FALSE, 2.17 +1, {"Density"|"Viscosity"|"Temperature";0.457|3.55|500;0.525|3.25|400;0.616|2.93|300;0.675|2.75|250;0.746|2.57|200;0.835|2.38|150;0.946|2.17|100;1.09|1.95|50;1.29|1.71|0}, 3, TRUE, 100 +.7, {"Density"|"Viscosity"|"Temperature";0.457|3.55|500;0.525|3.25|400;0.616|2.93|300;0.675|2.75|250;0.746|2.57|200;0.835|2.38|150;0.946|2.17|100;1.09|1.95|50;1.29|1.71|0}, 3, FALSE, "#N/A" +0.1, {"Density"|"Viscosity"|"Temperature";0.457|3.55|500;0.525|3.25|400;0.616|2.93|300;0.675|2.75|250;0.746|2.57|200;0.835|2.38|150;0.946|2.17|100;1.09|1.95|50;1.29|1.71|0}, 2, TRUE, "#N/A" +2, {"Density"|"Viscosity"|"Temperature";0.457|3.55|500;0.525|3.25|400;0.616|2.93|300;0.675|2.75|250;0.746|2.57|200;0.835|2.38|150;0.946|2.17|100;1.09|1.95|50;1.29|1.71|0}, 2, TRUE, 1.71