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 "helper/qahelper.hxx"
13 #include <comphelper/servicehelper.hxx>
16 #include <docfunc.hxx>
17 #include <cellmergeoption.hxx>
18 #include <tabvwsh.hxx>
20 #include <scitems.hxx>
22 #include <userlist.hxx>
23 #include <undomanager.hxx>
25 using namespace ::com::sun::star
;
26 using namespace ::com::sun::star::uno
;
28 class ScCopyPasteTest
: public ScModelTestBase
33 void testCopyPasteXLS();
38 void testTdf53431_fillOnAutofilter();
39 void testTdf40993_fillMergedCells();
40 void testTdf43958_clickSelectOnMergedCells();
41 void testTdf88782_autofillLinearNumbersInMergedCells();
42 void tdf137621_autofillMergedBool();
43 void tdf137205_autofillDatesInMergedCells();
44 void tdf137653_137654_autofillUserlist();
45 void tdf113500_autofillMixed();
46 void tdf137625_autofillMergedUserlist();
47 void tdf137624_autofillMergedMixed();
48 void tdf122716_rtf_portion_encoding();
50 CPPUNIT_TEST_SUITE(ScCopyPasteTest
);
51 CPPUNIT_TEST(testCopyPasteXLS
);
52 CPPUNIT_TEST(testTdf84411
);
53 CPPUNIT_TEST(testTdf124565
);
54 CPPUNIT_TEST(testTdf126421
);
55 CPPUNIT_TEST(testTdf107394
);
56 CPPUNIT_TEST(testTdf53431_fillOnAutofilter
);
57 CPPUNIT_TEST(testTdf40993_fillMergedCells
);
58 CPPUNIT_TEST(testTdf43958_clickSelectOnMergedCells
);
59 CPPUNIT_TEST(testTdf88782_autofillLinearNumbersInMergedCells
);
60 CPPUNIT_TEST(tdf137621_autofillMergedBool
);
61 CPPUNIT_TEST(tdf137205_autofillDatesInMergedCells
);
62 CPPUNIT_TEST(tdf137653_137654_autofillUserlist
);
63 CPPUNIT_TEST(tdf113500_autofillMixed
);
64 CPPUNIT_TEST(tdf137625_autofillMergedUserlist
);
65 CPPUNIT_TEST(tdf137624_autofillMergedMixed
);
66 CPPUNIT_TEST(tdf122716_rtf_portion_encoding
);
67 CPPUNIT_TEST_SUITE_END();
70 void addToUserList(const OUString
& rStr
);
74 void ScCopyPasteTest::testCopyPasteXLS()
76 createScDoc("xls/chartx2.xls");
77 ScDocument
* pDoc
= getScDoc();
78 ScTabViewShell
* pViewShell
= getViewShell();
82 ScRefFlags nRes
= aSrcRange
.Parse(u
"B2:C5"_ustr
, *pDoc
, pDoc
->GetAddressConvention());
83 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes
& ScRefFlags::VALID
));
85 ScMarkData
aMark(pDoc
->GetSheetLimits());
86 aMark
.SetMarkArea(aSrcRange
);
88 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
91 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
92 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, false, false);
94 // Open a new document
97 pViewShell
= getViewShell();
100 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
105 ScMarkData::MarkedTabsType
TabsInRange(const ScRange
& r
)
107 ScMarkData::MarkedTabsType aResult
;
108 for (SCTAB i
= r
.aStart
.Tab(); i
<= r
.aEnd
.Tab(); ++i
)
113 void lcl_copy( const OUString
& rSrcRange
, const OUString
& rDstRange
, ScDocument
& rDoc
, ScTabViewShell
* pViewShell
)
115 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
119 ScRefFlags nRes
= aSrcRange
.Parse(rSrcRange
, rDoc
, rDoc
.GetAddressConvention());
120 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes
& ScRefFlags::VALID
));
121 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aSrcRange
);
122 pViewShell
->GetViewData().GetMarkData().SetSelectedTabs(TabsInRange(aSrcRange
));
123 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, false, false);
127 nRes
= aDstRange
.Parse(rDstRange
, rDoc
, rDoc
.GetAddressConvention());
128 CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes
& ScRefFlags::VALID
));
129 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aDstRange
);
130 pViewShell
->GetViewData().GetMarkData().SetSelectedTabs(TabsInRange(aDstRange
));
131 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
134 } // anonymous namespace
136 void ScCopyPasteTest::testTdf84411()
139 ScDocument
* pDoc
= getScDoc();
140 ScTabViewShell
* pViewShell
= getViewShell();
142 // 2. Setup data and formulas
143 for (unsigned int r
= 0; r
<= 4991; ++r
)
144 for (unsigned int c
= 0; c
<= 14; ++c
)
145 pDoc
->SetValue( ScAddress(c
,r
,0), (r
+1)*(c
+1) );
147 pDoc
->SetString(ScAddress(15,10000,0), u
"=AVERAGE(A10001:O10001)"_ustr
);
148 pDoc
->SetString(ScAddress(16,10000,0), u
"=MIN(A10001:O10001)"_ustr
);
149 pDoc
->SetString(ScAddress(17,10000,0), u
"=MAX(A10001:O10001)"_ustr
);
151 lcl_copy(u
"P10001:R10001"_ustr
, u
"P10002:R12500"_ustr
, *pDoc
, pViewShell
);
155 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
156 CPPUNIT_ASSERT(pModelObj
);
157 bool bOpenCLState
= ScCalcConfig::isOpenCLEnabled();
158 pModelObj
->enableOpenCL(false);
159 CPPUNIT_ASSERT(!ScCalcConfig::isOpenCLEnabled() || ScCalcConfig::getForceCalculationType() == ForceCalculationOpenCL
);
160 pModelObj
->enableAutomaticCalculation(true);
164 lcl_copy(u
"A1:O2500"_ustr
, u
"A10001:O12500"_ustr
, *pDoc
, pViewShell
);
166 lcl_copy(u
"A2501:O5000"_ustr
, u
"A12501:O15000"_ustr
, *pDoc
, pViewShell
);
168 lcl_copy(u
"P10001:R10001"_ustr
, u
"P12501:R15000"_ustr
, *pDoc
, pViewShell
);
171 // 5. Close the document (Ctrl-W)
172 pModelObj
->enableOpenCL(bOpenCLState
);
175 void ScCopyPasteTest::testTdf124565()
178 ScDocument
* pDoc
= getScDoc();
179 ScTabViewShell
* pViewShell
= getViewShell();
181 // Set content and height of first row
182 pDoc
->SetString(ScAddress(0, 0, 0), u
"Test"_ustr
);
183 pDoc
->SetRowHeight(0, 0, 500);
184 pDoc
->SetManualHeight(0, 0, 0, true);
187 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
188 ScRange
aCopyRange(0, 0, 0, aClipDoc
.MaxCol(), 0, 0);
189 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aCopyRange
);
190 pViewShell
->GetViewData().GetView()->CopyToClip(&aClipDoc
, false, false, false, false);
192 // Paste to second row
197 ScRange
aPasteRange(nCol
, nRow
, nTab
, aClipDoc
.MaxCol(), nRow
, nTab
);
198 pViewShell
->GetViewData().GetMarkData().SetMarkArea(aPasteRange
);
199 pViewShell
->GetViewData().GetView()->PasteFromClip(InsertDeleteFlags::ALL
, &aClipDoc
);
202 CPPUNIT_ASSERT_EQUAL_MESSAGE("String was not pasted!", u
"Test"_ustr
, pDoc
->GetString(nCol
, nRow
, nTab
));
204 // And height same as in source?
205 CPPUNIT_ASSERT_EQUAL_MESSAGE("Row#2 height is invalid!", sal_uInt16(500), pDoc
->GetRowHeight(nRow
, nTab
));
207 CPPUNIT_ASSERT_MESSAGE("Row#2 must be manual height!", pDoc
->IsManualRowHeight(nRow
, nTab
));
210 void ScCopyPasteTest::testTdf126421()
213 ScDocument
* pDoc
= getScDoc();
214 ScTabViewShell
* pViewShell
= getViewShell();
217 for (int r
= 0; r
< 2; ++r
)
218 for (int c
= 0; c
< 1024; ++c
)
219 pDoc
->SetValue(c
, r
, 0, (c
+ 1) * 100 + (r
+ 1));
221 const SCTAB n2ndTab
= pDoc
->GetMaxTableNumber() + 1;
222 pDoc
->MakeTable(n2ndTab
);
223 const auto aTabNames
= pDoc
->GetAllTableNames();
225 lcl_copy(aTabNames
[0] + ".A1:AMJ2", aTabNames
[n2ndTab
] + ".A1:AMJ2", *pDoc
, pViewShell
);
227 // 3. Check all cells in destination table
228 for (int r
= 0; r
< 2; ++r
)
229 for (int c
= 0; c
< 1024; ++c
)
230 CPPUNIT_ASSERT_EQUAL(double((c
+ 1) * 100 + (r
+ 1)), pDoc
->GetValue(c
, r
, n2ndTab
));
233 void ScCopyPasteTest::testTdf107394()
236 ScDocument
* pDoc
= getScDoc();
238 sal_uInt16 nFirstRowHeight
= pDoc
->GetRowHeight(0, 0);
239 sal_uInt16 nSecondRowHeight
= pDoc
->GetRowHeight(1, 0);
240 CPPUNIT_ASSERT_EQUAL(nFirstRowHeight
, nSecondRowHeight
);
242 // Import values to A1:A2.
243 ScImportExport
aObj(*pDoc
, ScAddress(0,0,0));
244 aObj
.SetImportBroadcast(true);
246 SvMemoryStream aStream
;
247 aStream
.WriteOString("<pre>First\nVery long sentence.</pre>");
249 CPPUNIT_ASSERT(aObj
.ImportStream(aStream
, OUString(), SotClipboardFormatId::HTML
));
251 CPPUNIT_ASSERT_EQUAL(u
"First"_ustr
, pDoc
->GetString(ScAddress(0,0,0)));
252 CPPUNIT_ASSERT_EQUAL(u
"Very long sentence."_ustr
, pDoc
->GetString(ScAddress(0,1,0)));
254 nFirstRowHeight
= pDoc
->GetRowHeight(0, 0);
255 nSecondRowHeight
= pDoc
->GetRowHeight(1, 0);
256 CPPUNIT_ASSERT_GREATER(nFirstRowHeight
, nSecondRowHeight
);
258 // Undo, and check the result.
259 SfxUndoManager
* pUndoMgr
= pDoc
->GetUndoManager();
260 CPPUNIT_ASSERT_MESSAGE("Failed to get the undo manager.", pUndoMgr
);
263 CPPUNIT_ASSERT(pDoc
->GetString(ScAddress(0,0,0)).isEmpty());
264 CPPUNIT_ASSERT(pDoc
->GetString(ScAddress(0,1,0)).isEmpty());
266 nFirstRowHeight
= pDoc
->GetRowHeight(0, 0);
267 nSecondRowHeight
= pDoc
->GetRowHeight(1, 0);
268 // Without the accompanying fix in place, this test would have failed:
271 // i.e. the increased height of the second row remained after undo.
272 CPPUNIT_ASSERT_EQUAL(nFirstRowHeight
, nSecondRowHeight
);
275 static ScMF
lcl_getMergeFlagOfCell(const ScDocument
& rDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
277 const SfxPoolItem
& rPoolItem
= rDoc
.GetPattern(nCol
, nRow
, nTab
)->GetItem(ATTR_MERGE_FLAG
);
278 const ScMergeFlagAttr
& rMergeFlag
= static_cast<const ScMergeFlagAttr
&>(rPoolItem
);
279 return rMergeFlag
.GetValue();
282 static ScAddress
lcl_getMergeSizeOfCell(const ScDocument
& rDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
284 const SfxPoolItem
& rPoolItem
= rDoc
.GetPattern(nCol
, nRow
, nTab
)->GetItem(ATTR_MERGE
);
285 const ScMergeAttr
& rMerge
= static_cast<const ScMergeAttr
&>(rPoolItem
);
286 return ScAddress(rMerge
.GetColMerge(), rMerge
.GetRowMerge(), nTab
);
289 void ScCopyPasteTest::testTdf53431_fillOnAutofilter()
291 createScDoc("ods/tdf53431_autofilterFilldown.ods");
292 ScDocument
* pDoc
= getScDoc();
293 ScTabViewShell
* pViewShell
= getViewShell();
295 //Fill should not clone Autofilter button
296 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(1, 1, 0, 2, 4, 0));
297 pViewShell
->FillSimple(FILL_TO_BOTTOM
);
298 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
299 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
300 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
302 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(1, 1, 0, 4, 4, 0));
303 pViewShell
->FillSimple(FILL_TO_RIGHT
);
304 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
305 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
306 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 1, 0) & ScMF::Auto
));
307 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
308 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 4, 0) & ScMF::Auto
));
310 //Fill should not delete Autofilter buttons
311 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(0, 0, 0, 2, 4, 0));
312 pViewShell
->FillSimple(FILL_TO_TOP
);
313 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
314 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
315 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 0, 0) & ScMF::Auto
));
317 //Fill should not clone Autofilter button
318 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(1, 1, 0, 2, 4, 0));
319 pViewShell
->FillSimple(FILL_TO_BOTTOM
);
320 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
321 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
322 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
324 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(1, 1, 0, 4, 4, 0));
325 pViewShell
->FillSimple(FILL_TO_RIGHT
);
326 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
327 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
328 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 1, 0) & ScMF::Auto
));
329 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 1, 4, 0) & ScMF::Auto
));
330 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 4, 4, 0) & ScMF::Auto
));
332 //Fill should not delete Autofilter buttons
333 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(0, 0, 0, 2, 4, 0));
334 pViewShell
->FillSimple(FILL_TO_TOP
);
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
, 1, 0, 0) & ScMF::Auto
));
339 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(0, 0, 0, 4, 4, 0));
340 pViewShell
->FillSimple(FILL_TO_LEFT
);
341 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 1, 1, 0) & ScMF::Auto
));
342 CPPUNIT_ASSERT((lcl_getMergeFlagOfCell(*pDoc
, 2, 1, 0) & ScMF::Auto
));
343 CPPUNIT_ASSERT(!(lcl_getMergeFlagOfCell(*pDoc
, 0, 1, 0) & ScMF::Auto
));
346 void ScCopyPasteTest::testTdf40993_fillMergedCells()
348 createScDoc("ods/tdf40993_fillMergedCells.ods");
349 ScDocument
* pDoc
= getScDoc();
350 ScTabViewShell
* pViewShell
= getViewShell();
352 // check content of the merged cell H11:I11
353 CPPUNIT_ASSERT_EQUAL(u
"1.5"_ustr
, pDoc
->GetString(ScAddress(7, 10, 0)));
355 // fill operation on the merged cell should clone ATTR_MERGE and ATTR_MERGE_FLAG
356 // (as long as ATTR_MERGE_FLAG has only ScMF::Hor or ScMF::Ver)
358 // select merged cell
359 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(7, 10, 0, 8, 10, 0));
360 // copy its content in the next ten rows
361 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 7, 10, 8, 10, 10);
362 for (int i
= 7; i
< 9; i
++)
364 ScMF nOriginFlag
= lcl_getMergeFlagOfCell(*pDoc
, i
, 10, 0);
365 ScAddress aOriginMerge
= lcl_getMergeSizeOfCell(*pDoc
, i
, 10, 0);
367 // ATTR_MERGE_FLAG: top left cell is NONE, the other cell shows horizontal overlapping
368 CPPUNIT_ASSERT_EQUAL(i
== 7 ? ScMF::NONE
: ScMF::Hor
, nOriginFlag
);
370 // ATTR_MERGE: top left cell contains the size of the
371 // merged area (2:1), the other cell doesn't
372 CPPUNIT_ASSERT_EQUAL(i
== 7 ? ScAddress(2, 1, 0): ScAddress(0, 0, 0), aOriginMerge
);
374 for (int j
= 11; j
< 21; j
++)
376 // check copying of ATTR_MERGE and ATTR_MERGE_FLAG
377 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, i
, j
, 0), nOriginFlag
);
378 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, i
, j
, 0), aOriginMerge
);
382 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, 7, 21, 0),
383 lcl_getMergeFlagOfCell(*pDoc
, 7, 10, 0));
384 CPPUNIT_ASSERT(lcl_getMergeSizeOfCell(*pDoc
, 7, 21, 0) !=
385 lcl_getMergeSizeOfCell(*pDoc
, 7, 10, 0));
386 CPPUNIT_ASSERT(lcl_getMergeFlagOfCell(*pDoc
, 8, 21, 0) !=
387 lcl_getMergeFlagOfCell(*pDoc
, 8, 10, 0));
388 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 8, 21, 0),
389 lcl_getMergeSizeOfCell(*pDoc
, 8, 10, 0));
391 // area A6:E9 with various merged cells copied vertically and horizontally
392 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(0, 5, 0, 4, 8, 0));
393 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 0, 5, 4, 8, 12);
394 pViewShell
->GetViewData().GetMarkData().SetMarkArea(ScRange(0, 5, 0, 4, 8, 0));
395 pViewShell
->FillAuto(FILL_TO_RIGHT
, 0, 5, 4, 8, 10);
396 for (int i
= 0; i
< 5; i
++)
398 for (int j
= 5; j
< 9; j
++)
400 ScMF nOriginFlag
= lcl_getMergeFlagOfCell(*pDoc
, i
, j
, 0);
401 ScAddress aOriginMerge
= lcl_getMergeSizeOfCell(*pDoc
, i
, j
, 0);
402 // copies contain the same ATTR_MERGE and ATTR_MERGE_FLAG
403 for (int k
= 0; k
< 12; k
+= 4)
405 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, i
, j
+ k
, 0), nOriginFlag
);
406 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, i
, j
+ k
, 0), aOriginMerge
);
408 for (int k
= 0; k
< 10; k
+= 5)
410 CPPUNIT_ASSERT_EQUAL(lcl_getMergeFlagOfCell(*pDoc
, i
+ k
, j
, 0), nOriginFlag
);
411 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, i
+ k
, j
, 0), aOriginMerge
);
415 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 1, 5, 0), ScAddress(2, 4, 0));
416 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 0, 5, 0), ScAddress(1, 2, 0));
417 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 4, 6, 0), ScAddress(1, 2, 0));
418 CPPUNIT_ASSERT_EQUAL(lcl_getMergeSizeOfCell(*pDoc
, 3, 5, 0), ScAddress(2, 1, 0));
421 static void lcl_clickAndCheckCurrentArea(SCCOL nCol
, SCROW nRow
, SCCOL nCol2
, SCROW nRow2
, ScTabViewShell
* pViewShell
)
424 pViewShell
->GetViewData().SetCurX(nCol
);
425 pViewShell
->GetViewData().SetCurY(nRow
);
426 pViewShell
->GetViewData().GetSimpleArea(aRange
);
427 CPPUNIT_ASSERT_EQUAL(aRange
, ScRange(nCol
, nRow
, 0, nCol2
, nRow2
, 0));
430 void ScCopyPasteTest::testTdf43958_clickSelectOnMergedCells()
432 createScDoc("ods/tdf40993_fillMergedCells.ods");
433 ScTabViewShell
* pViewShell
= getViewShell();
435 // select cell (e.g. by clicking on it) and check what is selected [but not marked]:
436 // if it is the top left cell of a merged area, the selection is enlarged to the area
437 lcl_clickAndCheckCurrentArea(1, 5, 2, 8, pViewShell
); // B6 -> B6:C9
438 lcl_clickAndCheckCurrentArea(0, 5, 0, 6, pViewShell
); // A6 -> A6:A7
439 lcl_clickAndCheckCurrentArea(3, 5, 4, 5, pViewShell
); // D6 -> D6:E6
440 lcl_clickAndCheckCurrentArea(4, 6, 4, 7, pViewShell
); // D7 -> D6:D7
441 lcl_clickAndCheckCurrentArea(7, 10, 8, 10, pViewShell
); // H11 -> H11:I11
442 lcl_clickAndCheckCurrentArea(7, 13, 8, 13, pViewShell
); // H14 -> H14:I14
444 // otherwise it remains the same
445 lcl_clickAndCheckCurrentArea(0, 7, 0, 7, pViewShell
); // A8
446 lcl_clickAndCheckCurrentArea(0, 8, 0, 8, pViewShell
); // A9
447 lcl_clickAndCheckCurrentArea(2, 6, 2, 6, pViewShell
); // C7
448 lcl_clickAndCheckCurrentArea(2, 7, 2, 7, pViewShell
); // C8
449 lcl_clickAndCheckCurrentArea(2, 8, 2, 8, pViewShell
); // C9
452 void ScCopyPasteTest::testTdf88782_autofillLinearNumbersInMergedCells()
454 createScDoc("ods/tdf88782_AutofillLinearNumbersInMergedCells.ods");
455 ScDocument
* pDoc
= getScDoc();
456 ScTabViewShell
* pViewShell
= getViewShell();
458 // merge the yellow cells
459 ScCellMergeOption
aMergeOptions(9, 11, 10, 13); //J12:K14
460 aMergeOptions
.maTabs
.insert(0);
461 ScDocShell
* pDocSh
= pViewShell
->GetViewData().GetDocShell();
462 pDocSh
->GetDocFunc().MergeCells(aMergeOptions
, false, true, true, false);
464 // fillauto numbers, these areas contain mostly merged cells
465 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 1, 8, 3, 14, 7); // B9:D15 -> B9:D22
466 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 5, 8, 7, 17, 10); // F9:H18 -> F9:H28
467 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 9, 8, 10, 13, 6); // J9:K14 -> J9:K20
468 pViewShell
->FillAuto(FILL_TO_RIGHT
, 9, 30, 16, 35, 8); //J31:Q36 -> J31:Y36
469 pViewShell
->FillAuto(FILL_TO_LEFT
, 9, 30, 16, 35, 8); //J31:Q36 -> B31:Q36
471 // compare the results of fill-down with the reference stored in the test file
472 // this compares the whole area blindly, for specific test cases, check the test file
473 // the test file have instructions / explanations, so that is easy to understand
474 for (int nCol
= 1; nCol
<= 10; nCol
++)
476 for (int nRow
= 8; nRow
<= 27; nRow
++)
478 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
479 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
+ 22, nRow
, 0));
480 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
481 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
+ 22, nRow
, 0));
483 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
484 if (pValue2
!= nullptr)
485 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
); //cells with number value
487 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
); //empty cells
491 // compare the results of fill-right and left with the reference stored in the test file
492 for (int nCol
= 1; nCol
<= 24; nCol
++)
494 for (int nRow
= 30; nRow
<= 35; nRow
++)
496 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
497 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 16, 0));
498 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
499 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
+ 16, 0));
501 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
502 if (pValue2
!= nullptr)
503 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
);
505 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
);
510 void ScCopyPasteTest::tdf137621_autofillMergedBool()
512 createScDoc("ods/tdf137621_autofillMergedBool.ods");
513 ScDocument
* pDoc
= getScDoc();
514 ScTabViewShell
* pViewShell
= getViewShell();
516 // fillauto booleans, these areas contain only merged cells
517 pViewShell
->FillAuto(FILL_TO_RIGHT
, 0, 4, 3, 5, 8); //A5:D6
519 // compare the results of fill-right with the reference stored in the test file
520 // this compares the whole area blindly, for specific test cases, check the test file
521 for (int nCol
= 4; nCol
<= 11; nCol
++)
523 for (int nRow
= 4; nRow
<= 5; nRow
++)
525 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
526 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 3, 0));
527 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
528 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
+ 3, 0));
530 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
531 if (pValue2
!= nullptr)
532 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
); //cells with boolean value
534 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
); //empty cells
539 void ScCopyPasteTest::tdf137205_autofillDatesInMergedCells()
541 createScDoc("ods/tdf137205_AutofillDatesInMergedCells.ods");
542 ScDocument
* pDoc
= getScDoc();
543 ScTabViewShell
* pViewShell
= getViewShell();
545 // fillauto dates, this areas contain only merged cells
546 pViewShell
->FillAuto(FILL_TO_RIGHT
, 1, 5, 4, 7, 8); //B6:E8
548 // compare the results of fill-right with the reference stored in the test file
549 // this compares the whole area blindly, for specific test cases, check the test file
550 for (int nCol
= 5; nCol
<= 12; nCol
++)
552 for (int nRow
= 5; nRow
<= 7; nRow
++)
554 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
555 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 5, 0));
556 double* pValue1
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
, 0));
557 double* pValue2
= pDoc
->GetValueCell(ScAddress(nCol
, nRow
+ 5, 0));
559 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
560 if (pValue2
!= nullptr)
561 CPPUNIT_ASSERT_EQUAL(*pValue1
, *pValue2
); //cells with number value
563 CPPUNIT_ASSERT_EQUAL(pValue1
, pValue2
); //empty cells
568 void ScCopyPasteTest::addToUserList(const OUString
& rStr
)
570 ScGlobal::GetUserList().emplace_back(rStr
);
573 void ScCopyPasteTest::tdf137653_137654_autofillUserlist()
575 createScDoc("ods/tdf137653_137654_autofillUserlist.ods");
576 ScDocument
* pDoc
= getScDoc();
577 ScTabViewShell
* pViewShell
= getViewShell();
579 // delete every userlist to make sure there won't be any string that is in 2 different userlist
580 ScGlobal::GetUserList().clear();
581 addToUserList({ u
"January,February,March,April,May,June,July,August,September,October,November,December"_ustr
});
582 const ScUserListData
* pListData
= ScGlobal::GetUserList().GetData(u
"January"_ustr
);
583 sal_uInt16 nIdx1
= 0, nIdx2
= 0;
584 bool bHasIdx1
, bHasIdx2
;
585 bool bMatchCase
= false;
587 // fillauto userlist, these areas contain only merged cells
588 pViewShell
->FillAuto(FILL_TO_RIGHT
, 4, 5, 6, 7, 3); //E6:G8
589 pViewShell
->FillAuto(FILL_TO_LEFT
, 4, 5, 6, 7, 3); //E6:G8
590 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 1, 18, 3, 19, 2); //B19:D20
591 pViewShell
->FillAuto(FILL_TO_TOP
, 1, 18, 3, 19, 2); //B19:D20
593 // compare the results of fill-right / -left 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
= 1; nCol
<= 9; 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
+ 4, 0));
601 bHasIdx1
= pListData
->GetSubIndex(pDoc
->GetString(nCol
, nRow
, 0), nIdx1
, bMatchCase
);
602 bHasIdx2
= pListData
->GetSubIndex(pDoc
->GetString(nCol
, nRow
+ 4, 0), nIdx2
, bMatchCase
);
604 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
605 CPPUNIT_ASSERT(bHasIdx1
);
606 CPPUNIT_ASSERT(bHasIdx2
);
607 CPPUNIT_ASSERT_EQUAL(nIdx1
, nIdx2
); // userlist index value of cells
611 // compare the results of fill-up / -down
612 for (int nCol
= 1; nCol
<= 3; nCol
++)
614 for (int nRow
= 16; nRow
<= 21; nRow
++)
616 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
617 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
+ 4, nRow
, 0));
618 bHasIdx1
= pListData
->GetSubIndex(pDoc
->GetString(nCol
, nRow
, 0), nIdx1
, bMatchCase
);
619 bHasIdx2
= pListData
->GetSubIndex(pDoc
->GetString(nCol
+ 4, nRow
, 0), nIdx2
, bMatchCase
);
621 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
622 CPPUNIT_ASSERT(bHasIdx1
);
623 CPPUNIT_ASSERT(bHasIdx2
);
624 CPPUNIT_ASSERT_EQUAL(nIdx1
, nIdx2
); // userlist index value of cells
629 void ScCopyPasteTest::tdf113500_autofillMixed()
631 createScDoc("ods/tdf113500_autofillMixed.ods");
632 ScDocument
* pDoc
= getScDoc();
633 ScTabViewShell
* pViewShell
= getViewShell();
635 // fillauto userlist, these areas contain only merged cells
636 pViewShell
->FillAuto(FILL_TO_RIGHT
, 4, 5, 6, 7, 3); //E6:G8
637 pViewShell
->FillAuto(FILL_TO_LEFT
, 4, 5, 6, 7, 3); //E6:G8
638 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 1, 18, 3, 19, 2); //B19:D20
639 pViewShell
->FillAuto(FILL_TO_TOP
, 1, 18, 3, 19, 2); //B19:D20
641 // compare the results of fill-right / -left with the reference stored in the test file
642 // this compares the whole area blindly, for specific test cases, check the test file
643 // do not check the 3. row: a1,b2,a3. It is another bug to fix
644 for (int nCol
= 1; nCol
<= 9; nCol
++)
646 for (int nRow
= 5; nRow
<= 6; nRow
++)
648 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
649 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 4, 0));
650 OUString aStr1
= pDoc
->GetString(nCol
, nRow
, 0);
651 OUString aStr2
= pDoc
->GetString(nCol
, nRow
+ 4, 0);
653 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
654 CPPUNIT_ASSERT_EQUAL(aStr1
, aStr2
);
658 // compare the results of fill-up / -down
659 // do not check the 2. column: 1st,3rd. It is another bug to fix
660 for (int nCol
= 1; nCol
<= 3; nCol
+=2)
662 for (int nRow
= 16; nRow
<= 21; nRow
++)
664 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
665 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
+ 4, nRow
, 0));
666 OUString aStr1
= pDoc
->GetString(nCol
, nRow
, 0);
667 OUString aStr2
= pDoc
->GetString(nCol
+ 4, nRow
, 0);
669 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
670 CPPUNIT_ASSERT_EQUAL(aStr1
, aStr2
);
675 void ScCopyPasteTest::tdf137625_autofillMergedUserlist()
677 createScDoc("ods/tdf137625_autofillMergedUserlist.ods");
678 ScDocument
* pDoc
= getScDoc();
679 ScTabViewShell
* pViewShell
= getViewShell();
681 // delete every userlist to make sure there won't be any string that is in 2 different userlist
682 ScGlobal::GetUserList().clear();
683 addToUserList({ u
"January,February,March,April,May,June,July,August,September,October,November,December"_ustr
});
684 const ScUserListData
* pListData
= ScGlobal::GetUserList().GetData(u
"January"_ustr
);
685 sal_uInt16 nIdx1
= 0, nIdx2
= 0;
686 bool bHasIdx1
, bHasIdx2
;
687 bool bMatchCase
= false;
689 // fillauto userlist, these areas contain only merged cells
690 pViewShell
->FillAuto(FILL_TO_RIGHT
, 7, 5, 12, 7, 6); //H6:M8
691 pViewShell
->FillAuto(FILL_TO_LEFT
, 7, 5, 12, 7, 6); //H6:M8
692 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 1, 20, 3, 23, 4); //B21:D24
693 pViewShell
->FillAuto(FILL_TO_TOP
, 1, 20, 3, 23, 4); //B21:D24
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 for (int nCol
= 1; nCol
<= 18; nCol
++)
699 for (int nRow
= 5; nRow
<= 7; nRow
++)
701 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
702 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 4, 0));
703 bHasIdx1
= pListData
->GetSubIndex(pDoc
->GetString(nCol
, nRow
, 0), nIdx1
, bMatchCase
);
704 bHasIdx2
= pListData
->GetSubIndex(pDoc
->GetString(nCol
, nRow
+ 4, 0), nIdx2
, bMatchCase
);
706 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
707 CPPUNIT_ASSERT_EQUAL(bHasIdx1
, bHasIdx2
);
709 CPPUNIT_ASSERT_EQUAL(nIdx1
, nIdx2
); //cells with userlist value
713 // compare the results of fill-up / -down
714 for (int nCol
= 1; nCol
<= 3; nCol
++)
716 for (int nRow
= 16; nRow
<= 27; nRow
++)
718 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
719 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
+ 4, nRow
, 0));
720 bHasIdx1
= pListData
->GetSubIndex(pDoc
->GetString(nCol
, nRow
, 0), nIdx1
, bMatchCase
);
721 bHasIdx2
= pListData
->GetSubIndex(pDoc
->GetString(nCol
+ 4, nRow
, 0), nIdx2
, bMatchCase
);
723 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
724 CPPUNIT_ASSERT_EQUAL(bHasIdx1
, bHasIdx2
);
726 CPPUNIT_ASSERT_EQUAL(nIdx1
, nIdx2
); //cells with userlist value
731 void ScCopyPasteTest::tdf137624_autofillMergedMixed()
733 createScDoc("ods/tdf137624_autofillMergedMixed.ods");
734 ScDocument
* pDoc
= getScDoc();
735 ScTabViewShell
* pViewShell
= getViewShell();
737 // add 1aa,2bb,3cc,4dd,5ee,6ff to userlist, to test that autofill won't confuse it with 1aa,3aa
738 // delete every userlist to make sure there won't be any string that is in 2 different userlist
739 ScGlobal::GetUserList().clear();
740 addToUserList({ u
"1aa,2bb,3cc,4dd,5ee,6ff"_ustr
});
742 // fillauto mixed (string + number), these areas contain only merged cells
743 pViewShell
->FillAuto(FILL_TO_RIGHT
, 7, 5, 12, 7, 6); //H6:M8
744 pViewShell
->FillAuto(FILL_TO_LEFT
, 7, 5, 12, 7, 6); //H6:M8
745 pViewShell
->FillAuto(FILL_TO_BOTTOM
, 1, 20, 3, 23, 4); //B21:D24
746 pViewShell
->FillAuto(FILL_TO_TOP
, 1, 20, 3, 23, 4); //B21:D24
748 // compare the results of fill-right / -left with the reference stored in the test file
749 // this compares the whole area blindly, for specific test cases, check the test file
750 for (int nCol
= 1; nCol
<= 18; nCol
++)
752 for (int nRow
= 5; nRow
<= 7; nRow
++)
754 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
755 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
, nRow
+ 4, 0));
756 OUString aStr1
= pDoc
->GetString(nCol
, nRow
, 0);
757 OUString aStr2
= pDoc
->GetString(nCol
, nRow
+ 4, 0);
759 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
760 CPPUNIT_ASSERT_EQUAL(aStr1
, aStr2
);
764 // compare the results of fill-up / -down
765 for (int nCol
= 1; nCol
<= 3; nCol
++)
767 for (int nRow
= 16; nRow
<= 27; nRow
++)
769 CellType nType1
= pDoc
->GetCellType(ScAddress(nCol
, nRow
, 0));
770 CellType nType2
= pDoc
->GetCellType(ScAddress(nCol
+ 4, nRow
, 0));
771 OUString aStr1
= pDoc
->GetString(nCol
, nRow
, 0);
772 OUString aStr2
= pDoc
->GetString(nCol
+ 4, nRow
, 0);
774 CPPUNIT_ASSERT_EQUAL(nType1
, nType2
);
775 CPPUNIT_ASSERT_EQUAL(aStr1
, aStr2
);
780 void ScCopyPasteTest::tdf122716_rtf_portion_encoding()
782 // Given a document with an explicitly defined "204" (Russian) charset for a font,
783 // and a cell having contents of "Šampūnas", which has character "Š" representable
784 // in Windows-1252 (RTF default), but not in Windows-1251 (i.e. charset 204):
785 createScDoc("xlsx/tdf122716_font_with_charset.xlsx");
786 ScModelObj
* pModelObj
= comphelper::getFromUnoTunnel
<ScModelObj
>(mxComponent
);
787 // Obtain a transferable, similar to what happens on copy to clipboard:
788 auto xTransferable
= pModelObj
->getSelection();
790 auto rtf_any
= xTransferable
->getTransferData({ u
"text/rtf"_ustr
, {}, {} });
791 css::uno::Sequence
<sal_Int8
> rtf_bytes
;
792 CPPUNIT_ASSERT(rtf_any
>>= rtf_bytes
);
793 OString
rtf_string(reinterpret_cast<const char*>(rtf_bytes
.getConstArray()),
794 rtf_bytes
.getLength());
795 // Check that the font with charset was actually emitted
796 CPPUNIT_ASSERT(rtf_string
.indexOf("\\fcharset204 Liberation Sans;") >= 0);
797 // Make sure that Unicode markup is emitted for the non-Ascii characters.
798 // Without the fix, "\u352" wasn't there, because the export was using Windows-1252
799 // encoding unconditionally, even though the exported font defined a different one;
800 // so the exported characters only had Unicode markup, when not representable in the
801 // Windows-1252 encoding, and "Š" got exported as "\'8a". On import to Writer, font
802 // encoding was used, and "\'8a" was interpreted as a Cyrillic alphabet character.
803 CPPUNIT_ASSERT(rtf_string
.indexOf("\\u352\\'3famp\\u363\\'3fnas") >= 0);
806 ScCopyPasteTest::ScCopyPasteTest()
807 : ScModelTestBase(u
"/sc/qa/unit/data/"_ustr
)
811 CPPUNIT_TEST_SUITE_REGISTRATION(ScCopyPasteTest
);
813 CPPUNIT_PLUGIN_IMPLEMENT();
815 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */