Index: sc/inc/dbcolect.hxx =================================================================== RCS file: /cvs/sc/sc/inc/dbcolect.hxx,v --- sc/inc/dbcolect.hxx 25 Apr 2007 15:56:28 -0000 1.12 +++ sc/inc/dbcolect.hxx 24 May 2007 19:06:59 -0000 @@ -113,6 +113,8 @@ String* pQueryStr[MAXQUERY]; double nQueryVal[MAXQUERY]; ScQueryConnect eQueryConnect[MAXQUERY]; + BOOL bMatchMultiStrValues[MAXQUERY]; + ScHashOUStringSet aStrValues[MAXQUERY]; BOOL bIsAdvanced; // TRUE if created by advanced filter ScRange aAdvSource; // source range // SubTotalParam Index: sc/inc/global.hxx =================================================================== RCS file: /cvs/sc/sc/inc/global.hxx,v --- sc/inc/global.hxx 25 Apr 2007 15:57:24 -0000 1.48 +++ sc/inc/global.hxx 24 May 2007 19:07:02 -0000 @@ -58,6 +58,8 @@ #include "scdllapi.h" #endif +#include + class ImageList; class Bitmap; class SfxItemSet; @@ -887,6 +889,16 @@ class TextSearch; } +struct ScHashOUString +{ + size_t operator()( const ::rtl::OUString& str ) const + { + return str.hashCode(); + } +}; + +typedef ::std::hash_set< ::rtl::OUString, ScHashOUString, ::std::equal_to > ScHashOUStringSet; + struct ScQueryEntry { BOOL bDoQuery; @@ -899,6 +911,9 @@ utl::SearchParam* pSearchParam; // falls RegExp, nicht gespeichert utl::TextSearch* pSearchText; // falls RegExp, nicht gespeichert + ScHashOUStringSet aStrValues; + BOOL bMatchMultiStrValues; // match individual string values. + ScQueryEntry(); ScQueryEntry(const ScQueryEntry& r); ~ScQueryEntry(); Index: sc/source/core/data/dpsave.cxx =================================================================== RCS file: /cvs/sc/sc/source/core/data/dpsave.cxx,v --- sc/source/core/data/dpsave.cxx 27 Feb 2007 12:04:25 -0000 1.11 +++ sc/source/core/data/dpsave.cxx 24 May 2007 19:07:02 -0000 @@ -619,7 +619,8 @@ { // single filter field: first field equal to selected string sheet::TableFilterField aField( sheet::FilterConnection_AND, 0, - sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage ); + sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage, + uno::Sequence(), sal_False ); aFilter = uno::Sequence( &aField, 1 ); } // else keep empty sequence Index: sc/source/core/data/dptabsrc.cxx =================================================================== RCS file: /cvs/sc/sc/source/core/data/dptabsrc.cxx,v --- sc/source/core/data/dptabsrc.cxx 5 Mar 2007 14:40:18 -0000 1.19 +++ sc/source/core/data/dptabsrc.cxx 24 May 2007 19:07:06 -0000 @@ -1529,7 +1529,8 @@ { // single filter field: first field equal to selected string sheet::TableFilterField aField( sheet::FilterConnection_AND, 0, - sheet::FilterOperator_EQUAL, sal_False, 0.0, aSelectedPage ); + sheet::FilterOperator_EQUAL, sal_False, 0.0, aSelectedPage, + uno::Sequence(), sal_False ); aRet <<= uno::Sequence( &aField, 1 ); } else Index: sc/source/core/data/global2.cxx =================================================================== RCS file: /cvs/sc/sc/source/core/data/global2.cxx,v --- sc/source/core/data/global2.cxx 27 Feb 2007 12:06:31 -0000 1.21 +++ sc/source/core/data/global2.cxx 24 May 2007 19:07:06 -0000 @@ -163,6 +163,7 @@ pStr = new String; pSearchParam = NULL; pSearchText = NULL; + bMatchMultiStrValues = FALSE; } ScQueryEntry::ScQueryEntry(const ScQueryEntry& r) @@ -176,6 +177,8 @@ pStr = new String(*r.pStr); pSearchParam = NULL; pSearchText = NULL; + bMatchMultiStrValues = r.bMatchMultiStrValues; + aStrValues = r.aStrValues; } ScQueryEntry::~ScQueryEntry() @@ -205,6 +208,9 @@ pSearchParam = NULL; pSearchText = NULL; + bMatchMultiStrValues = r.bMatchMultiStrValues; + aStrValues = r.aStrValues; + return *this; } @@ -224,6 +230,8 @@ } pSearchParam = NULL; pSearchText = NULL; + bMatchMultiStrValues = FALSE; + aStrValues.clear(); } BOOL ScQueryEntry::operator==( const ScQueryEntry& r ) const @@ -234,7 +242,9 @@ && eConnect == r.eConnect && nField == r.nField && nVal == r.nVal - && *pStr == *r.pStr; + && *pStr == *r.pStr + && bMatchMultiStrValues == r.bMatchMultiStrValues + && aStrValues == r.aStrValues; //! pSearchParam und pSearchText nicht vergleichen } Index: sc/source/core/data/table3.cxx =================================================================== RCS file: /cvs/sc/sc/source/core/data/table3.cxx,v --- sc/source/core/data/table3.cxx 5 Mar 2007 14:40:30 -0000 1.28 +++ sc/source/core/data/table3.cxx 24 May 2007 19:07:09 -0000 @@ -1036,82 +1036,100 @@ else GetInputString( static_cast(rEntry.nField), nRow, aCellStr ); - BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL) - || (rEntry.eOp == SC_NOT_EQUAL))); - BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp - && ((rEntry.eOp == SC_LESS_EQUAL) - || (rEntry.eOp == SC_GREATER_EQUAL))); - if ( bRealRegExp || bTestRegExp ) + if ( rEntry.bMatchMultiStrValues ) { - xub_StrLen nStart = 0; - xub_StrLen nEnd = aCellStr.Len(); - BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens ) - ->SearchFrwrd( aCellStr, &nStart, &nEnd ); - // from 614 on, nEnd is behind the found text - if ( bMatch && bMatchWholeCell - && (nStart != 0 || nEnd != aCellStr.Len()) ) - bMatch = FALSE; // RegExp must match entire cell string - if ( bRealRegExp ) - bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch); + // Filter by individual string values. + rtl::OUString aCellStr2(aCellStr); + fprintf(stdout, "ScTable::ValidQuery: filter by individual string values (%s)\n", + OUStringToOString(aCellStr2, RTL_TEXTENCODING_UTF8).getStr());fflush(stdout); + ScHashOUStringSet::const_iterator pos = rEntry.aStrValues.find(aCellStr2); + if (pos == rEntry.aStrValues.end()) + bOk = FALSE; else - bTestEqual = bMatch; + bOk = TRUE; } - if ( !bRealRegExp ) - { - if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL ) - { - if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 ) + else + { + rtl::OUString aCellStr2(aCellStr); + fprintf(stdout, "ScTable::ValidQuery: other string matching (%s)\n", + OUStringToOString(aCellStr2, RTL_TEXTENCODING_UTF8).getStr());fflush(stdout); + BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL) + || (rEntry.eOp == SC_NOT_EQUAL))); + BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp + && ((rEntry.eOp == SC_LESS_EQUAL) + || (rEntry.eOp == SC_GREATER_EQUAL))); + if ( bRealRegExp || bTestRegExp ) + { + xub_StrLen nStart = 0; + xub_StrLen nEnd = aCellStr.Len(); + BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens ) + ->SearchFrwrd( aCellStr, &nStart, &nEnd ); + // from 614 on, nEnd is behind the found text + if ( bMatch && bMatchWholeCell + && (nStart != 0 || nEnd != aCellStr.Len()) ) + bMatch = FALSE; // RegExp must match entire cell string + if ( bRealRegExp ) + bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch); + else + bTestEqual = bMatch; + } + if ( !bRealRegExp ) + { + if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL ) { - // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup), - // the query value is assigned directly, and the string is empty. In that case, - // don't find any string (isEqual would find empty string results in formula cells). - bOk = FALSE; + if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 ) + { + // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup), + // the query value is assigned directly, and the string is empty. In that case, + // don't find any string (isEqual would find empty string results in formula cells). + bOk = FALSE; + } + else if ( bMatchWholeCell ) + bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr ); + else + { + ::com::sun::star::uno::Sequence< sal_Int32 > xOff; + String aCell( pTransliteration->transliterate( + aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), + &xOff ) ); + String aQuer( pTransliteration->transliterate( + *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(), + &xOff ) ); + bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND); + } + if ( rEntry.eOp == SC_NOT_EQUAL ) + bOk = !bOk; } - else if ( bMatchWholeCell ) - bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr ); - else - { - ::com::sun::star::uno::Sequence< sal_Int32 > xOff; - String aCell( pTransliteration->transliterate( - aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), - &xOff ) ); - String aQuer( pTransliteration->transliterate( - *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(), - &xOff ) ); - bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND); - } - if ( rEntry.eOp == SC_NOT_EQUAL ) - bOk = !bOk; - } - else - { // use collator here because data was probably sorted - sal_Int32 nCompare = pCollator->compareString( - aCellStr, *rEntry.pStr ); - switch (rEntry.eOp) - { - case SC_LESS : - bOk = (nCompare < 0); - break; - case SC_GREATER : - bOk = (nCompare > 0); - break; - case SC_LESS_EQUAL : - bOk = (nCompare <= 0); - if ( bOk && pbTestEqualCondition && !bTestEqual ) - bTestEqual = (nCompare == 0); - break; - case SC_GREATER_EQUAL : - bOk = (nCompare >= 0); - if ( bOk && pbTestEqualCondition && !bTestEqual ) - bTestEqual = (nCompare == 0); - break; - default: + else + { // use collator here because data was probably sorted + sal_Int32 nCompare = pCollator->compareString( + aCellStr, *rEntry.pStr ); + switch (rEntry.eOp) { - // added to avoid warnings + case SC_LESS : + bOk = (nCompare < 0); + break; + case SC_GREATER : + bOk = (nCompare > 0); + break; + case SC_LESS_EQUAL : + bOk = (nCompare <= 0); + if ( bOk && pbTestEqualCondition && !bTestEqual ) + bTestEqual = (nCompare == 0); + break; + case SC_GREATER_EQUAL : + bOk = (nCompare >= 0); + if ( bOk && pbTestEqualCondition && !bTestEqual ) + bTestEqual = (nCompare == 0); + break; + default: + { + // added to avoid warnings + } } - } - } - } + } + } + } } else if (rParam.bMixedComparison) { @@ -1325,7 +1343,11 @@ { ScQueryEntry& rEntry = rParamOrg.GetEntry(i); - if ( rEntry.bQueryByString ) + if ( rEntry.bMatchMultiStrValues ) + { + // Do nothing. + } + else if ( rEntry.bQueryByString ) { sal_uInt32 nIndex = 0; rEntry.bQueryByString = !(pDocument->GetFormatTable()-> Index: sc/source/core/tool/dbcolect.cxx =================================================================== RCS file: /cvs/sc/sc/source/core/tool/dbcolect.cxx,v --- sc/source/core/tool/dbcolect.cxx 27 Feb 2007 12:14:19 -0000 1.16 +++ sc/source/core/tool/dbcolect.cxx 24 May 2007 19:07:09 -0000 @@ -544,6 +544,8 @@ *pQueryStr[i] = *rData.pQueryStr[i]; nQueryVal[i] = rData.nQueryVal[i]; eQueryConnect[i] = rData.eQueryConnect[i]; + bMatchMultiStrValues[i] = rData.bMatchMultiStrValues[i]; + aStrValues[i] = rData.aStrValues[i]; } for (i=0; i(nField) - 1) : static_cast(0); rEntry.eOp = eOp; + + // Disable multi-string matching until we have the UI implemented. + // TODO: Implement it in the UI (kohei). + rEntry.bMatchMultiStrValues = false; } } Index: sc/source/ui/unoobj/datauno.cxx =================================================================== RCS file: /cvs/sc/sc/source/ui/unoobj/datauno.cxx,v --- sc/source/ui/unoobj/datauno.cxx 5 Mar 2007 14:45:54 -0000 1.28 +++ sc/source/ui/unoobj/datauno.cxx 24 May 2007 19:07:11 -0000 @@ -1150,6 +1150,7 @@ aField.IsNumeric = !rEntry.bQueryByString; aField.StringValue = aStringValue; aField.NumericValue = rEntry.nVal; + aField.MatchMultiStringValues = rEntry.bMatchMultiStrValues; switch (rEntry.eOp) // ScQueryOp { @@ -1184,6 +1185,16 @@ DBG_ERROR("Falscher Filter-enum"); aField.Operator = sheet::FilterOperator_EMPTY; } + + if (rEntry.bMatchMultiStrValues && rEntry.aStrValues.size()) + { + uno::Sequence aStrList(rEntry.aStrValues.size()); + ScHashOUStringSet::const_iterator itr, itrEnd = rEntry.aStrValues.end(); + sal_Int32 nStrCount = 0; + for (itr = rEntry.aStrValues.begin(); itr != itrEnd; ++itr, ++nStrCount) + aStrList[nStrCount] = *itr; + aField.StringValues = aStrList; + } pAry[i] = aField; } return aSeq; @@ -1216,6 +1227,7 @@ rEntry.bQueryByString = !pAry[i].IsNumeric; *rEntry.pStr = String( pAry[i].StringValue ); rEntry.nVal = pAry[i].NumericValue; + rEntry.bMatchMultiStrValues = pAry[i].MatchMultiStringValues; if (!rEntry.bQueryByString && pDocSh) { @@ -1254,6 +1266,15 @@ DBG_ERROR("Falscher Query-enum"); rEntry.eOp = SC_EQUAL; } + + if (pAry[i].MatchMultiStringValues) + { + // The option for matching individual string values is set. + const uno::Sequence& aStrValues = pAry[i].StringValues; + sal_Int32 nLen = aStrValues.getLength(); + for (sal_Int32 nStrCount = 0; nStrCount < nLen; ++nStrCount) + rEntry.aStrValues.insert(aStrValues[nStrCount]); + } } SCSIZE nParamCount = aParam.GetEntryCount(); // Param wird nicht unter 8 resized Index: sc/source/ui/view/gridwin.cxx =================================================================== RCS file: /cvs/sc/sc/source/ui/view/gridwin.cxx,v --- sc/source/ui/view/gridwin.cxx 27 Feb 2007 13:51:41 -0000 1.80 +++ sc/source/ui/view/gridwin.cxx 24 May 2007 19:07:14 -0000 @@ -1299,6 +1299,10 @@ ScQueryParam aParam; pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben + // Disable multi-string match flag until we implement it in the UI. + for (SCSIZE i = 0; i < MAXQUERY; ++i) + aParam.GetEntry(i).bMatchMultiStrValues = false; + if (SC_AUTOFILTER_CUSTOM == nSel) { pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??