sc/qa/unit/ucalc.hxx | 2 sc/qa/unit/ucalc_formula.cxx | 115 +++++++++++++++++++++++++++++++++++++++ sc/source/core/tool/compiler.cxx | 35 +++++------ sc/source/core/tool/token.cxx | 12 +--- 4 files changed, 136 insertions(+), 28 deletions(-)
New commits: commit bf73c22c2110c8ca29e7a00e02d293a85e5db70e Author: Eike Rathke <er...@redhat.com> Date: Sun Jun 21 18:23:54 2015 +0200 unit test for adjustSingleRefInName() during column insertion Change-Id: Ie406361c3a3497619f4faf3680f389f3bdf76a4b (cherry picked from commit 8ade7dce21143cd280935b174f4359d3d6d6d20b) diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index 487981a..08026cb 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -1704,6 +1704,11 @@ void Test::testFormulaRefUpdateInsertColumns() m_pDoc->InsertTab(0, "Formula"); + // Set named range for B2 with absolute column and relative same row. + const ScAddress aNamePos(0,1,0); + bool bInserted = m_pDoc->InsertNewRangeName("RowRelativeRange", aNamePos, "$Formula.$B2"); + CPPUNIT_ASSERT(bInserted); + // Set values in B1:B3. m_pDoc->SetValue(ScAddress(1,0,0), 1.0); m_pDoc->SetValue(ScAddress(1,1,0), 2.0); @@ -1713,6 +1718,10 @@ void Test::testFormulaRefUpdateInsertColumns() m_pDoc->SetString(ScAddress(1,3,0), "=SUM(B1:B3)"); CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(1,3,0))); + // Use named range in C2 to reference B2. + m_pDoc->SetString(ScAddress(2,1,0), "=RowRelativeRange"); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(2,1,0))); + // Inert columns over A:B. ScMarkData aMark; aMark.SelectOneTable(0); @@ -1725,6 +1734,18 @@ void Test::testFormulaRefUpdateInsertColumns() CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(3,3,0))); + // Check that the named reference points to the moved cell, now D2. + ScRangeData* pName = m_pDoc->GetRangeName()->findByUpperName("ROWRELATIVERANGE"); + CPPUNIT_ASSERT(pName); + OUString aSymbol; + pName->GetSymbol(aSymbol, aNamePos, formula::FormulaGrammar::GRAM_ENGLISH); + CPPUNIT_ASSERT_EQUAL(OUString("$Formula.$D2"), aSymbol); + + // Check that the formula using the name, now in E2, still has the same result. + if (!checkFormula(*m_pDoc, ScAddress(4,1,0), "RowRelativeRange")) + CPPUNIT_FAIL("Wrong formula in E2 after column insertion."); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(4,1,0))); + m_pDoc->DeleteTab(0); } commit e6080277c586dbc9f02b9893dd561e98d76027ba Author: Eike Rathke <er...@redhat.com> Date: Sun Jun 21 17:50:10 2015 +0200 adjustSingleRefInName() handle relative column and row independently The absolute part needs to be adjusted when the referenced column or row is moved, even if the other part is relative. Change-Id: Ibd6c2f58b7e01ced4d2e521f29295c044d27924a (cherry picked from commit f35673a825ecd4c4b331302c0408c65b9906f97f) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 07b121c..8be2390 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -3227,18 +3227,12 @@ bool adjustSingleRefInName( return false; } - if (rRef.IsColRel() || rRef.IsRowRel()) - { - // Adjust references only when both column and row are absolute. - return false; - } - if (!rCxt.maRange.In(rRef.toAbs(rPos))) return false; bool bChanged = false; - if (rCxt.mnColDelta) + if (rCxt.mnColDelta && !rRef.IsColRel()) { // Adjust absolute column reference. if (rCxt.maRange.aStart.Col() <= rRef.Col() && rRef.Col() <= rCxt.maRange.aEnd.Col()) @@ -3248,7 +3242,7 @@ bool adjustSingleRefInName( } } - if (rCxt.mnRowDelta) + if (rCxt.mnRowDelta && !rRef.IsRowRel()) { // Adjust absolute row reference. if (rCxt.maRange.aStart.Row() <= rRef.Row() && rRef.Row() <= rCxt.maRange.aEnd.Row()) commit 17cffd941e34808f311e6ebb4014759ef59308c1 Author: Eike Rathke <er...@redhat.com> Date: Sun Jun 21 00:14:41 2015 +0200 TableRef: clone inner reference token in copy-ctor Change-Id: I4d195932bf81c105197de64cc592894e2492b801 (cherry picked from commit 6a3c3673d2d50cc42c1b92a841306232a8cf022f) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 00f1d45..07b121c 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -892,7 +892,7 @@ ScTableRefToken::ScTableRefToken( sal_uInt16 nIndex, ScTableRefToken::Item eItem ScTableRefToken::ScTableRefToken( const ScTableRefToken& r ) : FormulaToken(r), - mxAreaRefRPN(r.mxAreaRefRPN), + mxAreaRefRPN(r.mxAreaRefRPN->Clone()), mnIndex(r.mnIndex), meItem(r.meItem) { commit 3f2c50d0532746a6cd207e3cb91981ed0ba618e9 Author: Eike Rathke <er...@redhat.com> Date: Sat Jun 20 00:37:54 2015 +0200 TableRef: sheet reference always absolute and 3D Change-Id: I17a2889c21efe9943b348049a1e9384df167435d (cherry picked from commit 9e978e58650c18500aaea6e2e927d5439c65917f) diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 23b9d9f..64a7d61 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -5203,12 +5203,7 @@ bool ScCompiler::HandleTableRef() { aRefData.SetRowRel( true); } - if (aRange.aStart.Tab() != aPos.Tab()) - aRefData.SetFlag3D( true); - else - { - aRefData.SetTabRel( true); - } + aRefData.SetFlag3D( true); aRefData.SetAddress( aRange.aStart, aPos); pTR->SetAreaRefRPN( pNew->AddSingleReference( aRefData )); } @@ -5223,13 +5218,7 @@ bool ScCompiler::HandleTableRef() aRefData.Ref1.SetRowRel( true); aRefData.Ref2.SetRowRel( true); } - if (aRange.aStart.Tab() != aPos.Tab()) - aRefData.Ref1.SetFlag3D( true); - else - { - aRefData.Ref1.SetTabRel( true); - aRefData.Ref2.SetTabRel( true); - } + aRefData.Ref1.SetFlag3D( true); aRefData.SetRange( aRange, aPos); pTR->SetAreaRefRPN( pNew->AddDoubleReference( aRefData )); } commit d461f601f49abfd47ae398388b70c4e10ffbbc2f Author: Eike Rathke <er...@redhat.com> Date: Fri Jun 19 23:57:43 2015 +0200 TableRef: generated reference's column relativity follows column specifier Change-Id: Ie0781bf5ebeb4cec0e3bb96f8c471e469b1b223a (cherry picked from commit afa74bb6e8b828bdc08b8b214bce9c9c3797abdb) diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 662b6fd..23b9d9f 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -5079,6 +5079,8 @@ bool ScCompiler::HandleTableRef() break; } bool bColumnRange = false; + bool bCol1Rel = false; + bool bCol2Rel = false; int nLevel = 0; if (bForwardToClose && GetTokenIfOpCode( ocTableRefOpen)) { @@ -5128,6 +5130,7 @@ bool ScCompiler::HandleTableRef() if (eState == sOpen && p->GetType() == svSingleRef) { bColumnRange = true; + bCol1Rel = p->GetSingleRef()->IsColRel(); eState = sLast; } else @@ -5173,6 +5176,7 @@ bool ScCompiler::HandleTableRef() { aColRange.aEnd = mpToken->GetSingleRef()->toAbs( aPos); aColRange.Justify(); + bCol2Rel = mpToken->GetSingleRef()->IsColRel(); } } } @@ -5194,7 +5198,7 @@ bool ScCompiler::HandleTableRef() { ScSingleRefData aRefData; aRefData.InitFlags(); - aRefData.SetColRel( true); + aRefData.SetColRel( bCol1Rel); if (eItem == ScTableRefToken::THIS_ROW) { aRefData.SetRowRel( true); @@ -5212,8 +5216,8 @@ bool ScCompiler::HandleTableRef() { ScComplexRefData aRefData; aRefData.InitFlags(); - aRefData.Ref1.SetColRel( true); - aRefData.Ref2.SetColRel( true); + aRefData.Ref1.SetColRel( bCol1Rel); + aRefData.Ref2.SetColRel( bCol2Rel); if (eItem == ScTableRefToken::THIS_ROW) { aRefData.Ref1.SetRowRel( true); commit 85b7436b2c2060bb1168cc37eee537de417795e0 Author: Eike Rathke <er...@redhat.com> Date: Fri Jun 19 22:49:50 2015 +0200 TableRef: column specifier is an absolute reference Change-Id: Ia7de5dc101a410aa1c25f36e64627fa3461ee772 (cherry picked from commit 2a5f48f7f48804d5ac7d67c5a4f3f28315815a7a) diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 82fd38e..662b6fd 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -3451,10 +3451,14 @@ bool ScCompiler::IsTableRefColumn( const OUString& rName ) const OUString aStr = aIter.getString(); if (ScGlobal::GetpTransliteration()->isEqual( aStr, aName)) { + /* XXX NOTE: we could init the column as relative so copying a + * formula across columns would point to the relative column, + * but do it absolute because: + * a) it makes the reference work in named expressions without + * having to distinguish + * b) Excel does it the same. */ ScSingleRefData aRef; - aRef.InitFlags(); - aRef.SetColRel( true ); - aRef.SetAddress( aIter.GetPos(), aPos); + aRef.InitAddress( aIter.GetPos()); maRawToken.SetSingleReference( aRef ); return true; } commit 0cae2d3719403cf7266f1c5da9c5ee1e3977a7ca Author: Eike Rathke <er...@redhat.com> Date: Fri Jun 19 16:49:29 2015 +0200 add unit test for ocRangeOp and ScComplexRefData::Extend() Change-Id: Iae97c409a84f47d591ef8adf8e42fb6f52c104e2 (cherry picked from commit 72be3521524f1c01842010f26c234f4e6cceb358) diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index afc4d0a..da56b73 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -179,6 +179,7 @@ public: void testFuncGETPIVOTDATA(); void testFuncGETPIVOTDATALeafAccess(); void testMatrixOp(); + void testFuncRangeOp(); void testExternalRef(); void testExternalRefFunctions(); @@ -501,6 +502,7 @@ public: CPPUNIT_TEST(testFuncGETPIVOTDATA); CPPUNIT_TEST(testFuncGETPIVOTDATALeafAccess); CPPUNIT_TEST(testMatrixOp); + CPPUNIT_TEST(testFuncRangeOp); CPPUNIT_TEST(testExternalRef); CPPUNIT_TEST(testExternalRefFunctions); CPPUNIT_TEST(testCopyToDocument); diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index 09ac70d..487981a 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -4972,4 +4972,98 @@ void Test::testMatrixOp() m_pDoc->DeleteTab(0); } +void Test::testFuncRangeOp() +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc. + + m_pDoc->InsertTab(0, "Sheet1"); + m_pDoc->InsertTab(1, "Sheet2"); + m_pDoc->InsertTab(2, "Sheet3"); + + // Sheet1.B1:B3 + m_pDoc->SetValue(1,0,0, 1.0); + m_pDoc->SetValue(1,1,0, 2.0); + m_pDoc->SetValue(1,2,0, 4.0); + // Sheet2.B1:B3 + m_pDoc->SetValue(1,0,1, 8.0); + m_pDoc->SetValue(1,1,1, 16.0); + m_pDoc->SetValue(1,2,1, 32.0); + // Sheet3.B1:B3 + m_pDoc->SetValue(1,0,2, 64.0); + m_pDoc->SetValue(1,1,2, 128.0); + m_pDoc->SetValue(1,2,2, 256.0); + + // Range operator should extend concatenated literal references during + // parse time already, so with this we can test ScComplexRefData::Extend() + + // Current sheet is Sheet1, so B1:B2 implies relative Sheet1.B1:B2 + + ScAddress aPos(0,0,0); + m_pDoc->SetString( aPos, "=SUM(B1:B2:B3)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(B1:B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(B1:B3:B2)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(B1:B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(B2:B3:B1)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(B1:B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(Sheet2.B1:B2:B3)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(Sheet2.B1:B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 56.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(B2:B2:Sheet1.B2)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(Sheet1.B2:B2)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 2.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(B2:B3:Sheet2.B1)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(Sheet1.B1:Sheet2.B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 63.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(Sheet1.B1:Sheet2.B2:Sheet3.B3)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(Sheet1.B1:Sheet3.B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 511.0, m_pDoc->GetValue(aPos)); + + // B1:Sheet2.B2 would be ambiguous, Sheet1.B1:Sheet2.B2 or Sheet2.B1:B2 + // The actual representation of the error case may change, so this test may + // have to be adapted. + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(B1:Sheet2.B2:Sheet3.B3)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(#REF!.B2:#REF!.B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( OUString("#REF!"), m_pDoc->GetString(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(Sheet1.B1:Sheet3.B2:Sheet2.B3)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(Sheet1.B1:Sheet3.B3)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 511.0, m_pDoc->GetValue(aPos)); + + aPos.IncRow(); + m_pDoc->SetString( aPos, "=SUM(B$2:B$2:B2)"); + if (!checkFormula( *m_pDoc, aPos, "SUM(B$2:B2)")) + CPPUNIT_FAIL("Wrong formula."); + CPPUNIT_ASSERT_EQUAL( 2.0, m_pDoc->GetValue(aPos)); + + m_pDoc->DeleteTab(2); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits