diff options
Diffstat (limited to 'sc/source/core/data/dociter.cxx')
-rw-r--r-- | sc/source/core/data/dociter.cxx | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index 3277d3692433..565565f00a11 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -1245,6 +1245,17 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol, SCROW& nFoundRow, bool bSearchForEqualAfterMismatch, bool bIgnoreMismatchOnLeadingStringsP ) { + // Set and automatically reset mpParam->mbRangeLookup when returning. We + // could use comphelper::FlagRestorationGuard, but really, that one is + // overengineered for this simple purpose here. + struct BoolResetter + { + bool& mr; + bool mb; + BoolResetter( bool& r, bool b ) : mr(r), mb(r) { r = b; } + ~BoolResetter() { mr = mb; } + } aRangeLookupResetter( mpParam->mbRangeLookup, true); + nFoundCol = MAXCOL+1; nFoundRow = MAXROW+1; SetStopOnMismatch( true ); // assume sorted keys @@ -1253,7 +1264,22 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol, bool bRegExp = mpParam->bRegExp && mpParam->GetEntry(0).GetQueryItem().meType == ScQueryEntry::ByString; bool bBinary = !bRegExp && mpParam->bByRow && (mpParam->GetEntry(0).eOp == SC_LESS_EQUAL || mpParam->GetEntry(0).eOp == SC_GREATER_EQUAL); - if (bBinary ? (BinarySearch() ? GetThis() : 0) : GetFirst()) + bool bFound = false; + if (bBinary) + { + if (BinarySearch()) + { + // BinarySearch() already positions correctly and only needs real + // query comparisons afterwards, skip the verification check below. + mpParam->mbRangeLookup = false; + bFound = GetThis(); + } + } + else + { + bFound = GetFirst(); + } + if (bFound) { // First equal entry or last smaller than (greater than) entry. PositionType aPosSave; @@ -1272,9 +1298,43 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol, { // Step back to last in range and adjust position markers for // GetNumberFormat() or similar. + SCCOL nColDiff = nCol - nFoundCol; nCol = nFoundCol; nRow = nFoundRow; maCurPos = aPosSave; + if (mpParam->mbRangeLookup) + { + // Verify that the found entry does not only fulfill the range + // lookup but also the real query, i.e. not numeric was found + // if query is ByString and vice versa. + mpParam->mbRangeLookup = false; + // Step back the last field advance if GetNext() did one. + if (bAdvanceQuery && nColDiff) + { + SCSIZE nEntries = mpParam->GetEntryCount(); + for (SCSIZE j=0; j < nEntries; ++j) + { + ScQueryEntry& rEntry = mpParam->GetEntry( j ); + if (rEntry.bDoQuery) + { + if (rEntry.nField - nColDiff >= 0) + rEntry.nField -= nColDiff; + else + { + assert(!"FindEqualOrSortedLastInRange: rEntry.nField -= nColDiff < 0"); + } + } + else + break; // for + } + } + // Check it. + if (!GetThis()) + { + nFoundCol = MAXCOL+1; + nFoundRow = MAXROW+1; + } + } } } if ( IsEqualConditionFulfilled() ) |