sc: carry a table into the clipboard only from a copied range
CopyToClip() copies named database ranges into the clipboard document through CopyDBsToClip(), which decided whether to carry a table by testing it against the bounding box of the copied area. For a non-contiguous selection the bounding box also covers the gaps between the selected ranges, so a table sitting in such a gap was carried even though none of its cells were copied. Test the table against the actually copied ranges instead of their bounding box, so a table that lies entirely in a gap is left out. Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> Change-Id: I1c8663e5190247dae0edf3878efe37186a7f6a4d Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5095 Reviewed-by: Balázs Varga <balazs.varga@collabora.com> Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com> (cherry picked from commit 37543af628671f723c9a661e2add91d6bc641591) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207944 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
2d2a39e989
commit
499ca3e23e
+1
-1
@@ -2928,7 +2928,7 @@ private:
|
||||
const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz );
|
||||
|
||||
void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks);
|
||||
void CopyDBsToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks);
|
||||
void CopyDBsToClip(ScDocument* pClipDoc, const ScRangeList& rClipRanges, const ScMarkData* pMarks);
|
||||
void CopyDBsFromClip(const ScRange& rDestRange, const ScRange& rClipRange, const ScDocument* pClipDoc);
|
||||
|
||||
bool HasPartOfMerged( const ScRange& rRange );
|
||||
|
||||
@@ -10129,8 +10129,8 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipCrossDocSameNameNoBind)
|
||||
auto pTable = std::make_unique<ScDBData>(u"MyTable"_ustr, 0, 0, 0, 2, 3, true, true);
|
||||
pTable->SetTableColumnNames(std::vector<OUString>{ u"H1"_ustr, u"H2"_ustr, u"H3"_ustr });
|
||||
CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable)));
|
||||
m_pDoc->SetValue(0, 1, 0, 1.0); // A2
|
||||
m_pDoc->SetValue(0, 2, 0, 4.0); // A3
|
||||
m_pDoc->SetValue(0, 1, 0, 1.0); // A2
|
||||
m_pDoc->SetValue(0, 2, 0, 4.0); // A3
|
||||
m_pDoc->SetValue(0, 3, 0, 16.0); // A4
|
||||
m_pDoc->SetString(2, 1, 0, u"=SUM(MyTable[H1])"_ustr); // C2
|
||||
m_pDoc->CalcAll();
|
||||
@@ -10148,7 +10148,8 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipCrossDocSameNameNoBind)
|
||||
// Destination document with its OWN unrelated MyTable at F11:H14
|
||||
// carrying distinct H1 data.
|
||||
ScDocShellRef xDestDocSh = new ScDocShell;
|
||||
xDestDocSh->DoLoad(new SfxMedium(u"file:///crossdocnameclash.fake"_ustr, StreamMode::STD_READWRITE));
|
||||
xDestDocSh->DoLoad(
|
||||
new SfxMedium(u"file:///crossdocnameclash.fake"_ustr, StreamMode::STD_READWRITE));
|
||||
ScDocument& rDestDoc = xDestDocSh->GetDocument();
|
||||
rDestDoc.InsertTab(0, u"Dest"_ustr);
|
||||
auto pDestTable = std::make_unique<ScDBData>(u"MyTable"_ustr, 0, 5, 10, 7, 13, true, true);
|
||||
@@ -10166,8 +10167,7 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipCrossDocSameNameNoBind)
|
||||
rDestDoc.CalcAll();
|
||||
|
||||
// The pasted formula resolves to FormulaError::NoRef.
|
||||
CPPUNIT_ASSERT_EQUAL(int(FormulaError::NoRef),
|
||||
int(rDestDoc.GetErrCode(ScAddress(2, 1, 0))));
|
||||
CPPUNIT_ASSERT_EQUAL(int(FormulaError::NoRef), int(rDestDoc.GetErrCode(ScAddress(2, 1, 0))));
|
||||
|
||||
// The source's H1 data landed in the destination at A2:A4.
|
||||
CPPUNIT_ASSERT_EQUAL(1.0, rDestDoc.GetValue(0, 1, 0));
|
||||
@@ -10190,6 +10190,42 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipCrossDocSameNameNoBind)
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyToClipMultiRangeGapTable)
|
||||
{
|
||||
// A non-contiguous copy must carry only the tables that lie inside a copied
|
||||
// range, not one sitting in the gap between two ranges. The gap table is
|
||||
// inside the bounding box of the selection but none of its cells are copied.
|
||||
m_pDoc->InsertTab(0, u"Test"_ustr);
|
||||
|
||||
// Column-direction multi-selection A1:B3 and E1:F3; the gap is columns C, D.
|
||||
|
||||
// InRangeTable at A1:B3 lies inside the first range. The clip carries it.
|
||||
auto pInRange = std::make_unique<ScDBData>(u"InRangeTable"_ustr, 0, 0, 0, 1, 2, true, true);
|
||||
CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pInRange)));
|
||||
|
||||
// GapTable at C1:D3 lies in the gap. The clip leaves it out.
|
||||
auto pGap = std::make_unique<ScDBData>(u"GapTable"_ustr, 0, 2, 0, 3, 2, true, true);
|
||||
CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pGap)));
|
||||
|
||||
ScMarkData aMark(m_pDoc->GetSheetLimits());
|
||||
aMark.SelectOneTable(0);
|
||||
ScClipParam aClipParam;
|
||||
aClipParam.meDirection = ScClipParam::Column;
|
||||
aClipParam.maRanges.push_back(ScRange(0, 0, 0, 1, 2, 0)); // A1:B3
|
||||
aClipParam.maRanges.push_back(ScRange(4, 0, 0, 5, 2, 0)); // E1:F3
|
||||
|
||||
ScDocument aClipDoc(SCDOCMODE_CLIP);
|
||||
m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false);
|
||||
|
||||
ScDBCollection::NamedDBs& rClipDBs = aClipDoc.GetDBCollection()->getNamedDBs();
|
||||
CPPUNIT_ASSERT_MESSAGE("a table inside a copied range is carried",
|
||||
rClipDBs.findByUpperName(u"INRANGETABLE"_ustr));
|
||||
CPPUNIT_ASSERT_MESSAGE("a table in the gap between copied ranges must not be carried",
|
||||
!rClipDBs.findByUpperName(u"GAPTABLE"_ustr));
|
||||
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteFormulasExternalDoc)
|
||||
{
|
||||
SfxMedium* pMedium = new SfxMedium(u"file:///source.fake"_ustr, StreamMode::STD_READWRITE);
|
||||
|
||||
@@ -2320,7 +2320,7 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam,
|
||||
|
||||
sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags);
|
||||
CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks);
|
||||
CopyDBsToClip(pClipDoc, aClipRange, pMarks);
|
||||
CopyDBsToClip(pClipDoc, rClipParam.maRanges, pMarks);
|
||||
|
||||
// 1. Copy selected cells
|
||||
for (SCTAB i = 0; i < nEndTab; ++i)
|
||||
@@ -2588,7 +2588,7 @@ void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClip
|
||||
// copied formulas have no ScDBData to resolve against on the clip side,
|
||||
// so any later stringification of those formulas writes #REF! in place
|
||||
// of the column name.
|
||||
void ScDocument::CopyDBsToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks)
|
||||
void ScDocument::CopyDBsToClip(ScDocument* pClipDoc, const ScRangeList& rClipRanges, const ScMarkData* pMarks)
|
||||
{
|
||||
if (!pDBCollection || pDBCollection->getNamedDBs().empty())
|
||||
return;
|
||||
@@ -2604,7 +2604,10 @@ void ScDocument::CopyDBsToClip(ScDocument* pClipDoc, const ScRange& rClipRange,
|
||||
rxSrc->GetArea(aArea);
|
||||
if (pMarks && !pMarks->GetTableSelect(aArea.aStart.Tab()))
|
||||
continue;
|
||||
if (!aArea.Intersects(rClipRange))
|
||||
// Carry only a table that overlaps a copied range. A table sitting in
|
||||
// the gap of a non-contiguous selection falls inside the bounding box
|
||||
// but in none of the copied ranges, and its cells are not copied.
|
||||
if (!rClipRanges.Intersects(aArea))
|
||||
continue;
|
||||
auto pClone = std::make_unique<ScDBData>(*rxSrc);
|
||||
rDest.insert(std::move(pClone));
|
||||
|
||||
Reference in New Issue
Block a user