[Libreoffice-commits] core.git: Branch 'libreoffice-4-2' - 2 commits - sc/inc sc/source

Eike Rathke erack at redhat.com
Wed Nov 27 16:05:33 PST 2013


 sc/inc/queryparam.hxx                     |    1 
 sc/source/core/data/dociter.cxx           |   62 +++++++++++++++++++++++++++++-
 sc/source/core/data/table3.cxx            |   42 ++++++++++++++++++++
 sc/source/core/tool/queryparam.cxx        |    5 +-
 sc/source/filter/oox/workbookfragment.cxx |    2 
 5 files changed, 107 insertions(+), 5 deletions(-)

New commits:
commit a0fea02736c8ecfa091676a066bf02503be1f7c4
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Nov 28 01:04:27 2013 +0100

    macro "MULTI_THREAD_SHEET_PARSING" is not used [-Werror=unused-macros]
    
    Change-Id: I1988e28f1feb64bb10c7941b02d9a76770871449

diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx
index 5eea78b..485642c 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -54,8 +54,6 @@
 #include <queue>
 #include <boost/scoped_ptr.hpp>
 
-#define MULTI_THREAD_SHEET_PARSING 0
-
 #include "oox/ole/vbaproject.hxx"
 
 namespace oox {
commit 799ac18af53342597a5d3f14702de2204536c14b
Author: Eike Rathke <erack at redhat.com>
Date:   Wed Nov 27 23:43:09 2013 +0100

    resolved fdo#71589 reimplemented horizontal range lookup
    
    Regression introduced with ebdd9c300718bce454ef56a31d5d8fb699fc1822
    (first eaea417bfdf8d06df2b7f2e42c904c32ce77e871) that removed the
    bMixedComparison member from ScQueryParam under the false assumption
    that is was only used to emulate a legacy Excel behavior. In fact it was
    also needed to do the at least horizontal range lookup in sorted mixed
    data, though didn't evaluate exactly the same conditions as Excel and
    defined in ODFF.
    
    Reimplemented a similar behavior for the new code structures but this
    time also checking for the additional condtion that a query ByString
    does not return the last numeric result and vice versa, which previously
    was missing.
    
    Change-Id: I46061777879ba5301bfcaca2d50cf87a994f93f2
    (cherry picked from commit f0701470858f57a855ba57c0c2283e52953db327)

diff --git a/sc/inc/queryparam.hxx b/sc/inc/queryparam.hxx
index ff89d3e..a0e94f8 100644
--- a/sc/inc/queryparam.hxx
+++ b/sc/inc/queryparam.hxx
@@ -42,6 +42,7 @@ struct ScQueryParamBase
     bool            bCaseSens;
     bool            bRegExp;
     bool            bDuplicate;
+    bool            mbRangeLookup;      ///< for spreadsheet functions like MATCH, LOOKUP, HLOOKUP, VLOOKUP
 
     virtual ~ScQueryParamBase();
 
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 3277d36..565565f 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -1245,6 +1245,17 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
         SCROW& nFoundRow, bool bSearchForEqualAfterMismatch,
         bool bIgnoreMismatchOnLeadingStringsP )
 {
+    // Set and automatically reset mpParam->mbRangeLookup when returning. We
+    // could use comphelper::FlagRestorationGuard, but really, that one is
+    // overengineered for this simple purpose here.
+    struct BoolResetter
+    {
+        bool& mr;
+        bool  mb;
+        BoolResetter( bool& r, bool b ) : mr(r), mb(r) { r = b; }
+        ~BoolResetter() { mr = mb; }
+    } aRangeLookupResetter( mpParam->mbRangeLookup, true);
+
     nFoundCol = MAXCOL+1;
     nFoundRow = MAXROW+1;
     SetStopOnMismatch( true ); // assume sorted keys
@@ -1253,7 +1264,22 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
     bool bRegExp = mpParam->bRegExp && mpParam->GetEntry(0).GetQueryItem().meType == ScQueryEntry::ByString;
     bool bBinary = !bRegExp && mpParam->bByRow && (mpParam->GetEntry(0).eOp ==
             SC_LESS_EQUAL || mpParam->GetEntry(0).eOp == SC_GREATER_EQUAL);
-    if (bBinary ? (BinarySearch() ? GetThis() : 0) : GetFirst())
+    bool bFound = false;
+    if (bBinary)
+    {
+        if (BinarySearch())
+        {
+            // BinarySearch() already positions correctly and only needs real
+            // query comparisons afterwards, skip the verification check below.
+            mpParam->mbRangeLookup = false;
+            bFound = GetThis();
+        }
+    }
+    else
+    {
+        bFound = GetFirst();
+    }
+    if (bFound)
     {
         // First equal entry or last smaller than (greater than) entry.
         PositionType aPosSave;
@@ -1272,9 +1298,43 @@ bool ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL& nFoundCol,
         {
             // Step back to last in range and adjust position markers for
             // GetNumberFormat() or similar.
+            SCCOL nColDiff = nCol - nFoundCol;
             nCol = nFoundCol;
             nRow = nFoundRow;
             maCurPos = aPosSave;
+            if (mpParam->mbRangeLookup)
+            {
+                // Verify that the found entry does not only fulfill the range
+                // lookup but also the real query, i.e. not numeric was found
+                // if query is ByString and vice versa.
+                mpParam->mbRangeLookup = false;
+                // Step back the last field advance if GetNext() did one.
+                if (bAdvanceQuery && nColDiff)
+                {
+                    SCSIZE nEntries = mpParam->GetEntryCount();
+                    for (SCSIZE j=0; j < nEntries; ++j)
+                    {
+                        ScQueryEntry& rEntry = mpParam->GetEntry( j );
+                        if (rEntry.bDoQuery)
+                        {
+                            if (rEntry.nField - nColDiff >= 0)
+                                rEntry.nField -= nColDiff;
+                            else
+                            {
+                                assert(!"FindEqualOrSortedLastInRange: rEntry.nField -= nColDiff < 0");
+                            }
+                        }
+                        else
+                            break;  // for
+                    }
+                }
+                // Check it.
+                if (!GetThis())
+                {
+                    nFoundCol = MAXCOL+1;
+                    nFoundRow = MAXROW+1;
+                }
+            }
         }
     }
     if ( IsEqualConditionFulfilled() )
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 05c43c3..a927485 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1513,6 +1513,41 @@ public:
 
         return std::pair<bool,bool>(bOk, bTestEqual);
     }
