Fix VLOOKUP whose return was impacted by order for a $not_exact_match (#854)

* Highlight VLOOKUP bug with a new test

* Remove useless statements + fix VLOOKUP bug

Please not that we have still inconsistencies in Excel (See LOOKUP and
VLOOKUP.php test files)

* Base strtolower on our StringHelper in LookupRef
This commit is contained in:
Fräntz Miccoli 2019-04-15 21:37:23 +02:00 committed by Mark Baker
parent dfd9c5bb3e
commit ccebf0f288
4 changed files with 45 additions and 9 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
- Fix handling for escaped enclosures and new lines in CSV Separator Inference
- Fix MATCH an error was appearing when comparing strings against 0 (always true)
- Fix VLOOKUP
- Fix return type hint
## [1.6.0] - 2019-01-02

View File

@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class LookupRef
@ -473,8 +474,9 @@ class LookupRef
$lookupValue = Functions::flattenSingleValue($lookupValue);
$matchType = ($matchType === null) ? 1 : (int) Functions::flattenSingleValue($matchType);
$initialLookupValue = $lookupValue;
// MATCH is not case sensitive
$lookupValue = strtolower($lookupValue);
$lookupValue = StringHelper::strToLower($lookupValue);
// Lookup_value type has to be number, text, or logical values
if ((!is_numeric($lookupValue)) && (!is_string($lookupValue)) && (!is_bool($lookupValue))) {
@ -502,7 +504,7 @@ class LookupRef
}
// Convert strings to lowercase for case-insensitive testing
if (is_string($lookupArrayValue)) {
$lookupArray[$i] = strtolower($lookupArrayValue);
$lookupArray[$i] = StringHelper::strToLower($lookupArrayValue);
}
if (($lookupArrayValue === null) && (($matchType == 1) || ($matchType == -1))) {
$lookupArray = array_slice($lookupArray, 0, $i - 1);
@ -665,7 +667,9 @@ class LookupRef
{
reset($a);
$firstColumn = key($a);
if (($aLower = strtolower($a[$firstColumn])) == ($bLower = strtolower($b[$firstColumn]))) {
$aLower = StringHelper::strToLower($a[$firstColumn]);
$bLower = StringHelper::strToLower($b[$firstColumn]);
if ($aLower == $bLower) {
return 0;
}
@ -711,11 +715,14 @@ class LookupRef
uasort($lookup_array, ['self', 'vlookupSort']);
}
$lookupLower = StringHelper::strToLower($lookup_value);
$rowNumber = $rowValue = false;
foreach ($lookup_array as $rowKey => $rowData) {
$firstLower = StringHelper::strToLower($rowData[$firstColumn]);
// break if we have passed possible keys
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) ||
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)))) {
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && ($firstLower > $lookupLower))) {
break;
}
// remember the last key, but only if datatypes match
@ -723,17 +730,15 @@ class LookupRef
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]))) {
if ($not_exact_match) {
$rowNumber = $rowKey;
$rowValue = $rowData[$firstColumn];
continue;
} elseif ((strtolower($rowData[$firstColumn]) == strtolower($lookup_value))
} elseif (($firstLower == $lookupLower)
// Spreadsheets software returns first exact match,
// we have sorted and we might have broken key orders
// we want the first one (by its initial index)
&& (($rowNumber == false) || ($rowKey < $rowNumber))
) {
$rowNumber = $rowKey;
$rowValue = $rowData[$firstColumn];
}
}
}
@ -786,8 +791,11 @@ class LookupRef
// break if we have passed possible keys
$bothNumeric = is_numeric($lookup_value) && is_numeric($rowData);
$bothNotNumeric = !is_numeric($lookup_value) && !is_numeric($rowData);
$lookupLower = StringHelper::strToLower($lookup_value);
$rowDataLower = StringHelper::strToLower($rowData);
if (($bothNumeric && $rowData > $lookup_value) ||
($bothNotNumeric && strtolower($rowData) > strtolower($lookup_value))) {
($bothNotNumeric && $rowDataLower > $lookupLower)) {
break;
}
@ -797,7 +805,7 @@ class LookupRef
$rowNumber = $rowKey;
continue;
} elseif (strtolower($rowData) === strtolower($lookup_value)
} elseif ($rowDataLower === $lookupLower
&& ($rowNumber === null || $rowKey < $rowNumber)
) {
$rowNumber = $rowKey;

View File

@ -106,6 +106,21 @@ return [
['author_100'],
['author_101']
]
],
[
'#N/A',
'10y2',
[
['5y-1'],
['10y1'],
['10y2'],
],
[
[2.0],
[7.0],
[10.0],
],
]
];

View File

@ -311,5 +311,17 @@ return [
],
2,
false
],
[
'#N/A',
'10y2',
[
['5y-1', 2.0],
['10y1', 7.0],
['10y2', 10.0]
],
2.0
]
];