diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index ae33e45cb8..12826a759b 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -463,18 +463,18 @@ class Calculation ], 'CEILING' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'CEILING'], - 'argumentCount' => '2', + 'functionCall' => [MathTrig\Ceiling::class, 'funcCeiling'], + 'argumentCount' => '1-2', // 2 for Excel, 1-2 for Ods/Gnumeric ], 'CEILING.MATH' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [Functions::class, 'DUMMY'], - 'argumentCount' => '3', + 'functionCall' => [MathTrig\CeilingMath::class, 'funcCeilingMath'], + 'argumentCount' => '1-3', ], 'CEILING.PRECISE' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [Functions::class, 'DUMMY'], - 'argumentCount' => '2', + 'functionCall' => [MathTrig\CeilingPrecise::class, 'funcCeilingPrecise'], + 'argumentCount' => '1,2', ], 'CELL' => [ 'category' => Category::CATEGORY_INFORMATION, @@ -1069,18 +1069,18 @@ class Calculation ], 'FLOOR' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'FLOOR'], - 'argumentCount' => '2', + 'functionCall' => [MathTrig\Floor::class, 'funcFloor'], + 'argumentCount' => '1-2', // Excel requries 2, Ods/Gnumeric 1-2 ], 'FLOOR.MATH' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'FLOORMATH'], - 'argumentCount' => '3', + 'functionCall' => [MathTrig\FloorMath::class, 'funcFloorMath'], + 'argumentCount' => '1-3', ], 'FLOOR.PRECISE' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'FLOORPRECISE'], - 'argumentCount' => '2', + 'functionCall' => [MathTrig\FloorPrecise::class, 'funcFloorPrecise'], + 'argumentCount' => '1-2', ], 'FORECAST' => [ 'category' => Category::CATEGORY_STATISTICAL, @@ -1418,7 +1418,7 @@ class Calculation ], 'INT' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'INT'], + 'functionCall' => [MathTrig\IntClass::class, 'funcInt'], 'argumentCount' => '1', ], 'INTERCEPT' => [ @@ -1725,7 +1725,7 @@ class Calculation ], 'MROUND' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'MROUND'], + 'functionCall' => [MathTrig\Mround::class, 'funcMround'], 'argumentCount' => '2', ], 'MULTINOMIAL' => [ @@ -2112,17 +2112,17 @@ class Calculation ], 'ROUND' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'builtinROUND'], + 'functionCall' => [MathTrig\Round::class, 'builtinROUND'], 'argumentCount' => '2', ], 'ROUNDDOWN' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'ROUNDDOWN'], + 'functionCall' => [MathTrig\RoundDown::class, 'funcRoundDown'], 'argumentCount' => '2', ], 'ROUNDUP' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'ROUNDUP'], + 'functionCall' => [MathTrig\RoundUp::class, 'funcRoundUp'], 'argumentCount' => '2', ], 'ROW' => [ @@ -2474,7 +2474,7 @@ class Calculation ], 'TRUNC' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, - 'functionCall' => [MathTrig::class, 'TRUNC'], + 'functionCall' => [MathTrig\Trunc::class, 'funcTrunc'], 'argumentCount' => '1,2', ], 'TTEST' => [ diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index 9ce4a75244..7a864b977f 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -223,34 +223,18 @@ public static function BASE($number, $radix, $minLength = null) * Excel Function: * CEILING(number[,significance]) * + * @Deprecated 2.0.0 Use the funcCeiling method in the MathTrig\Ceiling class instead + * * @param float $number the number you want to round * @param float $significance the multiple to which you want to round * * @return float|string Rounded Number, or a string containing an error + * + * @codeCoverageIgnore */ public static function CEILING($number, $significance = null) { - $number = Functions::flattenSingleValue($number); - $significance = Functions::flattenSingleValue($significance); - - if ( - ($significance === null) && - (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) - ) { - $significance = $number / abs($number); - } - - if ((is_numeric($number)) && (is_numeric($significance))) { - if (($number == 0.0) || ($significance == 0.0)) { - return 0.0; - } elseif (self::SIGN($number) == self::SIGN($significance)) { - return ceil($number / $significance) * $significance; - } - - return Functions::NAN(); - } - - return Functions::VALUE(); + return MathTrig\Ceiling::funcCeiling($number, $significance); } /** @@ -312,14 +296,19 @@ public static function EVEN($number) } if (is_numeric($number)) { - $significance = 2 * self::SIGN($number); - - return (int) self::CEILING($number, $significance); + return self::getEven((float) $number); } return Functions::VALUE(); } + public static function getEven(float $number): int + { + $significance = 2 * self::returnSign($number); + + return (int) MathTrig\Ceiling::funcCeiling($number, $significance); + } + /** * FACT. * @@ -401,38 +390,18 @@ public static function FACTDOUBLE($factVal) * Excel Function: * FLOOR(number[,significance]) * + * @Deprecated 2.0.0 Use the funcFloor method in the MathTrig\Floor class instead + * * @param float $number Number to round * @param float $significance Significance * * @return float|string Rounded Number, or a string containing an error + * + * @codeCoverageIgnore */ public static function FLOOR($number, $significance = null) { - $number = Functions::flattenSingleValue($number); - $significance = Functions::flattenSingleValue($significance); - - if ( - ($significance === null) && - (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) - ) { - $significance = $number / abs($number); - } - - if ((is_numeric($number)) && (is_numeric($significance))) { - if ($significance == 0.0) { - return Functions::DIV0(); - } elseif ($number == 0.0) { - return 0.0; - } elseif (self::SIGN($significance) == 1) { - return floor($number / $significance) * $significance; - } elseif (self::SIGN($number) == -1 && self::SIGN($significance) == -1) { - return floor($number / $significance) * $significance; - } - - return Functions::NAN(); - } - - return Functions::VALUE(); + return MathTrig\Floor::funcFloor($number, $significance); } /** @@ -443,35 +412,19 @@ public static function FLOOR($number, $significance = null) * Excel Function: * FLOOR.MATH(number[,significance[,mode]]) * + * @Deprecated 2.0.0 Use the funcFloorMath method in the MathTrig\FloorMath class instead + * * @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 + * + * @codeCoverageIgnore */ 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(); + return MathTrig\FloorMath::funcFloorMath($number, $significance, $mode); } /** @@ -482,27 +435,18 @@ public static function FLOORMATH($number, $significance = null, $mode = 0) * Excel Function: * FLOOR.PRECISE(number[,significance]) * + * @Deprecated 2.0.0 Use the funcFloorPrecise method in the MathTrig\FloorPrecise class instead + * * @param float $number Number to round * @param float $significance Significance * * @return float|string Rounded Number, or a string containing an error + * + * @codeCoverageIgnore */ 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(); + return MathTrig\FloorPrecise::funcFloorPrecise($number, $significance); } private static function evaluateGCD($a, $b) @@ -510,6 +454,27 @@ private static function evaluateGCD($a, $b) return $b ? self::evaluateGCD($b, $a % $b) : $a; } + /** + * INT. + * + * Casts a floating point value to an integer + * + * Excel Function: + * INT(number) + * + * @Deprecated 2.0.0 Use the funcInt method in the MathTrig\IntClass class instead + * + * @param float $number Number to cast to an integer + * + * @return int|string Integer value, or a string containing an error + * + * @codeCoverageIgnore + */ + public static function INT($number) + { + return MathTrig\IntClass::funcInt($number); + } + /** * GCD. * @@ -544,34 +509,6 @@ public static function GCD(...$args) return $gcd; } - /** - * INT. - * - * Casts a floating point value to an integer - * - * Excel Function: - * INT(number) - * - * @param float $number Number to cast to an integer - * - * @return int|string Integer value, or a string containing an error - */ - public static function INT($number) - { - $number = Functions::flattenSingleValue($number); - - if ($number === null) { - return 0; - } elseif (is_bool($number)) { - return (int) $number; - } - if (is_numeric($number)) { - return (int) floor($number); - } - - return Functions::VALUE(); - } - /** * LCM. * @@ -847,30 +784,18 @@ public static function MOD($a = 1, $b = 1) * * Rounds a number to the nearest multiple of a specified value * + * @Deprecated 2.0.0 Use the funcMround method in the MathTrig\Mround class instead + * * @param float $number Number to round * @param int $multiple Multiple to which you want to round $number * * @return float|string Rounded Number, or a string containing an error + * + * @codeCoverageIgnore */ public static function MROUND($number, $multiple) { - $number = Functions::flattenSingleValue($number); - $multiple = Functions::flattenSingleValue($multiple); - - if ((is_numeric($number)) && (is_numeric($multiple))) { - if ($number == 0 || $multiple == 0) { - return 0; - } - if ((self::SIGN($number)) == (self::SIGN($multiple))) { - $multiplier = 1 / $multiple; - - return round($number * $multiplier) / $multiplier; - } - - return Functions::NAN(); - } - - return Functions::VALUE(); + return MathTrig\Mround::funcMround($number, $multiple); } /** @@ -928,13 +853,16 @@ public static function ODD($number) } elseif (is_bool($number)) { return 1; } elseif (is_numeric($number)) { - $significance = self::SIGN($number); + $significance = self::returnSign($number); if ($significance == 0) { return 1; } - $result = self::CEILING($number, $significance); - if ($result == self::EVEN($result)) { + $result = MathTrig\Ceiling::funcCeiling($number, $significance); + if (is_string($result)) { + return $result; + } + if ($result == self::getEven((float) $result)) { $result += $significance; } @@ -1104,29 +1032,18 @@ public static function ROMAN($aValue, $style = 0) * * Rounds a number up to a specified number of decimal places * + * @Deprecated 2.0.0 Use the funcRoundUp method in the MathTrig\RoundUp class instead + * * @param float $number Number to round * @param int $digits Number of digits to which you want to round $number * * @return float|string Rounded Number, or a string containing an error + * + * @codeCoverageIgnore */ public static function ROUNDUP($number, $digits) { - $number = Functions::flattenSingleValue($number); - $digits = Functions::flattenSingleValue($digits); - - if ((is_numeric($number)) && (is_numeric($digits))) { - if ($number == 0.0) { - return 0.0; - } - - if ($number < 0.0) { - return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN); - } - - return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN); - } - - return Functions::VALUE(); + return MathTrig\RoundUp::funcRoundUp($number, $digits); } /** @@ -1134,29 +1051,18 @@ public static function ROUNDUP($number, $digits) * * Rounds a number down to a specified number of decimal places * + * @Deprecated 2.0.0 Use the funcRoundDown method in the MathTrig\RoundDown class instead + * * @param float $number Number to round * @param int $digits Number of digits to which you want to round $number * * @return float|string Rounded Number, or a string containing an error + * + * @codeCoverageIgnore */ public static function ROUNDDOWN($number, $digits) { - $number = Functions::flattenSingleValue($number); - $digits = Functions::flattenSingleValue($digits); - - if ((is_numeric($number)) && (is_numeric($digits))) { - if ($number == 0.0) { - return 0.0; - } - - if ($number < 0.0) { - return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP); - } - - return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP); - } - - return Functions::VALUE(); + return MathTrig\RoundDown::funcRoundDown($number, $digits); } /** @@ -1215,16 +1121,17 @@ public static function SIGN($number) return (int) $number; } if (is_numeric($number)) { - if ($number == 0.0) { - return 0; - } - - return $number / abs($number); + return self::returnSign($number); } return Functions::VALUE(); } + public static function returnSign(float $number): int + { + return $number ? (($number > 0) ? 1 : -1) : 0; + } + /** * SQRTPI. * @@ -1628,30 +1535,18 @@ public static function SUMXMY2($matrixData1, $matrixData2) * * Truncates value to the number of fractional digits by number_digits. * + * @Deprecated 2.0.0 Use the funcTrunc method in the MathTrig\Trunc class instead + * * @param float $value * @param int $digits * * @return float|string Truncated value, or a string containing an error + * + * @codeCoverageIgnore */ public static function TRUNC($value = 0, $digits = 0) { - $value = Functions::flattenSingleValue($value); - $digits = Functions::flattenSingleValue($digits); - - // Validate parameters - if ((!is_numeric($value)) || (!is_numeric($digits))) { - return Functions::VALUE(); - } - $digits = floor($digits); - - // Truncate - $adjust = 10 ** $digits; - - if (($digits > 0) && (rtrim((int) ((abs($value) - abs((int) $value)) * $adjust), '0') < $adjust / 10)) { - return $value; - } - - return ((int) ($value * $adjust)) / $adjust; + return MathTrig\Trunc::funcTrunc($value, $digits); } /** @@ -1845,20 +1740,18 @@ public static function ACOTH($number) * * Returns the result of builtin function round after validating args. * + * @Deprecated 2.0.0 Use the builtinRound method in the MathTrig\Round class instead + * * @param mixed $number Should be numeric * @param mixed $precision Should be int * * @return float|string Rounded number + * + * @codeCoverageIgnore */ public static function builtinROUND($number, $precision) { - $number = Functions::flattenSingleValue($number); - - if (!is_numeric($number) || !is_numeric($precision)) { - return Functions::VALUE(); - } - - return round($number, $precision); + return MathTrig\Round::builtinRound($number, $precision); } /** @@ -2245,4 +2138,19 @@ private static function verySmallDivisor(float $number): bool { return abs($number) < 1.0E-12; } + + /** + * Many functions accept null/false/true argument treated as 0/0/1. + * + * @param mixed $number + */ + public static function nullFalseTrueToNumber(&$number): void + { + $number = Functions::flattenSingleValue($number); + if ($number === null) { + $number = 0; + } elseif (is_bool($number)) { + $number = (int) $number; + } + } } diff --git a/src/PhpSpreadsheet/Calculation/MathTrig/Ceiling.php b/src/PhpSpreadsheet/Calculation/MathTrig/Ceiling.php new file mode 100644 index 0000000000..6fdd616586 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/MathTrig/Ceiling.php @@ -0,0 +1,68 @@ + 0) && (rtrim((int) ((abs($value) - abs((int) $value)) * $adjust), '0') < $adjust / 10)) { + return $value; + } + + return ((int) ($value * $adjust)) / $adjust; + } +} diff --git a/src/PhpSpreadsheet/Calculation/TextData.php b/src/PhpSpreadsheet/Calculation/TextData.php index 163756649f..cea15fdca1 100644 --- a/src/PhpSpreadsheet/Calculation/TextData.php +++ b/src/PhpSpreadsheet/Calculation/TextData.php @@ -172,7 +172,7 @@ public static function DOLLAR($value = 0, $decimals = 2) if ($value < 0) { $round = 0 - $round; } - $value = MathTrig::MROUND($value, $round); + $value = MathTrig\Mround::funcMround($value, $round); } $mask = "$mask;($mask)"; diff --git a/src/PhpSpreadsheet/Calculation/functionlist.txt b/src/PhpSpreadsheet/Calculation/functionlist.txt index 8fed43a6fb..96c28a9739 100644 --- a/src/PhpSpreadsheet/Calculation/functionlist.txt +++ b/src/PhpSpreadsheet/Calculation/functionlist.txt @@ -40,6 +40,8 @@ BITOR BITRSHIFT BITXOR CEILING +CEILING.MATH +CEILING.PRECISE CELL CHAR CHIDIST diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php b/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php index 8f7c07e83a..c322dfc75f 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php @@ -10,6 +10,7 @@ class Xlfn . '|beta[.]inv' . '|binom[.]dist' . '|binom[.]inv' + . '|ceiling[.]precise' . '|chisq[.]dist' . '|chisq[.]dist[.]rt' . '|chisq[.]inv' @@ -27,6 +28,7 @@ class Xlfn . '|f[.]inv' . '|f[.]inv[.]rt' . '|f[.]test' + . '|floor[.]precise' . '|gamma[.]dist' . '|gamma[.]inv' . '|gammaln[.]precise' diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingMathTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingMathTest.php new file mode 100644 index 0000000000..1d62b8c3b0 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingMathTest.php @@ -0,0 +1,37 @@ +expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=CEILING.MATH($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta($expectedResult, $result, 1E-12); + } + + public function providerCEILINGMATH() + { + return require 'tests/data/Calculation/MathTrig/CEILINGMATH.php'; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingPreciseTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingPreciseTest.php new file mode 100644 index 0000000000..d47670b71e --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingPreciseTest.php @@ -0,0 +1,37 @@ +expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=CEILING.PRECISE($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta($expectedResult, $result, 1E-12); + } + + public function providerFLOORPRECISE() + { + return require 'tests/data/Calculation/MathTrig/CEILINGPRECISE.php'; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingTest.php index b60d7c304e..ad99b5f02d 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/CeilingTest.php @@ -2,25 +2,45 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class CeilingTest extends TestCase { + private $compatibilityMode; + protected function setUp(): void { + $this->compatibilityMode = Functions::getCompatibilityMode(); Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); } + protected function tearDown(): void + { + Functions::setCompatibilityMode($this->compatibilityMode); + } + /** * @dataProvider providerCEILING * * @param mixed $expectedResult + * @param string $formula */ - public function testCEILING($expectedResult, ...$args): void + public function testCEILING($expectedResult, $formula): void { - $result = MathTrig::CEILING(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=CEILING($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } @@ -28,4 +48,35 @@ public function providerCEILING() { return require 'tests/data/Calculation/MathTrig/CEILING.php'; } + + public function testCEILINGGnumeric1Arg(): void + { + Functions::setCompatibilityMode(Functions::COMPATIBILITY_GNUMERIC); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('=CEILING(5.1)'); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta(6, $result, 1E-12); + } + + public function testCELINGOpenOffice1Arg(): void + { + Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('=CEILING(5.1)'); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta(6, $result, 1E-12); + } + + public function testFLOORExcel1Arg(): void + { + $this->expectException(CalcExp::class); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); + $sheet->getCell('A1')->setValue('=CEILING(5.1)'); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta(6, $result, 1E-12); + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php index d7d51b590b..ce546159fb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorMathTest.php @@ -2,25 +2,31 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class FloorMathTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerFLOORMATH * * @param mixed $expectedResult + * @param string $formula */ - public function testFLOORMATH($expectedResult, ...$args): void + public function testFLOORMATH($expectedResult, $formula): void { - $result = MathTrig::FLOORMATH(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=FLOOR.MATH($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php index ae5a3199f7..961ca8ae76 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorPreciseTest.php @@ -2,25 +2,31 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class FloorPreciseTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerFLOORPRECISE * * @param mixed $expectedResult + * @param string $formula */ - public function testFLOOR($expectedResult, ...$args): void + public function testFLOORPRECISE($expectedResult, $formula): void { - $result = MathTrig::FLOORPRECISE(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=FLOOR.PRECISE($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorTest.php index e66d97ae26..82a142c2d5 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FloorTest.php @@ -2,25 +2,45 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class FloorTest extends TestCase { + private $compatibilityMode; + protected function setUp(): void { + $this->compatibilityMode = Functions::getCompatibilityMode(); Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); } + protected function tearDown(): void + { + Functions::setCompatibilityMode($this->compatibilityMode); + } + /** * @dataProvider providerFLOOR * * @param mixed $expectedResult + * @param string $formula */ - public function testFLOOR($expectedResult, ...$args): void + public function testFLOOR($expectedResult, $formula): void { - $result = MathTrig::FLOOR(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=FLOOR($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } @@ -28,4 +48,35 @@ public function providerFLOOR() { return require 'tests/data/Calculation/MathTrig/FLOOR.php'; } + + public function testFLOORGnumeric1Arg(): void + { + Functions::setCompatibilityMode(Functions::COMPATIBILITY_GNUMERIC); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('=FLOOR(5.1)'); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta(5, $result, 1E-12); + } + + public function testFLOOROpenOffice1Arg(): void + { + Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->getCell('A1')->setValue('=FLOOR(5.1)'); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta(5, $result, 1E-12); + } + + public function testFLOORExcel1Arg(): void + { + $this->expectException(CalcExp::class); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); + $sheet->getCell('A1')->setValue('=FLOOR(5.1)'); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta(5, $result, 1E-12); + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php index f400a7feb6..5c0b12c8dc 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php @@ -2,27 +2,32 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class IntTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerINT * * @param mixed $expectedResult - * @param $value + * @param string $formula */ - public function testINT($expectedResult, $value): void + public function testINT($expectedResult, $formula): void { - $result = MathTrig::INT($value); - self::assertEquals($expectedResult, $result); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=INT($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); + self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } public function providerINT() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MRoundTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MRoundTest.php index 32c9c35544..87554d06ee 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MRoundTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MRoundTest.php @@ -2,25 +2,31 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class MRoundTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerMROUND * * @param mixed $expectedResult + * @param mixed $formula */ - public function testMROUND($expectedResult, ...$args): void + public function testMROUND($expectedResult, $formula): void { - $result = MathTrig::MROUND(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=MROUND($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MovedFunctionsTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MovedFunctionsTest.php new file mode 100644 index 0000000000..d8b55e7cc4 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/MovedFunctionsTest.php @@ -0,0 +1,30 @@ +expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=ROUNDDOWN($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } - public function providerROUNDDOWN() + public function providerRoundDown() { return require 'tests/data/Calculation/MathTrig/ROUNDDOWN.php'; } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundTest.php index 3cd353a492..dd09bbaa47 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundTest.php @@ -12,23 +12,20 @@ class RoundTest extends TestCase * @dataProvider providerRound * * @param mixed $expectedResult - * @param mixed $val - * @param mixed $precision + * @param mixed $formula */ - public function testRound($expectedResult, $val = null, $precision = null): void + public function testRound($expectedResult, $formula): void { - if ($val === null) { + if ($expectedResult === 'exception') { $this->expectException(CalcExp::class); - $formula = '=ROUND()'; - } elseif ($precision === null) { - $this->expectException(CalcExp::class); - $formula = "=ROUND($val)"; - } else { - $formula = "=ROUND($val, $precision)"; } $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); - $sheet->getCell('A1')->setValue($formula); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=ROUND($formula)"); $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundUpTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundUpTest.php index 825fe4194b..7907be42b1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundUpTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/RoundUpTest.php @@ -2,29 +2,35 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class RoundUpTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** - * @dataProvider providerROUNDUP + * @dataProvider providerRoundUp * * @param mixed $expectedResult + * @param mixed $formula */ - public function testROUNDUP($expectedResult, ...$args): void + public function testRoundUp($expectedResult, $formula): void { - $result = MathTrig::ROUNDUP(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=ROUNDUP($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } - public function providerROUNDUP() + public function providerRoundUp() { return require 'tests/data/Calculation/MathTrig/ROUNDUP.php'; } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/TruncTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/TruncTest.php index 5fc248ccea..37740c0dff 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/TruncTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/TruncTest.php @@ -2,25 +2,31 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig; +use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp; +use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; class TruncTest extends TestCase { - protected function setUp(): void - { - Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); - } - /** * @dataProvider providerTRUNC * * @param mixed $expectedResult + * @param string $formula */ - public function testTRUNC($expectedResult, ...$args): void + public function testTRUNC($expectedResult, $formula): void { - $result = MathTrig::TRUNC(...$args); + if ($expectedResult === 'exception') { + $this->expectException(CalcExp::class); + } + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A2', 1.3); + $sheet->setCellValue('A3', 2.7); + $sheet->setCellValue('A4', -3.8); + $sheet->setCellValue('A5', -5.2); + $sheet->getCell('A1')->setValue("=TRUNC($formula)"); + $result = $sheet->getCell('A1')->getCalculatedValue(); self::assertEqualsWithDelta($expectedResult, $result, 1E-12); } diff --git a/tests/data/Calculation/MathTrig/CEILING.php b/tests/data/Calculation/MathTrig/CEILING.php index 4005f12bdf..a4af7df1cd 100644 --- a/tests/data/Calculation/MathTrig/CEILING.php +++ b/tests/data/Calculation/MathTrig/CEILING.php @@ -1,104 +1,34 @@