summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/rangenam.hxx15
-rw-r--r--sc/inc/tokenarray.hxx12
-rw-r--r--sc/qa/unit/ucalc.hxx2
-rw-r--r--sc/qa/unit/ucalc_formula.cxx56
-rw-r--r--sc/source/core/data/documen3.cxx2
-rw-r--r--sc/source/core/data/table1.cxx2
-rw-r--r--sc/source/core/tool/rangenam.cxx39
-rw-r--r--sc/source/core/tool/token.cxx85
8 files changed, 171 insertions, 42 deletions
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index 4a5944f8814b..e3b507e924c8 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -33,6 +33,10 @@
class ScDocument;
class ScTokenArray;
+namespace sc {
+ struct RefUpdateContext;
+}
+
typedef sal_uInt16 RangeType;
#define RT_NAME ((RangeType)0x0000)
@@ -65,7 +69,7 @@ private:
SCROW mnMaxRow;
SCCOL mnMaxCol;
- void CompileRangeData( const String& rSymbol, bool bSetError );
+ void CompileRangeData( const OUString& rSymbol, bool bSetError );
void InitCode();
public:
@@ -75,7 +79,7 @@ public:
SC_DLLPUBLIC ScRangeData( ScDocument* pDoc,
const OUString& rName,
- const String& rSymbol,
+ const OUString& rSymbol,
const ScAddress& rAdr = ScAddress(),
RangeType nType = RT_NAME,
const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT );
@@ -118,9 +122,7 @@ public:
SC_DLLPUBLIC void GetSymbol( OUString& rSymbol, const ScAddress& rPos, const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
void UpdateSymbol( OUStringBuffer& rBuffer, const ScAddress&,
const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT );
- void UpdateReference( UpdateRefMode eUpdateRefMode,
- const ScRange& r,
- SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bLocal = false );
+ void UpdateReference( const sc::RefUpdateContext& rCxt, bool bLocal = false );
bool IsModified() const { return bModified; }
SC_DLLPUBLIC void GuessPosition();
@@ -181,8 +183,7 @@ public:
SC_DLLPUBLIC ScRangeData* findByUpperName(const OUString& rName);
SC_DLLPUBLIC const ScRangeData* findByUpperName(const OUString& rName) const;
SC_DLLPUBLIC ScRangeData* findByIndex(sal_uInt16 i) const;
- void UpdateReference(UpdateRefMode eUpdateRefMode, const ScRange& rRange,
- SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bLocal = false);
+ void UpdateReference(const sc::RefUpdateContext& rCxt, bool bLocal = false);
void UpdateTabRef(SCTAB nTable, ScRangeData::TabRefUpdateMode eMode, SCTAB nNewTable = 0, SCTAB nNewSheets = 1);
void UpdateTranspose(const ScRange& rSource, const ScAddress& rDest);
void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY);
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index b3fb5ef375da..71d8c7aa442f 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -133,6 +133,18 @@ public:
const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos );
/**
+ * Adjust all references in named expression. In named expression, we only
+ * update absolute positions, and leave relative positions intact.
+ *
+ * Also, there is no such thing as the base position in named expressions.
+ *
+ * @param rCxt context that stores details of shifted region
+ *
+ * @return update result.
+ */
+ sc::RefUpdateResult AdjustReferenceInName( const sc::RefUpdateContext& rCxt );
+
+ /**
* Adjust all references on sheet deletion.
*
* @param nDelPos position of sheet being deleted.
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 5a1d0aea89e9..241331791c5a 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -90,6 +90,7 @@ public:
void testFormulaRefUpdateRange();
void testFormulaRefUpdateSheets();
void testFormulaRefUpdateMove();
+ void testFormulaRefUpdateNamedExpression();
void testFuncCOLUMN();
void testFuncROW();
void testFuncSUM();
@@ -282,6 +283,7 @@ public:
CPPUNIT_TEST(testFormulaRefUpdateRange);
CPPUNIT_TEST(testFormulaRefUpdateSheets);
CPPUNIT_TEST(testFormulaRefUpdateMove);
+ CPPUNIT_TEST(testFormulaRefUpdateNamedExpression);
CPPUNIT_TEST(testFuncCOLUMN);
CPPUNIT_TEST(testFuncROW);
CPPUNIT_TEST(testFuncSUM);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index def390273859..68c0f07ae3cb 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -964,6 +964,62 @@ void Test::testFormulaRefUpdateMove()
m_pDoc->DeleteTab(0);
}
+void Test::testFormulaRefUpdateNamedExpression()
+{
+ m_pDoc->InsertTab(0, "Formula");
+
+ sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+ // Fill C2:C5 with values.
+ m_pDoc->SetValue(ScAddress(2,1,0), 1);
+ m_pDoc->SetValue(ScAddress(2,2,0), 2);
+ m_pDoc->SetValue(ScAddress(2,3,0), 3);
+ m_pDoc->SetValue(ScAddress(2,4,0), 4);
+
+ // Add a named expression that references the immediate left cell.
+ ScRangeName* pGlobalNames = m_pDoc->GetRangeName();
+ CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames);
+ ScRangeData* pName = new ScRangeData(
+ m_pDoc, "ToLeft", "RC[-1]", ScAddress(2,1,0), RT_NAME, formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1);
+
+ bool bInserted = pGlobalNames->insert(pName);
+ CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted);
+
+ // Insert formulas in D2:D5 using the named expression.
+ m_pDoc->SetString(ScAddress(3,1,0), "=ToLeft");
+ m_pDoc->SetString(ScAddress(3,2,0), "=ToLeft");
+ m_pDoc->SetString(ScAddress(3,3,0), "=ToLeft");
+ m_pDoc->SetString(ScAddress(3,4,0), "=ToLeft");
+
+ // Make sure the results are correct.
+ CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(3,1,0));
+ CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(3,2,0));
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(3,3,0));
+ CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(3,4,0));
+
+ // Push cells in column C down by one cell.
+ m_pDoc->InsertRow(ScRange(2,0,0,2,0,0));
+
+ // Make sure the results change accordingly.
+ CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(3,1,0));
+ CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(3,2,0));
+ CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(3,3,0));
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(3,4,0));
+
+ // Move cells back.
+ m_pDoc->DeleteRow(ScRange(2,0,0,2,0,0));
+
+ // Make sure the results are back as well.
+ CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(3,1,0));
+ CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(3,2,0));
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(3,3,0));
+ CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(3,4,0));
+
+
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testFuncCOLUMN()
{
m_pDoc->InsertTab(0, "Formula");
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 04973f4db031..c9254bc0ce3b 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -1006,7 +1006,7 @@ void ScDocument::UpdateReference(
xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
if (pRangeName)
- pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ pRangeName->UpdateReference(rCxt, false);
if ( pDPCollection )
pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index f4bb6b9aac6e..86e8d1b2bd25 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -1475,7 +1475,7 @@ void ScTable::UpdateReference(
// Named expressions need to be updated before formulas acessing them.
if (mpRangeName)
- mpRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, true );
+ mpRangeName->UpdateReference(rCxt, true);
for ( ; i<=iMax; i++)
bUpdated |= aCol[i].UpdateReference(rCxt, pUndoDoc);
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index e838b49a412d..0f99769f87ee 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -33,6 +33,7 @@
#include "rechead.hxx"
#include "refupdat.hxx"
#include "document.hxx"
+#include "refupdatecontext.hxx"
#include "formula/errorcodes.hxx"
@@ -46,7 +47,7 @@ using ::std::unary_function;
ScRangeData::ScRangeData( ScDocument* pDok,
const OUString& rName,
- const String& rSymbol,
+ const OUString& rSymbol,
const ScAddress& rAddress,
RangeType nType,
const FormulaGrammar::Grammar eGrammar ) :
@@ -62,7 +63,7 @@ ScRangeData::ScRangeData( ScDocument* pDok,
mnMaxRow (-1),
mnMaxCol (-1)
{
- if (rSymbol.Len() > 0)
+ if (!rSymbol.isEmpty())
CompileRangeData( rSymbol, pDoc->IsImportingXML());
// Let the compiler set an error on unknown names for a subsequent
// CompileUnresolvedXML().
@@ -141,7 +142,7 @@ ScRangeData::~ScRangeData()
delete pCode;
}
-void ScRangeData::CompileRangeData( const String& rSymbol, bool bSetError )
+void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError )
{
if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
{
@@ -270,34 +271,13 @@ void ScRangeData::UpdateSymbol( OUStringBuffer& rBuffer, const ScAddress& rPos,
aComp.CreateStringFromTokenArray( rBuffer );
}
-void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode,
- const ScRange& r,
- SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bLocal )
+void ScRangeData::UpdateReference( const sc::RefUpdateContext& rCxt, bool /*bLocal*/ )
{
bool bChanged = false;
-
- pCode->Reset();
- if( pCode->GetNextReference() )
- {
- bool bSharedFormula = ((eType & RT_SHARED) == RT_SHARED);
- ScCompiler aComp( pDoc, aPos, *pCode );
- aComp.SetGrammar(pDoc->GetGrammar());
- const bool bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
- nDx, nDy, nDz,
- bChanged, bSharedFormula, bLocal);
- if (bSharedFormula)
- {
- if (bRelRef)
- eType = eType | RT_SHAREDMOD;
- else
- eType = eType & ~RT_SHAREDMOD;
- }
- }
-
- bModified = bChanged;
+ sc::RefUpdateResult aRes = pCode->AdjustReferenceInName(rCxt);
+ bModified = aRes.mbReferenceModified;
}
-
void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
{
bool bChanged = false;
@@ -733,12 +713,11 @@ ScRangeData* ScRangeName::findByIndex(sal_uInt16 i) const
return nPos < maIndexToData.size() ? maIndexToData[nPos] : NULL;
}
-void ScRangeName::UpdateReference(
- UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bLocal)
+void ScRangeName::UpdateReference(const sc::RefUpdateContext& rCxt, bool bLocal)
{
DataType::iterator itr = maData.begin(), itrEnd = maData.end();
for (; itr != itrEnd; ++itr)
- itr->second->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz, bLocal);
+ itr->second->UpdateReference(rCxt, bLocal);
}
void ScRangeName::UpdateTabRef(SCTAB nTable, ScRangeData::TabRefUpdateMode eMode, SCTAB nNewTable, SCTAB nNewSheets)
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index df54e8fbdacc..c5246920c578 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2156,7 +2156,6 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddres
AdjustSingleRefData( rRef1, rOldPos, rNewPos );
if (!bRangeName || !(rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel()))
AdjustSingleRefData( rRef2, rOldPos, rNewPos );
-
}
break;
case svSingleRef :
@@ -2169,8 +2168,6 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddres
// for range names only adjust if all parts are absolute
if (!bRangeName || !(rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()))
AdjustSingleRefData( rRef, rOldPos, rNewPos );
-
-
}
break;
default:
@@ -2536,6 +2533,88 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
namespace {
+bool adjustSingleRefInName( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
+{
+ if (rRef.IsTabRel())
+ // Ignore reference with relative sheet position for now.
+ return false;
+
+ if (rRef.Tab() < rCxt.maRange.aStart.Tab() || rCxt.maRange.aEnd.Tab() < rRef.Tab())
+ // References sheet that has not shifted. Don't change it.
+ return false;
+
+ bool bChanged = false;
+
+ if (!rRef.IsColRel() && rCxt.mnColDelta)
+ {
+ // Adjust absolute column reference.
+ if (rCxt.maRange.aStart.Col() <= rRef.Col() && rRef.Col() <= rCxt.maRange.aEnd.Col())
+ {
+ rRef.IncCol(rCxt.mnColDelta);
+ bChanged = true;
+ }
+ }
+
+ if (!rRef.IsRowRel() && rCxt.mnRowDelta)
+ {
+ // Adjust absolute row reference.
+ if (rCxt.maRange.aStart.Row() <= rRef.Row() && rRef.Row() <= rCxt.maRange.aEnd.Row())
+ {
+ rRef.IncRow(rCxt.mnRowDelta);
+ bChanged = true;
+ }
+ }
+
+ if (!rRef.IsTabRel() && rCxt.mnTabDelta)
+ {
+ // Sheet range has already been checked above.
+ rRef.IncTab(rCxt.mnTabDelta);
+ bChanged = true;
+ }
+
+ return bChanged;
+}
+
+}
+
+sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( const sc::RefUpdateContext& rCxt )
+{
+ 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 (adjustSingleRefInName(rRef, rCxt))
+ aRes.mbReferenceModified = true;
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScComplexRefData& rRef = pToken->GetDoubleRef();
+ if (adjustSingleRefInName(rRef.Ref1, rCxt))
+ aRes.mbReferenceModified = true;
+ if (adjustSingleRefInName(rRef.Ref2, rCxt))
+ aRes.mbReferenceModified = true;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ return aRes;
+}
+
+namespace {
+
bool adjustSingleRefOnDeletedTab( ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
{
ScAddress aAbs = rRef.toAbs(rOldPos);