2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <sal/config.h>
12 #include <test/bootstrapfixture.hxx>
14 #include <rtl/strbuf.hxx>
15 #include <osl/file.hxx>
19 #include "formulacell.hxx"
20 #include "stringutil.hxx"
21 #include "scmatrix.hxx"
22 #include "drwlayer.hxx"
23 #include "scitems.hxx"
24 #include "reffind.hxx"
25 #include "markdata.hxx"
26 #include "clipparam.hxx"
27 #include "refundo.hxx"
28 #include "undoblk.hxx"
29 #include "undotab.hxx"
30 #include "queryentry.hxx"
34 #include "reftokenhelper.hxx"
35 #include "userdat.hxx"
38 #include "docfunc.hxx"
39 #include "dbdocfun.hxx"
40 #include "funcdesc.hxx"
41 #include "externalrefmgr.hxx"
43 #include "calcconfig.hxx"
44 #include "interpre.hxx"
45 #include "columniterator.hxx"
47 #include "conditio.hxx"
48 #include "colorscale.hxx"
49 #include "fillinfo.hxx"
50 #include "globstr.hrc"
51 #include "tokenarray.hxx"
52 #include "scopetools.hxx"
53 #include "dociter.hxx"
54 #include "queryparam.hxx"
55 #include "edittextiterator.hxx"
56 #include "editutil.hxx"
57 #include <asciiopt.hxx>
59 #include <columnspanset.hxx>
60 #include <docoptio.hxx>
61 #include <patattr.hxx>
62 #include <docpool.hxx>
63 #include <globalnames.hxx>
64 #include <inputopt.hxx>
66 #include <editable.hxx>
67 #include <bcaslot.hxx>
68 #include <sharedformula.hxx>
70 #include <formula/IFunctionDescription.hxx>
72 #include <basegfx/polygon/b2dpolygon.hxx>
73 #include <editeng/boxitem.hxx>
74 #include <editeng/brushitem.hxx>
75 #include <editeng/wghtitem.hxx>
76 #include <editeng/postitem.hxx>
78 #include <svx/svdograf.hxx>
79 #include <svx/svdpage.hxx>
80 #include <svx/svdocirc.hxx>
81 #include <svx/svdopath.hxx>
82 #include <svx/svdocapt.hxx>
83 #include <svl/srchitem.hxx>
84 #include <svl/sharedstringpool.hxx>
86 #include <sfx2/docfile.hxx>
92 #include <com/sun/star/i18n/TransliterationModules.hpp>
96 ScDocShellRef m_xDocShell
;
99 FormulaGrammarSwitch::FormulaGrammarSwitch(ScDocument
* pDoc
, formula::FormulaGrammar::Grammar eGrammar
) :
100 mpDoc(pDoc
), meOldGrammar(pDoc
->GetGrammar())
102 mpDoc
->SetGrammar(eGrammar
);
105 FormulaGrammarSwitch::~FormulaGrammarSwitch()
107 mpDoc
->SetGrammar(meOldGrammar
);
110 class MeasureTimeSwitch
113 TimeValue maTimeBefore
;
115 MeasureTimeSwitch(double& rDiff
) : mrDiff(rDiff
)
118 osl_getSystemTime(&maTimeBefore
);
123 TimeValue aTimeAfter
;
124 osl_getSystemTime(&aTimeAfter
);
125 mrDiff
= getTimeDiff(aTimeAfter
, maTimeBefore
);
128 static double getTimeDiff(const TimeValue
& t1
, const TimeValue
& t2
)
130 double tv1
= t1
.Seconds
;
131 double tv2
= t2
.Seconds
;
132 tv1
+= t1
.Nanosec
/ 1000000000.0;
133 tv2
+= t2
.Nanosec
/ 1000000000.0;
140 m_pImpl(new TestImpl
),
150 ScDocShell
& Test::getDocShell()
152 return *m_pImpl
->m_xDocShell
;
157 BootstrapFixture::setUp();
160 m_pImpl
->m_xDocShell
= new ScDocShell(
161 SfxModelFlags::EMBEDDED_OBJECT
|
162 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS
|
163 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY
);
165 m_pImpl
->m_xDocShell
->DoInitUnitTest();
166 m_pDoc
= &m_pImpl
->m_xDocShell
->GetDocument();
169 void Test::tearDown()
171 m_pImpl
->m_xDocShell
->DoClose();
172 m_pImpl
->m_xDocShell
.Clear();
173 BootstrapFixture::tearDown();
176 #define PERF_ASSERT(df,scale,time,message) \
178 double dfscaled = df / scale; \
179 if ((dfscaled) >= (time)) \
181 std::ostringstream os; \
182 os << message " took " << dfscaled << " pseudo-cycles (" << df << " real-time seconds), expected: " << time << " pseudo-cycles."; \
183 CPPUNIT_FAIL(os.str().c_str()); \
187 void Test::testPerf()
189 CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc
->InsertTab (0, "foo"));
191 // First do a set of simple operations to try to work out
192 // how fast (or not) this particular machine is:
195 MeasureTimeSwitch
aTime(scale
);
196 for (int i
= 0; i
< 10000000; ++i
)
198 // Bang on the allocator
199 volatile ScRange
*pRange
= new ScRange (ScAddress (0,0,0));
200 // Calc does quite a bit of string conversion
201 volatile double it
= OUString::number ((double)i
/253.0).toDouble();
202 // Do we have floating point math ?
203 volatile double another
= rtl::math::sin (it
);
208 printf("CPU scale factor %g\n", scale
);
210 // FIXME: we should check if this already took too long
211 // and if so not run the perf. tests to have pity on some
212 // slow ARM machines - I think.
214 // to make the numbers more round and helpful,
215 // but the calculation of scale reasonably precise.
220 // Clearing an already empty sheet should finish in a fraction of a
221 // second. Flag failure if it takes more than one second. Clearing 100
222 // columns should be large enough to flag if something goes wrong.
224 MeasureTimeSwitch
aTime(diff
);
225 clearRange(m_pDoc
, ScRange(0,0,0,99,MAXROW
,0));
227 PERF_ASSERT(diff
, scale
, 1.0, "Clearing an empty sheet");
230 // Switch to R1C1 to make it easier to input relative references in multiple cells.
231 FormulaGrammarSwitch
aFGSwitch(m_pDoc
, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1
);
233 // Insert formulas in B1:B100000. This shouldn't take long, but may take
234 // close to a second on a slower machine. We don't measure this yet, for
236 for (SCROW i
= 0; i
< 100000; ++i
)
237 m_pDoc
->SetString(ScAddress(1,i
,0), "=RC[-1]");
239 // Now, Delete B2:B100000. This should complete in a fraction of a second
240 // (0.06 sec on my machine).
242 MeasureTimeSwitch
aTime(diff
);
243 clearRange(m_pDoc
, ScRange(1,1,0,1,99999,0));
245 PERF_ASSERT(diff
, scale
, 2000, "Removal of a large array of formula cells");
248 clearRange(m_pDoc
, ScRange(0,0,0,1,MAXROW
,0)); // Clear columns A:B.
249 CPPUNIT_ASSERT_MESSAGE("Column A shouldn't have any broadcasters.", !m_pDoc
->HasBroadcaster(0,0));
250 CPPUNIT_ASSERT_MESSAGE("Column B shouldn't have any broadcasters.", !m_pDoc
->HasBroadcaster(0,1));
253 // Measure the performance of repeat-pasting a single cell to a large
254 // cell range, undoing it, and redoing it.
256 ScAddress
aPos(0,0,0);
257 m_pDoc
->SetString(aPos
, "test");
259 aMark
.SelectOneTable(0);
261 // Copy cell A1 to clipboard.
262 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
263 ScClipParam
aParam(aPos
, false);
264 m_pDoc
->CopyToClip(aParam
, &aClipDoc
, &aMark
);
265 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), aClipDoc
.GetString(aPos
));
267 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
268 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
269 m_pDoc
->CopyToDocument(ScRange(aPos
), IDF_CONTENTS
, false, pUndoDoc
, &aMark
);
271 // Paste it to A2:A100000, and measure its duration.
272 ScRange
aPasteRange(0,1,0,0,99999,0);
273 aMark
.SetMarkArea(aPasteRange
);
276 MeasureTimeSwitch
aTime(diff
);
277 m_pDoc
->CopyFromClip(aPasteRange
, aMark
, IDF_CONTENTS
, pUndoDoc
, &aClipDoc
);
279 PERF_ASSERT(diff
, scale
, 1500.0, "Pasting a single cell to A2:A100000");
281 ScDocument
* pRedoDoc
= new ScDocument(SCDOCMODE_UNDO
);
282 pRedoDoc
->InitUndo(m_pDoc
, 0, 0);
283 m_pDoc
->CopyToDocument(aPasteRange
, IDF_CONTENTS
, false, pRedoDoc
, &aMark
);
285 // Create an undo object for this.
286 ScRefUndoData
* pRefUndoData
= new ScRefUndoData(m_pDoc
);
287 ScUndoPaste
aUndo(&getDocShell(), aPasteRange
, aMark
, pUndoDoc
, pRedoDoc
, IDF_CONTENTS
, pRefUndoData
);
289 // Make sure it did what it's supposed to do.
290 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aStart
));
291 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aEnd
));
294 MeasureTimeSwitch
aTime(diff
);
297 PERF_ASSERT(diff
, scale
, 500.0, "Undoing a pasting of a cell to A2:A100000");
299 // Make sure it's really undone.
300 CPPUNIT_ASSERT_EQUAL(CELLTYPE_STRING
, m_pDoc
->GetCellType(aPos
));
301 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aPasteRange
.aStart
));
302 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aPasteRange
.aEnd
));
306 MeasureTimeSwitch
aTime(diff
);
309 PERF_ASSERT(diff
, scale
, 1000.0, "Redoing a pasting of a cell to A2:A100000");
311 // Make sure it's really redone.
312 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aStart
));
313 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aEnd
));
316 clearRange(m_pDoc
, ScRange(0,0,0,1,MAXROW
,0)); // Clear columns A:B.
317 CPPUNIT_ASSERT_MESSAGE("Column A shouldn't have any broadcasters.", !m_pDoc
->HasBroadcaster(0,0));
318 CPPUNIT_ASSERT_MESSAGE("Column B shouldn't have any broadcasters.", !m_pDoc
->HasBroadcaster(0,1));
321 // Measure the performance of repeat-pasting 2 adjacent cells to a
322 // large cell range, undoing it, and redoing it. The bottom one of
323 // the two source cells is empty.
325 ScRange
aSrcRange(0,0,0,0,1,0); // A1:A2
327 ScAddress
aPos(0,0,0);
328 m_pDoc
->SetValue(aPos
, 12);
330 aMark
.SetMarkArea(aSrcRange
);
332 // Copy to clipboard.
333 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
334 ScClipParam
aParam(aSrcRange
, false);
335 m_pDoc
->CopyToClip(aParam
, &aClipDoc
, &aMark
);
336 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), aClipDoc
.GetString(aPos
));
338 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
339 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
340 m_pDoc
->CopyToDocument(aSrcRange
, IDF_CONTENTS
, false, pUndoDoc
, &aMark
);
342 // Paste it to A3:A100001, and measure its duration.
343 ScRange
aPasteRange(0,2,0,0,100000,0);
344 aMark
.SetMarkArea(aPasteRange
);
347 MeasureTimeSwitch
aTime(diff
);
348 m_pDoc
->CopyFromClip(aPasteRange
, aMark
, IDF_CONTENTS
, pUndoDoc
, &aClipDoc
);
350 PERF_ASSERT(diff
, scale
, 1000.0, "Pasting A1:A2 to A3:A100001");
352 ScDocument
* pRedoDoc
= new ScDocument(SCDOCMODE_UNDO
);
353 pRedoDoc
->InitUndo(m_pDoc
, 0, 0);
354 m_pDoc
->CopyToDocument(aPasteRange
, IDF_CONTENTS
, false, pRedoDoc
, &aMark
);
356 // Create an undo object for this.
357 ScRefUndoData
* pRefUndoData
= new ScRefUndoData(m_pDoc
);
358 ScUndoPaste
aUndo(&getDocShell(), aPasteRange
, aMark
, pUndoDoc
, pRedoDoc
, IDF_CONTENTS
, pRefUndoData
);
360 // Make sure it did what it's supposed to do.
361 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aStart
));
362 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aEnd
));
363 ScAddress aTmp
= aPasteRange
.aStart
;
365 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aTmp
));
368 MeasureTimeSwitch
aTime(diff
);
371 PERF_ASSERT(diff
, scale
, 500.0, "Undoing");
373 // Make sure it's really undone.
374 CPPUNIT_ASSERT_EQUAL(CELLTYPE_VALUE
, m_pDoc
->GetCellType(aPos
));
375 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aPasteRange
.aStart
));
376 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aPasteRange
.aEnd
));
380 MeasureTimeSwitch
aTime(diff
);
383 PERF_ASSERT(diff
, scale
, 800.0, "Redoing");
385 // Make sure it's really redone.
386 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aStart
));
387 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), m_pDoc
->GetString(aPasteRange
.aEnd
));
390 clearRange(m_pDoc
, ScRange(0,0,0,1,MAXROW
,0)); // Clear columns A:B.
391 CPPUNIT_ASSERT_MESSAGE("Column A shouldn't have any broadcasters.", !m_pDoc
->HasBroadcaster(0,0));
392 CPPUNIT_ASSERT_MESSAGE("Column B shouldn't have any broadcasters.", !m_pDoc
->HasBroadcaster(0,1));
395 // Measure the performance of repeat-pasting 2 adjacent cells to a
396 // large cell range, undoing it, and redoing it. The bottom one of
397 // the two source cells is empty. In this scenario, the non-empty
398 // cell is a formula cell referencing a cell to the right, which
399 // inserts a broadcaster to cell it references. So it has a higher
400 // overhead than the previous scenario.
402 ScRange
aSrcRange(0,0,0,0,1,0); // A1:A2
404 ScAddress
aPos(0,0,0);
405 m_pDoc
->SetString(aPos
, "=B1");
407 aMark
.SetMarkArea(aSrcRange
);
409 // Copy to clipboard.
410 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
411 ScClipParam
aParam(aSrcRange
, false);
412 m_pDoc
->CopyToClip(aParam
, &aClipDoc
, &aMark
);
413 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), aClipDoc
.GetString(aPos
));
415 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
416 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
417 m_pDoc
->CopyToDocument(aSrcRange
, IDF_CONTENTS
, false, pUndoDoc
, &aMark
);
419 // Paste it to A3:A50001, and measure its duration.
420 ScRange
aPasteRange(0,2,0,0,50000,0);
421 aMark
.SetMarkArea(aPasteRange
);
424 MeasureTimeSwitch
aTime(diff
);
425 m_pDoc
->CopyFromClip(aPasteRange
, aMark
, IDF_CONTENTS
, pUndoDoc
, &aClipDoc
);
427 PERF_ASSERT(diff
, scale
, 2000.0, "Pasting");
429 ScDocument
* pRedoDoc
= new ScDocument(SCDOCMODE_UNDO
);
430 pRedoDoc
->InitUndo(m_pDoc
, 0, 0);
431 m_pDoc
->CopyToDocument(aPasteRange
, IDF_CONTENTS
, false, pRedoDoc
, &aMark
);
433 // Create an undo object for this.
434 ScRefUndoData
* pRefUndoData
= new ScRefUndoData(m_pDoc
);
435 ScUndoPaste
aUndo(&getDocShell(), aPasteRange
, aMark
, pUndoDoc
, pRedoDoc
, IDF_CONTENTS
, pRefUndoData
);
437 // Make sure it did what it's supposed to do.
438 CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA
, m_pDoc
->GetCellType(aPasteRange
.aStart
));
439 CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA
, m_pDoc
->GetCellType(aPasteRange
.aEnd
));
440 ScAddress aTmp
= aPasteRange
.aStart
;
442 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aTmp
));
444 #if 0 // TODO: Undo and redo of this scenario is currently not fast enough to be tested reliably.
446 MeasureTimeSwitch
aTime(diff
);
449 PERF_ASSERT(diff
, scale
, 1.0, "Undoing");
451 // Make sure it's really undone.
452 CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA
, m_pDoc
->GetCellType(aPos
));
453 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aPasteRange
.aStart
));
454 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(aPasteRange
.aEnd
));
458 MeasureTimeSwitch
aTime(diff
);
461 PERF_ASSERT(diff
, scale
, 1.0, "Redoing");
463 // Make sure it's really redone.
464 CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA
, m_pDoc
->GetCellType(aPasteRange
.aStart
));
465 CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA
, m_pDoc
->GetCellType(aPasteRange
.aEnd
));
469 m_pDoc
->DeleteTab(0);
472 void Test::testCollator()
474 CollatorWrapper
* p
= ScGlobal::GetCollator();
475 sal_Int32 nRes
= p
->compareString("A", "B");
476 CPPUNIT_ASSERT_MESSAGE("these strings are supposed to be different!", nRes
!= 0);
479 void Test::testSharedStringPool()
481 m_pDoc
->InsertTab(0, "foo");
483 // Strings that are identical.
484 m_pDoc
->SetString(ScAddress(0,0,0), "Andy"); // A1
485 m_pDoc
->SetString(ScAddress(0,1,0), "Andy"); // A2
486 m_pDoc
->SetString(ScAddress(0,2,0), "Bruce"); // A3
487 m_pDoc
->SetString(ScAddress(0,3,0), "andy"); // A4
488 m_pDoc
->SetString(ScAddress(0,4,0), "BRUCE"); // A5
491 // These two shared string objects must go out of scope before the purge test.
492 svl::SharedString aSS1
= m_pDoc
->GetSharedString(ScAddress(0,0,0));
493 svl::SharedString aSS2
= m_pDoc
->GetSharedString(ScAddress(0,1,0));
494 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid shared string.", aSS1
.isValid());
495 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid shared string.", aSS2
.isValid());
496 CPPUNIT_ASSERT_EQUAL(aSS1
.getData(), aSS2
.getData());
498 aSS2
= m_pDoc
->GetSharedString(ScAddress(0,2,0));
499 CPPUNIT_ASSERT_MESSAGE("They must differ", aSS1
.getData() != aSS2
.getData());
501 aSS2
= m_pDoc
->GetSharedString(ScAddress(0,3,0));
502 CPPUNIT_ASSERT_MESSAGE("They must differ", aSS1
.getData() != aSS2
.getData());
504 aSS2
= m_pDoc
->GetSharedString(ScAddress(0,4,0));
505 CPPUNIT_ASSERT_MESSAGE("They must differ", aSS1
.getData() != aSS2
.getData());
507 // A3 and A5 should differ but should be equal case-insensitively.
508 aSS1
= m_pDoc
->GetSharedString(ScAddress(0,2,0));
509 aSS2
= m_pDoc
->GetSharedString(ScAddress(0,4,0));
510 CPPUNIT_ASSERT_MESSAGE("They must differ", aSS1
.getData() != aSS2
.getData());
511 CPPUNIT_ASSERT_MESSAGE("They must be equal when cases are ignored.", aSS1
.getDataIgnoreCase() == aSS2
.getDataIgnoreCase());
513 // A2 and A4 should be equal when ignoring cases.
514 aSS1
= m_pDoc
->GetSharedString(ScAddress(0,1,0));
515 aSS2
= m_pDoc
->GetSharedString(ScAddress(0,3,0));
516 CPPUNIT_ASSERT_MESSAGE("They must be equal when cases are ignored.", aSS1
.getDataIgnoreCase() == aSS2
.getDataIgnoreCase());
519 // Check the string counts after purging. Purging shouldn't remove any strings in this case.
520 svl::SharedStringPool
& rPool
= m_pDoc
->GetSharedStringPool();
522 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rPool
.getCount());
523 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPool
.getCountIgnoreCase());
525 // Clear A1 and purge again.
526 clearRange(m_pDoc
, ScAddress(0,0,0));
528 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rPool
.getCount());
529 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPool
.getCountIgnoreCase());
531 // Clear A2 and purge again.
532 clearRange(m_pDoc
, ScAddress(0,1,0));
534 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rPool
.getCount());
535 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPool
.getCountIgnoreCase());
537 // Clear A3 and purge again.
538 clearRange(m_pDoc
, ScAddress(0,2,0));
540 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPool
.getCount());
541 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPool
.getCountIgnoreCase());
543 // Clear A4 and purge again.
544 clearRange(m_pDoc
, ScAddress(0,3,0));
546 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPool
.getCount());
547 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPool
.getCountIgnoreCase());
549 // Clear A5 and the pool should be completely empty.
550 clearRange(m_pDoc
, ScAddress(0,4,0));
552 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rPool
.getCount());
553 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rPool
.getCountIgnoreCase());
555 // Now, compare string and edit text cells.
556 m_pDoc
->SetString(ScAddress(0,0,0), "Andy and Bruce"); // A1
557 ScFieldEditEngine
& rEE
= m_pDoc
->GetEditEngine();
558 rEE
.SetText("Andy and Bruce");
561 aSel
.nStartPara
= aSel
.nEndPara
= 0;
565 SfxItemSet aItemSet
= rEE
.GetEmptyItemSet();
568 SvxWeightItem
aWeight(WEIGHT_BOLD
, EE_CHAR_WEIGHT
);
569 aItemSet
.Put(aWeight
);
570 rEE
.QuickSetAttribs(aItemSet
, aSel
);
574 // Set 'Bruce' italic.
575 SfxItemSet aItemSet
= rEE
.GetEmptyItemSet();
576 SvxPostureItem
aItalic(ITALIC_NORMAL
, EE_CHAR_ITALIC
);
577 aItemSet
.Put(aItalic
);
580 rEE
.QuickSetAttribs(aItemSet
, aSel
);
583 m_pDoc
->SetEditText(ScAddress(1,0,0), rEE
.CreateTextObject()); // B1
585 // These two should be equal.
586 svl::SharedString aSS1
= m_pDoc
->GetSharedString(ScAddress(0,0,0));
587 svl::SharedString aSS2
= m_pDoc
->GetSharedString(ScAddress(1,0,0));
588 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid string ID.", aSS1
.isValid());
589 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid string ID.", aSS2
.isValid());
590 CPPUNIT_ASSERT_EQUAL(aSS1
.getData(), aSS2
.getData());
592 rEE
.SetText("ANDY and BRUCE");
593 m_pDoc
->SetEditText(ScAddress(2,0,0), rEE
.CreateTextObject()); // C1
594 aSS2
= m_pDoc
->GetSharedString(ScAddress(2,0,0));
595 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid string ID.", aSS2
.isValid());
596 CPPUNIT_ASSERT_MESSAGE("These two should be different when cases are considered.", aSS1
.getData() != aSS2
.getData());
598 // But they should be considered equal when cases are ignored.
599 aSS1
= m_pDoc
->GetSharedString(ScAddress(0,0,0));
600 aSS2
= m_pDoc
->GetSharedString(ScAddress(2,0,0));
601 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid string ID.", aSS1
.isValid());
602 CPPUNIT_ASSERT_MESSAGE("Failed to get a valid string ID.", aSS2
.isValid());
603 CPPUNIT_ASSERT_EQUAL(aSS1
.getDataIgnoreCase(), aSS2
.getDataIgnoreCase());
605 m_pDoc
->DeleteTab(0);
608 void Test::testSharedStringPoolUndoDoc()
612 bool check( ScDocument
& rSrcDoc
, ScDocument
& rCopyDoc
)
614 // Copy A1:A4 to the undo document.
615 for (SCROW i
= 0; i
<= 4; ++i
)
617 ScAddress
aPos(0,i
,0);
618 rCopyDoc
.SetString(aPos
, rSrcDoc
.GetString(aPos
));
621 // String values in A1:A4 should have identical hash.
622 for (SCROW i
= 0; i
<= 4; ++i
)
624 ScAddress
aPos(0,i
,0);
625 svl::SharedString aSS1
= rSrcDoc
.GetSharedString(aPos
);
626 svl::SharedString aSS2
= rCopyDoc
.GetSharedString(aPos
);
627 if (aSS1
.getDataIgnoreCase() != aSS2
.getDataIgnoreCase())
629 cerr
<< "String hash values are not equal at row " << (i
+1)
630 << " for string '" << aSS1
.getString() << "'" << endl
;
640 m_pDoc
->InsertTab(0, "Test");
642 m_pDoc
->SetString(ScAddress(0,0,0), "Header");
643 m_pDoc
->SetString(ScAddress(0,1,0), "A1");
644 m_pDoc
->SetString(ScAddress(0,2,0), "A2");
645 m_pDoc
->SetString(ScAddress(0,3,0), "A3");
647 ScDocument
aUndoDoc(SCDOCMODE_UNDO
);
648 aUndoDoc
.InitUndo(m_pDoc
, 0, 0);
650 bool bSuccess
= aTest
.check(*m_pDoc
, aUndoDoc
);
651 CPPUNIT_ASSERT_MESSAGE("Check failed with undo document.", bSuccess
);
653 // Test the clip document as well.
654 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
655 aClipDoc
.ResetClip(m_pDoc
, static_cast<SCTAB
>(0));
657 bSuccess
= aTest
.check(*m_pDoc
, aClipDoc
);
658 CPPUNIT_ASSERT_MESSAGE("Check failed with clip document.", bSuccess
);
660 m_pDoc
->DeleteTab(0);
663 void Test::testRangeList()
665 m_pDoc
->InsertTab(0, "foo");
668 aRL
.Append(ScRange(1,1,0,3,10,0));
669 CPPUNIT_ASSERT_MESSAGE("List should have one range.", aRL
.size() == 1);
670 const ScRange
* p
= aRL
[0];
671 CPPUNIT_ASSERT_MESSAGE("Failed to get the range object.", p
);
672 CPPUNIT_ASSERT_MESSAGE("Wrong range.", p
->aStart
== ScAddress(1,1,0) && p
->aEnd
== ScAddress(3,10,0));
674 // TODO: Add more tests here.
676 m_pDoc
->DeleteTab(0);
679 void Test::testMarkData()
681 ScMarkData aMarkData
;
683 // Empty mark. Nothing is selected.
684 std::vector
<sc::ColRowSpan
> aSpans
= aMarkData
.GetMarkedRowSpans();
685 CPPUNIT_ASSERT_MESSAGE("Span should be empty.", aSpans
.empty());
686 aSpans
= aMarkData
.GetMarkedColSpans();
687 CPPUNIT_ASSERT_MESSAGE("Span should be empty.", aSpans
.empty());
690 aMarkData
.SetMarkArea(ScRange(1,2,0,5,6,0));
691 aSpans
= aMarkData
.GetMarkedRowSpans();
692 CPPUNIT_ASSERT_MESSAGE("There should be one selected row span.", aSpans
.size() == 1);
693 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(2), aSpans
[0].mnStart
);
694 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(6), aSpans
[0].mnEnd
);
696 aSpans
= aMarkData
.GetMarkedColSpans();
697 CPPUNIT_ASSERT_MESSAGE("There should be one selected column span.", aSpans
.size() == 1);
698 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(1), aSpans
[0].mnStart
);
699 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(5), aSpans
[0].mnEnd
);
702 aMarkData
.SetMultiMarkArea(ScRange(0,10,0,1,12,0));
703 aSpans
= aMarkData
.GetMarkedRowSpans();
704 CPPUNIT_ASSERT_MESSAGE("There should be 2 selected row spans.", aSpans
.size() == 2);
705 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(2), aSpans
[0].mnStart
);
706 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(6), aSpans
[0].mnEnd
);
707 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(10), aSpans
[1].mnStart
);
708 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(12), aSpans
[1].mnEnd
);
710 aSpans
= aMarkData
.GetMarkedColSpans();
711 CPPUNIT_ASSERT_MESSAGE("There should be one selected column span.", aSpans
.size() == 1);
712 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(0), aSpans
[0].mnStart
);
713 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(5), aSpans
[0].mnEnd
);
716 aMarkData
.SetMultiMarkArea(ScRange(2,7,0,2,9,0));
717 aSpans
= aMarkData
.GetMarkedRowSpans();
718 CPPUNIT_ASSERT_MESSAGE("There should be one selected row span.", aSpans
.size() == 1);
719 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(2), aSpans
[0].mnStart
);
720 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(12), aSpans
[0].mnEnd
);
722 aSpans
= aMarkData
.GetMarkedColSpans();
723 CPPUNIT_ASSERT_MESSAGE("There should be one selected column span.", aSpans
.size() == 1);
724 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(0), aSpans
[0].mnStart
);
725 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOLROW
>(5), aSpans
[0].mnEnd
);
728 void Test::testInput()
731 CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
732 m_pDoc
->InsertTab (0, "foo"));
735 m_pDoc
->SetString(0, 0, 0, "'10.5");
736 test
= m_pDoc
->GetString(0, 0, 0);
737 bool bTest
= test
== "10.5";
738 CPPUNIT_ASSERT_MESSAGE("String number should have the first apostrophe stripped.", bTest
);
739 m_pDoc
->SetString(0, 0, 0, "'apple'");
740 test
= m_pDoc
->GetString(0, 0, 0);
741 bTest
= test
== "'apple'";
742 CPPUNIT_ASSERT_MESSAGE("Text content should have retained the first apostrophe.", bTest
);
744 // Customized string handling policy.
745 ScSetStringParam aParam
;
746 aParam
.setTextInput();
747 m_pDoc
->SetString(0, 0, 0, "000123", &aParam
);
748 test
= m_pDoc
->GetString(0, 0, 0);
749 CPPUNIT_ASSERT_MESSAGE("Text content should have been treated as string, not number.", test
== "000123");
751 m_pDoc
->DeleteTab(0);
754 void Test::testDocStatistics()
756 SCTAB nStartTabs
= m_pDoc
->GetTableCount();
757 m_pDoc
->InsertTab(0, "Sheet1");
758 CPPUNIT_ASSERT_MESSAGE("Failed to increment sheet count.", m_pDoc
->GetTableCount() == nStartTabs
+1);
759 m_pDoc
->InsertTab(1, "Sheet2");
760 CPPUNIT_ASSERT_MESSAGE("Failed to increment sheet count.", m_pDoc
->GetTableCount() == nStartTabs
+2);
762 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(0), m_pDoc
->GetCellCount());
763 m_pDoc
->SetValue(ScAddress(0,0,0), 2.0);
764 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(1), m_pDoc
->GetCellCount());
765 m_pDoc
->SetValue(ScAddress(2,2,0), 2.5);
766 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(2), m_pDoc
->GetCellCount());
767 m_pDoc
->SetString(ScAddress(1,1,1), "Test");
768 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(3), m_pDoc
->GetCellCount());
770 m_pDoc
->DeleteTab(1);
771 CPPUNIT_ASSERT_MESSAGE("Failed to decrement sheet count.", m_pDoc
->GetTableCount() == nStartTabs
+1);
772 m_pDoc
->DeleteTab(0); // This may fail in case there is only one sheet in the document.
775 void Test::testDataEntries()
777 m_pDoc
->InsertTab(0, "Test");
779 m_pDoc
->SetString(ScAddress(0,5,0), "Andy");
780 m_pDoc
->SetString(ScAddress(0,6,0), "Bruce");
781 m_pDoc
->SetString(ScAddress(0,7,0), "Charlie");
782 m_pDoc
->SetString(ScAddress(0,10,0), "Andy");
784 std::vector
<ScTypedStrData
> aEntries
;
785 m_pDoc
->GetDataEntries(0, 0, 0, true, aEntries
); // Try at the very top.
787 // Entries are supposed to be sorted in ascending order, and are all unique.
788 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aEntries
.size());
789 std::vector
<ScTypedStrData
>::const_iterator it
= aEntries
.begin();
790 CPPUNIT_ASSERT_EQUAL(OUString("Andy"), it
->GetString());
792 CPPUNIT_ASSERT_EQUAL(OUString("Bruce"), it
->GetString());
794 CPPUNIT_ASSERT_EQUAL(OUString("Charlie"), it
->GetString());
796 CPPUNIT_ASSERT_MESSAGE("The entries should have ended here.", it
== aEntries
.end());
799 m_pDoc
->GetDataEntries(0, MAXROW
, 0, true, aEntries
); // Try at the very bottom.
800 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aEntries
.size());
802 // Make sure we get the same set of suggestions.
803 it
= aEntries
.begin();
804 CPPUNIT_ASSERT_EQUAL(OUString("Andy"), it
->GetString());
806 CPPUNIT_ASSERT_EQUAL(OUString("Bruce"), it
->GetString());
808 CPPUNIT_ASSERT_EQUAL(OUString("Charlie"), it
->GetString());
810 CPPUNIT_ASSERT_MESSAGE("The entries should have ended here.", it
== aEntries
.end());
812 m_pDoc
->DeleteTab(0);
815 void Test::testSelectionFunction()
817 m_pDoc
->InsertTab(0, "Test");
819 // Insert values into B2:B4.
820 m_pDoc
->SetString(ScAddress(1,1,0), "=1"); // formula
821 m_pDoc
->SetValue(ScAddress(1,2,0), 2.0);
822 m_pDoc
->SetValue(ScAddress(1,3,0), 3.0);
824 // Insert strings into B5:B8.
825 m_pDoc
->SetString(ScAddress(1,4,0), "A");
826 m_pDoc
->SetString(ScAddress(1,5,0), "B");
827 m_pDoc
->SetString(ScAddress(1,6,0), "=\"C\""); // formula
828 m_pDoc
->SetString(ScAddress(1,7,0), "D");
830 // Insert values into D2:D4.
831 m_pDoc
->SetValue(ScAddress(3,1,0), 4.0);
832 m_pDoc
->SetValue(ScAddress(3,2,0), 5.0);
833 m_pDoc
->SetValue(ScAddress(3,3,0), 6.0);
835 // Insert edit text into D5.
836 ScFieldEditEngine
& rEE
= m_pDoc
->GetEditEngine();
837 rEE
.SetText("Rich Text");
838 m_pDoc
->SetEditText(ScAddress(3,4,0), rEE
.CreateTextObject());
840 // Insert Another string into D6.
841 m_pDoc
->SetString(ScAddress(3,5,0), "E");
843 // Select B2:B8 & D2:D8 disjoint region.
845 aRanges
.Append(ScRange(1,1,0,1,7,0)); // B2:B8
846 aRanges
.Append(ScRange(3,1,0,3,7,0)); // D2:D8
848 aMark
.MarkFromRangeList(aRanges
, true);
852 ScSubTotalFunc meFunc
;
859 { SUBTOTAL_FUNC_AVE
, 3.5 },
860 { SUBTOTAL_FUNC_CNT2
, 12.0 },
861 { SUBTOTAL_FUNC_CNT
, 6.0 },
862 { SUBTOTAL_FUNC_MAX
, 6.0 },
863 { SUBTOTAL_FUNC_MIN
, 1.0 },
864 { SUBTOTAL_FUNC_SUM
, 21.0 },
865 { SUBTOTAL_FUNC_SELECTION_COUNT
, 14.0 }
868 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
871 bool bRes
= m_pDoc
->GetSelectionFunction(aChecks
[i
].meFunc
, ScAddress(), aMark
, fRes
);
872 CPPUNIT_ASSERT_MESSAGE("Failed to fetch selection function result.", bRes
);
873 CPPUNIT_ASSERT_EQUAL(aChecks
[i
].mfExpected
, fRes
);
877 // Hide rows 4 and 6 and check the results again.
879 m_pDoc
->SetRowHidden(3, 3, 0, true);
880 m_pDoc
->SetRowHidden(5, 5, 0, true);
881 CPPUNIT_ASSERT_MESSAGE("This row should be hidden.", m_pDoc
->RowHidden(3, 0));
882 CPPUNIT_ASSERT_MESSAGE("This row should be hidden.", m_pDoc
->RowHidden(5, 0));
887 { SUBTOTAL_FUNC_AVE
, 3.0 },
888 { SUBTOTAL_FUNC_CNT2
, 8.0 },
889 { SUBTOTAL_FUNC_CNT
, 4.0 },
890 { SUBTOTAL_FUNC_MAX
, 5.0 },
891 { SUBTOTAL_FUNC_MIN
, 1.0 },
892 { SUBTOTAL_FUNC_SUM
, 12.0 },
893 { SUBTOTAL_FUNC_SELECTION_COUNT
, 10.0 }
896 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
899 bool bRes
= m_pDoc
->GetSelectionFunction(aChecks
[i
].meFunc
, ScAddress(), aMark
, fRes
);
900 CPPUNIT_ASSERT_MESSAGE("Failed to fetch selection function result.", bRes
);
901 CPPUNIT_ASSERT_EQUAL(aChecks
[i
].mfExpected
, fRes
);
905 // Make sure that when no selection is present, use the current cursor position.
909 // D3 (numeric cell containing 5.)
910 ScAddress
aPos(3, 2, 0);
914 { SUBTOTAL_FUNC_AVE
, 5.0 },
915 { SUBTOTAL_FUNC_CNT2
, 1.0 },
916 { SUBTOTAL_FUNC_CNT
, 1.0 },
917 { SUBTOTAL_FUNC_MAX
, 5.0 },
918 { SUBTOTAL_FUNC_MIN
, 5.0 },
919 { SUBTOTAL_FUNC_SUM
, 5.0 },
920 { SUBTOTAL_FUNC_SELECTION_COUNT
, 1.0 }
923 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
926 bool bRes
= m_pDoc
->GetSelectionFunction(aChecks
[i
].meFunc
, aPos
, aEmpty
, fRes
);
927 CPPUNIT_ASSERT_MESSAGE("Failed to fetch selection function result.", bRes
);
928 CPPUNIT_ASSERT_EQUAL(aChecks
[i
].mfExpected
, fRes
);
933 // B7 (string formula cell containing ="C".)
934 ScAddress
aPos(1, 6, 0);
938 { SUBTOTAL_FUNC_CNT2
, 1.0 },
939 { SUBTOTAL_FUNC_SELECTION_COUNT
, 1.0 }
942 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aChecks
); ++i
)
945 bool bRes
= m_pDoc
->GetSelectionFunction(aChecks
[i
].meFunc
, aPos
, aEmpty
, fRes
);
946 CPPUNIT_ASSERT_MESSAGE("Failed to fetch selection function result.", bRes
);
947 CPPUNIT_ASSERT_EQUAL(aChecks
[i
].mfExpected
, fRes
);
951 m_pDoc
->DeleteTab(0);
954 void Test::testCopyToDocument()
956 CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc
->InsertTab (0, "src"));
958 m_pDoc
->SetString(0, 0, 0, "Header");
959 m_pDoc
->SetString(0, 1, 0, "1");
960 m_pDoc
->SetString(0, 2, 0, "2");
961 m_pDoc
->SetString(0, 3, 0, "3");
962 m_pDoc
->SetString(0, 4, 0, "=4/2");
966 ScAddress
aAdrA1 (0, 0, 0); // numerical cell content
967 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(aAdrA1
);
968 pNote
->SetText(aAdrA1
, "Hello world in A1");
970 // Copy statically to another document.
972 ScDocument
aDestDoc(SCDOCMODE_DOCUMENT
);
973 aDestDoc
.InsertTab(0, "src");
974 m_pDoc
->CopyStaticToDocument(ScRange(0,1,0,0,3,0), 0, &aDestDoc
); // Copy A2:A4
975 m_pDoc
->CopyStaticToDocument(ScAddress(0,0,0), 0, &aDestDoc
); // Copy A1
976 m_pDoc
->CopyStaticToDocument(ScRange(0,4,0,0,7,0), 0, &aDestDoc
); // Copy A5:A8
978 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(0,0,0), aDestDoc
.GetString(0,0,0));
979 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(0,1,0), aDestDoc
.GetString(0,1,0));
980 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(0,2,0), aDestDoc
.GetString(0,2,0));
981 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(0,3,0), aDestDoc
.GetString(0,3,0));
982 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(0,4,0), aDestDoc
.GetString(0,4,0));
985 CPPUNIT_ASSERT_MESSAGE("There should be a note in A1 destDocument", aDestDoc
.HasNote(ScAddress(0, 0, 0)));
986 CPPUNIT_ASSERT_MESSAGE("The notes content should be the same on both documents",
987 aDestDoc
.GetNote(ScAddress(0, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(0, 0, 0))->GetText());
989 m_pDoc
->DeleteTab(0);
1001 template<size_t _Size
>
1002 bool checkHorizontalIterator(ScDocument
* pDoc
, const char* pData
[][_Size
], size_t nDataCount
, const HoriIterCheck
* pChecks
, size_t nCheckCount
)
1004 ScAddress
aPos(0,0,0);
1005 Test::insertRangeData(pDoc
, aPos
, pData
, nDataCount
);
1006 ScHorizontalCellIterator
aIter(pDoc
, 0, 0, 0, 1, nDataCount
-1);
1011 for (ScRefCellValue
* pCell
= aIter
.GetNext(nCol
, nRow
); pCell
; pCell
= aIter
.GetNext(nCol
, nRow
), ++i
)
1013 if (i
>= nCheckCount
)
1015 cerr
<< "hit invalid check " << i
<< " of " << nCheckCount
<< endl
;
1016 CPPUNIT_FAIL("Iterator claims there is more data than there should be.");
1020 if (pChecks
[i
].nCol
!= nCol
)
1022 cerr
<< "Column mismatch " << pChecks
[i
].nCol
<< " vs. " << nCol
<< endl
;
1026 if (pChecks
[i
].nRow
!= nRow
)
1028 cerr
<< "Row mismatch " << pChecks
[i
].nRow
<< " vs. " << nRow
<< endl
;
1032 if (OUString::createFromAscii(pChecks
[i
].pVal
) != pCell
->getString(pDoc
))
1034 cerr
<< "String mismatch " << pChecks
[i
].pVal
<< " vs. " <<
1035 OUStringToOString(pCell
->getString(pDoc
), RTL_TEXTENCODING_UTF8
).getStr() << endl
;
1045 void Test::testHorizontalIterator()
1047 m_pDoc
->InsertTab(0, "test");
1050 // Raw data - mixed types
1051 const char* aData
[][2] = {
1058 HoriIterCheck aChecks
[] = {
1069 bool bRes
= checkHorizontalIterator(
1070 m_pDoc
, aData
, SAL_N_ELEMENTS(aData
), aChecks
, SAL_N_ELEMENTS(aChecks
));
1073 CPPUNIT_FAIL("Failed on test mixed.");
1077 // Raw data - 'hole' data
1078 const char* aData
[][2] = {
1084 HoriIterCheck aChecks
[] = {
1092 bool bRes
= checkHorizontalIterator(
1093 m_pDoc
, aData
, SAL_N_ELEMENTS(aData
), aChecks
, SAL_N_ELEMENTS(aChecks
));
1096 CPPUNIT_FAIL("Failed on test hole.");
1101 const char* aData
[][2] = {
1113 HoriIterCheck aChecks
[] = {
1125 bool bRes
= checkHorizontalIterator(
1126 m_pDoc
, aData
, SAL_N_ELEMENTS(aData
), aChecks
, SAL_N_ELEMENTS(aChecks
));
1129 CPPUNIT_FAIL("Failed on test holy.");
1134 const char* aData
[][2] = {
1140 bool bRes
= checkHorizontalIterator(
1141 m_pDoc
, aData
, SAL_N_ELEMENTS(aData
), NULL
, 0);
1144 CPPUNIT_FAIL("Failed on test degenerate.");
1149 const char* aData
[][2] = {
1155 HoriIterCheck aChecks
[] = {
1159 bool bRes
= checkHorizontalIterator(
1160 m_pDoc
, aData
, SAL_N_ELEMENTS(aData
), aChecks
, SAL_N_ELEMENTS(aChecks
));
1163 CPPUNIT_FAIL("Failed on test at end.");
1168 const char* aData
[][2] = {
1176 HoriIterCheck aChecks
[] = {
1181 bool bRes
= checkHorizontalIterator(
1182 m_pDoc
, aData
, SAL_N_ELEMENTS(aData
), aChecks
, SAL_N_ELEMENTS(aChecks
));
1185 CPPUNIT_FAIL("Failed on test in middle.");
1188 m_pDoc
->DeleteTab(0);
1191 void Test::testValueIterator()
1193 m_pDoc
->InsertTab(0, "Test");
1195 // Turn on "precision as shown" option.
1196 ScDocOptions aOpt
= m_pDoc
->GetDocOptions();
1197 aOpt
.SetCalcAsShown(true);
1198 m_pDoc
->SetDocOptions(aOpt
);
1200 // Purely horizontal data layout with numeric data.
1201 for (SCCOL i
= 1; i
<= 3; ++i
)
1202 m_pDoc
->SetValue(ScAddress(i
,2,0), i
);
1208 const double aChecks
[] = { 1.0, 2.0, 3.0 };
1209 size_t nCheckLen
= SAL_N_ELEMENTS(aChecks
);
1211 ScValueIterator
aIter(m_pDoc
, ScRange(1,2,0,3,2,0));
1214 size_t nCheckPos
= 0;
1215 for (bHas
= aIter
.GetFirst(fVal
, nErr
); bHas
; bHas
= aIter
.GetNext(fVal
, nErr
), ++nCheckPos
)
1217 CPPUNIT_ASSERT_MESSAGE("Iteration longer than expected.", nCheckPos
< nCheckLen
);
1218 CPPUNIT_ASSERT_EQUAL(aChecks
[nCheckPos
], fVal
);
1219 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(0), nErr
);
1223 m_pDoc
->DeleteTab(0);
1226 void Test::testHorizontalAttrIterator()
1228 m_pDoc
->InsertTab(0, "Test");
1230 // Set the background color of B2:C3,D2,E3,C4:D4,B5:D5 to blue
1231 ScPatternAttr
aCellBackColor(m_pDoc
->GetPool());
1232 aCellBackColor
.GetItemSet().Put(SvxBrushItem(COL_BLUE
, ATTR_BACKGROUND
));
1233 m_pDoc
->ApplyPatternAreaTab(1, 1, 2, 2, 0, aCellBackColor
);
1234 m_pDoc
->ApplyPatternAreaTab(3, 1, 3, 1, 0, aCellBackColor
);
1235 m_pDoc
->ApplyPatternAreaTab(4, 2, 4, 2, 0, aCellBackColor
);
1236 m_pDoc
->ApplyPatternAreaTab(2, 3, 3, 3, 0, aCellBackColor
);
1237 m_pDoc
->ApplyPatternAreaTab(1, 4, 4, 4, 0, aCellBackColor
);
1239 // some numeric data
1240 for (SCCOL i
= 1; i
<= 4; ++i
)
1241 for (SCROW j
= 1; j
<= 4; ++j
)
1242 m_pDoc
->SetValue(ScAddress(i
,j
,0), i
*10+j
);
1245 const int aChecks
[][3] = { {1, 3, 1}, {1, 2, 2}, {4, 4, 2}, {2, 3, 3}, {1, 4, 4} };
1246 size_t nCheckLen
= SAL_N_ELEMENTS(aChecks
);
1248 ScHorizontalAttrIterator
aIter(m_pDoc
, 0, 0, 0, 5, 5);
1251 size_t nCheckPos
= 0;
1252 for (const ScPatternAttr
* pAttr
= aIter
.GetNext(nCol1
, nCol2
, nRow
); pAttr
; pAttr
= aIter
.GetNext(nCol1
, nCol2
, nRow
), ++nCheckPos
)
1254 CPPUNIT_ASSERT_MESSAGE("Iteration longer than expected.", nCheckPos
< nCheckLen
);
1255 CPPUNIT_ASSERT_EQUAL(aChecks
[nCheckPos
][0], static_cast<int>(nCol1
));
1256 CPPUNIT_ASSERT_EQUAL(aChecks
[nCheckPos
][1], static_cast<int>(nCol2
));
1257 CPPUNIT_ASSERT_EQUAL(aChecks
[nCheckPos
][2], static_cast<int>(nRow
));
1261 m_pDoc
->DeleteTab(0);
1266 bool broadcasterShifted(const ScDocument
& rDoc
, const ScAddress
& rFrom
, const ScAddress
& rTo
)
1268 const SvtBroadcaster
* pBC
= rDoc
.GetBroadcaster(rFrom
);
1271 cerr
<< "Broadcaster shouldn't be here." << endl
;
1275 pBC
= rDoc
.GetBroadcaster(rTo
);
1278 cerr
<< "Broadcaster should be here." << endl
;
1284 formula::FormulaToken
* getSingleRefToken(ScDocument
& rDoc
, const ScAddress
& rPos
)
1286 ScFormulaCell
* pFC
= rDoc
.GetFormulaCell(rPos
);
1289 cerr
<< "Formula cell expected, but not found." << endl
;
1293 ScTokenArray
* pTokens
= pFC
->GetCode();
1296 cerr
<< "Token array is not present." << endl
;
1300 formula::FormulaToken
* pToken
= pTokens
->First();
1301 if (!pToken
|| pToken
->GetType() != formula::svSingleRef
)
1303 cerr
<< "Not a single reference token." << endl
;
1310 bool checkRelativeRefToken(ScDocument
& rDoc
, const ScAddress
& rPos
, SCsCOL nRelCol
, SCsROW nRelRow
)
1312 formula::FormulaToken
* pToken
= getSingleRefToken(rDoc
, rPos
);
1316 ScSingleRefData
& rRef
= *pToken
->GetSingleRef();
1317 if (!rRef
.IsColRel() || rRef
.Col() != nRelCol
)
1319 cerr
<< "Unexpected relative column address." << endl
;
1323 if (!rRef
.IsRowRel() || rRef
.Row() != nRelRow
)
1325 cerr
<< "Unexpected relative row address." << endl
;
1332 bool checkDeletedRefToken(ScDocument
& rDoc
, const ScAddress
& rPos
)
1334 formula::FormulaToken
* pToken
= getSingleRefToken(rDoc
, rPos
);
1338 ScSingleRefData
& rRef
= *pToken
->GetSingleRef();
1339 if (!rRef
.IsDeleted())
1341 cerr
<< "Deleted reference is expected, but it's still a valid reference." << endl
;
1350 void Test::testCellBroadcaster()
1352 CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc
->InsertTab (0, "foo"));
1354 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // turn on auto calculation.
1355 m_pDoc
->SetString(ScAddress(1,0,0), "=A1"); // B1 depends on A1.
1356 double val
= m_pDoc
->GetValue(ScAddress(1,0,0)); // A1 is empty, so the result should be 0.
1357 CPPUNIT_ASSERT_EQUAL(0.0, val
);
1359 const SvtBroadcaster
* pBC
= m_pDoc
->GetBroadcaster(ScAddress(0,0,0));
1360 CPPUNIT_ASSERT_MESSAGE("Cell A1 should have a broadcaster.", pBC
);
1362 // Change the value of A1 and make sure that B1 follows.
1363 m_pDoc
->SetValue(ScAddress(0,0,0), 1.23);
1364 val
= m_pDoc
->GetValue(ScAddress(1,0,0));
1365 CPPUNIT_ASSERT_EQUAL(1.23, val
);
1367 // Move column A down 5 cells. Make sure B1 now references A6, not A1.
1368 m_pDoc
->InsertRow(0, 0, 0, 0, 0, 5);
1369 CPPUNIT_ASSERT_MESSAGE("Relative reference check failed.",
1370 checkRelativeRefToken(*m_pDoc
, ScAddress(1,0,0), -1, 5));
1372 // Make sure the broadcaster has also moved.
1373 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1374 broadcasterShifted(*m_pDoc
, ScAddress(0,0,0), ScAddress(0,5,0)));
1376 // Set new value to A6 and make sure B1 gets updated.
1377 m_pDoc
->SetValue(ScAddress(0,5,0), 45.6);
1378 val
= m_pDoc
->GetValue(ScAddress(1,0,0));
1379 CPPUNIT_ASSERT_EQUAL(45.6, val
);
1381 // Move column A up 3 cells, and make sure B1 now references A3, not A6.
1382 m_pDoc
->DeleteRow(0, 0, 0, 0, 0, 3);
1383 CPPUNIT_ASSERT_MESSAGE("Relative reference check failed.",
1384 checkRelativeRefToken(*m_pDoc
, ScAddress(1,0,0), -1, 2));
1386 // The broadcaster should also have been relocated from A6 to A3.
1387 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1388 broadcasterShifted(*m_pDoc
, ScAddress(0,5,0), ScAddress(0,2,0)));
1390 // Insert cells over A1:A10 and shift cells to right.
1391 m_pDoc
->InsertCol(ScRange(0, 0, 0, 0, 10, 0));
1392 CPPUNIT_ASSERT_MESSAGE("Relative reference check failed.",
1393 checkRelativeRefToken(*m_pDoc
, ScAddress(2,0,0), -1, 2));
1394 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1395 broadcasterShifted(*m_pDoc
, ScAddress(0,2,0), ScAddress(1,2,0)));
1397 // Delete formula in C2, which should remove the broadcaster in B3.
1398 pBC
= m_pDoc
->GetBroadcaster(ScAddress(1,2,0));
1399 CPPUNIT_ASSERT_MESSAGE("Broadcaster in B3 should still exist.", pBC
);
1400 clearRange(m_pDoc
, ScAddress(2,0,0));
1401 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, m_pDoc
->GetCellType(ScAddress(2,0,0))); // C2 should be empty.
1402 pBC
= m_pDoc
->GetBroadcaster(ScAddress(1,2,0));
1403 CPPUNIT_ASSERT_MESSAGE("Broadcaster in B3 should have been removed.", !pBC
);
1405 // Clear everything and start over.
1406 clearRange(m_pDoc
, ScRange(0,0,0,10,100,0));
1408 m_pDoc
->SetString(ScAddress(1,0,0), "=A1"); // B1 depends on A1.
1409 pBC
= m_pDoc
->GetBroadcaster(ScAddress(0,0,0));
1410 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist in A1.", pBC
);
1412 // While column A is still empty, move column A down 2 cells. This should
1413 // move the broadcaster from A1 to A3.
1414 m_pDoc
->InsertRow(0, 0, 0, 0, 0, 2);
1415 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1416 broadcasterShifted(*m_pDoc
, ScAddress(0,0,0), ScAddress(0,2,0)));
1418 // Move it back while column A is still empty.
1419 m_pDoc
->DeleteRow(0, 0, 0, 0, 0, 2);
1420 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1421 broadcasterShifted(*m_pDoc
, ScAddress(0,2,0), ScAddress(0,0,0)));
1423 // Clear everything again
1424 clearRange(m_pDoc
, ScRange(0,0,0,10,100,0));
1426 // B1:B3 depends on A1:A3
1427 m_pDoc
->SetString(ScAddress(1,0,0), "=A1");
1428 m_pDoc
->SetString(ScAddress(1,1,0), "=A2");
1429 m_pDoc
->SetString(ScAddress(1,2,0), "=A3");
1430 CPPUNIT_ASSERT_MESSAGE("Relative reference check in B1 failed.",
1431 checkRelativeRefToken(*m_pDoc
, ScAddress(1,0,0), -1, 0));
1432 CPPUNIT_ASSERT_MESSAGE("Relative reference check in B2 failed.",
1433 checkRelativeRefToken(*m_pDoc
, ScAddress(1,1,0), -1, 0));
1434 CPPUNIT_ASSERT_MESSAGE("Relative reference check in B3 failed.",
1435 checkRelativeRefToken(*m_pDoc
, ScAddress(1,2,0), -1, 0));
1436 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist in A1.", m_pDoc
->GetBroadcaster(ScAddress(0,0,0)));
1437 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist in A2.", m_pDoc
->GetBroadcaster(ScAddress(0,1,0)));
1438 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist in A3.", m_pDoc
->GetBroadcaster(ScAddress(0,2,0)));
1440 // Insert Rows at row 2, down 5 rows.
1441 m_pDoc
->InsertRow(0, 0, 0, 0, 1, 5);
1442 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist in A1.", m_pDoc
->GetBroadcaster(ScAddress(0,0,0)));
1443 CPPUNIT_ASSERT_MESSAGE("Relative reference check in B1 failed.",
1444 checkRelativeRefToken(*m_pDoc
, ScAddress(1,0,0), -1, 0));
1446 // Broadcasters in A2 and A3 should shift down by 5 rows.
1447 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1448 broadcasterShifted(*m_pDoc
, ScAddress(0,1,0), ScAddress(0,6,0)));
1449 CPPUNIT_ASSERT_MESSAGE("Broadcaster relocation failed.",
1450 broadcasterShifted(*m_pDoc
, ScAddress(0,2,0), ScAddress(0,7,0)));
1452 // B2 and B3 should reference shifted cells.
1453 CPPUNIT_ASSERT_MESSAGE("Relative reference check in B2 failed.",
1454 checkRelativeRefToken(*m_pDoc
, ScAddress(1,1,0), -1, 5));
1455 CPPUNIT_ASSERT_MESSAGE("Relative reference check in B2 failed.",
1456 checkRelativeRefToken(*m_pDoc
, ScAddress(1,2,0), -1, 5));
1458 // Delete cells with broadcasters.
1459 m_pDoc
->DeleteRow(0, 0, 0, 0, 4, 6);
1460 CPPUNIT_ASSERT_MESSAGE("Broadcaster should NOT exist in A7.", !m_pDoc
->GetBroadcaster(ScAddress(0,6,0)));
1461 CPPUNIT_ASSERT_MESSAGE("Broadcaster should NOT exist in A8.", !m_pDoc
->GetBroadcaster(ScAddress(0,7,0)));
1463 // References in B2 and B3 should be invalid.
1464 CPPUNIT_ASSERT_MESSAGE("Deleted reference check in B2 failed.",
1465 checkDeletedRefToken(*m_pDoc
, ScAddress(1,1,0)));
1466 CPPUNIT_ASSERT_MESSAGE("Deleted reference check in B3 failed.",
1467 checkDeletedRefToken(*m_pDoc
, ScAddress(1,2,0)));
1469 // Clear everything again
1470 clearRange(m_pDoc
, ScRange(0,0,0,10,100,0));
1473 // Switch to R1C1 to make it easier to input relative references in multiple cells.
1474 FormulaGrammarSwitch
aFGSwitch(m_pDoc
, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1
);
1476 // Have B1:B20 reference A1:A20.
1478 for (SCROW i
= 0; i
< 20; ++i
)
1480 m_pDoc
->SetValue(ScAddress(0,i
,0), val
++);
1481 m_pDoc
->SetString(ScAddress(1,i
,0), "=RC[-1]");
1485 // Ensure that the formula cells show correct values, and the referenced
1486 // cells have broadcasters.
1488 for (SCROW i
= 0; i
< 20; ++i
, ++val
)
1490 CPPUNIT_ASSERT_EQUAL(val
, m_pDoc
->GetValue(ScAddress(1,i
,0)));
1491 pBC
= m_pDoc
->GetBroadcaster(ScAddress(0,i
,0));
1492 CPPUNIT_ASSERT_MESSAGE("Broadcast should exist here.", pBC
);
1495 // Delete formula cells in B2:B19.
1496 clearRange(m_pDoc
, ScRange(1,1,0,1,18,0));
1497 // Ensure that A2:A19 no longer have broadcasters, but A1 and A20 still do.
1498 CPPUNIT_ASSERT_MESSAGE("A1 should still have broadcaster.", m_pDoc
->GetBroadcaster(ScAddress(0,0,0)));
1499 CPPUNIT_ASSERT_MESSAGE("A20 should still have broadcaster.", m_pDoc
->GetBroadcaster(ScAddress(0,19,0)));
1500 for (SCROW i
= 1; i
<= 18; ++i
)
1502 pBC
= m_pDoc
->GetBroadcaster(ScAddress(0,i
,0));
1503 CPPUNIT_ASSERT_MESSAGE("Broadcaster should have been deleted.", !pBC
);
1506 // Clear everything again
1507 clearRange(m_pDoc
, ScRange(0,0,0,10,100,0));
1509 m_pDoc
->SetValue(ScAddress(0,0,0), 2.0);
1510 m_pDoc
->SetString(ScAddress(1,0,0), "=A1");
1511 m_pDoc
->SetString(ScAddress(2,0,0), "=B1");
1512 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(0,0,0));
1513 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(1,0,0));
1514 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(2,0,0));
1516 pBC
= m_pDoc
->GetBroadcaster(ScAddress(0,0,0));
1517 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist here.", pBC
);
1518 pBC
= m_pDoc
->GetBroadcaster(ScAddress(1,0,0));
1519 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist here.", pBC
);
1521 // Change the value of A1 and make sure everyone follows suit.
1522 m_pDoc
->SetValue(ScAddress(0,0,0), 3.5);
1523 CPPUNIT_ASSERT_EQUAL(3.5, m_pDoc
->GetValue(0,0,0));
1524 CPPUNIT_ASSERT_EQUAL(3.5, m_pDoc
->GetValue(1,0,0));
1525 CPPUNIT_ASSERT_EQUAL(3.5, m_pDoc
->GetValue(2,0,0));
1527 // Insert a column at column B.
1528 m_pDoc
->InsertCol(ScRange(1,0,0,1,MAXROW
,0));
1529 pBC
= m_pDoc
->GetBroadcaster(ScAddress(0,0,0));
1530 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist here.", pBC
);
1531 pBC
= m_pDoc
->GetBroadcaster(ScAddress(2,0,0));
1532 CPPUNIT_ASSERT_MESSAGE("Broadcaster should exist here.", pBC
);
1534 // Change the value of A1 again.
1535 m_pDoc
->SetValue(ScAddress(0,0,0), 5.5);
1536 CPPUNIT_ASSERT_EQUAL(5.5, m_pDoc
->GetValue(0,0,0));
1537 CPPUNIT_ASSERT_EQUAL(5.5, m_pDoc
->GetValue(2,0,0));
1538 CPPUNIT_ASSERT_EQUAL(5.5, m_pDoc
->GetValue(3,0,0));
1540 m_pDoc
->DeleteTab(0);
1543 void Test::testFuncParam()
1546 CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
1547 m_pDoc
->InsertTab (0, "foo"));
1549 // First, the normal case, with no missing parameters.
1550 m_pDoc
->SetString(0, 0, 0, "=AVERAGE(1;2;3)");
1551 m_pDoc
->CalcFormulaTree(false, false);
1553 m_pDoc
->GetValue(0, 0, 0, val
);
1554 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 2);
1556 // Now function with missing parameters. Missing values should be treated
1558 m_pDoc
->SetString(0, 0, 0, "=AVERAGE(1;;;)");
1559 m_pDoc
->CalcFormulaTree(false, false);
1560 m_pDoc
->GetValue(0, 0, 0, val
);
1561 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 0.25);
1563 // Conversion of string to numeric argument.
1564 m_pDoc
->SetString(0, 0, 0, "=\"\"+3"); // empty string
1565 m_pDoc
->SetString(0, 1, 0, "=\" \"+3"); // only blank
1566 m_pDoc
->SetString(0, 2, 0, "=\" 4 \"+3"); // number in blanks
1567 m_pDoc
->SetString(0, 3, 0, "=\" x \"+3"); // non-numeric
1568 m_pDoc
->SetString(0, 4, 0, "=\"4.4\"+3"); // locale dependent
1571 ScCalcConfig aConfig
;
1573 // With "Convert also locale dependent" and "Empty string as zero"=True option.
1574 aConfig
.meStringConversion
= ScCalcConfig::StringConversion::LOCALE
;
1575 aConfig
.mbEmptyStringAsZero
= true;
1576 m_pDoc
->SetCalcConfig(aConfig
);
1578 m_pDoc
->GetValue(0, 0, 0, val
);
1579 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1580 m_pDoc
->GetValue(0, 1, 0, val
);
1581 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1582 m_pDoc
->GetValue(0, 2, 0, val
);
1583 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 7);
1584 aVal
= m_pDoc
->GetString( 0, 3, 0);
1585 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1586 m_pDoc
->GetValue(0, 4, 0, val
);
1587 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 7.4);
1589 // With "Convert also locale dependent" and "Empty string as zero"=False option.
1590 aConfig
.meStringConversion
= ScCalcConfig::StringConversion::LOCALE
;
1591 aConfig
.mbEmptyStringAsZero
= false;
1592 m_pDoc
->SetCalcConfig(aConfig
);
1594 aVal
= m_pDoc
->GetString( 0, 0, 0);
1595 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1596 aVal
= m_pDoc
->GetString( 0, 1, 0);
1597 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1598 m_pDoc
->GetValue(0, 2, 0, val
);
1599 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 7);
1600 aVal
= m_pDoc
->GetString( 0, 3, 0);
1601 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1602 m_pDoc
->GetValue(0, 4, 0, val
);
1603 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 7.4);
1605 // With "Convert only unambiguous" and "Empty string as zero"=True option.
1606 aConfig
.meStringConversion
= ScCalcConfig::StringConversion::UNAMBIGUOUS
;
1607 aConfig
.mbEmptyStringAsZero
= true;
1608 m_pDoc
->SetCalcConfig(aConfig
);
1610 m_pDoc
->GetValue(0, 0, 0, val
);
1611 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1612 m_pDoc
->GetValue(0, 1, 0, val
);
1613 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1614 m_pDoc
->GetValue(0, 2, 0, val
);
1615 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 7);
1616 aVal
= m_pDoc
->GetString( 0, 3, 0);
1617 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1618 aVal
= m_pDoc
->GetString( 0, 4, 0);
1619 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1621 // With "Convert only unambiguous" and "Empty string as zero"=False option.
1622 aConfig
.meStringConversion
= ScCalcConfig::StringConversion::UNAMBIGUOUS
;
1623 aConfig
.mbEmptyStringAsZero
= false;
1624 m_pDoc
->SetCalcConfig(aConfig
);
1626 aVal
= m_pDoc
->GetString( 0, 0, 0);
1627 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1628 aVal
= m_pDoc
->GetString( 0, 1, 0);
1629 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1630 m_pDoc
->GetValue(0, 2, 0, val
);
1631 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 7);
1632 aVal
= m_pDoc
->GetString( 0, 3, 0);
1633 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1634 aVal
= m_pDoc
->GetString( 0, 4, 0);
1635 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1637 // With "Treat as zero" ("Empty string as zero" is ignored).
1638 aConfig
.meStringConversion
= ScCalcConfig::StringConversion::ZERO
;
1639 aConfig
.mbEmptyStringAsZero
= true;
1640 m_pDoc
->SetCalcConfig(aConfig
);
1642 m_pDoc
->GetValue(0, 0, 0, val
);
1643 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1644 m_pDoc
->GetValue(0, 1, 0, val
);
1645 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1646 m_pDoc
->GetValue(0, 2, 0, val
);
1647 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1648 m_pDoc
->GetValue(0, 3, 0, val
);
1649 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1650 m_pDoc
->GetValue(0, 4, 0, val
);
1651 CPPUNIT_ASSERT_MESSAGE("incorrect result", val
== 3);
1653 // With "Generate #VALUE! error" ("Empty string as zero" is ignored).
1654 aConfig
.meStringConversion
= ScCalcConfig::StringConversion::ILLEGAL
;
1655 aConfig
.mbEmptyStringAsZero
= false;
1656 m_pDoc
->SetCalcConfig(aConfig
);
1658 aVal
= m_pDoc
->GetString( 0, 0, 0);
1659 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1660 aVal
= m_pDoc
->GetString( 0, 1, 0);
1661 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1662 aVal
= m_pDoc
->GetString( 0, 2, 0);
1663 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1664 aVal
= m_pDoc
->GetString( 0, 3, 0);
1665 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1666 aVal
= m_pDoc
->GetString( 0, 4, 0);
1667 CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal
== "#VALUE!");
1669 m_pDoc
->DeleteTab(0);
1672 void Test::testNamedRange()
1674 RangeNameDef aNames
[] = {
1675 { "Divisor", "$Sheet1.$A$1:$A$1048576", 1 },
1676 { "MyRange1", "$Sheet1.$A$1:$A$100", 2 },
1677 { "MyRange2", "$Sheet1.$B$1:$B$100", 3 },
1678 { "MyRange3", "$Sheet1.$C$1:$C$100", 4 }
1681 CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc
->InsertTab (0, "Sheet1"));
1683 m_pDoc
->SetValue (0, 0, 0, 101);
1685 ScRangeName
* pNames
= new ScRangeName
;
1686 bool bSuccess
= insertRangeNames(m_pDoc
, pNames
, aNames
, aNames
+ SAL_N_ELEMENTS(aNames
));
1687 CPPUNIT_ASSERT_MESSAGE("Failed to insert range names.", bSuccess
);
1688 m_pDoc
->SetRangeName(pNames
);
1690 ScRangeName
* pNewRanges
= m_pDoc
->GetRangeName();
1691 CPPUNIT_ASSERT(pNewRanges
);
1693 // Make sure the index lookup does the right thing.
1694 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aNames
); ++i
)
1696 const ScRangeData
* p
= pNewRanges
->findByIndex(aNames
[i
].mnIndex
);
1697 CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed.", p
);
1698 OUString aName
= p
->GetName();
1699 CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved.", aName
.equalsAscii(aNames
[i
].mpName
));
1702 // Test usage in formula expression.
1703 m_pDoc
->SetString (1, 0, 0, "=A1/Divisor");
1707 m_pDoc
->GetValue (1, 0, 0, result
);
1708 CPPUNIT_ASSERT_MESSAGE ("calculation failed", result
== 1.0);
1710 // Test copy-ability of range names.
1711 ScRangeName
* pCopiedRanges
= new ScRangeName(*pNewRanges
);
1712 m_pDoc
->SetRangeName(pCopiedRanges
);
1713 // Make sure the index lookup still works.
1714 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aNames
); ++i
)
1716 const ScRangeData
* p
= pCopiedRanges
->findByIndex(aNames
[i
].mnIndex
);
1717 CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed with the copied instance.", p
);
1718 OUString aName
= p
->GetName();
1719 CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved with the copied instance.", aName
.equalsAscii(aNames
[i
].mpName
));
1722 m_pDoc
->SetRangeName(NULL
); // Delete the names.
1723 m_pDoc
->DeleteTab(0);
1726 void Test::testInsertNameList()
1728 m_pDoc
->InsertTab(0, "Test");
1730 RangeNameDef aNames
[] = {
1731 { "MyRange1", "$Test.$A$1:$A$100", 1 },
1732 { "MyRange2", "$Test.$B$1:$B$100", 2 },
1733 { "MyRange3", "$Test.$C$1:$C$100", 3 }
1736 ScRangeName
* pNames
= new ScRangeName
;
1737 bool bSuccess
= insertRangeNames(m_pDoc
, pNames
, aNames
, aNames
+ SAL_N_ELEMENTS(aNames
));
1738 CPPUNIT_ASSERT_MESSAGE("Failed to insert range names.", bSuccess
);
1739 m_pDoc
->SetRangeName(pNames
);
1741 ScDocFunc
& rDocFunc
= getDocShell().GetDocFunc();
1742 ScAddress
aPos(1,1,0);
1743 rDocFunc
.InsertNameList(aPos
, true);
1745 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aNames
); ++i
, aPos
.IncRow())
1747 OUString aName
= m_pDoc
->GetString(aPos
);
1748 CPPUNIT_ASSERT_EQUAL(OUString::createFromAscii(aNames
[i
].mpName
), aName
);
1749 ScAddress aExprPos
= aPos
;
1751 OUString aExpr
= m_pDoc
->GetString(aExprPos
);
1752 OUString aExpected
= "=";
1753 aExpected
+= OUString::createFromAscii(aNames
[i
].mpExpr
);
1754 CPPUNIT_ASSERT_EQUAL(aExpected
, aExpr
);
1757 m_pDoc
->DeleteTab(0);
1760 void Test::testCSV()
1762 const int English
= 0, European
= 1;
1764 const char *pStr
; int eSep
; bool bResult
; double nValue
;
1766 { "foo", English
, false, 0.0 },
1767 { "1.0", English
, true, 1.0 },
1768 { "1,0", English
, false, 0.0 },
1769 { "1.0", European
, false, 0.0 },
1770 { "1.000", European
, true, 1000.0 },
1771 { "1,000", European
, true, 1.0 },
1772 { "1.000", English
, true, 1.0 },
1773 { "1,000", English
, true, 1000.0 },
1774 { " 1.0", English
, true, 1.0 },
1775 { " 1.0 ", English
, true, 1.0 },
1776 { "1.0 ", European
, false, 0.0 },
1777 { "1.000", European
, true, 1000.0 },
1778 { "1137.999", English
, true, 1137.999 },
1779 { "1.000.00", European
, false, 0.0 }
1781 for (sal_uInt32 i
= 0; i
< SAL_N_ELEMENTS(aTests
); i
++) {
1782 OUString
aStr(aTests
[i
].pStr
, strlen (aTests
[i
].pStr
), RTL_TEXTENCODING_UTF8
);
1783 double nValue
= 0.0;
1784 bool bResult
= ScStringUtil::parseSimpleNumber
1785 (aStr
, aTests
[i
].eSep
== English
? '.' : ',',
1786 aTests
[i
].eSep
== English
? ',' : '.',
1788 CPPUNIT_ASSERT_MESSAGE ("CSV numeric detection failure", bResult
== aTests
[i
].bResult
);
1789 CPPUNIT_ASSERT_MESSAGE ("CSV numeric value failure", nValue
== aTests
[i
].nValue
);
1793 template<typename Evaluator
>
1794 void checkMatrixElements(const ScMatrix
& rMat
)
1797 rMat
.GetDimensions(nC
, nR
);
1799 for (SCSIZE i
= 0; i
< nC
; ++i
)
1801 for (SCSIZE j
= 0; j
< nR
; ++j
)
1803 aEval(i
, j
, rMat
.Get(i
, j
));
1808 struct AllZeroMatrix
1810 void operator() (SCSIZE
/*nCol*/, SCSIZE
/*nRow*/, const ScMatrixValue
& rVal
) const
1812 CPPUNIT_ASSERT_MESSAGE("element is not of numeric type", rVal
.nType
== SC_MATVAL_VALUE
);
1813 CPPUNIT_ASSERT_MESSAGE("element value must be zero", rVal
.fVal
== 0.0);
1817 struct PartiallyFilledZeroMatrix
1819 void operator() (SCSIZE nCol
, SCSIZE nRow
, const ScMatrixValue
& rVal
) const
1821 CPPUNIT_ASSERT_MESSAGE("element is not of numeric type", rVal
.nType
== SC_MATVAL_VALUE
);
1822 if (1 <= nCol
&& nCol
<= 2 && 2 <= nRow
&& nRow
<= 8)
1824 CPPUNIT_ASSERT_MESSAGE("element value must be 3.0", rVal
.fVal
== 3.0);
1828 CPPUNIT_ASSERT_MESSAGE("element value must be zero", rVal
.fVal
== 0.0);
1833 struct AllEmptyMatrix
1835 void operator() (SCSIZE
/*nCol*/, SCSIZE
/*nRow*/, const ScMatrixValue
& rVal
) const
1837 CPPUNIT_ASSERT_MESSAGE("element is not of empty type", rVal
.nType
== SC_MATVAL_EMPTY
);
1838 CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal
.fVal
== 0.0);
1842 struct PartiallyFilledEmptyMatrix
1844 void operator() (SCSIZE nCol
, SCSIZE nRow
, const ScMatrixValue
& rVal
) const
1846 if (nCol
== 1 && nRow
== 1)
1848 CPPUNIT_ASSERT_MESSAGE("element is not of boolean type", rVal
.nType
== SC_MATVAL_BOOLEAN
);
1849 CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal
.fVal
== 1.0);
1851 else if (nCol
== 4 && nRow
== 5)
1853 CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal
.nType
== SC_MATVAL_VALUE
);
1854 CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal
.fVal
== -12.5);
1856 else if (nCol
== 8 && nRow
== 2)
1858 CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal
.nType
== SC_MATVAL_STRING
);
1859 CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal
.aStr
.getString() == "Test");
1861 else if (nCol
== 8 && nRow
== 11)
1863 CPPUNIT_ASSERT_MESSAGE("element is not of empty path type", rVal
.nType
== SC_MATVAL_EMPTYPATH
);
1864 CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal
.fVal
== 0.0);
1868 CPPUNIT_ASSERT_MESSAGE("element is not of empty type", rVal
.nType
== SC_MATVAL_EMPTY
);
1869 CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal
.fVal
== 0.0);
1874 void Test::testMatrix()
1876 svl::SharedStringPool
& rPool
= m_pDoc
->GetSharedStringPool();
1877 ScMatrixRef pMat
, pMat2
;
1879 // First, test the zero matrix type.
1880 pMat
= new ScMatrix(0, 0, 0.0);
1882 pMat
->GetDimensions(nC
, nR
);
1883 CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC
== 0 && nR
== 0);
1884 pMat
->Resize(4, 10, 0.0);
1885 pMat
->GetDimensions(nC
, nR
);
1886 CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC
== 4 && nR
== 10);
1887 CPPUNIT_ASSERT_MESSAGE("both 'and' and 'or' should evaluate to false",
1888 !pMat
->And() && !pMat
->Or());
1890 // Resizing into a larger matrix should fill the void space with zeros.
1891 checkMatrixElements
<AllZeroMatrix
>(*pMat
);
1893 pMat
->FillDouble(3.0, 1, 2, 2, 8);
1894 checkMatrixElements
<PartiallyFilledZeroMatrix
>(*pMat
);
1895 CPPUNIT_ASSERT_MESSAGE("matrix is expected to be numeric", pMat
->IsNumeric());
1896 CPPUNIT_ASSERT_MESSAGE("partially non-zero matrix should evaluate false on 'and' and true on 'or",
1897 !pMat
->And() && pMat
->Or());
1898 pMat
->FillDouble(5.0, 0, 0, nC
-1, nR
-1);
1899 CPPUNIT_ASSERT_MESSAGE("fully non-zero matrix should evaluate true both on 'and' and 'or",
1900 pMat
->And() && pMat
->Or());
1902 // Test the AND and OR evaluations.
1903 pMat
= new ScMatrix(2, 2, 0.0);
1905 // Only some of the elements are non-zero.
1906 pMat
->PutBoolean(true, 0, 0);
1907 pMat
->PutDouble(1.0, 1, 1);
1908 CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat
->Or());
1909 CPPUNIT_ASSERT_MESSAGE("incorrect AND result", !pMat
->And());
1911 // All of the elements are non-zero.
1912 pMat
->PutBoolean(true, 0, 1);
1913 pMat
->PutDouble(2.3, 1, 0);
1914 CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat
->Or());
1915 CPPUNIT_ASSERT_MESSAGE("incorrect AND result", pMat
->And());
1917 // Now test the emtpy matrix type.
1918 pMat
= new ScMatrix(10, 20);
1919 pMat
->GetDimensions(nC
, nR
);
1920 CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC
== 10 && nR
== 20);
1921 checkMatrixElements
<AllEmptyMatrix
>(*pMat
);
1923 pMat
->PutBoolean(true, 1, 1);
1924 pMat
->PutDouble(-12.5, 4, 5);
1925 pMat
->PutString(rPool
.intern("Test"), 8, 2);
1926 pMat
->PutEmptyPath(8, 11);
1927 checkMatrixElements
<PartiallyFilledEmptyMatrix
>(*pMat
);
1930 pMat
= new ScMatrix(0, 0);
1931 pMat
->Resize(2, 2, 1.5);
1932 pMat
->PutEmpty(1, 1);
1934 CPPUNIT_ASSERT_EQUAL(1.5, pMat
->GetDouble(0, 0));
1935 CPPUNIT_ASSERT_EQUAL(1.5, pMat
->GetDouble(0, 1));
1936 CPPUNIT_ASSERT_EQUAL(1.5, pMat
->GetDouble(1, 0));
1937 CPPUNIT_ASSERT_MESSAGE("PutEmpty() call failed.", pMat
->IsEmpty(1, 1));
1939 // Max and min values.
1940 pMat
= new ScMatrix(2, 2, 0.0);
1941 pMat
->PutDouble(-10, 0, 0);
1942 pMat
->PutDouble(-12, 0, 1);
1943 pMat
->PutDouble(-8, 1, 0);
1944 pMat
->PutDouble(-25, 1, 1);
1945 CPPUNIT_ASSERT_EQUAL(-25.0, pMat
->GetMinValue(false));
1946 CPPUNIT_ASSERT_EQUAL(-8.0, pMat
->GetMaxValue(false));
1947 pMat
->PutString(rPool
.intern("Test"), 0, 0);
1948 CPPUNIT_ASSERT_EQUAL(0.0, pMat
->GetMaxValue(true)); // text as zero.
1949 CPPUNIT_ASSERT_EQUAL(-8.0, pMat
->GetMaxValue(false)); // ignore text.
1950 pMat
->PutBoolean(true, 0, 0);
1951 CPPUNIT_ASSERT_EQUAL(1.0, pMat
->GetMaxValue(false));
1952 pMat
= new ScMatrix(2, 2, 10.0);
1953 pMat
->PutBoolean(false, 0, 0);
1954 pMat
->PutDouble(12.5, 1, 1);
1955 CPPUNIT_ASSERT_EQUAL(0.0, pMat
->GetMinValue(false));
1956 CPPUNIT_ASSERT_EQUAL(12.5, pMat
->GetMaxValue(false));
1958 // Convert matrix into a linear double array. String elements become NaN
1959 // and empty elements become 0.
1960 pMat
= new ScMatrix(3, 3);
1961 pMat
->PutDouble(2.5, 0, 0);
1962 pMat
->PutDouble(1.2, 0, 1);
1963 pMat
->PutString(rPool
.intern("A"), 1, 1);
1964 pMat
->PutDouble(2.3, 2, 1);
1965 pMat
->PutDouble(-20, 2, 2);
1968 rtl::math::setNan(&fNaN
);
1970 std::vector
<double> aDoubles
;
1971 pMat
->GetDoubleArray(aDoubles
);
1974 const double pChecks
[] = { 2.5, 1.2, 0, 0, fNaN
, 0, 0, 2.3, -20 };
1975 CPPUNIT_ASSERT_EQUAL(SAL_N_ELEMENTS(pChecks
), aDoubles
.size());
1976 for (size_t i
= 0, n
= aDoubles
.size(); i
< n
; ++i
)
1978 if (rtl::math::isNan(pChecks
[i
]))
1979 CPPUNIT_ASSERT_MESSAGE("NaN is expected, but it's not.", rtl::math::isNan(aDoubles
[i
]));
1981 CPPUNIT_ASSERT_EQUAL(pChecks
[i
], aDoubles
[i
]);
1985 pMat2
= new ScMatrix(3, 3, 10.0);
1986 pMat2
->PutString(rPool
.intern("B"), 1, 0);
1987 pMat2
->MergeDoubleArray(aDoubles
, ScMatrix::Mul
);
1990 const double pChecks
[] = { 25, 12, 0, fNaN
, fNaN
, 0, 0, 23, -200 };
1991 CPPUNIT_ASSERT_EQUAL(SAL_N_ELEMENTS(pChecks
), aDoubles
.size());
1992 for (size_t i
= 0, n
= aDoubles
.size(); i
< n
; ++i
)
1994 if (rtl::math::isNan(pChecks
[i
]))
1995 CPPUNIT_ASSERT_MESSAGE("NaN is expected, but it's not.", rtl::math::isNan(aDoubles
[i
]));
1997 CPPUNIT_ASSERT_EQUAL(pChecks
[i
], aDoubles
[i
]);
2002 void Test::testMatrixComparisonWithErrors()
2004 m_pDoc
->InsertTab(0, "foo");
2006 // Insert the source values in A1:A2.
2007 m_pDoc
->SetString(0, 0, 0, "=1/0");
2008 m_pDoc
->SetValue( 0, 1, 0, 1.0);
2010 // Create a matrix formula in B3:B4 referencing A1:A2 and doing a greater
2011 // than comparison on it's values. Error value must be propagated.
2013 aMark
.SelectOneTable(0);
2014 m_pDoc
->InsertMatrixFormula(1, 2, 1, 3, aMark
, "=A1:A2>0");
2016 CPPUNIT_ASSERT_EQUAL(OUString("#DIV/0!"), m_pDoc
->GetString(0,0,0));
2017 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue( 0,1,0));
2018 CPPUNIT_ASSERT_EQUAL(OUString("#DIV/0!"), m_pDoc
->GetString(1,2,0));
2019 CPPUNIT_ASSERT_EQUAL(OUString("TRUE"), m_pDoc
->GetString(1,3,0));
2021 m_pDoc
->DeleteTab(0);
2024 void Test::testEnterMixedMatrix()
2026 m_pDoc
->InsertTab(0, "foo");
2028 // Insert the source values in A1:B2.
2029 m_pDoc
->SetString(0, 0, 0, "A");
2030 m_pDoc
->SetString(1, 0, 0, "B");
2032 m_pDoc
->SetValue(0, 1, 0, val
);
2034 m_pDoc
->SetValue(1, 1, 0, val
);
2036 // Create a matrix range in A4:B5 referencing A1:B2.
2038 aMark
.SelectOneTable(0);
2039 m_pDoc
->InsertMatrixFormula(0, 3, 1, 4, aMark
, "=A1:B2", NULL
);
2041 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(0,0,0), m_pDoc
->GetString(0,3,0));
2042 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(1,0,0), m_pDoc
->GetString(1,3,0));
2043 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetValue(0,1,0), m_pDoc
->GetValue(0,4,0));
2044 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetValue(1,1,0), m_pDoc
->GetValue(1,4,0));
2046 m_pDoc
->DeleteTab(0);
2049 void Test::testMatrixEditable()
2051 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // turn auto calc on.
2053 m_pDoc
->InsertTab(0, "Test");
2056 m_pDoc
->SetValue(ScAddress(0,0,0), 1.0);
2057 m_pDoc
->SetValue(ScAddress(1,0,0), 2.0);
2059 // A2 is a normal formula.
2060 m_pDoc
->SetString(ScAddress(0,1,0), "=5");
2062 // A3:A4 is a matrix.
2063 ScRange
aMatRange(0,2,0,0,3,0);
2065 aMark
.SetMarkArea(aMatRange
);
2066 m_pDoc
->InsertMatrixFormula(0, 2, 0, 3, aMark
, "=TRANSPOSE(A1:B1)", NULL
);
2068 // Check their values.
2069 CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
2070 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
2071 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(0,3,0)));
2073 // Make sure A3:A4 is a matrix.
2074 ScFormulaCell
* pFC
= m_pDoc
->GetFormulaCell(ScAddress(0,2,0));
2075 CPPUNIT_ASSERT(pFC
);
2076 CPPUNIT_ASSERT_MESSAGE("A3 should be matrix origin.", pFC
->GetMatrixFlag() == MM_FORMULA
);
2078 pFC
= m_pDoc
->GetFormulaCell(ScAddress(0,3,0));
2079 CPPUNIT_ASSERT(pFC
);
2080 CPPUNIT_ASSERT_MESSAGE("A4 should be matrix reference.", pFC
->GetMatrixFlag() == MM_REFERENCE
);
2082 // Check to make sure A3:A4 combined is editable.
2083 ScEditableTester aTester
;
2084 aTester
.TestSelection(m_pDoc
, aMark
);
2085 CPPUNIT_ASSERT(aTester
.IsEditable());
2087 m_pDoc
->DeleteTab(0);
2090 void Test::testCellCopy()
2092 m_pDoc
->InsertTab(0, "TestTab");
2093 ScAddress
aSrc(0,0,0);
2094 ScAddress
aDest(0,1,0);
2095 OUString
aStr("please copy me");
2096 m_pDoc
->SetString(aSrc
, "please copy me");
2097 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aSrc
), aStr
);
2098 // copy to self - why not ?
2099 m_pDoc
->CopyCellToDocument(aSrc
,aDest
,*m_pDoc
);
2100 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aDest
), aStr
);
2103 void Test::testSheetCopy()
2105 m_pDoc
->InsertTab(0, "TestTab");
2106 CPPUNIT_ASSERT_MESSAGE("document should have one sheet to begin with.", m_pDoc
->GetTableCount() == 1);
2108 // Insert text in A1.
2109 m_pDoc
->SetString(ScAddress(0,0,0), "copy me");
2111 // Insert edit cells in B1:B3.
2112 ScFieldEditEngine
& rEE
= m_pDoc
->GetEditEngine();
2113 rEE
.SetText("Edit 1");
2114 m_pDoc
->SetEditText(ScAddress(1,0,0), rEE
.CreateTextObject());
2115 rEE
.SetText("Edit 2");
2116 m_pDoc
->SetEditText(ScAddress(1,1,0), rEE
.CreateTextObject());
2117 rEE
.SetText("Edit 3");
2118 m_pDoc
->SetEditText(ScAddress(1,2,0), rEE
.CreateTextObject());
2121 bool bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
2122 CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
2125 ScAddress
aAdrA1 (0,2,0); // empty cell content.
2126 ScPostIt
*pNoteA1
= m_pDoc
->GetOrCreateNote(aAdrA1
);
2127 pNoteA1
->SetText(aAdrA1
, "Hello world in A3");
2129 // Copy and test the result.
2130 m_pDoc
->CopyTab(0, 1);
2131 CPPUNIT_ASSERT_MESSAGE("document now should have two sheets.", m_pDoc
->GetTableCount() == 2);
2132 bHidden
= m_pDoc
->RowHidden(0, 1, &nRow1
, &nRow2
);
2133 CPPUNIT_ASSERT_MESSAGE("copied sheet should also have all rows visible as the original.", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
2134 CPPUNIT_ASSERT_MESSAGE("There should be note on A3 in new sheet", m_pDoc
->HasNote(ScAddress(0,2,1)));
2135 CPPUNIT_ASSERT_EQUAL(OUString("copy me"), m_pDoc
->GetString(ScAddress(0,0,1)));
2137 // Check the copied edit cells.
2138 const EditTextObject
* pEditObj
= m_pDoc
->GetEditText(ScAddress(1,0,1));
2139 CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in B1.", pEditObj
);
2140 CPPUNIT_ASSERT_EQUAL(OUString("Edit 1"), pEditObj
->GetText(0));
2141 pEditObj
= m_pDoc
->GetEditText(ScAddress(1,1,1));
2142 CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in B2.", pEditObj
);
2143 CPPUNIT_ASSERT_EQUAL(OUString("Edit 2"), pEditObj
->GetText(0));
2144 pEditObj
= m_pDoc
->GetEditText(ScAddress(1,2,1));
2145 CPPUNIT_ASSERT_MESSAGE("There should be an edit cell in B3.", pEditObj
);
2146 CPPUNIT_ASSERT_EQUAL(OUString("Edit 3"), pEditObj
->GetText(0));
2148 m_pDoc
->DeleteTab(1);
2150 m_pDoc
->SetRowHidden(5, 10, 0, true);
2151 bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
2152 CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden
&& nRow1
== 0 && nRow2
== 4);
2153 bHidden
= m_pDoc
->RowHidden(5, 0, &nRow1
, &nRow2
);
2154 CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden
&& nRow1
== 5 && nRow2
== 10);
2155 bHidden
= m_pDoc
->RowHidden(11, 0, &nRow1
, &nRow2
);
2156 CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden
&& nRow1
== 11 && nRow2
== MAXROW
);
2158 // Copy the sheet once again.
2159 m_pDoc
->CopyTab(0, 1);
2160 CPPUNIT_ASSERT_MESSAGE("document now should have two sheets.", m_pDoc
->GetTableCount() == 2);
2161 bHidden
= m_pDoc
->RowHidden(0, 1, &nRow1
, &nRow2
);
2162 CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden
&& nRow1
== 0 && nRow2
== 4);
2163 bHidden
= m_pDoc
->RowHidden(5, 1, &nRow1
, &nRow2
);
2164 CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden
&& nRow1
== 5 && nRow2
== 10);
2165 bHidden
= m_pDoc
->RowHidden(11, 1, &nRow1
, &nRow2
);
2166 CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden
&& nRow1
== 11 && nRow2
== MAXROW
);
2167 m_pDoc
->DeleteTab(1);
2168 m_pDoc
->DeleteTab(0);
2171 void Test::testSheetMove()
2173 m_pDoc
->InsertTab(0, "TestTab1");
2174 CPPUNIT_ASSERT_EQUAL_MESSAGE("document should have one sheet to begin with.", m_pDoc
->GetTableCount(), static_cast<SCTAB
>(1));
2176 bool bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
2177 CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
2179 //test if inserting before another sheet works
2180 m_pDoc
->InsertTab(0, "TestTab2");
2181 CPPUNIT_ASSERT_EQUAL_MESSAGE("document should have two sheets", m_pDoc
->GetTableCount(), static_cast<SCTAB
>(2));
2182 bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
2183 CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
2185 // Move and test the result.
2186 m_pDoc
->MoveTab(0, 1);
2187 CPPUNIT_ASSERT_EQUAL_MESSAGE("document now should have two sheets.", m_pDoc
->GetTableCount(), static_cast<SCTAB
>(2));
2188 bHidden
= m_pDoc
->RowHidden(0, 1, &nRow1
, &nRow2
);
2189 CPPUNIT_ASSERT_MESSAGE("copied sheet should also have all rows visible as the original.", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
2191 m_pDoc
->GetName(0, aName
);
2192 CPPUNIT_ASSERT_MESSAGE( "sheets should have changed places", aName
== "TestTab1" );
2194 m_pDoc
->SetRowHidden(5, 10, 0, true);
2195 bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
2196 CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden
&& nRow1
== 0 && nRow2
== 4);
2197 bHidden
= m_pDoc
->RowHidden(5, 0, &nRow1
, &nRow2
);
2198 CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden
&& nRow1
== 5 && nRow2
== 10);
2199 bHidden
= m_pDoc
->RowHidden(11, 0, &nRow1
, &nRow2
);
2200 CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden
&& nRow1
== 11 && nRow2
== MAXROW
);
2202 // Move the sheet once again.
2203 m_pDoc
->MoveTab(1, 0);
2204 CPPUNIT_ASSERT_EQUAL_MESSAGE("document now should have two sheets.", m_pDoc
->GetTableCount(), static_cast<SCTAB
>(2));
2205 bHidden
= m_pDoc
->RowHidden(0, 1, &nRow1
, &nRow2
);
2206 CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden
&& nRow1
== 0 && nRow2
== 4);
2207 bHidden
= m_pDoc
->RowHidden(5, 1, &nRow1
, &nRow2
);
2208 CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden
&& nRow1
== 5 && nRow2
== 10);
2209 bHidden
= m_pDoc
->RowHidden(11, 1, &nRow1
, &nRow2
);
2210 CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden
&& nRow1
== 11 && nRow2
== MAXROW
);
2211 m_pDoc
->GetName(0, aName
);
2212 CPPUNIT_ASSERT_MESSAGE( "sheets should have changed places", aName
== "TestTab2" );
2213 m_pDoc
->DeleteTab(1);
2214 m_pDoc
->DeleteTab(0);
2217 void Test::testDataArea()
2219 m_pDoc
->InsertTab(0, "Data");
2221 // Totally empty sheet should be rightfully considered empty in all accounts.
2222 CPPUNIT_ASSERT_MESSAGE("Sheet is expected to be empty.", m_pDoc
->IsPrintEmpty(0, 0, 0, 100, 100));
2223 CPPUNIT_ASSERT_MESSAGE("Sheet is expected to be empty.", m_pDoc
->IsBlockEmpty(0, 0, 0, 100, 100));
2225 // Now, set borders in some cells....
2226 ::editeng::SvxBorderLine
aLine(NULL
, 50, table::BorderLineStyle::SOLID
);
2227 SvxBoxItem
aBorderItem(ATTR_BORDER
);
2228 aBorderItem
.SetLine(&aLine
, SvxBoxItemLine::LEFT
);
2229 aBorderItem
.SetLine(&aLine
, SvxBoxItemLine::RIGHT
);
2230 for (SCROW i
= 0; i
< 100; ++i
)
2231 // Set borders from row 1 to 100.
2232 m_pDoc
->ApplyAttr(0, i
, 0, aBorderItem
);
2234 // Now the sheet is considered non-empty for printing purposes, but still
2235 // be empty in all the other cases.
2236 CPPUNIT_ASSERT_MESSAGE("Empty sheet with borders should be printable.",
2237 !m_pDoc
->IsPrintEmpty(0, 0, 0, 100, 100));
2238 CPPUNIT_ASSERT_MESSAGE("But it should still be considered empty in all the other cases.",
2239 m_pDoc
->IsBlockEmpty(0, 0, 0, 100, 100));
2241 // Adding a real cell content should turn the block non-empty.
2242 m_pDoc
->SetString(0, 0, 0, "Some text");
2243 CPPUNIT_ASSERT_MESSAGE("Now the block should not be empty with a real cell content.",
2244 !m_pDoc
->IsBlockEmpty(0, 0, 0, 100, 100));
2246 // TODO: Add more tests for normal data area calculation.
2248 m_pDoc
->DeleteTab(0);
2251 void Test::testStreamValid()
2253 m_pDoc
->InsertTab(0, "Sheet1");
2254 m_pDoc
->InsertTab(1, "Sheet2");
2255 m_pDoc
->InsertTab(2, "Sheet3");
2256 m_pDoc
->InsertTab(3, "Sheet4");
2257 CPPUNIT_ASSERT_EQUAL_MESSAGE("We should have 4 sheet instances.", m_pDoc
->GetTableCount(), static_cast<SCTAB
>(4));
2263 // Put values into Sheet1.
2264 m_pDoc
->SetString(0, 0, 0, a1
);
2265 m_pDoc
->SetString(0, 1, 0, a2
);
2266 test
= m_pDoc
->GetString(0, 0, 0);
2267 CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet1.A1", test
.equals(a1
));
2268 test
= m_pDoc
->GetString(0, 1, 0);
2269 CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet1.A2", test
.equals(a2
));
2271 // Put formulas into Sheet2 to Sheet4 to reference values from Sheet1.
2272 m_pDoc
->SetString(0, 0, 1, "=Sheet1.A1");
2273 m_pDoc
->SetString(0, 1, 1, "=Sheet1.A2");
2274 m_pDoc
->SetString(0, 0, 2, "=Sheet1.A1");
2275 m_pDoc
->SetString(0, 0, 3, "=Sheet1.A2");
2277 test
= m_pDoc
->GetString(0, 0, 1);
2278 CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet2.A1", test
.equals(a1
));
2279 test
= m_pDoc
->GetString(0, 1, 1);
2280 CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet2.A2", test
.equals(a2
));
2281 test
= m_pDoc
->GetString(0, 0, 2);
2282 CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet3.A1", test
.equals(a1
));
2283 test
= m_pDoc
->GetString(0, 0, 3);
2284 CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet3.A1", test
.equals(a2
));
2286 // Set all sheet streams valid after all the initial cell values are in
2287 // place. In reality we need to have real XML streams stored in order to
2288 // claim they are valid, but we are just testing the flag values here.
2289 m_pDoc
->SetStreamValid(0, true);
2290 m_pDoc
->SetStreamValid(1, true);
2291 m_pDoc
->SetStreamValid(2, true);
2292 m_pDoc
->SetStreamValid(3, true);
2293 CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc
->IsStreamValid(0));
2294 CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc
->IsStreamValid(1));
2295 CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc
->IsStreamValid(2));
2296 CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc
->IsStreamValid(3));
2298 // Now, insert a new row at row 2 position on Sheet1. This will move cell
2299 // A2 downward but cell A1 remains unmoved.
2300 m_pDoc
->InsertRow(0, 0, MAXCOL
, 0, 1, 2);
2301 test
= m_pDoc
->GetString(0, 0, 0);
2302 CPPUNIT_ASSERT_MESSAGE("Cell A1 should not have moved.", test
.equals(a1
));
2303 test
= m_pDoc
->GetString(0, 3, 0);
2304 CPPUNIT_ASSERT_MESSAGE("the old cell A2 should now be at A4.", test
.equals(a2
));
2305 ScRefCellValue aCell
;
2306 aCell
.assign(*m_pDoc
, ScAddress(0,1,0));
2307 CPPUNIT_ASSERT_MESSAGE("Cell A2 should be empty.", aCell
.isEmpty());
2308 aCell
.assign(*m_pDoc
, ScAddress(0,2,0));
2309 CPPUNIT_ASSERT_MESSAGE("Cell A3 should be empty.", aCell
.isEmpty());
2311 // After the move, Sheet1, Sheet2, and Sheet4 should have their stream
2312 // invalidated, whereas Sheet3's stream should still be valid.
2313 CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc
->IsStreamValid(0));
2314 CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc
->IsStreamValid(1));
2315 CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc
->IsStreamValid(3));
2316 CPPUNIT_ASSERT_MESSAGE("Stream should still be valid.", m_pDoc
->IsStreamValid(2));
2318 m_pDoc
->DeleteTab(3);
2319 m_pDoc
->DeleteTab(2);
2320 m_pDoc
->DeleteTab(1);
2321 m_pDoc
->DeleteTab(0);
2324 void Test::testFunctionLists()
2326 const char* aDataBase
[] = {
2342 const char* aDateTime
[] = {
2374 const char* aFinancial
[] = {
2404 const char* aInformation
[] = {
2427 const char* aLogical
[] = {
2440 const char* aMathematical
[] = {
2514 const char* aArray
[] = {
2532 const char* aStatistical
[] = {
2677 const char* aSpreadsheet
[] = {
2703 const char* aText
[] = {
2749 const char* Category
; const char** Functions
;
2751 { "Database", aDataBase
},
2752 { "Date&Time", aDateTime
},
2753 { "Financial", aFinancial
},
2754 { "Information", aInformation
},
2755 { "Logical", aLogical
},
2756 { "Mathematical", aMathematical
},
2757 { "Array", aArray
},
2758 { "Statistical", aStatistical
},
2759 { "Spreadsheet", aSpreadsheet
},
2765 ScFunctionMgr
* pFuncMgr
= ScGlobal::GetStarCalcFunctionMgr();
2766 sal_uInt32 n
= pFuncMgr
->getCount();
2767 for (sal_uInt32 i
= 0; i
< n
; ++i
)
2769 const formula::IFunctionCategory
* pCat
= pFuncMgr
->getCategory(i
);
2770 CPPUNIT_ASSERT_MESSAGE("Unexpected category name", pCat
->getName().equalsAscii(aTests
[i
].Category
));
2771 sal_uInt32 nFuncCount
= pCat
->getCount();
2772 for (sal_uInt32 j
= 0; j
< nFuncCount
; ++j
)
2774 const formula::IFunctionDescription
* pFunc
= pCat
->getFunction(j
);
2775 CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected function name", OUString::createFromAscii(aTests
[i
].Functions
[j
]), pFunc
->getFunctionName());
2780 void Test::testGraphicsInGroup()
2782 m_pDoc
->InsertTab(0, "TestTab");
2783 CPPUNIT_ASSERT_MESSAGE("document should have one sheet to begin with.", m_pDoc
->GetTableCount() == 1);
2785 bool bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
2786 CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
2788 m_pDoc
->InitDrawLayer();
2789 ScDrawLayer
*pDrawLayer
= m_pDoc
->GetDrawLayer();
2790 CPPUNIT_ASSERT_MESSAGE("must have a draw layer", pDrawLayer
!= NULL
);
2791 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
2792 CPPUNIT_ASSERT_MESSAGE("must have a draw page", pPage
!= NULL
);
2796 Rectangle
aOrigRect(2,2,100,100);
2797 SdrRectObj
*pObj
= new SdrRectObj(aOrigRect
);
2798 pPage
->InsertObject(pObj
);
2799 const Rectangle
&rNewRect
= pObj
->GetLogicRect();
2800 CPPUNIT_ASSERT_MESSAGE("must have equal position and size", aOrigRect
== rNewRect
);
2802 ScDrawLayer::SetPageAnchored(*pObj
);
2804 //Use a range of rows guaranteed to include all of the square
2805 m_pDoc
->ShowRows(0, 100, 0, false);
2806 m_pDoc
->SetDrawPageSize(0);
2807 CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect
== rNewRect
);
2808 m_pDoc
->ShowRows(0, 100, 0, true);
2809 m_pDoc
->SetDrawPageSize(0);
2810 CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect
== rNewRect
);
2812 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *m_pDoc
, 0);
2813 CPPUNIT_ASSERT_MESSAGE("That shouldn't change size or positioning", aOrigRect
== rNewRect
);
2815 m_pDoc
->ShowRows(0, 100, 0, false);
2816 m_pDoc
->SetDrawPageSize(0);
2817 CPPUNIT_ASSERT_MESSAGE("Left and Right should be unchanged",
2818 aOrigRect
.Left() == rNewRect
.Left() && aOrigRect
.Right() == rNewRect
.Right());
2819 CPPUNIT_ASSERT_MESSAGE("Height should be minimum allowed height",
2820 (rNewRect
.Bottom() - rNewRect
.Top()) <= 1);
2821 m_pDoc
->ShowRows(0, 100, 0, true);
2822 m_pDoc
->SetDrawPageSize(0);
2823 CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect
== rNewRect
);
2828 Rectangle aOrigRect
= Rectangle(10,10,210,210); // 200 x 200
2829 SdrCircObj
* pObj
= new SdrCircObj(OBJ_CIRC
, aOrigRect
);
2830 pPage
->InsertObject(pObj
);
2831 const Rectangle
& rNewRect
= pObj
->GetLogicRect();
2832 CPPUNIT_ASSERT_MESSAGE("Position and size of the circle shouldn't change when inserted into the page.",
2833 aOrigRect
== rNewRect
);
2835 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *m_pDoc
, 0);
2836 CPPUNIT_ASSERT_MESSAGE("Size changed when cell anchored. Not good.",
2837 aOrigRect
== rNewRect
);
2839 // Insert 2 rows at the top. This should push the circle object down.
2840 m_pDoc
->InsertRow(0, 0, MAXCOL
, 0, 0, 2);
2841 m_pDoc
->SetDrawPageSize(0);
2843 // Make sure the size of the circle is still identical.
2844 CPPUNIT_ASSERT_MESSAGE("Size of the circle has changed, but shouldn't!",
2845 aOrigRect
.GetSize() == rNewRect
.GetSize());
2847 // Delete 2 rows at the top. This should bring the circle object to its original position.
2848 m_pDoc
->DeleteRow(0, 0, MAXCOL
, 0, 0, 2);
2849 m_pDoc
->SetDrawPageSize(0);
2850 CPPUNIT_ASSERT_MESSAGE("Failed to move back to its original position.", aOrigRect
== rNewRect
);
2855 basegfx::B2DPolygon aTempPoly
;
2856 Point
aStartPos(10,300), aEndPos(110,200); // bottom-left to top-right.
2857 Rectangle
aOrigRect(10,200,110,300); // 100 x 100
2858 aTempPoly
.append(basegfx::B2DPoint(aStartPos
.X(), aStartPos
.Y()));
2859 aTempPoly
.append(basegfx::B2DPoint(aEndPos
.X(), aEndPos
.Y()));
2860 SdrPathObj
* pObj
= new SdrPathObj(OBJ_LINE
, basegfx::B2DPolyPolygon(aTempPoly
));
2861 pObj
->NbcSetLogicRect(aOrigRect
);
2862 pPage
->InsertObject(pObj
);
2863 const Rectangle
& rNewRect
= pObj
->GetLogicRect();
2864 CPPUNIT_ASSERT_MESSAGE("Size differ.", aOrigRect
== rNewRect
);
2866 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *m_pDoc
, 0);
2867 CPPUNIT_ASSERT_MESSAGE("Size changed when cell-anchored. Not good.",
2868 aOrigRect
== rNewRect
);
2870 // Insert 2 rows at the top and delete them immediately.
2871 m_pDoc
->InsertRow(0, 0, MAXCOL
, 0, 0, 2);
2872 m_pDoc
->DeleteRow(0, 0, MAXCOL
, 0, 0, 2);
2873 m_pDoc
->SetDrawPageSize(0);
2874 CPPUNIT_ASSERT_MESSAGE("Size of a line object changed after row insertion and removal.",
2875 aOrigRect
== rNewRect
);
2877 sal_Int32 n
= pObj
->GetPointCount();
2878 CPPUNIT_ASSERT_MESSAGE("There should be exactly 2 points in a line object.", n
== 2);
2879 CPPUNIT_ASSERT_MESSAGE("Line shape has changed.",
2880 aStartPos
== pObj
->GetPoint(0) && aEndPos
== pObj
->GetPoint(1));
2883 m_pDoc
->DeleteTab(0);
2886 void Test::testGraphicsOnSheetMove()
2888 m_pDoc
->InsertTab(0, "Tab1");
2889 m_pDoc
->InsertTab(1, "Tab2");
2890 CPPUNIT_ASSERT_MESSAGE("There should be only 2 sheets to begin with", m_pDoc
->GetTableCount() == 2);
2892 m_pDoc
->InitDrawLayer();
2893 ScDrawLayer
* pDrawLayer
= m_pDoc
->GetDrawLayer();
2894 CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer
);
2895 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
2896 CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage
);
2898 // Insert an object.
2899 Rectangle
aObjRect(2,2,100,100);
2900 SdrObject
* pObj
= new SdrRectObj(aObjRect
);
2901 pPage
->InsertObject(pObj
);
2902 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *m_pDoc
, 0);
2904 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be one object on the 1st sheet.", pPage
->GetObjCount(), static_cast<size_t>(1));
2906 const ScDrawObjData
* pData
= ScDrawLayer::GetObjData(pObj
);
2907 CPPUNIT_ASSERT_MESSAGE("Object meta-data doesn't exist.", pData
);
2908 CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData
->maStart
.Tab() == 0 && pData
->maEnd
.Tab() == 0);
2910 pPage
= pDrawLayer
->GetPage(1);
2911 CPPUNIT_ASSERT_MESSAGE("No page instance for the 2nd sheet.", pPage
);
2912 CPPUNIT_ASSERT_EQUAL_MESSAGE("2nd sheet shouldn't have any object.", pPage
->GetObjCount(), static_cast<size_t>(0));
2914 // Insert a new sheet at left-end, and make sure the object has moved to
2916 m_pDoc
->InsertTab(0, "NewTab");
2917 CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 3 sheets.", m_pDoc
->GetTableCount(), static_cast<SCTAB
>(3));
2918 pPage
= pDrawLayer
->GetPage(0);
2919 CPPUNIT_ASSERT_MESSAGE("1st sheet should have no object.", pPage
&& pPage
->GetObjCount() == 0);
2920 pPage
= pDrawLayer
->GetPage(1);
2921 CPPUNIT_ASSERT_MESSAGE("2nd sheet should have one object.", pPage
&& pPage
->GetObjCount() == 1);
2922 pPage
= pDrawLayer
->GetPage(2);
2923 CPPUNIT_ASSERT_MESSAGE("3rd sheet should have no object.", pPage
&& pPage
->GetObjCount() == 0);
2925 CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData
->maStart
.Tab() == 1 && pData
->maEnd
.Tab() == 1);
2927 // Now, delete the sheet that just got inserted. The object should be back
2928 // on the 1st sheet.
2929 m_pDoc
->DeleteTab(0);
2930 pPage
= pDrawLayer
->GetPage(0);
2931 CPPUNIT_ASSERT_MESSAGE("1st sheet should have one object.", pPage
&& pPage
->GetObjCount() == 1);
2932 CPPUNIT_ASSERT_MESSAGE("Size and position of the object shouldn't change.",
2933 pObj
->GetLogicRect() == aObjRect
);
2935 CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData
->maStart
.Tab() == 0 && pData
->maEnd
.Tab() == 0);
2937 // Move the 1st sheet to the last position.
2938 m_pDoc
->MoveTab(0, 1);
2939 pPage
= pDrawLayer
->GetPage(0);
2940 CPPUNIT_ASSERT_MESSAGE("1st sheet should have no object.", pPage
&& pPage
->GetObjCount() == 0);
2941 pPage
= pDrawLayer
->GetPage(1);
2942 CPPUNIT_ASSERT_MESSAGE("2nd sheet should have one object.", pPage
&& pPage
->GetObjCount() == 1);
2943 CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData
->maStart
.Tab() == 1 && pData
->maEnd
.Tab() == 1);
2945 // Copy the 2nd sheet, which has one drawing object to the last position.
2946 m_pDoc
->CopyTab(1, 2);
2947 pPage
= pDrawLayer
->GetPage(2);
2948 CPPUNIT_ASSERT_MESSAGE("Copied sheet should have one object.", pPage
&& pPage
->GetObjCount() == 1);
2949 pObj
= pPage
->GetObj(0);
2950 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj
);
2951 pData
= ScDrawLayer::GetObjData(pObj
);
2952 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object meta-data.", pData
);
2953 CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData
->maStart
.Tab() == 2 && pData
->maEnd
.Tab() == 2);
2955 m_pDoc
->DeleteTab(2);
2956 m_pDoc
->DeleteTab(1);
2957 m_pDoc
->DeleteTab(0);
2960 void Test::testToggleRefFlag()
2962 // In this test, there is no need to insert formula string into a cell in
2963 // the document, as ScRefFinder does not depend on the content of the
2964 // document except for the sheet names.
2966 m_pDoc
->InsertTab(0, "Test");
2969 // Calc A1: basic 2D reference
2971 OUString
aFormula("=B100");
2972 ScAddress
aPos(1, 5, 0);
2973 ScRefFinder
aFinder(aFormula
, aPos
, m_pDoc
, formula::FormulaGrammar::CONV_OOO
);
2976 CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula
.equals(aFinder
.GetText()));
2978 // column relative / row relative -> column absolute / row absolute
2979 aFinder
.ToggleRel(0, aFormula
.getLength());
2980 aFormula
= aFinder
.GetText();
2981 CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula
== "=$B$100" );
2983 // column absolute / row absolute -> column relative / row absolute
2984 aFinder
.ToggleRel(0, aFormula
.getLength());
2985 aFormula
= aFinder
.GetText();
2986 CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula
== "=B$100" );
2988 // column relative / row absolute -> column absolute / row relative
2989 aFinder
.ToggleRel(0, aFormula
.getLength());
2990 aFormula
= aFinder
.GetText();
2991 CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula
== "=$B100" );
2993 // column absolute / row relative -> column relative / row relative
2994 aFinder
.ToggleRel(0, aFormula
.getLength());
2995 aFormula
= aFinder
.GetText();
2996 CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula
== "=B100" );
3000 // Excel R1C1: basic 2D reference
3002 OUString
aFormula("=R2C1");
3003 ScAddress
aPos(3, 5, 0);
3004 ScRefFinder
aFinder(aFormula
, aPos
, m_pDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
3007 CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula
.equals(aFinder
.GetText()));
3009 // column absolute / row absolute -> column relative / row absolute
3010 aFinder
.ToggleRel(0, aFormula
.getLength());
3011 aFormula
= aFinder
.GetText();
3012 CPPUNIT_ASSERT_EQUAL(OUString("=R2C[-3]"), aFormula
);
3014 // column relative / row absolute - > column absolute / row relative
3015 aFinder
.ToggleRel(0, aFormula
.getLength());
3016 aFormula
= aFinder
.GetText();
3017 CPPUNIT_ASSERT_EQUAL(OUString("=R[-4]C1"), aFormula
);
3019 // column absolute / row relative -> column relative / row relative
3020 aFinder
.ToggleRel(0, aFormula
.getLength());
3021 aFormula
= aFinder
.GetText();
3022 CPPUNIT_ASSERT_EQUAL(OUString("=R[-4]C[-3]"), aFormula
);
3024 // column relative / row relative -> column absolute / row absolute
3025 aFinder
.ToggleRel(0, aFormula
.getLength());
3026 aFormula
= aFinder
.GetText();
3027 CPPUNIT_ASSERT_EQUAL(OUString("=R2C1"), aFormula
);
3031 // Excel R1C1: Selection at the end of the formula string and does not
3032 // overlap the formula string at all (inspired by fdo#39135).
3033 OUString
aFormula("=R1C1");
3034 ScAddress
aPos(1, 1, 0);
3035 ScRefFinder
aFinder(aFormula
, aPos
, m_pDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
3038 CPPUNIT_ASSERT_EQUAL(aFormula
, aFinder
.GetText());
3040 // Make the column relative.
3041 sal_Int32 n
= aFormula
.getLength();
3042 aFinder
.ToggleRel(n
, n
);
3043 aFormula
= aFinder
.GetText();
3044 CPPUNIT_ASSERT_EQUAL(OUString("=R1C[-1]"), aFormula
);
3046 // Make the row relative.
3047 n
= aFormula
.getLength();
3048 aFinder
.ToggleRel(n
, n
);
3049 aFormula
= aFinder
.GetText();
3050 CPPUNIT_ASSERT_EQUAL(OUString("=R[-1]C1"), aFormula
);
3052 // Make both relative.
3053 n
= aFormula
.getLength();
3054 aFinder
.ToggleRel(n
, n
);
3055 aFormula
= aFinder
.GetText();
3056 CPPUNIT_ASSERT_EQUAL(OUString("=R[-1]C[-1]"), aFormula
);
3058 // Back to the original.
3059 n
= aFormula
.getLength();
3060 aFinder
.ToggleRel(n
, n
);
3061 aFormula
= aFinder
.GetText();
3062 CPPUNIT_ASSERT_EQUAL(OUString("=R1C1"), aFormula
);
3067 OUString
aFormula("=A1+4");
3068 ScAddress
aPos(1, 1, 0);
3069 ScRefFinder
aFinder(aFormula
, aPos
, m_pDoc
, formula::FormulaGrammar::CONV_OOO
);
3072 CPPUNIT_ASSERT_EQUAL(aFormula
, aFinder
.GetText());
3074 // Set the cursor over the 'A1' part and toggle.
3075 aFinder
.ToggleRel(2, 2);
3076 aFormula
= aFinder
.GetText();
3077 CPPUNIT_ASSERT_EQUAL(OUString("=$A$1+4"), aFormula
);
3079 aFinder
.ToggleRel(2, 2);
3080 aFormula
= aFinder
.GetText();
3081 CPPUNIT_ASSERT_EQUAL(OUString("=A$1+4"), aFormula
);
3083 aFinder
.ToggleRel(2, 2);
3084 aFormula
= aFinder
.GetText();
3085 CPPUNIT_ASSERT_EQUAL(OUString("=$A1+4"), aFormula
);
3087 aFinder
.ToggleRel(2, 2);
3088 aFormula
= aFinder
.GetText();
3089 CPPUNIT_ASSERT_EQUAL(OUString("=A1+4"), aFormula
);
3092 // TODO: Add more test cases esp. for 3D references, Excel A1 syntax, and
3093 // partial selection within formula string.
3095 m_pDoc
->DeleteTab(0);
3098 void Test::testAutofilter()
3100 OUString
aDBName("NONAME");
3102 m_pDoc
->InsertTab( 0, "Test" );
3104 // cell contents (0 = empty cell)
3105 const char* aData
[][3] = {
3106 { "C1", "C2", "C3" },
3113 SCCOL nCols
= SAL_N_ELEMENTS(aData
[0]);
3114 SCROW nRows
= SAL_N_ELEMENTS(aData
);
3117 for (SCROW i
= 0; i
< nRows
; ++i
)
3118 for (SCCOL j
= 0; j
< nCols
; ++j
)
3120 m_pDoc
->SetString(j
, i
, 0, OUString::createFromAscii(aData
[i
][j
]));
3122 ScDBData
* pDBData
= new ScDBData(aDBName
, 0, 0, 0, nCols
-1, nRows
-1);
3123 m_pDoc
->SetAnonymousDBData(0,pDBData
);
3125 pDBData
->SetAutoFilter(true);
3127 pDBData
->GetArea(aRange
);
3128 m_pDoc
->ApplyFlagsTab( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
3129 aRange
.aEnd
.Col(), aRange
.aStart
.Row(),
3130 aRange
.aStart
.Tab(), SC_MF_AUTO
);
3132 //create the query param
3133 ScQueryParam aParam
;
3134 pDBData
->GetQueryParam(aParam
);
3135 ScQueryEntry
& rEntry
= aParam
.GetEntry(0);
3136 rEntry
.bDoQuery
= true;
3138 rEntry
.eOp
= SC_EQUAL
;
3139 rEntry
.GetQueryItem().mfVal
= 0;
3140 // add queryParam to database range.
3141 pDBData
->SetQueryParam(aParam
);
3143 // perform the query.
3144 m_pDoc
->Query(0, aParam
, true);
3148 bool bHidden
= m_pDoc
->RowHidden(2, 0, &nRow1
, &nRow2
);
3149 CPPUNIT_ASSERT_MESSAGE("rows 2 & 3 should be hidden", bHidden
&& nRow1
== 2 && nRow2
== 3);
3151 // Remove filtering.
3153 m_pDoc
->Query(0, aParam
, true);
3154 bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
3155 CPPUNIT_ASSERT_MESSAGE("All rows should be shown.", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
3157 // Filter for non-empty cells by column C.
3158 rEntry
.bDoQuery
= true;
3160 rEntry
.SetQueryByNonEmpty();
3161 m_pDoc
->Query(0, aParam
, true);
3163 // only row 3 should be hidden. The rest should be visible.
3164 bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
3165 CPPUNIT_ASSERT_MESSAGE("rows 1 & 2 should be visible.", !bHidden
&& nRow1
== 0 && nRow2
== 1);
3166 bHidden
= m_pDoc
->RowHidden(2, 0, &nRow1
, &nRow2
);
3167 CPPUNIT_ASSERT_MESSAGE("row 3 should be hidden.", bHidden
&& nRow1
== 2 && nRow2
== 2);
3168 bHidden
= m_pDoc
->RowHidden(3, 0, &nRow1
, &nRow2
);
3169 CPPUNIT_ASSERT_MESSAGE("row 4 and down should be visible.", !bHidden
&& nRow1
== 3 && nRow2
== MAXROW
);
3171 // Now, filter for empty cells by column C.
3172 rEntry
.SetQueryByEmpty();
3173 m_pDoc
->Query(0, aParam
, true);
3175 // Now, only row 1 and 3, and 6 and down should be visible.
3176 bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
3177 CPPUNIT_ASSERT_MESSAGE("row 1 should be visible.", !bHidden
&& nRow1
== 0 && nRow2
== 0);
3178 bHidden
= m_pDoc
->RowHidden(1, 0, &nRow1
, &nRow2
);
3179 CPPUNIT_ASSERT_MESSAGE("row 2 should be hidden.", bHidden
&& nRow1
== 1 && nRow2
== 1);
3180 bHidden
= m_pDoc
->RowHidden(2, 0, &nRow1
, &nRow2
);
3181 CPPUNIT_ASSERT_MESSAGE("row 3 should be visible.", !bHidden
&& nRow1
== 2 && nRow2
== 2);
3182 bHidden
= m_pDoc
->RowHidden(3, 0, &nRow1
, &nRow2
);
3183 CPPUNIT_ASSERT_MESSAGE("rows 4 & 5 should be hidden.", bHidden
&& nRow1
== 3 && nRow2
== 4);
3184 bHidden
= m_pDoc
->RowHidden(5, 0, &nRow1
, &nRow2
);
3185 CPPUNIT_ASSERT_MESSAGE("rows 6 and down should be all visible.", !bHidden
&& nRow1
== 5 && nRow2
== MAXROW
);
3187 m_pDoc
->DeleteTab(0);
3190 void Test::testCopyPaste()
3192 m_pDoc
->InsertTab(0, "Sheet1");
3193 m_pDoc
->InsertTab(1, "Sheet2");
3194 //test copy&paste + ScUndoPaste
3195 //copy local and global range names in formulas
3196 //string cells and value cells
3197 m_pDoc
->SetValue(0, 0, 0, 1);
3198 m_pDoc
->SetValue(3, 0, 0, 0);
3199 m_pDoc
->SetValue(3, 1, 0, 1);
3200 m_pDoc
->SetValue(3, 2, 0, 2);
3201 m_pDoc
->SetValue(3, 3, 0, 3);
3202 m_pDoc
->SetString(2, 0, 0, "test");
3203 ScAddress
aAdr (0, 0, 0);
3205 //create some range names, local and global
3206 ScRangeData
* pLocal1
= new ScRangeData(m_pDoc
, OUString("local1"), aAdr
);
3207 ScRangeData
* pLocal2
= new ScRangeData(m_pDoc
, OUString("local2"), aAdr
);
3208 ScRangeData
* pGlobal
= new ScRangeData(m_pDoc
, OUString("global"), aAdr
);
3209 ScRangeName
* pGlobalRangeName
= new ScRangeName();
3210 pGlobalRangeName
->insert(pGlobal
);
3211 ScRangeName
* pLocalRangeName1
= new ScRangeName();
3212 pLocalRangeName1
->insert(pLocal1
);
3213 pLocalRangeName1
->insert(pLocal2
);
3214 m_pDoc
->SetRangeName(pGlobalRangeName
);
3215 m_pDoc
->SetRangeName(0, pLocalRangeName1
);
3217 // Add formula to B1.
3218 OUString
aFormulaString("=local1+global+SUM($C$1:$D$4)");
3219 m_pDoc
->SetString(1, 0, 0, aFormulaString
);
3221 double fValue
= m_pDoc
->GetValue(ScAddress(1,0,0));
3222 ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 8", fValue
, 8);
3224 // add notes to A1:C1
3225 ScAddress
aAdrA1 (0, 0, 0); // empty cell content
3226 OUString
aHelloA1("Hello world in A1");
3227 ScPostIt
* pNoteA1
= m_pDoc
->GetOrCreateNote(aAdrA1
);
3228 pNoteA1
->SetText(aAdrA1
, aHelloA1
);
3229 ScAddress
aAdrB1 (1, 0, 0); // formula cell content
3230 OUString
aHelloB1("Hello world in B1");
3231 ScPostIt
* pNoteB1
= m_pDoc
->GetOrCreateNote(aAdrB1
);
3232 pNoteB1
->SetText(aAdrB1
, aHelloB1
);
3233 ScAddress
aAdrC1 (2, 0, 0); // string cell content
3234 OUString
aHelloC1("Hello world in C1");
3235 ScPostIt
* pNoteC1
= m_pDoc
->GetOrCreateNote(aAdrC1
);
3236 pNoteC1
->SetText(aAdrC1
, aHelloC1
);
3238 //copy Sheet1.A1:C1 to Sheet2.A2:C2
3239 ScRange
aRange(0,0,0,2,0,0);
3240 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3241 copyToClip(m_pDoc
, aRange
, &aClipDoc
);
3243 aRange
= ScRange(0,1,1,2,1,1);//target: Sheet2.A2:C2
3244 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
3245 pUndoDoc
->InitUndo(m_pDoc
, 1, 1, true, true);
3246 boost::scoped_ptr
<ScUndoPaste
> pUndo(createUndoPaste(getDocShell(), aRange
, pUndoDoc
));
3248 aMark
.SetMarkArea(aRange
);
3249 m_pDoc
->CopyFromClip(aRange
, aMark
, IDF_ALL
, NULL
, &aClipDoc
);
3251 //check values after copying
3253 fValue
= m_pDoc
->GetValue(ScAddress(1,1,1));
3254 m_pDoc
->GetFormula(1,1,1, aString
);
3255 ASSERT_DOUBLES_EQUAL_MESSAGE("copied formula should return 2", fValue
, 2);
3256 CPPUNIT_ASSERT_MESSAGE("formula string was not copied correctly", aString
== aFormulaString
);
3257 fValue
= m_pDoc
->GetValue(ScAddress(0,1,1));
3258 CPPUNIT_ASSERT_MESSAGE("copied value should be 1", fValue
== 1);
3260 //check local range name after copying
3261 pLocal1
= m_pDoc
->GetRangeName(1)->findByUpperName(OUString("LOCAL1"));
3262 CPPUNIT_ASSERT_MESSAGE("local range name 1 should be copied", pLocal1
);
3263 ScRange aRangeLocal1
;
3264 bool bIsValidRef
= pLocal1
->IsValidReference(aRangeLocal1
);
3265 CPPUNIT_ASSERT_MESSAGE("local range name 1 should be valid", bIsValidRef
);
3266 CPPUNIT_ASSERT_MESSAGE("local range 1 should still point to Sheet1.A1",aRangeLocal1
== ScRange(0,0,0,0,0,0));
3267 pLocal2
= m_pDoc
->GetRangeName(1)->findByUpperName(OUString("LOCAL2"));
3268 CPPUNIT_ASSERT_MESSAGE("local2 should not be copied", pLocal2
== NULL
);
3270 // check notes after copying
3271 CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.A2", m_pDoc
->HasNote(ScAddress(0, 1, 1)));
3272 CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.B2", m_pDoc
->HasNote(ScAddress(1, 1, 1)));
3273 CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.C2", m_pDoc
->HasNote(ScAddress(2, 1, 1)));
3274 CPPUNIT_ASSERT_MESSAGE("Note content on Sheet1.A1 not copied to Sheet2.A2, empty cell content",
3275 m_pDoc
->GetNote(ScAddress(0, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(0, 1, 1))->GetText());
3276 CPPUNIT_ASSERT_MESSAGE("Note content on Sheet1.B1 not copied to Sheet2.B2, formula cell content",
3277 m_pDoc
->GetNote(ScAddress(1, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(1, 1, 1))->GetText());
3278 CPPUNIT_ASSERT_MESSAGE("Note content on Sheet1.C1 not copied to Sheet2.C2, string cell content",
3279 m_pDoc
->GetNote(ScAddress(2, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(2, 1, 1))->GetText());
3281 //check undo and redo
3283 fValue
= m_pDoc
->GetValue(ScAddress(1,1,1));
3284 ASSERT_DOUBLES_EQUAL_MESSAGE("after undo formula should return nothing", fValue
, 0);
3285 aString
= m_pDoc
->GetString(2, 1, 1);
3286 CPPUNIT_ASSERT_MESSAGE("after undo, string should be removed", aString
.isEmpty());
3287 CPPUNIT_ASSERT_MESSAGE("after undo, note on A2 should be removed", !m_pDoc
->HasNote(ScAddress(0, 1, 1)));
3288 CPPUNIT_ASSERT_MESSAGE("after undo, note on B2 should be removed", !m_pDoc
->HasNote(ScAddress(1, 1, 1)));
3289 CPPUNIT_ASSERT_MESSAGE("after undo, note on C2 should be removed", !m_pDoc
->HasNote(ScAddress(2, 1, 1)));
3292 fValue
= m_pDoc
->GetValue(ScAddress(1,1,1));
3293 ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 2 after redo", fValue
, 2);
3294 aString
= m_pDoc
->GetString(2, 1, 1);
3295 CPPUNIT_ASSERT_MESSAGE("Cell Sheet2.C2 should contain: test", aString
== "test");
3296 m_pDoc
->GetFormula(1,1,1, aString
);
3297 CPPUNIT_ASSERT_MESSAGE("Formula should be correct again", aString
== aFormulaString
);
3299 CPPUNIT_ASSERT_MESSAGE("After Redo, there should be a note on Sheet2.A2", m_pDoc
->HasNote(ScAddress(0, 1, 1)));
3300 CPPUNIT_ASSERT_MESSAGE("After Redo, there should be a note on Sheet2.B2", m_pDoc
->HasNote(ScAddress(1, 1, 1)));
3301 CPPUNIT_ASSERT_MESSAGE("After Redo, there should be a note on Sheet2.C2", m_pDoc
->HasNote(ScAddress(2, 1, 1)));
3302 CPPUNIT_ASSERT_MESSAGE("After Redo, note again on Sheet2.A2, empty cell content",
3303 m_pDoc
->GetNote(ScAddress(0, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(0, 1, 1))->GetText());
3304 CPPUNIT_ASSERT_MESSAGE("After Redo, note again on Sheet2.B2, formula cell content",
3305 m_pDoc
->GetNote(ScAddress(1, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(1, 1, 1))->GetText());
3306 CPPUNIT_ASSERT_MESSAGE("After Redo, note again on Sheet2.C2, string cell content",
3307 m_pDoc
->GetNote(ScAddress(2, 0, 0))->GetText() == m_pDoc
->GetNote(ScAddress(2, 1, 1))->GetText());
3309 m_pDoc
->DeleteTab(1);
3310 m_pDoc
->DeleteTab(0);
3313 void Test::testCopyPasteAsLink()
3315 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // Turn on auto calc.
3317 m_pDoc
->InsertTab(0, "Sheet1");
3318 m_pDoc
->InsertTab(1, "Sheet2");
3320 m_pDoc
->SetValue(ScAddress(0,0,0), 1); // A1
3321 m_pDoc
->SetValue(ScAddress(0,1,0), 2); // A2
3322 m_pDoc
->SetValue(ScAddress(0,2,0), 3); // A3
3324 ScRange
aRange(0,0,0,0,2,0); // Copy A1:A3 to clip.
3325 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3326 copyToClip(m_pDoc
, aRange
, &aClipDoc
);
3328 aRange
= ScRange(1,1,1,1,3,1); // Paste to B2:B4 on Sheet2.
3330 aMark
.SetMarkArea(aRange
);
3331 // Paste range as link.
3332 m_pDoc
->CopyFromClip(aRange
, aMark
, IDF_CONTENTS
, NULL
, &aClipDoc
, true, true);
3334 // Check pasted content to make sure they reference the correct cells.
3335 ScFormulaCell
* pFC
= m_pDoc
->GetFormulaCell(ScAddress(1,1,1));
3336 CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC
);
3337 CPPUNIT_ASSERT_EQUAL(1.0, pFC
->GetValue());
3339 pFC
= m_pDoc
->GetFormulaCell(ScAddress(1,2,1));
3340 CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC
);
3341 CPPUNIT_ASSERT_EQUAL(2.0, pFC
->GetValue());
3343 pFC
= m_pDoc
->GetFormulaCell(ScAddress(1,3,1));
3344 CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC
);
3345 CPPUNIT_ASSERT_EQUAL(3.0, pFC
->GetValue());
3347 m_pDoc
->DeleteTab(1);
3348 m_pDoc
->DeleteTab(0);
3351 void Test::testCopyPasteTranspose()
3353 m_pDoc
->InsertTab(0, "Sheet1");
3354 m_pDoc
->InsertTab(1, "Sheet2");
3356 m_pDoc
->SetValue(0, 0, 0, 1);
3357 m_pDoc
->SetString(1, 0, 0, "=A1+1");
3358 m_pDoc
->SetString(2, 0, 0, "test");
3360 // add notes to A1:C1
3361 ScAddress
aAdrA1 (0, 0, 0); // numerical cell content
3362 OUString
aHelloA1("Hello world in A1");
3363 ScPostIt
* pNoteA1
= m_pDoc
->GetOrCreateNote(aAdrA1
);
3364 pNoteA1
->SetText(aAdrA1
, aHelloA1
);
3365 ScAddress
aAdrB1 (1, 0, 0); // formula cell content
3366 OUString
aHelloB1("Hello world in B1");
3367 ScPostIt
* pNoteB1
= m_pDoc
->GetOrCreateNote(aAdrB1
);
3368 pNoteB1
->SetText(aAdrB1
, aHelloB1
);
3369 ScAddress
aAdrC1 (2, 0, 0); // string cell content
3370 OUString
aHelloC1("Hello world in C1");
3371 ScPostIt
* pNoteC1
= m_pDoc
->GetOrCreateNote(aAdrC1
);
3372 pNoteC1
->SetText(aAdrC1
, aHelloC1
);
3374 // transpose clipboard, paste and check on Sheet2
3375 m_pDoc
->InsertTab(1, "Sheet2");
3377 ScRange aSrcRange
= ScRange(0,0,0,2,0,0);
3378 ScDocument
aNewClipDoc(SCDOCMODE_CLIP
);
3379 copyToClip(m_pDoc
, aSrcRange
, &aNewClipDoc
);
3381 ::std::unique_ptr
<ScDocument
> pTransClip
;
3382 pTransClip
.reset(new ScDocument(SCDOCMODE_CLIP
));
3383 aNewClipDoc
.TransposeClip(pTransClip
.get(), IDF_ALL
, false);
3384 ScDocument
* pTransposedClip
= pTransClip
.release();
3386 ScRange aDestRange
= ScRange(3,1,1,3,3,1);//target: Sheet2.D2:D4
3388 aMark
.SetMarkArea(aDestRange
);
3389 m_pDoc
->CopyFromClip(aDestRange
, aMark
, IDF_ALL
, NULL
, pTransposedClip
);
3391 //check cell content after transposed copy/paste
3392 OUString aString
= m_pDoc
->GetString(3, 3, 1);
3393 CPPUNIT_ASSERT_MESSAGE("Cell Sheet2.D4 should contain: test", aString
== "test");
3394 double fValue
= m_pDoc
->GetValue(ScAddress(3,1,1));
3395 ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied cell should return 1", fValue
, 1);
3396 fValue
= m_pDoc
->GetValue(ScAddress(3,2,1));
3397 ASSERT_DOUBLES_EQUAL_MESSAGE("transposed copied formula should return 2", fValue
, 2);
3398 m_pDoc
->GetFormula(3, 2, 1, aString
);
3399 CPPUNIT_ASSERT_MESSAGE("transposed formula should point on Sheet2.D2", aString
== "=D2+1");
3401 // check notes after transposed copy/paste
3402 CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.D2", m_pDoc
->HasNote(ScAddress(3, 1, 1)));
3403 CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.D3", m_pDoc
->HasNote(ScAddress(3, 2, 1)));
3404 CPPUNIT_ASSERT_MESSAGE("There should be a note on Sheet2.D4", m_pDoc
->HasNote(ScAddress(3, 3, 1)));
3405 CPPUNIT_ASSERT_MESSAGE("Content of cell note on Sheet2.D2",
3406 m_pDoc
->GetNote(ScAddress(3, 1, 1))->GetText() == m_pDoc
->GetNote(ScAddress(0, 0, 0))->GetText());
3407 CPPUNIT_ASSERT_MESSAGE("Content of cell note on Sheet2.D3",
3408 m_pDoc
->GetNote(ScAddress(3, 2, 1))->GetText() == m_pDoc
->GetNote(ScAddress(1, 0, 0))->GetText());
3409 CPPUNIT_ASSERT_MESSAGE("Content of cell note on Sheet2.D4",
3410 m_pDoc
->GetNote(ScAddress(3, 3, 1))->GetText() == m_pDoc
->GetNote(ScAddress(2, 0, 0))->GetText());
3412 m_pDoc
->DeleteTab(1);
3413 m_pDoc
->DeleteTab(0);
3417 void Test::testCopyPasteMultiRange()
3419 m_pDoc
->InsertTab(0, "Test");
3421 // Fill A2:B6 with numbers.
3422 for (SCROW nRow
= 1; nRow
<= 5; ++nRow
)
3424 for (SCCOL nCol
= 0; nCol
<= 1; ++nCol
)
3426 ScAddress
aPos(nCol
,nRow
,0);
3427 m_pDoc
->SetValue(aPos
, nRow
+nCol
);
3431 // Fill D9:E11 with numbers.
3432 for (SCROW nRow
= 8; nRow
<= 10; ++nRow
)
3434 for (SCCOL nCol
= 3; nCol
<= 4; ++nCol
)
3436 ScAddress
aPos(nCol
,nRow
,0);
3437 m_pDoc
->SetValue(aPos
, 10.0);
3442 aMark
.SelectOneTable(0);
3444 // Copy A2:B2, A4:B4, and A6:B6 to clipboard.
3445 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3446 ScClipParam aClipParam
;
3447 aClipParam
.maRanges
.Append(ScRange(0,1,0,1,1,0)); // A2:B2
3448 aClipParam
.maRanges
.Append(ScRange(0,3,0,1,3,0)); // A4:B4
3449 aClipParam
.maRanges
.Append(ScRange(0,5,0,1,5,0)); // A6:B6
3450 aClipParam
.meDirection
= ScClipParam::Row
;
3451 m_pDoc
->CopyToClip(aClipParam
, &aClipDoc
, &aMark
);
3453 // Paste to D9:E11, and make sure it won't crash (rhbz#1080196).
3454 m_pDoc
->CopyMultiRangeFromClip(ScAddress(3,8,0), aMark
, IDF_CONTENTS
, &aClipDoc
);
3455 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(3,8,0)));
3456 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(4,8,0)));
3457 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(3,9,0)));
3458 CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc
->GetValue(ScAddress(4,9,0)));
3459 CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc
->GetValue(ScAddress(3,10,0)));
3460 CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc
->GetValue(ScAddress(4,10,0)));
3462 m_pDoc
->DeleteTab(0);
3465 void Test::testCopyPasteSkipEmpty()
3478 TestRange( ScDocument
* pDoc
) : mpDoc(pDoc
) {}
3480 bool checkRange( const ScAddress
& rPos
, const Check
* p
, const Check
* pEnd
)
3482 ScAddress
aPos(rPos
);
3483 OUString aPosStr
= aPos
.Format(SCA_VALID
);
3484 for (; p
!= pEnd
; ++p
, aPos
.IncRow())
3486 if (!mpDoc
->GetString(aPos
).equalsAscii(p
->mpStr
))
3488 cerr
<< aPosStr
<< ": incorrect string value: expected='" << p
->mpStr
<< "' actual='" << mpDoc
->GetString(aPos
) << endl
;
3492 const SvxBrushItem
* pBrush
=
3493 dynamic_cast<const SvxBrushItem
*>(mpDoc
->GetAttr(aPos
, ATTR_BACKGROUND
));
3497 cerr
<< aPosStr
<< ": failed to get brush item from the cell." << endl
;
3501 if (pBrush
->GetColor() != p
->maColor
)
3503 Color aExpected
= p
->maColor
;
3504 Color aActual
= pBrush
->GetColor();
3505 cerr
<< aPosStr
<< ": incorrect cell background color: expected=("
3506 << static_cast<int>(aExpected
.GetRed()) << ","
3507 << static_cast<int>(aExpected
.GetGreen()) << ","
3508 << static_cast<int>(aExpected
.GetBlue()) << "), actual=("
3509 << static_cast<int>(aActual
.GetRed()) << ","
3510 << static_cast<int>(aActual
.GetGreen()) << ","
3511 << static_cast<int>(aActual
.GetBlue()) << ")" << endl
;
3516 bool bHasNote
= mpDoc
->HasNote(aPos
);
3517 if (bHasNote
!= p
->mbHasNote
)
3519 cerr
<< aPosStr
<< ": ";
3521 cerr
<< "this cell should have a cell note, but doesn't." << endl
;
3523 cerr
<< "this cell should NOT have a cell note, but one is found." << endl
;
3534 m_pDoc
->InsertTab(0, "Test");
3535 m_pDoc
->InitDrawLayer(&getDocShell()); // for cell note objects.
3537 ScRange
aSrcRange(0,0,0,0,4,0);
3538 ScRange
aDestRange(1,0,0,1,4,0);
3541 aMark
.SetMarkArea(aDestRange
);
3543 // Put some texts in B1:B5.
3544 m_pDoc
->SetString(ScAddress(1,0,0), "A");
3545 m_pDoc
->SetString(ScAddress(1,1,0), "B");
3546 m_pDoc
->SetString(ScAddress(1,2,0), "C");
3547 m_pDoc
->SetString(ScAddress(1,3,0), "D");
3548 m_pDoc
->SetString(ScAddress(1,4,0), "E");
3550 // Set the background color of B1:B5 to blue.
3551 ScPatternAttr
aCellBackColor(m_pDoc
->GetPool());
3552 aCellBackColor
.GetItemSet().Put(SvxBrushItem(COL_BLUE
, ATTR_BACKGROUND
));
3553 m_pDoc
->ApplyPatternAreaTab(1, 0, 1, 4, 0, aCellBackColor
);
3555 // Insert notes to B1:B5.
3556 m_pDoc
->GetOrCreateNote(ScAddress(1,0,0));
3557 m_pDoc
->GetOrCreateNote(ScAddress(1,1,0));
3558 m_pDoc
->GetOrCreateNote(ScAddress(1,2,0));
3559 m_pDoc
->GetOrCreateNote(ScAddress(1,3,0));
3560 m_pDoc
->GetOrCreateNote(ScAddress(1,4,0));
3562 // Prepare a clipboard content interleaved with empty cells.
3563 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3564 aClipDoc
.ResetClip(m_pDoc
, &aMark
);
3565 ScClipParam
aParam(aSrcRange
, false);
3566 aClipDoc
.SetClipParam(aParam
);
3567 aClipDoc
.SetString(ScAddress(0,0,0), "Clip1");
3568 aClipDoc
.SetString(ScAddress(0,2,0), "Clip2");
3569 aClipDoc
.SetString(ScAddress(0,4,0), "Clip3");
3571 // Set the background color of A1:A5 to yellow.
3572 aCellBackColor
.GetItemSet().Put(SvxBrushItem(COL_YELLOW
, ATTR_BACKGROUND
));
3573 aClipDoc
.ApplyPatternAreaTab(0, 0, 0, 4, 0, aCellBackColor
);
3575 CPPUNIT_ASSERT_EQUAL(CELLTYPE_STRING
, aClipDoc
.GetCellType(ScAddress(0,0,0)));
3576 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, aClipDoc
.GetCellType(ScAddress(0,1,0)));
3577 CPPUNIT_ASSERT_EQUAL(CELLTYPE_STRING
, aClipDoc
.GetCellType(ScAddress(0,2,0)));
3578 CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE
, aClipDoc
.GetCellType(ScAddress(0,3,0)));
3579 CPPUNIT_ASSERT_EQUAL(CELLTYPE_STRING
, aClipDoc
.GetCellType(ScAddress(0,4,0)));
3581 // Check the initial condition.
3584 { "A", COL_BLUE
, true },
3585 { "B", COL_BLUE
, true },
3586 { "C", COL_BLUE
, true },
3587 { "D", COL_BLUE
, true },
3588 { "E", COL_BLUE
, true },
3591 bool bRes
= aTest
.checkRange(ScAddress(1,0,0), aChecks
, aChecks
+ SAL_N_ELEMENTS(aChecks
));
3592 CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bRes
);
3595 // Create undo document.
3596 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
3597 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
3598 m_pDoc
->CopyToDocument(aDestRange
, IDF_ALL
, false, pUndoDoc
, &aMark
);
3600 // Paste clipboard content onto A1:A5 but skip empty cells.
3601 bool bSkipEmpty
= true;
3602 m_pDoc
->CopyFromClip(aDestRange
, aMark
, IDF_ALL
, pUndoDoc
, &aClipDoc
, true, false, false, bSkipEmpty
);
3604 // Create redo document.
3605 ScDocument
* pRedoDoc
= new ScDocument(SCDOCMODE_UNDO
);
3606 pRedoDoc
->InitUndo(m_pDoc
, 0, 0);
3607 m_pDoc
->CopyToDocument(aDestRange
, IDF_ALL
, false, pRedoDoc
, &aMark
);
3609 // Create an undo object for this.
3610 ScRefUndoData
* pRefUndoData
= new ScRefUndoData(m_pDoc
);
3611 ScUndoPaste
aUndo(&getDocShell(), aDestRange
, aMark
, pUndoDoc
, pRedoDoc
, IDF_ALL
, pRefUndoData
);
3613 // Check the content after the paste.
3616 { "Clip1", COL_YELLOW
, false },
3617 { "B", COL_BLUE
, true },
3618 { "Clip2", COL_YELLOW
, false },
3619 { "D", COL_BLUE
, true },
3620 { "Clip3", COL_YELLOW
, false },
3623 bool bRes
= aTest
.checkRange(ScAddress(1,0,0), aChecks
, aChecks
+ SAL_N_ELEMENTS(aChecks
));
3624 CPPUNIT_ASSERT_MESSAGE("Check after paste failed.", bRes
);
3627 // Undo, and check the content.
3631 { "A", COL_BLUE
, true },
3632 { "B", COL_BLUE
, true },
3633 { "C", COL_BLUE
, true },
3634 { "D", COL_BLUE
, true },
3635 { "E", COL_BLUE
, true },
3638 bool bRes
= aTest
.checkRange(ScAddress(1,0,0), aChecks
, aChecks
+ SAL_N_ELEMENTS(aChecks
));
3639 CPPUNIT_ASSERT_MESSAGE("Check after undo failed.", bRes
);
3642 // Redo, and check the content again.
3646 { "Clip1", COL_YELLOW
, false },
3647 { "B", COL_BLUE
, true },
3648 { "Clip2", COL_YELLOW
, false },
3649 { "D", COL_BLUE
, true },
3650 { "Clip3", COL_YELLOW
, false },
3653 bool bRes
= aTest
.checkRange(ScAddress(1,0,0), aChecks
, aChecks
+ SAL_N_ELEMENTS(aChecks
));
3654 CPPUNIT_ASSERT_MESSAGE("Check after redo failed.", bRes
);
3657 m_pDoc
->DeleteTab(0);
3660 void Test::testCopyPasteSkipEmpty2()
3662 m_pDoc
->InsertTab(0, "Test");
3664 m_pDoc
->SetString(ScAddress(0,0,0), "A");
3665 m_pDoc
->SetString(ScAddress(2,0,0), "C");
3667 // Copy A1:C1 to clipboard.
3668 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3669 aClipDoc
.ResetClip(m_pDoc
, static_cast<SCTAB
>(0));
3670 copyToClip(m_pDoc
, ScRange(0,0,0,2,0,0), &aClipDoc
);
3672 // Paste to A3 with the skip empty option set. This used to freeze. (fdo#77735)
3673 ScRange
aDestRange(0,2,0,2,2,0);
3675 aMark
.SetMarkArea(aDestRange
);
3676 m_pDoc
->CopyFromClip(aDestRange
, aMark
, IDF_ALL
, NULL
, &aClipDoc
, false, false, true, true);
3678 CPPUNIT_ASSERT_EQUAL(OUString("A"), m_pDoc
->GetString(ScAddress(0,2,0)));
3679 CPPUNIT_ASSERT_MESSAGE("B3 should be empty.", m_pDoc
->GetCellType(ScAddress(1,2,0)) == CELLTYPE_NONE
);
3680 CPPUNIT_ASSERT_EQUAL(OUString("C"), m_pDoc
->GetString(ScAddress(2,2,0)));
3682 m_pDoc
->DeleteTab(0);
3685 void Test::testCopyPasteSkipEmptyConditionalFormatting()
3687 m_pDoc
->InsertTab(0, "Test");
3689 ScRange
aDestRange(0,0,0,1,2,0);
3690 ScRange
aSrcRange(3,3,0,5,4,0);
3693 aMark
.SetMarkArea(aDestRange
);
3695 m_pDoc
->SetValue(0,0,0,1);
3696 m_pDoc
->SetValue(1,0,0,1);
3697 m_pDoc
->SetValue(0,1,0,1);
3698 m_pDoc
->SetValue(0,2,0,1);
3699 m_pDoc
->SetValue(1,2,0,1);
3701 //create conditional formatting for A1:B3
3702 ScConditionalFormatList
* pCondFormatList
= new ScConditionalFormatList();
3703 m_pDoc
->SetCondFormList(pCondFormatList
, 0);
3705 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
3706 pFormat
->SetRange(aDestRange
);
3707 sal_uLong nCondFormatKey
= m_pDoc
->AddCondFormat(pFormat
, 0);
3709 // Prepare a clipboard content interleaved with empty cells.
3710 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3711 aClipDoc
.ResetClip(m_pDoc
, &aMark
);
3712 ScClipParam
aParam(aSrcRange
, false);
3713 aClipDoc
.SetClipParam(aParam
);
3714 aClipDoc
.SetValue(3,3,0,2);
3715 aClipDoc
.SetValue(4,3,0,2);
3716 aClipDoc
.SetValue(4,4,0,2);
3717 aClipDoc
.SetValue(3,5,0,2);
3718 aClipDoc
.SetValue(4,5,0,2);
3720 ScConditionalFormat
* pClipFormat
= new ScConditionalFormat(2, &aClipDoc
);
3721 pClipFormat
->SetRange(aSrcRange
);
3722 aClipDoc
.AddCondFormat(pClipFormat
, 0);
3724 // Create undo document.
3725 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
3726 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
3727 m_pDoc
->CopyToDocument(aDestRange
, IDF_CONTENTS
, false, pUndoDoc
, &aMark
);
3729 // Paste clipboard content onto A1:A5 but skip empty cells.
3730 bool bSkipEmpty
= true;
3731 m_pDoc
->CopyFromClip(aDestRange
, aMark
, IDF_CONTENTS
, pUndoDoc
, &aClipDoc
, true, false, false, bSkipEmpty
);
3733 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
3734 CPPUNIT_ASSERT_EQUAL(size_t(2), pList
->size());
3735 CPPUNIT_ASSERT(m_pDoc
->GetCondFormat(1,1,0));
3736 // empty cell in copy area does not overwrite conditional formatting
3737 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nCondFormatKey
), m_pDoc
->GetCondFormat(1,1,0)->GetKey());
3738 for(SCCOL nCol
= 0; nCol
<= 1; ++nCol
)
3740 for(SCROW nRow
= 0; nRow
<= 2; ++nRow
)
3742 if(nRow
== 1 && nCol
== 1)
3745 CPPUNIT_ASSERT(m_pDoc
->GetCondFormat(nCol
, nRow
, 0));
3746 CPPUNIT_ASSERT(nCondFormatKey
!= m_pDoc
->GetCondFormat(nCol
, nRow
, 0)->GetKey());
3749 m_pDoc
->DeleteTab(0);
3752 void Test::testCutPasteRefUndo()
3754 // Testing scenario: A2 references B2, and B2 gets cut and pasted onto C2,
3755 // which updates A2's formula to reference C2. Then the paste action gets
3756 // undone, which should also undo A2's formula to reference back to B2.
3758 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // turn on auto calc.
3760 m_pDoc
->InsertTab(0, "Test");
3762 // A2 references B2.
3763 m_pDoc
->SetString(ScAddress(0,1,0), "=B2");
3766 aMark
.SelectOneTable(0);
3768 // Set up clip document for cutting of B2.
3769 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3770 aClipDoc
.ResetClip(m_pDoc
, &aMark
);
3771 ScClipParam
aParam(ScAddress(1,1,0), true);
3772 aClipDoc
.SetClipParam(aParam
);
3773 aClipDoc
.SetValue(ScAddress(1,1,0), 12.0);
3775 // Set up undo document for reference update.
3776 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
3777 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
3779 // Do the pasting of 12 into C2. This should update A2 to reference C2.
3780 m_pDoc
->CopyFromClip(ScAddress(2,1,0), aMark
, IDF_CONTENTS
, pUndoDoc
, &aClipDoc
, true, false);
3781 CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc
->GetValue(0,1,0));
3783 if (!checkFormula(*m_pDoc
, ScAddress(0,1,0), "C2"))
3784 CPPUNIT_FAIL("A2 should be referencing C2.");
3786 // At this point, the ref undo document should contain a formula cell at A2 that references B2.
3787 if (!checkFormula(*pUndoDoc
, ScAddress(0,1,0), "B2"))
3788 CPPUNIT_FAIL("A2 in the undo document should be referencing B2.");
3790 ScUndoPaste
aUndo(&getDocShell(), ScRange(ScAddress(2,1,0)), aMark
, pUndoDoc
, NULL
, IDF_CONTENTS
, NULL
, false, NULL
);
3793 // Now A2 should be referencing B2 once again.
3794 if (!checkFormula(*m_pDoc
, ScAddress(0,1,0), "B2"))
3795 CPPUNIT_FAIL("A2 should be referencing B2 after undo.");
3797 m_pDoc
->DeleteTab(0);
3800 void Test::testMoveRefBetweenSheets()
3802 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // turn on auto calc.
3804 m_pDoc
->InsertTab(0, "Test1");
3805 m_pDoc
->InsertTab(1, "Test2");
3807 m_pDoc
->SetValue(ScAddress(0,0,0), 12.0);
3808 m_pDoc
->SetValue(ScAddress(1,0,0), 10.0);
3809 m_pDoc
->SetValue(ScAddress(2,0,0), 8.0);
3810 m_pDoc
->SetString(ScAddress(0,1,0), "=A1");
3811 m_pDoc
->SetString(ScAddress(0,2,0), "=SUM(A1:C1)");
3813 CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
3814 CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
3815 CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
3817 // These formulas should not display the sheet name.
3818 if (!checkFormula(*m_pDoc
, ScAddress(0,1,0), "A1"))
3819 CPPUNIT_FAIL("Wrong formula!");
3820 if (!checkFormula(*m_pDoc
, ScAddress(0,2,0), "SUM(A1:C1)"))
3821 CPPUNIT_FAIL("Wrong formula!");
3823 // Move Test1.A2:A3 to Test2.A2:A3.
3824 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
3825 bool bMoved
= rFunc
.MoveBlock(ScRange(0,1,0,0,2,0), ScAddress(0,1,1), true, true, false, true);
3826 CPPUNIT_ASSERT(bMoved
);
3828 CPPUNIT_ASSERT_MESSAGE("This cell should be empty after the move.", m_pDoc
->GetCellType(ScAddress(0,1,0)) == CELLTYPE_NONE
);
3829 CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc
->GetValue(ScAddress(0,1,1)));
3830 CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc
->GetValue(ScAddress(0,2,1)));
3832 // The reference in the pasted formula should display sheet name after the move.
3833 if (!checkFormula(*m_pDoc
, ScAddress(0,1,1), "Test1.A1"))
3834 CPPUNIT_FAIL("Wrong formula!");
3835 if (!checkFormula(*m_pDoc
, ScAddress(0,2,1), "SUM(Test1.A1:C1)"))
3836 CPPUNIT_FAIL("Wrong formula!");
3838 m_pDoc
->DeleteTab(1);
3839 m_pDoc
->DeleteTab(0);
3842 void Test::testUndoCut()
3844 m_pDoc
->InsertTab(0, "Test");
3846 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // turn on auto calc.
3848 // Insert values into A1:A3.
3849 m_pDoc
->SetValue(ScAddress(0,0,0), 1.0);
3850 m_pDoc
->SetValue(ScAddress(0,1,0), 10.0);
3851 m_pDoc
->SetValue(ScAddress(0,2,0), 100.0);
3854 m_pDoc
->SetString(ScAddress(0,3,0), "=SUM(A1:A3)");
3855 CPPUNIT_ASSERT_EQUAL(111.0, m_pDoc
->GetValue(0,3,0));
3859 ScRange
aRange(0,0,0,0,2,0);
3860 aMark
.SetMarkArea(aRange
);
3861 aMark
.MarkToMulti();
3863 // Set up an undo object for cutting A1:A3.
3864 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
3865 pUndoDoc
->InitUndo(m_pDoc
, 0 ,0);
3866 m_pDoc
->CopyToDocument(aRange
, IDF_ALL
, false, pUndoDoc
);
3867 CPPUNIT_ASSERT_EQUAL( 1.0, pUndoDoc
->GetValue(ScAddress(0,0,0)));
3868 CPPUNIT_ASSERT_EQUAL( 10.0, pUndoDoc
->GetValue(ScAddress(0,1,0)));
3869 CPPUNIT_ASSERT_EQUAL(100.0, pUndoDoc
->GetValue(ScAddress(0,2,0)));
3870 ScUndoCut
aUndo(&getDocShell(), aRange
, aRange
.aEnd
, aMark
, pUndoDoc
);
3872 // "Cut" the selection.
3873 m_pDoc
->DeleteSelection(IDF_ALL
, aMark
);
3874 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(0,3,0)); // The SUM should be zero after the "cut".
3876 // Undo it, and check the result.
3878 CPPUNIT_ASSERT_EQUAL( 1.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
3879 CPPUNIT_ASSERT_EQUAL( 10.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
3880 CPPUNIT_ASSERT_EQUAL(100.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
3881 CPPUNIT_ASSERT_EQUAL(111.0, m_pDoc
->GetValue(0,3,0)); // The SUM value should be back to the original.
3883 // Redo it and check.
3885 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(0,3,0));
3889 CPPUNIT_ASSERT_EQUAL(111.0, m_pDoc
->GetValue(0,3,0));
3891 m_pDoc
->DeleteTab(0);
3894 void Test::testMoveBlock()
3896 m_pDoc
->InsertTab(0, "SheetNotes");
3898 m_pDoc
->SetValue(0, 0, 0, 1);
3899 m_pDoc
->SetString(1, 0, 0, "=A1+1");
3900 m_pDoc
->SetString(2, 0, 0, "test");
3902 // add notes to A1:C1
3903 ScAddress
aAddrA1 (0, 0, 0);
3904 OUString
aHelloA1("Hello world in A1");
3905 ScPostIt
* pNoteA1
= m_pDoc
->GetOrCreateNote(aAddrA1
);
3906 pNoteA1
->SetText(aAddrA1
, aHelloA1
);
3907 ScAddress
aAddrB1 (1, 0, 0);
3908 OUString
aHelloB1("Hello world in B1");
3909 ScPostIt
* pNoteB1
= m_pDoc
->GetOrCreateNote(aAddrB1
);
3910 pNoteB1
->SetText(aAddrB1
, aHelloB1
);
3911 ScAddress
aAddrC1 (2, 0, 0);
3912 OUString
aHelloC1("Hello world in C1");
3913 ScPostIt
* pNoteC1
= m_pDoc
->GetOrCreateNote(aAddrC1
);
3914 pNoteC1
->SetText(aAddrC1
, aHelloC1
);
3915 ScAddress
aAddrD1 (3, 0, 0);
3917 // previous tests on cell note content are ok. this one fails !!! :(
3918 //CPPUNIT_ASSERT_MESSAGE("Note content in B1 before move block", m_pDoc->GetNote(aAddrB1)->GetText() == aHelloB1);
3920 // move notes to B1:D1
3922 ScDocFunc
& rDocFunc
= getDocShell().GetDocFunc();
3923 bool bMoveDone
= rDocFunc
.MoveBlock(ScRange(0, 0 ,0 ,2 ,0 ,0), ScAddress(1, 0, 0), bCut
, false, false, false);
3925 CPPUNIT_ASSERT_MESSAGE("Cells not moved", bMoveDone
);
3927 //check cell content
3928 OUString aString
= m_pDoc
->GetString(3, 0, 0);
3929 CPPUNIT_ASSERT_MESSAGE("Cell D1 should contain: test", aString
== "test");
3930 m_pDoc
->GetFormula(2, 0, 0, aString
);
3931 CPPUNIT_ASSERT_MESSAGE("Cell C1 should contain an updated formula", aString
== "=B1+1");
3932 double fValue
= m_pDoc
->GetValue(aAddrB1
);
3933 ASSERT_DOUBLES_EQUAL_MESSAGE("Cell B1 should contain 1", fValue
, 1);
3935 // cell notes has been moved 1 cell right (event when overlapping)
3936 CPPUNIT_ASSERT_MESSAGE("There should be NO note on A1", !m_pDoc
->HasNote(aAddrA1
));
3937 CPPUNIT_ASSERT_MESSAGE("There should be a note on B1", m_pDoc
->HasNote(aAddrB1
));
3938 CPPUNIT_ASSERT_MESSAGE("There should be a note on C1", m_pDoc
->HasNote(aAddrC1
));
3939 CPPUNIT_ASSERT_MESSAGE("There should be a note on D1", m_pDoc
->HasNote(aAddrD1
));
3940 /* still failing, wrong content ???
3942 sNoteText = m_pDoc->GetNote(aAddrB1)->GetText();
3943 CPPUNIT_ASSERT_MESSAGE("Note content in B1", sNoteText == aHelloA1);
3944 sNoteText = m_pDoc->GetNote(aAddrC1)->GetText();
3945 CPPUNIT_ASSERT_MESSAGE("Note content in C1", sNoteText == aHelloB1);
3946 sNoteText = m_pDoc->GetNote(aAddrD1)->GetText();
3947 CPPUNIT_ASSERT_MESSAGE("Note content in D1", sNoteText == aHelloC1);
3950 m_pDoc
->DeleteTab(0);
3953 void Test::testCopyPasteRelativeFormula()
3955 m_pDoc
->InsertTab(0, "Formula");
3957 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true);
3959 // Insert values to A2 and A4.
3960 m_pDoc
->SetValue(ScAddress(0,1,0), 1);
3961 m_pDoc
->SetValue(ScAddress(0,3,0), 2);
3963 // Insert formula to B4.
3964 m_pDoc
->SetString(ScAddress(1,3,0), "=A4");
3965 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(1,3,0)));
3967 // Select and copy B3:B4 to the clipboard.
3968 ScRange
aRange(1,2,0,1,3,0);
3969 ScClipParam
aClipParam(aRange
, false);
3971 aMark
.SetMarkArea(aRange
);
3972 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
3973 m_pDoc
->CopyToClip(aClipParam
, &aClipDoc
, &aMark
);
3975 // Paste it to B1:B2.
3976 InsertDeleteFlags nFlags
= IDF_ALL
;
3977 ScRange
aDestRange(1,0,0,1,1,0);
3978 aMark
.SetMarkArea(aDestRange
);
3979 m_pDoc
->CopyFromClip(aDestRange
, aMark
, nFlags
, NULL
, &aClipDoc
);
3981 // B2 references A2, so the value should be 1.
3982 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(1,1,0)));
3984 // Clear content and start over.
3985 clearSheet(m_pDoc
, 0);
3986 clearSheet(&aClipDoc
, 0);
3988 // Insert a single formula cell in A1.
3989 m_pDoc
->SetString(ScAddress(0,0,0), "=ROW()");
3990 const ScFormulaCell
* pFC
= m_pDoc
->GetFormulaCell(ScAddress(0,0,0));
3991 CPPUNIT_ASSERT(pFC
);
3992 CPPUNIT_ASSERT(!pFC
->IsShared()); // single formula cell is never shared.
3994 // Copy A1 to clipboard.
3995 aClipParam
= ScClipParam(ScAddress(0,0,0), false);
3996 m_pDoc
->CopyToClip(aClipParam
, &aClipDoc
, &aMark
);
3998 pFC
= aClipDoc
.GetFormulaCell(ScAddress(0,0,0));
3999 CPPUNIT_ASSERT(pFC
);
4000 CPPUNIT_ASSERT(!pFC
->IsShared());
4003 aDestRange
= ScRange(0,2,0,0,2,0);
4004 aMark
.SetMarkArea(aDestRange
);
4005 m_pDoc
->CopyFromClip(aDestRange
, aMark
, nFlags
, NULL
, &aClipDoc
);
4007 pFC
= m_pDoc
->GetFormulaCell(ScAddress(0,2,0));
4008 CPPUNIT_ASSERT(pFC
);
4009 CPPUNIT_ASSERT(!pFC
->IsShared());
4011 // Delete A3 and make sure it doesn't crash (see fdo#76132).
4012 clearRange(m_pDoc
, ScAddress(0,2,0));
4013 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(0,2,0)) == CELLTYPE_NONE
);
4015 m_pDoc
->DeleteTab(0);
4018 void Test::testCopyPasteRepeatOneFormula()
4020 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true);
4022 m_pDoc
->InsertTab(0, "Test");
4024 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
4027 // Insert values in A1:B10.
4028 for (SCROW i
= 0; i
< 10; ++i
)
4030 m_pDoc
->SetValue(ScAddress(0,i
,0), i
+1.0); // column A
4031 m_pDoc
->SetValue(ScAddress(1,i
,0), (i
+1.0)*10.0); // column B
4034 // Insert a formula in C1.
4035 ScAddress
aPos(2,0,0); // C1
4036 m_pDoc
->SetString(aPos
, "=SUM(A1:B1)");
4037 CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc
->GetValue(aPos
));
4039 // This check makes only sense if group listeners are activated.
4040 #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER
4041 // At this point, there should be only one normal area listener listening
4043 ScRange
aWholeSheet(0,0,0,MAXCOL
,MAXROW
,0);
4044 ScBroadcastAreaSlotMachine
* pBASM
= m_pDoc
->GetBASM();
4045 CPPUNIT_ASSERT(pBASM
);
4046 std::vector
<sc::AreaListener
> aListeners
= pBASM
->GetAllListeners(aWholeSheet
, sc::AreaInside
);
4047 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aListeners
.size());
4048 const sc::AreaListener
* pListener
= &aListeners
[0];
4049 CPPUNIT_ASSERT_EQUAL(ScRange(0,0,0,1,0,0), pListener
->maArea
);
4050 CPPUNIT_ASSERT_MESSAGE("This listener shouldn't be a group listener.", !pListener
->mbGroupListening
);
4053 // Copy C1 to clipboard.
4054 ScClipParam
aClipParam(aPos
, false);
4055 aMark
.SetMarkArea(aPos
);
4056 m_pDoc
->CopyToClip(aClipParam
, &aClipDoc
, &aMark
);
4058 // Paste it to C2:C10.
4059 InsertDeleteFlags nFlags
= IDF_CONTENTS
;
4060 ScRange
aDestRange(2,1,0,2,9,0);
4061 aMark
.SetMarkArea(aDestRange
);
4062 m_pDoc
->CopyFromClip(aDestRange
, aMark
, nFlags
, NULL
, &aClipDoc
);
4064 // Make sure C1:C10 are grouped.
4065 const ScFormulaCell
* pFC
= m_pDoc
->GetFormulaCell(aPos
);
4066 CPPUNIT_ASSERT(pFC
);
4067 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(10), pFC
->GetSharedLength());
4069 // Check the formula results.
4070 for (SCROW i
= 0; i
< 10; ++i
)
4072 double fExpected
= (i
+1.0)*11.0;
4073 CPPUNIT_ASSERT_EQUAL(fExpected
, m_pDoc
->GetValue(ScAddress(2,i
,0)));
4076 // This check makes only sense if group listeners are activated.
4077 #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER
4078 // At this point, there should only be one area listener and it should be
4079 // a group listener listening on A1:B10.
4080 aListeners
= pBASM
->GetAllListeners(aWholeSheet
, sc::AreaInside
);
4081 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aListeners
.size());
4082 pListener
= &aListeners
[0];
4083 CPPUNIT_ASSERT_EQUAL(ScRange(0,0,0,1,9,0), pListener
->maArea
);
4084 CPPUNIT_ASSERT_MESSAGE("This listener should be a group listener.", pListener
->mbGroupListening
);
4087 // Insert a new row at row 1.
4088 ScRange
aRowOne(0,0,0,MAXCOL
,0,0);
4089 aMark
.SetMarkArea(aRowOne
);
4090 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
4091 rFunc
.InsertCells(aRowOne
, &aMark
, INS_INSROWS
, true, true, false);
4093 CPPUNIT_ASSERT_MESSAGE("C1 should be empty.", m_pDoc
->GetCellType(ScAddress(2,0,0)) == CELLTYPE_NONE
);
4095 // This check makes only sense if group listeners are activated.
4096 #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER
4097 // Make there we only have one group area listener listening on A2:B11.
4098 aListeners
= pBASM
->GetAllListeners(aWholeSheet
, sc::AreaInside
);
4099 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aListeners
.size());
4100 pListener
= &aListeners
[0];
4101 CPPUNIT_ASSERT_EQUAL(ScRange(0,1,0,1,10,0), pListener
->maArea
);
4102 CPPUNIT_ASSERT_MESSAGE("This listener should be a group listener.", pListener
->mbGroupListening
);
4105 // Check the formula results.
4106 for (SCROW i
= 0; i
< 10; ++i
)
4108 double fExpected
= (i
+1.0)*11.0;
4109 CPPUNIT_ASSERT_EQUAL(fExpected
, m_pDoc
->GetValue(ScAddress(2,i
+1,0)));
4112 // Delete row at row 1 to shift the cells up.
4113 rFunc
.DeleteCells(aRowOne
, &aMark
, DEL_DELROWS
, true, true);
4115 // Check the formula results again.
4116 for (SCROW i
= 0; i
< 10; ++i
)
4118 double fExpected
= (i
+1.0)*11.0;
4119 CPPUNIT_ASSERT_EQUAL(fExpected
, m_pDoc
->GetValue(ScAddress(2,i
,0)));
4122 // This check makes only sense if group listeners are activated.
4123 #if !defined(USE_FORMULA_GROUP_LISTENER) || USE_FORMULA_GROUP_LISTENER
4124 // Check the group area listener again to make sure it's listening on A1:B10 once again.
4125 aListeners
= pBASM
->GetAllListeners(aWholeSheet
, sc::AreaInside
);
4126 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aListeners
.size());
4127 pListener
= &aListeners
[0];
4128 CPPUNIT_ASSERT_EQUAL(ScRange(0,0,0,1,9,0), pListener
->maArea
);
4129 CPPUNIT_ASSERT_MESSAGE("This listener should be a group listener.", pListener
->mbGroupListening
);
4132 m_pDoc
->DeleteTab(0);
4135 void Test::testMergedCells()
4137 //test merge and unmerge
4138 //TODO: an undo/redo test for this would be a good idea
4139 m_pDoc
->InsertTab(0, "Sheet1");
4140 m_pDoc
->DoMerge(0, 1, 1, 3, 3, false);
4143 m_pDoc
->ExtendMerge( 1, 1, nEndCol
, nEndRow
, 0, false);
4144 CPPUNIT_ASSERT_MESSAGE("did not merge cells", nEndCol
== 3 && nEndRow
== 3);
4145 ScRange
aRange(0,2,0,MAXCOL
,2,0);
4147 aMark
.SetMarkArea(aRange
);
4148 getDocShell().GetDocFunc().InsertCells(aRange
, &aMark
, INS_INSROWS
, true, true);
4149 m_pDoc
->ExtendMerge(1, 1, nEndCol
, nEndRow
, 0, false);
4150 CPPUNIT_ASSERT_MESSAGE("did not increase merge area", nEndCol
== 3 && nEndRow
== 4);
4151 m_pDoc
->DeleteTab(0);
4154 void Test::testRenameTable()
4156 //test set rename table
4157 //TODO: set name1 and name2 and do an undo to check if name 1 is set now
4158 //TODO: also check if new name for table is same as another table
4160 m_pDoc
->InsertTab(0, "Sheet1");
4161 m_pDoc
->InsertTab(1, "Sheet2");
4163 //test case 1 , rename table2 to sheet 1, it should return error
4164 OUString nameToSet
= "Sheet1";
4165 ScDocFunc
& rDocFunc
= getDocShell().GetDocFunc();
4166 CPPUNIT_ASSERT_MESSAGE("name same as another table is being set", !rDocFunc
.RenameTable(1,nameToSet
,false,true) );
4168 //test case 2 , simple rename to check name
4169 nameToSet
= "test1";
4170 getDocShell().GetDocFunc().RenameTable(0,nameToSet
,false,true);
4171 OUString nameJustSet
;
4172 m_pDoc
->GetName(0,nameJustSet
);
4173 CPPUNIT_ASSERT_MESSAGE("table not renamed", nameToSet
== nameJustSet
);
4175 //test case 3 , rename again
4177 m_pDoc
->GetName(0,anOldName
);
4179 nameToSet
= "test2";
4180 rDocFunc
.RenameTable(0,nameToSet
,false,true);
4181 m_pDoc
->GetName(0,nameJustSet
);
4182 CPPUNIT_ASSERT_MESSAGE("table not renamed", nameToSet
== nameJustSet
);
4184 //test case 4 , check if undo works
4185 SfxUndoAction
* pUndo
= new ScUndoRenameTab(&getDocShell(),0,anOldName
,nameToSet
);
4187 m_pDoc
->GetName(0,nameJustSet
);
4188 CPPUNIT_ASSERT_MESSAGE("the correct name is not set after undo", nameJustSet
== anOldName
);
4191 m_pDoc
->GetName(0,nameJustSet
);
4192 CPPUNIT_ASSERT_MESSAGE("the correct color is not set after redo", nameJustSet
== nameToSet
);
4194 m_pDoc
->DeleteTab(0);
4195 m_pDoc
->DeleteTab(1);
4198 void Test::testSetBackgroundColor()
4200 //test set background color
4201 //TODO: set color1 and set color2 and do an undo to check if color1 is set now.
4203 m_pDoc
->InsertTab(0, "Sheet1");
4207 aColor
=Color(COL_YELLOW
);
4208 getDocShell().GetDocFunc().SetTabBgColor(0,aColor
,false, true);
4209 CPPUNIT_ASSERT_MESSAGE("the correct color is not set",
4210 m_pDoc
->GetTabBgColor(0) == aColor
);
4212 Color aOldTabBgColor
=m_pDoc
->GetTabBgColor(0);
4213 aColor
.SetColor(COL_BLUE
);//set BLUE
4214 getDocShell().GetDocFunc().SetTabBgColor(0,aColor
,false, true);
4215 CPPUNIT_ASSERT_MESSAGE("the correct color is not set the second time",
4216 m_pDoc
->GetTabBgColor(0) == aColor
);
4218 //now check for undo
4219 SfxUndoAction
* pUndo
= new ScUndoTabColor(&getDocShell(), 0, aOldTabBgColor
, aColor
);
4221 CPPUNIT_ASSERT_MESSAGE("the correct color is not set after undo", m_pDoc
->GetTabBgColor(0)== aOldTabBgColor
);
4223 CPPUNIT_ASSERT_MESSAGE("the correct color is not set after undo", m_pDoc
->GetTabBgColor(0)== aColor
);
4224 m_pDoc
->DeleteTab(0);
4227 void Test::testUpdateReference()
4229 //test that formulas are correctly updated during sheet delete
4230 //TODO: add tests for relative references, updating of named ranges, ...
4231 m_pDoc
->InsertTab(0, "Sheet1");
4232 m_pDoc
->InsertTab(1, "Sheet2");
4233 m_pDoc
->InsertTab(2, "Sheet3");
4234 m_pDoc
->InsertTab(3, "Sheet4");
4236 m_pDoc
->SetValue(0,0,2, 1);
4237 m_pDoc
->SetValue(1,0,2, 2);
4238 m_pDoc
->SetValue(1,1,3, 4);
4239 m_pDoc
->SetString(2,0,2, "=A1+B1");
4240 m_pDoc
->SetString(2,1,2, "=Sheet4.B2+A1");
4243 m_pDoc
->GetValue(2,0,2, aValue
);
4244 ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue
, 3);
4245 m_pDoc
->GetValue(2,1,2, aValue
);
4246 ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue
, 5);
4248 //test deleting both sheets: one is not directly before the sheet, the other one is
4249 m_pDoc
->DeleteTab(0);
4250 m_pDoc
->GetValue(2,0,1, aValue
);
4251 ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue
, 3);
4252 m_pDoc
->GetValue(2,1,1, aValue
);
4253 ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue
, 5);
4255 m_pDoc
->DeleteTab(0);
4256 m_pDoc
->GetValue(2,0,0, aValue
);
4257 ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue
, 3);
4258 m_pDoc
->GetValue(2,1,0, aValue
);
4259 ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue
, 5);
4261 //test adding two sheets
4262 m_pDoc
->InsertTab(0, "Sheet2");
4263 m_pDoc
->GetValue(2,0,1, aValue
);
4264 ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue
, 3);
4265 m_pDoc
->GetValue(2,1,1, aValue
);
4266 ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue
, 5);
4268 m_pDoc
->InsertTab(0, "Sheet1");
4269 m_pDoc
->GetValue(2,0,2, aValue
);
4270 ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue
, 3);
4271 m_pDoc
->GetValue(2,1,2, aValue
);
4272 ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue
, 5);
4274 //test new DeleteTabs/InsertTabs methods
4275 m_pDoc
->DeleteTabs(0, 2);
4276 m_pDoc
->GetValue(2, 0, 0, aValue
);
4277 ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue
, 3);
4278 m_pDoc
->GetValue(2, 1, 0, aValue
);
4279 ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue
, 5);
4281 std::vector
<OUString
> aSheets
;
4282 aSheets
.push_back("Sheet1");
4283 aSheets
.push_back("Sheet2");
4284 m_pDoc
->InsertTabs(0, aSheets
, false, true);
4285 m_pDoc
->GetValue(2, 0, 2, aValue
);
4287 m_pDoc
->GetFormula(2,0,2, aFormula
);
4289 ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue
, 3);
4290 m_pDoc
->GetValue(2, 1, 2, aValue
);
4291 ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue
, 5);
4293 m_pDoc
->DeleteTab(3);
4294 m_pDoc
->DeleteTab(2);
4295 m_pDoc
->DeleteTab(1);
4296 m_pDoc
->DeleteTab(0);
4299 void Test::testSearchCells()
4301 m_pDoc
->InsertTab(0, "Test");
4303 m_pDoc
->SetString(ScAddress(0,0,0), "A");
4304 m_pDoc
->SetString(ScAddress(0,1,0), "B");
4305 m_pDoc
->SetString(ScAddress(0,2,0), "A");
4307 m_pDoc
->SetString(ScAddress(0,4,0), "A");
4308 m_pDoc
->SetString(ScAddress(0,5,0), "B");
4309 m_pDoc
->SetString(ScAddress(0,6,0), "C");
4311 SvxSearchItem
aItem(SID_SEARCH_ITEM
);
4312 aItem
.SetSearchString(OUString("A"));
4313 aItem
.SetCommand(SvxSearchCmd::FIND_ALL
);
4314 ScMarkData aMarkData
;
4315 aMarkData
.SelectOneTable(0);
4319 ScRangeList aMatchedRanges
;
4321 bool bSuccess
= m_pDoc
->SearchAndReplace(aItem
, nCol
, nRow
, nTab
, aMarkData
, aMatchedRanges
, aUndoStr
);
4323 CPPUNIT_ASSERT_MESSAGE("Search And Replace should succeed", bSuccess
);
4324 CPPUNIT_ASSERT_MESSAGE("There should be exactly 3 matching cells.", aMatchedRanges
.size() == 3);
4325 ScAddress
aHit(0,0,0);
4326 CPPUNIT_ASSERT_MESSAGE("A1 should be inside the matched range.", aMatchedRanges
.In(aHit
));
4328 CPPUNIT_ASSERT_MESSAGE("A3 should be inside the matched range.", aMatchedRanges
.In(aHit
));
4330 CPPUNIT_ASSERT_MESSAGE("A5 should be inside the matched range.", aMatchedRanges
.In(aHit
));
4332 m_pDoc
->DeleteTab(0);
4335 void Test::testFormulaPosition()
4337 m_pDoc
->InsertTab(0, "Test");
4339 ScAddress
aPos(0,0,0); // A1
4340 m_pDoc
->SetString(aPos
, "=ROW()");
4341 aPos
.IncRow(); // A2
4342 m_pDoc
->SetString(aPos
, "=ROW()");
4343 aPos
.SetRow(3); // A4;
4344 m_pDoc
->SetString(aPos
, "=ROW()");
4347 SCROW aRows
[] = { 0, 1, 3 };
4348 bool bRes
= checkFormulaPositions(*m_pDoc
, aPos
.Tab(), aPos
.Col(), aRows
, SAL_N_ELEMENTS(aRows
));
4349 CPPUNIT_ASSERT(bRes
);
4352 m_pDoc
->InsertRow(0,0,0,0,1,5); // Insert 5 rows at A2.
4354 SCROW aRows
[] = { 0, 6, 8 };
4355 bool bRes
= checkFormulaPositions(*m_pDoc
, aPos
.Tab(), aPos
.Col(), aRows
, SAL_N_ELEMENTS(aRows
));
4356 CPPUNIT_ASSERT(bRes
);
4359 m_pDoc
->DeleteTab(0);
4364 bool hasRange(const std::vector
<ScTokenRef
>& rRefTokens
, const ScRange
& rRange
, const ScAddress
& rPos
)
4366 std::vector
<ScTokenRef
>::const_iterator it
= rRefTokens
.begin(), itEnd
= rRefTokens
.end();
4367 for (; it
!= itEnd
; ++it
)
4369 const ScTokenRef
& p
= *it
;
4370 if (!ScRefTokenHelper::isRef(p
) || ScRefTokenHelper::isExternalRef(p
))
4373 switch (p
->GetType())
4375 case formula::svSingleRef
:
4377 ScSingleRefData aData
= *p
->GetSingleRef();
4378 if (rRange
.aStart
!= rRange
.aEnd
)
4381 ScAddress aThis
= aData
.toAbs(rPos
);
4382 if (aThis
== rRange
.aStart
)
4386 case formula::svDoubleRef
:
4388 ScComplexRefData aData
= *p
->GetDoubleRef();
4389 ScRange aThis
= aData
.toAbs(rPos
);
4390 if (aThis
== rRange
)
4403 void Test::testJumpToPrecedentsDependents()
4405 // Precedent is another cell that the cell references, while dependent is
4406 // another cell that references it.
4407 m_pDoc
->InsertTab(0, "Test");
4409 m_pDoc
->SetString(2, 0, 0, "=A1+A2+B3"); // C1
4410 m_pDoc
->SetString(2, 1, 0, "=A1"); // C2
4413 std::vector
<ScTokenRef
> aRefTokens
;
4414 ScDocFunc
& rDocFunc
= getDocShell().GetDocFunc();
4417 // C1's precedent should be A1:A2,B3.
4418 ScAddress
aC1(2, 0, 0);
4419 ScRangeList
aRange(aC1
);
4420 rDocFunc
.DetectiveCollectAllPreds(aRange
, aRefTokens
);
4421 CPPUNIT_ASSERT_MESSAGE("A1:A2 should be a precedent of C1.",
4422 hasRange(aRefTokens
, ScRange(0, 0, 0, 0, 1, 0), aC1
));
4423 CPPUNIT_ASSERT_MESSAGE("B3 should be a precedent of C1.",
4424 hasRange(aRefTokens
, ScRange(1, 2, 0), aC1
));
4428 // C2's precedent should be A1 only.
4429 ScAddress
aC2(2, 1, 0);
4430 ScRangeList
aRange(aC2
);
4431 rDocFunc
.DetectiveCollectAllPreds(aRange
, aRefTokens
);
4432 CPPUNIT_ASSERT_EQUAL_MESSAGE("there should only be one reference token.",
4433 aRefTokens
.size(), static_cast<size_t>(1));
4434 CPPUNIT_ASSERT_MESSAGE("A1 should be a precedent of C1.",
4435 hasRange(aRefTokens
, ScRange(0, 0, 0), aC2
));
4439 // A1's dependent should be C1:C2.
4440 ScAddress
aA1(0, 0, 0);
4441 ScRangeList
aRange(aA1
);
4442 rDocFunc
.DetectiveCollectAllSuccs(aRange
, aRefTokens
);
4443 CPPUNIT_ASSERT_MESSAGE("C1:C2 should be the only dependent of A1.",
4444 aRefTokens
.size() == 1 && hasRange(aRefTokens
, ScRange(2, 0, 0, 2, 1, 0), aA1
));
4447 m_pDoc
->DeleteTab(0);
4450 void Test::testAutoFill()
4452 m_pDoc
->InsertTab(0, "test");
4454 m_pDoc
->SetValue(0,0,0,1);
4456 ScMarkData aMarkData
;
4457 aMarkData
.SelectTable(0, true);
4459 m_pDoc
->Fill( 0, 0, 0, 0, NULL
, aMarkData
, 5);
4460 for (SCROW i
= 0; i
< 6; ++i
)
4461 ASSERT_DOUBLES_EQUAL(static_cast<double>(i
+1.0), m_pDoc
->GetValue(0, i
, 0));
4463 // check that hidden rows are not affected by autofill
4464 // set values for hidden rows
4465 m_pDoc
->SetValue(0,1,0,10);
4466 m_pDoc
->SetValue(0,2,0,10);
4468 m_pDoc
->SetRowHidden(1, 2, 0, true);
4469 m_pDoc
->Fill( 0, 0, 0, 0, NULL
, aMarkData
, 8);
4471 ASSERT_DOUBLES_EQUAL(10.0, m_pDoc
->GetValue(0,1,0));
4472 ASSERT_DOUBLES_EQUAL(10.0, m_pDoc
->GetValue(0,2,0));
4473 for (SCROW i
= 3; i
< 8; ++i
)
4474 ASSERT_DOUBLES_EQUAL(static_cast<double>(i
-1.0), m_pDoc
->GetValue(0, i
, 0));
4476 m_pDoc
->Fill( 0, 0, 0, 8, NULL
, aMarkData
, 5, FILL_TO_RIGHT
);
4477 for (SCCOL i
= 0; i
< 5; ++i
)
4479 for(SCROW j
= 0; j
< 8; ++j
)
4483 ASSERT_DOUBLES_EQUAL(static_cast<double>(j
-1+i
), m_pDoc
->GetValue(i
, j
, 0));
4487 ASSERT_DOUBLES_EQUAL(static_cast<double>(i
+1), m_pDoc
->GetValue(i
, 0, 0));
4489 else if (j
== 1 || j
== 2)
4492 ASSERT_DOUBLES_EQUAL(10.0, m_pDoc
->GetValue(0,j
,0));
4494 ASSERT_DOUBLES_EQUAL(0.0, m_pDoc
->GetValue(i
,j
,0));
4499 // test auto fill user data lists
4500 m_pDoc
->SetString( 0, 100, 0, "January" );
4501 m_pDoc
->Fill( 0, 100, 0, 100, NULL
, aMarkData
, 2, FILL_TO_BOTTOM
, FILL_AUTO
);
4502 OUString aTestValue
= m_pDoc
->GetString( 0, 101, 0 );
4503 CPPUNIT_ASSERT_EQUAL( aTestValue
, OUString("February") );
4504 aTestValue
= m_pDoc
->GetString( 0, 102, 0 );
4505 CPPUNIT_ASSERT_EQUAL( aTestValue
, OUString("March") );
4507 // test that two same user data list entries will not result in incremental fill
4508 m_pDoc
->SetString( 0, 101, 0, "January" );
4509 m_pDoc
->Fill( 0, 100, 0, 101, NULL
, aMarkData
, 2, FILL_TO_BOTTOM
, FILL_AUTO
);
4510 for ( SCROW i
= 102; i
<= 103; ++i
)
4512 aTestValue
= m_pDoc
->GetString( 0, i
, 0 );
4513 CPPUNIT_ASSERT_EQUAL( aTestValue
, OUString("January") );
4516 // Clear column A for a new test.
4517 clearRange(m_pDoc
, ScRange(0,0,0,0,MAXROW
,0));
4518 m_pDoc
->SetRowHidden(0, MAXROW
, 0, false); // Show all rows.
4520 // Fill A1:A6 with 1,2,3,4,5,6.
4521 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
4522 m_pDoc
->SetValue(ScAddress(0,0,0), 1.0);
4523 ScRange
aRange(0,0,0,0,5,0);
4524 aMarkData
.SetMarkArea(aRange
);
4525 rFunc
.FillSeries(aRange
, &aMarkData
, FILL_TO_BOTTOM
, FILL_AUTO
, FILL_DAY
, MAXDOUBLE
, 1.0, MAXDOUBLE
, true, true);
4526 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
4527 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
4528 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
4529 CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc
->GetValue(ScAddress(0,3,0)));
4530 CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc
->GetValue(ScAddress(0,4,0)));
4531 CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc
->GetValue(ScAddress(0,5,0)));
4533 // Undo should clear the area except for the top cell.
4534 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
4535 CPPUNIT_ASSERT(pUndoMgr
);
4538 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
4539 for (SCROW i
= 1; i
<= 5; ++i
)
4540 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(0,i
,0)) == CELLTYPE_NONE
);
4542 // Redo should put the serial values back in.
4544 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
4545 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
4546 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
4547 CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc
->GetValue(ScAddress(0,3,0)));
4548 CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc
->GetValue(ScAddress(0,4,0)));
4549 CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc
->GetValue(ScAddress(0,5,0)));
4551 // test that filling formulas vertically up does the right thing
4552 for(SCROW nRow
= 0; nRow
< 10; ++nRow
)
4553 m_pDoc
->SetValue(100, 100 + nRow
, 0, 1);
4555 m_pDoc
->SetString(100, 110, 0, "=A111");
4557 m_pDoc
->Fill(100, 110, 100, 110, NULL
, aMarkData
, 10, FILL_TO_TOP
, FILL_AUTO
);
4558 for(SCROW nRow
= 110; nRow
>= 100; --nRow
)
4560 OUString aExpected
= "=A" + OUString::number(nRow
+1);
4562 m_pDoc
->GetFormula(100, nRow
, 0, aFormula
);
4563 CPPUNIT_ASSERT_EQUAL(aExpected
, aFormula
);
4566 m_pDoc
->DeleteTab(0);
4569 void Test::testAutoFillSimple()
4571 m_pDoc
->InsertTab(0, "test");
4573 m_pDoc
->SetValue(0, 0, 0, 1);
4574 m_pDoc
->SetString(0, 1, 0, "=10");
4576 ScMarkData aMarkData
;
4577 aMarkData
.SelectTable(0, true);
4579 m_pDoc
->Fill( 0, 0, 0, 1, NULL
, aMarkData
, 6, FILL_TO_BOTTOM
, FILL_AUTO
);
4581 for(SCROW nRow
= 0; nRow
< 8; ++nRow
)
4585 double nVal
= m_pDoc
->GetValue(0, nRow
, 0);
4586 CPPUNIT_ASSERT_EQUAL((nRow
+2)/2.0, nVal
);
4590 OString aMsg
= OString("wrong value in row: ") + OString::number(nRow
);
4591 double nVal
= m_pDoc
->GetValue(0, nRow
, 0);
4592 CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg
.getStr(), 10.0, nVal
);
4596 m_pDoc
->DeleteTab(0);
4599 void Test::testCopyPasteFormulas()
4601 m_pDoc
->InsertTab(0, "Sheet1");
4602 m_pDoc
->InsertTab(1, "Sheet2");
4604 m_pDoc
->SetString(0,0,0, "=COLUMN($A$1)");
4605 m_pDoc
->SetString(0,1,0, "=$A$1+B2" );
4606 m_pDoc
->SetString(0,2,0, "=$Sheet2.A1");
4607 m_pDoc
->SetString(0,3,0, "=$Sheet2.$A$1");
4608 m_pDoc
->SetString(0,4,0, "=$Sheet2.A$1");
4610 // to prevent ScEditableTester in ScDocFunc::MoveBlock
4611 ASSERT_DOUBLES_EQUAL(m_pDoc
->GetValue(0,0,0), 1.0);
4612 ASSERT_DOUBLES_EQUAL(m_pDoc
->GetValue(0,1,0), 1.0);
4613 ScDocFunc
& rDocFunc
= getDocShell().GetDocFunc();
4614 bool bMoveDone
= rDocFunc
.MoveBlock(ScRange(0,0,0,0,4,0), ScAddress( 10, 10, 0), false, false, false, true);
4616 // check that moving was successful, mainly for editable tester
4617 CPPUNIT_ASSERT(bMoveDone
);
4618 ASSERT_DOUBLES_EQUAL(m_pDoc
->GetValue(10,10,0), 1.0);
4619 ASSERT_DOUBLES_EQUAL(m_pDoc
->GetValue(10,11,0), 1.0);
4621 m_pDoc
->GetFormula(10,10,0, aFormula
);
4622 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=COLUMN($A$1)"));
4623 m_pDoc
->GetFormula(10,11,0, aFormula
);
4624 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=$A$1+L12"));
4625 m_pDoc
->GetFormula(10,12,0, aFormula
);
4626 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=$Sheet2.K11"));
4627 m_pDoc
->GetFormula(10,13,0, aFormula
);
4628 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=$Sheet2.$A$1"));
4629 m_pDoc
->GetFormula(10,14,0, aFormula
);
4630 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=$Sheet2.K$1"));
4633 void Test::testCopyPasteFormulasExternalDoc()
4635 OUString
aDocName("file:///source.fake");
4636 SfxMedium
* pMedium
= new SfxMedium(aDocName
, STREAM_STD_READWRITE
);
4637 getDocShell().DoInitNew(pMedium
);
4638 m_pDoc
= &getDocShell().GetDocument();
4640 ScDocShellRef xExtDocSh
= new ScDocShell
;
4641 OUString
aExtDocName("file:///extdata.fake");
4642 OUString
aExtSh1Name("ExtSheet1");
4643 OUString
aExtSh2Name("ExtSheet2");
4644 SfxMedium
* pMed
= new SfxMedium(aExtDocName
, STREAM_STD_READWRITE
);
4645 xExtDocSh
->DoInitNew(pMed
);
4646 CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
4647 findLoadedDocShellByName(aExtDocName
) != NULL
);
4649 ScDocument
& rExtDoc
= xExtDocSh
->GetDocument();
4650 rExtDoc
.InsertTab(0, aExtSh1Name
);
4651 rExtDoc
.InsertTab(1, aExtSh2Name
);
4653 m_pDoc
->InsertTab(0, "Sheet1");
4654 m_pDoc
->InsertTab(1, "Sheet2");
4656 m_pDoc
->SetString(0,0,0, "=COLUMN($A$1)");
4657 m_pDoc
->SetString(0,1,0, "=$A$1+B2" );
4658 m_pDoc
->SetString(0,2,0, "=$Sheet2.A1");
4659 m_pDoc
->SetString(0,3,0, "=$Sheet2.$A$1");
4660 m_pDoc
->SetString(0,4,0, "=$Sheet2.A$1");
4661 m_pDoc
->SetString(0,5,0, "=$Sheet1.$A$1");
4663 ScRange
aRange(0,0,0,0,5,0);
4664 ScClipParam
aClipParam(aRange
, false);
4666 aMark
.SetMarkArea(aRange
);
4667 ScDocument
* pClipDoc
= new ScDocument(SCDOCMODE_CLIP
);
4668 m_pDoc
->CopyToClip(aClipParam
, pClipDoc
, &aMark
);
4670 InsertDeleteFlags nFlags
= IDF_ALL
;
4671 aRange
= ScRange(1,1,1,1,6,1);
4672 ScMarkData aMarkData2
;
4673 aMarkData2
.SetMarkArea(aRange
);
4674 rExtDoc
.CopyFromClip(aRange
, aMarkData2
, nFlags
, NULL
, pClipDoc
);
4677 rExtDoc
.GetFormula(1,1,1, aFormula
);
4678 //adjust absolute refs pointing to the copy area
4679 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=COLUMN($B$2)"));
4680 rExtDoc
.GetFormula(1,2,1, aFormula
);
4681 //adjust absolute refs and keep relative refs
4682 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=$B$2+C3"));
4683 rExtDoc
.GetFormula(1,3,1, aFormula
);
4684 // make absolute sheet refs external refs
4685 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("='file:///source.fake'#$Sheet2.B2"));
4686 rExtDoc
.GetFormula(1,4,1, aFormula
);
4687 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("='file:///source.fake'#$Sheet2.$A$1"));
4688 rExtDoc
.GetFormula(1,5,1, aFormula
);
4689 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("='file:///source.fake'#$Sheet2.B$1"));
4690 rExtDoc
.GetFormula(1,6,1, aFormula
);
4691 CPPUNIT_ASSERT_EQUAL(aFormula
, OUString("=$ExtSheet2.$B$2"));
4693 xExtDocSh
->DoClose();
4696 void Test::testFindAreaPosVertical()
4698 const char* aData
[][3] = {
4708 m_pDoc
->InsertTab(0, "Test1");
4709 clearRange( m_pDoc
, ScRange(0, 0, 0, 1, SAL_N_ELEMENTS(aData
), 0));
4710 ScAddress
aPos(0,0,0);
4711 ScRange aDataRange
= insertRangeData( m_pDoc
, aPos
, aData
, SAL_N_ELEMENTS(aData
));
4712 CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange
.aStart
== aPos
);
4714 m_pDoc
->SetRowHidden(4,4,0,true);
4715 bool bHidden
= m_pDoc
->RowHidden(4,0);
4716 CPPUNIT_ASSERT(bHidden
);
4720 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4722 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(1), nRow
);
4723 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(0), nCol
);
4725 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4727 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(2), nRow
);
4728 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(0), nCol
);
4730 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4732 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(5), nRow
);
4733 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(0), nCol
);
4735 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4737 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(6), nRow
);
4738 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(0), nCol
);
4740 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4742 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(MAXROW
), nRow
);
4743 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(0), nCol
);
4748 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4750 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(3), nRow
);
4751 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(1), nCol
);
4753 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_DOWN
);
4755 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(6), nRow
);
4756 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(1), nCol
);
4760 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_UP
);
4761 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(0), nRow
);
4762 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(2), nCol
);
4764 m_pDoc
->DeleteTab(0);
4767 void Test::testFindAreaPosColRight()
4769 const char* aData
[][7] = {
4770 { "", "1", "1", "", "1", "1", "1" },
4771 { "", "", "1", "1", "1", "", "1" }, };
4773 m_pDoc
->InsertTab(0, "test1");
4774 clearRange( m_pDoc
, ScRange(0, 0, 0, 7, SAL_N_ELEMENTS(aData
), 0));
4775 ScAddress
aPos(0,0,0);
4776 ScRange aDataRange
= insertRangeData( m_pDoc
, aPos
, aData
, SAL_N_ELEMENTS(aData
));
4777 CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange
.aStart
== aPos
);
4779 m_pDoc
->SetColHidden(4,4,0,true);
4780 bool bHidden
= m_pDoc
->ColHidden(4,0);
4781 CPPUNIT_ASSERT(bHidden
);
4785 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4787 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(0), nRow
);
4788 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(1), nCol
);
4790 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4792 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(0), nRow
);
4793 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(2), nCol
);
4795 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4797 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(0), nRow
);
4798 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(5), nCol
);
4800 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4802 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(0), nRow
);
4803 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(6), nCol
);
4805 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4807 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(0), nRow
);
4808 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(MAXCOL
), nCol
);
4813 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4815 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(1), nRow
);
4816 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(3), nCol
);
4818 m_pDoc
->FindAreaPos(nCol
, nRow
, 0, SC_MOVE_RIGHT
);
4820 CPPUNIT_ASSERT_EQUAL(static_cast<SCROW
>(1), nRow
);
4821 CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL
>(6), nCol
);
4823 m_pDoc
->DeleteTab(0);
4826 void Test::testShiftCells()
4828 m_pDoc
->InsertTab(0, "foo");
4830 OUString
aTestVal("Some Text");
4832 // Text into cell E5.
4833 m_pDoc
->SetString(4, 3, 0, aTestVal
);
4835 // put a Note in cell E5
4836 ScAddress
rAddr(4, 3, 0);
4837 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(rAddr
);
4838 pNote
->SetText(rAddr
, "Hello");
4840 CPPUNIT_ASSERT_MESSAGE("there should be a note", m_pDoc
->HasNote(4, 3, 0));
4842 // Insert cell at D5. This should shift the string cell to right.
4843 m_pDoc
->InsertCol(3, 0, 3, 0, 3, 1);
4844 OUString aStr
= m_pDoc
->GetString(5, 3, 0);
4845 CPPUNIT_ASSERT_MESSAGE("We should have a string cell here.", aStr
== aTestVal
);
4846 CPPUNIT_ASSERT_MESSAGE("D5 is supposed to be blank.", m_pDoc
->IsBlockEmpty(0, 3, 4, 3, 4));
4848 CPPUNIT_ASSERT_MESSAGE("there should be NO note", !m_pDoc
->HasNote(4, 3, 0));
4849 CPPUNIT_ASSERT_MESSAGE("there should be a note", m_pDoc
->HasNote(5, 3, 0));
4851 // Delete cell D5, to shift the text cell back into D5.
4852 m_pDoc
->DeleteCol(3, 0, 3, 0, 3, 1);
4853 aStr
= m_pDoc
->GetString(4, 3, 0);
4854 CPPUNIT_ASSERT_MESSAGE("We should have a string cell here.", aStr
== aTestVal
);
4855 CPPUNIT_ASSERT_MESSAGE("E5 is supposed to be blank.", m_pDoc
->IsBlockEmpty(0, 4, 4, 4, 4));
4857 CPPUNIT_ASSERT_MESSAGE("there should be NO note", !m_pDoc
->HasNote(5, 3, 0));
4858 CPPUNIT_ASSERT_MESSAGE("there should be a note", m_pDoc
->HasNote(4, 3, 0));
4860 m_pDoc
->DeleteTab(0);
4863 void Test::testNoteBasic()
4865 m_pDoc
->InsertTab(0, "PostIts");
4867 CPPUNIT_ASSERT(!m_pDoc
->HasNotes());
4869 // Check for note's presence in all tables before inserting any notes.
4870 for (SCTAB i
= 0; i
<= MAXTAB
; ++i
)
4872 bool bHasNotes
= m_pDoc
->HasTabNotes(i
);
4873 CPPUNIT_ASSERT(!bHasNotes
);
4876 ScAddress
aAddr(2, 2, 0); // cell C3
4877 ScPostIt
*pNote
= m_pDoc
->GetOrCreateNote(aAddr
);
4879 pNote
->SetText(aAddr
, "Hello world");
4880 pNote
->SetAuthor("Jim Bob");
4882 ScPostIt
*pGetNote
= m_pDoc
->GetNote(aAddr
);
4883 CPPUNIT_ASSERT_MESSAGE("note should be itself", pGetNote
== pNote
);
4885 // Insert one row at row 1.
4886 bool bInsertRow
= m_pDoc
->InsertRow(0, 0, MAXCOL
, 0, 1, 1);
4887 CPPUNIT_ASSERT_MESSAGE("failed to insert row", bInsertRow
);
4889 CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc
->GetNote(aAddr
) == NULL
);
4890 aAddr
.IncRow(); // cell C4
4891 CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc
->GetNote(aAddr
) == pNote
);
4893 // Insert column at column A.
4894 bool bInsertCol
= m_pDoc
->InsertCol(0, 0, MAXROW
, 0, 1, 1);
4895 CPPUNIT_ASSERT_MESSAGE("failed to insert column", bInsertCol
);
4897 CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc
->GetNote(aAddr
) == NULL
);
4898 aAddr
.IncCol(); // cell D4
4899 CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc
->GetNote(aAddr
) == pNote
);
4901 // Insert a new sheet to shift the current sheet to the right.
4902 m_pDoc
->InsertTab(0, "Table2");
4903 CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc
->GetNote(aAddr
) == NULL
);
4904 aAddr
.IncTab(); // Move to the next sheet.
4905 CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc
->GetNote(aAddr
) == pNote
);
4907 m_pDoc
->DeleteTab(0);
4909 CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc
->GetNote(aAddr
) == pNote
);
4911 // Insert cell at C4. This should NOT shift the note position.
4912 bInsertRow
= m_pDoc
->InsertRow(2, 0, 2, 0, 3, 1);
4913 CPPUNIT_ASSERT_MESSAGE("Failed to insert cell at C4.", bInsertRow
);
4914 CPPUNIT_ASSERT_MESSAGE("Note shouldn't have moved but it has.", m_pDoc
->GetNote(aAddr
) == pNote
);
4916 // Delete cell at C4. Again, this should NOT shift the note position.
4917 m_pDoc
->DeleteRow(2, 0, 2, 0, 3, 1);
4918 CPPUNIT_ASSERT_MESSAGE("Note shouldn't have moved but it has.", m_pDoc
->GetNote(aAddr
) == pNote
);
4920 // Now, with the note at D4, delete cell D3. This should shift the note one cell up.
4921 m_pDoc
->DeleteRow(3, 0, 3, 0, 2, 1);
4922 aAddr
.IncRow(-1); // cell D3
4923 CPPUNIT_ASSERT_MESSAGE("Note at D4 should have shifted up to D3.", m_pDoc
->GetNote(aAddr
) == pNote
);
4925 // Delete column C. This should shift the note one cell left.
4926 m_pDoc
->DeleteCol(0, 0, MAXROW
, 0, 2, 1);
4927 aAddr
.IncCol(-1); // cell C3
4928 CPPUNIT_ASSERT_MESSAGE("Note at D3 should have shifted left to C3.", m_pDoc
->GetNote(aAddr
) == pNote
);
4930 // Insert a text where the note is.
4931 m_pDoc
->SetString(aAddr
, "Note is here.");
4933 // Delete row 1. This should shift the note from C3 to C2.
4934 m_pDoc
->DeleteRow(0, 0, MAXCOL
, 0, 0, 1);
4935 aAddr
.IncRow(-1); // C2
4936 CPPUNIT_ASSERT_MESSAGE("Note at C3 should have shifted up to C2.", m_pDoc
->GetNote(aAddr
) == pNote
);
4938 m_pDoc
->DeleteTab(0);
4941 void Test::testNoteDeleteRow()
4943 m_pDoc
->InsertTab(0, "Sheet1");
4945 // We need a drawing layer in order to create caption objects.
4946 m_pDoc
->InitDrawLayer(&getDocShell());
4948 OUString
aHello("Hello");
4949 OUString
aJimBob("Jim Bob");
4950 ScAddress
aPos(1, 1, 0);
4951 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(aPos
);
4952 pNote
->SetText(aPos
, aHello
);
4953 pNote
->SetAuthor(aJimBob
);
4955 CPPUNIT_ASSERT_MESSAGE("there should be a note", m_pDoc
->HasNote(1, 1, 0));
4957 // test with IsBlockEmpty
4958 bool bIgnoreNotes
= true;
4959 CPPUNIT_ASSERT_MESSAGE("The Block should be detected as empty (no Notes)", m_pDoc
->IsBlockEmpty(0, 0, 0, 100, 100, bIgnoreNotes
));
4960 bIgnoreNotes
= false;
4961 CPPUNIT_ASSERT_MESSAGE("The Block should NOT be detected as empty", !m_pDoc
->IsBlockEmpty(0, 0, 0, 100, 100, bIgnoreNotes
));
4963 m_pDoc
->DeleteRow(0, 0, MAXCOL
, 0, 1, 1);
4965 CPPUNIT_ASSERT_MESSAGE("there should be no more note", !m_pDoc
->HasNote(1, 1, 0));
4967 // Set values and notes into B3:B4.
4968 aPos
= ScAddress(1,2,0); // B3
4969 m_pDoc
->SetString(aPos
, "First");
4970 ScNoteUtil::CreateNoteFromString(*m_pDoc
, aPos
, "First Note", false, false);
4972 aPos
= ScAddress(1,3,0); // B4
4973 m_pDoc
->SetString(aPos
, "Second");
4974 ScNoteUtil::CreateNoteFromString(*m_pDoc
, aPos
, "Second Note", false, false);
4977 ScDocFunc
& rDocFunc
= getDocShell().GetDocFunc();
4979 aMark
.SelectOneTable(0);
4980 rDocFunc
.DeleteCells(ScRange(0,1,0,MAXCOL
,1,0), &aMark
, DEL_CELLSUP
, true, true);
4982 // Check to make sure the notes have shifted upward.
4983 pNote
= m_pDoc
->GetNote(ScAddress(1,1,0));
4984 CPPUNIT_ASSERT_MESSAGE("B2 should have a note.", pNote
);
4985 CPPUNIT_ASSERT_EQUAL(OUString("First Note"), pNote
->GetText());
4986 pNote
= m_pDoc
->GetNote(ScAddress(1,2,0));
4987 CPPUNIT_ASSERT_MESSAGE("B3 should have a note.", pNote
);
4988 CPPUNIT_ASSERT_EQUAL(OUString("Second Note"), pNote
->GetText());
4989 pNote
= m_pDoc
->GetNote(ScAddress(1,3,0));
4990 CPPUNIT_ASSERT_MESSAGE("B4 should NOT have a note.", !pNote
);
4994 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
4995 CPPUNIT_ASSERT_MESSAGE("Failed to get undo manager.", pUndoMgr
);
4996 m_pDoc
->CreateAllNoteCaptions(); // to make sure that all notes have their corresponding caption objects...
4999 pNote
= m_pDoc
->GetNote(ScAddress(1,1,0));
5000 CPPUNIT_ASSERT_MESSAGE("B2 should NOT have a note.", !pNote
);
5001 pNote
= m_pDoc
->GetNote(ScAddress(1,2,0));
5002 CPPUNIT_ASSERT_MESSAGE("B3 should have a note.", pNote
);
5003 CPPUNIT_ASSERT_EQUAL(OUString("First Note"), pNote
->GetText());
5004 pNote
= m_pDoc
->GetNote(ScAddress(1,3,0));
5005 CPPUNIT_ASSERT_MESSAGE("B4 should have a note.", pNote
);
5006 CPPUNIT_ASSERT_EQUAL(OUString("Second Note"), pNote
->GetText());
5009 rDocFunc
.DeleteCells(ScRange(0,2,0,MAXCOL
,2,0), &aMark
, DEL_CELLSUP
, true, true);
5011 pNote
= m_pDoc
->GetNote(ScAddress(1,2,0));
5012 CPPUNIT_ASSERT_MESSAGE("B3 should have a note.", pNote
);
5013 CPPUNIT_ASSERT_EQUAL(OUString("Second Note"), pNote
->GetText());
5014 pNote
= m_pDoc
->GetNote(ScAddress(1,3,0));
5015 CPPUNIT_ASSERT_MESSAGE("B4 should NOT have a note.", !pNote
);
5017 // Undo and check the result.
5019 pNote
= m_pDoc
->GetNote(ScAddress(1,2,0));
5020 CPPUNIT_ASSERT_MESSAGE("B3 should have a note.", pNote
);
5021 CPPUNIT_ASSERT_EQUAL(OUString("First Note"), pNote
->GetText());
5022 pNote
= m_pDoc
->GetNote(ScAddress(1,3,0));
5023 CPPUNIT_ASSERT_MESSAGE("B4 should have a note.", pNote
);
5024 CPPUNIT_ASSERT_EQUAL(OUString("Second Note"), pNote
->GetText());
5026 m_pDoc
->DeleteTab(0);
5029 void Test::testNoteDeleteCol()
5031 ScDocument
& rDoc
= getDocShell().GetDocument();
5032 rDoc
.InsertTab(0, "Sheet1");
5034 ScAddress
rAddr(1, 1, 0);
5035 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(rAddr
);
5036 pNote
->SetText(rAddr
, "Hello");
5037 pNote
->SetAuthor("Jim Bob");
5039 CPPUNIT_ASSERT_MESSAGE("there should be a note", rDoc
.HasNote(1, 1, 0));
5041 rDoc
.DeleteCol(0, 0, MAXROW
, 0, 1, 1);
5043 CPPUNIT_ASSERT_MESSAGE("there should be no more note", !rDoc
.HasNote(1, 1, 0));
5048 void Test::testNoteLifeCycle()
5050 m_pDoc
->InsertTab(0, "Test");
5052 // We need a drawing layer in order to create caption objects.
5053 m_pDoc
->InitDrawLayer(&getDocShell());
5055 ScAddress
aPos(1,1,0);
5056 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(aPos
);
5057 CPPUNIT_ASSERT_MESSAGE("Failed to insert a new cell comment.", pNote
);
5059 pNote
->SetText(aPos
, "New note");
5060 ScPostIt
* pNote2
= m_pDoc
->ReleaseNote(aPos
);
5061 CPPUNIT_ASSERT_MESSAGE("This note instance is expected to be identical to the original.", pNote
== pNote2
);
5062 CPPUNIT_ASSERT_MESSAGE("The note shouldn't be here after it's been released.", !m_pDoc
->HasNote(aPos
));
5064 // Modify the internal state of the note instance to make sure it's really
5066 pNote
->SetText(aPos
, "New content");
5068 // Re-insert the note back to the same place.
5069 m_pDoc
->SetNote(aPos
, pNote
);
5070 const SdrCaptionObj
* pCaption
= pNote
->GetOrCreateCaption(aPos
);
5071 CPPUNIT_ASSERT_MESSAGE("Failed to create a caption object.", pCaption
);
5072 CPPUNIT_ASSERT_MESSAGE("This caption should belong to the drawing layer of the document.",
5073 pCaption
->GetModel() == m_pDoc
->GetDrawLayer());
5075 // Copy B2 with note to a clipboard.
5077 ScClipParam
aClipParam(aPos
, false);
5078 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
5079 ScMarkData aMarkData
;
5080 aMarkData
.SelectOneTable(0);
5081 m_pDoc
->CopyToClip(aClipParam
, &aClipDoc
, &aMarkData
, false, false, true, true, false);
5083 ScPostIt
* pClipNote
= aClipDoc
.GetNote(aPos
);
5084 CPPUNIT_ASSERT_MESSAGE("Failed to copy note to the clipboard.", pClipNote
);
5085 CPPUNIT_ASSERT_MESSAGE("Note on the clipboard should share the same caption object from the original.",
5086 pClipNote
->GetCaption() == pCaption
);
5088 m_pDoc
->DeleteTab(0);
5091 void Test::testNoteCopyPaste()
5093 m_pDoc
->InsertTab(0, "Test");
5095 // We need a drawing layer in order to create caption objects.
5096 m_pDoc
->InitDrawLayer(&getDocShell());
5098 // Insert in B2 a text and cell comment.
5099 ScAddress
aPos(1,1,0);
5100 m_pDoc
->SetString(aPos
, "Text");
5101 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(aPos
);
5102 CPPUNIT_ASSERT(pNote
);
5103 pNote
->SetText(aPos
, "Note1");
5105 // Insert in B4 a number and cell comment.
5107 m_pDoc
->SetValue(aPos
, 1.1);
5108 pNote
= m_pDoc
->GetOrCreateNote(aPos
);
5109 CPPUNIT_ASSERT(pNote
);
5110 pNote
->SetText(aPos
, "Note2");
5112 // Copy B2:B4 to clipboard.
5114 aMark
.SelectOneTable(0);
5115 ScRange
aCopyRange(1,1,0,1,3,0);
5116 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
5117 aClipDoc
.ResetClip(m_pDoc
, &aMark
);
5118 ScClipParam
aClipParam(aCopyRange
, false);
5119 m_pDoc
->CopyToClip(aClipParam
, &aClipDoc
, &aMark
, false, false, false, true, false);
5121 // Make sure the notes are in the clipboard.
5122 pNote
= aClipDoc
.GetNote(ScAddress(1,1,0));
5123 CPPUNIT_ASSERT(pNote
);
5124 CPPUNIT_ASSERT_EQUAL(OUString("Note1"), pNote
->GetText());
5126 pNote
= aClipDoc
.GetNote(ScAddress(1,3,0));
5127 CPPUNIT_ASSERT(pNote
);
5128 CPPUNIT_ASSERT_EQUAL(OUString("Note2"), pNote
->GetText());
5130 // Paste to B6:B8 but only cell notes.
5131 ScRange
aDestRange(1,5,0,1,7,0);
5132 m_pDoc
->CopyFromClip(aDestRange
, aMark
, IDF_NOTE
, NULL
, &aClipDoc
);
5134 // Make sure the notes are there.
5135 pNote
= m_pDoc
->GetNote(ScAddress(1,5,0));
5136 CPPUNIT_ASSERT(pNote
);
5137 CPPUNIT_ASSERT_EQUAL(OUString("Note1"), pNote
->GetText());
5139 pNote
= m_pDoc
->GetNote(ScAddress(1,7,0));
5140 CPPUNIT_ASSERT(pNote
);
5141 CPPUNIT_ASSERT_EQUAL(OUString("Note2"), pNote
->GetText());
5143 m_pDoc
->DeleteTab(0);
5146 void Test::testAreasWithNotes()
5148 ScDocument
& rDoc
= getDocShell().GetDocument();
5149 rDoc
.InsertTab(0, "Sheet1");
5151 ScAddress
rAddr(1, 5, 0);
5152 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(rAddr
);
5153 pNote
->SetText(rAddr
, "Hello");
5154 pNote
->SetAuthor("Jim Bob");
5155 ScAddress
rAddrMin(2, 2, 0);
5156 ScPostIt
* pNoteMin
= m_pDoc
->GetOrCreateNote(rAddrMin
);
5157 pNoteMin
->SetText(rAddrMin
, "Hello");
5161 bool dataFound
= false;
5163 // only cell notes (empty content)
5165 dataFound
= rDoc
.GetDataStart(0,col
,row
);
5167 CPPUNIT_ASSERT_MESSAGE("No DataStart found", dataFound
);
5168 CPPUNIT_ASSERT_MESSAGE("DataStart wrong col for notes", col
== 1);
5169 CPPUNIT_ASSERT_MESSAGE("DataStart wrong row for notes", row
== 2);
5171 dataFound
= rDoc
.GetCellArea(0,col
,row
);
5173 CPPUNIT_ASSERT_MESSAGE("No CellArea found", dataFound
);
5174 CPPUNIT_ASSERT_MESSAGE("CellArea wrong col for notes", col
== 2);
5175 CPPUNIT_ASSERT_MESSAGE("CellArea wrong row for notes", row
== 5);
5178 dataFound
= rDoc
.GetPrintArea(0,col
,row
, bNotes
);
5180 CPPUNIT_ASSERT_MESSAGE("No PrintArea found", dataFound
);
5181 CPPUNIT_ASSERT_MESSAGE("PrintArea wrong col for notes", col
== 2);
5182 CPPUNIT_ASSERT_MESSAGE("PrintArea wrong row for notes", row
== 5);
5185 dataFound
= rDoc
.GetPrintArea(0,col
,row
, bNotes
);
5186 CPPUNIT_ASSERT_MESSAGE("No PrintArea should be found", !dataFound
);
5189 dataFound
= rDoc
.GetPrintAreaVer(0,0,1,row
, bNotes
); // cols 0 & 1
5190 CPPUNIT_ASSERT_MESSAGE("No PrintAreaVer found", dataFound
);
5191 CPPUNIT_ASSERT_MESSAGE("PrintAreaVer wrong row for notes", row
== 5);
5193 dataFound
= rDoc
.GetPrintAreaVer(0,2,3,row
, bNotes
); // cols 2 & 3
5194 CPPUNIT_ASSERT_MESSAGE("No PrintAreaVer found", dataFound
);
5195 CPPUNIT_ASSERT_MESSAGE("PrintAreaVer wrong row for notes", row
== 2);
5198 dataFound
= rDoc
.GetPrintAreaVer(0,0,1,row
, bNotes
); // col 0 & 1
5199 CPPUNIT_ASSERT_MESSAGE("No PrintAreaVer should be found", !dataFound
);
5201 // now add cells with value, check that notes are taken into accompt in good cases
5203 m_pDoc
->SetString(0, 3, 0, "Some Text");
5204 m_pDoc
->SetString(3, 3, 0, "Some Text");
5206 dataFound
= rDoc
.GetDataStart(0,col
,row
);
5208 CPPUNIT_ASSERT_MESSAGE("No DataStart found", dataFound
);
5209 CPPUNIT_ASSERT_MESSAGE("DataStart wrong col", col
== 0);
5210 CPPUNIT_ASSERT_MESSAGE("DataStart wrong row", row
== 2);
5212 dataFound
= rDoc
.GetCellArea(0,col
,row
);
5214 CPPUNIT_ASSERT_MESSAGE("No CellArea found", dataFound
);
5215 CPPUNIT_ASSERT_MESSAGE("CellArea wrong col", col
== 3);
5216 CPPUNIT_ASSERT_MESSAGE("CellArea wrong row", row
== 5);
5219 dataFound
= rDoc
.GetPrintArea(0,col
,row
, bNotes
);
5221 CPPUNIT_ASSERT_MESSAGE("No PrintArea found", dataFound
);
5222 CPPUNIT_ASSERT_MESSAGE("PrintArea wrong col", col
== 3);
5223 CPPUNIT_ASSERT_MESSAGE("PrintArea wrong row", row
== 5);
5226 dataFound
= rDoc
.GetPrintArea(0,col
,row
, bNotes
);
5227 CPPUNIT_ASSERT_MESSAGE("No PrintArea found", dataFound
);
5228 CPPUNIT_ASSERT_MESSAGE("PrintArea wrong col", col
== 3);
5229 CPPUNIT_ASSERT_MESSAGE("PrintArea wrong row", row
== 3);
5232 dataFound
= rDoc
.GetPrintAreaVer(0,0,1,row
, bNotes
); // cols 0 & 1
5233 CPPUNIT_ASSERT_MESSAGE("No PrintAreaVer found", dataFound
);
5234 CPPUNIT_ASSERT_MESSAGE("PrintAreaVer wrong row", row
== 5);
5236 dataFound
= rDoc
.GetPrintAreaVer(0,2,3,row
, bNotes
); // cols 2 & 3
5237 CPPUNIT_ASSERT_MESSAGE("No PrintAreaVer found", dataFound
);
5238 CPPUNIT_ASSERT_MESSAGE("PrintAreaVer wrong row", row
== 3);
5241 dataFound
= rDoc
.GetPrintAreaVer(0,0,1,row
, bNotes
); // cols 0 & 1
5242 CPPUNIT_ASSERT_MESSAGE("No PrintAreaVer found", dataFound
);
5243 CPPUNIT_ASSERT_MESSAGE("PrintAreaVer wrong row", row
== 3);
5248 void Test::testAnchoredRotatedShape()
5250 m_pDoc
->InsertTab(0, "TestTab");
5252 bool bHidden
= m_pDoc
->RowHidden(0, 0, &nRow1
, &nRow2
);
5253 CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden
&& nRow1
== 0 && nRow2
== MAXROW
);
5255 m_pDoc
->InitDrawLayer();
5256 ScDrawLayer
*pDrawLayer
= m_pDoc
->GetDrawLayer();
5257 CPPUNIT_ASSERT_MESSAGE("must have a draw layer", pDrawLayer
!= NULL
);
5258 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
5259 CPPUNIT_ASSERT_MESSAGE("must have a draw page", pPage
!= NULL
);
5260 m_pDoc
->SetRowHeightRange( 0, MAXROW
, 0, sc::HMMToTwips( 1000 ) );
5261 const long TOLERANCE
= 30; //30 hmm
5262 for ( SCCOL nCol
= 0; nCol
< MAXCOL
; ++nCol
)
5263 m_pDoc
->SetColWidth( nCol
, 0, sc::HMMToTwips( 1000 ) );
5266 Rectangle
aRect( 4000, 5000, 10000, 7000 );
5268 Rectangle
aRotRect( 6000, 3000, 8000, 9000 );
5269 SdrRectObj
*pObj
= new SdrRectObj(aRect
);
5270 pPage
->InsertObject(pObj
);
5271 Point
aRef1(pObj
->GetSnapRect().Center());
5272 int nAngle
= 9000; //90 deg.
5273 double nSin
=sin(nAngle
*nPi180
);
5274 double nCos
=cos(nAngle
*nPi180
);
5275 pObj
->Rotate(aRef1
,nAngle
,nSin
,nCos
);
5277 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *m_pDoc
, 0);
5279 Rectangle aSnap
= pObj
->GetSnapRect();
5280 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRotRect
.GetHeight(), aSnap
.GetHeight(), TOLERANCE
) );
5281 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRotRect
.GetWidth(), aSnap
.GetWidth(), TOLERANCE
) );
5282 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRotRect
.Left(), aSnap
.Left(), TOLERANCE
) );
5283 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRotRect
.Top(), aSnap
.Top(), TOLERANCE
) );
5285 ScDrawObjData aAnchor
;
5286 ScDrawObjData
* pData
= ScDrawLayer::GetObjData( pObj
);
5287 CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object meta-data.", pData
);
5289 aAnchor
.maStart
= pData
->maStart
;
5290 aAnchor
.maEnd
= pData
->maEnd
;
5292 m_pDoc
->SetDrawPageSize(0);
5294 // increase row 5 by 2000 hmm
5295 m_pDoc
->SetRowHeight( 5, 0, sc::HMMToTwips( 3000 ) );
5296 // increase col 6 by 1000 hmm
5297 m_pDoc
->SetColWidth( 6, 0, sc::HMMToTwips( 2000 ) );
5299 aRotRect
.setWidth( aRotRect
.GetWidth() + 1000 );
5300 aRotRect
.setHeight( aRotRect
.GetHeight() + 2000 );
5302 m_pDoc
->SetDrawPageSize(0);
5304 aSnap
= pObj
->GetSnapRect();
5306 // ensure that width and height have been adjusted accordingly
5307 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRotRect
.GetHeight(), aSnap
.GetHeight(), TOLERANCE
) );
5308 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRotRect
.GetWidth(), aSnap
.GetWidth(), TOLERANCE
) );
5310 // ensure that anchor start and end addresses haven't changed
5311 CPPUNIT_ASSERT_EQUAL( aAnchor
.maStart
.Row(), pData
->maStart
.Row() ); // start row 0
5312 CPPUNIT_ASSERT_EQUAL( aAnchor
.maStart
.Col(), pData
->maStart
.Col() ); // start column 5
5313 CPPUNIT_ASSERT_EQUAL( aAnchor
.maEnd
.Row(), pData
->maEnd
.Row() ); // end row 3
5314 CPPUNIT_ASSERT_EQUAL( aAnchor
.maEnd
.Col(), pData
->maEnd
.Col() ); // end col 7
5316 m_pDoc
->DeleteTab(0);
5319 void Test::testCellTextWidth()
5321 m_pDoc
->InsertTab(0, "Test");
5323 ScAddress
aTopCell(0, 0, 0);
5326 boost::scoped_ptr
<ScColumnTextWidthIterator
> pIter(new ScColumnTextWidthIterator(*m_pDoc
, aTopCell
, MAXROW
));
5327 CPPUNIT_ASSERT_MESSAGE("Column should have no text widths stored.", !pIter
->hasCell());
5329 // Sheet only has one cell.
5330 m_pDoc
->SetString(0, 0, 0, "Only one cell");
5331 pIter
.reset(new ScColumnTextWidthIterator(*m_pDoc
, aTopCell
, MAXROW
));
5332 CPPUNIT_ASSERT_MESSAGE("Column should have a cell.", pIter
->hasCell());
5334 CPPUNIT_ASSERT_EQUAL(nTestRow
, pIter
->getPos());
5336 // Setting a text width here should commit it to the column.
5337 sal_uInt16 nTestVal
= 432;
5338 pIter
->setValue(nTestVal
);
5339 CPPUNIT_ASSERT_EQUAL(nTestVal
, m_pDoc
->GetTextWidth(aTopCell
));
5341 // Set values to row 2 through 6.
5342 for (SCROW i
= 2; i
<= 6; ++i
)
5343 m_pDoc
->SetString(0, i
, 0, "foo");
5345 // Set values to row 10 through 18.
5346 for (SCROW i
= 10; i
<= 18; ++i
)
5347 m_pDoc
->SetString(0, i
, 0, "foo");
5351 pIter
.reset(new ScColumnTextWidthIterator(*m_pDoc
, aTopCell
, MAXROW
));
5352 SCROW aRows
[] = { 0, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
5353 size_t n
= SAL_N_ELEMENTS(aRows
);
5354 for (size_t i
= 0; i
< n
; ++i
, pIter
->next())
5356 CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter
->hasCell());
5357 CPPUNIT_ASSERT_EQUAL(aRows
[i
], pIter
->getPos());
5359 CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter
->hasCell());
5363 // Specify start and end rows (6 - 16)
5364 ScAddress aStart
= aTopCell
;
5366 pIter
.reset(new ScColumnTextWidthIterator(*m_pDoc
, aStart
, 16));
5367 SCROW aRows
[] = { 6, 10, 11, 12, 13, 14, 15, 16 };
5368 size_t n
= SAL_N_ELEMENTS(aRows
);
5369 for (size_t i
= 0; i
< n
; ++i
, pIter
->next())
5371 CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter
->hasCell());
5372 CPPUNIT_ASSERT_EQUAL(aRows
[i
], pIter
->getPos());
5374 CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter
->hasCell());
5377 // Clear from row 3 to row 17. After this, we should only have cells at rows 0, 2 and 18.
5378 clearRange(m_pDoc
, ScRange(0, 3, 0, 0, 17, 0));
5381 // Full range again.
5382 pIter
.reset(new ScColumnTextWidthIterator(*m_pDoc
, aTopCell
, MAXROW
));
5383 SCROW aRows
[] = { 0, 2, 18 };
5384 size_t n
= SAL_N_ELEMENTS(aRows
);
5385 for (size_t i
= 0; i
< n
; ++i
, pIter
->next())
5387 CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter
->hasCell());
5388 CPPUNIT_ASSERT_EQUAL(aRows
[i
], pIter
->getPos());
5390 CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter
->hasCell());
5393 // Delete row 2 which shifts all cells below row 2 upward. After this, we
5394 // should only have cells at rows 0 and 17.
5395 m_pDoc
->DeleteRow(0, 0, MAXCOL
, MAXTAB
, 2, 1);
5397 // Full range again.
5398 pIter
.reset(new ScColumnTextWidthIterator(*m_pDoc
, aTopCell
, MAXROW
));
5399 SCROW aRows
[] = { 0, 17 };
5400 size_t n
= SAL_N_ELEMENTS(aRows
);
5401 for (size_t i
= 0; i
< n
; ++i
, pIter
->next())
5403 CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter
->hasCell());
5404 CPPUNIT_ASSERT_EQUAL(aRows
[i
], pIter
->getPos());
5406 CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter
->hasCell());
5409 m_pDoc
->DeleteTab(0);
5412 bool checkEditTextIterator(sc::EditTextIterator
& rIter
, const char** pChecks
)
5414 const EditTextObject
* pText
= rIter
.first();
5415 const char* p
= *pChecks
;
5417 for (int i
= 0; i
< 100; ++i
) // cap it to 100 loops.
5420 // No more edit cells. The check string array should end too.
5424 // More edit cell, but no more check string. Bad.
5427 if (pText
->GetParagraphCount() != 1)
5428 // For this test, we don't handle multi-paragraph text.
5431 if (pText
->GetText(0) != OUString::createFromAscii(p
))
5432 // Text differs from what's expected.
5435 pText
= rIter
.next();
5443 void Test::testEditTextIterator()
5445 m_pDoc
->InsertTab(0, "Test");
5448 // First, try with an empty sheet.
5449 sc::EditTextIterator
aIter(*m_pDoc
,0);
5450 const char* pChecks
[] = { NULL
};
5451 CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter
, pChecks
));
5454 ScFieldEditEngine
& rEditEngine
= m_pDoc
->GetEditEngine();
5457 // Only set one edit cell.
5458 rEditEngine
.SetText("A2");
5459 m_pDoc
->SetEditText(ScAddress(0,1,0), rEditEngine
.CreateTextObject());
5460 sc::EditTextIterator
aIter(*m_pDoc
,0);
5461 const char* pChecks
[] = { "A2", NULL
};
5462 CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter
, pChecks
));
5466 // Add a series of edit cells.
5467 rEditEngine
.SetText("A5");
5468 m_pDoc
->SetEditText(ScAddress(0,4,0), rEditEngine
.CreateTextObject());
5469 rEditEngine
.SetText("A6");
5470 m_pDoc
->SetEditText(ScAddress(0,5,0), rEditEngine
.CreateTextObject());
5471 rEditEngine
.SetText("A7");
5472 m_pDoc
->SetEditText(ScAddress(0,6,0), rEditEngine
.CreateTextObject());
5473 sc::EditTextIterator
aIter(*m_pDoc
,0);
5474 const char* pChecks
[] = { "A2", "A5", "A6", "A7", NULL
};
5475 CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter
, pChecks
));
5479 // Add more edit cells to column C. Skip column B.
5480 rEditEngine
.SetText("C1");
5481 m_pDoc
->SetEditText(ScAddress(2,0,0), rEditEngine
.CreateTextObject());
5482 rEditEngine
.SetText("C3");
5483 m_pDoc
->SetEditText(ScAddress(2,2,0), rEditEngine
.CreateTextObject());
5484 rEditEngine
.SetText("C4");
5485 m_pDoc
->SetEditText(ScAddress(2,3,0), rEditEngine
.CreateTextObject());
5486 sc::EditTextIterator
aIter(*m_pDoc
,0);
5487 const char* pChecks
[] = { "A2", "A5", "A6", "A7", "C1", "C3", "C4", NULL
};
5488 CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter
, pChecks
));
5492 // Add some numeric, string and formula cells. This shouldn't affect the outcome.
5493 m_pDoc
->SetString(ScAddress(0,99,0), "=ROW()");
5494 m_pDoc
->SetValue(ScAddress(1,3,0), 1.2);
5495 m_pDoc
->SetString(ScAddress(2,4,0), "Simple string");
5496 sc::EditTextIterator
aIter(*m_pDoc
,0);
5497 const char* pChecks
[] = { "A2", "A5", "A6", "A7", "C1", "C3", "C4", NULL
};
5498 CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter
, pChecks
));
5501 m_pDoc
->DeleteTab(0);
5504 void Test::testCondFormatINSDEL()
5507 m_pDoc
->InsertTab(0, "Test");
5508 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
5510 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5511 ScRangeList
aRangeList(ScRange(0,0,0,0,3,0));
5512 pFormat
->SetRange(aRangeList
);
5513 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5514 pFormat
->AddEntry(pEntry
);
5516 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
5517 pList
->InsertNew(pFormat
);
5519 m_pDoc
->InsertCol(0,0,MAXROW
,0,0,2);
5520 const ScRangeList
& rRange
= pFormat
->GetRange();
5521 CPPUNIT_ASSERT(rRange
== ScRange(2,0,0,2,3,0));
5523 OUString aExpr
= pEntry
->GetExpression(ScAddress(2,0,0), 0);
5524 CPPUNIT_ASSERT_EQUAL(aExpr
, OUString("D2"));
5526 m_pDoc
->DeleteTab(0);
5529 void Test::testCondFormatInsertCol()
5531 m_pDoc
->InsertTab(0, "Test");
5532 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
5534 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5535 ScRangeList
aRangeList(ScRange(0,0,0,3,3,0));
5536 pFormat
->SetRange(aRangeList
);
5538 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5539 pFormat
->AddEntry(pEntry
);
5541 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
5542 pList
->InsertNew(pFormat
);
5544 m_pDoc
->InsertCol(0,0,MAXROW
,0,4,2);
5545 const ScRangeList
& rRange
= pFormat
->GetRange();
5546 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,0,5,3,0)), rRange
);
5548 m_pDoc
->DeleteTab(0);
5551 void Test::testCondFormatInsertRow()
5553 m_pDoc
->InsertTab(0, "Test");
5554 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
5556 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5557 ScRangeList
aRangeList(ScRange(0,0,0,3,3,0));
5558 pFormat
->SetRange(aRangeList
);
5560 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5561 pFormat
->AddEntry(pEntry
);
5563 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
5564 pList
->InsertNew(pFormat
);
5566 m_pDoc
->InsertRow(0,0,MAXCOL
,0,4,2);
5567 const ScRangeList
& rRange
= pFormat
->GetRange();
5568 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,0,3,5,0)), rRange
);
5570 m_pDoc
->DeleteTab(0);
5573 void Test::testCondFormatInsertDeleteSheets()
5575 m_pDoc
->InsertTab(0, "Test");
5577 // Add a conditional format to B2:B4.
5578 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5579 pFormat
->SetRange(ScRange(1,1,0,1,3,0));
5581 sal_uLong nKey
= m_pDoc
->AddCondFormat(pFormat
, 0);
5583 // Add condition in which if the value equals 2, set the "Result" style.
5584 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(
5585 SC_COND_EQUAL
, "=2", "" , m_pDoc
, ScAddress(0,0,0), ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5586 pFormat
->AddEntry(pEntry
);
5588 // Apply the format to the range.
5589 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, nKey
);
5591 // Make sure this conditional format entry is really there.
5592 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
5593 CPPUNIT_ASSERT(pList
);
5594 const ScConditionalFormat
* pCheck
= pList
->GetFormat(nKey
);
5595 CPPUNIT_ASSERT_MESSAGE("Wrong condntional format instance.", pCheck
== pFormat
);
5597 // ... and its range is B2:B4.
5598 ScRangeList aCheckRange
= pCheck
->GetRange();
5599 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange
.size() == 1);
5600 const ScRange
* pRange
= aCheckRange
[0];
5601 CPPUNIT_ASSERT(pRange
);
5602 CPPUNIT_ASSERT_MESSAGE("Format should be applied to B2:B4.", *pRange
== ScRange(1,1,0,1,3,0));
5604 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
5606 // Insert a new sheet at the left.
5607 bool bInserted
= rFunc
.InsertTable(0, "Inserted", true, true);
5608 CPPUNIT_ASSERT(bInserted
);
5610 pList
= m_pDoc
->GetCondFormList(1);
5611 CPPUNIT_ASSERT(pList
);
5612 pCheck
= pList
->GetFormat(nKey
);
5613 CPPUNIT_ASSERT(pCheck
);
5615 // Make sure the range also got shifted.
5616 aCheckRange
= pCheck
->GetRange();
5617 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange
.size() == 1);
5618 pRange
= aCheckRange
[0];
5619 CPPUNIT_ASSERT(pRange
);
5620 CPPUNIT_ASSERT_MESSAGE("Format should be applied to B2:B4 on the 2nd sheet after the sheet insertion.", *pRange
== ScRange(1,1,1,1,3,1));
5622 // Delete the sheet to the left.
5623 bool bDeleted
= rFunc
.DeleteTable(0, true, true);
5624 CPPUNIT_ASSERT(bDeleted
);
5626 pList
= m_pDoc
->GetCondFormList(0);
5627 CPPUNIT_ASSERT(pList
);
5628 pCheck
= pList
->GetFormat(nKey
);
5629 CPPUNIT_ASSERT(pCheck
);
5631 // Make sure the range got shifted back.
5632 aCheckRange
= pCheck
->GetRange();
5633 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange
.size() == 1);
5634 pRange
= aCheckRange
[0];
5635 CPPUNIT_ASSERT(pRange
);
5636 CPPUNIT_ASSERT_MESSAGE("Format should be applied to B2:B4 on the 1st sheet after the sheet removal.", *pRange
== ScRange(1,1,0,1,3,0));
5638 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
5639 CPPUNIT_ASSERT(pUndoMgr
);
5641 // Undo and re-check.
5644 pList
= m_pDoc
->GetCondFormList(1);
5645 CPPUNIT_ASSERT(pList
);
5646 pCheck
= pList
->GetFormat(nKey
);
5647 CPPUNIT_ASSERT(pCheck
);
5649 aCheckRange
= pCheck
->GetRange();
5650 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange
.size() == 1);
5651 pRange
= aCheckRange
[0];
5652 CPPUNIT_ASSERT(pRange
);
5653 CPPUNIT_ASSERT_MESSAGE("Format should be applied to B2:B4 on the 2nd sheet after the undo of the sheet removal.", *pRange
== ScRange(1,1,1,1,3,1));
5655 #if 0 // TODO : Undo of sheet insertion currently depends on the presence of
5656 // view shell, and crashes when executed during cppunit run.
5658 // Undo again and re-check.
5661 pList
= m_pDoc
->GetCondFormList(0);
5662 CPPUNIT_ASSERT(pList
);
5663 pCheck
= pList
->GetFormat(nKey
);
5664 CPPUNIT_ASSERT(pCheck
);
5666 // Make sure the range got shifted back.
5667 aCheckRange
= pCheck
->GetRange();
5668 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange
.size() == 1);
5669 pRange
= aCheckRange
[0];
5670 CPPUNIT_ASSERT(pRange
);
5671 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));
5673 m_pDoc
->DeleteTab(1);
5676 m_pDoc
->DeleteTab(0);
5679 void Test::testCondCopyPaste()
5681 m_pDoc
->InsertTab(0, "Test");
5683 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5684 ScRange
aCondFormatRange(0,0,0,3,3,0);
5685 ScRangeList
aRangeList(aCondFormatRange
);
5686 pFormat
->SetRange(aRangeList
);
5688 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5689 pFormat
->AddEntry(pEntry
);
5690 sal_uLong nIndex
= m_pDoc
->AddCondFormat(pFormat
, 0);
5692 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
5693 copyToClip(m_pDoc
, aCondFormatRange
, &aClipDoc
);
5695 ScRange
aTargetRange(4,4,0,7,7,0);
5696 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
5698 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(7,7,0);
5699 CPPUNIT_ASSERT(pPastedFormat
);
5701 CPPUNIT_ASSERT_EQUAL(ScRangeList(aTargetRange
), pPastedFormat
->GetRange());
5702 CPPUNIT_ASSERT( nIndex
!= pPastedFormat
->GetKey());
5703 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 7, 7, 0, ATTR_CONDITIONAL
);
5704 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
5706 CPPUNIT_ASSERT(pCondFormatItem
);
5707 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
5708 CPPUNIT_ASSERT( nIndex
!= pCondFormatItem
->GetCondFormatData().at(0) );
5710 m_pDoc
->DeleteTab(0);
5713 void Test::testCondCopyPasteSingleCell()
5715 m_pDoc
->InsertTab(0, "Test");
5717 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5718 ScRange
aCondFormatRange(0,0,0,3,3,0);
5719 ScRangeList
aRangeList(aCondFormatRange
);
5720 pFormat
->SetRange(aRangeList
);
5722 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5723 pFormat
->AddEntry(pEntry
);
5724 sal_uLong nIndex
= m_pDoc
->AddCondFormat(pFormat
, 0);
5726 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
5727 copyToClip(m_pDoc
, ScRange(0,0,0,0,0,0), &aClipDoc
);
5729 ScRange
aTargetRange(4,4,0,4,4,0);
5730 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
5732 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(4,4,0);
5733 CPPUNIT_ASSERT(pPastedFormat
);
5735 CPPUNIT_ASSERT_EQUAL(ScRangeList(aTargetRange
), pPastedFormat
->GetRange());
5736 CPPUNIT_ASSERT( nIndex
!= pPastedFormat
->GetKey());
5737 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 4, 4, 0, ATTR_CONDITIONAL
);
5738 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
5740 CPPUNIT_ASSERT(pCondFormatItem
);
5741 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
5742 CPPUNIT_ASSERT( nIndex
!= pCondFormatItem
->GetCondFormatData().at(0) );
5744 m_pDoc
->DeleteTab(0);
5747 void Test::testCondCopyPasteSingleCellToRange()
5749 m_pDoc
->InsertTab(0, "Test");
5751 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5752 ScRange
aCondFormatRange(0,0,0,3,3,0);
5753 ScRangeList
aRangeList(aCondFormatRange
);
5754 pFormat
->SetRange(aRangeList
);
5756 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5757 pFormat
->AddEntry(pEntry
);
5758 sal_uLong nIndex
= m_pDoc
->AddCondFormat(pFormat
, 0);
5760 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
5761 copyToClip(m_pDoc
, ScRange(0,0,0,0,0,0), &aClipDoc
);
5763 ScRange
aTargetRange(4,4,0,4,8,0);
5764 pasteFromClip(m_pDoc
, aTargetRange
, &aClipDoc
);
5766 std::set
<sal_uLong
> aCondFormatIndices
;
5767 for(SCROW nRow
= 4; nRow
<= 8; ++nRow
)
5769 ScConditionalFormat
* pPastedFormat
= m_pDoc
->GetCondFormat(4, nRow
, 0);
5770 CPPUNIT_ASSERT(pPastedFormat
);
5772 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(4, nRow
, 0)), pPastedFormat
->GetRange());
5773 sal_uLong nPastedKey
= pPastedFormat
->GetKey();
5774 CPPUNIT_ASSERT( nIndex
!= nPastedKey
);
5775 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 4, nRow
, 0, ATTR_CONDITIONAL
);
5776 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
5778 CPPUNIT_ASSERT(pCondFormatItem
);
5779 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
5780 CPPUNIT_ASSERT( nIndex
!= pCondFormatItem
->GetCondFormatData().at(0) );
5781 auto itr
= aCondFormatIndices
.find(nPastedKey
);
5782 CPPUNIT_ASSERT(itr
== aCondFormatIndices
.end());
5783 aCondFormatIndices
.insert(nPastedKey
);
5786 m_pDoc
->DeleteTab(0);
5789 void Test::testCondCopyPasteSheetBetweenDoc()
5791 m_pDoc
->InsertTab(0, "Test");
5793 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5794 ScRange
aCondFormatRange(0,0,0,3,3,0);
5795 ScRangeList
aRangeList(aCondFormatRange
);
5796 pFormat
->SetRange(aRangeList
);
5798 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5799 pFormat
->AddEntry(pEntry
);
5800 m_pDoc
->AddCondFormat(pFormat
, 0);
5803 aDoc
.TransferTab(m_pDoc
, 0, 0, true);
5805 ScConditionalFormatList
* pList
= aDoc
.GetCondFormList(0);
5806 CPPUNIT_ASSERT_EQUAL(size_t(1), pList
->size());
5808 m_pDoc
->DeleteTab(0);
5811 void Test::testCondCopyPasteSheet()
5813 m_pDoc
->InsertTab(0, "Test");
5815 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5816 ScRange
aCondFormatRange(0,0,0,3,3,0);
5817 ScRangeList
aRangeList(aCondFormatRange
);
5818 pFormat
->SetRange(aRangeList
);
5820 ScCondFormatEntry
* pEntry
= new ScCondFormatEntry(SC_COND_DIRECT
,"=B2","",m_pDoc
,ScAddress(0,0,0),ScGlobal::GetRscString(STR_STYLENAME_RESULT
));
5821 pFormat
->AddEntry(pEntry
);
5822 m_pDoc
->AddCondFormat(pFormat
, 0);
5824 m_pDoc
->CopyTab(0, SC_TAB_APPEND
);
5826 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(1);
5827 CPPUNIT_ASSERT_EQUAL(size_t(1), pList
->size());
5829 ScConditionalFormat
& rFormat
= *pList
->begin();
5830 const ScRangeList
& rRange
= rFormat
.GetRange();
5831 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,1,3,3,1)), rRange
);
5832 sal_uInt32 nKey
= rFormat
.GetKey();
5833 const SfxPoolItem
* pItem
= m_pDoc
->GetAttr( 2, 2, 1, ATTR_CONDITIONAL
);
5834 const ScCondFormatItem
* pCondFormatItem
= static_cast<const ScCondFormatItem
*>(pItem
);
5836 CPPUNIT_ASSERT(pCondFormatItem
);
5837 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem
->GetCondFormatData().size());
5838 CPPUNIT_ASSERT( nKey
== pCondFormatItem
->GetCondFormatData().at(0) );
5840 m_pDoc
->DeleteTab(1);
5841 m_pDoc
->DeleteTab(0);
5844 void Test::testIconSet()
5846 m_pDoc
->InsertTab(0, "Test");
5847 ScConditionalFormatList
* pList
= m_pDoc
->GetCondFormList(0);
5849 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, m_pDoc
);
5850 ScRangeList
aRangeList(ScRange(0,0,0,0,0,0));
5851 pFormat
->SetRange(aRangeList
);
5853 ScIconSetFormat
* pEntry
= new ScIconSetFormat(m_pDoc
);
5854 ScIconSetFormatData
* pData
= new ScIconSetFormatData
;
5855 pData
->maEntries
.push_back(new ScColorScaleEntry(0, COL_BLUE
));
5856 pData
->maEntries
.push_back(new ScColorScaleEntry(1, COL_GREEN
));
5857 pData
->maEntries
.push_back(new ScColorScaleEntry(2, COL_RED
));
5858 pEntry
->SetIconSetData(pData
);
5860 m_pDoc
->AddCondFormatData(pFormat
->GetRange(), 0, 1);
5861 pList
->InsertNew(pFormat
);
5864 double nVal
; sal_Int32 nIndex
;
5872 for(size_t i
= 0; i
< SAL_N_ELEMENTS(aTests
); ++i
)
5874 m_pDoc
->SetValue(0,0,0,aTests
[i
].nVal
);
5875 ScIconSetInfo
* pInfo
= pEntry
->GetIconSetInfo(ScAddress(0,0,0));
5876 CPPUNIT_ASSERT_EQUAL(aTests
[i
].nIndex
, pInfo
->nIconIndex
);
5881 m_pDoc
->DeleteTab(0);
5886 struct ScDataBarLengthData
5892 void testDataBarLengthImpl(ScDocument
* pDoc
, ScDataBarLengthData
* pData
, const ScRange
& rRange
,
5893 double nMinVal
, ScColorScaleEntryType eMinType
,
5894 double nMaxVal
, ScColorScaleEntryType eMaxType
,
5895 double nZeroPos
, databar::ScAxisPosition eAxisPos
)
5897 ScConditionalFormat
* pFormat
= new ScConditionalFormat(1, pDoc
);
5898 ScRangeList
aRangeList(rRange
);
5899 pFormat
->SetRange(aRangeList
);
5901 SCCOL nCol
= rRange
.aStart
.Col();
5903 ScDataBarFormat
* pDatabar
= new ScDataBarFormat(pDoc
);
5904 pFormat
->AddEntry(pDatabar
);
5906 ScDataBarFormatData
* pFormatData
= new ScDataBarFormatData();
5907 pFormatData
->meAxisPosition
= eAxisPos
;
5909 pFormatData
->mpLowerLimit
.reset(new ScColorScaleEntry());
5910 pFormatData
->mpLowerLimit
->SetValue(nMinVal
);
5911 pFormatData
->mpLowerLimit
->SetType(eMinType
);
5912 pFormatData
->mpUpperLimit
.reset(new ScColorScaleEntry());
5913 pFormatData
->mpUpperLimit
->SetValue(nMaxVal
);
5914 pFormatData
->mpUpperLimit
->SetType(eMaxType
);
5915 pDatabar
->SetDataBarData(pFormatData
);
5917 for (size_t i
= 0; pData
[i
].nLength
!= -200; ++i
)
5919 pDoc
->SetValue(nCol
, i
, 0, pData
[i
].nVal
);
5922 for (size_t i
= 0; pData
[i
].nLength
!= -200; ++i
)
5924 ScDataBarInfo
* pInfo
= pDatabar
->GetDataBarInfo(ScAddress(nCol
, i
, 0));
5925 CPPUNIT_ASSERT(pInfo
);
5926 ASSERT_DOUBLES_EQUAL(pData
[i
].nLength
, pInfo
->mnLength
);
5927 ASSERT_DOUBLES_EQUAL(nZeroPos
, pInfo
->mnZero
);
5934 void Test::testDataBarLengthAutomaticAxis()
5936 m_pDoc
->InsertTab(0, "Test");
5938 ScDataBarLengthData aValues
[] = {
5950 testDataBarLengthImpl(m_pDoc
, aValues
, ScRange(0,0,0,0,7,0),
5951 3, COLORSCALE_VALUE
, 7, COLORSCALE_VALUE
, 0.0, databar::AUTOMATIC
);
5953 ScDataBarLengthData aValues2
[] = {
5972 testDataBarLengthImpl(m_pDoc
, aValues2
, ScRange(1,0,0,1,15,0),
5973 -4, COLORSCALE_VALUE
, 8, COLORSCALE_VALUE
, 1.0/3.0 * 100, databar::AUTOMATIC
);
5975 ScDataBarLengthData aValues3
[] = {
5982 testDataBarLengthImpl(m_pDoc
, aValues3
, ScRange(2,0,0,2,3,0),
5983 0, COLORSCALE_MIN
, 0, COLORSCALE_MAX
, 0, databar::AUTOMATIC
);
5985 ScDataBarLengthData aValues4
[] = {
5992 testDataBarLengthImpl(m_pDoc
, aValues4
, ScRange(3,0,0,3,3,0),
5993 0, COLORSCALE_AUTO
, 0, COLORSCALE_AUTO
, 0, databar::AUTOMATIC
);
5995 m_pDoc
->DeleteTab(0);
5998 void Test::testDataBarLengthMiddleAxis()
6000 m_pDoc
->InsertTab(0, "Test");
6002 ScDataBarLengthData aValues
[] = {
6015 testDataBarLengthImpl(m_pDoc
, aValues
, ScRange(0,0,0,0,8,0),
6016 2, COLORSCALE_VALUE
, 8, COLORSCALE_VALUE
, 50.0, databar::MIDDLE
);
6018 ScDataBarLengthData aValues2
[] = {
6037 testDataBarLengthImpl(m_pDoc
, aValues2
, ScRange(1,0,0,1,15,0),
6038 -4, COLORSCALE_VALUE
, 8, COLORSCALE_VALUE
, 50.0, databar::MIDDLE
);
6040 m_pDoc
->DeleteTab(0);
6043 void Test::testImportStream()
6045 sc::AutoCalcSwitch
aAC(*m_pDoc
, true); // turn on auto calc.
6046 sc::UndoSwitch
aUndo(*m_pDoc
, true); // enable undo.
6048 m_pDoc
->InsertTab(0, "Test");
6050 m_pDoc
->SetString(ScAddress(0,1,0), "=SUM(A1:C1)"); // A2
6052 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
6054 // CSV import options.
6055 ScAsciiOptions aOpt
;
6056 aOpt
.SetFieldSeps(",");
6058 // Import values to A1:C1.
6059 ScImportExport
aObj(m_pDoc
, ScAddress(0,0,0));
6060 aObj
.SetImportBroadcast(true);
6061 aObj
.SetExtOptions(aOpt
);
6062 aObj
.ImportString("1,2,3", SotClipboardFormatId::STRING
);
6064 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
6065 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(1,0,0)));
6066 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(2,0,0)));
6068 // Formula value should have been updated.
6069 CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
6071 // Undo, and check the result.
6072 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
6073 CPPUNIT_ASSERT_MESSAGE("Failed to get the undo manager.", pUndoMgr
);
6076 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
6077 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(ScAddress(1,0,0)));
6078 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(ScAddress(2,0,0)));
6080 CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc
->GetValue(ScAddress(0,1,0))); // formula
6082 // Redo, and check the result.
6085 CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc
->GetValue(ScAddress(0,0,0)));
6086 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(ScAddress(1,0,0)));
6087 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(2,0,0)));
6089 CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc
->GetValue(ScAddress(0,1,0))); // formula
6093 m_pDoc
->DeleteTab(0);
6096 void Test::testDeleteContents()
6098 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true); // turn on auto calc.
6099 sc::UndoSwitch
aUndoSwitch(*m_pDoc
, true); // enable undo.
6101 m_pDoc
->InsertTab(0, "Test");
6103 m_pDoc
->SetValue(ScAddress(3,1,0), 1.0);
6104 m_pDoc
->SetValue(ScAddress(3,2,0), 1.0);
6105 m_pDoc
->SetValue(ScAddress(3,3,0), 1.0);
6106 m_pDoc
->SetValue(ScAddress(3,4,0), 1.0);
6107 m_pDoc
->SetValue(ScAddress(3,5,0), 1.0);
6108 m_pDoc
->SetValue(ScAddress(3,6,0), 1.0);
6109 m_pDoc
->SetValue(ScAddress(3,7,0), 1.0);
6110 m_pDoc
->SetValue(ScAddress(3,8,0), 1.0);
6111 m_pDoc
->SetString(ScAddress(3,15,0), "=SUM(D2:D15)");
6113 CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc
->GetValue(ScAddress(3,15,0))); // formula
6116 ScRange
aRange(3,1,0,3,5,0);
6118 aMark
.SelectOneTable(0);
6119 aMark
.SetMarkArea(aRange
);
6121 ScDocument
* pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
6122 pUndoDoc
->InitUndo(m_pDoc
, 0, 0);
6123 m_pDoc
->CopyToDocument(aRange
, IDF_CONTENTS
, false, pUndoDoc
, &aMark
);
6124 ScUndoDeleteContents
aUndo(&getDocShell(), aMark
, aRange
, pUndoDoc
, false, IDF_CONTENTS
, true);
6126 clearRange(m_pDoc
, aRange
);
6127 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(3,15,0))); // formula
6130 CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc
->GetValue(ScAddress(3,15,0))); // formula
6133 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(ScAddress(3,15,0))); // formula
6135 m_pDoc
->DeleteTab(0);
6138 void Test::testTransliterateText()
6140 m_pDoc
->InsertTab(0, "Test");
6142 // Set texts to A1:A3.
6143 m_pDoc
->SetString(ScAddress(0,0,0), "Mike");
6144 m_pDoc
->SetString(ScAddress(0,1,0), "Noah");
6145 m_pDoc
->SetString(ScAddress(0,2,0), "Oscar");
6147 // Change them to uppercase.
6149 aMark
.SetMarkArea(ScRange(0,0,0,0,2,0));
6150 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
6151 rFunc
.TransliterateText(
6152 aMark
, i18n::TransliterationModules_LOWERCASE_UPPERCASE
, true, true);
6154 CPPUNIT_ASSERT_EQUAL(OUString("MIKE"), m_pDoc
->GetString(ScAddress(0,0,0)));
6155 CPPUNIT_ASSERT_EQUAL(OUString("NOAH"), m_pDoc
->GetString(ScAddress(0,1,0)));
6156 CPPUNIT_ASSERT_EQUAL(OUString("OSCAR"), m_pDoc
->GetString(ScAddress(0,2,0)));
6158 // Test the undo and redo.
6159 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
6160 CPPUNIT_ASSERT_MESSAGE("Failed to get undo manager.", pUndoMgr
);
6163 CPPUNIT_ASSERT_EQUAL(OUString("Mike"), m_pDoc
->GetString(ScAddress(0,0,0)));
6164 CPPUNIT_ASSERT_EQUAL(OUString("Noah"), m_pDoc
->GetString(ScAddress(0,1,0)));
6165 CPPUNIT_ASSERT_EQUAL(OUString("Oscar"), m_pDoc
->GetString(ScAddress(0,2,0)));
6168 CPPUNIT_ASSERT_EQUAL(OUString("MIKE"), m_pDoc
->GetString(ScAddress(0,0,0)));
6169 CPPUNIT_ASSERT_EQUAL(OUString("NOAH"), m_pDoc
->GetString(ScAddress(0,1,0)));
6170 CPPUNIT_ASSERT_EQUAL(OUString("OSCAR"), m_pDoc
->GetString(ScAddress(0,2,0)));
6172 m_pDoc
->DeleteTab(0);
6175 void Test::testFormulaToValue()
6177 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true);
6178 FormulaGrammarSwitch
aFGSwitch(m_pDoc
, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1
);
6180 m_pDoc
->InsertTab(0, "Test");
6182 const char* aData
[][3] = {
6183 { "=1", "=RC[-1]*2", "=ISFORMULA(RC[-1])" },
6184 { "=2", "=RC[-1]*2", "=ISFORMULA(RC[-1])" },
6185 { "=3", "=RC[-1]*2", "=ISFORMULA(RC[-1])" },
6186 { "=4", "=RC[-1]*2", "=ISFORMULA(RC[-1])" },
6187 { "=5", "=RC[-1]*2", "=ISFORMULA(RC[-1])" },
6188 { "=6", "=RC[-1]*2", "=ISFORMULA(RC[-1])" },
6191 ScAddress
aPos(1,2,0); // B3
6192 ScRange aDataRange
= insertRangeData(m_pDoc
, aPos
, aData
, SAL_N_ELEMENTS(aData
));
6193 CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange
.aStart
== aPos
);
6196 // Expected output table content. 0 = empty cell
6197 const char* aOutputCheck
[][3] = {
6198 { "1", "2", "TRUE" },
6199 { "2", "4", "TRUE" },
6200 { "3", "6", "TRUE" },
6201 { "4", "8", "TRUE" },
6202 { "5", "10", "TRUE" },
6203 { "6", "12", "TRUE" },
6206 bool bSuccess
= checkOutput
<3>(m_pDoc
, aDataRange
, aOutputCheck
, "Initial value");
6207 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6210 // Convert B5:C6 to static values, and check the result.
6211 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
6212 ScRange
aConvRange(1,4,0,2,5,0); // B5:C6
6213 rFunc
.ConvertFormulaToValue(aConvRange
, true, false);
6216 // Expected output table content. 0 = empty cell
6217 const char* aOutputCheck
[][3] = {
6218 { "1", "2", "TRUE" },
6219 { "2", "4", "TRUE" },
6220 { "3", "6", "FALSE" },
6221 { "4", "8", "FALSE" },
6222 { "5", "10", "TRUE" },
6223 { "6", "12", "TRUE" },
6226 bool bSuccess
= checkOutput
<3>(m_pDoc
, aDataRange
, aOutputCheck
, "Converted");
6227 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6230 // Make sure that B3:B4 and B7:B8 are formula cells.
6231 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,2,0)) == CELLTYPE_FORMULA
);
6232 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,3,0)) == CELLTYPE_FORMULA
);
6233 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,6,0)) == CELLTYPE_FORMULA
);
6234 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,7,0)) == CELLTYPE_FORMULA
);
6236 // Make sure that B5:C6 are numeric cells.
6237 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,4,0)) == CELLTYPE_VALUE
);
6238 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,5,0)) == CELLTYPE_VALUE
);
6239 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(2,4,0)) == CELLTYPE_VALUE
);
6240 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(2,5,0)) == CELLTYPE_VALUE
);
6242 // Make sure that formula cells in C3:C4 and C7:C8 are grouped.
6243 const ScFormulaCell
* pFC
= m_pDoc
->GetFormulaCell(ScAddress(2,2,0));
6244 CPPUNIT_ASSERT(pFC
);
6245 CPPUNIT_ASSERT(pFC
->GetSharedTopRow() == 2);
6246 CPPUNIT_ASSERT(pFC
->GetSharedLength() == 2);
6247 pFC
= m_pDoc
->GetFormulaCell(ScAddress(2,6,0));
6248 CPPUNIT_ASSERT(pFC
);
6249 CPPUNIT_ASSERT(pFC
->GetSharedTopRow() == 6);
6250 CPPUNIT_ASSERT(pFC
->GetSharedLength() == 2);
6253 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
6254 CPPUNIT_ASSERT(pUndoMgr
);
6258 // Expected output table content. 0 = empty cell
6259 const char* aOutputCheck
[][3] = {
6260 { "1", "2", "TRUE" },
6261 { "2", "4", "TRUE" },
6262 { "3", "6", "TRUE" },
6263 { "4", "8", "TRUE" },
6264 { "5", "10", "TRUE" },
6265 { "6", "12", "TRUE" },
6268 bool bSuccess
= checkOutput
<3>(m_pDoc
, aDataRange
, aOutputCheck
, "After undo");
6269 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6272 // B3:B8 should all be (ungrouped) formula cells.
6273 for (SCROW i
= 2; i
<= 7; ++i
)
6275 pFC
= m_pDoc
->GetFormulaCell(ScAddress(1,i
,0));
6276 CPPUNIT_ASSERT(pFC
);
6277 CPPUNIT_ASSERT(!pFC
->IsShared());
6280 // C3:C8 should be shared formula cells.
6281 pFC
= m_pDoc
->GetFormulaCell(ScAddress(2,2,0));
6282 CPPUNIT_ASSERT(pFC
);
6283 CPPUNIT_ASSERT(pFC
->GetSharedTopRow() == 2);
6284 CPPUNIT_ASSERT(pFC
->GetSharedLength() == 6);
6289 // Expected output table content. 0 = empty cell
6290 const char* aOutputCheck
[][3] = {
6291 { "1", "2", "TRUE" },
6292 { "2", "4", "TRUE" },
6293 { "3", "6", "FALSE" },
6294 { "4", "8", "FALSE" },
6295 { "5", "10", "TRUE" },
6296 { "6", "12", "TRUE" },
6299 bool bSuccess
= checkOutput
<3>(m_pDoc
, aDataRange
, aOutputCheck
, "Converted");
6300 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6303 // Make sure that B3:B4 and B7:B8 are formula cells.
6304 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,2,0)) == CELLTYPE_FORMULA
);
6305 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,3,0)) == CELLTYPE_FORMULA
);
6306 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,6,0)) == CELLTYPE_FORMULA
);
6307 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,7,0)) == CELLTYPE_FORMULA
);
6309 // Make sure that B5:C6 are numeric cells.
6310 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,4,0)) == CELLTYPE_VALUE
);
6311 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(1,5,0)) == CELLTYPE_VALUE
);
6312 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(2,4,0)) == CELLTYPE_VALUE
);
6313 CPPUNIT_ASSERT(m_pDoc
->GetCellType(ScAddress(2,5,0)) == CELLTYPE_VALUE
);
6315 // Make sure that formula cells in C3:C4 and C7:C8 are grouped.
6316 pFC
= m_pDoc
->GetFormulaCell(ScAddress(2,2,0));
6317 CPPUNIT_ASSERT(pFC
);
6318 CPPUNIT_ASSERT(pFC
->GetSharedTopRow() == 2);
6319 CPPUNIT_ASSERT(pFC
->GetSharedLength() == 2);
6320 pFC
= m_pDoc
->GetFormulaCell(ScAddress(2,6,0));
6321 CPPUNIT_ASSERT(pFC
);
6322 CPPUNIT_ASSERT(pFC
->GetSharedTopRow() == 6);
6323 CPPUNIT_ASSERT(pFC
->GetSharedLength() == 2);
6325 // Undo again and make sure the recovered formulas in C5:C6 still track B5:B6.
6327 m_pDoc
->SetValue(ScAddress(1,4,0), 10);
6328 m_pDoc
->SetValue(ScAddress(1,5,0), 11);
6329 CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc
->GetValue(ScAddress(2,4,0)));
6330 CPPUNIT_ASSERT_EQUAL(22.0, m_pDoc
->GetValue(ScAddress(2,5,0)));
6332 m_pDoc
->DeleteTab(0);
6335 void Test::testFormulaToValue2()
6337 sc::AutoCalcSwitch
aACSwitch(*m_pDoc
, true);
6338 FormulaGrammarSwitch
aFGSwitch(m_pDoc
, formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1
);
6340 m_pDoc
->InsertTab(0, "Test");
6342 const char* aData
[][2] = {
6343 { "=1", "=ISFORMULA(RC[-1])" },
6344 { "=2", "=ISFORMULA(RC[-1])" },
6345 { "3", "=ISFORMULA(RC[-1])" },
6346 { "=4", "=ISFORMULA(RC[-1])" },
6347 { "=5", "=ISFORMULA(RC[-1])" },
6350 // Insert data into B2:C6.
6351 ScAddress
aPos(1,1,0); // B2
6352 ScRange aDataRange
= insertRangeData(m_pDoc
, aPos
, aData
, SAL_N_ELEMENTS(aData
));
6353 CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange
.aStart
== aPos
);
6356 // Expected output table content. 0 = empty cell
6357 const char* aOutputCheck
[][2] = {
6365 bool bSuccess
= checkOutput
<2>(m_pDoc
, aDataRange
, aOutputCheck
, "Initial value");
6366 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6369 // Convert B3:B5 to a value.
6370 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
6371 ScRange
aConvRange(1,2,0,1,4,0); // B3:B5
6372 rFunc
.ConvertFormulaToValue(aConvRange
, true, false);
6375 // Expected output table content. 0 = empty cell
6376 const char* aOutputCheck
[][2] = {
6384 bool bSuccess
= checkOutput
<2>(m_pDoc
, aDataRange
, aOutputCheck
, "Initial value");
6385 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6389 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
6390 CPPUNIT_ASSERT(pUndoMgr
);
6394 // Expected output table content. 0 = empty cell
6395 const char* aOutputCheck
[][2] = {
6403 bool bSuccess
= checkOutput
<2>(m_pDoc
, aDataRange
, aOutputCheck
, "Initial value");
6404 CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess
);
6407 m_pDoc
->DeleteTab(0);
6410 void Test::testMixData()
6412 m_pDoc
->InsertTab(0, "Test");
6414 m_pDoc
->SetValue(ScAddress(1,0,0), 2.0); // B1
6415 m_pDoc
->SetValue(ScAddress(0,1,0), 3.0); // A2
6417 // Copy A1:B1 to the clip document.
6418 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
6419 copyToClip(m_pDoc
, ScRange(0,0,0,1,0,0), &aClipDoc
); // A1:B1
6421 // Copy A2:B2 to the mix document (for arithemetic paste).
6422 ScDocument
aMixDoc(SCDOCMODE_CLIP
);
6423 copyToClip(m_pDoc
, ScRange(0,1,0,1,1,0), &aMixDoc
); // A2:B2
6425 // Paste A1:B1 to A2:B2 and perform addition.
6426 pasteFromClip(m_pDoc
, ScRange(0,1,0,1,1,0), &aClipDoc
);
6427 m_pDoc
->MixDocument(ScRange(0,1,0,1,1,0), PASTE_ADD
, false, &aMixDoc
);
6429 CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc
->GetValue(0,1,0)); // A2
6430 CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc
->GetValue(1,1,0)); // B2
6432 // Clear everything and start over.
6433 clearSheet(m_pDoc
, 0);
6434 clearSheet(&aClipDoc
, 0);
6435 clearSheet(&aMixDoc
, 0);
6437 // Set values to A1, A2, and B1. B2 will remain empty.
6438 m_pDoc
->SetValue(ScAddress(0,0,0), 15.0);
6439 m_pDoc
->SetValue(ScAddress(0,1,0), 16.0);
6440 m_pDoc
->SetValue(ScAddress(1,0,0), 12.0);
6441 CPPUNIT_ASSERT_MESSAGE("B2 should be empty.", m_pDoc
->GetCellType(ScAddress(1,1,0)) == CELLTYPE_NONE
);
6443 // Copy A1:A2 and paste it onto B1:B2 with subtraction operation.
6444 copyToClip(m_pDoc
, ScRange(0,0,0,0,1,0), &aClipDoc
);
6445 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetValue(ScAddress(0,0,0)), aClipDoc
.GetValue(ScAddress(0,0,0)));
6446 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetValue(ScAddress(0,1,0)), aClipDoc
.GetValue(ScAddress(0,1,0)));
6448 copyToClip(m_pDoc
, ScRange(1,0,0,1,1,0), &aMixDoc
);
6449 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetValue(ScAddress(1,0,0)), aMixDoc
.GetValue(ScAddress(1,0,0)));
6450 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetValue(ScAddress(1,1,0)), aMixDoc
.GetValue(ScAddress(1,1,0)));
6452 pasteFromClip(m_pDoc
, ScRange(1,0,0,1,1,0), &aClipDoc
);
6453 m_pDoc
->MixDocument(ScRange(1,0,0,1,1,0), PASTE_SUB
, false, &aMixDoc
);
6455 CPPUNIT_ASSERT_EQUAL( -3.0, m_pDoc
->GetValue(ScAddress(1,0,0))); // 12 - 15
6456 CPPUNIT_ASSERT_EQUAL(-16.0, m_pDoc
->GetValue(ScAddress(1,1,0))); // 0 - 16
6458 m_pDoc
->DeleteTab(0);
6461 void Test::testSetStringAndNote()
6463 m_pDoc
->InsertTab(0, "Test");
6466 ScAddress
aAdrA1 (0, 0, 0);
6467 ScPostIt
* pNote
= m_pDoc
->GetOrCreateNote(aAdrA1
);
6468 pNote
->SetText(aAdrA1
, "Hello world in A1");
6470 m_pDoc
->SetString(0, 0, 0, "");
6472 pNote
= m_pDoc
->GetNote(aAdrA1
);
6473 CPPUNIT_ASSERT(pNote
);
6475 m_pDoc
->DeleteTab(0);
6478 void Test::testCopyPasteMatrixFormula()
6480 m_pDoc
->InsertTab(0, "hcv");
6482 // Set Values to B1, C1, D1
6483 m_pDoc
->SetValue(ScAddress(1,0,0), 2.0); // B1
6484 m_pDoc
->SetValue(ScAddress(2,0,0), 5.0); // C1
6485 m_pDoc
->SetValue(ScAddress(3,0,0), 3.0); // D1
6487 // Set Values to B2, C2
6488 m_pDoc
->SetString(ScAddress(1,1,0), "B2"); // B2
6489 //m_pDoc->SetString(ScAddress(2,1,0), "C2"); // C2
6490 m_pDoc
->SetString(ScAddress(3,1,0), "D2"); // D2
6492 // Set Vallues to D3
6493 //m_pDoc->SetValue(ScAddress(1,2,0), 9.0); // B3
6494 //m_pDoc->SetString(ScAddress(2,2,0), "C3"); // C3
6495 m_pDoc
->SetValue(ScAddress(3,2,0), 11.0); // D3
6497 // Insert matrix formula to A1
6499 aMark
.SelectOneTable(0);
6500 m_pDoc
->InsertMatrixFormula(0, 0, 0, 0, aMark
, "=COUNTIF(ISBLANK(B1:D1);TRUE())");
6502 // A1 should containg 0
6503 CPPUNIT_ASSERT_EQUAL( 0.0, m_pDoc
->GetValue(ScAddress(0,0,0)) ); // A1
6505 // Copy cell A1 to clipboard.
6506 ScAddress
aPos(0,0,0); // A1
6507 ScDocument
aClipDoc(SCDOCMODE_CLIP
);
6508 ScClipParam
aParam(aPos
, false);
6509 m_pDoc
->CopyToClip(aParam
, &aClipDoc
, &aMark
);
6510 // Formula string should be equal.
6511 CPPUNIT_ASSERT_EQUAL(m_pDoc
->GetString(aPos
), aClipDoc
.GetString(aPos
));
6513 // First try single range.
6514 // Paste matrix formula to A2
6515 pasteFromClip(m_pDoc
, ScRange(0,1,0,0,1,0), &aClipDoc
); // A2
6516 // A2 Cell value should contain 1.0
6517 CPPUNIT_ASSERT_EQUAL( 1.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
6519 // Paste matrix formula to A3
6520 pasteFromClip(m_pDoc
, ScRange(0,2,0,0,2,0), &aClipDoc
); // A3
6521 // A3 Cell value should contain 2.0
6522 CPPUNIT_ASSERT_EQUAL( 2.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
6524 // Paste matrix formula to A4
6525 pasteFromClip(m_pDoc
, ScRange(0,3,0,0,3,0), &aClipDoc
); // A4
6526 // A4 Cell value should contain 3.0
6527 CPPUNIT_ASSERT_EQUAL( 3.0, m_pDoc
->GetValue(ScAddress(0,3,0)));
6530 clearRange(m_pDoc
, ScRange(0,1,0,0,3,0));
6532 // Paste matrix formula to range A2:A4
6533 pasteFromClip(m_pDoc
, ScRange(0,1,0,0,3,0), &aClipDoc
); // A2:A4
6535 // A2 Cell value should contain 1.0
6536 CPPUNIT_ASSERT_EQUAL( 1.0, m_pDoc
->GetValue(ScAddress(0,1,0)));
6537 // A3 Cell value should contain 2.0
6538 CPPUNIT_ASSERT_EQUAL( 2.0, m_pDoc
->GetValue(ScAddress(0,2,0)));
6539 // A4 Cell value should contain 3.0
6540 CPPUNIT_ASSERT_EQUAL( 3.0, m_pDoc
->GetValue(ScAddress(0,3,0)));
6542 m_pDoc
->DeleteTab(0);
6545 void Test::testUndoDataAnchor()
6547 m_pDoc
->InsertTab(0, "Tab1");
6548 CPPUNIT_ASSERT_MESSAGE("There should be only 1 sheets to begin with", m_pDoc
->GetTableCount() == 1);
6550 m_pDoc
->InitDrawLayer();
6551 ScDrawLayer
* pDrawLayer
= m_pDoc
->GetDrawLayer();
6552 CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer
);
6553 SdrPage
* pPage
= pDrawLayer
->GetPage(0);
6554 CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage
);
6556 // Insert an object.
6557 Rectangle
aObjRect(2,1000,100,1100);
6558 SdrObject
* pObj
= new SdrRectObj(aObjRect
);
6559 pPage
->InsertObject(pObj
);
6560 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *m_pDoc
, 0);
6563 ScDrawObjData
* pData
= ScDrawLayer::GetObjData(pObj
, false);
6564 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
6566 ScAddress aOldStart
= pData
->maStart
;
6567 ScAddress aOldEnd
= pData
->maEnd
;
6569 // Get non rotated anchor data
6570 ScDrawObjData
* pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
6571 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
6573 ScAddress aNOldStart
= pNData
->maStart
;
6574 ScAddress aNOldEnd
= pNData
->maEnd
;
6575 CPPUNIT_ASSERT_EQUAL(aOldStart
, aNOldStart
);
6576 CPPUNIT_ASSERT_EQUAL(aOldEnd
, aNOldEnd
);
6578 //pDrawLayer->BeginCalcUndo(false);
6579 // Insert a new row at row 3.
6580 ScDocFunc
& rFunc
= getDocShell().GetDocFunc();
6582 aMark
.SelectOneTable(0);
6583 rFunc
.InsertCells(ScRange( 0, aOldStart
.Row() - 1, 0, MAXCOL
, aOldStart
.Row(), 0 ), &aMark
, INS_INSROWS
, true, true, false);
6585 pData
= ScDrawLayer::GetObjData(pObj
, false);
6586 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
6588 ScAddress aNewStart
= pData
->maStart
;
6589 ScAddress aNewEnd
= pData
->maEnd
;
6591 // Get non rotated anchor data
6592 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
6593 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
6595 ScAddress aNNewStart
= pNData
->maStart
;
6596 ScAddress aNNewEnd
= pNData
->maEnd
;
6597 CPPUNIT_ASSERT_EQUAL(aNewStart
, aNNewStart
);
6598 CPPUNIT_ASSERT_EQUAL(aNewEnd
, aNNewEnd
);
6599 CPPUNIT_ASSERT_MESSAGE("Failed to compare Address.", aNewStart
!= aOldStart
&& aNewEnd
!= aOldEnd
&&
6600 aNNewStart
!= aNOldStart
&& aNNewEnd
!= aNOldEnd
);
6602 SfxUndoManager
* pUndoMgr
= m_pDoc
->GetUndoManager();
6603 CPPUNIT_ASSERT(pUndoMgr
);
6607 ScAnchorType oldType
= ScDrawLayer::GetAnchorType(*pObj
);
6608 CPPUNIT_ASSERT_MESSAGE( "Failed to check state SCA_CELL.", oldType
== SCA_CELL
);
6611 pData
= ScDrawLayer::GetObjData(pObj
, false);
6612 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
6614 // Get non rotated anchor data
6615 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
6616 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
6618 // Check if data has moved to new rows
6619 CPPUNIT_ASSERT_EQUAL(pData
->maStart
, aOldStart
);
6620 CPPUNIT_ASSERT_EQUAL(pData
->maEnd
, aOldEnd
);
6622 CPPUNIT_ASSERT_EQUAL(pNData
->maStart
, aNOldStart
);
6623 CPPUNIT_ASSERT_EQUAL(pNData
->maEnd
, aNOldEnd
);
6628 pData
= ScDrawLayer::GetObjData(pObj
, false);
6629 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData
);
6631 // Get non rotated anchor data
6632 pNData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
6633 CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData
);
6635 // Check if data has moved to new rows
6636 CPPUNIT_ASSERT_EQUAL(pData
->maStart
, aNewStart
);
6637 CPPUNIT_ASSERT_EQUAL(pData
->maEnd
, aNewEnd
);
6639 CPPUNIT_ASSERT_EQUAL(pNData
->maStart
, aNNewStart
);
6640 CPPUNIT_ASSERT_EQUAL(pNData
->maEnd
, aNNewEnd
);
6642 m_pDoc
->DeleteTab(0);
6645 ScDocShell
* Test::findLoadedDocShellByName(const OUString
& rName
)
6647 TypeId
aType(TYPE(ScDocShell
));
6648 ScDocShell
* pShell
= static_cast<ScDocShell
*>(SfxObjectShell::GetFirst(&aType
, false));
6651 SfxMedium
* pMedium
= pShell
->GetMedium();
6654 OUString aName
= pMedium
->GetName();
6655 if (aName
.equals(rName
))
6658 pShell
= static_cast<ScDocShell
*>(SfxObjectShell::GetNext(*pShell
, &aType
, false));
6663 bool Test::insertRangeNames(
6664 ScDocument
* pDoc
, ScRangeName
* pNames
, const RangeNameDef
* p
, const RangeNameDef
* pEnd
)
6666 ScAddress
aA1(0, 0, 0);
6667 for (; p
!= pEnd
; ++p
)
6669 ScRangeData
* pNew
= new ScRangeData(
6671 OUString::createFromAscii(p
->mpName
),
6672 OUString::createFromAscii(p
->mpExpr
),
6673 aA1
, 0, formula::FormulaGrammar::GRAM_ENGLISH
);
6674 pNew
->SetIndex(p
->mnIndex
);
6675 bool bSuccess
= pNames
->insert(pNew
);
6678 cerr
<< "Insertion failed." << endl
;
6686 void Test::printRange(ScDocument
* pDoc
, const ScRange
& rRange
, const char* pCaption
)
6688 SCROW nRow1
= rRange
.aStart
.Row(), nRow2
= rRange
.aEnd
.Row();
6689 SCCOL nCol1
= rRange
.aStart
.Col(), nCol2
= rRange
.aEnd
.Col();
6690 svl::GridPrinter
printer(nRow2
- nRow1
+ 1, nCol2
- nCol1
+ 1, CALC_DEBUG_OUTPUT
!= 0);
6691 for (SCROW nRow
= nRow1
; nRow
<= nRow2
; ++nRow
)
6693 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
6695 OUString aVal
= pDoc
->GetString(nCol
, nRow
, rRange
.aStart
.Tab());
6696 printer
.set(nRow
-nRow1
, nCol
-nCol1
, aVal
);
6699 printer
.print(pCaption
);
6702 void Test::clearRange(ScDocument
* pDoc
, const ScRange
& rRange
)
6704 ScMarkData aMarkData
;
6705 aMarkData
.SetMarkArea(rRange
);
6707 rRange
.aStart
.Col(), rRange
.aStart
.Row(),
6708 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), aMarkData
, IDF_CONTENTS
);
6711 void Test::clearSheet(ScDocument
* pDoc
, SCTAB nTab
)
6713 ScRange
aRange(0,0,nTab
,MAXCOL
,MAXROW
,nTab
);
6714 clearRange(pDoc
, aRange
);
6717 void Test::copyToClip(ScDocument
* pSrcDoc
, const ScRange
& rRange
, ScDocument
* pClipDoc
)
6719 ScClipParam
aClipParam(rRange
, false);
6721 aMark
.SetMarkArea(rRange
);
6722 pSrcDoc
->CopyToClip(aClipParam
, pClipDoc
, &aMark
);
6725 void Test::pasteFromClip(ScDocument
* pDestDoc
, const ScRange
& rDestRange
, ScDocument
* pClipDoc
)
6728 aMark
.SetMarkArea(rDestRange
);
6729 pDestDoc
->CopyFromClip(rDestRange
, aMark
, IDF_ALL
, NULL
, pClipDoc
);
6732 ScUndoPaste
* Test::createUndoPaste(ScDocShell
& rDocSh
, const ScRange
& rRange
, ScDocument
* pUndoDoc
)
6734 ScDocument
& rDoc
= rDocSh
.GetDocument();
6735 ScMarkData aMarkData
;
6736 aMarkData
.SetMarkArea(rRange
);
6737 ScRefUndoData
* pRefUndoData
= new ScRefUndoData(&rDoc
);
6739 return new ScUndoPaste(
6740 &rDocSh
, rRange
, aMarkData
, pUndoDoc
, NULL
, IDF_ALL
, pRefUndoData
, false);
6743 void Test::setExpandRefs(bool bExpand
)
6745 ScModule
* pMod
= SC_MOD();
6746 ScInputOptions aOpt
= pMod
->GetInputOptions();
6747 aOpt
.SetExpandRefs(bExpand
);
6748 pMod
->SetInputOptions(aOpt
);
6751 void Test::setCalcAsShown(ScDocument
* pDoc
, bool bCalcAsShown
)
6753 ScDocOptions aOpt
= pDoc
->GetDocOptions();
6754 aOpt
.SetCalcAsShown(bCalcAsShown
);
6755 pDoc
->SetDocOptions(aOpt
);
6758 CPPUNIT_TEST_SUITE_REGISTRATION(Test
);
6760 CPPUNIT_PLUGIN_IMPLEMENT();
6762 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */