sc/CppunitTest_sc_ucalc_formula2.mk |   14 
 sc/Module_sc.mk                     |    1 
 sc/qa/unit/ucalc_formula.cxx        | 4493 -----------------------------------
 sc/qa/unit/ucalc_formula2.cxx       | 4613 ++++++++++++++++++++++++++++++++++++
 4 files changed, 4628 insertions(+), 4493 deletions(-)

New commits:
commit b7be39c5f45f8268acd9e19c3abd731fee6dcca3
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Tue Mar 14 17:15:09 2023 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Mar 15 08:09:05 2023 +0000

    CppunitTest_sc_ucalc_formula: split in two
    
    it already has 118 tests
    
    Change-Id: I13d6fe65aca2fa01cf115c5873b9ca853cf5e77b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148891
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sc/CppunitTest_sc_ucalc_formula2.mk 
b/sc/CppunitTest_sc_ucalc_formula2.mk
new file mode 100644
index 000000000000..dc02436aa939
--- /dev/null
+++ b/sc/CppunitTest_sc_ucalc_formula2.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call sc_ucalc_test,_formula2))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk
index ba5f0710060a..b8761a24e78a 100644
--- a/sc/Module_sc.mk
+++ b/sc/Module_sc.mk
@@ -47,6 +47,7 @@ $(eval $(call gb_Module_add_check_targets,sc,\
        CppunitTest_sc_ucalc_copypaste \
        CppunitTest_sc_ucalc_datatransformation \
        CppunitTest_sc_ucalc_formula \
+       CppunitTest_sc_ucalc_formula2 \
        CppunitTest_sc_ucalc_parallelism \
        CppunitTest_sc_ucalc_pivottable \
        CppunitTest_sc_ucalc_rangelst \
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index d6453cf0815d..0c0c5d4481ad 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -9,7 +9,6 @@
 
 #include "helper/debughelper.hxx"
 #include "helper/qahelper.hxx"
-#include <clipparam.hxx>
 #include <scopetools.hxx>
 #include <formulacell.hxx>
 #include <docfunc.hxx>
@@ -17,67 +16,22 @@
 #include <tokenstringcontext.hxx>
 #include <refupdatecontext.hxx>
 #include <dbdata.hxx>
-#include <scmatrix.hxx>
 #include <validat.hxx>
 #include <scitems.hxx>
 #include <docpool.hxx>
-#include <docoptio.hxx>
-#include <externalrefmgr.hxx>
 #include <scmod.hxx>
 #include <undomanager.hxx>
-#include <broadcast.hxx>
 
 #include <formula/vectortoken.hxx>
-#include <svl/broadcast.hxx>
 #include <svl/intitem.hxx>
-#include <sfx2/docfile.hxx>
 
 #include <memory>
-#include <functional>
-#include <set>
 #include <algorithm>
 #include <vector>
 
 using namespace formula;
 
 namespace {
-
-ScRange getCachedRange(const ScExternalRefCache::TableTypeRef& pCacheTab)
-{
-    ScRange aRange;
-
-    vector<SCROW> aRows;
-    pCacheTab->getAllRows(aRows);
-    bool bFirst = true;
-    for (const SCROW nRow : aRows)
-    {
-        vector<SCCOL> aCols;
-        pCacheTab->getAllCols(nRow, aCols);
-        for (const SCCOL nCol : aCols)
-        {
-            if (bFirst)
-            {
-                aRange.aStart = ScAddress(nCol, nRow, 0);
-                aRange.aEnd = aRange.aStart;
-                bFirst = false;
-            }
-            else
-            {
-                if (nCol < aRange.aStart.Col())
-                    aRange.aStart.SetCol(nCol);
-                else if (aRange.aEnd.Col() < nCol)
-                    aRange.aEnd.SetCol(nCol);
-
-                if (nRow < aRange.aStart.Row())
-                    aRange.aStart.SetRow(nRow);
-                else if (aRange.aEnd.Row() < nRow)
-                    aRange.aEnd.SetRow(nRow);
-            }
-        }
-    }
-    return aRange;
-}
-
 void setExpandRefs(bool bExpand)
 {
     ScModule* pMod = SC_MOD();
@@ -130,85 +84,11 @@ void testFormulaRefUpdateNameCopySheetCheckTab( const 
ScDocument* pDoc, SCTAB nT
     CPPUNIT_ASSERT_EQUAL( 1100000.0 * nSheet, pDoc->GetValue(aPos));
 }
 
-class ColumnTest
-{
-    ScDocument * m_pDoc;
-
-    const SCROW m_nTotalRows;
-    const SCROW m_nStart1;
-    const SCROW m_nEnd1;
-    const SCROW m_nStart2;
-    const SCROW m_nEnd2;
-
-public:
-    ColumnTest( ScDocument * pDoc, SCROW nTotalRows,
-                SCROW nStart1, SCROW nEnd1, SCROW nStart2, SCROW nEnd2 )
-        : m_pDoc(pDoc), m_nTotalRows(nTotalRows)
-        , m_nStart1(nStart1), m_nEnd1(nEnd1)
-        , m_nStart2(nStart2), m_nEnd2(nEnd2)
-    {}
-
-    void operator() ( SCCOL nColumn, const OUString& rFormula,
-                      std::function<double(SCROW )> const & lExpected ) const
-    {
-        ScDocument aClipDoc(SCDOCMODE_CLIP);
-        ScMarkData aMark(m_pDoc->GetSheetLimits());
-
-        ScAddress aPos(nColumn, m_nStart1, 0);
-        m_pDoc->SetString(aPos, rFormula);
-        ASSERT_DOUBLES_EQUAL( lExpected(m_nStart1), m_pDoc->GetValue(aPos) );
-
-        // Copy formula cell to clipboard.
-        ScClipParam aClipParam(aPos, false);
-        aMark.SetMarkArea(aPos);
-        m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false);
-
-        // Paste it to first range.
-        InsertDeleteFlags nFlags = InsertDeleteFlags::CONTENTS;
-        ScRange aDestRange(nColumn, m_nStart1, 0, nColumn, m_nEnd1, 0);
-        aMark.SetMarkArea(aDestRange);
-        m_pDoc->CopyFromClip(aDestRange, aMark, nFlags, nullptr, &aClipDoc);
-
-        // Paste it second range.
-        aDestRange = ScRange(nColumn, m_nStart2, 0, nColumn, m_nEnd2, 0);
-        aMark.SetMarkArea(aDestRange);
-        m_pDoc->CopyFromClip(aDestRange, aMark, nFlags, nullptr, &aClipDoc);
-
-        // Check the formula results for passed column.
-        for( SCROW i = 0; i < m_nTotalRows; ++i )
-        {
-            if( !((m_nStart1 <= i && i <= m_nEnd1) || (m_nStart2 <= i && i <= 
m_nEnd2)) )
-                continue;
-            double fExpected = lExpected(i);
-            ASSERT_DOUBLES_EQUAL(fExpected, 
m_pDoc->GetValue(ScAddress(nColumn,i,0)));
-        }
-    }
-};
-
-}
-
-namespace {
-
-struct StrStrCheck {
-    const char* pVal;
-    const char* pRes;
-};
 
 }
 
 class TestFormula : public ScUcalcTestBase
 {
-protected:
-    template<size_t DataSize, size_t FormulaSize, int Type>
-    void runTestMATCH(ScDocument* pDoc, const char* aData[DataSize], const 
StrStrCheck aChecks[FormulaSize]);
-
-    template<size_t DataSize, size_t FormulaSize, int Type>
-    void runTestHorizontalMATCH(ScDocument* pDoc, const char* aData[DataSize], 
const StrStrCheck aChecks[FormulaSize]);
-
-    void testExtRefFuncT(ScDocument* pDoc, ScDocument& rExtDoc);
-    void testExtRefFuncOFFSET(ScDocument* pDoc, ScDocument& rExtDoc);
-    void testExtRefFuncVLOOKUP(ScDocument* pDoc, ScDocument& rExtDoc);
-    void testExtRefConcat(ScDocument* pDoc, ScDocument& rExtDoc);
 };
 
 CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaCreateStringFromTokens)
@@ -5156,4379 +5036,6 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFuncCOUNTIF)
     m_pDoc->DeleteTab(0);
 }
 
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncIF)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
-
-    m_pDoc->InsertTab(0, "Formula");
-
-    m_pDoc->SetString(ScAddress(0,0,0), "=IF(B1=2;\"two\";\"not two\")");
-    CPPUNIT_ASSERT_EQUAL(OUString("not two"), 
m_pDoc->GetString(ScAddress(0,0,0)));
-    m_pDoc->SetValue(ScAddress(1,0,0), 2.0);
-    CPPUNIT_ASSERT_EQUAL(OUString("two"), m_pDoc->GetString(ScAddress(0,0,0)));
-    m_pDoc->SetValue(ScAddress(1,0,0), 3.0);
-    CPPUNIT_ASSERT_EQUAL(OUString("not two"), 
m_pDoc->GetString(ScAddress(0,0,0)));
-
-    // Test nested IF in array/matrix if the nested IF condition is a scalar.
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    m_pDoc->InsertMatrixFormula(0,2, 1,2, aMark, "=IF({1;0};IF(1;23);42)");
-    // Results must be 23 and 42.
-    CPPUNIT_ASSERT_EQUAL(23.0, m_pDoc->GetValue(ScAddress(0,2,0)));
-    CPPUNIT_ASSERT_EQUAL(42.0, m_pDoc->GetValue(ScAddress(1,2,0)));
-
-    // Test nested IF in array/matrix if nested IF conditions are range
-    // references, data in A5:C8, matrix formula in D4 so there is no
-    // implicit intersection between formula and ranges.
-    {
-        std::vector<std::vector<const char*>> aData = {
-            { "1", "1", "16" },
-            { "0", "1", "32" },
-            { "1", "0", "64" },
-            { "0", "0", "128" }
-        };
-        ScAddress aPos(0,4,0);
-        ScRange aRange = insertRangeData(m_pDoc, aPos, aData);
-        CPPUNIT_ASSERT_EQUAL(aPos, aRange.aStart);
-    }
-    m_pDoc->InsertMatrixFormula(3,3, 3,3, aMark, 
"=SUM(IF(A5:A8;IF(B5:B8;C5:C8;0);0))");
-    // Result must be 16, only the first row matches all criteria.
-    CPPUNIT_ASSERT_EQUAL(16.0, m_pDoc->GetValue(ScAddress(3,3,0)));
-
-    // A11:B11
-    // Test nested IF in array/matrix if the nested IF has no Else path.
-    m_pDoc->InsertMatrixFormula(0,10, 1,10, aMark, "=IF(IF({1;0};12);34;56)");
-    // Results must be 34 and 56.
-    CPPUNIT_ASSERT_EQUAL(34.0, m_pDoc->GetValue(ScAddress(0,10,0)));
-    CPPUNIT_ASSERT_EQUAL(56.0, m_pDoc->GetValue(ScAddress(1,10,0)));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncCHOOSE)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
-
-    m_pDoc->InsertTab(0, "Formula");
-
-    m_pDoc->SetString(ScAddress(0,0,0), 
"=CHOOSE(B1;\"one\";\"two\";\"three\")");
-    FormulaError nError = m_pDoc->GetErrCode(ScAddress(0,0,0));
-    CPPUNIT_ASSERT_MESSAGE("Formula result should be an error since B1 is 
still empty.", nError != FormulaError::NONE);
-    m_pDoc->SetValue(ScAddress(1,0,0), 1.0);
-    CPPUNIT_ASSERT_EQUAL(OUString("one"), m_pDoc->GetString(ScAddress(0,0,0)));
-    m_pDoc->SetValue(ScAddress(1,0,0), 2.0);
-    CPPUNIT_ASSERT_EQUAL(OUString("two"), m_pDoc->GetString(ScAddress(0,0,0)));
-    m_pDoc->SetValue(ScAddress(1,0,0), 3.0);
-    CPPUNIT_ASSERT_EQUAL(OUString("three"), 
m_pDoc->GetString(ScAddress(0,0,0)));
-    m_pDoc->SetValue(ScAddress(1,0,0), 4.0);
-    nError = m_pDoc->GetErrCode(ScAddress(0,0,0));
-    CPPUNIT_ASSERT_MESSAGE("Formula result should be an error due to 
out-of-bound input..", nError != FormulaError::NONE);
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncIFERROR)
-{
-    // IFERROR/IFNA (fdo#56124)
-
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    // Empty A1:A39 first.
-    clearRange(m_pDoc, ScRange(0, 0, 0, 0, 40, 0));
-
-    // Raw data (rows 1 through 12)
-    const char* aData[] = {
-        "1",
-        "e",
-        "=SQRT(4)",
-        "=SQRT(-2)",
-        "=A4",
-        "=1/0",
-        "=NA()",
-        "bar",
-        "4",
-        "gee",
-        "=1/0",
-        "23"
-    };
-
-    SCROW nRows = SAL_N_ELEMENTS(aData);
-    for (SCROW i = 0; i < nRows; ++i)
-        m_pDoc->SetString(0, i, 0, OUString::createFromAscii(aData[i]));
-
-    printRange(m_pDoc, ScRange(0, 0, 0, 0, nRows-1, 0), "data range for 
IFERROR/IFNA");
-
-    // formulas and results
-    static const struct {
-        const char* pFormula; const char* pResult;
-    } aChecks[] = {
-        { "=IFERROR(A1;9)",                         "1" },
-        { "=IFERROR(A2;9)",                         "e" },
-        { "=IFERROR(A3;9)",                         "2" },
-        { "=IFERROR(A4;-7)",                       "-7" },
-        { "=IFERROR(A5;-7)",                       "-7" },
-        { "=IFERROR(A6;-7)",                       "-7" },
-        { "=IFERROR(A7;-7)",                       "-7" },
-        { "=IFNA(A6;9)",                      "#DIV/0!" },
-        { "=IFNA(A7;-7)",                          "-7" },
-        { "=IFNA(VLOOKUP(\"4\";A8:A10;1;0);-2)",    "4" },
-        { "=IFNA(VLOOKUP(\"fop\";A8:A10;1;0);-2)", "-2" },
-        { "{=IFERROR(3*A11:A12;1998)}[0]",       "1998" },  // um... this is 
not the correct way to insert a
-        { "{=IFERROR(3*A11:A12;1998)}[1]",         "69" }   // matrix formula, 
just a place holder, see below
-    };
-
-    nRows = SAL_N_ELEMENTS(aChecks);
-    for (SCROW i = 0; i < nRows-2; ++i)
-    {
-        SCROW nRow = 20 + i;
-        m_pDoc->SetString(0, nRow, 0, 
OUString::createFromAscii(aChecks[i].pFormula));
-    }
-
-    // Create a matrix range in last two rows of the range above, actual data
-    // of the placeholders.
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    m_pDoc->InsertMatrixFormula(0, 20 + nRows-2, 0, 20 + nRows-1, aMark, 
"=IFERROR(3*A11:A12;1998)");
-
-    m_pDoc->CalcAll();
-
-    for (SCROW i = 0; i < nRows; ++i)
-    {
-        SCROW nRow = 20 + i;
-        OUString aResult = m_pDoc->GetString(0, nRow, 0);
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-            aChecks[i].pFormula, OUString::createFromAscii( 
aChecks[i].pResult), aResult);
-    }
-
-    const SCCOL nCols = 3;
-    std::vector<std::vector<const char*>> aData2 = {
-        { "1", "2",    "3" },
-        { "4", "=1/0", "6" },
-        { "7", "8",    "9" }
-    };
-    const char* aCheck2[][nCols] = {
-        { "1", "2",    "3" },
-        { "4", "Error","6" },
-        { "7", "8",    "9" }
-    };
-
-    // Data in C1:E3
-    ScAddress aPos(2,0,0);
-    ScRange aRange = insertRangeData(m_pDoc, aPos, aData2);
-    CPPUNIT_ASSERT_EQUAL(aPos, aRange.aStart);
-
-    // Array formula in F4:H6
-    const SCROW nElems2 = SAL_N_ELEMENTS(aCheck2);
-    const SCCOL nStartCol = aPos.Col() + nCols;
-    const SCROW nStartRow = aPos.Row() + nElems2;
-    m_pDoc->InsertMatrixFormula( nStartCol, nStartRow, nStartCol+nCols-1, 
nStartRow+nElems2-1, aMark,
-            "=IFERROR(C1:E3;\"Error\")");
-
-    m_pDoc->CalcAll();
-
-    for (SCCOL nCol = nStartCol; nCol < nStartCol + nCols; ++nCol)
-    {
-        for (SCROW nRow = nStartRow; nRow < nStartRow + nElems2; ++nRow)
-        {
-            OUString aResult = m_pDoc->GetString( nCol, nRow, 0);
-            CPPUNIT_ASSERT_EQUAL_MESSAGE( "IFERROR array result",
-                    OUString::createFromAscii( 
aCheck2[nRow-nStartRow][nCol-nStartCol]), aResult);
-        }
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncSHEET)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (SC_TAB_APPEND, "test1"));
-
-    m_pDoc->SetString(0, 0, 0, "=SHEETS()");
-    m_pDoc->CalcFormulaTree(false, false);
-    double original = m_pDoc->GetValue(0, 0, 0);
-
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("result of SHEETS() should equal the number 
of sheets, but doesn't.",
-                           static_cast<SCTAB>(original), 
m_pDoc->GetTableCount());
-
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (SC_TAB_APPEND, "test2"));
-
-    double modified = m_pDoc->GetValue(0, 0, 0);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("result of SHEETS() did not get updated after 
sheet insertion.",
-                           1.0, modified - original);
-
-    SCTAB nTabCount = m_pDoc->GetTableCount();
-    m_pDoc->DeleteTab(--nTabCount);
-
-    modified = m_pDoc->GetValue(0, 0, 0);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("result of SHEETS() did not get updated after 
sheet removal.",
-                           0.0, modified - original);
-
-    m_pDoc->DeleteTab(--nTabCount);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncNOW)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    double val = 1;
-    m_pDoc->SetValue(0, 0, 0, val);
-    m_pDoc->SetString(0, 1, 0, "=IF(A1>0;NOW();0");
-    double now1 = m_pDoc->GetValue(0, 1, 0);
-    CPPUNIT_ASSERT_MESSAGE("Value of NOW() should be positive.", now1 > 0.0);
-
-    val = 0;
-    m_pDoc->SetValue(0, 0, 0, val);
-    m_pDoc->CalcFormulaTree(false, false);
-    double zero = m_pDoc->GetValue(0, 1, 0);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Result should equal the 3rd parameter of IF, 
which is zero.", 0.0, zero);
-
-    val = 1;
-    m_pDoc->SetValue(0, 0, 0, val);
-    m_pDoc->CalcFormulaTree(false, false);
-    double now2 = m_pDoc->GetValue(0, 1, 0);
-    CPPUNIT_ASSERT_MESSAGE("Result should be the value of NOW() again.", (now2 
- now1) >= 0.0);
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncNUMBERVALUE)
-{
-    // NUMBERVALUE fdo#57180
-
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    // Empty A1:A39 first.
-    clearRange(m_pDoc, ScRange(0, 0, 0, 0, 40, 0));
-
-    // Raw data (rows 1 through 6)
-    const char* aData[] = {
-        "1ag9a9b9",
-        "1ag34 5g g6  78b9%%",
-        "1 234d56E-2",
-        "d4",
-        "54.4",
-        "1a2b3e1%"
-    };
-
-    SCROW nRows = SAL_N_ELEMENTS(aData);
-    for (SCROW i = 0; i < nRows; ++i)
-        m_pDoc->SetString(0, i, 0, OUString::createFromAscii(aData[i]));
-
-    printRange(m_pDoc, ScRange(0, 0, 0, 0, nRows - 1, 0), "data range for 
NUMBERVALUE");
-
-    // formulas and results
-    static const struct {
-        const char* pFormula; const char* pResult;
-    } aChecks[] = {
-        { "=NUMBERVALUE(A1;\"b\";\"ag\")",  "199.9" },
-        { "=NUMBERVALUE(A2;\"b\";\"ag\")",  "134.56789" },
-        { "=NUMBERVALUE(A2;\"b\";\"g\")",   "#VALUE!" },
-        { "=NUMBERVALUE(A3;\"d\")",         "12.3456" },
-        { "=NUMBERVALUE(A4;\"d\";\"foo\")", "0.4" },
-        { "=NUMBERVALUE(A4;)",              "Err:502" },
-        { "=NUMBERVALUE(A5;)",              "Err:502" },
-        { "=NUMBERVALUE(A6;\"b\";\"a\")",   "1.23" }
-    };
-
-    nRows = SAL_N_ELEMENTS(aChecks);
-    for (SCROW i = 0; i < nRows; ++i)
-    {
-        SCROW nRow = 20 + i;
-        m_pDoc->SetString(0, nRow, 0, 
OUString::createFromAscii(aChecks[i].pFormula));
-    }
-    m_pDoc->CalcAll();
-
-    for (SCROW i = 0; i < nRows; ++i)
-    {
-        SCROW nRow = 20 + i;
-        OUString aResult = m_pDoc->GetString(0, nRow, 0);
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(
-            aChecks[i].pFormula, OUString::createFromAscii( 
aChecks[i].pResult), aResult);
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncLEN)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
-
-    m_pDoc->InsertTab(0, "Formula");
-
-    // Leave A1:A3 empty, and insert an array of LEN in B1:B3 that references
-    // these empty cells.
-
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    m_pDoc->InsertMatrixFormula(1, 0, 1, 2, aMark, "=LEN(A1:A3)");
-
-    ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
-    CPPUNIT_ASSERT(pFC);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("This formula should be a matrix origin.",
-                           ScMatrixMode::Formula, pFC->GetMatrixFlag());
-
-    // This should be a 1x3 matrix.
-    SCCOL nCols = -1;
-    SCROW nRows = -1;
-    pFC->GetMatColsRows(nCols, nRows);
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCols);
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), nRows);
-
-    // LEN value should be 0 for an empty cell.
-    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(1,0,0)));
-    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(1,1,0)));
-    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(1,2,0)));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncLOOKUP)
-{
-    FormulaGrammarSwitch aFGSwitch(m_pDoc, 
formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
-
-    m_pDoc->InsertTab(0, "Test");
-
-    // Raw data
-    const char* aData[][2] = {
-        { "=CONCATENATE(\"A\")", "1" },
-        { "=CONCATENATE(\"B\")", "2" },
-        { "=CONCATENATE(\"C\")", "3" },
-        { nullptr, nullptr } // terminator
-    };
-
-    // Insert raw data into A1:B3.
-    for (SCROW i = 0; aData[i][0]; ++i)
-    {
-        m_pDoc->SetString(0, i, 0, OUString::createFromAscii(aData[i][0]));
-        m_pDoc->SetString(1, i, 0, OUString::createFromAscii(aData[i][1]));
-    }
-
-    const char* aData2[][2] = {
-        { "A", "=LOOKUP(RC[-1];R1C1:R3C1;R1C2:R3C2)" },
-        { "B", "=LOOKUP(RC[-1];R1C1:R3C1;R1C2:R3C2)" },
-        { "C", "=LOOKUP(RC[-1];R1C1:R3C1;R1C2:R3C2)" },
-        { nullptr, nullptr } // terminator
-    };
-
-    // Insert check formulas into A5:B7.
-    for (SCROW i = 0; aData2[i][0]; ++i)
-    {
-        m_pDoc->SetString(0, i+4, 0, OUString::createFromAscii(aData2[i][0]));
-        m_pDoc->SetString(1, i+4, 0, OUString::createFromAscii(aData2[i][1]));
-    }
-
-    printRange(m_pDoc, ScRange(0,4,0,1,6,0), "Data range for LOOKUP.");
-
-    // Values for B5:B7 should be 1, 2, and 3.
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("This formula should not have an error 
code.", 0, static_cast<int>(m_pDoc->GetErrCode(ScAddress(1,4,0))));
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("This formula should not have an error 
code.", 0, static_cast<int>(m_pDoc->GetErrCode(ScAddress(1,5,0))));
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("This formula should not have an error 
code.", 0, static_cast<int>(m_pDoc->GetErrCode(ScAddress(1,6,0))));
-
-    ASSERT_DOUBLES_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,4,0)));
-    ASSERT_DOUBLES_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,5,0)));
-    ASSERT_DOUBLES_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,6,0)));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncLOOKUParrayWithError)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true);
-    m_pDoc->InsertTab(0, "Test");
-
-    std::vector<std::vector<const char*>> aData = {
-        { "x", "y", "z" },
-        { "a", "b", "c" }
-    };
-    insertRangeData(m_pDoc, ScAddress(2,1,0), aData);               // C2:E3
-    m_pDoc->SetString(0,0,0, "=LOOKUP(2;1/(C2:E2<>\"\");C3:E3)");   // A1
-
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Should find match for last column.", 
OUString("c"), m_pDoc->GetString(0,0,0));
-    m_pDoc->SetString(4,1,0, "");                                   // E2
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Should find match for second last column.", 
OUString("b"), m_pDoc->GetString(0,0,0));
-
-    m_pDoc->SetString(6,1,0, "one");                                // G2
-    m_pDoc->SetString(6,5,0, "two");                                // G6
-    // Creates an interim array 
{1,#DIV/0!,#DIV/0!,#DIV/0!,1,#DIV/0!,#DIV/0!,#DIV/0!}
-    m_pDoc->SetString(7,8,0, "=LOOKUP(2;1/(NOT(ISBLANK(G2:G9)));G2:G9)"); // H9
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Should find match for last row.", 
OUString("two"), m_pDoc->GetString(7,8,0));
-
-    // Lookup on empty range.
-    m_pDoc->SetString(9,8,0, "=LOOKUP(2;1/(NOT(ISBLANK(I2:I9)));I2:I9)"); // J9
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Should find no match.", OUString("#N/A"), 
m_pDoc->GetString(9,8,0));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testTdf141146)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true);
-    m_pDoc->InsertTab(0, "Test1");
-    m_pDoc->InsertTab(1, "Test2");
-
-    std::vector<std::vector<const char*>> aData = {
-        { "k1", "value1"},
-        { "k2", "value2"},
-        { "k3", "value3"}
-    };
-
-    insertRangeData(m_pDoc, ScAddress(0,1,1), aData); // A2:B4
-    m_pDoc->SetString(4,0,1, "k2");                   // E1
-
-    m_pDoc->SetString(4,1,1, "=LOOKUP(1;1/(A$2:A$4=E$1);1)");
-    m_pDoc->SetString(4,2,1, "=LOOKUP(E1;A$2:A$4;B2:B4)");
-    m_pDoc->SetString(4,3,1, "=LOOKUP(1;1/(A$2:A$4=E$1);B2:B4)");
-
-    // Without the fix in place, this test would have failed with
-    // - Expected: #N/A
-    // - Actual  :
-    CPPUNIT_ASSERT_EQUAL(OUString("#N/A"), m_pDoc->GetString(4,1,1));
-    CPPUNIT_ASSERT_EQUAL(OUString("value2"), m_pDoc->GetString(4,2,1));
-    CPPUNIT_ASSERT_EQUAL(OUString("value2"), m_pDoc->GetString(4,3,1));
-
-    m_pDoc->DeleteTab(1);
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncVLOOKUP)
-{
-    // VLOOKUP
-
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    // Clear A1:F40.
-    clearRange(m_pDoc, ScRange(0, 0, 0, 5, 39, 0));
-
-    // Raw data
-    const char* aData[][2] = {
-        { "Key", "Val" },
-        {  "10",   "3" },
-        {  "20",   "4" },
-        {  "30",   "5" },
-        {  "40",   "6" },
-        {  "50",   "7" },
-        {  "60",   "8" },
-        {  "70",   "9" },
-        {   "B",  "10" },
-        {   "B",  "11" },
-        {   "C",  "12" },
-        {   "D",  "13" },
-        {   "E",  "14" },
-        {   "F",  "15" },
-        { nullptr, nullptr } // terminator
-    };
-
-    // Insert raw data into A1:B14.
-    for (SCROW i = 0; aData[i][0]; ++i)
-    {
-        m_pDoc->SetString(0, i, 0, OUString::createFromAscii(aData[i][0]));
-        m_pDoc->SetString(1, i, 0, OUString::createFromAscii(aData[i][1]));
-    }
-
-    printRange(m_pDoc, ScRange(0, 0, 0, 1, 13, 0), "raw data for VLOOKUP");
-
-    // Formula data
-    static const struct {
-        const char* pLookup; const char* pFormula; const char* pRes;
-    } aChecks[] = {
-        { "Lookup",  "Formula", nullptr },
-        { "12",      "=VLOOKUP(D2;A2:B14;2;1)",     "3" },
-        { "29",      "=VLOOKUP(D3;A2:B14;2;1)",     "4" },
-        { "31",      "=VLOOKUP(D4;A2:B14;2;1)",     "5" },
-        { "45",      "=VLOOKUP(D5;A2:B14;2;1)",     "6" },
-        { "56",      "=VLOOKUP(D6;A2:B14;2;1)",     "7" },
-        { "65",      "=VLOOKUP(D7;A2:B14;2;1)",     "8" },
-        { "78",      "=VLOOKUP(D8;A2:B14;2;1)",     "9" },
-        { "Andy",    "=VLOOKUP(D9;A2:B14;2;1)",  "#N/A" },
-        { "Bruce",   "=VLOOKUP(D10;A2:B14;2;1)",   "11" },
-        { "Charlie", "=VLOOKUP(D11;A2:B14;2;1)",   "12" },
-        { "David",   "=VLOOKUP(D12;A2:B14;2;1)",   "13" },
-        { "Edward",  "=VLOOKUP(D13;A2:B14;2;1)",   "14" },
-        { "Frank",   "=VLOOKUP(D14;A2:B14;2;1)",   "15" },
-        { "Henry",   "=VLOOKUP(D15;A2:B14;2;1)",   "15" },
-        { "100",     "=VLOOKUP(D16;A2:B14;2;1)",    "9" },
-        { "1000",    "=VLOOKUP(D17;A2:B14;2;1)",    "9" },
-        { "Zena",    "=VLOOKUP(D18;A2:B14;2;1)",   "15" }
-    };
-
-    // Insert formula data into D1:E18.
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-    {
-        m_pDoc->SetString(3, i, 0, 
OUString::createFromAscii(aChecks[i].pLookup));
-        m_pDoc->SetString(4, i, 0, 
OUString::createFromAscii(aChecks[i].pFormula));
-    }
-    m_pDoc->CalcAll();
-    printRange(m_pDoc, ScRange(3, 0, 0, 4, 17, 0), "formula data for VLOOKUP");
-
-    // Verify results.
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-    {
-        if (i == 0)
-            // Skip the header row.
-            continue;
-
-        OUString aRes = m_pDoc->GetString(4, i, 0);
-        bool bGood = aRes.equalsAscii(aChecks[i].pRes);
-        if (!bGood)
-        {
-            cerr << "row " << (i+1) << ": lookup value='" << aChecks[i].pLookup
-                << "'  expected='" << aChecks[i].pRes << "' actual='" << aRes 
<< "'" << endl;
-            CPPUNIT_ASSERT_MESSAGE("Unexpected result for VLOOKUP", false);
-        }
-    }
-
-    // Clear the sheet and start over.
-    clearSheet(m_pDoc, 0);
-
-    // Lookup on sorted data interspersed with empty cells.
-
-    // A1:B8 is the search range.
-    m_pDoc->SetValue(ScAddress(0,2,0), 1.0);
-    m_pDoc->SetValue(ScAddress(0,4,0), 2.0);
-    m_pDoc->SetValue(ScAddress(0,7,0), 4.0);
-    m_pDoc->SetString(ScAddress(1,2,0), "One");
-    m_pDoc->SetString(ScAddress(1,4,0), "Two");
-    m_pDoc->SetString(ScAddress(1,7,0), "Four");
-
-    // D1:D5 contain match values.
-    m_pDoc->SetValue(ScAddress(3,0,0), 1.0);
-    m_pDoc->SetValue(ScAddress(3,1,0), 2.0);
-    m_pDoc->SetValue(ScAddress(3,2,0), 3.0);
-    m_pDoc->SetValue(ScAddress(3,3,0), 4.0);
-    m_pDoc->SetValue(ScAddress(3,4,0), 5.0);
-
-    // E1:E5 contain formulas.
-    m_pDoc->SetString(ScAddress(4,0,0), "=VLOOKUP(D1;$A$1:$B$8;2)");
-    m_pDoc->SetString(ScAddress(4,1,0), "=VLOOKUP(D2;$A$1:$B$8;2)");
-    m_pDoc->SetString(ScAddress(4,2,0), "=VLOOKUP(D3;$A$1:$B$8;2)");
-    m_pDoc->SetString(ScAddress(4,3,0), "=VLOOKUP(D4;$A$1:$B$8;2)");
-    m_pDoc->SetString(ScAddress(4,4,0), "=VLOOKUP(D5;$A$1:$B$8;2)");
-    m_pDoc->CalcAll();
-
-    // Check the formula results in E1:E5.
-    CPPUNIT_ASSERT_EQUAL(OUString("One"), m_pDoc->GetString(ScAddress(4,0,0)));
-    CPPUNIT_ASSERT_EQUAL(OUString("Two"), m_pDoc->GetString(ScAddress(4,1,0)));
-    CPPUNIT_ASSERT_EQUAL(OUString("Two"), m_pDoc->GetString(ScAddress(4,2,0)));
-    CPPUNIT_ASSERT_EQUAL(OUString("Four"), 
m_pDoc->GetString(ScAddress(4,3,0)));
-    CPPUNIT_ASSERT_EQUAL(OUString("Four"), 
m_pDoc->GetString(ScAddress(4,4,0)));
-
-    // Start over again.
-    clearSheet(m_pDoc, 0);
-
-    // Set A,B,...,G to A1:A7.
-    m_pDoc->SetString(ScAddress(0,0,0), "A");
-    m_pDoc->SetString(ScAddress(0,1,0), "B");
-    m_pDoc->SetString(ScAddress(0,2,0), "C");
-    m_pDoc->SetString(ScAddress(0,3,0), "D");
-    m_pDoc->SetString(ScAddress(0,4,0), "E");
-    m_pDoc->SetString(ScAddress(0,5,0), "F");
-    m_pDoc->SetString(ScAddress(0,6,0), "G");
-
-    // Set the formula in C1.
-    m_pDoc->SetString(ScAddress(2,0,0), "=VLOOKUP(\"C\";A1:A16;1)");
-    CPPUNIT_ASSERT_EQUAL(OUString("C"), m_pDoc->GetString(ScAddress(2,0,0)));
-
-
-    // A21:E24, test position dependent implicit intersection as argument to a
-    // scalar value parameter in a function that has a ReferenceOrForceArray
-    // type parameter somewhere else and formula is not in array mode,
-    // VLOOKUP(Value;ReferenceOrForceArray;...)
-    std::vector<std::vector<const char*>> aData2 = {
-        { "1", "one",   "3", "=VLOOKUP(C21:C24;A21:B24;2;0)", "three" },
-        { "2", "two",   "1", "=VLOOKUP(C21:C24;A21:B24;2;0)", "one"   },
-        { "3", "three", "4", "=VLOOKUP(C21:C24;A21:B24;2;0)", "four"  },
-        { "4", "four",  "2", "=VLOOKUP(C21:C24;A21:B24;2;0)", "two"   }
-    };
-
-    ScAddress aPos2(0,20,0);
-    ScRange aRange2 = insertRangeData(m_pDoc, aPos2, aData2);
-    CPPUNIT_ASSERT_EQUAL(aPos2, aRange2.aStart);
-
-    aPos2.SetCol(3);    // column D formula results
-    for (size_t i=0; i < aData2.size(); ++i)
-    {
-        CPPUNIT_ASSERT_EQUAL( OUString::createFromAscii( aData2[i][4]), 
m_pDoc->GetString(aPos2));
-        aPos2.IncRow();
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-template<size_t DataSize, size_t FormulaSize, int Type>
-void TestFormula::runTestMATCH(ScDocument* pDoc, const char* aData[DataSize], 
const StrStrCheck aChecks[FormulaSize])
-{
-    size_t nDataSize = DataSize;
-    for (size_t i = 0; i < nDataSize; ++i)
-        pDoc->SetString(0, i, 0, OUString::createFromAscii(aData[i]));
-
-    for (size_t i = 0; i < FormulaSize; ++i)
-    {
-        pDoc->SetString(1, i, 0, OUString::createFromAscii(aChecks[i].pVal));
-
-        OUString aFormula = "=MATCH(B" + OUString::number(i+1) + ";A1:A"
-            + OUString::number(nDataSize) + ";" + OUString::number(Type) + ")";
-        pDoc->SetString(2, i, 0, aFormula);
-    }
-
-    pDoc->CalcAll();
-    printRange(pDoc, ScRange(0, 0, 0, 2, FormulaSize-1, 0), "MATCH");
-
-    // verify the results.
-    for (size_t i = 0; i < FormulaSize; ++i)
-    {
-        OUString aStr = pDoc->GetString(2, i, 0);
-        if (!aStr.equalsAscii(aChecks[i].pRes))
-        {
-            cerr << "row " << (i+1) << ": expected='" << aChecks[i].pRes << "' 
actual='" << aStr << "'"
-                " criterion='" << aChecks[i].pVal << "'" << endl;
-            CPPUNIT_ASSERT_MESSAGE("Unexpected result for MATCH", false);
-        }
-    }
-}
-
-template<size_t DataSize, size_t FormulaSize, int Type>
-void TestFormula::runTestHorizontalMATCH(ScDocument* pDoc, const char* 
aData[DataSize], const StrStrCheck aChecks[FormulaSize])
-{
-    size_t nDataSize = DataSize;
-    for (size_t i = 0; i < nDataSize; ++i)
-        pDoc->SetString(i, 0, 0, OUString::createFromAscii(aData[i]));
-
-    for (size_t i = 0; i < FormulaSize; ++i)
-    {
-        pDoc->SetString(i, 1, 0, OUString::createFromAscii(aChecks[i].pVal));
-
-        // Assume we don't have more than 26 data columns...
-        OUString aFormula = "=MATCH(" + 
OUStringChar(static_cast<sal_Unicode>('A'+i)) + "2;A1:"
-            + OUStringChar(static_cast<sal_Unicode>('A'+nDataSize)) + "1;" + 
OUString::number(Type)
-            + ")";
-        pDoc->SetString(i, 2, 0, aFormula);
-    }
-
-    pDoc->CalcAll();
-    printRange(pDoc, ScRange(0, 0, 0, FormulaSize-1, 2, 0), "MATCH");
-
-    // verify the results.
-    for (size_t i = 0; i < FormulaSize; ++i)
-    {
-        OUString aStr = pDoc->GetString(i, 2, 0);
-        if (!aStr.equalsAscii(aChecks[i].pRes))
-        {
-            cerr << "column " << char('A'+i) << ": expected='" << 
aChecks[i].pRes << "' actual='" << aStr << "'"
-                " criterion='" << aChecks[i].pVal << "'" << endl;
-            CPPUNIT_ASSERT_MESSAGE("Unexpected result for horizontal MATCH", 
false);
-        }
-    }
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncMATCH)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    clearRange(m_pDoc, ScRange(0, 0, 0, 40, 40, 0));
-    {
-        // Ascending in-exact match
-
-        // data range (A1:A9)
-        const char* aData[] = {
-            "1",
-            "2",
-            "3",
-            "4",
-            "5",
-            "6",
-            "7",
-            "8",
-            "9",
-            "B",
-            "B",
-            "C",
-        };
-
-        // formula (B1:C12)
-        static const StrStrCheck aChecks[] = {
-            { "0.8",   "#N/A" },
-            { "1.2",      "1" },
-            { "2.3",      "2" },
-            { "3.9",      "3" },
-            { "4.1",      "4" },
-            { "5.99",     "5" },
-            { "6.1",      "6" },
-            { "7.2",      "7" },
-            { "8.569",    "8" },
-            { "9.59",     "9" },
-            { "10",       "9" },
-            { "100",      "9" },
-            { "Andy",  "#N/A" },
-            { "Bruce",   "11" },
-            { "Charlie", "12" }
-        };
-
-        runTestMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),1>(m_pDoc, 
aData, aChecks);
-        clearRange(m_pDoc, ScRange(0, 0, 0, 4, 40, 0));
-        
runTestHorizontalMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),1>(m_pDoc, 
aData, aChecks);
-        clearRange(m_pDoc, ScRange(0, 0, 0, 40, 4, 0));
-    }
-
-    {
-        // Descending in-exact match
-
-        // data range (A1:A9)
-        const char* aData[] = {
-            "D",
-            "C",
-            "B",
-            "9",
-            "8",
-            "7",
-            "6",
-            "5",
-            "4",
-            "3",
-            "2",
-            "1"
-        };
-
-        // formula (B1:C12)
-        static const StrStrCheck aChecks[] = {
-            { "10",      "#N/A" },
-            { "8.9",     "4" },
-            { "7.8",     "5" },
-            { "6.7",     "6" },
-            { "5.5",     "7" },
-            { "4.6",     "8" },
-            { "3.3",     "9" },
-            { "2.2",     "10" },
-            { "1.1",     "11" },
-            { "0.8",     "12" },
-            { "0",       "12" },
-            { "-2",      "12" },
-            { "Andy",    "3" },
-            { "Bruce",   "2" },
-            { "Charlie", "1" },
-            { "David", "#N/A" }
-        };
-
-        runTestMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),-1>(m_pDoc, 
aData, aChecks);
-        clearRange(m_pDoc, ScRange(0, 0, 0, 4, 40, 0));
-        
runTestHorizontalMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),-1>(m_pDoc,
 aData, aChecks);
