Skip to content

Commit 42fc71f

Browse files
zdenekdrahosMark Baker
authored and
Mark Baker
committed
Calculation/Statistical :: Add MAXIFS, MINIFS, COUNTIFS and Remove MINIF, MAXIF (#1059)
* #1056 - replace invalid minif/maxif functions by not implemented minifs/maxifs minif/maxif is not support in Excel, Google Spreadsheets, Libreoffice https://support.office.com/en-us/article/excel-functions-alphabetical-b3944572-255d-4efb-bb96-c6d90033e188#bm13 * #1056 - implement minifs/maxifs Copy-pasted sumifs... https://github.com/PHPOffice/PhpSpreadsheet/blob/1.8.1/src/PhpSpreadsheet/Calculation/MathTrig.php#L1254 * #1056 - implement countifs * #1056 - fix code style composer check composer fix * #1056 - update changelog
1 parent 2219061 commit 42fc71f

File tree

10 files changed

+337
-55
lines changed

10 files changed

+337
-55
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
1010
### Added
1111

1212
- When <br> appears in a table cell, set the cell to wrap [Issue #1071](https://github.com/PHPOffice/PhpSpreadsheet/issues/1071) and [PR #1070](https://github.com/PHPOffice/PhpSpreadsheet/pull/1070)
13+
- Add MAXIFS, MINIFS, COUNTIFS and Remove MINIF, MAXIF - [Issue #1056](https://github.com/PHPOffice/PhpSpreadsheet/issues/1056)
1314

1415
### Fixed
1516

docs/references/function-list-by-category.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ COUNT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNT
333333
COUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTA
334334
COUNTBLANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTBLANK
335335
COUNTIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIF
336-
COUNTIFS | **Not yet Implemented**
336+
COUNTIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIFS
337337
COVAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR
338338
CRITBINOM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM
339339
DEVSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ
@@ -361,12 +361,12 @@ LOGINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV
361361
LOGNORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST
362362
MAX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX
363363
MAXA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA
364-
MAXIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIF
364+
MAXIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIFS
365365
MEDIAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MEDIAN
366366
MEDIANIF | **Not yet Implemented**
367367
MIN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MIN
368368
MINA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINA
369-
MINIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIF
369+
MINIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIFS
370370
MODE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
371371
MODE.SNGL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE
372372
NEGBINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST

docs/references/function-list-by-name.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ COUNT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet
7979
COUNTA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTA
8080
COUNTBLANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTBLANK
8181
COUNTIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIF
82-
COUNTIFS | CATEGORY_STATISTICAL | **Not yet Implemented**
82+
COUNTIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIFS
8383
COUPDAYBS | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYBS
8484
COUPDAYS | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYS
8585
COUPDAYSNC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYSNC
@@ -295,7 +295,7 @@ Excel Function | Category | PhpSpreadsheet Function
295295
MATCH | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::MATCH
296296
MAX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX
297297
MAXA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA
298-
MAXIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIF
298+
MAXIFS | CATEGORY_STATISTICAL | **Not yet Implemented**
299299
MDETERM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MDETERM
300300
MDURATION | CATEGORY_FINANCIAL | **Not yet Implemented**
301301
MEDIAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MEDIAN
@@ -304,7 +304,7 @@ MID | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet
304304
MIDB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::MID
305305
MIN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MIN
306306
MINA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINA
307-
MINIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIF
307+
MINIFS | CATEGORY_STATISTICAL | **Not yet Implemented**
308308
MINUTE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::MINUTE
309309
MINVERSE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MINVERSE
310310
MIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::MIRR

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ class Calculation
527527
],
528528
'COUNTIFS' => [
529529
'category' => Category::CATEGORY_STATISTICAL,
530-
'functionCall' => [Functions::class, 'DUMMY'],
530+
'functionCall' => [Statistical::class, 'COUNTIFS'],
531531
'argumentCount' => '2+',
532532
],
533533
'COUPDAYBS' => [
@@ -1356,10 +1356,10 @@ class Calculation
13561356
'functionCall' => [Statistical::class, 'MAXA'],
13571357
'argumentCount' => '1+',
13581358
],
1359-
'MAXIF' => [
1359+
'MAXIFS' => [
13601360
'category' => Category::CATEGORY_STATISTICAL,
1361-
'functionCall' => [Statistical::class, 'MAXIF'],
1362-
'argumentCount' => '2+',
1361+
'functionCall' => [Statistical::class, 'MAXIFS'],
1362+
'argumentCount' => '3+',
13631363
],
13641364
'MDETERM' => [
13651365
'category' => Category::CATEGORY_MATH_AND_TRIG,
@@ -1401,10 +1401,10 @@ class Calculation
14011401
'functionCall' => [Statistical::class, 'MINA'],
14021402
'argumentCount' => '1+',
14031403
],
1404-
'MINIF' => [
1404+
'MINIFS' => [
14051405
'category' => Category::CATEGORY_STATISTICAL,
1406-
'functionCall' => [Statistical::class, 'MINIF'],
1407-
'argumentCount' => '2+',
1406+
'functionCall' => [Statistical::class, 'MINIFS'],
1407+
'argumentCount' => '3+',
14081408
],
14091409
'MINUTE' => [
14101410
'category' => Category::CATEGORY_DATE_AND_TIME,

src/PhpSpreadsheet/Calculation/Statistical.php

Lines changed: 138 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,68 @@ public static function COUNTIF($aArgs, $condition)
11341134
return $returnValue;
11351135
}
11361136

1137+
/**
1138+
* COUNTIFS.
1139+
*
1140+
* Counts the number of cells that contain numbers within the list of arguments
1141+
*
1142+
* Excel Function:
1143+
* COUNTIFS(criteria_range1, criteria1, [criteria_range2, criteria2]…)
1144+
*
1145+
* @category Statistical Functions
1146+
*
1147+
* @param mixed $args Criterias
1148+
*
1149+
* @return int
1150+
*/
1151+
public static function COUNTIFS(...$args)
1152+
{
1153+
$arrayList = $args;
1154+
1155+
// Return value
1156+
$returnValue = 0;
1157+
1158+
if (!$arrayList) {
1159+
return $returnValue;
1160+
}
1161+
1162+
$aArgsArray = [];
1163+
$conditions = [];
1164+
1165+
while (count($arrayList) > 0) {
1166+
$aArgsArray[] = Functions::flattenArray(array_shift($arrayList));
1167+
$conditions[] = Functions::ifCondition(array_shift($arrayList));
1168+
}
1169+
1170+
// Loop through each arg and see if arguments and conditions are true
1171+
foreach (array_keys($aArgsArray[0]) as $index) {
1172+
$valid = true;
1173+
1174+
foreach ($conditions as $cidx => $condition) {
1175+
$arg = $aArgsArray[$cidx][$index];
1176+
1177+
// Loop through arguments
1178+
if (!is_numeric($arg)) {
1179+
$arg = Calculation::wrapResult(strtoupper($arg));
1180+
}
1181+
$testCondition = '=' . $arg . $condition;
1182+
if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1183+
// Is not a value within our criteria
1184+
$valid = false;
1185+
1186+
break; // if false found, don't need to check other conditions
1187+
}
1188+
}
1189+
1190+
if ($valid) {
1191+
++$returnValue;
1192+
}
1193+
}
1194+
1195+
// Return
1196+
return $returnValue;
1197+
}
1198+
11371199
/**
11381200
* COVAR.
11391201
*
@@ -2105,44 +2167,61 @@ public static function MAXA(...$args)
21052167
}
21062168

21072169
/**
2108-
* MAXIF.
2170+
* MAXIFS.
21092171
*
21102172
* Counts the maximum value within a range of cells that contain numbers within the list of arguments
21112173
*
21122174
* Excel Function:
2113-
* MAXIF(value1[,value2[, ...]],condition)
2175+
* MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)
21142176
*
2115-
* @category Mathematical and Trigonometric Functions
2177+
* @category Statistical Functions
21162178
*
2117-
* @param mixed $aArgs Data values
2118-
* @param string $condition the criteria that defines which cells will be checked
2119-
* @param mixed $sumArgs
2179+
* @param mixed $args Data range and criterias
21202180
*
21212181
* @return float
21222182
*/
2123-
public static function MAXIF($aArgs, $condition, $sumArgs = [])
2183+
public static function MAXIFS(...$args)
21242184
{
2185+
$arrayList = $args;
2186+
2187+
// Return value
21252188
$returnValue = null;
21262189

2127-
$aArgs = Functions::flattenArray($aArgs);
2128-
$sumArgs = Functions::flattenArray($sumArgs);
2129-
if (empty($sumArgs)) {
2130-
$sumArgs = $aArgs;
2190+
$maxArgs = Functions::flattenArray(array_shift($arrayList));
2191+
$aArgsArray = [];
2192+
$conditions = [];
2193+
2194+
while (count($arrayList) > 0) {
2195+
$aArgsArray[] = Functions::flattenArray(array_shift($arrayList));
2196+
$conditions[] = Functions::ifCondition(array_shift($arrayList));
21312197
}
2132-
$condition = Functions::ifCondition($condition);
2133-
// Loop through arguments
2134-
foreach ($aArgs as $key => $arg) {
2135-
if (!is_numeric($arg)) {
2136-
$arg = Calculation::wrapResult(strtoupper($arg));
2137-
}
2138-
$testCondition = '=' . $arg . $condition;
2139-
if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2140-
if (($returnValue === null) || ($arg > $returnValue)) {
2141-
$returnValue = $arg;
2198+
2199+
// Loop through each arg and see if arguments and conditions are true
2200+
foreach ($maxArgs as $index => $value) {
2201+
$valid = true;
2202+
2203+
foreach ($conditions as $cidx => $condition) {
2204+
$arg = $aArgsArray[$cidx][$index];
2205+
2206+
// Loop through arguments
2207+
if (!is_numeric($arg)) {
2208+
$arg = Calculation::wrapResult(strtoupper($arg));
2209+
}
2210+
$testCondition = '=' . $arg . $condition;
2211+
if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2212+
// Is not a value within our criteria
2213+
$valid = false;
2214+
2215+
break; // if false found, don't need to check other conditions
21422216
}
21432217
}
2218+
2219+
if ($valid) {
2220+
$returnValue = $returnValue === null ? $value : max($value, $returnValue);
2221+
}
21442222
}
21452223

2224+
// Return
21462225
return $returnValue;
21472226
}
21482227

@@ -2268,44 +2347,61 @@ public static function MINA(...$args)
22682347
}
22692348

22702349
/**
2271-
* MINIF.
2350+
* MINIFS.
22722351
*
22732352
* Returns the minimum value within a range of cells that contain numbers within the list of arguments
22742353
*
22752354
* Excel Function:
2276-
* MINIF(value1[,value2[, ...]],condition)
2355+
* MINIFS(min_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)
22772356
*
2278-
* @category Mathematical and Trigonometric Functions
2357+
* @category Statistical Functions
22792358
*
2280-
* @param mixed $aArgs Data values
2281-
* @param string $condition the criteria that defines which cells will be checked
2282-
* @param mixed $sumArgs
2359+
* @param mixed $args Data range and criterias
22832360
*
22842361
* @return float
22852362
*/
2286-
public static function MINIF($aArgs, $condition, $sumArgs = [])
2363+
public static function MINIFS(...$args)
22872364
{
2365+
$arrayList = $args;
2366+
2367+
// Return value
22882368
$returnValue = null;
22892369

2290-
$aArgs = Functions::flattenArray($aArgs);
2291-
$sumArgs = Functions::flattenArray($sumArgs);
2292-
if (empty($sumArgs)) {
2293-
$sumArgs = $aArgs;
2370+
$minArgs = Functions::flattenArray(array_shift($arrayList));
2371+
$aArgsArray = [];
2372+
$conditions = [];
2373+
2374+
while (count($arrayList) > 0) {
2375+
$aArgsArray[] = Functions::flattenArray(array_shift($arrayList));
2376+
$conditions[] = Functions::ifCondition(array_shift($arrayList));
22942377
}
2295-
$condition = Functions::ifCondition($condition);
2296-
// Loop through arguments
2297-
foreach ($aArgs as $key => $arg) {
2298-
if (!is_numeric($arg)) {
2299-
$arg = Calculation::wrapResult(strtoupper($arg));
2300-
}
2301-
$testCondition = '=' . $arg . $condition;
2302-
if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2303-
if (($returnValue === null) || ($arg < $returnValue)) {
2304-
$returnValue = $arg;
2378+
2379+
// Loop through each arg and see if arguments and conditions are true
2380+
foreach ($minArgs as $index => $value) {
2381+
$valid = true;
2382+
2383+
foreach ($conditions as $cidx => $condition) {
2384+
$arg = $aArgsArray[$cidx][$index];
2385+
2386+
// Loop through arguments
2387+
if (!is_numeric($arg)) {
2388+
$arg = Calculation::wrapResult(strtoupper($arg));
2389+
}
2390+
$testCondition = '=' . $arg . $condition;
2391+
if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2392+
// Is not a value within our criteria
2393+
$valid = false;
2394+
2395+
break; // if false found, don't need to check other conditions
23052396
}
23062397
}
2398+
2399+
if ($valid) {
2400+
$returnValue = $returnValue === null ? $value : min($value, $returnValue);
2401+
}
23072402
}
23082403

2404+
// Return
23092405
return $returnValue;
23102406
}
23112407

src/PhpSpreadsheet/Calculation/functionlist.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,15 @@ LOWER
224224
MATCH
225225
MAX
226226
MAXA
227+
MAXIFS
227228
MDETERM
228229
MDURATION
229230
MEDIAN
230231
MID
231232
MIDB
232233
MIN
233234
MINA
235+
MINIFS
234236
MINUTE
235237
MINVERSE
236238
MIRR

0 commit comments

Comments
 (0)