diff --git a/CHANGELOG.md b/CHANGELOG.md index d4fae5c4..6f4bae1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Added - Improved the ARABIC function to also hande short-hand roman numerals +- Added support for the FLOOR.MATH and FLOOR.PRECISE functions [#1351](https://github.com/PHPOffice/PhpSpreadsheet/pull/1351) ### Fixed diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index ae86a963..69f72033 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -914,6 +914,16 @@ class Calculation 'functionCall' => [MathTrig::class, 'FLOOR'], 'argumentCount' => '2', ], + 'FLOOR.MATH' => [ + 'category' => Category::CATEGORY_MATH_AND_TRIG, + 'functionCall' => [MathTrig::class, 'FLOORMATH'], + 'argumentCount' => '3', + ], + 'FLOOR.PRECISE' => [ + 'category' => Category::CATEGORY_MATH_AND_TRIG, + 'functionCall' => [MathTrig::class, 'FLOORPRECISE'], + 'argumentCount' => '2', + ], 'FORECAST' => [ 'category' => Category::CATEGORY_STATISTICAL, 'functionCall' => [Statistical::class, 'FORECAST'], diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index 73403686..590ad99b 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -438,6 +438,80 @@ class MathTrig return Functions::VALUE(); } + /** + * FLOOR.MATH. + * + * Round a number down to the nearest integer or to the nearest multiple of significance. + * + * Excel Function: + * FLOOR.MATH(number[,significance[,mode]]) + * + * @category Mathematical and Trigonometric Functions + * + * @param float $number Number to round + * @param float $significance Significance + * @param int $mode direction to round negative numbers + * + * @return float|string Rounded Number, or a string containing an error + */ + public static function FLOORMATH($number, $significance = null, $mode = 0) + { + $number = Functions::flattenSingleValue($number); + $significance = Functions::flattenSingleValue($significance); + $mode = Functions::flattenSingleValue($mode); + + if (is_numeric($number) && $significance === null) { + $significance = $number / abs($number); + } + + if (is_numeric($number) && is_numeric($significance) && is_numeric($mode)) { + if ($significance == 0.0) { + return Functions::DIV0(); + } elseif ($number == 0.0) { + return 0.0; + } elseif (self::SIGN($significance) == -1 || (self::SIGN($number) == -1 && !empty($mode))) { + return ceil($number / $significance) * $significance; + } + + return floor($number / $significance) * $significance; + } + + return Functions::VALUE(); + } + + /** + * FLOOR.PRECISE. + * + * Rounds number down, toward zero, to the nearest multiple of significance. + * + * Excel Function: + * FLOOR.PRECISE(number[,significance]) + * + * @category Mathematical and Trigonometric Functions + * + * @param float $number Number to round + * @param float $significance Significance + * + * @return float|string Rounded Number, or a string containing an error + */ + public static function FLOORPRECISE($number, $significance = 1) + { + $number = Functions::flattenSingleValue($number); + $significance = Functions::flattenSingleValue($significance); + + if ((is_numeric($number)) && (is_numeric($significance))) { + if ($significance == 0.0) { + return Functions::DIV0(); + } elseif ($number == 0.0) { + return 0.0; + } + + return floor($number / abs($significance)) * abs($significance); + } + + return Functions::VALUE(); + } + private static function evaluateGCD($a, $b) { return $b ? self::evaluateGCD($b, $a % $b) : $a; diff --git a/src/PhpSpreadsheet/Calculation/functionlist.txt b/src/PhpSpreadsheet/Calculation/functionlist.txt index 7776e6ea..77fd4ee0 100644 --- a/src/PhpSpreadsheet/Calculation/functionlist.txt +++ b/src/PhpSpreadsheet/Calculation/functionlist.txt @@ -139,6 +139,8 @@ FISHER FISHERINV FIXED FLOOR +FLOOR.MATH +FLOOR.PRECISE FORECAST FREQUENCY FTEST diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php new file mode 100644 index 00000000..0e693e80 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php @@ -0,0 +1,31 @@ +assertEquals($expectedResult, $result, '', 1E-12); + } + + public function providerFLOORMATH() + { + return require 'data/Calculation/MathTrig/FLOORMATH.php'; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php new file mode 100644 index 00000000..616cb43b --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php @@ -0,0 +1,31 @@ +assertEquals($expectedResult, $result, '', 1E-12); + } + + public function providerFLOORPRECISE() + { + return require 'data/Calculation/MathTrig/FLOORPRECISE.php'; + } +} diff --git a/tests/data/Calculation/MathTrig/FLOORMATH.php b/tests/data/Calculation/MathTrig/FLOORMATH.php new file mode 100644 index 00000000..691b5245 --- /dev/null +++ b/tests/data/Calculation/MathTrig/FLOORMATH.php @@ -0,0 +1,89 @@ +