-        clearRange(m_pDoc, ScRange(0, 0, 0, 40, 4, 0));
-    }
-
-    {
-        // search range contains leading and trailing empty cell ranges.
-
-        clearRange(m_pDoc, ScRange(0,0,0,2,100,0));
-
-        // A5:A8 contains sorted values.
-        m_pDoc->SetValue(ScAddress(0,4,0), 1.0);
-        m_pDoc->SetValue(ScAddress(0,5,0), 2.0);
-        m_pDoc->SetValue(ScAddress(0,6,0), 3.0);
-        m_pDoc->SetValue(ScAddress(0,7,0), 4.0);
-
-        // Find value 2 which is in A6.
-        m_pDoc->SetString(ScAddress(1,0,0), "=MATCH(2;A1:A20)");
-        m_pDoc->CalcAll();
-
-        CPPUNIT_ASSERT_EQUAL(OUString("6"), 
m_pDoc->GetString(ScAddress(1,0,0)));
-    }
-
-    {
-        // Test the ReferenceOrForceArray parameter.
-
-        clearRange(m_pDoc, ScRange(0,0,0,1,7,0));
-
-        // B1:B5 contain numeric values.
-        m_pDoc->SetValue(ScAddress(1,0,0), 1.0);
-        m_pDoc->SetValue(ScAddress(1,1,0), 2.0);
-        m_pDoc->SetValue(ScAddress(1,2,0), 3.0);
-        m_pDoc->SetValue(ScAddress(1,3,0), 4.0);
-        m_pDoc->SetValue(ScAddress(1,4,0), 5.0);
-
-        // Find string value "33" in concatenated array, no implicit
-        // intersection is involved, array is forced.
-        m_pDoc->SetString(ScAddress(0,5,0), "=MATCH(\"33\";B1:B5&B1:B5)");
-        m_pDoc->CalcAll();
-        CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,5,0)));
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncCELL)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    clearRange(m_pDoc, ScRange(0, 0, 0, 2, 20, 0)); // Clear A1:C21.
-
-    {
-        const char* pContent = "Some random text";
-        m_pDoc->SetString(2, 9, 0, OUString::createFromAscii(pContent)); // 
Set this value to C10.
-        m_pDoc->SetValue(2, 0, 0, 1.2); // Set numeric value to C1;
-
-        // We don't test: FILENAME, FORMAT, WIDTH, PROTECT, PREFIX
-        StrStrCheck aChecks[] = {
-            { "=CELL(\"COL\";C10)",           "3" },
-            { "=CELL(\"COL\";C5:C10)",        "3" },
-            { "=CELL(\"ROW\";C10)",          "10" },
-            { "=CELL(\"ROW\";C10:E10)",      "10" },
-            { "=CELL(\"SHEET\";C10)",         "1" },
-            { "=CELL(\"ADDRESS\";C10)",   "$C$10" },
-            { "=CELL(\"CONTENTS\";C10)", pContent },
-            { "=CELL(\"COLOR\";C10)",         "0" },
-            { "=CELL(\"TYPE\";C9)",           "b" },
-            { "=CELL(\"TYPE\";C10)",          "l" },
-            { "=CELL(\"TYPE\";C1)",           "v" },
-            { "=CELL(\"PARENTHESES\";C10)",   "0" }
-        };
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-            m_pDoc->SetString(0, i, 0, 
OUString::createFromAscii(aChecks[i].pVal));
-        m_pDoc->CalcAll();
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-        {
-            OUString aVal = m_pDoc->GetString(0, i, 0);
-            CPPUNIT_ASSERT_MESSAGE("Unexpected result for CELL", 
aVal.equalsAscii(aChecks[i].pRes));
-        }
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-/** See also test case document fdo#44456 sheet cpearson */
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncDATEDIF)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-
-    std::vector<std::vector<const char*>> aData = {
-        { "2007-01-01", "2007-01-10",  "d",   "9", "=DATEDIF(A1;B1;C1)" } ,
-        { "2007-01-01", "2007-01-31",  "m",   "0", "=DATEDIF(A2;B2;C2)" } ,
-        { "2007-01-01", "2007-02-01",  "m",   "1", "=DATEDIF(A3;B3;C3)" } ,
-        { "2007-01-01", "2007-02-28",  "m",   "1", "=DATEDIF(A4;B4;C4)" } ,
-        { "2007-01-01", "2007-12-31",  "d", "364", "=DATEDIF(A5;B5;C5)" } ,
-        { "2007-01-01", "2007-01-31",  "y",   "0", "=DATEDIF(A6;B6;C6)" } ,
-        { "2007-01-01", "2008-07-01",  "d", "547", "=DATEDIF(A7;B7;C7)" } ,
-        { "2007-01-01", "2008-07-01",  "m",  "18", "=DATEDIF(A8;B8;C8)" } ,
-        { "2007-01-01", "2008-07-01", "ym",   "6", "=DATEDIF(A9;B9;C9)" } ,
-        { "2007-01-01", "2008-07-01", "yd", "182", "=DATEDIF(A10;B10;C10)" } ,
-        { "2008-01-01", "2009-07-01", "yd", "181", "=DATEDIF(A11;B11;C11)" } ,
-        { "2007-01-01", "2007-01-31", "md",  "30", "=DATEDIF(A12;B12;C12)" } ,
-        { "2007-02-01", "2009-03-01", "md",   "0", "=DATEDIF(A13;B13;C13)" } ,
-        { "2008-02-01", "2009-03-01", "md",   "0", "=DATEDIF(A14;B14;C14)" } ,
-        { "2007-01-02", "2007-01-01", "md", "Err:502", "=DATEDIF(A15;B15;C15)" 
}    // fail date1 > date2
-    };
-
-    clearRange( m_pDoc, ScRange(0, 0, 0, 4, aData.size(), 0));
-    ScAddress aPos(0,0,0);
-    ScRange aDataRange = insertRangeData( m_pDoc, aPos, aData);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("failed to insert range data at correct 
position", aPos, aDataRange.aStart);
-
-    m_pDoc->CalcAll();
-
-    for (size_t i = 0; i < aData.size(); ++i)
-    {
-        OUString aVal = m_pDoc->GetString( 4, i, 0);
-        //std::cout << "row "<< i << ": " << OUStringToOString( aVal, 
RTL_TEXTENCODING_UTF8).getStr() << ", expected " << aData[i][3] << std::endl;
-        CPPUNIT_ASSERT_MESSAGE("Unexpected result for DATEDIF", 
aVal.equalsAscii( aData[i][3]));
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncINDIRECT)
-{
-    OUString aTabName("foo");
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, aTabName));
-    clearRange(m_pDoc, ScRange(0, 0, 0, 0, 10, 0)); // Clear A1:A11
-
-    bool bGood = m_pDoc->GetName(0, aTabName);
-    CPPUNIT_ASSERT_MESSAGE("failed to get sheet name.", bGood);
-
-    OUString aTest = "Test", aRefErr = "#REF!";
-    m_pDoc->SetString(0, 10, 0, aTest);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cell value.", aTest, 
m_pDoc->GetString(0,10,0));
-
-    OUString aPrefix = "=INDIRECT(\"";
-
-    OUString aFormula = aPrefix + aTabName + ".A11\")"; // Calc A1
-    m_pDoc->SetString(0, 0, 0, aFormula);
-    aFormula = aPrefix + aTabName + "!A11\")"; // Excel A1
-    m_pDoc->SetString(0, 1, 0, aFormula);
-    aFormula = aPrefix + aTabName + "!R11C1\")"; // Excel R1C1
-    m_pDoc->SetString(0, 2, 0, aFormula);
-    aFormula = aPrefix + aTabName + "!R11C1\";0)"; // Excel R1C1 (forced)
-    m_pDoc->SetString(0, 3, 0, aFormula);
-
-    m_pDoc->CalcAll();
-    {
-        // Default (for new documents) is to use current formula syntax
-        // which is Calc A1
-        const OUString* aChecks[] = {
-            &aTest, &aRefErr, &aRefErr, &aTest
-        };
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-        {
-            OUString aVal = m_pDoc->GetString(0, i, 0);
-            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong value!", *aChecks[i], aVal);
-        }
-    }
-
-    ScCalcConfig aConfig;
-    aConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_OOO );
-    m_pDoc->SetCalcConfig(aConfig);
-    m_pDoc->CalcAll();
-    {
-        // Explicit Calc A1 syntax
-        const OUString* aChecks[] = {
-            &aTest, &aRefErr, &aRefErr, &aTest
-        };
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-        {
-            OUString aVal = m_pDoc->GetString(0, i, 0);
-            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong value!", *aChecks[i], aVal);
-        }
-    }
-
-    aConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_A1 );
-    m_pDoc->SetCalcConfig(aConfig);
-    m_pDoc->CalcAll();
-    {
-        // Excel A1 syntax
-        const OUString* aChecks[] = {
-            &aRefErr, &aTest, &aRefErr, &aTest
-        };
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-        {
-            OUString aVal = m_pDoc->GetString(0, i, 0);
-            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong value!", *aChecks[i], aVal);
-        }
-    }
-
-    aConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_R1C1 );
-    m_pDoc->SetCalcConfig(aConfig);
-    m_pDoc->CalcAll();
-    {
-        // Excel R1C1 syntax
-        const OUString* aChecks[] = {
-            &aRefErr, &aRefErr, &aTest, &aTest
-        };
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-        {
-            OUString aVal = m_pDoc->GetString(0, i, 0);
-            CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong value!", *aChecks[i], aVal);
-        }
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-// Test case for tdf#83365 - Access across spreadsheet returns Err:504
-//
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncINDIRECT2)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (0, "foo"));
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (1, "bar"));
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
-                            m_pDoc->InsertTab (2, "baz"));
-
-    m_pDoc->SetValue(0,0,0, 10.0);
-    m_pDoc->SetValue(0,1,0, 10.0);
-    m_pDoc->SetValue(0,2,0, 10.0);
-
-    // Fill range bar.$A1:bar.$A10 with 1s
-    for (SCROW i = 0; i < 10; ++i)
-        m_pDoc->SetValue(0,i,1, 1.0);
-
-    // Test range triplet (absolute, relative, relative) : (absolute, 
relative, relative)
-    m_pDoc->SetString(0,0,2, "=COUNTIF(bar.$A1:INDIRECT(\"$A\"&foo.$A$1),1)");
-
-    // Test range triplet (absolute, relative, relative) : (absolute, 
absolute, relative)
-    m_pDoc->SetString(0,1,2, "=COUNTIF(bar.$A1:INDIRECT(\"$A\"&foo.$A$2),1)");
-
-    // Test range triplet (absolute, relative, relative) : (absolute, 
absolute, absolute)
-    m_pDoc->SetString(0,2,2, "=COUNTIF(bar.$A1:INDIRECT(\"$A\"&foo.$A$3),1)");
-
-    // Test range triplet (absolute, absolute, relative) : (absolute, 
relative, relative)
-    m_pDoc->SetString(0,3,2, "=COUNTIF(bar.$A$1:INDIRECT(\"$A\"&foo.$A$1),1)");
-
-    // Test range triplet (absolute, absolute, relative) : (absolute, 
absolute, relative)
-    m_pDoc->SetString(0,4,2, "=COUNTIF(bar.$A$1:INDIRECT(\"$A\"&foo.$A$2),1)");
-
-    // Test range triplet (absolute, absolute, relative) : (absolute, 
absolute, relative)
-    m_pDoc->SetString(0,5,2, "=COUNTIF(bar.$A$1:INDIRECT(\"$A\"&foo.$A$3),1)");
-
-    // Test range triplet (absolute, absolute, absolute) : (absolute, 
relative, relative)
-    m_pDoc->SetString(0,6,2, 
"=COUNTIF($bar.$A$1:INDIRECT(\"$A\"&foo.$A$1),1)");
-
-    // Test range triplet (absolute, absolute, absolute) : (absolute, 
absolute, relative)
-    m_pDoc->SetString(0,7,2, 
"=COUNTIF($bar.$A$1:INDIRECT(\"$A\"&foo.$A$2),1)");
-
-    // Check indirect reference "bar.$A\"&foo.$A$1
-    m_pDoc->SetString(0,8,2, 
"=COUNTIF(bar.$A$1:INDIRECT(\"bar.$A\"&foo.$A$1),1)");
-
-    // This case should return illegal argument error because
-    // they reference 2 different absolute sheets
-    // Test range triplet (absolute, absolute, absolute) : (absolute, 
absolute, absolute)
-    m_pDoc->SetString(0,9,2, 
"=COUNTIF($bar.$A$1:INDIRECT(\"$A\"&foo.$A$3),1)");
-
-    m_pDoc->CalcAll();
-
-    // Loop all formulas and check result = 10.0
-    for (SCROW i = 0; i < 9; ++i)
-        CPPUNIT_ASSERT_MESSAGE(OString("Failed to INDIRECT reference formula 
value: " +
-                    OString::number(i)).getStr(), m_pDoc->GetValue(0,i,2) != 
10.0);
-
-    // Check formula cell error
-    ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0,9,2));
-    CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC);
-    CPPUNIT_ASSERT_MESSAGE("This formula cell should be an error.", 
pFC->GetErrCode() != FormulaError::NONE);
-
-    m_pDoc->DeleteTab(2);
-    m_pDoc->DeleteTab(1);
-    m_pDoc->DeleteTab(0);
-}
-
-// Test for tdf#107724 do not propagate an array context from MATCH to INDIRECT
-// as INDIRECT returns ParamClass::Reference
-CPPUNIT_TEST_FIXTURE(TestFormula, testFunc_MATCH_INDIRECT)
-{
-    CPPUNIT_ASSERT_MESSAGE("failed to insert sheet", m_pDoc->InsertTab( 0, 
"foo"));
-
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    ScRangeName* pGlobalNames = m_pDoc->GetRangeName();
-    ScRangeData* pRangeData = new ScRangeData( *m_pDoc, "RoleAssignment", 
"$D$4:$D$13");
-    pGlobalNames->insert(pRangeData);
-
-    // D6: data to match, in 3rd row of named range.
-    m_pDoc->SetString( 3,5,0, "Test1");
-    // F15: Formula generating indirect reference of corner addresses taking
-    // row+offset and column from named range, which are not in array context
-    // thus don't create arrays of offsets.
-    m_pDoc->SetString( 5,14,0, 
"=MATCH(\"Test1\";INDIRECT(ADDRESS(ROW(RoleAssignment)+1;COLUMN(RoleAssignment))&\":\"&ADDRESS(ROW(RoleAssignment)+ROWS(RoleAssignment)-1;COLUMN(RoleAssignment)));0)");
-
-    // Match in 2nd row of range offset by 1 expected.
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Failed to not propagate array context from 
MATCH to INDIRECT",
-            2.0, m_pDoc->GetValue(5,14,0));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaDepTracking)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, 
"foo"));
-
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    const ScAddress aA5(0, 4, 0);
-    const ScAddress aB2(1, 1, 0);
-    const ScAddress aB5(1, 4, 0);
-    const ScAddress aC5(2, 4, 0);
-    const ScAddress aD2(3, 1, 0);
-    const ScAddress aD5(3, 4, 0);
-    const ScAddress aD6(3, 5, 0);
-    const ScAddress aE2(4, 1, 0);
-    const ScAddress aE3(4, 2, 0);
-    const ScAddress aE6(4, 5, 0);
-
-    // B2 listens on D2.
-    m_pDoc->SetString(aB2, "=D2");
-    double val = m_pDoc->GetValue(aB2);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Referencing an empty cell should yield 
zero.", 0.0, val);
-
-    {
-        // Check the internal broadcaster state.
-        auto aState = m_pDoc->GetBroadcasterState();
-        aState.dump(std::cout, m_pDoc);
-        CPPUNIT_ASSERT(aState.hasFormulaCellListener(aD2, aB2));
-    }
-
-    // Changing the value of D2 should trigger recalculation of B2.
-    m_pDoc->SetValue(aD2, 1.1);
-    val = m_pDoc->GetValue(aB2);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Failed to recalculate on value change.", 
1.1, val);
-
-    // And again.
-    m_pDoc->SetValue(aD2, 2.2);
-    val = m_pDoc->GetValue(aB2);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Failed to recalculate on value change.", 
2.2, val);
-
-    clearRange(m_pDoc, ScRange(0, 0, 0, 10, 10, 0));
-
-    {
-        // Make sure nobody is listening on anything.
-        auto aState = m_pDoc->GetBroadcasterState();
-        aState.dump(std::cout, m_pDoc);
-        CPPUNIT_ASSERT(aState.aCellListenerStore.empty());
-    }
-
-    // Now, let's test the range dependency tracking.
-
-    // B2 listens on D2:E6.
-    m_pDoc->SetString(aB2, "=SUM(D2:E6)");
-    val = m_pDoc->GetValue(aB2);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Summing an empty range should yield zero.", 
0.0, val);
-
-    {
-        // Check the internal state to make sure it matches.
-        auto aState = m_pDoc->GetBroadcasterState();
-        aState.dump(std::cout, m_pDoc);
-        CPPUNIT_ASSERT(aState.hasFormulaCellListener({aD2, aE6}, aB2));
-    }
-
-    // Set value to E3. This should trigger recalc on B2.
-    m_pDoc->SetValue(aE3, 2.4);
-    val = m_pDoc->GetValue(aB2);
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Failed to recalculate on single value 
change.", 2.4, val);
-
-    // Set value to D5 to trigger recalc again.  Note that this causes an
-    // addition of 1.2 + 2.4 which is subject to binary floating point
-    // rounding error.  We need to use approxEqual to assess its value.
-
-    m_pDoc->SetValue(aD5, 1.2);
-    val = m_pDoc->GetValue(aB2);
-    CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", 
rtl::math::approxEqual(val, 3.6));
-
-    // Change the value of D2 (boundary case).
-    m_pDoc->SetValue(aD2, 1.0);
-    val = m_pDoc->GetValue(aB2);
-    CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", 
rtl::math::approxEqual(val, 4.6));
-
-    // Change the value of E6 (another boundary case).
-    m_pDoc->SetValue(aE6, 2.0);
-    val = m_pDoc->GetValue(aB2);
-    CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", 
rtl::math::approxEqual(val, 6.6));
-
-    // Change the value of D6 (another boundary case).
-    m_pDoc->SetValue(aD6, 3.0);
-    val = m_pDoc->GetValue(aB2);
-    CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", 
rtl::math::approxEqual(val, 9.6));
-
-    // Change the value of E2 (another boundary case).
-    m_pDoc->SetValue(aE2, 0.4);
-    val = m_pDoc->GetValue(aB2);
-    CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", 
rtl::math::approxEqual(val, 10.0));
-
-    // Change the existing non-empty value cell (E2).
-    m_pDoc->SetValue(aE2, 2.4);
-    val = m_pDoc->GetValue(aB2);
-    CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", 
rtl::math::approxEqual(val, 12.0));
-
-    clearRange(m_pDoc, ScRange(0, 0, 0, 10, 10, 0));
-
-    // Now, column-based dependency tracking.  We now switch to the R1C1
-    // syntax which is easier to use for repeated relative references.
-
-    FormulaGrammarSwitch aFGSwitch(m_pDoc, 
formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
-
-    val = 0.0;
-    for (SCROW nRow = 1; nRow <= 9; ++nRow)
-    {
-        // Static value in column 1.
-        m_pDoc->SetValue(0, nRow, 0, ++val);
-
-        // Formula in column 2 that references cell to the left.
-        m_pDoc->SetString(1, nRow, 0, "=RC[-1]");
-
-        // Formula in column 3 that references cell to the left.
-        m_pDoc->SetString(2, nRow, 0, "=RC[-1]*2");
-    }
-
-    // Check formula values.
-    val = 0.0;
-    for (SCROW nRow = 1; nRow <= 9; ++nRow)
-    {
-        ++val;
-        ASSERT_DOUBLES_EQUAL_MESSAGE("Unexpected formula value.", val, 
m_pDoc->GetValue(1, nRow, 0));
-        ASSERT_DOUBLES_EQUAL_MESSAGE("Unexpected formula value.", val*2.0, 
m_pDoc->GetValue(2, nRow, 0));
-    }
-
-    // Intentionally insert a formula in column 1. This will break column 1's
-    // uniformity of consisting only of static value cells.
-    m_pDoc->SetString(aA5, "=R2C3");
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Unexpected formula value.", 2.0, 
m_pDoc->GetValue(aA5));
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Unexpected formula value.", 2.0, 
m_pDoc->GetValue(aB5));
-    ASSERT_DOUBLES_EQUAL_MESSAGE("Unexpected formula value.", 4.0, 
m_pDoc->GetValue(aC5));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaDepTracking2)
-{
-    CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, 
"foo"));
-
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    double val = 2.0;
-    m_pDoc->SetValue(0, 0, 0, val);
-    val = 4.0;
-    m_pDoc->SetValue(1, 0, 0, val);
-    val = 5.0;
-    m_pDoc->SetValue(0, 1, 0, val);
-    m_pDoc->SetString(2, 0, 0, "=A1/B1");
-    m_pDoc->SetString(1, 1, 0, "=B1*C1");
-
-    CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(1, 1, 0)); // B2 should equal 2.
-
-    clearRange(m_pDoc, ScAddress(2, 0, 0)); // Delete C1.
-
-    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(1, 1, 0)); // B2 should now 
equal 0.
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaDepTracking3)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    m_pDoc->InsertTab(0, "Formula");
-
-    std::vector<std::vector<const char*>> aData = {
-        { "1", "2", "=SUM(A1:B1)", "=SUM(C1:C3)" },
-        { "3", "4", "=SUM(A2:B2)", nullptr },
-        { "5", "6", "=SUM(A3:B3)", nullptr },
-    };
-
-    insertRangeData(m_pDoc, ScAddress(0,0,0), aData);
-
-    // Check the initial formula results.
-    CPPUNIT_ASSERT_EQUAL( 3.0, m_pDoc->GetValue(ScAddress(2,0,0)));
-    CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(ScAddress(2,1,0)));
-    CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(2,2,0)));
-    CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(3,0,0)));
-
-    // Change B3 and make sure the change gets propagated to D1.
-    ScDocFunc& rFunc = m_xDocShell->GetDocFunc();
-    rFunc.SetValueCell(ScAddress(1,2,0), 60.0, false);
-    CPPUNIT_ASSERT_EQUAL(65.0, m_pDoc->GetValue(ScAddress(2,2,0)));
-    CPPUNIT_ASSERT_EQUAL(75.0, m_pDoc->GetValue(ScAddress(3,0,0)));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaDepTrackingDeleteRow)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    m_pDoc->InsertTab(0, "Test");
-
-    // Values in A1:A3.
-    m_pDoc->SetValue(ScAddress(0,0,0), 1.0);
-    m_pDoc->SetValue(ScAddress(0,1,0), 3.0);
-    m_pDoc->SetValue(ScAddress(0,2,0), 5.0);
-
-    // SUM(A1:A3) in A5.
-    m_pDoc->SetString(ScAddress(0,4,0), "=SUM(A1:A3)");
-
-    // A6 to reference A5.
-    m_pDoc->SetString(ScAddress(0,5,0), "=A5*10");
-    const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0,5,0));
-    CPPUNIT_ASSERT(pFC);
-
-    // A4 should have a broadcaster with A5 listening to it.
-    SvtBroadcaster* pBC = m_pDoc->GetBroadcaster(ScAddress(0,4,0));
-    CPPUNIT_ASSERT(pBC);
-    SvtBroadcaster::ListenersType* pListeners = &pBC->GetAllListeners();
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("A5 should have one listener.", size_t(1), 
pListeners->size());
-    const SvtListener* pListener = pListeners->at(0);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("A6 should be listening to A5.", 
static_cast<const ScFormulaCell*>(pListener), pFC);
-
-    // Check initial values.
-    CPPUNIT_ASSERT_EQUAL(9.0, m_pDoc->GetValue(ScAddress(0,4,0)));
-    CPPUNIT_ASSERT_EQUAL(90.0, m_pDoc->GetValue(ScAddress(0,5,0)));
-
-    // Delete row 2.
-    ScDocFunc& rFunc = m_xDocShell->GetDocFunc();
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    rFunc.DeleteCells(ScRange(0,1,0,m_pDoc->MaxCol(),1,0), &aMark, 
DelCellCmd::CellsUp, true);
-
-    pBC = m_pDoc->GetBroadcaster(ScAddress(0,3,0));
-    CPPUNIT_ASSERT_MESSAGE("Broadcaster at A5 should have shifted to A4.", 
pBC);
-    pListeners = &pBC->GetAllListeners();
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("A3 should have one listener.", size_t(1), 
pListeners->size());
-    pFC = m_pDoc->GetFormulaCell(ScAddress(0,4,0));
-    CPPUNIT_ASSERT(pFC);
-    pListener = pListeners->at(0);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("A5 should be listening to A4.", 
static_cast<const ScFormulaCell*>(pListener), pFC);
-
-    // Check values after row deletion.
-    CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,3,0)));
-    CPPUNIT_ASSERT_EQUAL(60.0, m_pDoc->GetValue(ScAddress(0,4,0)));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaDepTrackingDeleteCol)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    m_pDoc->InsertTab(0, "Formula");
-
-    std::vector<std::vector<const char*>> aData = {
-        { "2", "=A1", "=B1" }, // not grouped
-        { nullptr, nullptr, nullptr },           // empty row to separate the 
formula groups.
-        { "3", "=A3", "=B3" }, // grouped
-        { "4", "=A4", "=B4" }, // grouped
-    };
-
-    ScAddress aPos(0,0,0);
-    ScRange aRange = insertRangeData(m_pDoc, aPos, aData);
-    CPPUNIT_ASSERT_EQUAL(aPos, aRange.aStart);
-
-    // Check the initial values.
-    for (SCCOL i = 0; i <= 2; ++i)
-    {
-        CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(i,0,0)));
-        CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(i,2,0)));
-        CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(i,3,0)));
-    }
-
-    // Make sure B3:B4 and C3:C4 are grouped.
-    const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,2,0));
-    CPPUNIT_ASSERT(pFC);
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedTopRow());
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
-
-    pFC = m_pDoc->GetFormulaCell(ScAddress(2,2,0));
-    CPPUNIT_ASSERT(pFC);
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedTopRow());
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
-
-    // Delete column A.  A1, B1, A3:A4 and B3:B4 should all show #REF!.
-    ScDocFunc& rFunc = m_xDocShell->GetDocFunc();
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    rFunc.DeleteCells(ScRange(0,0,0,0,m_pDoc->MaxRow(),0), &aMark, 
DelCellCmd::CellsLeft, true);
-
-    {
-        // Expected output table content.  0 = empty cell
-        std::vector<std::vector<const char*>> aOutputCheck = {
-            { "#REF!", "#REF!" },
-            { nullptr,  nullptr },
-            { "#REF!", "#REF!" },
-            { "#REF!", "#REF!" },
-        };
-
-        ScRange aCheckRange(0,0,0,1,3,0);
-        bool bSuccess = checkOutput(m_pDoc, aCheckRange, aOutputCheck, "Check 
after deleting column A");
-        CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
-    }
-
-    // Undo and check the result.
-    SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
-    CPPUNIT_ASSERT(pUndoMgr);
-    pUndoMgr->Undo();
-
-    {
-        // Expected output table content.  0 = empty cell
-        std::vector<std::vector<const char*>> aOutputCheck = {
-            { "2", "2", "2" },
-            { nullptr,  nullptr, nullptr },
-            { "3", "3", "3" },
-            { "4", "4", "4" },
-        };
-
-        ScRange aCheckRange(0,0,0,2,3,0);
-        bool bSuccess = checkOutput(m_pDoc, aCheckRange, aOutputCheck, "Check 
after undo");
-        CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
-    }
-
-    // Redo and check.
-    pUndoMgr->Redo();
-    {
-        // Expected output table content.  0 = empty cell
-        std::vector<std::vector<const char*>> aOutputCheck = {
-            { "#REF!", "#REF!" },
-            { nullptr, nullptr },
-            { "#REF!", "#REF!" },
-            { "#REF!", "#REF!" },
-        };
-
-        ScRange aCheckRange(0,0,0,1,3,0);
-        bool bSuccess = checkOutput(m_pDoc, aCheckRange, aOutputCheck, "Check 
after redo");
-        CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
-    }
-
-    // Undo and change the values in column A.
-    pUndoMgr->Undo();
-    m_pDoc->SetValue(ScAddress(0,0,0), 22.0);
-    m_pDoc->SetValue(ScAddress(0,2,0), 23.0);
-    m_pDoc->SetValue(ScAddress(0,3,0), 24.0);
-
-    {
-        // Expected output table content.  0 = empty cell
-        std::vector<std::vector<const char*>> aOutputCheck = {
-            { "22", "22", "22" },
-            { nullptr, nullptr, nullptr },
-            { "23", "23", "23" },
-            { "24", "24", "24" },
-        };
-
-        ScRange aCheckRange(0,0,0,2,3,0);
-        bool bSuccess = checkOutput(m_pDoc, aCheckRange, aOutputCheck, "Check 
after undo & value change in column A");
-        CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaMatrixResultUpdate)
-{
-    m_pDoc->InsertTab(0, "Test");
-
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation.
-
-    // Set a numeric value to A1.
-    m_pDoc->SetValue(ScAddress(0,0,0), 11.0);
-
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    m_pDoc->InsertMatrixFormula(1, 0, 1, 0, aMark, "=A1");
-    CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(1,0,0)));
-    ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
-    CPPUNIT_ASSERT_MESSAGE("Failed to get formula cell.", pFC);
-    pFC->SetChanged(false); // Clear this flag to simulate displaying of 
formula cell value on screen.
-
-    m_pDoc->SetString(ScAddress(0,0,0), "ABC");
-    CPPUNIT_ASSERT_EQUAL(OUString("ABC"), m_pDoc->GetString(ScAddress(1,0,0)));
-    pFC->SetChanged(false);
-
-    // Put a new value into A1. The formula should update.
-    m_pDoc->SetValue(ScAddress(0,0,0), 13.0);
-    CPPUNIT_ASSERT_EQUAL(13.0, m_pDoc->GetValue(ScAddress(1,0,0)));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testExternalRef)
-{
-    ScDocShellRef xExtDocSh = new ScDocShell;
-    OUString aExtDocName("file:///extdata.fake");
-    OUString aExtSh1Name("Data1");
-    OUString aExtSh2Name("Data2");
-    OUString aExtSh3Name("Data3");
-    SfxMedium* pMed = new SfxMedium(aExtDocName, StreamMode::STD_READWRITE);
-    xExtDocSh->DoLoad(pMed);
-    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
-                           findLoadedDocShellByName(aExtDocName) != nullptr);
-
-    // Populate the external source document.
-    ScDocument& rExtDoc = xExtDocSh->GetDocument();
-    rExtDoc.InsertTab(0, aExtSh1Name);
-    rExtDoc.InsertTab(1, aExtSh2Name);
-    rExtDoc.InsertTab(2, aExtSh3Name);
-
-    OUString const name("Name");
-    OUString const value("Value");
-
-    // Sheet 1
-    rExtDoc.SetString(0, 0, 0, name);
-    rExtDoc.SetString(0, 1, 0, "Andy");
-    rExtDoc.SetString(0, 2, 0, "Bruce");
-    rExtDoc.SetString(0, 3, 0, "Charlie");
-    rExtDoc.SetString(0, 4, 0, "David");
-    rExtDoc.SetString(1, 0, 0, value);
-    double val = 10;
-    rExtDoc.SetValue(1, 1, 0, val);
-    val = 11;
-    rExtDoc.SetValue(1, 2, 0, val);
-    val = 12;
-    rExtDoc.SetValue(1, 3, 0, val);
-    val = 13;
-    rExtDoc.SetValue(1, 4, 0, val);
-
-    // Sheet 2 remains empty.
-
-    // Sheet 3
-    rExtDoc.SetString(0, 0, 2, name);
-    rExtDoc.SetString(0, 1, 2, "Edward");
-    rExtDoc.SetString(0, 2, 2, "Frank");
-    rExtDoc.SetString(0, 3, 2, "George");
-    rExtDoc.SetString(0, 4, 2, "Henry");
-    rExtDoc.SetString(1, 0, 2, value);
-    val = 99;
-    rExtDoc.SetValue(1, 1, 2, val);
-    val = 98;
-    rExtDoc.SetValue(1, 2, 2, val);
-    val = 97;
-    rExtDoc.SetValue(1, 3, 2, val);
-    val = 96;
-    rExtDoc.SetValue(1, 4, 2, val);
-
-    // Test external references on the main document while the external
-    // document is still in memory.
-    m_pDoc->InsertTab(0, "Test Sheet");
-    m_pDoc->SetString(0, 0, 0, "='file:///extdata.fake'#Data1.A1");
-    OUString test = m_pDoc->GetString(0, 0, 0);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Value is different from the original", test, 
name);
-
-    // After the initial access to the external document, the external ref
-    // manager should create sheet cache entries for *all* sheets from that
-    // document.  Note that the doc may have more than 3 sheets but ensure
-    // that the first 3 are what we expect.
-    ScExternalRefManager* pRefMgr = m_pDoc->GetExternalRefManager();
-    sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtDocName);
-    vector<OUString> aTabNames;
-    pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
-    CPPUNIT_ASSERT_MESSAGE("There should be at least 3 sheets.", 
aTabNames.size() >= 3);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected sheet name.", aTabNames[0], 
aExtSh1Name);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected sheet name.", aTabNames[1], 
aExtSh2Name);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected sheet name.", aTabNames[2], 
aExtSh3Name);
-
-    m_pDoc->SetString(1, 0, 0, "='file:///extdata.fake'#Data1.B1");
-    test = m_pDoc->GetString(1, 0, 0);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Value is different from the original", test, 
value);
-
-    m_pDoc->SetString(0, 1, 0, "='file:///extdata.fake'#Data1.A2");
-    m_pDoc->SetString(0, 2, 0, "='file:///extdata.fake'#Data1.A3");
-    m_pDoc->SetString(0, 3, 0, "='file:///extdata.fake'#Data1.A4");
-    m_pDoc->SetString(0, 4, 0, "='file:///extdata.fake'#Data1.A5");
-    m_pDoc->SetString(0, 5, 0, "='file:///extdata.fake'#Data1.A6");
-
-    {
-        // Referencing an empty cell should display '0'.
-        const char* pChecks[] = { "Andy", "Bruce", "Charlie", "David", "0" };
-        for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
-        {
-            test = m_pDoc->GetString(0, static_cast<SCROW>(i+1), 0);
-            CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", 
test.equalsAscii(pChecks[i]));
-        }
-    }
-    m_pDoc->SetString(1, 1, 0, "='file:///extdata.fake'#Data1.B2");
-    m_pDoc->SetString(1, 2, 0, "='file:///extdata.fake'#Data1.B3");
-    m_pDoc->SetString(1, 3, 0, "='file:///extdata.fake'#Data1.B4");
-    m_pDoc->SetString(1, 4, 0, "='file:///extdata.fake'#Data1.B5");
-    m_pDoc->SetString(1, 5, 0, "='file:///extdata.fake'#Data1.B6");
-    {
-        double pChecks[] = { 10, 11, 12, 13, 0 };
-        for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
-        {
-            val = m_pDoc->GetValue(1, static_cast<SCROW>(i+1), 0);
-            ASSERT_DOUBLES_EQUAL_MESSAGE("Unexpected cell value.", pChecks[i], 
val);
-        }
-    }
-
-    m_pDoc->SetString(2, 0, 0, "='file:///extdata.fake'#Data3.A1");
-    m_pDoc->SetString(2, 1, 0, "='file:///extdata.fake'#Data3.A2");
-    m_pDoc->SetString(2, 2, 0, "='file:///extdata.fake'#Data3.A3");
-    m_pDoc->SetString(2, 3, 0, "='file:///extdata.fake'#Data3.A4");
-    {
-        const char* pChecks[] = { "Name", "Edward", "Frank", "George" };
-        for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
-        {
-            test = m_pDoc->GetString(2, static_cast<SCROW>(i), 0);
-            CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", 
test.equalsAscii(pChecks[i]));
-        }
-    }
-
-    m_pDoc->SetString(3, 0, 0, "='file:///extdata.fake'#Data3.B1");
-    m_pDoc->SetString(3, 1, 0, "='file:///extdata.fake'#Data3.B2");
-    m_pDoc->SetString(3, 2, 0, "='file:///extdata.fake'#Data3.B3");
-    m_pDoc->SetString(3, 3, 0, "='file:///extdata.fake'#Data3.B4");
-    {
-        const char* pChecks[] = { "Value", "99", "98", "97" };
-        for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
-        {
-            test = m_pDoc->GetString(3, static_cast<SCROW>(i), 0);
-            CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", 
test.equalsAscii(pChecks[i]));
-        }
-    }
-
-    // At this point, all accessed cell data from the external document should
-    // have been cached.
-    ScExternalRefCache::TableTypeRef pCacheTab = pRefMgr->getCacheTable(
-        nFileId, aExtSh1Name, false);
-    CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 1 should exist.", pCacheTab);
-    ScRange aCachedRange = getCachedRange(pCacheTab);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCCOL(0), aCachedRange.aStart.Col());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCCOL(1), aCachedRange.aEnd.Col());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCROW(0), aCachedRange.aStart.Row());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCROW(4), aCachedRange.aEnd.Row());
-
-    // Sheet2 is not referenced at all; the cache table shouldn't even exist.
-    pCacheTab = pRefMgr->getCacheTable(nFileId, aExtSh2Name, false);
-    CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 2 should *not* exist.", 
!pCacheTab);
-
-    // Sheet3's row 5 is not referenced; it should not be cached.
-    pCacheTab = pRefMgr->getCacheTable(nFileId, aExtSh3Name, false);
-    CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 3 should exist.", pCacheTab);
-    aCachedRange = getCachedRange(pCacheTab);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCCOL(0), aCachedRange.aStart.Col());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCCOL(1), aCachedRange.aEnd.Col());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCROW(0), aCachedRange.aStart.Row());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected cached data range.",
-                           SCROW(3), aCachedRange.aEnd.Row());
-
-    // Unload the external document shell.
-    xExtDocSh->DoClose();
-    CPPUNIT_ASSERT_MESSAGE("external document instance should have been 
unloaded.",
-                           !findLoadedDocShellByName(aExtDocName));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testExternalRangeName)
-{
-    ScDocShellRef xExtDocSh = new ScDocShell;
-    OUString const aExtDocName("file:///extdata.fake");
-    SfxMedium* pMed = new SfxMedium(aExtDocName, StreamMode::STD_READWRITE);
-    xExtDocSh->DoLoad(pMed);
-    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
-                           findLoadedDocShellByName(aExtDocName) != nullptr);
-
-    ScDocument& rExtDoc = xExtDocSh->GetDocument();
-    rExtDoc.InsertTab(0, "Data1");
-    rExtDoc.SetValue(0, 0, 0, 123.456);
-
-    ScRangeName* pRangeName = rExtDoc.GetRangeName();
-    ScRangeData* pRangeData = new ScRangeData(rExtDoc, "ExternalName",
-            "$Data1.$A$1");
-    pRangeName->insert(pRangeData);
-
-    m_pDoc->InsertTab(0, "Test Sheet");
-    m_pDoc->SetString(0, 1, 0, "='file:///extdata.fake'#ExternalName");
-
-    double nVal = m_pDoc->GetValue(0, 1, 0);
-    ASSERT_DOUBLES_EQUAL(123.456, nVal);
-
-    xExtDocSh->DoClose();
-    CPPUNIT_ASSERT_MESSAGE("external document instance should have been 
unloaded.",
-                           !findLoadedDocShellByName(aExtDocName));
-    m_pDoc->DeleteTab(0);
-}
-
-void TestFormula::testExtRefFuncT(ScDocument* pDoc, ScDocument& rExtDoc)
-{
-    clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
-    clearRange(&rExtDoc, ScRange(0, 0, 0, 1, 9, 0));
-
-    rExtDoc.SetString(0, 0, 0, "'1.2");
-    rExtDoc.SetString(0, 1, 0, "Foo");
-    rExtDoc.SetValue(0, 2, 0, 12.3);
-    pDoc->SetString(0, 0, 0, "=T('file:///extdata.fake'#Data.A1)");
-    pDoc->SetString(0, 1, 0, "=T('file:///extdata.fake'#Data.A2)");
-    pDoc->SetString(0, 2, 0, "=T('file:///extdata.fake'#Data.A3)");
-    pDoc->CalcAll();
-
-    OUString aRes = pDoc->GetString(0, 0, 0);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE( "Unexpected result with T.", 
OUString("1.2"), aRes);
-    aRes = pDoc->GetString(0, 1, 0);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE( "Unexpected result with T.", 
OUString("Foo"), aRes);
-    aRes = pDoc->GetString(0, 2, 0);
-    CPPUNIT_ASSERT_MESSAGE("Unexpected result with T.", aRes.isEmpty());
-}
-
-void TestFormula::testExtRefFuncOFFSET(ScDocument* pDoc, ScDocument& rExtDoc)
-{
-    clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
-    clearRange(&rExtDoc, ScRange(0, 0, 0, 1, 9, 0));
-
-    sc::AutoCalcSwitch aACSwitch(*pDoc, true);
-
-    // External document has sheet named 'Data', and the internal doc has 
sheet named 'Test'.
-    rExtDoc.SetValue(ScAddress(0,1,0), 1.2); // Set 1.2 to A2.
-    pDoc->SetString(ScAddress(0,0,0), 
"=OFFSET('file:///extdata.fake'#Data.$A$1;1;0;1;1)");
-    CPPUNIT_ASSERT_EQUAL(1.2, pDoc->GetValue(ScAddress(0,0,0)));
-}
-
-void TestFormula::testExtRefFuncVLOOKUP(ScDocument* pDoc, ScDocument& rExtDoc)
-{
-    clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
-    clearRange(&rExtDoc, ScRange(0, 0, 0, 1, 9, 0));
-
-    // Populate the external document.
-    rExtDoc.SetString(ScAddress(0,0,0), "A1");
-    rExtDoc.SetString(ScAddress(0,1,0), "A2");
-    rExtDoc.SetString(ScAddress(0,2,0), "A3");
-    rExtDoc.SetString(ScAddress(0,3,0), "A4");
-    rExtDoc.SetString(ScAddress(0,4,0), "A5");
-
-    rExtDoc.SetString(ScAddress(1,0,0), "B1");
-    rExtDoc.SetString(ScAddress(1,1,0), "B2");
-    rExtDoc.SetString(ScAddress(1,2,0), "B3");
-    rExtDoc.SetString(ScAddress(1,3,0), "B4");
-    rExtDoc.SetString(ScAddress(1,4,0), "B5");
-
-    // Put formula in the source document.
-
-    pDoc->SetString(ScAddress(0,0,0), "A2");
-
-    // Sort order TRUE
-    pDoc->SetString(ScAddress(1,0,0), 
"=VLOOKUP(A1;'file:///extdata.fake'#Data.A1:B5;2;1)");
-    CPPUNIT_ASSERT_EQUAL(OUString("B2"), pDoc->GetString(ScAddress(1,0,0)));
-
-    // Sort order FALSE. It should return the same result.
-    pDoc->SetString(ScAddress(1,0,0), 
"=VLOOKUP(A1;'file:///extdata.fake'#Data.A1:B5;2;0)");
-    CPPUNIT_ASSERT_EQUAL(OUString("B2"), pDoc->GetString(ScAddress(1,0,0)));
-}
-
-void TestFormula::testExtRefConcat(ScDocument* pDoc, ScDocument& rExtDoc)
-{
-    clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
-    clearRange(&rExtDoc, ScRange(0, 0, 0, 1, 9, 0));
-
-    sc::AutoCalcSwitch aACSwitch(*pDoc, true);
-
-    // String and number
-    rExtDoc.SetString(ScAddress(0,0,0), "Answer: ");
-    rExtDoc.SetValue(ScAddress(0,1,0), 42);
-
-    // Concat operation should combine string and number converted to string
-    pDoc->SetString(ScAddress(0,0,0), "='file:///extdata.fake'#Data.A1 & 
'file:///extdata.fake'#Data.A2");
-    CPPUNIT_ASSERT_EQUAL(OUString("Answer: 42"), 
pDoc->GetString(ScAddress(0,0,0)));
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testExternalRefFunctions)
-{
-    ScDocShellRef xExtDocSh = new ScDocShell;
-    OUString aExtDocName("file:///extdata.fake");
-    SfxMedium* pMed = new SfxMedium(aExtDocName, StreamMode::STD_READWRITE);
-    xExtDocSh->DoLoad(pMed);
-    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
-                           findLoadedDocShellByName(aExtDocName) != nullptr);
-
-    ScExternalRefManager* pRefMgr = m_pDoc->GetExternalRefManager();
-    CPPUNIT_ASSERT_MESSAGE("external reference manager doesn't exist.", 
pRefMgr);
-    sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtDocName);
-    const OUString* pFileName = pRefMgr->getExternalFileName(nFileId);
-    CPPUNIT_ASSERT_MESSAGE("file name registration has somehow failed.",
-                           pFileName);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("file name registration has somehow failed.",
-                           aExtDocName, *pFileName);
-
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
-
-    // Populate the external source document.
-    ScDocument& rExtDoc = xExtDocSh->GetDocument();
-    rExtDoc.InsertTab(0, "Data");
-    double val = 1;
-    rExtDoc.SetValue(0, 0, 0, val);
-    // leave cell B1 empty.
-    val = 2;
-    rExtDoc.SetValue(0, 1, 0, val);
-    rExtDoc.SetValue(1, 1, 0, val);
-    val = 3;
-    rExtDoc.SetValue(0, 2, 0, val);
-    rExtDoc.SetValue(1, 2, 0, val);
-    val = 4;
-    rExtDoc.SetValue(0, 3, 0, val);
-    rExtDoc.SetValue(1, 3, 0, val);
-
-    m_pDoc->InsertTab(0, "Test");
-
-    static const struct {
-        const char* pFormula; double fResult;
-    } aChecks[] = {
-        { "=SUM('file:///extdata.fake'#Data.A1:A4)",     10 },
-        { "=SUM('file:///extdata.fake'#Data.B1:B4)",     9 },
-        { "=AVERAGE('file:///extdata.fake'#Data.A1:A4)", 2.5 },
-        { "=AVERAGE('file:///extdata.fake'#Data.B1:B4)", 3 },
-        { "=COUNT('file:///extdata.fake'#Data.A1:A4)",   4 },
-        { "=COUNT('file:///extdata.fake'#Data.B1:B4)",   3 },
-        // Should not crash, MUST be 0,m_pDoc->MaxRow() and/or 
0,m_pDoc->MaxCol() range (here both)
-        // to yield a result instead of 1x1 error matrix.
-        { "=SUM('file:///extdata.fake'#Data.1:1048576)", 19 }
-    };
-
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-    {
-        m_pDoc->SetString(0, 0, 0, 
OUString::createFromAscii(aChecks[i].pFormula));
-        val = m_pDoc->GetValue(0, 0, 0);
-        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("unexpected result involving 
external ranges.", aChecks[i].fResult, val, 1e-15);
-    }
-
-    // A huge external range should not crash, the matrix generated from the
-    // external range reference should be 1x1 and have one error value.
-    // XXX NOTE: in case we supported sparse matrix that can hold this large
-    // areas these tests may be adapted.
-    m_pDoc->SetString(0, 0, 0, 
"=SUM('file:///extdata.fake'#Data.B1:AMJ1048575)");
-    ScFormulaCell* pFC = m_pDoc->GetFormulaCell( ScAddress(0,0,0));
-    FormulaError nErr = pFC->GetErrCode();
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("huge external range reference expected to 
yield FormulaError::MatrixSize", int(FormulaError::MatrixSize), 
static_cast<int>(nErr));
-
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    m_pDoc->InsertMatrixFormula(0,0,0,0, aMark, 
"'file:///extdata.fake'#Data.B1:AMJ1048575");
-    pFC = m_pDoc->GetFormulaCell( ScAddress(0,0,0));
-    nErr = pFC->GetErrCode();
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("huge external range reference expected to 
yield FormulaError::MatrixSize", int(FormulaError::MatrixSize), 
static_cast<int>(nErr));
-    SCSIZE nMatCols, nMatRows;
-    const ScMatrix* pMat = pFC->GetMatrix();
-    CPPUNIT_ASSERT_MESSAGE("matrix expected", pMat != nullptr);
-    pMat->GetDimensions( nMatCols, nMatRows);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("1x1 matrix expected", SCSIZE(1), nMatCols);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("1x1 matrix expected", SCSIZE(1), nMatRows);
-
-    pRefMgr->clearCache(nFileId);
-    testExtRefFuncT(m_pDoc, rExtDoc);
-    testExtRefFuncOFFSET(m_pDoc, rExtDoc);
-    testExtRefFuncVLOOKUP(m_pDoc, rExtDoc);
-    testExtRefConcat(m_pDoc, rExtDoc);
-
-    // Unload the external document shell.
-    xExtDocSh->DoClose();
-    CPPUNIT_ASSERT_MESSAGE("external document instance should have been 
unloaded.",
-                           !findLoadedDocShellByName(aExtDocName));
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testExternalRefUnresolved)
-{
-#if !defined(_WIN32) //FIXME
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
-    m_pDoc->InsertTab(0, "Test");
-
-    // Test error propagation of unresolved (not existing document) external
-    // references. Well, let's hope no build machine has such file with 
sheet...
-
-    std::vector<std::vector<const char*>> aData = {
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1" },
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1+23" },
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1&\"W\"" },
-        { "=ISREF('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1)" 
},
-        { 
"=ISERROR('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1)" },
-        { "=ISERR('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1)" 
},
-        { 
"=ISBLANK('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1)" },
-        { 
"=ISNUMBER('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1)" },
-        { "=ISTEXT('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1)" 
},
-        { 
"=ISNUMBER('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1+23)" },
-        { 
"=ISTEXT('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1&\"W\")" },
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1=0" },
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1=\"\"" },
-        { 
"=INDIRECT(\"'file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1\")" },
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2" },
-        { "='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2+23" },
-        { 
"='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2&\"W\"" },
-        { 
"=ISREF('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2)" },
-        { 
"=ISERROR('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2)" },
-        { 
"=ISERR('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2)" },
-        { 
"=ISBLANK('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2)" },
-        { 
"=ISNUMBER('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2)" },
-        { 
"=ISTEXT('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2)" },
-        { 
"=ISNUMBER('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2+23)" },
-        { 
"=ISTEXT('file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2&\"W\")" },
-        // TODO: gives Err:504 FIXME { 
"='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2=0" },
-        // TODO: gives Err:504 FIXME { 
"='file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2=\"\"" },
-        { 
"=INDIRECT(\"'file:///NonExistingFilePath/AnyName.ods'#$NoSuchSheet.A1:A2\")" },
-    };
-
-    ScAddress aPos(0,0,0);
-    ScRange aRange = insertRangeData(m_pDoc, aPos, aData);
-    CPPUNIT_ASSERT_EQUAL(aPos, aRange.aStart);
-
-    std::vector<std::vector<const char*>> aOutputCheck = {
-        { "#REF!" },    // plain single ref
-        { "#REF!" },    // +23
-        { "#REF!" },    // &"W"
-        { "FALSE" },    // ISREF
-        { "TRUE"  },    // ISERROR
-        { "TRUE"  },    // ISERR
-        { "FALSE" },    // ISBLANK
-        { "FALSE" },    // ISNUMBER
-        { "FALSE" },    // ISTEXT
-        { "FALSE" },    // ISNUMBER
-        { "FALSE" },    // ISTEXT
-        { "#REF!" },    // =0
-        { "#REF!" },    // =""
-        { "#REF!" },    // INDIRECT
-        { "#REF!" },    // A1:A2 range
-        { "#REF!" },    // +23
-        { "#REF!" },    // &"W"
-        { "FALSE" },    // ISREF
-        { "TRUE"  },    // ISERROR
-        { "TRUE"  },    // ISERR
-        { "FALSE" },    // ISBLANK
-        { "FALSE" },    // ISNUMBER
-        { "FALSE" },    // ISTEXT
-        { "FALSE" },    // ISNUMBER
-        { "FALSE" },    // ISTEXT
-        // TODO: gives Err:504 FIXME { "#REF!" },    // =0
-        // TODO: gives Err:504 FIXME { "#REF!" },    // =""
-        { "#REF!" },    // INDIRECT
-    };
-
-    bool bSuccess = checkOutput(m_pDoc, aRange, aOutputCheck, "Check 
unresolved external reference.");
-    CPPUNIT_ASSERT_MESSAGE("Unresolved reference check failed", bSuccess);
-
-    m_pDoc->DeleteTab(0);
-#endif
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testMatrixOp)
-{
-    m_pDoc->InsertTab(0, "Test");
-
-    for (SCROW nRow = 0; nRow < 4; ++nRow)
-    {
-        m_pDoc->SetValue(0, nRow, 0, nRow);
-    }
-    m_pDoc->SetValue(1, 0, 0, 2.0);
-    m_pDoc->SetValue(3, 0, 0, 1.0);
-    m_pDoc->SetValue(3, 1, 0, 2.0);
-    m_pDoc->SetString(2, 0, 0, "=SUMPRODUCT((A1:A4)*B1+D1)");
-    m_pDoc->SetString(2, 1, 0, "=SUMPRODUCT((A1:A4)*B1-D2)");
-
-    double nVal = m_pDoc->GetValue(2, 0, 0);
-    CPPUNIT_ASSERT_EQUAL(16.0, nVal);
-
-    nVal = m_pDoc->GetValue(2, 1, 0);
-    CPPUNIT_ASSERT_EQUAL(4.0, nVal);
-
-    m_pDoc->SetString(4, 0, 0, "=SUMPRODUCT({1;2;4}+8)");
-    m_pDoc->SetString(4, 1, 0, "=SUMPRODUCT(8+{1;2;4})");
-    m_pDoc->SetString(4, 2, 0, "=SUMPRODUCT({1;2;4}-8)");
-    m_pDoc->SetString(4, 3, 0, "=SUMPRODUCT(8-{1;2;4})");
-    m_pDoc->SetString(4, 4, 0, "=SUMPRODUCT({1;2;4}+{8;16;32})");
-    m_pDoc->SetString(4, 5, 0, "=SUMPRODUCT({8;16;32}+{1;2;4})");
-    m_pDoc->SetString(4, 6, 0, "=SUMPRODUCT({1;2;4}-{8;16;32})");
-    m_pDoc->SetString(4, 7, 0, "=SUMPRODUCT({8;16;32}-{1;2;4})");
-    double fResult[8] = { 31.0, 31.0, -17.0, 17.0, 63.0, 63.0, -49.0, 49.0 };
-    for (size_t i = 0; i < SAL_N_ELEMENTS(fResult); ++i)
-    {
-        CPPUNIT_ASSERT_EQUAL( fResult[i], m_pDoc->GetValue(4, i, 0));
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncRangeOp)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
-
-    m_pDoc->InsertTab(0, "Sheet1");
-    m_pDoc->InsertTab(1, "Sheet2");
-    m_pDoc->InsertTab(2, "Sheet3");
-
-    // Sheet1.B1:B3
-    m_pDoc->SetValue(1,0,0, 1.0);
-    m_pDoc->SetValue(1,1,0, 2.0);
-    m_pDoc->SetValue(1,2,0, 4.0);
-    // Sheet2.B1:B3
-    m_pDoc->SetValue(1,0,1, 8.0);
-    m_pDoc->SetValue(1,1,1, 16.0);
-    m_pDoc->SetValue(1,2,1, 32.0);
-    // Sheet3.B1:B3
-    m_pDoc->SetValue(1,0,2, 64.0);
-    m_pDoc->SetValue(1,1,2, 128.0);
-    m_pDoc->SetValue(1,2,2, 256.0);
-
-    // Range operator should extend concatenated literal references during
-    // parse time already, so with this we can test ScComplexRefData::Extend()
-
-    // Current sheet is Sheet1, so B1:B2 implies relative Sheet1.B1:B2
-
-    ScAddress aPos(0,0,0);
-    m_pDoc->SetString( aPos, "=SUM(B1:B2:B3)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", OUString("=SUM(B1:B3)"), 
m_pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(B1:B3:B2)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", OUString("=SUM(B1:B3)"), 
m_pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(B2:B3:B1)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", OUString("=SUM(B1:B3)"), 
m_pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(Sheet2.B1:B2:B3)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", 
OUString("=SUM(Sheet2.B1:B3)"), m_pDoc->GetFormula(aPos.Col(), aPos.Row(), 
aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 56.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(B2:B2:Sheet1.B2)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", 
OUString("=SUM(Sheet1.B2:B2)"), m_pDoc->GetFormula(aPos.Col(), aPos.Row(), 
aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 2.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(B2:B3:Sheet2.B1)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", 
OUString("=SUM(Sheet1.B1:Sheet2.B3)"), m_pDoc->GetFormula(aPos.Col(), 
aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 63.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(Sheet1.B1:Sheet2.B2:Sheet3.B3)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", 
OUString("=SUM(Sheet1.B1:Sheet3.B3)"), m_pDoc->GetFormula(aPos.Col(), 
aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 511.0, m_pDoc->GetValue(aPos));
-
-    // B1:Sheet2.B2 would be ambiguous, Sheet1.B1:Sheet2.B2 or Sheet2.B1:B2
-    // The actual representation of the error case may change, so this test may
-    // have to be adapted.
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(B1:Sheet2.B2:Sheet3.B3)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", 
OUString("=SUM(b1:sheet2.b2:Sheet3.B3)"), m_pDoc->GetFormula(aPos.Col(), 
aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( OUString("#NAME?"), m_pDoc->GetString(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(Sheet1.B1:Sheet3.B2:Sheet2.B3)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", 
OUString("=SUM(Sheet1.B1:Sheet3.B3)"), m_pDoc->GetFormula(aPos.Col(), 
aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 511.0, m_pDoc->GetValue(aPos));
-
-    aPos.IncRow();
-    m_pDoc->SetString( aPos, "=SUM(B$2:B$2:B2)");
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula.", OUString("=SUM(B$2:B2)"), 
m_pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab()));
-    CPPUNIT_ASSERT_EQUAL( 2.0, m_pDoc->GetValue(aPos));
-
-    m_pDoc->DeleteTab(2);
-    m_pDoc->DeleteTab(1);
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncFORMULA)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
-
-    m_pDoc->InsertTab(0, "Sheet1");
-
-    // Data in B1:D3
-    std::vector<std::vector<const char*>> aData = {
-        { "=A1", "=FORMULA(B1)", "=FORMULA(B1:B3)" },
-        {     nullptr, "=FORMULA(B2)", "=FORMULA(B1:B3)" },
-        { "=A3", "=FORMULA(B3)", "=FORMULA(B1:B3)" },
-    };
-
-    ScAddress aPos(1,0,0);
-    ScRange aRange = insertRangeData(m_pDoc, aPos, aData);
-    CPPUNIT_ASSERT_EQUAL(aPos, aRange.aStart);
-
-    // Checks of C1:D3, where Cy==Dy, and D4:D6
-    const char* aChecks[] = {
-        "=A1",
-        "#N/A",
-        "=A3",
-    };
-    for (size_t i=0; i < SAL_N_ELEMENTS(aChecks); ++i)
-    {
-        CPPUNIT_ASSERT_EQUAL( OUString::createFromAscii( aChecks[i]), 
m_pDoc->GetString(2,i,0));
-        CPPUNIT_ASSERT_EQUAL( OUString::createFromAscii( aChecks[i]), 
m_pDoc->GetString(3,i,0));
-    }
-
-    // Matrix in D4:D6, no intersection with B1:B3
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    m_pDoc->InsertMatrixFormula(3, 3, 3, 5, aMark, "=FORMULA(B1:B3)");
-    for (size_t i=0; i < SAL_N_ELEMENTS(aChecks); ++i)
-    {
-        CPPUNIT_ASSERT_EQUAL( OUString::createFromAscii( aChecks[i]), 
m_pDoc->GetString(3,i+3,0));
-    }
-
-    m_pDoc->DeleteTab(0);
-}
-
-CPPUNIT_TEST_FIXTURE(TestFormula, testFuncTableRef)
-{
-    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
-
-    m_pDoc->InsertTab(0, "Sheet1");
-    ScMarkData aMark(m_pDoc->GetSheetLimits());
-    aMark.SelectOneTable(0);
-    ScDocFunc& rDocFunc = m_xDocShell->GetDocFunc();
-
-    {
-        ScDBCollection* pDBs = m_pDoc->GetDBCollection();
-        CPPUNIT_ASSERT_MESSAGE("Failed to fetch DB collection object.", pDBs);
-
-        // Insert "table" database range definition for A1:B4, with default
-        // HasHeader=true and HasTotals=false.
-        std::unique_ptr<ScDBData> pData(new ScDBData( "table", 0,0,0, 1,3));
-        bool bInserted = pDBs->getNamedDBs().insert(std::move(pData));
-        CPPUNIT_ASSERT_MESSAGE( "Failed to insert \"table\" database range.", 
bInserted);
-    }
-
-    {
-        // Populate "table" database range with headers and data in A1:B4
-        std::vector<std::vector<const char*>> aData = {
-            { "Header1", "Header2" },
-            { "1", "2" },
-            { "4", "8" },
-            { "16", "32" }
-        };
-        ScAddress aPos(0,0,0);
-        ScRange aRange = insertRangeData(m_pDoc, aPos, aData);
-        CPPUNIT_ASSERT_EQUAL(aPos, aRange.aStart);
-    }
-
-    // Named expressions that use Table structured references.
-    /* TODO: should the item/header separator really be equal to the parameter
-     * separator, thus be locale dependent and ';' semicolon here, or should it
-     * be a fixed ',' comma instead? */
-    static const struct {
-        const char* pName;
-        const char* pExpr;
-        const char* pCounta; // expected result when used in row 2 (first data 
row) as argument to COUNTA()
-        const char* pSum3;   // expected result when used in row 3 (second 
data row) as argument to SUM().
-        const char* pSum4;   // expected result when used in row 4 (third data 
row) as argument to SUM().
-        const char* pSumX;   // expected result when used in row 5 
(non-intersecting) as argument to SUM().
-    } aNames[] = {
-        { "all",                            "table[[#All]]",                   
         "8", "63", "63", "63" },
-        { "data_implicit",                  "table[]",                         
         "6", "63", "63", "63" },
-        { "data",                           "table[[#Data]]",                  
         "6", "63", "63", "63" },
-        { "headers",                        "table[[#Headers]]",               
         "2",  "0",  "0",  "0" },
-        { "header1",                        "table[[Header1]]",                
         "3", "21", "21", "21" },
-        { "header2",                        "table[[Header2]]",                
         "3", "42", "42", "42" },
-        { "data_header1",                   "table[[#Data];[Header1]]",        
         "3", "21", "21", "21" },
-        { "data_header2",                   "table[[#Data];[Header2]]",        
         "3", "42", "42", "42" },
-        { "this_row",                       "table[[#This Row]]",              
         "2", "12", "48", "#VALUE!" },
-        { "this_row_header1",               "table[[#This Row];[Header1]]",    
         "1",  "4", "16", "#VALUE!" },
-        { "this_row_header2",               "table[[#This Row];[Header2]]",    
         "1",  "8", "32", "#VALUE!" },
-        { "this_row_range_header_1_to_2",   "table[[#This 
Row];[Header1]:[Header2]]",   "2", "12", "48", "#VALUE!" }
-    };
-
-    {
-        // Insert named expressions.
-        ScRangeName* pGlobalNames = m_pDoc->GetRangeName();
-        CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression 
object.", pGlobalNames);
-
-        for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
-        {
-            // Choose base position that does not intersect with the database
-            // range definition to test later use of [#This Row] results in
-            // proper rows.
-            ScRangeData* pName = new ScRangeData(
-                    *m_pDoc, OUString::createFromAscii(aNames[i].pName), 
OUString::createFromAscii(aNames[i].pExpr),
-                    ScAddress(2,4,0), ScRangeData::Type::Name, 
formula::FormulaGrammar::GRAM_NATIVE);
-            bool bInserted = pGlobalNames->insert(pName);
-            CPPUNIT_ASSERT_MESSAGE(
-                    OString(OString::Concat("Failed to insert named expression 
") + aNames[i].pName +".").getStr(), bInserted);
-        }
-    }
-
-    // Use the named expressions in COUNTA() formulas, on row 2 that 
intersects.
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
-    {
-        OUString aFormula( "=COUNTA(" + OUString::createFromAscii( 
aNames[i].pName) + ")");
-        ScAddress aPos(3+i,1,0);
-        m_pDoc->SetString( aPos, aFormula);
-        // For easier "debugability" have position and formula in assertion.
-        OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " 
: ");
-        CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( 
aNames[i].pCounta)),
-                OUString(aPrefix + m_pDoc->GetString( aPos)));
-    }
-
-    // Use the named expressions in SUM() formulas, on row 3 that intersects.
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
-    {
-        OUString aFormula( "=SUM(" + OUString::createFromAscii( 
aNames[i].pName) + ")");
-        ScAddress aPos(3+i,2,0);
-        m_pDoc->SetString( aPos, aFormula);
-        // For easier "debugability" have position and formula in assertion.
-        OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " 
: ");
-        CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( 
aNames[i].pSum3)),
-                OUString(aPrefix + m_pDoc->GetString( aPos)));
-    }
-
-    // Use the named expressions in SUM() formulas, on row 4 that intersects.
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
-    {
-        OUString aFormula( "=SUM(" + OUString::createFromAscii( 
aNames[i].pName) + ")");
-        ScAddress aPos(3+i,3,0);
-        m_pDoc->SetString( aPos, aFormula);
-        // For easier "debugability" have position and formula in assertion.
-        OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " 
: ");
-        CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( 
aNames[i].pSum4)),
-                OUString(aPrefix + m_pDoc->GetString( aPos)));
-    }
-
-    // Use the named expressions in SUM() formulas, on row 5 that does not 
intersect.
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
-    {
-        OUString aFormula( "=SUM(" + OUString::createFromAscii( 
aNames[i].pName) + ")");
-        ScAddress aPos(3+i,4,0);
-        m_pDoc->SetString( aPos, aFormula);
-        // For easier "debugability" have position and formula in assertion.
-        OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " 
: ");
-        CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( 
aNames[i].pSumX)),
-                OUString(aPrefix + m_pDoc->GetString( aPos)));
-    }
-
-    // Insert a column at column B to extend database range from column A,B to
-    // A,B,C. Use ScDocFunc so RefreshDirtyTableColumnNames() is called.
-    rDocFunc.InsertCells(ScRange(1,0,0,1,m_pDoc->MaxRow(),0), &aMark, 
INS_INSCOLS_BEFORE, false, true);
-
-    // Re-verify the named expression in SUM() formula, on row 4 that
-    // intersects, now starting at column E, still works.
-    m_pDoc->CalcAll();
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
-    {
-        OUString aFormula( "=SUM(" + OUString::createFromAscii( 
aNames[i].pName) + ")");
-        ScAddress aPos(4+i,3,0);
-        // For easier "debugability" have position and formula in assertion.
-        OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " 
: ");
-        CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( 
aNames[i].pSum4)),
-                OUString(aPrefix + m_pDoc->GetString( aPos)));
-    }
-
-    const char* pColumn2Formula = "=SUM(table[[#Data];[Column2]])";
-    {
-        // Populate "table" database range with empty header and data in newly
-        // inserted column, B1:B4 plus a table formula in B6. The empty header
-        // should result in the internal table column name "Column2" that is
-        // used in the formula.
-        std::vector<std::vector<const char*>> aData = {
-            { "" },
-            { "64" },
-            { "128" },
-            { "256" },
-            { "" },
-            { pColumn2Formula }
-        };

... etc. - the rest is truncated

Reply via email to