[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 194 commits - android/sdremote basctl/source bin/lint-ui.py compilerplugins/clang compilerplugins/Makefile-clang.mk config_host/config_global.h.in config_host/config_probes.h.in config_host.mk.in configure.ac connectivity/source cui/AllLangResTarget_cui.mk cui/source cui/uiconfig cui/UIConfig_cui.mk dbaccess/qa dbaccess/source editeng/source extensions/source extras/source filter/source forms/source fpicker/source framework/inc framework/Library_fwk.mk framework/source framework/uiconfig framework/UIConfig_startmodule.mk framework/util .gitignore helpcontent2 hwpfilter/source i18nlangtag/source include/sal include/sfx2 include/sot include/svl include/svtools include/svx include/toolkit include/tools include/vcl ios/.DS_Store ios/iosremote jfreereport/patches jfreereport/UnpackedTarball_jfreereport_libformula.mk odk/examples offapi/com offapi/type_reference officecfg/registry oox/source qadevOOo/runner qadevOOo/tests sa l/osl sal/rtl sax/qa sc/AllLangResTarget_sc.mk sc/inc sc/Library_scfilt.mk sc/qa scripting/source sc/source sc/uiconfig sc/UIConfig_scalc.mk sd/AllLangResTarget_sd.mk sd/inc sd/source sd/uiconfig sfx2/inc sfx2/Library_sfx.mk sfx2/source sfx2/uiconfig sfx2/UIConfig_sfx.mk sfx2/util slideshow/Library_slideshow.mk slideshow/source solenv/gbuild starmath/source svtools/Library_svt.mk svtools/source svx/source sw/AllLangResTarget_sw.mk sw/inc sw/qa sw/source sw/uiconfig sw/UIConfig_swriter.mk toolkit/source tools/source ucb/source vcl/aqua vcl/coretext vcl/source vcl/unx vcl/win writerfilter/source writerperfect/CppunitTest_writerperfect_stream.mk writerperfect/Module_writerperfect.mk writerperfect/qa writerperfect/source xmloff/source xmlscript/source

Kohei Yoshida kohei.yoshida at gmail.com
Thu Aug 8 11:56:19 PDT 2013


Rebased ref, commits from common ancestor:
commit f1f493235fd4c149b37b31b62620e90e0de2278a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Aug 8 07:52:45 2013 -0400

    Fix the (Windows) build. No idea how this was buildable on Linux.
    
    Change-Id: I9c0701b1b8f30c36f45bbee0d95e92a59f9891fe

diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 59518bc..e4277c0 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -33,12 +33,12 @@ using namespace ::com::sun::star::container;
 
 namespace oox { namespace xls {
 
-FormulaBuffer::FormulaBuffer::SharedFormulaEntry::SharedFormulaEntry(
+FormulaBuffer::SharedFormulaEntry::SharedFormulaEntry(
     const table::CellAddress& rAddr, const table::CellRangeAddress& rRange,
     const OUString& rTokenStr, sal_Int32 nSharedId ) :
     maAddress(rAddr), maRange(rRange), maTokenStr(rTokenStr), mnSharedId(nSharedId) {}
 
-FormulaBuffer::FormulaBuffer::SharedFormulaDesc::SharedFormulaDesc(
+FormulaBuffer::SharedFormulaDesc::SharedFormulaDesc(
     const com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
     const OUString& rCellValue, sal_Int32 nValueType ) :
     maAddress(rAddr), mnSharedId(nSharedId), maCellValue(rCellValue), mnValueType(nValueType) {}
commit 83e787b099ca2b76dade2658d44331b03aebc855
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Aug 8 00:27:15 2013 -0400

    Detect self-referencing groups, and disable group-calculation.
    
    And re-enable group-calculation on named ranges.
    
    Change-Id: I4957ff05bac23bd266bbc96fe5619ad5f0a65688

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index fd103bc..c87b045 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3279,6 +3279,49 @@ class GroupTokenConverter
     ScDocument& mrDoc;
     ScFormulaCell& mrCell;
     const ScAddress& mrPos;
+
+    bool isSelfReferenceRelative(const ScAddress& rRefPos, SCROW nRelRow)
+    {
+        if (rRefPos.Col() != mrPos.Col())
+            return false;
+
+        SCROW nLen = mrCell.GetCellGroup()->mnLength;
+        SCROW nEndRow = mrPos.Row() + nLen - 1;
+
+        if (nRelRow < 0)
+        {
+            SCROW nTest = nEndRow;
+            nTest += nRelRow;
+            if (nTest >= mrPos.Row())
+                return true;
+        }
+        else if (nRelRow > 0)
+        {
+            SCROW nTest = mrPos.Row(); // top row.
+            nTest += nRelRow;
+            if (nTest <= nEndRow)
+                return true;
+        }
+
+        return false;
+    }
+
+    bool isSelfReferenceAbsolute(const ScAddress& rRefPos)
+    {
+        if (rRefPos.Col() != mrPos.Col())
+            return false;
+
+        SCROW nLen = mrCell.GetCellGroup()->mnLength;
+        SCROW nEndRow = mrPos.Row() + nLen - 1;
+
+        if (rRefPos.Row() < mrPos.Row())
+            return false;
+
+        if (rRefPos.Row() > nEndRow)
+            return false;
+
+        return true;
+    }
 public:
     GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) :
         mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) {}
@@ -3302,6 +3345,7 @@ public:
             // absolute reference state for row directions.
 
             const ScToken* pToken = static_cast<const ScToken*>(p);
+            SCROW nLen = mrCell.GetCellGroup()->mnLength;
             switch (pToken->GetType())
             {
                 case svSingleRef:
@@ -3310,20 +3354,26 @@ public:
                     ScAddress aRefPos = aRef.toAbs(mrPos);
                     if (aRef.IsRowRel())
                     {
+                        if (isSelfReferenceRelative(aRefPos, aRef.Row()))
+                            return false;
+
                         // Fetch double array guarantees that the length of the
                         // returned array equals or greater than the requested
                         // length.
 
-                        const double* pArray = mrDoc.FetchDoubleArray(mrCxt, aRefPos, mrCell.GetCellGroup()->mnLength);
+                        const double* pArray = mrDoc.FetchDoubleArray(mrCxt, aRefPos, nLen);
                         if (!pArray)
                             return false;
 
-                        formula::SingleVectorRefToken aTok(pArray, mrCell.GetCellGroup()->mnLength);
+                        formula::SingleVectorRefToken aTok(pArray, nLen);
                         mrGroupTokens.AddToken(aTok);
                     }
                     else
                     {
                         // Absolute row reference.
+                        if (isSelfReferenceAbsolute(aRefPos))
+                            return false;
+
                         formula::FormulaTokenRef pNewToken = mrDoc.ResolveStaticReference(aRefPos);
                         if (!pNewToken)
                             return false;
@@ -3337,6 +3387,23 @@ public:
                     ScComplexRefData aRef = pToken->GetDoubleRef();
                     ScRange aAbs = aRef.toAbs(mrCell.aPos);
 
+                    // Check for self reference.
+                    if (aRef.Ref1.IsRowRel())
+                    {
+                        if (isSelfReferenceRelative(aAbs.aStart, aRef.Ref1.Row()))
+                            return false;
+                    }
+                    else if (isSelfReferenceAbsolute(aAbs.aStart))
+                        return false;
+
+                    if (aRef.Ref2.IsRowRel())
+                    {
+                        if (isSelfReferenceRelative(aAbs.aEnd, aRef.Ref2.Row()))
+                            return false;
+                    }
+                    else if (isSelfReferenceAbsolute(aAbs.aEnd))
+                        return false;
+
                     // Row reference is relative.
                     bool bAbsFirst = !aRef.Ref1.IsRowRel();
                     bool bAbsLast = !aRef.Ref2.IsRowRel();
@@ -3344,7 +3411,7 @@ public:
                     size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1;
                     std::vector<const double*> aArrays;
                     aArrays.reserve(nCols);
-                    SCROW nArrayLength = mrCell.GetCellGroup()->mnLength;
+                    SCROW nArrayLength = nLen;
                     SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1;
                     if (!bAbsLast)
                     {
@@ -3366,6 +3433,32 @@ public:
                     mrGroupTokens.AddToken(aTok);
                 }
                 break;
+                case svIndex:
+                {
+                    // Named range.
+                    ScRangeName* pNames = mrDoc.GetRangeName();
+                    if (!pNames)
+                        // This should never fail.
+                        return false;
+
+                    ScRangeData* pRange = pNames->findByIndex(p->GetIndex());
+                    if (!pRange)
+                        // No named range exists by that index.
+                        return false;
+
+                    ScTokenArray* pNamedTokens = pRange->GetCode();
+                    if (!pNamedTokens)
+                        // This named range is empty.
+                        return false;
+
+                    mrGroupTokens.AddOpCode(ocOpen);
+
+                    if (!convert(*pNamedTokens))
+                        return false;
+
+                    mrGroupTokens.AddOpCode(ocClose);
+                }
+                break;
                 default:
                     mrGroupTokens.AddToken(*pToken);
             }
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 9f58380..d74182d 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1347,9 +1347,6 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
                 ;
         }
     }
-
-    if (eOp == ocName)
-        meVectorState = FormulaVectorDisabled;
 }
 
 bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
commit 9a291549b13e385ea612eeb6f15dbbb2af7ed32f
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 23:58:32 2013 -0400

    Fix import of negative relative row reference from xls.
    
    Change-Id: Ibaa325396a8a06c45cf59af9809ed5cbff6d10d0

diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index 35de70f..043b3f4 100644
--- a/sc/source/filter/excel/excform8.cxx
+++ b/sc/source/filter/excel/excform8.cxx
@@ -1417,7 +1417,7 @@ void ExcelToSc8::ExcRelToScRel8( sal_uInt16 nRow, sal_uInt16 nC, ScSingleRefData
 
         // R O W
         if( bRowRel )
-            rSRD.SetRelRow(nRow);
+            rSRD.SetRelRow(static_cast<sal_Int16>(nRow));
         else
             rSRD.SetAbsRow(std::min( static_cast<SCROW>(nRow), MAXROW));
     }
commit b9b9feaaf17a8e27a3836ad61d2d416dc2e2e5f2
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 23:09:43 2013 -0400

    Disable vectorization on named ranges for now.
    
    Change-Id: Ibc10d5eb9afff6062106c952aa2e7d3f9cb58100

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 4a05c4c..fd103bc 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3366,32 +3366,6 @@ public:
                     mrGroupTokens.AddToken(aTok);
                 }
                 break;
-                case svIndex:
-                {
-                    // Named range.
-                    ScRangeName* pNames = mrDoc.GetRangeName();
-                    if (!pNames)
-                        // This should never fail.
-                        return false;
-
-                    ScRangeData* pRange = pNames->findByIndex(p->GetIndex());
-                    if (!pRange)
-                        // No named range exists by that index.
-                        return false;
-
-                    ScTokenArray* pNamedTokens = pRange->GetCode();
-                    if (!pNamedTokens)
-                        // This named range is empty.
-                        return false;
-
-                    mrGroupTokens.AddOpCode(ocOpen);
-
-                    if (!convert(*pNamedTokens))
-                        return false;
-
-                    mrGroupTokens.AddOpCode(ocClose);
-                }
-                break;
                 default:
                     mrGroupTokens.AddToken(*pToken);
             }
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index d74182d..9f58380 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1347,6 +1347,9 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
                 ;
         }
     }
