sc/inc/document.hxx              |   13 ++-
 sc/qa/unit/ucalc.cxx             |   53 ++++++++++++++
 sc/source/core/data/documen2.cxx |  143 +++++++++++++++++++++++----------------
 3 files changed, 147 insertions(+), 62 deletions(-)

New commits:
commit 040b5fb8258e6f5b77c46be61e5087508f737038
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Tue Feb 3 13:59:17 2026 +0900
Commit:     Miklos Vajna <[email protected]>
CommitDate: Fri Feb 13 08:29:34 2026 +0100

    sc: Add OverwriteContent to ScDocument
    
    OverwriteContent overwrites the content of the target table with
    the content of source table. This will be needed for sync between
    sheet views and default view.
    
    Change-Id: I578f12e32504bf6c5a6ca9a93bd03beffa1e7b82
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198733
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index c77ab3acac12..1390d25ff476 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -90,8 +90,8 @@ class SharedStringPool;
 
 namespace tools { class Guid; }
 
-namespace sc {
-
+namespace sc
+{
 struct BroadcasterState;
 struct FormulaGroupContext;
 class StartListeningContext;
@@ -121,6 +121,8 @@ class Sparkline;
 class SparklineGroup;
 class SparklineList;
 class SheetViewManager;
+class AutoCalcSwitch;
+struct RefUpdateInsertTabContext;
 }
 
 class Fraction;
@@ -1067,8 +1069,11 @@ public:
     SC_DLLPUBLIC bool           RenameTab( SCTAB nTab, const OUString& rName,
                                            bool bExternalDocument = false );
     bool                        MoveTab( SCTAB nOldPos, SCTAB nNewPos, 
ScProgress* pProgress = nullptr );
-    SC_DLLPUBLIC bool           CopyTab( SCTAB nOldPos, SCTAB nNewPos,
-                                         const ScMarkData* pOnlyMarked = 
nullptr );
+    SC_DLLPUBLIC bool           CopyTab( SCTAB nOldPos, SCTAB nNewPos, const 
ScMarkData* pOnlyMarked = nullptr );
+
+    void CopyContent(SCTAB nSourceTabNo, SCTAB nTargetTabNo, const ScMarkData* 
pOnlyMarked, sc::RefUpdateInsertTabContext& rContext);
+    bool OverwriteContent(SCTAB nSourceTabNo, SCTAB nTargetTabNo);
+
     SC_DLLPUBLIC bool      TransferTab(ScDocument& rSrcDoc, SCTAB nSrcPos, 
SCTAB nDestPos,
                                             bool bInsertNew = true,
                                             bool bResultsOnly = false );
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 3d43896f7b2c..c793d093b5a5 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -7149,6 +7149,59 @@ CPPUNIT_TEST_FIXTURE(Test, 
testDocumentModelAccessor_getDocumentCurrencies)
     CPPUNIT_ASSERT_EQUAL(u"€"_ustr, aCurrencyIDs[0].aSymbol);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testOverwriteContent)
+{
+    m_pDoc->InsertTab(0, u"Tab1"_ustr);
+    m_pDoc->InsertTab(1, u"Tab2"_ustr);
+    m_pDoc->InsertTab(2, u"Tab3"_ustr);
+
+    std::vector<std::vector<OUString>> aData = {
+        { u"C1"_ustr, u"C2"_ustr, u"C3"_ustr },
+        {  u"7"_ustr,  u"1"_ustr,  u"A"_ustr },
+        {  u"3"_ustr,  u"2"_ustr,   u""_ustr },
+        {  u"2"_ustr,  u"4"_ustr,  u"B"_ustr },
+        {  u"4"_ustr,  u"3"_ustr,  u"B"_ustr }
+    };
+
+    // Populate cells.
+    for (size_t i = 0; i < aData.size(); ++i)
+    {
+        for (size_t j = 0; j < aData[0].size(); ++j)
+        {
+            if (!aData[i][j].isEmpty())
+            {
+                m_pDoc->SetString(j, i, 0, aData[i][j]);
+            }
+        }
+    }
+
+    CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 0)));
+    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(0, 1, 1)));
+    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(0, 1, 2)));
+
+    m_pDoc->OverwriteContent(0, 1);
+
+    CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 0)));
+    CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 1)));
+    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(0, 1, 2)));
+
+    m_pDoc->SetString(0, 1, 0, u"9.0"_ustr);
+
+    CPPUNIT_ASSERT_EQUAL(9.0, m_pDoc->GetValue(ScAddress(0, 1, 0)));
+    CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 1)));
+    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(0, 1, 2)));
+
+
+    m_pDoc->OverwriteContent(0, 1);
+
+    CPPUNIT_ASSERT_EQUAL(9.0, m_pDoc->GetValue(ScAddress(0, 1, 0)));
+    CPPUNIT_ASSERT_EQUAL(9.0, m_pDoc->GetValue(ScAddress(0, 1, 1)));
+    CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(0, 1, 2)));
+
+    m_pDoc->DeleteTab(0);
+    m_pDoc->DeleteTab(1);
+    m_pDoc->DeleteTab(2);
+}
 
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 6372d9412018..a3d3d5939cb3 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -820,6 +820,86 @@ bool ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos, 
ScProgress* pProgress )
     return bValid;
 }
 
