From dd2decfe19c09fbd69f0ccb420c14b114ac1169b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Vajngerl?= Date: Sun, 21 Jun 2026 14:15:04 +0000 Subject: [PATCH] sc: recreate a pasted table only when formulas are pasted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CopyFromClip() recreates a named table the copy fully covered so the structured-reference tokens in the pasted formulas can resolve against it. It ran that step for any content paste, so a values-only paste also registered the table, with its autofilter and style, even though it carries no formula that would reference the table. Gate the table recreation on the formula content flag, so a values-only paste leaves the destination without a table. Signed-off-by: Tomaž Vajngerl Change-Id: I8bf7b30ef4fc415229d05f57955ac9d6cf65910e Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5097 Tested-by: Jenkins CPCI Reviewed-by: Balázs Varga (cherry picked from commit c0ec48adf51d34a50469b78df4136aaaa1dce074) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207946 Tested-by: Jenkins Reviewed-by: Xisco Fauli --- sc/qa/unit/ucalc_copypaste.cxx | 42 ++++++++++++++++++++++++++++++++ sc/source/core/data/document.cxx | 7 +++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/sc/qa/unit/ucalc_copypaste.cxx b/sc/qa/unit/ucalc_copypaste.cxx index 3cd2160f13f6..b3875d7a2f73 100644 --- a/sc/qa/unit/ucalc_copypaste.cxx +++ b/sc/qa/unit/ucalc_copypaste.cxx @@ -10261,6 +10261,48 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyToClipMultiSheetForeignTable) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipValuesOnlyNoTable) +{ + // Pasting only values of a copied table must not recreate the table in the + // destination. The table is recreated so structured-reference formulas can + // resolve against it. A values-only paste carries no such formula, so it + // should leave the destination without a table. + m_pDoc->InsertTab(0, u"Src"_ustr); + + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 0, 0, 2, 2, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + m_pDoc->SetString(0, 0, 0, u"Name"_ustr); + m_pDoc->SetValue(2, 2, 0, 42.0); + + // Copy the whole table A1:C3. + ScRange aClipRange(0, 0, 0, 2, 2, 0); + ScClipParam aClipParam(aClipRange, false); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aClipRange); + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + // Fresh destination document that has no MyTable of its own. + ScDocShellRef xDestDocSh = new ScDocShell; + xDestDocSh->DoLoad(new SfxMedium(u"file:///valuesonly.fake"_ustr, StreamMode::STD_READWRITE)); + ScDocument& rDestDoc = xDestDocSh->GetDocument(); + rDestDoc.InsertTab(0, u"Dest"_ustr); + + // Paste values only, no formulas. + ScRange aDestRange(0, 0, 0, 2, 2, 0); + ScMarkData aDestMark(rDestDoc.GetSheetLimits()); + aDestMark.SelectOneTable(0); + rDestDoc.CopyFromClip(aDestRange, aDestMark, InsertDeleteFlags::VALUE, nullptr, &aClipDoc); + + ScDBCollection* pDestDBs = rDestDoc.GetDBCollection(); + CPPUNIT_ASSERT_MESSAGE("a values-only paste must not recreate the table", + !pDestDBs || pDestDBs->getNamedDBs().empty()); + + xDestDocSh->DoClose(); + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteFormulasExternalDoc) { SfxMedium* pMedium = new SfxMedium(u"file:///source.fake"_ustr, StreamMode::STD_READWRITE); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 2a4c9f3e2b65..34332513da13 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -3131,9 +3131,10 @@ void ScDocument::CopyFromClip( // Recreate named tables the copy fully covered at the paste location, so the // structured-reference tokens resolved further down bind to a table placed - // at the paste position. Must run before the cells, and their formulas, are - // copied in. - if (nInsFlag & InsertDeleteFlags::CONTENTS) + // at the paste position. Only a formula paste carries such tokens, so a + // values-only paste needs no table. Must run before the cells, and their + // formulas, are copied in. + if (nInsFlag & InsertDeleteFlags::FORMULA) CopyDBsFromClip(rDestRange, aClipRange, pClipDoc); bInsertingFromOtherDoc = true; // No Broadcast/Listener created at Insert