+
+    if (eOp == ocName)
+        meVectorState = FormulaVectorDisabled;
 }
 
 bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
commit d2ad4b1fa36f845da97ec1d2dc8a479532cebab7
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 22:59:23 2013 -0400

    Uncomment this.
    
    Change-Id: I628c826905d0c1074fbc5c12e821c0efd6489bbf

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index d6254c2..4a05c4c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3410,7 +3410,7 @@ bool ScFormulaCell::InterpretFormulaGroup()
 
     // Re-build formulae groups if necessary - ideally this is done at
     // import / insert / delete etc. and is integral to the data structures
-//  pDocument->RebuildFormulaGroups();
+    pDocument->RebuildFormulaGroups();
 
     if (!mxGroup || !pCode)
         return false;
commit 2600509d89542cf361544a82b2c32368b6af2f4f
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 19:04:53 2013 -0400

    No more RT_SHARED and RT_SHAREDMOD named range types.
    
    Change-Id: Ic8d98b62747ae29cc968ce926e2ae42537023840

diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index 4a56ea1..e2731b5 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -51,8 +51,6 @@ typedef sal_uInt16 RangeType;
 #define RT_ABSAREA          ((RangeType)0x0020)
 #define RT_REFAREA          ((RangeType)0x0040)
 #define RT_ABSPOS           ((RangeType)0x0080)
-#define RT_SHARED           ((RangeType)0x0100)
-#define RT_SHAREDMOD        ((RangeType)0x0200)
 
 class ScRangeData
 {
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index c3ab5cd..d6254c2 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2825,8 +2825,6 @@ void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rD
             {
                 if (pName->IsModified())
                     bRefChanged = true;
-                if (pName->HasType(RT_SHAREDMOD))
-                    pShared = pName;
             }
         }
         else if( t->GetType() != svIndex )
@@ -2902,8 +2900,6 @@ void ScFormulaCell::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY
             {
                 if (pName->IsModified())
                     bRefChanged = true;
-                if (pName->HasType(RT_SHAREDMOD))
-                    pShared = pName;
             }
         }
         else if( t->GetType() != svIndex )
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 6391690..547daa6 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -4302,12 +4302,7 @@ void ScCompiler::CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* _pT
         {
             ScRangeData* pData = GetRangeData( *_pTokenP);
             if (pData)
-            {
-                if (pData->HasType(RT_SHARED))
-                    pData->UpdateSymbol( aBuffer, aPos, GetGrammar());
-                else
-                    aBuffer.append(pData->GetName());
-            }
+                aBuffer.append(pData->GetName());
         }
         break;
         case ocDBArea:
diff --git a/sc/source/filter/excel/xename.cxx b/sc/source/filter/excel/xename.cxx
index 276624c..54f2e8d 100644
--- a/sc/source/filter/excel/xename.cxx
+++ b/sc/source/filter/excel/xename.cxx
@@ -657,7 +657,7 @@ void XclExpNameManagerImpl::CreateUserNames()
     for (; itr != itrEnd; ++itr)
     {
         // skip definitions of shared formulas
-        if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(SCTAB_GLOBAL, itr->second->GetIndex()))
+        if (!FindNamedExpIndex(SCTAB_GLOBAL, itr->second->GetIndex()))
             CreateName(SCTAB_GLOBAL, *itr->second);
     }
     //look at every sheet for local range names
@@ -670,7 +670,7 @@ void XclExpNameManagerImpl::CreateUserNames()
         for (; itr != itrEnd; ++itr)
         {
             // skip definitions of shared formulas
-            if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(tabIt->first, itr->second->GetIndex()))
+            if (!FindNamedExpIndex(tabIt->first, itr->second->GetIndex()))
                 CreateName(tabIt->first, *itr->second);
         }
     }
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx
index 94d9594..2eff911 100644
--- a/sc/source/filter/excel/xlformula.cxx
+++ b/sc/source/filter/excel/xlformula.cxx
@@ -765,15 +765,9 @@ void XclTokenArrayHelper::ConvertStringToList( ScTokenArray& rScTokArr, sal_Unic
 
 // shared formulas ------------------------------------------------------------
 
-const ScTokenArray* XclTokenArrayHelper::GetSharedFormula( const XclRoot& rRoot, const ScTokenArray& rScTokArr )
-{
-    if( rScTokArr.GetLen() == 1 )
-        if( const FormulaToken* pScToken = rScTokArr.GetArray()[ 0 ] )
-            if( pScToken->GetOpCode() == ocName )
-                if( ScRangeData* pData = rRoot.GetNamedRanges().findByIndex( pScToken->GetIndex() ) )
-                    if( pData->HasType( RT_SHARED ) )
-                        return pData->GetCode();
-    return 0;
+const ScTokenArray* XclTokenArrayHelper::GetSharedFormula( const XclRoot& /*rRoot*/, const ScTokenArray& /*rScTokArr*/ )
+{
+    return NULL;
 }
 
 // multiple operations --------------------------------------------------------
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 2b26a73..f1b3491 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -5069,7 +5069,7 @@ sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
     for (ScRangeName::iterator itr = itrLocalBeg; itr != itrLocalEnd; ++itr)
     {
         const ScRangeData& r = *itr->second;
-        if (!r.HasType(RT_DATABASE) && !r.HasType(RT_SHARED))
+        if (!r.HasType(RT_DATABASE))
             ++nValidCount;
     }
     ScRangeName* pList = pDoc->GetRangeName();
@@ -5077,7 +5077,7 @@ sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
     for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
     {
         const ScRangeData& r = *itr->second;
-        if (!r.HasType(RT_DATABASE) && !r.HasType(RT_SHARED) && !pLocalList->findByUpperName(r.GetUpperName()))
+        if (!r.HasType(RT_DATABASE) && !pLocalList->findByUpperName(r.GetUpperName()))
             ++nValidCount;
     }
 
@@ -5106,13 +5106,13 @@ sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
             for (ScRangeName::iterator itr = itrLocalBeg; itr != itrLocalEnd; ++itr)
             {
                 ScRangeData& r = *itr->second;
-                if (!r.HasType(RT_DATABASE) && !r.HasType(RT_SHARED))
+                if (!r.HasType(RT_DATABASE))
                     ppSortArray[j++] = &r;
             }
             for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
             {
                 ScRangeData& r = *itr->second;
-                if (!r.HasType(RT_DATABASE) && !r.HasType(RT_SHARED) && !pLocalList->findByUpperName(itr->first))
+                if (!r.HasType(RT_DATABASE) && !pLocalList->findByUpperName(itr->first))
                     ppSortArray[j++] = &r;
             }
 #ifndef ICC
diff --git a/sc/source/ui/namedlg/namemgrtable.cxx b/sc/source/ui/namedlg/namemgrtable.cxx
index fd315c0..0fee2be 100644
--- a/sc/source/ui/namedlg/namemgrtable.cxx
+++ b/sc/source/ui/namedlg/namemgrtable.cxx
@@ -143,7 +143,7 @@ void ScRangeManagerTable::Init()
         for (ScRangeName::const_iterator it = pLocalRangeName->begin();
                 it != pLocalRangeName->end(); ++it)
         {
-            if (!it->second->HasType(RT_DATABASE) && !it->second->HasType(RT_SHARED))
+            if (!it->second->HasType(RT_DATABASE))
             {
                 aLine.aName = it->second->GetName();
                 addEntry(aLine, false);
diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx
index 0ec46ba..ae7a342 100644
--- a/sc/source/ui/unoobj/nameuno.cxx
+++ b/sc/source/ui/unoobj/nameuno.cxx
@@ -82,7 +82,7 @@ static bool lcl_UserVisibleName(const ScRangeData& rData)
 {
     //! als Methode an ScRangeData
 
-    return !rData.HasType(RT_DATABASE) && !rData.HasType(RT_SHARED);
+    return !rData.HasType(RT_DATABASE);
 }
 
 ScNamedRangeObj::ScNamedRangeObj( rtl::Reference< ScNamedRangesObj > xParent, ScDocShell* pDocSh, const String& rNm, Reference<container::XNamed> xSheet):
@@ -378,7 +378,7 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScNamedRangeObj::getPropertySet
 }
 
 void SAL_CALL ScNamedRangeObj::setPropertyValue(
-                        const OUString& rPropertyName, const uno::Any& aValue )
+                        const OUString& rPropertyName, const uno::Any& /*aValue*/ )
                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
                         lang::IllegalArgumentException, lang::WrappedTargetException,
                         uno::RuntimeException)
@@ -386,12 +386,7 @@ void SAL_CALL ScNamedRangeObj::setPropertyValue(
     SolarMutexGuard aGuard;
     if ( rPropertyName == SC_UNONAME_ISSHAREDFMLA )
     {
-        bool bIsShared = false;
-        if( aValue >>= bIsShared )
-        {
-            sal_uInt16 nNewType = bIsShared ? RT_SHARED : RT_NAME;
-            Modify_Impl( NULL, NULL, NULL, NULL, &nNewType,formula::FormulaGrammar::GRAM_PODF_A1 );
-        }
+        // Ignore this.
     }
 }
 
@@ -417,8 +412,8 @@ uno::Any SAL_CALL ScNamedRangeObj::getPropertyValue( const OUString& rPropertyNa
     }
     else if ( rPropertyName == SC_UNONAME_ISSHAREDFMLA )
     {
-        if( ScRangeData* pData = GetRangeData_Impl() )
-            aRet <<= static_cast< bool >( pData->HasType( RT_SHARED ) );
+        if (GetRangeData_Impl())
+            aRet <<= false;
     }
     return aRet;
 }
commit 550cfb64cd9586cd3666c4e8ae61d7163fd15cc9
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 18:46:57 2013 -0400

    Rework shared formula import in orcus handler.
    
    Change-Id: I3a6ed347565fff7cc984960929c66997e3a18f1e

diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index 89b96ed..75ee0fe 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -133,6 +133,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
 	sc/source/filter/ftools/fapihelper \
 	sc/source/filter/ftools/fprogressbar \
 	sc/source/filter/ftools/ftools \
+	sc/source/filter/ftools/sharedformulagroups \
 	sc/source/filter/html/htmlexp \
 	sc/source/filter/html/htmlexp2 \
 	sc/source/filter/html/htmlimp \
diff --git a/sc/source/filter/ftools/sharedformulagroups.cxx b/sc/source/filter/ftools/sharedformulagroups.cxx
new file mode 100644
index 0000000..77da587
--- /dev/null
+++ b/sc/source/filter/ftools/sharedformulagroups.cxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#include "sharedformulagroups.hxx"
+
+namespace sc {
+
+SharedFormulaGroups::Key::Key(size_t nId, SCCOL nCol) : mnId(nId), mnCol(nCol) {}
+
+bool SharedFormulaGroups::Key::operator== ( const Key& rOther ) const
+{
+    return mnId == rOther.mnId && mnCol == rOther.mnCol;
+}
+
+bool SharedFormulaGroups::Key::operator!= ( const Key& rOther ) const
+{
+    return !operator==(rOther);
+}
+
+size_t SharedFormulaGroups::KeyHash::operator ()( const Key& rKey ) const
+{
+    double nVal = rKey.mnId;
+    nVal *= 256.0;
+    nVal += rKey.mnCol;
+    return static_cast<size_t>(nVal);
+}
+
+void SharedFormulaGroups::set( size_t nSharedId, SCCOL nCol, const ScFormulaCellGroupRef& xGroup )
+{
+    Key aKey(nSharedId, nCol);
+    maStore.insert(StoreType::value_type(aKey, xGroup));
+}
+
+ScFormulaCellGroupRef SharedFormulaGroups::get( size_t nSharedId, SCCOL nCol ) const
+{
+    Key aKey(nSharedId, nCol);
+    StoreType::const_iterator it = maStore.find(aKey);
+    return it == maStore.end() ? ScFormulaCellGroupRef() : it->second;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx
index 6e6f2db..75b49f4 100644
--- a/sc/source/filter/inc/orcusinterface.hxx
+++ b/sc/source/filter/inc/orcusinterface.hxx
@@ -12,6 +12,9 @@
 
 #include "address.hxx"
 #include "documentimport.hxx"
+
+#include "sharedformulagroups.hxx"
+
 #include "rtl/strbuf.hxx"
 
 #define __ORCUS_STATIC_LIB
@@ -68,6 +71,7 @@ class ScOrcusSheet : public orcus::spreadsheet::iface::import_sheet
     ScDocumentImport& mrDoc;
     SCTAB mnTab;
     ScOrcusFactory& mrFactory;
+    sc::SharedFormulaGroups maFormulaGroups;
 
     typedef std::map<size_t, ScRangeData*> SharedFormulaContainer;
     SharedFormulaContainer maSharedFormulas;
diff --git a/sc/source/filter/inc/sharedformulagroups.hxx b/sc/source/filter/inc/sharedformulagroups.hxx
new file mode 100644
index 0000000..c6058fc
--- /dev/null
+++ b/sc/source/filter/inc/sharedformulagroups.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef SC_FILTER_SHAREDFORMULAGROUPS_HXX
+#define SC_FILTER_SHAREDFORMULAGROUPS_HXX
+
+#include "address.hxx"
+#include "formulacell.hxx"
+
+#include <boost/unordered_map.hpp>
+
+namespace sc {
+
+class SharedFormulaGroups
+{
+    struct Key
+    {
+        size_t mnId;
+        SCCOL mnCol;
+
+        Key(size_t nId, SCCOL nCol);
+
+        bool operator== ( const Key& rOther ) const;
+        bool operator!= ( const Key& rOther ) const;
+    };
+
+    struct KeyHash
+    {
+        size_t operator() ( const Key& rKey ) const;
+    };
+
+    typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
+    StoreType maStore;
+public:
+
+    void set( size_t nSharedId, SCCOL nCol, const ScFormulaCellGroupRef& xGroup );
+    ScFormulaCellGroupRef get( size_t nSharedId, SCCOL nCol ) const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 66d15ea..59518bc 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -22,6 +22,7 @@
 #include "autonamecache.hxx"
 #include "tokenuno.hxx"
 #include "tokenarray.hxx"
+#include "sharedformulagroups.hxx"
 #include "oox/token/tokens.hxx"
 
 using namespace com::sun::star;
@@ -137,59 +138,6 @@ void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair
     }
 }
 
-namespace {
-
-class SharedFormulaGroups
-{
-    struct Key
-    {
-        sal_Int32 mnId;
-        sal_Int32 mnCol;
-
-        Key(sal_Int32 nId, sal_Int32 nCol) : mnId(nId), mnCol(nCol) {}
-
-        bool operator== ( const Key& rOther ) const
-        {
-            return mnId == rOther.mnId && mnCol == rOther.mnCol;
-        }
-
-        bool operator!= ( const Key& rOther ) const
-        {
-            return !operator==(rOther);
-        }
-    };
-
-    struct KeyHash
-    {
-        size_t operator() ( const Key& rKey ) const
-        {
-            double nVal = rKey.mnId;
-            nVal *= 256.0;
-            nVal += rKey.mnCol;
-            return static_cast<size_t>(nVal);
-        }
-    };
-
-    typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
-    StoreType maStore;
-public:
-
-    void set( sal_Int32 nSharedId, sal_Int32 nCol, const ScFormulaCellGroupRef& xGroup )
-    {
-        Key aKey(nSharedId, nCol);
-        maStore.insert(StoreType::value_type(aKey, xGroup));
-    }
-
-    ScFormulaCellGroupRef get( sal_Int32 nSharedId, sal_Int32 nCol ) const
-    {
-        Key aKey(nSharedId, nCol);
-        StoreType::const_iterator it = maStore.find(aKey);
-        return it == maStore.end() ? ScFormulaCellGroupRef() : it->second;
-    }
-};
-
-}
-
 void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
 {
     SheetToFormulaEntryMap::const_iterator itShared = sharedFormulas.find(nTab);
@@ -207,7 +155,7 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
 
     ScDocument& rDoc = getScDocument();
 
-    SharedFormulaGroups aGroups;
+    sc::SharedFormulaGroups aGroups;
     {
         // Process shared formulas first.
         std::vector<SharedFormulaEntry>::const_iterator it = rSharedFormulas.begin(), itEnd = rSharedFormulas.end();
@@ -231,7 +179,7 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
                     // shared formulas across multiple columns.
                     ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup);
                     xNewGroup->mnStart = rRange.StartRow;
-                    xNewGroup->mnLength = rRange.EndRow - rRange.StartRow;
+                    xNewGroup->mnLength = rRange.EndRow - rRange.StartRow + 1;
                     xNewGroup->setCode(*pArray);
                     aGroups.set(nId, nCol, xNewGroup);
                 }
diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx
index a3c1e6d..495715f 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -16,6 +16,7 @@
 #include "globalnames.hxx"
 #include "docoptio.hxx"
 #include "globstr.hrc"
+#include "compiler.hxx"
 
 #include "formula/token.hxx"
 #include "tools/datetime.hxx"
@@ -256,7 +257,7 @@ formula::FormulaGrammar::Grammar getCalcGrammarFromOrcus( os::formula_grammar_t
             break;
         case orcus::spreadsheet::xlsx_2007:
         case orcus::spreadsheet::xlsx_2010:
-            eGrammar = formula::FormulaGrammar::GRAM_ENGLISH_XL_A1;
+            eGrammar = formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX;
             break;
         case orcus::spreadsheet::gnumeric:
             eGrammar = formula::FormulaGrammar::GRAM_ENGLISH_XL_A1;
@@ -266,6 +267,55 @@ formula::FormulaGrammar::Grammar getCalcGrammarFromOrcus( os::formula_grammar_t
     return eGrammar;
 }
 
+class SharedFormulaGroups
+{
+    struct Key
+    {
+        sal_Int32 mnId;
+        sal_Int32 mnCol;
+
+        Key(sal_Int32 nId, sal_Int32 nCol) : mnId(nId), mnCol(nCol) {}
+
+        bool operator== ( const Key& rOther ) const
+        {
+            return mnId == rOther.mnId && mnCol == rOther.mnCol;
+        }
+
+        bool operator!= ( const Key& rOther ) const
+        {
+            return !operator==(rOther);
+        }
+    };
+
+    struct KeyHash
+    {
+        size_t operator() ( const Key& rKey ) const
+        {
+            double nVal = rKey.mnId;
+            nVal *= 256.0;
+            nVal += rKey.mnCol;
+            return static_cast<size_t>(nVal);
+        }
+    };
+
+    typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
+    StoreType maStore;
+public:
+
+    void set( sal_Int32 nSharedId, sal_Int32 nCol, const ScFormulaCellGroupRef& xGroup )
+    {
+        Key aKey(nSharedId, nCol);
+        maStore.insert(StoreType::value_type(aKey, xGroup));
+    }
+
+    ScFormulaCellGroupRef get( sal_Int32 nSharedId, sal_Int32 nCol ) const
+    {
+        Key aKey(nSharedId, nCol);
+        StoreType::const_iterator it = maStore.find(aKey);
+        return it == maStore.end() ? ScFormulaCellGroupRef() : it->second;
+    }
+};
+
 }
 
 void ScOrcusSheet::set_formula(
@@ -291,57 +341,76 @@ void ScOrcusSheet::set_formula_result(os::row_t row, os::col_t col, const char*
 }
 
 void ScOrcusSheet::set_shared_formula(
-    os::row_t row, os::col_t col, os::formula_grammar_t grammar, size_t sindex,
-    const char* p_formula, size_t n_formula)
+    os::row_t /*row*/, os::col_t /*col*/, os::formula_grammar_t /*grammar*/, size_t /*sindex*/,
+    const char* /*p_formula*/, size_t /*n_formula*/)
 {
-    OUString aFormula( p_formula, n_formula, RTL_TEXTENCODING_UTF8 );
-    formula::FormulaGrammar::Grammar eGrammar =  getCalcGrammarFromOrcus( grammar );
-    ScRangeName* pRangeName = mrDoc.getDoc().GetRangeName();
-
-    OUString aName("shared_");
-    aName += OUString::valueOf(sal_Int32(pRangeName->size()));
-    ScRangeData* pSharedFormula = new ScRangeData(&mrDoc.getDoc(), aName, aFormula, ScAddress(col, row, mnTab), RT_SHARED, eGrammar);
-    if(pRangeName->insert(pSharedFormula))
-    {
-        maSharedFormulas.insert( std::pair<size_t, ScRangeData*>(sindex, pSharedFormula) );
-        ScTokenArray aArr;
-        aArr.AddToken( formula::FormulaIndexToken( ocName, pSharedFormula->GetIndex() ) );
-        mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aArr);
-        cellInserted();
-    }
+    // TODO: We need to revise this interface in orcus.
 }
 
 void ScOrcusSheet::set_shared_formula(
     os::row_t row, os::col_t col, os::formula_grammar_t grammar, size_t sindex,
-    const char* p_formula, size_t n_formula, const char* /*p_range*/, size_t /*n_range*/)
-{
-    OUString aFormula( p_formula, n_formula, RTL_TEXTENCODING_UTF8 );
-    formula::FormulaGrammar::Grammar eGrammar = getCalcGrammarFromOrcus( grammar );
-    ScRangeName* pRangeName = mrDoc.getDoc().GetRangeName();
+    const char* p_formula, size_t n_formula, const char* p_range, size_t n_range)
+{
+    ScAddress aPos(col, row, mnTab);
+    OUString aFormula(p_formula, n_formula, RTL_TEXTENCODING_UTF8);
+    OUString aRangeStr(p_range, n_range, RTL_TEXTENCODING_UTF8);
+    formula::FormulaGrammar::Grammar eGram = getCalcGrammarFromOrcus(grammar);
+    formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::extractRefConvention(eGram);
+
+    // Convert the shared formula range.
+    ScRange aRange;
+    sal_uInt16 nRes = aRange.Parse(aRangeStr, &mrDoc.getDoc(), eConv);
+    if (!(nRes & SCA_VALID))
+        // Conversion failed.
+        return;
+
+    // Compile the formula expression into tokens.
+    ScCompiler aComp(&mrDoc.getDoc(), aPos);
+    aComp.SetGrammar(eGram);
+    ScTokenArray* pArray = aComp.CompileString(aFormula);
+    if (!pArray)
+        // Tokenization failed.
+        return;
 
-    OUString aName("shared_");
-    aName += OUString::valueOf(sal_Int32(pRangeName->size()));
-    ScRangeData* pSharedFormula = new ScRangeData(&mrDoc.getDoc(), aName, aFormula, ScAddress(col, row, mnTab), RT_SHARED, eGrammar);
-    if(pRangeName->insert(pSharedFormula))
+    for (sal_Int32 nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
     {
-        maSharedFormulas.insert( std::pair<size_t, ScRangeData*>(sindex, pSharedFormula) );
-        ScTokenArray aArr;
-        aArr.AddToken( formula::FormulaIndexToken( ocName, pSharedFormula->GetIndex() ) );
-        mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aArr);
-        cellInserted();
+        // Create one group per column, since Calc doesn't support shared
+        // formulas across multiple columns.
+        ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup);
+        xNewGroup->mnStart = aRange.aStart.Row();
+        xNewGroup->mnLength = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+        xNewGroup->setCode(*pArray);
+        maFormulaGroups.set(sindex, nCol, xNewGroup);
     }
+
+    ScFormulaCellGroupRef xGroup = maFormulaGroups.get(sindex, aPos.Col());
+    if (!xGroup)
+        return;
+
+    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, xGroup);
+    mrDoc.setFormulaCell(aPos, pCell);
+    cellInserted();
+
+    // For now, orcus doesn't support setting cached result. Mark it for re-calculation.
+    pCell->SetDirty(true);
+    pCell->StartListeningTo(&mrDoc.getDoc());
 }
 
 void ScOrcusSheet::set_shared_formula(os::row_t row, os::col_t col, size_t sindex)
 {
-    if(maSharedFormulas.find(sindex) == maSharedFormulas.end())
+    ScAddress aPos(col, row, mnTab);
+
+    ScFormulaCellGroupRef xGroup = maFormulaGroups.get(sindex, aPos.Col());
+    if (!xGroup)
         return;
 
-    ScRangeData* pSharedFormula = maSharedFormulas.find(sindex)->second;
-    ScTokenArray aArr;
-    aArr.AddToken( formula::FormulaIndexToken( ocName, pSharedFormula->GetIndex() ) );
-    mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aArr);
+    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, xGroup);
+    mrDoc.setFormulaCell(aPos, pCell);
     cellInserted();
+
+    // For now, orcus doesn't support setting cached result. Mark it for re-calculation.
+    pCell->SetDirty(true);
+    pCell->StartListeningTo(&mrDoc.getDoc());
 }
 
 void ScOrcusSheet::set_array_formula(
commit a9cf5f91ef83257155190a0ebe44b57a6fc9d01b
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 17:30:20 2013 -0400

    This code is no longer needed.
    
    Change-Id: I319aae9d58fe1798e6add168f5a3613bceef7c26

diff --git a/sc/source/filter/inc/sheetdatabuffer.hxx b/sc/source/filter/inc/sheetdatabuffer.hxx
index 563145e..e826bd2 100644
--- a/sc/source/filter/inc/sheetdatabuffer.hxx
+++ b/sc/source/filter/inc/sheetdatabuffer.hxx
@@ -143,12 +143,6 @@ public:
                             const ::com::sun::star::table::CellRangeAddress& rRange,
                             const DataTableModel& rModel );
 
-    /** Creates a named range with a special name for a shared formula with the
-        specified base address and formula definition (BIFF only). */
-    void                createSharedFormula(
-                            const ::com::sun::star::table::CellAddress& rCellAddr,
-                            const ApiTokenSequence& rTokens );
-
     /** Sets default cell formatting for the specified range of rows. */
     void                setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat );
     /** Merges the cells in the passed cell range. */
@@ -173,9 +167,6 @@ private:
                             const ::com::sun::star::table::CellAddress& rCellAddr,
                             const ApiTokenSequence& rTokens );
 
-    /** Creates a named range with a special name for a shared formula with the
-        specified base address and formula definition. */
-    void                createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens );
     /** Creates a formula token array representing the shared formula with the
         passed identifier. */
     ApiTokenSequence    resolveSharedFormula( const BinAddress& rMapKey ) const;
diff --git a/sc/source/filter/oox/sheetdatabuffer.cxx b/sc/source/filter/oox/sheetdatabuffer.cxx
index 174842a..99e8054 100644
--- a/sc/source/filter/oox/sheetdatabuffer.cxx
+++ b/sc/source/filter/oox/sheetdatabuffer.cxx
@@ -276,11 +276,6 @@ void SheetDataBuffer::createTableOperation( const CellRangeAddress& rRange, cons
     maTableOperations.push_back( TableOperation( rRange, rModel ) );
 }
 
-void SheetDataBuffer::createSharedFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
-{
-    createSharedFormula( BinAddress( rCellAddr ), rTokens );
-}
-
 void SheetDataBuffer::setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat )
 {
     // set row formatting
@@ -554,33 +549,6 @@ void SheetDataBuffer::setCellFormula( const CellAddress& rCellAddr, const ApiTok
     }
 }
 
-void SheetDataBuffer::createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens )
-{
-    // create the defined name that will represent the shared formula
-    OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
-        append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ).
-        append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ).
-        append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear();
-    ScRangeData* pScRangeData = createNamedRangeObject( aName, rTokens, 0 );
-    pScRangeData->SetType(RT_SHARED);
-
-    // get and store the token index of the defined name
-    OSL_ENSURE( maSharedFormulas.count( rMapKey ) == 0, "SheetDataBuffer::createSharedFormula - shared formula exists already" );
-    sal_Int32 nTokenIndex = static_cast< sal_Int32 >( pScRangeData->GetIndex() );
-    if( nTokenIndex >= 0 ) try
-    {
-        // store the token index in the map
-        maSharedFormulas[ rMapKey ] = nTokenIndex;
-        // retry to insert a pending shared formula cell
-        if( mbPendingSharedFmla )
-            setCellFormula( maSharedFmlaAddr, resolveSharedFormula( maSharedBaseAddr ) );
-    }
-    catch( Exception& )
-    {
-    }
-    mbPendingSharedFmla = false;
-}
-
 ApiTokenSequence SheetDataBuffer::resolveSharedFormula( const BinAddress& rMapKey ) const
 {
     sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maSharedFormulas, rMapKey, -1 );
diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx
index 24be4d7..3aaaaac 100644
--- a/sc/source/filter/oox/sheetdatacontext.cxx
+++ b/sc/source/filter/oox/sheetdatacontext.cxx
@@ -578,17 +578,10 @@ void SheetDataContext::importDataTable( SequenceInputStream& rStrm )
     }
 }
 
-void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm )
+void SheetDataContext::importSharedFmla( SequenceInputStream& /*rStrm*/ )
 {
-    if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
-    {
-        ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
-        mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens );
-    }
 }
 
-// ============================================================================
-
 } // namespace xls
 } // namespace oox
 
commit 2ef9d3898f1774a2ab791d20ca532590d1e56ed8
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Aug 7 16:35:06 2013 -0400

    Map shared formulas to Calc's formula groups on xlsx import.
    
    Change-Id: If8d11c5ee55afd8529070a699ca50284880ceb45

diff --git a/sc/source/filter/excel/namebuff.cxx b/sc/source/filter/excel/namebuff.cxx
index ac609a4..4e47c09 100644
--- a/sc/source/filter/excel/namebuff.cxx
+++ b/sc/source/filter/excel/namebuff.cxx
@@ -89,8 +89,6 @@ void SharedFormulaBuffer::Store( const ScRange& rRange, const ScTokenArray& rArr
         ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup);
         xNewGroup->mnStart = rRange.aStart.Row();
         xNewGroup->mnLength = nGroupLen;
-        xNewGroup->mpCode = rArray.Clone();
-        xNewGroup->mbInvariant = rArray.IsInvariant();
         xNewGroup->setCode(rArray);
         maFormulaGroups.insert(FormulaGroupsType::value_type(aPos, xNewGroup));
     }
diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx
index 1e98060..c5d8f96 100644
--- a/sc/source/filter/inc/formulabuffer.hxx
+++ b/sc/source/filter/inc/formulabuffer.hxx
@@ -29,13 +29,35 @@ namespace oox { namespace xls {
 
 class FormulaBuffer : public WorkbookHelper
 {
+    /**
+     * Represents a shared formula definition.
+     */
     struct SharedFormulaEntry
     {
-        ::com::sun::star::table::CellAddress maAddress;
+        com::sun::star::table::CellAddress maAddress;
+        com::sun::star::table::CellRangeAddress maRange;
         OUString maTokenStr;
         sal_Int32 mnSharedId;
-        ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens > mxFormulaTokens;
-        SharedFormulaEntry( const ::com::sun::star::table::CellAddress& rAddress, const OUString& rTokenStr, sal_Int32 nSharedId ) : maAddress( rAddress ), maTokenStr( rTokenStr ), mnSharedId( nSharedId ) {}
+
+        SharedFormulaEntry(
+            const com::sun::star::table::CellAddress& rAddress,
+            const com::sun::star::table::CellRangeAddress& rRange,
+            const OUString& rTokenStr, sal_Int32 nSharedId );
+    };
+
+    /**
+     * Represents a formula cell that uses shared formula.
+     */
+    struct SharedFormulaDesc
+    {
+        com::sun::star::table::CellAddress maAddress;
+        sal_Int32 mnSharedId;
+        OUString maCellValue;
+        sal_Int32 mnValueType;
+
+        SharedFormulaDesc(
+            const com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
+            const OUString& rCellValue, sal_Int32 nValueType );
     };
 
     struct TokenAddressItem
@@ -54,8 +76,6 @@ class FormulaBuffer : public WorkbookHelper
 
     typedef ::std::map< sal_Int32, std::vector< TokenAddressItem > > FormulaDataMap;
     typedef ::std::map< sal_Int32, std::vector< TokenRangeAddressItem > > ArrayFormulaDataMap;
-    // shared formuala descriptions, the id and address the formula is at
-    typedef std::pair< ::com::sun::star::table::CellAddress, sal_Int32 > SharedFormulaDesc;
     // sheet -> list of shared formula descriptions
     typedef ::std::map< sal_Int32, std::vector< SharedFormulaDesc > > SheetToSharedFormulaid;
     // sheet -> stuff needed to create shared formulae
@@ -66,7 +86,6 @@ class FormulaBuffer : public WorkbookHelper
     typedef ::std::pair< ::com::sun::star::table::CellAddress, double > ValueAddressPair;
     typedef ::std::map< sal_Int32, std::vector< ValueAddressPair > > FormulaValueMap;
 
-    void createSharedFormula(  const ::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const OUString& rTokens );
     ::com::sun::star::uno::Reference< com::sun::star::table::XCellRange > getRange( const ::com::sun::star::table::CellRangeAddress& rRange);
     com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheet > mxCurrSheet;
     FormulaDataMap      cellFormulas;
@@ -80,15 +99,23 @@ class FormulaBuffer : public WorkbookHelper
     void                applyCellFormula( ScDocument& rDoc, const ApiTokenSequence& rTokens, const ::com::sun::star::table::CellAddress& rAddress );
     void                applyCellFormulas(  const std::vector< TokenAddressItem >& rVector );
     void                applyCellFormulaValues( const std::vector< ValueAddressPair >& rVector );
+    void applySharedFormulas( sal_Int32 nTab );
 
 public:
     explicit            FormulaBuffer( const WorkbookHelper& rHelper );
     void                finalizeImport();
     void                setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, const OUString&  );
-    void                setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId );
+
+    void setCellFormula(
+        const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId,
+        const OUString& rCellValue, sal_Int32 nValueType );
+
     void                setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress, double fValue  );
     void                setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString&  );
-    void                createSharedFormulaMapEntry( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens );
+    void createSharedFormulaMapEntry(
+        const com::sun::star::table::CellAddress& rAddress,
+        const com::sun::star::table::CellRangeAddress& rRange,
+        sal_Int32 nSharedId, const OUString& rTokens );
 };
 
 }}
diff --git a/sc/source/filter/inc/workbookhelper.hxx b/sc/source/filter/inc/workbookhelper.hxx
index f4ce1cc..e540ba0 100644
--- a/sc/source/filter/inc/workbookhelper.hxx
+++ b/sc/source/filter/inc/workbookhelper.hxx
@@ -156,7 +156,7 @@ public:
 
     /** Returns a reference to the specified spreadsheet in the document model. */
     ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >
-                        getSheetFromDoc( sal_Int16 nSheet ) const;
+                        getSheetFromDoc( sal_Int32 nSheet ) const;
     /** Returns a reference to the specified spreadsheet in the document model. */
     ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >
                         getSheetFromDoc( const OUString& rSheet ) const;
diff --git a/sc/source/filter/inc/worksheethelper.hxx b/sc/source/filter/inc/worksheethelper.hxx
index 53b7ed1..270cafe 100644
--- a/sc/source/filter/inc/worksheethelper.hxx
+++ b/sc/source/filter/inc/worksheethelper.hxx
@@ -307,9 +307,18 @@ public:
     void finalizeDrawingImport();
 
     void                setCellFormula( const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString&  );
-    void                setCellFormula( const ::com::sun::star::table::CellAddress& rTokenAddress, sal_Int32  );
+
+    void setCellFormula(
+        const com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
+        const OUString& rCellValue, sal_Int32 nValueType );
+
     void                setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString&  );
-    void                createSharedFormulaMapEntry( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens );
+
+    void createSharedFormulaMapEntry(
+        const com::sun::star::table::CellAddress& rAddress,
+        const com::sun::star::table::CellRangeAddress& rRange,
+        sal_Int32 nSharedId, const OUString& rTokens );
+
     void                setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress,
                             double fValue  );
 private:
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 3889b53..66d15ea 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -22,15 +22,26 @@
 #include "autonamecache.hxx"
 #include "tokenuno.hxx"
 #include "tokenarray.hxx"
+#include "oox/token/tokens.hxx"
 
-namespace oox {
-namespace xls {
-
+using namespace com::sun::star;
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::table;
 using namespace ::com::sun::star::sheet;
 using namespace ::com::sun::star::container;
 
+namespace oox { namespace xls {
+
+FormulaBuffer::FormulaBuffer::SharedFormulaEntry::SharedFormulaEntry(
+    const table::CellAddress& rAddr, const table::CellRangeAddress& rRange,
+    const OUString& rTokenStr, sal_Int32 nSharedId ) :
+    maAddress(rAddr), maRange(rRange), maTokenStr(rTokenStr), mnSharedId(nSharedId) {}
+
+FormulaBuffer::FormulaBuffer::SharedFormulaDesc::SharedFormulaDesc(
+    const com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
+    const OUString& rCellValue, sal_Int32 nValueType ) :
+    maAddress(rAddr), mnSharedId(nSharedId), maCellValue(rCellValue), mnValueType(nValueType) {}
+
 FormulaBuffer::FormulaBuffer( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper )
 {
 }
@@ -55,43 +66,13 @@ void FormulaBuffer::finalizeImport()
     ScDocument& rDoc = getScDocument();
     Reference< XIndexAccess > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW );
     rDoc.SetAutoNameCache( new ScAutoNameCache( &rDoc ) );
-    for ( sal_Int16 nTab = 0, nElem = xSheets->getCount(); nTab < nElem; ++nTab )
+    for ( sal_Int32 nTab = 0, nElem = xSheets->getCount(); nTab < nElem; ++nTab )
     {
         double fPosition = static_cast< double> (nTab + 1) /static_cast<double>(nElem);
         xFormulaBar->setPosition( fPosition );
         mxCurrSheet = getSheetFromDoc( nTab );
-        // process shared Formula
-        SheetToFormulaEntryMap::iterator sharedIt = sharedFormulas.find( nTab );
-        if ( sharedIt != sharedFormulas.end() )
-        {
-            // shared id ( to create the special shared names from )
-            std::vector<SharedFormulaEntry>& rSharedFormulas = sharedIt->second;
-            for ( std::vector<SharedFormulaEntry>::iterator it = rSharedFormulas.begin(), it_end = rSharedFormulas.end(); it != it_end; ++it )
-            {
-                 createSharedFormula( it->maAddress, it->mnSharedId, it->maTokenStr );
-            }
-        }
-        // now process any defined shared formulae
-        SheetToSharedFormulaid::iterator formulDescIt = sharedFormulaIds.find( nTab );
-        SheetToSharedIdToTokenIndex::iterator tokensIt = tokenIndexes.find( nTab );
-        if ( formulDescIt != sharedFormulaIds.end() && tokensIt !=  tokenIndexes.end() )
-        {
-            SharedIdToTokenIndex& rTokenIdMap = tokensIt->second;
-            std::vector< SharedFormulaDesc >& rVector = formulDescIt->second;
-            for ( std::vector< SharedFormulaDesc >::iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
-            {
-                // see if we have a
-                // resolved tokenId
-                CellAddress& rAddress = it->first;
-                sal_Int32& rnSharedId = it->second;
-                SharedIdToTokenIndex::iterator itTokenId =  rTokenIdMap.find( rnSharedId );
-                if ( itTokenId != rTokenIdMap.end() )
-                {
-                    ApiTokenSequence aTokens =  getFormulaParser().convertNameToFormula( itTokenId->second );
-                    applyCellFormula( rDoc, aTokens, rAddress );
-                }
-            }
-        }
+
+        applySharedFormulas(nTab);
 
         FormulaDataMap::iterator cellIt = cellFormulas.find( nTab );
         if ( cellIt != cellFormulas.end() )
@@ -155,6 +136,157 @@ void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair
         }
     }
 }
+
+namespace {
+
+class SharedFormulaGroups
+{
+    struct Key
+    {
+        sal_Int32 mnId;
+        sal_Int32 mnCol;
+
+        Key(sal_Int32 nId, sal_Int32 nCol) : mnId(nId), mnCol(nCol) {}
+
+        bool operator== ( const Key& rOther ) const
+        {
+            return mnId == rOther.mnId && mnCol == rOther.mnCol;
+        }
+
+        bool operator!= ( const Key& rOther ) const
+        {
+            return !operator==(rOther);
+        }
+    };
+
+    struct KeyHash
+    {
+        size_t operator() ( const Key& rKey ) const
+        {
+            double nVal = rKey.mnId;
+            nVal *= 256.0;
+            nVal += rKey.mnCol;
+            return static_cast<size_t>(nVal);
+        }
+    };
+
+    typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
+    StoreType maStore;
+public:
+
+    void set( sal_Int32 nSharedId, sal_Int32 nCol, const ScFormulaCellGroupRef& xGroup )
+    {
+        Key aKey(nSharedId, nCol);
+        maStore.insert(StoreType::value_type(aKey, xGroup));
+    }
+
+    ScFormulaCellGroupRef get( sal_Int32 nSharedId, sal_Int32 nCol ) const
+    {
+        Key aKey(nSharedId, nCol);
+        StoreType::const_iterator it = maStore.find(aKey);
+        return it == maStore.end() ? ScFormulaCellGroupRef() : it->second;
+    }
+};
+
+}
+
+void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
+{
+    SheetToFormulaEntryMap::const_iterator itShared = sharedFormulas.find(nTab);
+    if (itShared == sharedFormulas.end())
+        // There is no shared formulas for this sheet.
+        return;
+
+    SheetToSharedFormulaid::const_iterator itCells = sharedFormulaIds.find(nTab);
+    if (itCells == sharedFormulaIds.end())
+        // There is no formula cells that use shared formulas for this sheet.
+        return;
+
+    const std::vector<SharedFormulaEntry>& rSharedFormulas = itShared->second;
+    const std::vector<SharedFormulaDesc>& rCells = itCells->second;
+
+    ScDocument& rDoc = getScDocument();
+
+    SharedFormulaGroups aGroups;
+    {
+        // Process shared formulas first.
+        std::vector<SharedFormulaEntry>::const_iterator it = rSharedFormulas.begin(), itEnd = rSharedFormulas.end();
+        for (; it != itEnd; ++it)
+        {
+            const table::CellAddress& rAddr = it->maAddress;
+            const table::CellRangeAddress& rRange = it->maRange;
+            sal_Int32 nId = it->mnSharedId;
+            const OUString& rTokenStr = it->maTokenStr;
+
+            ScAddress aPos;
+            ScUnoConversion::FillScAddress(aPos, rAddr);
+            ScCompiler aComp(&rDoc, aPos);
+            aComp.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
+            ScTokenArray* pArray = aComp.CompileString(rTokenStr);
+            if (pArray)
+            {
+                for (sal_Int32 nCol = rRange.StartColumn; nCol <= rRange.EndColumn; ++nCol)
+                {
+                    // Create one group per column, since Calc doesn't support
+                    // shared formulas across multiple columns.
+                    ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup);
+                    xNewGroup->mnStart = rRange.StartRow;
+                    xNewGroup->mnLength = rRange.EndRow - rRange.StartRow;
+                    xNewGroup->setCode(*pArray);
+                    aGroups.set(nId, nCol, xNewGroup);
+                }
+            }
+        }
+    }
+
+    {
+        // Process formulas that use shared formulas.
+        std::vector<SharedFormulaDesc>::const_iterator it = rCells.begin(), itEnd = rCells.end();
+        for (; it != itEnd; ++it)
+        {
+            const table::CellAddress& rAddr = it->maAddress;
+
+            ScFormulaCellGroupRef xGroup = aGroups.get(it->mnSharedId, rAddr.Column);
+            if (!xGroup)
+                continue;
+
+            ScAddress aPos;
+            ScUnoConversion::FillScAddress(aPos, rAddr);
+            ScFormulaCell* pCell = new ScFormulaCell(&rDoc, aPos, xGroup);
+
+            bool bInserted = rDoc.SetGroupFormulaCell(aPos, pCell);
+            if (!bInserted)
+            {
+                // Insertion failed.
+                delete pCell;
+                continue;
+            }
+
+            pCell->StartListeningTo(&rDoc);
+
+            if (it->maCellValue.isEmpty())
+            {
+                // No cached cell value. Mark it for re-calculation.
+                pCell->SetDirty(true);
+                continue;
+            }
+
+            // Set cached formula results. For now, we only use numeric
+            // results. Find out how to utilize cached results of other types.
+            switch (it->mnValueType)
+            {
+                case XML_n:
+                    // numeric value.
+                    pCell->SetResultDouble(it->maCellValue.toDouble());
+                break;
+                default:
+                    // Mark it for re-calculation.
+                    pCell->SetDirty(true);
+            }
+        }
+    }
+}
+
 // bound to need this somewhere else, if so probably need to move it to
 // worksheethelper or somewhere else more suitable
 void StartCellListening( sal_Int16 nSheet, sal_Int32 nRow, sal_Int32 nCol, ScDocument& rDoc )
@@ -193,10 +325,12 @@ void FormulaBuffer::applyArrayFormulas( const std::vector< TokenRangeAddressItem
     }
 }
 
-void FormulaBuffer::createSharedFormulaMapEntry( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens )
+void FormulaBuffer::createSharedFormulaMapEntry(
+    const table::CellAddress& rAddress, const table::CellRangeAddress& rRange,
+    sal_Int32 nSharedId, const OUString& rTokens )
 {
     std::vector<SharedFormulaEntry>& rSharedFormulas = sharedFormulas[ rAddress.Sheet ];
-    SharedFormulaEntry aEntry( rAddress, rTokens, nSharedId );
+    SharedFormulaEntry aEntry(rAddress, rRange, rTokens, nSharedId);
     rSharedFormulas.push_back( aEntry );
 }
 
@@ -205,9 +339,11 @@ void FormulaBuffer::setCellFormula( const ::com::sun::star::table::CellAddress&
     cellFormulas[ rAddress.Sheet ].push_back( TokenAddressItem( rTokenStr, rAddress ) );
 }
 
-void FormulaBuffer::setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId )
+void FormulaBuffer::setCellFormula(
+    const table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rCellValue, sal_Int32 nValueType )
 {
-    sharedFormulaIds[ rAddress.Sheet ].push_back( SharedFormulaDesc( rAddress, nSharedId ) );
+    sharedFormulaIds[rAddress.Sheet].push_back(
+        SharedFormulaDesc(rAddress, nSharedId, rCellValue, nValueType));
 }
 
 void FormulaBuffer::setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString& rTokenStr )
@@ -222,21 +358,6 @@ void FormulaBuffer::setCellFormulaValue( const ::com::sun::star::table::CellAddr
     cellFormulaValues[ rAddress.Sheet ].push_back( ValueAddressPair( rAddress, fValue ) );
 }
 
-void FormulaBuffer::createSharedFormula( const ::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const OUString& rTokenStr )
-{
-    ApiTokenSequence aTokens = getFormulaParser().importFormula( rAddress, rTokenStr );
-    OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
-        append( static_cast< sal_Int32 >( rAddress.Sheet + 1 ) ).
-        append( sal_Unicode( '_' ) ).append( nSharedId ).
-        append( OUString("_0") ).makeStringAndClear();
-    ScRangeData* pScRangeData  = createNamedRangeObject( aName, aTokens, 0  );
-
-    pScRangeData->SetType(RT_SHARED);
-    sal_Int32 nTokenIndex = static_cast< sal_Int32 >( pScRangeData->GetIndex() );
-
-        // store the token index in the map
-   tokenIndexes[  rAddress.Sheet ][ nSharedId ] = nTokenIndex;
-}
-} // namespace xls
-} // namespace oox
+}}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx
index e1efe16..24be4d7 100644
--- a/sc/source/filter/oox/sheetdatacontext.cxx
+++ b/sc/source/filter/oox/sheetdatacontext.cxx
@@ -157,7 +157,7 @@ void SheetDataContext::onCharacters( const OUString& rChars )
         case XLS_TOKEN( f ):
             if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID )
             {
-                  maFormulaStr = rChars;
+                maFormulaStr = rChars;
             }
         break;
     }
@@ -187,10 +187,9 @@ void SheetDataContext::onEndElement()
                 if( maFmlaData.mnSharedId >= 0 )
                 {
                     if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
-                    {
-                        createSharedFormulaMapEntry( maCellData.maCellAddr, maFmlaData.mnSharedId, maFormulaStr );
-                    }
-                    setCellFormula( maCellData.maCellAddr, maFmlaData.mnSharedId );
+                        createSharedFormulaMapEntry(maCellData.maCellAddr, maFmlaData.maFormulaRef, maFmlaData.mnSharedId, maFormulaStr);
+
+                    setCellFormula(maCellData.maCellAddr, maFmlaData.mnSharedId, maCellValue, maCellData.mnCellType);
                     mrSheetData.setCellFormat( maCellData );
                 }
                 else
diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx
index 37d5191..8802389 100644
--- a/sc/source/filter/oox/workbookhelper.cxx
+++ b/sc/source/filter/oox/workbookhelper.cxx
@@ -740,7 +740,7 @@ Reference< XSpreadsheetDocument > WorkbookHelper::getDocument() const
     return mrBookGlob.getDocument();
 }
 
-Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( sal_Int16 nSheet ) const
+Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( sal_Int32 nSheet ) const
 {
     Reference< XSpreadsheet > xSheet;
     try
diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx
index bd8b9ba..9fe9144 100644
--- a/sc/source/filter/oox/worksheethelper.cxx
+++ b/sc/source/filter/oox/worksheethelper.cxx
@@ -1602,9 +1602,11 @@ void WorksheetHelper::setCellFormula( const ::com::sun::star::table::CellAddress
     getFormulaBuffer().setCellFormula( rTokenAddress,  rTokenStr );
 }
 
-void WorksheetHelper::setCellFormula( const ::com::sun::star::table::CellAddress& rTokenAddress, sal_Int32 nSharedId )
+void WorksheetHelper::setCellFormula(
+    const ::com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
+    const OUString& rCellValue, sal_Int32 nValueType )
 {
-    getFormulaBuffer().setCellFormula( rTokenAddress,  nSharedId );
+    getFormulaBuffer().setCellFormula(rAddr, nSharedId, rCellValue, nValueType);
 }
 
 void WorksheetHelper::setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString& rTokenStr )
@@ -1612,9 +1614,10 @@ void WorksheetHelper::setCellArrayFormula( const ::com::sun::star::table::CellRa
     getFormulaBuffer().setCellArrayFormula( rRangeAddress,  rTokenAddress, rTokenStr );
 }
 
-void WorksheetHelper::createSharedFormulaMapEntry(  const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens )
+void WorksheetHelper::createSharedFormulaMapEntry(
+    const table::CellAddress& rAddress, const table::CellRangeAddress& rRange, sal_Int32 nSharedId, const OUString& rTokens )
 {
-    getFormulaBuffer().createSharedFormulaMapEntry( rAddress, nSharedId, rTokens );
+    getFormulaBuffer().createSharedFormulaMapEntry(rAddress, rRange, nSharedId, rTokens);
 }
 
 // ============================================================================
commit 33138d03847abf30fb18bd8596e41faa35e08fc6
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Aug 6 15:40:43 2013 -0400

    Const correctness at ScFormulaCell side.
    
    Though I had to use const_cast in some places...
    
    Change-Id: I22830bf291179efafc1b400f33a520072b7fab0f

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 3d70200..0d258a0 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -248,7 +248,8 @@ public:
     sal_uInt16      GetRawError();  // don't interpret, just return code or result error
     bool GetErrorOrValue( sal_uInt16& rErr, double& rVal );
     sal_uInt8       GetMatrixFlag() const;
-    ScTokenArray*   GetCode() const;
+    ScTokenArray* GetCode();
+    const ScTokenArray* GetCode() const;
 
     bool            IsRunning() const;
     void            SetRunning( bool bVal );
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 25af317..c4276d9 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -978,7 +978,7 @@ void lcl_AddCode( ScTokenArray& rArr, const ScFormulaCell* pCell )
 {
     rArr.AddOpCode(ocOpen);
 
-    ScTokenArray* pCode = pCell->GetCode();
+    ScTokenArray* pCode = const_cast<ScFormulaCell*>(pCell)->GetCode();
     if (pCode)
     {
         const formula::FormulaToken* pToken = pCode->First();
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 485d45c..c3ab5cd 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2987,10 +2987,30 @@ void ScFormulaCell::SetChanged(bool b)
     bChanged = b;
 }
 
-sal_uInt8       ScFormulaCell::GetMatrixFlag() const                   { return cMatrixFlag; }
-ScTokenArray*   ScFormulaCell::GetCode() const                         { return pCode; }
-bool            ScFormulaCell::IsRunning() const                       { return bRunning; }
-void            ScFormulaCell::SetRunning( bool bVal )                 { bRunning = bVal; }
+sal_uInt8 ScFormulaCell::GetMatrixFlag() const
+{
+    return cMatrixFlag;
+}
+
+ScTokenArray* ScFormulaCell::GetCode()
+{
+    return pCode;
+}
+
+const ScTokenArray* ScFormulaCell::GetCode() const
+{
+    return pCode;
+}
+
+bool ScFormulaCell::IsRunning() const
+{
+    return bRunning;
+}
+
+void ScFormulaCell::SetRunning( bool bVal )
+{
+    bRunning = bVal;
+}
 
 void ScFormulaCell::CompileDBFormula()
 {
diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index de764b2..c90719a 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -845,10 +845,11 @@ OUString XclXmlUtils::ToOUString( const String& s )
     return OUString( s.GetBuffer(), s.Len() );
 }
 
-OUString XclXmlUtils::ToOUString( ScDocument& rDocument, const ScAddress& rAddress,
-        ScTokenArray* pTokenArray, const FormulaCompiler::OpCodeMapPtr & xOpCodeMap )
+OUString XclXmlUtils::ToOUString(
+    ScDocument& rDocument, const ScAddress& rAddress, const ScTokenArray* pTokenArray,
+    const FormulaCompiler::OpCodeMapPtr & xOpCodeMap )
 {
-    ScCompiler aCompiler( &rDocument, rAddress, *pTokenArray);
+    ScCompiler aCompiler( &rDocument, rAddress, const_cast<ScTokenArray&>(*pTokenArray));
     if (xOpCodeMap)
     {
         aCompiler.SetFormulaLanguage( xOpCodeMap );
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index 4b37a68..ba759ae 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -288,7 +288,7 @@ public:
     static OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 );
     static OUString ToOUString( const String& s );
     static OUString ToOUString( ScDocument& rDocument, const ScAddress& rAddress,
-                                       ScTokenArray* pTokenArray, const ScCompiler::OpCodeMapPtr & xOpCodeMap );
+                                const ScTokenArray* pTokenArray, const ScCompiler::OpCodeMapPtr & xOpCodeMap );
     static OUString ToOUString( const XclExpString& s );
     static const char* ToPsz( bool b );
 
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 51a9b8d..528cc9e 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -5176,7 +5176,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens() thr
         {
             if (aStart1 == aStart2)
             {
-                ScTokenArray* pTokenArray = pFCell1->GetCode();
+                const ScTokenArray* pTokenArray = pFCell1->GetCode();
                 if (pTokenArray)
                     (void)ScTokenConversion::ConvertToTokenSequence(*pDoc, aSequence, *pTokenArray);
             }
commit e0f50396decbc9d4e402b50e5421aef7f6a36ab0
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Aug 6 21:25:50 2013 -0400

    Some cosmetic "fix"
    
    Change-Id: I80baff3b1794619659e505622164e2582e762248

diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx
index 984f9c8..1e98060 100644
--- a/sc/source/filter/inc/formulabuffer.hxx
+++ b/sc/source/filter/inc/formulabuffer.hxx
@@ -25,49 +25,46 @@
 #include "sheetdatabuffer.hxx"
 #include <com/sun/star/sheet/XFormulaTokens.hpp>
 
-namespace oox {
-namespace xls {
+namespace oox { namespace xls {
 
 class FormulaBuffer : public WorkbookHelper
 {
-private:
-struct SharedFormulaEntry
-{
-    ::com::sun::star::table::CellAddress maAddress;
-    OUString maTokenStr;
-    sal_Int32 mnSharedId;
-    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens > mxFormulaTokens;
-    SharedFormulaEntry( const ::com::sun::star::table::CellAddress& rAddress, const OUString& rTokenStr, sal_Int32 nSharedId ) : maAddress( rAddress ), maTokenStr( rTokenStr ), mnSharedId( nSharedId ) {}
-};
-
+    struct SharedFormulaEntry
+    {
+        ::com::sun::star::table::CellAddress maAddress;
+        OUString maTokenStr;
+        sal_Int32 mnSharedId;
+        ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens > mxFormulaTokens;
+        SharedFormulaEntry( const ::com::sun::star::table::CellAddress& rAddress, const OUString& rTokenStr, sal_Int32 nSharedId ) : maAddress( rAddress ), maTokenStr( rTokenStr ), mnSharedId( nSharedId ) {}
+    };
 
-struct TokenAddressItem
-{
-    OUString maTokenStr;
-    ::com::sun::star::table::CellAddress maCellAddress;
-    TokenAddressItem( const OUString& rTokenStr, const ::com::sun::star::table::CellAddress& rCellAddress ) : maTokenStr( rTokenStr ), maCellAddress( rCellAddress ) {}
-};
+    struct TokenAddressItem
+    {
+        OUString maTokenStr;
+        ::com::sun::star::table::CellAddress maCellAddress;
+        TokenAddressItem( const OUString& rTokenStr, const ::com::sun::star::table::CellAddress& rCellAddress ) : maTokenStr( rTokenStr ), maCellAddress( rCellAddress ) {}
+    };
 
-struct TokenRangeAddressItem
-{
-    TokenAddressItem maTokenAndAddress;
-    ::com::sun::star::table::CellRangeAddress maCellRangeAddress;
-    TokenRangeAddressItem( const TokenAddressItem& rTokenAndAddress, const ::com::sun::star::table::CellRangeAddress& rCellRangeAddress ) : maTokenAndAddress( rTokenAndAddress ), maCellRangeAddress( rCellRangeAddress ) {}
-};
+    struct TokenRangeAddressItem
+    {
+        TokenAddressItem maTokenAndAddress;
+        ::com::sun::star::table::CellRangeAddress maCellRangeAddress;
+        TokenRangeAddressItem( const TokenAddressItem& rTokenAndAddress, const ::com::sun::star::table::CellRangeAddress& rCellRangeAddress ) : maTokenAndAddress( rTokenAndAddress ), maCellRangeAddress( rCellRangeAddress ) {}
+    };
 
-typedef ::std::map< sal_Int32, std::vector< TokenAddressItem > > FormulaDataMap;
-typedef ::std::map< sal_Int32, std::vector< TokenRangeAddressItem > > ArrayFormulaDataMap;
-// shared formuala descriptions, the id and address the formula is at
-typedef std::pair< ::com::sun::star::table::CellAddress, sal_Int32 > SharedFormulaDesc;
-// sheet -> list of shared formula descriptions
-typedef ::std::map< sal_Int32, std::vector< SharedFormulaDesc > > SheetToSharedFormulaid;
-// sheet -> stuff needed to create shared formulae
-typedef ::std::map< sal_Int32, std::vector< SharedFormulaEntry > >  SheetToFormulaEntryMap;
-// sharedId -> tokedId
-typedef ::std::map< sal_Int32, sal_Int32 > SharedIdToTokenIndex;
-typedef ::std::map< sal_Int32, SharedIdToTokenIndex > SheetToSharedIdToTokenIndex;
-typedef ::std::pair< ::com::sun::star::table::CellAddress, double > ValueAddressPair;
-typedef ::std::map< sal_Int32, std::vector< ValueAddressPair > > FormulaValueMap;
+    typedef ::std::map< sal_Int32, std::vector< TokenAddressItem > > FormulaDataMap;
+    typedef ::std::map< sal_Int32, std::vector< TokenRangeAddressItem > > ArrayFormulaDataMap;
+    // shared formuala descriptions, the id and address the formula is at
+    typedef std::pair< ::com::sun::star::table::CellAddress, sal_Int32 > SharedFormulaDesc;
+    // sheet -> list of shared formula descriptions
+    typedef ::std::map< sal_Int32, std::vector< SharedFormulaDesc > > SheetToSharedFormulaid;
+    // sheet -> stuff needed to create shared formulae
+    typedef ::std::map< sal_Int32, std::vector< SharedFormulaEntry > >  SheetToFormulaEntryMap;
+    // sharedId -> tokedId
+    typedef ::std::map< sal_Int32, sal_Int32 > SharedIdToTokenIndex;
+    typedef ::std::map< sal_Int32, SharedIdToTokenIndex > SheetToSharedIdToTokenIndex;
+    typedef ::std::pair< ::com::sun::star::table::CellAddress, double > ValueAddressPair;
+    typedef ::std::map< sal_Int32, std::vector< ValueAddressPair > > FormulaValueMap;
 
     void createSharedFormula(  const ::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const OUString& rTokens );
     ::com::sun::star::uno::Reference< com::sun::star::table::XCellRange > getRange( const ::com::sun::star::table::CellRangeAddress& rRange);
@@ -93,7 +90,9 @@ public:
     void                setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString&  );
     void                createSharedFormulaMapEntry( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens );
 };
-}
-}
+
+}}
+
 #endif
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 0c44329..3889b53 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -222,7 +222,7 @@ void FormulaBuffer::setCellFormulaValue( const ::com::sun::star::table::CellAddr
     cellFormulaValues[ rAddress.Sheet ].push_back( ValueAddressPair( rAddress, fValue ) );
 }
 
-void  FormulaBuffer::createSharedFormula( const ::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const OUString& rTokenStr )
+void FormulaBuffer::createSharedFormula( const ::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const OUString& rTokenStr )
 {
     ApiTokenSequence aTokens = getFormulaParser().importFormula( rAddress, rTokenStr );
     OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
commit 48d4b334e73ad8a61077e8e3f838ccf090602299
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Aug 6 19:03:47 2013 -0400

    Handle shared token array correctly when adjusting formula grouping.
    
    Change-Id: Ib4b141f415b36565106e946ccbc47f2b9f80d89c

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index f857aff..3d70200 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -314,6 +314,10 @@ public:
 
     void            MaybeInterpret();
 
+    /**
+     * Turn a non-grouped cell into the top of a grouped cell.
+     */
+    ScFormulaCellGroupRef CreateCellGroup( SCROW nStart, SCROW nLen, bool bInvariant );
     ScFormulaCellGroupRef GetCellGroup();
     void SetCellGroup( const ScFormulaCellGroupRef &xRef );
 
@@ -333,6 +337,8 @@ public:
     bool IsSharedInvariant() const;
     SCROW GetSharedTopRow() const;
     SCROW GetSharedLength() const;
+    ScTokenArray* GetSharedCode();
+    const ScTokenArray* GetSharedCode() const;
 };
 
 #endif
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 866c22f..232c4bc 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -46,11 +46,7 @@ public:
             }
 
             // Create a new group.
-            xGroup.reset(new ScFormulaCellGroup);
-            xGroup->mnStart = pPrev->aPos.Row();
-            xGroup->mnLength = 2;
-            xGroup->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
-            pPrev->SetCellGroup(xGroup);
+            xGroup = pPrev->CreateCellGroup(pPrev->aPos.Row(), 2, eState == ScFormulaCell::EqualInvariant);
             pCur->SetCellGroup(xGroup);
         }
     }
diff --git a/sc/qa/unit/ucalc_sharedformula.cxx b/sc/qa/unit/ucalc_sharedformula.cxx
index 7934483..1eba457 100644
--- a/sc/qa/unit/ucalc_sharedformula.cxx
+++ b/sc/qa/unit/ucalc_sharedformula.cxx
@@ -32,6 +32,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     aPos.SetRow(8); // B9
     m_pDoc->SetString(aPos, "=A9*2");
@@ -39,6 +40,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     aPos.SetRow(12); // B13
     m_pDoc->SetString(aPos, "=A13*2");
@@ -52,6 +54,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Insert formulas to B15:B16.
     aPos.SetRow(14); // B15
@@ -62,6 +65,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(14), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Insert a formula to B14, and B9:B16 should be shared.
     aPos.SetRow(13); // B14
@@ -70,6 +74,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Insert an incompatible formula to B12, to split the shared range to B9:B11 and B13:B16.
     aPos.SetRow(11); // B12
@@ -82,12 +87,14 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     aPos.SetRow(12); // B13
     pFC = m_pDoc->GetFormulaCell(aPos);
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Extend B13:B16 to B13:B20.
     aPos.SetRow(16); // B17
@@ -103,6 +110,7 @@ void Test::testSharedFormulas()
     // B13:B20 shuld be shared.
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Empty B19. This should split it into B13:B18, and B20 non-shared.
     aPos.SetRow(18);
@@ -113,6 +121,7 @@ void Test::testSharedFormulas()
     // B13:B18 should be shared.
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
     // B20 shold be non-shared.
     aPos.SetRow(19); // B20
     pFC = m_pDoc->GetFormulaCell(aPos);
@@ -132,6 +141,7 @@ void Test::testSharedFormulas()
     pFC = m_pDoc->GetFormulaCell(aPos);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(14), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Set numeric value to B15, to make B16:B18 shared.
     aPos.SetRow(14);
@@ -141,6 +151,7 @@ void Test::testSharedFormulas()
     // B16:B18 should be shared.
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(15), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Set string value to B16 to make B17:B18 shared.
     aPos.SetRow(15);
@@ -153,6 +164,7 @@ void Test::testSharedFormulas()
     // B17:B18 should be shared.
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(16), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Set edit text to B17. Now B18 should be non-shared.
     ScFieldEditEngine& rEditEngine = m_pDoc->GetEditEngine();
@@ -191,6 +203,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("B10 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Delete A4:B8. This should splite the grouping to B2:B3 and B9:B10.
     clearRange(m_pDoc, ScRange(0,3,0,1,7,0));
@@ -199,12 +212,14 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     aPos.SetRow(8);
     pFC = m_pDoc->GetFormulaCell(aPos);
     CPPUNIT_ASSERT_MESSAGE("B9 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Delete rows 4:8 and shift row 9 and below up to row 4.  This should
     // re-merge the two into a group of B2:B5.
@@ -214,6 +229,7 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Insert 2 rows at row 4, to split it into B2:B3 and B6:B7.
     m_pDoc->InsertRow(ScRange(0,3,0,MAXCOL,4,0));
@@ -221,12 +237,14 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     aPos.SetRow(5);
     pFC = m_pDoc->GetFormulaCell(aPos);
     CPPUNIT_ASSERT_MESSAGE("B6 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     m_pDoc->DeleteTab(0);
 }
@@ -245,6 +263,7 @@ void Test::testSharedFormulasCopyPaste()
     CPPUNIT_ASSERT_MESSAGE("B9 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Copy formulas in B6:B9 to the clipboard doc.
     ScRange aSrcRange(1,5,0,1,8,0); // B6:B9
@@ -254,6 +273,7 @@ void Test::testSharedFormulasCopyPaste()
     CPPUNIT_ASSERT_MESSAGE("B9 in the clip doc should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     // Paste them to C2:C10.
     ScRange aDestRange(2,1,0,2,9,0);
@@ -266,6 +286,7 @@ void Test::testSharedFormulasCopyPaste()
     CPPUNIT_ASSERT_MESSAGE("C2 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
 
     ScRange aRange(1,0,0,1,9,0); // B1:B10
     ScDocument* pUndoDoc = new ScDocument(SCDOCMODE_UNDO);
@@ -282,6 +303,7 @@ void Test::testSharedFormulasCopyPaste()
         CPPUNIT_ASSERT_MESSAGE("Must be a formula cell.", pFC);
         CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
         CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
+        CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
     }
 
     // Overwrite B1:B10.
@@ -302,6 +324,7 @@ void Test::testSharedFormulasCopyPaste()
         CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC);
         CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
         CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
+        CPPUNIT_ASSERT_MESSAGE("The token is expected to be shared.", pFC->GetCode() == pFC->GetSharedCode());
     }
 
     m_pDoc->DeleteTab(0);
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 66343a7..0171fab 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1287,11 +1287,7 @@ class CopyToClipHandler
             }
 
             // Create a new group.
-            xGroup.reset(new ScFormulaCellGroup);
-            xGroup->mnStart = pPrev->aPos.Row();
-            xGroup->mnLength = 2;
-            xGroup->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
-            pPrev->SetCellGroup(xGroup);
+            xGroup = pPrev->CreateCellGroup(pPrev->aPos.Row(), 2, eState == ScFormulaCell::EqualInvariant);
             pCur->SetCellGroup(xGroup);
         }
     }
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 461193c..25af317 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -2677,13 +2677,8 @@ public:
             if (!xGroup)
             {
                 // create a new group ...
-                xGroup.reset(new ScFormulaCellGroup);
-                xGroup->mnStart = nRow - 1;
-                xGroup->mbInvariant = (eCompState == ScFormulaCell::EqualInvariant);
-                xGroup->mnLength = 2;
-
+                xGroup = pPrev->CreateCellGroup(nRow - 1, 2, eCompState == ScFormulaCell::EqualInvariant);
                 pCur->SetCellGroup(xGroup);
-                pPrev->SetCellGroup(xGroup);
             }
             else
             {
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index b9db55a..485d45c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3129,6 +3129,20 @@ ScFormulaCell*  ScFormulaCell::GetNextTrack() const                    { return
 void            ScFormulaCell::SetPreviousTrack( ScFormulaCell* pF )   { pPreviousTrack = pF; }
 void            ScFormulaCell::SetNextTrack( ScFormulaCell* pF )       { pNextTrack = pF; }
 
+ScFormulaCellGroupRef ScFormulaCell::CreateCellGroup( SCROW nStart, SCROW nLen, bool bInvariant )
+{
+    if (mxGroup)
+        // You can't create a new group if the cell is already a part of a group.
+        return ScFormulaCellGroupRef();
+
+    mxGroup.reset(new ScFormulaCellGroup);
+    mxGroup->mnStart = nStart;
+    mxGroup->mbInvariant = bInvariant;
+    mxGroup->mnLength = nLen;
+    mxGroup->mpCode = pCode; // Move this to the shared location.
+    return mxGroup;
+}
+
 ScFormulaCellGroupRef ScFormulaCell::GetCellGroup()
 {
     return mxGroup;
@@ -3136,7 +3150,23 @@ ScFormulaCellGroupRef ScFormulaCell::GetCellGroup()
 
 void ScFormulaCell::SetCellGroup( const ScFormulaCellGroupRef &xRef )
 {
+    if (!xRef)
+    {
+        // Make this cell a non-grouped cell.
+        if (mxGroup)
+            pCode = mxGroup->mpCode->Clone();
+
+        mxGroup = xRef;
+        return;
+    }
+
+    // Group object has shared token array.
+    if (!mxGroup)
+        // Currently not shared. Delete the existing token array first.
+        delete pCode;
+
     mxGroup = xRef;
+    pCode = mxGroup->mpCode;
 }
 
 ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell& rOther ) const
@@ -3711,9 +3741,20 @@ SCROW ScFormulaCell::GetSharedTopRow() const
 {
     return mxGroup ? mxGroup->mnStart : -1;
 }
+
 SCROW ScFormulaCell::GetSharedLength() const
 {
     return mxGroup ? mxGroup->mnLength : 0;
 }
 
+ScTokenArray* ScFormulaCell::GetSharedCode()
+{
+    return mxGroup ? mxGroup->mpCode : NULL;
+}
+
+const ScTokenArray* ScFormulaCell::GetSharedCode() const
+{
+    return mxGroup ? mxGroup->mpCode : NULL;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index 2ea5cf8..3e77934 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -9,6 +9,7 @@
 
 #include "sharedformula.hxx"
 #include "calcmacros.hxx"
+#include "tokenarray.hxx"
 
 namespace sc {
 
@@ -41,6 +42,7 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
     xGroup2->mbInvariant = xGroup->mbInvariant;
     xGroup2->mnStart = nRow;
     xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow;
+    xGroup2->mpCode = xGroup->mpCode->Clone();
 
     xGroup->mnLength = nRow - xGroup->mnStart;
 
@@ -110,12 +112,7 @@ void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPo
         else
         {
             // neither cells are shared.
-            xGroup1.reset(new ScFormulaCellGroup);
-            xGroup1->mnStart = nRow;
-            xGroup1->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
-            xGroup1->mnLength = 2;
-
-            rCell1.SetCellGroup(xGroup1);
+            xGroup1 = rCell1.CreateCellGroup(nRow, 2, eState == ScFormulaCell::EqualInvariant);
             rCell2.SetCellGroup(xGroup1);
         }
     }
@@ -226,6 +223,7 @@ void SharedFormulaUtil::unshareFormulaCell(const CellStoreType::position_type& a
             xGroup2->mnStart = rCell.aPos.Row() + 1;
             xGroup2->mnLength = nLength2;
             xGroup2->mbInvariant = xGroup->mbInvariant;
+            xGroup2->mpCode = xGroup->mpCode->Clone();
 #if DEBUG_COLUMN_STORAGE
             if (xGroup2->mnStart + xGroup2->mnLength > it->position + it->size)
             {
commit 1078756b9df5a1d0065c7f6c4b52ce451b0f6698
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Aug 6 00:15:10 2013 -0400

    Map shared formula from xls to formula groups, and share the tokens as well.
    
    No more mapping to range names.
    
    Change-Id: Ic43b6ef35a91fe4d6fff748ebc22969ba4e036db

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 045b76a..22bb9bd 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -275,6 +275,7 @@ public:
      */
     ScFormulaCell* SetFormulaCell( SCROW nRow, ScFormulaCell* pCell );
     ScFormulaCell* SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell );
+    bool SetGroupFormulaCell( SCROW nRow, ScFormulaCell* pCell );
 
     void SetRawString( SCROW nRow, const OUString& rStr, bool bBroadcast = true );
     void SetRawString( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const OUString& rStr, bool bBroadcast = true );
@@ -507,8 +508,8 @@ private:
 
     sc::CellStoreType::iterator GetPositionToInsert( SCROW nRow );
     sc::CellStoreType::iterator GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow );
-    void ActivateNewFormulaCell( const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell );
-    void ActivateNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell );
+    void ActivateNewFormulaCell( const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin = true );
+    void ActivateNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin = true );
     void BroadcastNewCell( SCROW nRow );
     bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow );
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 90e0148..8b82fb7 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -804,6 +804,7 @@ public:
      *         is deleted automatically on failure to insert.
      */
     SC_DLLPUBLIC ScFormulaCell* SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell );
+    SC_DLLPUBLIC bool SetGroupFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell );
 
     SC_DLLPUBLIC void InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
                                         SCCOL nCol2, SCROW nRow2,
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 6480056..f857aff 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -27,6 +27,7 @@
 #include "types.hxx"
 
 #include <set>
+#include <boost/noncopyable.hpp>
 
 namespace sc {
 
@@ -43,7 +44,7 @@ class ScProgress;
 class ScTokenArray;
 struct ScSimilarFormulaDelta;
 
-struct SC_DLLPUBLIC ScFormulaCellGroup
+struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable
 {
     mutable size_t mnRefCount;
 
@@ -55,6 +56,8 @@ struct SC_DLLPUBLIC ScFormulaCellGroup
 
     ScFormulaCellGroup();
     ~ScFormulaCellGroup();
+
+    void setCode( const ScTokenArray& rCode );
 };
 
 inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 37c1430..a95f2bc 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -340,6 +340,7 @@ public:
      *         is deleted automatically on failure to insert.
      */
     ScFormulaCell* SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell );
+    bool SetGroupFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell );
 
     void        SetValue( SCCOL nCol, SCROW nRow, const double& rVal );
     void        SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError);
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index f9a4ff1..09a9798 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -62,6 +62,12 @@ public:
 
     ScFormulaVectorState GetVectorState() const;
 
+    /**
+     * If the array contains at least one relative row reference or named
+     * expression, it's variant. Otherwise invariant.
+     */
+    bool IsInvariant() const;
+
     /// Exactly and only one range (valid or deleted)
     bool IsReference( ScRange& rRange, const ScAddress& rPos ) const;
     /// Exactly and only one valid range (no #REF!s)
diff --git a/sc/qa/unit/data/xls/shared-formula.xls b/sc/qa/unit/data/xls/shared-formula.xls
index a9be6b7..f27acb4 100644
Binary files a/sc/qa/unit/data/xls/shared-formula.xls and b/sc/qa/unit/data/xls/shared-formula.xls differ
diff --git a/sc/qa/unit/filters-test.cxx b/sc/qa/unit/filters-test.cxx
index 1d7eeca..957e0e0 100644
--- a/sc/qa/unit/filters-test.cxx
+++ b/sc/qa/unit/filters-test.cxx
@@ -32,6 +32,8 @@
 #include "cellform.hxx"
 #include "drwlayer.hxx"
 #include "userdat.hxx"
+#include "formulacell.hxx"
+
 #include <svx/svdpage.hxx>
 
 using namespace ::com::sun::star;
@@ -344,6 +346,13 @@ void ScFiltersTest::testSharedFormulaXLS()
         double fCheck = i*10.0;
         CPPUNIT_ASSERT_EQUAL(fCheck, fVal);
     }
+
+    ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1,18,0));
+    CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pCell);
+    ScFormulaCellGroupRef xGroup = pCell->GetCellGroup();
+    CPPUNIT_ASSERT_MESSAGE("This cell should be a part of a cell group.", xGroup);
+    CPPUNIT_ASSERT_MESSAGE("Incorrect group geometry.", xGroup->mnStart == 2 && xGroup->mnLength == 17);
+
     xDocSh->DoClose();
 }
 
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 4474aec..461193c 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -381,16 +381,17 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreTy
 }
 
 void ScColumn::ActivateNewFormulaCell(
-    const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell )
+    const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin )
 {
-    ActivateNewFormulaCell(maCells.position(itPos, nRow), rCell);
+    ActivateNewFormulaCell(maCells.position(itPos, nRow), rCell, bJoin);
 }
 
 void ScColumn::ActivateNewFormulaCell(
-    const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell )
+    const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin )
 {
-    // See if this new formula cell can join an existing shared formula group.
-    JoinNewFormulaCell(aPos, rCell);
+    if (bJoin)
+        // See if this new formula cell can join an existing shared formula group.
+        JoinNewFormulaCell(aPos, rCell);
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list