[Libreoffice-commits] core.git: formula/source include/formula sc/inc sc/qa sc/source

Dennis Francis dennis.francis at collabora.co.uk
Tue Jun 26 13:42:17 UTC 2018


 formula/source/core/api/FormulaCompiler.cxx |   24 ++-
 formula/source/ui/dlg/formula.cxx           |    2 
 include/formula/FormulaCompiler.hxx         |   16 +-
 sc/inc/compiler.hxx                         |   16 +-
 sc/qa/unit/ucalc.hxx                        |   10 +
 sc/qa/unit/ucalc_formula.cxx                |  197 +++++++++++++++++++++++++++-
 sc/source/core/data/column.cxx              |    3 
 sc/source/core/data/column4.cxx             |    3 
 sc/source/core/data/formulacell.cxx         |   60 ++++++--
 sc/source/core/data/simpleformulacalc.cxx   |    2 
 sc/source/core/tool/compiler.cxx            |  178 ++++++++++++++++++++-----
 sc/source/core/tool/interpr4.cxx            |   53 -------
 sc/source/filter/oox/formulabuffer.cxx      |    4 
 sc/source/ui/view/viewfunc.cxx              |    2 
 14 files changed, 449 insertions(+), 121 deletions(-)

New commits:
commit 60c5ca1b874ead7251653d01b0d50fdd42482e09
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date:   Wed May 2 14:22:09 2018 +0530

    More Implicit intersection computation
    
    Do implicit intersection computation for
    for single parameter functions while generating
    RPN token array when the argument is a doubleref
    with relative row references. This optimization
    is not done when under forced array mode or
    matrix formula mode.
    
    The computation logic was already present in ScInterpreter,
    so factored it out and reused.
    
    This also adds unit tests to ensure correctness of
    II computation for various cases.
    
    Change-Id: I509c3f6f811aa036b1dc3296e8f68904b26c3c49
    Reviewed-on: https://gerrit.libreoffice.org/53885
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index f5e06e77deba..671d2c2b9f62 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -697,7 +697,7 @@ void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode
 
 // class FormulaCompiler
 
-FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr )
+FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr, bool bComputeII, bool bMatrixFlag )
         :
         nCurrentFactorParam(0),
         pArr( &rArr ),
@@ -714,13 +714,15 @@ FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr )
         glSubTotal( false ),
         needsRPNTokenCheck( false ),
         mbJumpCommandReorder(true),
-        mbStopOnError(true)
+        mbStopOnError(true),
+        mbComputeII(bComputeII),
+        mbMatrixFlag(bMatrixFlag)
 {
 }
 
 FormulaTokenArray FormulaCompiler::smDummyTokenArray;
 
-FormulaCompiler::FormulaCompiler()
+FormulaCompiler::FormulaCompiler(bool bComputeII, bool bMatrixFlag)
         :
         nCurrentFactorParam(0),
         pArr( nullptr ),
@@ -737,7 +739,9 @@ FormulaCompiler::FormulaCompiler()
         glSubTotal( false ),
         needsRPNTokenCheck( false ),
         mbJumpCommandReorder(true),
-        mbStopOnError(true)
+        mbStopOnError(true),
+        mbComputeII(bComputeII),
+        mbMatrixFlag(bMatrixFlag)
 {
 }
 
@@ -1549,6 +1553,7 @@ void FormulaCompiler::Factor()
             else
             {
                 // standard handling of 1-parameter opcodes
+                OpCode eMyLastOp = eOp;
                 pFacToken = mpToken;
                 eOp = NextToken();
                 if( nNumFmt == SvNumFormatType::UNDEFINED && eOp == ocNot )
@@ -1564,7 +1569,14 @@ void FormulaCompiler::Factor()
                 if (eOp != ocClose)
                     SetError( FormulaError::PairExpected);
                 else if ( pArr->GetCodeError() == FormulaError::NONE )
+                {
                     pFacToken->SetByte( 1 );
+                    if (mbComputeII && IsIIOpCode(eMyLastOp))
+                    {
+                        FormulaToken** pArg = pCode - 1;
+                        HandleIIOpCode(eMyLastOp, pFacToken->GetInForceArray(), &pArg, 1);
+                    }
+                }
                 PutCode( pFacToken );
                 NextToken();
             }
@@ -1606,7 +1618,7 @@ void FormulaCompiler::Factor()
             sal_uInt32 nSepCount = 0;
             if( !bNoParam )
             {
-                bool bDoIICompute = IsIIOpCode(eMyLastOp);
+                bool bDoIICompute = mbComputeII && IsIIOpCode(eMyLastOp);
                 // Array of FormulaToken double pointers to collect the parameters of II opcodes.
                 FormulaToken*** pArgArray = nullptr;
                 if (bDoIICompute)
@@ -1633,7 +1645,7 @@ void FormulaCompiler::Factor()
                         pArgArray[nSepCount - 1] = pCode - 1; // Add rest of the arguments
                 }
                 if (bDoIICompute)
-                    HandleIIOpCode(eMyLastOp, pArgArray,
+                    HandleIIOpCode(eMyLastOp, pFacToken->GetInForceArray(), pArgArray,
                                    std::min(nSepCount, static_cast<sal_uInt32>(FORMULA_MAXPARAMSII)));
             }
             if (bBadName)
diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx
index e5b07260915a..5abc04622e15 100644
--- a/formula/source/ui/dlg/formula.cxx
+++ b/formula/source/ui/dlg/formula.cxx
@@ -831,6 +831,8 @@ void FormulaDlg_Impl::UpdateTokenArray( const OUString& rStrExp)
     // #i101512# Disable special handling of jump commands.
     pCompiler->EnableJumpCommandReorder(false);
     pCompiler->EnableStopOnError(false);
+    pCompiler->SetComputeIIFlag(true);
+    pCompiler->SetMatrixFlag(m_bUserMatrixFlag);
     pCompiler->CompileTokenArray();
 }
 
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index 321e288fcc55..1f0bb0d95c5b 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -76,8 +76,8 @@ private:
     FormulaCompiler(const FormulaCompiler&) = delete;
     FormulaCompiler& operator=(const FormulaCompiler&) = delete;
 public:
-    FormulaCompiler();
-    FormulaCompiler(FormulaTokenArray& _rArr);
+    FormulaCompiler(bool bComputeII = false, bool bMatrixFlag = false);
+    FormulaCompiler(FormulaTokenArray& _rArr, bool bComputeII = false, bool bMatrixFlag = false);
     virtual ~FormulaCompiler();
 
     /** Mappings from strings to OpCodes and vice versa. */
@@ -269,6 +269,12 @@ public:
     static void ResetNativeSymbols();
     static void SetNativeSymbols( const OpCodeMapPtr& xMap );
 
+    /** Sets the implicit intersection compute flag */
+    void SetComputeIIFlag(bool bSet) { mbComputeII = bSet; }
+
+    /** Sets the matrix flag for the formula*/
+    void SetMatrixFlag(bool bSet) { mbMatrixFlag = bSet; }
+
     /** Separators mapped when loading opcodes from the resource, values other
         than RESOURCE_BASE may override the resource strings. Used by OpCodeList
         implementation via loadSymbols().
@@ -327,7 +333,8 @@ protected:
     // This is no-op for this class.
     virtual bool IsIIOpCode(OpCode /*nOpCode*/) const { return false; }
     // Handles II opcode and passes the parameter array and number of parameters.
-    virtual void HandleIIOpCode(OpCode /*nOpCode*/, FormulaToken*** /*pppToken*/, sal_uInt8 /*nNumParams*/) {}
+    virtual void HandleIIOpCode(OpCode /*nOpCode*/, formula::ParamClass /*eClass*/,
+                                FormulaToken*** /*pppToken*/, sal_uInt8 /*nNumParams*/) {}
 
     OUString            aCorrectedFormula;      // autocorrected Formula
     OUString            aCorrectedSymbol;       // autocorrected Symbol
@@ -359,6 +366,9 @@ protected:
     bool mbJumpCommandReorder; /// Whether or not to reorder RPN for jump commands.
     bool mbStopOnError;        /// Whether to stop compilation on first encountered error.
 
+    bool mbComputeII;  // whether to attempt computing implicit intersection ranges while building the RPN array.
+    bool mbMatrixFlag; // whether the formula is a matrix formula (needed for II computation)
+
 private:
     void InitSymbolsNative() const;    /// only SymbolsNative, on first document creation
     void InitSymbolsEnglish() const;   /// only SymbolsEnglish, maybe later
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index ffd783a32506..767d08b36e62 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -335,24 +335,25 @@ private:
     static void InitCharClassEnglish();
 
 public:
-    ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, const ScInterpreterContext* pContext = nullptr );
+    ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
+            bool bComputeII = false, bool bMatrixFlag = false, const ScInterpreterContext* pContext = nullptr );
 
     /** If eGrammar == GRAM_UNSPECIFIED then the grammar of pDocument is used,
         if pDocument==nullptr then GRAM_DEFAULT.
      */
     ScCompiler( ScDocument* pDocument, const ScAddress&,
             formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_UNSPECIFIED,
-            const ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, const ScInterpreterContext* pContext = nullptr );
 
     ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, ScTokenArray& rArr,
-            const ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, const ScInterpreterContext* pContext = nullptr );
 
     /** If eGrammar == GRAM_UNSPECIFIED then the grammar of pDocument is used,
         if pDocument==nullptr then GRAM_DEFAULT.
      */
     ScCompiler( ScDocument* pDocument, const ScAddress&, ScTokenArray& rArr,
             formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_UNSPECIFIED,
-            const ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, const ScInterpreterContext* pContext = nullptr );
 
     virtual ~ScCompiler() override;
 
@@ -451,6 +452,10 @@ public:
     static bool IsCharFlagAllConventions(
         OUString const & rStr, sal_Int32 nPos, ScCharFlags nFlags );
 
+    /** TODO : Move this to somewhere appropriate. */
+    static bool DoubleRefToPosSingleRefScalarCase(const ScRange& rRange, ScAddress& rAdr,
+                                                  const ScAddress& rFormulaPos);
+
 private:
     // FormulaCompiler
     virtual OUString FindAddInFunction( const OUString& rUpperName, bool bLocalFirst ) const override;
@@ -480,7 +485,8 @@ private:
         { return c < 128 ? pConv->getCharTableFlags(c, cLast) : ScCharFlags::NONE; }
 
     bool IsIIOpCode(OpCode nOpCode) const override;
-    void HandleIIOpCode(OpCode nOpCode, formula::FormulaToken*** pppToken, sal_uInt8 nNumParams) override;
+    void HandleIIOpCode(OpCode nOpCode, formula::ParamClass eClass, formula::FormulaToken*** pppToken, sal_uInt8 nNumParams) override;
+    void ReplaceDoubleRefII(formula::FormulaToken** ppDoubleRefTok);
     bool AdjustSumRangeShape(const ScComplexRefData& rBaseRange, ScComplexRefData& rSumRange);
     void CorrectSumRange(const ScComplexRefData& rBaseRange, ScComplexRefData& rSumRange, formula::FormulaToken** ppSumRangeToken);
 };
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index f1d6acb476eb..03305a8ad74e 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -143,7 +143,10 @@ public:
     void testFormulaRefData();
     void testFormulaCompiler();
     void testFormulaCompilerJumpReordering();
-    void testFormulaCompilerImplicitIntersection();
+    void testFormulaCompilerImplicitIntersection2Param();
+    void testFormulaCompilerImplicitIntersection1ParamNoChange();
+    void testFormulaCompilerImplicitIntersection1ParamWithChange();
+    void testFormulaCompilerImplicitIntersection1NoGroup();
     void testFormulaRefUpdate();
     void testFormulaRefUpdateRange();
     void testFormulaRefUpdateSheets();
@@ -568,7 +571,10 @@ public:
     CPPUNIT_TEST(testFormulaRefData);
     CPPUNIT_TEST(testFormulaCompiler);
     CPPUNIT_TEST(testFormulaCompilerJumpReordering);
-    CPPUNIT_TEST(testFormulaCompilerImplicitIntersection);
+    CPPUNIT_TEST(testFormulaCompilerImplicitIntersection2Param);
+    CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1ParamNoChange);
+    CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1ParamWithChange);
+    CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1NoGroup);
     CPPUNIT_TEST(testFormulaRefUpdate);
     CPPUNIT_TEST(testFormulaRefUpdateRange);
     CPPUNIT_TEST(testFormulaRefUpdateSheets);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 126bed6c9289..5900e3555ada 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1105,7 +1105,7 @@ void Test::testFormulaCompilerJumpReordering()
     }
 }
 
-void Test::testFormulaCompilerImplicitIntersection()
+void Test::testFormulaCompilerImplicitIntersection2Param()
 {
     struct TestCaseFormula
     {
@@ -1231,6 +1231,201 @@ void Test::testFormulaCompilerImplicitIntersection()
     }
 }
 
+void Test::testFormulaCompilerImplicitIntersection1ParamNoChange()
+{
+    struct TestCaseFormulaNoChange
+    {
+        OUString  aFormula;
+        ScAddress aCellAddress;
+        bool      bMatrixFormula;
+        bool      bForcedArray;
+    };
+
+    m_pDoc->InsertTab(0, "Formula");
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+    {
+        ScAddress aStartAddr(4, 5, 0);
+        TestCaseFormulaNoChange aCasesNoChange[] =
+        {
+            {
+                OUString("=COS(A$2:A$100)"),  // No change because of abs col ref.
+                aStartAddr,
+                false,
+                false
+            },
+            {
+                OUString("=COS($A7:$A100)"),  // No intersection
+                aStartAddr,
+                false,
+                false
+            },
+            {
+                OUString("=COS($A5:$C7)"),   // No intersection 2-D range
+                aStartAddr,
+                false,
+                false
+            },
+            {
+                OUString("=SUMPRODUCT(COS(A6:A10))"),  // COS() in forced array mode
+                aStartAddr,
+                false,
+                true
+            },
+            {
+                OUString("=COS(A6:A10)"),  // Matrix formula
+                aStartAddr,
+                true,
+                false
+            }
+        };
+
+        for (auto& rCase : aCasesNoChange)
+        {
+            if (rCase.bMatrixFormula)
+            {
+                ScMarkData aMark;
+                aMark.SelectOneTable(0);
+                SCCOL nColStart = rCase.aCellAddress.Col();
+                SCROW nRowStart = rCase.aCellAddress.Row();
+                m_pDoc->InsertMatrixFormula(nColStart, nRowStart, nColStart, nRowStart + 4,
+                                            aMark, rCase.aFormula);
+            }
+            else
+                m_pDoc->SetString(rCase.aCellAddress, rCase.aFormula);
+
+            const ScFormulaCell* pCell = m_pDoc->GetFormulaCell(rCase.aCellAddress);
+            const ScTokenArray* pCode = pCell->GetCode();
+            CPPUNIT_ASSERT(pCode);
+
+            sal_uInt16 nRPNLen = pCode->GetCodeLen();
+            sal_uInt16 nRawLen = pCode->GetLen();
+            sal_uInt16 nRawArgPos;
+            if (rCase.bForcedArray)
+            {
+                nRawArgPos = 4;
+                CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong raw token count.", static_cast<sal_uInt16>(7), nRawLen);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong RPN token count.", static_cast<sal_uInt16>(3), nRPNLen);
+            }
+            else
+            {
+                nRawArgPos = 2;
+                CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong raw token count.", static_cast<sal_uInt16>(4), nRawLen);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong RPN token count.", static_cast<sal_uInt16>(2), nRPNLen);
+            }
+
+            FormulaToken** ppRawTokens = pCode->GetArray();
+            FormulaToken** ppRPNTokens = pCode->GetCode();
+
+            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of raw token(argument to COS)", svDoubleRef, ppRawTokens[nRawArgPos]->GetType());
+            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of RPN token(argument to COS)", svDoubleRef, ppRPNTokens[0]->GetType());
+
+            ScComplexRefData aArgRangeRaw = *ppRawTokens[nRawArgPos]->GetDoubleRef();
+            ScComplexRefData aArgRangeRPN = *ppRPNTokens[0]->GetDoubleRef();
+            bool bRawMatchRPNToken(aArgRangeRaw == aArgRangeRPN);
+            CPPUNIT_ASSERT_MESSAGE("raw arg token and RPN arg token contents do not match", bRawMatchRPNToken);
+        }
+    }
+}
+
+void Test::testFormulaCompilerImplicitIntersection1ParamWithChange()
+{
+    struct TestCaseFormula
+    {
+        OUString  aFormula;
+        ScAddress aCellAddress;
+        ScAddress aArgAddr;
+    };
+
+    m_pDoc->InsertTab(0, "Formula");
+    m_pDoc->InsertTab(1, "Formula1");
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+    {
+        ScAddress aStartAddr(10, 5, 0);
+        TestCaseFormula aCasesWithChange[] =
+        {
+            {
+                OUString("=COS($A6:$A100)"),  // Corner case with intersection
+                aStartAddr,
+                ScAddress(0, 5, 0)
+            },
+            {
+                OUString("=COS($A2:$A6)"),    // Corner case with intersection
+                aStartAddr,
+                ScAddress(0, 5, 0)
+            },
+            {
+                OUString("=COS($A2:$A100)"),    // Typical 1D case
+                aStartAddr,
+                ScAddress(0, 5, 0)
+            },
+            {
+                OUString("=COS($Formula.$A1:$C3)"),      // 2D corner case
+                ScAddress(0, 0, 1),                      // Formula in sheet 1
+                ScAddress(0, 0, 0)
+            },
+            {
+                OUString("=COS($Formula.$A1:$C3)"),      // 2D corner case
+                ScAddress(0, 2, 1),                      // Formula in sheet 1
+                ScAddress(0, 2, 0)
+            },
+            {
+                OUString("=COS($Formula.$A1:$C3)"),      // 2D corner case
+                ScAddress(2, 0, 1),                      // Formula in sheet 1
+                ScAddress(2, 0, 0)
+            },
+            {
+                OUString("=COS($Formula.$A1:$C3)"),      // 2D corner case
+                ScAddress(2, 2, 1),                      // Formula in sheet 1
+                ScAddress(2, 2, 0)
+            },
+            {
+                OUString("=COS($Formula.$A1:$C3)"),      // Typical 2D case
+                ScAddress(1, 1, 1),                      // Formula in sheet 1
+                ScAddress(1, 1, 0)
+            }
+        };
+
+        for (auto& rCase : aCasesWithChange)
+        {
+            m_pDoc->SetString(rCase.aCellAddress, rCase.aFormula);
+
+            const ScFormulaCell* pCell = m_pDoc->GetFormulaCell(rCase.aCellAddress);
+            const ScTokenArray* pCode = pCell->GetCode();
+            CPPUNIT_ASSERT(pCode);
+
+            sal_uInt16 nRPNLen = pCode->GetCodeLen();
+            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong RPN token count.", static_cast<sal_uInt16>(2), nRPNLen);
+
+            FormulaToken** ppRPNTokens = pCode->GetCode();
+
+            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of RPN token(argument to COS)", svSingleRef, ppRPNTokens[0]->GetType());
+
+            ScSingleRefData aArgAddrRPN = *ppRPNTokens[0]->GetSingleRef();
+            ScAddress aArgAddrActual = aArgAddrRPN.toAbs(rCase.aCellAddress);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE("Computed implicit intersection singleref is wrong", rCase.aArgAddr, aArgAddrActual);
+        }
+    }
+}
+
+void Test::testFormulaCompilerImplicitIntersection1NoGroup()
+{
+    m_pDoc->InsertTab(0, "Formula");
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+    m_pDoc->SetString(ScAddress(1,2,0), "=COS(A1:A5)"); // B3
+    m_pDoc->SetString(ScAddress(1,3,0), "=COS(A1:A5)"); // B4
+
+    // Implicit intersection optimization in ScCompiler::HandleIIOpCode() internally changes
+    // these to "=COS(A3)" and "=COS(A4)", but these shouldn't be merged into a formula group,
+    // otherwise B4's formula would then be "=COS(A2:A6)".
+    ASSERT_FORMULA_EQUAL(*m_pDoc, ScAddress(1,2,0), "COS(A1:A5)", "Formula in B3 has changed.");
+    ASSERT_FORMULA_EQUAL(*m_pDoc, ScAddress(1,3,0), "COS(A1:A5)", "Formula in B4 has changed.");
+
+    m_pDoc->DeleteTab(0);
+}
+
 void Test::testFormulaRefUpdate()
 {
     m_pDoc->InsertTab(0, "Formula");
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index d8f164e0c916..268ec1b7793c 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2112,7 +2112,8 @@ class UpdateRefOnNonCopy
         // We need to re-compile the token array when a range name is
         // modified, to correctly reflect the new references in the
         // name.
-        ScCompiler aComp(&mpCxt->mrDoc, rTopCell.aPos, *rTopCell.GetCode(), mpCxt->mrDoc.GetGrammar());
+        ScCompiler aComp(&mpCxt->mrDoc, rTopCell.aPos, *rTopCell.GetCode(), mpCxt->mrDoc.GetGrammar(),
+                         true, rTopCell.GetMatrixFlag() != ScMatrixMode::NONE);
         aComp.CompileTokenArray();
     }
 
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 832351d275a7..34566ac15bb1 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -928,7 +928,8 @@ public:
                 ScTokenArray* pNewCode = aComp.CompileString(aFormula);
 
                 // Generate RPN tokens.
