Skip to content

Commit a69c360

Browse files
committed
Exact match in VLOOKUP now returns first match (it was inconsistent with
spreadsheet software before)
1 parent f0e6940 commit a69c360

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
1616

1717
- Improve XLSX parsing speed if no readFilter is applied - [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772)
1818
- Fix column names if read filter calls in XLSX reader skip columns - [#777](https://github.com/PHPOffice/PhpSpreadsheet/pull/777)
19+
- Fix VLOOKUP with exact matches
1920

2021
## [1.5.2] - 2018-11-25
2122

src/PhpSpreadsheet/Calculation/LookupRef.php

+15-6
Original file line numberDiff line numberDiff line change
@@ -709,23 +709,32 @@ public static function VLOOKUP($lookup_value, $lookup_array, $index_number, $not
709709

710710
$rowNumber = $rowValue = false;
711711
foreach ($lookup_array as $rowKey => $rowData) {
712+
// break if we have passed possible keys
712713
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) ||
713714
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)))) {
714715
break;
715716
}
716717
// remember the last key, but only if datatypes match
717718
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn])) ||
718719
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]))) {
719-
$rowNumber = $rowKey;
720-
$rowValue = $rowData[$firstColumn];
720+
if ($not_exact_match) {
721+
$rowNumber = $rowKey;
722+
$rowValue = $rowData[$firstColumn];
723+
724+
continue;
725+
} elseif ((strtolower($rowData[$firstColumn]) == strtolower($lookup_value))
726+
// Spreadsheets software returns first exact match,
727+
// we have sorted and we might have broken key orders
728+
// we want the first one (by its initial index)
729+
&& (($rowNumber == false) || ($rowKey < $rowNumber))
730+
) {
731+
$rowNumber = $rowKey;
732+
$rowValue = $rowData[$firstColumn];
733+
}
721734
}
722735
}
723736

724737
if ($rowNumber !== false) {
725-
if ((!$not_exact_match) && ($rowValue != $lookup_value)) {
726-
// if an exact match is required, we have what we need to return an appropriate response
727-
return Functions::NA();
728-
}
729738
// otherwise return the appropriate value
730739
return $lookup_array[$rowNumber][$returnColumn];
731740
}

tests/data/Calculation/LookupRef/VLOOKUP.php

+21
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,25 @@
291291
2,
292292
true,
293293
],
294+
[
295+
5,
296+
'x',
297+
[
298+
[
299+
'Selection column',
300+
'Value to retrieve',
301+
],
302+
['0', 1],
303+
['0', 2],
304+
['0', 3],
305+
['0', 4],
306+
['x', 5],
307+
['x', 6],
308+
['x', 7],
309+
['x', 8],
310+
['x', 9],
311+
],
312+
2,
313+
false
314+
]
294315
];

0 commit comments

Comments
 (0)