summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2017-01-09 19:47:06 +0100
committerAndras Timar <andras.timar@collabora.com>2017-02-08 11:56:05 +0100
commitb714c05213ff193d14db15ae3f0a1a60c8677848 (patch)
treee2ac2e1e1d09f03b2644baeda12e130113748124 /sc
parentbf4255849fad4a0674d75165452659e132d97bda (diff)
Resolves: tdf#104711 adjust range reference constructed of named anchors
A constructed range reference of named anchors (i.e. extended during expression compilation) forms a range listened at that needs to be adjusted if the cell is shifted and one or both anchor parts are individually named relative references. Currently the resulting range (ScComplexRefData aka DoubleRef) does not know to distinguish between whether its anchors are the result of a literal range in a named expression or the result of individually named anchors, so such RelName DoubleRef needs to be adjusted unconditionally when shifting or moving the formula cell. Change-Id: I75e2cc79ac60116671acce7641567337d5f5f7ed (cherry picked from commit 439b2a134218b93e6ca9fa23005b89c19498f586) Reviewed-on: https://gerrit.libreoffice.org/32924 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com> (cherry picked from commit 33c1491acb3fd6b87ac16d80ed728f423762e867)
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/formulacell.hxx9
-rw-r--r--sc/source/core/data/column.cxx2
-rw-r--r--sc/source/core/data/formulacell.cxx40
-rw-r--r--sc/source/core/tool/refdata.cxx4
4 files changed, 45 insertions, 10 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 5424cb48252f..f77d0a4406df 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -241,7 +241,14 @@ public:
It is similar to HasOneReference(), but more general.
*/
bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
- bool HasRelNameReference() const;
+
+ enum class RelNameRef
+ {
+ NONE, ///< no relative reference from named expression
+ SINGLE, ///< only single cell relative reference
+ DOUBLE ///< at least one range relative reference from named expression
+ };
+ RelNameRef HasRelNameReference() const;
bool UpdateReference(
const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 194a2347e465..da9e9d8e9cbd 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2825,7 +2825,7 @@ struct SetDirtyIfPostponedHandler
{
void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
{
- if (pCell->IsPostponedDirty() || pCell->HasRelNameReference())
+ if (pCell->IsPostponedDirty() || (pCell->HasRelNameReference() != ScFormulaCell::RelNameRef::NONE))
pCell->SetDirty();
}
};
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index e262e8faee7b..baa4301e04ac 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2879,18 +2879,34 @@ ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
return false;
}
-bool ScFormulaCell::HasRelNameReference() const
+ScFormulaCell::RelNameRef ScFormulaCell::HasRelNameReference() const
{
+ RelNameRef eRelNameRef = RelNameRef::NONE;
pCode->Reset();
formula::FormulaToken* t;
while ( ( t = pCode->GetNextReferenceRPN() ) != nullptr )
{
- if ( t->GetSingleRef()->IsRelName() ||
- (t->GetType() == formula::svDoubleRef &&
- t->GetDoubleRef()->Ref2.IsRelName()) )
- return true;
+ switch (t->GetType())
+ {
+ case formula::svSingleRef:
+ if (t->GetSingleRef()->IsRelName() && eRelNameRef == RelNameRef::NONE)
+ eRelNameRef = RelNameRef::SINGLE;
+ break;
+ case formula::svDoubleRef:
+ if (t->GetDoubleRef()->Ref1.IsRelName() || t->GetDoubleRef()->Ref2.IsRelName())
+ // May originate from individual cell names, in which case
+ // it needs recompilation.
+ return RelNameRef::DOUBLE;
+ /* TODO: have an extra flag at ScComplexRefData if range was
+ * extended? or too cumbersome? might narrow recompilation to
+ * only needed cases.
+ * */
+ break;
+ default:
+ ; // nothing
+ }
}
- return false;
+ return eRelNameRef;
}
bool ScFormulaCell::UpdatePosOnShift( const sc::RefUpdateContext& rCxt )
@@ -3095,7 +3111,13 @@ bool ScFormulaCell::UpdateReferenceOnShift(
bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());
// RelNameRefs are always moved
- bool bHasRelName = HasRelNameReference();
+ bool bHasRelName = false;
+ if (!bRecompile)
+ {
+ RelNameRef eRelNameRef = HasRelNameReference();
+ bHasRelName = (eRelNameRef != RelNameRef::NONE);
+ bRecompile = (eRelNameRef == RelNameRef::DOUBLE);
+ }
// Reference changed and new listening needed?
// Except in Insert/Delete without specialties.
bNewListening = (bRefModified || bRecompile
@@ -3219,7 +3241,9 @@ bool ScFormulaCell::UpdateReferenceOnMove(
bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo());
// RelNameRefs are always moved
- bHasRelName = HasRelNameReference();
+ RelNameRef eRelNameRef = HasRelNameReference();
+ bHasRelName = (eRelNameRef != RelNameRef::NONE);
+ bCompile |= (eRelNameRef == RelNameRef::DOUBLE);
// Reference changed and new listening needed?
// Except in Insert/Delete without specialties.
bNewListening = (bRefModified || bColRowNameCompile
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index a78036426312..93fc43e20d8f 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -451,6 +451,10 @@ ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const
if (rRef.IsFlag3D())
Ref1.SetFlag3D( true);
+ // Inherit RelNameRef from extending part.
+ if (rRef.IsRelName())
+ Ref2.SetRelName(true);
+
SetRange(aAbsRange, rPos);
return *this;