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

Eike Rathke erack at redhat.com
Fri Mar 18 09:38:12 UTC 2016


 formula/source/core/api/token.cxx    |   16 ++--
 include/formula/token.hxx            |   16 ++--
 sc/inc/address.hxx                   |   10 ++
 sc/inc/compiler.hxx                  |    7 +
 sc/inc/document.hxx                  |    9 ++
 sc/inc/token.hxx                     |    2 
 sc/inc/tokenarray.hxx                |    2 
 sc/source/core/data/conditio.cxx     |    2 
 sc/source/core/data/documen3.cxx     |    6 +
 sc/source/core/data/formulacell.cxx  |   48 +++++++++----
 sc/source/core/data/validat.cxx      |    2 
 sc/source/core/tool/address.cxx      |   91 +++++++++++++++++--------
 sc/source/core/tool/compiler.cxx     |   79 +++++++++++++++------
 sc/source/core/tool/token.cxx        |  127 ++++++++++++++++++++++++++++-------
 sc/source/filter/excel/excform.cxx   |    4 -
 sc/source/filter/excel/excform8.cxx  |    4 -
 sc/source/filter/excel/tokstack.cxx  |    8 +-
 sc/source/filter/excel/xeformula.cxx |    6 -
 sc/source/filter/inc/tokstack.hxx    |    4 -
 sc/source/ui/unoobj/tokenuno.cxx     |    3 
 20 files changed, 321 insertions(+), 125 deletions(-)

New commits:
commit 64e542413851236c75e25185c137d6fd6ddfe3a1
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Mar 17 23:18:06 2016 +0100

    Resolves: tdf#96915 implement other-sheet-local named expressions
    
    Change-Id: I0d62536caa6eb455473a755067abc585662cd9a5

diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 22d3c84..7009d94 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -221,15 +221,15 @@ void FormulaToken::SetIndex( sal_uInt16 )
     SAL_WARN( "formula.core", "FormulaToken::SetIndex: virtual dummy called" );
 }
 
-bool FormulaToken::IsGlobal() const
+sal_Int16 FormulaToken::GetSheet() const
 {
-    SAL_WARN( "formula.core", "FormulaToken::IsGlobal: virtual dummy called" );
-    return true;
+    SAL_WARN( "formula.core", "FormulaToken::GetSheet: virtual dummy called" );
+    return -1;
 }
 
-void FormulaToken::SetGlobal( bool )
+void FormulaToken::SetSheet( sal_Int16 )
 {
-    SAL_WARN( "formula.core", "FormulaToken::SetGlobal: virtual dummy called" );
+    SAL_WARN( "formula.core", "FormulaToken::SetSheet: virtual dummy called" );
 }
 
 short* FormulaToken::GetJump() const
@@ -1724,12 +1724,12 @@ bool FormulaStringOpToken::operator==( const FormulaToken& r ) const
 
 sal_uInt16  FormulaIndexToken::GetIndex() const             { return nIndex; }
 void        FormulaIndexToken::SetIndex( sal_uInt16 n )     { nIndex = n; }
-bool        FormulaIndexToken::IsGlobal() const             { return mbGlobal; }
-void        FormulaIndexToken::SetGlobal( bool b )          { mbGlobal = b; }
+sal_Int16   FormulaIndexToken::GetSheet() const             { return mnSheet; }
+void        FormulaIndexToken::SetSheet( sal_Int16 n )      { mnSheet = n; }
 bool FormulaIndexToken::operator==( const FormulaToken& r ) const
 {
     return FormulaToken::operator==( r ) && nIndex == r.GetIndex() &&
-        mbGlobal == r.IsGlobal();
+        mnSheet == r.GetSheet();
 }
 const OUString& FormulaExternalToken::GetExternal() const       { return aExternal; }
 sal_uInt8       FormulaExternalToken::GetByte() const           { return nByte; }
diff --git a/include/formula/token.hxx b/include/formula/token.hxx
index 618168e..e0cd6b7 100644
--- a/include/formula/token.hxx
+++ b/include/formula/token.hxx
@@ -154,8 +154,8 @@ public:
     virtual void                SetString( const svl::SharedString& rStr );
     virtual sal_uInt16          GetIndex() const;
     virtual void                SetIndex( sal_uInt16 n );
-    virtual bool                IsGlobal() const;
-    virtual void                SetGlobal( bool b );
+    virtual sal_Int16           GetSheet() const;
+    virtual void                SetSheet( sal_Int16 n );
     virtual short*              GetJump() const;
     virtual const OUString&     GetExternal() const;
     virtual FormulaToken*       GetFAPOrigToken() const;
@@ -310,18 +310,18 @@ class FORMULA_DLLPUBLIC FormulaIndexToken : public FormulaToken
 {
 private:
             sal_uInt16          nIndex;
-            bool                mbGlobal;
+            sal_Int16           mnSheet;
 public:
-                                FormulaIndexToken( OpCode e, sal_uInt16 n, bool bGlobal = true ) :
-                                    FormulaToken(  svIndex, e ), nIndex( n ), mbGlobal( bGlobal ) {}
+                                FormulaIndexToken( OpCode e, sal_uInt16 n, sal_Int16 nSheet = -1 ) :
+                                    FormulaToken(  svIndex, e ), nIndex( n ), mnSheet( nSheet ) {}
                                 FormulaIndexToken( const FormulaIndexToken& r ) :
-                                    FormulaToken( r ), nIndex( r.nIndex ), mbGlobal( r.mbGlobal ) {}
+                                    FormulaToken( r ), nIndex( r.nIndex ), mnSheet( r.mnSheet ) {}
 
     virtual FormulaToken*       Clone() const override { return new FormulaIndexToken(*this); }
     virtual sal_uInt16          GetIndex() const override;
     virtual void                SetIndex( sal_uInt16 n ) override;
-    virtual bool                IsGlobal() const override;
-    virtual void                SetGlobal( bool b ) override;
+    virtual sal_Int16           GetSheet() const override;
+    virtual void                SetSheet( sal_Int16 n ) override;
     virtual bool                operator==( const FormulaToken& rToken ) const override;
 };
 
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index a917de7..218f346 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -308,11 +308,19 @@ public:
         nTabP = nTab;
     }
 
+    /**
+        @param  pSheetEndPos
+                If given and Parse() sucessfully parsed a sheet name it returns
+                the end position (exclusive) behind the sheet name AND a
+                following sheet name separator. This independent of whether the
+                resulting reference is fully valid or not.
+     */
     SC_DLLPUBLIC ScRefFlags Parse(
                     const OUString&, ScDocument* = nullptr,
                     const Details& rDetails = detailsOOOa1,
                     ExternalInfo* pExtInfo = nullptr,
-                    const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr );
+                    const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
+                    sal_Int32* pSheetEndPos = nullptr );
 
     SC_DLLPUBLIC void Format( OStringBuffer& r, ScRefFlags nFlags = ScRefFlags::ZERO,
                                   const ScDocument* pDocument = nullptr,
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 2af43e4..e1887aa 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -120,7 +120,7 @@ public:
             sal_Unicode cName[MAXSTRLEN+1];
         } extname;
         struct {
-            bool        bGlobal;
+            sal_Int16   nSheet;
             sal_uInt16  nIndex;
         } name;
         struct {
@@ -157,7 +157,7 @@ public:
     void SetErrorConstant( sal_uInt16 nErr );
 
     // These methods are ok to use, reference count not cleared.
-    void SetName(bool bGlobal, sal_uInt16 nIndex);
+    void SetName(sal_Int16 nSheet, sal_uInt16 nIndex);
     void SetExternalSingleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
     void SetExternalDoubleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef );
     void SetExternalName( sal_uInt16 nFileId, const OUString& rName );
@@ -272,6 +272,9 @@ private:
 
     SvNumberFormatter* mpFormatter;
 
+    SCTAB       mnCurrentSheetTab;      // indicates current sheet number parsed so far
+    sal_Int32   mnCurrentSheetEndPos;   // position after current sheet name if parsed
+
     // For CONV_XL_OOX, may be set via API by MOOXML filter.
     css::uno::Sequence<css::sheet::ExternalLinkInfo> maExternalLinks;
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 7da2b4d..825e511 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -535,6 +535,15 @@ public:
     void SetRangeName(SCTAB nTab, ScRangeName* pNew);
     void SetRangeName( ScRangeName* pNewRangeName );
 
+    /** Find a named expression / range name in either global or a local scope.
+        @param  nIndex
+                Index of named expression / range name.
+        @param  nTab
+                If <0 search nIndex in global scope, if >=0 search nIndex in scope of nTab.
+        @return nullptr if indexed name not found.
+     */
+    ScRangeData* FindRangeNameByIndexAndSheet( sal_uInt16 nIndex, SCTAB nTab ) const;
+
     /**
      * Call this immediately before updating all named ranges.
      */
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index 63c5ec7..b056d41 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -231,7 +231,7 @@ public:
 
     virtual sal_uInt16          GetIndex() const override;
     virtual void                SetIndex( sal_uInt16 n ) override;
-    virtual bool                IsGlobal() const override;
+    virtual sal_Int16           GetSheet() const override;
     virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
     virtual FormulaToken*       Clone() const override { return new ScTableRefToken(*this); }
 
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 26d6ca4..e495346 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -95,7 +95,7 @@ public:
     /** ScSingleRefOpToken with ocMatRef. */
     formula::FormulaToken* AddMatrixSingleReference( const ScSingleRefData& rRef );
     formula::FormulaToken* AddDoubleReference( const ScComplexRefData& rRef );
-    formula::FormulaToken* AddRangeName( sal_uInt16 n, bool bGlobal );
+    formula::FormulaToken* AddRangeName( sal_uInt16 n, sal_Int16 nSheet );
     formula::FormulaToken* AddDBRange( sal_uInt16 n );
     formula::FormulaToken* AddExternalName( sal_uInt16 nFileId, const OUString& rName );
     void AddExternalSingleReference( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index b67b04f..84de73c 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -107,7 +107,7 @@ static bool lcl_HasRelRef( ScDocument* pDoc, ScTokenArray* pFormula, sal_uInt16
                 case svIndex:
                 {
                     if( t->GetOpCode() == ocName )      // DB areas always absolute
-                        if( ScRangeData* pRangeData = pDoc->GetRangeName()->findByIndex( t->GetIndex() ) )
+                        if( ScRangeData* pRangeData = pDoc->FindRangeNameByIndexAndSheet( t->GetIndex(), t->GetSheet()) )
                             if( (nRecursion < 42) && lcl_HasRelRef( pDoc, pRangeData->GetCode(), nRecursion + 1 ) )
                                 return true;
                 }
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 9f10d88..bada3af 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -234,6 +234,12 @@ const ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, OUString*
     return pData;
 }
 
+ScRangeData* ScDocument::FindRangeNameByIndexAndSheet( sal_uInt16 nIndex, SCTAB nTab ) const
+{
+    const ScRangeName* pRN = (nTab < 0 ? GetRangeName() : GetRangeName(nTab));
+    return (pRN ? pRN->findByIndex( nIndex) : nullptr);
+}
+
 void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, bool bRemoveAutoFilter )
 {
     if (pDBCollection && bRemoveAutoFilter)
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index c97e330..0db0ab4 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -422,16 +422,22 @@ bool lcl_isReference(const FormulaToken& rToken)
 
 void adjustRangeName(formula::FormulaToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldDoc, const ScAddress& aNewPos, const ScAddress& aOldPos)
 {
-    bool bOldGlobal = pToken->IsGlobal();
-    SCTAB aOldTab = aOldPos.Tab();
+    bool bSameDoc = (rNewDoc.GetPool() == const_cast<ScDocument*>(pOldDoc)->GetPool());
+    SCTAB nOldSheet = pToken->GetSheet();
+    if (bSameDoc && (nOldSheet < 0 || nOldSheet != aOldPos.Tab()))
+        // Same doc and global name or sheet-local name on other sheet stays
+        // the same.
+        return;
+
     OUString aRangeName;
     int nOldIndex = pToken->GetIndex();
     ScRangeData* pOldRangeData = nullptr;
 
     //search the name of the RangeName
-    if (!bOldGlobal)
+    if (nOldSheet >= 0)
     {
-        pOldRangeData = pOldDoc->GetRangeName(aOldTab)->findByIndex(nOldIndex);
+        const ScRangeName* pRangeName = pOldDoc->GetRangeName(nOldSheet);
+        pOldRangeData = pRangeName ? pRangeName->findByIndex(nOldIndex) : nullptr;
         if (!pOldRangeData)
             return;     //might be an error in the formula array
         aRangeName = pOldRangeData->GetUpperName();
@@ -444,12 +450,15 @@ void adjustRangeName(formula::FormulaToken* pToken, ScDocument& rNewDoc, const S
         aRangeName = pOldRangeData->GetUpperName();
     }
 
+    SAL_WARN_IF( !bSameDoc && nOldSheet >= 0 && nOldSheet != aOldPos.Tab(),
+            "sc.core", "adjustRangeName - sheet-local name was on other sheet in other document");
+    /* TODO: can we do something about that? e.g. loop over sheets? */
+
     //find corresponding range name in new document
     //first search for local range name then global range names
-    SCTAB aNewTab = aNewPos.Tab();
-    ScRangeName* pRangeName = rNewDoc.GetRangeName(aNewTab);
+    SCTAB nNewSheet = aNewPos.Tab();
+    ScRangeName* pRangeName = rNewDoc.GetRangeName(nNewSheet);
     ScRangeData* pRangeData = nullptr;
-    bool bNewGlobal = false;
     //search local range names
     if (pRangeName)
     {
@@ -458,7 +467,7 @@ void adjustRangeName(formula::FormulaToken* pToken, ScDocument& rNewDoc, const S
     //search global range names
     if (!pRangeData)
     {
-        bNewGlobal = true;
+        nNewSheet = -1;
         pRangeName = rNewDoc.GetRangeName();
         if (pRangeName)
             pRangeData = pRangeName->findByUpperName(aRangeName);
@@ -466,21 +475,24 @@ void adjustRangeName(formula::FormulaToken* pToken, ScDocument& rNewDoc, const S
     //if no range name was found copy it
     if (!pRangeData)
     {
-        bNewGlobal = bOldGlobal;
+        if (nOldSheet < 0)
+            nNewSheet = -1;
+        else
+            nNewSheet = aNewPos.Tab();
         pRangeData = new ScRangeData(*pOldRangeData, &rNewDoc);
         pRangeData->SetIndex(0);    // needed for insert to assign a new index
         ScTokenArray* pRangeNameToken = pRangeData->GetCode();
-        if (rNewDoc.GetPool() != const_cast<ScDocument*>(pOldDoc)->GetPool())
+        if (!bSameDoc)
         {
             pRangeNameToken->ReadjustAbsolute3DReferences(pOldDoc, &rNewDoc, pRangeData->GetPos(), true);
             pRangeNameToken->AdjustAbsoluteRefs(pOldDoc, aOldPos, aNewPos, false, true);
         }
 
         bool bInserted;
-        if (bNewGlobal)
+        if (nNewSheet < 0)
             bInserted = rNewDoc.GetRangeName()->insert(pRangeData);
         else
-            bInserted = rNewDoc.GetRangeName(aNewTab)->insert(pRangeData);
+            bInserted = rNewDoc.GetRangeName(nNewSheet)->insert(pRangeData);
         if (!bInserted)
         {
             //if this happened we have a real problem
@@ -492,7 +504,7 @@ void adjustRangeName(formula::FormulaToken* pToken, ScDocument& rNewDoc, const S
     }
     sal_Int32 nIndex = pRangeData->GetIndex();
     pToken->SetIndex(nIndex);
-    pToken->SetGlobal(bNewGlobal);
+    pToken->SetSheet(nNewSheet);
 }
 
 void adjustDBRange(formula::FormulaToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldDoc)
@@ -3603,7 +3615,7 @@ void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rD
     {
         if( t->GetOpCode() == ocName )
         {
-            ScRangeData* pName = pDocument->GetRangeName()->findByIndex( t->GetIndex() );
+            const ScRangeData* pName = pDocument->FindRangeNameByIndexAndSheet( t->GetIndex(), t->GetSheet());
             if (pName)
             {
                 if (pName->IsModified())
@@ -3657,7 +3669,7 @@ void ScFormulaCell::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY
     {
         if( t->GetOpCode() == ocName )
         {
-            ScRangeData* pName = pDocument->GetRangeName()->findByIndex( t->GetIndex() );
+            const ScRangeData* pName = pDocument->FindRangeNameByIndexAndSheet( t->GetIndex(), t->GetSheet());
             if (pName)
             {
                 if (pName->IsModified())
@@ -3694,6 +3706,12 @@ static void lcl_FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes, ScTokenArray
     {
         if (p->GetOpCode() == ocName)
         {
+            /* TODO: this should collect also sheet-local names, currently it
+             * collects only global names. But looking even for indexes of
+             * local names.. this always was wrong. Probably use
+             * UpdatedRangeNames instead of the set, but doing so would also
+             * need more work in copying things over clipboard and such. */
+
             sal_uInt16 nTokenIndex = p->GetIndex();
             rIndexes.insert( nTokenIndex );
 
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
index 2535990..278ae4e 100644
--- a/sc/source/core/data/validat.cxx
+++ b/sc/source/core/data/validat.cxx
@@ -694,7 +694,7 @@ bool ScValidationData::GetSelectionFromFormula(
         }
         else if (eOpCode == ocName)
         {
-            ScRangeData* pName = pDocument->GetRangeName()->findByIndex( t->GetIndex() );
+            const ScRangeData* pName = pDocument->FindRangeNameByIndexAndSheet( t->GetIndex(), t->GetSheet());
             if (pName && pName->IsReference(aRange))
             {
                 bRef = true;
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index ef2e492..c016102 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -704,8 +704,12 @@ static ScRefFlags lcl_ScRange_Parse_XL_R1C1( ScRange& r,
                                              ScDocument* pDoc,
                                              const ScAddress::Details& rDetails,
                                              bool bOnlyAcceptSingle,
-                                             ScAddress::ExternalInfo* pExtInfo )
+                                             ScAddress::ExternalInfo* pExtInfo,
+                                             sal_Int32* pSheetEndPos )
 {
+    const sal_Unicode* const pStart = p;
+    if (pSheetEndPos)
+        *pSheetEndPos = 0;
     const sal_Unicode* pTmp = nullptr;
     OUString aExternDocName, aStartTabName, aEndTabName;
     ScRefFlags nFlags = ScRefFlags::VALID | ScRefFlags::TAB_VALID;
@@ -715,6 +719,13 @@ static ScRefFlags lcl_ScRange_Parse_XL_R1C1( ScRange& r,
     p = r.Parse_XL_Header( p, pDoc, aExternDocName, aStartTabName,
             aEndTabName, nFlags, bOnlyAcceptSingle );
 
+    ScRefFlags nBailOutFlags = ScRefFlags::ZERO;
+    if (pSheetEndPos && pStart < p && (nFlags & ScRefFlags::TAB_VALID) && (nFlags & ScRefFlags::TAB_3D))
+    {
+        *pSheetEndPos = p - pStart;
+        nBailOutFlags = ScRefFlags::TAB_VALID | ScRefFlags::TAB_3D;
+    }
+
     if (!aExternDocName.isEmpty())
         lcl_ScRange_External_TabSpan( r, nFlags, pExtInfo, aExternDocName,
                 aStartTabName, aEndTabName, pDoc);
@@ -725,7 +736,7 @@ static ScRefFlags lcl_ScRange_Parse_XL_R1C1( ScRange& r,
     if( *p == 'R' || *p == 'r' )
     {
         if( nullptr == (p = lcl_r1c1_get_row( p, rDetails, &r.aStart, &nFlags )) )
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         if( *p != 'C' && *p != 'c' )    // full row R#
         {
@@ -800,7 +811,7 @@ static ScRefFlags lcl_ScRange_Parse_XL_R1C1( ScRange& r,
     else if( *p == 'C' || *p == 'c' )   // full col C#
     {
         if( nullptr == (p = lcl_r1c1_get_col( p, rDetails, &r.aStart, &nFlags )))
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         if( p[0] != ':' || (p[1] != 'C' && p[1] != 'c') ||
             nullptr == (pTmp = lcl_r1c1_get_col( p+1, rDetails, &r.aEnd, &nFlags2 )))
@@ -831,7 +842,7 @@ static ScRefFlags lcl_ScRange_Parse_XL_R1C1( ScRange& r,
         return bOnlyAcceptSingle ? ScRefFlags::ZERO : nFlags;
     }
 
-    return ScRefFlags::ZERO;
+    return nBailOutFlags;
 }
 
 static inline const sal_Unicode* lcl_a1_get_col( const sal_Unicode* p,
@@ -897,8 +908,12 @@ static ScRefFlags lcl_ScRange_Parse_XL_A1( ScRange& r,
                                            ScDocument* pDoc,
                                            bool bOnlyAcceptSingle,
                                            ScAddress::ExternalInfo* pExtInfo,
-                                           const uno::Sequence<sheet::ExternalLinkInfo>* pExternalLinks )
+                                           const uno::Sequence<sheet::ExternalLinkInfo>* pExternalLinks,
+                                           sal_Int32* pSheetEndPos )
 {
+    const sal_Unicode* const pStart = p;
+    if (pSheetEndPos)
+        *pSheetEndPos = 0;
     const sal_Unicode* tmp1, *tmp2;
     OUString aExternDocName, aStartTabName, aEndTabName; // for external link table
     ScRefFlags nFlags = ScRefFlags::VALID | ScRefFlags::TAB_VALID, nFlags2 = ScRefFlags::TAB_VALID;
@@ -906,29 +921,36 @@ static ScRefFlags lcl_ScRange_Parse_XL_A1( ScRange& r,
     p = r.Parse_XL_Header( p, pDoc, aExternDocName, aStartTabName,
             aEndTabName, nFlags, bOnlyAcceptSingle, pExternalLinks );
 
+    ScRefFlags nBailOutFlags = ScRefFlags::ZERO;
+    if (pSheetEndPos && pStart < p && (nFlags & ScRefFlags::TAB_VALID) && (nFlags & ScRefFlags::TAB_3D))
+    {
+        *pSheetEndPos = p - pStart;
+        nBailOutFlags = ScRefFlags::TAB_VALID | ScRefFlags::TAB_3D;
+    }
+
     if (!aExternDocName.isEmpty())
         lcl_ScRange_External_TabSpan( r, nFlags, pExtInfo, aExternDocName,
                 aStartTabName, aEndTabName, pDoc);
 
     if( nullptr == p )
-        return ScRefFlags::ZERO;
+        return nBailOutFlags;
 
     tmp1 = lcl_a1_get_col( p, &r.aStart, &nFlags );
     if( tmp1 == nullptr )          // Is it a row only reference 3:5
     {
         if( bOnlyAcceptSingle ) // by definition full row refs are ranges
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         tmp1 = lcl_a1_get_row( p, &r.aStart, &nFlags );
 
         tmp1 = lcl_eatWhiteSpace( tmp1 );
         if( !tmp1 || *tmp1++ != ':' ) // Even a singleton requires ':' (eg 2:2)
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         tmp1 = lcl_eatWhiteSpace( tmp1 );
         tmp2 = lcl_a1_get_row( tmp1, &r.aEnd, &nFlags2 );
         if( !tmp2 || *tmp2 != 0 )   // Must have fully parsed a singleton.
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         r.aStart.SetCol( 0 ); r.aEnd.SetCol( MAXCOL );
         nFlags |=
@@ -942,16 +964,16 @@ static ScRefFlags lcl_ScRange_Parse_XL_A1( ScRange& r,
     if( tmp2 == nullptr )          // check for col only reference F:H
     {
         if( bOnlyAcceptSingle ) // by definition full col refs are ranges
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         tmp1 = lcl_eatWhiteSpace( tmp1 );
         if( *tmp1++ != ':' )    // Even a singleton requires ':' (eg F:F)
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         tmp1 = lcl_eatWhiteSpace( tmp1 );
         tmp2 = lcl_a1_get_col( tmp1, &r.aEnd, &nFlags2 );
         if( !tmp2 || *tmp2 != 0 )   // Must have fully parsed a singleton.
-            return ScRefFlags::ZERO;
+            return nBailOutFlags;
 
         r.aStart.SetRow( 0 ); r.aEnd.SetRow( MAXROW );
         nFlags |=
@@ -1047,8 +1069,13 @@ static ScRefFlags lcl_ScRange_Parse_XL_A1( ScRange& r,
  */
 static ScRefFlags lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
                                            ScRefFlags& rRawRes,
-                                           ScAddress::ExternalInfo* pExtInfo = nullptr, ScRange* pRange = nullptr )
+                                           ScAddress::ExternalInfo* pExtInfo,
+                                           ScRange* pRange,
+                                           sal_Int32* pSheetEndPos )
 {
+    const sal_Unicode* const pStart = p;
+    if (pSheetEndPos)
+        *pSheetEndPos = 0;
     ScRefFlags  nRes = ScRefFlags::ZERO;
     rRawRes = ScRefFlags::ZERO;
     OUString aDocName;       // the pure Document Name
@@ -1061,7 +1088,6 @@ static ScRefFlags lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDo
     // document name is always quoted and has a trailing #.
     if (*p == '\'')
     {
-        const sal_Unicode* pStart = p;
         OUString aTmp;
         p = parseQuotedName(p, aTmp);
         aDocName = aTmp;
@@ -1081,7 +1107,8 @@ static ScRefFlags lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDo
     SCCOL   nCol = 0;
     SCROW   nRow = 0;
     SCTAB   nTab = 0;
-    ScRefFlags  nBits = ScRefFlags::TAB_VALID;
+    ScRefFlags nBailOutFlags = ScRefFlags::ZERO;
+    ScRefFlags nBits = ScRefFlags::TAB_VALID;
     const sal_Unicode* q;
     if ( ScGlobal::FindUnquoted( p, '.') )
     {
@@ -1121,6 +1148,12 @@ static ScRefFlags lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDo
         if( *p++ != '.' )
             nBits = ScRefFlags::ZERO;
 
+        if (pSheetEndPos && (nBits & ScRefFlags::TAB_VALID))
+        {
+            *pSheetEndPos = p - pStart;
+            nBailOutFlags = ScRefFlags::TAB_VALID | ScRefFlags::TAB_3D;
+        }
+
         if (!bExtDoc && (!pDoc || !pDoc->GetTable( aTab, nTab )))
         {
             // Specified table name is not found in this document.  Assume this is an external document.
@@ -1305,14 +1338,15 @@ static ScRefFlags lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDo
             nRes |= ScRefFlags::VALID;
     }
     else
-        nRes = ScRefFlags::ZERO;
+        nRes = nBailOutFlags;
     return nRes;
 }
 
 static ScRefFlags lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
                                         const ScAddress::Details& rDetails,
                                         ScAddress::ExternalInfo* pExtInfo = nullptr,
-                                        const uno::Sequence<sheet::ExternalLinkInfo>* pExternalLinks = nullptr )
+                                        const uno::Sequence<sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
+                                        sal_Int32* pSheetEndPos = nullptr )
 {
     if( !*p )
         return ScRefFlags::ZERO;
@@ -1324,15 +1358,16 @@ static ScRefFlags lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc,
         {
             ScRange rRange = rAddr;
             ScRefFlags nFlags = lcl_ScRange_Parse_XL_A1(
-                                    rRange, p, pDoc, true, pExtInfo,
-                                    (rDetails.eConv == formula::FormulaGrammar::CONV_XL_OOX ? pExternalLinks : nullptr) );
+                    rRange, p, pDoc, true, pExtInfo,
+                    (rDetails.eConv == formula::FormulaGrammar::CONV_XL_OOX ? pExternalLinks : nullptr),
+                    pSheetEndPos);
             rAddr = rRange.aStart;
             return nFlags;
         }
         case formula::FormulaGrammar::CONV_XL_R1C1:
         {
             ScRange rRange = rAddr;
-            ScRefFlags nFlags = lcl_ScRange_Parse_XL_R1C1( rRange, p, pDoc, rDetails, true, pExtInfo );
+            ScRefFlags nFlags = lcl_ScRange_Parse_XL_R1C1( rRange, p, pDoc, rDetails, true, pExtInfo, pSheetEndPos);
             rAddr = rRange.aStart;
             return nFlags;
         }
@@ -1340,7 +1375,7 @@ static ScRefFlags lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc,
         case formula::FormulaGrammar::CONV_OOO:
         {
             ScRefFlags nRawRes = ScRefFlags::ZERO;
-            return lcl_ScAddress_Parse_OOo( p, pDoc, rAddr, nRawRes, pExtInfo );
+            return lcl_ScAddress_Parse_OOo( p, pDoc, rAddr, nRawRes, pExtInfo, nullptr, pSheetEndPos);
         }
     }
 }
@@ -1396,9 +1431,10 @@ bool ConvertDoubleRef( ScDocument* pDoc, const OUString& rRefString, SCTAB nDefT
 ScRefFlags ScAddress::Parse( const OUString& r, ScDocument* pDoc,
                              const Details& rDetails,
                              ExternalInfo* pExtInfo,
-                             const uno::Sequence<sheet::ExternalLinkInfo>* pExternalLinks )
+                             const uno::Sequence<sheet::ExternalLinkInfo>* pExternalLinks,
+                             sal_Int32* pSheetEndPos )
 {
-    return lcl_ScAddress_Parse( r.getStr(), pDoc, *this, rDetails, pExtInfo, pExternalLinks );
+    return lcl_ScAddress_Parse( r.getStr(), pDoc, *this, rDetails, pExtInfo, pExternalLinks, pSheetEndPos );
 }
 
 bool ScRange::Intersects( const ScRange& rRange ) const
@@ -1476,13 +1512,14 @@ static ScRefFlags lcl_ScRange_Parse_OOo( ScRange& rRange,
         aTmp[nPos] = 0;
         const sal_Unicode* p = aTmp.getStr();
         ScRefFlags nRawRes1 = ScRefFlags::ZERO;
-        if (((nRes1 = lcl_ScAddress_Parse_OOo( p, pDoc, rRange.aStart, nRawRes1, pExtInfo)) != ScRefFlags::ZERO) ||
+        nRes1 = lcl_ScAddress_Parse_OOo( p, pDoc, rRange.aStart, nRawRes1, pExtInfo, nullptr, nullptr);
+        if ((nRes1 != ScRefFlags::ZERO) ||
                 ((nRawRes1 & (ScRefFlags::COL_VALID | ScRefFlags::ROW_VALID)) &&
                  (nRawRes1 & ScRefFlags::TAB_VALID)))
         {
             rRange.aEnd = rRange.aStart;  // sheet must be initialized identical to first sheet
             ScRefFlags nRawRes2 = ScRefFlags::ZERO;
-            nRes2 = lcl_ScAddress_Parse_OOo( p + nPos+ 1, pDoc, rRange.aEnd, nRawRes2, pExtInfo, &rRange);
+            nRes2 = lcl_ScAddress_Parse_OOo( p + nPos+ 1, pDoc, rRange.aEnd, nRawRes2, pExtInfo, &rRange, nullptr);
             if (!((nRes1 & ScRefFlags::VALID) && (nRes2 & ScRefFlags::VALID)) &&
                     // If not fully valid addresses, check if both have a valid
                     // column or row, and both have valid (or omitted) sheet references.
@@ -1596,12 +1633,12 @@ ScRefFlags ScRange::Parse( const OUString& rString, ScDocument* pDoc,
         case formula::FormulaGrammar::CONV_XL_OOX:
         {
             return lcl_ScRange_Parse_XL_A1( *this, rString.getStr(), pDoc, false, pExtInfo,
-                    (rDetails.eConv == formula::FormulaGrammar::CONV_XL_OOX ? pExternalLinks : nullptr) );
+                    (rDetails.eConv == formula::FormulaGrammar::CONV_XL_OOX ? pExternalLinks : nullptr), nullptr );
         }
 
         case formula::FormulaGrammar::CONV_XL_R1C1:
         {
-            return lcl_ScRange_Parse_XL_R1C1( *this, rString.getStr(), pDoc, rDetails, false, pExtInfo );
+            return lcl_ScRange_Parse_XL_R1C1( *this, rString.getStr(), pDoc, rDetails, false, pExtInfo, nullptr );
         }
 
         default:
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 2f88dd9..c57f192 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -2892,14 +2892,34 @@ bool ScCompiler::IsDoubleReference( const OUString& rName )
 
 bool ScCompiler::IsSingleReference( const OUString& rName )
 {
+    mnCurrentSheetEndPos = 0;
+    mnCurrentSheetTab = -1;
     ScAddress aAddr( aPos );
     const ScAddress::Details aDetails( pConv->meConv, aPos );
     ScAddress::ExternalInfo aExtInfo;
-    ScRefFlags nFlags = aAddr.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
+    ScRefFlags nFlags = aAddr.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks, &mnCurrentSheetEndPos);
     // Something must be valid in order to recognize Sheet1.blah or blah.a1
     // as a (wrong) reference.
     if( nFlags & ( ScRefFlags::COL_VALID|ScRefFlags::ROW_VALID|ScRefFlags::TAB_VALID ) )
     {
+        // Valid given tab and invalid col or row may indicate a sheet-local
+        // named expression, bail out early and don't create a reference token.
+        if (!(nFlags & ScRefFlags::VALID) && mnCurrentSheetEndPos > 0 &&
+                (nFlags & ScRefFlags::TAB_VALID) && (nFlags & ScRefFlags::TAB_3D))
+        {
+            if (aExtInfo.mbExternal)
+            {
+                // External names are handled separately.
+                mnCurrentSheetEndPos = 0;
+                mnCurrentSheetTab = -1;
+            }
+            else
+            {
+                mnCurrentSheetTab = aAddr.Tab();
+            }
+            return false;
+        }
+
         ScSingleRefData aRef;
         aRef.InitAddress( aAddr );
         aRef.SetColRel( (nFlags & ScRefFlags::COL_ABS) == ScRefFlags::ZERO );
@@ -3093,8 +3113,8 @@ bool ScCompiler::IsNamedRange( const OUString& rUpperName )
     // IsNamedRange is called only from NextNewToken, with an upper-case string
 
     // try local names first
-    bool bGlobal = false;
-    ScRangeName* pRangeName = pDoc->GetRangeName(aPos.Tab());
+    sal_Int16 nSheet = aPos.Tab();
+    ScRangeName* pRangeName = pDoc->GetRangeName(nSheet);
     const ScRangeData* pData = nullptr;
     if (pRangeName)
         pData = pRangeName->findByUpperName(rUpperName);
@@ -3104,16 +3124,32 @@ bool ScCompiler::IsNamedRange( const OUString& rUpperName )
         if (pRangeName)
             pData = pRangeName->findByUpperName(rUpperName);
         if (pData)
-            bGlobal = true;
+            nSheet = -1;
     }
 
     if (pData)
     {
-        maRawToken.SetName(bGlobal, pData->GetIndex());
+        maRawToken.SetName( nSheet, pData->GetIndex());
         return true;
     }
-    else
-        return false;
+
+    // Sheet-local name with sheet specified.
+    if (mnCurrentSheetEndPos > 0 && mnCurrentSheetTab >= 0)
+    {
+        OUString aName( rUpperName.copy( mnCurrentSheetEndPos));
+        pRangeName = pDoc->GetRangeName( mnCurrentSheetTab);
+        if (pRangeName)
+        {
+            pData = pRangeName->findByUpperName(aName);
+            if (pData)
+            {
+                maRawToken.SetName( mnCurrentSheetTab, pData->GetIndex());
+                return true;
+            }
+        }
+    }
+
+    return false;
 }
 
 bool ScCompiler::IsExternalNamedRange( const OUString& rSymbol, bool& rbInvalidExternalNameRange )
@@ -3161,7 +3197,7 @@ bool ScCompiler::IsDBRange( const OUString& rName )
     if (!p)
         return false;
 
-    maRawToken.SetName(true, p->GetIndex()); // DB range is always global.
+    maRawToken.SetName( -1, p->GetIndex()); // DB range is always global.
     maRawToken.eOp = ocDBArea;
     return true;
 }
@@ -4387,19 +4423,7 @@ ScTokenArray* ScCompiler::CompileString( const OUString& rFormula, const OUStrin
 
 ScRangeData* ScCompiler::GetRangeData( const FormulaToken& rToken ) const
 {
-    ScRangeData* pRangeData = nullptr;
-    bool bGlobal = rToken.IsGlobal();
-    if (bGlobal)
-        // global named range.
-        pRangeData = pDoc->GetRangeName()->findByIndex( rToken.GetIndex());
-    else
-    {
-        // sheet local named range.
-        const ScRangeName* pRN = pDoc->GetRangeName( aPos.Tab());
-        if (pRN)
-            pRangeData = pRN->findByIndex( rToken.GetIndex());
-    }
-    return pRangeData;
+    return pDoc->FindRangeNameByIndexAndSheet( rToken.GetIndex(), rToken.GetSheet());
 }
 
 bool ScCompiler::HandleRange()
@@ -4759,7 +4783,20 @@ void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaTo
         {
             const ScRangeData* pData = GetRangeData( *_pTokenP);
             if (pData)
+            {
+                SCTAB nTab = _pTokenP->GetSheet();
+                if (nTab >= 0 && nTab != aPos.Tab())
+                {
+                    // Sheet-local on other sheet.
+                    OUString aName;
+                    if (pDoc->GetName( nTab, aName))
+                        aBuffer.append( aName);
+                    else
+                        aBuffer.append( ScGlobal::GetRscString( STR_NO_NAME_REF));
+                    aBuffer.append( pConv->getSpecialSymbol( ScCompiler::Convention::SHEET_SEPARATOR));
+                }
                 aBuffer.append(pData->GetName());
+            }
         }
         break;
         case ocDBArea:
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 6a3f271..3d82694 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -293,12 +293,12 @@ void ScRawToken::SetErrorConstant( sal_uInt16 nErr )
     nError = nErr;
 }
 
-void ScRawToken::SetName(bool bGlobal, sal_uInt16 nIndex)
+void ScRawToken::SetName(sal_Int16 nSheet, sal_uInt16 nIndex)
 {
     eOp = ocName;
     eType = svIndex;
 
-    name.bGlobal = bGlobal;
+    name.nSheet = nSheet;
     name.nIndex = nIndex;
 }
 
@@ -409,7 +409,7 @@ FormulaToken* ScRawToken::CreateToken() const
             if (eOp == ocTableRef)
                 return new ScTableRefToken( table.nIndex, table.eItem);
             else
-                return new FormulaIndexToken( eOp, name.nIndex, name.bGlobal);
+                return new FormulaIndexToken( eOp, name.nIndex, name.nSheet);
         case svExternalSingleRef:
             {
                 OUString aTabName(extref.cTabName);
@@ -933,13 +933,13 @@ void ScTableRefToken::SetIndex( sal_uInt16 n )
     mnIndex = n;
 }
 
-bool ScTableRefToken::IsGlobal() const
+sal_Int16 ScTableRefToken::GetSheet() const
 {
     // Code asking for this may have to be adapted as it might assume an
     // svIndex token would always be ocName or ocDBArea.
-    SAL_WARN("sc.core","ScTableRefToken::IsGlobal - maybe adapt caller to know about TableRef?");
+    SAL_WARN("sc.core","ScTableRefToken::GetSheet - maybe adapt caller to know about TableRef?");
     // Database range is always global.
-    return true;
+    return -1;
 }
 
 ScTableRefToken::Item ScTableRefToken::GetItem() const
@@ -1212,7 +1212,16 @@ bool ScTokenArray::AddFormulaToken(
                         sheet::NameToken aTokenData;
                         rToken.Data >>= aTokenData;
                         if ( eOpCode == ocName )
-                            AddRangeName(aTokenData.Index, aTokenData.Global);
+                        {
+                            /* TODO: new token type with sheet number */
+                            if (aTokenData.Global)
+                                AddRangeName(aTokenData.Index, -1);
+                            else
+                                bError = true;
+                            /* FIXME: resolve the non-global case to the
+                             * current position's sheet as it implicitly was
+                             * before, currently this is broken. */
+                        }
                         else if (eOpCode == ocDBArea)
                             AddDBRange(aTokenData.Index);
                         else if (eOpCode == ocTableRef)
@@ -2059,9 +2068,9 @@ FormulaToken* ScTokenArray::AddMatrix( const ScMatrixRef& p )
     return Add( new ScMatrixToken( p ) );
 }
 
-FormulaToken* ScTokenArray::AddRangeName( sal_uInt16 n, bool bGlobal )
+FormulaToken* ScTokenArray::AddRangeName( sal_uInt16 n, sal_Int16 nSheet )
 {
-    return Add( new FormulaIndexToken( ocName, n, bGlobal));
+    return Add( new FormulaIndexToken( ocName, n, nSheet));
 }
 
 FormulaToken* ScTokenArray::AddDBRange( sal_uInt16 n )
@@ -2826,7 +2835,7 @@ bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, co
 bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken )
 {
     SCTAB nTab = -1;
-    if (!rToken.IsGlobal())
+    if (rToken.GetSheet() >= 0)
         nTab = nOldTab;
 
     // Check if this named expression has been modified.
@@ -3003,8 +3012,17 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
                 switch ((*pp)->GetOpCode())
                 {
                     case ocName:
-                        if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **pp))
-                            aRes.mbNameModified = true;
+                        {
+                            SCTAB nOldTab = (*pp)->GetSheet();
+                            if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
+                                aRes.mbNameModified = true;
+                            if (rCxt.mnTabDelta &&
+                                    rCxt.maRange.aStart.Tab() <= nOldTab && nOldTab <= rCxt.maRange.aEnd.Tab())
+                            {
+                                aRes.mbNameModified = true;
+                                (*pp)->SetSheet( nOldTab + rCxt.mnTabDelta);
+                            }
+                        }
                         break;
                     case ocDBArea:
                     case ocTableRef:
@@ -3099,8 +3117,17 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
                 switch ((*pp)->GetOpCode())
                 {
                     case ocName:
-                        if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **pp))
-                            aRes.mbNameModified = true;
+                        {
+                            SCTAB nOldTab = (*pp)->GetSheet();
+                            if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
+                                aRes.mbNameModified = true;
+                            if (rCxt.mnTabDelta &&
+                                    rCxt.maRange.aStart.Tab() <= nOldTab && nOldTab <= rCxt.maRange.aEnd.Tab())
+                            {
+                                aRes.mbNameModified = true;
+                                (*pp)->SetSheet( nOldTab + rCxt.mnTabDelta);
+                            }
+                        }
                         break;
                     case ocDBArea:
                     case ocTableRef:
@@ -3171,8 +3198,17 @@ sc::RefUpdateResult ScTokenArray::MoveReference( const ScAddress& rPos, const sc
                 switch ((*p)->GetOpCode())
                 {
                     case ocName:
-                        if (isNameModified(rCxt.maUpdatedNames, aOldRange.aStart.Tab(), **p))
-                            aRes.mbNameModified = true;
+                        {
+                            SCTAB nOldTab = (*p)->GetSheet();
+                            if (isNameModified(rCxt.maUpdatedNames, nOldTab, **p))
+                                aRes.mbNameModified = true;
+                            if (rCxt.mnTabDelta &&
+                                    rCxt.maRange.aStart.Tab() <= nOldTab && nOldTab <= rCxt.maRange.aEnd.Tab())
+                            {
+                                aRes.mbNameModified = true;
+                                (*p)->SetSheet( nOldTab + rCxt.mnTabDelta);
+                            }
+                        }
                         break;
                     case ocDBArea:
                     case ocTableRef:
@@ -3868,8 +3904,20 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( sc::RefUpdateDele
                 switch ((*pp)->GetOpCode())
                 {
                     case ocName:
-                        if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **pp))
-                            aRes.mbNameModified = true;
+                        {
+                            SCTAB nOldTab = (*pp)->GetSheet();
+                            if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
+                                aRes.mbNameModified = true;
+                            if (rCxt.mnDeletePos <= nOldTab)
+                            {
+                                aRes.mbNameModified = true;
+                                if (rCxt.mnDeletePos + rCxt.mnSheets < nOldTab)
+                                    (*pp)->SetSheet( nOldTab - rCxt.mnSheets);
+                                else
+                                    // Would point to a deleted sheet. Invalidate.
+                                    (*pp)->SetSheet( SCTAB_MAX);
+                            }
+                        }
                         break;
                     case ocDBArea:
                     case ocTableRef:
@@ -3932,8 +3980,16 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( sc::RefUpdateIns
                 switch ((*pp)->GetOpCode())
                 {
                     case ocName:
-                        if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **pp))
-                            aRes.mbNameModified = true;
+                        {
+                            SCTAB nOldTab = (*pp)->GetSheet();
+                            if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
+                                aRes.mbNameModified = true;
+                            if (rCxt.mnInsertPos <= nOldTab)
+                            {
+                                aRes.mbNameModified = true;
+                                (*pp)->SetSheet( nOldTab + rCxt.mnSheets);
+                            }
+                        }
                         break;
                     case ocDBArea:
                     case ocTableRef:
@@ -4017,8 +4073,17 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTa
                 switch ((*pp)->GetOpCode())
                 {
                     case ocName:
-                        if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **pp))
-                            aRes.mbNameModified = true;
+                        {
+                            SCTAB nOldTab = (*pp)->GetSheet();
+                            if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp))
+                                aRes.mbNameModified = true;
+                            SCTAB nNewTab = rCxt.getNewTab( nOldTab);
+                            if (nNewTab != nOldTab)
+                            {
+                                aRes.mbNameModified = true;
+                                (*pp)->SetSheet( nNewTab);
+                            }
+                        }
                         break;
                     case ocDBArea:
                     case ocTableRef:
@@ -4614,7 +4679,8 @@ void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, cons
             {
                 case ocName:
                 {
-                    if (rToken.IsGlobal())
+                    SCTAB nTab = rToken.GetSheet();
+                    if (nTab < 0)
                     {
                         // global named range
                         NameType::const_iterator it = rCxt.maGlobalRangeNames.find(nIndex);
@@ -4629,7 +4695,20 @@ void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, cons
                     else
                     {
                         // sheet-local named range
-                        sc::TokenStringContext::TabIndexMapType::const_iterator itTab = rCxt.maSheetRangeNames.find(rPos.Tab());
+                        if (nTab != rPos.Tab())
+                        {
+                            // On other sheet.
+                            OUString aName;
+                            if (static_cast<size_t>(nTab) < rCxt.maTabNames.size())
+                                aName = rCxt.maTabNames[nTab];
+                            if (!aName.isEmpty())
+                                rBuf.append( aName);
+                            else
+                                rBuf.append( ScGlobal::GetRscString( STR_NO_NAME_REF));
+                            rBuf.append( rCxt.mpRefConv->getSpecialSymbol( ScCompiler::Convention::SHEET_SEPARATOR));
+                        }
+
+                        sc::TokenStringContext::TabIndexMapType::const_iterator itTab = rCxt.maSheetRangeNames.find(nTab);
                         if (itTab == rCxt.maSheetRangeNames.end())
                         {
                             rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx
index 2be528a..33ec52f 100644
--- a/sc/source/filter/excel/excform.cxx
+++ b/sc/source/filter/excel/excform.cxx
@@ -544,7 +544,7 @@ ConvErr ExcelToSc::Convert( const ScTokenArray*& pErgebnis, XclImpStream& aIn, s
                 if(pName && !pName->GetScRangeData())
                     aStack << aPool.Store( ocMacro, pName->GetXclName() );
                 else
-                    aStack << aPool.StoreName(nUINT16, true);
+                    aStack << aPool.StoreName(nUINT16, -1);
             }
                 break;
             case 0x44:
@@ -733,7 +733,7 @@ ConvErr ExcelToSc::Convert( const ScTokenArray*& pErgebnis, XclImpStream& aIn, s
                     aPool >> aStack;
                 }
                 else
-                    aStack << aPool.StoreName( nUINT16, true );
+                    aStack << aPool.StoreName( nUINT16, -1 );
                 aIn.Ignore( 12 );
                 break;
             }
diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx
index c13876c..f0668cb 100644
--- a/sc/source/filter/excel/excform8.cxx
+++ b/sc/source/filter/excel/excform8.cxx
@@ -493,7 +493,7 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
                         // user-defined macro name.
                         aStack << aPool.Store(ocMacro, pName->GetXclName());
                     else
-                        aStack << aPool.StoreName(nUINT16, pName->IsGlobal());
+                        aStack << aPool.StoreName(nUINT16, pName->IsGlobal() ? -1 : pName->GetScTab());
                 }
                 break;
             }
@@ -680,7 +680,7 @@ ConvErr ExcelToSc8::Convert( const ScTokenArray*& rpTokArray, XclImpStream& aIn,
                     if (pName)
                     {
                         if (pName->GetScRangeData())
-                            aStack << aPool.StoreName( nNameIdx, pName->IsGlobal());
+                            aStack << aPool.StoreName( nNameIdx, pName->IsGlobal() ? -1 : pName->GetScTab());
                         else
                             aStack << aPool.Store(ocMacro, pName->GetXclName());
                     }
diff --git a/sc/source/filter/excel/tokstack.cxx b/sc/source/filter/excel/tokstack.cxx
index 31e8995..9323f93 100644
--- a/sc/source/filter/excel/tokstack.cxx
+++ b/sc/source/filter/excel/tokstack.cxx
@@ -425,7 +425,7 @@ bool TokenPool::GetElement( const sal_uInt16 nId )
                 if (n < maRangeNames.size())
                 {
                     const RangeName& r = maRangeNames[n];
-                    pScToken->AddRangeName(r.mnIndex, r.mbGlobal);
+                    pScToken->AddRangeName(r.mnIndex, r.mnSheet);
                 }
             }
             break;
@@ -623,7 +623,7 @@ const TokenId TokenPool::Store( const double& rDouble )
 
 const TokenId TokenPool::Store( const sal_uInt16 nIndex )
 {
-    return StoreName(nIndex, true);
+    return StoreName(nIndex, -1);
 }
 
 const TokenId TokenPool::Store( const OUString& rString )
@@ -790,7 +790,7 @@ const TokenId TokenPool::StoreMatrix()
     return static_cast<const TokenId>(nElementAkt);
 }
 
-const TokenId TokenPool::StoreName( sal_uInt16 nIndex, bool bGlobal )
+const TokenId TokenPool::StoreName( sal_uInt16 nIndex, sal_Int16 nSheet )
 {
     if ( nElementAkt >= nElement )
         if (!GrowElement())
@@ -802,7 +802,7 @@ const TokenId TokenPool::StoreName( sal_uInt16 nIndex, bool bGlobal )
     maRangeNames.push_back(RangeName());
     RangeName& r = maRangeNames.back();
     r.mnIndex = nIndex;
-    r.mbGlobal = bGlobal;
+    r.mnSheet = nSheet;
 
     ++nElementAkt;
 
diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx
index 29ac7a0..9742cb6 100644
--- a/sc/source/filter/excel/xeformula.cxx
+++ b/sc/source/filter/excel/xeformula.cxx
@@ -2079,10 +2079,8 @@ void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData
 
 void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData )
 {
-    SCTAB nTab = SCTAB_GLOBAL;
-    bool bGlobal = rTokData.mpScToken->IsGlobal();
-    if (!bGlobal)
-        nTab = GetCurrScTab();
+    sal_Int16 nSheet = rTokData.mpScToken->GetSheet();
+    SCTAB nTab = (nSheet < 0 ? SCTAB_GLOBAL : nSheet);
 
     XclExpNameManager& rNameMgr = GetNameManager();
     sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, rTokData.mpScToken->GetIndex());
diff --git a/sc/source/filter/inc/tokstack.hxx b/sc/source/filter/inc/tokstack.hxx
index 9ceb2a4..71ef978 100644
--- a/sc/source/filter/inc/tokstack.hxx
+++ b/sc/source/filter/inc/tokstack.hxx
@@ -126,7 +126,7 @@ private:
         struct RangeName
         {
             sal_uInt16 mnIndex;
-            bool mbGlobal;
+            sal_Int16  mnSheet;
         };
         ::std::vector<RangeName> maRangeNames;
 
@@ -205,7 +205,7 @@ public:
                                         // 4 externals (e.g. AddIns, Macros...)
         const TokenId               StoreNlf( const ScSingleRefData& rTr );
         const TokenId               StoreMatrix();
-        const TokenId               StoreName( sal_uInt16 nIndex, bool bGlobal );
+        const TokenId               StoreName( sal_uInt16 nIndex, sal_Int16 nSheet );
         const TokenId               StoreExtName( sal_uInt16 nFileId, const OUString& rName );
         const TokenId               StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
         const TokenId               StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef );
diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx
index 6e769d0..edea996 100644
--- a/sc/source/ui/unoobj/tokenuno.cxx
+++ b/sc/source/ui/unoobj/tokenuno.cxx
@@ -424,7 +424,8 @@ bool ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc,
                     {
                         sheet::NameToken aNameToken;
                         aNameToken.Index = static_cast<sal_Int32>( rToken.GetIndex() );
-                        aNameToken.Global = rToken.IsGlobal();
+                        /* FIXME: we need a new token with sheet number */
+                        aNameToken.Global = (rToken.GetSheet() < 0);
                         rAPI.Data <<= aNameToken;
                     }
                     break;


More information about the Libreoffice-commits mailing list