diff --git a/CHANGELOG.md b/CHANGELOG.md index f8baacc01e..8f178b7c02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Added +- Implementation of the Excel `AVERAGEIFS()` functions as part of a restructuring of Database functions and Conditional Statistical functions. - Support for date values and percentages in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1875](https://github.com/PHPOffice/PhpSpreadsheet/pull/1875) -- Support for booleans, and for wildcard text search in query parameters for Database functions. [#1876](https://github.com/PHPOffice/PhpSpreadsheet/pull/1876) +- Support for booleans, and for wildcard text search in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1876](https://github.com/PHPOffice/PhpSpreadsheet/pull/1876) - Implemented DataBar for conditional formatting in Xlsx, providing read/write and creation of (type, value, direction, fills, border, axis position, color settings) as DataBar options in Excel. [#1754](https://github.com/PHPOffice/PhpSpreadsheet/pull/1754) - Alignment for ODS Writer [#1796](https://github.com/PHPOffice/PhpSpreadsheet/issues/1796) - Basic implementation of the PERMUTATIONA() Statistical Function diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index ba6299572f..e114a00d19 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -343,12 +343,12 @@ class Calculation ], 'AVERAGEIF' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'AVERAGEIF'], + 'functionCall' => [Statistical\Conditional::class, 'AVERAGEIF'], 'argumentCount' => '2,3', ], 'AVERAGEIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Functions::class, 'DUMMY'], + 'functionCall' => [Statistical\Conditional::class, 'AVERAGEIFS'], 'argumentCount' => '3+', ], 'BAHTTEXT' => [ @@ -639,12 +639,12 @@ class Calculation ], 'COUNTIF' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'COUNTIF'], + 'functionCall' => [Statistical\Conditional::class, 'COUNTIF'], 'argumentCount' => '2', ], 'COUNTIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'COUNTIFS'], + 'functionCall' => [Statistical\Conditional::class, 'COUNTIFS'], 'argumentCount' => '2+', ], 'COUPDAYBS' => [ @@ -1630,7 +1630,7 @@ class Calculation ], 'MAXIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MAXIFS'], + 'functionCall' => [Statistical\Conditional::class, 'MAXIFS'], 'argumentCount' => '3+', ], 'MDETERM' => [ @@ -1675,7 +1675,7 @@ class Calculation ], 'MINIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MINIFS'], + 'functionCall' => [Statistical\Conditional::class, 'MINIFS'], 'argumentCount' => '3+', ], 'MINUTE' => [ diff --git a/src/PhpSpreadsheet/Calculation/Database.php b/src/PhpSpreadsheet/Calculation/Database.php index db16e2df8f..7643197988 100644 --- a/src/PhpSpreadsheet/Calculation/Database.php +++ b/src/PhpSpreadsheet/Calculation/Database.php @@ -34,7 +34,7 @@ class Database * the column label in which you specify a condition for the * column. * - * @return float|string + * @return null|float|string */ public static function DAVERAGE($database, $field, $criteria) { diff --git a/src/PhpSpreadsheet/Calculation/Database/DAverage.php b/src/PhpSpreadsheet/Calculation/Database/DAverage.php index 899b242669..ea45beda8f 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DAverage.php +++ b/src/PhpSpreadsheet/Calculation/Database/DAverage.php @@ -29,7 +29,7 @@ class DAverage extends DatabaseAbstract * the column label in which you specify a condition for the * column. * - * @return float|string + * @return null|float|string */ public static function evaluate($database, $field, $criteria) { diff --git a/src/PhpSpreadsheet/Calculation/Database/DCountA.php b/src/PhpSpreadsheet/Calculation/Database/DCountA.php index 5e2ef110f0..1beaf012d9 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DCountA.php +++ b/src/PhpSpreadsheet/Calculation/Database/DCountA.php @@ -36,7 +36,7 @@ public static function evaluate($database, $field, $criteria) $field = self::fieldExtract($database, $field); return Statistical::COUNTA( - self::getFilteredColumn($database, $field, $criteria) + self::getFilteredColumn($database, $field ?? 0, $criteria) ); } } diff --git a/src/PhpSpreadsheet/Calculation/Database/DGet.php b/src/PhpSpreadsheet/Calculation/Database/DGet.php index 64858d9d28..c2ffe30265 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DGet.php +++ b/src/PhpSpreadsheet/Calculation/Database/DGet.php @@ -44,6 +44,8 @@ public static function evaluate($database, $field, $criteria) return Functions::NAN(); } - return $columnData[0]; + $row = array_pop($columnData); + + return array_pop($row); } } diff --git a/src/PhpSpreadsheet/Calculation/Database/DatabaseAbstract.php b/src/PhpSpreadsheet/Calculation/Database/DatabaseAbstract.php index a08f1251fc..2148ebc0b9 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DatabaseAbstract.php +++ b/src/PhpSpreadsheet/Calculation/Database/DatabaseAbstract.php @@ -25,19 +25,20 @@ abstract public static function evaluate($database, $field, $criteria); * represents the position of the column within the list: 1 for * the first column, 2 for the second column, and so on. */ - protected static function fieldExtract(array $database, $field): ?string + protected static function fieldExtract(array $database, $field): ?int { $field = strtoupper(Functions::flattenSingleValue($field)); - $fieldNames = array_map('strtoupper', array_shift($database)); + if ($field === '') { + return null; + } + $fieldNames = array_map('strtoupper', array_shift($database)); if (is_numeric($field)) { - $keys = array_keys($fieldNames); - - return $keys[$field - 1]; + return ((int) $field) - 1; } - $key = array_search($field, $fieldNames); + $key = array_search($field, array_values($fieldNames), true); - return $key ?: null; + return ($key !== false) ? (int) $key : null; } /** @@ -70,14 +71,19 @@ protected static function filter(array $database, array $criteria): array return self::executeQuery($database, $query, $criteriaNames, $fieldNames); } - protected static function getFilteredColumn(array $database, $field, array $criteria): array + protected static function getFilteredColumn(array $database, ?int $field, array $criteria): array { // reduce the database to a set of rows that match all the criteria $database = self::filter($database, $criteria); + $defaultReturnColumnValue = ($field === null) ? 1 : null; + // extract an array of values for the requested column $columnData = []; - foreach ($database as $row) { - $columnData[] = ($field !== null) ? $row[$field] : true; + foreach ($database as $rowKey => $row) { + $keys = array_keys($row); + $key = $keys[$field] ?? null; + $columnKey = $key ?? 'A'; + $columnData[$rowKey][$columnKey] = $row[$key] ?? $defaultReturnColumnValue; } return $columnData; diff --git a/src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php b/src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php index 5b4fe5b14d..2ba2034686 100644 --- a/src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php +++ b/src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php @@ -5,9 +5,9 @@ class WildcardMatch { private const SEARCH_SET = [ - '/([^~])(\*)/ui', + '/(? $arg) { - if (!is_numeric($arg)) { - if ($conditionIsNumeric) { - continue; - } - $arg = Calculation::wrapResult(strtoupper($arg)); - } elseif (!$conditionIsNumeric) { - continue; - } - $testCondition = '=' . $arg . $condition; - if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - $returnValue += $averageArgs[$key]; - ++$aCount; - } - } - - if ($aCount > 0) { - return $returnValue / $aCount; - } - - return Functions::DIV0(); + return Statistical\Conditional::AVERAGEIF($range, $condition, $averageRange); } /** @@ -1137,38 +1111,21 @@ public static function COUNTBLANK(...$args) * Counts the number of cells that contain numbers within the list of arguments * * Excel Function: - * COUNTIF(value1[,value2[, ...]],condition) + * COUNTIF(range,condition) * - * @param mixed $aArgs Data values + * @Deprecated 1.17.0 + * + * @see Statistical\Conditional::COUNTIF() + * Use the COUNTIF() method in the Statistical\Conditional class instead + * + * @param mixed $range Data values * @param string $condition the criteria that defines which cells will be counted * * @return int */ - public static function COUNTIF($aArgs, $condition) + public static function COUNTIF($range, $condition) { - $returnValue = 0; - - $aArgs = Functions::flattenArray($aArgs); - $condition = Functions::ifCondition($condition); - $conditionIsNumeric = strpos($condition, '"') === false; - // Loop through arguments - foreach ($aArgs as $arg) { - if (!is_numeric($arg)) { - if ($conditionIsNumeric) { - continue; - } - $arg = Calculation::wrapResult(strtoupper($arg)); - } elseif (!$conditionIsNumeric) { - continue; - } - $testCondition = '=' . $arg . $condition; - if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - // Is it a value within our criteria - ++$returnValue; - } - } - - return $returnValue; + return Statistical\Conditional::COUNTIF($range, $condition); } /** @@ -1179,66 +1136,18 @@ public static function COUNTIF($aArgs, $condition) * Excel Function: * COUNTIFS(criteria_range1, criteria1, [criteria_range2, criteria2]…) * - * @param mixed $args Criterias + * @Deprecated 1.17.0 + * + * @see Statistical\Conditional::COUNTIFS() + * Use the COUNTIFS() method in the Statistical\Conditional class instead + * + * @param mixed $args Pairs of Ranges and Criteria * * @return int */ public static function COUNTIFS(...$args) { - $arrayList = $args; - - // Return value - $returnValue = 0; - - if (empty($arrayList)) { - return $returnValue; - } - - $aArgsArray = []; - $conditions = []; - - while (count($arrayList) > 0) { - $aArgsArray[] = Functions::flattenArray(array_shift($arrayList)); - $conditions[] = Functions::ifCondition(array_shift($arrayList)); - } - - // Loop through each arg and see if arguments and conditions are true - foreach (array_keys($aArgsArray[0]) as $index) { - $valid = true; - - foreach ($conditions as $cidx => $condition) { - $conditionIsNumeric = strpos($condition, '"') === false; - $arg = $aArgsArray[$cidx][$index]; - - // Loop through arguments - if (!is_numeric($arg)) { - if ($conditionIsNumeric) { - $valid = false; - - break; // if false found, don't need to check other conditions - } - $arg = Calculation::wrapResult(strtoupper($arg)); - } elseif (!$conditionIsNumeric) { - $valid = false; - - break; // if false found, don't need to check other conditions - } - $testCondition = '=' . $arg . $condition; - if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - // Is not a value within our criteria - $valid = false; - - break; // if false found, don't need to check other conditions - } - } - - if ($valid) { - ++$returnValue; - } - } - - // Return - return $returnValue; + return Statistical\Conditional::COUNTIFS(...$args); } /** @@ -2348,53 +2257,18 @@ public static function MAXA(...$args) * Excel Function: * MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...) * + * @Deprecated 1.17.0 + * + * @see Statistical\Conditional::MAXIFS() + * Use the MAXIFS() method in the Statistical\Conditional class instead + * * @param mixed $args Data range and criterias * * @return float */ public static function MAXIFS(...$args) { - $arrayList = $args; - - // Return value - $returnValue = null; - - $maxArgs = Functions::flattenArray(array_shift($arrayList)); - $aArgsArray = []; - $conditions = []; - - while (count($arrayList) > 0) { - $aArgsArray[] = Functions::flattenArray(array_shift($arrayList)); - $conditions[] = Functions::ifCondition(array_shift($arrayList)); - } - - // Loop through each arg and see if arguments and conditions are true - foreach ($maxArgs as $index => $value) { - $valid = true; - - foreach ($conditions as $cidx => $condition) { - $arg = $aArgsArray[$cidx][$index]; - - // Loop through arguments - if (!is_numeric($arg)) { - $arg = Calculation::wrapResult(strtoupper($arg)); - } - $testCondition = '=' . $arg . $condition; - if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - // Is not a value within our criteria - $valid = false; - - break; // if false found, don't need to check other conditions - } - } - - if ($valid) { - $returnValue = $returnValue === null ? $value : max($value, $returnValue); - } - } - - // Return - return $returnValue; + return Conditional::MAXIFS(...$args); } /** @@ -2520,53 +2394,18 @@ public static function MINA(...$args) * Excel Function: * MINIFS(min_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...) * + * @Deprecated 1.17.0 + * + * @see Statistical\Conditional::MINIFS() + * Use the MINIFS() method in the Statistical\Conditional class instead + * * @param mixed $args Data range and criterias * * @return float */ public static function MINIFS(...$args) { - $arrayList = $args; - - // Return value - $returnValue = null; - - $minArgs = Functions::flattenArray(array_shift($arrayList)); - $aArgsArray = []; - $conditions = []; - - while (count($arrayList) > 0) { - $aArgsArray[] = Functions::flattenArray(array_shift($arrayList)); - $conditions[] = Functions::ifCondition(array_shift($arrayList)); - } - - // Loop through each arg and see if arguments and conditions are true - foreach ($minArgs as $index => $value) { - $valid = true; - - foreach ($conditions as $cidx => $condition) { - $arg = $aArgsArray[$cidx][$index]; - - // Loop through arguments - if (!is_numeric($arg)) { - $arg = Calculation::wrapResult(strtoupper($arg)); - } - $testCondition = '=' . $arg . $condition; - if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - // Is not a value within our criteria - $valid = false; - - break; // if false found, don't need to check other conditions - } - } - - if ($valid) { - $returnValue = $returnValue === null ? $value : min($value, $returnValue); - } - } - - // Return - return $returnValue; + return Conditional::MINIFS(...$args); } // diff --git a/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php b/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php new file mode 100644 index 0000000000..02bb0782f3 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php @@ -0,0 +1,234 @@ + 0) { + $conditions[] = array_merge([sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], [array_pop($args)]); + $database[] = array_merge( + [sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], + Functions::flattenArray(array_pop($args)) + ); + ++$pairCount; + } + + $conditions = array_map(null, ...$conditions); + $database = array_map(null, ...$database); + + return DCount::evaluate($database, null, $conditions); + } + + /** + * MAXIFS. + * + * Returns the maximum value within a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2]…) + * + * @param mixed $args Pairs of Ranges and Criteria + * + * @return null|float|string + */ + public static function MAXIFS(...$args) + { + if (empty($args)) { + return 0.0; + } + + $conditions = self::buildConditionSet(...$args); + $database = self::buildDatabase(...$args); + + return DMax::evaluate($database, self::VALUE_COLUMN_NAME, $conditions); + } + + /** + * MINIFS. + * + * Returns the minimum value within a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * MINIFS(min_range, criteria_range1, criteria1, [criteria_range2, criteria2]…) + * + * @param mixed $args Pairs of Ranges and Criteria + * + * @return null|float|string + */ + public static function MINIFS(...$args) + { + if (empty($args)) { + return 0.0; + } + + $conditions = self::buildConditionSet(...$args); + $database = self::buildDatabase(...$args); + + return DMin::evaluate($database, self::VALUE_COLUMN_NAME, $conditions); + } + + private static function buildConditionSet(...$args): array + { + array_shift($args); + + $conditions = []; + $pairCount = 1; + while (count($args) > 0) { + $conditions[] = array_merge([sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], [array_pop($args)]); + array_pop($args); + ++$pairCount; + } + + if (count($conditions) === 1) { + return array_map( + function ($value) { + return [$value]; + }, + $conditions[0] + ); + } + + return array_map(null, ...$conditions); + } + + private static function buildDatabase(...$args): array + { + $database = []; + $database[] = array_merge( + [self::VALUE_COLUMN_NAME], + Functions::flattenArray(array_shift($args)) + ); + + $pairCount = 1; + while (count($args) > 0) { + array_pop($args); + $database[] = array_merge( + [sprintf(self::CONDITIONAL_COLUMN_NAME, $pairCount)], + Functions::flattenArray(array_pop($args)) + ); + ++$pairCount; + } + + return array_map(null, ...$database); + } +} diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 02305b7a7f..191199704d 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -824,7 +824,7 @@ public function getTitle() /** * Set title. * - * @param string $pValue String containing the dimension of this worksheet + * @param string $title String containing the dimension of this worksheet * @param bool $updateFormulaCellReferences Flag indicating whether cell references in formulae should * be updated to reflect the new sheet name. * This should be left as the default true, unless you are @@ -835,10 +835,10 @@ public function getTitle() * * @return $this */ - public function setTitle($pValue, $updateFormulaCellReferences = true, $validate = true) + public function setTitle($title, $updateFormulaCellReferences = true, $validate = true) { // Is this a 'rename' or not? - if ($this->getTitle() == $pValue) { + if ($this->getTitle() == $title) { return $this; } @@ -847,37 +847,37 @@ public function setTitle($pValue, $updateFormulaCellReferences = true, $validate if ($validate) { // Syntax check - self::checkSheetTitle($pValue); + self::checkSheetTitle($title); if ($this->parent) { // Is there already such sheet name? - if ($this->parent->sheetNameExists($pValue)) { + if ($this->parent->sheetNameExists($title)) { // Use name, but append with lowest possible integer - if (Shared\StringHelper::countCharacters($pValue) > 29) { - $pValue = Shared\StringHelper::substring($pValue, 0, 29); + if (Shared\StringHelper::countCharacters($title) > 29) { + $title = Shared\StringHelper::substring($title, 0, 29); } $i = 1; - while ($this->parent->sheetNameExists($pValue . ' ' . $i)) { + while ($this->parent->sheetNameExists($title . ' ' . $i)) { ++$i; if ($i == 10) { - if (Shared\StringHelper::countCharacters($pValue) > 28) { - $pValue = Shared\StringHelper::substring($pValue, 0, 28); + if (Shared\StringHelper::countCharacters($title) > 28) { + $title = Shared\StringHelper::substring($title, 0, 28); } } elseif ($i == 100) { - if (Shared\StringHelper::countCharacters($pValue) > 27) { - $pValue = Shared\StringHelper::substring($pValue, 0, 27); + if (Shared\StringHelper::countCharacters($title) > 27) { + $title = Shared\StringHelper::substring($title, 0, 27); } } } - $pValue .= " $i"; + $title .= " $i"; } } } // Set title - $this->title = $pValue; + $this->title = $title; $this->dirty = true; if ($this->parent && $this->parent->getCalculationEngine()) { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php index 4cfea42f75..f5214ed0aa 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php @@ -80,10 +80,6 @@ public function providerDCountA() ['Science', 'Male'], ], ], - /* - * Null value in datacolumn behaviour for DCOUNTA... will include not include a null value in the count - * if it is an actual cell value; but it will be included if it is a literal... this test case is - * currently passing literals [ 1, $this->database2(), @@ -93,7 +89,6 @@ public function providerDCountA() ['Math', 'Female'], ], ], - */ [ 3, $this->database2(), diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php index 10915b3c93..5c270fd2b1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php @@ -103,6 +103,15 @@ public function providerDSum() ['3', 'C*'], ], ], + [ + 705000, + $this->database2(), + 'Sales', + [ + ['Quarter', 'Sales Rep.'], + ['3', '<>C*'], + ], + ], [ null, $this->database1(), diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AverageIfsTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AverageIfsTest.php new file mode 100644 index 0000000000..84c53431c6 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AverageIfsTest.php @@ -0,0 +1,31 @@ +getSamples() as $samples) { foreach ($samples as $sample) { +// if (array_pop(explode('/', $sample)) !== 'DGET.php') { +// continue; +// } if (!in_array($sample, $skipped)) { $file = 'samples/' . $sample; $result[] = [$file]; diff --git a/tests/data/Calculation/Statistical/AVERAGEIF.php b/tests/data/Calculation/Statistical/AVERAGEIF.php index 422a277130..736b833fab 100644 --- a/tests/data/Calculation/Statistical/AVERAGEIF.php +++ b/tests/data/Calculation/Statistical/AVERAGEIF.php @@ -46,8 +46,39 @@ '<2013', ], [ - 14000, - [7000, 14000, 'Hello World', 21000, 28000], + 200, + [7000, 14000, 21000, 28000], '<23000', + [100, 200, 300, 800], + ], + [ + (2 + 4 + 8) / 3, + [true, true, false, true, false], + true, + [2, 4, 6, 8, 10], + ], + [ + (6 + 10) / 2, + [true, true, false, true, false], + '<>true', + [2, 4, 6, 8, 10], + ], + [ + (1 + 2 + 5 + 6) / 4, + ['North', 'South', 'East', 'West', 'North', 'South', 'East', 'West'], + '???th', + [1, 2, 3, 4, 5, 6, 7, 8], + ], + [ + 16733.5, + ['East', 'West', 'North', 'South (New Office)', 'Midwest'], + '=*West', + [45678, 23789, -4789, 0, 9678], + ], + [ + 18589, + ['East', 'West', 'North', 'South (New Office)', 'Midwest'], + '<>*(New Office)', + [45678, 23789, -4789, 0, 9678], ], ]; diff --git a/tests/data/Calculation/Statistical/AVERAGEIFS.php b/tests/data/Calculation/Statistical/AVERAGEIFS.php new file mode 100644 index 0000000000..6c94300cc1 --- /dev/null +++ b/tests/data/Calculation/Statistical/AVERAGEIFS.php @@ -0,0 +1,42 @@ +70', + [75, 94, 86, 'incomplete'], + '<90', + ], + [ + '#DIV/0!', + [85, 80, 93, 75], + [85, 80, 93, 75], + '>95', + ], + [ + 87.5, + [87, 88, 'incomplete', 75], + [87, 88, 'incomplete', 75], + '<>incomplete', + [87, 88, 'incomplete', 75], + '>80', + ], + [ + 174000, + [223000, 125000, 456000, 322000, 340000, 198000, 310000, 250000, 460000, 261000, 389000, 305000], + [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], + 1, + ['North', 'North', 'South', 'North', 'North', 'South', 'North', 'North', 'South', 'North', 'North', 'South'], + 'North', + ], + [ + 285500, + [223000, 125000, 456000, 322000, 340000, 198000, 310000, 250000, 460000, 261000, 389000, 305000], + [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], + '>2', + ['Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol'], + 'Jeff', + ], +]; diff --git a/tests/data/Calculation/Statistical/COUNTIF.php b/tests/data/Calculation/Statistical/COUNTIF.php index c0e69c6769..69277e7234 100644 --- a/tests/data/Calculation/Statistical/COUNTIF.php +++ b/tests/data/Calculation/Statistical/COUNTIF.php @@ -23,12 +23,55 @@ ], [ 2, - [6, 3, 4, 'X', ''], + [6, 3, 4, 'X', '', null], '<=4', ], [ 2, - [6, 3, 4, 'X', ''], + [6, 3, 4, 31, 'X', '', null], '<="4"', ], + [ + 2, + [0, 1, 1, 2, 3, 5, 8, 0, 13, 21], + 0, + ], + [ + 3, + [true, false, false, true, false, true, false, false], + true, + ], + [ + 5, + [true, false, false, true, false, true, false, false], + '<>true', + ], + [ + 4, + ['apples', 'oranges', 'peaches', 'apples'], + '*', + ], + [ + 3, + ['apples', 'oranges', 'peaches', 'apples'], + '*p*s*', + ], + [ + 4, + [ + ['apples', 'oranges', 'peaches', 'apples'], + ['bananas', 'mangoes', 'grapes', 'cherries'], + ], + '*p*e*', + ], + [ + 2, + ['apples', 'oranges', 'peaches', 'apples'], + '?????es', + ], + [ + 2, + ['great * ratings', 'bad * ratings', 'films * wars', 'films * trek', 'music * radio'], + '*~* ra*s', + ], ]; diff --git a/tests/data/Calculation/Statistical/COUNTIFS.php b/tests/data/Calculation/Statistical/COUNTIFS.php index 32f64d7138..07f96d3837 100644 --- a/tests/data/Calculation/Statistical/COUNTIFS.php +++ b/tests/data/Calculation/Statistical/COUNTIFS.php @@ -16,9 +16,28 @@ ['C', 'B', 'A', 'B', 'B'], '=B', ], + // [ + // 2, + // [1, 2, 3, 'B', null, '', false], + // '<=2', + // ], + // [ + // 2, + // [1, 2, 3, 'B', null, '', false], + // '<=B', + // ], + [ + 4, + ['Female', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Male'], + 'Female', + [0.63, 0.78, 0.39, 0.55, 0.71, 0.51, 0.78, 0.81, 0.49, 0.35, 0.69, 0.65], + '>60%', + ], [ 2, - [1, 2, 3, 'B', '', false], - '<=2', + ['Maths', 'English', 'Science', 'Maths', 'English', 'Science', 'Maths', 'English', 'Science', 'Maths', 'English', 'Science'], + 'Science', + [0.63, 0.78, 0.39, 0.55, 0.71, 0.51, 0.78, 0.81, 0.49, 0.35, 0.69, 0.65], + '<50%', ], ]; diff --git a/tests/data/Calculation/Statistical/MAXIFS.php b/tests/data/Calculation/Statistical/MAXIFS.php index deb4bcebc4..58ed5e4672 100644 --- a/tests/data/Calculation/Statistical/MAXIFS.php +++ b/tests/data/Calculation/Statistical/MAXIFS.php @@ -21,6 +21,20 @@ ], '=H', ], + [ + 2, + [ + [1], + [2], + [3], + ], + [ + ['Y'], + ['Y'], + ['N'], + ], + '=Y', + ], [ 2, [ @@ -41,4 +55,18 @@ ], '=B', ], + [ + 456000, + [223000, 125000, 456000, 322000, 340000, 198000, 310000, 250000, 460000, 261000, 389000, 305000], + [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], + 1, + ], + [ + 310000, + [223000, 125000, 456000, 322000, 340000, 198000, 310000, 250000, 460000, 261000, 389000, 305000], + [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], + '>2', + ['Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol'], + 'Jeff', + ], ]; diff --git a/tests/data/Calculation/Statistical/MINIFS.php b/tests/data/Calculation/Statistical/MINIFS.php index a00f25b7f8..6ecade9fdf 100644 --- a/tests/data/Calculation/Statistical/MINIFS.php +++ b/tests/data/Calculation/Statistical/MINIFS.php @@ -21,6 +21,20 @@ ], '=H', ], + [ + 1, + [ + [1], + [2], + [3], + ], + [ + ['Y'], + ['Y'], + ['N'], + ], + '=Y', + ], [ 2, [ @@ -41,4 +55,18 @@ ], '=B', ], + [ + 125000, + [223000, 125000, 456000, 322000, 340000, 198000, 310000, 250000, 460000, 261000, 389000, 305000], + [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], + 1, + ], + [ + 261000, + [223000, 125000, 456000, 322000, 340000, 198000, 310000, 250000, 460000, 261000, 389000, 305000], + [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], + '>2', + ['Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol', 'Jeff', 'Chris', 'Carol'], + 'Jeff', + ], ];