/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
ScAddress aPos(1, 9, 0); // B10
m_pDoc->SetString(aPos, u"=A10*2"_ustr); // Insert into B10. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("Expected to be a non-shared cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("Expected to be a non-shared cell.", !pFC->IsShared());
aPos.SetRow(10); // B11
m_pDoc->SetString(aPos, u"=A11*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
aPos.SetRow(8); // B9
m_pDoc->SetString(aPos, u"=A9*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
aPos.SetRow(12); // B13
m_pDoc->SetString(aPos, u"=A13*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This formula cell shouldn't be shared yet.", pFC);
CPPUNIT_ASSERT_MESSAGE("This formula cell shouldn't be shared yet.", !pFC->IsShared());
// Insert a formula to B12, and B9:B13 should be shared.
aPos.SetRow(11); // B12
m_pDoc->SetString(aPos, u"=A12*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Insert formulas to B15:B16.
aPos.SetRow(14); // B15
m_pDoc->SetString(aPos, u"=A15*2"_ustr);
aPos.SetRow(15); // B16
m_pDoc->SetString(aPos, u"=A16*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(14), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Insert a formula to B14, and B9:B16 should be shared.
aPos.SetRow(13); // B14
m_pDoc->SetString(aPos, u"=A14*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Insert an incompatible formula to B12, to split the shared range to B9:B11 and B13:B16.
aPos.SetRow(11); // B12
m_pDoc->SetString(aPos, u"=$A$1*4"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell shouldn't be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell shouldn't be shared.", !pFC->IsShared());
aPos.SetRow(8); // B9
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
aPos.SetRow(12); // B13
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Extend B13:B16 to B13:B20.
aPos.SetRow(16); // B17
m_pDoc->SetString(aPos, u"=A17*2"_ustr);
aPos.IncRow();
m_pDoc->SetString(aPos, u"=A18*2"_ustr);
aPos.IncRow();
m_pDoc->SetString(aPos, u"=A19*2"_ustr);
aPos.IncRow();
m_pDoc->SetString(aPos, u"=A20*2"_ustr);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC->IsShared()); // B13:B20 should be shared.
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Empty B19. This should split it into B13:B18, and B20 non-shared.
aPos.SetRow(18);
m_pDoc->SetEmptyCell(aPos);
CPPUNIT_ASSERT_EQUAL_MESSAGE("This cell should have been emptied.", CELLTYPE_NONE, m_pDoc->GetCellType(aPos));
aPos.SetRow(12); // B13
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC); // B13:B18 should be shared.
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode()); // B20 should be non-shared.
aPos.SetRow(19); // B20
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B20 should be a formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell should be non-shared.", !pFC->IsShared());
// Empty B14, to make B13 non-shared and B15:B18 shared.
aPos.SetRow(13); // B14
m_pDoc->SetEmptyCell(aPos);
aPos.SetRow(12); // B13
pFC = m_pDoc->GetFormulaCell(aPos); // B13 should be non-shared.
CPPUNIT_ASSERT_MESSAGE("B13 should be a formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This cell should be non-shared.", !pFC->IsShared()); // B15:B18 should be shared.
aPos.SetRow(14); // B15
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(14), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Set numeric value to B15, to make B16:B18 shared.
aPos.SetRow(14);
m_pDoc->SetValue(aPos, 1.2);
aPos.SetRow(15);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC); // B16:B18 should be shared.
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(15), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Set string value to B16 to make B17:B18 shared.
aPos.SetRow(15);
ScCellValue aCell(svl::SharedString(u"Test"_ustr));
CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a string value.", CELLTYPE_STRING, aCell.getType());
aCell.commit(*m_pDoc, aPos);
CPPUNIT_ASSERT_EQUAL(aCell.getSharedString()->getString(), m_pDoc->GetString(aPos));
aPos.SetRow(16);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC); // B17:B18 should be shared.
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(16), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Set edit text to B17. Now B18 should be non-shared.
ScFieldEditEngine& rEditEngine = m_pDoc->GetEditEngine();
rEditEngine.SetTextCurrentDefaults(u"Edit Text"_ustr);
aPos.SetRow(16);
m_pDoc->SetEditText(aPos, rEditEngine.CreateTextObject());
CPPUNIT_ASSERT_EQUAL(CELLTYPE_EDIT, m_pDoc->GetCellType(aPos));
aPos.SetRow(17);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B18 should be a formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B18 should be non-shared.", !pFC->IsShared());
// Set up a new group for shared formulas in B2:B10.
clearRange(m_pDoc, ScRange(0,0,0,2,100,0));
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B10 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Delete A4:B8. This should split the grouping to B2:B3 and B9:B10.
clearRange(m_pDoc, ScRange(0,3,0,1,7,0));
aPos.SetRow(1);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
aPos.SetRow(8);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B9 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Delete rows 4:8 and shift row 9 and below up to row 4. This should // re-merge the two into a group of B2:B5.
m_pDoc->DeleteRow(ScRange(0,3,0,m_pDoc->MaxCol(),7,0));
aPos.SetRow(1);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Insert 2 rows at row 4, to split it into B2:B3 and B6:B7.
m_pDoc->InsertRow(ScRange(0,3,0,m_pDoc->MaxCol(),4,0));
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
aPos.SetRow(5);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B6 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Test implicit intersection with shared formulas.
aPos.Set(2,0,0);
{ // Insert data in C1:D2 and formulas in E1:E2 const std::vector<std::vector<constchar*>> aData = {
{ "5", "1", "=C:C/D:D" },
{ "4", "2", "=C:C/D:D" }
};
insertRangeData(m_pDoc, aPos, aData);
}
aPos.Set(4,1,0);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("E2 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=A11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=A12"_ustr, m_pDoc->GetFormula(1,2,0));
const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
// Insert cells over A11:B11 to shift to right. This should split the B1:B3 grouping into 3.
m_pDoc->InsertCol(ScRange(0,10,0,1,10,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=C11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=A12"_ustr, m_pDoc->GetFormula(1,2,0));
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", !pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,1,0));
CPPUNIT_ASSERT_MESSAGE("B2 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B2 should be a non-shared formula cell.", !pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,2,0));
CPPUNIT_ASSERT_MESSAGE("B3 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B3 should be a non-shared formula cell.", !pFC->IsShared());
// Delete cells over A11:B11 to bring it back to the previous state.
m_pDoc->DeleteCol(ScRange(0,10,0,1,10,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=A11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=A12"_ustr, m_pDoc->GetFormula(1,2,0));
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
// Insert cells over A11:A12 and shift down.
m_pDoc->InsertRow(ScRange(0,10,0,0,11,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=A13"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=A14"_ustr, m_pDoc->GetFormula(1,2,0));
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", !pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,1,0));
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
// Delete A11:A12 to bring it back to the way it was.
m_pDoc->DeleteRow(ScRange(0,10,0,0,11,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=A11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=A12"_ustr, m_pDoc->GetFormula(1,2,0));
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
// Insert cells over A11:B11 to shift to right again.
m_pDoc->InsertCol(ScRange(0,10,0,1,10,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=C11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=A12"_ustr, m_pDoc->GetFormula(1,2,0));
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", !pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,1,0));
CPPUNIT_ASSERT_MESSAGE("B2 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B2 should be a non-shared formula cell.", !pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,2,0));
CPPUNIT_ASSERT_MESSAGE("B3 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B3 should be a non-shared formula cell.", !pFC->IsShared());
// Insert cells over A12:B12 to shift to right.
m_pDoc->InsertCol(ScRange(0,11,0,1,11,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=A10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=C11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=C12"_ustr, m_pDoc->GetFormula(1,2,0));
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("B1 should be a non-shared formula cell.", !pFC->IsShared()); // B2 and B3 should be grouped.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,1,0));
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
// Insert cells over A10:B10 to shift to right.
m_pDoc->InsertCol(ScRange(0,9,0,1,9,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B1", u"=C10"_ustr, m_pDoc->GetFormula(1,0,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B2", u"=C11"_ustr, m_pDoc->GetFormula(1,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula in B3", u"=C12"_ustr, m_pDoc->GetFormula(1,2,0));
// B1:B3 should be now grouped.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("This must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
m_pDoc->DeleteTab(0);
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulasRefUpdateMove)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
m_pDoc->InsertTab(0, u"Test"_ustr);
// Set values in B2:B4. for (SCROW i = 1; i <= 3; ++i)
m_pDoc->SetValue(ScAddress(1,i,0), i);
// Make sure the values are really there.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,2,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,3,0)));
// Make sure the values have been moved for real.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,0,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,2,0)));
// The formulas should have been adjusted for the move.
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", u"=R[-1]C[-1]"_ustr, m_pDoc->GetFormula(2,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", u"=R[-1]C[-1]"_ustr, m_pDoc->GetFormula(2,2,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", u"=R[-1]C[-1]"_ustr, m_pDoc->GetFormula(2,3,0));
// The values should have moved back.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,2,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,3,0)));
// And the formulas should have been re-adjusted to their original references.
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", u"=RC[-1]"_ustr, m_pDoc->GetFormula(2,1,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", u"=RC[-1]"_ustr, m_pDoc->GetFormula(2,2,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", u"=RC[-1]"_ustr, m_pDoc->GetFormula(2,3,0));
m_pDoc->DeleteTab(0);
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulasRefUpdateMove2)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, false); // turn auto calc off this time.
FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
m_pDoc->InsertTab(0, u"Test"_ustr);
// Set values in B2:B3, and E2:E3. for (SCROW i = 1; i <= 2; ++i)
{
m_pDoc->SetValue(ScAddress(1,i,0), i);
m_pDoc->SetValue(ScAddress(4,i,0), i);
}
// Make sure the values are really there.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,2,0)));
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(4,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(4,2,0)));
{ // Set formulas in C2:C3 that reference B2:B3 individually, and F2:F3 to E2:E3. const std::vector<std::vector<constchar*>> aData = {
{ "=RC[-1]" },
{ "=RC[-1]" }
};
// Make sure the range has been moved.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(2,2,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(2,3,0)));
// The formula cells should retain their results even with auto calc off // and without recalculation.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(3,2,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(3,3,0)));
// And these formulas in F2:F3 are unaffected, therefore should not change.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(5,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(5,2,0)));
// Check the formula results. The results should still be intact.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(2,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(2,2,0)));
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(5,1,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(5,2,0)));
// B3:B5 should be shared. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,2,0));
CPPUNIT_ASSERT_MESSAGE("B3 should be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("B3 should be shared.", pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,3,0));
CPPUNIT_ASSERT_MESSAGE("B4 should be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("B4 should be shared.", pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,4,0));
CPPUNIT_ASSERT_MESSAGE("B3 should be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("B3 should be shared.", pFC->IsShared());
// Insert 2 rows at row 1.
m_pDoc->InsertRow(ScRange(0,0,0,m_pDoc->MaxCol(),1,0));
// B5:B7 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,4,0));
CPPUNIT_ASSERT_MESSAGE("B5 should be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("B5 should be shared.", pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,5,0));
CPPUNIT_ASSERT_MESSAGE("B6 should be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("B6 should be shared.", pFC->IsShared());
pFC = m_pDoc->GetFormulaCell(ScAddress(1,6,0));
CPPUNIT_ASSERT_MESSAGE("B7 should be shared.", pFC);
CPPUNIT_ASSERT_MESSAGE("B7 should be shared.", pFC->IsShared());
// Check the area listener status.
ScBroadcastAreaSlotMachine* pBASM = m_pDoc->GetBASM();
CPPUNIT_ASSERT(pBASM);
std::vector<sc::AreaListener> aListeners = pBASM->GetAllListeners(aWholeArea, sc::AreaOverlapType::Inside);
std::sort(aListeners.begin(), aListeners.end(), SortByArea());
// This check makes only sense if group listeners are activated. #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER
CPPUNIT_ASSERT_EQUAL_MESSAGE("There should only be 2 area listeners.", size_t(2), aListeners.size()); // First one should be group-listening on A1:B2.
CPPUNIT_ASSERT_EQUAL_MESSAGE("This listener should be listening on A1:B2.", ScRange(0,0,0,1,1,0), aListeners[0].maArea);
CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening); // Second one should be group-listening on A4:B5.
CPPUNIT_ASSERT_EQUAL_MESSAGE("This listener should be listening on A1:B2.", ScRange(0,0,0,1,1,0), aListeners[0].maArea);
CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening); #endif
// Make sure that C1:C2 and C4:C5 are formula groups. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
// Delete row 3. This will merge the two formula groups.
ScDocFunc& rFunc = m_xDocShell->GetDocFunc();
ScMarkData aMark(m_pDoc->GetSheetLimits());
aMark.SelectOneTable(0);
rFunc.DeleteCells(ScRange(0,2,0,m_pDoc->MaxCol(),2,0), &aMark, DelCellCmd::Rows, true);
// Make sure C1:C4 belong to the same group.
pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
// This check makes only sense if group listeners are activated. #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER // We should only have one listener group-listening on A1:B4.
aListeners = pBASM->GetAllListeners(aWholeArea, sc::AreaOverlapType::Inside);
CPPUNIT_ASSERT_EQUAL_MESSAGE("There should only be 1 area listener.", size_t(1), aListeners.size());
CPPUNIT_ASSERT_EQUAL_MESSAGE("This listener should be listening on A1:B4.", ScRange(0,0,0,1,3,0), aListeners[0].maArea);
CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening); #endif
// Change the value of B4 and make sure the value of C4 changes.
rFunc.SetValueCell(ScAddress(1,3,0), 100.0, false);
CPPUNIT_ASSERT_EQUAL(107.0, m_pDoc->GetValue(ScAddress(2,3,0)));
// Undo the value change in B4, and make sure C4 follows.
pUndoMgr->Undo();
CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2,3,0)));
// Undo the deletion of row 3.
pUndoMgr->Undo();
// Make sure that C1:C2 and C4:C5 are formula groups again.
pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
// This check makes only sense if group listeners are activated. #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER
CPPUNIT_ASSERT_EQUAL_MESSAGE("There should only be 2 area listeners.", size_t(2), aListeners.size()); // First one should be group-listening on A1:B2.
CPPUNIT_ASSERT_EQUAL_MESSAGE("This listener should be listening on A1:B2.", ScRange(0,0,0,1,1,0), aListeners[0].maArea);
CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening); // Second one should be group-listening on A4:B5.
CPPUNIT_ASSERT_EQUAL_MESSAGE("This listener should be listening on A1:B2.", ScRange(0,0,0,1,1,0), aListeners[0].maArea);
CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening); #endif
m_pDoc->DeleteTab(0);
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulasRefUpdateExternal)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
m_pDoc->InsertTab(0, u"Formula"_ustr);
// Launch an external document shell.
ScDocShellRef xExtDocSh = new ScDocShell;
// Delete rows 1 and 2. This should not change the references in the formula cells below.
ScDocFunc& rDocFunc = m_xDocShell->GetDocFunc();
ScMarkData aMark(m_pDoc->GetSheetLimits());
aMark.SelectOneTable(0);
rDocFunc.DeleteCells(ScRange(0,0,0,m_pDoc->MaxCol(),1,0), &aMark, DelCellCmd::CellsUp, true);
// Check the shifted formula cells now in A5:A8.
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula!", u"='file:///extdata.fake'#$Data.A1"_ustr, m_pDoc->GetFormula(0,4,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula!", u"='file:///extdata.fake'#$Data.A2"_ustr, m_pDoc->GetFormula(0,5,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula!", u"='file:///extdata.fake'#$Data.A3"_ustr, m_pDoc->GetFormula(0,6,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula!", u"=COUNTA('file:///extdata.fake'#$Data.A1:A3)"_ustr, m_pDoc->GetFormula(0,7,0));
// Insert a new row at row 3.
ScDocFunc& rFunc = m_xDocShell->GetDocFunc();
ScMarkData aMark(m_pDoc->GetSheetLimits());
aMark.SelectOneTable(0);
rFunc.InsertCells(ScRange(0,2,0,m_pDoc->MaxCol(),2,0), &aMark, INS_INSROWS_BEFORE, true, true);
bool bResult = aCheck.checkContent(m_pDoc);
CPPUNIT_ASSERT_MESSAGE("Failed on the initial content check.", bResult);
// Undo and check its result.
SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
CPPUNIT_ASSERT(pUndoMgr);
pUndoMgr->Undo();
bResult = aCheck.checkContentUndo(m_pDoc);
CPPUNIT_ASSERT_MESSAGE("Failed on the content check after undo.", bResult);
// Redo and check its result.
pUndoMgr->Redo();
bResult = aCheck.checkContent(m_pDoc);
CPPUNIT_ASSERT_MESSAGE("Failed on the content check after redo.", bResult);
// B1:B10 should be shared. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength()); // B11:B20 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,10,0));
CPPUNIT_ASSERT_MESSAGE("1,10 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,10 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
// B1:B8 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength()); // B9:B16 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,8,0));
CPPUNIT_ASSERT_MESSAGE("1,8 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,8 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
// B1:B7 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(7), pFC->GetSharedLength()); // B8:B15 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,7,0));
CPPUNIT_ASSERT_MESSAGE("1,7 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,7 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(7), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
// B1:B6 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,0 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedLength()); // B7:B14 should be shared.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,6,0));
CPPUNIT_ASSERT_MESSAGE("1,6 must be a shared formula cell.", pFC);
CPPUNIT_ASSERT_MESSAGE("1,6 must be a shared formula cell.", pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
}
// First, test a single cell case. A value in B1 and formula in C1.
m_pDoc->SetValue(ScAddress(1,0,0), 11.0);
m_pDoc->SetString(ScAddress(2,0,0), u"=RC[-1]"_ustr);
CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(2,0,0)));
// Delete column B.
rFunc.DeleteCells(ScRange(1,0,0,1,m_pDoc->MaxRow(),0), &aMark, DelCellCmd::CellsLeft, true);
CPPUNIT_ASSERT_EQUAL(u"#REF!"_ustr, m_pDoc->GetString(ScAddress(1,0,0)));
// The reference should still point to row 1 but the column status should be set to 'deleted'. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT(pFC); const ScTokenArray* pCode = pFC->GetCode();
CPPUNIT_ASSERT(pCode);
CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pCode->GetLen()); const FormulaToken* pToken = pCode->GetArray()[0];
CPPUNIT_ASSERT_EQUAL(svSingleRef, pToken->GetType()); const ScSingleRefData* pSRef = pToken->GetSingleRef();
CPPUNIT_ASSERT(pSRef->IsColDeleted());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pSRef->toAbs(*m_pDoc, ScAddress(1,0,0)).Row());
// The formula string should show #REF! in lieu of the column position (only for Calc A1 syntax).
sc::CompileFormulaContext aCFCxt(*m_pDoc, FormulaGrammar::GRAM_ENGLISH);
CPPUNIT_ASSERT_EQUAL(u"=#REF!1"_ustr, pFC->GetFormula(aCFCxt));
// Undo and make sure the deleted flag is gone.
pUndoMgr->Undo();
CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(2,0,0)));
pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(u"=B1"_ustr, pFC->GetFormula(aCFCxt));
// Clear row 1 and move over to a formula group case.
clearRange(m_pDoc, ScRange(0,0,0,m_pDoc->MaxCol(),0,0));
// Fill A1:B2 with numbers, and C1:C2 with formula that reference those numbers. for (SCROW i = 0; i <= 1; ++i)
{
m_pDoc->SetValue(ScAddress(0,i,0), (i+1));
m_pDoc->SetValue(ScAddress(1,i,0), (i+11));
m_pDoc->SetString(ScAddress(2,i,0), u"=RC[-2]+RC[-1]"_ustr); double fCheck = m_pDoc->GetValue(ScAddress(0,i,0));
fCheck += m_pDoc->GetValue(ScAddress(1,i,0));
CPPUNIT_ASSERT_EQUAL(fCheck, m_pDoc->GetValue(ScAddress(2,i,0)));
}
// Delete column B.
rFunc.DeleteCells(ScRange(1,0,0,1,m_pDoc->MaxRow(),0), &aMark, DelCellCmd::CellsLeft, true);
for (SCROW i = 0; i <= 1; ++i)
{
ScAddress aPos(1,i,0);
CPPUNIT_ASSERT_EQUAL(u"#REF!"_ustr, m_pDoc->GetString(aPos));
}
// Undo deletion of column B and check the results of C1:C2.
pUndoMgr->Undo(); for (SCROW i = 0; i <= 1; ++i)
{ double fCheck = m_pDoc->GetValue(ScAddress(0,i,0));
fCheck += m_pDoc->GetValue(ScAddress(1,i,0));
CPPUNIT_ASSERT_EQUAL(fCheck, m_pDoc->GetValue(ScAddress(2,i,0)));
}
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // make sure auto calc is on.
// Switch to R1C1 for ease of repeated formula insertions.
FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
// Fill numbers in A1:A8 on Sheet2. for (SCROW i = 0; i <= 7; ++i)
m_pDoc->SetValue(ScAddress(0,i,1), i+1);
// Fill formula cells A1:A8 on Sheet1, to refer to the same cell address on Sheet2. for (SCROW i = 0; i <= 7; ++i)
m_pDoc->SetString(ScAddress(0,i,0), u"=Sheet2!RC"_ustr);
// Check the results. for (SCROW i = 0; i <= 7; ++i)
CPPUNIT_ASSERT_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(ScAddress(0,i,0)));
// Move Sheet3 to the leftmost position before Sheet1.
m_pDoc->MoveTab(2, 0);
// Check sheet names.
std::vector<OUString> aTabNames = m_pDoc->GetAllTableNames();
CPPUNIT_ASSERT_MESSAGE("There should be at least 3 sheets.", aTabNames.size() >= 3);
CPPUNIT_ASSERT_EQUAL(u"Sheet3"_ustr, aTabNames[0]);
CPPUNIT_ASSERT_EQUAL(u"Sheet1"_ustr, aTabNames[1]);
CPPUNIT_ASSERT_EQUAL(u"Sheet2"_ustr, aTabNames[2]);
// Check the results again on Sheet1. for (SCROW i = 0; i <= 7; ++i)
{
CPPUNIT_ASSERT_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(ScAddress(0,i,1)));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula expression.", u"=Sheet2!RC"_ustr, m_pDoc->GetFormula(0,i,1));
}
// Insert a new sheet at the left end.
m_pDoc->InsertTab(0, u"Sheet4"_ustr);
// Check sheet names.
aTabNames = m_pDoc->GetAllTableNames();
CPPUNIT_ASSERT_MESSAGE("There should be at least 4 sheets.", aTabNames.size() >= 4);
CPPUNIT_ASSERT_EQUAL(u"Sheet4"_ustr, aTabNames[0]);
CPPUNIT_ASSERT_EQUAL(u"Sheet3"_ustr, aTabNames[1]);
CPPUNIT_ASSERT_EQUAL(u"Sheet1"_ustr, aTabNames[2]);
CPPUNIT_ASSERT_EQUAL(u"Sheet2"_ustr, aTabNames[3]);
// Check the results again on Sheet1. for (SCROW i = 0; i <= 7; ++i)
{
CPPUNIT_ASSERT_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(ScAddress(0,i,2)));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula expression.", u"=Sheet2!RC"_ustr, m_pDoc->GetFormula(0,i,2));
}
// Delete Sheet4.
m_pDoc->DeleteTab(0);
// Check sheet names.
aTabNames = m_pDoc->GetAllTableNames();
CPPUNIT_ASSERT_MESSAGE("There should be at least 3 sheets.", aTabNames.size() >= 3);
CPPUNIT_ASSERT_EQUAL(u"Sheet3"_ustr, aTabNames[0]);
CPPUNIT_ASSERT_EQUAL(u"Sheet1"_ustr, aTabNames[1]);
CPPUNIT_ASSERT_EQUAL(u"Sheet2"_ustr, aTabNames[2]);
// Check the results again on Sheet1. for (SCROW i = 0; i <= 7; ++i)
{
CPPUNIT_ASSERT_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(ScAddress(0,i,1)));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula expression.", u"=Sheet2!RC"_ustr, m_pDoc->GetFormula(0,i,1));
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulasRefUpdateCopySheets)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // make sure auto calc is on.
m_pDoc->SetValue(ScAddress(0,0,1), 1.0); // A1 on Sheet2
m_pDoc->SetValue(ScAddress(0,1,1), 2.0); // A2 on Sheet2
// Reference values on Sheet2, but use absolute sheet references.
m_pDoc->SetString(ScAddress(0,0,0), u"=$Sheet2.A1"_ustr);
m_pDoc->SetString(ScAddress(0,1,0), u"=$Sheet2.A2"_ustr);
// Check the values on the copied sheet.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,0,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0,1,0)));
// Check the values on the original sheet.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,0,1)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0,1,1)));
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulasRefUpdateDeleteSheets)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // make sure auto calc is on.
// Set values to B2:B4 on Sheet2.
m_pDoc->SetValue(ScAddress(1,1,1), 1.0);
m_pDoc->SetValue(ScAddress(1,2,1), 2.0);
m_pDoc->SetValue(ScAddress(1,3,1), 3.0);
// Set formulas in A1:A3 on Sheet1 that reference B2:B4 on Sheet2.
m_pDoc->SetString(ScAddress(0,0,0), u"=Sheet2.B2"_ustr);
m_pDoc->SetString(ScAddress(0,1,0), u"=Sheet2.B3"_ustr);
m_pDoc->SetString(ScAddress(0,2,0), u"=Sheet2.B4"_ustr);
// Check the formula results.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0,0,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0,1,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0,2,0)));
// Undo the deletion and make sure the formulas are back to the way they were.
SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
CPPUNIT_ASSERT(pUndoMgr);
pUndoMgr->Undo();
// Fill formula cells B1:B10. for (SCROW i = 0; i <= 9; ++i)
m_pDoc->SetString(1, i, 0, u"=RC[-1]"_ustr);
ScAddress aPos(1, 8, 0); // B9
ScFormulaCell* pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B9 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Copy formulas in B6:B9 to the clipboard doc.
ScRange aSrcRange(1,5,0,1,8,0); // B6:B9
ScDocument aClipDoc(SCDOCMODE_CLIP);
copyToClip(m_pDoc, aSrcRange, &aClipDoc);
pFC = aClipDoc.GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("B9 in the clip doc should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// Paste them to C2:C10.
ScRange aDestRange(2,1,0,2,9,0);
pasteFromClip(m_pDoc, aDestRange, &aClipDoc);
aPos.SetCol(2);
aPos.SetRow(1);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("C2 should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
// First, make sure the formula cells are shared in the undo document.
aPos.SetCol(1); for (SCROW i = 0; i <= 9; ++i)
{
aPos.SetRow(i);
pFC = pUndoDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("Must be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
}
// Overwrite B1:B10. for (SCROW i = 0; i <= 9; ++i)
m_pDoc->SetValue(ScAddress(1,i,0), i*10);
for (SCROW i = 0; i <= 9; ++i)
CPPUNIT_ASSERT_EQUAL_MESSAGE("Numeric cell was expected.", CELLTYPE_VALUE, m_pDoc->GetCellType(ScAddress(1,i,0)));
// Undo the action to fill B1:B10 with formula cells again.
pUndo->Undo();
aPos.SetCol(1); for (SCROW i = 0; i <= 9; ++i)
{
aPos.SetRow(i);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(10), pFC->GetSharedLength());
CPPUNIT_ASSERT_EQUAL_MESSAGE("The token is expected to be shared.", pFC->GetCode(), pFC->GetSharedCode());
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulaMoveBlock)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
m_pDoc->InsertTab(0, u"Test"_ustr);
// Set values to A1:A3.
m_pDoc->SetValue(ScAddress(0,0,0), 1.0);
m_pDoc->SetValue(ScAddress(0,1,0), 2.0);
m_pDoc->SetValue(ScAddress(0,2,0), 3.0);
// Set formulas in B1:B3 to reference A1:A3.
m_pDoc->SetString(ScAddress(1,0,0), u"=RC[-1]"_ustr);
m_pDoc->SetString(ScAddress(1,1,0), u"=RC[-1]"_ustr);
m_pDoc->SetString(ScAddress(1,2,0), u"=RC[-1]"_ustr);
// The result should stay the same.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,0,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,2,0)));
// Make sure these formula cells in B1:B3 have correct positions even after the move.
std::vector<SCROW> aRows { 0, 1, 2 }; bool bRes = checkFormulaPositions(*m_pDoc, 0, 1, aRows.data(), aRows.size());
CPPUNIT_ASSERT(bRes);
// Check the formula values again. They should not change.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,0,0)));
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1,2,0)));
CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(1,3,0)));
CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(1,4,0)));
// Set values to A1:A4.
m_pDoc->SetValue(ScAddress(0,0,0), 1.0);
m_pDoc->SetValue(ScAddress(0,1,0), 2.0);
m_pDoc->SetValue(ScAddress(0,2,0), 3.0);
m_pDoc->SetValue(ScAddress(0,3,0), 4.0);
// Set formula to B1:B3.
m_pDoc->SetString(ScAddress(1,0,0), u"=SUM(MyRange)"_ustr);
m_pDoc->SetString(ScAddress(1,1,0), u"=SUM(MyRange)"_ustr);
m_pDoc->SetString(ScAddress(1,2,0), u"=SUM(MyRange)"_ustr);
// Set single formula with no named range to B5.
m_pDoc->SetString(ScAddress(1,4,0), u"=ROW()"_ustr);
// Set shared formula with no named range to B7:B8.
m_pDoc->SetString(ScAddress(1,6,0), u"=ROW()"_ustr);
m_pDoc->SetString(ScAddress(1,7,0), u"=ROW()"_ustr);
// B1:B3 should be grouped.
ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
// B7:B8 should be grouped.
pFC = m_pDoc->GetFormulaCell(ScAddress(1,6,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
// Set a single formula to C1.
m_pDoc->SetString(ScAddress(2,0,0), u"=AVERAGE(MyRange)"_ustr);
pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("C1 should not be shared.", !pFC->IsShared());
CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(2,0,0)));
// Update the range of MyRange.
pNames.reset(new ScRangeName);
aName.mpExpr = pExpr2;
bSuccess = insertRangeNames(m_pDoc, pNames.get(), &aName, &aName + 1);
CPPUNIT_ASSERT(bSuccess);
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pNames->size());
ScDocFunc& rFunc = m_xDocShell->GetDocFunc();
// Change the value of A4 and make sure the value change gets propagated.
m_pDoc->SetValue(ScAddress(0,3,0), 0.0);
CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(1,0,0)));
CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(1,2,0)));
m_pDoc->DeleteTab(0);
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulaUpdateOnDBChange)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
m_pDoc->InsertTab(0, u"RangeTest"_ustr);
// Put 1, 2, 3, 4 in A1:A4. for (SCROW i = 0; i <= 3; ++i)
m_pDoc->SetValue(ScAddress(0,i,0), (i+1));
ScDBCollection* pDBs = m_pDoc->GetDBCollection();
CPPUNIT_ASSERT_MESSAGE("Failed to fetch DB collection object.", pDBs);
// Define database range 'MyRange' for A1:A2.
std::unique_ptr<ScDBData> pData(new ScDBData(u"MyRange"_ustr, 0, 0, 0, 0, 1)); bool bInserted = pDBs->getNamedDBs().insert(std::move(pData));
CPPUNIT_ASSERT_MESSAGE("Failed to insert a new database range.", bInserted);
// Insert in C2:C4 a group of formula cells that reference MyRange. for (SCROW i = 1; i <= 3; ++i)
m_pDoc->SetString(ScAddress(2,i,0), u"=SUM(MyRange)"_ustr);
// Make sure C2:C4 is a formula group. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(2,1,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT(pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
// Check the initial formula results.
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(2,1,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(2,2,0)));
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(2,3,0)));
ScDBDocFunc aFunc(*m_xDocShell);
// Change the range referenced by MyRange to A1:A4.
ScDBCollection aNewDBs(*m_pDoc);
std::unique_ptr<ScDBData> pNewData(new ScDBData(u"MyRange"_ustr, 0, 0, 0, 0, 3));
bInserted = aNewDBs.getNamedDBs().insert(std::move(pNewData));
CPPUNIT_ASSERT_MESSAGE("Failed to insert a new database range.", bInserted);
// A1 should have 3 listeners listening into it. const SvtBroadcaster* pBC = m_pDoc->GetBroadcaster(ScAddress(0,0,0));
CPPUNIT_ASSERT(pBC);
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pBC->GetAllListeners().size());
// Check the formula results.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,0,0)));
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,1,0)));
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1,2,0)));
// Change the value of A1 and make sure B1:B3 follows.
m_pDoc->SetValue(ScAddress(0,0,0), 2.5);
// Check that A1:A3 is a formula group. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
m_pDoc->SetValue(ScAddress(0,1,0), 23.0); // unshare at A2
m_pDoc->SetValue(ScAddress(1,1,0), 16.0); // change value of B2
m_pDoc->SetValue(ScAddress(1,2,0), 32.0); // change value of B3 // A1 and A3 should be recalculated.
CPPUNIT_ASSERT_EQUAL(17.0, m_pDoc->GetValue(ScAddress(0,0,0)));
CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(0,2,0)));
// Check that A2:A6 is a formula group.
pFC = m_pDoc->GetFormulaCell(aOrgPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("A2", pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared top row.", aOrgPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared length.", static_cast<SCROW>(5), pFC->GetSharedLength());
// Overwrite and thus unshare formula in A3. // Check different code paths with different methods.
ScAddress aPos(aOrgPos);
aPos.IncRow(2); switch (nRun)
{ case 0: // Directly set a different formula cell, which bypasses // ScDocument::SetString(), mimicking formula input in view.
{
ScFormulaCell* pCell = new ScFormulaCell( *m_pDoc, aPos, u"=B4"_ustr);
ScDocFunc& rDocFunc = m_xDocShell->GetDocFunc();
rDocFunc.SetFormulaCell( aPos, pCell, false);
} break; case 1:
m_pDoc->SetString( aPos, u"=B4"_ustr); // set formula break; case 2:
m_pDoc->SetString( aPos, u"x"_ustr); // set string break; case 3:
m_pDoc->SetString( aPos, u"4096"_ustr); // set number/numeric break; case 4:
m_pDoc->SetValue( aPos, 4096.0); // set numeric break; case 5:
m_pDoc->SetValues( aPos, {4096.0}); // set numeric vector break; case 6: // Set formula cell vector.
{
ScFormulaCell* pCell = new ScFormulaCell( *m_pDoc, aPos, u"=B4"_ustr);
std::vector<ScFormulaCell*> aCells { pCell };
m_pDoc->SetFormulaCells( aPos, aCells);
} break;
}
// Check that A2:A3 and A5:A6 are two formula groups.
aPos = aOrgPos;
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("A2", pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared top row.", aPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared length.", static_cast<SCROW>(2), pFC->GetSharedLength());
aPos.IncRow(3);
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("A5", pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared top row.", aPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared length.", static_cast<SCROW>(2), pFC->GetSharedLength());
// Check that listeners were set up and formulas are updated when B2:B6 // get new values input (tdf#123736).
aPos = aOrgPos;
aPos.IncCol();
m_pDoc->SetValues( aPos, {1024.0, 2048.0, 4096.0, 8192.0, 16384.0});
aPos = aOrgPos;
CPPUNIT_ASSERT_EQUAL(1026.0, m_pDoc->GetValue(aPos));
aPos.IncRow();
CPPUNIT_ASSERT_EQUAL(2056.0, m_pDoc->GetValue(aPos));
aPos.IncRow(); if (nRun != 2) // if not string
CPPUNIT_ASSERT_EQUAL(4096.0, m_pDoc->GetValue(aPos));
aPos.IncRow();
CPPUNIT_ASSERT_EQUAL(8320.0, m_pDoc->GetValue(aPos));
aPos.IncRow();
CPPUNIT_ASSERT_EQUAL(16896.0, m_pDoc->GetValue(aPos));
clearRange(m_pDoc, ScRange( 0,0,0, 2,5,0));
}
// Check detach/regroup combinations of overlapping when setting formula // cell vectors.
{ // Fixed data in A3:C7, modified formula range A1:A9 const ScAddress aOrgPos(0,2,0);
ScAddress aPos( ScAddress::UNINITIALIZED);
ScFormulaCell* pCell;
std::vector<ScFormulaCell*> aCells; const std::vector<std::vector<constchar*>> aData2 = {
{ "=SUM(B3:C3)", "1", "2" },
{ "=SUM(B4:C4)", "4", "8" },
{ "=SUM(B5:C5)", "16", "32" },
{ "=SUM(B6:C6)", "64", "128" },
{ "=SUM(B7:C7)", "256", "512" },
};
// Check it is one formula group.
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("A1", pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared top row.", aPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared length.", static_cast<SCROW>(7), pFC->GetSharedLength());
// Check notification of setting new values.
CPPUNIT_ASSERT_EQUAL(32426.0, checkNewValuesNotification( m_pDoc, aOrgPos));
// Check it is one formula group.
aPos = aOrgPos;
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("A1", pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared top row.", aPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared length.", static_cast<SCROW>(7), pFC->GetSharedLength());
// Check notification of setting new values.
CPPUNIT_ASSERT_EQUAL(32426.0, checkNewValuesNotification( m_pDoc, aOrgPos));
// Check it is one formula group.
aPos = aOrgPos;
pFC = m_pDoc->GetFormulaCell(aPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_MESSAGE("A1", pFC->IsSharedTop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared top row.", aPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Shared length.", static_cast<SCROW>(5), pFC->GetSharedLength());
// Check notification of setting new values.
CPPUNIT_ASSERT_EQUAL(32426.0, checkNewValuesNotification( m_pDoc, aOrgPos));
clearRange(m_pDoc, ScRange( 0,0,0, 2,8,0));
}
m_pDoc->DeleteTab(0);
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulaListenerDeleteArea)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
// Check that Test1.A1:A2 and Test1.B1:B2 are formula groups. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0,0,1));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
m_pDoc->SetValue(ScAddress(0,1,0), 1.0); // change value of Test0.A2
m_pDoc->SetValue(ScAddress(1,1,0), 2.0); // change value of Test0.B2 // Test0.C2 should be recalculated.
CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(2,1,0)));
// Delete Test0.B2
clearRange(m_pDoc, ScRange(1,1,0)); // Test0.C2 should be recalculated.
CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(2,1,0)));
m_pDoc->DeleteTab(1);
m_pDoc->DeleteTab(0);
}
CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulaUpdateOnReplacement)
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
// Check that A2:A8 is a formula group. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0,1,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(7), pFC->GetSharedLength());
// Check that A2:A8 is a formula group.
pFC = m_pDoc->GetFormulaCell(ScAddress(0,1,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(7), pFC->GetSharedLength());
// Check that A2:A8 is a formula group.
pFC = m_pDoc->GetFormulaCell(ScAddress(0,1,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(7), pFC->GetSharedLength());
// Check that A1:A2 is a formula group. const ScFormulaCell* pFC = m_pDoc->GetFormulaCell( ScAddress(0,0,0));
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
// Check that E3:E9 is a formula group. const ScAddress aFormulaPos(4,2,0); const ScFormulaCell* pFC = m_pDoc->GetFormulaCell( aFormulaPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shared formula top row.", aFormulaPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shared formula length.", static_cast<SCROW>(7), pFC->GetSharedLength());
{ // Check that C1:C2 is a formula group. const ScAddress aFormulaPos(2,0,0); const ScFormulaCell* pFC = m_pDoc->GetFormulaCell( aFormulaPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shared formula top row.", aFormulaPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shared formula length.", static_cast<SCROW>(2), pFC->GetSharedLength());
}
{ // Check that D1:D2 is a formula group. const ScAddress aFormulaPos(3,0,0); const ScFormulaCell* pFC = m_pDoc->GetFormulaCell( aFormulaPos);
CPPUNIT_ASSERT(pFC);
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shared formula top row.", aFormulaPos.Row(), pFC->GetSharedTopRow());
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shared formula length.", static_cast<SCROW>(2), pFC->GetSharedLength());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.