Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / sc / qa / unit / copy_paste_test.cxx
blobc020565655ef84b8f6081aadaec3999fc9c14004
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sal/config.h>
12 #include <string_view>
14 #include <test/unoapi_test.hxx>
15 #include <comphelper/processfactory.hxx>
16 #include <comphelper/propertyvalue.hxx>
18 #include <docsh.hxx>
19 #include <docfunc.hxx>
20 #include <cellmergeoption.hxx>
21 #include <tabvwsh.hxx>
22 #include <impex.hxx>
23 #include <scitems.hxx>
24 #include <attrib.hxx>
25 #include <userlist.hxx>
26 #include <undomanager.hxx>
28 using namespace ::com::sun::star;
29 using namespace ::com::sun::star::uno;
31 class ScCopyPasteTest : public UnoApiTest
33 public:
34 ScCopyPasteTest();
36 void testCopyPasteXLS();
37 void testTdf84411();
38 void testTdf124565();
39 void testTdf126421();
40 void testTdf107394();
41 void testTdf53431_fillOnAutofilter();
42 void testTdf40993_fillMergedCells();
43 void testTdf43958_clickSelectOnMergedCells();
44 void testTdf88782_autofillLinearNumbersInMergedCells();
45 void tdf137621_autofillMergedBool();
46 void tdf137205_autofillDatesInMergedCells();
47 void tdf137653_137654_autofillUserlist();
48 void tdf113500_autofillMixed();
49 void tdf137625_autofillMergedUserlist();
50 void tdf137624_autofillMergedMixed();
52 CPPUNIT_TEST_SUITE(ScCopyPasteTest);
53 CPPUNIT_TEST(testCopyPasteXLS);
54 CPPUNIT_TEST(testTdf84411);
55 CPPUNIT_TEST(testTdf124565);
56 CPPUNIT_TEST(testTdf126421);
57 CPPUNIT_TEST(testTdf107394);
58 CPPUNIT_TEST(testTdf53431_fillOnAutofilter);
59 CPPUNIT_TEST(testTdf40993_fillMergedCells);
60 CPPUNIT_TEST(testTdf43958_clickSelectOnMergedCells);
61 CPPUNIT_TEST(testTdf88782_autofillLinearNumbersInMergedCells);
62 CPPUNIT_TEST(tdf137621_autofillMergedBool);
63 CPPUNIT_TEST(tdf137205_autofillDatesInMergedCells);
64 CPPUNIT_TEST(tdf137653_137654_autofillUserlist);
65 CPPUNIT_TEST(tdf113500_autofillMixed);
66 CPPUNIT_TEST(tdf137625_autofillMergedUserlist);
67 CPPUNIT_TEST(tdf137624_autofillMergedMixed);
68 CPPUNIT_TEST_SUITE_END();
70 private:
71 void addToUserList(const OUString& rStr);
74 // tdf#83366
75 void ScCopyPasteTest::testCopyPasteXLS()
77 loadFromURL(u"xls/chartx2.xls");
79 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
80 CPPUNIT_ASSERT(pModelObj);
81 ScDocument* pDoc = pModelObj->GetDocument();
83 // Get the document controller
84 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
86 // 2. Highlight B2:C5
87 ScRange aSrcRange;
88 ScRefFlags nRes = aSrcRange.Parse("B2:C5", *pDoc, pDoc->GetAddressConvention());
89 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
91 ScMarkData aMark(pDoc->GetSheetLimits());
92 aMark.SetMarkArea(aSrcRange);
94 pViewShell->GetViewData().GetMarkData().SetMarkArea(aSrcRange);
96 // 3. Copy
97 ScDocument aClipDoc(SCDOCMODE_CLIP);
98 pViewShell->GetViewData().GetView()->CopyToClip(&aClipDoc, false, false, false, false);
100 // 4. Close the document (Ctrl-W)
101 mxComponent->dispose();
102 mxComponent.clear();
104 // Open a new document
105 mxComponent = loadFromDesktop("private:factory/scalc");
107 // Get the document controller
108 pViewShell = ScDocShell::GetViewData()->GetViewShell();
110 // 6. Paste
111 pViewShell->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL, &aClipDoc);
114 namespace {
116 ScMarkData::MarkedTabsType TabsInRange(const ScRange& r)
118 ScMarkData::MarkedTabsType aResult;
119 for (SCTAB i = r.aStart.Tab(); i <= r.aEnd.Tab(); ++i)
120 aResult.insert(i);
121 return aResult;
124 void lcl_copy( const OUString& rSrcRange, const OUString& rDstRange, ScDocument& rDoc, ScTabViewShell* pViewShell )
126 ScDocument aClipDoc(SCDOCMODE_CLIP);
128 // 1. Copy
129 ScRange aSrcRange;
130 ScRefFlags nRes = aSrcRange.Parse(rSrcRange, rDoc, rDoc.GetAddressConvention());
131 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
132 pViewShell->GetViewData().GetMarkData().SetMarkArea(aSrcRange);
133 pViewShell->GetViewData().GetMarkData().SetSelectedTabs(TabsInRange(aSrcRange));
134 pViewShell->GetViewData().GetView()->CopyToClip(&aClipDoc, false, false, false, false);
136 // 2. Paste
137 ScRange aDstRange;
138 nRes = aDstRange.Parse(rDstRange, rDoc, rDoc.GetAddressConvention());
139 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
140 pViewShell->GetViewData().GetMarkData().SetMarkArea(aDstRange);
141 pViewShell->GetViewData().GetMarkData().SetSelectedTabs(TabsInRange(aDstRange));
142 pViewShell->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL, &aClipDoc);
145 } // anonymous namespace
147 void ScCopyPasteTest::testTdf84411()
149 mxComponent = loadFromDesktop("private:factory/scalc");
151 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
152 CPPUNIT_ASSERT(pModelObj);
153 ScDocument* pDoc = pModelObj->GetDocument();
155 // Get the document controller
156 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
158 // 2. Setup data and formulas
159 for (unsigned int r = 0; r <= 4991; ++r)
160 for (unsigned int c = 0; c <= 14; ++c)
161 pDoc->SetValue( ScAddress(c,r,0), (r+1)*(c+1) );
163 pDoc->SetString(ScAddress(15,10000,0), "=AVERAGE(A10001:O10001)");
164 pDoc->SetString(ScAddress(16,10000,0), "=MIN(A10001:O10001)");
165 pDoc->SetString(ScAddress(17,10000,0), "=MAX(A10001:O10001)");
167 lcl_copy("P10001:R10001", "P10002:R12500", *pDoc, pViewShell);
170 // 3. Disable OpenCL
171 bool bOpenCLState = ScCalcConfig::isOpenCLEnabled();
172 pModelObj->enableOpenCL(false);
173 CPPUNIT_ASSERT(!ScCalcConfig::isOpenCLEnabled() || ScCalcConfig::getForceCalculationType() == ForceCalculationOpenCL);
174 pModelObj->enableAutomaticCalculation(true);
177 // 4. Copy and Paste
178 lcl_copy("A1:O2500", "A10001:O12500", *pDoc, pViewShell);
180 lcl_copy("A2501:O5000", "A12501:O15000", *pDoc, pViewShell);
182 lcl_copy("P10001:R10001", "P12501:R15000", *pDoc, pViewShell);
185 // 5. Close the document (Ctrl-W)
186 pModelObj->enableOpenCL(bOpenCLState);
189 void ScCopyPasteTest::testTdf124565()
191 mxComponent = loadFromDesktop("private:factory/scalc");
193 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
194 CPPUNIT_ASSERT(pModelObj);
195 ScDocument* pDoc = pModelObj->GetDocument();
197 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
199 // Set content and height of first row
200 pDoc->SetString(ScAddress(0, 0, 0), "Test");
201 pDoc->SetRowHeight(0, 0, 500);
202 pDoc->SetManualHeight(0, 0, 0, true);
204 // Copy first row
205 ScDocument aClipDoc(SCDOCMODE_CLIP);
206 ScRange aCopyRange(0, 0, 0, aClipDoc.MaxCol(), 0, 0);
207 pViewShell->GetViewData().GetMarkData().SetMarkArea(aCopyRange);
208 pViewShell->GetViewData().GetView()->CopyToClip(&aClipDoc, false, false, false, false);
210 // Paste to second row
211 SCTAB nTab = 0;
212 SCCOL nCol = 0;
213 SCROW nRow = 1;
215 ScRange aPasteRange(nCol, nRow, nTab, aClipDoc.MaxCol(), nRow, nTab);
216 pViewShell->GetViewData().GetMarkData().SetMarkArea(aPasteRange);
217 pViewShell->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL, &aClipDoc);
219 // Copy-pasted?
220 CPPUNIT_ASSERT_EQUAL_MESSAGE("String was not pasted!", OUString("Test"), pDoc->GetString(nCol, nRow, nTab));
222 // And height same as in source?
223 CPPUNIT_ASSERT_EQUAL_MESSAGE("Row#2 height is invalid!", sal_uInt16(500), pDoc->GetRowHeight(nRow, nTab));
225 CPPUNIT_ASSERT_MESSAGE("Row#2 must be manual height!", pDoc->IsManualRowHeight(nRow, nTab));
228 void ScCopyPasteTest::testTdf126421()
230 mxComponent = loadFromDesktop("private:factory/scalc");
232 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
233 CPPUNIT_ASSERT(pModelObj);
234 ScDocument* pDoc = pModelObj->GetDocument();
236 // Get the document controller
237 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
239 // 2. Setup data
240 for (int r = 0; r < 2; ++r)
241 for (int c = 0; c < 1024; ++c)
242 pDoc->SetValue(c, r, 0, (c + 1) * 100 + (r + 1));
244 const SCTAB n2ndTab = pDoc->GetMaxTableNumber() + 1;
245 pDoc->MakeTable(n2ndTab);
246 const auto aTabNames = pDoc->GetAllTableNames();
248 lcl_copy(aTabNames[0] + ".A1:AMJ2", aTabNames[n2ndTab] + ".A1:AMJ2", *pDoc, pViewShell);
250 // 3. Check all cells in destination table
251 for (int r = 0; r < 2; ++r)
252 for (int c = 0; c < 1024; ++c)
253 CPPUNIT_ASSERT_EQUAL(double((c + 1) * 100 + (r + 1)), pDoc->GetValue(c, r, n2ndTab));
256 void ScCopyPasteTest::testTdf107394()
258 mxComponent = loadFromDesktop("private:factory/scalc");
260 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
261 CPPUNIT_ASSERT(pModelObj);
262 ScDocument* pDoc = pModelObj->GetDocument();
264 sal_uInt16 nFirstRowHeight = pDoc->GetRowHeight(0, 0);
265 sal_uInt16 nSecondRowHeight = pDoc->GetRowHeight(1, 0);
266 CPPUNIT_ASSERT_EQUAL(nFirstRowHeight, nSecondRowHeight);
268 // Import values to A1:A2.
269 ScImportExport aObj(*pDoc, ScAddress(0,0,0));
270 aObj.SetImportBroadcast(true);
272 SvMemoryStream aStream;
273 aStream.WriteOString("<pre>First\nVery long sentence.</pre>");
274 aStream.Seek(0);
275 CPPUNIT_ASSERT(aObj.ImportStream(aStream, OUString(), SotClipboardFormatId::HTML));
277 CPPUNIT_ASSERT_EQUAL(OUString("First"), pDoc->GetString(ScAddress(0,0,0)));
278 CPPUNIT_ASSERT_EQUAL(OUString("Very long sentence."), pDoc->GetString(ScAddress(0,1,0)));
280 nFirstRowHeight = pDoc->GetRowHeight(0, 0);
281 nSecondRowHeight = pDoc->GetRowHeight(1, 0);
282 CPPUNIT_ASSERT_GREATER(nFirstRowHeight, nSecondRowHeight);
284 // Undo, and check the result.
285 SfxUndoManager* pUndoMgr = pDoc->GetUndoManager();
286 CPPUNIT_ASSERT_MESSAGE("Failed to get the undo manager.", pUndoMgr);
287 pUndoMgr->Undo();
289 CPPUNIT_ASSERT(pDoc->GetString(ScAddress(0,0,0)).isEmpty());
290 CPPUNIT_ASSERT(pDoc->GetString(ScAddress(0,1,0)).isEmpty());
292 nFirstRowHeight = pDoc->GetRowHeight(0, 0);
293 nSecondRowHeight = pDoc->GetRowHeight(1, 0);
294 // Without the accompanying fix in place, this test would have failed:
295 // - Expected: 256
296 // - Actual : 477
297 // i.e. the increased height of the second row remained after undo.
298 CPPUNIT_ASSERT_EQUAL(nFirstRowHeight, nSecondRowHeight);
301 static ScMF lcl_getMergeFlagOfCell(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
303 const SfxPoolItem& rPoolItem = rDoc.GetPattern(nCol, nRow, nTab)->GetItem(ATTR_MERGE_FLAG);
304 const ScMergeFlagAttr& rMergeFlag = static_cast<const ScMergeFlagAttr&>(rPoolItem);
305 return rMergeFlag.GetValue();
308 static ScAddress lcl_getMergeSizeOfCell(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
310 const SfxPoolItem& rPoolItem = rDoc.GetPattern(nCol, nRow, nTab)->GetItem(ATTR_MERGE);
311 const ScMergeAttr& rMerge = static_cast<const ScMergeAttr&>(rPoolItem);
312 return ScAddress(rMerge.GetColMerge(), rMerge.GetRowMerge(), nTab);
315 void ScCopyPasteTest::testTdf53431_fillOnAutofilter()
317 loadFromURL(u"ods/tdf53431_autofilterFilldown.ods");
318 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
319 CPPUNIT_ASSERT(pModelObj);
320 ScDocument* pDoc = pModelObj->GetDocument();
322 // Get the document controller
323 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
325 //Fill should not clone Autofilter button
326 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 2, 4, 0));
327 pViewShell->FillSimple(FILL_TO_BOTTOM);
328 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
329 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
330 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 1, 4, 0) & ScMF::Auto));
332 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 4, 4, 0));
333 pViewShell->FillSimple(FILL_TO_RIGHT);
334 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
335 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
336 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 4, 1, 0) & ScMF::Auto));
337 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 1, 4, 0) & ScMF::Auto));
338 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 4, 4, 0) & ScMF::Auto));
340 //Fill should not delete Autofilter buttons
341 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 0, 0, 2, 4, 0));
342 pViewShell->FillSimple(FILL_TO_TOP);
343 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
344 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
345 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 1, 0, 0) & ScMF::Auto));
347 //Fill should not clone Autofilter button
348 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 2, 4, 0));
349 pViewShell->FillSimple(FILL_TO_BOTTOM);
350 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
351 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
352 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 1, 4, 0) & ScMF::Auto));
354 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 4, 4, 0));
355 pViewShell->FillSimple(FILL_TO_RIGHT);
356 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
357 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
358 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 4, 1, 0) & ScMF::Auto));
359 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 1, 4, 0) & ScMF::Auto));
360 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 4, 4, 0) & ScMF::Auto));
362 //Fill should not delete Autofilter buttons
363 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 0, 0, 2, 4, 0));
364 pViewShell->FillSimple(FILL_TO_TOP);
365 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
366 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
367 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 1, 0, 0) & ScMF::Auto));
369 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 0, 0, 4, 4, 0));
370 pViewShell->FillSimple(FILL_TO_LEFT);
371 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 1, 1, 0) & ScMF::Auto));
372 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc, 2, 1, 0) & ScMF::Auto));
373 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc, 0, 1, 0) & ScMF::Auto));
376 void ScCopyPasteTest::testTdf40993_fillMergedCells()
378 loadFromURL(u"ods/tdf40993_fillMergedCells.ods");
379 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
380 CPPUNIT_ASSERT(pModelObj);
381 ScDocument* pDoc = pModelObj->GetDocument();
383 // Get the document controller
384 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
386 // check content of the merged cell H11:I11
387 CPPUNIT_ASSERT_EQUAL(OUString("1.5"), pDoc->GetString(ScAddress(7, 10, 0)));
389 // fill operation on the merged cell should clone ATTR_MERGE and ATTR_MERGE_FLAG
390 // (as long as ATTR_MERGE_FLAG has only ScMF::Hor or ScMF::Ver)
392 // select merged cell
393 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(7, 10, 0, 8, 10, 0));
394 // copy its content in the next ten rows
395 pViewShell->FillAuto(FILL_TO_BOTTOM, 7, 10, 8, 10, 10);
396 for (int i = 7; i < 9; i++)
398 ScMF nOriginFlag = lcl_getMergeFlagOfCell(*pDoc, i, 10, 0);
399 ScAddress aOriginMerge = lcl_getMergeSizeOfCell(*pDoc, i, 10, 0);
401 // ATTR_MERGE_FLAG: top left cell is NONE, the other cell shows horizontal overlapping
402 CPPUNIT_ASSERT_EQUAL(i == 7 ? ScMF::NONE : ScMF::Hor, nOriginFlag);
404 // ATTR_MERGE: top left cell contains the size of the
405 // merged area (2:1), the other cell doesn't
406 CPPUNIT_ASSERT_EQUAL(i == 7 ? ScAddress(2, 1, 0): ScAddress(0, 0, 0), aOriginMerge);
408 for (int j = 11; j < 21; j++)
410 // check copying of ATTR_MERGE and ATTR_MERGE_FLAG
411 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc, i, j, 0), nOriginFlag);
412 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, i, j, 0), aOriginMerge);
416 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc, 7, 21, 0),
417 lcl_getMergeFlagOfCell(*pDoc, 7, 10, 0));
418 CPPUNIT_ASSERT(lcl_getMergeSizeOfCell(*pDoc, 7, 21, 0) !=
419 lcl_getMergeSizeOfCell(*pDoc, 7, 10, 0));
420 CPPUNIT_ASSERT(lcl_getMergeFlagOfCell(*pDoc, 8, 21, 0) !=
421 lcl_getMergeFlagOfCell(*pDoc, 8, 10, 0));
422 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, 8, 21, 0),
423 lcl_getMergeSizeOfCell(*pDoc, 8, 10, 0));
425 // area A6:E9 with various merged cells copied vertically and horizontally
426 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 5, 0, 4, 8, 0));
427 pViewShell->FillAuto(FILL_TO_BOTTOM, 0, 5, 4, 8, 12);
428 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 5, 0, 4, 8, 0));
429 pViewShell->FillAuto(FILL_TO_RIGHT, 0, 5, 4, 8, 10);
430 for (int i = 0; i < 5; i++)
432 for (int j = 5; j < 9; j++)
434 ScMF nOriginFlag = lcl_getMergeFlagOfCell(*pDoc, i, j, 0);
435 ScAddress aOriginMerge = lcl_getMergeSizeOfCell(*pDoc, i, j, 0);
436 // copies contain the same ATTR_MERGE and ATTR_MERGE_FLAG
437 for (int k = 0; k < 12; k += 4)
439 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc, i, j + k, 0), nOriginFlag);
440 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, i, j + k, 0), aOriginMerge);
442 for (int k = 0; k < 10; k += 5)
444 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc, i + k, j, 0), nOriginFlag);
445 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, i + k, j, 0), aOriginMerge);
449 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, 1, 5, 0), ScAddress(2, 4, 0));
450 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, 0, 5, 0), ScAddress(1, 2, 0));
451 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, 4, 6, 0), ScAddress(1, 2, 0));
452 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc, 3, 5, 0), ScAddress(2, 1, 0));
455 static void lcl_clickAndCheckCurrentArea(SCCOL nCol, SCROW nRow, SCCOL nCol2, SCROW nRow2)
457 ScRange aRange;
458 ScDocShell::GetViewData()->SetCurX(nCol);
459 ScDocShell::GetViewData()->SetCurY(nRow);
460 ScDocShell::GetViewData()->GetSimpleArea(aRange);
461 CPPUNIT_ASSERT_EQUAL(aRange, ScRange(nCol, nRow, 0, nCol2, nRow2, 0));
464 void ScCopyPasteTest::testTdf43958_clickSelectOnMergedCells()
466 loadFromURL(u"ods/tdf40993_fillMergedCells.ods");
468 // select cell (e.g. by clicking on it) and check what is selected [but not marked]:
469 // if it is the top left cell of a merged area, the selection is enlarged to the area
470 lcl_clickAndCheckCurrentArea(1, 5, 2, 8); // B6 -> B6:C9
471 lcl_clickAndCheckCurrentArea(0, 5, 0, 6); // A6 -> A6:A7
472 lcl_clickAndCheckCurrentArea(3, 5, 4, 5); // D6 -> D6:E6
473 lcl_clickAndCheckCurrentArea(4, 6, 4, 7); // D7 -> D6:D7
474 lcl_clickAndCheckCurrentArea(7, 10, 8, 10); // H11 -> H11:I11
475 lcl_clickAndCheckCurrentArea(7, 13, 8, 13); // H14 -> H14:I14
477 // otherwise it remains the same
478 lcl_clickAndCheckCurrentArea(0, 7, 0, 7); // A8
479 lcl_clickAndCheckCurrentArea(0, 8, 0, 8); // A9
480 lcl_clickAndCheckCurrentArea(2, 6, 2, 6); // C7
481 lcl_clickAndCheckCurrentArea(2, 7, 2, 7); // C8
482 lcl_clickAndCheckCurrentArea(2, 8, 2, 8); // C9
485 void ScCopyPasteTest::testTdf88782_autofillLinearNumbersInMergedCells()
487 loadFromURL(u"ods/tdf88782_AutofillLinearNumbersInMergedCells.ods");
488 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
489 CPPUNIT_ASSERT(pModelObj);
490 ScDocument* pDoc = pModelObj->GetDocument();
492 // Get the document controller
493 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
495 // merge the yellow cells
496 ScCellMergeOption aMergeOptions(9, 11, 10, 13); //J12:K14
497 aMergeOptions.maTabs.insert(0);
498 ScDocShell* pDocSh = ScDocShell::GetViewData()->GetDocShell();
499 pDocSh->GetDocFunc().MergeCells(aMergeOptions, false, true, true, false);
501 // fillauto numbers, these areas contain mostly merged cells
502 pViewShell->FillAuto(FILL_TO_BOTTOM, 1, 8, 3, 14, 7); // B9:D15 -> B9:D22
503 pViewShell->FillAuto(FILL_TO_BOTTOM, 5, 8, 7, 17, 10); // F9:H18 -> F9:H28
504 pViewShell->FillAuto(FILL_TO_BOTTOM, 9, 8, 10, 13, 6); // J9:K14 -> J9:K20
505 pViewShell->FillAuto(FILL_TO_RIGHT, 9, 30, 16, 35, 8); //J31:Q36 -> J31:Y36
506 pViewShell->FillAuto(FILL_TO_LEFT, 9, 30, 16, 35, 8); //J31:Q36 -> B31:Q36
508 // compare the results of fill-down with the reference stored in the test file
509 // this compares the whole area blindly, for specific test cases, check the test file
510 // the test file have instructions / explanations, so that is easy to understand
511 for (int nCol = 1; nCol <= 10; nCol++)
513 for (int nRow = 8; nRow <= 27; nRow++)
515 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
516 CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 22, nRow, 0));
517 double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0));
518 double* pValue2 = pDoc->GetValueCell(ScAddress(nCol + 22, nRow, 0));
520 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
521 if (pValue2 != nullptr)
522 CPPUNIT_ASSERT_EQUAL(*pValue1, *pValue2); //cells with number value
523 else
524 CPPUNIT_ASSERT_EQUAL(pValue1, pValue2); //empty cells
528 // compare the results of fill-right and left with the reference stored in the test file
529 for (int nCol = 1; nCol <= 24; nCol++)
531 for (int nRow = 30; nRow <= 35; nRow++)
533 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
534 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 16, 0));
535 double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0));
536 double* pValue2 = pDoc->GetValueCell(ScAddress(nCol, nRow + 16, 0));
538 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
539 if (pValue2 != nullptr)
540 CPPUNIT_ASSERT_EQUAL(*pValue1, *pValue2);
541 else
542 CPPUNIT_ASSERT_EQUAL(pValue1, pValue2);
547 void ScCopyPasteTest::tdf137621_autofillMergedBool()
549 loadFromURL(u"ods/tdf137621_autofillMergedBool.ods");
550 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
551 CPPUNIT_ASSERT(pModelObj);
552 ScDocument* pDoc = pModelObj->GetDocument();
554 // Get the document controller
555 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
557 // fillauto booleans, these areas contain only merged cells
558 pViewShell->FillAuto(FILL_TO_RIGHT, 0, 4, 3, 5, 8); //A5:D6
560 // compare the results of fill-right with the reference stored in the test file
561 // this compares the whole area blindly, for specific test cases, check the test file
562 for (int nCol = 4; nCol <= 11; nCol++)
564 for (int nRow = 4; nRow <= 5; nRow++)
566 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
567 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 3, 0));
568 double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0));
569 double* pValue2 = pDoc->GetValueCell(ScAddress(nCol, nRow + 3, 0));
571 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
572 if (pValue2 != nullptr)
573 CPPUNIT_ASSERT_EQUAL(*pValue1, *pValue2); //cells with boolean value
574 else
575 CPPUNIT_ASSERT_EQUAL(pValue1, pValue2); //empty cells
580 void ScCopyPasteTest::tdf137205_autofillDatesInMergedCells()
582 loadFromURL(u"ods/tdf137205_AutofillDatesInMergedCells.ods");
583 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
584 CPPUNIT_ASSERT(pModelObj);
585 ScDocument* pDoc = pModelObj->GetDocument();
587 // Get the document controller
588 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
590 // fillauto dates, this areas contain only merged cells
591 pViewShell->FillAuto(FILL_TO_RIGHT, 1, 5, 4, 7, 8); //B6:E8
593 // compare the results of fill-right with the reference stored in the test file
594 // this compares the whole area blindly, for specific test cases, check the test file
595 for (int nCol = 5; nCol <= 12; nCol++)
597 for (int nRow = 5; nRow <= 7; nRow++)
599 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
600 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 5, 0));
601 double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0));
602 double* pValue2 = pDoc->GetValueCell(ScAddress(nCol, nRow + 5, 0));
604 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
605 if (pValue2 != nullptr)
606 CPPUNIT_ASSERT_EQUAL(*pValue1, *pValue2); //cells with number value
607 else
608 CPPUNIT_ASSERT_EQUAL(pValue1, pValue2); //empty cells
613 void ScCopyPasteTest::addToUserList(const OUString& rStr)
615 ScUserListData* aListData = new ScUserListData(rStr);
616 ScGlobal::GetUserList()->push_back(aListData);
619 void ScCopyPasteTest::tdf137653_137654_autofillUserlist()
621 loadFromURL(u"ods/tdf137653_137654_autofillUserlist.ods");
622 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
623 CPPUNIT_ASSERT(pModelObj);
624 ScDocument* pDoc = pModelObj->GetDocument();
626 // Get the document controller
627 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
629 // delete every userlist to make sure there won't be any string that is in 2 different userlist
630 ScGlobal::GetUserList()->clear();
631 addToUserList({ "January,February,March,April,May,June,July,August,September,October,November,December" });
632 const ScUserListData* pListData = ScGlobal::GetUserList()->GetData("January");
633 sal_uInt16 nIdx1 = 0, nIdx2 = 0;
634 bool bHasIdx1, bHasIdx2;
635 bool bMatchCase = false;
637 // fillauto userlist, these areas contain only merged cells
638 pViewShell->FillAuto(FILL_TO_RIGHT, 4, 5, 6, 7, 3); //E6:G8
639 pViewShell->FillAuto(FILL_TO_LEFT, 4, 5, 6, 7, 3); //E6:G8
640 pViewShell->FillAuto(FILL_TO_BOTTOM, 1, 18, 3, 19, 2); //B19:D20
641 pViewShell->FillAuto(FILL_TO_TOP, 1, 18, 3, 19, 2); //B19:D20
643 // compare the results of fill-right / -left with the reference stored in the test file
644 // this compares the whole area blindly, for specific test cases, check the test file
645 for (int nCol = 1; nCol <= 9; nCol++)
647 for (int nRow = 5; nRow <= 7; nRow++)
649 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
650 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0));
651 bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase);
652 bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow + 4, 0), nIdx2, bMatchCase);
654 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
655 CPPUNIT_ASSERT(bHasIdx1);
656 CPPUNIT_ASSERT(bHasIdx2);
657 CPPUNIT_ASSERT_EQUAL(nIdx1, nIdx2); // userlist index value of cells
661 // compare the results of fill-up / -down
662 for (int nCol = 1; nCol <= 3; nCol++)
664 for (int nRow = 16; nRow <= 21; nRow++)
666 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
667 CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0));
668 bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase);
669 bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol + 4, nRow, 0), nIdx2, bMatchCase);
671 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
672 CPPUNIT_ASSERT(bHasIdx1);
673 CPPUNIT_ASSERT(bHasIdx2);
674 CPPUNIT_ASSERT_EQUAL(nIdx1, nIdx2); // userlist index value of cells
679 void ScCopyPasteTest::tdf113500_autofillMixed()
681 loadFromURL(u"ods/tdf113500_autofillMixed.ods");
682 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
683 CPPUNIT_ASSERT(pModelObj);
684 ScDocument* pDoc = pModelObj->GetDocument();
686 // Get the document controller
687 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
689 // fillauto userlist, these areas contain only merged cells
690 pViewShell->FillAuto(FILL_TO_RIGHT, 4, 5, 6, 7, 3); //E6:G8
691 pViewShell->FillAuto(FILL_TO_LEFT, 4, 5, 6, 7, 3); //E6:G8
692 pViewShell->FillAuto(FILL_TO_BOTTOM, 1, 18, 3, 19, 2); //B19:D20
693 pViewShell->FillAuto(FILL_TO_TOP, 1, 18, 3, 19, 2); //B19:D20
695 // compare the results of fill-right / -left with the reference stored in the test file
696 // this compares the whole area blindly, for specific test cases, check the test file
697 // do not check the 3. row: a1,b2,a3. It is another bug to fix
698 for (int nCol = 1; nCol <= 9; nCol++)
700 for (int nRow = 5; nRow <= 6; nRow++)
702 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
703 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0));
704 OUString aStr1 = pDoc->GetString(nCol, nRow, 0);
705 OUString aStr2 = pDoc->GetString(nCol, nRow + 4, 0);
707 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
708 CPPUNIT_ASSERT_EQUAL(aStr1, aStr2);
712 // compare the results of fill-up / -down
713 // do not check the 2. column: 1st,3rd. It is another bug to fix
714 for (int nCol = 1; nCol <= 3; nCol+=2)
716 for (int nRow = 16; nRow <= 21; nRow++)
718 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
719 CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0));
720 OUString aStr1 = pDoc->GetString(nCol, nRow, 0);
721 OUString aStr2 = pDoc->GetString(nCol + 4, nRow, 0);
723 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
724 CPPUNIT_ASSERT_EQUAL(aStr1, aStr2);
729 void ScCopyPasteTest::tdf137625_autofillMergedUserlist()
731 loadFromURL(u"ods/tdf137625_autofillMergedUserlist.ods");
732 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
733 CPPUNIT_ASSERT(pModelObj);
734 ScDocument* pDoc = pModelObj->GetDocument();
736 // Get the document controller
737 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
739 // delete every userlist to make sure there won't be any string that is in 2 different userlist
740 ScGlobal::GetUserList()->clear();
741 addToUserList({ "January,February,March,April,May,June,July,August,September,October,November,December" });
742 const ScUserListData* pListData = ScGlobal::GetUserList()->GetData("January");
743 sal_uInt16 nIdx1 = 0, nIdx2 = 0;
744 bool bHasIdx1, bHasIdx2;
745 bool bMatchCase = false;
747 // fillauto userlist, these areas contain only merged cells
748 pViewShell->FillAuto(FILL_TO_RIGHT, 7, 5, 12, 7, 6); //H6:M8
749 pViewShell->FillAuto(FILL_TO_LEFT, 7, 5, 12, 7, 6); //H6:M8
750 pViewShell->FillAuto(FILL_TO_BOTTOM, 1, 20, 3, 23, 4); //B21:D24
751 pViewShell->FillAuto(FILL_TO_TOP, 1, 20, 3, 23, 4); //B21:D24
753 // compare the results of fill-right / -left with the reference stored in the test file
754 // this compares the whole area blindly, for specific test cases, check the test file
755 for (int nCol = 1; nCol <= 18; nCol++)
757 for (int nRow = 5; nRow <= 7; nRow++)
759 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
760 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0));
761 bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase);
762 bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow + 4, 0), nIdx2, bMatchCase);
764 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
765 CPPUNIT_ASSERT_EQUAL(bHasIdx1, bHasIdx2);
766 if (bHasIdx1)
767 CPPUNIT_ASSERT_EQUAL(nIdx1, nIdx2); //cells with userlist value
771 // compare the results of fill-up / -down
772 for (int nCol = 1; nCol <= 3; nCol++)
774 for (int nRow = 16; nRow <= 27; nRow++)
776 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
777 CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0));
778 bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase);
779 bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol + 4, nRow, 0), nIdx2, bMatchCase);
781 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
782 CPPUNIT_ASSERT_EQUAL(bHasIdx1, bHasIdx2);
783 if (bHasIdx1)
784 CPPUNIT_ASSERT_EQUAL(nIdx1, nIdx2); //cells with userlist value
789 void ScCopyPasteTest::tdf137624_autofillMergedMixed()
791 loadFromURL(u"ods/tdf137624_autofillMergedMixed.ods");
792 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
793 CPPUNIT_ASSERT(pModelObj);
794 ScDocument* pDoc = pModelObj->GetDocument();
796 // Get the document controller
797 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
799 // add 1aa,2bb,3cc,4dd,5ee,6ff to userlist, to test that autofill won't confuse it with 1aa,3aa
800 // delete every userlist to make sure there won't be any string that is in 2 different userlist
801 ScGlobal::GetUserList()->clear();
802 addToUserList({ "1aa,2bb,3cc,4dd,5ee,6ff" });
804 // fillauto mixed (string + number), these areas contain only merged cells
805 pViewShell->FillAuto(FILL_TO_RIGHT, 7, 5, 12, 7, 6); //H6:M8
806 pViewShell->FillAuto(FILL_TO_LEFT, 7, 5, 12, 7, 6); //H6:M8
807 pViewShell->FillAuto(FILL_TO_BOTTOM, 1, 20, 3, 23, 4); //B21:D24
808 pViewShell->FillAuto(FILL_TO_TOP, 1, 20, 3, 23, 4); //B21:D24
810 // compare the results of fill-right / -left with the reference stored in the test file
811 // this compares the whole area blindly, for specific test cases, check the test file
812 for (int nCol = 1; nCol <= 18; nCol++)
814 for (int nRow = 5; nRow <= 7; nRow++)
816 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
817 CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0));
818 OUString aStr1 = pDoc->GetString(nCol, nRow, 0);
819 OUString aStr2 = pDoc->GetString(nCol, nRow + 4, 0);
821 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
822 CPPUNIT_ASSERT_EQUAL(aStr1, aStr2);
826 // compare the results of fill-up / -down
827 for (int nCol = 1; nCol <= 3; nCol++)
829 for (int nRow = 16; nRow <= 27; nRow++)
831 CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0));
832 CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0));
833 OUString aStr1 = pDoc->GetString(nCol, nRow, 0);
834 OUString aStr2 = pDoc->GetString(nCol + 4, nRow, 0);
836 CPPUNIT_ASSERT_EQUAL(nType1, nType2);
837 CPPUNIT_ASSERT_EQUAL(aStr1, aStr2);
842 ScCopyPasteTest::ScCopyPasteTest()
843 : UnoApiTest("/sc/qa/unit/data/")
847 CPPUNIT_TEST_SUITE_REGISTRATION(ScCopyPasteTest);
849 CPPUNIT_PLUGIN_IMPLEMENT();
851 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */