[Libreoffice-commits] core.git: Branch 'feature/cib_contract138' - sc/inc sc/source
Katarina Behrens
Katarina.Behrens at cib.de
Thu Mar 23 17:43:57 UTC 2017
Rebased ref, commits from common ancestor:
commit 6b18ef78db8ba4cb816dcbb51a2e7e7a7bbc7195
Author: Katarina Behrens <Katarina.Behrens at cib.de>
Date: Thu Mar 9 10:08:06 2017 +0100
tdf#35636: Match also empty cells (backport of the idea)
Change-Id: I11fc198ef43250618b43e3c11e7c192accc6b7b8
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index cfffb7ef2f56..ac19951e50dc 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -284,7 +284,7 @@ private:
bool bAdvanceQuery;
bool bIgnoreMismatchOnLeadingStrings;
- ScBaseCell* GetThis();
+ bool GetThis();
/* Only works if no regular expression is involved, only
searches for rows in one column, and only the first
@@ -302,8 +302,8 @@ public:
const ScQueryParam& aParam, bool bMod = true);
// for bMod = FALSE the QueryParam has to be filled
// (bIsString)
- ScBaseCell* GetFirst();
- ScBaseCell* GetNext();
+ bool GetFirst();
+ bool GetNext();
SCCOL GetCol() { return nCol; }
SCROW GetRow() { return nRow; }
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 08a2f811fd77..7c67aa19558f 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -42,8 +42,9 @@ struct SC_DLLPUBLIC ScQueryEntry
QueryType meType;
double mfVal;
OUString maString;
+ bool mbMatchEmpty;
- Item() : meType(ByValue), mfVal(0.0) {}
+ Item() : meType(ByValue), mfVal(0.0), mbMatchEmpty(false) {}
bool operator== (const Item& r) const;
};
diff --git a/sc/inc/queryparam.hxx b/sc/inc/queryparam.hxx
index 445c23c06aac..6fb95b03b1b3 100644
--- a/sc/inc/queryparam.hxx
+++ b/sc/inc/queryparam.hxx
@@ -25,6 +25,8 @@
#include <boost/ptr_container/ptr_vector.hpp>
+class SvNumberFormatter;
+
struct ScDBQueryParamInternal;
struct ScQueryEntry;
@@ -49,7 +51,8 @@ struct ScQueryParamBase
ScQueryEntry* FindEntryByField(SCCOLROW nField, bool bNew);
SC_DLLPUBLIC void RemoveEntryByField(SCCOLROW nField);
void Resize(size_t nNew);
- void FillInExcelSyntax(const OUString& aCellStr, SCSIZE nIndex);
+ void FillInExcelSyntax(const OUString& aCellStr, SCSIZE nIndex,
+ SvNumberFormatter* pFormatter);
protected:
typedef boost::ptr_vector<ScQueryEntry> EntriesType;
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index e050e5816c5a..d31f17038b26 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -56,6 +56,23 @@ namespace
{
rStr = ScGlobal::pCharClass->uppercase(rStr.trim());
}
+
+ void lcl_FillBlankCells( std::vector<ColEntry> &rSrcCols, std::vector<ColEntry> &rDestCols, SCROW nLastRow )
+ {
+ for( SCROW i = 0, n = 0; i <= nLastRow; ++i )
+ {
+ rDestCols.push_back(ColEntry());
+ rDestCols.back().nRow = i;
+
+ if ( rSrcCols[n].nRow == i )
+ {
+ rDestCols.back().pCell = rSrcCols[n].pCell;
+ ++n;
+ }
+ else
+ rDestCols.back().pCell = NULL;
+ }
+ }
}
ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
@@ -1178,7 +1195,7 @@ ScQueryCellIterator::ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
nAttrEndRow = 0;
}
-ScBaseCell* ScQueryCellIterator::GetThis()
+bool ScQueryCellIterator::GetThis()
{
if (nTab >= pDoc->GetTableCount())
OSL_FAIL("try to access index out of bounds, FIX IT");
@@ -1193,6 +1210,18 @@ ScBaseCell* ScQueryCellIterator::GetThis()
!mpParam->bHasHeader && rItem.meType == ScQueryEntry::ByString &&
((mpParam->bByRow && nRow == mpParam->nRow1) ||
(!mpParam->bByRow && nCol == mpParam->nCol1));
+
+ bool bMatchEmpty = ( rItem.mbMatchEmpty && rEntry.GetQueryItems().size() == 1 );
+
+ std::vector<ColEntry> rColItems;
+ if ( !bMatchEmpty )
+ rColItems = pCol->maItems;
+ else
+ {
+ SCROW nLastRow = pCol->maItems.back().nRow;
+ lcl_FillBlankCells( pCol->maItems, rColItems, std::max(nLastRow, mpParam->nRow2) );
+ }
+
for ( ;; )
{
if ( nRow > mpParam->nRow2 )
@@ -1203,7 +1232,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
do
{
if ( ++nCol > mpParam->nCol2 )
- return NULL; // Over and out
+ return false; // Over and out
if ( bAdvanceQuery )
{
AdvanceQueryParamEntryField();
@@ -1217,13 +1246,19 @@ ScBaseCell* ScQueryCellIterator::GetThis()
mpParam->bByRow;
}
- while ( nColRow < pCol->maItems.size() && pCol->maItems[nColRow].nRow < nRow )
+ while ( nColRow < rColItems.size() && rColItems[nColRow].nRow < nRow )
nColRow++;
- if ( nColRow < pCol->maItems.size() &&
- (nRow = pCol->maItems[nColRow].nRow) <= mpParam->nRow2 )
+ if ( nColRow < rColItems.size() &&
+ (nRow = rColItems[nColRow].nRow) <= mpParam->nRow2 )
{
- ScBaseCell* pCell = pCol->maItems[nColRow].pCell;
+ ScBaseCell* pCell = rColItems[nColRow].pCell;
+
+ // empty cell when empty cells should be matched
+ if ( bMatchEmpty && ( pCell == NULL ) )
+ return true;
+
+
if (bAllStringIgnore && pCell->HasStringData())
++nRow;
else
@@ -1235,7 +1270,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
{
if ( nTestEqualCondition && bTestEqualCondition )
nTestEqualCondition |= nTestEqualConditionMatched;
- return pCell; // Found it!
+ return true; // Found it!
}
else if ( nStopOnMismatch )
{
@@ -1246,7 +1281,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
{
nTestEqualCondition |= nTestEqualConditionMatched;
nStopOnMismatch |= nStopOnMismatchOccurred;
- return NULL;
+ return false;
}
bool bStop;
if (bFirstStringIgnore)
@@ -1264,7 +1299,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
if (bStop)
{
nStopOnMismatch |= nStopOnMismatchOccurred;
- return NULL;
+ return false;
}
}
else
@@ -1277,7 +1312,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
}
}
-ScBaseCell* ScQueryCellIterator::GetFirst()
+bool ScQueryCellIterator::GetFirst()
{
if (nTab >= pDoc->GetTableCount())
OSL_FAIL("try to access index out of bounds, FIX IT");
@@ -1290,7 +1325,7 @@ ScBaseCell* ScQueryCellIterator::GetFirst()
return GetThis();
}
-ScBaseCell* ScQueryCellIterator::GetNext()
+bool ScQueryCellIterator::GetNext()
{
++nRow;
if ( nStopOnMismatch )
@@ -1363,17 +1398,17 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
{
// First equal entry or last smaller than (greater than) entry.
SCSIZE nColRowSave;
- ScBaseCell* pNext = 0;
+ bool bNext = false;
do
{
nFoundCol = GetCol();
nFoundRow = GetRow();
nColRowSave = nColRow;
- } while ( !IsEqualConditionFulfilled() && (pNext = GetNext()) != NULL );
+ } while ( !IsEqualConditionFulfilled() && (bNext = GetNext() ) );
// There may be no pNext but equal condition fulfilled if regular
// expressions are involved. Keep the found entry and proceed.
- if (!pNext && !IsEqualConditionFulfilled())
+ if (!bNext && !IsEqualConditionFulfilled())
{
// Step back to last in range and adjust position markers for
// GetNumberFormat() or similar.
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 73f952ddc9e0..d13992d5f7aa 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -2041,7 +2041,7 @@ bool ScTable::CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow
if (nIndex < nNewEntries)
{
rQueryParam.GetEntry(nIndex).nField = pFields[nCol - nCol1];
- rQueryParam.FillInExcelSyntax(aCellStr, nIndex);
+ rQueryParam.FillInExcelSyntax(aCellStr, nIndex, NULL);
nIndex++;
if (nIndex < nNewEntries)
rQueryParam.GetEntry(nIndex).eConnect = SC_AND;
diff --git a/sc/source/core/tool/doubleref.cxx b/sc/source/core/tool/doubleref.cxx
index f7d873cb61a8..94976d488845 100644
--- a/sc/source/core/tool/doubleref.cxx
+++ b/sc/source/core/tool/doubleref.cxx
@@ -185,7 +185,7 @@ bool lcl_createExcelQuery(
if (nIndex < nNewEntries)
{
pParam->GetEntry(nIndex).nField = aFields[nCol];
- pParam->FillInExcelSyntax(OUString(aCellStr), nIndex);
+ pParam->FillInExcelSyntax(OUString(aCellStr), nIndex, NULL);
nIndex++;
if (nIndex < nNewEntries)
pParam->GetEntry(nIndex).eConnect = SC_AND;
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index a03b13a3c5a7..19d5544d641d 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5700,11 +5700,7 @@ double ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc )
}
else
{
- rParam.FillInExcelSyntax(aString, 0);
- sal_uInt32 nIndex = 0;
- bool bNumber = pFormatter->IsNumberFormat(
- rItem.maString, nIndex, rItem.mfVal);
- rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
+ rParam.FillInExcelSyntax(aString, 0, pFormatter);
if (rItem.meType == ScQueryEntry::ByString)
rParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
}
@@ -6003,11 +5999,7 @@ void ScInterpreter::ScCountIf()
}
else
{
- rParam.FillInExcelSyntax(aString, 0);
- sal_uInt32 nIndex = 0;
- bool bNumber = pFormatter->IsNumberFormat(
- rItem.maString, nIndex, rItem.mfVal);
- rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
+ rParam.FillInExcelSyntax(aString, 0, pFormatter);
if (rItem.meType == ScQueryEntry::ByString)
rParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
}
@@ -6255,11 +6247,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
}
else
{
- rParam.FillInExcelSyntax(aString, 0);
- sal_uInt32 nIndex = 0;
- bool bNumber = pFormatter->IsNumberFormat(
- rItem.maString, nIndex, rItem.mfVal);
- rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
+ rParam.FillInExcelSyntax(aString, 0, pFormatter);
if (rItem.meType == ScQueryEntry::ByString)
rParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
}
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index 1ac1a899327b..53ffb5d80aba 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -32,7 +32,7 @@
bool ScQueryEntry::Item::operator== (const Item& r) const
{
- return meType == r.meType && mfVal == r.mfVal && maString.equals(r.maString);
+ return meType == r.meType && mfVal == r.mfVal && maString.equals(r.maString) && mbMatchEmpty == r.mbMatchEmpty;
}
ScQueryEntry::ScQueryEntry() :
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
index 781816a3d9e5..8ebf5e974d55 100644
--- a/sc/source/core/tool/queryparam.cxx
+++ b/sc/source/core/tool/queryparam.cxx
@@ -20,6 +20,8 @@
#include "queryparam.hxx"
#include "queryentry.hxx"
+#include <svl/zforlist.hxx>
+
namespace {
const size_t MAXQUERY = 8;
@@ -166,17 +168,17 @@ void ScQueryParamBase::Resize(size_t nNew)
}
}
-void ScQueryParamBase::FillInExcelSyntax(const OUString& rStr, SCSIZE nIndex)
+void ScQueryParamBase::FillInExcelSyntax(const OUString& rStr, SCSIZE nIndex, SvNumberFormatter *pFormatter)
{
const String aCellStr = rStr;
- if (aCellStr.Len() > 0)
- {
- if ( nIndex >= maEntries.size() )
- Resize( nIndex+1 );
+ if ( nIndex >= maEntries.size() )
+ Resize( nIndex+1 );
- ScQueryEntry& rEntry = GetEntry(nIndex);
- ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
+ ScQueryEntry& rEntry = GetEntry(nIndex);
+ ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
+ if (aCellStr.Len() > 0)
+ {
rEntry.bDoQuery = sal_True;
// Operatoren herausfiltern
if (aCellStr.GetChar(0) == '<')
@@ -218,6 +220,21 @@ void ScQueryParamBase::FillInExcelSyntax(const OUString& rStr, SCSIZE nIndex)
rItem.maString = aCellStr;
rEntry.eOp = SC_EQUAL;
}
+
+ }
+
+ if (pFormatter)
+ {
+ sal_uInt32 nFormat = 0;
+ bool bNumber = pFormatter->IsNumberFormat( rItem.maString, nFormat, rItem.mfVal);
+ rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
+
+ /* TODO: pFormatter currently is also used as a flag whether matching
+ * empty cells with an empty string is triggered from the interpreter.
+ * This could be handled independently if all queries should support
+ * it, needs to be evaluated if that actually is desired. */
+ if (rItem.meType == ScQueryEntry::ByString)
+ rItem.mbMatchEmpty = (rEntry.eOp == SC_EQUAL && rItem.maString.isEmpty());
}
}
More information about the Libreoffice-commits
mailing list