From 859bef1901d072d771efadf521e9d75f427cd852 Mon Sep 17 00:00:00 2001 From: Dawid Warmuz Date: Sat, 20 Jun 2020 18:21:19 +0200 Subject: [PATCH] Add support for IFS() logical function (#1442) * Add support for IFS() logical function * Use Exception as false value in IFS logical function, so it never collides with string in spreadsheet --- docs/references/function-list-by-category.md | 2 +- docs/references/function-list-by-name.md | 2 +- .../Calculation/Calculation.php | 2 +- src/PhpSpreadsheet/Calculation/Logical.php | 35 +++++++++++++ .../Calculation/functionlist.txt | 1 + .../Calculation/Functions/Logical/IfsTest.php | 32 ++++++++++++ tests/data/Calculation/Logical/IFS.php | 50 +++++++++++++++++++ 7 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfsTest.php create mode 100644 tests/data/Calculation/Logical/IFS.php diff --git a/docs/references/function-list-by-category.md b/docs/references/function-list-by-category.md index 49bb66c0..3cc1c2b8 100644 --- a/docs/references/function-list-by-category.md +++ b/docs/references/function-list-by-category.md @@ -213,7 +213,7 @@ FALSE | \PhpOffice\PhpSpreadsheet\Calculation\Logical::FALSE IF | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementIf IFERROR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR IFNA | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFNA -IFS | **Not yet Implemented** +IFS | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFS NOT | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT OR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalOr SWITCH | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementSwitch diff --git a/docs/references/function-list-by-name.md b/docs/references/function-list-by-name.md index f5493d03..c787ee00 100644 --- a/docs/references/function-list-by-name.md +++ b/docs/references/function-list-by-name.md @@ -212,7 +212,7 @@ Excel Function | Category | PhpSpreadsheet Function IF | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::statementIf IFERROR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR IFNA | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFNA -IFS | CATEGORY_LOGICAL | **Not yet Implemented** +IFS | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFS IMABS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMABS IMAGINARY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMAGINARY IMARGUMENT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 848f9068..e65cd425 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -1059,7 +1059,7 @@ class Calculation ], 'IFS' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Functions::class, 'DUMMY'], + 'functionCall' => [Logical::class, 'IFS'], 'argumentCount' => '2+', ], 'IMABS' => [ diff --git a/src/PhpSpreadsheet/Calculation/Logical.php b/src/PhpSpreadsheet/Calculation/Logical.php index a362a275..69c543ce 100644 --- a/src/PhpSpreadsheet/Calculation/Logical.php +++ b/src/PhpSpreadsheet/Calculation/Logical.php @@ -352,4 +352,39 @@ class Logical return self::statementIf(Functions::isNa($testValue), $napart, $testValue); } + + /** + * IFS. + * + * Excel Function: + * =IFS(testValue1;returnIfTrue1;testValue2;returnIfTrue2;...;testValue_n;returnIfTrue_n) + * + * testValue1 ... testValue_n + * Conditions to Evaluate + * returnIfTrue1 ... returnIfTrue_n + * Value returned if corresponding testValue (nth) was true + * + * @param mixed ...$arguments Statement arguments + * + * @return mixed|string The value of returnIfTrue_n, if testValue_n was true. #N/A if none of testValues was true + */ + public static function IFS(...$arguments) + { + if (count($arguments) % 2 != 0) { + return Functions::NA(); + } + // We use instance of Exception as a falseValue in order to prevent string collision with value in cell + $falseValueException = new Exception(); + for ($i = 0; $i < count($arguments); $i += 2) { + $testValue = ($arguments[$i] === null) ? '' : Functions::flattenSingleValue($arguments[$i]); + $returnIfTrue = ($arguments[$i + 1] === null) ? '' : Functions::flattenSingleValue($arguments[$i + 1]); + $result = self::statementIf($testValue, $returnIfTrue, $falseValueException); + + if ($result !== $falseValueException) { + return $result; + } + } + + return Functions::NA(); + } } diff --git a/src/PhpSpreadsheet/Calculation/functionlist.txt b/src/PhpSpreadsheet/Calculation/functionlist.txt index 2556ec90..e71d18f4 100644 --- a/src/PhpSpreadsheet/Calculation/functionlist.txt +++ b/src/PhpSpreadsheet/Calculation/functionlist.txt @@ -163,6 +163,7 @@ HYPERLINK HYPGEOMDIST IF IFERROR +IFS IMABS IMAGINARY IMARGUMENT diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfsTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfsTest.php new file mode 100644 index 00000000..15687cd6 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfsTest.php @@ -0,0 +1,32 @@ +