-                ScCompiler aComp2(mpDoc, pCell->aPos, *pNewCode);
+                ScCompiler aComp2(mpDoc, pCell->aPos, *pNewCode, formula::FormulaGrammar::GRAM_UNSPECIFIED,
+                                  true, pCell->GetMatrixFlag() != ScMatrixMode::NONE);
                 aComp2.CompileTokenArray();
 
                 pCell->SetCode(pNewCode);
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index e489f60936b7..3800397a9ca7 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -562,7 +562,8 @@ void ScFormulaCellGroup::compileCode(
 
     if (mpCode->GetLen() && mpCode->GetCodeError() == FormulaError::NONE && !mpCode->GetCodeLen())
     {
-        ScCompiler aComp(&rDoc, rPos, *mpCode, eGram);
+        bool bMatrixFormula = mpTopCell->GetMatrixFlag() != ScMatrixMode::NONE;
+        ScCompiler aComp(&rDoc, rPos, *mpCode, eGram, true, bMatrixFormula);
         mbSubTotal = aComp.CompileTokenArray();
         mnFormatType = aComp.GetNumFormatType();
     }
@@ -700,7 +701,7 @@ ScFormulaCell::ScFormulaCell(
     // Generate RPN token array.
     if (pCode->GetLen() && pCode->GetCodeError() == FormulaError::NONE && !pCode->GetCodeLen())
     {
-        ScCompiler aComp( pDocument, aPos, *pCode, eTempGrammar);
+        ScCompiler aComp( pDocument, aPos, *pCode, eTempGrammar, true, cMatrixFlag != ScMatrixMode::NONE );
         bSubTotal = aComp.CompileTokenArray();
         nFormatType = aComp.GetNumFormatType();
     }
@@ -747,7 +748,7 @@ ScFormulaCell::ScFormulaCell(
     // RPN array generation
     if( pCode->GetLen() && pCode->GetCodeError() == FormulaError::NONE && !pCode->GetCodeLen() )
     {
-        ScCompiler aComp( pDocument, aPos, *pCode, eTempGrammar);
+        ScCompiler aComp( pDocument, aPos, *pCode, eTempGrammar, true, cMatrixFlag != ScMatrixMode::NONE );
         bSubTotal = aComp.CompileTokenArray();
         nFormatType = aComp.GetNumFormatType();
     }
@@ -993,7 +994,7 @@ void ScFormulaCell::GetFormula( OUStringBuffer& rBuffer,
             }
             else
             {
-                ScCompiler aComp( pDocument, aPos, *pCode, eGrammar, pContext );
+                ScCompiler aComp( pDocument, aPos, *pCode, eGrammar, false, false, pContext );
                 aComp.CreateStringFromTokenArray( rBuffer );
             }
         }
@@ -1004,7 +1005,7 @@ void ScFormulaCell::GetFormula( OUStringBuffer& rBuffer,
     }
     else
     {
-        ScCompiler aComp( pDocument, aPos, *pCode, eGrammar, pContext );
+        ScCompiler aComp( pDocument, aPos, *pCode, eGrammar, false, false, pContext );
         aComp.CreateStringFromTokenArray( rBuffer );
     }
 
@@ -1031,7 +1032,7 @@ OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, const ScInt
     {
         ScTokenArray aCode;
         aCode.AddToken( FormulaErrorToken( pCode->GetCodeError()));
-        ScCompiler aComp(rCxt, aPos, aCode, pContext);
+        ScCompiler aComp(rCxt, aPos, aCode, false, false, pContext);
         aComp.CreateStringFromTokenArray(aBuf);
         return aBuf.makeStringAndClear();
     }
@@ -1058,7 +1059,7 @@ OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, const ScInt
             }
             else
             {
-                ScCompiler aComp(rCxt, aPos, *pCode, pContext);
+                ScCompiler aComp(rCxt, aPos, *pCode, false, false, pContext);
                 aComp.CreateStringFromTokenArray(aBuf);
             }
         }
@@ -1069,7 +1070,7 @@ OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, const ScInt
     }
     else
     {
-        ScCompiler aComp(rCxt, aPos, *pCode, pContext);
+        ScCompiler aComp(rCxt, aPos, *pCode, false, false, pContext);
         aComp.CreateStringFromTokenArray(aBuf);
     }
 
@@ -1199,7 +1200,7 @@ void ScFormulaCell::CompileTokenArray( bool bNoListening )
 
         if( !bNoListening && pCode->GetCodeLen() )
             EndListeningTo( pDocument );
-        ScCompiler aComp(pDocument, aPos, *pCode, pDocument->GetGrammar());
+        ScCompiler aComp(pDocument, aPos, *pCode, pDocument->GetGrammar(), true, cMatrixFlag != ScMatrixMode::NONE);
         bSubTotal = aComp.CompileTokenArray();
         if( pCode->GetCodeError() == FormulaError::NONE )
         {
@@ -1239,7 +1240,7 @@ void ScFormulaCell::CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNo
 
         if( !bNoListening && pCode->GetCodeLen() )
             EndListeningTo( pDocument );
-        ScCompiler aComp(rCxt, aPos, *pCode);
+        ScCompiler aComp(rCxt, aPos, *pCode, true, cMatrixFlag != ScMatrixMode::NONE);
         bSubTotal = aComp.CompileTokenArray();
         if( pCode->GetCodeError() == FormulaError::NONE )
         {
@@ -1277,7 +1278,7 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr
     if (bWasInFormulaTree)
         pDocument->RemoveFromFormulaTree( this);
     rCxt.setGrammar(eTempGrammar);
-    ScCompiler aComp(rCxt, aPos, *pCode);
+    ScCompiler aComp(rCxt, aPos, *pCode, true, cMatrixFlag != ScMatrixMode::NONE);
     OUString aFormula, aFormulaNmsp;
     aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp );
     pDocument->DecXMLImportedFormulaCount( aFormula.getLength() );
@@ -1395,7 +1396,7 @@ void ScFormulaCell::CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartL
     // The RPN array is not created when a Calc 3.0-Doc has been read as the Range Names exist until now.
     if( pCode->GetLen() && !pCode->GetCodeLen() && pCode->GetCodeError() == FormulaError::NONE )
     {
-        ScCompiler aComp(rCxt, aPos, *pCode);
+        ScCompiler aComp(rCxt, aPos, *pCode, true, cMatrixFlag != ScMatrixMode::NONE);
         bSubTotal = aComp.CompileTokenArray();
         nFormatType = aComp.GetNumFormatType();
         bDirty = true;
@@ -4110,6 +4111,39 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC
 
         switch (pThisTok->GetType())
         {
+            // ScCompiler::HandleIIOpCode() may optimize some refs only in RPN code,
+            // resulting in identical RPN references that could lead to creating
+            // a formula group from formulas that should not be merged into a group,
+            // so check also the formula itself.
+            case formula::svSingleRef:
+            {
+                // Single cell reference.
+                const ScSingleRefData& rRef = *pThisTok->GetSingleRef();
+                if (rRef != *pOtherTok->GetSingleRef())
+                    return NotEqual;
+
+                if (rRef.IsRowRel())
+                    bInvariant = false;
+            }
+            break;
+            case formula::svDoubleRef:
+            {
+                // Range reference.
+                const ScSingleRefData& rRef1 = *pThisTok->GetSingleRef();
+                const ScSingleRefData& rRef2 = *pThisTok->GetSingleRef2();
+                if (rRef1 != *pOtherTok->GetSingleRef())
+                    return NotEqual;
+
+                if (rRef2 != *pOtherTok->GetSingleRef2())
+                    return NotEqual;
+
+                if (rRef1.IsRowRel())
+                    bInvariant = false;
+
+                if (rRef2.IsRowRel())
+                    bInvariant = false;
+            }
+            break;
             // All index tokens are names. Different categories already had
             // different OpCode values.
             case formula::svIndex:
@@ -4802,7 +4836,7 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
             }
         }
 
-        ScCompiler aComp(pDocument, aPos, aCode, pDocument->GetGrammar());
+        ScCompiler aComp(pDocument, aPos, aCode, pDocument->GetGrammar(), true, cMatrixFlag != ScMatrixMode::NONE);
         aComp.CompileTokenArray(); // Create RPN token array.
         ScInterpreter aInterpreter(this, pDocument, pDocument->GetNonThreadedContext(), aPos, aCode);
         aInterpreter.Interpret();
diff --git a/sc/source/core/data/simpleformulacalc.cxx b/sc/source/core/data/simpleformulacalc.cxx
index a710d8a34cbf..9882fd7a352f 100644
--- a/sc/source/core/data/simpleformulacalc.cxx
+++ b/sc/source/core/data/simpleformulacalc.cxx
@@ -28,7 +28,7 @@ ScSimpleFormulaCalculator::ScSimpleFormulaCalculator( ScDocument* pDoc, const Sc
     , mbMatrixFormula(bMatrixFormula)
 {
     // compile already here
-    ScCompiler aComp(mpDoc, maAddr, eGram);
+    ScCompiler aComp(mpDoc, maAddr, eGram, true, bMatrixFormula);
     mpCode.reset(aComp.CompileString(rFormula));
     if(mpCode->GetCodeError() == FormulaError::NONE && mpCode->GetLen())
         aComp.CompileTokenArray();
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 4ec04d968042..d8a68b50fb43 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -1733,8 +1733,8 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
 };
 
 ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, ScTokenArray& rArr,
-        const ScInterpreterContext* pContext )
-    : FormulaCompiler(rArr),
+                        bool bComputeII, bool bMatrixFlag, const ScInterpreterContext* pContext )
+    : FormulaCompiler(rArr, bComputeII, bMatrixFlag),
     pDoc(rCxt.getDoc()),
     aPos(rPos),
     mpFormatter(pContext? pContext->GetFormatTable() : pDoc->GetFormatTable()),
@@ -1753,8 +1753,9 @@ ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
 }
 
 ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos, ScTokenArray& rArr,
-            formula::FormulaGrammar::Grammar eGrammar, const ScInterpreterContext* pContext )
-        : FormulaCompiler(rArr),
+                        formula::FormulaGrammar::Grammar eGrammar,
+                        bool bComputeII, bool bMatrixFlag, const ScInterpreterContext* pContext )
+    : FormulaCompiler(rArr, bComputeII, bMatrixFlag),
         pDoc( pDocument ),
         aPos( rPos ),
         mpFormatter(pContext ? pContext->GetFormatTable() : pDoc->GetFormatTable()),
@@ -1774,8 +1775,10 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos, ScTokenArr
                 eGrammar );
 }
 
-ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, const ScInterpreterContext* pContext )
-    : pDoc(rCxt.getDoc()),
+ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
+                        bool bComputeII, bool bMatrixFlag, const ScInterpreterContext* pContext )
+    : FormulaCompiler(bComputeII, bMatrixFlag),
+    pDoc(rCxt.getDoc()),
     aPos(rPos),
     mpFormatter(pContext ? pContext->GetFormatTable() : pDoc ? pDoc->GetFormatTable() : nullptr),
     mnCurrentSheetTab(-1),
@@ -1793,8 +1796,9 @@ ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
 }
 
 ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,
-            formula::FormulaGrammar::Grammar eGrammar, const ScInterpreterContext* pContext )
-        :
+                        formula::FormulaGrammar::Grammar eGrammar,
+                        bool bComputeII, bool bMatrixFlag, const ScInterpreterContext* pContext )
+        : FormulaCompiler(bComputeII, bMatrixFlag),
         pDoc( pDocument ),
         aPos( rPos ),
         mpFormatter(pContext ? pContext->GetFormatTable() : pDoc ? pDoc->GetFormatTable() : nullptr),
@@ -5791,50 +5795,154 @@ formula::ParamClass ScCompiler::GetForceArrayParameter( const formula::FormulaTo
 
 bool ScCompiler::IsIIOpCode(OpCode nOpCode) const
 {
-    if (nOpCode == ocSumIf || nOpCode == ocAverageIf)
+    if (nOpCode == ocSumIf || nOpCode == ocAverageIf || (nOpCode >= SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR))
         return true;
 
     return false;
 }
 
-void ScCompiler::HandleIIOpCode(OpCode nOpCode, FormulaToken*** pppToken, sal_uInt8 nNumParams)
+void ScCompiler::HandleIIOpCode(OpCode nOpCode, formula::ParamClass eClass, FormulaToken*** pppToken, sal_uInt8 nNumParams)
 {
-    switch (nOpCode)
+    if (!mbComputeII)
+        return;
+
+    if (nOpCode == ocSumIf || nOpCode == ocAverageIf)
     {
-        case ocSumIf:
-        case ocAverageIf:
+        if (nNumParams != 3)
+            return;
+
+        if (!(pppToken[0] && pppToken[2] && *pppToken[0] && *pppToken[2]))
+            return;
+
+        if ((*pppToken[0])->GetType() != svDoubleRef)
+            return;
+
+        const StackVar eSumRangeType = (*pppToken[2])->GetType();
+
+        if ( eSumRangeType != svSingleRef && eSumRangeType != svDoubleRef )
+            return;
+
+        const ScComplexRefData& rBaseRange = *(*pppToken[0])->GetDoubleRef();
+
+        ScComplexRefData aSumRange;
+        if (eSumRangeType == svSingleRef)
         {
-            if (nNumParams != 3)
-                return;
+            aSumRange.Ref1 = *(*pppToken[2])->GetSingleRef();
+            aSumRange.Ref2 = aSumRange.Ref1;
+        }
+        else
+            aSumRange = *(*pppToken[2])->GetDoubleRef();
 
-            if (!(pppToken[0] && pppToken[2] && *pppToken[0] && *pppToken[2]))
-                return;
+        CorrectSumRange(rBaseRange, aSumRange, pppToken[2]);
+    }
+    else if (nOpCode >= SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR)
+    {
+        if (nNumParams != 1)
+            return;
 
-            if ((*pppToken[0])->GetType() != svDoubleRef)
-                return;
+        if (eClass == formula::ForceArray || mbMatrixFlag)
+            return;
 
-            const StackVar eSumRangeType = (*pppToken[2])->GetType();
+        if ((*pppToken[0])->GetType() != svDoubleRef)
+            return;
 
-            if ( eSumRangeType != svSingleRef && eSumRangeType != svDoubleRef )
-                return;
+        ReplaceDoubleRefII(pppToken[0]);
+    }
+}
 
-            const ScComplexRefData& rBaseRange = *(*pppToken[0])->GetDoubleRef();
+void ScCompiler::ReplaceDoubleRefII(FormulaToken** ppDoubleRefTok)
+{
+    const ScComplexRefData& rRange = *(*ppDoubleRefTok)->GetDoubleRef();
+
+    // Can't do optimization reliably in this case (when row references are absolute).
+    // Example : =SIN(A$1:A$10) filled in a formula group starting at B5 and of length 100.
+    // If we just optimize the argument $A$1:$A$10 to singleref "A5" for the top cell in the fg, then
+    // the results in cells B11:B104 will be incorrect (sin(0) = 0, assuming empty cells in A11:A104)
+    // instead of the #VALUE! errors we would expect. We need to know the formula-group length to
+    // fix this, but that is unknown at this stage, so skip such cases.
+    if (!rRange.Ref1.IsRowRel() && !rRange.Ref2.IsRowRel())
+        return;
 
-            ScComplexRefData aSumRange;
-            if (eSumRangeType == svSingleRef)
-            {
-                aSumRange.Ref1 = *(*pppToken[2])->GetSingleRef();
-                aSumRange.Ref2 = aSumRange.Ref1;
-            }
-            else
-                aSumRange = *(*pppToken[2])->GetDoubleRef();
+    ScRange aAbsRange = rRange.toAbs(aPos);
+    if (aAbsRange.aStart == aAbsRange.aEnd)
+        return; // Nothing to do (trivial case).
+
+    ScAddress aAddr;
+
+    if (!DoubleRefToPosSingleRefScalarCase(aAbsRange, aAddr, aPos))
+        return;
 
-            CorrectSumRange(rBaseRange, aSumRange, pppToken[2]);
+    ScSingleRefData aSingleRef;
+    aSingleRef.InitFlags();
+    aSingleRef.SetColRel(rRange.Ref1.IsColRel());
+    aSingleRef.SetRowRel(true);
+    aSingleRef.SetTabRel(rRange.Ref1.IsTabRel());
+    aSingleRef.SetAddress(aAddr, aPos);
+
+    // Replace the original doubleref token with computed singleref token
+    FormulaToken* pNewSingleRefTok = new ScSingleRefToken(aSingleRef);
+    (*ppDoubleRefTok)->DecRef();
+    *ppDoubleRefTok = pNewSingleRefTok;
+    pNewSingleRefTok->IncRef();
+}
+
+bool ScCompiler::DoubleRefToPosSingleRefScalarCase(const ScRange& rRange, ScAddress& rAdr, const ScAddress& rFormulaPos)
+{
+    assert(rRange.aStart != rRange.aEnd);
+
+    bool bOk = false;
+    SCCOL nMyCol = rFormulaPos.Col();
+    SCROW nMyRow = rFormulaPos.Row();
+    SCTAB nMyTab = rFormulaPos.Tab();
+    SCCOL nCol = 0;
+    SCROW nRow = 0;
+    SCTAB nTab;
+    nTab = rRange.aStart.Tab();
+    if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
+    {
+        nRow = rRange.aStart.Row();
+        if ( nRow == rRange.aEnd.Row() )
+        {
+            bOk = true;
+            nCol = nMyCol;
+        }
+        else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
+                && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
+        {
+            bOk = true;
+            nCol = nMyCol;
+            nRow = nMyRow;
+        }
+    }
+    else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
+    {
+        nCol = rRange.aStart.Col();
+        if ( nCol == rRange.aEnd.Col() )
+        {
+            bOk = true;
+            nRow = nMyRow;
+        }
+        else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
+                && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
+        {
+            bOk = true;
+            nCol = nMyCol;
+            nRow = nMyRow;
         }
-        break;
-        default:
-            ;
     }
+    if ( bOk )
+    {
+        if ( nTab == rRange.aEnd.Tab() )
+            ;   // all done
+        else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
+            nTab = nMyTab;
+        else
+            bOk = false;
+        if ( bOk )
+            rAdr.Set( nCol, nRow, nTab );
+    }
+
+    return bOk;
 }
 
 static void lcl_GetColRowDeltas(const ScRange& rRange, SCCOL& rXDelta, SCROW& rYDelta)
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index c600cdca34b1..6194fa5abe02 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -65,6 +65,7 @@
 #include <doubleref.hxx>
 #include <queryparam.hxx>
 #include <tokenarray.hxx>
+#include <compiler.hxx>
 
 #include <math.h>
 #include <float.h>
@@ -2004,56 +2005,8 @@ bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& r
         return bOk;
     }
 
