diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-03-25 22:34:18 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-03-25 22:37:10 -0400 |
commit | 003a27a14d5cf65fe0b528b6d6015e37a64dbb8e (patch) | |
tree | ca799c7a0462525af093db17a93e46170c21c1d6 /sc | |
parent | 3edc49d11765372fa54c52b71b49bf52675f4dda (diff) |
fdo#74322: Handle moving of named ranges correctly.
But named ranges are adjusted if and only if the references are absolute.
Change-Id: I6c5287b413884b045f1a798c6c6683aa17863f24
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/tokenarray.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 15 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 135 |
4 files changed, 108 insertions, 46 deletions
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index eb68997b8cad..e8b96cc54e20 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -163,6 +163,8 @@ public: */ sc::RefUpdateResult AdjustReferenceInName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ); + sc::RefUpdateResult AdjustReferenceInMovedName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ); + /** * Adjust all references on sheet deletion. * diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 5c196a01c60b..e08766e9f63b 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2537,8 +2537,21 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void> bRecalcOnMove = aPos != aOldPos; sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(*mpCxt, aOldPos, aPos); - if (aRes.mbReferenceModified || bRecalcOnMove) + + if (aRes.mbReferenceModified || aRes.mbNameModified || bRecalcOnMove) { + sc::AutoCalcSwitch(mpCxt->mrDoc, false); + + if (aRes.mbNameModified) + { + // We need to re-compile the token array when a range name is + // modified, to correctly reflect the new references in the + // name. + ScCompiler aComp(&mpCxt->mrDoc, aPos, *pCode); + aComp.SetGrammar(mpCxt->mrDoc.GetGrammar()); + aComp.CompileTokenArray(); + } + // Perform end-listening, start-listening, and dirtying on all // formula cells in the group. diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 320a2c246bf7..b4b3ddf40052 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2833,7 +2833,7 @@ bool ScFormulaCell::UpdateReferenceOnMove( { // Update cell or range references. sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(rCxt, aOldPos, aPos); - bRefModified = aRes.mbReferenceModified; + bRefModified = aRes.mbReferenceModified || aRes.mbNameModified; bValChanged = aRes.mbValueChanged; } diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index f1982bd66988..e2a0fdb45352 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2634,6 +2634,19 @@ bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, co return false; } +bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken ) +{ + if (rToken.GetOpCode() != ocName) + return false; + + SCTAB nTab = -1; + if (!rToken.IsGlobal()) + nTab = nOldTab; + + // Check if this named expression has been modified. + return rUpdatedNames.isNameUpdated(nTab, rToken.GetIndex()); +} + } sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos ) @@ -2772,17 +2785,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: @@ -2837,6 +2841,12 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( rRef.SetRange(aAbs, rNewPos); } break; + case svIndex: + { + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; + } + break; default: ; } @@ -2967,6 +2977,9 @@ bool adjustDoubleRefInName( sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ) { + if (rCxt.meMode == URM_MOVE) + return AdjustReferenceInMovedName(rCxt, rPos); + sc::RefUpdateResult aRes; FormulaToken** p = pCode; @@ -3029,6 +3042,67 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( return aRes; } +sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ) +{ + // When moving, the range is the destination range. + ScRange aOldRange = rCxt.maRange; + aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta); + + // In a named expression, we'll move the reference only when the reference + // is entirely absolute. + + sc::RefUpdateResult aRes; + + + FormulaToken** p = pCode; + FormulaToken** pEnd = p + static_cast<size_t>(nLen); + for (; p != pEnd; ++p) + { + switch ((*p)->GetType()) + { + case svSingleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + ScSingleRefData& rRef = pToken->GetSingleRef(); + if (rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()) + continue; + + ScAddress aAbs = rRef.toAbs(rPos); + if (aOldRange.In(aAbs)) + { + aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); + aRes.mbReferenceModified = true; + } + + rRef.SetAddress(aAbs, rPos); + } + break; + case svDoubleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + ScComplexRefData& rRef = pToken->GetDoubleRef(); + if (rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() || + rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel()) + continue; + + ScRange aAbs = rRef.toAbs(rPos); + if (aOldRange.In(aAbs)) + { + aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); + aRes.mbReferenceModified = true; + } + + rRef.SetRange(aAbs, rPos); + } + break; + default: + ; + } + } + + return aRes; +} + namespace { bool adjustSingleRefOnDeletedTab( ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos ) @@ -3112,17 +3186,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( sc::RefUpdateDele break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: @@ -3165,17 +3230,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( sc::RefUpdateIns break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: @@ -3239,17 +3295,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTa break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: |