[Libreoffice-commits] core.git: sc/inc sc/qa sc/source

scito (via logerrit) logerrit at kemper.freedesktop.org
Sat May 29 20:46:52 UTC 2021


 sc/inc/clipparam.hxx                     |    7 
 sc/inc/document.hxx                      |    5 
 sc/inc/refupdatecontext.hxx              |    5 
 sc/qa/unit/helper/qahelper.cxx           |   44 
 sc/qa/unit/helper/qahelper.hxx           |    9 
 sc/qa/unit/ucalc_copypaste.cxx           | 4810 +++++++++++++++++++++++++++++--
 sc/source/core/data/clipparam.cxx        |    2 
 sc/source/core/data/document.cxx         |    2 
 sc/source/core/data/formulacell.cxx      |   15 
 sc/source/core/data/refupdatecontext.cxx |   15 
 sc/source/core/tool/rangenam.cxx         |    2 
 sc/source/core/tool/refupdat.cxx         |    6 
 sc/source/core/tool/token.cxx            |   30 
 13 files changed, 4657 insertions(+), 295 deletions(-)

New commits:
commit bda9929821de620f1f85528abd1c4bba46d937d6
Author:     scito <info at scito.ch>
AuthorDate: Wed May 26 21:00:33 2021 +0200
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Sat May 29 22:46:11 2021 +0200

    tdf#142201 tdf#142065 fix cut paste transpose references, incl. undo
    
    For cut paste transposed, references are not anymore updated during
    UpdateReference(), but all these references will be updated during
    UpdateTranspose(). In previous implementation, some references were moved (i.e.
    updated). This caused problems in UpdateTranspose().
    
    A transposed flag is added to the clipparam. This flag is checked during
    UpdateReference().
    
    UpdateTranspose() must only operate on (i.e. transpose) references pointing to
    the source area. That's why updates must not be made during UpdateReference().
    Otherwise references pointing to the destination range will be transposed
    wrongly during UpdateTranspose().
    
    References in formulas as well as in named ranges are fixed and tested.
    
    I've added unit tests for all these cases and I've enhanced my previous
    copy/paste test framework (6491c205acb3c166d93ef6a41199d344e21d98ac) for
    cut/paste tests, incl. undo.
    
    Before LibreOffice 7.2, adjusting of references in cut paste transposed was
    completely broken (tdf#71058, tdf#68976, tdf#142065 and tdf#142201).
    
    Change-Id: I8a8d295f1cc683572905ae9633e16d010cfb8792
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116073
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/inc/clipparam.hxx b/sc/inc/clipparam.hxx
index 55f37fe1d89e..4487e77093ff 100644
--- a/sc/inc/clipparam.hxx
+++ b/sc/inc/clipparam.hxx
@@ -36,6 +36,8 @@ struct SC_DLLPUBLIC ScClipParam
     bool                mbCutMode;
     sal_uInt32          mnSourceDocID;
     ScRangeListVector   maProtectedChartRangesVector;
+    /** Was this clip transposed? */
+    bool mbTransposed = false;
 
     ScClipParam();
     ScClipParam(const ScRange& rRange, bool bCutMode);
@@ -69,6 +71,11 @@ struct SC_DLLPUBLIC ScClipParam
 
     sal_uInt32 getSourceDocID() const { return mnSourceDocID; }
     void setSourceDocID( sal_uInt32 nVal ) { mnSourceDocID = nVal; }
+
+    /**
+     * Was this clip transposed?
+     */
+    bool isTransposed() const { return mbTransposed; }
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index e4127d426d25..63aec33a5161 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1706,7 +1706,10 @@ public:
     void               UpdateReference( sc::RefUpdateContext& rCxt,  ScDocument*
                                         pUndoDoc = nullptr, bool bIncludeDraw = true,
                                         bool bUpdateNoteCaptionPos = true );
-
+    /**
+     * @param pClipDoc original clipboard doc, i.e. non-transposed
+     *                 This clip doc is used to check references pointing to cut cells.
+     */
     SC_DLLPUBLIC void  UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
                                         const ScMarkData& rMark, ScDocument* pUndoDoc );
 
diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx
index 7e1a4d9e8dd6..1c50c7a2c0d1 100644
--- a/sc/inc/refupdatecontext.hxx
+++ b/sc/inc/refupdatecontext.hxx
@@ -68,6 +68,9 @@ struct RefUpdateContext
      */
     ScRange maRange;
 
+    /** Are the data transposed? */
+    bool mbTransposed;
+
     /** Amount and direction of movement in the column direction. */
     SCCOL mnColDelta;
     /** Amount and direction of movement in the row direction. */
@@ -80,7 +83,7 @@ struct RefUpdateContext
 
     ColumnBlockPositionSet* mpBlockPos; // not owning
 
-    RefUpdateContext(ScDocument& rDoc);
+    RefUpdateContext(ScDocument& rDoc, ScDocument* pClipdoc = nullptr);
 
     bool isInserted() const;
     bool isDeleted() const;
diff --git a/sc/qa/unit/helper/qahelper.cxx b/sc/qa/unit/helper/qahelper.cxx
index 8502cf6caf52..590250847d95 100644
--- a/sc/qa/unit/helper/qahelper.cxx
+++ b/sc/qa/unit/helper/qahelper.cxx
@@ -1027,7 +1027,38 @@ bool insertRangeNames(
     return true;
 }
 
-void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption)
+OUString getRangeByName(ScDocument* pDoc, const OUString& aRangeName)
+{
+    ScRangeData* pName = pDoc->GetRangeName()->findByUpperName(aRangeName.toAsciiUpperCase());
+    CPPUNIT_ASSERT(pName);
+    OUString aSymbol;
+    pName->GetSymbol(aSymbol, pDoc->GetGrammar());
+
+    return aSymbol;
+}
+
+OUString getFormula(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
+{
+    OUString aFormula;
+    pDoc->GetFormula(nCol, nRow, nTab, aFormula);
+    return aFormula;
+}
+
+#if CALC_DEBUG_OUTPUT != 0
+void printFormula(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, const char* pCaption)
+{
+    if (pCaption != nullptr)
+        cout << pCaption << ", ";
+    cout << nCol << "/" << nRow << ": " << getFormula(pDoc, nCol, nRow, nTab);
+    cout << endl;
+}
+#else
+// Avoid unused parameter warning
+void printFormula(ScDocument*, SCCOL, SCROW, SCTAB, const char*) {}
+#endif
+
+void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption,
+                const bool printFormula)
 {
     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
     SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
@@ -1038,13 +1069,20 @@ void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption)
         {
             ScAddress aPos(nCol, nRow, rRange.aStart.Tab());
             ScRefCellValue aCell(*pDoc, aPos);
-            OUString aVal = ScCellFormat::GetOutputString(*pDoc, aPos, aCell);
-            printer.set(nRow-nRow1, nCol-nCol1, aVal);
+            OUString aVal = printFormula ? getFormula(pDoc, nCol, nRow, rRange.aStart.Tab())
+                                         : ScCellFormat::GetOutputString(*pDoc, aPos, aCell);
+            printer.set(nRow - nRow1, nCol - nCol1, aVal);
         }
     }
     printer.print(pCaption);
 }
 
+void printRange(ScDocument* pDoc, const ScRange& rRange, const OString& rCaption,
+                const bool printFormula)
+{
+    printRange(pDoc, rRange, rCaption.getStr(), printFormula);
+}
+
 void clearRange(ScDocument* pDoc, const ScRange& rRange)
 {
     ScMarkData aMarkData(pDoc->GetSheetLimits());
diff --git a/sc/qa/unit/helper/qahelper.hxx b/sc/qa/unit/helper/qahelper.hxx
index d0a449f88f5d..ce981b5c9346 100644
--- a/sc/qa/unit/helper/qahelper.hxx
+++ b/sc/qa/unit/helper/qahelper.hxx
@@ -258,7 +258,14 @@ SCQAHELPER_DLLPUBLIC ScRange insertRangeData(ScDocument* pDoc, const ScAddress&
                                    const std::vector<std::vector<const char*>>& rData);
 SCQAHELPER_DLLPUBLIC bool insertRangeNames(ScDocument* pDoc, ScRangeName* pNames, const RangeNameDef* p,
                                    const RangeNameDef* pEnd);
-SCQAHELPER_DLLPUBLIC void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption);
+SCQAHELPER_DLLPUBLIC OUString getRangeByName(ScDocument* pDoc, const OUString& aRangeName);
+SCQAHELPER_DLLPUBLIC OUString getFormula(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab);
+SCQAHELPER_DLLPUBLIC void printFormula(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
+                                       const char* pCaption = nullptr);
+SCQAHELPER_DLLPUBLIC void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption,
+                                     const bool printFormula = false);
+SCQAHELPER_DLLPUBLIC void printRange(ScDocument* pDoc, const ScRange& rRange,
+                                     const OString& rCaption, const bool printFormula = false);
 SCQAHELPER_DLLPUBLIC void clearRange(ScDocument* pDoc, const ScRange& rRange);
 SCQAHELPER_DLLPUBLIC void clearSheet(ScDocument* pDoc, SCTAB nTab);
 
diff --git a/sc/qa/unit/ucalc_copypaste.cxx b/sc/qa/unit/ucalc_copypaste.cxx
index 35c1bb72f276..9dc3fe8ba3c0 100644
--- a/sc/qa/unit/ucalc_copypaste.cxx
+++ b/sc/qa/unit/ucalc_copypaste.cxx
@@ -117,6 +117,27 @@ public:
     void testTdf68976();
     void testTdf71058();
 
+    void testCutPasteSpecial();
+    void testCutPasteSpecialTranspose();
+    void testCutPasteSpecialSkipEmpty();
+    void testCutPasteSpecialSkipEmptyTranspose();
+    void testTdf142201Row();
+    void testTdf142201ColRel();
+    void testTdf142201ColAbs();
+    void testTdf142065();
+    void testCutTransposedFormulas();
+    void testCutTransposedFormulasSquare();
+    void testReferencedCutRangesRow();
+    void testReferencedCutTransposedRangesRowTab0To0();
+    void testReferencedCutTransposedRangesRowTab0To1();
+    void testReferencedCutTransposedRangesRowTab1To3();
+    void testReferencedCutTransposedRangesRowTab3To1();
+    void testReferencedCutRangesCol();
+    void testReferencedCutTransposedRangesColTab0To0();
+    void testReferencedCutTransposedRangesColTab0To1();
+    void testReferencedCutTransposedRangesColTab1To3();
+    void testReferencedCutTransposedRangesColTab3To1();
+
     CPPUNIT_TEST_SUITE(TestCopyPaste);
 
     CPPUNIT_TEST(testCopyPaste);
@@ -193,19 +214,61 @@ public:
     CPPUNIT_TEST(testTdf68976);
     CPPUNIT_TEST(testTdf71058);
 
+    CPPUNIT_TEST(testCutPasteSpecial);
+    CPPUNIT_TEST(testCutPasteSpecialTranspose);
+    CPPUNIT_TEST(testCutPasteSpecialSkipEmpty);
+    CPPUNIT_TEST(testCutPasteSpecialSkipEmptyTranspose);
+    CPPUNIT_TEST(testTdf142201Row);
+    CPPUNIT_TEST(testTdf142201ColRel);
+    CPPUNIT_TEST(testTdf142201ColAbs);
+    CPPUNIT_TEST(testTdf142065);
+    CPPUNIT_TEST(testCutTransposedFormulas);
+    CPPUNIT_TEST(testCutTransposedFormulasSquare);
+    CPPUNIT_TEST(testReferencedCutRangesRow);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesRowTab0To0);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesRowTab0To1);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesRowTab1To3);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesRowTab3To1);
+    CPPUNIT_TEST(testReferencedCutRangesCol);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesColTab0To0);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesColTab0To1);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesColTab1To3);
+    CPPUNIT_TEST(testReferencedCutTransposedRangesColTab3To1);
+
     CPPUNIT_TEST_SUITE_END();
 
 private:
     ScDocShellRef m_xDocShell;
     ScDocument* m_pDoc;
 
+    enum CalcMode
+    {
+        NoCalc,
+        AutoCalc,
+        RecalcAtEnd,
+        HardRecalcAtEnd
+    };
+
     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);
+                                 bool bCut = false,
+                                 ScClipParam::Direction eDirection = ScClipParam::Column,
+                                 CalcMode eCalcMode = CalcMode::AutoCalc,
+                                 InsertDeleteFlags aFlags
+                                 = InsertDeleteFlags::CONTENTS | InsertDeleteFlags::ATTRIB);
+    void executeCopyPasteSpecial(const SCTAB srcSheet, const SCTAB destSheet, bool bApplyFilter,
+                                 bool bIncludedFiltered, bool bAsLink, bool bTranspose,
+                                 bool bMultiRangeSelection, bool bSkipEmpty,
+                                 std::unique_ptr<ScUndoCut>& pUndoCut,
+                                 std::unique_ptr<ScUndoPaste>& pUndoPaste, bool bCut = false,
+                                 ScClipParam::Direction eDirection = ScClipParam::Column,
+                                 CalcMode eCalcMode = CalcMode::AutoCalc,
+                                 InsertDeleteFlags aFlags
+                                 = InsertDeleteFlags::CONTENTS | InsertDeleteFlags::ATTRIB);
+    void checkCopyPasteSpecialInitial(const SCTAB srcSheet);
+    void checkCopyPasteSpecial(bool bSkipEmpty, bool bCut = false);
     void checkCopyPasteSpecialFiltered(bool bSkipEmpty);
-    void checkCopyPasteSpecialTranspose(bool bSkipEmpty);
+    void checkCopyPasteSpecialTranspose(bool bSkipEmpty, bool bCut = false);
     void checkCopyPasteSpecialFilteredTranspose(bool bSkipEmpty);
     void checkCopyPasteSpecialMultiRangeCol(bool bSkipEmpty);
     void checkCopyPasteSpecialMultiRangeColFiltered(bool bSkipEmpty);
@@ -215,6 +278,38 @@ private:
     void checkCopyPasteSpecialMultiRangeRowFiltered(bool bSkipEmpty);
     void checkCopyPasteSpecialMultiRangeRowTranspose(bool bSkipEmpty);
     void checkCopyPasteSpecialMultiRangeRowFilteredTranspose(bool bSkipEmpty);
+    void checkReferencedCutTransposedRangesRowUndo(const SCTAB nSrcTab, const SCTAB nDestTab);
+    void executeReferencedCutRangesRow(const bool bTransposed, const SCTAB nSrcTab,
+                                       const SCTAB nDestTab, const bool bUndo,
+                                       std::unique_ptr<ScUndoCut>& pUndoCut,
+                                       std::unique_ptr<ScUndoPaste>& pUndoPaste);
+    void checkReferencedCutRangesRowIntitial(const SCTAB nSrcTab, const OUString& rDesc);
+    void checkReferencedCutRangesRow(const SCTAB nSrcTab, const SCTAB nDestTab);
+    void checkReferencedCutTransposedRangesRow(const SCTAB nSrcTab, const SCTAB nDestTab);
+    void executeReferencedCutRangesCol(const bool bTransposed, const SCTAB nSrcTab,
+                                       const SCTAB nDestTab, const bool bUndo,
+                                       std::unique_ptr<ScUndoCut>& pUndoCut,
+                                       std::unique_ptr<ScUndoPaste>& pUndoPaste);
+    void checkReferencedCutRangesColIntitial(const SCTAB nSrcTab, const SCTAB nDestTab,
+                                             const OUString& rDesc);
+    void checkReferencedCutRangesCol(const SCTAB nSrcTab, const SCTAB nDestTab);
+    void checkReferencedCutTransposedRangesColUndo(const SCTAB nSrcTab, const SCTAB nDestTab);
+    void checkReferencedCutTransposedRangesCol(const SCTAB nSrcTab, const SCTAB nDestTab);
+    void prepareUndoBeforePaste(bool bCut, ScDocumentUniquePtr& pPasteUndoDoc,
+                                std::unique_ptr<ScDocument>& pPasteRefUndoDoc,
+                                const ScMarkData& rDestMark, const ScRange& rDestRange,
+                                std::unique_ptr<ScRefUndoData>& pUndoData);
+    void prepareUndoAfterPaste(ScDocumentUniquePtr& pPasteUndoDoc,
+                               std::unique_ptr<ScDocument>& pPasteRefUndoDoc,
+                               const ScMarkData& rDestMark, const ScRange& rDestRange,
+                               std::unique_ptr<ScRefUndoData>& pUndoData,
+                               std::unique_ptr<ScUndoPaste>& pUndoPaste, bool bTranspose = false,
+                               bool bAsLink = false, bool bSkipEmpty = false,
+                               ScPasteFunc nFunction = ScPasteFunc::NONE,
+                               InsCellCmd eMoveMode = InsCellCmd::INS_NONE);
+
+    OUString getFormula(SCCOL nCol, SCROW nRow, SCTAB nTab);
+    OUString getRangeByName(const OUString& aRangeName);
 };
 
 TestCopyPaste::TestCopyPaste() {}
@@ -256,6 +351,101 @@ static ScAddress lcl_getMergeSizeOfCell(const ScDocument& rDoc, SCCOL nCol, SCRO
     return ScAddress(rMerge.GetColMerge(), rMerge.GetRowMerge(), nTab);
 }
 
+static void lcl_printValuesAndFormulasInRange(ScDocument* pDoc, const ScRange& rRange,
+                                              const OString& rCaption)
+{
+    printRange(pDoc, rRange, rCaption, false);
+    printRange(pDoc, rRange, rCaption, true);
+}
+
+OUString TestCopyPaste::getFormula(SCCOL nCol, SCROW nRow, SCTAB nTab)
+{
+    return ::getFormula(m_pDoc, nCol, nRow, nTab);
+}
+
+OUString TestCopyPaste::getRangeByName(const OUString& aRangeName)
+{
+    return ::getRangeByName(m_pDoc, aRangeName);
+}
+
+// Cannot be moved to qahelper since ScDocument::CopyToDocument() is not SC_DLLPUBLIC
+/** Executes the same steps for undo as ScViewFunc::PasteFromClip(). */
+void TestCopyPaste::prepareUndoBeforePaste(bool bCut, ScDocumentUniquePtr& pPasteUndoDoc,
+                                           std::unique_ptr<ScDocument>& pPasteRefUndoDoc,
+                                           const ScMarkData& rDestMark, const ScRange& rDestRange,
+                                           std::unique_ptr<ScRefUndoData>& pUndoData)
+{
+    InsertDeleteFlags nUndoFlags = InsertDeleteFlags::CONTENTS;
+    SCTAB nTabCount = m_pDoc->GetTableCount();
+
+    pPasteUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+    pPasteUndoDoc->InitUndoSelected(*m_pDoc, rDestMark, false, false);
+    // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
+    m_pDoc->CopyToDocument(rDestRange.aStart.Col(), rDestRange.aStart.Row(), 0,
+                           rDestRange.aEnd.Col(), rDestRange.aEnd.Row(), nTabCount - 1, nUndoFlags,
+                           false, *pPasteUndoDoc);
+
+    if (bCut)
+    {
+        // save changed references
+        pPasteRefUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+        pPasteRefUndoDoc->InitUndo(*m_pDoc, 0, nTabCount - 1);
+
+        pUndoData.reset(new ScRefUndoData(m_pDoc));
+    }
+}
+
+// Cannot be moved to qahelper since ScDocument::CopyToDocument() is not SC_DLLPUBLIC
+/** Executes the same steps for undo as ScViewFunc::PasteFromClip(). */
+void TestCopyPaste::prepareUndoAfterPaste(ScDocumentUniquePtr& pPasteUndoDoc,
+                                          std::unique_ptr<ScDocument>& pPasteRefUndoDoc,
+                                          const ScMarkData& rDestMark, const ScRange& rDestRange,
+                                          std::unique_ptr<ScRefUndoData>& pUndoData,
+                                          std::unique_ptr<ScUndoPaste>& pUndoPaste, bool bTranspose,
+                                          bool bAsLink, bool bSkipEmpty, ScPasteFunc nFunction,
+                                          InsCellCmd eMoveMode)
+{
+    InsertDeleteFlags nUndoFlags = InsertDeleteFlags::CONTENTS;
+    SCTAB nTabCount = m_pDoc->GetTableCount();
+
+    ScDocumentUniquePtr pPasteRedoDoc;
+    // copy redo data after appearance of the first undo
+    // don't create Redo-Doc without RefUndoDoc
+
+    if (pPasteRefUndoDoc)
+    {
+        pPasteRedoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+        pPasteRedoDoc->InitUndo(*m_pDoc, rDestRange.aStart.Tab(), rDestRange.aEnd.Tab(), false,
+                                false);
+
+        // move adapted refs to Redo-Doc
+
+        pPasteRedoDoc->AddUndoTab(0, nTabCount - 1);
+        m_pDoc->CopyUpdated(pPasteRefUndoDoc.get(), pPasteRedoDoc.get());
+
+        pPasteUndoDoc->AddUndoTab(0, nTabCount - 1);
+        pPasteRefUndoDoc->DeleteArea(rDestRange.aStart.Col(), rDestRange.aStart.Row(),
+                                     rDestRange.aEnd.Col(), rDestRange.aEnd.Row(), rDestMark,
+                                     InsertDeleteFlags::ALL);
+        pPasteRefUndoDoc->CopyToDocument(0, 0, 0, pPasteUndoDoc->MaxCol(), pPasteUndoDoc->MaxRow(),
+                                         nTabCount - 1, InsertDeleteFlags::FORMULA, false,
+                                         *pPasteUndoDoc);
+        pPasteRefUndoDoc.reset();
+    }
+
+    ScUndoPasteOptions aOptions; // store options for repeat
+    aOptions.nFunction = nFunction;
+    aOptions.bSkipEmpty = bSkipEmpty;
+    aOptions.bTranspose = bTranspose;
+    aOptions.bAsLink = bAsLink;
+    aOptions.eMoveMode = eMoveMode;
+
+    pUndoPaste.reset(new ScUndoPaste(&*m_xDocShell, rDestRange, rDestMark, std::move(pPasteUndoDoc),
+                                     std::move(pPasteRedoDoc), nUndoFlags, std::move(pUndoData),
+                                     false,
+                                     &aOptions)); // false = Redo data not yet copied
+}
+
 void TestCopyPaste::testCopyPaste()
 {
     m_pDoc->InsertTab(0, "Sheet1");
@@ -1029,7 +1219,7 @@ void TestCopyPaste::testCopyPasteSpecialMultiRangeRowAsLinkFilteredTranspose()
     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(&aClipDoc, ScRange(0, 0, 0, 4, 5, 0), "Base doc (&aClipDoc)");
     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.
@@ -1453,17 +1643,36 @@ void TestCopyPaste::testCopyPasteSpecialAllAsLinkFilteredTranspose()
     m_pDoc->DeleteTab(srcSheet);
 }
 
+// Compatibility method since normal copy/paste tests do not test undo
+void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFiltered, bool bAsLink,
+                                            bool bTranspose, bool bMultiRangeSelection,
+                                            bool bSkipEmpty, bool bCut,
+                                            ScClipParam::Direction eDirection, CalcMode eCalcMode,
+                                            InsertDeleteFlags aFlags)
+{
+    std::unique_ptr<ScUndoCut> pUndoCut;
+    std::unique_ptr<ScUndoPaste> pUndoPaste;
+    executeCopyPasteSpecial(0, 1, bApplyFilter, bIncludedFiltered, bAsLink, bTranspose,
+                            bMultiRangeSelection, bSkipEmpty, pUndoCut, pUndoPaste, bCut,
+                            eDirection, eCalcMode, aFlags);
+}
+
 // 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 TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFiltered, bool bAsLink,
+void TestCopyPaste::executeCopyPasteSpecial(const SCTAB srcSheet, const SCTAB destSheet,
+                                            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)
+                                            bool bSkipEmpty, std::unique_ptr<ScUndoCut>& pUndoCut,
+                                            std::unique_ptr<ScUndoPaste>& pUndoPaste, bool bCut,
+                                            ScClipParam::Direction eDirection, CalcMode eCalcMode,
+                                            InsertDeleteFlags aFlags)
 {
-    const SCTAB srcSheet = 0;
+    // turn on/off auto calc
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, eCalcMode == AutoCalc);
+
+    for (int i = 0; i < srcSheet; ++i)
+        m_pDoc->InsertTab(i, "Empty Tab " + OUString::number(i));
+
     m_pDoc->InsertTab(srcSheet, "SrcSheet");
 
     // We need a drawing layer in order to create caption objects.
@@ -1485,6 +1694,10 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
           \______________/      \________________________________________/
              col range 1                     col range 2
 
+    refs to cells (used for cut/paste tests)
+    15   | =B3 | =$B$3    | =$B3 | =B$3| =SUM(B3:B3) | =SUM($B3:$B3) | =SUM($B3:$B3) | =SUM(B$3:B$3) | =SUM($A$1:$A$4) | =SUM($A$1:$A$8) |
+    16   | =Range_B3 | =Range_aBa3    | =Range_aB3 | =Range_Ba3| =SUM(Range_B3_B3) | =SUM(Range_aBa3_aBa3) | =SUM(Range_aB3_aB3) | =SUM(Range_Ba3_Ba3) | =SUM(Range_aAa1_aAa4) | =SUM(Range_aAa1_aAa8) |
+
     * means note attached
     B means background
     b means border
@@ -1607,6 +1820,45 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
     m_pDoc->SetValue(8, 4, srcSheet, 135);
     m_pDoc->SetValue(8, 5, srcSheet, 136);
 
+    // row 14, refs to copied/cut range
+    m_pDoc->SetString(0, 14, srcSheet, "=B3");
+    m_pDoc->SetString(1, 14, srcSheet, "=$B$3");
+    m_pDoc->SetString(2, 14, srcSheet, "=$B3");
+    m_pDoc->SetString(3, 14, srcSheet, "=B$3");
+    m_pDoc->SetString(4, 14, srcSheet, "=SUM(B3:B3)");
+    m_pDoc->SetString(5, 14, srcSheet, "=SUM($B$3:$B$3)");
+    m_pDoc->SetString(6, 14, srcSheet, "=SUM($B3:$B3)");
+    m_pDoc->SetString(7, 14, srcSheet, "=SUM(B$3:B$3)");
+    m_pDoc->SetString(8, 14, srcSheet, "=SUM($A$1:$A$4)");
+    m_pDoc->SetString(9, 14, srcSheet, "=SUM($A$1:$A$8)");
+
+    // Cell position is used for ranges relative to current position
+    ScAddress cellB4(1, 3, srcSheet);
+    ScAddress cellA1(0, 0, srcSheet);
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_B3", cellB4, "$SrcSheet.B3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aBa3", cellA1, "$SrcSheet.$B$3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aB3", cellB4, "$SrcSheet.$B3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_Ba3", cellB4, "$SrcSheet.B$3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_B3_B3", cellB4, "$SrcSheet.B3:B3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aBa3_aBa3", cellA1, "$SrcSheet.$B$3:$B$3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aB3_aB3", cellB4, "$SrcSheet.$B3:$B3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aB3_aB3", cellB4, "$SrcSheet.$B3:$B3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_Ba3_Ba3", cellB4, "$SrcSheet.B$3:B$3"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aAa1_aAa4", cellA1, "$SrcSheet.$A$1:$A$4"));
+    CPPUNIT_ASSERT(m_pDoc->InsertNewRangeName("Range_aAa1_aAa8", cellA1, "$SrcSheet.$A$1:$A$8"));
+
+    // row 15, refs to copied/cut range using range
+    m_pDoc->SetString(0, 15, srcSheet, "=Range_B3");
+    m_pDoc->SetString(1, 15, srcSheet, "=Range_aBa3");
+    m_pDoc->SetString(2, 15, srcSheet, "=Range_aB3");
+    m_pDoc->SetString(3, 15, srcSheet, "=Range_Ba3");
+    m_pDoc->SetString(4, 15, srcSheet, "=SUM(Range_B3_B3)");
+    m_pDoc->SetString(5, 15, srcSheet, "=SUM(Range_aBa3_aBa3)");
+    m_pDoc->SetString(6, 15, srcSheet, "=SUM(Range_aB3_aB3)");
+    m_pDoc->SetString(7, 15, srcSheet, "=SUM(Range_Ba3_Ba3)");
+    m_pDoc->SetString(8, 15, srcSheet, "=SUM(Range_aAa1_aAa4)");
+    m_pDoc->SetString(9, 15, srcSheet, "=SUM(Range_aAa1_aAa8)");
+
     // add patterns
     ScPatternAttr aCellBlueColor(m_pDoc->GetPool());
     aCellBlueColor.GetItemSet().Put(SvxBrushItem(COL_BLUE, ATTR_BACKGROUND));
@@ -1673,48 +1925,48 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
     // add notes row 0
     ScAddress aAdrA1(0, 0, srcSheet);
     ScPostIt* pNoteA1 = m_pDoc->GetOrCreateNote(aAdrA1);
-    pNoteA1->SetText(aAdrA1, "Hello world in A1");
+    pNoteA1->SetText(aAdrA1, "Note A1");
     ScAddress aAdrB1(1, 0, srcSheet);
     ScPostIt* pNoteB1 = m_pDoc->GetOrCreateNote(aAdrB1);
-    pNoteB1->SetText(aAdrB1, "Hello world in B1");
+    pNoteB1->SetText(aAdrB1, "Note B1");
     // No note on C1
     ScAddress aAdrD1(3, 0, srcSheet);
     ScPostIt* pNoteD1 = m_pDoc->GetOrCreateNote(aAdrD1);
-    pNoteD1->SetText(aAdrD1, "Hello world in D1");
+    pNoteD1->SetText(aAdrD1, "Note 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");
+    pNoteA2->SetText(aAdrA2, "Note A2");
     // No note on B2
     ScAddress aAdrC2(2, 1, srcSheet);
     ScPostIt* pNoteC2 = m_pDoc->GetOrCreateNote(aAdrC2);
-    pNoteC2->SetText(aAdrC2, "Hello world in C2");
+    pNoteC2->SetText(aAdrC2, "Note C2");
     ScAddress aAdrD2(3, 1, srcSheet);
     ScPostIt* pNoteD2 = m_pDoc->GetOrCreateNote(aAdrD2);
-    pNoteD2->SetText(aAdrD2, "Hello world in D2");
+    pNoteD2->SetText(aAdrD2, "Note D2");
     ScAddress aAdrE2(4, 2, srcSheet);
     ScPostIt* pNoteE2 = m_pDoc->GetOrCreateNote(aAdrE2);
-    pNoteE2->SetText(aAdrE2, "Hello world in E2");
+    pNoteE2->SetText(aAdrE2, "Note E2");
     ScAddress aAdrF2(5, 1, srcSheet);
     ScPostIt* pNoteF2 = m_pDoc->GetOrCreateNote(aAdrF2);
-    pNoteF2->SetText(aAdrF2, "Hello world in F2");
+    pNoteF2->SetText(aAdrF2, "Note F2");
 
     // add notes row 2
     ScAddress aAdrA3(0, 2, srcSheet);
     ScPostIt* pNoteA3 = m_pDoc->GetOrCreateNote(aAdrA3);
-    pNoteA3->SetText(aAdrA3, "Hello world in A3");
+    pNoteA3->SetText(aAdrA3, "Note A3");
     ScAddress aAdrB3(1, 2, srcSheet);
     ScPostIt* pNoteB3 = m_pDoc->GetOrCreateNote(aAdrB3);
-    pNoteB3->SetText(aAdrB3, "Hello world in B3");
+    pNoteB3->SetText(aAdrB3, "Note B3");
     ScAddress aAdrC3(2, 2, srcSheet);
     ScPostIt* pNoteC3 = m_pDoc->GetOrCreateNote(aAdrC3);
-    pNoteC3->SetText(aAdrC3, "Hello world in C3");
+    pNoteC3->SetText(aAdrC3, "Note C3");
     ScAddress aAdrD3(3, 2, srcSheet);
     ScPostIt* pNoteD3 = m_pDoc->GetOrCreateNote(aAdrD3);
-    pNoteD3->SetText(aAdrD3, "Hello world in D3");
+    pNoteD3->SetText(aAdrD3, "Note D3");
     // No note on E3
     // No note on F3
 
@@ -1722,24 +1974,32 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
     // No note on A4
     ScAddress aAdrB4(1, 3, srcSheet);
     ScPostIt* pNoteB4 = m_pDoc->GetOrCreateNote(aAdrB4);
-    pNoteB4->SetText(aAdrB4, "Hello world in B4");
+    pNoteB4->SetText(aAdrB4, "Note B4");
     ScAddress aAdrC4(2, 3, srcSheet);
     ScPostIt* pNoteC4 = m_pDoc->GetOrCreateNote(aAdrC4);
-    pNoteC4->SetText(aAdrC4, "Hello world in C4");
+    pNoteC4->SetText(aAdrC4, "Note C4");
     ScAddress aAdrD4(3, 3, srcSheet);
     ScPostIt* pNoteD4 = m_pDoc->GetOrCreateNote(aAdrD4);
-    pNoteD4->SetText(aAdrD4, "Hello world in D4");
+    pNoteD4->SetText(aAdrD4, "Note D4");
     ScAddress aAdrE4(4, 3, srcSheet);
     ScPostIt* pNoteE4 = m_pDoc->GetOrCreateNote(aAdrE4);
-    pNoteE4->SetText(aAdrE4, "Hello world in E4");
+    pNoteE4->SetText(aAdrE4, "Note E4");
     ScAddress aAdrF4(5, 3, srcSheet);
     ScPostIt* pNoteF4 = m_pDoc->GetOrCreateNote(aAdrF4);
-    pNoteF4->SetText(aAdrF4, "Hello world in F4");
+    pNoteF4->SetText(aAdrF4, "Note 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");
+    pNoteC5->SetText(aAdrC5, "Note C5");
+
+    // Recalc if needed
+    if (bMultiRangeSelection && bTranspose && eDirection == ScClipParam::Row
+        && eCalcMode == RecalcAtEnd)
+        m_pDoc->CalcFormulaTree();
+    else if (bMultiRangeSelection && bTranspose && eDirection == ScClipParam::Row
+             && eCalcMode == HardRecalcAtEnd)
+        m_pDoc->CalcAll();
 
     // Filter out row 1
     if (bApplyFilter)
@@ -1782,44 +2042,140 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
     }
 
     // create destination sheet
-    const SCTAB destSheet = 1;
-    m_pDoc->InsertTab(destSheet, "DestSheet");
+    // const SCTAB destSheet = 1;
+    for (int i = srcSheet + 1; i < destSheet; ++i)
+        m_pDoc->InsertTab(i, "Empty Tab " + OUString::number(i));
+
+    if (srcSheet != destSheet)
+        m_pDoc->InsertTab(destSheet, "DestSheet");
+
+    m_pDoc->SetString(3, 101, srcSheet, "=DestSheet.D1");
+    m_pDoc->SetString(3, 102, srcSheet, "=DestSheet.D2");
+    m_pDoc->SetString(3, 103, srcSheet, "=DestSheet.D3");
+    m_pDoc->SetString(3, 104, srcSheet, "=DestSheet.D4");
+    m_pDoc->SetString(3, 105, srcSheet, "=DestSheet.D5");
+    m_pDoc->SetString(3, 106, srcSheet, "=DestSheet.D6");
+    m_pDoc->SetString(3, 107, srcSheet, "=DestSheet.D7");
+    m_pDoc->SetString(4, 101, srcSheet, "=DestSheet.E1");
+    m_pDoc->SetString(4, 102, srcSheet, "=DestSheet.E2");
+    m_pDoc->SetString(4, 103, srcSheet, "=DestSheet.E3");
+    m_pDoc->SetString(4, 104, srcSheet, "=DestSheet.E4");
+    m_pDoc->SetString(4, 105, srcSheet, "=DestSheet.E5");
+    m_pDoc->SetString(4, 106, srcSheet, "=DestSheet.E6");
+    m_pDoc->SetString(4, 107, srcSheet, "=DestSheet.E7");
+    m_pDoc->SetString(5, 101, srcSheet, "=DestSheet.F1");
+    m_pDoc->SetString(5, 102, srcSheet, "=DestSheet.F2");
+    m_pDoc->SetString(5, 103, srcSheet, "=DestSheet.F3");
+    m_pDoc->SetString(5, 104, srcSheet, "=DestSheet.F4");
+    m_pDoc->SetString(5, 105, srcSheet, "=DestSheet.F5");
+    m_pDoc->SetString(5, 106, srcSheet, "=DestSheet.F6");
+    m_pDoc->SetString(5, 107, srcSheet, "=DestSheet.F7");
+    m_pDoc->SetString(6, 101, srcSheet, "=DestSheet.G1");
+    m_pDoc->SetString(6, 102, srcSheet, "=DestSheet.G2");
+    m_pDoc->SetString(6, 103, srcSheet, "=DestSheet.G3");
+    m_pDoc->SetString(6, 104, srcSheet, "=DestSheet.G4");
+    m_pDoc->SetString(6, 105, srcSheet, "=DestSheet.G5");
+    m_pDoc->SetString(6, 106, srcSheet, "=DestSheet.G6");
+    m_pDoc->SetString(6, 107, srcSheet, "=DestSheet.G7");
+    m_pDoc->SetString(7, 101, srcSheet, "=DestSheet.H1");
+    m_pDoc->SetString(7, 102, srcSheet, "=DestSheet.H2");
+    m_pDoc->SetString(7, 103, srcSheet, "=DestSheet.H3");
+    m_pDoc->SetString(7, 104, srcSheet, "=DestSheet.H4");
+    m_pDoc->SetString(7, 105, srcSheet, "=DestSheet.H5");
+    m_pDoc->SetString(7, 106, srcSheet, "=DestSheet.H6");
+    m_pDoc->SetString(7, 107, srcSheet, "=DestSheet.H7");
+    m_pDoc->SetString(8, 101, srcSheet, "=DestSheet.I1");
+    m_pDoc->SetString(8, 102, srcSheet, "=DestSheet.I2");
+    m_pDoc->SetString(8, 103, srcSheet, "=DestSheet.I3");
+    m_pDoc->SetString(8, 104, srcSheet, "=DestSheet.I4");
+    m_pDoc->SetString(8, 105, srcSheet, "=DestSheet.I5");
+    m_pDoc->SetString(8, 106, srcSheet, "=DestSheet.I6");
+    m_pDoc->SetString(8, 107, srcSheet, "=DestSheet.I7");
+    m_pDoc->SetString(9, 101, srcSheet, "=DestSheet.J1");
+    m_pDoc->SetString(9, 102, srcSheet, "=DestSheet.J2");
+    m_pDoc->SetString(9, 103, srcSheet, "=DestSheet.J3");
+    m_pDoc->SetString(9, 104, srcSheet, "=DestSheet.J4");
+    m_pDoc->SetString(9, 105, srcSheet, "=DestSheet.J5");
+    m_pDoc->SetString(9, 106, srcSheet, "=DestSheet.J6");
+    m_pDoc->SetString(9, 107, srcSheet, "=DestSheet.J7");
+
+    // Check precondition
+    checkCopyPasteSpecialInitial(srcSheet);
+
     // 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);
+    ScDocument aClipDoc(SCDOCMODE_CLIP);
     ScMarkData aDestMark(m_pDoc->GetSheetLimits());
+    ScRange aDestRange;
+
+    ScDocumentUniquePtr pPasteUndoDoc;
+    std::unique_ptr<ScDocument> pPasteRefUndoDoc;
+    std::unique_ptr<ScRefUndoData> pUndoData;
+
     if (!bMultiRangeSelection)
     {
         ScRange aSrcRange(0, 0, srcSheet, nSrcCols - 1, nSrcRows - 1, srcSheet);
-        copyToClip(m_pDoc, aSrcRange, &aNewClipDoc);
+        printRange(m_pDoc, aSrcRange, "Src range");
+        if (!bCut)
+            copyToClip(m_pDoc, aSrcRange, &aClipDoc);
+        else
+        {
+            pUndoCut.reset(cutToClip(*m_xDocShell, aSrcRange, &aClipDoc, true));
+        }
+
+        printRange(&aClipDoc, ScRange(0, 0, srcSheet, nSrcCols, nSrcRows, srcSheet),
+                   "Base doc (&aClipDoc)");
 
         // ScDocument::TransposeClip() and ScDocument::CopyFromClip() calls
         // analog to ScViewFunc::PasteFromClip()
         if (bTranspose)
         {
+            ScDocument* pOrigClipDoc = &aClipDoc;
             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
+            aClipDoc.TransposeClip(pTransClip.get(), aFlags, bAsLink, bIncludedFiltered);
+            aDestRange = ScRange(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);
+            printRange(pTransClip.get(), ScRange(0, 0, srcSheet, nSrcCols, nSrcRows, srcSheet),
+                       "Transposed clipdoc (pTransClip.get())");
+
+            if (bCut)
+                prepareUndoBeforePaste(bCut, pPasteUndoDoc, pPasteRefUndoDoc, aDestMark, aDestRange,
+                                       pUndoData);
+
+            m_pDoc->CopyFromClip(aDestRange, aDestMark, aFlags, pPasteRefUndoDoc.get(),
+                                 pTransClip.get(), true, bAsLink, bIncludedFiltered, bSkipEmpty);
+            printRange(m_pDoc, aDestRange, "Transposed dest sheet");
+            if (bCut)
+            {
+                m_pDoc->UpdateTranspose(aDestRange.aStart, pOrigClipDoc, aDestMark,
+                                        pPasteRefUndoDoc.get());
+                printRange(m_pDoc, aDestRange, "Transposed dest sheet after UpdateTranspose()");
+            }
             pTransClip.reset();
         }
         else
         {
-            ScRange aDestRange(3, 1, destSheet, 3 + nSrcCols - 1, 1 + nSrcRows - 1,
-                               destSheet); //target: D2:I5
+            aDestRange = ScRange(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);
+            if (bCut)
+                prepareUndoBeforePaste(bCut, pPasteUndoDoc, pPasteRefUndoDoc, aDestMark, aDestRange,
+                                       pUndoData);
+
+            m_pDoc->CopyFromClip(aDestRange, aDestMark, aFlags, pPasteRefUndoDoc.get(), &aClipDoc,
+                                 true, bAsLink, bIncludedFiltered, bSkipEmpty);
         }
+
+        if (bCut)
+            prepareUndoAfterPaste(pPasteUndoDoc, pPasteRefUndoDoc, aDestMark, aDestRange, pUndoData,
+                                  pUndoPaste, bTranspose, bAsLink, bSkipEmpty);
     }
-    else
+    else // multi range selection
     {
         ScMarkData aSrcMark(m_pDoc->GetSheetLimits());
         aSrcMark.SelectOneTable(0);
@@ -1838,7 +2194,7 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
             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);
+        m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aSrcMark, false, false);
 
         // ScDocument::TransposeClip() and ScDocument::CopyMultiRangeFromClip() calls
         // analog to ScViewFunc::PasteFromClipToMultiRanges()
@@ -1846,14 +2202,14 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
         {
             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
+            aClipDoc.TransposeClip(pTransClip.get(), aFlags, bAsLink, bIncludedFiltered);
+            aDestRange = ScRange(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())");
+            printRange(&aClipDoc, ScRange(0, 0, srcSheet, nSrcCols, nSrcRows, srcSheet),
+                       "Base doc (&aClipDoc)");
+            printRange(pTransClip.get(), ScRange(0, 0, srcSheet, nSrcCols, nSrcRows, srcSheet),
+                       "Transposed clipdoc (pTransClip.get())");
             m_pDoc->CopyMultiRangeFromClip(ScAddress(3, 1, destSheet), aDestMark, aFlags,
                                            pTransClip.get(), true, bAsLink && !bTranspose,
                                            bIncludedFiltered, bSkipEmpty);
@@ -1862,15 +2218,18 @@ void TestCopyPaste::executeCopyPasteSpecial(bool bApplyFilter, bool bIncludedFil
         }
         else
         {
-            ScRange aDestRange(3, 1, destSheet, 3 + nSrcCols - 1 - 1, 1 + nSrcRows - 1,
-                               destSheet); //target col: D2:I5, target row: D2:I6
+            aDestRange = ScRange(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);
+            m_pDoc->CopyMultiRangeFromClip(ScAddress(3, 1, destSheet), aDestMark, aFlags, &aClipDoc,
+                                           true, bAsLink && !bTranspose, bIncludedFiltered,
+                                           bSkipEmpty);
         }
     }
-    if (bCalcAll)
+
+    if (eCalcMode == RecalcAtEnd)
+        m_pDoc->CalcFormulaTree();
+    else if (eCalcMode == HardRecalcAtEnd)
         m_pDoc->CalcAll();
 }
 
@@ -1924,21 +2283,21 @@ void TestCopyPaste::testCopyPasteSpecialTransposeIncludeFiltered()
 
 void TestCopyPaste::testCopyPasteSpecialMultiRangeCol()
 {
-    executeCopyPasteSpecial(false, false, false, false, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(false, false, false, false, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeCol(false);
 }
 
 void TestCopyPaste::testCopyPasteSpecialMultiRangeColIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(false, true, false, false, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(false, true, false, false, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeCol(false);
 }
 
 // tdf#45958
 void TestCopyPaste::testCopyPasteSpecialMultiRangeColFiltered()
 {
-    executeCopyPasteSpecial(true, false, false, false, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(true, false, false, false, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColFiltered(false);
 }
 
@@ -1946,20 +2305,20 @@ void TestCopyPaste::testCopyPasteSpecialMultiRangeColFiltered()
 void TestCopyPaste::testCopyPasteSpecialMultiRangeColFilteredIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, false, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(true, true, false, false, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeCol(false);
 }
 
 void TestCopyPaste::testCopyPasteSpecialMultiRangeColTranspose()
 {
-    executeCopyPasteSpecial(false, false, false, true, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(false, false, false, true, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColTranspose(false);
 }
 
 // tdf#45958, tdf#107348
 void TestCopyPaste::testCopyPasteSpecialMultiRangeColFilteredTranspose()
 {
-    executeCopyPasteSpecial(true, false, false, true, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(true, false, false, true, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColFilteredTranspose(false);
 }
 
@@ -1967,27 +2326,27 @@ void TestCopyPaste::testCopyPasteSpecialMultiRangeColFilteredTranspose()
 void TestCopyPaste::testCopyPasteSpecialMultiRangeColFilteredIncludeFilteredTranspose()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, true, true, false, ScClipParam::Column);
+    executeCopyPasteSpecial(true, true, false, true, true, false, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColTranspose(false);
 }
 
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRow()
 {
-    executeCopyPasteSpecial(false, false, false, false, true, false, ScClipParam::Row);
+    executeCopyPasteSpecial(false, false, false, false, true, false, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRow(false);
 }
 
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRowIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(false, true, false, false, true, false, ScClipParam::Row);
+    executeCopyPasteSpecial(false, true, false, false, true, false, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRow(false);
 }
 
 // tdf#45958
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRowFiltered()
 {
-    executeCopyPasteSpecial(true, false, false, false, true, false, ScClipParam::Row);
+    executeCopyPasteSpecial(true, false, false, false, true, false, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRowFiltered(false);
 }
 
@@ -1995,20 +2354,22 @@ void TestCopyPaste::testCopyPasteSpecialMultiRangeRowFiltered()
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRowFilteredIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, false, true, false, ScClipParam::Row);
+    executeCopyPasteSpecial(true, true, false, false, true, false, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRow(false);
 }
 
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRowTranspose()
 {
-    executeCopyPasteSpecial(false, false, false, true, true, false, ScClipParam::Row, true);
+    executeCopyPasteSpecial(false, false, false, true, true, false, false, ScClipParam::Row,
+                            HardRecalcAtEnd);
     checkCopyPasteSpecialMultiRangeRowTranspose(false);
 }
 
 // tdf#45958, tdf#107348
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRowFilteredTranspose()
 {
-    executeCopyPasteSpecial(true, false, false, true, true, false, ScClipParam::Row, true);
+    executeCopyPasteSpecial(true, false, false, true, true, false, false, ScClipParam::Row,
+                            HardRecalcAtEnd);
     checkCopyPasteSpecialMultiRangeRowFilteredTranspose(false);
 }
 
@@ -2016,7 +2377,8 @@ void TestCopyPaste::testCopyPasteSpecialMultiRangeRowFilteredTranspose()
 void TestCopyPaste::testCopyPasteSpecialMultiRangeRowFilteredIncludeFilteredTranspose()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, true, true, false, ScClipParam::Row, true);
+    executeCopyPasteSpecial(true, true, false, true, true, false, false, ScClipParam::Row,
+                            HardRecalcAtEnd);
     checkCopyPasteSpecialMultiRangeRowTranspose(false);
 }
 
@@ -2070,21 +2432,21 @@ void TestCopyPaste::testCopyPasteSpecialSkipEmptyTransposeIncludeFiltered()
 
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeCol()
 {
-    executeCopyPasteSpecial(false, false, false, false, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(false, false, false, false, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeCol(true);
 }
 
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(false, true, false, false, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(false, true, false, false, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeCol(true);
 }
 
 // tdf#45958
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColFiltered()
 {
-    executeCopyPasteSpecial(true, false, false, false, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(true, false, false, false, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColFiltered(true);
 }
 
@@ -2092,13 +2454,13 @@ void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColFiltered()
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, false, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(true, true, false, false, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeCol(true);
 }
 
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColTranspose()
 {
-    executeCopyPasteSpecial(false, false, false, true, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(false, false, false, true, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColTranspose(true);
 }
 
@@ -2106,7 +2468,7 @@ void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColTranspose()
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredTranspose()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, false, false, true, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(true, false, false, true, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColFilteredTranspose(true);
 }
 
@@ -2114,27 +2476,27 @@ void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredTranspose(
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeColFilteredIncludeFilteredTranspose()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, true, true, true, ScClipParam::Column);
+    executeCopyPasteSpecial(true, true, false, true, true, true, false, ScClipParam::Column);
     checkCopyPasteSpecialMultiRangeColTranspose(true);
 }
 
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRow()
 {
-    executeCopyPasteSpecial(false, false, false, false, true, true, ScClipParam::Row);
+    executeCopyPasteSpecial(false, false, false, false, true, true, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRow(true);
 }
 
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(false, true, false, false, true, true, ScClipParam::Row);
+    executeCopyPasteSpecial(false, true, false, false, true, true, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRow(true);
 }
 
 // tdf#45958
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowFiltered()
 {
-    executeCopyPasteSpecial(true, false, false, false, true, true, ScClipParam::Row);
+    executeCopyPasteSpecial(true, false, false, false, true, true, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRowFiltered(true);
 }
 
@@ -2142,20 +2504,22 @@ void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowFiltered()
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFiltered()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, false, true, true, ScClipParam::Row);
+    executeCopyPasteSpecial(true, true, false, false, true, true, false, ScClipParam::Row);
     checkCopyPasteSpecialMultiRangeRow(true);
 }
 
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowTranspose()
 {
-    executeCopyPasteSpecial(false, false, false, true, true, true, ScClipParam::Row, true);
+    executeCopyPasteSpecial(false, false, false, true, true, true, false, ScClipParam::Row,
+                            HardRecalcAtEnd);
     checkCopyPasteSpecialMultiRangeRowTranspose(true);
 }
 
 // tdf#45958, tdf#107348
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredTranspose()
 {
-    executeCopyPasteSpecial(true, false, false, true, true, true, ScClipParam::Row, true);
+    executeCopyPasteSpecial(true, false, false, true, true, true, false, ScClipParam::Row,
+                            HardRecalcAtEnd);
     checkCopyPasteSpecialMultiRangeRowFilteredTranspose(true);
 }
 
@@ -2163,12 +2527,415 @@ void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredTranspose(
 void TestCopyPaste::testCopyPasteSpecialSkipEmptyMultiRangeRowFilteredIncludeFilteredTranspose()
 {
     // For bIncludeFiltered=true, the non-filtered outcome is expected
-    executeCopyPasteSpecial(true, true, false, true, true, true, ScClipParam::Row, true);
+    executeCopyPasteSpecial(true, true, false, true, true, true, false, ScClipParam::Row,
+                            HardRecalcAtEnd);
     checkCopyPasteSpecialMultiRangeRowTranspose(true);
 }
 
+void TestCopyPaste::testCutPasteSpecial()
+{
+    const SCTAB srcSheet = 0;
+    const SCTAB destSheet = 1;
+    std::unique_ptr<ScUndoCut> pUndoCut;
+    std::unique_ptr<ScUndoPaste> pUndoPaste;
+
+    executeCopyPasteSpecial(srcSheet, destSheet, false, true, false, false, false, false, pUndoCut,
+                            pUndoPaste, true);
+    checkCopyPasteSpecial(false, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoCut->Redo();
+    pUndoPaste->Redo();
+    checkCopyPasteSpecial(false, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoPaste.reset();
+    pUndoCut.reset();
+
+    for (int i = m_pDoc->GetTableCount(); i > 0; --i)
+        m_pDoc->DeleteTab(i - 1);
+}
+
+void TestCopyPaste::testCutPasteSpecialTranspose()
+{
+    const SCTAB srcSheet = 0;
+    const SCTAB destSheet = 1;
+    std::unique_ptr<ScUndoCut> pUndoCut;
+    std::unique_ptr<ScUndoPaste> pUndoPaste;
+
+    executeCopyPasteSpecial(srcSheet, destSheet, false, true, false, true, false, false, pUndoCut,
+                            pUndoPaste, true);
+    checkCopyPasteSpecialTranspose(false, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoCut->Redo();
+    pUndoPaste->Redo();
+    checkCopyPasteSpecialTranspose(false, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoPaste.reset();
+    pUndoCut.reset();
+
+    for (int i = m_pDoc->GetTableCount(); i > 0; --i)
+        m_pDoc->DeleteTab(i - 1);
+}
+
+void TestCopyPaste::testCutPasteSpecialSkipEmpty()
+{
+    const SCTAB srcSheet = 0;
+    const SCTAB destSheet = 1;
+    std::unique_ptr<ScUndoCut> pUndoCut;
+    std::unique_ptr<ScUndoPaste> pUndoPaste;
+
+    executeCopyPasteSpecial(srcSheet, destSheet, false, true, false, false, false, true, pUndoCut,
+                            pUndoPaste, true);
+    checkCopyPasteSpecial(true, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoCut->Redo();
+    pUndoPaste->Redo();
+    checkCopyPasteSpecial(true, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoPaste.reset();
+    pUndoCut.reset();
+
+    for (int i = m_pDoc->GetTableCount(); i > 0; --i)
+        m_pDoc->DeleteTab(i - 1);
+}
+
+void TestCopyPaste::testCutPasteSpecialSkipEmptyTranspose()
+{
+    const SCTAB srcSheet = 0;
+    const SCTAB destSheet = 1;
+    std::unique_ptr<ScUndoCut> pUndoCut;
+    std::unique_ptr<ScUndoPaste> pUndoPaste;
+
+    executeCopyPasteSpecial(srcSheet, destSheet, false, true, false, true, false, true, pUndoCut,
+                            pUndoPaste, true);
+    checkCopyPasteSpecialTranspose(true, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoCut->Redo();
+    pUndoPaste->Redo();
+    checkCopyPasteSpecialTranspose(true, true);
+
+    pUndoPaste->Undo();
+    pUndoCut->Undo();
+    checkCopyPasteSpecialInitial(srcSheet);
+
+    pUndoPaste.reset();
+    pUndoCut.reset();
+
+    for (int i = m_pDoc->GetTableCount(); i > 0; --i)
+        m_pDoc->DeleteTab(i - 1);
+}
+
+// check initial source
+void TestCopyPaste::checkCopyPasteSpecialInitial(const SCTAB srcSheet)
+{
+    OUString aString;
+    double fValue;
+    const EditTextObject* pEditObj;
+    // col 0
+    ASSERT_DOUBLES_EQUAL(1, m_pDoc->GetValue(0, 0, srcSheet));
+    ASSERT_DOUBLES_EQUAL(2, m_pDoc->GetValue(0, 1, srcSheet));
+    ASSERT_DOUBLES_EQUAL(3, m_pDoc->GetValue(0, 2, srcSheet));
+    ASSERT_DOUBLES_EQUAL(4, m_pDoc->GetValue(0, 3, srcSheet));
+    // col 1, formulas
+    ASSERT_DOUBLES_EQUAL(11, m_pDoc->GetValue(1, 0, srcSheet));
+    m_pDoc->GetFormula(1, 0, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=A1+10"), aString);
+    m_pDoc->GetFormula(1, 1, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=A2+20"), aString);
+    ASSERT_DOUBLES_EQUAL(22, m_pDoc->GetValue(1, 1, srcSheet));
+    ASSERT_DOUBLES_EQUAL(35, m_pDoc->GetValue(1, 2, srcSheet));
+    m_pDoc->GetFormula(1, 2, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=D3+30"), aString);
+    ASSERT_DOUBLES_EQUAL(42, m_pDoc->GetValue(1, 3, srcSheet));
+    m_pDoc->GetFormula(1, 3, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=A2+40"), aString);
+    // col 2, strings
+    aString = m_pDoc->GetString(2, 0, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(OUString("a"), aString);
+    aString = m_pDoc->GetString(2, 1, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(OUString("b"), aString);
+    aString = m_pDoc->GetString(2, 2, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(OUString("c"), aString);
+    aString = m_pDoc->GetString(2, 3, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(OUString("d"), aString);
+    // col 3, rich text
+    pEditObj = m_pDoc->GetEditText(ScAddress(3, 0, srcSheet));
+    CPPUNIT_ASSERT(pEditObj);
+    CPPUNIT_ASSERT_EQUAL(OUString("R1"), pEditObj->GetText(0));
+    pEditObj = m_pDoc->GetEditText(ScAddress(3, 1, srcSheet));
+    CPPUNIT_ASSERT(pEditObj);
+    CPPUNIT_ASSERT_EQUAL(OUString("R2"), pEditObj->GetText(0));
+    ASSERT_DOUBLES_EQUAL(5, m_pDoc->GetValue(3, 2, srcSheet));
+    pEditObj = m_pDoc->GetEditText(ScAddress(3, 3, srcSheet));
+    CPPUNIT_ASSERT(pEditObj);
+    CPPUNIT_ASSERT_EQUAL(OUString("R4"), pEditObj->GetText(0));
+    // col 4, formulas
+    m_pDoc->GetFormula(4, 0, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=A1+A3+60"), aString);
+    ASSERT_DOUBLES_EQUAL(64, m_pDoc->GetValue(4, 0, srcSheet));
+    aString = m_pDoc->GetString(4, 1, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString);
+    aString = m_pDoc->GetString(4, 2, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString);
+    fValue = m_pDoc->GetValue(4, 3, srcSheet);
+    m_pDoc->GetFormula(4, 3, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=A1+A3+70"), aString);
+    ASSERT_DOUBLES_EQUAL(74, fValue);
+    // col 5, formulas
+    m_pDoc->GetFormula(5, 0, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUMIF(A1:A4;\"<4\")"), aString);
+    ASSERT_DOUBLES_EQUAL(6, m_pDoc->GetValue(5, 0, srcSheet));
+    aString = m_pDoc->GetString(5, 1, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString);
+    aString = m_pDoc->GetString(5, 2, srcSheet);
+    CPPUNIT_ASSERT_EQUAL(EMPTY_OUSTRING, aString);
+    fValue = m_pDoc->GetValue(5, 3, srcSheet);
+    m_pDoc->GetFormula(5, 3, srcSheet, aString);
+    CPPUNIT_ASSERT_EQUAL(OUString("=B$1+$A$3+80"), aString);
+    ASSERT_DOUBLES_EQUAL(94, fValue);
+
+    // check patterns
+    const SfxPoolItem* pItem = nullptr;
+    m_pDoc->GetPattern(ScAddress(0, 0, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem);
+    CPPUNIT_ASSERT(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(pItem);
+    CPPUNIT_ASSERT_EQUAL(COL_BLUE, static_cast<const SvxBrushItem*>(pItem)->GetColor());
+    m_pDoc->GetPattern(ScAddress(0, 2, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &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(!pItem);
+    m_pDoc->GetPattern(ScAddress(0, 4, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem);
+    CPPUNIT_ASSERT(!pItem);
+    m_pDoc->GetPattern(ScAddress(4, 2, srcSheet))->GetItemSet().HasItem(ATTR_BACKGROUND, &pItem);
+    CPPUNIT_ASSERT(pItem);
+    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(1, 0, srcSheet), 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(1, 1, srcSheet), 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(1, 2, srcSheet), 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(1, 3, srcSheet), 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(1, 4, srcSheet), 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(0, 0, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(1, 0, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(2, 0, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 0, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 0, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 0, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 0, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(0, 1, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(1, 1, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(2, 1, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 1, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 1, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 1, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 1, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(0, 2, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(1, 2, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(2, 2, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 2, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 2, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 2, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 2, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(0, 3, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(1, 3, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(2, 3, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(3, 3, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(4, 3, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(5, 3, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 3, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(0, 4, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(1, 4, srcSheet)));
+    CPPUNIT_ASSERT(m_pDoc->HasNote(ScAddress(2, 4, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(3, 4, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(4, 4, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(5, 4, srcSheet)));
+    CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(6, 4, srcSheet)));
+
+    // check values of notes
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A1"),
+                         m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A2"),
+                         m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A3"),
+                         m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note B1"),
+                         m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note B3"),
+                         m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note C2"),
+                         m_pDoc->GetNote(ScAddress(2, 1, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note C3"),
+                         m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D1"),
+                         m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D2"),
+                         m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D3"),
+                         m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note E2"),
+                         m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note E4"),
+                         m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note F2"),
+                         m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText());
+    CPPUNIT_ASSERT_EQUAL(OUString("Note F4"),
+                         m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText());
+
+    CPPUNIT_ASSERT_EQUAL(OUString("=B3"), getFormula(0, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=$B$3"), getFormula(1, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=$B3"), getFormula(2, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=B$3"), getFormula(3, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(B3:B3)"), getFormula(4, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM($B$3:$B$3)"), getFormula(5, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM($B3:$B3)"), getFormula(6, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(B$3:B$3)"), getFormula(7, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$4)"), getFormula(8, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$8)"), getFormula(9, 14, srcSheet));
+
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(0, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(1, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(2, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(3, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(4, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(5, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(6, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(7, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(8, 14, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(-17.0, m_pDoc->GetValue(9, 14, srcSheet));
+
+    CPPUNIT_ASSERT_EQUAL(OUString("=Range_B3"), getFormula(0, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=Range_aBa3"), getFormula(1, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=Range_aB3"), getFormula(2, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=Range_Ba3"), getFormula(3, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_B3_B3)"), getFormula(4, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aBa3_aBa3)"), getFormula(5, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aB3_aB3)"), getFormula(6, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_Ba3_Ba3)"), getFormula(7, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aAa1_aAa4)"), getFormula(8, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aAa1_aAa8)"), getFormula(9, 15, srcSheet));
+
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(0, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(1, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(2, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(3, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(4, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(5, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(6, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(123.0, m_pDoc->GetValue(7, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(8, 15, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(-17.0, m_pDoc->GetValue(9, 15, srcSheet));
+
+    // Existing references to the destination range must not change
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D1"), getFormula(3, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D2"), getFormula(3, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D3"), getFormula(3, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D4"), getFormula(3, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D5"), getFormula(3, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D6"), getFormula(3, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D7"), getFormula(3, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E1"), getFormula(4, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E2"), getFormula(4, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E3"), getFormula(4, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E4"), getFormula(4, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E5"), getFormula(4, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E6"), getFormula(4, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E7"), getFormula(4, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F1"), getFormula(5, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F2"), getFormula(5, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F3"), getFormula(5, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F4"), getFormula(5, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F5"), getFormula(5, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F6"), getFormula(5, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F7"), getFormula(5, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G1"), getFormula(6, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G2"), getFormula(6, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G3"), getFormula(6, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G4"), getFormula(6, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G5"), getFormula(6, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G6"), getFormula(6, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G7"), getFormula(6, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H1"), getFormula(7, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H2"), getFormula(7, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H3"), getFormula(7, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H4"), getFormula(7, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H5"), getFormula(7, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H6"), getFormula(7, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H7"), getFormula(7, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I1"), getFormula(8, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I2"), getFormula(8, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I3"), getFormula(8, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I4"), getFormula(8, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I5"), getFormula(8, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I6"), getFormula(8, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I7"), getFormula(8, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J1"), getFormula(9, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J2"), getFormula(9, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J3"), getFormula(9, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J4"), getFormula(9, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J5"), getFormula(9, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J6"), getFormula(9, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J7"), getFormula(9, 107, srcSheet));
+}
+
 // Base check, nothing filtered, nothing transposed
-void TestCopyPaste::checkCopyPasteSpecial(bool bSkipEmpty)
+void TestCopyPaste::checkCopyPasteSpecial(bool bSkipEmpty, bool bCut)
 {
     const SCTAB srcSheet = 0;
     const SCTAB destSheet = 1;
@@ -2297,8 +3064,16 @@ void TestCopyPaste::checkCopyPasteSpecial(bool bSkipEmpty)
     }
     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);
+    if (!bCut)
+    {
+        CPPUNIT_ASSERT_EQUAL(OUString("=E$1+$A$3+80"), aString);
+        ASSERT_DOUBLES_EQUAL(2080, fValue);
+    }
+    else
+    {
+        CPPUNIT_ASSERT_EQUAL(OUString("=E$2+$D$4+80"), aString);
+        ASSERT_DOUBLES_EQUAL(94, fValue);
+    }
     ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(8, 5, destSheet));
     aString = m_pDoc->GetString(8, 5, destSheet);
     CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString);
@@ -2412,39 +3187,184 @@ void TestCopyPaste::checkCopyPasteSpecial(bool bSkipEmpty)
     CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 5, destSheet)));
 
     // check values of notes
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A1"),
                          m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 1, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A2"),
                          m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A3"),
                          m_pDoc->GetNote(ScAddress(3, 3, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note B1"),
                          m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note B3"),
                          m_pDoc->GetNote(ScAddress(4, 3, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 1, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note C2"),
                          m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note C3"),
                          m_pDoc->GetNote(ScAddress(5, 3, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D1"),
                          m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 1, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D2"),
                          m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D3"),
                          m_pDoc->GetNote(ScAddress(6, 3, destSheet))->GetText());
     if (!bSkipEmpty)
-        CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(),
+        CPPUNIT_ASSERT_EQUAL(OUString("Note E2"),
                              m_pDoc->GetNote(ScAddress(7, 3, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note E4"),
                          m_pDoc->GetNote(ScAddress(7, 4, destSheet))->GetText());
     if (!bSkipEmpty)
-        CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 1, srcSheet))->GetText(),
+        CPPUNIT_ASSERT_EQUAL(OUString("Note F2"),
                              m_pDoc->GetNote(ScAddress(8, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note F4"),
                          m_pDoc->GetNote(ScAddress(8, 4, destSheet))->GetText());
 
-    m_pDoc->DeleteTab(destSheet);
-    m_pDoc->DeleteTab(srcSheet);
+    // Existing references to the destination range must not change
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D1"), getFormula(3, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D2"), getFormula(3, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D3"), getFormula(3, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D4"), getFormula(3, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D5"), getFormula(3, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D6"), getFormula(3, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.D7"), getFormula(3, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E1"), getFormula(4, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E2"), getFormula(4, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E3"), getFormula(4, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E4"), getFormula(4, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E5"), getFormula(4, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E6"), getFormula(4, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E7"), getFormula(4, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F1"), getFormula(5, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F2"), getFormula(5, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F3"), getFormula(5, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F4"), getFormula(5, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F5"), getFormula(5, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F6"), getFormula(5, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.F7"), getFormula(5, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G1"), getFormula(6, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G2"), getFormula(6, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G3"), getFormula(6, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G4"), getFormula(6, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G5"), getFormula(6, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G6"), getFormula(6, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.G7"), getFormula(6, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H1"), getFormula(7, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H2"), getFormula(7, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H3"), getFormula(7, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H4"), getFormula(7, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H5"), getFormula(7, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H6"), getFormula(7, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.H7"), getFormula(7, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I1"), getFormula(8, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I2"), getFormula(8, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I3"), getFormula(8, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I4"), getFormula(8, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I5"), getFormula(8, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I6"), getFormula(8, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.I7"), getFormula(8, 107, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J1"), getFormula(9, 101, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J2"), getFormula(9, 102, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J3"), getFormula(9, 103, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J4"), getFormula(9, 104, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J5"), getFormula(9, 105, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J6"), getFormula(9, 106, srcSheet));
+    CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.J7"), getFormula(9, 107, srcSheet));
+
+    // row 14 on src sheet, refs to copied/cut range
+    if (!bCut)
+    {
+        CPPUNIT_ASSERT_EQUAL(OUString("=B3"), getFormula(0, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=$B$3"), getFormula(1, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=$B3"), getFormula(2, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=B$3"), getFormula(3, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(B3:B3)"), getFormula(4, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($B$3:$B$3)"), getFormula(5, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($B3:$B3)"), getFormula(6, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(B$3:B$3)"), getFormula(7, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$4)"), getFormula(8, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$8)"), getFormula(9, 14, srcSheet));
+
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(0, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(1, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(2, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(3, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(4, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(5, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(6, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(7, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(8, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(-17.0, m_pDoc->GetValue(9, 14, srcSheet));
+
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_B3"), getFormula(0, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_aBa3"), getFormula(1, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_aB3"), getFormula(2, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_Ba3"), getFormula(3, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_B3_B3)"), getFormula(4, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aBa3_aBa3)"), getFormula(5, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aB3_aB3)"), getFormula(6, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_Ba3_Ba3)"), getFormula(7, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aAa1_aAa4)"), getFormula(8, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aAa1_aAa8)"), getFormula(9, 15, srcSheet));
+
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(0, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(1, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(2, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(3, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(4, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(5, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(6, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(123.0, m_pDoc->GetValue(7, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(8, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(-17.0, m_pDoc->GetValue(9, 15, srcSheet));
+
+        m_pDoc->DeleteTab(destSheet);
+        m_pDoc->DeleteTab(srcSheet);
+    }
+    else
+    {
+        CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E4"), getFormula(0, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.$E$4"), getFormula(1, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.$E4"), getFormula(2, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=DestSheet.E$4"), getFormula(3, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(DestSheet.E4:E4)"), getFormula(4, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(DestSheet.$E$4:$E$4)"), getFormula(5, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(DestSheet.$E4:$E4)"), getFormula(6, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(DestSheet.E$4:E$4)"), getFormula(7, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(DestSheet.$D$2:$D$5)"), getFormula(8, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$8)"), getFormula(9, 14, srcSheet));
+
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(0, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(1, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(2, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(3, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(4, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(5, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(6, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(7, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(8, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(-27.0, m_pDoc->GetValue(9, 14, srcSheet));
+
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_B3"), getFormula(0, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_aBa3"), getFormula(1, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_aB3"), getFormula(2, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=Range_Ba3"), getFormula(3, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_B3_B3)"), getFormula(4, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aBa3_aBa3)"), getFormula(5, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aB3_aB3)"), getFormula(6, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_Ba3_Ba3)"), getFormula(7, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aAa1_aAa4)"), getFormula(8, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(Range_aAa1_aAa8)"), getFormula(9, 15, srcSheet));
+
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(0, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(1, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(2, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(3, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(4, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(5, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(35.0, m_pDoc->GetValue(6, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(123.0, m_pDoc->GetValue(7, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(8, 15, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(-27.0, m_pDoc->GetValue(9, 15, srcSheet));
+    }
 }
 
 void TestCopyPaste::checkCopyPasteSpecialFiltered(bool bSkipEmpty)
@@ -2692,33 +3612,33 @@ void TestCopyPaste::checkCopyPasteSpecialFiltered(bool bSkipEmpty)
     CPPUNIT_ASSERT(!m_pDoc->HasNote(ScAddress(9, 5, destSheet)));
 
     // check values of notes
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 0, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A1"),
                          m_pDoc->GetNote(ScAddress(3, 1, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(0, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note A3"),
                          m_pDoc->GetNote(ScAddress(3, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 0, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note B1"),
                          m_pDoc->GetNote(ScAddress(4, 1, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(1, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note B3"),
                          m_pDoc->GetNote(ScAddress(4, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(2, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note C3"),
                          m_pDoc->GetNote(ScAddress(5, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 0, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D1"),
                          m_pDoc->GetNote(ScAddress(6, 1, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(3, 2, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note D3"),
                          m_pDoc->GetNote(ScAddress(6, 2, destSheet))->GetText());
     if (!bSkipEmpty)
-        CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(),
+        CPPUNIT_ASSERT_EQUAL(OUString("Note E2"),
                              m_pDoc->GetNote(ScAddress(7, 2, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 3, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note E4"),
                          m_pDoc->GetNote(ScAddress(7, 3, destSheet))->GetText());
-    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(5, 3, srcSheet))->GetText(),
+    CPPUNIT_ASSERT_EQUAL(OUString("Note F4"),
                          m_pDoc->GetNote(ScAddress(8, 3, destSheet))->GetText());
 
     m_pDoc->DeleteTab(destSheet);
     m_pDoc->DeleteTab(srcSheet);
 }
 
-void TestCopyPaste::checkCopyPasteSpecialTranspose(bool bSkipEmpty)
+void TestCopyPaste::checkCopyPasteSpecialTranspose(bool bSkipEmpty, bool bCut)
 {
     const SCTAB srcSheet = 0;
     const SCTAB destSheet = 1;
@@ -2873,8 +3793,16 @@ void TestCopyPaste::checkCopyPasteSpecialTranspose(bool bSkipEmpty)
     }
     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);
+    if (!bCut)
+    {
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("transposed formula G7", OUString("=C$1+$A$3+80"), aString);
+        ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula G7", 2080, fValue);
+    }
+    else
+    {
+        CPPUNIT_ASSERT_EQUAL(OUString("=D$3+$F$2+80"), aString);
+        ASSERT_DOUBLES_EQUAL(94, fValue);
+    }
     ASSERT_DOUBLES_EQUAL(1000, m_pDoc->GetValue(7, 6, destSheet));
     aString = m_pDoc->GetString(7, 6, destSheet);
     CPPUNIT_ASSERT_EQUAL(OUString("1000"), aString);
@@ -3061,55 +3989,238 @@ void TestCopyPaste::checkCopyPasteSpecialTranspose(bool bSkipEmpty)
                            !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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D2", OUString("Note A1"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E2", OUString("Note A2"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F2", OUString("Note A3"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on D3", OUString("Note B1"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F3", OUString("Note B3"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on E4", OUString("Note C2"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong content of cell note on F4", OUString("Note C3"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on D5", OUString("Note D1"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E5", OUString("Note D2"),
                                  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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on F5", OUString("Note D3"),
                                  m_pDoc->GetNote(ScAddress(5, 4, destSheet))->GetText());
     if (!bSkipEmpty)
-        CPPUNIT_ASSERT_EQUAL(m_pDoc->GetNote(ScAddress(4, 2, srcSheet))->GetText(),
+        CPPUNIT_ASSERT_EQUAL(OUString("Note E2"),
                              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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on G6", OUString("Note E4"),
                                  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(),
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on E7", OUString("Note F2"),
                                      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(),
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Content of cell note on G7", OUString("Note F4"),
                                  m_pDoc->GetNote(ScAddress(6, 6, destSheet))->GetText());
 
-    m_pDoc->DeleteTab(destSheet);
-    m_pDoc->DeleteTab(srcSheet);
+    // row 14 on src sheet, refs to copied/cut range
+    if (!bCut)
+    {
+        CPPUNIT_ASSERT_EQUAL(OUString("=B3"), getFormula(0, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=$B$3"), getFormula(1, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=$B3"), getFormula(2, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=B$3"), getFormula(3, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(B3:B3)"), getFormula(4, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($B$3:$B$3)"), getFormula(5, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($B3:$B3)"), getFormula(6, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM(B$3:B$3)"), getFormula(7, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$4)"), getFormula(8, 14, srcSheet));
+        CPPUNIT_ASSERT_EQUAL(OUString("=SUM($A$1:$A$8)"), getFormula(9, 14, srcSheet));
+

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list