summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-03-25 22:34:18 -0400
committerAndras Timar <andras.timar@collabora.com>2014-03-26 10:01:21 +0000
commit0568f9f55b0054629e86561e96e78ecf13a8df5f (patch)
tree42b15317457eba5d15c4664e1909690bba862900
parentf384598d8eec91c3c0f84a07ff3e59b8e3e13b3f (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 (cherry picked from commit 003a27a14d5cf65fe0b528b6d6015e37a64dbb8e) Reviewed-on: https://gerrit.libreoffice.org/8756 Reviewed-by: Andras Timar <andras.timar@collabora.com> Tested-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r--sc/inc/tokenarray.hxx2
-rw-r--r--sc/source/core/data/column.cxx15
-rw-r--r--sc/source/core/data/formulacell.cxx2
-rw-r--r--sc/source/core/tool/token.cxx135
4 files changed, 108 insertions, 46 deletions
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 58ff8d46e437..5b3e080f8822 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -164,6 +164,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 7a448fd4683f..518766dde6a0 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2529,8 +2529,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 eb40441fdeb7..10c4c14c88af 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2801,7 +2801,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 77cc06d3a2a6..5618ed38dd89 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:
;
}
@@ -2954,6 +2964,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;
@@ -3004,6 +3017,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 )
@@ -3087,17 +3161,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:
@@ -3140,17 +3205,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:
@@ -3214,17 +3270,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: