Refactor the Excel Database functions; and rewrite the query building (#1871)
* Refactor the Excel Database functions; and rewrite the query building to fix a bug with complex multi-criteria queries that involve both AND and OR conditions * Fix handling for empty cells and NULL values in searches * Expand unit tests; and add TODOs for dates, percentages, and wildcard text comparisons
This commit is contained in:
parent
1318b90330
commit
3764f30354
|
|
@ -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 @@ class Calculation
|
|||
$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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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 @@ class Database
|
|||
* 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 @@ class Database
|
|||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DAverage extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DAVERAGE.
|
||||
*
|
||||
* Averages the values in a column of a list or database that match conditions you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DAVERAGE(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float|string
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::AVERAGE(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DCount extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DCOUNT.
|
||||
*
|
||||
* Counts the cells that contain numbers in a column of a list or database that match conditions
|
||||
* that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DCOUNT(database,[field],criteria)
|
||||
*
|
||||
* @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 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
|
||||
* the first column, 2 for the second column, and so on.
|
||||
* @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 int
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
|
||||
return Statistical::COUNT(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DCountA extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DCOUNTA.
|
||||
*
|
||||
* Counts the nonblank cells in a column of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DCOUNTA(database,[field],criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 int
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
|
||||
return Statistical::COUNTA(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class DGet extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DGET.
|
||||
*
|
||||
* Extracts a single value from a column of a list or database that matches conditions that you
|
||||
* specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DGET(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 mixed
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$columnData = self::getFilteredColumn($database, $field, $criteria);
|
||||
if (count($columnData) > 1) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
return $columnData[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DMax extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DMAX.
|
||||
*
|
||||
* Returns the largest number in a column of a list or database that matches conditions you that
|
||||
* specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DMAX(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::MAX(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DMin extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DMIN.
|
||||
*
|
||||
* Returns the smallest number in a column of a list or database that matches conditions you that
|
||||
* specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DMIN(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::MIN(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||
|
||||
class DProduct extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DPRODUCT.
|
||||
*
|
||||
* Multiplies the values in a column of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DPRODUCT(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MathTrig::PRODUCT(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DStDev extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DSTDEV.
|
||||
*
|
||||
* Estimates the standard deviation of a population based on a sample by using the numbers in a
|
||||
* column of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DSTDEV(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float|string
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::STDEV(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DStDevP extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DSTDEVP.
|
||||
*
|
||||
* Calculates the standard deviation of a population based on the entire population by using the
|
||||
* numbers in a column of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DSTDEVP(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float|string
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::STDEVP(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||
|
||||
class DSum extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DSUM.
|
||||
*
|
||||
* Adds the numbers in a column of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DSUM(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MathTrig::SUM(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DVar extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DVAR.
|
||||
*
|
||||
* Estimates the variance of a population based on a sample by using the numbers in a column
|
||||
* of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DVAR(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float|string (string if result is an error)
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::VARFunc(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||
|
||||
class DVarP extends DatabaseAbstract
|
||||
{
|
||||
/**
|
||||
* DVARP.
|
||||
*
|
||||
* Calculates the variance of a population based on the entire population by using the numbers
|
||||
* in a column of a list or database that match conditions that you specify.
|
||||
*
|
||||
* Excel Function:
|
||||
* DVARP(database,field,criteria)
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
* @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 float|string (string if result is an error)
|
||||
*/
|
||||
public static function evaluate($database, $field, $criteria)
|
||||
{
|
||||
$field = self::fieldExtract($database, $field);
|
||||
if ($field === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Statistical::VARP(
|
||||
self::getFilteredColumn($database, $field, $criteria)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
abstract class DatabaseAbstract
|
||||
{
|
||||
abstract public static function evaluate($database, $field, $criteria);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected static function fieldExtract(array $database, $field): ?string
|
||||
{
|
||||
$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
|
||||
*/
|
||||
protected static function filter(array $database, array $criteria): array
|
||||
{
|
||||
$fieldNames = array_shift($database);
|
||||
$criteriaNames = array_shift($criteria);
|
||||
|
||||
// Convert the criteria into a set of AND/OR conditions with [:placeholders]
|
||||
$query = self::buildQuery($criteriaNames, $criteria);
|
||||
|
||||
// Loop through each row of the database
|
||||
return self::executeQuery($database, $query, $criteriaNames, $fieldNames);
|
||||
}
|
||||
|
||||
protected static function getFilteredColumn(array $database, $field, array $criteria): array
|
||||
{
|
||||
// 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
|
||||
$columnData = [];
|
||||
foreach ($database as $row) {
|
||||
$columnData[] = ($field !== null) ? $row[$field] : true;
|
||||
}
|
||||
|
||||
return $columnData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO Support for Dates (including handling for >, <=, 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DAverageTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDAverage
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDAverage($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DAVERAGE($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 76.8],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Quarter', 'Area', 'Sales Rep.', 'Sales'],
|
||||
[1, 'North', 'Jeff', 223000],
|
||||
[1, 'North', 'Chris', 125000],
|
||||
[1, 'South', 'Carol', 456000],
|
||||
[1, 'South', 'Tina', 289000],
|
||||
[2, 'North', 'Jeff', 322000],
|
||||
[2, 'North', 'Chris', 340000],
|
||||
[2, 'South', 'Carol', 198000],
|
||||
[2, 'South', 'Tina', 222000],
|
||||
[3, 'North', 'Jeff', 310000],
|
||||
[3, 'North', 'Chris', 250000],
|
||||
[3, 'South', 'Carol', 460000],
|
||||
[3, 'South', 'Tina', 395000],
|
||||
[4, 'North', 'Jeff', 261000],
|
||||
[4, 'North', 'Chris', 389000],
|
||||
[4, 'South', 'Carol', 305000],
|
||||
[4, 'South', 'Tina', 188000],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDAverage()
|
||||
{
|
||||
return [
|
||||
[
|
||||
12,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DCountATest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDCountA
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDCountA($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DCOUNTA($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 76.8],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 8, 'Math', 0.63],
|
||||
['Amy', 'Female', 8, 'English', 0.78],
|
||||
['Amy', 'Female', 8, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 'awaiting'],
|
||||
['Sue', 'Female', 9, 'Math', null],
|
||||
['Sue', 'Female', 9, 'English', 0.52],
|
||||
['Sue', 'Female', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDCountA()
|
||||
{
|
||||
return [
|
||||
[
|
||||
1,
|
||||
$this->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'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DCountTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDCount
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDCount($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DCOUNT($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 'N/A', 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 12, 11, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 8, 'Math', 0.63],
|
||||
['Amy', 'Female', 8, 'English', 0.78],
|
||||
['Amy', 'Female', 8, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 'awaiting'],
|
||||
['Sue', 'Female', 9, 'Math', null],
|
||||
['Sue', 'Female', 9, 'English', 0.52],
|
||||
['Sue', 'Female', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDCount()
|
||||
{
|
||||
return [
|
||||
[
|
||||
1,
|
||||
$this->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'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DGetTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDGet
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDGet($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DGET($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Quarter', 'Area', 'Sales Rep.', 'Sales'],
|
||||
[1, 'North', 'Jeff', 223000],
|
||||
[1, 'North', 'Chris', 125000],
|
||||
[1, 'South', 'Carol', 456000],
|
||||
[1, 'South', 'Tina', 289000],
|
||||
[2, 'North', 'Jeff', 322000],
|
||||
[2, 'North', 'Chris', 340000],
|
||||
[2, 'South', 'Carol', 198000],
|
||||
[2, 'South', 'Tina', 222000],
|
||||
[3, 'North', 'Jeff', 310000],
|
||||
[3, 'North', 'Chris', 250000],
|
||||
[3, 'South', 'Carol', 460000],
|
||||
[3, 'South', 'Tina', 395000],
|
||||
[4, 'North', 'Jeff', 261000],
|
||||
[4, 'North', 'Chris', 389000],
|
||||
[4, 'South', 'Carol', 305000],
|
||||
[4, 'South', 'Tina', 188000],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDGet()
|
||||
{
|
||||
return [
|
||||
[
|
||||
Functions::NAN(),
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DMaxTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDMax
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDMax($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DMAX($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Quarter', 'Area', 'Sales Rep.', 'Sales'],
|
||||
[1, 'North', 'Jeff', 223000],
|
||||
[1, 'North', 'Chris', 125000],
|
||||
[1, 'South', 'Carol', 456000],
|
||||
[1, 'South', 'Tina', 289000],
|
||||
[2, 'North', 'Jeff', 322000],
|
||||
[2, 'North', 'Chris', 340000],
|
||||
[2, 'South', 'Carol', 198000],
|
||||
[2, 'South', 'Tina', 222000],
|
||||
[3, 'North', 'Jeff', 310000],
|
||||
[3, 'North', 'Chris', 250000],
|
||||
[3, 'South', 'Carol', 460000],
|
||||
[3, 'South', 'Tina', 395000],
|
||||
[4, 'North', 'Jeff', 261000],
|
||||
[4, 'North', 'Chris', 389000],
|
||||
[4, 'South', 'Carol', 305000],
|
||||
[4, 'South', 'Tina', 188000],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDMax()
|
||||
{
|
||||
return [
|
||||
[
|
||||
96,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DMinTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDMin
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDMin($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DMIN($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 8, 'Math', 0.63],
|
||||
['Amy', 'Female', 8, 'English', 0.78],
|
||||
['Amy', 'Female', 8, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 0.51],
|
||||
['Sue', 'Female', 9, 'Math', 0.39],
|
||||
['Sue', 'Female', 9, 'English', 0.52],
|
||||
['Sue', 'Female', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDMin()
|
||||
{
|
||||
return [
|
||||
[
|
||||
75,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\DateTime;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DProductTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDProduct
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDProduct($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DPRODUCT($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Date', 'Test', 'Score'],
|
||||
['Gary', DateTime::getDateValue('01-Jan-2017'), 'Test1', 4],
|
||||
['Gary', DateTime::getDateValue('01-Jan-2017'), 'Test2', 4],
|
||||
['Gary', DateTime::getDateValue('01-Jan-2017'), 'Test3', 3],
|
||||
['Gary', DateTime::getDateValue('05-Jan-2017'), 'Test1', 3],
|
||||
['Gary', DateTime::getDateValue('05-Jan-2017'), 'Test2', 4],
|
||||
['Gary', DateTime::getDateValue('05-Jan-2017'), 'Test3', 3],
|
||||
['Kev', DateTime::getDateValue('02-Jan-2017'), 'Test1', 2],
|
||||
['Kev', DateTime::getDateValue('02-Jan-2017'), 'Test2', 3],
|
||||
['Kev', DateTime::getDateValue('02-Jan-2017'), 'Test3', 5],
|
||||
['Kev', DateTime::getDateValue('05-Jan-2017'), 'Test1', 3],
|
||||
['Kev', DateTime::getDateValue('05-Jan-2017'), 'Test2', 2],
|
||||
['Kev', DateTime::getDateValue('05-Jan-2017'), 'Test3', 5],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDProduct()
|
||||
{
|
||||
return [
|
||||
[
|
||||
800,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DStDevPTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDStDevP
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDStDevP($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DSTDEVP($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 10, 'Math', 0.63],
|
||||
['Amy', 'Female', 10, 'English', 0.78],
|
||||
['Amy', 'Female', 10, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 0.51],
|
||||
['Sam', 'Male', 9, 'Math', 0.39],
|
||||
['Sam', 'Male', 9, 'English', 0.52],
|
||||
['Sam', 'Male', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDStDevP()
|
||||
{
|
||||
return [
|
||||
[
|
||||
2.653299832284,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DStDevTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDStDev
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDStDev($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DSTDEV($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 10, 'Math', 0.63],
|
||||
['Amy', 'Female', 10, 'English', 0.78],
|
||||
['Amy', 'Female', 10, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 0.51],
|
||||
['Sam', 'Male', 9, 'Math', 0.39],
|
||||
['Sam', 'Male', 9, 'English', 0.52],
|
||||
['Sam', 'Male', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDStDev()
|
||||
{
|
||||
return [
|
||||
[
|
||||
2.966479394838,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DSumTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDSum
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDSum($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DSUM($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Quarter', 'Area', 'Sales Rep.', 'Sales'],
|
||||
[1, 'North', 'Jeff', 223000],
|
||||
[1, 'North', 'Chris', 125000],
|
||||
[1, 'South', 'Carol', 456000],
|
||||
[1, 'South', 'Tina', 289000],
|
||||
[2, 'North', 'Jeff', 322000],
|
||||
[2, 'North', 'Chris', 340000],
|
||||
[2, 'South', 'Carol', 198000],
|
||||
[2, 'South', 'Tina', 222000],
|
||||
[3, 'North', 'Jeff', 310000],
|
||||
[3, 'North', 'Chris', 250000],
|
||||
[3, 'South', 'Carol', 460000],
|
||||
[3, 'South', 'Tina', 395000],
|
||||
[4, 'North', 'Jeff', 261000],
|
||||
[4, 'North', 'Chris', 389000],
|
||||
[4, 'South', 'Carol', 305000],
|
||||
[4, 'South', 'Tina', 188000],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDSum()
|
||||
{
|
||||
return [
|
||||
[
|
||||
225,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DVarPTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDVarP
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDVarP($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DVARP($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 10, 'Math', 0.63],
|
||||
['Amy', 'Female', 10, 'English', 0.78],
|
||||
['Amy', 'Female', 10, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 0.51],
|
||||
['Sam', 'Male', 9, 'Math', 0.39],
|
||||
['Sam', 'Male', 9, 'English', 0.52],
|
||||
['Sam', 'Male', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDVarP()
|
||||
{
|
||||
return [
|
||||
[
|
||||
7.04,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Database;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Database;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DVarTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDVar
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $database
|
||||
* @param mixed $field
|
||||
* @param mixed $criteria
|
||||
*/
|
||||
public function testDVar($expectedResult, $database, $field, $criteria): void
|
||||
{
|
||||
$result = Database::DVAR($database, $field, $criteria);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
protected function database1()
|
||||
{
|
||||
return [
|
||||
['Tree', 'Height', 'Age', 'Yield', 'Profit'],
|
||||
['Apple', 18, 20, 14, 105],
|
||||
['Pear', 12, 12, 10, 96],
|
||||
['Cherry', 13, 14, 9, 105],
|
||||
['Apple', 14, 15, 10, 75],
|
||||
['Pear', 9, 8, 8, 77],
|
||||
['Apple', 8, 9, 6, 45],
|
||||
];
|
||||
}
|
||||
|
||||
protected function database2()
|
||||
{
|
||||
return [
|
||||
['Name', 'Gender', 'Age', 'Subject', 'Score'],
|
||||
['Amy', 'Female', 10, 'Math', 0.63],
|
||||
['Amy', 'Female', 10, 'English', 0.78],
|
||||
['Amy', 'Female', 10, 'Science', 0.39],
|
||||
['Bill', 'Male', 8, 'Math', 0.55],
|
||||
['Bill', 'Male', 8, 'English', 0.71],
|
||||
['Bill', 'Male', 8, 'Science', 0.51],
|
||||
['Sam', 'Male', 9, 'Math', 0.39],
|
||||
['Sam', 'Male', 9, 'English', 0.52],
|
||||
['Sam', 'Male', 9, 'Science', 0.48],
|
||||
['Tom', 'Male', 9, 'Math', 0.78],
|
||||
['Tom', 'Male', 9, 'English', 0.69],
|
||||
['Tom', 'Male', 9, 'Science', 0.65],
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDVar()
|
||||
{
|
||||
return [
|
||||
[
|
||||
8.8,
|
||||
$this->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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue