diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index f49fb9d7..8ef63078 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -1945,6 +1945,11 @@ class Calculation 'functionCall' => [MathTrig::class, 'SUMXMY2'], 'argumentCount' => '2', ], + 'SWITCH' => [ + 'category' => Category::CATEGORY_LOGICAL, + 'functionCall' => [Logical::class, 'statementSwitch'], + 'argumentCount' => '3+', + ], 'SYD' => [ 'category' => Category::CATEGORY_FINANCIAL, 'functionCall' => [Financial::class, 'SYD'], diff --git a/src/PhpSpreadsheet/Calculation/Logical.php b/src/PhpSpreadsheet/Calculation/Logical.php index c36e3fca..3e6c5e74 100644 --- a/src/PhpSpreadsheet/Calculation/Logical.php +++ b/src/PhpSpreadsheet/Calculation/Logical.php @@ -273,6 +273,60 @@ class Logical return ($condition) ? $returnIfTrue : $returnIfFalse; } + /** + * STATEMENT_SWITCH. + * + * Returns corresponding with first match (any data type such as a string, numeric, date, etc). + * + * Excel Function: + * =SWITCH (expression, value1, result1, value2, result2, ... value_n, result_n [, default]) + * + * Expression + * The expression to compare to a list of values. + * value1, value2, ... value_n + * A list of values that are compared to expression. The SWITCH function is looking for the first value that matches the expression. + * result1, result2, ... result_n + * A list of results. The SWITCH function returns the corresponding result when a value matches expression. + * default + * Optional. It is the default to return if expression does not match any of the values (value1, value2, ... value_n). + * + * @category Logical Functions + * + * @param mixed $arguments Statement arguments + * + * @return mixed The value of matched expression + */ + public static function statementSwitch(...$arguments) + { + $result = Functions::VALUE(); + + if (count($arguments) > 0) { + $targetValue = Functions::flattenSingleValue($arguments[0]); + $argc = count($arguments) - 1; + $switchCount = floor($argc / 2); + $switchSatisfied = false; + $hasDefaultClause = $argc % 2 !== 0; + $defaultClause = $argc % 2 === 0 ? null : $arguments[count($arguments) - 1]; + + if ($switchCount) { + for ($index = 0; $index < $switchCount; ++$index) { + if ($targetValue == $arguments[$index * 2 + 1]) { + $result = $arguments[$index * 2 + 2]; + $switchSatisfied = true; + + break; + } + } + } + + if (!$switchSatisfied) { + $result = $hasDefaultClause ? $defaultClause : Functions::NA(); + } + } + + return $result; + } + /** * IFERROR. * diff --git a/src/PhpSpreadsheet/Calculation/functionlist.txt b/src/PhpSpreadsheet/Calculation/functionlist.txt index ee87c17f..4a5cd265 100644 --- a/src/PhpSpreadsheet/Calculation/functionlist.txt +++ b/src/PhpSpreadsheet/Calculation/functionlist.txt @@ -337,6 +337,7 @@ SUMSQ SUMX2MY2 SUMX2PY2 SUMXMY2 +SWITCH SYD T TAN diff --git a/tests/PhpSpreadsheetTests/Calculation/LogicalTest.php b/tests/PhpSpreadsheetTests/Calculation/LogicalTest.php index 3dec0c7f..37f9434e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/LogicalTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/LogicalTest.php @@ -120,4 +120,20 @@ class LogicalTest extends TestCase { return require 'data/Calculation/Logical/IFERROR.php'; } + + /** + * @dataProvider providerSwitch + * + * @param mixed $expectedResult + */ + public function testSWITCH($expectedResult, ...$args) + { + $result = Logical::statementSwitch(...$args); + self::assertEquals($expectedResult, $result); + } + + public function providerSwitch() + { + return require 'data/Calculation/Logical/SWITCH.php'; + } } diff --git a/tests/data/Calculation/Logical/SWITCH.php b/tests/data/Calculation/Logical/SWITCH.php new file mode 100644 index 00000000..d062b7fe --- /dev/null +++ b/tests/data/Calculation/Logical/SWITCH.php @@ -0,0 +1,46 @@ +