sc: test that a cross-doc table-name clash leaves paste unresolved
Pasting a fully-copied named table into a different document that already owns an unrelated table of the same name must not bind the pasted structured-reference formula to that destination table. The name is document-global and the copied table cannot be recreated under it, so the reference stays unresolved (#REF!) instead of silently computing the unrelated table's data. The engine already behaves this way. This test guards against a regression that would bind the pasted reference to the destination's table and produce a silent wrong result. Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> Change-Id: I7304951c03ea090703f8e4232f92b1d14179b537 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5093 Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com> Reviewed-by: Balázs Varga <balazs.varga@collabora.com> (cherry picked from commit cd8c7ad4578b5a7c5225e82b212f45b20cbb7d96) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207942 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
21221fe1f0
commit
a84060c9ec
@@ -21,6 +21,7 @@
|
||||
#include <editeng/borderline.hxx>
|
||||
#include <editeng/brushitem.hxx>
|
||||
#include <editutil.hxx>
|
||||
#include <formula/errorcodes.hxx>
|
||||
#include <formulacell.hxx>
|
||||
#include <impex.hxx>
|
||||
#include <iostream>
|
||||
@@ -10114,6 +10115,81 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipPartialTableNoPhantom)
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipCrossDocSameNameNoBind)
|
||||
{
|
||||
// A full table copy pasted into a different document that already owns an
|
||||
// unrelated table of the same name must not bind the pasted structured
|
||||
// reference to that destination table. The name is document-global and
|
||||
// cannot be recreated, so the reference is left unresolved (#REF!) instead
|
||||
// of silently computing the wrong table's data.
|
||||
m_pDoc->InsertTab(0, u"Src"_ustr);
|
||||
|
||||
// Source MyTable A1:C4; a structured-ref formula in C2 reads its H1
|
||||
// column.
|
||||
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, 3, 0, 16.0); // A4
|
||||
m_pDoc->SetString(2, 1, 0, u"=SUM(MyTable[H1])"_ustr); // C2
|
||||
m_pDoc->CalcAll();
|
||||
CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(2, 1, 0));
|
||||
|
||||
// Copy the whole table A1:C4.
|
||||
ScRange aClipRange(0, 0, 0, 2, 3, 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);
|
||||
|
||||
// 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));
|
||||
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);
|
||||
pDestTable->SetTableColumnNames(std::vector<OUString>{ u"H1"_ustr, u"H2"_ustr, u"H3"_ustr });
|
||||
CPPUNIT_ASSERT(rDestDoc.GetDBCollection()->getNamedDBs().insert(std::move(pDestTable)));
|
||||
rDestDoc.SetValue(5, 11, 0, 100.0); // F12
|
||||
rDestDoc.SetValue(5, 12, 0, 200.0); // F13
|
||||
rDestDoc.SetValue(5, 13, 0, 400.0); // F14
|
||||
|
||||
// Paste the copied table at A1, clear of the destination's own table.
|
||||
ScRange aDestRange(0, 0, 0, 2, 3, 0);
|
||||
ScMarkData aDestMark(rDestDoc.GetSheetLimits());
|
||||
aDestMark.SelectOneTable(0);
|
||||
rDestDoc.CopyFromClip(aDestRange, aDestMark, InsertDeleteFlags::ALL, nullptr, &aClipDoc);
|
||||
rDestDoc.CalcAll();
|
||||
|
||||
// The pasted formula resolves to FormulaError::NoRef.
|
||||
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));
|
||||
CPPUNIT_ASSERT_EQUAL(4.0, rDestDoc.GetValue(0, 2, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(16.0, rDestDoc.GetValue(0, 3, 0));
|
||||
|
||||
// The destination's own table stays at its original area with its data
|
||||
// untouched by the paste.
|
||||
const ScDBData* pDestOwn
|
||||
= rDestDoc.GetDBCollection()->getNamedDBs().findByUpperName(u"MYTABLE"_ustr);
|
||||
CPPUNIT_ASSERT(pDestOwn);
|
||||
ScRange aDestOwnArea;
|
||||
pDestOwn->GetArea(aDestOwnArea);
|
||||
CPPUNIT_ASSERT_EQUAL(ScRange(5, 10, 0, 7, 13, 0), aDestOwnArea);
|
||||
CPPUNIT_ASSERT_EQUAL(100.0, rDestDoc.GetValue(5, 11, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(200.0, rDestDoc.GetValue(5, 12, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(400.0, rDestDoc.GetValue(5, 13, 0));
|
||||
|
||||
xDestDocSh->DoClose();
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteFormulasExternalDoc)
|
||||
{
|
||||
SfxMedium* pMedium = new SfxMedium(u"file:///source.fake"_ustr, StreamMode::STD_READWRITE);
|
||||
|
||||
Reference in New Issue
Block a user