+
+    // To be called only if both isQueryByValue() and isQueryByString()
+    // returned false and range lookup is wanted! In range lookup comparison
+    // numbers are less than strings. Nothing else is compared.
+    std::pair<bool,bool> compareByRangeLookup(
+        const ScRefCellValue& rCell, SCCOL nCol, SCROW nRow,
+        const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem)
+    {
+        bool bTestEqual = false;
+
+        if (rItem.meType == ScQueryEntry::ByString && rEntry.eOp != SC_LESS && rEntry.eOp != SC_LESS_EQUAL)
+            return std::pair<bool,bool>(false, bTestEqual);
+
+        if (rItem.meType != ScQueryEntry::ByString && rEntry.eOp != SC_GREATER && rEntry.eOp != SC_GREATER_EQUAL)
+            return std::pair<bool,bool>(false, bTestEqual);
+
+        if (!rCell.isEmpty())
+        {
+            if (rItem.meType == ScQueryEntry::ByString)
+            {
+                if (rCell.meType == CELLTYPE_FORMULA && rCell.mpFormula->GetErrCode())
+                    // Error values are compared as string.
+                    return std::pair<bool,bool>(false, bTestEqual);
+
+                return std::pair<bool,bool>(rCell.hasNumeric(), bTestEqual);
+            }
+
+            return std::pair<bool,bool>(!rCell.hasNumeric(), bTestEqual);
+        }
+
+        if (rItem.meType == ScQueryEntry::ByString)
+            return std::pair<bool,bool>(mrTab.HasValueData(nCol, nRow), bTestEqual);
+
+        return std::pair<bool,bool>(!mrTab.HasValueData(nCol, nRow), bTestEqual);
+    }
 };
 
 }
@@ -1578,6 +1613,13 @@ bool ScTable::ValidQuery(
                     aRes.first |= aThisRes.first;
                     aRes.second |= aThisRes.second;
                 }
+                else if (rParam.mbRangeLookup)
+                {
+                    std::pair<bool,bool> aThisRes =
+                        aEval.compareByRangeLookup(aCell, nCol, nRow, rEntry, *itr);
+                    aRes.first |= aThisRes.first;
+                    aRes.second |= aThisRes.second;
+                }
 
                 if (aRes.first && aRes.second)
                     break;
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
index 071c345..e7f73ca 100644
--- a/sc/source/core/tool/queryparam.cxx
+++ b/sc/source/core/tool/queryparam.cxx
@@ -64,7 +64,8 @@ ScQueryParamBase::ScQueryParamBase() :
     bInplace(true),
     bCaseSens(false),
     bRegExp(false),
-    bDuplicate(false)
+    bDuplicate(false),
+    mbRangeLookup(false)
 {
     for (size_t i = 0; i < MAXQUERY; ++i)
         maEntries.push_back(new ScQueryEntry);
@@ -72,7 +73,7 @@ ScQueryParamBase::ScQueryParamBase() :
 
 ScQueryParamBase::ScQueryParamBase(const ScQueryParamBase& r) :
     bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
-    bRegExp(r.bRegExp), bDuplicate(r.bDuplicate),
+    bRegExp(r.bRegExp), bDuplicate(r.bDuplicate), mbRangeLookup(r.mbRangeLookup),
     maEntries(r.maEntries)
 {
 }


More information about the Libreoffice-commits mailing list