[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