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;
