[Libreoffice-commits] .: 8 commits - sc/inc sc/source
Kohei Yoshida
kohei at kemper.freedesktop.org
Mon Nov 14 14:27:25 PST 2011
sc/inc/dpcachetable.hxx | 3
sc/inc/dpshttab.hxx | 1
sc/inc/dptablecache.hxx | 2
sc/inc/queryentry.hxx | 4
sc/inc/table.hxx | 10
sc/source/core/data/dociter.cxx | 4
sc/source/core/data/dpcachetable.cxx | 4
sc/source/core/data/dpshttab.cxx | 10
sc/source/core/data/dptablecache.cxx | 4
sc/source/core/data/table2.cxx | 4
sc/source/core/data/table3.cxx | 770 ++++++++++++++++++-----------------
sc/source/core/tool/queryentry.cxx | 18
sc/source/core/tool/queryparam.cxx | 2
13 files changed, 451 insertions(+), 385 deletions(-)
New commits:
commit e2577c3df784be265ff2314b4c25601f4f30fe04
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 17:26:50 2011 -0500
This can be const.
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index afdbed1..8d51028 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1700,7 +1700,7 @@ public:
}
};
-void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
+void lcl_PrepareQuery( const ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
{
bool bTopTen = false;
SCSIZE nEntryCount = rParam.GetEntryCount();
commit d56778ac4b75517f87aaf71763c51dfdc1eb02c3
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 17:25:31 2011 -0500
Prefer for_each over manual loop.
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index f94f6b2..afdbed1 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1664,7 +1664,43 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
DestroySortCollator();
}
-static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
+namespace {
+
+class PrepareQueryItem : public std::unary_function<ScQueryEntry::Item, void>
+{
+ const ScDocument& mrDoc;
+public:
+ PrepareQueryItem(const ScDocument& rDoc) : mrDoc(rDoc) {}
+
+ void operator() (ScQueryEntry::Item& rItem)
+ {
+ // Double-check if the query by date is really appropriate.
+
+ if (rItem.meType != ScQueryEntry::ByDate)
+ return;
+
+ sal_uInt32 nIndex = 0;
+ bool bNumber = mrDoc.GetFormatTable()->
+ IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
+
+ if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
+ {
+ const SvNumberformat* pEntry = mrDoc.GetFormatTable()->GetEntry(nIndex);
+ if (pEntry)
+ {
+ short nNumFmtType = pEntry->GetType();
+ if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
+ rItem.meType = ScQueryEntry::ByValue; // not a date only
+ }
+ else
+ rItem.meType = ScQueryEntry::ByValue; // what the ... not a date
+ }
+ else
+ rItem.meType = ScQueryEntry::ByValue; // not a date
+ }
+};
+
+void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
{
bool bTopTen = false;
SCSIZE nEntryCount = rParam.GetEntryCount();
@@ -1672,53 +1708,26 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
for ( SCSIZE i = 0; i < nEntryCount; ++i )
{
ScQueryEntry& rEntry = rParam.GetEntry(i);
- if ( rEntry.bDoQuery )
+ if (!rEntry.bDoQuery)
+ continue;
+
+ ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+ std::for_each(rItems.begin(), rItems.end(), PrepareQueryItem(*pDoc));
+
+ if ( !bTopTen )
{
- ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
- ScQueryEntry::QueryItemsType::iterator itr = rItems.begin(), itrEnd = rItems.end();
- for (; itr != itrEnd; ++itr)
+ switch ( rEntry.eOp )
{
- ScQueryEntry::Item& rItem = *itr;
- if (rItem.meType == ScQueryEntry::ByString)
+ case SC_TOPVAL:
+ case SC_BOTVAL:
+ case SC_TOPPERC:
+ case SC_BOTPERC:
{
- sal_uInt32 nIndex = 0;
- bool bNumber = pDoc->GetFormatTable()->
- IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
- if (rItem.meType == ScQueryEntry::ByDate)
- {
- if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
- {
- const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
- if (pEntry)
- {
- short nNumFmtType = pEntry->GetType();
- if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
- rItem.meType = ScQueryEntry::ByValue; // not a date only
- }
- else
- rItem.meType = ScQueryEntry::ByValue; // what the ... not a date
- }
- else
- rItem.meType = ScQueryEntry::ByValue; // not a date
- }
+ bTopTen = true;
}
- }
-
- if ( !bTopTen )
- {
- switch ( rEntry.eOp )
+ break;
+ default:
{
- case SC_TOPVAL:
- case SC_BOTVAL:
- case SC_TOPPERC:
- case SC_BOTPERC:
- {
- bTopTen = true;
- }
- break;
- default:
- {
- }
}
}
}
@@ -1730,6 +1739,8 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
}
}
+}
+
SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
{
ScQueryParam aParam( rParamOrg );
commit 4740d607c09025aa2a645e7578514a580dec15e5
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 17:15:31 2011 -0500
Adopt lcl_PrepareQuery to multi-item queries.
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 3538710..19adf3f 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -71,6 +71,7 @@ struct ScQueryEntry
// creates pSearchParam and pSearchText if necessary, always RegExp!
utl::TextSearch* GetSearchTextPtr( bool bCaseSens ) const;
+ QueryItemsType& GetQueryItems();
const QueryItemsType& GetQueryItems() const;
SC_DLLPUBLIC void SetQueryByEmpty();
SC_DLLPUBLIC bool IsQueryByEmpty() const;
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index e1c5902..f94f6b2 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1674,29 +1674,33 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
ScQueryEntry& rEntry = rParam.GetEntry(i);
if ( rEntry.bDoQuery )
{
- // TODO: adapt this for multi-query items.
- ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
- if (rItem.meType == ScQueryEntry::ByString)
+ ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+ ScQueryEntry::QueryItemsType::iterator itr = rItems.begin(), itrEnd = rItems.end();
+ for (; itr != itrEnd; ++itr)
{
- sal_uInt32 nIndex = 0;
- bool bNumber = pDoc->GetFormatTable()->
- IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
- if (rItem.meType == ScQueryEntry::ByDate)
+ ScQueryEntry::Item& rItem = *itr;
+ if (rItem.meType == ScQueryEntry::ByString)
{
- if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
+ sal_uInt32 nIndex = 0;
+ bool bNumber = pDoc->GetFormatTable()->
+ IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
+ if (rItem.meType == ScQueryEntry::ByDate)
{
- const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
- if (pEntry)
+ if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
{
- short nNumFmtType = pEntry->GetType();
- if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
- rItem.meType = ScQueryEntry::ByValue; // not a date only
+ const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
+ if (pEntry)
+ {
+ short nNumFmtType = pEntry->GetType();
+ if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
+ rItem.meType = ScQueryEntry::ByValue; // not a date only
+ }
+ else
+ rItem.meType = ScQueryEntry::ByValue; // what the ... not a date
}
else
- rItem.meType = ScQueryEntry::ByValue; // what the ... not a date
+ rItem.meType = ScQueryEntry::ByValue; // not a date
}
- else
- rItem.meType = ScQueryEntry::ByValue; // not a date
}
}
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index be16cf8..47a88e7 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -91,6 +91,11 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
return *this;
}
+ScQueryEntry::QueryItemsType& ScQueryEntry::GetQueryItems()
+{
+ return maQueryItems;
+}
+
const ScQueryEntry::QueryItemsType& ScQueryEntry::GetQueryItems() const
{
return maQueryItems;
commit 04fc63b20088bb704728c05d0460cf18f5f152ea
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 16:54:44 2011 -0500
No more pSpecial treatment of empty / non-empty queries.
diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx
index 9c6353d..62efc84 100644
--- a/sc/inc/dpcachetable.hxx
+++ b/sc/inc/dpcachetable.hxx
@@ -138,8 +138,7 @@ public:
/** Fill the internal table from the cell range provided. This function
assumes that the first row is the column header. */
- void fillTable( const ScQueryParam& rQuery, bool* pSpecial,
- bool bIgnoreEmptyRows, bool bRepeatIfEmpty );
+ void fillTable(const ScQueryParam& rQuery, bool bIgnoreEmptyRows, bool bRepeatIfEmpty);
/** Fill the internal table from database connection object. This function
assumes that the first row is the column header. */
diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx
index 505a275..8255135 100644
--- a/sc/inc/dpshttab.hxx
+++ b/sc/inc/dpshttab.hxx
@@ -103,7 +103,6 @@ class SC_DLLPUBLIC ScSheetDPData : public ScDPTableData
{
private:
ScQueryParam aQuery;
- bool* pSpecial;
bool bIgnoreEmptyRows;
bool bRepeatIfEmpty;
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
index 4bfb14d..950cc54 100644
--- a/sc/inc/dptablecache.hxx
+++ b/sc/inc/dptablecache.hxx
@@ -114,7 +114,7 @@ public:
bool IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const;
bool IsRowEmpty( SCROW nRow ) const;
bool IsValid() const;
- bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, bool* pSpecial ) const;
+ bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam) const;
ScDocument* GetDoc() const;//ms-cache-core
long GetColumnCount() const;
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 6305480..3538710 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -44,7 +44,7 @@ namespace utl {
*/
struct ScQueryEntry
{
- enum QueryType { ByValue, ByString, ByDate };
+ enum QueryType { ByValue, ByString, ByDate, ByEmpty };
struct Item
{
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 041cdaa..906d306 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -758,9 +758,9 @@ public:
void ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 );
void Sort(const ScSortParam& rSortParam, bool bKeepQuery);
- bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam,
- bool* pSpecial = NULL, ScBaseCell* pCell = NULL,
- bool* pbTestEqualCondition = NULL );
+ bool ValidQuery(
+ SCROW nRow, const ScQueryParam& rQueryParam, ScBaseCell* pCell = NULL,
+ bool* pbTestEqualCondition = NULL);
void TopTenQuery( ScQueryParam& );
SCSIZE Query(ScQueryParam& rQueryParam, bool bKeepSub);
bool CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 689e68e..f31610e 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -500,7 +500,7 @@ bool ScDBQueryDataIterator::IsQueryValid(ScDocument& rDoc, const ScQueryParam& r
{
if (nTab >= rDoc.GetTableCount())
OSL_FAIL("try to access index out of bounds, FIX IT");
- return rDoc.maTabs[nTab]->ValidQuery(nRow, rParam, NULL, pCell);
+ return rDoc.maTabs[nTab]->ValidQuery(nRow, rParam, pCell);
}
SCSIZE ScDBQueryDataIterator::SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol)
@@ -1168,7 +1168,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
else
{
bool bTestEqualCondition;
- if ( (pDoc->maTabs[nTab])->ValidQuery( nRow, aParam, NULL,
+ if ( (pDoc->maTabs[nTab])->ValidQuery( nRow, aParam,
(nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL),
(nTestEqualCondition ? &bTestEqualCondition : NULL) ) )
{
diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx
index 89d01df..9f3ae49 100644
--- a/sc/source/core/data/dpcachetable.cxx
+++ b/sc/source/core/data/dpcachetable.cxx
@@ -190,7 +190,7 @@ sal_Int32 ScDPCacheTable::getColSize() const
}
void ScDPCacheTable::fillTable(
- const ScQueryParam& rQuery, bool* pSpecial, bool bIgnoreEmptyRows, bool bRepeatIfEmpty)
+ const ScQueryParam& rQuery, bool bIgnoreEmptyRows, bool bRepeatIfEmpty)
{
const SCROW nRowCount = getRowSize();
const SCCOL nColCount = (SCCOL) getColSize();
@@ -224,7 +224,7 @@ void ScDPCacheTable::fillTable(
}
if ( lcl_HasQueryEntry(rQuery) &&
- !getCache()->ValidQuery( nRow , rQuery, pSpecial ) )
+ !getCache()->ValidQuery(nRow , rQuery) )
continue;
if ( bIgnoreEmptyRows && getCache()->IsRowEmpty( nRow ) )
continue;
diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx
index f10d62b..fdb472c 100644
--- a/sc/source/core/data/dpshttab.cxx
+++ b/sc/source/core/data/dpshttab.cxx
@@ -63,21 +63,18 @@ using ::std::vector;
ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache) :
ScDPTableData(pD),
aQuery ( rDesc.GetQueryParam() ),
- pSpecial(NULL),
bIgnoreEmptyRows( false ),
bRepeatIfEmpty(false),
mrDesc(rDesc),
aCacheTable(pCache)
{
SCSIZE nEntryCount( aQuery.GetEntryCount());
- pSpecial = new bool[nEntryCount];
for (SCSIZE j = 0; j < nEntryCount; ++j)
{
ScQueryEntry& rEntry = aQuery.GetEntry(j);
if (rEntry.bDoQuery)
{
ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
- pSpecial[j] = false;
if (rItem.meType == ScQueryEntry::ByString)
{
sal_uInt32 nIndex = 0;
@@ -85,17 +82,12 @@ ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, con
rItem.maString, nIndex, rItem.mfVal);
rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
}
- else if (rEntry.IsQueryByEmpty() || rEntry.IsQueryByNonEmpty())
- {
- pSpecial[j] = true;
- }
}
}
}
ScSheetDPData::~ScSheetDPData()
{
- delete[] pSpecial;
}
void ScSheetDPData::DisposeData()
@@ -203,7 +195,7 @@ void ScSheetDPData::CreateCacheTable()
if (!aCacheTable.hasCache())
aCacheTable.setCache(mrDesc.CreateCache());
- aCacheTable.fillTable(aQuery, pSpecial, bIgnoreEmptyRows, bRepeatIfEmpty);
+ aCacheTable.fillTable(aQuery, bIgnoreEmptyRows, bRepeatIfEmpty);
}
void ScSheetDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rCatDims)
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 0ebf847..0ab7334 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -576,7 +576,7 @@ sal_uLong ScDPCache::GetDimNumType( SCCOL nDim) const
return GetNumType(maTableDataValues[nDim][0].nNumFormat);
}
-bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial) const
+bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const
{
if (!rParam.GetEntry(0).bDoQuery)
return true;
@@ -616,7 +616,7 @@ bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpeci
bool bOk = false;
bool bTestEqual = false;
- if (pSpecial && pSpecial[i])
+ if (rEntry.GetQueryItem().meType == ScQueryEntry::ByEmpty)
{
if (rEntry.IsQueryByEmpty())
bOk = !pCellData->IsHasData();
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index f9bab9a..e1c5902 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1441,9 +1441,9 @@ public:
}
-bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
- bool* pSpecial /* =NULL */ , ScBaseCell* pCell /* =NULL */ ,
- bool* pbTestEqualCondition /* = NULL */ )
+bool ScTable::ValidQuery(
+ SCROW nRow, const ScQueryParam& rParam, ScBaseCell* pCell,
+ bool* pbTestEqualCondition)
{
if (!rParam.GetEntry(0).bDoQuery)
return true;
@@ -1468,7 +1468,8 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
std::pair<bool,bool> aRes(false, false);
- if ( pSpecial && pSpecial[i] )
+ const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+ if (rItems.size() == 1 && rItems.front().meType == ScQueryEntry::ByEmpty)
{
if (rEntry.IsQueryByEmpty())
aRes.first = !aCol[rEntry.nField].HasDataAt(nRow);
@@ -1480,7 +1481,6 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
}
else
{
- const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
ScQueryEntry::QueryItemsType::const_iterator itr = rItems.begin(), itrEnd = rItems.end();
for (; itr != itrEnd; ++itr)
@@ -1664,14 +1664,13 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
DestroySortCollator();
}
-static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam, bool* pSpecial )
+static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
{
bool bTopTen = false;
SCSIZE nEntryCount = rParam.GetEntryCount();
for ( SCSIZE i = 0; i < nEntryCount; ++i )
{
- pSpecial[i] = false;
ScQueryEntry& rEntry = rParam.GetEntry(i);
if ( rEntry.bDoQuery )
{
@@ -1700,14 +1699,7 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
rItem.meType = ScQueryEntry::ByValue; // not a date
}
}
- else
- {
- // call from UNO or second call from autofilter
- if (rEntry.IsQueryByEmpty() || rEntry.IsQueryByNonEmpty())
- {
- pSpecial[i] = true;
- }
- }
+
if ( !bTopTen )
{
switch ( rEntry.eOp )
@@ -1749,9 +1741,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
SCROW nOutRow = 0;
SCROW nHeader = aParam.bHasHeader ? 1 : 0;
- SCSIZE nEntryCount = aParam.GetEntryCount();
- bool* pSpecial = new bool[nEntryCount];
- lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
+ lcl_PrepareQuery(pDocument, this, aParam);
if (!aParam.bInplace)
{
@@ -1769,7 +1759,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
for (SCROW j = aParam.nRow1 + nHeader; j <= nRealRow2; ++j)
{
bool bResult; // Filterergebnis
- bool bValid = ValidQuery(j, aParam, pSpecial);
+ bool bValid = ValidQuery(j, aParam);
if (!bValid && bKeepSub) // Subtotals stehenlassen
{
for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++)
@@ -1845,7 +1835,6 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
if (aParam.bInplace)
SetDrawPageSize();
- delete[] pSpecial;
return nCount;
}
@@ -2113,12 +2102,11 @@ void ScTable::GetFilteredFilterEntries(
}
nEntryCount = aParam.GetEntryCount();
- bool* pSpecial = new bool[nEntryCount];
- lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
+ lcl_PrepareQuery(pDocument, this, aParam);
bool bHasDates = false;
for ( SCROW j = nRow1; j <= nRow2; ++j )
{
- if ( ValidQuery( j, aParam, pSpecial ) )
+ if (ValidQuery(j, aParam))
{
bool bThisHasDates = false;
aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates );
@@ -2127,7 +2115,6 @@ void ScTable::GetFilteredFilterEntries(
}
rHasDates = bHasDates;
- delete[] pSpecial;
}
bool ScTable::GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStrings, bool bLimit)
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index c58f37f..be16cf8 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -100,7 +100,7 @@ void ScQueryEntry::SetQueryByEmpty()
{
eOp = SC_EQUAL;
Item& rItem = GetQueryItem();
- rItem.meType = ByValue;
+ rItem.meType = ByEmpty;
rItem.maString = rtl::OUString();
rItem.mfVal = SC_EMPTYFIELDS;
}
@@ -113,7 +113,7 @@ bool ScQueryEntry::IsQueryByEmpty() const
const Item& rItem = GetQueryItem();
return eOp == SC_EQUAL &&
- rItem.meType == ByValue &&
+ rItem.meType == ByEmpty &&
rItem.maString.isEmpty() &&
rItem.mfVal == SC_EMPTYFIELDS;
}
@@ -122,7 +122,7 @@ void ScQueryEntry::SetQueryByNonEmpty()
{
eOp = SC_EQUAL;
Item& rItem = GetQueryItem();
- rItem.meType = ByValue;
+ rItem.meType = ByEmpty;
rItem.maString = rtl::OUString();
rItem.mfVal = SC_NONEMPTYFIELDS;
}
@@ -135,7 +135,7 @@ bool ScQueryEntry::IsQueryByNonEmpty() const
const Item& rItem = GetQueryItem();
return eOp == SC_EQUAL &&
- rItem.meType == ByValue &&
+ rItem.meType == ByEmpty &&
rItem.maString.isEmpty() &&
rItem.mfVal == SC_NONEMPTYFIELDS;
}
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
index a1df6a2..d4ead74 100644
--- a/sc/source/core/tool/queryparam.cxx
+++ b/sc/source/core/tool/queryparam.cxx
@@ -264,7 +264,7 @@ ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
bByRow = r.bByRow;
bDestPers = r.bDestPers;
- maEntries = r.maEntries;
+ maEntries = r.maEntries.clone();
return *this;
}
commit f6d50b0ebb08ccdeae2d62ad070145a28ce732f8
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 16:00:30 2011 -0500
Make multi-item query possible.
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 6419141..6305480 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -71,6 +71,7 @@ struct ScQueryEntry
// creates pSearchParam and pSearchText if necessary, always RegExp!
utl::TextSearch* GetSearchTextPtr( bool bCaseSens ) const;
+ const QueryItemsType& GetQueryItems() const;
SC_DLLPUBLIC void SetQueryByEmpty();
SC_DLLPUBLIC bool IsQueryByEmpty() const;
SC_DLLPUBLIC void SetQueryByNonEmpty();
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index f2846ee..f9bab9a 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1468,10 +1468,6 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
std::pair<bool,bool> aRes(false, false);
- // For now, we only handle single item queries. We need to adopt this
- // to multi-item queries later.
- const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
-
if ( pSpecial && pSpecial[i] )
{
if (rEntry.IsQueryByEmpty())
@@ -1482,13 +1478,31 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
aRes.first = aCol[rEntry.nField].HasDataAt(nRow);
}
}
- else if (aEval.isQueryByValue(rItem, nCol, nRow, pCell))
- {
- aRes = aEval.compareByValue(pCell, nCol, nRow, rEntry, rItem);
- }
- else if (aEval.isQueryByString(rEntry, rItem, nCol, nRow, pCell))
+ else
{
- aRes = aEval.compareByString(pCell, nRow, rEntry, rItem);
+ const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+ ScQueryEntry::QueryItemsType::const_iterator itr = rItems.begin(), itrEnd = rItems.end();
+
+ for (; itr != itrEnd; ++itr)
+ {
+ if (aEval.isQueryByValue(*itr, nCol, nRow, pCell))
+ {
+ std::pair<bool,bool> aThisRes =
+ aEval.compareByValue(pCell, nCol, nRow, rEntry, *itr);
+ aRes.first |= aThisRes.first;
+ aRes.second |= aThisRes.second;
+ }
+ else if (aEval.isQueryByString(rEntry, *itr, nCol, nRow, pCell))
+ {
+ std::pair<bool,bool> aThisRes =
+ aEval.compareByString(pCell, nRow, rEntry, *itr);
+ aRes.first |= aThisRes.first;
+ aRes.second |= aThisRes.second;
+ }
+
+ if (aRes.first && aRes.second)
+ break;
+ }
}
if (nPos == -1)
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index 7ea2c49..c58f37f 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -91,6 +91,11 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
return *this;
}
+const ScQueryEntry::QueryItemsType& ScQueryEntry::GetQueryItems() const
+{
+ return maQueryItems;
+}
+
void ScQueryEntry::SetQueryByEmpty()
{
eOp = SC_EQUAL;
commit 625025f6c24a96fa899ad1d9b493dfd73f2755c9
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 15:35:02 2011 -0500
Aggregate all these local functions into a class.
This also reduces the number of parameters in each function.
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index a7604dd..f2846ee 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1067,348 +1067,377 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
namespace {
-bool isQueryByValue(
- const ScTable& rTable, const ScQueryEntry::Item& rItem,
- SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
+class QueryEvaluator
{
- if (rItem.meType == ScQueryEntry::ByString)
- return false;
-
- if (pCell)
- return pCell->HasValueData();
-
- return rTable.HasValueData(nCol, nRow);
-}
-
-std::pair<bool,bool> compareByValue(
- const ScDocument& rDoc, const ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
- const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool* pbTestEqualCondition)
-{
- bool bOk = false;
- bool bTestEqual = false;
- double nCellVal;
- if ( pCell )
+ const ScDocument& mrDoc;
+ const ScTable& mrTab;
+ const ScQueryParam& mrParam;
+ const bool* mpTestEqualCondition;
+ utl::TransliterationWrapper* mpTransliteration;
+ CollatorWrapper* mpCollator;
+ const bool mbMatchWholeCell;
+
+ bool isPartialTextMatchOp(const ScQueryEntry& rEntry) const
{
- switch ( pCell->GetCellType() )
+ switch (rEntry.eOp)
{
- case CELLTYPE_VALUE :
- nCellVal = ((ScValueCell*)pCell)->GetValue();
- break;
- case CELLTYPE_FORMULA :
- nCellVal = ((ScFormulaCell*)pCell)->GetValue();
- break;
+ // these operators can only be used with textural comparisons.
+ case SC_CONTAINS:
+ case SC_DOES_NOT_CONTAIN:
+ case SC_BEGINS_WITH:
+ case SC_ENDS_WITH:
+ case SC_DOES_NOT_BEGIN_WITH:
+ case SC_DOES_NOT_END_WITH:
+ return true;
default:
- nCellVal = 0.0;
- }
-
- }
- else
- nCellVal = rTab.GetValue(nCol, nRow);
-
- /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
- * date+time format was queried rEntry.bQueryByDate is not set. In
- * case other queries wanted to use this mechanism they should do
- * the same, in other words only if rEntry.nVal is an integer value
- * rEntry.bQueryByDate should be true and the time fraction be
- * stripped here. */
- if (rItem.meType == ScQueryEntry::ByDate)
- {
- sal_uInt32 nNumFmt = rTab.GetNumberFormat(nCol, nRow);
- const SvNumberformat* pEntry = rDoc.GetFormatTable()->GetEntry(nNumFmt);
- if (pEntry)
- {
- short nNumFmtType = pEntry->GetType();
- /* NOTE: Omitting the check for absence of
- * NUMBERFORMAT_TIME would include also date+time formatted
- * values of the same day. That may be desired in some
- * cases, querying all time values of a day, but confusing
- * in other cases. A user can always setup a standard
- * filter query for x >= date AND x < date+1 */
- if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
- {
- // The format is of date type. Strip off the time
- // element.
- nCellVal = ::rtl::math::approxFloor(nCellVal);
- }
+ ;
}
+ return false;
}
- switch (rEntry.eOp)
+ bool isTextMatchOp(const ScQueryEntry& rEntry) const
{
- case SC_EQUAL :
- bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_LESS :
- bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_GREATER :
- bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_LESS_EQUAL :
- bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- if ( bOk && pbTestEqualCondition )
- bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_GREATER_EQUAL :
- bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
- if ( bOk && pbTestEqualCondition )
- bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_NOT_EQUAL :
- bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- default:
+ if (isPartialTextMatchOp(rEntry))
+ return true;
+
+ switch (rEntry.eOp)
{
- // added to avoid warnings
+ // these operators can be used for either textural or value comparison.
+ case SC_EQUAL:
+ case SC_NOT_EQUAL:
+ return true;
+ default:
+ ;
}
+ return false;
}
- return std::pair<bool,bool>(bOk, bTestEqual);
-}
-
-bool isPartialTextMatchOp(const ScQueryEntry& rEntry)
-{
- switch (rEntry.eOp)
+ bool isRealRegExp(const ScQueryEntry& rEntry) const
{
- // these operators can only be used with textural comparisons.
- case SC_CONTAINS:
- case SC_DOES_NOT_CONTAIN:
- case SC_BEGINS_WITH:
- case SC_ENDS_WITH:
- case SC_DOES_NOT_BEGIN_WITH:
- case SC_DOES_NOT_END_WITH:
- return true;
- default:
- ;
- }
- return false;
-}
-
-bool isTextMatchOp(const ScQueryEntry& rEntry)
-{
- if (isPartialTextMatchOp(rEntry))
- return true;
+ if (!mrParam.bRegExp)
+ return false;
- switch (rEntry.eOp)
- {
- // these operators can be used for either textural or value comparison.
- case SC_EQUAL:
- case SC_NOT_EQUAL:
- return true;
- default:
- ;
+ return isTextMatchOp(rEntry);
}
- return false;
-}
-bool isQueryByString(
- const ScTable& rTable, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem,
- SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
-{
- if (isTextMatchOp(rEntry))
- return true;
+ bool isTestRegExp(const ScQueryEntry& rEntry) const
+ {
+ if (!mpTestEqualCondition)
+ return false;
- if (rItem.meType != ScQueryEntry::ByString)
- return false;
+ if (!mrParam.bRegExp)
+ return false;
- if (pCell)
- return pCell->HasStringData();
+ return (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL);
+ }
- return rTable.HasStringData(nCol, nRow);
-}
+public:
+ QueryEvaluator(const ScDocument& rDoc, const ScTable& rTab, const ScQueryParam& rParam,
+ const bool* pTestEqualCondition) :
+ mrDoc(rDoc),
+ mrTab(rTab),
+ mrParam(rParam),
+ mpTestEqualCondition(pTestEqualCondition),
+ mbMatchWholeCell(rDoc.GetDocOptions().IsMatchWholeCell())
+ {
+ if (rParam.bCaseSens)
+ {
+ mpTransliteration = ScGlobal::GetCaseTransliteration();
+ mpCollator = ScGlobal::GetCaseCollator();
+ }
+ else
+ {
+ mpTransliteration = ScGlobal::GetpTransliteration();
+ mpCollator = ScGlobal::GetCollator();
+ }
+ }
-bool isRealRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry)
-{
- if (!rParam.bRegExp)
- return false;
+ bool isQueryByValue(
+ const ScQueryEntry::Item& rItem, SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
+ {
+ if (rItem.meType == ScQueryEntry::ByString)
+ return false;
- return isTextMatchOp(rEntry);
-}
+ if (pCell)
+ return pCell->HasValueData();
-bool isTestRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry, bool* pbTestEqualCondition)
-{
- if (!pbTestEqualCondition)
- return false;
+ return mrTab.HasValueData(nCol, nRow);
+ }
- if (!rParam.bRegExp)
- return false;
+ bool isQueryByString(
+ const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem,
+ SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
+ {
+ if (isTextMatchOp(rEntry))
+ return true;
- return (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL);
-}
+ if (rItem.meType != ScQueryEntry::ByString)
+ return false;
-std::pair<bool,bool> compareByString(
- const ScDocument& rDoc, const ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
- const ScQueryParam& rParam, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool bMatchWholeCell,
- ::utl::TransliterationWrapper* pTransliteration, CollatorWrapper* pCollator,
- bool* pbTestEqualCondition)
-{
- bool bOk = false;
- bool bTestEqual = false;
- rtl::OUString aCellStr;
- if (isPartialTextMatchOp(rEntry))
- // may have to do partial textural comparison.
- bMatchWholeCell = false;
+ if (pCell)
+ return pCell->HasStringData();
- if ( pCell )
- {
- if (pCell->GetCellType() != CELLTYPE_NOTE)
- {
- sal_uLong nFormat = rTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
- ScCellFormat::GetInputString(pCell, nFormat, aCellStr, *rDoc.GetFormatTable());
- }
+ return mrTab.HasStringData(nCol, nRow);
}
- else
- rTab.GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
-
- bool bRealRegExp = isRealRegExp(rParam, rEntry);
- bool bTestRegExp = isTestRegExp(rParam, rEntry, pbTestEqualCondition);
- if ( bRealRegExp || bTestRegExp )
+ std::pair<bool,bool> compareByValue(
+ const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
+ const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem)
{
- xub_StrLen nStart = 0;
- xub_StrLen nEnd = aCellStr.getLength();
-
- // from 614 on, nEnd is behind the found text
- bool bMatch = false;
- if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+ bool bOk = false;
+ bool bTestEqual = false;
+ double nCellVal;
+ if ( pCell )
{
- nEnd = 0;
- nStart = aCellStr.getLength();
- bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchBkwrd( aCellStr, &nStart, &nEnd );
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ nCellVal = ((ScValueCell*)pCell)->GetValue();
+ break;
+ case CELLTYPE_FORMULA :
+ nCellVal = ((ScFormulaCell*)pCell)->GetValue();
+ break;
+ default:
+ nCellVal = 0.0;
+ }
+
}
else
+ nCellVal = mrTab.GetValue(nCol, nRow);
+
+ /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
+ * date+time format was queried rEntry.bQueryByDate is not set. In
+ * case other queries wanted to use this mechanism they should do
+ * the same, in other words only if rEntry.nVal is an integer value
+ * rEntry.bQueryByDate should be true and the time fraction be
+ * stripped here. */
+ if (rItem.meType == ScQueryEntry::ByDate)
{
- bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+ sal_uInt32 nNumFmt = mrTab.GetNumberFormat(nCol, nRow);
+ const SvNumberformat* pEntry = mrDoc.GetFormatTable()->GetEntry(nNumFmt);
+ if (pEntry)
+ {
+ short nNumFmtType = pEntry->GetType();
+ /* NOTE: Omitting the check for absence of
+ * NUMBERFORMAT_TIME would include also date+time formatted
+ * values of the same day. That may be desired in some
+ * cases, querying all time values of a day, but confusing
+ * in other cases. A user can always setup a standard
+ * filter query for x >= date AND x < date+1 */
+ if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
+ {
+ // The format is of date type. Strip off the time
+ // element.
+ nCellVal = ::rtl::math::approxFloor(nCellVal);
+ }
+ }
}
- if ( bMatch && bMatchWholeCell
- && (nStart != 0 || nEnd != aCellStr.getLength()) )
- bMatch = false; // RegExp must match entire cell string
- if ( bRealRegExp )
- switch (rEntry.eOp)
+
+ switch (rEntry.eOp)
{
- case SC_EQUAL:
- case SC_CONTAINS:
- bOk = bMatch;
+ case SC_EQUAL :
+ bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
break;
- case SC_NOT_EQUAL:
- case SC_DOES_NOT_CONTAIN:
- bOk = !bMatch;
+ case SC_LESS :
+ bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
break;
- case SC_BEGINS_WITH:
- bOk = ( bMatch && (nStart == 0) );
+ case SC_GREATER :
+ bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
break;
- case SC_DOES_NOT_BEGIN_WITH:
- bOk = !( bMatch && (nStart == 0) );
+ case SC_LESS_EQUAL :
+ bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ if ( bOk && mpTestEqualCondition )
+ bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
break;
- case SC_ENDS_WITH:
- bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
+ case SC_GREATER_EQUAL :
+ bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
+ if ( bOk && mpTestEqualCondition )
+ bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
break;
- case SC_DOES_NOT_END_WITH:
- bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
+ case SC_NOT_EQUAL :
+ bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
break;
default:
- {
- // added to avoid warnings
- }
+ {
+ // added to avoid warnings
+ }
}
- else
- bTestEqual = bMatch;
+
+ return std::pair<bool,bool>(bOk, bTestEqual);
}
- if ( !bRealRegExp )
+
+ std::pair<bool,bool> compareByString(
+ ScBaseCell* pCell, SCROW nRow, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem)
{
- // Simple string matching i.e. no regexp match.
- if (isTextMatchOp(rEntry))
+ bool bOk = false;
+ bool bTestEqual = false;
+ bool bMatchWholeCell = mbMatchWholeCell;
+ rtl::OUString aCellStr;
+ if (isPartialTextMatchOp(rEntry))
+ // may have to do partial textural comparison.
+ bMatchWholeCell = false;
+
+ if ( pCell )
{
- if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
+ if (pCell->GetCellType() != CELLTYPE_NOTE)
{
- // #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.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
+ sal_uLong nFormat = mrTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
+ ScCellFormat::GetInputString(pCell, nFormat, aCellStr, *mrDoc.GetFormatTable());
}
- else if ( bMatchWholeCell )
+ }
+ else
+ mrTab.GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
+
+ bool bRealRegExp = isRealRegExp(rEntry);
+ bool bTestRegExp = isTestRegExp(rEntry);
+
+ if ( bRealRegExp || bTestRegExp )
+ {
+ xub_StrLen nStart = 0;
+ xub_StrLen nEnd = aCellStr.getLength();
+
+ // from 614 on, nEnd is behind the found text
+ bool bMatch = false;
+ if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
{
- bOk = pTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
- if ( rEntry.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
+ nEnd = 0;
+ nStart = aCellStr.getLength();
+ bMatch = (bool) rEntry.GetSearchTextPtr( mrParam.bCaseSens )
+ ->SearchBkwrd( aCellStr, &nStart, &nEnd );
}
else
{
- const rtl::OUString& rQueryStr = rItem.maString;
- String aCell( pTransliteration->transliterate(
- aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
- NULL ) );
- String aQuer( pTransliteration->transliterate(
- rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
- NULL ) );
- xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
- || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
- xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+ bMatch = (bool) rEntry.GetSearchTextPtr( mrParam.bCaseSens )
+ ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+ }
+ if ( bMatch && bMatchWholeCell
+ && (nStart != 0 || nEnd != aCellStr.getLength()) )
+ bMatch = false; // RegExp must match entire cell string
+ if ( bRealRegExp )
switch (rEntry.eOp)
- {
+ {
case SC_EQUAL:
case SC_CONTAINS:
- bOk = ( nStrPos != STRING_NOTFOUND );
+ bOk = bMatch;
break;
case SC_NOT_EQUAL:
case SC_DOES_NOT_CONTAIN:
- bOk = ( nStrPos == STRING_NOTFOUND );
+ bOk = !bMatch;
break;
case SC_BEGINS_WITH:
- bOk = ( nStrPos == 0 );
+ bOk = ( bMatch && (nStart == 0) );
break;
case SC_DOES_NOT_BEGIN_WITH:
- bOk = ( nStrPos != 0 );
+ bOk = !( bMatch && (nStart == 0) );
break;
case SC_ENDS_WITH:
- bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+ bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
break;
case SC_DOES_NOT_END_WITH:
- bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+ bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
break;
default:
{
// added to avoid warnings
}
- }
}
+ else
+ bTestEqual = bMatch;
}
- else
- { // use collator here because data was probably sorted
- sal_Int32 nCompare = pCollator->compareString(
- aCellStr, rEntry.GetQueryItem().maString);
- switch (rEntry.eOp)
+ if ( !bRealRegExp )
+ {
+ // Simple string matching i.e. no regexp match.
+ if (isTextMatchOp(rEntry))
{
- 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:
+ if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
+ {
+ // #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.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
+ else if ( bMatchWholeCell )
{
- // added to avoid warnings
+ bOk = mpTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
+ if ( rEntry.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
+ else
+ {
+ const rtl::OUString& rQueryStr = rItem.maString;
+ String aCell( mpTransliteration->transliterate(
+ aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
+ NULL ) );
+ String aQuer( mpTransliteration->transliterate(
+ rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
+ NULL ) );
+ xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
+ || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
+ xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_CONTAINS:
+ bOk = ( nStrPos != STRING_NOTFOUND );
+ break;
+ case SC_NOT_EQUAL:
+ case SC_DOES_NOT_CONTAIN:
+ bOk = ( nStrPos == STRING_NOTFOUND );
+ break;
+ case SC_BEGINS_WITH:
+ bOk = ( nStrPos == 0 );
+ break;
+ case SC_DOES_NOT_BEGIN_WITH:
+ bOk = ( nStrPos != 0 );
+ break;
+ case SC_ENDS_WITH:
+ bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+ break;
+ case SC_DOES_NOT_END_WITH:
+ bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ }
+ }
+ else
+ { // use collator here because data was probably sorted
+ sal_Int32 nCompare = mpCollator->compareString(
+ aCellStr, rEntry.GetQueryItem().maString);
+ 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 && mpTestEqualCondition && !bTestEqual )
+ bTestEqual = (nCompare == 0);
+ break;
+ case SC_GREATER_EQUAL :
+ bOk = (nCompare >= 0);
+ if ( bOk && mpTestEqualCondition && !bTestEqual )
+ bTestEqual = (nCompare == 0);
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
}
}
}
- }
- return std::pair<bool,bool>(bOk, bTestEqual);
-}
+ return std::pair<bool,bool>(bOk, bTestEqual);
+ }
+};
}
@@ -1426,11 +1455,7 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
std::vector<bool> aTestEqual(nEntryCount, false);
long nPos = -1;
- bool bMatchWholeCell = pDocument->GetDocOptions().IsMatchWholeCell();
- CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
- ScGlobal::GetCollator());
- ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
- ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
+ QueryEvaluator aEval(*pDocument, *this, rParam, pbTestEqualCondition);
for (size_t i = 0; i < nEntryCount && rParam.GetEntry(i).bDoQuery; ++i)
{
@@ -1441,8 +1466,7 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
if ( !pCell || i > 0 )
pCell = GetCell(nCol, nRow);
- bool bOk = false;
- bool bTestEqual = false;
+ std::pair<bool,bool> aRes(false, false);
// For now, we only handle single item queries. We need to adopt this
// to multi-item queries later.
@@ -1451,47 +1475,40 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
if ( pSpecial && pSpecial[i] )
{
if (rEntry.IsQueryByEmpty())
- bOk = !( aCol[rEntry.nField].HasDataAt( nRow ) );
+ aRes.first = !aCol[rEntry.nField].HasDataAt(nRow);
else
{
OSL_ASSERT(rEntry.IsQueryByNonEmpty());
- bOk = aCol[rEntry.nField].HasDataAt( nRow );
+ aRes.first = aCol[rEntry.nField].HasDataAt(nRow);
}
}
- else if (isQueryByValue(*this, rItem, nCol, nRow, pCell))
+ else if (aEval.isQueryByValue(rItem, nCol, nRow, pCell))
{
- std::pair<bool,bool> res = compareByValue(
- *pDocument, *this, pCell, nCol, nRow, rEntry, rItem, pbTestEqualCondition);
- bOk = res.first;
- bTestEqual = res.second;
+ aRes = aEval.compareByValue(pCell, nCol, nRow, rEntry, rItem);
}
- else if (isQueryByString(*this, rEntry, rItem, nCol, nRow, pCell))
+ else if (aEval.isQueryByString(rEntry, rItem, nCol, nRow, pCell))
{
- std::pair<bool,bool> res = compareByString(
- *pDocument, *this, pCell, nRow, rParam, rEntry, rItem, bMatchWholeCell,
- pTransliteration, pCollator, pbTestEqualCondition);
- bOk = res.first;
- bTestEqual = res.second;
+ aRes = aEval.compareByString(pCell, nRow, rEntry, rItem);
}
if (nPos == -1)
{
nPos++;
- aPassed[nPos] = bOk;
- aTestEqual[nPos] = bTestEqual;
+ aPassed[nPos] = aRes.first;
+ aTestEqual[nPos] = aRes.second;
}
else
{
if (rEntry.eConnect == SC_AND)
{
- aPassed[nPos] = aPassed[nPos] && bOk;
- aTestEqual[nPos] = aTestEqual[nPos] && bTestEqual;
+ aPassed[nPos] = aPassed[nPos] && aRes.first;
+ aTestEqual[nPos] = aTestEqual[nPos] && aRes.second;
}
else
{
nPos++;
- aPassed[nPos] = bOk;
- aTestEqual[nPos] = bTestEqual;
+ aPassed[nPos] = aRes.first;
+ aTestEqual[nPos] = aRes.second;
}
}
}
commit 3b58e5871f6da7be54dad5c1da1c0f0a8378ad73
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 15:04:41 2011 -0500
Marking methods const where possible.
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index c7f0617..041cdaa 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -312,14 +312,14 @@ public:
void SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError);
void GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString );
- void GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString );
+ void GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const;
double GetValue( const ScAddress& rPos ) const
{
return ValidColRow(rPos.Col(),rPos.Row()) ?
aCol[rPos.Col()].GetValue( rPos.Row() ) :
0.0;
}
- double GetValue( SCCOL nCol, SCROW nRow );
+ double GetValue( SCCOL nCol, SCROW nRow ) const;
void GetFormula( SCCOL nCol, SCROW nRow, rtl::OUString& rFormula );
CellType GetCellType( const ScAddress& rPos ) const
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 73c26ba..af10a16 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1067,7 +1067,7 @@ void ScTable::GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString )
}
-void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString )
+void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const
{
if (ValidColRow(nCol,nRow))
aCol[nCol].GetInputString( nRow, rString );
@@ -1076,7 +1076,7 @@ void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString )
}
-double ScTable::GetValue( SCCOL nCol, SCROW nRow )
+double ScTable::GetValue( SCCOL nCol, SCROW nRow ) const
{
if (ValidColRow( nCol, nRow ))
return aCol[nCol].GetValue( nRow );
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 598a833..a7604dd 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1081,7 +1081,7 @@ bool isQueryByValue(
}
std::pair<bool,bool> compareByValue(
- ScDocument& rDoc, ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
+ const ScDocument& rDoc, const ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool* pbTestEqualCondition)
{
bool bOk = false;
@@ -1237,7 +1237,7 @@ bool isTestRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry, bool*
}
std::pair<bool,bool> compareByString(
- ScDocument& rDoc, ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
+ const ScDocument& rDoc, const ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
const ScQueryParam& rParam, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool bMatchWholeCell,
::utl::TransliterationWrapper* pTransliteration, CollatorWrapper* pCollator,
bool* pbTestEqualCondition)
@@ -1254,7 +1254,7 @@ std::pair<bool,bool> compareByString(
if (pCell->GetCellType() != CELLTYPE_NOTE)
{
sal_uLong nFormat = rTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
- ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(rDoc.GetFormatTable()) );
+ ScCellFormat::GetInputString(pCell, nFormat, aCellStr, *rDoc.GetFormatTable());
}
}
else
commit 05dc62da44f0853bebf68e6f6c695900090a15ba
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date: Mon Nov 14 14:18:59 2011 -0500
Extracted compare-by-value and compare-by-string into functions.
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 4539055..598a833 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1080,6 +1080,92 @@ bool isQueryByValue(
return rTable.HasValueData(nCol, nRow);
}
+std::pair<bool,bool> compareByValue(
+ ScDocument& rDoc, ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
+ const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool* pbTestEqualCondition)
+{
+ bool bOk = false;
+ bool bTestEqual = false;
+ double nCellVal;
+ if ( pCell )
+ {
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ nCellVal = ((ScValueCell*)pCell)->GetValue();
+ break;
+ case CELLTYPE_FORMULA :
+ nCellVal = ((ScFormulaCell*)pCell)->GetValue();
+ break;
+ default:
+ nCellVal = 0.0;
+ }
+
+ }
+ else
+ nCellVal = rTab.GetValue(nCol, nRow);
+
+ /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
+ * date+time format was queried rEntry.bQueryByDate is not set. In
+ * case other queries wanted to use this mechanism they should do
+ * the same, in other words only if rEntry.nVal is an integer value
+ * rEntry.bQueryByDate should be true and the time fraction be
+ * stripped here. */
+ if (rItem.meType == ScQueryEntry::ByDate)
+ {
+ sal_uInt32 nNumFmt = rTab.GetNumberFormat(nCol, nRow);
+ const SvNumberformat* pEntry = rDoc.GetFormatTable()->GetEntry(nNumFmt);
+ if (pEntry)
+ {
+ short nNumFmtType = pEntry->GetType();
+ /* NOTE: Omitting the check for absence of
+ * NUMBERFORMAT_TIME would include also date+time formatted
+ * values of the same day. That may be desired in some
+ * cases, querying all time values of a day, but confusing
+ * in other cases. A user can always setup a standard
+ * filter query for x >= date AND x < date+1 */
+ if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
+ {
+ // The format is of date type. Strip off the time
+ // element.
+ nCellVal = ::rtl::math::approxFloor(nCellVal);
+ }
+ }
+ }
+
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL :
+ bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ break;
+ case SC_LESS :
+ bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ break;
+ case SC_GREATER :
+ bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ break;
+ case SC_LESS_EQUAL :
+ bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ if ( bOk && pbTestEqualCondition )
+ bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ break;
+ case SC_GREATER_EQUAL :
+ bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
+ if ( bOk && pbTestEqualCondition )
+ bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ break;
+ case SC_NOT_EQUAL :
+ bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+
+ return std::pair<bool,bool>(bOk, bTestEqual);
+}
+
bool isPartialTextMatchOp(const ScQueryEntry& rEntry)
{
switch (rEntry.eOp)
@@ -1150,6 +1236,180 @@ bool isTestRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry, bool*
return (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL);
}
+std::pair<bool,bool> compareByString(
+ ScDocument& rDoc, ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
+ const ScQueryParam& rParam, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool bMatchWholeCell,
+ ::utl::TransliterationWrapper* pTransliteration, CollatorWrapper* pCollator,
+ bool* pbTestEqualCondition)
+{
+ bool bOk = false;
+ bool bTestEqual = false;
+ rtl::OUString aCellStr;
+ if (isPartialTextMatchOp(rEntry))
+ // may have to do partial textural comparison.
+ bMatchWholeCell = false;
+
+ if ( pCell )
+ {
+ if (pCell->GetCellType() != CELLTYPE_NOTE)
+ {
+ sal_uLong nFormat = rTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
+ ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(rDoc.GetFormatTable()) );
+ }
+ }
+ else
+ rTab.GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
+
+ bool bRealRegExp = isRealRegExp(rParam, rEntry);
+ bool bTestRegExp = isTestRegExp(rParam, rEntry, pbTestEqualCondition);
+
+ if ( bRealRegExp || bTestRegExp )
+ {
+ xub_StrLen nStart = 0;
+ xub_StrLen nEnd = aCellStr.getLength();
+
+ // from 614 on, nEnd is behind the found text
+ bool bMatch = false;
+ if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+ {
+ nEnd = 0;
+ nStart = aCellStr.getLength();
+ bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+ ->SearchBkwrd( aCellStr, &nStart, &nEnd );
+ }
+ else
+ {
+ bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+ ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+ }
+ if ( bMatch && bMatchWholeCell
+ && (nStart != 0 || nEnd != aCellStr.getLength()) )
+ bMatch = false; // RegExp must match entire cell string
+ if ( bRealRegExp )
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_CONTAINS:
+ bOk = bMatch;
+ break;
+ case SC_NOT_EQUAL:
+ case SC_DOES_NOT_CONTAIN:
+ bOk = !bMatch;
+ break;
+ case SC_BEGINS_WITH:
+ bOk = ( bMatch && (nStart == 0) );
+ break;
+ case SC_DOES_NOT_BEGIN_WITH:
+ bOk = !( bMatch && (nStart == 0) );
+ break;
+ case SC_ENDS_WITH:
+ bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
+ break;
+ case SC_DOES_NOT_END_WITH:
+ bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ else
+ bTestEqual = bMatch;
+ }
+ if ( !bRealRegExp )
+ {
+ // Simple string matching i.e. no regexp match.
+ if (isTextMatchOp(rEntry))
+ {
+ if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
+ {
+ // #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.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
+ else if ( bMatchWholeCell )
+ {
+ bOk = pTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
+ if ( rEntry.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
+ else
+ {
+ const rtl::OUString& rQueryStr = rItem.maString;
+ String aCell( pTransliteration->transliterate(
+ aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
+ NULL ) );
+ String aQuer( pTransliteration->transliterate(
+ rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
+ NULL ) );
+ xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
+ || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
+ xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_CONTAINS:
+ bOk = ( nStrPos != STRING_NOTFOUND );
+ break;
+ case SC_NOT_EQUAL:
+ case SC_DOES_NOT_CONTAIN:
+ bOk = ( nStrPos == STRING_NOTFOUND );
+ break;
+ case SC_BEGINS_WITH:
+ bOk = ( nStrPos == 0 );
+ break;
+ case SC_DOES_NOT_BEGIN_WITH:
+ bOk = ( nStrPos != 0 );
+ break;
+ case SC_ENDS_WITH:
+ bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+ break;
+ case SC_DOES_NOT_END_WITH:
+ bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ }
+ }
+ else
+ { // use collator here because data was probably sorted
+ sal_Int32 nCompare = pCollator->compareString(
+ aCellStr, rEntry.GetQueryItem().maString);
+ 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:
+ {
+ // added to avoid warnings
+ }
+ }
+ }
+ }
+
+ return std::pair<bool,bool>(bOk, bTestEqual);
+}
+
}
bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
@@ -1200,247 +1460,18 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
}
else if (isQueryByValue(*this, rItem, nCol, nRow, pCell))
{
- double nCellVal;
- if ( pCell )
- {
- switch ( pCell->GetCellType() )
- {
- case CELLTYPE_VALUE :
- nCellVal = ((ScValueCell*)pCell)->GetValue();
- break;
- case CELLTYPE_FORMULA :
- nCellVal = ((ScFormulaCell*)pCell)->GetValue();
- break;
- default:
- nCellVal = 0.0;
- }
-
- }
- else
- nCellVal = GetValue(nCol, nRow);
-
- /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
- * date+time format was queried rEntry.bQueryByDate is not set. In
- * case other queries wanted to use this mechanism they should do
- * the same, in other words only if rEntry.nVal is an integer value
- * rEntry.bQueryByDate should be true and the time fraction be
- * stripped here. */
- if (rItem.meType == ScQueryEntry::ByDate)
- {
- sal_uInt32 nNumFmt = GetNumberFormat(nCol, nRow);
- const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt);
- if (pEntry)
- {
- short nNumFmtType = pEntry->GetType();
- /* NOTE: Omitting the check for absence of
- * NUMBERFORMAT_TIME would include also date+time formatted
- * values of the same day. That may be desired in some
- * cases, querying all time values of a day, but confusing
- * in other cases. A user can always setup a standard
- * filter query for x >= date AND x < date+1 */
- if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
- {
- // The format is of date type. Strip off the time
- // element.
- nCellVal = ::rtl::math::approxFloor(nCellVal);
- }
- }
- }
-
- switch (rEntry.eOp)
- {
- case SC_EQUAL :
- bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_LESS :
- bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_GREATER :
- bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_LESS_EQUAL :
- bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- if ( bOk && pbTestEqualCondition )
- bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_GREATER_EQUAL :
- bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
- if ( bOk && pbTestEqualCondition )
- bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- case SC_NOT_EQUAL :
- bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
- break;
- default:
- {
- // added to avoid warnings
- }
- }
+ std::pair<bool,bool> res = compareByValue(
+ *pDocument, *this, pCell, nCol, nRow, rEntry, rItem, pbTestEqualCondition);
+ bOk = res.first;
+ bTestEqual = res.second;
}
else if (isQueryByString(*this, rEntry, rItem, nCol, nRow, pCell))
{
- rtl::OUString aCellStr;
- if (isPartialTextMatchOp(rEntry))
- // may have to do partial textural comparison.
- bMatchWholeCell = false;
-
- if ( pCell )
- {
- if (pCell->GetCellType() != CELLTYPE_NOTE)
- {
- sal_uLong nFormat = GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
- ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(pDocument->GetFormatTable()) );
- }
- }
- else
- GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
-
- bool bRealRegExp = isRealRegExp(rParam, rEntry);
- bool bTestRegExp = isTestRegExp(rParam, rEntry, pbTestEqualCondition);
-
- if ( bRealRegExp || bTestRegExp )
- {
- xub_StrLen nStart = 0;
- xub_StrLen nEnd = aCellStr.getLength();
-
- // from 614 on, nEnd is behind the found text
- bool bMatch = false;
- if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
- {
- nEnd = 0;
- nStart = aCellStr.getLength();
- bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchBkwrd( aCellStr, &nStart, &nEnd );
- }
- else
- {
- bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchFrwrd( aCellStr, &nStart, &nEnd );
- }
- if ( bMatch && bMatchWholeCell
- && (nStart != 0 || nEnd != aCellStr.getLength()) )
- bMatch = false; // RegExp must match entire cell string
- if ( bRealRegExp )
- switch (rEntry.eOp)
- {
- case SC_EQUAL:
- case SC_CONTAINS:
- bOk = bMatch;
- break;
- case SC_NOT_EQUAL:
- case SC_DOES_NOT_CONTAIN:
- bOk = !bMatch;
- break;
- case SC_BEGINS_WITH:
- bOk = ( bMatch && (nStart == 0) );
- break;
- case SC_DOES_NOT_BEGIN_WITH:
- bOk = !( bMatch && (nStart == 0) );
- break;
- case SC_ENDS_WITH:
- bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
- break;
- case SC_DOES_NOT_END_WITH:
- bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- else
- bTestEqual = bMatch;
- }
- if ( !bRealRegExp )
- {
- // Simple string matching i.e. no regexp match.
- if (isTextMatchOp(rEntry))
- {
- if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
- {
- // #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.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
- }
- else if ( bMatchWholeCell )
- {
- bOk = pTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
- if ( rEntry.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
- }
- else
- {
- const rtl::OUString& rQueryStr = rItem.maString;
- String aCell( pTransliteration->transliterate(
- aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
- NULL ) );
- String aQuer( pTransliteration->transliterate(
- rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
- NULL ) );
- xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
- || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
- xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
- switch (rEntry.eOp)
- {
- case SC_EQUAL:
- case SC_CONTAINS:
- bOk = ( nStrPos != STRING_NOTFOUND );
- break;
- case SC_NOT_EQUAL:
- case SC_DOES_NOT_CONTAIN:
- bOk = ( nStrPos == STRING_NOTFOUND );
- break;
- case SC_BEGINS_WITH:
- bOk = ( nStrPos == 0 );
- break;
- case SC_DOES_NOT_BEGIN_WITH:
- bOk = ( nStrPos != 0 );
- break;
- case SC_ENDS_WITH:
- bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
- break;
- case SC_DOES_NOT_END_WITH:
- bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- }
- }
- else
- { // use collator here because data was probably sorted
- sal_Int32 nCompare = pCollator->compareString(
- aCellStr, rEntry.GetQueryItem().maString);
- 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:
- {
- // added to avoid warnings
- }
- }
- }
- }
+ std::pair<bool,bool> res = compareByString(
+ *pDocument, *this, pCell, nRow, rParam, rEntry, rItem, bMatchWholeCell,
+ pTransliteration, pCollator, pbTestEqualCondition);
+ bOk = res.first;
+ bTestEqual = res.second;
}
if (nPos == -1)
More information about the Libreoffice-commits
mailing list