diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index a3f45f19..bc0baa4d 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -328,17 +328,17 @@ class Calculation ], 'AVEDEV' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'AVEDEV'], + 'functionCall' => [Statistical\Averages::class, 'AVEDEV'], 'argumentCount' => '1+', ], 'AVERAGE' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'AVERAGE'], + 'functionCall' => [Statistical\Averages::class, 'AVERAGE'], 'argumentCount' => '1+', ], 'AVERAGEA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'AVERAGEA'], + 'functionCall' => [Statistical\Averages::class, 'AVERAGEA'], 'argumentCount' => '1+', ], 'AVERAGEIF' => [ @@ -624,17 +624,17 @@ class Calculation ], 'COUNT' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'COUNT'], + 'functionCall' => [Statistical\Counts::class, 'COUNT'], 'argumentCount' => '1+', ], 'COUNTA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'COUNTA'], + 'functionCall' => [Statistical\Counts::class, 'COUNTA'], 'argumentCount' => '1+', ], 'COUNTBLANK' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'COUNTBLANK'], + 'functionCall' => [Statistical\Counts::class, 'COUNTBLANK'], 'argumentCount' => '1', ], 'COUNTIF' => [ @@ -1620,12 +1620,12 @@ class Calculation ], 'MAX' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MAX'], + 'functionCall' => [Statistical\Maximum::class, 'MAX'], 'argumentCount' => '1+', ], 'MAXA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MAXA'], + 'functionCall' => [Statistical\Maximum::class, 'MAXA'], 'argumentCount' => '1+', ], 'MAXIFS' => [ @@ -1665,12 +1665,12 @@ class Calculation ], 'MIN' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MIN'], + 'functionCall' => [Statistical\Minimum::class, 'MIN'], 'argumentCount' => '1+', ], 'MINA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MINA'], + 'functionCall' => [Statistical\Minimum::class, 'MINA'], 'argumentCount' => '1+', ], 'MINIFS' => [ @@ -2263,22 +2263,22 @@ class Calculation ], 'STDEV' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'STDEV'], + 'functionCall' => [Statistical\StandardDeviations::class, 'STDEV'], 'argumentCount' => '1+', ], 'STDEV.S' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'STDEV'], + 'functionCall' => [Statistical\StandardDeviations::class, 'STDEV'], 'argumentCount' => '1+', ], 'STDEV.P' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'STDEVP'], + 'functionCall' => [Statistical\StandardDeviations::class, 'STDEVP'], 'argumentCount' => '1+', ], 'STDEVA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'STDEVA'], + 'functionCall' => [Statistical\StandardDeviations::class, 'STDEVA'], 'argumentCount' => '1+', ], 'STDEVP' => [ @@ -2524,32 +2524,32 @@ class Calculation ], 'VAR' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'VARFunc'], + 'functionCall' => [Statistical\Variances::class, 'VAR'], 'argumentCount' => '1+', ], 'VAR.P' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'VARP'], + 'functionCall' => [Statistical\Variances::class, 'VARP'], 'argumentCount' => '1+', ], 'VAR.S' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'VARFunc'], + 'functionCall' => [Statistical\Variances::class, 'VAR'], 'argumentCount' => '1+', ], 'VARA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'VARA'], + 'functionCall' => [Statistical\Variances::class, 'VARA'], 'argumentCount' => '1+', ], 'VARP' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'VARP'], + 'functionCall' => [Statistical\Variances::class, 'VARP'], 'argumentCount' => '1+', ], 'VARPA' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'VARPA'], + 'functionCall' => [Statistical\Variances::class, 'VARPA'], 'argumentCount' => '1+', ], 'VDB' => [ diff --git a/src/PhpSpreadsheet/Calculation/Database/DAverage.php b/src/PhpSpreadsheet/Calculation/Database/DAverage.php index ea45beda..738cb78e 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DAverage.php +++ b/src/PhpSpreadsheet/Calculation/Database/DAverage.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages; class DAverage extends DatabaseAbstract { @@ -38,7 +38,7 @@ class DAverage extends DatabaseAbstract return null; } - return Statistical::AVERAGE( + return Averages::AVERAGE( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DCount.php b/src/PhpSpreadsheet/Calculation/Database/DCount.php index da173c8c..bf41d6b5 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DCount.php +++ b/src/PhpSpreadsheet/Calculation/Database/DCount.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts; class DCount extends DatabaseAbstract { @@ -36,7 +36,7 @@ class DCount extends DatabaseAbstract { $field = self::fieldExtract($database, $field); - return Statistical::COUNT( + return Counts::COUNT( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DCountA.php b/src/PhpSpreadsheet/Calculation/Database/DCountA.php index 1beaf012..c48e53c5 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DCountA.php +++ b/src/PhpSpreadsheet/Calculation/Database/DCountA.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts; class DCountA extends DatabaseAbstract { @@ -35,7 +35,7 @@ class DCountA extends DatabaseAbstract { $field = self::fieldExtract($database, $field); - return Statistical::COUNTA( + return Counts::COUNTA( self::getFilteredColumn($database, $field ?? 0, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DMax.php b/src/PhpSpreadsheet/Calculation/Database/DMax.php index 8918c54d..6cf2f20d 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DMax.php +++ b/src/PhpSpreadsheet/Calculation/Database/DMax.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum; class DMax extends DatabaseAbstract { @@ -39,7 +39,7 @@ class DMax extends DatabaseAbstract return null; } - return Statistical::MAX( + return Maximum::MAX( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DMin.php b/src/PhpSpreadsheet/Calculation/Database/DMin.php index 357c9a91..5668bcf6 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DMin.php +++ b/src/PhpSpreadsheet/Calculation/Database/DMin.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum; class DMin extends DatabaseAbstract { @@ -39,7 +39,7 @@ class DMin extends DatabaseAbstract return null; } - return Statistical::MIN( + return Minimum::MIN( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DStDev.php b/src/PhpSpreadsheet/Calculation/Database/DStDev.php index 58bb4f7d..cfc7e952 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DStDev.php +++ b/src/PhpSpreadsheet/Calculation/Database/DStDev.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations; class DStDev extends DatabaseAbstract { @@ -39,7 +39,7 @@ class DStDev extends DatabaseAbstract return null; } - return Statistical::STDEV( + return StandardDeviations::STDEV( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DStDevP.php b/src/PhpSpreadsheet/Calculation/Database/DStDevP.php index 0d2e050d..2a04c5d9 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DStDevP.php +++ b/src/PhpSpreadsheet/Calculation/Database/DStDevP.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations; class DStDevP extends DatabaseAbstract { @@ -39,7 +39,7 @@ class DStDevP extends DatabaseAbstract return null; } - return Statistical::STDEVP( + return StandardDeviations::STDEVP( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DVar.php b/src/PhpSpreadsheet/Calculation/Database/DVar.php index 62c9f6c6..c70da073 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DVar.php +++ b/src/PhpSpreadsheet/Calculation/Database/DVar.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances; class DVar extends DatabaseAbstract { @@ -39,7 +39,7 @@ class DVar extends DatabaseAbstract return null; } - return Statistical::VARFunc( + return Variances::VAR( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/Database/DVarP.php b/src/PhpSpreadsheet/Calculation/Database/DVarP.php index 3a9744cb..f22f2cca 100644 --- a/src/PhpSpreadsheet/Calculation/Database/DVarP.php +++ b/src/PhpSpreadsheet/Calculation/Database/DVarP.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Database; -use PhpOffice\PhpSpreadsheet\Calculation\Statistical; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances; class DVarP extends DatabaseAbstract { @@ -39,7 +39,7 @@ class DVarP extends DatabaseAbstract return null; } - return Statistical::VARP( + return Variances::VARP( self::getFilteredColumn($database, $field, $criteria) ); } diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index 5a966cbf..e72e24cd 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -1222,27 +1222,27 @@ class MathTrig $aArgs = self::filterFormulaArgs($cellReference, $aArgs); switch ($subtotal) { case 1: - return Statistical::AVERAGE($aArgs); + return Statistical\Averages::AVERAGE($aArgs); case 2: - return Statistical::COUNT($aArgs); + return Statistical\Counts::COUNT($aArgs); case 3: - return Statistical::COUNTA($aArgs); + return Statistical\Counts::COUNTA($aArgs); case 4: - return Statistical::MAX($aArgs); + return Statistical\Maximum::MAX($aArgs); case 5: - return Statistical::MIN($aArgs); + return Statistical\Minimum::MIN($aArgs); case 6: return self::PRODUCT($aArgs); case 7: - return Statistical::STDEV($aArgs); + return Statistical\StandardDeviations::STDEV($aArgs); case 8: - return Statistical::STDEVP($aArgs); + return Statistical\StandardDeviations::STDEVP($aArgs); case 9: return self::SUM($aArgs); case 10: - return Statistical::VARFunc($aArgs); + return Statistical\Variances::VAR($aArgs); case 11: - return Statistical::VARP($aArgs); + return Statistical\Variances::VARP($aArgs); } } diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 2f695d5b..dc9c5b44 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -2,8 +2,14 @@ namespace PhpOffice\PhpSpreadsheet\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages; use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum; use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Permutations; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations; +use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances; use PhpOffice\PhpSpreadsheet\Shared\Trend\Trend; class Statistical @@ -520,48 +526,6 @@ class Statistical return Functions::NULL(); } - /** - * MS Excel does not count Booleans if passed as cell values, but they are counted if passed as literals. - * OpenOffice Calc always counts Booleans. - * Gnumeric never counts Booleans. - * - * @param mixed $arg - * @param mixed $k - * - * @return int|mixed - */ - private static function testAcceptedBoolean($arg, $k) - { - if ( - (is_bool($arg)) && - ((!Functions::isCellValue($k) && (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_EXCEL)) || - (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE)) - ) { - $arg = (int) $arg; - } - - return $arg; - } - - /** - * @param mixed $arg - * @param mixed $k - * - * @return bool - */ - private static function isAcceptedCountable($arg, $k) - { - if ( - ((is_numeric($arg)) && (!is_string($arg))) || - ((is_numeric($arg)) && (!Functions::isCellValue($k)) && - (Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_GNUMERIC)) - ) { - return true; - } - - return false; - } - /** * AVEDEV. * @@ -571,45 +535,18 @@ class Statistical * Excel Function: * AVEDEV(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Averages::AVEDEV() + * Use the AVEDEV() method in the Statistical\Averages class instead + * * @param mixed ...$args Data values * * @return float|string */ public static function AVEDEV(...$args) { - $aArgs = Functions::flattenArrayIndexed($args); - - // Return value - $returnValue = 0; - - $aMean = self::AVERAGE(...$args); - if ($aMean === Functions::DIV0()) { - return Functions::NAN(); - } elseif ($aMean === Functions::VALUE()) { - return Functions::VALUE(); - } - - $aCount = 0; - foreach ($aArgs as $k => $arg) { - $arg = self::testAcceptedBoolean($arg, $k); - // Is it a numeric value? - // Strings containing numeric values are only counted if they are string literals (not cell values) - // and then only in MS Excel and in Open Office, not in Gnumeric - if ((is_string($arg)) && (!is_numeric($arg)) && (!Functions::isCellValue($k))) { - return Functions::VALUE(); - } - if (self::isAcceptedCountable($arg, $k)) { - $returnValue += abs($arg - $aMean); - ++$aCount; - } - } - - // Return - if ($aCount === 0) { - return Functions::DIV0(); - } - - return $returnValue / $aCount; + return Averages::AVEDEV(...$args); } /** @@ -620,35 +557,18 @@ class Statistical * Excel Function: * AVERAGE(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Averages::AVERAGE() + * Use the AVERAGE() method in the Statistical\Averages class instead + * * @param mixed ...$args Data values * * @return float|string */ public static function AVERAGE(...$args) { - $returnValue = $aCount = 0; - - // Loop through arguments - foreach (Functions::flattenArrayIndexed($args) as $k => $arg) { - $arg = self::testAcceptedBoolean($arg, $k); - // Is it a numeric value? - // Strings containing numeric values are only counted if they are string literals (not cell values) - // and then only in MS Excel and in Open Office, not in Gnumeric - if ((is_string($arg)) && (!is_numeric($arg)) && (!Functions::isCellValue($k))) { - return Functions::VALUE(); - } - if (self::isAcceptedCountable($arg, $k)) { - $returnValue += $arg; - ++$aCount; - } - } - - // Return - if ($aCount > 0) { - return $returnValue / $aCount; - } - - return Functions::DIV0(); + return Averages::AVERAGE(...$args); } /** @@ -659,39 +579,18 @@ class Statistical * Excel Function: * AVERAGEA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Averages::AVERAGEA() + * Use the AVERAGEA() method in the Statistical\Averages class instead + * * @param mixed ...$args Data values * * @return float|string */ public static function AVERAGEA(...$args) { - $returnValue = null; - - $aCount = 0; - // Loop through arguments - foreach (Functions::flattenArrayIndexed($args) as $k => $arg) { - if ( - (is_bool($arg)) && - (!Functions::isMatrixValue($k)) - ) { - } else { - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - $returnValue += $arg; - ++$aCount; - } - } - } - - if ($aCount > 0) { - return $returnValue / $aCount; - } - - return Functions::DIV0(); + return Averages::AVERAGEA(...$args); } /** @@ -715,7 +614,7 @@ class Statistical */ public static function AVERAGEIF($range, $condition, $averageRange = []) { - return Statistical\Conditional::AVERAGEIF($range, $condition, $averageRange); + return Conditional::AVERAGEIF($range, $condition, $averageRange); } /** @@ -1026,27 +925,18 @@ class Statistical * Excel Function: * COUNT(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Counts::COUNT() + * Use the COUNT() method in the Statistical\Counts class instead + * * @param mixed ...$args Data values * * @return int */ public static function COUNT(...$args) { - $returnValue = 0; - - // Loop through arguments - $aArgs = Functions::flattenArrayIndexed($args); - foreach ($aArgs as $k => $arg) { - $arg = self::testAcceptedBoolean($arg, $k); - // Is it a numeric value? - // Strings containing numeric values are only counted if they are string literals (not cell values) - // and then only in MS Excel and in Open Office, not in Gnumeric - if (self::isAcceptedCountable($arg, $k)) { - ++$returnValue; - } - } - - return $returnValue; + return Counts::COUNT(...$args); } /** @@ -1057,24 +947,18 @@ class Statistical * Excel Function: * COUNTA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Counts::COUNTA() + * Use the COUNTA() method in the Statistical\Counts class instead + * * @param mixed ...$args Data values * * @return int */ public static function COUNTA(...$args) { - $returnValue = 0; - - // Loop through arguments - $aArgs = Functions::flattenArrayIndexed($args); - foreach ($aArgs as $k => $arg) { - // Nulls are counted if literals, but not if cell values - if ($arg !== null || (!Functions::isCellValue($k))) { - ++$returnValue; - } - } - - return $returnValue; + return Counts::COUNTA(...$args); } /** @@ -1085,24 +969,18 @@ class Statistical * Excel Function: * COUNTBLANK(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Counts::COUNTBLANK() + * Use the COUNTBLANK() method in the Statistical\Counts class instead + * * @param mixed ...$args Data values * * @return int */ public static function COUNTBLANK(...$args) { - $returnValue = 0; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - foreach ($aArgs as $arg) { - // Is it a blank cell? - if (($arg === null) || ((is_string($arg)) && ($arg == ''))) { - ++$returnValue; - } - } - - return $returnValue; + return Counts::COUNTBLANK(...$args); } /** @@ -1125,7 +1003,7 @@ class Statistical */ public static function COUNTIF($range, $condition) { - return Statistical\Conditional::COUNTIF($range, $condition); + return Conditional::COUNTIF($range, $condition); } /** @@ -1147,7 +1025,7 @@ class Statistical */ public static function COUNTIFS(...$args) { - return Statistical\Conditional::COUNTIFS(...$args); + return Conditional::COUNTIFS(...$args); } /** @@ -1325,7 +1203,7 @@ class Statistical // Return value $returnValue = null; - $aMean = self::AVERAGE($aArgs); + $aMean = Averages::AVERAGE($aArgs); if ($aMean != Functions::DIV0()) { $aCount = -1; foreach ($aArgs as $k => $arg) { @@ -1711,8 +1589,8 @@ class Statistical $aMean = MathTrig::PRODUCT($aArgs); if (is_numeric($aMean) && ($aMean > 0)) { - $aCount = self::COUNT($aArgs); - if (self::MIN($aArgs) > 0) { + $aCount = Counts::COUNT($aArgs); + if (Minimum::MIN($aArgs) > 0) { return $aMean ** (1 / $aCount); } } @@ -1772,7 +1650,7 @@ class Statistical // Loop through arguments $aArgs = Functions::flattenArray($args); - if (self::MIN($aArgs) < 0) { + if (Minimum::MIN($aArgs) < 0) { return Functions::NAN(); } $aCount = 0; @@ -1883,8 +1761,8 @@ class Statistical public static function KURT(...$args) { $aArgs = Functions::flattenArrayIndexed($args); - $mean = self::AVERAGE($aArgs); - $stdDev = self::STDEV($aArgs); + $mean = Averages::AVERAGE($aArgs); + $stdDev = StandardDeviations::STDEV($aArgs); if ($stdDev > 0) { $count = $summer = 0; @@ -1941,7 +1819,7 @@ class Statistical $mArgs[] = $arg; } } - $count = self::COUNT($mArgs); + $count = Counts::COUNT($mArgs); --$entry; if (($entry < 0) || ($entry >= $count) || ($count == 0)) { return Functions::NAN(); @@ -2184,30 +2062,18 @@ class Statistical * Excel Function: * MAX(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Maximum::MAX() + * Use the MAX() method in the Statistical\Maximum class instead + * * @param mixed ...$args Data values * * @return float */ public static function MAX(...$args) { - $returnValue = null; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - if (($returnValue === null) || ($arg > $returnValue)) { - $returnValue = $arg; - } - } - } - - if ($returnValue === null) { - return 0; - } - - return $returnValue; + return Maximum::MAX(...$args); } /** @@ -2218,35 +2084,18 @@ class Statistical * Excel Function: * MAXA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Maximum::MAXA() + * Use the MAXA() method in the Statistical\Maximum class instead + * * @param mixed ...$args Data values * * @return float */ public static function MAXA(...$args) { - $returnValue = null; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - if (($returnValue === null) || ($arg > $returnValue)) { - $returnValue = $arg; - } - } - } - - if ($returnValue === null) { - return 0; - } - - return $returnValue; + return Maximum::MAXA(...$args); } /** @@ -2321,30 +2170,18 @@ class Statistical * Excel Function: * MIN(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Minimum::MIN() + * Use the MIN() method in the Statistical\Minimum class instead + * * @param mixed ...$args Data values * * @return float */ public static function MIN(...$args) { - $returnValue = null; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - if (($returnValue === null) || ($arg < $returnValue)) { - $returnValue = $arg; - } - } - } - - if ($returnValue === null) { - return 0; - } - - return $returnValue; + return Minimum::MIN(...$args); } /** @@ -2355,35 +2192,18 @@ class Statistical * Excel Function: * MINA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Minimum::MINA() + * Use the MINA() method in the Statistical\Minimum class instead + * * @param mixed ...$args Data values * * @return float */ public static function MINA(...$args) { - $returnValue = null; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - if (($returnValue === null) || ($arg < $returnValue)) { - $returnValue = $arg; - } - } - } - - if ($returnValue === null) { - return 0; - } - - return $returnValue; + return Minimum::MINA(...$args); } /** @@ -2688,7 +2508,7 @@ class Statistical $mValueCount = count($mArgs); if ($mValueCount > 0) { sort($mArgs); - $count = self::COUNT($mArgs); + $count = Counts::COUNT($mArgs); $index = $entry * ($count - 1); $iBase = floor($index); if ($index == $iBase) { @@ -2775,7 +2595,7 @@ class Statistical */ public static function PERMUT($numObjs, $numInSet) { - return Statistical\Permutations::PERMUT($numObjs, $numInSet); + return Permutations::PERMUT($numObjs, $numInSet); } /** @@ -2930,8 +2750,8 @@ class Statistical public static function SKEW(...$args) { $aArgs = Functions::flattenArrayIndexed($args); - $mean = self::AVERAGE($aArgs); - $stdDev = self::STDEV($aArgs); + $mean = Averages::AVERAGE($aArgs); + $stdDev = StandardDeviations::STDEV($aArgs); $count = $summer = 0; // Loop through arguments @@ -3015,7 +2835,7 @@ class Statistical $mArgs[] = $arg; } } - $count = self::COUNT($mArgs); + $count = Counts::COUNT($mArgs); --$entry; if (($entry < 0) || ($entry >= $count) || ($count == 0)) { return Functions::NAN(); @@ -3065,45 +2885,18 @@ class Statistical * Excel Function: * STDEV(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\StandardDeviations::STDEV() + * Use the STDEV() method in the Statistical\StandardDeviations class instead + * * @param mixed ...$args Data values * * @return float|string The result, or a string containing an error */ public static function STDEV(...$args) { - $aArgs = Functions::flattenArrayIndexed($args); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGE($aArgs); - if ($aMean !== null) { - $aCount = -1; - foreach ($aArgs as $k => $arg) { - if ( - (is_bool($arg)) && - ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE)) - ) { - $arg = (int) $arg; - } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - if ($returnValue === null) { - $returnValue = ($arg - $aMean) ** 2; - } else { - $returnValue += ($arg - $aMean) ** 2; - } - ++$aCount; - } - } - - // Return - if (($aCount > 0) && ($returnValue >= 0)) { - return sqrt($returnValue / $aCount); - } - } - - return Functions::DIV0(); + return StandardDeviations::STDEV(...$args); } /** @@ -3114,48 +2907,18 @@ class Statistical * Excel Function: * STDEVA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\StandardDeviations::STDEVA() + * Use the STDEVA() method in the Statistical\StandardDeviations class instead + * * @param mixed ...$args Data values * * @return float|string */ public static function STDEVA(...$args) { - $aArgs = Functions::flattenArrayIndexed($args); - - $returnValue = null; - - $aMean = self::AVERAGEA($aArgs); - if ($aMean !== null) { - $aCount = -1; - foreach ($aArgs as $k => $arg) { - if ( - (is_bool($arg)) && - (!Functions::isMatrixValue($k)) - ) { - } else { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - if ($returnValue === null) { - $returnValue = ($arg - $aMean) ** 2; - } else { - $returnValue += ($arg - $aMean) ** 2; - } - ++$aCount; - } - } - } - - if (($aCount > 0) && ($returnValue >= 0)) { - return sqrt($returnValue / $aCount); - } - } - - return Functions::DIV0(); + return StandardDeviations::STDEVA(...$args); } /** @@ -3166,43 +2929,18 @@ class Statistical * Excel Function: * STDEVP(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\StandardDeviations::STDEVP() + * Use the STDEVP() method in the Statistical\StandardDeviations class instead + * * @param mixed ...$args Data values * * @return float|string */ public static function STDEVP(...$args) { - $aArgs = Functions::flattenArrayIndexed($args); - - $returnValue = null; - - $aMean = self::AVERAGE($aArgs); - if ($aMean !== null) { - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ( - (is_bool($arg)) && - ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE)) - ) { - $arg = (int) $arg; - } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - if ($returnValue === null) { - $returnValue = ($arg - $aMean) ** 2; - } else { - $returnValue += ($arg - $aMean) ** 2; - } - ++$aCount; - } - } - - if (($aCount > 0) && ($returnValue >= 0)) { - return sqrt($returnValue / $aCount); - } - } - - return Functions::DIV0(); + return StandardDeviations::STDEVP(...$args); } /** @@ -3213,48 +2951,18 @@ class Statistical * Excel Function: * STDEVPA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\StandardDeviations::STDEVPA() + * Use the STDEVPA() method in the Statistical\StandardDeviations class instead + * * @param mixed ...$args Data values * * @return float|string */ public static function STDEVPA(...$args) { - $aArgs = Functions::flattenArrayIndexed($args); - - $returnValue = null; - - $aMean = self::AVERAGEA($aArgs); - if ($aMean !== null) { - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ( - (is_bool($arg)) && - (!Functions::isMatrixValue($k)) - ) { - } else { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - if ($returnValue === null) { - $returnValue = ($arg - $aMean) ** 2; - } else { - $returnValue += ($arg - $aMean) ** 2; - } - ++$aCount; - } - } - } - - if (($aCount > 0) && ($returnValue >= 0)) { - return sqrt($returnValue / $aCount); - } - } - - return Functions::DIV0(); + return StandardDeviations::STDEVPA(...$args); } /** @@ -3472,14 +3180,14 @@ class Statistical $mArgs[] = $arg; } } - $discard = floor(self::COUNT($mArgs) * $percent / 2); + $discard = floor(Counts::COUNT($mArgs) * $percent / 2); sort($mArgs); for ($i = 0; $i < $discard; ++$i) { array_pop($mArgs); array_shift($mArgs); } - return self::AVERAGE($mArgs); + return Averages::AVERAGE($mArgs); } return Functions::VALUE(); @@ -3493,38 +3201,18 @@ class Statistical * Excel Function: * VAR(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * * @param mixed ...$args Data values * * @return float|string (string if result is an error) + * + *@see Statistical\Variances::VAR() + * Use the VAR() method in the Statistical\Variances class instead */ public static function VARFunc(...$args) { - $returnValue = Functions::DIV0(); - - $summerA = $summerB = 0; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - $aCount = 0; - foreach ($aArgs as $arg) { - if (is_bool($arg)) { - $arg = (int) $arg; - } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; - } - } - - if ($aCount > 1) { - $summerA *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); - } - - return $returnValue; + return Variances::VAR(...$args); } /** @@ -3535,51 +3223,18 @@ class Statistical * Excel Function: * VARA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Variances::VARA() + * Use the VARA() method in the Statistical\Variances class instead + * * @param mixed ...$args Data values * * @return float|string (string if result is an error) */ public static function VARA(...$args) { - $returnValue = Functions::DIV0(); - - $summerA = $summerB = 0; - - // Loop through arguments - $aArgs = Functions::flattenArrayIndexed($args); - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ( - (is_string($arg)) && - (Functions::isValue($k)) - ) { - return Functions::VALUE(); - } elseif ( - (is_string($arg)) && - (!Functions::isMatrixValue($k)) - ) { - } else { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; - } - } - } - - if ($aCount > 1) { - $summerA *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); - } - - return $returnValue; + return Variances::VARA(...$args); } /** @@ -3590,39 +3245,18 @@ class Statistical * Excel Function: * VARP(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Variances::VARP() + * Use the VARP() method in the Statistical\Variances class instead + * * @param mixed ...$args Data values * * @return float|string (string if result is an error) */ public static function VARP(...$args) { - // Return value - $returnValue = Functions::DIV0(); - - $summerA = $summerB = 0; - - // Loop through arguments - $aArgs = Functions::flattenArray($args); - $aCount = 0; - foreach ($aArgs as $arg) { - if (is_bool($arg)) { - $arg = (int) $arg; - } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; - } - } - - if ($aCount > 0) { - $summerA *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * $aCount); - } - - return $returnValue; + return Variances::VARP(...$args); } /** @@ -3633,51 +3267,18 @@ class Statistical * Excel Function: * VARPA(value1[,value2[, ...]]) * + * @Deprecated 1.17.0 + * + * @see Statistical\Variances::VARPA() + * Use the VARPA() method in the Statistical\Variances class instead + * * @param mixed ...$args Data values * * @return float|string (string if result is an error) */ public static function VARPA(...$args) { - $returnValue = Functions::DIV0(); - - $summerA = $summerB = 0; - - // Loop through arguments - $aArgs = Functions::flattenArrayIndexed($args); - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ( - (is_string($arg)) && - (Functions::isValue($k)) - ) { - return Functions::VALUE(); - } elseif ( - (is_string($arg)) && - (!Functions::isMatrixValue($k)) - ) { - } else { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (int) $arg; - } elseif (is_string($arg)) { - $arg = 0; - } - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; - } - } - } - - if ($aCount > 0) { - $summerA *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * $aCount); - } - - return $returnValue; + return Variances::VARPA(...$args); } /** @@ -3734,10 +3335,10 @@ class Statistical $sigma = Functions::flattenSingleValue($sigma); if ($sigma === null) { - $sigma = self::STDEV($dataSet); + $sigma = StandardDeviations::STDEV($dataSet); } $n = count($dataSet); - return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0) / ($sigma / sqrt($n))); + return 1 - self::NORMSDIST((Averages::AVERAGE($dataSet) - $m0) / ($sigma / sqrt($n))); } } diff --git a/src/PhpSpreadsheet/Calculation/Statistical/AggregateBase.php b/src/PhpSpreadsheet/Calculation/Statistical/AggregateBase.php new file mode 100644 index 00000000..75c012dc --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Statistical/AggregateBase.php @@ -0,0 +1,50 @@ + $arg) { + $arg = self::testAcceptedBoolean($arg, $k); + // Is it a numeric value? + // Strings containing numeric values are only counted if they are string literals (not cell values) + // and then only in MS Excel and in Open Office, not in Gnumeric + if ((is_string($arg)) && (!is_numeric($arg)) && (!Functions::isCellValue($k))) { + return Functions::VALUE(); + } + if (self::isAcceptedCountable($arg, $k)) { + $returnValue += abs($arg - $aMean); + ++$aCount; + } + } + + // Return + if ($aCount === 0) { + return Functions::DIV0(); + } + + return $returnValue / $aCount; + } + + /** + * AVERAGE. + * + * Returns the average (arithmetic mean) of the arguments + * + * Excel Function: + * AVERAGE(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string (string if result is an error) + */ + public static function AVERAGE(...$args) + { + $returnValue = $aCount = 0; + + // Loop through arguments + foreach (Functions::flattenArrayIndexed($args) as $k => $arg) { + $arg = self::testAcceptedBoolean($arg, $k); + // Is it a numeric value? + // Strings containing numeric values are only counted if they are string literals (not cell values) + // and then only in MS Excel and in Open Office, not in Gnumeric + if ((is_string($arg)) && (!is_numeric($arg)) && (!Functions::isCellValue($k))) { + return Functions::VALUE(); + } + if (self::isAcceptedCountable($arg, $k)) { + $returnValue += $arg; + ++$aCount; + } + } + + // Return + if ($aCount > 0) { + return $returnValue / $aCount; + } + + return Functions::DIV0(); + } + + /** + * AVERAGEA. + * + * Returns the average of its arguments, including numbers, text, and logical values + * + * Excel Function: + * AVERAGEA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string (string if result is an error) + */ + public static function AVERAGEA(...$args) + { + $returnValue = null; + + $aCount = 0; + // Loop through arguments + foreach (Functions::flattenArrayIndexed($args) as $k => $arg) { + if ((is_bool($arg)) && (!Functions::isMatrixValue($k))) { + } else { + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + if (is_bool($arg)) { + $arg = (int) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $returnValue += $arg; + ++$aCount; + } + } + } + + if ($aCount > 0) { + return $returnValue / $aCount; + } + + return Functions::DIV0(); + } +} diff --git a/src/PhpSpreadsheet/Calculation/Statistical/Counts.php b/src/PhpSpreadsheet/Calculation/Statistical/Counts.php new file mode 100644 index 00000000..13e7af79 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Statistical/Counts.php @@ -0,0 +1,95 @@ + $arg) { + $arg = self::testAcceptedBoolean($arg, $k); + // Is it a numeric value? + // Strings containing numeric values are only counted if they are string literals (not cell values) + // and then only in MS Excel and in Open Office, not in Gnumeric + if (self::isAcceptedCountable($arg, $k)) { + ++$returnValue; + } + } + + return $returnValue; + } + + /** + * COUNTA. + * + * Counts the number of cells that are not empty within the list of arguments + * + * Excel Function: + * COUNTA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return int + */ + public static function COUNTA(...$args) + { + $returnValue = 0; + + // Loop through arguments + $aArgs = Functions::flattenArrayIndexed($args); + foreach ($aArgs as $k => $arg) { + // Nulls are counted if literals, but not if cell values + if ($arg !== null || (!Functions::isCellValue($k))) { + ++$returnValue; + } + } + + return $returnValue; + } + + /** + * COUNTBLANK. + * + * Counts the number of empty cells within the list of arguments + * + * Excel Function: + * COUNTBLANK(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return int + */ + public static function COUNTBLANK(...$args) + { + $returnValue = 0; + + // Loop through arguments + $aArgs = Functions::flattenArray($args); + foreach ($aArgs as $arg) { + // Is it a blank cell? + if (($arg === null) || ((is_string($arg)) && ($arg == ''))) { + ++$returnValue; + } + } + + return $returnValue; + } +} diff --git a/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php b/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php new file mode 100644 index 00000000..bd17b062 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php @@ -0,0 +1,17 @@ + $returnValue)) { + $returnValue = $arg; + } + } + } + + if ($returnValue === null) { + return 0; + } + + return $returnValue; + } + + /** + * MAXA. + * + * Returns the greatest value in a list of arguments, including numbers, text, and logical values + * + * Excel Function: + * MAXA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float + */ + public static function MAXA(...$args) + { + $returnValue = null; + + // Loop through arguments + $aArgs = Functions::flattenArray($args); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + $arg = self::datatypeAdjustmentAllowStrings($arg); + if (($returnValue === null) || ($arg > $returnValue)) { + $returnValue = $arg; + } + } + } + + if ($returnValue === null) { + return 0; + } + + return $returnValue; + } +} diff --git a/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php b/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php new file mode 100644 index 00000000..bd46882e --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php @@ -0,0 +1,78 @@ + $arg) { + if ( + (is_bool($arg)) && + ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE)) + ) { + $arg = (int) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue += ($arg - $aMean) ** 2; + ++$aCount; + } + } + + if ($aCount > 0) { + return sqrt($returnValue / $aCount); + } + } + + return Functions::DIV0(); + } + + /** + * STDEVA. + * + * Estimates standard deviation based on a sample, including numbers, text, and logical values + * + * Excel Function: + * STDEVA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string + */ + public static function STDEVA(...$args) + { + $aArgs = Functions::flattenArrayIndexed($args); + + $aMean = Averages::AVERAGEA($aArgs); + + if (!is_string($aMean)) { + $returnValue = 0.0; + $aCount = -1; + + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && (!Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + $arg = self::datatypeAdjustmentAllowStrings($arg); + $returnValue += ($arg - $aMean) ** 2; + ++$aCount; + } + } + } + + if ($aCount > 0) { + return sqrt($returnValue / $aCount); + } + } + + return Functions::DIV0(); + } + + /** + * STDEVP. + * + * Calculates standard deviation based on the entire population + * + * Excel Function: + * STDEVP(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string + */ + public static function STDEVP(...$args) + { + $aArgs = Functions::flattenArrayIndexed($args); + + $aMean = Averages::AVERAGE($aArgs); + + if (!is_string($aMean)) { + $returnValue = 0.0; + $aCount = 0; + + foreach ($aArgs as $k => $arg) { + if ( + (is_bool($arg)) && + ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE)) + ) { + $arg = (int) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue += ($arg - $aMean) ** 2; + ++$aCount; + } + } + + if ($aCount > 0) { + return sqrt($returnValue / $aCount); + } + } + + return Functions::DIV0(); + } + + /** + * STDEVPA. + * + * Calculates standard deviation based on the entire population, including numbers, text, and logical values + * + * Excel Function: + * STDEVPA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string + */ + public static function STDEVPA(...$args) + { + $aArgs = Functions::flattenArrayIndexed($args); + + $aMean = Averages::AVERAGEA($aArgs); + + if (!is_string($aMean)) { + $returnValue = 0.0; + $aCount = 0; + + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && (!Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + $arg = self::datatypeAdjustmentAllowStrings($arg); + $returnValue += ($arg - $aMean) ** 2; + ++$aCount; + } + } + } + + if ($aCount > 0) { + return sqrt($returnValue / $aCount); + } + } + + return Functions::DIV0(); + } +} diff --git a/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php b/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php new file mode 100644 index 00000000..9762ec84 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php @@ -0,0 +1,26 @@ + 1) { + $summerA *= $aCount; + $summerB *= $summerB; + + return ($summerA - $summerB) / ($aCount * ($aCount - 1)); + } + + return $returnValue; + } + + /** + * VARA. + * + * Estimates variance based on a sample, including numbers, text, and logical values + * + * Excel Function: + * VARA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string (string if result is an error) + */ + public static function VARA(...$args) + { + $returnValue = Functions::DIV0(); + + $summerA = $summerB = 0.0; + + // Loop through arguments + $aArgs = Functions::flattenArrayIndexed($args); + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && (Functions::isValue($k))) { + return Functions::VALUE(); + } elseif ((is_string($arg)) && (!Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + $arg = self::datatypeAdjustmentAllowStrings($arg); + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + } + + if ($aCount > 1) { + $summerA *= $aCount; + $summerB *= $summerB; + + return ($summerA - $summerB) / ($aCount * ($aCount - 1)); + } + + return $returnValue; + } + + /** + * VARP. + * + * Calculates variance based on the entire population + * + * Excel Function: + * VARP(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string (string if result is an error) + */ + public static function VARP(...$args) + { + // Return value + $returnValue = Functions::DIV0(); + + $summerA = $summerB = 0.0; + + // Loop through arguments + $aArgs = Functions::flattenArray($args); + $aCount = 0; + foreach ($aArgs as $arg) { + $arg = self::datatypeAdjustmentBooleans($arg); + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + + if ($aCount > 0) { + $summerA *= $aCount; + $summerB *= $summerB; + + return ($summerA - $summerB) / ($aCount * $aCount); + } + + return $returnValue; + } + + /** + * VARPA. + * + * Calculates variance based on the entire population, including numbers, text, and logical values + * + * Excel Function: + * VARPA(value1[,value2[, ...]]) + * + * @param mixed ...$args Data values + * + * @return float|string (string if result is an error) + */ + public static function VARPA(...$args) + { + $returnValue = Functions::DIV0(); + + $summerA = $summerB = 0.0; + + // Loop through arguments + $aArgs = Functions::flattenArrayIndexed($args); + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && (Functions::isValue($k))) { + return Functions::VALUE(); + } elseif ((is_string($arg)) && (!Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + $arg = self::datatypeAdjustmentAllowStrings($arg); + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + } + + if ($aCount > 0) { + $summerA *= $aCount; + $summerB *= $summerB; + + return ($summerA - $summerB) / ($aCount * $aCount); + } + + return $returnValue; + } +} diff --git a/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php b/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php index 7530b1ef..56e917e3 100644 --- a/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php +++ b/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php @@ -24,7 +24,7 @@ class Tcpdf extends Pdf * * @param string $orientation Page orientation * @param string $unit Unit measure - * @param string $paperSize Paper size + * @param array|string $paperSize Paper size * * @return \TCPDF implementation */ diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/StDevATest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/StDevATest.php new file mode 100644 index 00000000..9115db46 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/StDevATest.php @@ -0,0 +1,26 @@ +