Countif strict comparison (#1078)

* Stricter-typed comparison testing in COUNTIF() and COUNTIFS() evaluation [Issue #1046](https://github.com/PHPOffice/PhpSpreadsheet/issues/1046)

* Codestyle

* Codestyle

* Codestyle in tests
This commit is contained in:
Mark Baker 2019-07-14 16:22:31 +02:00 committed by GitHub
parent 36135a4c05
commit a91acec5d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 21 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Fixed ### Fixed
- Stricter-typed comparison testing in COUNTIF() and COUNTIFS() evaluation [Issue #1046](https://github.com/PHPOffice/PhpSpreadsheet/issues/1046)
- COUPNUM should not return zero when settlement is in the last period - [Issue #1020](https://github.com/PHPOffice/PhpSpreadsheet/issues/1020) and [PR #1021](https://github.com/PHPOffice/PhpSpreadsheet/pull/1021) - COUPNUM should not return zero when settlement is in the last period - [Issue #1020](https://github.com/PHPOffice/PhpSpreadsheet/issues/1020) and [PR #1021](https://github.com/PHPOffice/PhpSpreadsheet/pull/1021)
## [1.8.2] - 2019-07-08 ## [1.8.2] - 2019-07-08

View File

@ -280,7 +280,9 @@ class Functions
preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches); preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches);
list(, $operator, $operand) = $matches; list(, $operator, $operand) = $matches;
if (!is_numeric($operand)) { if (is_numeric(trim($operand, '"'))) {
$operand = trim($operand, '"');
} elseif (!is_numeric($operand)) {
$operand = str_replace('"', '""', $operand); $operand = str_replace('"', '""', $operand);
$operand = Calculation::wrapResult(strtoupper($operand)); $operand = Calculation::wrapResult(strtoupper($operand));
} }

View File

@ -1119,10 +1119,16 @@ class Statistical
$aArgs = Functions::flattenArray($aArgs); $aArgs = Functions::flattenArray($aArgs);
$condition = Functions::ifCondition($condition); $condition = Functions::ifCondition($condition);
$conditionIsNumeric = strpos($condition, '"') === false;
// Loop through arguments // Loop through arguments
foreach ($aArgs as $arg) { foreach ($aArgs as $arg) {
if (!is_numeric($arg)) { if (!is_numeric($arg)) {
if ($conditionIsNumeric) {
continue;
}
$arg = Calculation::wrapResult(strtoupper($arg)); $arg = Calculation::wrapResult(strtoupper($arg));
} elseif (!$conditionIsNumeric) {
continue;
} }
$testCondition = '=' . $arg . $condition; $testCondition = '=' . $arg . $condition;
if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
@ -1172,11 +1178,21 @@ class Statistical
$valid = true; $valid = true;
foreach ($conditions as $cidx => $condition) { foreach ($conditions as $cidx => $condition) {
$conditionIsNumeric = strpos($condition, '"') === false;
$arg = $aArgsArray[$cidx][$index]; $arg = $aArgsArray[$cidx][$index];
// Loop through arguments // Loop through arguments
if (!is_numeric($arg)) { if (!is_numeric($arg)) {
if ($conditionIsNumeric) {
$valid = false;
break; // if false found, don't need to check other conditions
}
$arg = Calculation::wrapResult(strtoupper($arg)); $arg = Calculation::wrapResult(strtoupper($arg));
} elseif (!$conditionIsNumeric) {
$valid = false;
break; // if false found, don't need to check other conditions
} }
$testCondition = '=' . $arg . $condition; $testCondition = '=' . $arg . $condition;
if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) {

View File

@ -13,6 +13,22 @@ class StatisticalTest extends TestCase
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL); Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
} }
/**
* @dataProvider providerCOUNTIF
*
* @param mixed $expectedResult
*/
public function testCOUNTIF($expectedResult, ...$args)
{
$result = Statistical::COUNTIF(...$args);
self::assertEquals($expectedResult, $result, '', 1E-12);
}
public function providerCOUNTIF()
{
return require 'data/Calculation/Statistical/COUNTIF.php';
}
/** /**
* @dataProvider providerCOUNTIFS * @dataProvider providerCOUNTIFS
* *

View File

@ -0,0 +1,34 @@
<?php
return [
[
2,
['apples', 'oranges', 'peaches', 'apples'],
'apples',
],
[
2,
['ApPlEs', 'oranges', 'peaches', 'APPles'],
'aPpLeS',
],
[
2,
[32, 54, 75, 86],
'>55',
],
[
3,
[32, 54, 75, 86],
'<=75',
],
[
2,
[6, 3, 4, 'X', ''],
'<=4',
],
[
2,
[6, 3, 4, 'X', ''],
'<="4"',
],
];

View File

@ -3,30 +3,22 @@
return [ return [
[ [
2, 2,
[ ['Y', 'Y', 'N'],
['Y'],
['Y'],
['N'],
],
'=Y', '=Y',
], ],
[ [
3, 3,
[ ['A', 'B', 'C', 'B', 'B'],
['A'],
['B'],
['C'],
['B'],
['B'],
],
'=B',
[
['C'],
['B'],
['A'],
['B'],
['B'],
],
'=B', '=B',
], ],
[
3,
['C', 'B', 'A', 'B', 'B'],
'=B',
],
[
2,
[1, 2, 3, 'B', '', false],
'<=2',
],
]; ];