Fix VLOOKUP/HLOOKUP/MATCH type coercion to match Excel behavior#1721
Fix VLOOKUP/HLOOKUP/MATCH type coercion to match Excel behavior#1721ken-swyfft wants to merge 1 commit into
Conversation
Excel coerces types during lookup comparisons — string "10" matches numeric key 10, and vice versa. NPOI previously returned TypeMismatch for all cross-type comparisons, causing #N/A errors where Excel succeeds. Add TryCoercedCompare() virtual method to LookupValueComparerBase with overrides in StringLookupComparer and NumberLookupComparer that attempt numeric parsing before falling back to TypeMismatch. Includes 7 new tests covering exact match, approximate match, decimal values, non-numeric strings, same-type comparisons, and HLOOKUP. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Closing to deal with some additional issues. |
|
@tonyqus - I think this can stay closed. If you're wondering what was going on, I was working with Claude to fix some issues in how our solution is using NPOI to read some complex Excel files. Claude convinced itself that it needed this change to make our spreadsheets work, and it was fairly convincing, and it did in fact fix our tests, so I had it create this draft PR. But in looking around at it more, it became clear that this is not in fact how Excel handles |
|
Thank you for clarification of your use case. NPOI embeded formula evaulation engine is a simulation of Excel formula calculation. It's hard to say all the behavior is same and also some functions may have not been implemented in NPOI yet. However, NPOI can be much faster than Excel COM because Excel COM is mainly an automation based on Microsoft Excel UI running on backend. Since I'm also from Insurance industry, I do understand the complexity of your spreadsheets. It's a good chance to test if NPOI can meet all your production needs. |
Background
As background, my company (Swyfft) decided to try migrating its solution from using Excel COM to interact with some 50+ very large, very complex spreadsheets, to using NPOI. Given the complexity of these spreadsheets, the conversion process worked much better than we expected, but we discovered two issues that seemed to require some changes/fixes to NPOI itself. The first was #1720; this is the second. I believe that this is technically a breaking change, in that it does change behavior, but it moves NPOI in the direction of behaving as Excel does, so it seemed appropriate.
Summary
Excel's VLOOKUP, HLOOKUP, and MATCH functions perform implicit type coercion when comparing values — for example,
1 = TRUEevaluates toTRUE, and the numeric string"123"matches the number123. NPOI's formula evaluator currently does strict type comparison, causing these lookups to fail with#N/Awhen the lookup value and table key have different types but equivalent values.This PR fixes type coercion in
LookupUtilsto match Excel's behavior:TRUEmatches1,FALSEmatches0(and vice versa)123matches"123")TRUE/FALSEmatch"TRUE"/"FALSE"(case-insensitive)0in lookupsChanges
LookupUtils.cs: AddedCompareWithTypeCoercionmethod used by exact-match lookups, andResolveValueForBinarySearchfor sorted-range approximate-match lookupsTestVlookupTypeCoercion.cs: 302 lines of tests covering all type coercion scenariosContext
This was discovered while replacing Excel COM Interop with NPOI's formula evaluator in a production application. The rater workbooks use patterns like
IF(UseSar=TRUE, "", VLOOKUP(...))whereUseSaris a boolean cell — strict comparison caused the IF to take the wrong branch.This builds on #1720 (CSE array boolean arithmetic fix) which was merged previously.