summaryrefslogtreecommitdiff
path: root/sc/qa/unit/ucalc.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/qa/unit/ucalc.cxx')
-rw-r--r--sc/qa/unit/ucalc.cxx501
1 files changed, 448 insertions, 53 deletions
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 8eef4104ec99..59a70f8a5b45 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -62,6 +62,7 @@
#include "dpsave.hxx"
#include "dpdimsave.hxx"
#include "dpcache.hxx"
+#include "dpfilteredcache.hxx"
#include "calcconfig.hxx"
#include "interpre.hxx"
@@ -82,11 +83,13 @@
#include <com/sun/star/sheet/GeneralFunction.hpp>
#include <iostream>
+#include <sstream>
#include <vector>
#define CALC_DEBUG_OUTPUT 0
#include "helper/debughelper.hxx"
+#include "helper/qahelper.hxx"
const int indeterminate = 2;
@@ -118,10 +121,12 @@ public:
*/
void testSheetsFunc();
void testVolatileFunc();
+ void testFormulaDepTracking();
void testFuncParam();
void testNamedRange();
void testCSV();
void testMatrix();
+ void testEnterMixedMatrix();
/**
* Basic test for pivot tables.
@@ -175,6 +180,12 @@ public:
*/
void testPivotTableCaseInsensitiveStrings();
+ /**
+ * Test for pivot table's handling of double-precision numbers that are
+ * very close together.
+ */
+ void testPivotTableNumStability();
+
void testSheetCopy();
void testSheetMove();
void testExternalRef();
@@ -225,6 +236,9 @@ public:
void testFindAreaPosColRight();
void testSort();
void testSortWithFormulaRefs();
+ void testShiftCells();
+ void testDeleteRow();
+ void testDeleteCol();
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(testCollator);
@@ -233,10 +247,12 @@ public:
CPPUNIT_TEST(testCellFunctions);
CPPUNIT_TEST(testSheetsFunc);
CPPUNIT_TEST(testVolatileFunc);
+ CPPUNIT_TEST(testFormulaDepTracking);
CPPUNIT_TEST(testFuncParam);
CPPUNIT_TEST(testNamedRange);
CPPUNIT_TEST(testCSV);
CPPUNIT_TEST(testMatrix);
+ CPPUNIT_TEST(testEnterMixedMatrix);
CPPUNIT_TEST(testPivotTable);
CPPUNIT_TEST(testPivotTableLabels);
CPPUNIT_TEST(testPivotTableDateLabels);
@@ -250,6 +266,7 @@ public:
CPPUNIT_TEST(testPivotTableEmptyRows);
CPPUNIT_TEST(testPivotTableTextNumber);
CPPUNIT_TEST(testPivotTableCaseInsensitiveStrings);
+ CPPUNIT_TEST(testPivotTableNumStability);
CPPUNIT_TEST(testSheetCopy);
CPPUNIT_TEST(testSheetMove);
CPPUNIT_TEST(testExternalRef);
@@ -275,6 +292,9 @@ public:
CPPUNIT_TEST(testFindAreaPosColRight);
CPPUNIT_TEST(testSort);
CPPUNIT_TEST(testSortWithFormulaRefs);
+ CPPUNIT_TEST(testShiftCells);
+ CPPUNIT_TEST(testDeleteRow);
+ CPPUNIT_TEST(testDeleteCol);
CPPUNIT_TEST_SUITE_END();
private:
@@ -328,6 +348,45 @@ ScRange insertRangeData(ScDocument* pDoc, const ScAddress& rPos, const char* aDa
return aRange;
}
+/**
+ * Temporarily switch on/off auto calculation mode.
+ */
+class AutoCalcSwitch
+{
+ ScDocument* mpDoc;
+ bool mbOldValue;
+public:
+ AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc())
+ {
+ mpDoc->SetAutoCalc(bAutoCalc);
+ }
+
+ ~AutoCalcSwitch()
+ {
+ mpDoc->SetAutoCalc(mbOldValue);
+ }
+};
+
+/**
+ * Temporarily set formula grammar.
+ */
+class FormulaGrammarSwitch
+{
+ ScDocument* mpDoc;
+ formula::FormulaGrammar::Grammar meOldGrammar;
+public:
+ FormulaGrammarSwitch(ScDocument* pDoc, formula::FormulaGrammar::Grammar eGrammar) :
+ mpDoc(pDoc), meOldGrammar(pDoc->GetGrammar())
+ {
+ mpDoc->SetGrammar(eGrammar);
+ }
+
+ ~FormulaGrammarSwitch()
+ {
+ mpDoc->SetGrammar(meOldGrammar);
+ }
+};
+
Test::Test()
: m_pDoc(0)
{
@@ -1056,6 +1115,114 @@ void Test::testVolatileFunc()
m_pDoc->DeleteTab(0);
}
+void Test::testFormulaDepTracking()
+{
+ CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, "foo"));
+
+ AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
+
+ // B2 listens on D2.
+ m_pDoc->SetString(1, 1, 0, "=D2");
+ double val = -999.0; // dummy initial value
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Referencing an empty cell should yield zero.", val == 0.0);
+
+ // Changing the value of D2 should trigger recalculation of B2.
+ m_pDoc->SetValue(3, 1, 0, 1.1);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on value change.", val == 1.1);
+
+ // And again.
+ m_pDoc->SetValue(3, 1, 0, 2.2);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on value change.", val == 2.2);
+
+ clearRange(m_pDoc, ScRange(0, 0, 0, 10, 10, 0));
+
+ // Now, let's test the range dependency tracking.
+
+ // B2 listens on D2:E6.
+ m_pDoc->SetString(1, 1, 0, "=SUM(D2:E6)");
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Summing an empty range should yield zero.", val == 0.0);
+
+ // Set value to E3. This should trigger recalc on B2.
+ m_pDoc->SetValue(4, 2, 0, 2.4);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", val == 2.4);
+
+ // Set value to D5 to trigger recalc again. Note that this causes an
+ // addition of 1.2 + 2.4 which is subject to binary floating point
+ // rounding error. We need to use approxEqual to assess its value.
+
+ m_pDoc->SetValue(3, 4, 0, 1.2);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 3.6));
+
+ // Change the value of D2 (boundary case).
+ m_pDoc->SetValue(3, 1, 0, 1.0);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 4.6));
+
+ // Change the value of E6 (another boundary case).
+ m_pDoc->SetValue(4, 5, 0, 2.0);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 6.6));
+
+ // Change the value of D6 (another boundary case).
+ m_pDoc->SetValue(3, 5, 0, 3.0);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 9.6));
+
+ // Change the value of E2 (another boundary case).
+ m_pDoc->SetValue(4, 1, 0, 0.4);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 10.0));
+
+ // Change the existing non-empty value cell (E2).
+ m_pDoc->SetValue(4, 1, 0, 2.4);
+ m_pDoc->GetValue(1, 1, 0, val);
+ CPPUNIT_ASSERT_MESSAGE("Failed to recalculate on single value change.", rtl::math::approxEqual(val, 12.0));
+
+ clearRange(m_pDoc, ScRange(0, 0, 0, 10, 10, 0));
+
+ // Now, column-based dependency tracking. We now switch to the R1C1
+ // syntax which is easier to use for repeated relative references.
+
+ FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
+
+ val = 0.0;
+ for (SCROW nRow = 1; nRow <= 9; ++nRow)
+ {
+ // Static value in column 1.
+ m_pDoc->SetValue(0, nRow, 0, ++val);
+
+ // Formula in column 2 that references cell to the left.
+ m_pDoc->SetString(1, nRow, 0, "=RC[-1]");
+
+ // Formula in column 3 that references cell to the left.
+ m_pDoc->SetString(2, nRow, 0, "=RC[-1]*2");
+ }
+
+ // Check formula values.
+ val = 0.0;
+ for (SCROW nRow = 1; nRow <= 9; ++nRow)
+ {
+ ++val;
+ CPPUNIT_ASSERT_MESSAGE("Unexpected formula value.", m_pDoc->GetValue(1, nRow, 0) == val);
+ CPPUNIT_ASSERT_MESSAGE("Unexpected formula value.", m_pDoc->GetValue(2, nRow, 0) == val*2.0);
+ }
+
+ // Intentionally insert a formula in column 1. This will break column 1's
+ // uniformity of consisting only of static value cells.
+ m_pDoc->SetString(0, 4, 0, "=R2C3");
+ CPPUNIT_ASSERT_MESSAGE("Unexpected formula value.", m_pDoc->GetValue(0, 4, 0) == 2.0);
+ CPPUNIT_ASSERT_MESSAGE("Unexpected formula value.", m_pDoc->GetValue(1, 4, 0) == 2.0);
+ CPPUNIT_ASSERT_MESSAGE("Unexpected formula value.", m_pDoc->GetValue(2, 4, 0) == 4.0);
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testFuncParam()
{
rtl::OUString aTabName("foo");
@@ -1349,6 +1516,31 @@ void Test::testMatrix()
checkMatrixElements<PartiallyFilledEmptyMatrix>(*pMat);
}
+void Test::testEnterMixedMatrix()
+{
+ m_pDoc->InsertTab(0, "foo");
+
+ // Insert the source values in A1:B2.
+ m_pDoc->SetString(0, 0, 0, "A");
+ m_pDoc->SetString(1, 0, 0, "B");
+ double val = 1.0;
+ m_pDoc->SetValue(0, 1, 0, val);
+ val = 2.0;
+ m_pDoc->SetValue(1, 1, 0, val);
+
+ // Create a matrix range in A4:B5 referencing A1:B2.
+ ScMarkData aMark;
+ aMark.SelectOneTable(0);
+ m_pDoc->InsertMatrixFormula(0, 3, 1, 4, aMark, "=A1:B2", NULL);
+
+ CPPUNIT_ASSERT_EQUAL(m_pDoc->GetString(0,0,0), m_pDoc->GetString(0,3,0));
+ CPPUNIT_ASSERT_EQUAL(m_pDoc->GetString(1,0,0), m_pDoc->GetString(1,3,0));
+ CPPUNIT_ASSERT_EQUAL(m_pDoc->GetValue(0,1,0), m_pDoc->GetValue(0,4,0));
+ CPPUNIT_ASSERT_EQUAL(m_pDoc->GetValue(1,1,0), m_pDoc->GetValue(1,4,0));
+
+ m_pDoc->DeleteTab(0);
+}
+
namespace {
struct DPFieldDef
@@ -1536,22 +1728,6 @@ ScRange refreshGroups(ScDPCollection* pDPs, ScDPObject* pDPObj)
return refresh(pDPObj);
}
-class AutoCalcSwitch
-{
- ScDocument* mpDoc;
- bool mbOldValue;
-public:
- AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc())
- {
- mpDoc->SetAutoCalc(bAutoCalc);
- }
-
- ~AutoCalcSwitch()
- {
- mpDoc->SetAutoCalc(mbOldValue);
- }
-};
-
}
void Test::testPivotTable()
@@ -2283,6 +2459,29 @@ void Test::testPivotTableCache()
}
}
+ // Now, on to testing the filtered cache.
+
+ {
+ // Non-filtered cache - everything should be visible.
+ ScDPFilteredCache aFilteredCache(aCache);
+ aFilteredCache.fillTable();
+
+ sal_Int32 nRows = aFilteredCache.getRowSize();
+ CPPUNIT_ASSERT_MESSAGE("Wrong dimension.", nRows == 6 && aFilteredCache.getColSize() == 3);
+
+ for (sal_Int32 i = 0; i < nRows; ++i)
+ {
+ if (!aFilteredCache.isRowActive(i))
+ {
+ std::ostringstream os;
+ os << "Row " << i << " should be visible but it isn't.";
+ CPPUNIT_ASSERT_MESSAGE(os.str().c_str(), false);
+ }
+ }
+ }
+
+ // TODO : Add test for filtered caches.
+
m_pDoc->DeleteTab(0);
}
@@ -3022,6 +3221,111 @@ void Test::testPivotTableCaseInsensitiveStrings()
m_pDoc->DeleteTab(0);
}
+void Test::testPivotTableNumStability()
+{
+ FormulaGrammarSwitch aFGSwitch(m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1);
+
+ // Raw Data
+ const char* aData[][4] = {
+ { "Name", "Time Start", "Time End", "Total" },
+ { "Sam", "07:48 AM", "09:00 AM", "=RC[-1]-RC[-2]" },
+ { "Sam", "09:00 AM", "10:30 AM", "=RC[-1]-RC[-2]" },
+ { "Sam", "10:30 AM", "12:30 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "12:30 PM", "01:00 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "01:00 PM", "01:30 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "01:30 PM", "02:00 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "02:00 PM", "07:15 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "07:47 AM", "09:00 AM", "=RC[-1]-RC[-2]" },
+ { "Sam", "09:00 AM", "10:00 AM", "=RC[-1]-RC[-2]" },
+ { "Sam", "10:00 AM", "11:00 AM", "=RC[-1]-RC[-2]" },
+ { "Sam", "11:00 AM", "11:30 AM", "=RC[-1]-RC[-2]" },
+ { "Sam", "11:30 AM", "12:45 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "12:45 PM", "01:15 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "01:15 PM", "02:30 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "02:30 PM", "02:45 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "02:45 PM", "04:30 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "04:30 PM", "06:00 PM", "=RC[-1]-RC[-2]" },
+ { "Sam", "06:00 PM", "07:15 PM", "=RC[-1]-RC[-2]" },
+ { "Mike", "06:15 AM", "08:30 AM", "=RC[-1]-RC[-2]" },
+ { "Mike", "08:30 AM", "10:03 AM", "=RC[-1]-RC[-2]" },
+ { "Mike", "10:03 AM", "12:00 PM", "=RC[-1]-RC[-2]" },
+ { "Dennis", "11:00 AM", "01:00 PM", "=RC[-1]-RC[-2]" },
+ { "Dennis", "01:00 PM", "02:00 PM", "=RC[-1]-RC[-2]" }
+ };
+
+ // Dimension definition
+ DPFieldDef aFields[] = {
+ { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
+ { "Total", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
+ };
+
+ m_pDoc->InsertTab(0, OUString("Data"));
+ m_pDoc->InsertTab(1, OUString("Table"));
+
+ size_t nRowCount = SAL_N_ELEMENTS(aData);
+ ScAddress aPos(1,1,0);
+ ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, nRowCount);
+
+ // Insert formulas to manually calculate sums for each name.
+ m_pDoc->SetString(aDataRange.aStart.Col(), aDataRange.aEnd.Row()+1, aDataRange.aStart.Tab(), "=SUMIF(R[-23]C:R[-1]C;\"Dennis\";R[-23]C[3]:R[-1]C[3])");
+ m_pDoc->SetString(aDataRange.aStart.Col(), aDataRange.aEnd.Row()+2, aDataRange.aStart.Tab(), "=SUMIF(R[-24]C:R[-2]C;\"Mike\";R[-24]C[3]:R[-2]C[3])");
+ m_pDoc->SetString(aDataRange.aStart.Col(), aDataRange.aEnd.Row()+3, aDataRange.aStart.Tab(), "=SUMIF(R[-25]C:R[-3]C;\"Sam\";R[-25]C[3]:R[-3]C[3])");
+
+ m_pDoc->CalcAll();
+
+ // Get correct sum values.
+ double fDennisTotal = m_pDoc->GetValue(aDataRange.aStart.Col(), aDataRange.aEnd.Row()+1, aDataRange.aStart.Tab());
+ double fMikeTotal = m_pDoc->GetValue(aDataRange.aStart.Col(), aDataRange.aEnd.Row()+2, aDataRange.aStart.Tab());
+ double fSamTotal = m_pDoc->GetValue(aDataRange.aStart.Col(), aDataRange.aEnd.Row()+3, aDataRange.aStart.Tab());
+
+ ScDPObject* pDPObj = createDPFromRange(
+ m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
+
+ ScDPCollection* pDPs = m_pDoc->GetDPCollection();
+ bool bSuccess = pDPs->InsertNewTable(pDPObj);
+
+ CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
+ pDPs->GetCount(), static_cast<size_t>(1));
+ pDPObj->SetName(pDPs->CreateNewName());
+
+ ScRange aOutRange = refresh(pDPObj);
+
+ // Manually check the total value for each name.
+ //
+ // +--------------+----------------+
+ // | Name | |
+ // +--------------+----------------+
+ // | Dennis | <Dennis total> |
+ // +--------------+----------------+
+ // | Mike | <Miks total> |
+ // +--------------+----------------+
+ // | Sam | <Sam total> |
+ // +--------------+----------------+
+ // | Total Result | ... |
+ // +--------------+----------------+
+
+ aPos = aOutRange.aStart;
+ aPos.IncCol();
+ aPos.IncRow();
+ double fTest = m_pDoc->GetValue(aPos);
+ CPPUNIT_ASSERT_MESSAGE("Incorrect value for Dennis.", rtl::math::approxEqual(fTest, fDennisTotal));
+ aPos.IncRow();
+ fTest = m_pDoc->GetValue(aPos);
+ CPPUNIT_ASSERT_MESSAGE("Incorrect value for Mike.", rtl::math::approxEqual(fTest, fMikeTotal));
+ aPos.IncRow();
+ fTest = m_pDoc->GetValue(aPos);
+ CPPUNIT_ASSERT_MESSAGE("Incorrect value for Sam.", rtl::math::approxEqual(fTest, fSamTotal));
+
+ pDPs->FreeTable(pDPObj);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
+ pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
+
+ m_pDoc->DeleteTab(1);
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testSheetCopy()
{
OUString aTabName("TestTab");
@@ -3916,19 +4220,23 @@ void Test::testGraphicsInGroup()
//Use a range of rows guaranteed to include all of the square
m_pDoc->ShowRows(0, 100, 0, false);
+ m_pDoc->SetDrawPageSize(0);
CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
m_pDoc->ShowRows(0, 100, 0, true);
+ m_pDoc->SetDrawPageSize(0);
CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
CPPUNIT_ASSERT_MESSAGE("That shouldn't change size or positioning", aOrigRect == rNewRect);
m_pDoc->ShowRows(0, 100, 0, false);
+ m_pDoc->SetDrawPageSize(0);
CPPUNIT_ASSERT_MESSAGE("Left and Right should be unchanged",
aOrigRect.nLeft == rNewRect.nLeft && aOrigRect.nRight == rNewRect.nRight);
CPPUNIT_ASSERT_MESSAGE("Height should be minimum allowed height",
(rNewRect.nBottom - rNewRect.nTop) <= 1);
m_pDoc->ShowRows(0, 100, 0, true);
+ m_pDoc->SetDrawPageSize(0);
CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
}
@@ -3947,6 +4255,7 @@ void Test::testGraphicsInGroup()
// Insert 2 rows at the top. This should push the circle object down.
m_pDoc->InsertRow(0, 0, MAXCOL, 0, 0, 2);
+ m_pDoc->SetDrawPageSize(0);
// Make sure the size of the circle is still identical.
CPPUNIT_ASSERT_MESSAGE("Size of the circle has changed, but shouldn't!",
@@ -3954,6 +4263,7 @@ void Test::testGraphicsInGroup()
// Delete 2 rows at the top. This should bring the circle object to its original position.
m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 0, 2);
+ m_pDoc->SetDrawPageSize(0);
CPPUNIT_ASSERT_MESSAGE("Failed to move back to its original position.", aOrigRect == rNewRect);
}
@@ -3977,6 +4287,7 @@ void Test::testGraphicsInGroup()
// Insert 2 rows at the top and delete them immediately.
m_pDoc->InsertRow(0, 0, MAXCOL, 0, 0, 2);
m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 0, 2);
+ m_pDoc->SetDrawPageSize(0);
CPPUNIT_ASSERT_MESSAGE("Size of a line object changed after row insertion and removal.",
aOrigRect == rNewRect);
@@ -4071,7 +4382,7 @@ void Test::testPostIts()
rtl::OUString aTabName2("Table2");
m_pDoc->InsertTab(0, aTabName);
- ScAddress rAddr(2, 2, 0);
+ ScAddress rAddr(2, 2, 0); // cell C3
ScPostIt *pNote = m_pDoc->GetNotes(rAddr.Tab())->GetOrCreateNote(rAddr);
pNote->SetText(rAddr, aHello);
pNote->SetAuthor(aJimBob);
@@ -4079,29 +4390,51 @@ void Test::testPostIts()
ScPostIt *pGetNote = m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr);
CPPUNIT_ASSERT_MESSAGE("note should be itself", pGetNote == pNote );
- bool bInsertRow = m_pDoc->InsertRow( 0, 0, 100, 0, 1, 1 );
+ // Insert one row at row 1.
+ bool bInsertRow = m_pDoc->InsertRow(0, 0, MAXCOL, 0, 1, 1);
CPPUNIT_ASSERT_MESSAGE("failed to insert row", bInsertRow );
CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
- rAddr.IncRow();
+ rAddr.IncRow(); // cell C4
CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
- bool bInsertCol = m_pDoc->InsertCol( 0, 0, 100, 0, 1, 1 );
+ // Insert column at column A.
+ bool bInsertCol = m_pDoc->InsertCol(0, 0, MAXROW, 0, 1, 1);
CPPUNIT_ASSERT_MESSAGE("failed to insert column", bInsertCol );
CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
- rAddr.IncCol();
+ rAddr.IncCol(); // cell D4
CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
+ // Insert a new sheet to shift the current sheet to the right.
m_pDoc->InsertTab(0, aTabName2);
CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
- rAddr.IncTab();
+ rAddr.IncTab(); // Move to the next sheet.
CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
m_pDoc->DeleteTab(0);
rAddr.IncTab(-1);
CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
+ // Insert cell at C4. This should NOT shift the note position.
+ bInsertRow = m_pDoc->InsertRow(2, 0, 2, 0, 3, 1);
+ CPPUNIT_ASSERT_MESSAGE("Failed to insert cell at C4.", bInsertRow);
+ CPPUNIT_ASSERT_MESSAGE("Note shouldn't have moved but it has.", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
+
+ // Delete cell at C4. Again, this should NOT shift the note position.
+ m_pDoc->DeleteRow(2, 0, 2, 0, 3, 1);
+ CPPUNIT_ASSERT_MESSAGE("Note shouldn't have moved but it has.", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
+
+ // Now, with the note at D4, delete cell D3. This should shift the note one cell up.
+ m_pDoc->DeleteRow(3, 0, 3, 0, 2, 1);
+ rAddr.IncRow(-1); // cell D3
+ CPPUNIT_ASSERT_MESSAGE("Note at D4 should have shifted up to D3.", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
+
+ // Delete column C. This should shift the note one cell left.
+ m_pDoc->DeleteCol(0, 0, MAXROW, 0, 2, 1);
+ rAddr.IncCol(-1); // cell C3
+ CPPUNIT_ASSERT_MESSAGE("Note at D3 should have shifted left to C3.", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
+
m_pDoc->DeleteTab(0);
}
@@ -4309,7 +4642,7 @@ void Test::testCopyPaste()
double aValue = 0;
m_pDoc->GetValue(1, 0, 0, aValue);
std::cout << "Value: " << aValue << std::endl;
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 8", aValue, 8, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 8", aValue, 8);
//copy Sheet1.A1:C1 to Sheet2.A2:C2
ScRange aRange(0,0,0,2,0,0);
@@ -4334,7 +4667,7 @@ void Test::testCopyPaste()
rtl::OUString aString;
m_pDoc->GetValue(1,1,1, aValue);
m_pDoc->GetFormula(1,1,1, aString);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("copied formula should return 2", aValue, 2, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("copied formula should return 2", aValue, 2);
CPPUNIT_ASSERT_MESSAGE("formula string was not copied correctly", aString == aFormulaString);
m_pDoc->GetValue(0,1,1, aValue);
CPPUNIT_ASSERT_MESSAGE("copied value should be 1", aValue == 1);
@@ -4352,13 +4685,13 @@ void Test::testCopyPaste()
//check undo and redo
pUndo->Undo();
m_pDoc->GetValue(1,1,1, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after undo formula should return nothing", aValue, 0, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after undo formula should return nothing", aValue, 0);
m_pDoc->GetString(2,1,1, aString);
CPPUNIT_ASSERT_MESSAGE("after undo string should be removed", aString.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("")));
pUndo->Redo();
m_pDoc->GetValue(1,1,1, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 2 after redo", aValue, 2, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 2 after redo", aValue, 2);
m_pDoc->GetString(2,1,1, aString);
CPPUNIT_ASSERT_MESSAGE("Cell Sheet2.C2 should contain: test", aString.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("test")));
m_pDoc->GetFormula(1,1,1, aString);
@@ -4490,42 +4823,42 @@ void Test::testUpdateReference()
double aValue;
m_pDoc->GetValue(2,0,2, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2,1,2, aValue);
- CPPUNIT_ASSERT_MESSAGE("formula does not return correct result", aValue == 5);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue, 5);
//test deleting both sheets: one is not directly before the sheet, the other one is
m_pDoc->DeleteTab(0);
m_pDoc->GetValue(2,0,1, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2,1,1, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 5, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 5);
m_pDoc->DeleteTab(0);
m_pDoc->GetValue(2,0,0, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2,1,0, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 5, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 5);
//test adding two sheets
m_pDoc->InsertTab(0, aSheet2);
m_pDoc->GetValue(2,0,1, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2,1,1, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 5, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 5);
m_pDoc->InsertTab(0, aSheet1);
m_pDoc->GetValue(2,0,2, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2,1,2, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 5, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 5);
//test new DeleteTabs/InsertTabs methods
m_pDoc->DeleteTabs(0, 2);
m_pDoc->GetValue(2, 0, 0, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2, 1, 0, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 5, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 5);
std::vector<rtl::OUString> aSheets;
aSheets.push_back(aSheet1);
@@ -4536,9 +4869,9 @@ void Test::testUpdateReference()
m_pDoc->GetFormula(2,0,2, aFormula);
std::cout << "formel: " << rtl::OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8).getStr() << std::endl;
std::cout << std::endl << aValue << std::endl;
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 3, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 3);
m_pDoc->GetValue(2, 1, 2, aValue);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 5, 0.00000001);
+ ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 5);
m_pDoc->DeleteTab(3);
m_pDoc->DeleteTab(2);
@@ -4642,7 +4975,7 @@ void Test::testAutoFill()
m_pDoc->Fill( 0, 0, 0, 0, NULL, aMarkData, 5);
for (SCROW i = 0; i< 6; ++i)
- CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1.0), m_pDoc->GetValue(0, i, 0), 0.00000001);
+ ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1.0), m_pDoc->GetValue(0, i, 0));
// check that hidden rows are not affected by autofill
// set values for hidden rows
@@ -4652,10 +4985,10 @@ void Test::testAutoFill()
m_pDoc->SetRowHidden(1, 2, 0, true);
m_pDoc->Fill( 0, 0, 0, 0, NULL, aMarkData, 8);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,1,0), 1e-08);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,2,0), 1e-08);
+ ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,1,0));
+ ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,2,0));
for (SCROW i = 3; i< 8; ++i)
- CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i-1.0), m_pDoc->GetValue(0, i, 0), 0.00000001);
+ ASSERT_DOUBLES_EQUAL(static_cast<double>(i-1.0), m_pDoc->GetValue(0, i, 0));
m_pDoc->Fill( 0, 0, 0, 8, NULL, aMarkData, 5, FILL_TO_RIGHT );
for (SCCOL i = 0; i < 5; ++i)
@@ -4664,18 +4997,18 @@ void Test::testAutoFill()
{
if (j > 2)
{
- CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(j-1+i), m_pDoc->GetValue(i, j, 0), 1e-8);
+ ASSERT_DOUBLES_EQUAL(static_cast<double>(j-1+i), m_pDoc->GetValue(i, j, 0));
}
else if (j == 0)
{
- CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(i, 0, 0), 1e-8);
+ ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(i, 0, 0));
}
else if (j == 1 || j== 2)
{
if(i == 0)
- CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,j,0), 1e-8);
+ ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,j,0));
else
- CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, m_pDoc->GetValue(i,j,0), 1e-8);
+ ASSERT_DOUBLES_EQUAL(0.0, m_pDoc->GetValue(i,j,0));
}
}
}
@@ -4712,15 +5045,15 @@ void Test::testCopyPasteFormulas()
// to prevent ScEditableTester in ScDocFunc::MoveBlock
m_pDoc->SetInTest();
- CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,0,0), 1.0, 1e-08);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,1,0), 1.0, 1e-08);
+ ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,0,0), 1.0);
+ ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,1,0), 1.0);
ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
bool bMoveDone = rDocFunc.MoveBlock(ScRange(0,0,0,0,4,0), ScAddress( 10, 10, 0), false, false, false, true);
// check that moving was succesful, mainly for editable tester
CPPUNIT_ASSERT(bMoveDone);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,10,0), 1.0, 1e-8);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,11,0), 1.0, 1e-8);
+ ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,10,0), 1.0);
+ ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,11,0), 1.0);
rtl::OUString aFormula;
m_pDoc->GetFormula(10,10,0, aFormula);
CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=COLUMN($A$1)"));
@@ -5021,7 +5354,7 @@ void Test::testSort()
pDoc->Sort(0, aSortData, false, NULL);
double nVal = pDoc->GetValue(1,0,0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(nVal, 1.0, 1e-8);
+ ASSERT_DOUBLES_EQUAL(nVal, 1.0);
// check that note is also moved
pNote = m_pDoc->GetNotes(0)->findByAddress( 1, 0 );
@@ -5030,6 +5363,68 @@ void Test::testSort()
pDoc->DeleteTab(0);
}
+void Test::testShiftCells()
+{
+ m_pDoc->InsertTab(0, "foo");
+
+ OUString aTestVal("Some Text");
+
+ // Text into cell E5.
+ m_pDoc->SetString(4, 3, 0, aTestVal);
+
+ // Insert cell at D5. This should shift the string cell to right.
+ m_pDoc->InsertCol(3, 0, 3, 0, 3, 1);
+ OUString aStr = m_pDoc->GetString(5, 3, 0);
+ CPPUNIT_ASSERT_MESSAGE("We should have a string cell here.", aStr == aTestVal);
+ CPPUNIT_ASSERT_MESSAGE("D5 is supposed to be blank.", m_pDoc->IsBlockEmpty(0, 3, 4, 3, 4));
+
+ // Delete cell D5, to shift the text cell back into D5.
+ m_pDoc->DeleteCol(3, 0, 3, 0, 3, 1);
+ aStr = m_pDoc->GetString(4, 3, 0);
+ CPPUNIT_ASSERT_MESSAGE("We should have a string cell here.", aStr == aTestVal);
+ CPPUNIT_ASSERT_MESSAGE("E5 is supposed to be blank.", m_pDoc->IsBlockEmpty(0, 4, 4, 4, 4));
+
+ m_pDoc->DeleteTab(0);
+}
+
+void Test::testDeleteRow()
+{
+ ScDocument* pDoc = m_xDocShRef->GetDocument();
+ rtl::OUString aSheet1("Sheet1");
+ pDoc->InsertTab(0, aSheet1);
+
+ rtl::OUString aHello("Hello");
+ rtl::OUString aJimBob("Jim Bob");
+ ScAddress rAddr(1, 1, 0);
+ ScPostIt* pNote = m_pDoc->GetNotes(rAddr.Tab())->GetOrCreateNote(rAddr);
+ pNote->SetText(rAddr, aHello);
+ pNote->SetAuthor(aJimBob);
+
+ pDoc->DeleteRow(0, 0, MAXCOL, 0, 1, 1);
+
+ CPPUNIT_ASSERT(m_pDoc->GetNotes(0)->empty());
+ pDoc->DeleteTab(0);
+}
+
+void Test::testDeleteCol()
+{
+ ScDocument* pDoc = m_xDocShRef->GetDocument();
+ rtl::OUString aSheet1("Sheet1");
+ pDoc->InsertTab(0, aSheet1);
+
+ rtl::OUString aHello("Hello");
+ rtl::OUString aJimBob("Jim Bob");
+ ScAddress rAddr(1, 1, 0);
+ ScPostIt* pNote = m_pDoc->GetNotes(rAddr.Tab())->GetOrCreateNote(rAddr);
+ pNote->SetText(rAddr, aHello);
+ pNote->SetAuthor(aJimBob);
+
+ pDoc->DeleteCol(0, 0, MAXROW, 0, 1, 1);
+
+ CPPUNIT_ASSERT(m_pDoc->GetNotes(0)->empty());
+ pDoc->DeleteTab(0);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
}