[Libreoffice-commits] core.git: Branch 'feature/calc-group-interpreter' - 3 commits - sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Mon Jul 1 22:17:52 PDT 2013


 sc/inc/column.hxx                     |    1 
 sc/inc/formulacell.hxx                |    6 
 sc/inc/formularesult.hxx              |    2 
 sc/inc/token.hxx                      |   13 --
 sc/source/core/data/column.cxx        |   56 +++++++-
 sc/source/core/data/formulacell.cxx   |   14 ++
 sc/source/core/tool/formularesult.cxx |   12 +
 sc/source/core/tool/interpr1.cxx      |  219 ++++++++++++++++++++++++++++------
 sc/source/core/tool/token.cxx         |   12 +
 9 files changed, 282 insertions(+), 53 deletions(-)

New commits:
commit 170c957cef174aac6a727ff15b67a49f96fa80f7
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 01:12:27 2013 -0400

    COUNT should skip formula cells with error.
    
    Change-Id: I829eaf309056403f77949526877888315a2ad720

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 7df7335..9ade34f 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -201,6 +201,7 @@ public:
                     // display as empty string if formula::svEmptyCell result
     bool            IsEmptyDisplayedAsString();
     bool            IsValue();      // also true if formula::svEmptyCell
+    bool IsValueNoError();
     bool            IsHybridValueCell(); // for cells after import to deal with inherited number formats
     double          GetValue();
     double          GetValueAlways();   // ignore errors
diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx
index e215daf..fdb5d31 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -130,6 +130,8 @@ public:
         details instead. */
     bool IsValue() const;
 
+    bool IsValueNoError() const;
+
     /** Determines whether or not the result is a string containing more than
         one paragraph */
     bool IsMultiline() const;
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ca5c7ae..7843f7c 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -511,7 +511,7 @@ public:
                 for (; it != itEnd; ++it)
                 {
                     ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
-                    if (rCell.IsValue())
+                    if (rCell.IsValueNoError())
                         ++mnCount;
                 }
             }
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 96470e3..523995b 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1726,6 +1726,15 @@ bool ScFormulaCell::IsValue()
     return aResult.IsValue();
 }
 
+bool ScFormulaCell::IsValueNoError()
+{
+    MaybeInterpret();
+    if (pCode->GetCodeError())
+        return false;
+
+    return aResult.IsValueNoError();
+}
+
 bool ScFormulaCell::IsHybridValueCell()
 {
     return aResult.GetType() == formula::svHybridValueCell;
diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx
index 6052e66..baeef1d 100644
--- a/sc/source/core/tool/formularesult.cxx
+++ b/sc/source/core/tool/formularesult.cxx
@@ -265,6 +265,18 @@ bool ScFormulaResult::IsValue() const
     return isValue(GetCellResultType());
 }
 
+bool ScFormulaResult::IsValueNoError() const
+{
+    switch (GetCellResultType())
+    {
+        case formula::svDouble:
+        case formula::svEmptyCell:
+        case formula::svHybridValueCell:
+            return true;
+    }
+    return false;
+}
+
 bool ScFormulaResult::IsMultiline() const
 {
     if (meMultiline == MULTILINE_UNKNOWN)
commit b4ccd08f65e7236eca70651a6ee4169b4a980ccc
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 2630f6e..bde6e3d 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -402,6 +402,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 b15d090..ca5c7ae 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 8fd0f5b..af83cfb 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -3853,6 +3853,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)
@@ -4253,8 +4311,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);
 }
 
 
@@ -4271,39 +4453,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 aba6c7e275aa055bc613b6bec9692284c37500f1
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...
    
    Conflicts:
    	sc/inc/formulacell.hxx
    
    Change-Id: I676b3d9b702af51bf00dff9ef55d16e7fbdec65e

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 8b01ea8..7df7335 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -273,10 +273,7 @@ public:
     void SetHybridValueString( double nVal, const OUString& r )
                         { aResult.SetHybridValueString( nVal, r ); }
 
-    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 bc8a4bd..0ed95bd 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 7e9cadc..96470e3 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1603,6 +1603,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 8d64fb5..28a3ba5 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