1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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>
17 #include <comphelper/servicehelper.hxx>
20 #include <docfunc.hxx>
21 #include <cellmergeoption.hxx>
22 #include <tabvwsh.hxx>
24 #include <scitems.hxx>
26 #include <userlist.hxx>
27 #include <undomanager.hxx>
29 using namespace ::com::sun::star
;
30 using namespace ::com::sun::star::uno
;
32 class ScCopyPasteTest
: public UnoApiTest
37 void testCopyPasteXLS();
42 void testTdf53431_fillOnAutofilter();
43 void testTdf40993_fillMergedCells();
44 void testTdf43958_clickSelectOnMergedCells();
45 void testTdf88782_autofillLinearNumbersInMergedCells();
46 void tdf137621_autofillMergedBool();
47 void tdf137205_autofillDatesInMergedCells();
48 void tdf137653_137654_autofillUserlist();
49 void tdf113500_autofillMixed();
50 void tdf137625_autofillMergedUserlist();
51 void tdf137624_autofillMergedMixed();
53 CPPUNIT_TEST_SUITE(ScCopyPasteTest
);
54 CPPUNIT_TEST(testCopyPasteXLS
);
55 CPPUNIT_TEST(testTdf84411
);
56 CPPUNIT_TEST(testTdf124565
);
57 CPPUNIT_TEST(testTdf126421
);
58 CPPUNIT_TEST(testTdf107394
);
59 CPPUNIT_TEST(testTdf53431_fillOnAutofilter
);
60 CPPUNIT_TEST(testTdf40993_fillMergedCells
);
61 CPPUNIT_TEST(testTdf43958_clickSelectOnMergedCells
);
62 CPPUNIT_TEST(testTdf88782_autofillLinearNumbersInMergedCells
);
63 CPPUNIT_TEST(tdf137621_autofillMergedBool
);
64 CPPUNIT_TEST(tdf137205_autofillDatesInMergedCells
);
65 CPPUNIT_TEST(tdf137653_137654_autofillUserlist
);
66 CPPUNIT_TEST(tdf113500_autofillMixed
);
67 CPPUNIT_TEST(tdf137625_autofillMergedUserlist
);
68 CPPUNIT_TEST(tdf137624_autofillMergedMixed
);
69 CPPUNIT_TEST_SUITE_END();
72 void addToUserList(const OUString
& rStr
);
76 void ScCopyPasteTest::testCopyPasteXLS()
78 loadFromFile(u
"xls/chartx2.xls");
80 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
81 CPPUNIT_ASSERT(pModelObj
);
82 ScDocument
* pDoc
= pModelObj
->GetDocument();
84 // Get the document controller
85 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
89 ScRefFlags nRes
= aSrcRange
.Parse("B2:C5", *pDoc
, pDoc
->GetAddressConvention());
90 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes
& ScRefFlags::VALID
));
92 ScMarkData
aMark(pDoc
->GetSheetLimits());
93 aMark
.SetMarkArea(aSrcRange
);
95 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
98 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
99 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, false, false);
101 // 4. Close the document (Ctrl-W)
102 mxComponent
->dispose();
105 // Open a new document
106 mxComponent
= loadFromDesktop("private:factory/scalc");
108 // Get the document controller
109 pViewShell
= ScDocShell::GetViewData()->GetViewShell();
112 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
117 ScMarkData::MarkedTabsType
TabsInRange(const ScRange
& r
)
119 ScMarkData::MarkedTabsType aResult
;
120 for (SCTAB i
= r
.aStart
.Tab(); i
<= r
.aEnd
.Tab(); ++i
)
125 void lcl_copy( const OUString
& rSrcRange
, const OUString
& rDstRange
, ScDocument
& rDoc
, ScTabViewShell
* pViewShell
)
127 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
131 ScRefFlags nRes
= aSrcRange
.Parse(rSrcRange
, rDoc
, rDoc
.GetAddressConvention());
132 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes
& ScRefFlags::VALID
));
133 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
134 pViewShell
->GetViewData().GetMarkData().SetSelectedTabs(TabsInRange(aSrcRange
));
135 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, false, false);
139 nRes
= aDstRange
.Parse(rDstRange
, rDoc
, rDoc
.GetAddressConvention());
140 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes
& ScRefFlags::VALID
));
141 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aDstRange
);
142 pViewShell
->GetViewData().GetMarkData().SetSelectedTabs(TabsInRange(aDstRange
));
143 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
146 } // anonymous namespace
148 void ScCopyPasteTest::testTdf84411()
150 mxComponent
= loadFromDesktop("private:factory/scalc");
152 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
153 CPPUNIT_ASSERT(pModelObj
);
154 ScDocument
* pDoc
= pModelObj
->GetDocument();
156 // Get the document controller
157 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
159 // 2. Setup data and formulas
160 for (unsigned int r
= 0; r
<= 4991; ++r
)
161 for (unsigned int c
= 0; c
<= 14; ++c
)
162 pDoc
->SetValue( ScAddress(c
,r
,0), (r
+1)*(c
+1) );
164 pDoc
->SetString(ScAddress(15,10000,0), "=AVERAGE(A10001:O10001)");
165 pDoc
->SetString(ScAddress(16,10000,0), "=MIN(A10001:O10001)");
166 pDoc
->SetString(ScAddress(17,10000,0), "=MAX(A10001:O10001)");
168 lcl_copy("P10001:R10001", "P10002:R12500", *pDoc
, pViewShell
);
172 bool bOpenCLState
= ScCalcConfig::isOpenCLEnabled();
173 pModelObj
->enableOpenCL(false);
174 CPPUNIT_ASSERT(!ScCalcConfig::isOpenCLEnabled() || ScCalcConfig::getForceCalculationType() == ForceCalculationOpenCL
);
175 pModelObj
->enableAutomaticCalculation(true);
179 lcl_copy("A1:O2500", "A10001:O12500", *pDoc
, pViewShell
);
181 lcl_copy("A2501:O5000", "A12501:O15000", *pDoc
, pViewShell
);
183 lcl_copy("P10001:R10001", "P12501:R15000", *pDoc
, pViewShell
);
186 // 5. Close the document (Ctrl-W)
187 pModelObj
->enableOpenCL(bOpenCLState
);
190 void ScCopyPasteTest::testTdf124565()
192 mxComponent
= loadFromDesktop("private:factory/scalc");
194 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
195 CPPUNIT_ASSERT(pModelObj
);
196 ScDocument
* pDoc
= pModelObj
->GetDocument();
198 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
200 // Set content and height of first row
201 pDoc
->SetString(ScAddress(0, 0, 0), "Test");
202 pDoc
->SetRowHeight(0, 0, 500);
203 pDoc
->SetManualHeight(0, 0, 0, true);
206 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
207 ScRange
aCopyRange(0, 0, 0, aClipDoc
.MaxCol(), 0, 0);
208 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aCopyRange
);
209 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, false, false);
211 // Paste to second row
216 ScRange
aPasteRange(nCol
, nRow
, nTab
, aClipDoc
.MaxCol(), nRow
, nTab
);
217 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aPasteRange
);
218 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
221 CPPUNIT_ASSERT_EQUAL_MESSAGE("String was not pasted!", OUString("Test"), pDoc
->GetString(nCol
, nRow
, nTab
));
223 // And height same as in source?
224 CPPUNIT_ASSERT_EQUAL_MESSAGE("Row#2 height is invalid!", sal_uInt16(500), pDoc
->GetRowHeight(nRow
, nTab
));
226 CPPUNIT_ASSERT_MESSAGE("Row#2 must be manual height!", pDoc
->IsManualRowHeight(nRow
, nTab
));
229 void ScCopyPasteTest::testTdf126421()
231 mxComponent
= loadFromDesktop("private:factory/scalc");
233 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
234 CPPUNIT_ASSERT(pModelObj
);
235 ScDocument
* pDoc
= pModelObj
->GetDocument();
237 // Get the document controller
238 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
241 for (int r
= 0; r
< 2; ++r
)
242 for (int c
= 0; c
< 1024; ++c
)
243 pDoc
->SetValue(c
, r
, 0, (c
+ 1) * 100 + (r
+ 1));
245 const SCTAB n2ndTab
= pDoc
->GetMaxTableNumber() + 1;
246 pDoc
->MakeTable(n2ndTab
);
247 const auto aTabNames
= pDoc
->GetAllTableNames();
249 lcl_copy(aTabNames
[0] + ".A1:AMJ2", aTabNames
[n2ndTab
] + ".A1:AMJ2", *pDoc
, pViewShell
);
251 // 3. Check all cells in destination table
252 for (int r
= 0; r
< 2; ++r
)
253 for (int c
= 0; c
< 1024; ++c
)
254 CPPUNIT_ASSERT_EQUAL(double((c
+ 1) * 100 + (r
+ 1)), pDoc
->GetValue(c
, r
, n2ndTab
));
257 void ScCopyPasteTest::testTdf107394()
259 mxComponent
= loadFromDesktop("private:factory/scalc");
261 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
262 CPPUNIT_ASSERT(pModelObj
);
263 ScDocument
* pDoc
= pModelObj
->GetDocument();
265 sal_uInt16 nFirstRowHeight
= pDoc
->GetRowHeight(0, 0);
266 sal_uInt16 nSecondRowHeight
= pDoc
->GetRowHeight(1, 0);
267 CPPUNIT_ASSERT_EQUAL(nFirstRowHeight
, nSecondRowHeight
);
269 // Import values to A1:A2.
270 ScImportExport
aObj(*pDoc
, ScAddress(0,0,0));
271 aObj
.SetImportBroadcast(true);
273 SvMemoryStream aStream
;
274 aStream
.WriteOString("<pre>First\nVery long sentence.</pre>");
276 CPPUNIT_ASSERT(aObj
.ImportStream(aStream
, OUString(), SotClipboardFormatId::HTML
));
278 CPPUNIT_ASSERT_EQUAL(OUString("First"), pDoc
->GetString(ScAddress(0,0,0)));
279 CPPUNIT_ASSERT_EQUAL(OUString("Very long sentence."), pDoc
->GetString(ScAddress(0,1,0)));
281 nFirstRowHeight
= pDoc
->GetRowHeight(0, 0);
282 nSecondRowHeight
= pDoc
->GetRowHeight(1, 0);
283 CPPUNIT_ASSERT_GREATER(nFirstRowHeight
, nSecondRowHeight
);
285 // Undo, and check the result.
286 SfxUndoManager
* pUndoMgr
= pDoc
->GetUndoManager();
287 CPPUNIT_ASSERT_MESSAGE("Failed to get the undo manager.", pUndoMgr
);
290 CPPUNIT_ASSERT(pDoc
->GetString(ScAddress(0,0,0)).isEmpty());
291 CPPUNIT_ASSERT(pDoc
->GetString(ScAddress(0,1,0)).isEmpty());
293 nFirstRowHeight
= pDoc
->GetRowHeight(0, 0);
294 nSecondRowHeight
= pDoc
->GetRowHeight(1, 0);
295 // Without the accompanying fix in place, this test would have failed:
298 // i.e. the increased height of the second row remained after undo.
299 CPPUNIT_ASSERT_EQUAL(nFirstRowHeight
, nSecondRowHeight
);
302 static ScMF
lcl_getMergeFlagOfCell(const ScDocument
& rDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
304 const SfxPoolItem
& rPoolItem
= rDoc
.GetPattern(nCol
, nRow
, nTab
)->GetItem(ATTR_MERGE_FLAG
);
305 const ScMergeFlagAttr
& rMergeFlag
= static_cast<const ScMergeFlagAttr
&>(rPoolItem
);
306 return rMergeFlag
.GetValue();
309 static ScAddress
lcl_getMergeSizeOfCell(const ScDocument
& rDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
311 const SfxPoolItem
& rPoolItem
= rDoc
.GetPattern(nCol
, nRow
, nTab
)->GetItem(ATTR_MERGE
);
312 const ScMergeAttr
& rMerge
= static_cast<const ScMergeAttr
&>(rPoolItem
);
313 return ScAddress(rMerge
.GetColMerge(), rMerge
.GetRowMerge(), nTab
);
316 void ScCopyPasteTest::testTdf53431_fillOnAutofilter()
318 loadFromFile(u
"ods/tdf53431_autofilterFilldown.ods");
319 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
320 CPPUNIT_ASSERT(pModelObj
);
321 ScDocument
* pDoc
= pModelObj
->GetDocument();
323 // Get the document controller
324 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
326 //Fill should not clone Autofilter button
327 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 2, 4, 0));
328 pViewShell
->FillSimple(FILL_TO_BOTTOM
);
329 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
330 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
331 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
333 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 4, 4, 0));
334 pViewShell
->FillSimple(FILL_TO_RIGHT
);
335 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
336 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
337 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 1, 0) & ScMF::Auto
));
338 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
339 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 4, 0) & ScMF::Auto
));
341 //Fill should not delete Autofilter buttons
342 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 0, 0, 2, 4, 0));
343 pViewShell
->FillSimple(FILL_TO_TOP
);
344 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
345 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
346 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 0, 0) & ScMF::Auto
));
348 //Fill should not clone Autofilter button
349 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 2, 4, 0));
350 pViewShell
->FillSimple(FILL_TO_BOTTOM
);
351 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
352 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
353 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
355 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(1, 1, 0, 4, 4, 0));
356 pViewShell
->FillSimple(FILL_TO_RIGHT
);
357 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
358 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
359 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 1, 0) & ScMF::Auto
));
360 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
361 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 4, 0) & ScMF::Auto
));
363 //Fill should not delete Autofilter buttons
364 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 0, 0, 2, 4, 0));
365 pViewShell
->FillSimple(FILL_TO_TOP
);
366 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
367 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
368 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 0, 0) & ScMF::Auto
));
370 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 0, 0, 4, 4, 0));
371 pViewShell
->FillSimple(FILL_TO_LEFT
);
372 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
373 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
374 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 0, 1, 0) & ScMF::Auto
));
377 void ScCopyPasteTest::testTdf40993_fillMergedCells()
379 loadFromFile(u
"ods/tdf40993_fillMergedCells.ods");
380 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
381 CPPUNIT_ASSERT(pModelObj
);
382 ScDocument
* pDoc
= pModelObj
->GetDocument();
384 // Get the document controller
385 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
387 // check content of the merged cell H11:I11
388 CPPUNIT_ASSERT_EQUAL(OUString("1.5"), pDoc
->GetString(ScAddress(7, 10, 0)));
390 // fill operation on the merged cell should clone ATTR_MERGE and ATTR_MERGE_FLAG
391 // (as long as ATTR_MERGE_FLAG has only ScMF::Hor or ScMF::Ver)
393 // select merged cell
394 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(7, 10, 0, 8, 10, 0));
395 // copy its content in the next ten rows
396 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 7, 10, 8, 10, 10);
397 for (int i
= 7; i
< 9; i
++)
399 ScMF nOriginFlag
= lcl_getMergeFlagOfCell(*pDoc
, i
, 10, 0);
400 ScAddress aOriginMerge
= lcl_getMergeSizeOfCell(*pDoc
, i
, 10, 0);
402 // ATTR_MERGE_FLAG: top left cell is NONE, the other cell shows horizontal overlapping
403 CPPUNIT_ASSERT_EQUAL(i
== 7 ? ScMF::NONE
: ScMF::Hor
, nOriginFlag
);
405 // ATTR_MERGE: top left cell contains the size of the
406 // merged area (2:1), the other cell doesn't
407 CPPUNIT_ASSERT_EQUAL(i
== 7 ? ScAddress(2, 1, 0): ScAddress(0, 0, 0), aOriginMerge
);
409 for (int j
= 11; j
< 21; j
++)
411 // check copying of ATTR_MERGE and ATTR_MERGE_FLAG
412 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, i
, j
, 0), nOriginFlag
);
413 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, i
, j
, 0), aOriginMerge
);
417 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, 7, 21, 0),
418 lcl_getMergeFlagOfCell(*pDoc
, 7, 10, 0));
419 CPPUNIT_ASSERT(lcl_getMergeSizeOfCell(*pDoc
, 7, 21, 0) !=
420 lcl_getMergeSizeOfCell(*pDoc
, 7, 10, 0));
421 CPPUNIT_ASSERT(lcl_getMergeFlagOfCell(*pDoc
, 8, 21, 0) !=
422 lcl_getMergeFlagOfCell(*pDoc
, 8, 10, 0));
423 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 8, 21, 0),
424 lcl_getMergeSizeOfCell(*pDoc
, 8, 10, 0));
426 // area A6:E9 with various merged cells copied vertically and horizontally
427 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 5, 0, 4, 8, 0));
428 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 0, 5, 4, 8, 12);
429 ScDocShell::GetViewData()->GetMarkData().SetMarkArea(ScRange(0, 5, 0, 4, 8, 0));
430 pViewShell
->FillAuto(FILL_TO_RIGHT
, 0, 5, 4, 8, 10);
431 for (int i
= 0; i
< 5; i
++)
433 for (int j
= 5; j
< 9; j
++)
435 ScMF nOriginFlag
= lcl_getMergeFlagOfCell(*pDoc
, i
, j
, 0);
436 ScAddress aOriginMerge
= lcl_getMergeSizeOfCell(*pDoc
, i
, j
, 0);
437 // copies contain the same ATTR_MERGE and ATTR_MERGE_FLAG
438 for (int k
= 0; k
< 12; k
+= 4)
440 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, i
, j
+ k
, 0), nOriginFlag
);
441 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, i
, j
+ k
, 0), aOriginMerge
);
443 for (int k
= 0; k
< 10; k
+= 5)
445 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, i
+ k
, j
, 0), nOriginFlag
);
446 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, i
+ k
, j
, 0), aOriginMerge
);
450 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 1, 5, 0), ScAddress(2, 4, 0));
451 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 0, 5, 0), ScAddress(1, 2, 0));
452 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 4, 6, 0), ScAddress(1, 2, 0));
453 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 3, 5, 0), ScAddress(2, 1, 0));
456 static void lcl_clickAndCheckCurrentArea(SCCOL nCol
, SCROW nRow
, SCCOL nCol2
, SCROW nRow2
)
459 ScDocShell::GetViewData()->SetCurX(nCol
);
460 ScDocShell::GetViewData()->SetCurY(nRow
);
461 ScDocShell::GetViewData()->GetSimpleArea(aRange
);
462 CPPUNIT_ASSERT_EQUAL(aRange
, ScRange(nCol
, nRow
, 0, nCol2
, nRow2
, 0));
465 void ScCopyPasteTest::testTdf43958_clickSelectOnMergedCells()
467 loadFromFile(u
"ods/tdf40993_fillMergedCells.ods");
469 // select cell (e.g. by clicking on it) and check what is selected [but not marked]:
470 // if it is the top left cell of a merged area, the selection is enlarged to the area
471 lcl_clickAndCheckCurrentArea(1, 5, 2, 8); // B6 -> B6:C9
472 lcl_clickAndCheckCurrentArea(0, 5, 0, 6); // A6 -> A6:A7
473 lcl_clickAndCheckCurrentArea(3, 5, 4, 5); // D6 -> D6:E6
474 lcl_clickAndCheckCurrentArea(4, 6, 4, 7); // D7 -> D6:D7
475 lcl_clickAndCheckCurrentArea(7, 10, 8, 10); // H11 -> H11:I11
476 lcl_clickAndCheckCurrentArea(7, 13, 8, 13); // H14 -> H14:I14
478 // otherwise it remains the same
479 lcl_clickAndCheckCurrentArea(0, 7, 0, 7); // A8
480 lcl_clickAndCheckCurrentArea(0, 8, 0, 8); // A9
481 lcl_clickAndCheckCurrentArea(2, 6, 2, 6); // C7
482 lcl_clickAndCheckCurrentArea(2, 7, 2, 7); // C8
483 lcl_clickAndCheckCurrentArea(2, 8, 2, 8); // C9
486 void ScCopyPasteTest::testTdf88782_autofillLinearNumbersInMergedCells()
488 loadFromFile(u
"ods/tdf88782_AutofillLinearNumbersInMergedCells.ods");
489 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
490 CPPUNIT_ASSERT(pModelObj
);
491 ScDocument
* pDoc
= pModelObj
->GetDocument();
493 // Get the document controller
494 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
496 // merge the yellow cells
497 ScCellMergeOption
aMergeOptions(9, 11, 10, 13); //J12:K14
498 aMergeOptions
.maTabs
.insert(0);
499 ScDocShell
* pDocSh
= ScDocShell::GetViewData()->GetDocShell();
500 pDocSh
->GetDocFunc().MergeCells(aMergeOptions
, false, true, true, false);
502 // fillauto numbers, these areas contain mostly merged cells
503 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 1, 8, 3, 14, 7); // B9:D15 -> B9:D22
504 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 5, 8, 7, 17, 10); // F9:H18 -> F9:H28
505 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 9, 8, 10, 13, 6); // J9:K14 -> J9:K20
506 pViewShell
->FillAuto(FILL_TO_RIGHT
, 9, 30, 16, 35, 8); //J31:Q36 -> J31:Y36
507 pViewShell
->FillAuto(FILL_TO_LEFT
, 9, 30, 16, 35, 8); //J31:Q36 -> B31:Q36
509 // compare the results of fill-down with the reference stored in the test file
510 // this compares the whole area blindly, for specific test cases, check the test file
511 // the test file have instructions / explanations, so that is easy to understand
512 for (int nCol
= 1; nCol
<= 10; nCol
++)
514 for (int nRow
= 8; nRow
<= 27; nRow
++)
516 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
517 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
+ 22, nRow
, 0));
518 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
519 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
+ 22, nRow
, 0));
521 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
522 if (pValue2
!= nullptr)
523 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
); //cells with number value
525 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
); //empty cells
529 // compare the results of fill-right and left with the reference stored in the test file
530 for (int nCol
= 1; nCol
<= 24; nCol
++)
532 for (int nRow
= 30; nRow
<= 35; nRow
++)
534 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
535 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 16, 0));
536 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
537 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
+ 16, 0));
539 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
540 if (pValue2
!= nullptr)
541 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
);
543 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
);
548 void ScCopyPasteTest::tdf137621_autofillMergedBool()
550 loadFromFile(u
"ods/tdf137621_autofillMergedBool.ods");
551 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
552 CPPUNIT_ASSERT(pModelObj
);
553 ScDocument
* pDoc
= pModelObj
->GetDocument();
555 // Get the document controller
556 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
558 // fillauto booleans, these areas contain only merged cells
559 pViewShell
->FillAuto(FILL_TO_RIGHT
, 0, 4, 3, 5, 8); //A5:D6
561 // compare the results of fill-right with the reference stored in the test file
562 // this compares the whole area blindly, for specific test cases, check the test file
563 for (int nCol
= 4; nCol
<= 11; nCol
++)
565 for (int nRow
= 4; nRow
<= 5; nRow
++)
567 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
568 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 3, 0));
569 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
570 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
+ 3, 0));
572 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
573 if (pValue2
!= nullptr)
574 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
); //cells with boolean value
576 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
); //empty cells
581 void ScCopyPasteTest::tdf137205_autofillDatesInMergedCells()
583 loadFromFile(u
"ods/tdf137205_AutofillDatesInMergedCells.ods");
584 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
585 CPPUNIT_ASSERT(pModelObj
);
586 ScDocument
* pDoc
= pModelObj
->GetDocument();
588 // Get the document controller
589 ScTabViewShell
* pViewShell
= ScDocShell::GetViewData()->GetViewShell();
591 // fillauto dates, this areas contain only merged cells
592 pViewShell
->FillAuto(FILL_TO_RIGHT
, 1, 5, 4, 7, 8); //B6:E8
594 // compare the results of fill-right with the reference stored in the test file
595 // this compares the whole area blindly, for specific test cases, check the test file
596 for (int nCol
= 5; nCol
<= 12; nCol
++)
598 for (int nRow
= 5; nRow
<= 7; nRow
++)
600 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
601 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 5, 0));
602 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
603 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
+ 5, 0));
605 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
606 if (pValue2
!= nullptr)
607 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
); //cells with number value
609 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
); //empty cells
614 void ScCopyPasteTest::addToUserList(const OUString
& rStr
)
616 ScGlobal::GetUserList()->emplace_back(rStr
);
619 void ScCopyPasteTest::tdf137653_137654_autofillUserlist()
621 loadFromFile(u
"ods/tdf137653_137654_autofillUserlist.ods");
622 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
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 loadFromFile(u
"ods/tdf113500_autofillMixed.ods");
682 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
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 loadFromFile(u
"ods/tdf137625_autofillMergedUserlist.ods");
732 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
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
);
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
);
784 CPPUNIT_ASSERT_EQUAL(nIdx1
, nIdx2
); //cells with userlist value
789 void ScCopyPasteTest::tdf137624_autofillMergedMixed()
791 loadFromFile(u
"ods/tdf137624_autofillMergedMixed.ods");
792 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
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: */