+void ScDocument::CopyContent(SCTAB nSourceTabNo, SCTAB nTargetTabNo, const 
ScMarkData* pOnlyMarked, sc::RefUpdateInsertTabContext& rContext)
+{
+    SetNoListening( true );     // not yet at CopyToTable/Insert
+
+    const bool bGlobalNamesToLocal = true;
+    const SCTAB nRealOldPos = (nTargetTabNo < nSourceTabNo) ? nSourceTabNo - 1 
: nSourceTabNo;
+    const ScRangeName* pNames = GetRangeName( nSourceTabNo);
+    if (pNames)
+        pNames->CopyUsedNames( nSourceTabNo, nRealOldPos, nTargetTabNo, *this, 
*this, bGlobalNamesToLocal);
+    GetRangeName()->CopyUsedNames( -1, nRealOldPos, nTargetTabNo, *this, 
*this, bGlobalNamesToLocal);
+
+    sc::CopyToDocContext aCopyDocCxt(*this);
+    pDBCollection->CopyToTable(nSourceTabNo, nTargetTabNo);
+    maTabs[nSourceTabNo]->CopyToTable(aCopyDocCxt, 0, 0, MaxCol(), MaxRow(), 
InsertDeleteFlags::ALL,
+            (pOnlyMarked != nullptr), maTabs[nTargetTabNo].get(), pOnlyMarked,
+            false /*bAsLink*/, true /*bColRowFlags*/, bGlobalNamesToLocal, 
false /*bCopyCaptions*/ );
+    maTabs[nTargetTabNo]->SetTabBgColor(maTabs[nSourceTabNo]->GetTabBgColor());
+
+    SCTAB nDz = nTargetTabNo - nSourceTabNo;
+    sc::RefUpdateContext aRefContext(*this);
+    aRefContext.meMode = URM_COPY;
+    aRefContext.maRange = ScRange(0, 0, nTargetTabNo, MaxCol(), MaxRow(), 
nTargetTabNo);
+    aRefContext.mnTabDelta = nDz;
+    maTabs[nTargetTabNo]->UpdateReference(aRefContext);
+
+    maTabs[nTargetTabNo]->UpdateInsertTabAbs(nTargetTabNo); // move all 
paragraphs up by one!!
+    maTabs[nSourceTabNo]->UpdateInsertTab(rContext);
+
+    maTabs[nSourceTabNo]->UpdateCompile();
+    maTabs[nTargetTabNo]->UpdateCompile( true ); //  maybe already compiled in 
Clone, but used names need recompilation
+    SetNoListening( false );
+    sc::StartListeningContext aSLCxt(*this);
+    maTabs[nSourceTabNo]->StartListeners(aSLCxt, true);
+    maTabs[nTargetTabNo]->StartListeners(aSLCxt, true);
+
+    sc::SetFormulaDirtyContext aFormulaDirtyCxt;
+    SetAllFormulasDirty(aFormulaDirtyCxt);
+
+    if (mpDrawLayer) //  Skip cloning Note caption object
+        // page is already created in ScTable ctor
+        mpDrawLayer->ScCopyPage( static_cast<sal_uInt16>(nSourceTabNo), 
static_cast<sal_uInt16>(nTargetTabNo) );
+
+    if (pDPCollection)
+        pDPCollection->CopyToTab(nSourceTabNo, nTargetTabNo);
+
+    maTabs[nTargetTabNo]->SetPageStyle( maTabs[nSourceTabNo]->GetPageStyle() );
+    maTabs[nTargetTabNo]->SetPendingRowHeights( 
maTabs[nSourceTabNo]->IsPendingRowHeights() );
+
+    // Copy the custom print range if exists.
+    maTabs[nTargetTabNo]->CopyPrintRange(*maTabs[nSourceTabNo]);
+
+    // Copy the RTL settings
+    maTabs[nTargetTabNo]->SetLayoutRTL(maTabs[nSourceTabNo]->IsLayoutRTL());
+    maTabs[nTargetTabNo]->SetLoadingRTL(maTabs[nSourceTabNo]->IsLoadingRTL());
+
+    // Finally copy the note captions, which need
+    // 1. the updated source ScColumn::nTab members if nTargetTabNo <= 
nSourceTabNo
+    // 2. row heights and column widths of the destination
+    // 3. RTL settings of the destination
+    maTabs[nSourceTabNo]->CopyCaptionsToTable( 0, 0, MaxCol(), MaxRow(), 
maTabs[nTargetTabNo].get(), true /*bCloneCaption*/);
+}
+
+bool ScDocument::OverwriteContent(SCTAB nSourceTabNo, SCTAB nTargetTabNo)
+{
+    ScTable* pSourceTable = FetchTable(nSourceTabNo);
+    ScTable* pTargetTable = FetchTable(nTargetTabNo);
+
+    if (pSourceTable && pTargetTable)
+    {
+        pTargetTable->DeleteArea(0, 0, MaxCol(), MaxRow(), 
InsertDeleteFlags::ALL);
+
+        sc::AutoCalcSwitch aACSwitch(*this, false);
+        sc::RefUpdateInsertTabContext aContext(*this, nTargetTabNo, 1);
+        CopyContent(nSourceTabNo, nTargetTabNo, nullptr, aContext);
+        return true;
+    }
+    return false;
+}
+
+
 bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* 
