[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 2 commits - sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Mon Jul 1 21:52:03 PDT 2013


 sc/inc/column.hxx                   |    1 
 sc/inc/formulacell.hxx              |    5 
 sc/inc/token.hxx                    |   13 --
 sc/source/core/data/column.cxx      |   56 ++++++++-
 sc/source/core/data/formulacell.cxx |    5 
 sc/source/core/tool/interpr1.cxx    |  219 ++++++++++++++++++++++++++++++------
 sc/source/core/tool/token.cxx       |   12 +
 7 files changed, 258 insertions(+), 53 deletions(-)

New commits:
commit e603b646f3cd4f0b7ffbf6aa206f476923d2a3ff
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 00:51:10 2013 -0400

    Re-implement SUM function to make use of new cell storage.
    
    And fix a bug in my new COUNT function, where I forgot to tally numeric
    formula cells.
    
    Change-Id: I52d26be3e48f646f656821066e23594d52f78c6d

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 7ce53ad..359b8ac 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -409,6 +409,7 @@ public:
     void        ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark );
     void        ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark );
 
+    double SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
     size_t CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
 
     long GetNeededSize(
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 8d3f625..64aae03 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -468,18 +468,57 @@ void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
 
 namespace {
 
+class NumericCellAccumulator
+{
+    double mfSum;
+public:
+    NumericCellAccumulator() : mfSum(0.0) {}
+
+    void operator() (size_t, double fVal)
+    {
+        mfSum += fVal;
+    }
+
+    void operator() (size_t, const ScFormulaCell* pCell)
+    {
+        ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
+        if (rCell.IsValue())
+            mfSum += rCell.GetValue();
+    }
+
+    double getSum() const { return mfSum; }
+};
+
 class NumericCellCounter
 {
     size_t mnCount;
 public:
     NumericCellCounter() : mnCount(0) {}
 
-    void operator() (const sc::CellStoreType::value_type& rNode, size_t /*nOffset*/, size_t nDataSize)
+    void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
     {
-        if (rNode.type != sc::element_type_numeric)
-            return;
-
-        mnCount += nDataSize;
+        switch (rNode.type)
+        {
+            case sc::element_type_numeric:
+                mnCount += nDataSize;
+            break;
+            case sc::element_type_formula:
+            {
+                sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
+                std::advance(it, nOffset);
+                sc::formula_block::const_iterator itEnd = it;
+                std::advance(itEnd, nDataSize);
+                for (; it != itEnd; ++it)
+                {
+                    ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
+                    if (rCell.IsValue())
+                        ++mnCount;
+                }
+            }
+            break;
+            default:
+                ;
+        }
     }
 
     size_t getCount() const { return mnCount; }
@@ -487,6 +526,13 @@ public:
 
 }
 
+double ScColumn::SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
+{
+    NumericCellAccumulator aFunc;
+    rPos.miCellPos = sc::ParseFormulaNumeric(rPos.miCellPos, maCells, nRow1, nRow2, aFunc);
+    return aFunc.getSum();
+}
+
 size_t ScColumn::CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
 {
     NumericCellCounter aFunc;
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index f8acd73..d02a0bc 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -3854,6 +3854,64 @@ void ScInterpreter::ScMax( bool bTextAsZero )
 
 namespace {
 
+class FuncCount : public sc::ColumnSpanSet::ColumnAction
+{
+    sc::ColumnBlockConstPosition maPos;
+    ScColumn* mpCol;
+    size_t mnCount;
+    sal_uInt32 mnNumFmt;
+
+public:
+    FuncCount() : mnCount(0), mnNumFmt(0) {}
+
+    virtual void startColumn(ScColumn* pCol)
+    {
+        mpCol = pCol;
+        mpCol->InitBlockPosition(maPos);
+    }
+
+    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+    {
+        if (!bVal)
+            return;
+
+        mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
+        mnNumFmt = mpCol->GetNumberFormat(nRow2);
+    };
+
+    size_t getCount() const { return mnCount; }
+    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
+class FuncSum : public sc::ColumnSpanSet::ColumnAction
+{
+    sc::ColumnBlockConstPosition maPos;
+    ScColumn* mpCol;
+    double mfSum;
+    sal_uInt32 mnNumFmt;
+
+public:
+    FuncSum() : mfSum(0.0), mnNumFmt(0) {}
+
+    virtual void startColumn(ScColumn* pCol)
+    {
+        mpCol = pCol;
+        mpCol->InitBlockPosition(maPos);
+    }
+
+    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+    {
+        if (!bVal)
+            return;
+
+        mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
+        mnNumFmt = mpCol->GetNumberFormat(nRow2);
+    };
+
+    double getSum() const { return mfSum; }
+    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
 void IterateMatrix(
     const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
     sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
@@ -4258,8 +4316,132 @@ void ScInterpreter::ScSumSQ()
 
 void ScInterpreter::ScSum()
 {
-    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSum" );
-    PushDouble( IterateParameters( ifSUM ) );
+    short nParamCount = GetByte();
+    double fRes = 0.0;
+    double fVal = 0.0;
+    ScAddress aAdr;
+    ScRange aRange;
+    size_t nRefInList = 0;
+    while (nParamCount-- > 0)
+    {
+        switch (GetStackType())
+        {
+            case svString:
+            {
+                while (nParamCount-- > 0)
+                    Pop();
+                SetError( errNoValue );
+            }
+            break;
+            case svDouble    :
+                fVal = GetDouble();
+                fRes += fVal;
+                nFuncFmtType = NUMBERFORMAT_NUMBER;
+                break;
+            case svExternalSingleRef:
+            {
+                ScExternalRefCache::TokenRef pToken;
+                ScExternalRefCache::CellFormat aFmt;
+                PopExternalSingleRef(pToken, &aFmt);
+
+                if (!pToken)
+                    break;
+
+                StackVar eType = pToken->GetType();
+                if (eType == formula::svDouble)
+                {
+                    fVal = pToken->GetDouble();
+                    if (aFmt.mbIsSet)
+                    {
+                        nFuncFmtType = aFmt.mnType;
+                        nFuncFmtIndex = aFmt.mnIndex;
+                    }
+
+                    fRes += fVal;
+                }
+            }
+            break;
+            case svSingleRef :
+            {
+                PopSingleRef( aAdr );
+
+                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+                {
+                    break;
+                }
+                ScRefCellValue aCell;
+                aCell.assign(*pDok, aAdr);
+                if (!aCell.isEmpty())
+                {
+                    if (aCell.hasNumeric())
+                    {
+                        fVal = GetCellValue(aAdr, aCell);
+                        CurFmtToFuncFmt();
+                        fRes += fVal;
+                    }
+                }
+            }
+            break;
+            case svDoubleRef :
+            case svRefList :
+            {
+                PopDoubleRef( aRange, nParamCount, nRefInList);
+
+                sc::ColumnSpanSet aSet(false);
+                aSet.set(aRange, true);
+                if (glSubTotal)
+                    // Skip all filtered rows and subtotal formula cells.
+                    pDok->MarkSubTotalCells(aSet, aRange, false);
+
+                FuncSum aAction;
+                aSet.executeColumnAction(*pDok, aAction);
+                fRes = aAction.getSum();
+
+                // Get the number format of the last iterated cell.
+                nFuncFmtIndex = aAction.getNumberFormat();
+                nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
+            }
+            break;
+            case svExternalDoubleRef:
+            {
+                ScMatrixRef pMat;
+                PopExternalDoubleRef(pMat);
+                if (nGlobalError)
+                    break;
+
+                sal_uLong nCount = 0;
+                double fMem = 0.0;
+                bool bNull = true;
+                IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+                fRes += fMem;
+            }
+            break;
+            case svMatrix :
+            {
+                ScMatrixRef pMat = PopMatrix();
+                sal_uLong nCount = 0;
+                double fMem = 0.0;
+                bool bNull = true;
+                IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+                fRes += fMem;
+            }
+            break;
+            case svError:
+            {
+                PopError();
+            }
+            break;
+            default :
+                while (nParamCount-- > 0)
+                    PopError();
+                SetError(errIllegalParameter);
+        }
+    }
+
+    if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
+        nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+    PushDouble(fRes);
 }
 
 
@@ -4276,39 +4458,6 @@ void ScInterpreter::ScAverage( bool bTextAsZero )
     PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
 }
 
-namespace {
-
-class FuncCount : public sc::ColumnSpanSet::ColumnAction
-{
-    sc::ColumnBlockConstPosition maPos;
-    ScColumn* mpCol;
-    size_t mnCount;
-    sal_uInt32 mnNumFmt;
-
-public:
-    FuncCount() : mnCount(0), mnNumFmt(0) {}
-
-    virtual void startColumn(ScColumn* pCol)
-    {
-        mpCol = pCol;
-        mpCol->InitBlockPosition(maPos);
-    }
-
-    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
-    {
-        if (!bVal)
-            return;
-
-        mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
-        mnNumFmt = mpCol->GetNumberFormat(nRow2);
-    };
-
-    size_t getCount() const { return mnCount; }
-    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
-};
-
-}
-
 void ScInterpreter::ScCount()
 {
     short nParamCount = GetByte();
commit c35d63292d08bef1825b179a00cbc876c99a3887
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 00:06:22 2013 -0400

    Put the matrix header back in for Windows build...
    
    Change-Id: I676b3d9b702af51bf00dff9ef55d16e7fbdec65e

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 1f9b960..a63025c 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -259,10 +259,7 @@ public:
                                     const formula::FormulaGrammar::Grammar eGrammar )
                         { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; }
 
-    void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
-    {
-        aResult.SetMatrix(nCols, nRows, pMat, pUL);
-    }
+    void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL );
 
     /** For import only: set a double result.
         Use this instead of SetHybridDouble() if there is no (temporary)
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index 116022a..0839326 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -30,7 +30,7 @@
 #include "scdllapi.h"
 #include "formula/IFunctionDescription.hxx"
 #include "formula/token.hxx"
-#include "types.hxx"
+#include "scmatrix.hxx"
 
 class ScJumpMatrix;
 
@@ -318,7 +318,7 @@ public:
     virtual const String &      GetString() const;
     virtual const ScMatrix*     GetMatrix() const;
     virtual bool                operator==( const formula::FormulaToken& rToken ) const;
-    virtual FormulaToken*       Clone() const { return new ScMatrixCellResultToken(*this); }
+    virtual FormulaToken*       Clone() const;
     formula::StackVar           GetUpperLeftType() const
                                     {
                                         return xUpperLeft ?
@@ -357,12 +357,9 @@ public:
             SCCOL               GetMatCols() const  { return nCols; }
             SCROW               GetMatRows() const  { return nRows; }
 
-                                /** Assign matrix result, keep matrix formula
-                                    dimension. */
-            void                Assign( const ScMatrixCellResultToken & r )
-                                    {
-                                        ScMatrixCellResultToken::Assign( r);
-                                    }
+    /** Assign matrix result, keep matrix formula
+        dimension. */
+    void Assign( const ScMatrixCellResultToken & r );
 
                                 /** Assign any result, keep matrix formula
                                     dimension. If token is of type
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index f2d72da..1e86cfc 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1591,6 +1591,11 @@ void ScFormulaCell::SetResultToken( const formula::FormulaToken* pToken )
     aResult.SetToken(pToken);
 }
 
+void ScFormulaCell::SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
+{
+    aResult.SetMatrix(nCols, nRows, pMat, pUL);
+}
+
 void ScFormulaCell::SetErrCode( sal_uInt16 n )
 {
     /* FIXME: check the numerous places where ScTokenArray::GetCodeError() is
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 3f40fa7..ad8fdf2 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -37,7 +37,6 @@
 #include "rangeseq.hxx"
 #include "externalrefmgr.hxx"
 #include "document.hxx"
-#include "scmatrix.hxx"
 
 using ::std::vector;
 
@@ -1060,6 +1059,11 @@ bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
         xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
 }
 
+FormulaToken* ScMatrixCellResultToken::Clone() const
+{
+    return new ScMatrixCellResultToken(*this);
+}
+
 void ScMatrixCellResultToken::Assign( const ScMatrixCellResultToken & r )
 {
     xMatrix = r.xMatrix;
@@ -1088,6 +1092,12 @@ bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
     return p && ScMatrixCellResultToken::operator==( r ) &&
         nCols == p->nCols && nRows == p->nRows;
 }
+
+void ScMatrixFormulaCellToken::Assign( const ScMatrixCellResultToken & r )
+{
+    ScMatrixCellResultToken::Assign( r);
+}
+
 void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
 {
     if (this == &r)


More information about the Libreoffice-commits mailing list