diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 7868ec5ef7..87bf44a516 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -769,7 +769,7 @@ class Calculation ], 'DAVERAGE' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DAVERAGE'], + 'functionCall' => [Database\DAverage::class, 'evaluate'], 'argumentCount' => '3', ], 'DAY' => [ @@ -799,12 +799,12 @@ class Calculation ], 'DCOUNT' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DCOUNT'], + 'functionCall' => [Database\DCount::class, 'evaluate'], 'argumentCount' => '3', ], 'DCOUNTA' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DCOUNTA'], + 'functionCall' => [Database\DCountA::class, 'evaluate'], 'argumentCount' => '3', ], 'DDB' => [ @@ -849,7 +849,7 @@ class Calculation ], 'DGET' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DGET'], + 'functionCall' => [Database\DGet::class, 'evaluate'], 'argumentCount' => '3', ], 'DISC' => [ @@ -859,12 +859,12 @@ class Calculation ], 'DMAX' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DMAX'], + 'functionCall' => [Database\DMax::class, 'evaluate'], 'argumentCount' => '3', ], 'DMIN' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DMIN'], + 'functionCall' => [Database\DMin::class, 'evaluate'], 'argumentCount' => '3', ], 'DOLLAR' => [ @@ -884,22 +884,22 @@ class Calculation ], 'DPRODUCT' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DPRODUCT'], + 'functionCall' => [Database\DProduct::class, 'evaluate'], 'argumentCount' => '3', ], 'DSTDEV' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DSTDEV'], + 'functionCall' => [Database\DStDev::class, 'evaluate'], 'argumentCount' => '3', ], 'DSTDEVP' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DSTDEVP'], + 'functionCall' => [Database\DStDevP::class, 'evaluate'], 'argumentCount' => '3', ], 'DSUM' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DSUM'], + 'functionCall' => [Database\DSum::class, 'evaluate'], 'argumentCount' => '3', ], 'DURATION' => [ @@ -909,12 +909,12 @@ class Calculation ], 'DVAR' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DVAR'], + 'functionCall' => [Database\DVar::class, 'evaluate'], 'argumentCount' => '3', ], 'DVARP' => [ 'category' => Category::CATEGORY_DATABASE, - 'functionCall' => [Database::class, 'DVARP'], + 'functionCall' => [Database\DVarP::class, 'evaluate'], 'argumentCount' => '3', ], 'EDATE' => [ @@ -3437,6 +3437,7 @@ public function _calculateFormulaValue($formula, $cellID = null, ?Cell $pCell = $this->debugLog->writeDebugLog('Formula for cell ', $wsCellReference, ' is ', $formula); // Parse the formula onto the token stack and calculate the value $this->cyclicReferenceStack->push($wsCellReference); + $cellValue = $this->processTokenStack($this->internalParseFormula($formula, $pCell), $cellID, $pCell); $this->cyclicReferenceStack->pop(); diff --git a/src/PhpSpreadsheet/Calculation/Database.php b/src/PhpSpreadsheet/Calculation/Database.php index 5250e30693..db16e2df8f 100644 --- a/src/PhpSpreadsheet/Calculation/Database.php +++ b/src/PhpSpreadsheet/Calculation/Database.php @@ -2,126 +2,11 @@ namespace PhpOffice\PhpSpreadsheet\Calculation; +/** + * @deprecated 1.17.0 + */ class Database { - /** - * fieldExtract. - * - * Extracts the column ID to use for the data field. - * - * @param mixed[] $database The range of cells that makes up the list or database. - * A database is a list of related data in which rows of related - * information are records, and columns of data are fields. The - * first row of the list contains labels for each column. - * @param mixed $field Indicates which column is used in the function. Enter the - * column label enclosed between double quotation marks, such as - * "Age" or "Yield," or a number (without quotation marks) that - * represents the position of the column within the list: 1 for - * the first column, 2 for the second column, and so on. - * - * @return null|string - */ - private static function fieldExtract($database, $field) - { - $field = strtoupper(Functions::flattenSingleValue($field)); - $fieldNames = array_map('strtoupper', array_shift($database)); - - if (is_numeric($field)) { - $keys = array_keys($fieldNames); - - return $keys[$field - 1]; - } - $key = array_search($field, $fieldNames); - - return $key ?: null; - } - - /** - * filter. - * - * Parses the selection criteria, extracts the database rows that match those criteria, and - * returns that subset of rows. - * - * @param mixed[] $database The range of cells that makes up the list or database. - * A database is a list of related data in which rows of related - * information are records, and columns of data are fields. The - * first row of the list contains labels for each column. - * @param mixed[] $criteria The range of cells that contains the conditions you specify. - * You can use any range for the criteria argument, as long as it - * includes at least one column label and at least one cell below - * the column label in which you specify a condition for the - * column. - * - * @return array of mixed - */ - private static function filter($database, $criteria) - { - $fieldNames = array_shift($database); - $criteriaNames = array_shift($criteria); - - // Convert the criteria into a set of AND/OR conditions with [:placeholders] - $testConditions = $testValues = []; - $testConditionsCount = 0; - foreach ($criteriaNames as $key => $criteriaName) { - $testCondition = []; - $testConditionCount = 0; - foreach ($criteria as $row => $criterion) { - if ($criterion[$key] > '') { - $testCondition[] = '[:' . $criteriaName . ']' . Functions::ifCondition($criterion[$key]); - ++$testConditionCount; - } - } - if ($testConditionCount > 1) { - $testConditions[] = 'OR(' . implode(',', $testCondition) . ')'; - ++$testConditionsCount; - } elseif ($testConditionCount == 1) { - $testConditions[] = $testCondition[0]; - ++$testConditionsCount; - } - } - - if ($testConditionsCount > 1) { - $testConditionSet = 'AND(' . implode(',', $testConditions) . ')'; - } elseif ($testConditionsCount == 1) { - $testConditionSet = $testConditions[0]; - } - - // Loop through each row of the database - foreach ($database as $dataRow => $dataValues) { - // Substitute actual values from the database row for our [:placeholders] - $testConditionList = $testConditionSet; - foreach ($criteriaNames as $key => $criteriaName) { - $k = array_search($criteriaName, $fieldNames); - if (isset($dataValues[$k])) { - $dataValue = $dataValues[$k]; - $dataValue = (is_string($dataValue)) ? Calculation::wrapResult(strtoupper($dataValue)) : $dataValue; - $testConditionList = str_replace('[:' . $criteriaName . ']', $dataValue, $testConditionList); - } - } - // evaluate the criteria against the row data - $result = Calculation::getInstance()->_calculateFormulaValue('=' . $testConditionList); - // If the row failed to meet the criteria, remove it from the database - if (!$result) { - unset($database[$dataRow]); - } - } - - return $database; - } - - private static function getFilteredColumn($database, $field, $criteria) - { - // reduce the database to a set of rows that match all the criteria - $database = self::filter($database, $criteria); - // extract an array of values for the requested column - $colData = []; - foreach ($database as $row) { - $colData[] = $row[$field]; - } - - return $colData; - } - /** * DAVERAGE. * @@ -130,6 +15,10 @@ private static function getFilteredColumn($database, $field, $criteria) * Excel Function: * DAVERAGE(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DAverage class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -149,15 +38,7 @@ private static function getFilteredColumn($database, $field, $criteria) */ public static function DAVERAGE($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::AVERAGE( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DAverage::evaluate($database, $field, $criteria); } /** @@ -169,14 +50,15 @@ public static function DAVERAGE($database, $field, $criteria) * Excel Function: * DCOUNT(database,[field],criteria) * - * Excel Function: - * DAVERAGE(database,field,criteria) + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DCount class instead * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The * first row of the list contains labels for each column. - * @param int|string $field Indicates which column is used in the function. Enter the + * @param null|int|string $field Indicates which column is used in the function. Enter the * column label enclosed between double quotation marks, such as * "Age" or "Yield," or a number (without quotation marks) that * represents the position of the column within the list: 1 for @@ -194,15 +76,7 @@ public static function DAVERAGE($database, $field, $criteria) */ public static function DCOUNT($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::COUNT( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DCount::evaluate($database, $field, $criteria); } /** @@ -213,11 +87,15 @@ public static function DCOUNT($database, $field, $criteria) * Excel Function: * DCOUNTA(database,[field],criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DCountA class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The * first row of the list contains labels for each column. - * @param int|string $field Indicates which column is used in the function. Enter the + * @param null|int|string $field Indicates which column is used in the function. Enter the * column label enclosed between double quotation marks, such as * "Age" or "Yield," or a number (without quotation marks) that * represents the position of the column within the list: 1 for @@ -229,29 +107,10 @@ public static function DCOUNT($database, $field, $criteria) * column. * * @return int - * - * @TODO The field argument is optional. If field is omitted, DCOUNTA counts all records in the - * database that match the criteria. */ public static function DCOUNTA($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // reduce the database to a set of rows that match all the criteria - $database = self::filter($database, $criteria); - // extract an array of values for the requested column - $colData = []; - foreach ($database as $row) { - $colData[] = $row[$field]; - } - - // Return - return Statistical::COUNTA( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DCountA::evaluate($database, $field, $criteria); } /** @@ -263,6 +122,10 @@ public static function DCOUNTA($database, $field, $criteria) * Excel Function: * DGET(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DGet class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -282,18 +145,7 @@ public static function DCOUNTA($database, $field, $criteria) */ public static function DGET($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - $colData = self::getFilteredColumn($database, $field, $criteria); - if (count($colData) > 1) { - return Functions::NAN(); - } - - return $colData[0]; + return Database\DGet::evaluate($database, $field, $criteria); } /** @@ -305,6 +157,10 @@ public static function DGET($database, $field, $criteria) * Excel Function: * DMAX(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DMax class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -324,15 +180,7 @@ public static function DGET($database, $field, $criteria) */ public static function DMAX($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::MAX( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DMax::evaluate($database, $field, $criteria); } /** @@ -344,6 +192,10 @@ public static function DMAX($database, $field, $criteria) * Excel Function: * DMIN(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DMin class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -363,15 +215,7 @@ public static function DMAX($database, $field, $criteria) */ public static function DMIN($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::MIN( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DMin::evaluate($database, $field, $criteria); } /** @@ -382,6 +226,10 @@ public static function DMIN($database, $field, $criteria) * Excel Function: * DPRODUCT(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DProduct class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -401,15 +249,7 @@ public static function DMIN($database, $field, $criteria) */ public static function DPRODUCT($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return MathTrig::PRODUCT( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DProduct::evaluate($database, $field, $criteria); } /** @@ -421,6 +261,10 @@ public static function DPRODUCT($database, $field, $criteria) * Excel Function: * DSTDEV(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DStDev class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -440,15 +284,7 @@ public static function DPRODUCT($database, $field, $criteria) */ public static function DSTDEV($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::STDEV( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DStDev::evaluate($database, $field, $criteria); } /** @@ -460,6 +296,10 @@ public static function DSTDEV($database, $field, $criteria) * Excel Function: * DSTDEVP(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DStDevP class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -479,15 +319,7 @@ public static function DSTDEV($database, $field, $criteria) */ public static function DSTDEVP($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::STDEVP( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DStDevP::evaluate($database, $field, $criteria); } /** @@ -498,6 +330,10 @@ public static function DSTDEVP($database, $field, $criteria) * Excel Function: * DSUM(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DSum class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -517,15 +353,7 @@ public static function DSTDEVP($database, $field, $criteria) */ public static function DSUM($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return MathTrig::SUM( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DSum::evaluate($database, $field, $criteria); } /** @@ -537,6 +365,10 @@ public static function DSUM($database, $field, $criteria) * Excel Function: * DVAR(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DVar class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -556,15 +388,7 @@ public static function DSUM($database, $field, $criteria) */ public static function DVAR($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::VARFunc( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DVar::evaluate($database, $field, $criteria); } /** @@ -576,6 +400,10 @@ public static function DVAR($database, $field, $criteria) * Excel Function: * DVARP(database,field,criteria) * + * @Deprecated 1.17.0 + * + * @see Use the evaluate() method in the Database\DVarP class instead + * * @param mixed[] $database The range of cells that makes up the list or database. * A database is a list of related data in which rows of related * information are records, and columns of data are fields. The @@ -595,14 +423,6 @@ public static function DVAR($database, $field, $criteria) */ public static function DVARP($database, $field, $criteria) { - $field = self::fieldExtract($database, $field); - if ($field === null) { - return null; - } - - // Return - return Statistical::VARP( - self::getFilteredColumn($database, $field, $criteria) - ); + return Database\DVarP::evaluate($database, $field, $criteria); } } diff --git a/src/PhpSpreadsheet/Calculation/Database/DAverage.php b/src/PhpSpreadsheet/Calculation/Database/DAverage.php new file mode 100644 index 0000000000..899b242669 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Database/DAverage.php @@ -0,0 +1,45 @@ + 1) { + return Functions::NAN(); + } + + return $columnData[0]; + } +} diff --git a/src/PhpSpreadsheet/Calculation/Database/DMax.php b/src/PhpSpreadsheet/Calculation/Database/DMax.php new file mode 100644 index 0000000000..8918c54d2e --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Database/DMax.php @@ -0,0 +1,46 @@ +, <=, etc) + * @TODO Suport for formatted numerics (e.g. '>12.5%' => '>0.125') + * @TODO Suport for wildcard ? and * in strings (includng escaping) + */ + private static function buildQuery(array $criteriaNames, array $criteria): string + { + $baseQuery = []; + foreach ($criteria as $key => $criterion) { + foreach ($criterion as $field => $value) { + $criterionName = $criteriaNames[$field]; + if ($value !== null && $value !== '') { + $condition = '[:' . $criterionName . ']' . Functions::ifCondition($value); + $baseQuery[$key][] = $condition; + } + } + } + + $rowQuery = array_map( + function ($rowValue) { + return (count($rowValue) > 1) ? 'AND(' . implode(',', $rowValue) . ')' : $rowValue[0]; + }, + $baseQuery + ); + + return (count($rowQuery) > 1) ? 'OR(' . implode(',', $rowQuery) . ')' : $rowQuery[0]; + } + + /** + * @param $criteriaNames + * @param $fieldNames + */ + private static function executeQuery(array $database, string $query, $criteriaNames, $fieldNames): array + { + foreach ($database as $dataRow => $dataValues) { + // Substitute actual values from the database row for our [:placeholders] + $testConditionList = $query; + foreach ($criteriaNames as $key => $criteriaName) { + $key = array_search($criteriaName, $fieldNames, true); + if (isset($dataValues[$key])) { + $dataValue = $dataValues[$key]; + $dataValue = (is_string($dataValue)) ? Calculation::wrapResult(strtoupper($dataValue)) : $dataValue; + } else { + $dataValue = 'NULL'; + } + $testConditionList = str_replace('[:' . $criteriaName . ']', $dataValue, $testConditionList); + } + + // evaluate the criteria against the row data + $result = Calculation::getInstance()->_calculateFormulaValue('=' . $testConditionList); + // If the row failed to meet the criteria, remove it from the database + + if ($result !== true) { + unset($database[$dataRow]); + } + } + + return $database; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DAverageTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DAverageTest.php new file mode 100644 index 0000000000..910115045e --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DAverageTest.php @@ -0,0 +1,110 @@ +database1(), + 'Yield', + [ + ['Tree', 'Height'], + ['=Apple', '>10'], + ], + ], + [ + 13, + $this->database1(), + 3, + $this->database1(), + ], + [ + 268333.333333333333, + $this->database2(), + 'Sales', + [ + ['Quarter', 'Sales Rep.'], + ['>1', 'Tina'], + ], + ], + [ + 372500, + $this->database2(), + 'Sales', + [ + ['Quarter', 'Area'], + ['1', 'South'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php new file mode 100644 index 0000000000..ea856c57de --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountATest.php @@ -0,0 +1,108 @@ +database1(), + 'Profit', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ], + ], + [ + 2, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['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(), + 'Score', + [ + ['Subject', 'Gender'], + ['Math', 'Female'], + ], + ], + */ + [ + 3, + $this->database2(), + 'Score', + [ + ['Subject', 'Score'], + ['English', '>0.60'], + ], + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountTest.php new file mode 100644 index 0000000000..9e12ac96ba --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DCountTest.php @@ -0,0 +1,103 @@ +database1(), + 'Age', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ], + ], + [ + 1, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['Science', 'Male'], + ], + ], + [ + 1, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['Math', 'Female'], + ], + ], + [ + 3, + $this->database2(), + null, + [ + ['Subject', 'Score'], + ['English', '>0.63'], + ], + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DGetTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DGetTest.php new file mode 100644 index 0000000000..3d90ff9688 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DGetTest.php @@ -0,0 +1,115 @@ +database1(), + 'Yield', + [ + ['Tree'], + ['=Apple'], + ['=Pear'], + ], + ], + [ + 10, + $this->database1(), + 'Yield', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ['=Pear', '>12', null], + ], + ], + [ + 188000, + $this->database2(), + 'Sales', + [ + ['Sales Rep.', 'Quarter'], + ['Tina', 4], + ], + ], + [ + Functions::NAN(), + $this->database2(), + 'Sales', + [ + ['Area', 'Quarter'], + ['South', 4], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DMaxTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DMaxTest.php new file mode 100644 index 0000000000..b0ad59a705 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DMaxTest.php @@ -0,0 +1,105 @@ +database1(), + 'Profit', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ['=Pear', null, null], + ], + ], + [ + 340000, + $this->database2(), + 'Sales', + [ + ['Quarter', 'Area'], + [2, 'North'], + ], + ], + [ + 460000, + $this->database2(), + 'Sales', + [ + ['Sales Rep.', 'Quarter'], + ['Carol', '>1'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DMinTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DMinTest.php new file mode 100644 index 0000000000..bfd2af4c4e --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DMinTest.php @@ -0,0 +1,101 @@ +database1(), + 'Profit', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ['=Pear', '>12', null], + ], + ], + [ + 0.48, + $this->database2(), + 'Score', + [ + ['Subject', 'Age'], + ['Science', '>8'], + ], + ], + [ + 0.55, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['Math', 'Male'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DProductTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DProductTest.php new file mode 100644 index 0000000000..9b2f92b3d2 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DProductTest.php @@ -0,0 +1,105 @@ +database1(), + 'Yield', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ['=Pear', null, null], + ], + ], + /* + * We don't yet support date handling in the search query + [ + 36, + $this->database2(), + 'Score', + [ + ['Name', 'Date'], + ['Gary', '05-Jan-2017'], + ], + ], + [ + 8, + $this->database2(), + 'Score', + [ + ['Test', 'Date'], + ['Test1', '<05-Jan-2017'], + ], + ], + */ + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DStDevPTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DStDevPTest.php new file mode 100644 index 0000000000..210325d5c3 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DStDevPTest.php @@ -0,0 +1,101 @@ +database1(), + 'Yield', + [ + ['Tree'], + ['=Apple'], + ['=Pear'], + ], + ], + [ + 0.085244745684, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['English', 'Male'], + ], + ], + [ + 0.160623784042, + $this->database2(), + 'Score', + [ + ['Subject', 'Age'], + ['Math', '>8'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DStDevTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DStDevTest.php new file mode 100644 index 0000000000..71bbcd2a06 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DStDevTest.php @@ -0,0 +1,101 @@ +database1(), + 'Yield', + [ + ['Tree'], + ['=Apple'], + ['=Pear'], + ], + ], + [ + 0.104403065089, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['English', 'Male'], + ], + ], + [ + 0.196723155729, + $this->database2(), + 'Score', + [ + ['Subject', 'Age'], + ['Math', '>8'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php new file mode 100644 index 0000000000..fbb86bb92f --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DSumTest.php @@ -0,0 +1,117 @@ +database1(), + 'Profit', + [ + ['Tree'], + ['=Apple'], + ], + ], + [ + 248, + $this->database1(), + 'Profit', + [ + ['Tree', 'Height', 'Height'], + ['=Apple', '>10', '<16'], + ['=Pear', null, null], + ], + ], + [ + 1210000, + $this->database2(), + 'Sales', + [ + ['Quarter', 'Area'], + ['>2', 'North'], + ], + ], + /* + * We don't yet support woldcards in text search fields + [ + 710000, + $this->database2(), + 'Sales', + [ + ['Quarter', 'Sales Rep.'], + ['3', 'C*'], + ], + ], + */ + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DVarPTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DVarPTest.php new file mode 100644 index 0000000000..0436ea6705 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DVarPTest.php @@ -0,0 +1,101 @@ +database1(), + 'Yield', + [ + ['Tree'], + ['=Apple'], + ['=Pear'], + ], + ], + [ + 0.025622222222, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['Math', 'Male'], + ], + ], + [ + 0.011622222222, + $this->database2(), + 'Score', + [ + ['Subject', 'Age'], + ['Science', '>8'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DVarTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DVarTest.php new file mode 100644 index 0000000000..467db2f200 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/DVarTest.php @@ -0,0 +1,101 @@ +database1(), + 'Yield', + [ + ['Tree'], + ['=Apple'], + ['=Pear'], + ], + ], + [ + 0.038433333333, + $this->database2(), + 'Score', + [ + ['Subject', 'Gender'], + ['Math', 'Male'], + ], + ], + [ + 0.017433333333, + $this->database2(), + 'Score', + [ + ['Subject', 'Age'], + ['Science', '>8'], + ], + ], + [ + null, + $this->database1(), + null, + $this->database1(), + ], + ]; + } +}