Fix CSE array formula evaluation: count booleans in arithmetic operators#1720
Merged
tonyqus merged 2 commits intoMar 10, 2026
Merged
Conversation
The MutableValueCollector in TwoOperandNumericOperation's ArrayEval used
isReferenceBoolCounted=false, which silently dropped BoolEval values from
area references during array arithmetic. This caused CSE formulas like
{INDEX(...,MATCH(1,($range=val1)*($range=val2),0),col)} to fail because
the boolean arrays from comparisons were collected as empty/wrong-sized
arrays, cascading to #VALUE! errors.
Fix: Set isReferenceBoolCounted=true so boolean values from relational
operators (=, <, >, etc.) are properly coerced to 0/1 during array
multiplication.
Also: Handle ErrorEval in Match.EvaluateLookupRange() gracefully instead
of throwing a raw Exception.
Tested against 8 Swyfft rater workbooks (56 total available):
- Before: 158+ CSE array formula failures, cascading exceptions
- After: 0 CSE failures, 98.4-100% formula evaluation success rate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five tests covering the fix for boolean array handling in CSE formulas: 1. TestIndexMatchWithBooleanArrayMultiplication - End-to-end test of the INDEX/MATCH pattern with boolean array multiplication (the exact pattern used in real-world rater workbooks) 2. TestBooleanArrayMultiplicationDifferentMatches - Verifies correct results for different lookup value combinations 3. TestBooleanArrayMultiplicationNoMatch - Verifies #N/A (not #VALUE!) when no match exists 4. TestMatchWithErrorEvalInLookupRange - Verifies Match handles ErrorEval gracefully instead of throwing raw Exception 5. TestSimpleBooleanArrayMultiplication - Direct test of element-wise multiplication of two boolean arrays Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Member
|
Thank you for the detailed description. |
Member
|
LGTM |
Member
|
I glance at your Github profile and found that we have something in common. My last company is VRSK (insurance industry company) and the HQ of VRSK is also in NJ. What a coincidence 👯♂️ |
Contributor
Author
Oh, interesting. Yeah, probably like most insurance companies, we use Verisk for a whole bunch of things. Swyfft is almost entirely remote (I'm in the Seattle area), but our headquarters are in New Jersey. |
This was referenced Apr 6, 2026
This was referenced Apr 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
CSE (Ctrl+Shift+Enter) array formulas that use the common pattern of boolean array multiplication fail with
#VALUE!errors:The
=comparison operators correctly produceCacheAreaEvalarrays ofBoolEvalvalues (TRUE/FALSE) when in array mode. However, when the*operator then tries to multiply these arrays element-wise, all the boolean values are silently dropped, producing empty/wrong-sized arrays that cascade to#VALUE!errors.Root Cause
In
TwoOperandNumericOperation.ArrayEval, theMutableValueCollectoris constructed withisReferenceBoolCounted=false:When
CollectValuesiterates over aCacheAreaEval(which is aTwoDEval), it callsCollectValue(ve, isViaReference: true, temp). WithisReferenceBoolCounted=false, allBoolEvalvalues are silently skipped inMultiOperandNumericFunction.CollectValue():This is correct behavior for SUM-like functions (where booleans in ranges are ignored per Excel spec), but wrong for arithmetic operators in array mode, where booleans must be coerced to 0/1.
Fix
Change
isReferenceBoolCountedfromfalsetotrueinTwoOperandNumericOperation.ArrayEval:Also added
ErrorEvalhandling inMatch.EvaluateLookupRange()so that upstream errors propagate asEvaluationExceptionrather than throwing a rawException.Testing
New unit tests (
TestCseArrayBooleanArithmetic.cs— 5 tests):TestIndexMatchWithBooleanArrayMultiplication— End-to-end test of the{INDEX(range, MATCH(1, (col1=val1)*(col2=val2), 0))}pattern, the exact CSE formula used in real-world workbooksTestBooleanArrayMultiplicationDifferentMatches— Verifies correct results across multiple lookup value combinationsTestBooleanArrayMultiplicationNoMatch— Confirms#N/A(not#VALUE!) when no match existsTestMatchWithErrorEvalInLookupRange— Validates thatMatch.EvaluateLookupRangehandlesErrorEvalgracefully instead of throwing a rawExceptionTestSimpleBooleanArrayMultiplication— Direct test of element-wise multiplication of two boolean arraysAll existing NPOI tests pass (4,572 passed across net8.0 and net472, 0 failed).
Real-world validation against 56 Excel rater workbooks containing 460,000+ formula cells and 1,228 CSE array formula cells:
#VALUE!exceptions