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:
parent
dfd9c5bb3e
commit
ccebf0f288
|
@ -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 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 MATCH an error was appearing when comparing strings against 0 (always true)
|
||||||
|
- Fix VLOOKUP
|
||||||
- Fix return type hint
|
- Fix return type hint
|
||||||
|
|
||||||
## [1.6.0] - 2019-01-02
|
## [1.6.0] - 2019-01-02
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
class LookupRef
|
class LookupRef
|
||||||
|
@ -473,8 +474,9 @@ class LookupRef
|
||||||
$lookupValue = Functions::flattenSingleValue($lookupValue);
|
$lookupValue = Functions::flattenSingleValue($lookupValue);
|
||||||
$matchType = ($matchType === null) ? 1 : (int) Functions::flattenSingleValue($matchType);
|
$matchType = ($matchType === null) ? 1 : (int) Functions::flattenSingleValue($matchType);
|
||||||
|
|
||||||
|
$initialLookupValue = $lookupValue;
|
||||||
// MATCH is not case sensitive
|
// MATCH is not case sensitive
|
||||||
$lookupValue = strtolower($lookupValue);
|
$lookupValue = StringHelper::strToLower($lookupValue);
|
||||||
|
|
||||||
// Lookup_value type has to be number, text, or logical values
|
// Lookup_value type has to be number, text, or logical values
|
||||||
if ((!is_numeric($lookupValue)) && (!is_string($lookupValue)) && (!is_bool($lookupValue))) {
|
if ((!is_numeric($lookupValue)) && (!is_string($lookupValue)) && (!is_bool($lookupValue))) {
|
||||||
|
@ -502,7 +504,7 @@ class LookupRef
|
||||||
}
|
}
|
||||||
// Convert strings to lowercase for case-insensitive testing
|
// Convert strings to lowercase for case-insensitive testing
|
||||||
if (is_string($lookupArrayValue)) {
|
if (is_string($lookupArrayValue)) {
|
||||||
$lookupArray[$i] = strtolower($lookupArrayValue);
|
$lookupArray[$i] = StringHelper::strToLower($lookupArrayValue);
|
||||||
}
|
}
|
||||||
if (($lookupArrayValue === null) && (($matchType == 1) || ($matchType == -1))) {
|
if (($lookupArrayValue === null) && (($matchType == 1) || ($matchType == -1))) {
|
||||||
$lookupArray = array_slice($lookupArray, 0, $i - 1);
|
$lookupArray = array_slice($lookupArray, 0, $i - 1);
|
||||||
|
@ -665,7 +667,9 @@ class LookupRef
|
||||||
{
|
{
|
||||||
reset($a);
|
reset($a);
|
||||||
$firstColumn = key($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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,11 +715,14 @@ class LookupRef
|
||||||
uasort($lookup_array, ['self', 'vlookupSort']);
|
uasort($lookup_array, ['self', 'vlookupSort']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$lookupLower = StringHelper::strToLower($lookup_value);
|
||||||
$rowNumber = $rowValue = false;
|
$rowNumber = $rowValue = false;
|
||||||
foreach ($lookup_array as $rowKey => $rowData) {
|
foreach ($lookup_array as $rowKey => $rowData) {
|
||||||
|
$firstLower = StringHelper::strToLower($rowData[$firstColumn]);
|
||||||
|
|
||||||
// break if we have passed possible keys
|
// break if we have passed possible keys
|
||||||
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) ||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
// remember the last key, but only if datatypes match
|
// remember the last key, but only if datatypes match
|
||||||
|
@ -723,17 +730,15 @@ class LookupRef
|
||||||
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]))) {
|
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]))) {
|
||||||
if ($not_exact_match) {
|
if ($not_exact_match) {
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
$rowValue = $rowData[$firstColumn];
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} elseif ((strtolower($rowData[$firstColumn]) == strtolower($lookup_value))
|
} elseif (($firstLower == $lookupLower)
|
||||||
// Spreadsheets software returns first exact match,
|
// Spreadsheets software returns first exact match,
|
||||||
// we have sorted and we might have broken key orders
|
// we have sorted and we might have broken key orders
|
||||||
// we want the first one (by its initial index)
|
// we want the first one (by its initial index)
|
||||||
&& (($rowNumber == false) || ($rowKey < $rowNumber))
|
&& (($rowNumber == false) || ($rowKey < $rowNumber))
|
||||||
) {
|
) {
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
$rowValue = $rowData[$firstColumn];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,8 +791,11 @@ class LookupRef
|
||||||
// break if we have passed possible keys
|
// break if we have passed possible keys
|
||||||
$bothNumeric = is_numeric($lookup_value) && is_numeric($rowData);
|
$bothNumeric = is_numeric($lookup_value) && is_numeric($rowData);
|
||||||
$bothNotNumeric = !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) ||
|
if (($bothNumeric && $rowData > $lookup_value) ||
|
||||||
($bothNotNumeric && strtolower($rowData) > strtolower($lookup_value))) {
|
($bothNotNumeric && $rowDataLower > $lookupLower)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,7 +805,7 @@ class LookupRef
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} elseif (strtolower($rowData) === strtolower($lookup_value)
|
} elseif ($rowDataLower === $lookupLower
|
||||||
&& ($rowNumber === null || $rowKey < $rowNumber)
|
&& ($rowNumber === null || $rowKey < $rowNumber)
|
||||||
) {
|
) {
|
||||||
$rowNumber = $rowKey;
|
$rowNumber = $rowKey;
|
||||||
|
|
|
@ -106,6 +106,21 @@ return [
|
||||||
['author_100'],
|
['author_100'],
|
||||||
['author_101']
|
['author_101']
|
||||||
]
|
]
|
||||||
|
],
|
||||||
|
|
||||||
|
[
|
||||||
|
'#N/A',
|
||||||
|
'10y2',
|
||||||
|
[
|
||||||
|
['5y-1'],
|
||||||
|
['10y1'],
|
||||||
|
['10y2'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2.0],
|
||||||
|
[7.0],
|
||||||
|
[10.0],
|
||||||
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -311,5 +311,17 @@ return [
|
||||||
],
|
],
|
||||||
2,
|
2,
|
||||||
false
|
false
|
||||||
|
],
|
||||||
|
|
||||||
|
[
|
||||||
|
'#N/A',
|
||||||
|
'10y2',
|
||||||
|
[
|
||||||
|
['5y-1', 2.0],
|
||||||
|
['10y1', 7.0],
|
||||||
|
['10y2', 10.0]
|
||||||
|
],
|
||||||
|
2.0
|
||||||
]
|
]
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in New Issue