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 "helper/qahelper.hxx"
12 #include <conditio.hxx>
13 #include <colorscale.hxx>
16 #include <globstr.hrc>
17 #include <scresid.hxx>
18 #include <docfunc.hxx>
19 #include <scitems.hxx>
21 #include <fillinfo.hxx>
22 #include <compiler.hxx>
23 #include <undomanager.hxx>
25 #include <svl/sharedstringpool.hxx>
29 struct PaintListener
: public SfxListener
31 bool mbPaintAllMergedCell
= false;
32 virtual void Notify(SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
) override
34 const ScPaintHint
* pPaintHint
= dynamic_cast<const ScPaintHint
*>(&rHint
);
37 if (pPaintHint
->GetStartCol() == 0 && pPaintHint
->GetEndCol() == 0
38 && pPaintHint
->GetStartRow() == 0 && pPaintHint
->GetEndRow() == 1)
40 mbPaintAllMergedCell
= true;
46 struct ScDataBarLengthData
52 void testDataBarLengthImpl(ScDocument
* pDoc
, const ScDataBarLengthData
* pData
, const ScRange
& rRange
,
53 double nMinVal
, ScColorScaleEntryType eMinType
,
54 double nMaxVal
, ScColorScaleEntryType eMaxType
,
55 double nZeroPos
, databar::ScAxisPosition eAxisPos
)
57 std::unique_ptr
<ScConditionalFormat
> pFormat(new ScConditionalFormat(1, pDoc
));
58 ScRangeList
aRangeList(rRange
);
59 pFormat
->SetRange(aRangeList
);
61 SCCOL nCol
= rRange
.aStart
.Col();
63 ScDataBarFormat
* pDatabar
= new ScDataBarFormat(pDoc
);
64 pFormat
->AddEntry(pDatabar
);
66 ScDataBarFormatData
* pFormatData
= new ScDataBarFormatData();
67 pFormatData
->meAxisPosition
= eAxisPos
;
69 pFormatData
->mpLowerLimit
.reset(new ScColorScaleEntry());
70 pFormatData
->mpLowerLimit
->SetValue(nMinVal
);
71 pFormatData
->mpLowerLimit
->SetType(eMinType
);
72 pFormatData
->mpUpperLimit
.reset(new ScColorScaleEntry());
73 pFormatData
->mpUpperLimit
->SetValue(nMaxVal
);
74 pFormatData
->mpUpperLimit
->SetType(eMaxType
);
75 pDatabar
->SetDataBarData(pFormatData
);
77 for (size_t i
= 0; pData
[i
].nLength
!= -200; ++i
)
79 pDoc
->SetValue(nCol
, i
, 0, pData
[i
].nVal
);
82 for (size_t i
= 0; pData
[i
].nLength
!= -200; ++i
)
84 std::unique_ptr
<ScDataBarInfo
> xInfo(pDatabar
->GetDataBarInfo(ScAddress(nCol
, i
, 0)));
85 CPPUNIT_ASSERT(xInfo
);
86 ASSERT_DOUBLES_EQUAL(pData
[i
].nLength
, xInfo
->mnLength
);
87 ASSERT_DOUBLES_EQUAL(nZeroPos
, xInfo
->mnZero
);
91 sal_uInt32
addSingleCellCondFormat(ScDocument
* pDoc
, const ScAddress
& rAddr
, sal_uInt32 nKey
, const OUString
& rCondition
)
93 auto pFormat
= std::make_unique
<ScConditionalFormat
>(nKey
, pDoc
);
94 ScRange
aCondFormatRange(rAddr
);
95 ScRangeList
aRangeList(aCondFormatRange
);
96 pFormat
->SetRange(aRangeList
);
98 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
, rCondition
, "",
99 *pDoc
, ScAddress(0,0,0), ScResId(STR_STYLENAME_RESULT
));
100 pFormat
->AddEntry(pEntry
);
101 return pDoc
->AddCondFormat(std::move(pFormat
), 0);
106 class TestCondformat
: public ScUcalcTestBase
110 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatINSDEL
)
113 m_pDoc
->InsertTab(0, "Test");
114 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
116 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
117 ScRangeList
aRangeList(ScRange(0,0,0,0,3,0));
118 pFormat
->SetRange(aRangeList
);
119 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
120 pFormat
->AddEntry(pEntry
);
122 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
123 auto pFormatTmp
= pFormat
.get();
124 pList
->InsertNew(std::move(pFormat
));
126 m_pDoc
->InsertCol(0,0,m_pDoc
->MaxRow(),0,0,2);
127 const ScRangeList
& rRange
= pFormatTmp
->GetRange();
128 CPPUNIT_ASSERT_EQUAL(static_cast<const ScRangeList
&>(ScRange(2,0,0,2,3,0)), rRange
);
130 OUString aExpr
= pEntry
->GetExpression(ScAddress(2,0,0), 0);
131 CPPUNIT_ASSERT_EQUAL(OUString("D2"), aExpr
);
133 m_pDoc
->DeleteTab(0);
136 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatInsertCol
)
138 m_pDoc
->InsertTab(0, "Test");
139 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
141 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
142 ScRangeList
aRangeList(ScRange(0,0,0,3,3,0));
143 pFormat
->SetRange(aRangeList
);
145 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
146 pFormat
->AddEntry(pEntry
);
148 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
149 auto pFormatTmp
= pFormat
.get();
150 pList
->InsertNew(std::move(pFormat
));
152 m_pDoc
->InsertCol(0,0,m_pDoc
->MaxRow(),0,4,2);
153 const ScRangeList
& rRange
= pFormatTmp
->GetRange();
154 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,0,5,3,0)), rRange
);
156 m_pDoc
->DeleteTab(0);
159 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatInsertRow
)
161 m_pDoc
->InsertTab(0, "Test");
162 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
164 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
165 ScRangeList
aRangeList(ScRange(0,0,0,3,3,0));
166 pFormat
->SetRange(aRangeList
);
168 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
169 pFormat
->AddEntry(pEntry
);
171 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
172 auto pFormatTmp
= pFormat
.get();
173 pList
->InsertNew(std::move(pFormat
));
175 m_pDoc
->InsertRow(0,0,m_pDoc
->MaxCol(),0,4,2);
176 const ScRangeList
& rRange
= pFormatTmp
->GetRange();
177 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,0,3,5,0)), rRange
);
179 m_pDoc
->DeleteTab(0);
182 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatInsertDeleteSheets
)
184 m_pDoc
->InsertTab(0, "Test");
186 // Add a conditional format to B2:B4.
187 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
188 pFormat
->SetRange(ScRange(1,1,0,1,3,0));
190 auto pFormatTmp
= pFormat
.get();
191 sal_uLong nKey
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
193 // Add condition in which if the value equals 2, set the "Result" style.
194 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(
195 ScConditionMode::Equal
, "=2", "" , *m_pDoc
, ScAddress(0,0,0), ScResId(STR_STYLENAME_RESULT
));
196 pFormatTmp
->AddEntry(pEntry
);
198 // Apply the format to the range.
199 m_pDoc
->AddCondFormatData(pFormatTmp
->GetRange(), 0, nKey
);
201 // Make sure this conditional format entry is really there.
202 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
203 CPPUNIT_ASSERT(pList
);
204 const ScConditionalFormat
* pCheck
= pList
->GetFormat(nKey
);
205 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong conditional format instance.", pCheck
, const_cast<const ScConditionalFormat
*>(pFormatTmp
));
207 // ... and its range is B2:B4.
208 ScRangeList aCheckRange
= pCheck
->GetRange();
209 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange
.size());
210 const ScRange
* pRange
= &aCheckRange
[0];
211 CPPUNIT_ASSERT(pRange
);
212 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4.", ScRange(1,1,0,1,3,0), *pRange
);
214 ScDocFunc
& rFunc
= m_xDocShell
->GetDocFunc();
216 // Insert a new sheet at the left.
217 bool bInserted
= rFunc
.InsertTable(0, "Inserted", true, true);
218 CPPUNIT_ASSERT(bInserted
);
220 pList
= m_pDoc
->GetCondFormList(1);
221 CPPUNIT_ASSERT(pList
);
222 pCheck
= pList
->GetFormat(nKey
);
223 CPPUNIT_ASSERT(pCheck
);
225 // Make sure the range also got shifted.
226 aCheckRange
= pCheck
->GetRange();
227 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange
.size());
228 pRange
= &aCheckRange
[0];
229 CPPUNIT_ASSERT(pRange
);
230 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4 on the 2nd sheet after the sheet insertion.", ScRange(1,1,1,1,3,1), *pRange
);
232 // Delete the sheet to the left.
233 bool bDeleted
= rFunc
.DeleteTable(0, true);
234 CPPUNIT_ASSERT(bDeleted
);
236 pList
= m_pDoc
->GetCondFormList(0);
237 CPPUNIT_ASSERT(pList
);
238 pCheck
= pList
->GetFormat(nKey
);
239 CPPUNIT_ASSERT(pCheck
);
241 // Make sure the range got shifted back.
242 aCheckRange
= pCheck
->GetRange();
243 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange
.size());
244 pRange
= &aCheckRange
[0];
245 CPPUNIT_ASSERT(pRange
);
246 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4 on the 1st sheet after the sheet removal.", ScRange(1,1,0,1,3,0), *pRange
);
248 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
249 CPPUNIT_ASSERT(pUndoMgr
);
251 // Undo and re-check.
254 pList
= m_pDoc
->GetCondFormList(1);
255 CPPUNIT_ASSERT(pList
);
256 pCheck
= pList
->GetFormat(nKey
);
257 CPPUNIT_ASSERT(pCheck
);
259 aCheckRange
= pCheck
->GetRange();
260 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange
.size());
261 pRange
= &aCheckRange
[0];
262 CPPUNIT_ASSERT(pRange
);
263 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4 on the 2nd sheet after the undo of the sheet removal.", ScRange(1,1,1,1,3,1), *pRange
);
265 #if 0 // TODO : Undo of sheet insertion currently depends on the presence of
266 // view shell, and crashes when executed during cppunit run.
268 // Undo again and re-check.
271 pList
= m_pDoc
->GetCondFormList(0);
272 CPPUNIT_ASSERT(pList
);
273 pCheck
= pList
->GetFormat(nKey
);
274 CPPUNIT_ASSERT(pCheck
);
276 // Make sure the range got shifted back.
277 aCheckRange
= pCheck
->GetRange();
278 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange
.size() == 1);
279 pRange
= aCheckRange
[0];
280 CPPUNIT_ASSERT(pRange
);
281 CPPUNIT_ASSERT_MESSAGE("Format should be applied to B2:B4 on the 1st sheet after the undo of sheet insertion.", *pRange
== ScRange(1,1,0,1,3,0));
283 m_pDoc
->DeleteTab(1);
286 m_pDoc
->DeleteTab(0);
289 CPPUNIT_TEST_FIXTURE(TestCondformat
, testDataBarCondCopyPaste
)
291 m_pDoc
->InsertTab(0, "Test");
293 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
294 ScRange
aCondFormatRange(0, 0, 0, 2, 0, 0);
295 ScRangeList
aRangeList(aCondFormatRange
);
296 pFormat
->SetRange(aRangeList
);
298 ScDataBarFormat
* pDatabar
= new ScDataBarFormat(m_pDoc
);
299 ScDataBarFormatData
* pFormatData
= new ScDataBarFormatData();
300 pFormatData
->meAxisPosition
= databar::AUTOMATIC
;
301 pFormatData
->maPositiveColor
= COL_BLUE
;
302 pFormatData
->mxNegativeColor
= COL_GREEN
;
303 pFormatData
->mbGradient
= true;
305 pDatabar
->SetDataBarData(pFormatData
);
306 pFormat
->AddEntry(pDatabar
);
308 sal_uLong nIndex
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
310 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
311 copyToClip(m_pDoc
, aCondFormatRange
, &aClipDoc
);
313 ScRange
aTargetRange(0, 3, 0, 2, 3, 0);
314 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
316 // Pasting the same conditional format must modify existing format, making its range
317 // combined of previous range and newly pasted range having the conditional format.
318 // No new conditional formats must be created.
319 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
320 aRangeList
.Join(aTargetRange
);
321 for (SCCOL nCol
= 0; nCol
< 3; ++nCol
)
323 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(nCol
, 3, 0);
324 CPPUNIT_ASSERT(pPastedFormat
);
325 CPPUNIT_ASSERT_EQUAL(aRangeList
, pPastedFormat
->GetRange());
327 sal_uLong nPastedKey
= pPastedFormat
->GetKey();
328 CPPUNIT_ASSERT_EQUAL(nIndex
, nPastedKey
);
330 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr(nCol
, 3, 0, ATTR_CONDITIONAL
);
331 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
332 CPPUNIT_ASSERT(pCondFormatItem
);
333 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
334 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pCondFormatItem
->GetCondFormatData().front());
337 m_pDoc
->DeleteTab(0);
340 CPPUNIT_TEST_FIXTURE(TestCondformat
, testColorScaleInMergedCell
)
342 m_pDoc
->InsertTab(0, "Test");
343 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
345 // Add a conditional format to A1.
346 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
347 pFormat
->SetRange(ScRange(0, 0, 0, 0, 0, 0));
348 auto pFormatTmp
= pFormat
.get();
349 sal_uLong nKey
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
351 // Add color scale entries.
352 // The coloring is based on the value. (BLUE (x <= 0), GREEN (x == 1), RED (x >= 2))
353 ScColorScaleFormat
* pColorScaleFormat
= new ScColorScaleFormat(m_pDoc
);
354 ScColorScaleEntry
* pEntryBlue
= new ScColorScaleEntry(0, COL_BLUE
);
355 ScColorScaleEntry
* pEntryGreen
= new ScColorScaleEntry(1, COL_GREEN
);
356 ScColorScaleEntry
* pEntryRed
= new ScColorScaleEntry(2, COL_RED
);
357 pColorScaleFormat
->AddEntry(pEntryBlue
);
358 pColorScaleFormat
->AddEntry(pEntryGreen
);
359 pColorScaleFormat
->AddEntry(pEntryRed
);
361 pFormatTmp
->AddEntry(pColorScaleFormat
);
363 // Apply the format to the range.
364 m_pDoc
->AddCondFormatData(pFormatTmp
->GetRange(), 0, nKey
);
366 m_pDoc
->DoMerge(0, 0, 0, 1, 0); // A1:A2
367 CPPUNIT_ASSERT(m_pDoc
->IsMerged(ScAddress(0, 0, 0)));
369 ScTableInfo
aTabInfo(0, 2, false);
370 m_pDoc
->FillInfo(aTabInfo
, 0, 0, 0, 1, 0, 1, 1, false, false);
371 RowInfo
* pRowInfo
= aTabInfo
.mpRowInfo
.get();
373 RowInfo
* pRowInfoA1
= &pRowInfo
[1];
374 ScCellInfo
* pCellInfoA1
= &pRowInfoA1
->cellInfo(0);
375 // Check if there is a color scale in A1.
376 CPPUNIT_ASSERT_EQUAL_MESSAGE("There is no color scale in cell A1!", true,
377 pCellInfoA1
->mxColorScale
.has_value());
379 RowInfo
* pRowInfoA2
= &pRowInfo
[2];
380 ScCellInfo
* pCellInfoA2
= &pRowInfoA2
->cellInfo(0);
381 // Check if there is a color scale in A2.
382 CPPUNIT_ASSERT_EQUAL_MESSAGE("There is no color scale in cell A2!", true,
383 pCellInfoA2
->mxColorScale
.has_value());
385 // Check that cells A1 and A2 have the same color scale. (GREEN)
386 CPPUNIT_ASSERT(pCellInfoA1
->mxColorScale
.value().IsRGBEqual(pCellInfoA2
->mxColorScale
.value()));
388 m_pDoc
->DeleteTab(0);
392 CPPUNIT_TEST_FIXTURE(TestCondformat
, testColorScaleCondCopyPaste
)
394 m_pDoc
->InsertTab(0, "Test");
396 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
397 ScRange
aCondFormatRange(0, 0, 0, 2, 0, 0);
398 ScRangeList
aRangeList(aCondFormatRange
);
399 pFormat
->SetRange(aRangeList
);
401 ScColorScaleFormat
* pColorScaleFormat
= new ScColorScaleFormat(m_pDoc
);
402 ScColorScaleEntry
* pEntryBlue
= new ScColorScaleEntry(0, COL_BLUE
);
403 ScColorScaleEntry
* pEntryGreen
= new ScColorScaleEntry(1, COL_GREEN
);
404 ScColorScaleEntry
* pEntryRed
= new ScColorScaleEntry(2, COL_RED
);
405 pColorScaleFormat
->AddEntry(pEntryBlue
);
406 pColorScaleFormat
->AddEntry(pEntryGreen
);
407 pColorScaleFormat
->AddEntry(pEntryRed
);
409 pFormat
->AddEntry(pColorScaleFormat
);
410 sal_uLong nIndex
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
412 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
413 copyToClip(m_pDoc
, aCondFormatRange
, &aClipDoc
);
415 ScRange
aTargetRange(0, 3, 0, 2, 3, 0);
416 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
418 // Pasting the same conditional format must modify existing format, making its range
419 // combined of previous range and newly pasted range having the conditional format.
420 // No new conditional formats must be created.
421 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
422 aRangeList
.Join(aTargetRange
);
423 for (SCCOL nCol
= 0; nCol
< 3; ++nCol
)
425 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(nCol
, 3, 0);
426 CPPUNIT_ASSERT(pPastedFormat
);
427 CPPUNIT_ASSERT_EQUAL(aRangeList
, pPastedFormat
->GetRange());
429 sal_uLong nPastedKey
= pPastedFormat
->GetKey();
430 CPPUNIT_ASSERT_EQUAL(nIndex
, nPastedKey
);
432 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr(nCol
, 3, 0, ATTR_CONDITIONAL
);
433 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
434 CPPUNIT_ASSERT(pCondFormatItem
);
435 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
436 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pCondFormatItem
->GetCondFormatData().front());
439 m_pDoc
->DeleteTab(0);
442 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPaste
)
444 m_pDoc
->InsertTab(0, "Test");
446 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
447 ScRange
aCondFormatRange(0,0,0,3,3,0);
448 ScRangeList
aRangeList(aCondFormatRange
);
449 pFormat
->SetRange(aRangeList
);
451 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
452 pFormat
->AddEntry(pEntry
);
453 sal_uLong nIndex
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
455 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
456 copyToClip(m_pDoc
, aCondFormatRange
, &aClipDoc
);
458 ScRange
aTargetRange(4,4,0,7,7,0);
459 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
461 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(7,7,0);
462 CPPUNIT_ASSERT(pPastedFormat
);
464 // Pasting the same conditional format must modify existing format, making its range
465 // combined of previous range and newly pasted range having the conditional format.
466 // No new conditional formats must be created.
467 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
468 aRangeList
.Join(aTargetRange
);
469 CPPUNIT_ASSERT_EQUAL(aRangeList
, pPastedFormat
->GetRange());
470 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pPastedFormat
->GetKey());
471 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 7, 7, 0, ATTR_CONDITIONAL
);
472 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
474 CPPUNIT_ASSERT(pCondFormatItem
);
475 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
476 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pCondFormatItem
->GetCondFormatData().front());
478 m_pDoc
->DeleteTab(0);
481 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSingleCell
)
484 m_pDoc
->InsertTab(0, "Test");
486 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
487 ScRange
aCondFormatRange(0,0,0,3,3,0);
488 ScRangeList
aRangeList(aCondFormatRange
);
489 pFormat
->SetRange(aRangeList
);
491 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
492 pFormat
->AddEntry(pEntry
);
493 sal_uLong nIndex
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
495 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
496 copyToClip(m_pDoc
, ScRange(0,0,0,0,0,0), &aClipDoc
);
498 ScRange
aTargetRange(4,4,0,4,4,0);
499 pasteOneCellFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
501 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(4,4,0);
502 CPPUNIT_ASSERT(pPastedFormat
);
504 // Pasting the same conditional format must modify existing format, making its range
505 // combined of previous range and newly pasted range having the conditional format.
506 // No new conditional formats must be created.
507 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
508 aRangeList
.Join(aTargetRange
);
509 CPPUNIT_ASSERT_EQUAL(aRangeList
, pPastedFormat
->GetRange());
510 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pPastedFormat
->GetKey());
511 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 4, 4, 0, ATTR_CONDITIONAL
);
512 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
514 CPPUNIT_ASSERT(pCondFormatItem
);
515 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
516 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pCondFormatItem
->GetCondFormatData().front() );
518 m_pDoc
->DeleteTab(0);
521 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSingleCellToRange
)
524 m_pDoc
->InsertTab(0, "Test");
526 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
527 ScRange
aCondFormatRange(0,0,0,3,3,0);
528 ScRangeList
aRangeList(aCondFormatRange
);
529 pFormat
->SetRange(aRangeList
);
531 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
532 pFormat
->AddEntry(pEntry
);
533 sal_uLong nIndex
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
535 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
536 copyToClip(m_pDoc
, ScRange(0,0,0,0,0,0), &aClipDoc
);
537 ScRange
aTargetRange(4,4,0,5,8,0);
538 pasteOneCellFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
540 // Pasting the same conditional format must modify existing format, making its range
541 // combined of previous range and newly pasted range having the conditional format.
542 // No new conditional formats must be created.
543 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
544 aRangeList
.Join(aTargetRange
);
545 for(SCROW nRow
= 4; nRow
<= 8; ++nRow
)
547 for (SCCOL nCol
= 4; nCol
<= 5; ++nCol
)
549 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(nCol
, nRow
, 0);
550 CPPUNIT_ASSERT(pPastedFormat
);
552 CPPUNIT_ASSERT_EQUAL(aRangeList
, pPastedFormat
->GetRange());
553 sal_uLong nPastedKey
= pPastedFormat
->GetKey();
554 CPPUNIT_ASSERT_EQUAL(nIndex
, nPastedKey
);
555 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( nCol
, nRow
, 0, ATTR_CONDITIONAL
);
556 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
558 CPPUNIT_ASSERT(pCondFormatItem
);
559 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
560 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pCondFormatItem
->GetCondFormatData().front() );
564 m_pDoc
->DeleteTab(0);
567 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSingleCellIntoSameFormatRange
)
570 m_pDoc
->InsertTab(0, "Test");
572 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
573 ScRange
aCondFormatRange(0, 0, 0, 3, 3, 0);
574 ScRangeList
aRangeList(aCondFormatRange
);
575 pFormat
->SetRange(aRangeList
);
577 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
, "=B2", "", *m_pDoc
, ScAddress(0, 0, 0), ScResId(STR_STYLENAME_RESULT
));
578 pFormat
->AddEntry(pEntry
);
579 sal_uLong nIndex
= m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
581 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
582 copyToClip(m_pDoc
, ScRange(1, 1, 0, 1, 1, 0), &aClipDoc
);
584 ScRange
aTargetRange(2, 2, 0, 2, 2, 0);
585 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
587 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(2, 2, 0);
588 CPPUNIT_ASSERT(pPastedFormat
);
590 // Pasting the same conditional format into the same range must not modify existing format,
591 // since it already covers the pasted range. No new conditional formats must be created.
592 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
593 CPPUNIT_ASSERT_EQUAL(aRangeList
, pPastedFormat
->GetRange());
594 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pPastedFormat
->GetKey());
595 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr(2, 2, 0, ATTR_CONDITIONAL
);
596 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
598 CPPUNIT_ASSERT(pCondFormatItem
);
599 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
600 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex
), pCondFormatItem
->GetCondFormatData().front());
602 m_pDoc
->DeleteTab(0);
605 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSingleRowToRange
)
608 m_pDoc
->InsertTab(0, "Test");
610 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
611 ScRange
aCondFormatRange(0,0,0,0,0,0);
612 ScRangeList
aRangeList(aCondFormatRange
);
613 pFormat
->SetRange(aRangeList
);
615 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
616 pFormat
->AddEntry(pEntry
);
617 auto pFormatTmp
= pFormat
.get();
618 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
620 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
621 copyToClip(m_pDoc
, ScRange(0,0,0,m_pDoc
->MaxCol(),0,0), &aClipDoc
);
622 ScRange
aTargetRange(0,4,0,m_pDoc
->MaxCol(),4,0);
623 pasteOneCellFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
625 ScConditionalFormat
* pNewFormat
= m_pDoc
->GetCondFormat(0, 4, 0);
626 CPPUNIT_ASSERT(pNewFormat
);
627 CPPUNIT_ASSERT_EQUAL(pNewFormat
->GetKey(), pFormatTmp
->GetKey());
629 for (SCCOL nCol
= 1; nCol
<= m_pDoc
->MaxCol(); ++nCol
)
631 ScConditionalFormat
* pNewFormat2
= m_pDoc
->GetCondFormat(nCol
, 4, 0);
632 CPPUNIT_ASSERT(!pNewFormat2
);
635 m_pDoc
->DeleteTab(0);
638 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSingleRowToRange2
)
640 m_pDoc
->InsertTab(0, "Test");
642 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
643 ScRange
aCondFormatRange(0,0,0,0,0,0);
644 ScRangeList
aRangeList(aCondFormatRange
);
645 pFormat
->SetRange(aRangeList
);
647 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
648 pFormat
->AddEntry(pEntry
);
649 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
651 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
652 copyToClip(m_pDoc
, ScRange(0,0,0,3,0,0), &aClipDoc
);
653 ScRange
aTargetRange(0,4,0,m_pDoc
->MaxCol(),4,0);
654 pasteOneCellFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
656 for (SCCOL nCol
= 0; nCol
<= m_pDoc
->MaxCol(); ++nCol
)
658 ScConditionalFormat
* pNewFormat
= m_pDoc
->GetCondFormat(nCol
, 4, 0);
660 CPPUNIT_ASSERT(pNewFormat
);
662 CPPUNIT_ASSERT(!pNewFormat
);
665 m_pDoc
->DeleteTab(0);
668 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSheetBetweenDoc
)
670 m_pDoc
->InsertTab(0, "Test");
672 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
673 ScRange
aCondFormatRange(0,0,0,3,3,0);
674 ScRangeList
aRangeList(aCondFormatRange
);
675 pFormat
->SetRange(aRangeList
);
677 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
678 pFormat
->AddEntry(pEntry
);
679 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
682 aDoc
.TransferTab(*m_pDoc
, 0, 0);
684 ScConditionalFormatList
* pList
= aDoc
.GetCondFormList(0);
685 CPPUNIT_ASSERT_EQUAL(size_t(1), pList
->size());
687 m_pDoc
->DeleteTab(0);
690 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondCopyPasteSheet
)
692 m_pDoc
->InsertTab(0, "Test");
694 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
695 ScRange
aCondFormatRange(0,0,0,3,3,0);
696 ScRangeList
aRangeList(aCondFormatRange
);
697 pFormat
->SetRange(aRangeList
);
699 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Direct
,"=B2","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
700 pFormat
->AddEntry(pEntry
);
701 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
703 m_pDoc
->CopyTab(0, SC_TAB_APPEND
);
705 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(1);
706 CPPUNIT_ASSERT_EQUAL(size_t(1), pList
->size());
708 ScConditionalFormat
& rFormat
= **pList
->begin();
709 const ScRangeList
& rRange
= rFormat
.GetRange();
710 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,1,3,3,1)), rRange
);
711 sal_uInt32 nKey
= rFormat
.GetKey();
712 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 2, 2, 1, ATTR_CONDITIONAL
);
713 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
715 CPPUNIT_ASSERT(pCondFormatItem
);
716 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
717 CPPUNIT_ASSERT_EQUAL( nKey
, pCondFormatItem
->GetCondFormatData().front() );
719 m_pDoc
->DeleteTab(1);
720 m_pDoc
->DeleteTab(0);
723 CPPUNIT_TEST_FIXTURE(TestCondformat
, testIconSet
)
725 m_pDoc
->InsertTab(0, "Test");
726 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
728 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
729 ScRangeList
aRangeList(ScRange(0,0,0,0,0,0));
730 pFormat
->SetRange(aRangeList
);
732 ScIconSetFormat
* pEntry
= new ScIconSetFormat(m_pDoc
);
733 ScIconSetFormatData
* pData
= new ScIconSetFormatData
;
734 pData
->m_Entries
.emplace_back(new ScColorScaleEntry(0, COL_BLUE
));
735 pData
->m_Entries
.emplace_back(new ScColorScaleEntry(1, COL_GREEN
));
736 pData
->m_Entries
.emplace_back(new ScColorScaleEntry(2, COL_RED
));
737 pEntry
->SetIconSetData(pData
);
739 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
740 pList
->InsertNew(std::move(pFormat
));
743 double nVal
; sal_Int32 nIndex
;
751 for(size_t i
= 0; i
< SAL_N_ELEMENTS(aTests
); ++i
)
753 m_pDoc
->SetValue(0,0,0,aTests
[i
].nVal
);
754 std::unique_ptr
<ScIconSetInfo
> pInfo
= pEntry
->GetIconSetInfo(ScAddress(0,0,0));
755 CPPUNIT_ASSERT_EQUAL(aTests
[i
].nIndex
, pInfo
->nIconIndex
);
759 m_pDoc
->DeleteTab(0);
762 CPPUNIT_TEST_FIXTURE(TestCondformat
, testDataBarLengthAutomaticAxis
)
764 m_pDoc
->InsertTab(0, "Test");
766 static const ScDataBarLengthData aValues
[] = {
778 testDataBarLengthImpl(m_pDoc
, aValues
, ScRange(0,0,0,0,7,0),
779 3, COLORSCALE_VALUE
, 7, COLORSCALE_VALUE
, 0.0, databar::AUTOMATIC
);
781 static const ScDataBarLengthData aValues2
[] = {
800 testDataBarLengthImpl(m_pDoc
, aValues2
, ScRange(1,0,0,1,15,0),
801 -4, COLORSCALE_VALUE
, 8, COLORSCALE_VALUE
, 1.0/3.0 * 100, databar::AUTOMATIC
);
803 static const ScDataBarLengthData aValues3
[] = {
810 testDataBarLengthImpl(m_pDoc
, aValues3
, ScRange(2,0,0,2,3,0),
811 0, COLORSCALE_MIN
, 0, COLORSCALE_MAX
, 0, databar::AUTOMATIC
);
813 static const ScDataBarLengthData aValues4
[] = {
820 testDataBarLengthImpl(m_pDoc
, aValues4
, ScRange(3,0,0,3,3,0),
821 0, COLORSCALE_AUTO
, 0, COLORSCALE_AUTO
, 0, databar::AUTOMATIC
);
823 m_pDoc
->DeleteTab(0);
826 CPPUNIT_TEST_FIXTURE(TestCondformat
, testDataBarLengthMiddleAxis
)
828 m_pDoc
->InsertTab(0, "Test");
830 static const ScDataBarLengthData aValues
[] = {
843 testDataBarLengthImpl(m_pDoc
, aValues
, ScRange(0,0,0,0,8,0),
844 2, COLORSCALE_VALUE
, 8, COLORSCALE_VALUE
, 50.0, databar::MIDDLE
);
846 static const ScDataBarLengthData aValues2
[] = {
865 testDataBarLengthImpl(m_pDoc
, aValues2
, ScRange(1,0,0,1,15,0),
866 -4, COLORSCALE_VALUE
, 8, COLORSCALE_VALUE
, 50.0, databar::MIDDLE
);
868 m_pDoc
->DeleteTab(0);
871 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatEndsWithStr
)
873 m_pDoc
->InsertTab(0, "Test");
875 // case insensitive matching
876 ScConditionEntry
aEntry(ScConditionMode::EndsWith
, "\"teststring\"", "", *m_pDoc
, ScAddress(),
877 "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
879 svl::SharedStringPool
& rStringPool
= m_pDoc
->GetSharedStringPool();
880 svl::SharedString aStr
= rStringPool
.intern("SimpleTestString");
881 ScRefCellValue
aVal(&aStr
);
882 ScAddress
aPos(0, 0, 0);
884 bool bValid
= aEntry
.IsCellValid(aVal
, aPos
);
885 CPPUNIT_ASSERT(bValid
);
887 m_pDoc
->DeleteTab(0);
890 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatEndsWithVal
)
892 m_pDoc
->InsertTab(0, "Test");
894 ScConditionEntry
aEntry(ScConditionMode::EndsWith
, "2", "", *m_pDoc
, ScAddress(),
895 "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
897 for (sal_Int32 i
= 0; i
< 15; ++i
)
899 ScRefCellValue
aVal(i
);
900 ScAddress
aPos(0, 0, 0);
902 bool bValid
= aEntry
.IsCellValid(aVal
, aPos
);
903 bool bShouldBeValid
= (i
% 10) == 2;
904 CPPUNIT_ASSERT_EQUAL(bShouldBeValid
, bValid
);
907 m_pDoc
->DeleteTab(0);
910 CPPUNIT_TEST_FIXTURE(TestCondformat
, testFormulaListenerSingleCellToSingleCell
)
912 m_pDoc
->InsertTab(0, "test");
914 ScCompiler
aCompiler(*m_pDoc
, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH
);
916 std::unique_ptr
<ScTokenArray
> pTokenArray(aCompiler
.CompileString("A1"));
918 ScFormulaListener
aListener(*m_pDoc
);
920 aListener
.addTokenArray(pTokenArray
.get(), ScAddress(10, 10, 0));
922 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
923 CPPUNIT_ASSERT(aListener
.NeedsRepaint());
925 m_pDoc
->DeleteTab(0);
928 CPPUNIT_TEST_FIXTURE(TestCondformat
, testFormulaListenerSingleCellToMultipleCells
)
930 m_pDoc
->InsertTab(0, "test");
932 ScCompiler
aCompiler(*m_pDoc
, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH
);
934 std::unique_ptr
<ScTokenArray
> pTokenArray(aCompiler
.CompileString("A1"));
936 ScFormulaListener
aListener(*m_pDoc
);
938 aListener
.addTokenArray(pTokenArray
.get(), ScAddress(10, 10, 0));
940 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
941 CPPUNIT_ASSERT(aListener
.NeedsRepaint());
943 m_pDoc
->DeleteTab(0);
946 CPPUNIT_TEST_FIXTURE(TestCondformat
, testFormulaListenerMultipleCellsToSingleCell
)
948 m_pDoc
->InsertTab(0, "test");
950 ScCompiler
aCompiler(*m_pDoc
, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH
);
952 std::unique_ptr
<ScTokenArray
> pTokenArray(aCompiler
.CompileString("A1"));
954 ScFormulaListener
aListener(*m_pDoc
);
956 aListener
.addTokenArray(pTokenArray
.get(), ScAddress(10, 10, 0));
958 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
959 CPPUNIT_ASSERT(aListener
.NeedsRepaint());
961 m_pDoc
->DeleteTab(0);
964 CPPUNIT_TEST_FIXTURE(TestCondformat
, testFormulaListenerMultipleCellsToMultipleCells
)
966 m_pDoc
->InsertTab(0, "test");
968 ScCompiler
aCompiler(*m_pDoc
, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH
);
970 std::unique_ptr
<ScTokenArray
> pTokenArray(aCompiler
.CompileString("A1"));
972 ScFormulaListener
aListener(*m_pDoc
);
974 aListener
.addTokenArray(pTokenArray
.get(), ScAddress(10, 10, 0));
976 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
977 CPPUNIT_ASSERT(aListener
.NeedsRepaint());
979 m_pDoc
->DeleteTab(0);
982 CPPUNIT_TEST_FIXTURE(TestCondformat
, testFormulaListenerUpdateInsertTab
)
984 m_pDoc
->InsertTab(0, "test");
986 ScCompiler
aCompiler(*m_pDoc
, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH
);
987 std::unique_ptr
<ScTokenArray
> pTokenArray(aCompiler
.CompileString("A1"));
989 ScFormulaListener
aListener(*m_pDoc
);
990 aListener
.addTokenArray(pTokenArray
.get(), ScAddress(10, 10, 0));
991 CPPUNIT_ASSERT(!aListener
.NeedsRepaint());
993 m_pDoc
->InsertTab(0, "new_tab");
995 // check that the listener has moved to the new sheet
996 m_pDoc
->SetValue(ScAddress(0, 0, 1), 1.0);
997 CPPUNIT_ASSERT(aListener
.NeedsRepaint());
999 // check that we are not listening to the old sheet
1000 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
1001 CPPUNIT_ASSERT(!aListener
.NeedsRepaint());
1003 m_pDoc
->DeleteTab(0);
1006 CPPUNIT_TEST_FIXTURE(TestCondformat
, testFormulaListenerUpdateDeleteTab
)
1008 m_pDoc
->InsertTab(0, "test");
1009 m_pDoc
->InsertTab(0, "to_delete");
1011 ScCompiler
aCompiler(*m_pDoc
, ScAddress(10, 10, 1), formula::FormulaGrammar::GRAM_ENGLISH
);
1012 std::unique_ptr
<ScTokenArray
> pTokenArray(aCompiler
.CompileString("A1"));
1014 ScFormulaListener
aListener(*m_pDoc
);
1015 aListener
.addTokenArray(pTokenArray
.get(), ScAddress(10, 10, 1));
1016 CPPUNIT_ASSERT(!aListener
.NeedsRepaint());
1018 m_pDoc
->DeleteTab(0);
1020 // check that the listener has moved
1021 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
1022 CPPUNIT_ASSERT(aListener
.NeedsRepaint());
1024 m_pDoc
->DeleteTab(0);
1027 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUpdateMoveTab
)
1029 m_pDoc
->InsertTab(0, "test");
1030 m_pDoc
->InsertTab(1, "Test2");
1032 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "A1", "", *m_pDoc
, ScAddress(10, 10, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1034 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1035 pFormat
->SetRange(ScRange(10, 10, 0, 10, 12, 0));
1036 auto pFormatTmp
= pFormat
.get();
1037 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
1039 pFormatTmp
->AddEntry(pEntry
);
1041 // the conditional format should listen to A1:A3
1042 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1044 m_pDoc
->SetValue(ScAddress(0, nRow
, 0), 1.0);
1045 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1048 m_pDoc
->MoveTab(0, 1);
1050 // the conditional format should listen to A1:A3 on the second sheet
1051 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1053 m_pDoc
->SetValue(ScAddress(0, nRow
, 1), 1.0);
1054 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1056 m_pDoc
->SetValue(ScAddress(0, nRow
, 0), 1.0);
1057 CPPUNIT_ASSERT(!pEntry
->NeedsRepaint());
1060 m_pDoc
->DeleteTab(1);
1061 m_pDoc
->DeleteTab(0);
1064 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUpdateInsertTab
)
1066 m_pDoc
->InsertTab(0, "test");
1068 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "A1", "", *m_pDoc
, ScAddress(10, 10, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1070 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1071 pFormat
->SetRange(ScRange(10, 10, 0, 10, 12, 0));
1072 auto pFormatTmp
= pFormat
.get();
1073 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
1075 pFormatTmp
->AddEntry(pEntry
);
1077 // the conditional format should listen to A1:A3
1078 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1080 m_pDoc
->SetValue(ScAddress(0, nRow
, 0), 1.0);
1081 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1083 m_pDoc
->SetValue(ScAddress(0, nRow
, 1), 1.0);
1084 CPPUNIT_ASSERT(!pEntry
->NeedsRepaint());
1087 m_pDoc
->InsertTab(0, "test2");
1089 // the conditional format should listen to A1:A3 on the second sheet
1090 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1092 m_pDoc
->SetValue(ScAddress(0, nRow
, 1), 1.0);
1093 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1095 m_pDoc
->SetValue(ScAddress(0, nRow
, 0), 1.0);
1096 CPPUNIT_ASSERT(!pEntry
->NeedsRepaint());
1099 m_pDoc
->DeleteTab(1);
1100 m_pDoc
->DeleteTab(0);
1103 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUpdateDeleteTab
)
1105 m_pDoc
->InsertTab(0, "test");
1106 m_pDoc
->InsertTab(1, "Test2");
1108 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "A1", "", *m_pDoc
, ScAddress(10, 10, 1), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1110 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1111 pFormat
->SetRange(ScRange(10, 10, 1, 10, 12, 1));
1112 auto pFormatTmp
= pFormat
.get();
1113 m_pDoc
->AddCondFormat(std::move(pFormat
), 1);
1115 pFormatTmp
->AddEntry(pEntry
);
1117 // the conditional format should listen to A1:A3 on the second sheet
1118 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1120 m_pDoc
->SetValue(ScAddress(0, nRow
, 1), 1.0);
1121 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1124 m_pDoc
->DeleteTab(0);
1126 // the conditional format should listen to A1:A3 on the second sheet
1127 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1129 m_pDoc
->SetValue(ScAddress(0, nRow
, 0), 1.0);
1130 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1133 m_pDoc
->DeleteTab(0);
1136 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUpdateReference
)
1138 m_pDoc
->InsertTab(0, "test");
1139 m_pDoc
->InsertTab(1, "Test2");
1141 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "A1", "", *m_pDoc
, ScAddress(10, 10, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1143 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1144 pFormat
->SetRange(ScRange(10, 10, 0, 10, 12, 0));
1145 auto pFormatTmp
= pFormat
.get();
1146 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
1148 pFormatTmp
->AddEntry(pEntry
);
1150 // the conditional format should listen to A1:A3
1151 for (SCROW nRow
= 0; nRow
< 3; ++nRow
)
1153 m_pDoc
->SetValue(ScAddress(0, nRow
, 0), 1.0);
1154 CPPUNIT_ASSERT(pEntry
->NeedsRepaint());
1157 m_pDoc
->DeleteTab(1);
1158 m_pDoc
->DeleteTab(0);
1161 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUpdateReferenceDelRow
)
1163 m_pDoc
->InsertTab(0, "test");
1165 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "B6", "", *m_pDoc
, ScAddress(0, 5, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1167 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1168 pFormat
->SetRange(ScRange(0, 5, 0, 0, 5, 0));
1169 auto pFormatTmp
= pFormat
.get();
1170 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
1172 pFormatTmp
->AddEntry(pEntry
);
1174 m_pDoc
->DeleteRow(0, 0, m_pDoc
->MaxCol(), 0, 4, 1);
1176 OUString aStr
= pEntry
->GetExpression(ScAddress(0, 4, 0), 0);
1177 CPPUNIT_ASSERT_EQUAL(OUString("B5"), aStr
);
1179 m_pDoc
->DeleteTab(0);
1182 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUpdateReferenceInsRow
)
1184 m_pDoc
->InsertTab(0, "test");
1186 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "B6", "", *m_pDoc
, ScAddress(0, 5, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1188 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1189 pFormat
->SetRange(ScRange(0, 5, 0, 0, 5, 0));
1190 auto pFormatTmp
= pFormat
.get();
1191 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
1193 pFormatTmp
->AddEntry(pEntry
);
1195 m_pDoc
->InsertRow(0, 0, m_pDoc
->MaxCol(), 0, 4, 1);
1197 OUString aStr
= pEntry
->GetExpression(ScAddress(0, 6, 0), 0);
1198 CPPUNIT_ASSERT_EQUAL(OUString("B7"), aStr
);
1200 m_pDoc
->DeleteTab(0);
1203 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatUndoList
)
1205 m_pDoc
->InsertTab(0, "test");
1207 ScConditionEntry
* pEntry
= new ScConditionEntry(ScConditionMode::Equal
, "B6", "", *m_pDoc
, ScAddress(0, 5, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT
, formula::FormulaGrammar::GRAM_DEFAULT
);
1209 auto pFormat
= std::make_unique
<ScConditionalFormat
>(0, m_pDoc
);
1210 pFormat
->AddEntry(pEntry
);
1211 pFormat
->SetRange(ScRange(0, 0, 0, 0, 5, 0));
1212 auto pFormatTmp
= pFormat
.get();
1213 m_pDoc
->AddCondFormat(std::move(pFormat
), 0);
1214 m_pDoc
->AddCondFormatData(pFormatTmp
->GetRange(), 0, pFormatTmp
->GetKey());
1216 ScDocFunc
& rFunc
= m_xDocShell
->GetDocFunc();
1218 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
1219 for (SCROW nRow
= 0; nRow
<= 5; ++nRow
)
1220 CPPUNIT_ASSERT(m_pDoc
->GetCondFormat(0, nRow
, 0));
1222 ScConditionalFormatList
* pNewList
= new ScConditionalFormatList();
1224 rFunc
.SetConditionalFormatList(pNewList
, 0);
1226 CPPUNIT_ASSERT_EQUAL(size_t(0), m_pDoc
->GetCondFormList(0)->size());
1227 for (SCROW nRow
= 0; nRow
<= 5; ++nRow
)
1228 CPPUNIT_ASSERT(!m_pDoc
->GetCondFormat(0, nRow
, 0));
1230 m_pDoc
->GetUndoManager()->Undo();
1232 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc
->GetCondFormList(0)->size());
1233 for (SCROW nRow
= 0; nRow
<= 5; ++nRow
)
1234 CPPUNIT_ASSERT(m_pDoc
->GetCondFormat(0, nRow
, 0));
1236 m_pDoc
->GetUndoManager()->Redo();
1238 CPPUNIT_ASSERT_EQUAL(size_t(0), m_pDoc
->GetCondFormList(0)->size());
1239 for (SCROW nRow
= 0; nRow
<= 5; ++nRow
)
1240 CPPUNIT_ASSERT(!m_pDoc
->GetCondFormat(0, nRow
, 0));
1242 m_pDoc
->DeleteTab(0);
1245 CPPUNIT_TEST_FIXTURE(TestCondformat
, testMultipleSingleCellCondFormatCopyPaste
)
1247 m_pDoc
->InsertTab(0, "Test");
1249 sal_uInt32 nFirstCondFormatKey
= addSingleCellCondFormat(m_pDoc
, ScAddress(0, 0, 0), 1, "=A2");
1250 sal_uInt32 nSecondCondFormatKey
= addSingleCellCondFormat(m_pDoc
, ScAddress(1, 0, 0), 2, "=B3");
1252 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
1253 copyToClip(m_pDoc
, ScRange(0,0,0,2,0,0), &aClipDoc
);
1254 ScRange
aTargetRange(2,4,0,7,4,0);
1255 pasteOneCellFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
1257 for (SCCOL nCol
= 2; nCol
<= 7; ++nCol
)
1259 ScConditionalFormat
* pFormat
= m_pDoc
->GetCondFormat(nCol
, 4, 0);
1260 if (((nCol
- 2) % 3) == 0)
1262 CPPUNIT_ASSERT_EQUAL(pFormat
->GetKey(), nFirstCondFormatKey
);
1264 else if (((nCol
- 2) % 3) == 1)
1266 CPPUNIT_ASSERT_EQUAL(pFormat
->GetKey(), nSecondCondFormatKey
);
1270 CPPUNIT_ASSERT(!pFormat
);
1274 m_pDoc
->DeleteTab(0);
1277 CPPUNIT_TEST_FIXTURE(TestCondformat
, testDeduplicateMultipleCondFormats
)
1279 m_pDoc
->InsertTab(0, "Test");
1281 sal_uInt32 nFirstCondFormatKey
= addSingleCellCondFormat(m_pDoc
, ScAddress(0, 0, 0), 1, "=B2");
1282 sal_uInt32 nSecondCondFormatKey
= addSingleCellCondFormat(m_pDoc
, ScAddress(1, 0, 0), 2, "=B2");
1284 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
1285 copyToClip(m_pDoc
, ScRange(0,0,0,2,0,0), &aClipDoc
);
1286 ScRange
aTargetRange(2,4,0,7,4,0);
1287 pasteOneCellFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
1289 for (SCCOL nCol
= 2; nCol
<= 7; ++nCol
)
1291 ScConditionalFormat
* pFormat
= m_pDoc
->GetCondFormat(nCol
, 4, 0);
1292 if (((nCol
- 2) % 3) == 0)
1294 CPPUNIT_ASSERT_EQUAL(pFormat
->GetKey(), nFirstCondFormatKey
);
1296 else if (((nCol
- 2) % 3) == 1)
1298 CPPUNIT_ASSERT_EQUAL(pFormat
->GetKey(), nSecondCondFormatKey
);
1302 CPPUNIT_ASSERT(!pFormat
);
1306 m_pDoc
->DeleteTab(0);
1309 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatListenToOwnRange
)
1311 m_pDoc
->InsertTab(0, "Test");
1313 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
1315 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
1316 ScRangeList
aRangeList(ScRange(0,0,0,10,0,0));
1317 pFormat
->SetRange(aRangeList
);
1319 ScIconSetFormat
* pEntry
= new ScIconSetFormat(m_pDoc
);
1320 ScIconSetFormatData
* pData
= new ScIconSetFormatData
;
1321 pData
->m_Entries
.emplace_back(new ScColorScaleEntry(0, COL_BLUE
));
1322 pData
->m_Entries
.emplace_back(new ScColorScaleEntry(1, COL_GREEN
));
1323 pData
->m_Entries
.emplace_back(new ScColorScaleEntry(2, COL_RED
));
1324 pEntry
->SetIconSetData(pData
);
1325 pEntry
->SetParent(pFormat
.get());
1327 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
1328 pFormat
->AddEntry(pEntry
);
1329 pList
->InsertNew(std::move(pFormat
));
1331 bool bFirstCallbackCalled
= false;
1332 std::function
<void()> aFirstCallback
= [&]() {bFirstCallbackCalled
= true;};
1333 pData
->m_Entries
[0]->SetType(COLORSCALE_PERCENT
);
1334 pData
->m_Entries
[0]->SetRepaintCallback(aFirstCallback
);
1336 m_pDoc
->SetValue(0, 0, 0, -1.0);
1338 CPPUNIT_ASSERT(bFirstCallbackCalled
);
1340 m_pDoc
->DeleteTab(0);
1343 CPPUNIT_TEST_FIXTURE(TestCondformat
, testCondFormatVolatileFunctionRecalc
)
1345 m_pDoc
->InsertTab(0, "Test");
1347 m_pDoc
->SetValue(0, 0, 0, 0.5);
1349 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
1351 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
1352 ScRangeList
aRangeList(ScRange(0,0,0,10,0,0));
1353 pFormat
->SetRange(aRangeList
);
1355 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(ScConditionMode::Greater
,"RAND()","",*m_pDoc
,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT
));
1356 pEntry
->SetParent(pFormat
.get());
1358 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
1359 pFormat
->AddEntry(pEntry
);
1360 auto pFormatTmp
= pFormat
.get();
1361 pList
->InsertNew(std::move(pFormat
));
1363 ScRefCellValue
aCell(*m_pDoc
, ScAddress(0, 0, 0));
1364 bool bValid
= pEntry
->IsCellValid(aCell
, ScAddress(0, 0, 0));
1366 bool bNewValid
= bValid
;
1367 // chance of a random failure is 0.5^100, anyone hitting that will get a beer from me
1368 for (size_t i
= 0; i
< 100; ++i
)
1370 pFormatTmp
->CalcAll();
1371 bNewValid
= pEntry
->IsCellValid(aCell
, ScAddress(0, 0, 0));
1373 if (bValid
!= bNewValid
)
1377 CPPUNIT_ASSERT(bValid
!= bNewValid
);
1379 m_pDoc
->DeleteTab(0);
1382 CPPUNIT_TEST_FIXTURE(TestCondformat
, testConditionStyleInMergedCell
)
1384 m_pDoc
->InsertTab(0, "Test");
1386 PaintListener aListener
;
1387 aListener
.StartListening(*m_xDocShell
);
1389 m_pDoc
->DoMerge(0, 0, 0, 1, 0); // A1:A2
1390 CPPUNIT_ASSERT(m_pDoc
->IsMerged(ScAddress(0, 0, 0)));
1392 m_pDoc
->SetValue(ScAddress(0, 0, 0), 1.0);
1394 // Add a conditional format.
1395 auto pFormat
= std::make_unique
<ScConditionalFormat
>(1, m_pDoc
);
1396 pFormat
->SetRange(ScRange(0, 0, 0, 0, 0, 0));
1398 // Add condition in which if the value equals 1, set the "Good" style.
1399 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(
1400 ScConditionMode::Equal
, "=1", "", *m_pDoc
, ScAddress(0, 0, 0), ScResId(STR_STYLENAME_GOOD
));
1401 pFormat
->AddEntry(pEntry
);
1403 // Apply the format to the range.
1404 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
1406 ScDocFunc
& rFunc
= m_xDocShell
->GetDocFunc();
1407 sal_uInt32 nOldFormat
= pFormat
->GetKey();
1408 const ScRangeList
& rRangeList
= pFormat
->GetRange();
1409 rFunc
.ReplaceConditionalFormat(nOldFormat
, std::move(pFormat
), 0, rRangeList
);
1411 CPPUNIT_ASSERT_EQUAL(true, aListener
.mbPaintAllMergedCell
);
1413 m_pDoc
->DeleteTab(0);
1416 CPPUNIT_PLUGIN_IMPLEMENT();
1418 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */