diff options
Diffstat (limited to 'sc')
-rwxr-xr-x[-rw-r--r--] | sc/inc/clipparam.hxx | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/inc/document.hxx | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/inc/table.hxx | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/qa/unit/ucalc.cxx | 5361 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/qa/unit/ucalc.hxx | 122 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/qa/unit/uicalc/uicalc.cxx | 45 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/source/core/data/clipparam.cxx | 50 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/source/core/data/document.cxx | 124 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/source/core/data/formulacell.cxx | 22 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/source/core/data/table2.cxx | 258 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/source/ui/inc/viewfunc.hxx | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | sc/source/ui/view/viewfun3.cxx | 30 |
12 files changed, 5919 insertions, 151 deletions
diff --git a/sc/inc/clipparam.hxx b/sc/inc/clipparam.hxx index 7a4513ffb502..55f37fe1d89e 100644..100755 --- a/sc/inc/clipparam.hxx +++ b/sc/inc/clipparam.hxx @@ -21,6 +21,7 @@ #include "rangelst.hxx" #include "charthelper.hxx" +#include "document.hxx" /** * This struct stores general clipboard parameters associated with a @@ -52,14 +53,19 @@ struct SC_DLLPUBLIC ScClipParam * Same as the above method, but returns the row size of the compressed * range. */ - SCROW getPasteRowSize(); + SCROW getPasteRowSize(const ScDocument& rSrcDoc, bool bIncludeFiltered); /** * Return a single range that encompasses all individual ranges. */ ScRange getWholeRange() const; - void transpose(); + /** + * Transpose the clip parameters. + * Filtered rows are removed from parameters. + */ + void transpose(const ScDocument& rSrcDoc, bool bIncludeFiltered, + bool bIsMultiRangeRowFilteredTranspose); sal_uInt32 getSourceDocID() const { return mnSourceDocID; } void setSourceDocID( sal_uInt32 nVal ) { mnSourceDocID = nVal; } diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 96d7ec940059..f90e74e9c030 100644..100755 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1605,9 +1605,12 @@ public: void CopyBlockFromClip( sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, SCCOL nDx, SCROW nDy ); - void CopyNonFilteredFromClip( sc::CopyFromClipContext& rCxt, SCCOL nCol1, - SCROW nRow1, SCCOL nCol2, SCROW nRow2, - const ScMarkData& rMark, SCCOL nDx, SCROW & rClipStartRow ); + /** + * @return the number of non-filtered rows. + */ + SCROW CopyNonFilteredFromClip(sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, + SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, SCCOL nDx, + SCROW& rClipStartRow, SCROW nClipEndRow); void StartListeningFromClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, @@ -1642,7 +1645,8 @@ public: bool IsClipboardSource() const; - SC_DLLPUBLIC void TransposeClip( ScDocument* pTransClip, InsertDeleteFlags nFlags, bool bAsLink ); + SC_DLLPUBLIC void TransposeClip(ScDocument* pTransClip, InsertDeleteFlags nFlags, bool bAsLink, + bool bIncludeFiltered); ScClipParam& GetClipParam(); void SetClipParam(const ScClipParam& rParam); diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 211e317cb06d..416cbb5d9337 100644..100755 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -540,10 +540,15 @@ public: void CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCCOL nDx, SCROW nDy, const ScTable* pTable); - void TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - ScTable* pTransClip, InsertDeleteFlags nFlags, bool bAsLink ); + /** + * @param nRowDestOffset adjustment of destination row position; + * used for transposed multi range selection with row direction, otherwise 0 + */ + void TransposeClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCROW nRowDestOffset, + ScTable* pTransClip, InsertDeleteFlags nFlags, bool bAsLink, + bool bIncludeFiltered); - // mark of this document + // mark of this document void MixMarked( sc::MixDocContext& rCxt, const ScMarkData& rMark, ScPasteFunc nFunction, bool bSkipEmpty, const ScTable* pSrcTab ); @@ -1246,8 +1251,22 @@ private: SCCOL FindNextVisibleCol(SCCOL nCol, bool bRight) const; - // Clipboard transpose for notes - void TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2); + /** + * Transpose clipboard patterns + * @param nRowDestOffset adjustment of destination row position; + * used for transposed multi range row selections, otherwise 0 + */ + void TransposeColPatterns(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, + SCROW nRow2, bool bIncludeFiltered, + const std::vector<SCROW>& rFilteredRows, SCROW nRowDestOffset); + + /** + * Transpose clipboard notes + * @param nRowDestOffset adjustment of destination row position; + * used for transposed multi range row selections, otherwise 0 + */ + void TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2, + bool bIncludeFiltered, SCROW nRowDestOffset); ScColumn* FetchColumn( SCCOL nCol ); const ScColumn* FetchColumn( SCCOL nCol ) const; diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 52dedc42c070..02988bdd5ff4 100644..100755 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -20,6 +20,7 @@ #include <scdll.hxx> #include <formulacell.hxx> #include <simpleformulacalc.hxx> +#include <formulaopt.hxx> #include <stringutil.hxx> #include <scmatrix.hxx> #include <drwlayer.hxx> @@ -158,6 +159,20 @@ void Test::tearDown() BootstrapFixture::tearDown(); } +static ScMF lcl_getMergeFlagOfCell(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab) +{ + const SfxPoolItem& rPoolItem = rDoc.GetPattern(nCol, nRow, nTab)->GetItem(ATTR_MERGE_FLAG); + const ScMergeFlagAttr& rMergeFlag = static_cast<const ScMergeFlagAttr&>(rPoolItem); + return rMergeFlag.GetValue(); +} + +static ScAddress lcl_getMergeSizeOfCell(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab) +{ + const SfxPoolItem& rPoolItem = rDoc.GetPattern(nCol, nRow, nTab)->GetItem(ATTR_MERGE); + const ScMergeAttr& rMerge = static_cast<const ScMergeAttr&>(rPoolItem); + return ScAddress(rMerge.GetColMerge(), rMerge.GetRowMerge(), nTab); +} + void Test::testCollator() { CollatorWrapper* p = ScGlobal::GetCollator(); @@ -2050,10 +2065,10 @@ void Test::testCellCopy() ScAddress aDest(0,1,0); OUString aStr("please copy me"); m_pDoc->SetString(aSrc, "please copy me"); - CPPUNIT_ASSERT_EQUAL(m_pDoc->GetString(aSrc), aStr); + CPPUNIT_ASSERT_EQUAL(aStr, m_pDoc->GetString(aSrc)); // copy to self - why not ? m_pDoc->CopyCellToDocument(aSrc,aDest,*m_pDoc); - CPPUNIT_ASSERT_EQUAL(m_pDoc->GetString(aDest), aStr); + CPPUNIT_ASSERT_EQUAL(aStr, m_pDoc->GetString(aDest)); } void Test::testSheetCopy() @@ -3649,7 +3664,6 @@ void Test::testCopyPasteAsLink() void Test::testCopyPasteTranspose() { m_pDoc->InsertTab(0, "Sheet1"); - m_pDoc->InsertTab(1, "Sheet2"); // We need a drawing layer in order to create caption objects. m_pDoc->InitDrawLayer(&getDocShell()); @@ -3677,7 +3691,7 @@ void Test::testCopyPasteTranspose() copyToClip(m_pDoc, aSrcRange, &aNewClipDoc); ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); - aNewClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::ALL, false); + aNewClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::ALL, false, false); ScRange aDestRange(3,1,1,3,3,1);//target: Sheet2.D2:D4 ScMarkData aMark(m_pDoc->GetSheetLimits()); @@ -3689,9 +3703,9 @@ void Test::testCopyPasteTranspose() OUString aString = m_pDoc->GetString(3, 3, 1); CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell Sheet2.D4 should contain: test", OUString("test"), aString); double fValue = m_pDoc->GetValue(ScAddress(3,1,1)); - ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell should return 1", fValue, 1); + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell should return 1", 1, fValue); fValue = m_pDoc->GetValue(ScAddress(3,2,1)); - ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula should return 2", fValue, 2); + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula should return 2", 2, fValue); m_pDoc->GetFormula(3, 2, 1, aString); CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula should point on Sheet2.D2", OUString("=D2+1"), aString); @@ -3700,15 +3714,5344 @@ void Test::testCopyPasteTranspose() CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.D3", m_pDoc->HasNote(ScAddress(3, 2, 1))); CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.D4", m_pDoc->HasNote(ScAddress(3, 3, 1))); CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on Sheet2.D2", - m_pDoc->GetNote(ScAddress(3, 1, 1))->GetText(), m_pDoc->GetNote(ScAddress(0, 0, 0))->GetText()); + m_pDoc->GetNote(ScAddress(0, 0, 0))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, 1))->GetText()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on Sheet2.D3", - m_pDoc->GetNote(ScAddress(3, 2, 1))->GetText(), m_pDoc->GetNote(ScAddress(1, 0, 0))->GetText()); + m_pDoc->GetNote(ScAddress(1, 0, 0))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, 1))->GetText()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on Sheet2.D4", - m_pDoc->GetNote(ScAddress(3, 3, 1))->GetText(), m_pDoc->GetNote(ScAddress(2, 0, 0))->GetText()); + m_pDoc->GetNote(ScAddress(2, 0, 0))->GetText(), + m_pDoc->GetNote(ScAddress(3, 3, 1))->GetText()); m_pDoc->DeleteTab(1); m_pDoc->DeleteTab(0); +} + +void Test::testCopyPasteSpecialMergedCellsTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 2, srcSheet, 3); // A3 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + m_pDoc->DoMerge(srcSheet, 0, 1, 1, 1, false); // Merge A2 and B2 + m_pDoc->DoMerge(srcSheet, 0, 2, 1, 2, false); // Merge A3 and B3 + + // Test precondition + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 0, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 1, 0, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(2, 1, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 1, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 1, 1, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::Hor, lcl_getMergeFlagOfCell(*m_pDoc, 1, 1, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(2, 1, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 2, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 1, 2, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::Hor, lcl_getMergeFlagOfCell(*m_pDoc, 1, 2, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 3, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 1, 3, srcSheet)); + + ScRange aSrcRange(0, 0, srcSheet, 1, 3, srcSheet); // Copy A1:B4 to clip. + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, aSrcRange, &aClipDoc); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::ALL, true, false); + + ScRange aDestRange(1, 1, destSheet, 4, 2, destSheet); // Paste to B2:E3 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::ALL, nullptr, pTransClip.get(), true, + false); + pTransClip.reset(); + + // Check transpose of merged cells + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 1, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 1, 2, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(1, 2, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 2, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(2, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(1, 2, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 3, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(3, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 4, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 4, 2, destSheet)); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::testCopyPasteSpecialMergedCellsFilteredTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 2, srcSheet, 3); // A3 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + m_pDoc->DoMerge(srcSheet, 0, 1, 1, 1, false); // Merge A2 and B2 + m_pDoc->DoMerge(srcSheet, 0, 2, 1, 2, false); // Merge A3 and B3 + + // Filter row 1 + ScDBData* pDBData = new ScDBData("TRANSPOSE_TEST_DATA", srcSheet, 0, 0, 0, 3); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr<ScDBData>(pDBData)); + + pDBData->SetAutoFilter(true); + ScRange aRange; + pDBData->GetArea(aRange); + m_pDoc->ApplyFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aStart.Row(), aRange.aStart.Tab(), ScMF::Auto); + + //create the query param + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_NOT_EQUAL; + rEntry.GetQueryItem().mfVal = 2; // value of row A2 -> filtering row 1 + // add queryParam to database range. + pDBData->SetQueryParam(aParam); + + // perform the query. + m_pDoc->Query(srcSheet, aParam, true); + + // Test precondition + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 0, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 1, 0, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(2, 1, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 1, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 1, 1, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::Hor, lcl_getMergeFlagOfCell(*m_pDoc, 1, 1, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(2, 1, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 2, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 1, 2, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::Hor, lcl_getMergeFlagOfCell(*m_pDoc, 1, 2, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, srcSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 0, 3, srcSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 1, 3, srcSheet)); + + ScRange aSrcRange(0, 0, srcSheet, 1, 3, srcSheet); // Copy A1:B4 to clip. + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, aSrcRange, &aClipDoc); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::ALL, true, false); + + ScRange aDestRange(1, 1, destSheet, 3, 2, destSheet); // Paste to B2:D3 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::ALL, nullptr, pTransClip.get(), true, + false); + pTransClip.reset(); + + // Check transpose of merged cells + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 1, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 1, 2, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(1, 2, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 2, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(2, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScAddress(0, 0, destSheet), + lcl_getMergeSizeOfCell(*m_pDoc, 3, 1, destSheet)); + CPPUNIT_ASSERT_EQUAL(ScMF::NONE, lcl_getMergeFlagOfCell(*m_pDoc, 3, 2, destSheet)); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// InsertDeleteFlags::CONTENTS +void Test::testCopyPasteSpecialAsLinkTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + ScRange aSrcRange(0, 0, srcSheet, 0, 3, srcSheet); // Copy A1:A4 to clip. + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, aSrcRange, &aClipDoc); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::CONTENTS, true, false); + + ScRange aDestRange(1, 1, destSheet, 4, 1, destSheet); // Paste to B2:E2 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::CONTENTS, nullptr, pTransClip.get(), + true, false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(2, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C2", OUString("=$Sheet1.$A$2"), aString); + CPPUNIT_ASSERT_EQUAL(2.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell D2.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(4, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell E2", OUString("=$Sheet1.$A$4"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// InsertDeleteFlags::CONTENTS +void Test::testCopyPasteSpecialAsLinkFilteredTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + // Filter row 1 + ScDBData* pDBData = new ScDBData("TRANSPOSE_TEST_DATA", srcSheet, 0, 0, 0, 3); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr<ScDBData>(pDBData)); + + pDBData->SetAutoFilter(true); + ScRange aRange; + pDBData->GetArea(aRange); + m_pDoc->ApplyFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aStart.Row(), aRange.aStart.Tab(), ScMF::Auto); + + //create the query param + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_NOT_EQUAL; + rEntry.GetQueryItem().mfVal = 2; // value of row A2 -> filtering row 1 + // add queryParam to database range. + pDBData->SetQueryParam(aParam); + + // perform the query. + m_pDoc->Query(srcSheet, aParam, true); + + // Check precondition for test: row 1 is hidden/filtered + SCROW nRow1, nRow2; + SCROW nFilteredRow1, nFilteredRow2; + bool bHidden = m_pDoc->RowHidden(SCROW(1), srcSheet, &nRow1, &nRow2); + CPPUNIT_ASSERT_MESSAGE("row 1 should be hidden", bHidden); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be hidden", SCROW(1), nRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be hidden", SCROW(1), nRow2); + bool bFiltered = m_pDoc->RowFiltered(SCROW(1), srcSheet, &nFilteredRow1, &nFilteredRow2); + CPPUNIT_ASSERT_MESSAGE("row 1 should be filtered", bFiltered); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be filtered", SCROW(1), nFilteredRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be filtered", SCROW(1), nFilteredRow2); + + // Copy A1:A4 to clip. + ScRange aSrcRange(0, 0, srcSheet, 0, 3, srcSheet); + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, aSrcRange, &aClipDoc); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::CONTENTS, true, false); + + ScRange aDestRange(1, 1, destSheet, 3, 1, destSheet); // Paste to B2:D2 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::CONTENTS, nullptr, pTransClip.get(), + true, false, false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell C2.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(3, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D2", OUString("=$Sheet1.$A$4"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// tdf#141683 +// InsertDeleteFlags::CONTENTS +void Test::testCopyPasteSpecialMultiRangeRowAsLinkTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(1, 0, srcSheet, 2); // B1 + m_pDoc->SetValue(3, 0, srcSheet, 4); // D1 + + m_pDoc->SetValue(0, 2, srcSheet, 11); // A3 + m_pDoc->SetValue(1, 2, srcSheet, 12); // B3 + m_pDoc->SetValue(3, 2, srcSheet, 14); // D3 + + ScMarkData aSrcMark(m_pDoc->GetSheetLimits()); + aSrcMark.SelectOneTable(0); + ScClipParam aClipParam; + aClipParam.meDirection = ScClipParam::Row; + aClipParam.maRanges.push_back(ScRange(0, 0, srcSheet, 3, 0, srcSheet)); // A1:D1 + aClipParam.maRanges.push_back(ScRange(0, 2, srcSheet, 3, 2, srcSheet)); // A3:D3 + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aSrcMark, false, false); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::CONTENTS, true, false); + + ScRange aDestRange(1, 1, destSheet, 2, 4, destSheet); // Paste to B2:C5 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyMultiRangeFromClip(ScAddress(1, 1, destSheet), aMark, InsertDeleteFlags::CONTENTS, + pTransClip.get(), true, false /* false fixes tdf#141683 */, + false, false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B3.", pFC); + m_pDoc->GetFormula(1, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B3", OUString("=$Sheet1.$B$1"), aString); + CPPUNIT_ASSERT_EQUAL(2.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 3, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell B4.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(1, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B5", OUString("=$Sheet1.$D$1"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell C2.", pFC); + m_pDoc->GetFormula(2, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C2", OUString("=$Sheet1.$A$3"), aString); + CPPUNIT_ASSERT_EQUAL(11.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell C3.", pFC); + m_pDoc->GetFormula(2, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C3", OUString("=$Sheet1.$B$3"), aString); + CPPUNIT_ASSERT_EQUAL(12.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 3, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell C4.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(2, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C5", OUString("=$Sheet1.$D$3"), aString); + CPPUNIT_ASSERT_EQUAL(14.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// tdf#141683 +// InsertDeleteFlags::CONTENTS +void Test::testCopyPasteSpecialMultiRangeRowAsLinkFilteredTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(1, 0, srcSheet, 2); // B1 + m_pDoc->SetValue(3, 0, srcSheet, 4); // D1 + + m_pDoc->SetValue(0, 1, srcSheet, -1); // A2, filtered and selected + m_pDoc->SetValue(1, 1, srcSheet, -2); // B2, filtered and selected + m_pDoc->SetValue(3, 1, srcSheet, -4); // D2, filtered and selected + + m_pDoc->SetValue(0, 2, srcSheet, 11); // A3 + m_pDoc->SetValue(1, 2, srcSheet, 12); // B3 + m_pDoc->SetValue(3, 2, srcSheet, 14); // D3 + + m_pDoc->SetValue(0, 3, srcSheet, -11); // A4, filtered and not selected + m_pDoc->SetValue(1, 3, srcSheet, -12); // B4, filtered and not selected + m_pDoc->SetValue(3, 3, srcSheet, -14); // D4, filtered and not selected + + m_pDoc->SetValue(0, 5, srcSheet, 111); // A6 + m_pDoc->SetValue(1, 5, srcSheet, 112); // B6 + m_pDoc->SetValue(3, 5, srcSheet, 114); // D6 + + // Filter row 1 + ScDBData* pDBData = new ScDBData("TRANSPOSE_TEST_DATA", srcSheet, 0, 0, 3, 3); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr<ScDBData>(pDBData)); + + pDBData->SetAutoFilter(true); + ScRange aRange; + pDBData->GetArea(aRange); + m_pDoc->ApplyFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aStart.Row(), aRange.aStart.Tab(), ScMF::Auto); + + //create the query param + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_GREATER_EQUAL; + rEntry.GetQueryItem().mfVal = 0; // filtering neative values -> filtering row 1 and 2 + // add queryParam to database range. + pDBData->SetQueryParam(aParam); + + // perform the query. + m_pDoc->Query(srcSheet, aParam, true); + + ScMarkData aSrcMark(m_pDoc->GetSheetLimits()); + aSrcMark.SelectOneTable(0); + ScClipParam aClipParam; + aClipParam.meDirection = ScClipParam::Row; + aClipParam.maRanges.push_back(ScRange(0, 0, srcSheet, 3, 2, srcSheet)); // A1:C3 + aClipParam.maRanges.push_back(ScRange(0, 5, srcSheet, 3, 5, srcSheet)); // A6:C6 + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aSrcMark, false, false); + + printRange(m_pDoc, aClipParam.getWholeRange(), "Src range"); + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::CONTENTS, true, false); + + printRange(&aClipDoc, ScRange(0, 0, 0, 4, 5, 0), "Base doc (&aNewClipDoc)"); + printRange(pTransClip.get(), ScRange(0, 0, 0, 3, 3, 0), + "Transposed filtered clipdoc (pTransClip.get())"); + ScRange aDestRange(1, 1, destSheet, 3, 4, destSheet); // Paste to B2:D5 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyMultiRangeFromClip(ScAddress(1, 1, destSheet), aMark, InsertDeleteFlags::CONTENTS, + pTransClip.get(), true, false /* false fixes tdf#141683 */, + false, false); + pTransClip.reset(); + printRange(m_pDoc, aDestRange, "Transposed dest sheet"); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B3.", pFC); + m_pDoc->GetFormula(1, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B3", OUString("=$Sheet1.$B$1"), aString); + CPPUNIT_ASSERT_EQUAL(2.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 3, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell B4.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(1, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B5", OUString("=$Sheet1.$D$1"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell C2.", pFC); + m_pDoc->GetFormula(2, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C2", OUString("=$Sheet1.$A$3"), aString); + CPPUNIT_ASSERT_EQUAL(11.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell C3.", pFC); + m_pDoc->GetFormula(2, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C3", OUString("=$Sheet1.$B$3"), aString); + CPPUNIT_ASSERT_EQUAL(12.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 3, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell C4.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(2, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C5", OUString("=$Sheet1.$D$3"), aString); + CPPUNIT_ASSERT_EQUAL(14.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell D2.", pFC); + m_pDoc->GetFormula(3, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D2", OUString("=$Sheet1.$A$6"), aString); + CPPUNIT_ASSERT_EQUAL(111.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell D3.", pFC); + m_pDoc->GetFormula(3, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D3", OUString("=$Sheet1.$B$6"), aString); + CPPUNIT_ASSERT_EQUAL(112.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 3, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell D4.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(3, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D5", OUString("=$Sheet1.$D$6"), aString); + CPPUNIT_ASSERT_EQUAL(114.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// tdf#141683 +// InsertDeleteFlags::CONTENTS +void Test::testCopyPasteSpecialMultiRangeColAsLinkTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + m_pDoc->SetValue(2, 0, srcSheet, 11); // C1 + m_pDoc->SetValue(2, 1, srcSheet, 12); // C2 + m_pDoc->SetValue(2, 3, srcSheet, 14); // C4 + + ScMarkData aSrcMark(m_pDoc->GetSheetLimits()); + aSrcMark.SelectOneTable(0); + ScClipParam aClipParam; + aClipParam.meDirection = ScClipParam::Column; + aClipParam.maRanges.push_back(ScRange(0, 0, srcSheet, 0, 3, srcSheet)); // A1:A4 + aClipParam.maRanges.push_back(ScRange(2, 0, srcSheet, 2, 3, srcSheet)); // C1:C4 + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aSrcMark, false, false); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::CONTENTS, true, false); + + ScRange aDestRange(1, 1, destSheet, 4, 2, destSheet); // Paste to B2:E3 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyMultiRangeFromClip(ScAddress(1, 1, destSheet), aMark, InsertDeleteFlags::CONTENTS, + pTransClip.get(), true, false /* false fixes tdf#141683 */, + false, false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell C2.", pFC); + m_pDoc->GetFormula(2, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C2", OUString("=$Sheet1.$A$2"), aString); + CPPUNIT_ASSERT_EQUAL(2.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell D2.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(4, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell E2", OUString("=$Sheet1.$A$4"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B3.", pFC); + m_pDoc->GetFormula(1, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B3", OUString("=$Sheet1.$C$1"), aString); + CPPUNIT_ASSERT_EQUAL(11.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell C3.", pFC); + m_pDoc->GetFormula(2, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C3", OUString("=$Sheet1.$C$2"), aString); + CPPUNIT_ASSERT_EQUAL(12.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell D3.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(4, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell E3", OUString("=$Sheet1.$C$4"), aString); + CPPUNIT_ASSERT_EQUAL(14.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// tdf#141683 +// InsertDeleteFlags::CONTENTS +void Test::testCopyPasteSpecialMultiRangeColAsLinkFilteredTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + m_pDoc->SetValue(2, 0, srcSheet, 11); // C1 + m_pDoc->SetValue(2, 1, srcSheet, 12); // C2 + m_pDoc->SetValue(2, 3, srcSheet, 14); // C4 + + // Filter row 1 + ScDBData* pDBData = new ScDBData("TRANSPOSE_TEST_DATA", srcSheet, 0, 0, 0, 3); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr<ScDBData>(pDBData)); + + pDBData->SetAutoFilter(true); + ScRange aRange; + pDBData->GetArea(aRange); + m_pDoc->ApplyFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aStart.Row(), aRange.aStart.Tab(), ScMF::Auto); + + //create the query param + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_NOT_EQUAL; + rEntry.GetQueryItem().mfVal = 2; // value of row A2 -> filtering row 1 + // add queryParam to database range. + pDBData->SetQueryParam(aParam); + + // perform the query. + m_pDoc->Query(srcSheet, aParam, true); + + ScMarkData aSrcMark(m_pDoc->GetSheetLimits()); + aSrcMark.SelectOneTable(0); + ScClipParam aClipParam; + aClipParam.meDirection = ScClipParam::Column; + aClipParam.maRanges.push_back(ScRange(0, 0, srcSheet, 0, 3, srcSheet)); // A1:A4 + aClipParam.maRanges.push_back(ScRange(2, 0, srcSheet, 2, 3, srcSheet)); // C1:C4 + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aSrcMark, false, false); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::CONTENTS, true, false); + + ScRange aDestRange(1, 1, destSheet, 4, 2, destSheet); // Paste to B2:E3 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyMultiRangeFromClip(ScAddress(1, 1, destSheet), aMark, InsertDeleteFlags::CONTENTS, + pTransClip.get(), true, false /* false fixes tdf#141683 */, + false, false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell C2.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(3, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D2", OUString("=$Sheet1.$A$4"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(1, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B3.", pFC); + m_pDoc->GetFormula(1, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B3", OUString("=$Sheet1.$C$1"), aString); + CPPUNIT_ASSERT_EQUAL(11.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be no formula cell C3.", !pFC); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 2, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(3, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D3", OUString("=$Sheet1.$C$4"), aString); + CPPUNIT_ASSERT_EQUAL(14.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// InsertDeleteFlags::ALL +void Test::testCopyPasteSpecialAllAsLinkTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + ScRange aSrcRange(0, 0, srcSheet, 0, 3, srcSheet); // Copy A1:A4 to clip. + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, aSrcRange, &aClipDoc); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::ALL, true, false); + + ScRange aDestRange(1, 1, destSheet, 4, 1, destSheet); // Paste to B2:E2 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::ALL, nullptr, pTransClip.get(), true, + false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(2, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C2", OUString("=$Sheet1.$A$2"), aString); + CPPUNIT_ASSERT_EQUAL(2.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(3, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D2", OUString("=$Sheet1.$A$3"), aString); + CPPUNIT_ASSERT_EQUAL(0.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(4, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell E2", OUString("=$Sheet1.$A$4"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// InsertDeleteFlags::ALL +void Test::testCopyPasteSpecialAllAsLinkFilteredTranspose() +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. + + m_pDoc->InsertTab(srcSheet, "Sheet1"); + m_pDoc->InsertTab(destSheet, "Sheet2"); + + m_pDoc->SetValue(0, 0, srcSheet, 1); // A1 + m_pDoc->SetValue(0, 1, srcSheet, 2); // A2 + m_pDoc->SetValue(0, 3, srcSheet, 4); // A4 + + // Filter row 1 + ScDBData* pDBData = new ScDBData("TRANSPOSE_TEST_DATA", srcSheet, 0, 0, 0, 3); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr<ScDBData>(pDBData)); + + pDBData->SetAutoFilter(true); + ScRange aRange; + pDBData->GetArea(aRange); + m_pDoc->ApplyFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aStart.Row(), aRange.aStart.Tab(), ScMF::Auto); + //create the query param + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_NOT_EQUAL; + rEntry.GetQueryItem().mfVal = 2; // value of row A2 -> filtering row 1 + // add queryParam to database range. + pDBData->SetQueryParam(aParam); + + // perform the query. + m_pDoc->Query(srcSheet, aParam, true); + + // Check precondition for test: row 1 is hidden/filtered + SCROW nRow1, nRow2; + SCROW nFilteredRow1, nFilteredRow2; + bool bHidden = m_pDoc->RowHidden(SCROW(1), srcSheet, &nRow1, &nRow2); + CPPUNIT_ASSERT_MESSAGE("row 1 should be hidden", bHidden); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be hidden", SCROW(1), nRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be hidden", SCROW(1), nRow2); + bool bFiltered = m_pDoc->RowFiltered(SCROW(1), srcSheet, &nFilteredRow1, &nFilteredRow2); + CPPUNIT_ASSERT_MESSAGE("row 1 should be filtered", bFiltered); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be filtered", SCROW(1), nFilteredRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be filtered", SCROW(1), nFilteredRow2); + + // Copy A1:A4 to clip. + ScRange aSrcRange(0, 0, srcSheet, 0, 3, srcSheet); + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, aSrcRange, &aClipDoc); + + // transpose + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aClipDoc.TransposeClip(pTransClip.get(), InsertDeleteFlags::ALL, true, false); + + ScRange aDestRange(1, 1, destSheet, 3, 1, destSheet); // Paste to B2:D2 on Sheet2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::ALL, nullptr, pTransClip.get(), true, + false, false); + pTransClip.reset(); + + OUString aString; + // Check pasted content to make sure they reference the correct cells. + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(1, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell B2.", pFC); + m_pDoc->GetFormula(1, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell B2", OUString("=$Sheet1.$A$1"), aString); + CPPUNIT_ASSERT_EQUAL(1.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(2, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(2, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell C2", OUString("=$Sheet1.$A$3"), aString); + CPPUNIT_ASSERT_EQUAL(0.0, pFC->GetValue()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(3, 1, destSheet)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + m_pDoc->GetFormula(3, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula cell D2", OUString("=$Sheet1.$A$4"), aString); + CPPUNIT_ASSERT_EQUAL(4.0, pFC->GetValue()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +// This method is used to create the different copy/paste special test cases. +// Principle: Creation of test cases is parameterized, whereas checking uses a minimum of logic +void Test::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFiltered, bool bAsLink, + bool bTranspose, bool bMultiRangeSelection, bool bSkipEmpty, + ScClipParam::Direction eDirection = ScClipParam::Column, + bool bCalcAll = false, + InsertDeleteFlags aFlags + = InsertDeleteFlags::CONTENTS | InsertDeleteFlags::ATTRIB) +{ + // Reset settings needed for SUMIF() if run with other tests + ScFormulaOptions aOptions; + aOptions.SetFormulaSepArg(";"); + getDocShell().SetFormulaOptions(aOptions); + + const SCTAB srcSheet = 0; + m_pDoc->InsertTab(srcSheet, "SrcSheet"); + + // We need a drawing layer in order to create caption objects. + m_pDoc->InitDrawLayer(&getDocShell()); + ScFieldEditEngine& rEditEngine = m_pDoc->GetEditEngine(); + + /* + | A | B | C | D | E | F | + + 1r | 1 B*| =A1+10 *| a | R1 *| =A1+A3+60 | =SUMIF(A1:A4;"<4") | + 2r | 2 B*| =A2+20 b | b *| R2 *| | *| <- filtered row + 3r | 3 B*| =D3+30 b*| c *| 5 *| B*| | + 4 | 4 | =A2+40 b*| d *| R4 *| =A1+A3+70 *| =B$1+$A$3+80 *| + (5r | 6 | q | r bB*| s bB| t | u |) optional, for row range + (6 | -1 | -2 | -3 | -4 | -5 | -6 |) optional, for row range + (7r | -11 | -12 | -13 | -14 | -15 | -16 |) optional, for row range + (8 | -21 | -22 | -23 | -24 | -25 | -26 |) optional, for row range + + \______________/ \________________________________________/ + col range 1 col range 2 + + * means note attached + B means background + b means border + r means row selected for row range in multi range selection + + The following test scenarios can be created: + + * Filtered row + * Transpose + * All cell types: numbers, strings, formulas, rich text, empty cell + * Notes at different position + * Formula references to rows before and after filtered row + * Double reference (e.g. A1:A3) + * Relative and absolute references + * absolute references are not changed by transposing + * Formatting patterns (e.g. cell backgrounds and borders) + * Multi range selection with direction column and row + + */ + SCCOL nSrcCols = 6; + SCROW nSrcRows = 4; + // Add additional row for MultiRange test cases + if (bMultiRangeSelection) + { + nSrcRows = eDirection == ScClipParam::Row ? nSrcRows + 2 : nSrcRows; + nSrcCols = eDirection == ScClipParam::Column ? nSrcCols + 1 : nSrcCols; + } + + // col A + m_pDoc->SetValue(0, 0, srcSheet, 1); + m_pDoc->SetValue(0, 1, srcSheet, 2); + m_pDoc->SetValue(0, 2, srcSheet, 3); + m_pDoc->SetValue(0, 3, srcSheet, 4); + // col B + m_pDoc->SetString(1, 0, srcSheet, "=A1+10"); + m_pDoc->SetString(1, 1, srcSheet, "=A2+20"); + m_pDoc->SetString(1, 2, srcSheet, "=D3+30"); + m_pDoc->SetString(1, 3, srcSheet, "=A2+40"); + // col C + m_pDoc->SetString(2, 0, srcSheet, "a"); + m_pDoc->SetString(2, 1, srcSheet, "b"); + m_pDoc->SetString(2, 2, srcSheet, "c"); + m_pDoc->SetString(2, 3, srcSheet, "d"); + // col D + rEditEngine.SetTextCurrentDefaults("R1"); + m_pDoc->SetEditText(ScAddress(3, 0, srcSheet), rEditEngine.CreateTextObject()); + rEditEngine.SetTextCurrentDefaults("R2"); + m_pDoc->SetEditText(ScAddress(3, 1, srcSheet), rEditEngine.CreateTextObject()); + m_pDoc->SetValue(3, 2, srcSheet, 5); + rEditEngine.SetTextCurrentDefaults("R4"); + m_pDoc->SetEditText(ScAddress(3, 3, srcSheet), rEditEngine.CreateTextObject()); + // col E + m_pDoc->SetValue(4, 0, srcSheet, 9); + m_pDoc->SetString(4, 0, srcSheet, "=A1+A3+60"); + m_pDoc->SetEmptyCell(ScAddress(4, 1, srcSheet)); + m_pDoc->SetEmptyCell(ScAddress(4, 2, srcSheet)); + m_pDoc->SetString(4, 3, srcSheet, "=A1+A3+70"); + // col F + m_pDoc->SetValue(5, 0, srcSheet, 9); + m_pDoc->SetString(5, 0, srcSheet, "=SUMIF(A1:A4;\"<4\")"); + m_pDoc->SetEmptyCell(ScAddress(5, 1, srcSheet)); + m_pDoc->SetEmptyCell(ScAddress(5, 2, srcSheet)); + m_pDoc->SetString(5, 3, srcSheet, "=B$1+$A$3+80"); + + const SfxPoolItem* pItem = nullptr; + + // row 4, additional row for MultiRange test case, otherwise not selected + m_pDoc->SetValue(0, 4, srcSheet, 6); + m_pDoc->SetString(1, 4, srcSheet, "q"); + m_pDoc->SetString(2, 4, srcSheet, "r"); + m_pDoc->SetString(3, 4, srcSheet, "s"); + m_pDoc->SetString(4, 4, srcSheet, "t"); + m_pDoc->SetString(5, 4, srcSheet, "u"); + + // row 5, not selected + m_pDoc->SetValue(0, 5, srcSheet, -1); + m_pDoc->SetValue(1, 5, srcSheet, -2); + m_pDoc->SetValue(2, 5, srcSheet, -3); + m_pDoc->SetValue(3, 5, srcSheet, -4); + m_pDoc->SetValue(4, 5, srcSheet, -5); + m_pDoc->SetValue(5, 5, srcSheet, -6); + + // row 6, additional row for MultiRange test case, otherwise not selected + m_pDoc->SetValue(0, 6, srcSheet, -11); + m_pDoc->SetValue(1, 6, srcSheet, -12); + m_pDoc->SetValue(2, 6, srcSheet, -13); + m_pDoc->SetValue(3, 6, srcSheet, -14); + m_pDoc->SetValue(4, 6, srcSheet, -15); + m_pDoc->SetValue(5, 6, srcSheet, -16); + + // row 7, additional row for MultiRange test case, otherwise not selected + m_pDoc->SetValue(0, 7, srcSheet, -21); + m_pDoc->SetValue(1, 7, srcSheet, -22); + m_pDoc->SetValue(2, 7, srcSheet, -23); + m_pDoc->SetValue(3, 7, srcSheet, -24); + m_pDoc->SetValue(4, 7, srcSheet, -25); + m_pDoc->SetValue(5, 7, srcSheet, -26); + + // Col G, not selected + m_pDoc->SetValue(6, 0, srcSheet, 111); + m_pDoc->SetValue(6, 1, srcSheet, 112); + m_pDoc->SetValue(6, 2, srcSheet, 113); + m_pDoc->SetValue(6, 3, srcSheet, 114); + m_pDoc->SetValue(6, 4, srcSheet, 115); + m_pDoc->SetValue(6, 5, srcSheet, 116); + + // Col H, additional col for MultiRange test case, otherwise not selected + m_pDoc->SetValue(7, 0, srcSheet, 121); + m_pDoc->SetValue(7, 1, srcSheet, 122); + m_pDoc->SetValue(7, 2, srcSheet, 123); + m_pDoc->SetValue(7, 3, srcSheet, 124); + m_pDoc->SetValue(7, 4, srcSheet, 125); + m_pDoc->SetValue(7, 5, srcSheet, 126); + + // Col J, not selected + m_pDoc->SetValue(8, 0, srcSheet, 131); + m_pDoc->SetValue(8, 1, srcSheet, 132); + m_pDoc->SetValue(8, 2, srcSheet, 133); + m_pDoc->SetValue(8, 3, srcSheet, 134); + m_pDoc->SetValue(8, 4, srcSheet, 135); + m_pDoc->SetValue(8, 5, srcSheet, 136); + + // add patterns + ScPatternAttr aCellBlueColor(m_pDoc->GetPool()); + aCellBlueColor.GetItemSet().Put(SvxBrushItem(COL_BLUE, ATTR_BACKGROUND)); + m_pDoc->ApplyPatternAreaTab(0, 0, 0, 2, srcSheet, aCellBlueColor); + + // Check pattern precondition + m_pDoc->GetPattern(ScAddress(0, 0, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("SrcSheet.A1 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(0, 1, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("SrcSheet.A2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(0, 3, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("SrcSheet.A4 has no pattern", !pItem); + + // row 2 on empty cell + ScPatternAttr aCellGreenColor(m_pDoc->GetPool()); + aCellGreenColor.GetItemSet().Put(SvxBrushItem(COL_GREEN, ATTR_BACKGROUND)); + m_pDoc->ApplyPatternAreaTab(4, 2, 4, 2, srcSheet, aCellGreenColor); + + // row 4 for multi range row selection + ScPatternAttr aCellRedColor(m_pDoc->GetPool()); + aCellRedColor.GetItemSet().Put(SvxBrushItem(COL_RED, ATTR_BACKGROUND)); + m_pDoc->ApplyPatternAreaTab(2, 4, 3, 4, srcSheet, aCellRedColor); + + // add borders + ::editeng::SvxBorderLine aLine(nullptr, 50, SvxBorderLineStyle::SOLID); + SvxBoxItem aBorderItem(ATTR_BORDER); + aBorderItem.SetLine(&aLine, SvxBoxItemLine::LEFT); + aBorderItem.SetLine(&aLine, SvxBoxItemLine::RIGHT); + m_pDoc->ApplyAttr(1, 1, srcSheet, aBorderItem); + m_pDoc->ApplyAttr(1, 2, srcSheet, aBorderItem); + m_pDoc->ApplyAttr(1, 3, srcSheet, aBorderItem); + // Check border precondition + pItem = m_pDoc->GetAttr(ScAddress(1, 0, srcSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("SrcSheet.B1 has a border", pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + pItem = m_pDoc->GetAttr(ScAddress(1, 1, srcSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("SrcSheet.B2 has a border", pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + // Check border precondition 2 + m_pDoc->GetPattern(ScAddress(1, 1, srcSheet))->GetItemSet().HasItem(ATTR_BORDER, &pItem); + CPPUNIT_ASSERT_MESSAGE("SrcSheet.B2 has a border", pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + // row 4 for multi range row selection + ::editeng::SvxBorderLine aDoubleLine(nullptr, 50, SvxBorderLineStyle::DOUBLE); + SvxBoxItem aDoubleBorderItem(ATTR_BORDER); + aDoubleBorderItem.SetLine(&aDoubleLine, SvxBoxItemLine::TOP); + aDoubleBorderItem.SetLine(&aDoubleLine, SvxBoxItemLine::BOTTOM); + m_pDoc->ApplyAttr(2, 4, srcSheet, aDoubleBorderItem); + m_pDoc->ApplyAttr(3, 4, srcSheet, aDoubleBorderItem); + + // add notes to A1:F4 + + // add notes row 0 + ScAddress aAdrA1(0, 0, srcSheet); + ScPostIt* pNoteA1 = m_pDoc->GetOrCreateNote(aAdrA1); + pNoteA1->SetText(aAdrA1, "Hello world in A1"); + ScAddress aAdrB1(1, 0, srcSheet); + ScPostIt* pNoteB1 = m_pDoc->GetOrCreateNote(aAdrB1); + pNoteB1->SetText(aAdrB1, "Hello world in B1"); + // No note on C1 + ScAddress aAdrD1(3, 0, srcSheet); + ScPostIt* pNoteD1 = m_pDoc->GetOrCreateNote(aAdrD1); + pNoteD1->SetText(aAdrD1, "Hello world in D1"); + // No note on E1 + // No note on F1 + + // add notes row 1 + ScAddress aAdrA2(0, 1, srcSheet); + ScPostIt* pNoteA2 = m_pDoc->GetOrCreateNote(aAdrA2); + pNoteA2->SetText(aAdrA2, "Hello world in A2"); + // No note on B2 + ScAddress aAdrC2(2, 1, srcSheet); + ScPostIt* pNoteC2 = m_pDoc->GetOrCreateNote(aAdrC2); + pNoteC2->SetText(aAdrC2, "Hello world in C2"); + ScAddress aAdrD2(3, 1, srcSheet); + ScPostIt* pNoteD2 = m_pDoc->GetOrCreateNote(aAdrD2); + pNoteD2->SetText(aAdrD2, "Hello world in D2"); + ScAddress aAdrE2(4, 2, srcSheet); + ScPostIt* pNoteE2 = m_pDoc->GetOrCreateNote(aAdrE2); + pNoteE2->SetText(aAdrE2, "Hello world in E2"); + ScAddress aAdrF2(5, 1, srcSheet); + ScPostIt* pNoteF2 = m_pDoc->GetOrCreateNote(aAdrF2); + pNoteF2->SetText(aAdrF2, "Hello world in F2"); + + // add notes row 2 + ScAddress aAdrA3(0, 2, srcSheet); + ScPostIt* pNoteA3 = m_pDoc->GetOrCreateNote(aAdrA3); + pNoteA3->SetText(aAdrA3, "Hello world in A3"); + ScAddress aAdrB3(1, 2, srcSheet); + ScPostIt* pNoteB3 = m_pDoc->GetOrCreateNote(aAdrB3); + pNoteB3->SetText(aAdrB3, "Hello world in B3"); + ScAddress aAdrC3(2, 2, srcSheet); + ScPostIt* pNoteC3 = m_pDoc->GetOrCreateNote(aAdrC3); + pNoteC3->SetText(aAdrC3, "Hello world in C3"); + ScAddress aAdrD3(3, 2, srcSheet); + ScPostIt* pNoteD3 = m_pDoc->GetOrCreateNote(aAdrD3); + pNoteD3->SetText(aAdrD3, "Hello world in D3"); + // No note on E3 + // No note on F3 + + // add notes row 3 + // No note on A4 + ScAddress aAdrB4(1, 3, srcSheet); + ScPostIt* pNoteB4 = m_pDoc->GetOrCreateNote(aAdrB4); + pNoteB4->SetText(aAdrB4, "Hello world in B4"); + ScAddress aAdrC4(2, 3, srcSheet); + ScPostIt* pNoteC4 = m_pDoc->GetOrCreateNote(aAdrC4); + pNoteC4->SetText(aAdrC4, "Hello world in C4"); + ScAddress aAdrD4(3, 3, srcSheet); + ScPostIt* pNoteD4 = m_pDoc->GetOrCreateNote(aAdrD4); + pNoteD4->SetText(aAdrD4, "Hello world in D4"); + ScAddress aAdrE4(4, 3, srcSheet); + ScPostIt* pNoteE4 = m_pDoc->GetOrCreateNote(aAdrE4); + pNoteE4->SetText(aAdrE4, "Hello world in E4"); + ScAddress aAdrF4(5, 3, srcSheet); + ScPostIt* pNoteF4 = m_pDoc->GetOrCreateNote(aAdrF4); + pNoteF4->SetText(aAdrF4, "Hello world in F4"); + + // row 4 for multi range row selection + ScAddress aAdrC5(2, 4, srcSheet); + ScPostIt* pNoteC5 = m_pDoc->GetOrCreateNote(aAdrC5); + pNoteC5->SetText(aAdrC5, "Hello world in C5"); + + // Filter out row 1 + if (bApplyFilter) + { + ScDBData* pDBData + = new ScDBData("TRANSPOSE_TEST_DATA", srcSheet, 0, 0, nSrcCols - 1, nSrcRows - 1); + m_pDoc->SetAnonymousDBData(srcSheet, std::unique_ptr<ScDBData>(pDBData)); + + pDBData->SetAutoFilter(true); + ScRange aRange; + pDBData->GetArea(aRange); + m_pDoc->ApplyFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aStart.Row(), aRange.aStart.Tab(), ScMF::Auto); + + //create the query param + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_NOT_EQUAL; + rEntry.GetQueryItem().mfVal = 2; // value of row A2 -> filtering row 1 + // add queryParam to database range. + pDBData->SetQueryParam(aParam); + + // perform the query. + m_pDoc->Query(srcSheet, aParam, true); + + // Check precondition for test: row 1 is hidden/filtered + SCROW nRow1, nRow2; + SCROW nFilteredRow1, nFilteredRow2; + bool bHidden = m_pDoc->RowHidden(SCROW(1), srcSheet, &nRow1, &nRow2); + CPPUNIT_ASSERT_MESSAGE("row 1 should be hidden", bHidden); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be hidden", SCROW(1), nRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be hidden", SCROW(1), nRow2); + bool bFiltered = m_pDoc->RowFiltered(SCROW(1), srcSheet, &nFilteredRow1, &nFilteredRow2); + CPPUNIT_ASSERT_MESSAGE("row 1 should be filtered", bFiltered); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be filtered", SCROW(1), nFilteredRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("row 1 should be filtered", SCROW(1), nFilteredRow2); + } + + // create destination sheet + const SCTAB destSheet = 1; + m_pDoc->InsertTab(destSheet, "DestSheet"); + // set cells to 1000 to check empty cell behaviour and to detect destination range problems + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + m_pDoc->SetValue(i, j, destSheet, 1000); + + // transpose clipboard, paste on DestSheet + ScDocument aNewClipDoc(SCDOCMODE_CLIP); + ScMarkData aDestMark(m_pDoc->GetSheetLimits()); + if (!bMultiRangeSelection) + { + ScRange aSrcRange(0, 0, srcSheet, nSrcCols - 1, nSrcRows - 1, srcSheet); + copyToClip(m_pDoc, aSrcRange, &aNewClipDoc); + + // ScDocument::TransposeClip() and ScDocument::CopyFromClip() calls + // analog to ScViewFunc::PasteFromClip() + if (bTranspose) + { + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aNewClipDoc.TransposeClip(pTransClip.get(), aFlags, bAsLink, bIncludedFiltered); + ScRange aDestRange(3, 1, destSheet, 3 + nSrcRows - 1, 1 + nSrcCols - 1, + destSheet); //target: D2:F6 + aDestMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aDestMark, aFlags, nullptr, pTransClip.get(), true, + bAsLink, bIncludedFiltered, bSkipEmpty); + pTransClip.reset(); + } + else + { + ScRange aDestRange(3, 1, destSheet, 3 + nSrcCols - 1, 1 + nSrcRows - 1, + destSheet); //target: D2:I5 + aDestMark.SetMarkArea(aDestRange); + m_pDoc->CopyFromClip(aDestRange, aDestMark, aFlags, nullptr, &aNewClipDoc, true, + bAsLink, bIncludedFiltered, bSkipEmpty); + } + } + else + { + ScMarkData aSrcMark(m_pDoc->GetSheetLimits()); + aSrcMark.SelectOneTable(0); + ScClipParam aClipParam; + aClipParam.meDirection = eDirection; + if (eDirection == ScClipParam::Column) + { + aClipParam.maRanges.push_back(ScRange(0, 0, srcSheet, 1, 3, srcSheet)); // A1:B4 + aClipParam.maRanges.push_back(ScRange(3, 0, srcSheet, 5, 3, srcSheet)); // D1:F4 + aClipParam.maRanges.push_back(ScRange(7, 0, srcSheet, 7, 3, srcSheet)); // H1:H4 + } + else if (eDirection == ScClipParam::Row) + { + aClipParam.maRanges.push_back(ScRange(0, 0, srcSheet, 5, 2, srcSheet)); // A1:F3 + aClipParam.maRanges.push_back(ScRange(0, 4, srcSheet, 5, 4, srcSheet)); // A5:F5 + aClipParam.maRanges.push_back(ScRange(0, 6, srcSheet, 5, 6, srcSheet)); // A7:F7 + } + CPPUNIT_ASSERT(aClipParam.isMultiRange()); + m_pDoc->CopyToClip(aClipParam, &aNewClipDoc, &aSrcMark, false, false); + + // ScDocument::TransposeClip() and ScDocument::CopyMultiRangeFromClip() calls + // analog to ScViewFunc::PasteFromClipToMultiRanges() + if (bTranspose) + { + printRange(m_pDoc, aClipParam.getWholeRange(), "Src range"); + ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); + aNewClipDoc.TransposeClip(pTransClip.get(), aFlags, bAsLink, bIncludedFiltered); + ScRange aDestRange(3, 1, destSheet, 3 + nSrcRows - 1, 1 + nSrcCols - 1 - 1, + destSheet); //target col: D2:G6, target row: D2:H6 + aDestMark.SetMarkArea(aDestRange); + printRange(&aNewClipDoc, ScRange(0, 0, 0, nSrcCols, nSrcRows, 0), + "Base doc (&aNewClipDoc)"); + printRange(pTransClip.get(), ScRange(0, 0, 0, nSrcCols, nSrcRows, 0), + "Transposed filtered clipdoc (pTransClip.get())"); + m_pDoc->CopyMultiRangeFromClip(ScAddress(3, 1, destSheet), aDestMark, aFlags, + pTransClip.get(), true, bAsLink && !bTranspose, + bIncludedFiltered, bSkipEmpty); + pTransClip.reset(); + printRange(m_pDoc, aDestRange, "Transposed dest sheet"); + } + else + { + ScRange aDestRange(3, 1, destSheet, 3 + nSrcCols - 1 - 1, 1 + nSrcRows - 1, + destSheet); //target col: D2:I5, target row: D2:I6 + aDestMark.SetMarkArea(aDestRange); + m_pDoc->CopyMultiRangeFromClip(ScAddress(3, 1, destSheet), aDestMark, aFlags, + &aNewClipDoc, true, bAsLink && !bTranspose, + bIncludedFiltered, bSkipEmpty); + } + } + if (bCalcAll) + m_pDoc->CalcAll(); +} + +void Test::testCopyPasteSpecial() +{ + executeCopyPasteSpecial(false, false, false, false, false, false); + checkCopyPasteSpecial(false); +} + +void Test::testCopyPasteSpecialFiltered() +{ + executeCopyPasteSpecial(true, false, false, false, false, false); + checkCopyPasteSpecialFiltered(false); +} + +void Test::testCopyPasteSpecialIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(false, true, false, false, false, false); + checkCopyPasteSpecial(false); +} + +void Test::testCopyPasteSpecialFilteredIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, false, false, false); + checkCopyPasteSpecial(false); +} + +// similar to Test::testCopyPasteTranspose(), but this test is more complex +void Test::testCopyPasteSpecialTranspose() +{ + executeCopyPasteSpecial(false, false, false, true, false, false); + checkCopyPasteSpecialTranspose(false); +} + +// tdf#107348 +void Test::testCopyPasteSpecialFilteredTranspose() +{ + executeCopyPasteSpecial(true, false, false, true, false, false); + checkCopyPasteSpecialFilteredTranspose(false); +} + +// tdf#107348 +void Test::testCopyPasteSpecialTransposeIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, true, false, false); + checkCopyPasteSpecialTranspose(false); +} + +void Test::testCopyPasteSpecialMultiRangeCol() +{ + executeCopyPasteSpecial(false, false, false, false, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeCol(false); +} + +void Test::testCopyPasteSpecialMultiRangeColIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(false, true, false, false, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeCol(false); +} + +// tdf#45958 +void Test::testCopyPasteSpecialMultiRangeColFiltered() +{ + executeCopyPasteSpecial(true, false, false, false, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColFiltered(false); +} + +// tdf#45958 +void Test::testCopyPasteSpecialMultiRangeColFilteredIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, false, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeCol(false); +} + +void Test::testCopyPasteSpecialMultiRangeColTranspose() +{ + executeCopyPasteSpecial(false, false, false, true, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColTranspose(false); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialMultiRangeColFilteredTranspose() +{ + executeCopyPasteSpecial(true, false, false, true, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColFilteredTranspose(false); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialMultiRangeColFilteredIncludeFilteredTranspose() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, true, true, false, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColTranspose(false); +} + +void Test::testCopyPasteSpecialMultiRangeRow() +{ + executeCopyPasteSpecial(false, false, false, false, true, false, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRow(false); +} + +void Test::testCopyPasteSpecialMultiRangeRowIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(false, true, false, false, true, false, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRow(false); +} + +// tdf#45958 +void Test::testCopyPasteSpecialMultiRangeRowFiltered() +{ + executeCopyPasteSpecial(true, false, false, false, true, false, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRowFiltered(false); +} + +// tdf#45958 +void Test::testCopyPasteSpecialMultiRangeRowFilteredIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, false, true, false, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRow(false); +} + +void Test::testCopyPasteSpecialMultiRangeRowTranspose() +{ + executeCopyPasteSpecial(false, false, false, true, true, false, ScClipParam::Row, true); + checkCopyPasteSpecialMultiRangeRowTranspose(false); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialMultiRangeRowFilteredTranspose() +{ + executeCopyPasteSpecial(true, false, false, true, true, false, ScClipParam::Row, true); + checkCopyPasteSpecialMultiRangeRowFilteredTranspose(false); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialMultiRangeRowFilteredIncludeFilteredTranspose() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, true, true, false, ScClipParam::Row, true); + checkCopyPasteSpecialMultiRangeRowTranspose(false); +} + +void Test::testCopyPasteSpecialSkipEmpty() +{ + executeCopyPasteSpecial(false, false, false, false, false, true); + checkCopyPasteSpecial(true); +} + +void Test::testCopyPasteSpecialSkipEmptyFiltered() +{ + executeCopyPasteSpecial(true, false, false, false, false, true); + checkCopyPasteSpecialFiltered(true); +} + +void Test::testCopyPasteSpecialSkipEmptyIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(false, true, false, false, false, true); + checkCopyPasteSpecial(true); +} + +void Test::testCopyPasteSpecialSkipEmptyFilteredIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, false, false, true); + checkCopyPasteSpecial(true); +} + +// similar to Test::testCopyPasteTranspose(), but this test is more complex +void Test::testCopyPasteSpecialSkipEmptyTranspose() +{ + executeCopyPasteSpecial(false, false, false, true, false, true); + checkCopyPasteSpecialTranspose(true); +} + +// tdf#107348 +void Test::testCopyPasteSpecialSkipEmptyFilteredTranspose() +{ + executeCopyPasteSpecial(true, false, false, true, false, true); + checkCopyPasteSpecialFilteredTranspose(true); +} + +// tdf#107348 +void Test::testCopyPasteSpecialSkipEmptyTransposeIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, true, false, true); + checkCopyPasteSpecialTranspose(true); +} + +void Test::testCopyPasteSpecialSkipEmptyMultiRangeCol() +{ + executeCopyPasteSpecial(false, false, false, false, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeCol(true); +} + +void Test::testCopyPasteSpecialSkipEmptyMultiRangeColIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(false, true, false, false, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeCol(true); +} + +// tdf#45958 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeColFiltered() +{ + executeCopyPasteSpecial(true, false, false, false, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColFiltered(true); +} + +// tdf#45958 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, false, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeCol(true); +} + +void Test::testCopyPasteSpecialSkipEmptyMultiRangeColTranspose() +{ + executeCopyPasteSpecial(false, false, false, true, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColTranspose(true); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredTranspose() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, false, false, true, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColFilteredTranspose(true); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFilteredTranspose() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, true, true, true, ScClipParam::Column); + checkCopyPasteSpecialMultiRangeColTranspose(true); +} + +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRow() +{ + executeCopyPasteSpecial(false, false, false, false, true, true, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRow(true); +} + +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRowIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(false, true, false, false, true, true, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRow(true); +} + +// tdf#45958 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRowFiltered() +{ + executeCopyPasteSpecial(true, false, false, false, true, true, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRowFiltered(true); +} + +// tdf#45958 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFiltered() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, false, true, true, ScClipParam::Row); + checkCopyPasteSpecialMultiRangeRow(true); +} + +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRowTranspose() +{ + executeCopyPasteSpecial(false, false, false, true, true, true, ScClipParam::Row, true); + checkCopyPasteSpecialMultiRangeRowTranspose(true); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredTranspose() +{ + executeCopyPasteSpecial(true, false, false, true, true, true, ScClipParam::Row, true); + checkCopyPasteSpecialMultiRangeRowFilteredTranspose(true); +} + +// tdf#45958, tdf#107348 +void Test::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFilteredTranspose() +{ + // For bIncludeFiltered=true, the non-filtered outcome is expected + executeCopyPasteSpecial(true, true, false, true, true, true, ScClipParam::Row, true); + checkCopyPasteSpecialMultiRangeRowTranspose(true); +} + +// Base check, nothing filtered, nothing transposed +void Test::checkCopyPasteSpecial(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | H | I | + + 2 | 1 B*| =D2+10 *| a | R1 *| =D2+D4+60 | =SUMIF(D2:D5;"<4") | + 3 | 2 B*| =D3+20 b | b *| R2 *| | *| + 4 | 3 B*| =G4+30 b*| c *| 5 *| B*| | + 5 | 4 | =D3+40 b*| d *| R4 *| =D2+D4+70 *| =E$1+$A$3+80 *| + + * means note attached + B means background + b means border + */ + + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // col 2 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + // col 3, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(2, m_pDoc->GetValue(3, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(3, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(3, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 5, destSheet)); + // col 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 1, destSheet)); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D3+20"), aString); + ASSERT_DOUBLES_EQUAL(22, m_pDoc->GetValue(4, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(35, m_pDoc->GetValue(4, 3, destSheet)); + m_pDoc->GetFormula(4, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=G4+30"), aString); + ASSERT_DOUBLES_EQUAL(42, m_pDoc->GetValue(4, 4, destSheet)); + m_pDoc->GetFormula(4, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D3+40"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + // col 5, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + aString = m_pDoc->GetString(5, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(5, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("a"), aString); + aString = m_pDoc->GetString(5, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("b"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("c"), aString); + aString = m_pDoc->GetString(5, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("d"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + aString = m_pDoc->GetString(5, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 6, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 0, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 1, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 2, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R2"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(6, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 4, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 5, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 5, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // col 7, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + aString = m_pDoc->GetString(7, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(7, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+D4+60"), aString); + ASSERT_DOUBLES_EQUAL(64, m_pDoc->GetValue(7, 1, destSheet)); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + } + fValue = m_pDoc->GetValue(7, 4, destSheet); + m_pDoc->GetFormula(7, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+D4+70"), aString); + ASSERT_DOUBLES_EQUAL(74, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 8, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 0, destSheet)); + aString = m_pDoc->GetString(8, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(8, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D2:D5;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(6, m_pDoc->GetValue(8, 1, destSheet)); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(8, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(8, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 3, destSheet)); + } + fValue = m_pDoc->GetValue(8, 4, destSheet); + m_pDoc->GetFormula(8, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=E$1+$A$3+80"), aString); + ASSERT_DOUBLES_EQUAL(2080, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 5, destSheet)); + aString = m_pDoc->GetString(8, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 9, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 5, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(3, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(7, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(4, 1, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 5, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(8, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(8, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 5, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 3, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(8, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(8, 4, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialFiltered(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | H | I | + + 2 | 1 B*| =D2+10 *| a | R1 *| =D2+D4+60 | =SUMIF(D2:D5;"<4") | + 3 | 3 B*| =G3+30 b*| c *| 5 *| B*| | + 4 | 4 | =D2+40 b*| d *| R4 *| =D1+D3+70 *| =E$1+$A$3+80 *| + 5 | 1 B*| =D5+10 *| a | R1 *| =D5+D7+60 | =SUMIF(D5:D8;"<4") | <- repeated row + + * means note attached + B means background + b means border + */ + + OUString aString; + double fValue; + const EditTextObject* pEditObj; + + // col 2 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + // col 3, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(3, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(3, 3, destSheet)); + fValue = m_pDoc->GetValue(3, 4, destSheet); // repeated row 1 + ASSERT_DOUBLES_EQUAL(1, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 5, destSheet)); + // col 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + m_pDoc->GetFormula(4, 0, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 1, destSheet)); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=G3+30"), aString); + ASSERT_DOUBLES_EQUAL(35, fValue); + fValue = m_pDoc->GetValue(4, 3, destSheet); + m_pDoc->GetFormula(4, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+40"), aString); + ASSERT_DOUBLES_EQUAL(41, fValue); + fValue = m_pDoc->GetValue(4, 4, destSheet); // repeated row 1 + ASSERT_DOUBLES_EQUAL(11, fValue); + m_pDoc->GetFormula(4, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D5+10"), aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + // col 5, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + aString = m_pDoc->GetString(5, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("a"), aString); + aString = m_pDoc->GetString(5, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("c"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("d"), aString); + aString = m_pDoc->GetString(5, 4, destSheet); // repeated row 1 + CPPUNIT_ASSERT_EQUAL(OUString("a"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + m_pDoc->GetFormula(4, 5, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + // col 6, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 0, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 1, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(6, 2, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 4, destSheet)); // repeated row 1 + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 5, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 5, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // col 7, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + aString = m_pDoc->GetString(7, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(7, 1, destSheet, aString); + fValue = m_pDoc->GetValue(7, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+D4+60"), aString); + ASSERT_DOUBLES_EQUAL(65, fValue); // formula is not adjusted due to filter row + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + fValue = m_pDoc->GetValue(7, 3, destSheet); + m_pDoc->GetFormula(7, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D1+D3+70"), aString); + ASSERT_DOUBLES_EQUAL(1073, fValue); + m_pDoc->GetFormula(7, 4, destSheet, aString); // repeated row 1 + fValue = m_pDoc->GetValue(7, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("=D5+D7+60"), aString); + ASSERT_DOUBLES_EQUAL(1061, fValue); // formula is not adjusted due to filter row + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 8, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 0, destSheet)); + aString = m_pDoc->GetString(8, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(8, 1, destSheet, aString); + fValue = m_pDoc->GetValue(8, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D2:D5;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(5, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(8, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 2, destSheet)); + fValue = m_pDoc->GetValue(8, 3, destSheet); + m_pDoc->GetFormula(8, 3, destSheet, aString); + ASSERT_DOUBLES_EQUAL(2080, fValue); + CPPUNIT_ASSERT_EQUAL(OUString("=E$1+$A$3+80"), aString); + m_pDoc->GetFormula(8, 4, destSheet, aString); // repeated row 1 + fValue = m_pDoc->GetValue(8, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D5:D8;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(1, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 5, destSheet)); + aString = m_pDoc->GetString(8, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 9, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 5, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(3, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(7, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(4, 1, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(8, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 5, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(8, 3, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialTranspose(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | + + 2 | 1 B*| 2 B*| 3 B*| 4 | + 3 | =D2+10 *| =E2+20 b | =F5+30 b*| =E2+40 b*| + 4 | a | b *| c *| d *| + 5 | R1 *| R2 *| 5 *| R4 *| + 6 | =D2+F2+60 | | B*| =D2+F2+70 *| + 7 | =SUMIF(D2:G2;"<4") | *| | =C$1+$A$1+80 *| + + * means note attached + B means background + b means border + */ + + //check cell content after transposed copy/paste of filtered data + // Note: column F is a repetition of srcSheet.Column A + // Col C and G are checked to be empty + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // row 0 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + // row 1, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + fValue = m_pDoc->GetValue(3, 1, destSheet); // D2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell D2", 1, fValue); + fValue = m_pDoc->GetValue(4, 1, destSheet); // E2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell E2", 2, fValue); + fValue = m_pDoc->GetValue(5, 1, destSheet); // F2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell F2", 3, fValue); + fValue = m_pDoc->GetValue(6, 1, destSheet); // G2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell G2", 4, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 1, destSheet)); + // row 2, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + aString = m_pDoc->GetString(2, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 2, destSheet, aString); // D3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D3 should point on D2", OUString("=D2+10"), + aString); + fValue = m_pDoc->GetValue(3, 2, destSheet); // D3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D3", 11, fValue); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula E3 should point on E2", OUString("=E2+20"), + aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); // E3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula E3", 22, fValue); + m_pDoc->GetFormula(5, 2, destSheet, aString); // F3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula F3 should point on F2", OUString("=F5+30"), + aString); + fValue = m_pDoc->GetValue(5, 2, destSheet); // F3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula F3", 35, fValue); + m_pDoc->GetFormula(6, 2, destSheet, aString); // G3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G3 should point on E2", OUString("=E2+40"), + aString); + fValue = m_pDoc->GetValue(6, 2, destSheet); // G3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula G3", 42, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 3, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + aString = m_pDoc->GetString(2, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(3, 3, destSheet); // D4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell D4 should contain: a", OUString("a"), aString); + aString = m_pDoc->GetString(4, 3, destSheet); // E4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E4 should contain: b", OUString("b"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); // F4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F4 should contain: c", OUString("c"), aString); + aString = m_pDoc->GetString(6, 3, destSheet); // G4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G4 should contain: d", OUString("d"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 4, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(2, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in C5.", pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(3, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in D5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong in D5 ", OUString("R1"), + pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(4, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in E5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong E5.", OUString("R2"), pEditObj->GetText(0)); + fValue = m_pDoc->GetValue(5, 4, destSheet); // F5 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell F5", 5, fValue); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in G5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong G5.", OUString("R4"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(7, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in H5.", pEditObj == nullptr); + // row 5, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 5, destSheet, aString); // D6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D6", OUString("=D2+F2+60"), aString); + fValue = m_pDoc->GetValue(3, 5, destSheet); // D6 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D6", 64, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 5, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(5, 5, destSheet); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + } + fValue = m_pDoc->GetValue(6, 5, destSheet); // G6 + m_pDoc->GetFormula(6, 5, destSheet, aString); // G6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G6", OUString("=D2+F2+70"), aString); + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula G6", 74, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 6, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 6, destSheet)); + aString = m_pDoc->GetString(2, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 6, destSheet, aString); // D7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D7", OUString("=SUMIF(D2:G2;\"<4\")"), + aString); + fValue = m_pDoc->GetValue(3, 6, destSheet); // D7 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D7", 6, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 6, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(5, 6, destSheet); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 6, destSheet)); + } + fValue = m_pDoc->GetValue(6, 6, destSheet); // G7 + m_pDoc->GetFormula(6, 6, destSheet, aString); // G7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G7", OUString("=C$1+$A$3+80"), aString); + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula G7", 2080, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 6, destSheet)); + aString = m_pDoc->GetString(7, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 7 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("D2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("D2 has blue background", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(4, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("E2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("E2 has blue background", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("F2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("F2 has a pattern", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(6, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("G2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(7, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("H2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(5, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(3, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("D3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("D3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("D3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("D3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("D3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + m_pDoc->GetPattern(ScAddress(4, 2, destSheet))->GetItemSet().HasItem(ATTR_BORDER, &pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + + CPPUNIT_ASSERT_MESSAGE("E3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("E3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("E3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("F3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("F3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("F3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("F3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("F3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("G3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("G3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("G3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("G3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(7, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("H3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("H3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("H3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("H3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("H3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT_MESSAGE("There should be no note on C1", + !m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D1", + !m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E1", + !m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F1", + !m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G1", + !m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H1", + !m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C2", + !m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D2", + m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E2", + m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F2", + m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G2", + !m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H2", + !m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C3", + !m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D3", + m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E3", + !m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F3", + m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G3", + m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H3", + !m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C4", + !m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D4", + !m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E4", + m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F4", + m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G4", + m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H4", + !m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C5", + !m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D5", + m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E5", + m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F5", + m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G5", + m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H5", + !m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C6", + !m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D6", + !m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E6", + !m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G6", + m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H6", + !m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C7", + !m_pDoc->HasNote(ScAddress(2, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D7", + !m_pDoc->HasNote(ScAddress(3, 6, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(4, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F7", + !m_pDoc->HasNote(ScAddress(5, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note a G7", + m_pDoc->HasNote(ScAddress(6, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H7", + !m_pDoc->HasNote(ScAddress(7, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C8", + !m_pDoc->HasNote(ScAddress(2, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D8", + !m_pDoc->HasNote(ScAddress(3, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E8", + !m_pDoc->HasNote(ScAddress(4, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F8", + !m_pDoc->HasNote(ScAddress(5, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G8", + !m_pDoc->HasNote(ScAddress(6, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H8", + !m_pDoc->HasNote(ScAddress(7, 7, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D2", + m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E2", + m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F2", + m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 1, destSheet))->GetText()); + // G2 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D3", + m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + // E3 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F3", + m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + // D4 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E4", + m_pDoc->GetNote(ScAddress(2, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F4", + m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on D5", + m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E5", + m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on F5", + m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 5, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on G6", + m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 5, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E7", + m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 6, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on G7", + m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 6, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialFilteredTranspose(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + ┌--- filtered src row 2 ┌--- repeated row + v v + + | D | E | F | G | + + 2 | 1 B*| 3 B*| 4 | 1 B*| + 3 | =D2+10 *| =E5+30 b*| =D2+40 b*| =G2+10 *| + 4 | a | c *| d *| a | + 5 | R1 *| 5 *| R4 *| R1 *| + 6 | =D2+F2+60 | B*| =C2+E2+70 *| =G2+I2+60 | + 7 | =SUMIF(D2:G2;"<4") | | =B$1+$A$1+80 *| =SUMIF(G2:J2;"<4") | + + * means note attached + */ + + //check cell content after transposed copy/paste of filtered data + // Note: column F is a repetition of srcSheet.Column A + // Col C and G are checked to be empty + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // row 0 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + // row 1, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + aString = m_pDoc->GetString(2, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + fValue = m_pDoc->GetValue(3, 1, destSheet); // D2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell D2", 1, fValue); + fValue = m_pDoc->GetValue(4, 1, destSheet); // E2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell E2", 3, fValue); + fValue = m_pDoc->GetValue(5, 1, destSheet); // F2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell F2", 4, fValue); + fValue = m_pDoc->GetValue(6, 1, destSheet); // G2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell G2 (repetition of D2)", 1, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 1, destSheet)); + aString = m_pDoc->GetString(7, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 2, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + aString = m_pDoc->GetString(2, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + fValue = m_pDoc->GetValue(3, 2, destSheet); // D3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D3", 11, fValue); + m_pDoc->GetFormula(3, 2, destSheet, aString); // D3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D3 should point on D2", OUString("=D2+10"), + aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula E3 should point on E2", OUString("=E5+30"), + aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); // E3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula E3", 35, fValue); + m_pDoc->GetFormula(5, 2, destSheet, aString); // F3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula F3 should point on F2", OUString("=D2+40"), + aString); + fValue = m_pDoc->GetValue(5, 2, destSheet); // F3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula F3", 41, fValue); + fValue = m_pDoc->GetValue(6, 2, destSheet); // G3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula F3", 11, fValue); + m_pDoc->GetFormula(6, 2, destSheet, aString); // G3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G3 should point on G2 (repetition of D3)", + OUString("=G2+10"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 3, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + aString = m_pDoc->GetString(2, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(3, 3, destSheet); // D4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell D4 should contain: a", OUString("a"), aString); + aString = m_pDoc->GetString(4, 3, destSheet); // E4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E4 should contain: c", OUString("c"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); // F4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F4 should contain: d", OUString("d"), aString); + aString = m_pDoc->GetString(6, 3, destSheet); // G4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G4 should contain: a (repetition of D4)", OUString("a"), + aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 4, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(2, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in C5.", pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(3, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in D5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong in D5 ", OUString("R1"), + pEditObj->GetText(0)); + fValue = m_pDoc->GetValue(4, 4, destSheet); // E5 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell E5", 5, fValue); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in F5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong F5.", OUString("R4"), pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in G5. (repetition of D5)", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong G5. (repetition of D5)", OUString("R1"), + pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(7, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in H5.", pEditObj == nullptr); + // row 5, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 5, destSheet, aString); // D6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D6", OUString("=D2+F2+60"), aString); + fValue = m_pDoc->GetValue( + ScAddress(3, 5, destSheet)); // D6, formulas over filtered rows are not adjusted + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D6", 65, + fValue); // formulas over filtered rows are not adjusted + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 5, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + m_pDoc->GetFormula(5, 5, destSheet, aString); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula F6", OUString("=C2+E2+70"), aString); + fValue = m_pDoc->GetValue( + ScAddress(5, 5, destSheet)); // F6, formulas over filtered rows are not adjusted + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula F6", 1073, fValue); + m_pDoc->GetFormula(6, 5, destSheet, aString); // G6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G6 (repetition of D6)", OUString("=G2+I2+60"), + aString); + fValue = m_pDoc->GetValue(6, 5, destSheet); // G6 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula G6 (repetition of D6)", 1061, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 6, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 6, destSheet)); + aString = m_pDoc->GetString(2, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 6, destSheet, aString); // D7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D7", OUString("=SUMIF(D2:G2;\"<4\")"), + aString); + fValue = m_pDoc->GetValue(3, 6, destSheet); // D7 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D7", 5, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 6, destSheet); // E7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 6, destSheet)); + m_pDoc->GetFormula(5, 6, destSheet, aString); // F7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula F7", OUString("=B$1+$A$3+80"), aString); + fValue = m_pDoc->GetValue(5, 6, destSheet); // F7 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula F6", 2080, fValue); + m_pDoc->GetFormula(6, 6, destSheet, aString); // G7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G7 (repetition of D7)", + OUString("=SUMIF(G2:J2;\"<4\")"), aString); + fValue = m_pDoc->GetValue(6, 5, destSheet); // G7 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula G7 (repetition of D7)", 1061, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 6, destSheet)); + aString = m_pDoc->GetString(7, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + + // row + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + + // check patterns + + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("D2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("D2 has blue background", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(4, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("E2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("F2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(6, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("G2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("G2 has a pattern", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(7, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("H2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(4, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(3, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("D3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("D3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("D3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("D3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("D3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("E3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("E3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("E3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("F3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("F3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("F3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("F3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("F3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("G3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("G3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("G3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("G3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("G3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(7, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("H3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("H3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("H3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("H3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("H3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT_MESSAGE("There should be no note on C1", + !m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D1", + !m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E1", + !m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F1", + !m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G1", + !m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H1", + !m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C2", + !m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D2", + m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E2", + m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F2", + !m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G2", + m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H2", + !m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C3", + !m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D3", + m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E3", + m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F3", + m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G3", + m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H3", + !m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C4", + !m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D4", + !m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E4", + m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F4", + m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G4", + !m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H4", + !m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C5", + !m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D5", + m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E5", + m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F5", + m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G5", + m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H5", + !m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C6", + !m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D6", + !m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F6", + m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G6", + !m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H6", + !m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C7", + !m_pDoc->HasNote(ScAddress(2, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D7", + !m_pDoc->HasNote(ScAddress(3, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E7", + !m_pDoc->HasNote(ScAddress(4, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note a F7", + m_pDoc->HasNote(ScAddress(5, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G7", + !m_pDoc->HasNote(ScAddress(6, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H7", + !m_pDoc->HasNote(ScAddress(7, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C8", + !m_pDoc->HasNote(ScAddress(2, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D8", + !m_pDoc->HasNote(ScAddress(3, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E8", + !m_pDoc->HasNote(ScAddress(4, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F8", + !m_pDoc->HasNote(ScAddress(5, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G8", + !m_pDoc->HasNote(ScAddress(6, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H8", + !m_pDoc->HasNote(ScAddress(7, 7, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D2", + m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E2", + m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + // F2 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on G2", + m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D3", + m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E3", + m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F3", + m_pDoc->GetNote(ScAddress(1, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on G3", + m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText()); + // D4 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E4", + m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F4", + m_pDoc->GetNote(ScAddress(2, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + // G4 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on D5", + m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E5", + m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on F5", + m_pDoc->GetNote(ScAddress(3, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on G5", + m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 5, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on F6", + m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 5, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on F7", + m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 6, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeCol(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + ┌--- not selected src col C + v + + | D | E | F | G | H | I | + + 2 | 1 B*| =D2+10 *| R1 *| =C2+C4+60 | =SUMIF(C2:C5;"<4") | 121 | + 3 | 2 B*| =D3+20 b | R2 *| | *| 122 | <- filtered row + 4 | 3 B*| =G4+30 b*| 5 *| B*| | 123 | + 5 | 4 | =D3+40 b*| R4 *| =C2+C4+70 *| =D$1+$A$1+80 *| 124 | + + * means note attached + B means background + b means border + */ + + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // col 2 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + // col 3, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(2, m_pDoc->GetValue(3, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(3, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(3, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 5, destSheet)); + // col 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + aString = m_pDoc->GetString(4, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 1, destSheet)); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D3+20"), aString); + ASSERT_DOUBLES_EQUAL(22, m_pDoc->GetValue(4, 2, destSheet)); + fValue = m_pDoc->GetValue(4, 3, destSheet); + m_pDoc->GetFormula(4, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=G4+30"), + aString); // references over selection gaps are not adjusted + ASSERT_DOUBLES_EQUAL(bSkipEmpty ? 1030 : 30, fValue); // It was 35 + fValue = m_pDoc->GetValue(4, 4, destSheet); + m_pDoc->GetFormula(4, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D3+40"), aString); + ASSERT_DOUBLES_EQUAL(42, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + aString = m_pDoc->GetString(4, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 5, strings are not selected + // col 5, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + aString = m_pDoc->GetString(4, 5, destSheet); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 0, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 1, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 2, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R2"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(5, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 4, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 5, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // col 6, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + aString = m_pDoc->GetString(6, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(6, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=C2+C4+60"), aString); + ASSERT_DOUBLES_EQUAL(2060, m_pDoc->GetValue(6, 1, destSheet)); // It was 64 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(6, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(6, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 3, destSheet)); + } + fValue = m_pDoc->GetValue(6, 4, destSheet); + m_pDoc->GetFormula(6, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=C2+C4+70"), aString); + ASSERT_DOUBLES_EQUAL(2070, fValue); // It was 74 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 5, destSheet)); + aString = m_pDoc->GetString(6, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 7, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + aString = m_pDoc->GetString(7, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(7, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL( + OUString("=SUMIF(C2:C5;\"<4\")"), + aString); // CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D2:D5;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(0, m_pDoc->GetValue(7, 1, destSheet)); // It was 6 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + } + fValue = m_pDoc->GetValue(7, 4, destSheet); + m_pDoc->GetFormula(7, 4, destSheet, aString); + ASSERT_DOUBLES_EQUAL(2080, fValue); + CPPUNIT_ASSERT_EQUAL(OUString("=D$1+$A$3+80"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 8, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(121, m_pDoc->GetValue(8, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(122, m_pDoc->GetValue(8, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(123, m_pDoc->GetValue(8, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(124, m_pDoc->GetValue(8, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 5, destSheet)); + // col 9, col repetition is not supported for multi range copy/paste + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 5, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(3, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(6, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(4, 1, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 5, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 5, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 4, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeColFiltered(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + ┌--- not selected src col C + v + + | D | E | F | G | H | I | + + 2 | 1 B*| =D2+10 *| R1 *| =C2+C4+60 | =SUMIF(C2:C5;"<4") | 121 | + 3 | 3 B*| =G4+30 b*| 5 *| B*| | 123 | + 4 | 4 | =D2+40 b*| R4 *| =C1+C3+70 *| =D$1+$A$1+80 *| 124 | + + * means note attached + B means background + b means border + */ + + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // col 2 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + // col 3, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(3, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(3, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 4, destSheet)); + // col 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + m_pDoc->GetFormula(4, 0, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 1, destSheet)); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=G3+30"), + aString); // references over selection gaps are not adjusted + ASSERT_DOUBLES_EQUAL(bSkipEmpty ? 1030 : 30, fValue); // It was 35 + fValue = m_pDoc->GetValue(4, 3, destSheet); + m_pDoc->GetFormula(4, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+40"), aString); + ASSERT_DOUBLES_EQUAL(41, fValue); // was originally 42, not adjusted by filtering + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 4, destSheet)); + m_pDoc->GetFormula(4, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + // col 5, strings are not selected + // col 5, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 0, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 1, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(5, 2, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 4, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // col 6, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + m_pDoc->GetFormula(6, 0, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + m_pDoc->GetFormula(6, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=C2+C4+60"), aString); + ASSERT_DOUBLES_EQUAL(2060, m_pDoc->GetValue(6, 1, destSheet)); // It was 64 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(6, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 2, destSheet)); + fValue = m_pDoc->GetValue(6, 3, destSheet); + m_pDoc->GetFormula(6, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=C1+C3+70"), aString); + ASSERT_DOUBLES_EQUAL(2070, fValue); // It was 74 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 4, destSheet)); + m_pDoc->GetFormula(6, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + // col 7, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + m_pDoc->GetFormula(7, 0, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + m_pDoc->GetFormula(7, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(C2:C5;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(0, m_pDoc->GetValue(7, 1, destSheet)); // It was 6 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + fValue = m_pDoc->GetValue(7, 3, destSheet); + m_pDoc->GetFormula(7, 3, destSheet, aString); + ASSERT_DOUBLES_EQUAL(2080, fValue); + CPPUNIT_ASSERT_EQUAL(OUString("=D$1+$A$3+80"), aString); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 4, destSheet)); + m_pDoc->GetFormula(7, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + // col 8, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(121, m_pDoc->GetValue(8, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(123, m_pDoc->GetValue(8, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(124, m_pDoc->GetValue(8, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 4, destSheet)); + // col 9, col repetition is not supported for multi range copy/paste + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 5, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(3, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(6, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(4, 1, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 4, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 3, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeColTranspose(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | + + 2 | 1 B*| 2 B*| 3 B*| 4 | + 3 | =D2+10 *| =E2+20 b | =F5+30 b*| =E2+40 b*| + 4 | R1 *| R2 *| 5 *| R4 *| + 5 | =D1+F1+60 | | B*| =D1+F1+70 *| + 6 | =SUMIF(D1:G1;"<4") | *| | =C$1+$A$1+80 *| + 7 | 121 | 122 | 123 | 124 | + + * means note attached + B means background + b means border + */ + + // check cell content after transposed copy/paste of filtered data + // Col C and G are checked to be empty + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // row 0 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + // row 1, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(2, m_pDoc->GetValue(4, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(5, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(6, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 1, destSheet)); + // row 2, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + aString = m_pDoc->GetString(2, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(3, 2, destSheet)); + m_pDoc->GetFormula(3, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=E2+20"), aString); + ASSERT_DOUBLES_EQUAL(22, m_pDoc->GetValue(4, 2, destSheet)); + fValue = m_pDoc->GetValue(5, 2, destSheet); + m_pDoc->GetFormula(5, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=F5+30"), aString); + ASSERT_DOUBLES_EQUAL(bSkipEmpty ? 1030 : 30, fValue); // It was 35 + fValue = m_pDoc->GetValue(6, 2, destSheet); + m_pDoc->GetFormula(6, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=E2+40"), aString); + ASSERT_DOUBLES_EQUAL(42, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 3, strings was not selected in multi range selection + // row 3, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(2, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(3, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(4, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R2"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(5, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(7, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // row 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + aString = m_pDoc->GetString(2, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D1+F1+60"), aString); + ASSERT_DOUBLES_EQUAL(2060, m_pDoc->GetValue(3, 4, destSheet)); // It was 64 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 4, destSheet); // E5 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E5", EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(5, 4, destSheet); // F5 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E5", EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 4, destSheet)); + } + fValue = m_pDoc->GetValue(6, 4, destSheet); + m_pDoc->GetFormula(6, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D1+F1+70"), aString); + ASSERT_DOUBLES_EQUAL(2070, fValue); // It was 74 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 4, destSheet)); + aString = m_pDoc->GetString(7, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 5, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 5, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D1:G1;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(0, m_pDoc->GetValue(3, 5, destSheet)); // It was 6 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 5, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(5, 5, destSheet); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + } + + fValue = m_pDoc->GetValue(6, 5, destSheet); + m_pDoc->GetFormula(6, 5, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=C$1+$A$3+80"), aString); + ASSERT_DOUBLES_EQUAL(2080, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 6, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(121, m_pDoc->GetValue(3, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(122, m_pDoc->GetValue(4, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(123, m_pDoc->GetValue(5, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(124, m_pDoc->GetValue(6, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 6, destSheet)); + // row 7, not selected + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(4, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(6, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(7, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(5, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + // std::cout << "bSkipEmpty: " << bSkipEmpty << ", pItem == nullptr: " << (pItem == nullptr) << std::endl; + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(3, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + m_pDoc->GetPattern(ScAddress(4, 2, destSheet))->GetItemSet().HasItem(ATTR_BORDER, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(7, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 6, destSheet))); + + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 5, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 5, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeColFilteredTranspose(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + ┌--- filtered src row 2 + v + + | D | E | F | + + 2 | 1 B*| 3 B*| 4 | + 3 | =D2+10 *| =E5+30 b*| =D2+40 b*| + <- not copied col C + 4 | R1 *| 5 *| R4 *| + 5 | =D1+F1+60 | B*| =C1+E1+70 *| + 6 | =SUMIF(D1:G1;"<4") | | =B$1+$A$1+80 *| + 7 | 121 | 123 | 124 | + + * means note attached + B means background + b means border + */ + + // check cell content after transposed copy/paste of filtered data + // Col C and G are checked to be empty + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // row 0 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + // row 1, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(4, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(5, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 1, destSheet)); + // row 2, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(3, 2, destSheet)); + m_pDoc->GetFormula(3, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=E5+30"), aString); + ASSERT_DOUBLES_EQUAL(bSkipEmpty ? 1030 : 30, fValue); // It was 35 + fValue = m_pDoc->GetValue(5, 2, destSheet); + m_pDoc->GetFormula(5, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+40"), aString); + ASSERT_DOUBLES_EQUAL(41, fValue); // was originally 42, not adjusted by filtering + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 2, destSheet)); + aString = m_pDoc->GetString(6, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 3, strings was not selected in multi range selection + // row 3, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(2, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(3, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(4, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(5, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 3, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 3, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // row 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + aString = m_pDoc->GetString(2, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D1+F1+60"), + aString); // formulas over filtered rows are not adjusted + ASSERT_DOUBLES_EQUAL(2060, m_pDoc->GetValue(3, 4, destSheet)); // It was 64 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 4, destSheet)); + fValue = m_pDoc->GetValue(5, 4, destSheet); + m_pDoc->GetFormula(5, 4, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=C1+E1+70"), + aString); // formulas over filtered rows are not adjusted + ASSERT_DOUBLES_EQUAL(2070, fValue); // It was 74 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 4, destSheet)); + aString = m_pDoc->GetString(6, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 5, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 5, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D1:G1;\"<4\")"), + aString); // formulas over filtered rows are not adjusted + ASSERT_DOUBLES_EQUAL(0, m_pDoc->GetValue(3, 5, destSheet)); // It was 6 + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 5, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + fValue = m_pDoc->GetValue(5, 5, destSheet); + m_pDoc->GetFormula(5, 5, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=B$1+$A$3+80"), aString); + ASSERT_DOUBLES_EQUAL(2080, fValue); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 5, destSheet)); + aString = m_pDoc->GetString(6, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 6, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(121, m_pDoc->GetValue(3, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(123, m_pDoc->GetValue(4, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(124, m_pDoc->GetValue(5, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 6, destSheet)); + // row 7, not copied + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + // row 8, not copied + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(4, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(6, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(4, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(3, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + m_pDoc->GetPattern(ScAddress(4, 2, destSheet))->GetItemSet().HasItem(ATTR_BORDER, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 6, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 6, destSheet))); + + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 5, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeRow(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | H | I | + + 2 | 1 B*| =D2+10 *| a | R1 *| =D2+D4+60 | =SUMIF(D2:D5;"<4") | + 3 | 2 B*| =D3+20 b | b *| R2 *| | *| <- filtered row + 4 | 3 B*| =G4+30 b*| c *| 5 *| B*| | + <- not selected row + 5 | 6 | q | r bB*| s bB| t | u | + 6 | -11 | -12 | -13 | -14 | -15 | -16 | + + * means note attached + B means background + b means border + */ + + OUString aString; + const EditTextObject* pEditObj; + // col 2 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + // col 3, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(2, m_pDoc->GetValue(3, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(3, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(6, m_pDoc->GetValue(3, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(-11, m_pDoc->GetValue(3, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 6, destSheet)); + // col 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + aString = m_pDoc->GetString(4, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 1, destSheet)); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D3+20"), aString); + ASSERT_DOUBLES_EQUAL(22, m_pDoc->GetValue(4, 2, destSheet)); + m_pDoc->GetFormula(4, 3, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=G4+30"), aString); + ASSERT_DOUBLES_EQUAL(35, m_pDoc->GetValue(4, 3, destSheet)); + aString = m_pDoc->GetString(4, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("q"), aString); + ASSERT_DOUBLES_EQUAL(-12, m_pDoc->GetValue(4, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 6, destSheet)); + aString = m_pDoc->GetString(4, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 5, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + aString = m_pDoc->GetString(5, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(5, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("a"), aString); + aString = m_pDoc->GetString(5, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("b"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("c"), aString); + aString = m_pDoc->GetString(5, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("r"), aString); + ASSERT_DOUBLES_EQUAL(-13, m_pDoc->GetValue(5, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 6, destSheet)); + aString = m_pDoc->GetString(5, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 6, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 0, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 1, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 2, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R2"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(6, 3, destSheet)); + aString = m_pDoc->GetString(6, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("s"), aString); + ASSERT_DOUBLES_EQUAL(-14, m_pDoc->GetValue(6, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 6, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 6, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // col 7, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + aString = m_pDoc->GetString(7, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(7, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+D4+60"), aString); + ASSERT_DOUBLES_EQUAL(64, m_pDoc->GetValue(7, 1, destSheet)); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + } + aString = m_pDoc->GetString(7, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("t"), aString); + ASSERT_DOUBLES_EQUAL(-15, m_pDoc->GetValue(7, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 6, destSheet)); + aString = m_pDoc->GetString(7, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 8, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 0, destSheet)); + aString = m_pDoc->GetString(7, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(8, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D2:D5;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(6, m_pDoc->GetValue(8, 1, destSheet)); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(8, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(8, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 3, destSheet)); + } + aString = m_pDoc->GetString(8, 4, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("u"), aString); + ASSERT_DOUBLES_EQUAL(-16, m_pDoc->GetValue(8, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 6, destSheet)); + aString = m_pDoc->GetString(8, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 9 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 5, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(3, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(7, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + m_pDoc->GetPattern(ScAddress(4, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(5, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(6, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(7, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(4, 1, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 5, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + pItem = m_pDoc->GetAttr(ScAddress(3, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(7, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(8, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 5, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 5, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 3, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 3, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(8, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 4, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeRowFiltered(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | H | I | + + 2 | 1 B*| =D2+10 *| a | R1 *| =D2+D4+60 | =SUMIF(D2:D5;"<4") | + 3 | 3 B*| =G3+30 b*| c *| 5 *| B*| | + <- not selected + 4 | 6 | q | r | s | t | u | + 5 | -11 | -12 |-13 | -14 | -15 | -16 | + + * means note attached + B means background + b means border + */ + + OUString aString; + const EditTextObject* pEditObj; + // col 2 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + // col 3, numbers + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(3, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(3, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(6, m_pDoc->GetValue(3, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(-11, m_pDoc->GetValue(3, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 5, destSheet)); + // col 4, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + aString = m_pDoc->GetString(4, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(4, 1, destSheet)); + m_pDoc->GetFormula(4, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+10"), aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=G3+30"), aString); + ASSERT_DOUBLES_EQUAL(35, m_pDoc->GetValue(4, 2, destSheet)); + aString = m_pDoc->GetString(4, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("q"), aString); + ASSERT_DOUBLES_EQUAL(-12, m_pDoc->GetValue(4, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + aString = m_pDoc->GetString(4, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 5, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + aString = m_pDoc->GetString(5, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(5, 1, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("a"), aString); + aString = m_pDoc->GetString(5, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("c"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("r"), aString); + ASSERT_DOUBLES_EQUAL(-13, m_pDoc->GetValue(5, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + aString = m_pDoc->GetString(5, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 6, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 0, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 1, destSheet)); + CPPUNIT_ASSERT(pEditObj); + CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0)); + ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(6, 2, destSheet)); + aString = m_pDoc->GetString(6, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("s"), aString); + ASSERT_DOUBLES_EQUAL(-14, m_pDoc->GetValue(6, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 5, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(6, 5, destSheet)); + CPPUNIT_ASSERT(pEditObj == nullptr); + // col 7, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + aString = m_pDoc->GetString(7, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(7, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=D2+D4+60"), aString); + ASSERT_DOUBLES_EQUAL(67, m_pDoc->GetValue(7, 1, destSheet)); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("t"), aString); + ASSERT_DOUBLES_EQUAL(-15, m_pDoc->GetValue(7, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 8, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 0, destSheet)); + aString = m_pDoc->GetString(8, 0, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(8, 1, destSheet, aString); + CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(D2:D5;\"<4\")"), aString); + ASSERT_DOUBLES_EQUAL(6, m_pDoc->GetValue(8, 1, destSheet)); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(8, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 2, destSheet)); + aString = m_pDoc->GetString(8, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("u"), aString); + ASSERT_DOUBLES_EQUAL(-16, m_pDoc->GetValue(8, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 5, destSheet)); + aString = m_pDoc->GetString(8, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // col 9 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 1, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(9, 5, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(3, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(3, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(7, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + m_pDoc->GetPattern(ScAddress(4, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(5, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(6, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(7, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(4, 1, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + pItem = m_pDoc->GetAttr(ScAddress(3, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(4, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(7, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 0, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 1, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 2, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 3, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(8, 4, destSheet))); + CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 4, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(7, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 4, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeRowTranspose(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | H | + + 2 | 1 B*| 2 B*| 3 B*| 6 | -11 | + 3 | =D2+10 *| =E2+20 b | =F5+30 b*| q | -12 | + 4 | a | b *| c *| r | -13 | + 5 | R1 *| R2 *| 5 *| s | -14 | + 6 | =D2+F2+60 | | B*| t | -15 | + 7 | =SUMIF(D2:G2;"<4") | *| | u | -16 | + + * means note attached + B means background + b means border + */ + + //check cell content after transposed copy/paste of filtered data + // Note: column F is a repetition of srcSheet.Column A + // Col C and G are checked to be empty + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // row 0 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + // row 1, numbers + fValue = m_pDoc->GetValue(2, 1, destSheet); // C2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell C2", 1000, fValue); + fValue = m_pDoc->GetValue(3, 1, destSheet); // D2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell D2", 1, fValue); + fValue = m_pDoc->GetValue(4, 1, destSheet); // E2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell E2", 2, fValue); + fValue = m_pDoc->GetValue(5, 1, destSheet); // F2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell F2", 3, fValue); + fValue = m_pDoc->GetValue(6, 1, destSheet); // G2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell G2", 6, fValue); + ASSERT_DOUBLES_EQUAL(-11, m_pDoc->GetValue(7, 1, destSheet)); + fValue = m_pDoc->GetValue(8, 1, destSheet); // I2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell I2", 1000, fValue); + // row 2, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + aString = m_pDoc->GetString(2, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + fValue = m_pDoc->GetValue(3, 2, destSheet); // D3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D3", 11, fValue); + m_pDoc->GetFormula(3, 2, destSheet, aString); // D3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D3 should point on D2", OUString("=D2+10"), + aString); + m_pDoc->GetFormula(4, 2, destSheet, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula E3 should point on E2", OUString("=E2+20"), + aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); // E3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula E3", 22, fValue); + fValue = m_pDoc->GetValue(5, 2, destSheet); // F3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula F3", 35, fValue); + m_pDoc->GetFormula(5, 2, destSheet, aString); // F3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula F3 should point on F2", OUString("=F5+30"), + aString); + aString = m_pDoc->GetString(6, 2, destSheet); // G3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G4 should contain: q", OUString("q"), aString); + ASSERT_DOUBLES_EQUAL(-12, m_pDoc->GetValue(7, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 2, destSheet)); + aString = m_pDoc->GetString(8, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 3, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + aString = m_pDoc->GetString(2, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(3, 3, destSheet); // D4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell D4 should contain: a", OUString("a"), aString); + aString = m_pDoc->GetString(4, 3, destSheet); // E4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E4 should contain: b", OUString("b"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); // F4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F4 should contain: c", OUString("c"), aString); + aString = m_pDoc->GetString(6, 3, destSheet); // G4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G4 should contain: r", OUString("r"), aString); + ASSERT_DOUBLES_EQUAL(-13, m_pDoc->GetValue(7, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 3, destSheet)); + aString = m_pDoc->GetString(8, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 4, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(2, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in C5.", pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(3, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in D5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong in D5 ", OUString("R1"), + pEditObj->GetText(0)); + pEditObj = m_pDoc->GetEditText(ScAddress(4, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in E5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong E5.", OUString("R2"), pEditObj->GetText(0)); + fValue = m_pDoc->GetValue(5, 4, destSheet); // F5 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell F5", 5, fValue); + aString = m_pDoc->GetString(6, 4, destSheet); // G5 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G5 should contain: s", OUString("s"), aString); + ASSERT_DOUBLES_EQUAL(-14, m_pDoc->GetValue(7, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(8, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in I5.", pEditObj == nullptr); + // row 5, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 5, destSheet, aString); // D6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D6", OUString("=D2+F2+60"), aString); + fValue = m_pDoc->GetValue(3, 5, destSheet); // D6 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D6", 64, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 5, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(5, 5, destSheet); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 5, destSheet)); + } + aString = m_pDoc->GetString(6, 5, destSheet); // G6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G6 should contain: t", OUString("t"), aString); + ASSERT_DOUBLES_EQUAL(-15, m_pDoc->GetValue(7, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 5, destSheet)); + aString = m_pDoc->GetString(8, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 6, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 6, destSheet)); + aString = m_pDoc->GetString(2, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 6, destSheet, aString); // D7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D7", OUString("=SUMIF(D2:G2;\"<4\")"), + aString); + fValue = m_pDoc->GetValue(3, 6, destSheet); // D7 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D7", 6, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 6, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + aString = m_pDoc->GetString(5, 6, destSheet); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + { + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 6, destSheet)); + } + aString = m_pDoc->GetString(6, 6, destSheet); // G4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell G7 should contain: u", OUString("u"), aString); + ASSERT_DOUBLES_EQUAL(-16, m_pDoc->GetValue(7, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 6, destSheet)); + aString = m_pDoc->GetString(8, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 7 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("D2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("D2 has blue background", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(4, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("E2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("E2 has blue background", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("F2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("F2 has a pattern", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(6, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("G2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(7, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("H2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(5, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(3, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("D3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("D3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("D3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("D3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("D3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + m_pDoc->GetPattern(ScAddress(4, 2, destSheet))->GetItemSet().HasItem(ATTR_BORDER, &pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("E3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("E3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("E3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("F3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("F3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("F3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("F3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("F3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("G3 has top border", !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("G3 has bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("G3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("G3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(7, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("H3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("H3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("H3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("H3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("H3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT_MESSAGE("There should be no note on C1", + !m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D1", + !m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E1", + !m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F1", + !m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G1", + !m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H1", + !m_pDoc->HasNote(ScAddress(7, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C2", + !m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D2", + m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E2", + m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F2", + m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G2", + !m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H2", + !m_pDoc->HasNote(ScAddress(7, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C3", + !m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D3", + m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E3", + !m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F3", + m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G3", + !m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H3", + !m_pDoc->HasNote(ScAddress(7, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C4", + !m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D4", + !m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E4", + m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F4", + m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G4", + m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H4", + !m_pDoc->HasNote(ScAddress(7, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C5", + !m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D5", + m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E5", + m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F5", + m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G5", + !m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H5", + !m_pDoc->HasNote(ScAddress(7, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C6", + !m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D6", + !m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E6", + !m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on G6", + !m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H6", + !m_pDoc->HasNote(ScAddress(7, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C7", + !m_pDoc->HasNote(ScAddress(2, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D7", + !m_pDoc->HasNote(ScAddress(3, 6, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(4, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F7", + !m_pDoc->HasNote(ScAddress(5, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note a G7", + !m_pDoc->HasNote(ScAddress(6, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H7", + !m_pDoc->HasNote(ScAddress(7, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C8", + !m_pDoc->HasNote(ScAddress(2, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D8", + !m_pDoc->HasNote(ScAddress(3, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E8", + !m_pDoc->HasNote(ScAddress(4, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F8", + !m_pDoc->HasNote(ScAddress(5, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G8", + !m_pDoc->HasNote(ScAddress(6, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on H8", + !m_pDoc->HasNote(ScAddress(7, 7, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D2", + m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E2", + m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F2", + m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 1, destSheet))->GetText()); + // G2 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D3", + m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + // E3 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F3", + m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText()); + // D4 has no note + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E4", + m_pDoc->GetNote(ScAddress(2, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F4", + m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on D5", + m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E5", + m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on F5", + m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 5, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E7", + m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 6, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 4, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(6, 3, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); +} + +void Test::checkCopyPasteSpecialMultiRangeRowFilteredTranspose(bool bSkipEmpty) +{ + const SCTAB srcSheet = 0; + const SCTAB destSheet = 1; + + /* + | D | E | F | G | + + 2 | 1 B*| 3 B*| 6 | -11 | + 3 | =D2+10 *| =F5+30 b*| q | -12 | + 4 | a | c *| r | -13 | + 5 | R1 *| 5 *| s | -14 | + 6 | =D2+F2+60 | B*| t | -15 | + 7 | =SUMIF(D2:G2;"<4") | | u | -16 | + + * means note attached + B means background + b means border + */ + + //check cell content after transposed copy/paste of filtered data + // Note: column F is a repetition of srcSheet.Column A + // Col C and G are checked to be empty + OUString aString; + double fValue; + const EditTextObject* pEditObj; + // row 0 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 0, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 0, destSheet)); + // row 1, numbers + fValue = m_pDoc->GetValue(2, 1, destSheet); // C2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell C2", 1000, fValue); + fValue = m_pDoc->GetValue(3, 1, destSheet); // D2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell D2", 1, fValue); + fValue = m_pDoc->GetValue(4, 1, destSheet); // E2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell E2", 3, fValue); + fValue = m_pDoc->GetValue(5, 1, destSheet); // F2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell F2", 6, fValue); + ASSERT_DOUBLES_EQUAL(-11, m_pDoc->GetValue(6, 1, destSheet)); + fValue = m_pDoc->GetValue(7, 1, destSheet); // H2 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell H2", 1000, fValue); + // row 2, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 2, destSheet)); + aString = m_pDoc->GetString(2, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + fValue = m_pDoc->GetValue(3, 2, destSheet); // D3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D3", 11, fValue); + m_pDoc->GetFormula(3, 2, destSheet, aString); // D3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D3 should point on D2", OUString("=D2+10"), + aString); + fValue = m_pDoc->GetValue(4, 2, destSheet); // E3 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula E3", 35, fValue); + m_pDoc->GetFormula(4, 2, destSheet, aString); // E3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula E3 should point on F2", OUString("=E5+30"), + aString); + aString = m_pDoc->GetString(5, 2, destSheet); // F3 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F4 should contain: q", OUString("q"), aString); + ASSERT_DOUBLES_EQUAL(-12, m_pDoc->GetValue(6, 2, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 2, destSheet)); + aString = m_pDoc->GetString(7, 2, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 3, strings + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 3, destSheet)); + aString = m_pDoc->GetString(2, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + aString = m_pDoc->GetString(3, 3, destSheet); // D4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell D4 should contain: a", OUString("a"), aString); + aString = m_pDoc->GetString(4, 3, destSheet); // E4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E4 should contain: c", OUString("c"), aString); + aString = m_pDoc->GetString(5, 3, destSheet); // F4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F4 should contain: r", OUString("r"), aString); + ASSERT_DOUBLES_EQUAL(-13, m_pDoc->GetValue(6, 3, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 3, destSheet)); + aString = m_pDoc->GetString(7, 3, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 4, rich text + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(2, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in C5.", pEditObj == nullptr); + pEditObj = m_pDoc->GetEditText(ScAddress(3, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in D5.", pEditObj); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Edit cell value wrong in D5 ", OUString("R1"), + pEditObj->GetText(0)); + fValue = m_pDoc->GetValue(4, 4, destSheet); // E5 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell E5", 5, fValue); + aString = m_pDoc->GetString(5, 4, destSheet); // F5 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F5 should contain: s", OUString("s"), aString); + ASSERT_DOUBLES_EQUAL(-14, m_pDoc->GetValue(6, 4, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 4, destSheet)); + pEditObj = m_pDoc->GetEditText(ScAddress(7, 4, destSheet)); + CPPUNIT_ASSERT_MESSAGE("There should be no edit cell in H5.", pEditObj == nullptr); + // row 5, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 5, destSheet)); + aString = m_pDoc->GetString(2, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 5, destSheet, aString); // D6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D6", OUString("=D2+F2+60"), aString); + fValue = m_pDoc->GetValue(3, 5, destSheet); // D6 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D6", 67, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 5, destSheet); // E6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 5, destSheet)); + aString = m_pDoc->GetString(5, 5, destSheet); // F6 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F6 should contain: t", OUString("t"), aString); + ASSERT_DOUBLES_EQUAL(-15, m_pDoc->GetValue(6, 5, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 5, destSheet)); + aString = m_pDoc->GetString(7, 5, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 6, formulas + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 6, destSheet)); + aString = m_pDoc->GetString(2, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + m_pDoc->GetFormula(3, 6, destSheet, aString); // D7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula D7", OUString("=SUMIF(D2:G2;\"<4\")"), + aString); + fValue = m_pDoc->GetValue(3, 6, destSheet); // D7 + ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula D7", -7, fValue); + if (!bSkipEmpty) + { + aString = m_pDoc->GetString(4, 6, destSheet); // E7 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell E6", EMPTY_OUSTRING, aString); + } + else + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 6, destSheet)); + aString = m_pDoc->GetString(5, 6, destSheet); // F4 + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell F7 should contain: u", OUString("u"), aString); + ASSERT_DOUBLES_EQUAL(-16, m_pDoc->GetValue(6, 6, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 6, destSheet)); + aString = m_pDoc->GetString(7, 6, destSheet); + CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString); + // row 7 + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(2, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(3, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(4, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(5, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(6, 7, destSheet)); + ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 7, destSheet)); + + // check patterns + const SfxPoolItem* pItem = nullptr; + m_pDoc->GetPattern(ScAddress(3, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("D2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("D2 has blue background", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(4, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("E2 has a pattern", pItem); + CPPUNIT_ASSERT_EQUAL_MESSAGE("E2 has a pattern", COL_BLUE, + static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("F2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(6, 1, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_MESSAGE("G2 has no pattern", !pItem); + m_pDoc->GetPattern(ScAddress(4, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT_EQUAL(bSkipEmpty, pItem == nullptr); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(COL_GREEN, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + + m_pDoc->GetPattern(ScAddress(5, 2, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(5, 3, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 4, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT_EQUAL(COL_RED, static_cast<const SvxBrushItem*>(pItem)->GetColor()); + m_pDoc->GetPattern(ScAddress(5, 5, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + m_pDoc->GetPattern(ScAddress(5, 6, destSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem); + CPPUNIT_ASSERT(!pItem); + + // check border, left and right borders were transformed to top and bottom borders + pItem = m_pDoc->GetAttr(ScAddress(3, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("D3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("D3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("D3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("D3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("D3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + m_pDoc->GetPattern(ScAddress(4, 2, destSheet))->GetItemSet().HasItem(ATTR_BORDER, &pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + pItem = m_pDoc->GetAttr(ScAddress(4, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("E3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("E3 has top border", static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("E3 has bottom border", + static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("E3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("E3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("F3 has top border", !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("F3 has bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("F3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("F3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(6, 2, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT_MESSAGE("G3 has a border", pItem); + CPPUNIT_ASSERT_MESSAGE("G3 has no top border", + !static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT_MESSAGE("G3 has no bottom border", + !static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT_MESSAGE("G3 has no left border", + !static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT_MESSAGE("G3 has no right border", + !static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 3, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + pItem = m_pDoc->GetAttr(ScAddress(5, 4, destSheet), ATTR_BORDER); + CPPUNIT_ASSERT(pItem); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetTop()); + CPPUNIT_ASSERT(!static_cast<const SvxBoxItem*>(pItem)->GetBottom()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetLeft()); + CPPUNIT_ASSERT(static_cast<const SvxBoxItem*>(pItem)->GetRight()); + + // check notes after transposed copy/paste + // check presence of notes + CPPUNIT_ASSERT_MESSAGE("There should be no note on C1", + !m_pDoc->HasNote(ScAddress(2, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D1", + !m_pDoc->HasNote(ScAddress(3, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E1", + !m_pDoc->HasNote(ScAddress(4, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F1", + !m_pDoc->HasNote(ScAddress(5, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G1", + !m_pDoc->HasNote(ScAddress(6, 0, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C2", + !m_pDoc->HasNote(ScAddress(2, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D2", + m_pDoc->HasNote(ScAddress(3, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E2", + m_pDoc->HasNote(ScAddress(4, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F2", + !m_pDoc->HasNote(ScAddress(5, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G2", + !m_pDoc->HasNote(ScAddress(6, 1, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C3", + !m_pDoc->HasNote(ScAddress(2, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D3", + m_pDoc->HasNote(ScAddress(3, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E3", + m_pDoc->HasNote(ScAddress(4, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F3", + !m_pDoc->HasNote(ScAddress(5, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G3", + !m_pDoc->HasNote(ScAddress(6, 2, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C4", + !m_pDoc->HasNote(ScAddress(2, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D4", + !m_pDoc->HasNote(ScAddress(3, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E4", + m_pDoc->HasNote(ScAddress(4, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F4", + m_pDoc->HasNote(ScAddress(5, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G4", + !m_pDoc->HasNote(ScAddress(6, 3, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C5", + !m_pDoc->HasNote(ScAddress(2, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on D5", + m_pDoc->HasNote(ScAddress(3, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on E5", + m_pDoc->HasNote(ScAddress(4, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F5", + !m_pDoc->HasNote(ScAddress(5, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G5", + !m_pDoc->HasNote(ScAddress(6, 4, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C6", + !m_pDoc->HasNote(ScAddress(2, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D6", + !m_pDoc->HasNote(ScAddress(3, 5, destSheet))); + CPPUNIT_ASSERT_EQUAL(!bSkipEmpty, m_pDoc->HasNote(ScAddress(4, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be a note on F6", + !m_pDoc->HasNote(ScAddress(5, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G6", + !m_pDoc->HasNote(ScAddress(6, 5, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C7", + !m_pDoc->HasNote(ScAddress(2, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D7", + !m_pDoc->HasNote(ScAddress(3, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E7", + !m_pDoc->HasNote(ScAddress(4, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note a F7", + !m_pDoc->HasNote(ScAddress(5, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G7", + !m_pDoc->HasNote(ScAddress(6, 6, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on C8", + !m_pDoc->HasNote(ScAddress(2, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on D8", + !m_pDoc->HasNote(ScAddress(3, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on E8", + !m_pDoc->HasNote(ScAddress(4, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on F8", + !m_pDoc->HasNote(ScAddress(5, 7, destSheet))); + CPPUNIT_ASSERT_MESSAGE("There should be no note on G8", + !m_pDoc->HasNote(ScAddress(6, 7, destSheet))); + + // check values of notes + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D2", + m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E2", + m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D3", + m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E3", + m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E4", + m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on D5", + m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(3, 4, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E5", + m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 4, destSheet))->GetText()); + if (!bSkipEmpty) + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(4, 5, destSheet))->GetText()); + CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 4, srcSheet))->GetText(), + m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText()); + + m_pDoc->DeleteTab(destSheet); + m_pDoc->DeleteTab(srcSheet); } void Test::testCopyPasteMultiRange() diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index a5488bb4fe25..fe9d6f09c1cd 100644..100755 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -14,6 +14,7 @@ #include <document.hxx> #include <stringutil.hxx> #include <memory> +#include <clipparam.hxx> struct TestImpl; class ScUndoPaste; @@ -385,6 +386,58 @@ public: void testCopyPaste(); void testCopyPasteAsLink(); void testCopyPasteTranspose(); + void testCopyPasteSpecialAsLinkTranspose(); + void testCopyPasteSpecialAsLinkFilteredTranspose(); + void testCopyPasteSpecialMultiRangeColAsLinkTranspose(); + void testCopyPasteSpecialMultiRangeColAsLinkFilteredTranspose(); + void testCopyPasteSpecialMultiRangeRowAsLinkTranspose(); + void testCopyPasteSpecialMultiRangeRowAsLinkFilteredTranspose(); + void testCopyPasteSpecialAllAsLinkTranspose(); + void testCopyPasteSpecialAllAsLinkFilteredTranspose(); + void testCopyPasteSpecial(); + void testCopyPasteSpecialFiltered(); + void testCopyPasteSpecialIncludeFiltered(); + void testCopyPasteSpecialFilteredIncludeFiltered(); + void testCopyPasteSpecialTranspose(); + void testCopyPasteSpecialTransposeIncludeFiltered(); + void testCopyPasteSpecialFilteredTranspose(); + void testCopyPasteSpecialMergedCellsTranspose(); + void testCopyPasteSpecialMergedCellsFilteredTranspose(); + void testCopyPasteSpecialMultiRangeCol(); + void testCopyPasteSpecialMultiRangeColFiltered(); + void testCopyPasteSpecialMultiRangeColIncludeFiltered(); + void testCopyPasteSpecialMultiRangeColFilteredIncludeFiltered(); + void testCopyPasteSpecialMultiRangeColTranspose(); + void testCopyPasteSpecialMultiRangeColFilteredTranspose(); + void testCopyPasteSpecialMultiRangeColFilteredIncludeFilteredTranspose(); + void testCopyPasteSpecialMultiRangeRow(); + void testCopyPasteSpecialMultiRangeRowFiltered(); + void testCopyPasteSpecialMultiRangeRowIncludeFiltered(); + void testCopyPasteSpecialMultiRangeRowFilteredIncludeFiltered(); + void testCopyPasteSpecialMultiRangeRowTranspose(); + void testCopyPasteSpecialMultiRangeRowFilteredTranspose(); + void testCopyPasteSpecialMultiRangeRowFilteredIncludeFilteredTranspose(); + void testCopyPasteSpecialSkipEmpty(); + void testCopyPasteSpecialSkipEmptyFiltered(); + void testCopyPasteSpecialSkipEmptyIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyFilteredIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyTranspose(); + void testCopyPasteSpecialSkipEmptyTransposeIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyFilteredTranspose(); + void testCopyPasteSpecialSkipEmptyMultiRangeCol(); + void testCopyPasteSpecialSkipEmptyMultiRangeColFiltered(); + void testCopyPasteSpecialSkipEmptyMultiRangeColIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyMultiRangeColTranspose(); + void testCopyPasteSpecialSkipEmptyMultiRangeColFilteredTranspose(); + void testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFilteredTranspose(); + void testCopyPasteSpecialSkipEmptyMultiRangeRow(); + void testCopyPasteSpecialSkipEmptyMultiRangeRowFiltered(); + void testCopyPasteSpecialSkipEmptyMultiRangeRowIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFiltered(); + void testCopyPasteSpecialSkipEmptyMultiRangeRowTranspose(); + void testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredTranspose(); + void testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFilteredTranspose(); void testCopyPasteMultiRange(); void testCopyPasteSkipEmpty(); void testCopyPasteSkipEmpty2(); @@ -753,6 +806,58 @@ public: CPPUNIT_TEST(testCopyPaste); CPPUNIT_TEST(testCopyPasteAsLink); CPPUNIT_TEST(testCopyPasteTranspose); + CPPUNIT_TEST(testCopyPasteSpecialAsLinkTranspose); + CPPUNIT_TEST(testCopyPasteSpecialAllAsLinkTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColAsLinkTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColAsLinkFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowAsLinkTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowAsLinkFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialAsLinkFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialAllAsLinkFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMergedCellsTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMergedCellsFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecial); + CPPUNIT_TEST(testCopyPasteSpecialFiltered); + CPPUNIT_TEST(testCopyPasteSpecialIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialFilteredIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialTranspose); + CPPUNIT_TEST(testCopyPasteSpecialTransposeIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeCol); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColFiltered); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColFilteredIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeColFilteredIncludeFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRow); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowFiltered); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowFilteredIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialMultiRangeRowFilteredIncludeFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmpty); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyFilteredIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyTransposeIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeCol); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeColFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeColIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeColTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeColFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRow); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRowFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRowIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFiltered); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRowTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredTranspose); + CPPUNIT_TEST(testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFilteredTranspose); CPPUNIT_TEST(testCopyPasteMultiRange); CPPUNIT_TEST(testCopyPasteSkipEmpty); CPPUNIT_TEST(testCopyPasteSkipEmpty2); @@ -895,6 +1000,23 @@ public: private: std::unique_ptr<TestImpl> m_pImpl; ScDocument* m_pDoc; + + void executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFiltered, bool bAsLink, + bool bTranspose, bool bMultiRangeSelection, bool bSkipEmpty, + ScClipParam::Direction eDirection, bool bCalcAll, + InsertDeleteFlags aFlags); + void checkCopyPasteSpecial(bool bSkipEmpty); + void checkCopyPasteSpecialFiltered(bool bSkipEmpty); + void checkCopyPasteSpecialTranspose(bool bSkipEmpty); + void checkCopyPasteSpecialFilteredTranspose(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeCol(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeColFiltered(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeColTranspose(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeColFilteredTranspose(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeRow(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeRowFiltered(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeRowTranspose(bool bSkipEmpty); + void checkCopyPasteSpecialMultiRangeRowFilteredTranspose(bool bSkipEmpty); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/uicalc/uicalc.cxx b/sc/qa/unit/uicalc/uicalc.cxx index e42465402749..9ada6b120354 100644..100755 --- a/sc/qa/unit/uicalc/uicalc.cxx +++ b/sc/qa/unit/uicalc/uicalc.cxx @@ -464,6 +464,51 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf117706) CPPUNIT_ASSERT_EQUAL(OUString(""), pDoc->GetString(ScAddress(0, 2, 0))); } +// Inspired from testTdf117706, test columns instad of rows +CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testMultiRangeCol) +{ + mxComponent = loadFromDesktop("private:factory/scalc"); + ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get()); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + insertStringToCell(*pModelObj, "A1", "A1"); + insertStringToCell(*pModelObj, "C1", "C1"); + + // Use Adding Selection + dispatchCommand(mxComponent, ".uno:StatusSelectionModeExp", {}); + Scheduler::ProcessEventsToIdle(); + + goToCell("A1"); + dispatchCommand(mxComponent, ".uno:SelectColumn", {}); + Scheduler::ProcessEventsToIdle(); + + dispatchCommand(mxComponent, ".uno:GoRight", {}); + dispatchCommand(mxComponent, ".uno:GoRight", {}); + lcl_AssertCurrentCursorPosition(2, 0); + + dispatchCommand(mxComponent, ".uno:SelectColumn", {}); + Scheduler::ProcessEventsToIdle(); + + dispatchCommand(mxComponent, ".uno:Copy", {}); + + mxComponent->dispose(); + + // Open a new document + mxComponent = loadFromDesktop("private:factory/scalc"); + pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get()); + CPPUNIT_ASSERT(pModelObj); + pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + dispatchCommand(mxComponent, ".uno:Paste", {}); + + CPPUNIT_ASSERT_EQUAL(OUString("A1"), pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(OUString("C1"), pDoc->GetString(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT_EQUAL(OUString(""), pDoc->GetString(ScAddress(2, 0, 0))); +} + CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf131442) { mxComponent = loadFromDesktop("private:factory/scalc"); diff --git a/sc/source/core/data/clipparam.cxx b/sc/source/core/data/clipparam.cxx index b33c4998c10b..48840605364c 100644..100755 --- a/sc/source/core/data/clipparam.cxx +++ b/sc/source/core/data/clipparam.cxx @@ -70,7 +70,7 @@ SCCOL ScClipParam::getPasteColSize() return 0; } -SCROW ScClipParam::getPasteRowSize() +SCROW ScClipParam::getPasteRowSize(const ScDocument& rSrcDoc, bool bIncludeFiltered) { if (maRanges.empty()) return 0; @@ -81,7 +81,10 @@ SCROW ScClipParam::getPasteRowSize() { // We assume that all ranges have identical row size. const ScRange& rRange = maRanges.front(); - return rRange.aEnd.Row() - rRange.aStart.Row() + 1; + return bIncludeFiltered + ? rRange.aEnd.Row() - rRange.aStart.Row() + 1 + : rSrcDoc.CountNonFilteredRows(rRange.aStart.Row(), rRange.aEnd.Row(), + rRange.aStart.Tab()); } case ScClipParam::Row: { @@ -89,7 +92,10 @@ SCROW ScClipParam::getPasteRowSize() for ( size_t i = 0, nListSize = maRanges.size(); i < nListSize; ++i ) { const ScRange& rRange = maRanges[ i ]; - nRowSize += rRange.aEnd.Row() - rRange.aStart.Row() + 1; + nRowSize += bIncludeFiltered ? rRange.aEnd.Row() - rRange.aStart.Row() + 1 + : rSrcDoc.CountNonFilteredRows(rRange.aStart.Row(), + rRange.aEnd.Row(), + rRange.aStart.Tab()); } return nRowSize; } @@ -105,7 +111,8 @@ ScRange ScClipParam::getWholeRange() const return maRanges.Combine(); } -void ScClipParam::transpose() +void ScClipParam::transpose(const ScDocument& rSrcDoc, bool bIncludeFiltered, + bool bIsMultiRangeRowFilteredTranspose) { switch (meDirection) { @@ -126,21 +133,48 @@ void ScClipParam::transpose() const ScRange & rRange1 = maRanges.front(); SCCOL nColOrigin = rRange1.aStart.Col(); SCROW nRowOrigin = rRange1.aStart.Row(); - + SCROW nRowCount = 0; for ( size_t i = 0, n = maRanges.size(); i < n; ++i ) { const ScRange & rRange = maRanges[ i ]; SCCOL nColDelta = rRange.aStart.Col() - nColOrigin; SCROW nRowDelta = rRange.aStart.Row() - nRowOrigin; + SCROW nNonFilteredRows = rSrcDoc.CountNonFilteredRows( + rRange.aStart.Row(), rRange.aEnd.Row(), rRange.aStart.Tab()); + if (!bIsMultiRangeRowFilteredTranspose) + { + SCCOL nCol1 = 0; + SCCOL nCol2 = bIncludeFiltered + ? static_cast<SCCOL>(rRange.aEnd.Row() - rRange.aStart.Row()) + : nNonFilteredRows - 1; + SCROW nRow1 = 0; + SCROW nRow2 = static_cast<SCROW>(rRange.aEnd.Col() - rRange.aStart.Col()); + nCol1 += static_cast<SCCOL>(nRowDelta); + nCol2 += static_cast<SCCOL>(nRowDelta); + nRow1 += static_cast<SCROW>(nColDelta); + nRow2 += static_cast<SCROW>(nColDelta); + aNewRanges.push_back( ScRange(nCol1, nRow1, rRange.aStart.Tab(), nCol2, nRow2, rRange.aStart.Tab() ) ); + } + else + nRowCount += nNonFilteredRows; + } + + // Transpose of filtered multi range row selection is a special case since filtering + // and selection are in the same dimension (i.e. row), see ScDocument::TransposeClip() + if (bIsMultiRangeRowFilteredTranspose) + { + SCCOL nColDelta = rRange1.aStart.Col() - nColOrigin; + SCROW nRowDelta = rRange1.aStart.Row() - nRowOrigin; SCCOL nCol1 = 0; - SCCOL nCol2 = static_cast<SCCOL>(rRange.aEnd.Row() - rRange.aStart.Row()); + SCCOL nCol2 = nRowCount - 1; SCROW nRow1 = 0; - SCROW nRow2 = static_cast<SCROW>(rRange.aEnd.Col() - rRange.aStart.Col()); + SCROW nRow2 = static_cast<SCROW>(rRange1.aEnd.Col() - rRange1.aStart.Col()); nCol1 += static_cast<SCCOL>(nRowDelta); nCol2 += static_cast<SCCOL>(nRowDelta); nRow1 += static_cast<SCROW>(nColDelta); nRow2 += static_cast<SCROW>(nColDelta); - aNewRanges.push_back( ScRange(nCol1, nRow1, rRange.aStart.Tab(), nCol2, nRow2, rRange.aStart.Tab() ) ); + aNewRanges.push_back( + ScRange(nCol1, nRow1, rRange1.aStart.Tab(), nCol2, nRow2, rRange1.aStart.Tab())); } } maRanges = aNewRanges; diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index ad18c2f077bf..05036e0ee148 100644..100755 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -2317,17 +2317,18 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1, pClipDoc->GetClipParam().mbCutMode = false; } -void ScDocument::TransposeClip( ScDocument* pTransClip, InsertDeleteFlags nFlags, bool bAsLink ) +void ScDocument::TransposeClip(ScDocument* pTransClip, InsertDeleteFlags nFlags, bool bAsLink, + bool bIncludeFiltered) { OSL_ENSURE( bIsClip && pTransClip && pTransClip->bIsClip, "TransposeClip with wrong Document" ); - // initialize - // -> pTransClip has to be deleted before the original document! + // initialize + // -> pTransClip has to be deleted before the original document! pTransClip->ResetClip(this, nullptr); // all - // Take over range + // Take over range if (pRangeName) { @@ -2341,18 +2342,62 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, InsertDeleteFlags nFlags } } - // The data + ScRange aCombinedClipRange = GetClipParam().getWholeRange(); - ScRange aClipRange = GetClipParam().getWholeRange(); - if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) ) + if (!ValidRow(aCombinedClipRange.aEnd.Row() - aCombinedClipRange.aStart.Row())) { - for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++) + SAL_WARN("sc", "TransposeClip: Too big"); + return; + } + + // Transpose of filtered multi range row selection is a special case since filtering + // and selection are in the same dimension (i.e. row). + // The filtered row status and the selection ranges are not available at the same time, + // handle this case specially, do not use GetClipParam().getWholeRange(), + // instead loop through the ranges, calculate the row offest and handle filtered rows and + // create in ScClipParam::transpose() an unified range. + bool bIsMultiRangeRowFilteredTranspose + = !bIncludeFiltered && GetClipParam().isMultiRange() + && HasFilteredRows(aCombinedClipRange.aStart.Row(), aCombinedClipRange.aEnd.Row(), + aCombinedClipRange.aStart.Tab()) + && GetClipParam().meDirection == ScClipParam::Row; + + ScRangeList aClipRanges; + if (bIsMultiRangeRowFilteredTranspose) + aClipRanges = GetClipParam().maRanges; + else + aClipRanges = ScRangeList(aCombinedClipRange); + + // The data + ScRange aClipRange; + SCROW nRowCount = 0; // next consecutive row + for (size_t j = 0, n = aClipRanges.size(); j < n; ++j) + { + aClipRange = aClipRanges[j]; + + SCROW nRowOffset = 0; + if (bIsMultiRangeRowFilteredTranspose) + { + // adjust for the rows that are filtered + nRowOffset = nRowCount; + + // calculate filtered rows of current clip range + SCROW nRowCountAll = aClipRange.aEnd.Row() - aClipRange.aStart.Row() + 1; + SCROW nRowCountNonFiltered = CountNonFilteredRows( + aClipRange.aStart.Row(), aClipRange.aEnd.Row(), aClipRange.aStart.Tab()); + SCROW nRowCountInRange = bIncludeFiltered ? nRowCountAll : nRowCountNonFiltered; + nRowCount += nRowCountInRange; // for next iteration + } + + for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++) + { if (maTabs[i]) { - OSL_ENSURE( pTransClip->maTabs[i], "TransposeClip: Table not there" ); - maTabs[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(), - aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), - pTransClip->maTabs[i].get(), nFlags, bAsLink ); + OSL_ENSURE(pTransClip->maTabs[i], "TransposeClip: Table not there"); + maTabs[i]->TransposeClip(aClipRange.aStart.Col(), aClipRange.aStart.Row(), + aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), nRowOffset, + pTransClip->maTabs[i].get(), nFlags, bAsLink, + bIncludeFiltered); if ( mpDrawLayer && ( nFlags & InsertDeleteFlags::OBJECTS ) ) { @@ -2371,15 +2416,13 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, InsertDeleteFlags nFlags pTransClip->mpDrawLayer->CopyFromClip( mpDrawLayer.get(), i, aSourceRect, ScAddress(0,0,i), aDestRect ); } } - - pTransClip->SetClipParam(GetClipParam()); - pTransClip->GetClipParam().transpose(); - } - else - { - SAL_WARN("sc", "TransposeClip: Too big"); + } } + pTransClip->SetClipParam(GetClipParam()); + pTransClip->GetClipParam().transpose(*this, bIncludeFiltered, + bIsMultiRangeRowFilteredTranspose); + // This happens only when inserting... GetClipParam().mbCutMode = false; @@ -2711,9 +2754,9 @@ void ScDocument::CopyBlockFromClip( } } -void ScDocument::CopyNonFilteredFromClip( - sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - const ScMarkData& rMark, SCCOL nDx, SCROW & rClipStartRow ) +SCROW ScDocument::CopyNonFilteredFromClip(sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, + SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, + SCCOL nDx, SCROW& rClipStartRow, SCROW nClipEndRow) { // call CopyBlockFromClip for ranges of consecutive non-filtered rows // nCol1/nRow1 etc. is in target doc @@ -2725,15 +2768,16 @@ void ScDocument::CopyNonFilteredFromClip( ++nFlagTab; SCROW nSourceRow = rClipStartRow; - SCROW nSourceEnd = 0; - if (!rCxt.getClipDoc()->GetClipParam().maRanges.empty()) - nSourceEnd = rCxt.getClipDoc()->GetClipParam().maRanges.front().aEnd.Row(); + SCROW nSourceEnd = nClipEndRow; SCROW nDestRow = nRow1; + SCROW nFilteredRows = 0; while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 ) { // skip filtered rows + SCROW nSourceRowOriginal = nSourceRow; nSourceRow = rCxt.getClipDoc()->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab); + nFilteredRows += nSourceRow - nSourceRowOriginal; if ( nSourceRow <= nSourceEnd ) { @@ -2756,6 +2800,7 @@ void ScDocument::CopyNonFilteredFromClip( } } rClipStartRow = nSourceRow; + return nFilteredRows; } namespace { @@ -2936,8 +2981,8 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar } else { - CopyNonFilteredFromClip( - aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nClipStartRow); + CopyNonFilteredFromClip(aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nClipStartRow, + nClipEndRow); } nC1 = nC2 + 1; nC2 = std::min(static_cast<SCCOL>(nC1 + nXw), nCol2); @@ -3004,9 +3049,10 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar pClipDoc->GetClipParam().mbCutMode = false; } -void ScDocument::CopyMultiRangeFromClip( - const ScAddress& rDestPos, const ScMarkData& rMark, InsertDeleteFlags nInsFlag, ScDocument* pClipDoc, - bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty) +void ScDocument::CopyMultiRangeFromClip(const ScAddress& rDestPos, const ScMarkData& rMark, + InsertDeleteFlags nInsFlag, ScDocument* pClipDoc, + bool bResetCut, bool bAsLink, bool bIncludeFiltered, + bool bSkipAttrForEmpty) { if (bIsClip) return; @@ -3035,7 +3081,7 @@ void ScDocument::CopyMultiRangeFromClip( { // Do the deletion first. SCCOL nColSize = rClipParam.getPasteColSize(); - SCROW nRowSize = rClipParam.getPasteRowSize(); + SCROW nRowSize = rClipParam.getPasteRowSize(*pClipDoc, bIncludeFiltered); DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, InsertDeleteFlags::CONTENTS, false, &aBroadcastSpans); } @@ -3053,15 +3099,27 @@ void ScDocument::CopyMultiRangeFromClip( SCROW nDy = static_cast<SCROW>(nRow1 - rRange.aStart.Row()); SCCOL nCol2 = nCol1 + rRange.aEnd.Col() - rRange.aStart.Col(); SCROW nEndRow = nRow1 + nRowCount - 1; + SCROW nFilteredRows = 0; - CopyBlockFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, nDy); + if (bIncludeFiltered) + { + CopyBlockFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, nDy); + } + else + { + SCROW nClipStartRow = rRange.aStart.Row(); + SCROW nClipEndRow = rRange.aEnd.Row(); + nFilteredRows += CopyNonFilteredFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, + nClipStartRow, nClipEndRow); + nRowCount -= nFilteredRows; + } switch (rClipParam.meDirection) { case ScClipParam::Row: // Begin row for the next range being pasted. nRow1 += nRowCount; - break; + break; case ScClipParam::Column: nCol1 += rRange.aEnd.Col() - rRange.aStart.Col() + 1; break; diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 93e9067b9016..2e4d81c362d7 100644..100755 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -73,7 +73,6 @@ #include <memory> #include <map> -#include <vector> using namespace formula; @@ -3754,6 +3753,15 @@ void ScFormulaCell::UpdateCompile( bool bForceIfNameInUse ) CompileTokenArray(); } +static void lcl_TransposeReference(ScSingleRefData& rRef) +{ + // References to or over filtered rows are not adjusted + // analog to the normal (non-transposed) case + SCCOLROW nTemp = rRef.Col(); + rRef.SetRelCol(rRef.Row()); + rRef.SetRelRow(nTemp); +} + // Reference transposition is only called in Clipboard Document void ScFormulaCell::TransposeReference() { @@ -3769,18 +3777,10 @@ void ScFormulaCell::TransposeReference() ScSingleRefData& rRef2 = (bDouble ? t->GetDoubleRef()->Ref2 : rRef1); if ( !bDouble || (rRef2.IsColRel() && rRef2.IsRowRel()) ) { - SCCOLROW nTemp; - - nTemp = rRef1.Col(); - rRef1.SetRelCol(rRef1.Row()); - rRef1.SetRelRow(nTemp); + lcl_TransposeReference(rRef1); if ( bDouble ) - { - nTemp = rRef2.Col(); - rRef2.SetRelCol(rRef2.Row()); - rRef2.SetRelRow(nTemp); - } + lcl_TransposeReference(rRef2); bFound = true; } diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index a86c95da082d..af21428fde22 100644..100755 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -796,12 +796,19 @@ namespace { class TransClipHandler { ScTable& mrClipTab; + const ScTable& mrSrcTab; SCTAB mnSrcTab; SCCOL mnSrcCol; size_t mnTopRow; + size_t mnEndRow; SCROW mnTransRow; + SCROW mnFilteredRows = 0; + SCROW mnRowDestOffset = 0; bool mbAsLink; bool mbWasCut; + bool mbIncludeFiltered; + InsertDeleteFlags mnFlags; + std::vector<SCROW>& mrFilteredRows; ScAddress getDestPos(size_t nRow) const { @@ -822,62 +829,118 @@ class TransClipHandler void setLink(size_t nRow) { - SCCOL nTransCol = nRow - mnTopRow; - mrClipTab.SetFormulaCell( - nTransCol, mnTransRow, createRefCell(nRow, getDestPos(nRow))); + SCCOL nTransCol = nRow - mnTopRow - mnFilteredRows + mnRowDestOffset; + mrClipTab.SetFormulaCell(nTransCol, mnTransRow, + createRefCell(nRow, getDestPos(nRow))); } public: - TransClipHandler(ScTable& rClipTab, SCTAB nSrcTab, SCCOL nSrcCol, size_t nTopRow, SCROW nTransRow, bool bAsLink, bool bWasCut) : - mrClipTab(rClipTab), mnSrcTab(nSrcTab), mnSrcCol(nSrcCol), - mnTopRow(nTopRow), mnTransRow(nTransRow), mbAsLink(bAsLink), mbWasCut(bWasCut) {} + TransClipHandler(ScTable& rClipTab, const ScTable& rSrcTab, SCTAB nSrcTab, SCCOL nSrcCol, + size_t nTopRow, size_t nEndRow, SCROW nTransRow, SCROW nRowDestOffset, + bool bAsLink, bool bWasCut, const InsertDeleteFlags& nFlags, + const bool bIncludeFiltered, std::vector<SCROW>& rFilteredRows) + : mrClipTab(rClipTab) + , mrSrcTab(rSrcTab) + , mnSrcTab(nSrcTab) + , mnSrcCol(nSrcCol) + , mnTopRow(nTopRow) + , mnEndRow(nEndRow) + , mnTransRow(nTransRow) + , mnRowDestOffset(nRowDestOffset) + , mbAsLink(bAsLink) + , mbWasCut(bWasCut) + , mbIncludeFiltered(bIncludeFiltered) + , mnFlags(nFlags) + , mrFilteredRows(rFilteredRows) + { + // Create list of filtered rows. + if (!mbIncludeFiltered) + { + for (SCROW curRow = nTopRow; curRow <= static_cast<SCROW>(mnEndRow); ++curRow) + { + // maybe this loop could be optimized + bool bFiltered = mrSrcTab.RowFiltered(curRow, nullptr, nullptr); + if (bFiltered) + mrFilteredRows.push_back(curRow); + } + } + } void operator() (size_t nRow, double fVal) { + bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr); + if (!mbIncludeFiltered && bFiltered) + { + mnFilteredRows++; + return; + } + if (mbAsLink) { setLink(nRow); return; } - SCCOL nTransCol = nRow - mnTopRow; + SCCOL nTransCol = nRow - mnTopRow - mnFilteredRows + mnRowDestOffset; mrClipTab.SetValue(nTransCol, mnTransRow, fVal); } void operator() (size_t nRow, const svl::SharedString& rStr) { + bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr); + if (!mbIncludeFiltered && bFiltered) + { + mnFilteredRows++; + return; + } + if (mbAsLink) { setLink(nRow); return; } - SCCOL nTransCol = nRow - mnTopRow; + SCCOL nTransCol = nRow - mnTopRow - mnFilteredRows + mnRowDestOffset; mrClipTab.SetRawString(nTransCol, mnTransRow, rStr); } void operator() (size_t nRow, const EditTextObject* p) { + bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr); + if (!mbIncludeFiltered && bFiltered) + { + mnFilteredRows++; + return; + } + if (mbAsLink) { setLink(nRow); return; } - SCCOL nTransCol = nRow - mnTopRow; + SCCOL nTransCol = nRow - mnTopRow - mnFilteredRows + mnRowDestOffset; mrClipTab.SetEditText(nTransCol, mnTransRow, ScEditUtil::Clone(*p, mrClipTab.GetDoc())); } void operator() (size_t nRow, const ScFormulaCell* p) { + bool bFiltered = mrSrcTab.RowFiltered(nRow, nullptr, nullptr); + if (!mbIncludeFiltered && bFiltered) + { + mnFilteredRows++; + return; + } + if (mbAsLink) { setLink(nRow); return; } - ScFormulaCell* pNew = new ScFormulaCell( - *p, mrClipTab.GetDoc(), getDestPos(nRow), ScCloneFlags::StartListening); + ScFormulaCell* pNew = new ScFormulaCell(*p, mrClipTab.GetDoc(), + getDestPos(nRow - mnFilteredRows + mnRowDestOffset), + ScCloneFlags::StartListening); // rotate reference // for Cut, the references are later adjusted through UpdateTranspose @@ -885,52 +948,99 @@ public: if (!mbWasCut) pNew->TransposeReference(); - SCCOL nTransCol = nRow - mnTopRow; + SCCOL nTransCol = nRow - mnTopRow - mnFilteredRows + mnRowDestOffset; mrClipTab.SetFormulaCell(nTransCol, mnTransRow, pNew); } -}; + // empty cells + void operator()(const int /*type*/, size_t nRow, size_t nDataSize) + { + for (size_t curRow = nRow; curRow < nRow + nDataSize; ++curRow) + { + bool bFiltered = mrSrcTab.RowFiltered(curRow, nullptr, nullptr); + if (!mbIncludeFiltered && bFiltered) + { + mnFilteredRows++; + continue; } -void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - ScTable* pTransClip, InsertDeleteFlags nFlags, bool bAsLink ) + if (mbAsLink && mnFlags == InsertDeleteFlags::ALL) { - bool bWasCut = rDocument.IsCutMode(); + // with InsertDeleteFlags::ALL, also create links (formulas) for empty cells + setLink(nRow); + continue; + } + } + } +}; +} - ScDocument& rDestDoc = pTransClip->rDocument; +void ScTable::TransposeClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, + SCROW nRowDestOffset, ScTable* pTransClip, InsertDeleteFlags nFlags, + bool bAsLink, bool bIncludeFiltered) +{ + bool bWasCut = rDocument.IsCutMode(); for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++) { - SCROW nRow; - if ( bAsLink && nFlags == InsertDeleteFlags::ALL ) - { - // with InsertDeleteFlags::ALL, also create links (formulas) for empty cells + std::vector<SCROW> aFilteredRows; - for ( nRow=nRow1; nRow<=nRow2; nRow++ ) - { - // create simple formula, as in ScColumn::CreateRefCell - - ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab ); - ScSingleRefData aRef; - aRef.InitAddress(ScAddress(nCol,nRow,nTab)); - aRef.SetFlag3D(true); - ScTokenArray aArr(rDestDoc); - aArr.AddSingleReference( aRef ); - - pTransClip->SetFormulaCell( - static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), - new ScFormulaCell(rDestDoc, aDestPos, aArr)); - } - } - else + TransClipHandler aFunc(*pTransClip, *this, nTab, nCol, nRow1, nRow2, + static_cast<SCROW>(nCol - nCol1), nRowDestOffset, bAsLink, bWasCut, + nFlags, bIncludeFiltered, aFilteredRows); + + const sc::CellStoreType& rCells = aCol[nCol].maCells; + + // Loop through all rows by iterator and call aFunc operators + sc::ParseAll(rCells.begin(), rCells, nRow1, nRow2, aFunc, + aFunc); + + // Attributes + if (nFlags & InsertDeleteFlags::ATTRIB) + TransposeColPatterns(pTransClip, nCol1, nCol, nRow1, nRow2, bIncludeFiltered, + aFilteredRows, nRowDestOffset); + + // Cell Notes - fdo#68381 paste cell notes on Transpose + if ((nFlags & InsertDeleteFlags::NOTE) && rDocument.HasColNotes(nCol, nTab)) + TransposeColNotes(pTransClip, nCol1, nCol, nRow1, nRow2, bIncludeFiltered, + nRowDestOffset); + } +} + +static void lcl_SetTransposedPatternInRows(ScTable* pTransClip, SCROW nAttrRow1, SCROW nAttrRow2, + SCCOL nCol1, SCROW nRow1, SCCOL nCol, + const ScPatternAttr& rPatternAttr, bool bIncludeFiltered, + const std::vector<SCROW>& rFilteredRows, + SCROW nRowDestOffset) +{ + for (SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++) + { + size_t nFilteredRowAdjustment = 0; + if (!bIncludeFiltered) { - TransClipHandler aFunc(*pTransClip, nTab, nCol, nRow1, static_cast<SCROW>(nCol-nCol1), bAsLink, bWasCut); - const sc::CellStoreType& rCells = aCol[nCol].maCells; - sc::ParseAllNonEmpty(rCells.begin(), rCells, nRow1, nRow2, aFunc); + // aFilteredRows is sorted thus lower_bound() can be used. + // lower_bound() has a logarithmic complexity O(log(n)) + auto itRow1 = std::lower_bound(rFilteredRows.begin(), rFilteredRows.end(), nRow1); + auto itRow = std::lower_bound(rFilteredRows.begin(), rFilteredRows.end(), nRow); + bool bRefRowIsFiltered = itRow != rFilteredRows.end() && *itRow == nRow; + if (bRefRowIsFiltered) + continue; + + // How many filtered rows are between the formula cell and the reference? + // distance() has a constant complexity O(1) for vectors + nFilteredRowAdjustment = std::distance(itRow1, itRow); } - // Attribute + pTransClip->SetPattern( + static_cast<SCCOL>(nRow - nRow1 - nFilteredRowAdjustment + nRowDestOffset), + static_cast<SCROW>(nCol - nCol1), rPatternAttr); + } +} +void ScTable::TransposeColPatterns(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, + SCROW nRow2, bool bIncludeFiltered, + const std::vector<SCROW>& rFilteredRows, SCROW nRowDestOffset) +{ SCROW nAttrRow1 = {}; // spurious -Werror=maybe-uninitialized SCROW nAttrRow2 = {}; // spurious -Werror=maybe-uninitialized const ScPatternAttr* pPattern; @@ -944,9 +1054,11 @@ void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, rSet.GetItemState( ATTR_MERGE_FLAG, false ) == SfxItemState::DEFAULT && rSet.GetItemState( ATTR_BORDER, false ) == SfxItemState::DEFAULT ) { + // Set pattern in cells from nAttrRow1 to nAttrRow2 // no borders or merge items involved - use pattern as-is - for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++) - pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), *pPattern ); + lcl_SetTransposedPatternInRows(pTransClip, nAttrRow1, nAttrRow2, nCol1, nRow1, + nCol, *pPattern, bIncludeFiltered, rFilteredRows, + nRowDestOffset); } else { @@ -987,20 +1099,17 @@ void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, rNewSet.ClearItem( ATTR_MERGE_FLAG ); } - for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++) - pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), - static_cast<SCROW>(nCol-nCol1), aNewPattern); + // Set pattern in cells from nAttrRow1 to nAttrRow2 + lcl_SetTransposedPatternInRows(pTransClip, nAttrRow1, nAttrRow2, nCol1, nRow1, + nCol, aNewPattern, bIncludeFiltered, + rFilteredRows, nRowDestOffset); } } - } - - // Cell Notes - fdo#68381 paste cell notes on Transpose - if ( rDocument.HasColNotes(nCol, nTab) ) - TransposeColNotes(pTransClip, nCol1, nCol, nRow1, nRow2); } } -void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2) +void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, + SCROW nRow2, bool bIncludeFiltered, SCROW nRowDestOffset) { sc::CellNoteStoreType::const_iterator itBlk = aCol[nCol].maCellNotes.begin(), itBlkEnd = aCol[nCol].maCellNotes.end(); @@ -1023,6 +1132,7 @@ void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SC return; nRowPos = static_cast<size_t>(nRow2); // End row position. + SCCOL nFilteredRows = 0; // Keep processing until we hit the end row position. sc::cellnote_block::const_iterator itData, itDataEnd; @@ -1035,6 +1145,7 @@ void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SC itData = sc::cellnote_block::begin(*itBlk->data); std::advance(itData, nOffsetInBlock); + // selected area is smaller than the iteration block if (nBlockStart <= nRowPos && nRowPos < nBlockEnd) { // This block contains the end row. Only process partially. @@ -1044,7 +1155,16 @@ void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SC size_t curRow = nBlockStart + nOffsetInBlock; for (; itData != itDataEnd; ++itData, ++curRow) { - ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab ); + bool bFiltered = this->RowFiltered(curRow, nullptr, nullptr); + if (!bIncludeFiltered && bFiltered) + { + nFilteredRows++; + continue; + } + + ScAddress aDestPos( + static_cast<SCCOL>(curRow - nRow1 - nFilteredRows + nRowDestOffset), + static_cast<SCROW>(nCol - nCol1), pTransClip->nTab); pTransClip->rDocument.ReleaseNote(aDestPos); ScPostIt* pNote = *itData; if (pNote) @@ -1061,7 +1181,16 @@ void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SC size_t curRow = nBlockStart + nOffsetInBlock; for (; itData != itDataEnd; ++itData, ++curRow) { - ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab ); + bool bFiltered = this->RowFiltered(curRow, nullptr, nullptr); + if (!bIncludeFiltered && bFiltered) + { + nFilteredRows++; + continue; + } + + ScAddress aDestPos( + static_cast<SCCOL>(curRow - nRow1 - nFilteredRows + nRowDestOffset), + static_cast<SCROW>(nCol - nCol1), pTransClip->nTab); pTransClip->rDocument.ReleaseNote(aDestPos); ScPostIt* pNote = *itData; if (pNote) @@ -1072,16 +1201,23 @@ void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SC } } } - else + else // remove dest notes for rows without notes { - size_t curRow; - for ( curRow = nBlockStart + nOffsetInBlock; curRow <= nBlockEnd && curRow <= nRowPos; ++curRow) + for (size_t curRow = nBlockStart + nOffsetInBlock; + curRow <= nBlockEnd && curRow <= nRowPos; ++curRow) { - ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab ); + bool bFiltered = this->RowFiltered(curRow, nullptr, nullptr); + if (!bIncludeFiltered && bFiltered && curRow < nBlockEnd) + { + nFilteredRows++; + continue; + } + + ScAddress aDestPos( + static_cast<SCCOL>(curRow - nRow1 - nFilteredRows + nRowDestOffset), + static_cast<SCROW>(nCol - nCol1), pTransClip->nTab); pTransClip->rDocument.ReleaseNote(aDestPos); } - if (curRow == nRowPos) - break; } } } diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index 873312644634..ec037cc18e71 100644..100755 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -352,9 +352,10 @@ private: void PasteRTF( SCCOL nCol, SCROW nStartRow, const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable ); - bool PasteMultiRangesFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScPasteFunc nFunction, - bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, - InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags ); + bool PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* pClipDoc, + ScPasteFunc nFunction, bool bSkipEmpty, bool bIncludeFiltered, + bool bTranspose, bool bAsLink, bool bAllowDialogs, + InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags); bool PasteFromClipToMultiRanges( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScPasteFunc nFunction, bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index db5987e8b2a8..476e92cd7443 100644..100755 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -905,9 +905,8 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, if (rClipParam.isMultiRange()) { // Source data is multi-range. - return PasteMultiRangesFromClip( - nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs, - eMoveMode, nUndoFlags); + return PasteMultiRangesFromClip(nFlags, pClipDoc, nFunction, bSkipEmpty, false, bTranspose, + bAsLink, bAllowDialogs, eMoveMode, nUndoFlags); } ScMarkData& rMark = GetViewData().GetMarkData(); @@ -933,7 +932,6 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, SCCOL nX; SCROW nY; // include filtered rows until TransposeClip can skip them - bIncludeFiltered = true; pClipDoc->GetClipArea( nX, nY, true ); if ( nY > static_cast<sal_Int32>(pClipDoc->MaxCol()) ) // too many lines for transpose { @@ -950,7 +948,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScDrawLayer::SetGlobalDrawPersist( aTransShellRef.get() ); xTransClip.reset( new ScDocument( SCDOCMODE_CLIP )); - pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink ); + pClipDoc->TransposeClip(xTransClip.get(), nFlags, bAsLink, bIncludeFiltered); pClipDoc = xTransClip.get(); ScDrawLayer::SetGlobalDrawPersist(nullptr); @@ -1470,10 +1468,11 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, return true; } -bool ScViewFunc::PasteMultiRangesFromClip( - InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScPasteFunc nFunction, - bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, - InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags) +bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* pClipDoc, + ScPasteFunc nFunction, bool bSkipEmpty, + bool bIncludeFiltered, bool bTranspose, bool bAsLink, + bool bAllowDialogs, InsCellCmd eMoveMode, + InsertDeleteFlags nUndoFlags) { ScViewData& rViewData = GetViewData(); ScDocument& rDoc = rViewData.GetDocument(); @@ -1482,7 +1481,7 @@ bool ScViewFunc::PasteMultiRangesFromClip( const ScAddress& rCurPos = rViewData.GetCurPos(); ScClipParam& rClipParam = pClipDoc->GetClipParam(); SCCOL nColSize = rClipParam.getPasteColSize(); - SCROW nRowSize = rClipParam.getPasteRowSize(); + SCROW nRowSize = rClipParam.getPasteRowSize(*pClipDoc, bIncludeFiltered); if (bTranspose) { @@ -1493,7 +1492,7 @@ bool ScViewFunc::PasteMultiRangesFromClip( } ScDocumentUniquePtr pTransClip(new ScDocument(SCDOCMODE_CLIP)); - pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink); + pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink, bIncludeFiltered); pClipDoc = pTransClip.release(); SCCOL nTempColSize = nColSize; nColSize = static_cast<SCCOL>(nRowSize); @@ -1580,8 +1579,9 @@ bool ScViewFunc::PasteMultiRangesFromClip( rDoc.BeginDrawUndo(); InsertDeleteFlags nNoObjFlags = nFlags & ~InsertDeleteFlags::OBJECTS; - rDoc.CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc, - true, bAsLink, false, bSkipEmpty); + // in case of transpose, links were added in TransposeClip() + rDoc.CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc, true, bAsLink && !bTranspose, + bIncludeFiltered, bSkipEmpty); if (pMixDoc) rDoc.MixDocument(aMarkedRange, nFunction, bSkipEmpty, *pMixDoc); @@ -1591,8 +1591,8 @@ bool ScViewFunc::PasteMultiRangesFromClip( if (nFlags & InsertDeleteFlags::OBJECTS) { // Paste the drawing objects after the row heights have been updated. - rDoc.CopyMultiRangeFromClip(rCurPos, aMark, InsertDeleteFlags::OBJECTS, pClipDoc, - true, false, false, true); + rDoc.CopyMultiRangeFromClip(rCurPos, aMark, InsertDeleteFlags::OBJECTS, pClipDoc, true, + false, bIncludeFiltered, true); } if (bRowInfo) |