diff options
author | Eike Rathke <erack@redhat.com> | 2017-01-09 19:47:06 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2017-01-10 19:59:07 +0000 |
commit | 540e9f5f290b5801c10fa3a6e3ad9046607dcd9c (patch) | |
tree | 0748cb06529bf5410045892d052efce37f5506b8 /sc/source | |
parent | b6b0194661303d12e9c73ffadbe82afe77c862e2 (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/32923
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/data/column.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 40 | ||||
-rw-r--r-- | sc/source/core/tool/refdata.cxx | 4 |
3 files changed, 37 insertions, 9 deletions
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 7ffafdabb92b..ac65f8a1b7ca 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2834,7 +2834,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 bf6fc4ed20e4..b19bfba89bc9 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2906,18 +2906,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 ) @@ -3122,7 +3138,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 @@ -3246,7 +3268,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 53bf2e4866bb..d97289345ae5 100644 --- a/sc/source/core/tool/refdata.cxx +++ b/sc/source/core/tool/refdata.cxx @@ -455,6 +455,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; |