Skip to content

Commit fa5ab52

Browse files
committed
VLOOKUP Handling of Strings and Number
Fix #1402, another in our "better late than never" series. Stalebot closed it in May 2020, and I have reopened it. @ljcag submitted the issue, and PR #1403 to resolve it, also marked stale. That change is more complicated than this one. Since there were no tests in that PR, and since this PR solves the original problem (test added), I will stick with this version, but will continue to study 1403 before merging. This is also another in the "Excel doesn't believe in complete documentation" series. (See issue #3802 for a similar example.) Nothing that I have seen in the documentation suggests that a number will not match a numeric string, but that seems clearly to be the case. Despite the lack of complete documentation, PhpSpreadsheet implemented VLOOKUP with that in mind. Unfortunately, it did so by using `is_numeric` on its comparands, and so treats numeric strings as if they were numbers. This PR replaces those tests with `is_int() || is_float()`. The earlier PR used `is_string()` instead as a proxy for "not numeric" but that required other changes.
1 parent f7c183b commit fa5ab52

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ private static function vLookupSearch(mixed $lookupValue, array $lookupArray, $c
8888

8989
$rowNumber = null;
9090
foreach ($lookupArray as $rowKey => $rowData) {
91-
$bothNumeric = is_numeric($lookupValue) && is_numeric($rowData[$column]);
92-
$bothNotNumeric = !is_numeric($lookupValue) && !is_numeric($rowData[$column]);
91+
$bothNumeric = self::numeric($lookupValue) && self::numeric($rowData[$column]);
92+
$bothNotNumeric = !self::numeric($lookupValue) && !self::numeric($rowData[$column]);
9393
$cellDataLower = StringHelper::strToLower((string) $rowData[$column]);
9494

9595
// break if we have passed possible keys
@@ -114,4 +114,9 @@ private static function vLookupSearch(mixed $lookupValue, array $lookupArray, $c
114114

115115
return $rowNumber;
116116
}
117+
118+
private static function numeric(mixed $value): bool
119+
{
120+
return is_int($value) || is_float($value);
121+
}
117122
}

tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/VLookupTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
66

77
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
8+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
89
use PhpOffice\PhpSpreadsheet\Spreadsheet;
910
use PHPUnit\Framework\TestCase;
1011

@@ -78,4 +79,24 @@ public static function providerVLookupArray(): array
7879
],
7980
];
8081
}
82+
83+
public function testIssue1402(): void
84+
{
85+
$spreadsheet = new Spreadsheet();
86+
$worksheet = $spreadsheet->getActiveSheet();
87+
88+
$worksheet->setCellValueExplicit('A1', 1, DataType::TYPE_STRING);
89+
$worksheet->setCellValue('B1', 'Text Nr 1');
90+
$worksheet->setCellValue('A2', 2);
91+
$worksheet->setCellValue('B2', 'Numeric result');
92+
$worksheet->setCellValueExplicit('A3', 2, DataType::TYPE_STRING);
93+
$worksheet->setCellValue('B3', 'Text Nr 2');
94+
$worksheet->setCellValueExplicit('A4', 2, DataType::TYPE_STRING);
95+
$worksheet->setCellValue('B4', '=VLOOKUP(A4,$A$1:$B$3,2,0)');
96+
self::assertSame('Text Nr 2', $worksheet->getCell('B4')->getCalculatedValue());
97+
$worksheet->setCellValue('A5', 2);
98+
$worksheet->setCellValue('B5', '=VLOOKUP(A5,$A$1:$B$3,2,0)');
99+
self::assertSame('Numeric result', $worksheet->getCell('B5')->getCalculatedValue());
100+
$spreadsheet->disconnectWorksheets();
101+
}
81102
}

0 commit comments

Comments
 (0)