pOnlyMarked )
 {
     if (SC_TAB_APPEND == nNewPos  || nNewPos >= GetTableCount())
@@ -840,6 +920,10 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, 
const ScMarkData* pOnlyM
     else
         bValid = !GetTable( aName, nDummy );
 
+    // Early return
+    if (!bValid)
+        return false;
+
     sc::AutoCalcSwitch aACSwitch(*this, false);
     sc::RefUpdateInsertTabContext aCxt( *this, nNewPos, 1);
 
@@ -899,64 +983,7 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, 
const ScMarkData* pOnlyM
 
     if (bValid)
     {
-        SetNoListening( true );     // not yet at CopyToTable/Insert
-
-        const bool bGlobalNamesToLocal = true;
-        const SCTAB nRealOldPos = (nNewPos < nOldPos) ? nOldPos - 1 : nOldPos;
-        const ScRangeName* pNames = GetRangeName( nOldPos);
-        if (pNames)
-            pNames->CopyUsedNames( nOldPos, nRealOldPos, nNewPos, *this, 
*this, bGlobalNamesToLocal);
-        GetRangeName()->CopyUsedNames( -1, nRealOldPos, nNewPos, *this, *this, 
bGlobalNamesToLocal);
-
-        sc::CopyToDocContext aCopyDocCxt(*this);
-        pDBCollection->CopyToTable(nOldPos, nNewPos);
-        maTabs[nOldPos]->CopyToTable(aCopyDocCxt, 0, 0, MaxCol(), MaxRow(), 
InsertDeleteFlags::ALL,
-                (pOnlyMarked != nullptr), maTabs[nNewPos].get(), pOnlyMarked,
-                false /*bAsLink*/, true /*bColRowFlags*/, bGlobalNamesToLocal, 
false /*bCopyCaptions*/ );
-        maTabs[nNewPos]->SetTabBgColor(maTabs[nOldPos]->GetTabBgColor());
-
-        SCTAB nDz = nNewPos - nOldPos;
-        sc::RefUpdateContext aRefCxt(*this);
-        aRefCxt.meMode = URM_COPY;
-        aRefCxt.maRange = ScRange(0, 0, nNewPos, MaxCol(), MaxRow(), nNewPos);
-        aRefCxt.mnTabDelta = nDz;
-        maTabs[nNewPos]->UpdateReference(aRefCxt);
-
-        maTabs[nNewPos]->UpdateInsertTabAbs(nNewPos); // move all paragraphs 
up by one!!
-        maTabs[nOldPos]->UpdateInsertTab(aCxt);
-
-        maTabs[nOldPos]->UpdateCompile();
-        maTabs[nNewPos]->UpdateCompile( true ); //  maybe already compiled in 
Clone, but used names need recompilation
-        SetNoListening( false );
-        sc::StartListeningContext aSLCxt(*this);
-        maTabs[nOldPos]->StartListeners(aSLCxt, true);
-        maTabs[nNewPos]->StartListeners(aSLCxt, true);
-
-        sc::SetFormulaDirtyContext aFormulaDirtyCxt;
-        SetAllFormulasDirty(aFormulaDirtyCxt);
-
-        if (mpDrawLayer) //  Skip cloning Note caption object
-            // page is already created in ScTable ctor
-            mpDrawLayer->ScCopyPage( static_cast<sal_uInt16>(nOldPos), 
static_cast<sal_uInt16>(nNewPos) );
-
-        if (pDPCollection)
-            pDPCollection->CopyToTab(nOldPos, nNewPos);
-
-        maTabs[nNewPos]->SetPageStyle( maTabs[nOldPos]->GetPageStyle() );
-        maTabs[nNewPos]->SetPendingRowHeights( 
maTabs[nOldPos]->IsPendingRowHeights() );
-
-        // Copy the custom print range if exists.
-        maTabs[nNewPos]->CopyPrintRange(*maTabs[nOldPos]);
-
-        // Copy the RTL settings
-        maTabs[nNewPos]->SetLayoutRTL(maTabs[nOldPos]->IsLayoutRTL());
-        maTabs[nNewPos]->SetLoadingRTL(maTabs[nOldPos]->IsLoadingRTL());
-
-        // Finally copy the note captions, which need
-        // 1. the updated source ScColumn::nTab members if nNewPos <= nOldPos
-        // 2. row heights and column widths of the destination
-        // 3. RTL settings of the destination
-        maTabs[nOldPos]->CopyCaptionsToTable( 0, 0, MaxCol(), MaxRow(), 
maTabs[nNewPos].get(), true /*bCloneCaption*/);
+        CopyContent(nOldPos, nNewPos, pOnlyMarked, aCxt);
     }
 
     return bValid;

Reply via email to