Prepare search code for other functions than MATCH and XLOOKUP.
Purpose is to use one set of code for all similar lookup functions, as they now each have their own code, which is largely identical. Next steps will be to make the code used by XLOOKUP and MATCH work with each similar lookup function. This patch just changes the interface to accomodate other functions. Change-Id: I6950aa69404f3eb8acbf2d55e247058f3e798814 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163230 Tested-by: Jenkins Reviewed-by: Balazs Varga <balazs.varga.extern@allotropia.de>
This commit is contained in:
committed by
Balazs Varga
parent
b508e4f081
commit
88ba9fab08
@@ -183,7 +183,7 @@ protected:
|
||||
sal_uInt8 nSortedBinarySearch;
|
||||
bool bAdvanceQuery;
|
||||
bool bIgnoreMismatchOnLeadingStrings;
|
||||
bool bXLookUp;
|
||||
sal_uInt16 nSearchOpCode;
|
||||
SCCOL nBestFitCol;
|
||||
SCROW nBestFitRow;
|
||||
|
||||
@@ -276,8 +276,8 @@ public:
|
||||
nSearchbAscd : (nSearchMode == -2 ? nSearchbDesc : nBinarySearchDisabled));
|
||||
}
|
||||
|
||||
void SetXlookupMode( bool bVal )
|
||||
{ bXLookUp = bVal; }
|
||||
void SetLookupMode( sal_uInt16 nVal )
|
||||
{ nSearchOpCode = nVal; }
|
||||
};
|
||||
|
||||
|
||||
@@ -325,7 +325,7 @@ class ScQueryCellIterator
|
||||
using Base::getThisResult;
|
||||
using Base::nBestFitCol;
|
||||
using Base::nBestFitRow;
|
||||
using Base::bXLookUp;
|
||||
using Base::nSearchOpCode;
|
||||
|
||||
bool GetThis();
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ ScQueryCellIteratorBase< accessType, queryType >::ScQueryCellIteratorBase(ScDocu
|
||||
, nSortedBinarySearch( nBinarySearchDisabled )
|
||||
, bAdvanceQuery( false )
|
||||
, bIgnoreMismatchOnLeadingStrings( false )
|
||||
, bXLookUp( false )
|
||||
, nSearchOpCode( SC_OPCODE_NONE )
|
||||
, nBestFitCol(SCCOL_MAX)
|
||||
, nBestFitRow(SCROW_MAX)
|
||||
{
|
||||
@@ -207,7 +207,8 @@ void ScQueryCellIteratorBase< accessType, queryType >::PerformQuery()
|
||||
return;
|
||||
|
||||
// XLookUp: Forward/asc/backward/desc search for best fit value, except if we have an exact match
|
||||
if (bXLookUp && (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL) &&
|
||||
if (nSearchOpCode == SC_OPCODE_X_LOOKUP &&
|
||||
(rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL) &&
|
||||
(nBestFitCol != nCol || nBestFitRow != nRow))
|
||||
{
|
||||
bool bNumSearch = rItem.meType == ScQueryEntry::ByValue && aCell.hasNumeric();
|
||||
@@ -315,7 +316,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos()
|
||||
// is the one after it.
|
||||
lastRow = nRow;
|
||||
// BinarySearch() looks for the first match for XLOOKUP
|
||||
if (!bXLookUp)
|
||||
if (nSearchOpCode != SC_OPCODE_X_LOOKUP)
|
||||
{
|
||||
ScQueryOp saveOp = op;
|
||||
op = SC_LESS;
|
||||
@@ -341,7 +342,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos()
|
||||
if( BinarySearch( nCol ))
|
||||
lastRow = nRow;
|
||||
}
|
||||
AccessBase::InitPosFinish(beforeRow, lastRow, bXLookUp);
|
||||
AccessBase::InitPosFinish(beforeRow, lastRow, (nSearchOpCode == SC_OPCODE_X_LOOKUP));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +546,9 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch( SCCOL col,
|
||||
{
|
||||
if (fLastInRangeValue <= nCellVal)
|
||||
{
|
||||
if (bXLookUp && nSortedBinarySearch != nSearchbDesc && fLastInRangeValue == nCellVal && aIndexer.getLowIndex() != i)
|
||||
if (nSearchOpCode == SC_OPCODE_X_LOOKUP &&
|
||||
nSortedBinarySearch != nSearchbDesc &&
|
||||
fLastInRangeValue == nCellVal && aIndexer.getLowIndex() != i)
|
||||
bDone = true;
|
||||
else
|
||||
{
|
||||
@@ -593,7 +596,9 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch( SCCOL col,
|
||||
aCellStr);
|
||||
if (nTmp <= 0)
|
||||
{
|
||||
if (bXLookUp && nSortedBinarySearch != nSearchbDesc && nTmp == 0 && aIndexer.getLowIndex() != i)
|
||||
if (nSearchOpCode == SC_OPCODE_X_LOOKUP &&
|
||||
nSortedBinarySearch != nSearchbDesc &&
|
||||
nTmp == 0 && aIndexer.getLowIndex() != i)
|
||||
bDone = true;
|
||||
else
|
||||
{
|
||||
@@ -667,7 +672,8 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch( SCCOL col,
|
||||
{
|
||||
found = i;
|
||||
nLastInRange = i;
|
||||
if (bXLookUp && (nSortedBinarySearch == nSearchbAscd && (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_EQUAL)))
|
||||
if (nSearchOpCode == SC_OPCODE_X_LOOKUP && (nSortedBinarySearch == nSearchbAscd &&
|
||||
(rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_EQUAL)))
|
||||
bDone = true;
|
||||
else // But keep searching to find the last matching one.
|
||||
nLo = nMid + 1;
|
||||
@@ -747,7 +753,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo
|
||||
nFoundCol = rDoc.MaxCol()+1;
|
||||
nFoundRow = rDoc.MaxRow()+1;
|
||||
|
||||
if (bXLookUp && nSortedBinarySearch == nBinarySearchDisabled)
|
||||
if (nSearchOpCode == SC_OPCODE_X_LOOKUP && nSortedBinarySearch == nBinarySearchDisabled)
|
||||
SetStopOnMismatch( false ); // assume not sorted keys for XLookup
|
||||
else
|
||||
SetStopOnMismatch( true ); // assume sorted keys
|
||||
@@ -762,7 +768,8 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo
|
||||
(maParam.GetEntry(0).eOp == SC_LESS_EQUAL || maParam.GetEntry(0).eOp == SC_GREATER_EQUAL);
|
||||
|
||||
// assume not sorted properly if we are using XLookup with forward or backward search
|
||||
if (bBinary && bXLookUp && nSortedBinarySearch == nBinarySearchDisabled)
|
||||
if (bBinary && nSearchOpCode == SC_OPCODE_X_LOOKUP &&
|
||||
nSortedBinarySearch == nBinarySearchDisabled)
|
||||
bBinary = false;
|
||||
|
||||
bool bFound = false;
|
||||
@@ -855,7 +862,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( IsEqualConditionFulfilled() && !bXLookUp )
|
||||
if ( IsEqualConditionFulfilled() && nSearchOpCode != SC_OPCODE_X_LOOKUP )
|
||||
{
|
||||
// Position on last equal entry, except for XLOOKUP,
|
||||
// which looking for the first equal entry
|
||||
|
||||
@@ -61,8 +61,8 @@ enum SearchMode{ searchfwd=1, searchrev=-1, searchbasc=2, searchbdesc=-2 };
|
||||
struct VectorSearchArguments
|
||||
{
|
||||
// struct contains the contents of the function arguments
|
||||
// Struct owner, ScMatch or ScXLookup
|
||||
bool isXLookup = false;
|
||||
// OpCode of struct owner
|
||||
sal_uInt16 nSearchOpCode = SC_OPCODE_NONE;
|
||||
|
||||
// match mode (common, enum values are from XLOOKUP)
|
||||
// optional 5th argument to set match mode
|
||||
@@ -541,7 +541,7 @@ private:
|
||||
inline void TreatDoubleError( double& rVal );
|
||||
// Lookup using ScLookupCache, @returns true if found and result address
|
||||
bool LookupQueryWithCache( ScAddress & o_rResultPos, const ScQueryParam & rParam,
|
||||
const ScComplexRefData* refData, sal_Int8 nSearchMode, bool bXlookupMode ) const;
|
||||
const ScComplexRefData* refData, sal_Int8 nSearchMode, sal_Int16 nOpCode ) const;
|
||||
|
||||
void ScIfJump();
|
||||
void ScIfError( bool bNAonly );
|
||||
|
||||
@@ -4920,7 +4920,7 @@ void ScInterpreter::ScMatch()
|
||||
return;
|
||||
|
||||
VectorSearchArguments vsa;
|
||||
vsa.isXLookup = false;
|
||||
vsa.nSearchOpCode = SC_OPCODE_MATCH;
|
||||
|
||||
// get match mode
|
||||
double fType = ( nParamCount == 3 ? GetDouble() : 1.0 );
|
||||
@@ -7545,7 +7545,8 @@ void ScInterpreter::CalculateLookup(bool bHLookup)
|
||||
else
|
||||
{
|
||||
ScAddress aResultPos( nCol1, nRow1, nTab1);
|
||||
bFound = LookupQueryWithCache( aResultPos, aParam, refData, 0, false );
|
||||
bFound = LookupQueryWithCache( aResultPos, aParam, refData, 0,
|
||||
( bHLookup ? SC_OPCODE_H_LOOKUP : SC_OPCODE_V_LOOKUP ) );
|
||||
nRow = aResultPos.Row();
|
||||
nCol = nSpIndex;
|
||||
}
|
||||
@@ -7638,7 +7639,7 @@ void ScInterpreter::ScXLookup()
|
||||
return;
|
||||
|
||||
VectorSearchArguments vsa;
|
||||
vsa.isXLookup = true;
|
||||
vsa.nSearchOpCode = SC_OPCODE_X_LOOKUP;
|
||||
|
||||
if ( nParamCount == 6 )
|
||||
{
|
||||
@@ -10663,7 +10664,7 @@ bool ScInterpreter::SearchRangeForValue( VectorSearchArguments& vsa, ScQueryPara
|
||||
rParam.bByRow = true;
|
||||
ScAddress aResultPos( vsa.nCol1, vsa.nRow1, vsa.nTab1 );
|
||||
const ScComplexRefData* refData = nullptr;
|
||||
if ( LookupQueryWithCache( aResultPos, rParam, refData, vsa.eSearchMode, vsa.isXLookup ) )
|
||||
if ( LookupQueryWithCache( aResultPos, rParam, refData, vsa.eSearchMode, vsa.nSearchOpCode ) )
|
||||
vsa.nHitIndex = aResultPos.Row() - vsa.nRow1 + 1;
|
||||
}
|
||||
else
|
||||
@@ -10674,7 +10675,7 @@ bool ScInterpreter::SearchRangeForValue( VectorSearchArguments& vsa, ScQueryPara
|
||||
ScQueryCellIteratorDirect aCellIter(mrDoc, mrContext, vsa.nTab1, rParam, false, bReverseSearch);
|
||||
// Advance Entry.nField in Iterator if column changed
|
||||
aCellIter.SetAdvanceQueryParamEntryField(true);
|
||||
aCellIter.SetXlookupMode(vsa.isXLookup);
|
||||
aCellIter.SetLookupMode(vsa.nSearchOpCode);
|
||||
// TODO: no binary search for column (horizontal) search (use linear)
|
||||
aCellIter.SetSortedBinarySearchMode(vsa.eSearchMode);
|
||||
if (rEntry.eOp == SC_EQUAL)
|
||||
@@ -10741,7 +10742,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
|
||||
|
||||
case wildcard :
|
||||
// this mode can only used with XLOOKUP
|
||||
if ( vsa.isXLookup )
|
||||
if ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP )
|
||||
{
|
||||
rEntry.eOp = SC_EQUAL;
|
||||
if ( vsa.isStringSearch )
|
||||
@@ -10774,7 +10775,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
|
||||
{
|
||||
rItem.meType = ScQueryEntry::ByString;
|
||||
rItem.maString = vsa.sSearchStr;
|
||||
if ( !vsa.isXLookup )
|
||||
if ( vsa.nSearchOpCode == SC_OPCODE_MATCH )
|
||||
{
|
||||
if ( mrDoc.IsInVBAMode() )
|
||||
rParam.eSearchType = utl::SearchParam::SearchType::Wildcard;
|
||||
@@ -10805,12 +10806,12 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
|
||||
// MATCH expects index starting with 1, XLOOKUP expects index starting with 0
|
||||
if ( vsa.nHitIndex > 0 )
|
||||
{
|
||||
vsa.nIndex = ( vsa.isXLookup ? --vsa.nHitIndex : vsa.nHitIndex );
|
||||
vsa.nIndex = ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP ? --vsa.nHitIndex : vsa.nHitIndex );
|
||||
return true;
|
||||
}
|
||||
else if ( vsa.nHitIndex == 0 && vsa.nBestFit != SCSIZE_MAX )
|
||||
{
|
||||
if ( vsa.isXLookup )
|
||||
if ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP )
|
||||
{
|
||||
vsa.nIndex = vsa.nBestFit;
|
||||
if ( !vsa.pMatSrc )
|
||||
@@ -10832,7 +10833,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
|
||||
|
||||
static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInterpreterContext& rContext,
|
||||
const ScQueryParam & rParam, const ScQueryEntry & rEntry, const ScFormulaCell* cell,
|
||||
const ScComplexRefData* refData, sal_Int8 nSearchMode, bool bXlookupMode )
|
||||
const ScComplexRefData* refData, sal_Int8 nSearchMode, sal_Int16 nOpCode )
|
||||
{
|
||||
if (rEntry.eOp != SC_EQUAL)
|
||||
{
|
||||
@@ -10849,7 +10850,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
|
||||
// search for the first GreaterOrEqual value if SearchMode is asc
|
||||
ScQueryCellIteratorSortedCache aCellIter(rDoc, rContext, rParam.nTab, rParam, false, false);
|
||||
aCellIter.SetSortedBinarySearchMode(nSearchMode);
|
||||
aCellIter.SetXlookupMode(bXlookupMode);
|
||||
aCellIter.SetLookupMode(nOpCode);
|
||||
if (aCellIter.GetFirst())
|
||||
{
|
||||
o_rResultPos.SetCol(aCellIter.GetCol());
|
||||
@@ -10864,7 +10865,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
|
||||
ScQueryCellIteratorDirect aCellIter(rDoc, rContext, rParam.nTab, rParam, false, bReverse);
|
||||
|
||||
aCellIter.SetSortedBinarySearchMode(nSearchMode);
|
||||
aCellIter.SetXlookupMode(bXlookupMode);
|
||||
aCellIter.SetLookupMode(nOpCode);
|
||||
if (aCellIter.FindEqualOrSortedLastInRange(nCol, nRow))
|
||||
{
|
||||
o_rResultPos.SetCol(nCol);
|
||||
@@ -10886,7 +10887,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
|
||||
{
|
||||
ScQueryCellIteratorSortedCache aCellIter( rDoc, rContext, rParam.nTab, rParam, false, false );
|
||||
aCellIter.SetSortedBinarySearchMode(nSearchMode);
|
||||
aCellIter.SetXlookupMode(bXlookupMode);
|
||||
aCellIter.SetLookupMode(nOpCode);
|
||||
if (aCellIter.GetFirst())
|
||||
{
|
||||
o_rResultPos.SetCol( aCellIter.GetCol());
|
||||
@@ -10899,7 +10900,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
|
||||
ScQueryCellIteratorDirect aCellIter( rDoc, rContext, rParam.nTab, rParam, false,
|
||||
static_cast<SearchMode>(nSearchMode) == searchrev);
|
||||
aCellIter.SetSortedBinarySearchMode(nSearchMode);
|
||||
aCellIter.SetXlookupMode(bXlookupMode);
|
||||
aCellIter.SetLookupMode(nOpCode);
|
||||
if (aCellIter.GetFirst())
|
||||
{
|
||||
o_rResultPos.SetCol( aCellIter.GetCol());
|
||||
@@ -10951,7 +10952,7 @@ static SCROW lcl_getPrevRowWithEmptyValueLookup( const ScLookupCache& rCache,
|
||||
|
||||
bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
|
||||
const ScQueryParam & rParam, const ScComplexRefData* refData,
|
||||
sal_Int8 nSearchMode, bool bXlookupMode ) const
|
||||
sal_Int8 nSearchMode, sal_Int16 nOpCode ) const
|
||||
{
|
||||
bool bFound = false;
|
||||
const ScQueryEntry& rEntry = rParam.GetEntry(0);
|
||||
@@ -10964,7 +10965,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
|
||||
* parameter so it would affect only the lookup range parameter. */
|
||||
if (!bColumnsMatch || GetVolatileType() != NOT_VOLATILE)
|
||||
bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry, pMyFormulaCell,
|
||||
refData, nSearchMode, bXlookupMode );
|
||||
refData, nSearchMode, nOpCode );
|
||||
else
|
||||
{
|
||||
ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab,
|
||||
@@ -10996,7 +10997,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
|
||||
case ScLookupCache::NOT_CACHED :
|
||||
case ScLookupCache::CRITERIA_DIFFERENT :
|
||||
bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry,
|
||||
pMyFormulaCell, refData, nSearchMode, bXlookupMode );
|
||||
pMyFormulaCell, refData, nSearchMode, nOpCode );
|
||||
if (eCacheResult == ScLookupCache::NOT_CACHED)
|
||||
rCache.insert( o_rResultPos, aCriteria, aPos, bFound);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user