sc/inc/table.hxx | 1 sc/qa/unit/ucalc.cxx | 75 +++++++++++++++++++++++++++++++++++++++++ sc/qa/unit/ucalc.hxx | 2 + sc/source/core/data/table3.cxx | 8 ++++ sc/source/core/data/table7.cxx | 8 ++++ 5 files changed, 94 insertions(+)
New commits: commit a3fc7f20089062afa4f778e70ba8be84032a30a7 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Sun Jul 27 14:35:37 2014 -0400 fdo#81617: Split formula groups at sort range boundaries. Otherwise, partially sorting a range may crash, or at best incorrectly update formula references. Change-Id: Iefcb86d205d83ccc5b684048bfd9aadabf6e13eb diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 44c4951..9701463 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -884,6 +884,7 @@ public: formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); formula::VectorRefArray FetchVectorRefArray( SCCOL nCol, SCROW nRow1, SCROW nRow2 ); + void SplitFormulaGroups( SCCOL nCol, std::vector<SCROW>& rRows ); void UnshareFormulaCells( SCCOL nCol, std::vector<SCROW>& rRows ); void RegroupFormulaCells( SCCOL nCol ); diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index a842d82..25e088f 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -751,6 +751,14 @@ void ScTable::SortReorderByRow( ScSortInfoArray::RowsType* pRows = pArray->GetDataRows(); assert(pRows); // In sort-by-row mode we must have data rows already populated. + // Split formula groups at the sort range boundaries (if applicable). + std::vector<SCROW> aRowBounds; + aRowBounds.reserve(2); + aRowBounds.push_back(nRow1); + aRowBounds.push_back(nRow2+1); + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + SplitFormulaGroups(nCol, aRowBounds); + // Cells in the data rows only reference values in the document. Make // a copy before updating the document. diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx index f39e529..6ff53de 100644 --- a/sc/source/core/data/table7.cxx +++ b/sc/source/core/data/table7.cxx @@ -118,6 +118,14 @@ bool ScTable::HasUniformRowHeight( SCROW nRow1, SCROW nRow2 ) const return nRow2 <= aData.mnRow2; } +void ScTable::SplitFormulaGroups( SCCOL nCol, std::vector<SCROW>& rRows ) +{ + if (!ValidCol(nCol)) + return; + + sc::SharedFormulaUtil::splitFormulaCellGroups(aCol[nCol].maCells, rRows); +} + void ScTable::UnshareFormulaCells( SCCOL nCol, std::vector<SCROW>& rRows ) { if (!ValidCol(nCol)) commit 97f700721e942912101d5acd73433448e57e39e5 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Sun Jul 27 14:25:23 2014 -0400 fdo#81617: Write test for this first. This test currently crashes. Change-Id: I57133495b483664c960a15e638520d195eb02070 diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 65c91a4..bbed0c7 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -5705,6 +5705,81 @@ void Test::testSortOutOfPlaceResult() m_pDoc->DeleteTab(0); } +void Test::testSortPartialFormulaGroup() +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on. + FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1); + + m_pDoc->InsertTab(0, "Sort"); + + // Set up the sheet. + const char* aData[][2] = { + { "F1", "F2" }, + { "43", "=RC[-1]" }, + { "50", "=RC[-1]" }, + { "8", "=RC[-1]" }, + { "47", "=RC[-1]" }, + { "28", "=RC[-1]" }, + { 0, 0 } // terminator + }; + + // A1:B6. + for (SCROW i = 0; aData[i][0]; ++i) + { + m_pDoc->SetString(0, i, 0, OUString::createFromAscii(aData[i][0])); + m_pDoc->SetString(1, i, 0, OUString::createFromAscii(aData[i][1])); + } + + // Check the initial condition. + for (SCROW i = 1; i <= 5; ++i) + // A2:A6 should equal B2:B6. + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetValue(ScAddress(0,i,0)), m_pDoc->GetValue(ScAddress(1,i,0))); + + const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,1,0)); + CPPUNIT_ASSERT(pFC); + CPPUNIT_ASSERT_MESSAGE("This formula cell should be the first in a group.", pFC->IsSharedTop()); + CPPUNIT_ASSERT_MESSAGE("Incorrect formula group length.", pFC->GetSharedLength() == 5); + + ScDBDocFunc aFunc(getDocShell()); + + // Sort only B2:B4. This caused crash at one point (c.f. fdo#81617). + + m_pDoc->SetAnonymousDBData(0, new ScDBData(STR_DB_LOCAL_NONAME, 0, 1, 1, 1, 3)); + + ScSortParam aSortData; + aSortData.nCol1 = 1; + aSortData.nCol2 = 1; + aSortData.nRow1 = 1; + aSortData.nRow2 = 3; + aSortData.bHasHeader = false; + aSortData.bInplace = true; + aSortData.maKeyState[0].bDoSort = true; + aSortData.maKeyState[0].nField = 0; + aSortData.maKeyState[0].bAscending = true; + bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + CPPUNIT_ASSERT(bSorted); + + m_pDoc->CalcAll(); // just in case... + + // Check the cell values after the partial sort. + + // Column A + CPPUNIT_ASSERT_EQUAL(43.0, m_pDoc->GetValue(ScAddress(0,1,0))); + CPPUNIT_ASSERT_EQUAL(50.0, m_pDoc->GetValue(ScAddress(0,2,0))); + CPPUNIT_ASSERT_EQUAL( 8.0, m_pDoc->GetValue(ScAddress(0,3,0))); + CPPUNIT_ASSERT_EQUAL(47.0, m_pDoc->GetValue(ScAddress(0,4,0))); + CPPUNIT_ASSERT_EQUAL(28.0, m_pDoc->GetValue(ScAddress(0,5,0))); + + // Column B + CPPUNIT_ASSERT_EQUAL( 8.0, m_pDoc->GetValue(ScAddress(1,1,0))); + CPPUNIT_ASSERT_EQUAL(43.0, m_pDoc->GetValue(ScAddress(1,2,0))); + CPPUNIT_ASSERT_EQUAL(50.0, m_pDoc->GetValue(ScAddress(1,3,0))); + CPPUNIT_ASSERT_EQUAL(47.0, m_pDoc->GetValue(ScAddress(1,4,0))); + CPPUNIT_ASSERT_EQUAL(28.0, m_pDoc->GetValue(ScAddress(1,5,0))); + + m_pDoc->DeleteTab(0); +} + void Test::testShiftCells() { m_pDoc->InsertTab(0, "foo"); diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index 92342c4..3197990 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -350,6 +350,7 @@ public: void testSortRefUpdate2(); void testSortRefUpdate3(); void testSortOutOfPlaceResult(); + void testSortPartialFormulaGroup(); void testShiftCells(); void testNoteBasic(); @@ -523,6 +524,7 @@ public: CPPUNIT_TEST(testSortRefUpdate2); CPPUNIT_TEST(testSortRefUpdate3); CPPUNIT_TEST(testSortOutOfPlaceResult); + CPPUNIT_TEST(testSortPartialFormulaGroup); CPPUNIT_TEST(testShiftCells); CPPUNIT_TEST(testNoteBasic); CPPUNIT_TEST(testNoteDeleteRow); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits