[Libreoffice-commits] core.git: 3 commits - sc/qa sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Feb 20 13:08:15 PST 2014


 sc/qa/unit/ucalc.cxx                     |  347 +-----------------------------
 sc/qa/unit/ucalc.hxx                     |   10 
 sc/qa/unit/ucalc_formula.cxx             |  348 +++++++++++++++++++++++++++++++
 sc/source/ui/docshell/externalrefmgr.cxx |   33 ++
 4 files changed, 395 insertions(+), 343 deletions(-)

New commits:
commit 2bcd18892f1903d2434bc5dc6828841e49bb78a2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Feb 20 16:05:51 2014 -0500

    fdo#72041: Intern strings in the external ref cache with the host document.
    
    To ensure that string comparison with those from the external ref cache
    works correctly in functions such as VLOOKUP.
    
    Change-Id: Ib5a466cb6c4b26439abe61b0c17406fc8139f6c0

diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 343194f..7d77afb 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -1300,7 +1300,7 @@ IMPL_LINK_NOARG(ScExternalRefLink, ExternalRefEndEditHdl)
 
 // ============================================================================
 
-static FormulaToken* convertToToken( ScRefCellValue& rCell )
+static FormulaToken* convertToToken( ScDocument* pHostDoc, ScDocument* pSrcDoc, ScRefCellValue& rCell )
 {
     if (rCell.hasEmptyValue())
     {
@@ -1312,7 +1312,11 @@ static FormulaToken* convertToToken( ScRefCellValue& rCell )
     {
         case CELLTYPE_EDIT:
         case CELLTYPE_STRING:
-            return new formula::FormulaStringToken(rCell.getString(NULL));
+        {
+            OUString aStr = rCell.getString(pSrcDoc);
+            svl::SharedString aSS = pHostDoc->GetSharedStringPool().intern(aStr);
+            return new formula::FormulaStringToken(aSS);
+        }
         case CELLTYPE_VALUE:
             return new formula::FormulaDoubleToken(rCell.mfValue);
         case CELLTYPE_FORMULA:
@@ -1342,13 +1346,20 @@ static FormulaToken* convertToToken( ScRefCellValue& rCell )
 template<class T>
 struct ColumnBatch
 {
+    ScDocument* mpHostDoc;
+    ScDocument* mpSrcDoc;
+
     std::vector<T> maStorage;
     CellType meType1;
     CellType meType2;
     SCROW mnRowStart;
 
-    ColumnBatch(CellType eType1, CellType eType2) :
-        meType1(eType1), meType2(eType2), mnRowStart(-1) {}
+    ColumnBatch( ScDocument* pHostDoc, ScDocument* pSrcDoc, CellType eType1, CellType eType2 ) :
+        mpHostDoc(pHostDoc),
+        mpSrcDoc(pSrcDoc),
+        meType1(eType1),
+        meType2(eType2),
+        mnRowStart(-1) {}
 
     void update(ScRefCellValue& raCell, const SCCOL nCol, const SCROW nRow, ScMatrixRef& xMat)
     {
@@ -1380,7 +1391,8 @@ struct ColumnBatch
 template<>
 inline svl::SharedString ColumnBatch<svl::SharedString>::getValue(ScRefCellValue& rCell) const
 {
-    return svl::SharedString(rCell.getString(NULL));
+    OUString aStr = rCell.getString(mpSrcDoc);
+    return mpHostDoc->GetSharedStringPool().intern(aStr);
 }
 
 template<class T>
@@ -1402,7 +1414,7 @@ inline void ColumnBatch<T>::putValues(ScMatrixRef& xMat, const SCCOL nCol) const
 }
 
 static ScTokenArray* convertToTokenArray(
-    ScDocument* pSrcDoc, ScRange& rRange, vector<ScExternalRefCache::SingleRangeData>& rCacheData )
+    ScDocument* pHostDoc, ScDocument* pSrcDoc, ScRange& rRange, vector<ScExternalRefCache::SingleRangeData>& rCacheData )
 {
     ScAddress& s = rRange.aStart;
     ScAddress& e = rRange.aEnd;
@@ -1448,8 +1460,8 @@ static ScTokenArray* convertToTokenArray(
             static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
 
         ScRefCellValue aCell;
-        ColumnBatch<svl::SharedString> aStringBatch(CELLTYPE_STRING, CELLTYPE_EDIT);
-        ColumnBatch<double> aDoubleBatch(CELLTYPE_VALUE, CELLTYPE_VALUE);
+        ColumnBatch<svl::SharedString> aStringBatch(pHostDoc, pSrcDoc, CELLTYPE_STRING, CELLTYPE_EDIT);
+        ColumnBatch<double> aDoubleBatch(pHostDoc, pSrcDoc, CELLTYPE_VALUE, CELLTYPE_VALUE);
 
         for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol)
         {
@@ -1483,6 +1495,7 @@ static ScTokenArray* convertToTokenArray(
                         else
                         {
                             svl::SharedString aStr = pFCell->GetString();
+                            aStr = pHostDoc->GetSharedStringPool().intern(aStr.getString());
                             xMat->PutString(aStr, nC, nR);
                         }
                     }
@@ -2033,7 +2046,7 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefTokenFromSrcDoc(
     // Get the cell from src doc, and convert it into a token.
     ScRefCellValue aCell;
     aCell.assign(*pSrcDoc, rPos);
-    ScExternalRefCache::TokenRef pToken(convertToToken(aCell));
+    ScExternalRefCache::TokenRef pToken(convertToToken(mpDoc, pSrcDoc, aCell));
 
     if (!pToken.get())
     {
@@ -2086,7 +2099,7 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokensFromSr
     aRange.aStart.SetTab(nTab1);
     aRange.aEnd.SetTab(nTab1 + nTabSpan);
 
-    pArray.reset(convertToTokenArray(pSrcDoc, aRange, aCacheData));
+    pArray.reset(convertToTokenArray(mpDoc, pSrcDoc, aRange, aCacheData));
     rRange = aRange;
     rCacheData.swap(aCacheData);
     return pArray;
commit da3c8bfb0be627da9b74ebf2b1d1ec339b702980
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Feb 20 14:53:43 2014 -0500

    fdo#72041: Add test for this.
    
    Change-Id: I3d0f692529c3425aaab6080818882e8fb5326d1b

diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index ff9a1fc..05acecc 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -2988,6 +2988,37 @@ void testExtRefFuncOFFSET(ScDocument* pDoc, ScDocument* pExtDoc)
     CPPUNIT_ASSERT_EQUAL(1.2, pDoc->GetValue(ScAddress(0,0,0)));
 }
 
+void testExtRefFuncVLOOKUP(ScDocument* pDoc, ScDocument* pExtDoc)
+{
+    Test::clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
+    Test::clearRange(pExtDoc, ScRange(0, 0, 0, 1, 9, 0));
+
+    // Populate the external document.
+    pExtDoc->SetString(ScAddress(0,0,0), "A1");
+    pExtDoc->SetString(ScAddress(0,1,0), "A2");
+    pExtDoc->SetString(ScAddress(0,2,0), "A3");
+    pExtDoc->SetString(ScAddress(0,3,0), "A4");
+    pExtDoc->SetString(ScAddress(0,4,0), "A5");
+
+    pExtDoc->SetString(ScAddress(1,0,0), "B1");
+    pExtDoc->SetString(ScAddress(1,1,0), "B2");
+    pExtDoc->SetString(ScAddress(1,2,0), "B3");
+    pExtDoc->SetString(ScAddress(1,3,0), "B4");
+    pExtDoc->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 Test::testExternalRefFunctions()
 {
     ScDocShellRef xExtDocSh = new ScDocShell;
@@ -3004,6 +3035,8 @@ void Test::testExternalRefFunctions()
     CPPUNIT_ASSERT_MESSAGE("file name registration has somehow failed.",
                            pFileName && pFileName->equals(aExtDocName));
 
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
+
     // Populate the external source document.
     ScDocument* pExtDoc = xExtDocSh->GetDocument();
     pExtDoc->InsertTab(0, OUString("Data"));
@@ -3036,7 +3069,6 @@ void Test::testExternalRefFunctions()
     for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     {
         m_pDoc->SetString(0, 0, 0, OUString::createFromAscii(aChecks[i].pFormula));
-        m_pDoc->CalcAll();
         m_pDoc->GetValue(0, 0, 0, val);
         CPPUNIT_ASSERT_MESSAGE("unexpected result involving external ranges.", val == aChecks[i].fResult);
     }
@@ -3044,6 +3076,7 @@ void Test::testExternalRefFunctions()
     pRefMgr->clearCache(nFileId);
     testExtRefFuncT(m_pDoc, pExtDoc);
     testExtRefFuncOFFSET(m_pDoc, pExtDoc);
+    testExtRefFuncVLOOKUP(m_pDoc, pExtDoc);
 
     // Unload the external document shell.
     xExtDocSh->DoClose();
commit d64b92e77d391907bac4a1ce4791fbba9f18cffe
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Feb 20 14:22:03 2014 -0500

    Move these external reference test to ucalc_formula.cxx.
    
    Change-Id: Iaf8fc14e413eb44de3c796c97112e0868ad672df

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index ed84bf2..2afd4f8 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2208,335 +2208,6 @@ void Test::testSheetMove()
     m_pDoc->DeleteTab(0);
 }
 
-ScDocShell* findLoadedDocShellByName(const OUString& rName)
-{
-    TypeId aType(TYPE(ScDocShell));
-    ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
-    while (pShell)
-    {
-        SfxMedium* pMedium = pShell->GetMedium();
-        if (pMedium)
-        {
-            OUString aName = pMedium->GetName();
-            if (aName.equals(rName))
-                return pShell;
-        }
-        pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
-    }
-    return NULL;
-}
-
-ScRange getCachedRange(const ScExternalRefCache::TableTypeRef& pCacheTab)
-{
-    ScRange aRange;
-
-    vector<SCROW> aRows;
-    pCacheTab->getAllRows(aRows);
-    vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
-    bool bFirst = true;
-    for (; itrRow != itrRowEnd; ++itrRow)
-    {
-        SCROW nRow = *itrRow;
-        vector<SCCOL> aCols;
-        pCacheTab->getAllCols(nRow, aCols);
-        vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
-        for (; itrCol != itrColEnd; ++itrCol)
-        {
-            SCCOL nCol = *itrCol;
-            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 Test::testExternalRef()
-{
-    ScDocShellRef xExtDocSh = new ScDocShell;
-    OUString aExtDocName("file:///extdata.fake");
-    OUString aExtSh1Name("Data1");
-    OUString aExtSh2Name("Data2");
-    OUString aExtSh3Name("Data3");
-    SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
-    xExtDocSh->DoInitNew(pMed);
-    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
-                           findLoadedDocShellByName(aExtDocName) != NULL);
-
-    // Populate the external source document.
-    ScDocument* pExtDoc = xExtDocSh->GetDocument();
-    pExtDoc->InsertTab(0, aExtSh1Name);
-    pExtDoc->InsertTab(1, aExtSh2Name);
-    pExtDoc->InsertTab(2, aExtSh3Name);
-
-    OUString name("Name");
-    OUString value("Value");
-    OUString andy("Andy");
-    OUString bruce("Bruce");
-    OUString charlie("Charlie");
-    OUString david("David");
-    OUString edward("Edward");
-    OUString frank("Frank");
-    OUString george("George");
-    OUString henry("Henry");
-
-    // Sheet 1
-    pExtDoc->SetString(0, 0, 0, name);
-    pExtDoc->SetString(0, 1, 0, andy);
-    pExtDoc->SetString(0, 2, 0, bruce);
-    pExtDoc->SetString(0, 3, 0, charlie);
-    pExtDoc->SetString(0, 4, 0, david);
-    pExtDoc->SetString(1, 0, 0, value);
-    double val = 10;
-    pExtDoc->SetValue(1, 1, 0, val);
-    val = 11;
-    pExtDoc->SetValue(1, 2, 0, val);
-    val = 12;
-    pExtDoc->SetValue(1, 3, 0, val);
-    val = 13;
-    pExtDoc->SetValue(1, 4, 0, val);
-
-    // Sheet 2 remains empty.
-
-    // Sheet 3
-    pExtDoc->SetString(0, 0, 2, name);
-    pExtDoc->SetString(0, 1, 2, edward);
-    pExtDoc->SetString(0, 2, 2, frank);
-    pExtDoc->SetString(0, 3, 2, george);
-    pExtDoc->SetString(0, 4, 2, henry);
-    pExtDoc->SetString(1, 0, 2, value);
-    val = 99;
-    pExtDoc->SetValue(1, 1, 2, val);
-    val = 98;
-    pExtDoc->SetValue(1, 2, 2, val);
-    val = 97;
-    pExtDoc->SetValue(1, 3, 2, val);
-    val = 96;
-    pExtDoc->SetValue(1, 4, 2, val);
-
-    // Test external refernces on the main document while the external
-    // document is still in memory.
-    m_pDoc->InsertTab(0, OUString("Test Sheet"));
-    m_pDoc->SetString(0, 0, 0, OUString("='file:///extdata.fake'#Data1.A1"));
-    OUString test = m_pDoc->GetString(0, 0, 0);
-    CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(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_MESSAGE("Unexpected sheet name.", aTabNames[0].equals(aExtSh1Name));
-    CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[1].equals(aExtSh2Name));
-    CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[2].equals(aExtSh3Name));
-
-    m_pDoc->SetString(1, 0, 0, OUString("='file:///extdata.fake'#Data1.B1"));
-    test = m_pDoc->GetString(1, 0, 0);
-    CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(value));
-
-    m_pDoc->SetString(0, 1, 0, OUString("='file:///extdata.fake'#Data1.A2"));
-    m_pDoc->SetString(0, 2, 0, OUString("='file:///extdata.fake'#Data1.A3"));
-    m_pDoc->SetString(0, 3, 0, OUString("='file:///extdata.fake'#Data1.A4"));
-    m_pDoc->SetString(0, 4, 0, OUString("='file:///extdata.fake'#Data1.A5"));
-    m_pDoc->SetString(0, 5, 0, OUString("='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, OUString("='file:///extdata.fake'#Data1.B2"));
-    m_pDoc->SetString(1, 2, 0, OUString("='file:///extdata.fake'#Data1.B3"));
-    m_pDoc->SetString(1, 3, 0, OUString("='file:///extdata.fake'#Data1.B4"));
-    m_pDoc->SetString(1, 4, 0, OUString("='file:///extdata.fake'#Data1.B5"));
-    m_pDoc->SetString(1, 5, 0, OUString("='file:///extdata.fake'#Data1.B6"));
-    {
-        double pChecks[] = { 10, 11, 12, 13, 0 };
-        for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
-        {
-            m_pDoc->GetValue(1, static_cast<SCROW>(i+1), 0, val);
-            CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", val == pChecks[i]);
-        }
-    }
-
-    m_pDoc->SetString(2, 0, 0, OUString("='file:///extdata.fake'#Data3.A1"));
-    m_pDoc->SetString(2, 1, 0, OUString("='file:///extdata.fake'#Data3.A2"));
-    m_pDoc->SetString(2, 2, 0, OUString("='file:///extdata.fake'#Data3.A3"));
-    m_pDoc->SetString(2, 3, 0, OUString("='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, OUString("='file:///extdata.fake'#Data3.B1"));
-    m_pDoc->SetString(3, 1, 0, OUString("='file:///extdata.fake'#Data3.B2"));
-    m_pDoc->SetString(3, 2, 0, OUString("='file:///extdata.fake'#Data3.B3"));
-    m_pDoc->SetString(3, 3, 0, OUString("='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.get() != NULL);
-    ScRange aCachedRange = getCachedRange(pCacheTab);
-    CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
-                           aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
-                           aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 4);
-
-    // 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.get() == NULL);
-
-    // 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.get() != NULL);
-    aCachedRange = getCachedRange(pCacheTab);
-    CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
-                           aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
-                           aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 3);
-
-    // Unload the external document shell.
-    xExtDocSh->DoClose();
-    CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
-                           findLoadedDocShellByName(aExtDocName) == NULL);
-
-    m_pDoc->DeleteTab(0);
-}
-
-void testExtRefFuncT(ScDocument* pDoc, ScDocument* pExtDoc)
-{
-    Test::clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
-    Test::clearRange(pExtDoc, ScRange(0, 0, 0, 1, 9, 0));
-
-    pExtDoc->SetString(0, 0, 0, OUString("'1.2"));
-    pExtDoc->SetString(0, 1, 0, OUString("Foo"));
-    pExtDoc->SetValue(0, 2, 0, 12.3);
-    pDoc->SetString(0, 0, 0, OUString("=T('file:///extdata.fake'#Data.A1)"));
-    pDoc->SetString(0, 1, 0, OUString("=T('file:///extdata.fake'#Data.A2)"));
-    pDoc->SetString(0, 2, 0, OUString("=T('file:///extdata.fake'#Data.A3)"));
-    pDoc->CalcAll();
-
-    OUString aRes = pDoc->GetString(0, 0, 0);
-    CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "1.2" );
-    aRes = pDoc->GetString(0, 1, 0);
-    CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "Foo" );
-    aRes = pDoc->GetString(0, 2, 0);
-    CPPUNIT_ASSERT_MESSAGE("Unexpected result with T.", aRes.isEmpty());
-}
-
-void testExtRefFuncOFFSET(ScDocument* pDoc, ScDocument* pExtDoc)
-{
-    Test::clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
-    Test::clearRange(pExtDoc, 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'.
-    pExtDoc->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 Test::testExternalRefFunctions()
-{
-    ScDocShellRef xExtDocSh = new ScDocShell;
-    OUString aExtDocName("file:///extdata.fake");
-    SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
-    xExtDocSh->DoInitNew(pMed);
-    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
-                           findLoadedDocShellByName(aExtDocName) != NULL);
-
-    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 && pFileName->equals(aExtDocName));
-
-    // Populate the external source document.
-    ScDocument* pExtDoc = xExtDocSh->GetDocument();
-    pExtDoc->InsertTab(0, OUString("Data"));
-    double val = 1;
-    pExtDoc->SetValue(0, 0, 0, val);
-    // leave cell B1 empty.
-    val = 2;
-    pExtDoc->SetValue(0, 1, 0, val);
-    pExtDoc->SetValue(1, 1, 0, val);
-    val = 3;
-    pExtDoc->SetValue(0, 2, 0, val);
-    pExtDoc->SetValue(1, 2, 0, val);
-    val = 4;
-    pExtDoc->SetValue(0, 3, 0, val);
-    pExtDoc->SetValue(1, 3, 0, val);
-
-    m_pDoc->InsertTab(0, OUString("Test"));
-
-    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 }
-    };
-
-    for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
-    {
-        m_pDoc->SetString(0, 0, 0, OUString::createFromAscii(aChecks[i].pFormula));
-        m_pDoc->CalcAll();
-        m_pDoc->GetValue(0, 0, 0, val);
-        CPPUNIT_ASSERT_MESSAGE("unexpected result involving external ranges.", val == aChecks[i].fResult);
-    }
-
-    pRefMgr->clearCache(nFileId);
-    testExtRefFuncT(m_pDoc, pExtDoc);
-    testExtRefFuncOFFSET(m_pDoc, pExtDoc);
-
-    // Unload the external document shell.
-    xExtDocSh->DoClose();
-    CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
-                           findLoadedDocShellByName(aExtDocName) == NULL);
-
-    m_pDoc->DeleteTab(0);
-}
-
 void Test::testDataArea()
 {
     m_pDoc->InsertTab(0, OUString("Data"));
@@ -5866,6 +5537,24 @@ void Test::testMixData()
     m_pDoc->DeleteTab(0);
 }
 
+ScDocShell* Test::findLoadedDocShellByName(const OUString& rName)
+{
+    TypeId aType(TYPE(ScDocShell));
+    ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
+    while (pShell)
+    {
+        SfxMedium* pMedium = pShell->GetMedium();
+        if (pMedium)
+        {
+            OUString aName = pMedium->GetName();
+            if (aName.equals(rName))
+                return pShell;
+        }
+        pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
+    }
+    return NULL;
+}
+
 bool Test::insertRangeNames(ScDocument* pDoc, const RangeNameDef* p, const RangeNameDef* pEnd)
 {
     ScAddress aA1(0, 0, 0);
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 7ceabb4..29b4c53 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -38,6 +38,7 @@ public:
         sal_uInt16 mnIndex;
     };
 
+    static ScDocShell* findLoadedDocShellByName(const OUString& rName);
     static bool insertRangeNames(ScDocument* pDoc, const RangeNameDef* p, const RangeNameDef* pEnd);
     static void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption);
     static void clearRange(ScDocument* pDoc, const ScRange& rRange);
@@ -137,6 +138,9 @@ public:
     void testFuncGETPIVOTDATA();
     void testFuncGETPIVOTDATALeafAccess();
 
+    void testExternalRef();
+    void testExternalRefFunctions();
+
     void testCopyToDocument();
     /**
      * Make sure the SHEETS function gets properly updated during sheet
@@ -245,8 +249,6 @@ public:
     void testCellCopy();
     void testSheetCopy();
     void testSheetMove();
-    void testExternalRef();
-    void testExternalRefFunctions();
     void testDataArea();
     void testAutofilter();
     void testCopyPaste();
@@ -376,6 +378,8 @@ public:
     CPPUNIT_TEST(testFuncIFERROR);
     CPPUNIT_TEST(testFuncGETPIVOTDATA);
     CPPUNIT_TEST(testFuncGETPIVOTDATALeafAccess);
+    CPPUNIT_TEST(testExternalRef);
+    CPPUNIT_TEST(testExternalRefFunctions);
     CPPUNIT_TEST(testCopyToDocument);
     CPPUNIT_TEST(testSheetsFunc);
     CPPUNIT_TEST(testVolatileFunc);
@@ -410,8 +414,6 @@ public:
     CPPUNIT_TEST(testCellCopy);
     CPPUNIT_TEST(testSheetCopy);
     CPPUNIT_TEST(testSheetMove);
-    CPPUNIT_TEST(testExternalRef);
-    CPPUNIT_TEST(testExternalRefFunctions);
     CPPUNIT_TEST(testDataArea);
     CPPUNIT_TEST(testGraphicsInGroup);
     CPPUNIT_TEST(testGraphicsOnSheetMove);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 35e6369..ff9a1fc 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -31,6 +31,50 @@
 
 using namespace formula;
 
+namespace {
+
+ScRange getCachedRange(const ScExternalRefCache::TableTypeRef& pCacheTab)
+{
+    ScRange aRange;
+
+    vector<SCROW> aRows;
+    pCacheTab->getAllRows(aRows);
+    vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
+    bool bFirst = true;
+    for (; itrRow != itrRowEnd; ++itrRow)
+    {
+        SCROW nRow = *itrRow;
+        vector<SCCOL> aCols;
+        pCacheTab->getAllCols(nRow, aCols);
+        vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
+        for (; itrCol != itrColEnd; ++itrCol)
+        {
+            SCCOL nCol = *itrCol;
+            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 Test::testFormulaCreateStringFromTokens()
 {
     // Insert sheets.
@@ -2738,4 +2782,275 @@ void Test::testFuncINDIRECT()
     m_pDoc->DeleteTab(0);
 }
 
+void Test::testExternalRef()
+{
+    ScDocShellRef xExtDocSh = new ScDocShell;
+    OUString aExtDocName("file:///extdata.fake");
+    OUString aExtSh1Name("Data1");
+    OUString aExtSh2Name("Data2");
+    OUString aExtSh3Name("Data3");
+    SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
+    xExtDocSh->DoInitNew(pMed);
+    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
+                           findLoadedDocShellByName(aExtDocName) != NULL);
+
+    // Populate the external source document.
+    ScDocument* pExtDoc = xExtDocSh->GetDocument();
+    pExtDoc->InsertTab(0, aExtSh1Name);
+    pExtDoc->InsertTab(1, aExtSh2Name);
+    pExtDoc->InsertTab(2, aExtSh3Name);
+
+    OUString name("Name");
+    OUString value("Value");
+    OUString andy("Andy");
+    OUString bruce("Bruce");
+    OUString charlie("Charlie");
+    OUString david("David");
+    OUString edward("Edward");
+    OUString frank("Frank");
+    OUString george("George");
+    OUString henry("Henry");
+
+    // Sheet 1
+    pExtDoc->SetString(0, 0, 0, name);
+    pExtDoc->SetString(0, 1, 0, andy);
+    pExtDoc->SetString(0, 2, 0, bruce);
+    pExtDoc->SetString(0, 3, 0, charlie);
+    pExtDoc->SetString(0, 4, 0, david);
+    pExtDoc->SetString(1, 0, 0, value);
+    double val = 10;
+    pExtDoc->SetValue(1, 1, 0, val);
+    val = 11;
+    pExtDoc->SetValue(1, 2, 0, val);
+    val = 12;
+    pExtDoc->SetValue(1, 3, 0, val);
+    val = 13;
+    pExtDoc->SetValue(1, 4, 0, val);
+
+    // Sheet 2 remains empty.
+
+    // Sheet 3
+    pExtDoc->SetString(0, 0, 2, name);
+    pExtDoc->SetString(0, 1, 2, edward);
+    pExtDoc->SetString(0, 2, 2, frank);
+    pExtDoc->SetString(0, 3, 2, george);
+    pExtDoc->SetString(0, 4, 2, henry);
+    pExtDoc->SetString(1, 0, 2, value);
+    val = 99;
+    pExtDoc->SetValue(1, 1, 2, val);
+    val = 98;
+    pExtDoc->SetValue(1, 2, 2, val);
+    val = 97;
+    pExtDoc->SetValue(1, 3, 2, val);
+    val = 96;
+    pExtDoc->SetValue(1, 4, 2, val);
+
+    // Test external refernces on the main document while the external
+    // document is still in memory.
+    m_pDoc->InsertTab(0, OUString("Test Sheet"));
+    m_pDoc->SetString(0, 0, 0, OUString("='file:///extdata.fake'#Data1.A1"));
+    OUString test = m_pDoc->GetString(0, 0, 0);
+    CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(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_MESSAGE("Unexpected sheet name.", aTabNames[0].equals(aExtSh1Name));
+    CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[1].equals(aExtSh2Name));
+    CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[2].equals(aExtSh3Name));
+
+    m_pDoc->SetString(1, 0, 0, OUString("='file:///extdata.fake'#Data1.B1"));
+    test = m_pDoc->GetString(1, 0, 0);
+    CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(value));
+
+    m_pDoc->SetString(0, 1, 0, OUString("='file:///extdata.fake'#Data1.A2"));
+    m_pDoc->SetString(0, 2, 0, OUString("='file:///extdata.fake'#Data1.A3"));
+    m_pDoc->SetString(0, 3, 0, OUString("='file:///extdata.fake'#Data1.A4"));
+    m_pDoc->SetString(0, 4, 0, OUString("='file:///extdata.fake'#Data1.A5"));
+    m_pDoc->SetString(0, 5, 0, OUString("='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, OUString("='file:///extdata.fake'#Data1.B2"));
+    m_pDoc->SetString(1, 2, 0, OUString("='file:///extdata.fake'#Data1.B3"));
+    m_pDoc->SetString(1, 3, 0, OUString("='file:///extdata.fake'#Data1.B4"));
+    m_pDoc->SetString(1, 4, 0, OUString("='file:///extdata.fake'#Data1.B5"));
+    m_pDoc->SetString(1, 5, 0, OUString("='file:///extdata.fake'#Data1.B6"));
+    {
+        double pChecks[] = { 10, 11, 12, 13, 0 };
+        for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
+        {
+            m_pDoc->GetValue(1, static_cast<SCROW>(i+1), 0, val);
+            CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", val == pChecks[i]);
+        }
+    }
+
+    m_pDoc->SetString(2, 0, 0, OUString("='file:///extdata.fake'#Data3.A1"));
+    m_pDoc->SetString(2, 1, 0, OUString("='file:///extdata.fake'#Data3.A2"));
+    m_pDoc->SetString(2, 2, 0, OUString("='file:///extdata.fake'#Data3.A3"));
+    m_pDoc->SetString(2, 3, 0, OUString("='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, OUString("='file:///extdata.fake'#Data3.B1"));
+    m_pDoc->SetString(3, 1, 0, OUString("='file:///extdata.fake'#Data3.B2"));
+    m_pDoc->SetString(3, 2, 0, OUString("='file:///extdata.fake'#Data3.B3"));
+    m_pDoc->SetString(3, 3, 0, OUString("='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.get() != NULL);
+    ScRange aCachedRange = getCachedRange(pCacheTab);
+    CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
+                           aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
+                           aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 4);
+
+    // 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.get() == NULL);
+
+    // 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.get() != NULL);
+    aCachedRange = getCachedRange(pCacheTab);
+    CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
+                           aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
+                           aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 3);
+
+    // Unload the external document shell.
+    xExtDocSh->DoClose();
+    CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
+                           findLoadedDocShellByName(aExtDocName) == NULL);
+
+    m_pDoc->DeleteTab(0);
+}
+
+void testExtRefFuncT(ScDocument* pDoc, ScDocument* pExtDoc)
+{
+    Test::clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
+    Test::clearRange(pExtDoc, ScRange(0, 0, 0, 1, 9, 0));
+
+    pExtDoc->SetString(0, 0, 0, OUString("'1.2"));
+    pExtDoc->SetString(0, 1, 0, OUString("Foo"));
+    pExtDoc->SetValue(0, 2, 0, 12.3);
+    pDoc->SetString(0, 0, 0, OUString("=T('file:///extdata.fake'#Data.A1)"));
+    pDoc->SetString(0, 1, 0, OUString("=T('file:///extdata.fake'#Data.A2)"));
+    pDoc->SetString(0, 2, 0, OUString("=T('file:///extdata.fake'#Data.A3)"));
+    pDoc->CalcAll();
+
+    OUString aRes = pDoc->GetString(0, 0, 0);
+    CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "1.2" );
+    aRes = pDoc->GetString(0, 1, 0);
+    CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "Foo" );
+    aRes = pDoc->GetString(0, 2, 0);
+    CPPUNIT_ASSERT_MESSAGE("Unexpected result with T.", aRes.isEmpty());
+}
+
+void testExtRefFuncOFFSET(ScDocument* pDoc, ScDocument* pExtDoc)
+{
+    Test::clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
+    Test::clearRange(pExtDoc, 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'.
+    pExtDoc->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 Test::testExternalRefFunctions()
+{
+    ScDocShellRef xExtDocSh = new ScDocShell;
+    OUString aExtDocName("file:///extdata.fake");
+    SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
+    xExtDocSh->DoInitNew(pMed);
+    CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
+                           findLoadedDocShellByName(aExtDocName) != NULL);
+
+    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 && pFileName->equals(aExtDocName));
+
+    // Populate the external source document.
+    ScDocument* pExtDoc = xExtDocSh->GetDocument();
+    pExtDoc->InsertTab(0, OUString("Data"));
+    double val = 1;
+    pExtDoc->SetValue(0, 0, 0, val);
+    // leave cell B1 empty.
+    val = 2;
+    pExtDoc->SetValue(0, 1, 0, val);
+    pExtDoc->SetValue(1, 1, 0, val);
+    val = 3;
+    pExtDoc->SetValue(0, 2, 0, val);
+    pExtDoc->SetValue(1, 2, 0, val);
+    val = 4;
+    pExtDoc->SetValue(0, 3, 0, val);
+    pExtDoc->SetValue(1, 3, 0, val);
+
+    m_pDoc->InsertTab(0, OUString("Test"));
+
+    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 }
+    };
+
+    for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
+    {
+        m_pDoc->SetString(0, 0, 0, OUString::createFromAscii(aChecks[i].pFormula));
+        m_pDoc->CalcAll();
+        m_pDoc->GetValue(0, 0, 0, val);
+        CPPUNIT_ASSERT_MESSAGE("unexpected result involving external ranges.", val == aChecks[i].fResult);
+    }
+
+    pRefMgr->clearCache(nFileId);
+    testExtRefFuncT(m_pDoc, pExtDoc);
+    testExtRefFuncOFFSET(m_pDoc, pExtDoc);
+
+    // Unload the external document shell.
+    xExtDocSh->DoClose();
+    CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
+                           findLoadedDocShellByName(aExtDocName) == NULL);
+
+    m_pDoc->DeleteTab(0);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list