-    SCCOL nMyCol = aPos.Col();
-    SCROW nMyRow = aPos.Row();
-    SCTAB nMyTab = aPos.Tab();
-    SCCOL nCol = 0;
-    SCROW nRow = 0;
-    SCTAB nTab;
-    nTab = rRange.aStart.Tab();
-    if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
-    {
-        nRow = rRange.aStart.Row();
-        if ( nRow == rRange.aEnd.Row() )
-        {
-            bOk = true;
-            nCol = nMyCol;
-        }
-        else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
-                && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
-        {
-            bOk = true;
-            nCol = nMyCol;
-            nRow = nMyRow;
-        }
-    }
-    else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
-    {
-        nCol = rRange.aStart.Col();
-        if ( nCol == rRange.aEnd.Col() )
-        {
-            bOk = true;
-            nRow = nMyRow;
-        }
-        else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
-                && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
-        {
-            bOk = true;
-            nCol = nMyCol;
-            nRow = nMyRow;
-        }
-    }
-    if ( bOk )
-    {
-        if ( nTab == rRange.aEnd.Tab() )
-            ;   // all done
-        else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
-            nTab = nMyTab;
-        else
-            bOk = false;
-        if ( bOk )
-            rAdr.Set( nCol, nRow, nTab );
-    }
+    bOk = ScCompiler::DoubleRefToPosSingleRefScalarCase(rRange, rAdr, aPos);
+
     if ( !bOk )
         SetError( FormulaError::NoValue );
     return bOk;
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 87529dcad0d0..9f7977b5ddb2 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -121,7 +121,7 @@ void applySharedFormulas(
             sal_Int32 nId = rEntry.mnSharedId;
             const OUString& rTokenStr = rEntry.maTokenStr;
 
-            ScCompiler aComp(&rDoc.getDoc(), aPos, formula::FormulaGrammar::GRAM_OOXML);
+            ScCompiler aComp(&rDoc.getDoc(), aPos, formula::FormulaGrammar::GRAM_OOXML, true, false);
             aComp.SetNumberFormatter(&rFormatter);
             ScTokenArray* pArray = aComp.CompileString(rTokenStr);
             if (pArray)
@@ -206,7 +206,7 @@ void applyCellFormulas(
             continue;
         }
 
-        ScCompiler aCompiler(&rDoc.getDoc(), aPos, formula::FormulaGrammar::GRAM_OOXML);
+        ScCompiler aCompiler(&rDoc.getDoc(), aPos, formula::FormulaGrammar::GRAM_OOXML, true, false);
         aCompiler.SetNumberFormatter(&rFormatter);
         aCompiler.SetExternalLinks(rExternalLinks);
         ScTokenArray* pCode = aCompiler.CompileString(rItem.maTokenStr);
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 306d020ec947..9e29d72da734 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -400,7 +400,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
     {   // formula, compile with autoCorrection
         i = rMark.GetFirstSelected();
         ScAddress aPos( nCol, nRow, i );
-        ScCompiler aComp( pDoc, aPos, pDoc->GetGrammar());
+        ScCompiler aComp( pDoc, aPos, pDoc->GetGrammar(), true, false );
 //2do: enable/disable autoCorrection via calcoptions
         aComp.SetAutoCorrection( true );
         if ( rString[0] == '+' || rString[0] == '-' )


More information about the Libreoffice-commits mailing list