Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License. You may obtain a copy of the License at
8 : : * http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * The Initial Developer of the Original Code is
16 : : * Novell, Inc.
17 : : * Portions created by the Initial Developer are Copyright (C) 2010 the
18 : : * Initial Developer. All Rights Reserved.
19 : : *
20 : : * Contributor(s): Michael Meeks <michael.meeks@novell.com>
21 : : * Kohei Yoshida <kyoshida@novell.com>
22 : : *
23 : : * Alternatively, the contents of this file may be used under the terms of
24 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 : : * instead of those above.
28 : : */
29 : : #include <sal/config.h>
30 : : #include <test/bootstrapfixture.hxx>
31 : :
32 : : #include <rtl/strbuf.hxx>
33 : : #include <osl/file.hxx>
34 : :
35 : : #include "scdll.hxx"
36 : : #include "document.hxx"
37 : : #include "stringutil.hxx"
38 : : #include "scmatrix.hxx"
39 : : #include "drwlayer.hxx"
40 : : #include "scitems.hxx"
41 : : #include "reffind.hxx"
42 : : #include "markdata.hxx"
43 : : #include "clipparam.hxx"
44 : : #include "refundo.hxx"
45 : : #include "undoblk.hxx"
46 : : #include "undotab.hxx"
47 : : #include "queryentry.hxx"
48 : : #include "postit.hxx"
49 : : #include "attrib.hxx"
50 : : #include "dbdata.hxx"
51 : : #include "reftokenhelper.hxx"
52 : : #include "userdat.hxx"
53 : :
54 : : #include "docsh.hxx"
55 : : #include "docfunc.hxx"
56 : : #include "dbdocfun.hxx"
57 : : #include "funcdesc.hxx"
58 : : #include "externalrefmgr.hxx"
59 : :
60 : : #include "dpshttab.hxx"
61 : : #include "dpobject.hxx"
62 : : #include "dpsave.hxx"
63 : : #include "dpdimsave.hxx"
64 : : #include "dpcache.hxx"
65 : : #include "calcconfig.hxx"
66 : : #include "interpre.hxx"
67 : :
68 : : #include "formula/IFunctionDescription.hxx"
69 : :
70 : : #include <basegfx/polygon/b2dpolygon.hxx>
71 : : #include <editeng/boxitem.hxx>
72 : :
73 : : #include <svx/svdograf.hxx>
74 : : #include <svx/svdpage.hxx>
75 : : #include <svx/svdocirc.hxx>
76 : : #include <svx/svdopath.hxx>
77 : :
78 : : #include <sfx2/docfile.hxx>
79 : :
80 : : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
81 : : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
82 : : #include <com/sun/star/sheet/GeneralFunction.hpp>
83 : :
84 : : #include <ucbhelper/contentbroker.hxx>
85 : :
86 : : #include <iostream>
87 : : #include <vector>
88 : :
89 : : #define CALC_DEBUG_OUTPUT 0
90 : :
91 : : #include "helper/debughelper.hxx"
92 : :
93 : : const int indeterminate = 2;
94 : :
95 : : using namespace ::com::sun::star;
96 : : using ::rtl::OUString;
97 : : using ::rtl::OUStringBuffer;
98 : : using ::std::cout;
99 : : using ::std::cerr;
100 : : using ::std::endl;
101 : : using ::std::vector;
102 : :
103 : : namespace {
104 : :
105 [ + - ][ - + ]: 270 : class Test : public test::BootstrapFixture {
106 : : public:
107 : : Test();
108 : :
109 : : virtual void setUp();
110 : : virtual void tearDown();
111 : :
112 : : void testCollator();
113 : : void testInput();
114 : : void testCellFunctions();
115 : :
116 : : /**
117 : : * Make sure the SHEETS function gets properly updated during sheet
118 : : * insertion and removal.
119 : : */
120 : : void testSheetsFunc();
121 : : void testVolatileFunc();
122 : : void testFuncParam();
123 : : void testNamedRange();
124 : : void testCSV();
125 : : void testMatrix();
126 : :
127 : : /**
128 : : * Basic test for pivot tables.
129 : : */
130 : : void testPivotTable();
131 : :
132 : : /**
133 : : * Test against unwanted automatic format detection on field names and
134 : : * field members in pivot tables.
135 : : */
136 : : void testPivotTableLabels();
137 : :
138 : : /**
139 : : * Make sure that we set cells displaying date values numeric cells,
140 : : * rather than text cells. Grouping by date or number functionality
141 : : * depends on this.
142 : : */
143 : : void testPivotTableDateLabels();
144 : :
145 : : /**
146 : : * Test for pivot table's filtering functionality by page fields.
147 : : */
148 : : void testPivotTableFilters();
149 : :
150 : : /**
151 : : * Test for pivot table's named source range.
152 : : */
153 : : void testPivotTableNamedSource();
154 : :
155 : : /**
156 : : * Test for pivot table cache. Each dimension in the pivot cache stores
157 : : * only unique values that are sorted in ascending order.
158 : : */
159 : : void testPivotTableCache();
160 : :
161 : : /**
162 : : * Test for pivot table containing data fields that reference the same
163 : : * source field but different functions.
164 : : */
165 : : void testPivotTableDuplicateDataFields();
166 : :
167 : : void testPivotTableNormalGrouping();
168 : : void testPivotTableNumberGrouping();
169 : : void testPivotTableDateGrouping();
170 : : void testPivotTableEmptyRows();
171 : : void testPivotTableTextNumber();
172 : :
173 : : /**
174 : : * Test for checking that pivot table treats strings in a case insensitive
175 : : * manner.
176 : : */
177 : : void testPivotTableCaseInsensitiveStrings();
178 : :
179 : : void testSheetCopy();
180 : : void testSheetMove();
181 : : void testExternalRef();
182 : : void testExternalRefFunctions();
183 : : void testDataArea();
184 : : void testAutofilter();
185 : : void testCopyPaste();
186 : : void testMergedCells();
187 : : void testUpdateReference();
188 : :
189 : : /**
190 : : * Make sure the sheet streams are invalidated properly.
191 : : */
192 : : void testStreamValid();
193 : :
194 : : /**
195 : : * Test built-in cell functions to make sure their categories and order
196 : : * are correct.
197 : : */
198 : : void testFunctionLists();
199 : :
200 : : void testGraphicsInGroup();
201 : : void testGraphicsOnSheetMove();
202 : :
203 : : void testPostIts();
204 : :
205 : : /**
206 : : * Test toggling relative/absolute flag of cell and cell range references.
207 : : * This corresponds with hitting Shift-F4 while the cursor is on a formula
208 : : * cell.
209 : : */
210 : : void testToggleRefFlag();
211 : :
212 : : /**
213 : : * Test to make sure correct precedent / dependent cells are obtained when
214 : : * preparing to jump to them.
215 : : */
216 : : void testJumpToPrecedentsDependents();
217 : :
218 : : void testSetBackgroundColor();
219 : : void testRenameTable();
220 : :
221 : : void testAutoFill();
222 : : void testCopyPasteFormulas();
223 : : void testCopyPasteFormulasExternalDoc();
224 : :
225 : : void testFindAreaPosRowDown();
226 : : void testFindAreaPosColRight();
227 : :
228 [ + - ][ + - ]: 6 : CPPUNIT_TEST_SUITE(Test);
[ + - ][ + - ]
[ # # ]
229 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testCollator);
[ + - ][ + - ]
[ + - ][ + - ]
230 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testInput);
[ + - ][ + - ]
[ + - ][ + - ]
231 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testCellFunctions);
[ + - ][ + - ]
[ + - ][ + - ]
232 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testSheetsFunc);
[ + - ][ + - ]
[ + - ][ + - ]
233 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testVolatileFunc);
[ + - ][ + - ]
[ + - ][ + - ]
234 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testFuncParam);
[ + - ][ + - ]
[ + - ][ + - ]
235 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testNamedRange);
[ + - ][ + - ]
[ + - ][ + - ]
236 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testCSV);
[ + - ][ + - ]
[ + - ][ + - ]
237 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testMatrix);
[ + - ][ + - ]
[ + - ][ + - ]
238 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTable);
[ + - ][ + - ]
[ + - ][ + - ]
239 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableLabels);
[ + - ][ + - ]
[ + - ][ + - ]
240 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableDateLabels);
[ + - ][ + - ]
[ + - ][ + - ]
241 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableFilters);
[ + - ][ + - ]
[ + - ][ + - ]
242 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableNamedSource);
[ + - ][ + - ]
[ + - ][ + - ]
243 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableCache);
[ + - ][ + - ]
[ + - ][ + - ]
244 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableDuplicateDataFields);
[ + - ][ + - ]
[ + - ][ + - ]
245 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableNormalGrouping);
[ + - ][ + - ]
[ + - ][ + - ]
246 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableNumberGrouping);
[ + - ][ + - ]
[ + - ][ + - ]
247 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableDateGrouping);
[ + - ][ + - ]
[ + - ][ + - ]
248 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableEmptyRows);
[ + - ][ + - ]
[ + - ][ + - ]
249 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableTextNumber);
[ + - ][ + - ]
[ + - ][ + - ]
250 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPivotTableCaseInsensitiveStrings);
[ + - ][ + - ]
[ + - ][ + - ]
251 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testSheetCopy);
[ + - ][ + - ]
[ + - ][ + - ]
252 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testSheetMove);
[ + - ][ + - ]
[ + - ][ + - ]
253 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testExternalRef);
[ + - ][ + - ]
[ + - ][ + - ]
254 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testExternalRefFunctions);
[ + - ][ + - ]
[ + - ][ + - ]
255 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testDataArea);
[ + - ][ + - ]
[ + - ][ + - ]
256 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testGraphicsInGroup);
[ + - ][ + - ]
[ + - ][ + - ]
257 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testGraphicsOnSheetMove);
[ + - ][ + - ]
[ + - ][ + - ]
258 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testPostIts);
[ + - ][ + - ]
[ + - ][ + - ]
259 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testStreamValid);
[ + - ][ + - ]
[ + - ][ + - ]
260 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testFunctionLists);
[ + - ][ + - ]
[ + - ][ + - ]
261 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testToggleRefFlag);
[ + - ][ + - ]
[ + - ][ + - ]
262 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testAutofilter);
[ + - ][ + - ]
[ + - ][ + - ]
263 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testCopyPaste);
[ + - ][ + - ]
[ + - ][ + - ]
264 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testMergedCells);
[ + - ][ + - ]
[ + - ][ + - ]
265 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testUpdateReference);
[ + - ][ + - ]
[ + - ][ + - ]
266 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testJumpToPrecedentsDependents);
[ + - ][ + - ]
[ + - ][ + - ]
267 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testSetBackgroundColor);
[ + - ][ + - ]
[ + - ][ + - ]
268 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testRenameTable);
[ + - ][ + - ]
[ + - ][ + - ]
269 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testAutoFill);
[ + - ][ + - ]
[ + - ][ + - ]
270 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testCopyPasteFormulas);
[ + - ][ + - ]
[ + - ][ + - ]
271 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testCopyPasteFormulasExternalDoc);
[ + - ][ + - ]
[ + - ][ + - ]
272 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testFindAreaPosRowDown);
[ + - ][ + - ]
[ + - ][ + - ]
273 [ + - ][ + - ]: 3 : CPPUNIT_TEST(testFindAreaPosColRight);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
274 [ + - ][ + - ]: 6 : CPPUNIT_TEST_SUITE_END();
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
275 : :
276 : : private:
277 : : ScDocument *m_pDoc;
278 : : ScDocShellRef m_xDocShRef;
279 : : };
280 : :
281 : 36 : void clearRange(ScDocument* pDoc, const ScRange& rRange)
282 : : {
283 [ + - ]: 36 : ScMarkData aMarkData;
284 [ + - ]: 36 : aMarkData.SetMarkArea(rRange);
285 : : pDoc->DeleteArea(
286 : 36 : rRange.aStart.Col(), rRange.aStart.Row(),
287 [ + - ][ + - ]: 72 : rRange.aEnd.Col(), rRange.aEnd.Row(), aMarkData, IDF_CONTENTS);
288 : 36 : }
289 : :
290 : 63 : void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption)
291 : : {
292 : 63 : SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
293 : 63 : SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
294 [ + - ]: 63 : SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
295 [ + + ]: 651 : for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
296 : : {
297 [ + + ]: 2184 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
298 : : {
299 : 1596 : rtl::OUString aVal;
300 [ + - ]: 1596 : pDoc->GetString(nCol, nRow, rRange.aStart.Tab(), aVal);
301 [ + - ]: 1596 : printer.set(nRow-nRow1, nCol-nCol1, aVal);
302 : 1596 : }
303 : : }
304 [ + - ]: 63 : printer.print(pCaption);
305 : 63 : }
306 : :
307 : : template<size_t _Size>
308 : 30 : ScRange insertRangeData(ScDocument* pDoc, const ScAddress& rPos, const char* aData[][_Size], size_t nRowCount)
309 : : {
310 [ + + ][ + + ]: 117 : for (size_t i = 0; i < _Size; ++i)
[ + + ][ + + ]
311 : : {
312 [ + + ][ + + ]: 789 : for (size_t j = 0; j < nRowCount; ++j)
[ + + ][ + + ]
313 : : {
314 : 702 : SCCOL nCol = i + rPos.Col();
315 : 702 : SCROW nRow = j + rPos.Row();
316 [ + - ][ + - ]: 702 : pDoc->SetString(nCol, nRow, rPos.Tab(), OUString(aData[j][i], strlen(aData[j][i]), RTL_TEXTENCODING_UTF8));
[ + - ][ + - ]
317 : : }
318 : : }
319 : :
320 : 30 : ScRange aRange(rPos);
321 : 30 : aRange.aEnd.SetCol(rPos.Col()+_Size-1);
322 : 30 : aRange.aEnd.SetRow(rPos.Row()+nRowCount-1);
323 : 30 : printRange(pDoc, aRange, "Range data content");
324 : 30 : return aRange;
325 : : }
326 : :
327 : 135 : Test::Test()
328 : 135 : : m_pDoc(0)
329 : : {
330 : 135 : }
331 : :
332 : 135 : void Test::setUp()
333 : : {
334 : 135 : BootstrapFixture::setUp();
335 : :
336 : 135 : ScDLL::Init();
337 : : m_xDocShRef = new ScDocShell(
338 : : SFXMODEL_STANDARD |
339 : : SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
340 [ + - ]: 135 : SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
341 : :
342 : 135 : m_pDoc = m_xDocShRef->GetDocument();
343 : 135 : }
344 : :
345 : 135 : void Test::tearDown()
346 : : {
347 : 135 : m_xDocShRef.Clear();
348 : 135 : BootstrapFixture::tearDown();
349 : 135 : }
350 : :
351 : 3 : void Test::testCollator()
352 : : {
353 : 3 : OUString s1("A");
354 : 3 : OUString s2("B");
355 [ + - ]: 3 : CollatorWrapper* p = ScGlobal::GetCollator();
356 [ + - ]: 3 : sal_Int32 nRes = p->compareString(s1, s2);
357 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("these strings are supposed to be different!", nRes != 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
358 : 3 : }
359 : :
360 : 3 : void Test::testInput()
361 : : {
362 : 3 : rtl::OUString aTabName("foo");
363 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
364 [ + - ]: 3 : m_pDoc->InsertTab (0, aTabName));
365 : :
366 : 3 : OUString numstr("'10.5");
367 : 3 : OUString str("'apple'");
368 : 3 : OUString test;
369 : :
370 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, numstr);
371 [ + - ]: 3 : m_pDoc->GetString(0, 0, 0, test);
372 : 3 : bool bTest = test == "10.5";
373 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("String number should have the first apostrophe stripped.", bTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
374 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, str);
375 [ + - ]: 3 : m_pDoc->GetString(0, 0, 0, test);
376 : 3 : bTest = test == "'apple'";
377 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Text content should have retained the first apostrophe.", bTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
378 : :
379 : : // Customized string handling policy.
380 [ + - ]: 3 : ScSetStringParam aParam;
381 : 3 : aParam.mbDetectNumberFormat = false;
382 : 3 : aParam.meSetTextNumFormat = ScSetStringParam::Always;
383 : 3 : aParam.mbHandleApostrophe = false;
384 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, "000123", &aParam);
385 [ + - ]: 3 : m_pDoc->GetString(0, 0, 0, test);
386 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Text content should have been treated as string, not number.", test == "000123");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
387 : :
388 [ + - ]: 3 : m_pDoc->DeleteTab(0);
389 : 3 : }
390 : :
391 : 3 : void testFuncSUM(ScDocument* pDoc)
392 : : {
393 : 3 : double val = 1;
394 : : double result;
395 [ + - ]: 3 : pDoc->SetValue (0, 0, 0, val);
396 [ + - ]: 3 : pDoc->SetValue (0, 1, 0, val);
397 [ + - ]: 3 : pDoc->SetString (0, 2, 0, rtl::OUString("=SUM(A1:A2)"));
398 [ + - ]: 3 : pDoc->CalcAll();
399 [ + - ]: 3 : pDoc->GetValue (0, 2, 0, result);
400 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 2.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
401 : 3 : }
402 : :
403 : 3 : void testFuncPRODUCT(ScDocument* pDoc)
404 : : {
405 : 3 : double val = 1;
406 : : double result;
407 [ + - ]: 3 : pDoc->SetValue(0, 0, 0, val);
408 : 3 : val = 2;
409 [ + - ]: 3 : pDoc->SetValue(0, 1, 0, val);
410 : 3 : val = 3;
411 [ + - ]: 3 : pDoc->SetValue(0, 2, 0, val);
412 [ + - ]: 3 : pDoc->SetString(0, 3, 0, OUString("=PRODUCT(A1:A3)"));
413 [ + - ]: 3 : pDoc->CalcAll();
414 [ + - ]: 3 : pDoc->GetValue(0, 3, 0, result);
415 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT failed", result == 6.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
416 : :
417 [ + - ]: 3 : pDoc->SetString(0, 4, 0, OUString("=PRODUCT({1;2;3})"));
418 [ + - ]: 3 : pDoc->CalcAll();
419 [ + - ]: 3 : pDoc->GetValue(0, 4, 0, result);
420 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT with inline array failed", result == 6.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
421 : 3 : }
422 : :
423 : 3 : void testFuncN(ScDocument* pDoc)
424 : : {
425 : : double result;
426 : :
427 : : // Clear the area first.
428 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 1, 20, 0));
429 : :
430 : : // Put values to reference.
431 : 3 : double val = 0;
432 [ + - ]: 3 : pDoc->SetValue(0, 0, 0, val);
433 [ + - ]: 3 : pDoc->SetString(0, 2, 0, OUString("Text"));
434 : 3 : val = 1;
435 [ + - ]: 3 : pDoc->SetValue(0, 3, 0, val);
436 : 3 : val = -1;
437 [ + - ]: 3 : pDoc->SetValue(0, 4, 0, val);
438 : 3 : val = 12.3;
439 [ + - ]: 3 : pDoc->SetValue(0, 5, 0, val);
440 [ + - ]: 3 : pDoc->SetString(0, 6, 0, OUString("'12.3"));
441 : :
442 : : // Cell references
443 [ + - ]: 3 : pDoc->SetString(1, 0, 0, OUString("=N(A1)"));
444 [ + - ]: 3 : pDoc->SetString(1, 1, 0, OUString("=N(A2)"));
445 [ + - ]: 3 : pDoc->SetString(1, 2, 0, OUString("=N(A3)"));
446 [ + - ]: 3 : pDoc->SetString(1, 3, 0, OUString("=N(A4)"));
447 [ + - ]: 3 : pDoc->SetString(1, 4, 0, OUString("=N(A5)"));
448 [ + - ]: 3 : pDoc->SetString(1, 5, 0, OUString("=N(A6)"));
449 [ + - ]: 3 : pDoc->SetString(1, 6, 0, OUString("=N(A9)"));
450 : :
451 : : // In-line values
452 [ + - ]: 3 : pDoc->SetString(1, 7, 0, OUString("=N(0)"));
453 [ + - ]: 3 : pDoc->SetString(1, 8, 0, OUString("=N(1)"));
454 [ + - ]: 3 : pDoc->SetString(1, 9, 0, OUString("=N(-1)"));
455 [ + - ]: 3 : pDoc->SetString(1, 10, 0, OUString("=N(123)"));
456 [ + - ]: 3 : pDoc->SetString(1, 11, 0, OUString("=N(\"\")"));
457 [ + - ]: 3 : pDoc->SetString(1, 12, 0, OUString("=N(\"12\")"));
458 [ + - ]: 3 : pDoc->SetString(1, 13, 0, OUString("=N(\"foo\")"));
459 : :
460 : : // Range references
461 [ + - ]: 3 : pDoc->SetString(2, 2, 0, OUString("=N(A1:A8)"));
462 [ + - ]: 3 : pDoc->SetString(2, 3, 0, OUString("=N(A1:A8)"));
463 [ + - ]: 3 : pDoc->SetString(2, 4, 0, OUString("=N(A1:A8)"));
464 [ + - ]: 3 : pDoc->SetString(2, 5, 0, OUString("=N(A1:A8)"));
465 : :
466 : : // Calculate and check the results.
467 [ + - ]: 3 : pDoc->CalcAll();
468 : : double checks1[] = {
469 : : 0, 0, 0, 1, -1, 12.3, 0, // cell reference
470 : : 0, 1, -1, 123, 0, 0, 0 // in-line values
471 : 3 : };
472 [ + + ]: 45 : for (size_t i = 0; i < SAL_N_ELEMENTS(checks1); ++i)
473 : : {
474 [ + - ]: 42 : pDoc->GetValue(1, i, 0, result);
475 : 42 : bool bGood = result == checks1[i];
476 [ - + ]: 42 : if (!bGood)
477 : : {
478 [ # # ][ # # ]: 0 : cerr << "row " << (i+1) << ": expected=" << checks1[i] << " actual=" << result << endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
479 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for N", false);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
480 : : }
481 : : }
482 : : double checks2[] = {
483 : : 0, 1, -1, 12.3 // range references
484 : 3 : };
485 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(checks2); ++i)
486 : : {
487 [ + - ]: 12 : pDoc->GetValue(1, i+2, 0, result);
488 : 12 : bool bGood = result == checks2[i];
489 [ - + ]: 12 : if (!bGood)
490 : : {
491 [ # # ][ # # ]: 0 : cerr << "row " << (i+2+1) << ": expected=" << checks2[i] << " actual=" << result << endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
492 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for N", false);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
493 : : }
494 : : }
495 : 3 : }
496 : :
497 : 3 : void testFuncCOUNTIF(ScDocument* pDoc)
498 : : {
499 : : // COUNTIF (test case adopted from OOo i#36381)
500 : :
501 : : // Empty A1:A39 first.
502 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 0, 40, 0));
503 : :
504 : : // Raw data (rows 1 through 9)
505 : : const char* aData[] = {
506 : : "1999",
507 : : "2000",
508 : : "0",
509 : : "0",
510 : : "0",
511 : : "2002",
512 : : "2001",
513 : : "X",
514 : : "2002"
515 : 3 : };
516 : :
517 : 3 : SCROW nRows = SAL_N_ELEMENTS(aData);
518 [ + + ]: 30 : for (SCROW i = 0; i < nRows; ++i)
519 [ + - ]: 27 : pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aData[i]));
520 : :
521 [ + - ]: 3 : printRange(pDoc, ScRange(0, 0, 0, 0, 8, 0), "data range for COUNTIF");
522 : :
523 : : // formulas and results
524 : : struct {
525 : : const char* pFormula; double fResult;
526 : : } aChecks[] = {
527 : : { "=COUNTIF(A1:A12;1999)", 1 },
528 : : { "=COUNTIF(A1:A12;2002)", 2 },
529 : : { "=COUNTIF(A1:A12;1998)", 0 },
530 : : { "=COUNTIF(A1:A12;\">=1999\")", 5 },
531 : : { "=COUNTIF(A1:A12;\">1999\")", 4 },
532 : : { "=COUNTIF(A1:A12;\"<2001\")", 5 },
533 : : { "=COUNTIF(A1:A12;\">0\")", 5 },
534 : : { "=COUNTIF(A1:A12;\">=0\")", 8 },
535 : : { "=COUNTIF(A1:A12;0)", 3 },
536 : : { "=COUNTIF(A1:A12;\"X\")", 1 },
537 : : { "=COUNTIF(A1:A12;)", 3 }
538 : 3 : };
539 : :
540 : 3 : nRows = SAL_N_ELEMENTS(aChecks);
541 [ + + ]: 36 : for (SCROW i = 0; i < nRows; ++i)
542 : : {
543 : 33 : SCROW nRow = 20 + i;
544 [ + - ]: 33 : pDoc->SetString(0, nRow, 0, rtl::OUString::createFromAscii(aChecks[i].pFormula));
545 : : }
546 [ + - ]: 3 : pDoc->CalcAll();
547 : :
548 [ + + ]: 36 : for (SCROW i = 0; i < nRows; ++i)
549 : : {
550 : : double result;
551 : 33 : SCROW nRow = 20 + i;
552 [ + - ]: 33 : pDoc->GetValue(0, nRow, 0, result);
553 : 33 : bool bGood = result == aChecks[i].fResult;
554 [ - + ]: 33 : if (!bGood)
555 : : {
556 [ # # ][ # # ]: 0 : cerr << "row " << (nRow+1) << ": formula" << aChecks[i].pFormula
[ # # ][ # # ]
557 [ # # ][ # # ]: 0 : << " expected=" << aChecks[i].fResult << " actual=" << result << endl;
[ # # ][ # # ]
[ # # ]
558 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for COUNTIF", false);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
559 : : }
560 : : }
561 : :
562 : : // Don't count empty strings when searching for a number.
563 : :
564 : : // Clear A1:A2.
565 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 0, 1, 0));
566 : :
567 [ + - ]: 3 : pDoc->SetString(0, 0, 0, rtl::OUString("=\"\""));
568 [ + - ]: 3 : pDoc->SetString(0, 1, 0, rtl::OUString("=COUNTIF(A1;1)"));
569 [ + - ]: 3 : pDoc->CalcAll();
570 : :
571 [ + - ]: 3 : double result = pDoc->GetValue(0, 1, 0);
572 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("We shouldn't count empty string as valid number.", result == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
573 : 3 : }
574 : :
575 : 3 : void testFuncVLOOKUP(ScDocument* pDoc)
576 : : {
577 : : // VLOOKUP
578 : :
579 : : // Clear A1:F40.
580 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 5, 39, 0));
581 : :
582 : : // Raw data
583 : : const char* aData[][2] = {
584 : : { "Key", "Val" },
585 : : { "10", "3" },
586 : : { "20", "4" },
587 : : { "30", "5" },
588 : : { "40", "6" },
589 : : { "50", "7" },
590 : : { "60", "8" },
591 : : { "70", "9" },
592 : : { "B", "10" },
593 : : { "B", "11" },
594 : : { "C", "12" },
595 : : { "D", "13" },
596 : : { "E", "14" },
597 : : { "F", "15" },
598 : : { 0, 0 } // terminator
599 : 3 : };
600 : :
601 : : // Insert raw data into A1:B14.
602 [ + + ]: 45 : for (SCROW i = 0; aData[i][0]; ++i)
603 : : {
604 [ + - ]: 42 : pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aData[i][0]));
605 [ + - ]: 42 : pDoc->SetString(1, i, 0, rtl::OUString::createFromAscii(aData[i][1]));
606 : : }
607 : :
608 [ + - ]: 3 : printRange(pDoc, ScRange(0, 0, 0, 1, 13, 0), "raw data for VLOOKUP");
609 : :
610 : : // Formula data
611 : : struct {
612 : : const char* pLookup; const char* pFormula; const char* pRes;
613 : : } aChecks[] = {
614 : : { "Lookup", "Formula", 0 },
615 : : { "12", "=VLOOKUP(D2;A2:B14;2;1)", "3" },
616 : : { "29", "=VLOOKUP(D3;A2:B14;2;1)", "4" },
617 : : { "31", "=VLOOKUP(D4;A2:B14;2;1)", "5" },
618 : : { "45", "=VLOOKUP(D5;A2:B14;2;1)", "6" },
619 : : { "56", "=VLOOKUP(D6;A2:B14;2;1)", "7" },
620 : : { "65", "=VLOOKUP(D7;A2:B14;2;1)", "8" },
621 : : { "78", "=VLOOKUP(D8;A2:B14;2;1)", "9" },
622 : : { "Andy", "=VLOOKUP(D9;A2:B14;2;1)", "#N/A" },
623 : : { "Bruce", "=VLOOKUP(D10;A2:B14;2;1)", "11" },
624 : : { "Charlie", "=VLOOKUP(D11;A2:B14;2;1)", "12" },
625 : : { "David", "=VLOOKUP(D12;A2:B14;2;1)", "13" },
626 : : { "Edward", "=VLOOKUP(D13;A2:B14;2;1)", "14" },
627 : : { "Frank", "=VLOOKUP(D14;A2:B14;2;1)", "15" },
628 : : { "Henry", "=VLOOKUP(D15;A2:B14;2;1)", "15" },
629 : : { "100", "=VLOOKUP(D16;A2:B14;2;1)", "9" },
630 : : { "1000", "=VLOOKUP(D17;A2:B14;2;1)", "9" },
631 : : { "Zena", "=VLOOKUP(D18;A2:B14;2;1)", "15" }
632 : 3 : };
633 : :
634 : : // Insert formula data into D1:E18.
635 [ + + ]: 57 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
636 : : {
637 [ + - ]: 54 : pDoc->SetString(3, i, 0, rtl::OUString::createFromAscii(aChecks[i].pLookup));
638 [ + - ]: 54 : pDoc->SetString(4, i, 0, rtl::OUString::createFromAscii(aChecks[i].pFormula));
639 : : }
640 [ + - ]: 3 : pDoc->CalcAll();
641 [ + - ]: 3 : printRange(pDoc, ScRange(3, 0, 0, 4, 17, 0), "formula data for VLOOKUP");
642 : :
643 : : // Verify results.
644 [ + + ]: 57 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
645 : : {
646 [ + + ]: 54 : if (i == 0)
647 : : // Skip the header row.
648 : 3 : continue;
649 : :
650 : 51 : rtl::OUString aRes;
651 [ + - ]: 51 : pDoc->GetString(4, i, 0, aRes);
652 : 51 : bool bGood = aRes.equalsAscii(aChecks[i].pRes);
653 [ - + ]: 51 : if (!bGood)
654 : : {
655 [ # # ][ # # ]: 0 : cerr << "row " << (i+1) << ": lookup value='" << aChecks[i].pLookup
[ # # ][ # # ]
656 [ # # ][ # # ]: 0 : << "' expected='" << aChecks[i].pRes << "' actual='" << aRes << "'" << endl;
[ # # ][ # # ]
[ # # ][ # # ]
657 [ # # ][ # # ]: 0 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for VLOOKUP", false);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
658 : : }
659 : 51 : }
660 : 3 : }
661 : :
662 : : struct NumStrCheck {
663 : : double fVal;
664 : : const char* pRes;
665 : : };
666 : :
667 : : struct StrStrCheck {
668 : : const char* pVal;
669 : : const char* pRes;
670 : : };
671 : :
672 : : template<size_t _DataSize, size_t _FormulaSize, int _Type>
673 : 6 : void runTestMATCH(ScDocument* pDoc, const char* aData[_DataSize], StrStrCheck aChecks[_FormulaSize])
674 : : {
675 : 6 : size_t nDataSize = _DataSize;
676 [ + + ][ + + ]: 78 : for (size_t i = 0; i < nDataSize; ++i)
677 [ + - ][ + - ]: 72 : pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aData[i]));
678 : :
679 [ + + ][ + + ]: 99 : for (size_t i = 0; i < _FormulaSize; ++i)
680 : : {
681 [ + - ][ + - ]: 93 : pDoc->SetString(1, i, 0, rtl::OUString::createFromAscii(aChecks[i].pVal));
682 : :
683 : 93 : rtl::OUStringBuffer aBuf;
684 [ + - + - ]: 93 : aBuf.appendAscii("=MATCH(B");
685 [ + - ][ + - ]: 93 : aBuf.append(static_cast<sal_Int32>(i+1));
686 [ + - ][ + - ]: 93 : aBuf.appendAscii(";A1:A");
687 [ + - ][ + - ]: 93 : aBuf.append(static_cast<sal_Int32>(nDataSize));
688 [ + - ][ + - ]: 93 : aBuf.appendAscii(";");
689 [ + - ][ + - ]: 93 : aBuf.append(static_cast<sal_Int32>(_Type));
690 [ + - ][ + - ]: 93 : aBuf.appendAscii(")");
691 [ + - ][ + - ]: 93 : rtl::OUString aFormula = aBuf.makeStringAndClear();
692 [ + - ][ + - ]: 93 : pDoc->SetString(2, i, 0, aFormula);
693 : : }
694 : :
695 : 6 : pDoc->CalcAll();
696 [ + - + - ]: 6 : printRange(pDoc, ScRange(0, 0, 0, 2, _FormulaSize-1, 0), "MATCH");
697 : :
698 : : // verify the results.
699 [ + + ][ + + ]: 99 : for (size_t i = 0; i < _FormulaSize; ++i)
700 : : {
701 : 93 : rtl::OUString aStr;
702 [ + - + - ]: 93 : pDoc->GetString(2, i, 0, aStr);
703 [ - + ][ - + ]: 93 : if (!aStr.equalsAscii(aChecks[i].pRes))
704 : : {
705 [ # # ][ # # ]: 0 : cerr << "row " << (i+1) << ": expected='" << aChecks[i].pRes << "' actual='" << aStr << "'"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
706 : : << " criterion='" << aChecks[i].pVal << "'" << endl;
707 [ # # ][ # # ]: 93 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for MATCH", false);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
708 : : }
709 : : }
710 : 6 : }
711 : :
712 : 3 : void testFuncMATCH(ScDocument* pDoc)
713 : : {
714 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 4, 40, 0));
715 : : {
716 : : // Ascending in-exact match
717 : :
718 : : // data range (A1:A9)
719 : : const char* aData[] = {
720 : : "1",
721 : : "2",
722 : : "3",
723 : : "4",
724 : : "5",
725 : : "6",
726 : : "7",
727 : : "8",
728 : : "9",
729 : : "B",
730 : : "B",
731 : : "C",
732 : 3 : };
733 : :
734 : : // formula (B1:C12)
735 : : StrStrCheck aChecks[] = {
736 : : { "0.8", "#N/A" },
737 : : { "1.2", "1" },
738 : : { "2.3", "2" },
739 : : { "3.9", "3" },
740 : : { "4.1", "4" },
741 : : { "5.99", "5" },
742 : : { "6.1", "6" },
743 : : { "7.2", "7" },
744 : : { "8.569", "8" },
745 : : { "9.59", "9" },
746 : : { "10", "9" },
747 : : { "100", "9" },
748 : : { "Andy", "#N/A" },
749 : : { "Bruce", "11" },
750 : : { "Charlie", "12" }
751 : 3 : };
752 : :
753 [ + - ]: 3 : runTestMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),1>(pDoc, aData, aChecks);
754 : : }
755 : :
756 : : {
757 : : // Descending in-exact match
758 : :
759 : : // data range (A1:A9)
760 : : const char* aData[] = {
761 : : "D",
762 : : "C",
763 : : "B",
764 : : "9",
765 : : "8",
766 : : "7",
767 : : "6",
768 : : "5",
769 : : "4",
770 : : "3",
771 : : "2",
772 : : "1"
773 : 3 : };
774 : :
775 : : // formula (B1:C12)
776 : : StrStrCheck aChecks[] = {
777 : : { "10", "#N/A" },
778 : : { "8.9", "4" },
779 : : { "7.8", "5" },
780 : : { "6.7", "6" },
781 : : { "5.5", "7" },
782 : : { "4.6", "8" },
783 : : { "3.3", "9" },
784 : : { "2.2", "10" },
785 : : { "1.1", "11" },
786 : : { "0.8", "12" },
787 : : { "0", "12" },
788 : : { "-2", "12" },
789 : : { "Andy", "3" },
790 : : { "Bruce", "2" },
791 : : { "Charlie", "1" },
792 : : { "David", "#N/A" }
793 : 3 : };
794 : :
795 [ + - ]: 3 : runTestMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),-1>(pDoc, aData, aChecks);
796 : : }
797 : 3 : }
798 : :
799 : 3 : void testFuncCELL(ScDocument* pDoc)
800 : : {
801 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 2, 20, 0)); // Clear A1:C21.
802 : :
803 : : {
804 : 3 : const char* pContent = "Some random text";
805 [ + - ]: 3 : pDoc->SetString(2, 9, 0, rtl::OUString::createFromAscii(pContent)); // Set this value to C10.
806 : 3 : double val = 1.2;
807 [ + - ]: 3 : pDoc->SetValue(2, 0, 0, val); // Set numeric value to C1;
808 : :
809 : : // We don't test: FILENAME, FORMAT, WIDTH, PROTECT, PREFIX
810 : : StrStrCheck aChecks[] = {
811 : : { "=CELL(\"COL\";C10)", "3" },
812 : : { "=CELL(\"ROW\";C10)", "10" },
813 : : { "=CELL(\"SHEET\";C10)", "1" },
814 : : { "=CELL(\"ADDRESS\";C10)", "$C$10" },
815 : : { "=CELL(\"CONTENTS\";C10)", pContent },
816 : : { "=CELL(\"COLOR\";C10)", "0" },
817 : : { "=CELL(\"TYPE\";C9)", "b" },
818 : : { "=CELL(\"TYPE\";C10)", "l" },
819 : : { "=CELL(\"TYPE\";C1)", "v" },
820 : : { "=CELL(\"PARENTHESES\";C10)", "0" }
821 : 3 : };
822 : :
823 [ + + ]: 33 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
824 [ + - ]: 30 : pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aChecks[i].pVal));
825 [ + - ]: 3 : pDoc->CalcAll();
826 : :
827 [ + + ]: 33 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
828 : : {
829 [ + - ]: 30 : rtl::OUString aVal = pDoc->GetString(0, i, 0);
830 [ + - ][ + - ]: 30 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for CELL", aVal.equalsAscii(aChecks[i].pRes));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
831 : 30 : }
832 : : }
833 : 3 : }
834 : :
835 : : /** See also test case document fdo#44456 sheet cpearson */
836 : 3 : void testFuncDATEDIF( ScDocument* pDoc )
837 : : {
838 : : const char* aData[][5] = {
839 : : { "2007-01-01", "2007-01-10", "d", "9", "=DATEDIF(A1;B1;C1)" } ,
840 : : { "2007-01-01", "2007-01-31", "m", "0", "=DATEDIF(A2;B2;C2)" } ,
841 : : { "2007-01-01", "2007-02-01", "m", "1", "=DATEDIF(A3;B3;C3)" } ,
842 : : { "2007-01-01", "2007-02-28", "m", "1", "=DATEDIF(A4;B4;C4)" } ,
843 : : { "2007-01-01", "2007-12-31", "d", "364", "=DATEDIF(A5;B5;C5)" } ,
844 : : { "2007-01-01", "2007-01-31", "y", "0", "=DATEDIF(A6;B6;C6)" } ,
845 : : { "2007-01-01", "2008-07-01", "d", "547", "=DATEDIF(A7;B7;C7)" } ,
846 : : { "2007-01-01", "2008-07-01", "m", "18", "=DATEDIF(A8;B8;C8)" } ,
847 : : { "2007-01-01", "2008-07-01", "ym", "6", "=DATEDIF(A9;B9;C9)" } ,
848 : : { "2007-01-01", "2008-07-01", "yd", "182", "=DATEDIF(A10;B10;C10)" } ,
849 : : { "2008-01-01", "2009-07-01", "yd", "181", "=DATEDIF(A11;B11;C11)" } ,
850 : : { "2007-01-01", "2007-01-31", "md", "30", "=DATEDIF(A12;B12;C12)" } ,
851 : : { "2007-02-01", "2009-03-01", "md", "0", "=DATEDIF(A13;B13;C13)" } ,
852 : : { "2008-02-01", "2009-03-01", "md", "0", "=DATEDIF(A14;B14;C14)" } ,
853 : : { "2007-01-02", "2007-01-01", "md", "Err:502", "=DATEDIF(A15;B15;C15)" } // fail date1 > date2
854 : 3 : };
855 : :
856 [ + - ]: 3 : clearRange( pDoc, ScRange(0, 0, 0, 4, SAL_N_ELEMENTS(aData), 0));
857 : 3 : ScAddress aPos(0,0,0);
858 [ + - ]: 3 : ScRange aDataRange = insertRangeData( pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
859 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
860 : :
861 [ + - ]: 3 : pDoc->CalcAll();
862 : :
863 [ + + ]: 48 : for (size_t i = 0; i < SAL_N_ELEMENTS(aData); ++i)
864 : : {
865 [ + - ]: 45 : rtl::OUString aVal = pDoc->GetString( 4, i, 0);
866 : : //std::cout << "row "<< i << ": " << rtl::OUStringToOString( aVal, RTL_TEXTENCODING_UTF8).getStr() << ", expected " << aData[i][3] << std::endl;
867 [ + - ][ + - ]: 45 : CPPUNIT_ASSERT_MESSAGE("Unexpected result for DATEDIF", aVal.equalsAscii( aData[i][3]));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
868 : 45 : }
869 : 3 : }
870 : :
871 : 3 : void testFuncINDIRECT(ScDocument* pDoc)
872 : : {
873 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 0, 10, 0)); // Clear A1:A11
874 : 3 : rtl::OUString aTabName;
875 [ + - ]: 3 : bool bGood = pDoc->GetName(0, aTabName);
876 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to get sheet name.", bGood);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
877 : :
878 : 3 : rtl::OUString aTest = "Test", aRefErr = "#REF!";
879 [ + - ]: 3 : pDoc->SetString(0, 10, 0, aTest);
880 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", pDoc->GetString(0,10,0) == aTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
881 : :
882 : 3 : rtl::OUString aPrefix = "=INDIRECT(\"";
883 : :
884 : 3 : rtl::OUString aFormula = aPrefix + aTabName + ".A11\")"; // Calc A1
885 [ + - ]: 3 : pDoc->SetString(0, 0, 0, aFormula);
886 : 3 : aFormula = aPrefix + aTabName + "!A11\")"; // Excel A1
887 [ + - ]: 3 : pDoc->SetString(0, 1, 0, aFormula);
888 : 3 : aFormula = aPrefix + aTabName + "!R11C1\")"; // Excel R1C1
889 [ + - ]: 3 : pDoc->SetString(0, 2, 0, aFormula);
890 : 3 : aFormula = aPrefix + aTabName + "!R11C1\";0)"; // Excel R1C1 (forced)
891 [ + - ]: 3 : pDoc->SetString(0, 3, 0, aFormula);
892 : :
893 [ + - ]: 3 : pDoc->CalcAll();
894 : : {
895 : : // Default is to use the current formula syntax, which is Calc A1.
896 : : const rtl::OUString* aChecks[] = {
897 : : &aTest, &aRefErr, &aRefErr, &aTest
898 : 3 : };
899 : :
900 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
901 : : {
902 [ + - ]: 12 : rtl::OUString aVal = pDoc->GetString(0, i, 0);
903 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
904 : 12 : }
905 : : }
906 : :
907 [ + - ]: 3 : ScCalcConfig aConfig;
908 : 3 : aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_OOO;
909 [ + - ]: 3 : ScInterpreter::SetGlobalConfig(aConfig);
910 [ + - ]: 3 : pDoc->CalcAll();
911 : : {
912 : : // Explicit Calc A1 syntax
913 : : const rtl::OUString* aChecks[] = {
914 : : &aTest, &aRefErr, &aRefErr, &aTest
915 : 3 : };
916 : :
917 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
918 : : {
919 [ + - ]: 12 : rtl::OUString aVal = pDoc->GetString(0, i, 0);
920 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
921 : 12 : }
922 : : }
923 : :
924 : 3 : aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_XL_A1;
925 [ + - ]: 3 : ScInterpreter::SetGlobalConfig(aConfig);
926 [ + - ]: 3 : pDoc->CalcAll();
927 : : {
928 : : // Excel A1 syntax
929 : : const rtl::OUString* aChecks[] = {
930 : : &aRefErr, &aTest, &aRefErr, &aTest
931 : 3 : };
932 : :
933 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
934 : : {
935 [ + - ]: 12 : rtl::OUString aVal = pDoc->GetString(0, i, 0);
936 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
937 : 12 : }
938 : : }
939 : :
940 : 3 : aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_XL_R1C1;
941 [ + - ]: 3 : ScInterpreter::SetGlobalConfig(aConfig);
942 [ + - ]: 3 : pDoc->CalcAll();
943 : : {
944 : : // Excel R1C1 syntax
945 : : const rtl::OUString* aChecks[] = {
946 : : &aRefErr, &aRefErr, &aTest, &aTest
947 : 3 : };
948 : :
949 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
950 : : {
951 [ + - ]: 12 : rtl::OUString aVal = pDoc->GetString(0, i, 0);
952 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
953 : 12 : }
954 : 3 : }
955 : 3 : }
956 : :
957 : 3 : void Test::testCellFunctions()
958 : : {
959 : 3 : rtl::OUString aTabName("foo");
960 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
961 [ + - ]: 3 : m_pDoc->InsertTab (0, aTabName));
962 : :
963 [ + - ]: 3 : testFuncSUM(m_pDoc);
964 [ + - ]: 3 : testFuncPRODUCT(m_pDoc);
965 [ + - ]: 3 : testFuncN(m_pDoc);
966 [ + - ]: 3 : testFuncCOUNTIF(m_pDoc);
967 [ + - ]: 3 : testFuncVLOOKUP(m_pDoc);
968 [ + - ]: 3 : testFuncMATCH(m_pDoc);
969 [ + - ]: 3 : testFuncCELL(m_pDoc);
970 [ + - ]: 3 : testFuncDATEDIF(m_pDoc);
971 [ + - ]: 3 : testFuncINDIRECT(m_pDoc);
972 : :
973 [ + - ]: 3 : m_pDoc->DeleteTab(0);
974 : 3 : }
975 : :
976 : 3 : void Test::testSheetsFunc()
977 : : {
978 : 3 : rtl::OUString aTabName1("test1");
979 : 3 : rtl::OUString aTabName2("test2");
980 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
981 [ + - ]: 3 : m_pDoc->InsertTab (SC_TAB_APPEND, aTabName1));
982 : :
983 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, OUString("=SHEETS()"));
984 [ + - ]: 3 : m_pDoc->CalcFormulaTree(false, true);
985 : : double original;
986 [ + - ]: 3 : m_pDoc->GetValue(0, 0, 0, original);
987 : :
988 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("result of SHEETS() should equal the number of sheets, but doesn't.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
989 [ + - ]: 3 : static_cast<SCTAB>(original) == m_pDoc->GetTableCount());
990 : :
991 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
992 [ + - ]: 3 : m_pDoc->InsertTab (SC_TAB_APPEND, aTabName2));
993 : :
994 : : double modified;
995 [ + - ]: 3 : m_pDoc->GetValue(0, 0, 0, modified);
996 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("result of SHEETS() did not get updated after sheet insertion.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
997 [ + - ]: 3 : modified - original == 1.0);
998 : :
999 [ + - ]: 3 : SCTAB nTabCount = m_pDoc->GetTableCount();
1000 [ + - ]: 3 : m_pDoc->DeleteTab(--nTabCount);
1001 : :
1002 [ + - ]: 3 : m_pDoc->GetValue(0, 0, 0, modified);
1003 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("result of SHEETS() did not get updated after sheet removal.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1004 [ + - ]: 3 : modified - original == 0.0);
1005 : :
1006 [ + - ]: 3 : m_pDoc->DeleteTab(--nTabCount);
1007 : 3 : }
1008 : :
1009 : 3 : void Test::testVolatileFunc()
1010 : : {
1011 : 3 : rtl::OUString aTabName("foo");
1012 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1013 [ + - ]: 3 : m_pDoc->InsertTab (0, aTabName));
1014 : :
1015 : 3 : double val = 1;
1016 [ + - ]: 3 : m_pDoc->SetValue(0, 0, 0, val);
1017 [ + - ]: 3 : m_pDoc->SetString(0, 1, 0, OUString("=IF(A1>0;NOW();0"));
1018 : : double now1;
1019 [ + - ]: 3 : m_pDoc->GetValue(0, 1, 0, now1);
1020 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Value of NOW() should be positive.", now1 > 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1021 : :
1022 : 3 : val = 0;
1023 [ + - ]: 3 : m_pDoc->SetValue(0, 0, 0, val);
1024 [ + - ]: 3 : m_pDoc->CalcFormulaTree(false, true);
1025 : : double zero;
1026 [ + - ]: 3 : m_pDoc->GetValue(0, 1, 0, zero);
1027 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Result should equal the 3rd parameter of IF, which is zero.", zero == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1028 : :
1029 : 3 : val = 1;
1030 [ + - ]: 3 : m_pDoc->SetValue(0, 0, 0, val);
1031 [ + - ]: 3 : m_pDoc->CalcFormulaTree(false, true);
1032 : : double now2;
1033 [ + - ]: 3 : m_pDoc->GetValue(0, 1, 0, now2);
1034 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Result should be the value of NOW() again.", (now2 - now1) >= 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1035 : :
1036 [ + - ]: 3 : m_pDoc->DeleteTab(0);
1037 : 3 : }
1038 : :
1039 : 3 : void Test::testFuncParam()
1040 : : {
1041 : 3 : rtl::OUString aTabName("foo");
1042 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1043 [ + - ]: 3 : m_pDoc->InsertTab (0, aTabName));
1044 : :
1045 : : // First, the normal case, with no missing parameters.
1046 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, OUString("=AVERAGE(1;2;3)"));
1047 [ + - ]: 3 : m_pDoc->CalcFormulaTree(false, true);
1048 : : double val;
1049 [ + - ]: 3 : m_pDoc->GetValue(0, 0, 0, val);
1050 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1051 : :
1052 : : // Now function with missing parameters. Missing values should be treated
1053 : : // as zeros.
1054 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, OUString("=AVERAGE(1;;;)"));
1055 [ + - ]: 3 : m_pDoc->CalcFormulaTree(false, true);
1056 [ + - ]: 3 : m_pDoc->GetValue(0, 0, 0, val);
1057 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 0.25);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1058 : :
1059 : : // Conversion of string to numeric argument.
1060 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, OUString("=\"\"+3")); // empty string
1061 [ + - ]: 3 : m_pDoc->SetString(0, 1, 0, OUString("=\" \"+3")); // only blank
1062 [ + - ]: 3 : m_pDoc->SetString(0, 2, 0, OUString("=\" 4 \"+3")); // number in blanks
1063 [ + - ]: 3 : m_pDoc->SetString(0, 3, 0, OUString("=\" x \"+3")); // non-numeric => #VALUE! error
1064 : :
1065 : 3 : rtl::OUString aVal;
1066 [ + - ]: 3 : ScCalcConfig aConfig;
1067 : :
1068 : : // With "Empty string as zero" option.
1069 : 3 : aConfig.mbEmptyStringAsZero = true;
1070 [ + - ]: 3 : ScInterpreter::SetGlobalConfig(aConfig);
1071 [ + - ]: 3 : m_pDoc->CalcAll();
1072 [ + - ]: 3 : m_pDoc->GetValue(0, 0, 0, val);
1073 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1074 [ + - ]: 3 : m_pDoc->GetValue(0, 1, 0, val);
1075 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1076 [ + - ]: 3 : m_pDoc->GetValue(0, 2, 0, val);
1077 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 7);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1078 [ + - ]: 3 : aVal = m_pDoc->GetString( 0, 3, 0);
1079 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1080 : :
1081 : : // Without "Empty string as zero" option.
1082 : 3 : aConfig.mbEmptyStringAsZero = false;
1083 [ + - ]: 3 : ScInterpreter::SetGlobalConfig(aConfig);
1084 [ + - ]: 3 : m_pDoc->CalcAll();
1085 [ + - ]: 3 : aVal = m_pDoc->GetString( 0, 0, 0);
1086 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1087 [ + - ]: 3 : aVal = m_pDoc->GetString( 0, 1, 0);
1088 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1089 [ + - ]: 3 : m_pDoc->GetValue(0, 2, 0, val);
1090 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 7);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1091 [ + - ]: 3 : aVal = m_pDoc->GetString( 0, 3, 0);
1092 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1093 : :
1094 [ + - ]: 3 : m_pDoc->DeleteTab(0);
1095 : 3 : }
1096 : :
1097 : 3 : void Test::testNamedRange()
1098 : : {
1099 : : struct {
1100 : : const char* pName; const char* pExpr; sal_uInt16 nIndex;
1101 : : } aNames[] = {
1102 : : { "Divisor", "$Sheet1.$A$1:$A$1048576", 1 },
1103 : : { "MyRange1", "$Sheet1.$A$1:$A$100", 2 },
1104 : : { "MyRange2", "$Sheet1.$B$1:$B$100", 3 },
1105 : : { "MyRange3", "$Sheet1.$C$1:$C$100", 4 }
1106 : 3 : };
1107 : :
1108 : 3 : rtl::OUString aTabName("Sheet1");
1109 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1110 [ + - ]: 3 : m_pDoc->InsertTab (0, aTabName));
1111 : :
1112 [ + - ]: 3 : m_pDoc->SetValue (0, 0, 0, 101);
1113 : :
1114 : 3 : ScAddress aA1(0, 0, 0);
1115 [ + - ][ + - ]: 3 : ScRangeName* pNewRanges = new ScRangeName();
1116 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
1117 : : {
1118 : : ScRangeData* pNew = new ScRangeData(
1119 : : m_pDoc,
1120 : : rtl::OUString::createFromAscii(aNames[i].pName),
1121 : : rtl::OUString::createFromAscii(aNames[i].pExpr),
1122 [ + - ][ + - ]: 12 : aA1, 0, formula::FormulaGrammar::GRAM_ENGLISH);
[ + - ][ + - ]
1123 : 12 : pNew->SetIndex(aNames[i].nIndex);
1124 [ + - ]: 12 : bool bSuccess = pNewRanges->insert(pNew);
1125 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE ("insertion failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1126 : : }
1127 : :
1128 : : // Make sure the index lookup does the right thing.
1129 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
1130 : : {
1131 [ + - ]: 12 : const ScRangeData* p = pNewRanges->findByIndex(aNames[i].nIndex);
1132 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed.", p);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1133 : 12 : rtl::OUString aName = p->GetName();
1134 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved.", aName.equalsAscii(aNames[i].pName));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1135 : 12 : }
1136 : :
1137 : : // Test usage in formula expression.
1138 [ + - ]: 3 : m_pDoc->SetRangeName(pNewRanges);
1139 [ + - ]: 3 : m_pDoc->SetString (1, 0, 0, rtl::OUString("=A1/Divisor"));
1140 [ + - ]: 3 : m_pDoc->CalcAll();
1141 : :
1142 : : double result;
1143 [ + - ]: 3 : m_pDoc->GetValue (1, 0, 0, result);
1144 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 1.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1145 : :
1146 : : // Test copy-ability of range names.
1147 [ + - ][ + - ]: 3 : ScRangeName* pCopiedRanges = new ScRangeName(*pNewRanges);
1148 [ + - ]: 3 : m_pDoc->SetRangeName(pCopiedRanges);
1149 : : // Make sure the index lookup still works.
1150 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
1151 : : {
1152 [ + - ]: 12 : const ScRangeData* p = pCopiedRanges->findByIndex(aNames[i].nIndex);
1153 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed with the copied instance.", p);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1154 : 12 : rtl::OUString aName = p->GetName();
1155 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved with the copied instance.", aName.equalsAscii(aNames[i].pName));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1156 : 12 : }
1157 : :
1158 [ + - ]: 3 : m_pDoc->SetRangeName(NULL); // Delete the names.
1159 [ + - ]: 3 : m_pDoc->DeleteTab(0);
1160 : 3 : }
1161 : :
1162 : 3 : void Test::testCSV()
1163 : : {
1164 : 3 : const int English = 0, European = 1;
1165 : : struct {
1166 : : const char *pStr; int eSep; bool bResult; double nValue;
1167 : : } aTests[] = {
1168 : : { "foo", English, false, 0.0 },
1169 : : { "1.0", English, true, 1.0 },
1170 : : { "1,0", English, false, 0.0 },
1171 : : { "1.0", European, false, 0.0 },
1172 : : { "1.000", European, true, 1000.0 },
1173 : : { "1,000", European, true, 1.0 },
1174 : : { "1.000", English, true, 1.0 },
1175 : : { "1,000", English, true, 1000.0 },
1176 : : { " 1.0", English, true, 1.0 },
1177 : : { " 1.0 ", English, true, 1.0 },
1178 : : { "1.0 ", European, false, 0.0 },
1179 : : { "1.000", European, true, 1000.0 },
1180 : : { "1137.999", English, true, 1137.999 },
1181 : : { "1.000.00", European, false, 0.0 }
1182 : 3 : };
1183 [ + + ]: 45 : for (sal_uInt32 i = 0; i < SAL_N_ELEMENTS(aTests); i++) {
1184 [ + - ]: 42 : rtl::OUString aStr(aTests[i].pStr, strlen (aTests[i].pStr), RTL_TEXTENCODING_UTF8);
1185 : 42 : double nValue = 0.0;
1186 : : bool bResult = ScStringUtil::parseSimpleNumber
1187 : : (aStr, aTests[i].eSep == English ? '.' : ',',
1188 : : aTests[i].eSep == English ? ',' : '.',
1189 [ + + ][ + + ]: 42 : nValue);
[ + - ]
1190 [ + - ][ + - ]: 42 : CPPUNIT_ASSERT_MESSAGE ("CSV numeric detection failure", bResult == aTests[i].bResult);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1191 [ + - ][ + - ]: 42 : CPPUNIT_ASSERT_MESSAGE ("CSV numeric value failure", nValue == aTests[i].nValue);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1192 : 42 : }
1193 : 3 : }
1194 : :
1195 : : template<typename Evaluator>
1196 : 12 : void checkMatrixElements(const ScMatrix& rMat)
1197 : : {
1198 : : SCSIZE nC, nR;
1199 [ + - ][ + - ]: 12 : rMat.GetDimensions(nC, nR);
[ + - ][ + - ]
1200 : : Evaluator aEval;
1201 [ + + ][ + + ]: 96 : for (SCSIZE i = 0; i < nC; ++i)
[ + + ][ + + ]
1202 : : {
1203 [ + + ][ + + ]: 1524 : for (SCSIZE j = 0; j < nR; ++j)
[ + + ][ + + ]
1204 : : {
1205 [ + - ][ + - ]: 1440 : aEval(i, j, rMat.Get(i, j));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1206 : : }
1207 : : }
1208 : 12 : }
1209 : :
1210 : : struct AllZeroMatrix
1211 : : {
1212 : 120 : void operator() (SCSIZE /*nCol*/, SCSIZE /*nRow*/, const ScMatrixValue& rVal) const
1213 : : {
1214 [ + - ][ + - ]: 120 : CPPUNIT_ASSERT_MESSAGE("element is not of numeric type", rVal.nType == SC_MATVAL_VALUE);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1215 [ + - ][ + - ]: 120 : CPPUNIT_ASSERT_MESSAGE("element value must be zero", rVal.fVal == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1216 : 120 : }
1217 : : };
1218 : :
1219 : : struct PartiallyFilledZeroMatrix
1220 : : {
1221 : 120 : void operator() (SCSIZE nCol, SCSIZE nRow, const ScMatrixValue& rVal) const
1222 : : {
1223 [ + - ][ + - ]: 120 : CPPUNIT_ASSERT_MESSAGE("element is not of numeric type", rVal.nType == SC_MATVAL_VALUE);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1224 [ + + ][ + + ]: 120 : if (1 <= nCol && nCol <= 2 && 2 <= nRow && nRow <= 8)
[ + + ][ + + ]
1225 : : {
1226 [ + - ][ + - ]: 42 : CPPUNIT_ASSERT_MESSAGE("element value must be 3.0", rVal.fVal == 3.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1227 : : }
1228 : : else
1229 : : {
1230 [ + - ][ + - ]: 78 : CPPUNIT_ASSERT_MESSAGE("element value must be zero", rVal.fVal == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1231 : : }
1232 : 120 : }
1233 : : };
1234 : :
1235 : : struct AllEmptyMatrix
1236 : : {
1237 : 600 : void operator() (SCSIZE /*nCol*/, SCSIZE /*nRow*/, const ScMatrixValue& rVal) const
1238 : : {
1239 [ + - ][ + - ]: 600 : CPPUNIT_ASSERT_MESSAGE("element is not of empty type", rVal.nType == SC_MATVAL_EMPTY);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1240 [ + - ][ + - ]: 600 : CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal.fVal == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1241 : 600 : }
1242 : : };
1243 : :
1244 : : struct PartiallyFilledEmptyMatrix
1245 : : {
1246 : 600 : void operator() (SCSIZE nCol, SCSIZE nRow, const ScMatrixValue& rVal) const
1247 : : {
1248 [ + + ][ + + ]: 600 : if (nCol == 1 && nRow == 1)
1249 : : {
1250 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element is not of boolean type", rVal.nType == SC_MATVAL_BOOLEAN);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1251 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.fVal == 1.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1252 : : }
1253 [ + + ][ + + ]: 597 : else if (nCol == 4 && nRow == 5)
1254 : : {
1255 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal.nType == SC_MATVAL_VALUE);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1256 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.fVal == -12.5);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1257 : : }
1258 [ + + ][ + + ]: 594 : else if (nCol == 8 && nRow == 2)
1259 : : {
1260 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal.nType == SC_MATVAL_STRING);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1261 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.aStr == "Test");
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1262 : : }
1263 [ + + ][ + + ]: 591 : else if (nCol == 8 && nRow == 11)
1264 : : {
1265 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("element is not of empty path type", rVal.nType == SC_MATVAL_EMPTYPATH);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1266 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal.fVal == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1267 : : }
1268 : : else
1269 : : {
1270 [ + - ][ + - ]: 588 : CPPUNIT_ASSERT_MESSAGE("element is not of empty type", rVal.nType == SC_MATVAL_EMPTY);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1271 [ + - ][ + - ]: 588 : CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal.fVal == 0.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1272 : : }
1273 : 600 : }
1274 : : };
1275 : :
1276 : 3 : void Test::testMatrix()
1277 : : {
1278 : 3 : ScMatrixRef pMat;
1279 : :
1280 : : // First, test the zero matrix type.
1281 [ + - ][ + - ]: 3 : pMat = new ScMatrix(0, 0, 0.0);
[ + - ]
1282 : : SCSIZE nC, nR;
1283 [ + - ]: 3 : pMat->GetDimensions(nC, nR);
1284 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC == 0 && nR == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ]
1285 [ + - ]: 3 : pMat->Resize(4, 10, 0.0);
1286 [ + - ]: 3 : pMat->GetDimensions(nC, nR);
1287 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 4 && nR == 10);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ]
1288 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("both 'and' and 'or' should evaluate to false",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
1289 [ + - ]: 3 : !pMat->And() && !pMat->Or());
1290 : :
1291 : : // Resizing into a larger matrix should fill the void space with zeros.
1292 [ + - ]: 3 : checkMatrixElements<AllZeroMatrix>(*pMat);
1293 : :
1294 [ + - ]: 3 : pMat->FillDouble(3.0, 1, 2, 2, 8);
1295 [ + - ]: 3 : checkMatrixElements<PartiallyFilledZeroMatrix>(*pMat);
1296 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("matrix is expected to be numeric", pMat->IsNumeric());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1297 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("partially non-zero matrix should evaluate false on 'and' and true on 'or",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
1298 [ + - ]: 3 : !pMat->And() && pMat->Or());
1299 [ + - ]: 3 : pMat->FillDouble(5.0, 0, 0, nC-1, nR-1);
1300 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("fully non-zero matrix should evaluate true both on 'and' and 'or",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
1301 [ + - ]: 3 : pMat->And() && pMat->Or());
1302 : :
1303 : : // Test the AND and OR evaluations.
1304 [ + - ][ + - ]: 3 : pMat = new ScMatrix(2, 2, 0.0);
[ + - ]
1305 : :
1306 : : // Only some of the elements are non-zero.
1307 [ + - ]: 3 : pMat->PutBoolean(true, 0, 0);
1308 [ + - ]: 3 : pMat->PutDouble(1.0, 1, 1);
1309 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1310 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect AND result", !pMat->And());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1311 : :
1312 : : // All of the elements are non-zero.
1313 [ + - ]: 3 : pMat->PutBoolean(true, 0, 1);
1314 [ + - ]: 3 : pMat->PutDouble(2.3, 1, 0);
1315 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1316 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("incorrect AND result", pMat->And());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1317 : :
1318 : : // Now test the emtpy matrix type.
1319 [ + - ][ + - ]: 3 : pMat = new ScMatrix(10, 20);
[ + - ]
1320 [ + - ]: 3 : pMat->GetDimensions(nC, nR);
1321 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 10 && nR == 20);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ]
1322 [ + - ]: 3 : checkMatrixElements<AllEmptyMatrix>(*pMat);
1323 : :
1324 [ + - ]: 3 : pMat->PutBoolean(true, 1, 1);
1325 [ + - ]: 3 : pMat->PutDouble(-12.5, 4, 5);
1326 : 3 : rtl::OUString aStr("Test");
1327 [ + - ]: 3 : pMat->PutString(aStr, 8, 2);
1328 [ + - ]: 3 : pMat->PutEmptyPath(8, 11);
1329 [ + - ][ + - ]: 3 : checkMatrixElements<PartiallyFilledEmptyMatrix>(*pMat);
1330 : 3 : }
1331 : :
1332 : : namespace {
1333 : :
1334 : : struct DPFieldDef
1335 : : {
1336 : : const char* pName;
1337 : : sheet::DataPilotFieldOrientation eOrient;
1338 : :
1339 : : /**
1340 : : * Function for data field. It's used only for data field. When 0, the
1341 : : * default function (SUM) is used.
1342 : : */
1343 : : int eFunc;
1344 : : };
1345 : :
1346 : : template<size_t _Size>
1347 : 15 : ScRange insertDPSourceData(ScDocument* pDoc, DPFieldDef aFields[], size_t nFieldCount, const char* aData[][_Size], size_t nDataCount)
1348 : : {
1349 : : // Insert field names in row 0.
1350 [ + + ][ + + ]: 66 : for (size_t i = 0; i < nFieldCount; ++i)
1351 [ + - ][ + - ]: 51 : pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8));
[ + - ][ + - ]
1352 : :
1353 : : // Insert data into row 1 and downward.
1354 [ + + ][ + + ]: 93 : for (size_t i = 0; i < nDataCount; ++i)
1355 : : {
1356 : 78 : SCROW nRow = static_cast<SCROW>(i) + 1;
1357 [ + + ][ + + ]: 360 : for (size_t j = 0; j < nFieldCount; ++j)
1358 : : {
1359 : 282 : SCCOL nCol = static_cast<SCCOL>(j);
1360 [ + - ][ + - ]: 282 : pDoc->SetString(
[ + - ][ + - ]
1361 : : nCol, nRow, 0, OUString(aData[i][j], strlen(aData[i][j]), RTL_TEXTENCODING_UTF8));
1362 : : }
1363 : : }
1364 : :
1365 : 15 : SCROW nRow1 = 0, nRow2 = 0;
1366 : 15 : SCCOL nCol1 = 0, nCol2 = 0;
1367 [ + - ][ + - ]: 15 : pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false);
1368 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
1369 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_MESSAGE("Unexpected data range.",
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
1370 : : nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount));
1371 : :
1372 : 15 : ScRange aSrcRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
1373 [ + - ][ + - ]: 15 : printRange(pDoc, aSrcRange, "Data sheet content");
1374 : 15 : return aSrcRange;
1375 : : }
1376 : :
1377 : : template<size_t _Size>
1378 : 66 : bool checkDPTableOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* aOutputCheck[][_Size], const char* pCaption)
1379 : : {
1380 : 66 : bool bResult = true;
1381 : 66 : const ScAddress& s = aOutRange.aStart;
1382 : 66 : const ScAddress& e = aOutRange.aEnd;
1383 [ + - ][ + - ]: 66 : SheetPrinter printer(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1);
[ + - ][ + - ]
1384 : 66 : SCROW nOutRowSize = e.Row() - s.Row() + 1;
1385 : 66 : SCCOL nOutColSize = e.Col() - s.Col() + 1;
1386 [ + + ][ + + ]: 519 : for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow)
[ + + ][ + + ]
1387 : : {
1388 [ + + ][ + + ]: 1947 : for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol)
[ + + ][ + + ]
1389 : : {
1390 : 1494 : OUString aVal;
1391 [ + - + - : 1494 : pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal);
+ - + - ]
1392 [ + - ][ + - ]: 1494 : printer.set(nRow, nCol, aVal);
[ + - ][ + - ]
1393 : 1494 : const char* p = aOutputCheck[nRow][nCol];
1394 [ + + ][ + + ]: 1494 : if (p)
[ + + ][ + + ]
1395 : : {
1396 : 1116 : OUString aCheckVal = OUString::createFromAscii(p);
1397 : 1116 : bool bEqual = aCheckVal.equals(aVal);
1398 [ - + - + : 1116 : if (!bEqual)
- + - + ]
1399 : : {
1400 [ # # ][ # # ]: 0 : cout << "Expected: " << aCheckVal << " Actual: " << aVal << endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1401 : 1116 : bResult = false;
1402 : : }
1403 : : }
1404 [ - + ][ - + ]: 378 : else if (!aVal.isEmpty())
[ - + ][ - + ]
1405 : : {
1406 [ # # ][ # # ]: 0 : cout << "Empty cell expected" << endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1407 : 1494 : bResult = false;
1408 : : }
1409 : : }
1410 : : }
1411 : 66 : printer.print(pCaption);
1412 [ + - ][ + - ]: 66 : return bResult;
[ + - ][ + - ]
1413 : : }
1414 : :
1415 : 39 : ScDPObject* createDPFromSourceDesc(
1416 : : ScDocument* pDoc, const ScSheetSourceDesc& rDesc, DPFieldDef aFields[], size_t nFieldCount,
1417 : : bool bFilterButton)
1418 : : {
1419 [ + - ][ + - ]: 39 : ScDPObject* pDPObj = new ScDPObject(pDoc);
1420 [ + - ]: 39 : pDPObj->SetSheetDesc(rDesc);
1421 [ + - ]: 39 : pDPObj->SetOutRange(ScAddress(0, 0, 1));
1422 : :
1423 [ + - ]: 39 : ScDPSaveData aSaveData;
1424 : : // Set data pilot table output options.
1425 [ + - ]: 39 : aSaveData.SetIgnoreEmptyRows(false);
1426 [ + - ]: 39 : aSaveData.SetRepeatIfEmpty(false);
1427 [ + - ]: 39 : aSaveData.SetColumnGrand(true);
1428 [ + - ]: 39 : aSaveData.SetRowGrand(true);
1429 [ + - ]: 39 : aSaveData.SetFilterButton(bFilterButton);
1430 [ + - ]: 39 : aSaveData.SetDrillDown(true);
1431 : :
1432 : : // Check the sanity of the source range.
1433 [ + - ]: 39 : const ScRange& rSrcRange = rDesc.GetSourceRange();
1434 : 39 : SCROW nRow1 = rSrcRange.aStart.Row();
1435 : 39 : SCROW nRow2 = rSrcRange.aEnd.Row();
1436 [ + - ][ + - ]: 39 : CPPUNIT_ASSERT_MESSAGE("source range contains no data!", nRow2 - nRow1 > 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1437 : :
1438 : : // Set the dimension information.
1439 [ + + ]: 144 : for (size_t i = 0; i < nFieldCount; ++i)
1440 : : {
1441 : 105 : OUString aDimName = rtl::OUString::createFromAscii(aFields[i].pName);
1442 [ + - ]: 105 : ScDPSaveDimension* pDim = aSaveData.GetNewDimensionByName(aDimName);
1443 [ + - ]: 105 : pDim->SetOrientation(static_cast<sal_uInt16>(aFields[i].eOrient));
1444 [ + - ]: 105 : pDim->SetUsedHierarchy(0);
1445 : :
1446 [ + + ]: 105 : if (aFields[i].eOrient == sheet::DataPilotFieldOrientation_DATA)
1447 : : {
1448 : 45 : sheet::GeneralFunction eFunc = sheet::GeneralFunction_SUM;
1449 [ + + ]: 45 : if (aFields[i].eFunc)
1450 : 24 : eFunc = static_cast<sheet::GeneralFunction>(aFields[i].eFunc);
1451 : :
1452 [ + - ]: 45 : pDim->SetFunction(eFunc);
1453 [ + - ]: 45 : pDim->SetReferenceValue(NULL);
1454 : : }
1455 : : else
1456 : : {
1457 : 60 : sheet::DataPilotFieldSortInfo aSortInfo;
1458 : 60 : aSortInfo.IsAscending = true;
1459 : 60 : aSortInfo.Mode = 2;
1460 [ + - ]: 60 : pDim->SetSortInfo(&aSortInfo);
1461 : :
1462 : 60 : sheet::DataPilotFieldLayoutInfo aLayInfo;
1463 : 60 : aLayInfo.LayoutMode = 0;
1464 : 60 : aLayInfo.AddEmptyLines = false;
1465 [ + - ]: 60 : pDim->SetLayoutInfo(&aLayInfo);
1466 : 60 : sheet::DataPilotFieldAutoShowInfo aShowInfo;
1467 : 60 : aShowInfo.IsEnabled = false;
1468 : 60 : aShowInfo.ShowItemsMode = 0;
1469 : 60 : aShowInfo.ItemCount = 0;
1470 [ + - ]: 60 : pDim->SetAutoShowInfo(&aShowInfo);
1471 : : }
1472 : 105 : }
1473 : :
1474 : : // Don't forget the data layout dimension.
1475 [ + - ]: 39 : ScDPSaveDimension* pDim = aSaveData.GetDataLayoutDimension();
1476 [ + - ]: 39 : pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
1477 [ + - ]: 39 : pDim->SetShowEmpty(true);
1478 : :
1479 [ + - ]: 39 : pDPObj->SetSaveData(aSaveData);
1480 [ + - ]: 39 : pDPObj->SetAlive(true);
1481 [ + - ]: 39 : pDPObj->InvalidateData();
1482 : :
1483 [ + - ]: 39 : return pDPObj;
1484 : : }
1485 : :
1486 : 36 : ScDPObject* createDPFromRange(
1487 : : ScDocument* pDoc, const ScRange& rRange, DPFieldDef aFields[], size_t nFieldCount,
1488 : : bool bFilterButton)
1489 : : {
1490 [ + - ]: 36 : ScSheetSourceDesc aSheetDesc(pDoc);
1491 [ + - ]: 36 : aSheetDesc.SetSourceRange(rRange);
1492 [ + - ][ + - ]: 36 : return createDPFromSourceDesc(pDoc, aSheetDesc, aFields, nFieldCount, bFilterButton);
1493 : : }
1494 : :
1495 : 57 : ScRange refresh(ScDPObject* pDPObj)
1496 : : {
1497 : 57 : bool bOverFlow = false;
1498 [ + - ]: 57 : ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow);
1499 [ + - ][ + - ]: 57 : CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1500 : :
1501 [ + - ]: 57 : pDPObj->Output(aOutRange.aStart);
1502 : 57 : aOutRange = pDPObj->GetOutRange();
1503 : 57 : return aOutRange;
1504 : : }
1505 : :
1506 : 12 : ScRange refreshGroups(ScDPCollection* pDPs, ScDPObject* pDPObj)
1507 : : {
1508 : : // We need to first create group data in the cache, then the group data in
1509 : : // the object.
1510 [ + - ]: 12 : std::set<ScDPObject*> aRefs;
1511 [ + - ]: 12 : bool bSuccess = pDPs->ReloadGroupsInCache(pDPObj, aRefs);
1512 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Failed to reload group data in cache.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1513 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("There should be only one table linked to this cache.", aRefs.size() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1514 [ + - ]: 12 : pDPObj->ReloadGroupTableData();
1515 : :
1516 [ + - ]: 12 : return refresh(pDPObj);
1517 : : }
1518 : :
1519 : : class AutoCalcSwitch
1520 : : {
1521 : : ScDocument* mpDoc;
1522 : : bool mbOldValue;
1523 : : public:
1524 : 3 : AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc())
1525 : : {
1526 : 3 : mpDoc->SetAutoCalc(bAutoCalc);
1527 : 3 : }
1528 : :
1529 : 3 : ~AutoCalcSwitch()
1530 : : {
1531 : 3 : mpDoc->SetAutoCalc(mbOldValue);
1532 : 3 : }
1533 : : };
1534 : :
1535 : : }
1536 : :
1537 : 3 : void Test::testPivotTable()
1538 : : {
1539 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
1540 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
1541 : :
1542 : : // Dimension definition
1543 : : DPFieldDef aFields[] = {
1544 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
1545 : : { "Group", sheet::DataPilotFieldOrientation_COLUMN, 0 },
1546 : : { "Score", sheet::DataPilotFieldOrientation_DATA, 0 }
1547 : 3 : };
1548 : :
1549 : : // Raw data
1550 : : const char* aData[][3] = {
1551 : : { "Andy", "A", "30" },
1552 : : { "Bruce", "A", "20" },
1553 : : { "Charlie", "B", "45" },
1554 : : { "David", "B", "12" },
1555 : : { "Edward", "C", "8" },
1556 : : { "Frank", "C", "15" },
1557 : 3 : };
1558 : :
1559 : 3 : size_t nFieldCount = SAL_N_ELEMENTS(aFields);
1560 : 3 : size_t nDataCount = SAL_N_ELEMENTS(aData);
1561 : :
1562 [ + - ]: 3 : ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
1563 : 3 : SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
1564 : 3 : SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
1565 : :
1566 : : ScDPObject* pDPObj = createDPFromRange(
1567 [ + - ]: 3 : m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
1568 : :
1569 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
1570 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
1571 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1572 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1573 [ + - ]: 3 : pDPs->GetCount() == 1);
1574 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
1575 : :
1576 : 3 : bool bOverFlow = false;
1577 [ + - ]: 3 : ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow);
1578 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1579 : :
1580 [ + - ]: 3 : pDPObj->Output(aOutRange.aStart);
1581 : 3 : aOutRange = pDPObj->GetOutRange();
1582 : : {
1583 : : // Expected output table content. 0 = empty cell
1584 : : const char* aOutputCheck[][5] = {
1585 : : { "Sum - Score", "Group", 0, 0, 0 },
1586 : : { "Name", "A", "B", "C", "Total Result" },
1587 : : { "Andy", "30", 0, 0, "30" },
1588 : : { "Bruce", "20", 0, 0, "20" },
1589 : : { "Charlie", 0, "45", 0, "45" },
1590 : : { "David", 0, "12", 0, "12" },
1591 : : { "Edward", 0, 0, "8", "8" },
1592 : : { "Frank", 0, 0, "15", "15" },
1593 : : { "Total Result", "50", "57", "23", "130" }
1594 : 3 : };
1595 : :
1596 [ + - ]: 3 : bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
1597 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1598 : : }
1599 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1600 : :
1601 : : // Update the cell values.
1602 : 3 : double aData2[] = { 100, 200, 300, 400, 500, 600 };
1603 [ + + ]: 21 : for (size_t i = 0; i < SAL_N_ELEMENTS(aData2); ++i)
1604 : : {
1605 : 18 : SCROW nRow = i + 1;
1606 [ + - ]: 18 : m_pDoc->SetValue(2, nRow, 0, aData2[i]);
1607 : : }
1608 : :
1609 [ + - ]: 3 : printRange(m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), "Data sheet content (modified)");
1610 : :
1611 : : // Now, create a copy of the datapilot object for the updated table, but
1612 : : // don't reload the cache which should force the copy to use the old data
1613 : : // from the cache.
1614 [ + - ][ + - ]: 3 : ScDPObject* pDPObj2 = new ScDPObject(*pDPObj);
1615 [ + - ]: 3 : pDPs->InsertNewTable(pDPObj2);
1616 : :
1617 : 3 : aOutRange = pDPObj2->GetOutRange();
1618 [ + - ]: 3 : pDPObj2->ClearTableData();
1619 [ + - ]: 3 : pDPObj2->Output(aOutRange.aStart);
1620 : : {
1621 : : // Expected output table content. 0 = empty cell
1622 : : const char* aOutputCheck[][5] = {
1623 : : { "Sum - Score", "Group", 0, 0, 0 },
1624 : : { "Name", "A", "B", "C", "Total Result" },
1625 : : { "Andy", "30", 0, 0, "30" },
1626 : : { "Bruce", "20", 0, 0, "20" },
1627 : : { "Charlie", 0, "45", 0, "45" },
1628 : : { "David", 0, "12", 0, "12" },
1629 : : { "Edward", 0, 0, "8", "8" },
1630 : : { "Frank", 0, 0, "15", "15" },
1631 : : { "Total Result", "50", "57", "23", "130" }
1632 : 3 : };
1633 : :
1634 [ + - ]: 3 : bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (from old cache)");
1635 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1636 : : }
1637 : :
1638 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1639 : :
1640 : : // Free the first datapilot object after the 2nd one gets reloaded, to
1641 : : // prevent the data cache from being deleted before the reload.
1642 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
1643 : :
1644 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1645 : :
1646 : : // This time clear the cache to refresh the data from the source range.
1647 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1648 [ + - ]: 3 : std::set<ScDPObject*> aRefs;
1649 [ + - ]: 3 : sal_uLong nErrId = pDPs->ReloadCache(pDPObj2, aRefs);
1650 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache reload failed.", nErrId == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1651 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Reloading a cache shouldn't remove any cache.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1652 [ + - ]: 3 : pDPs->GetSheetCaches().size() == 1);
1653 : :
1654 [ + - ]: 3 : pDPObj2->ClearTableData();
1655 [ + - ]: 3 : pDPObj2->Output(aOutRange.aStart);
1656 : :
1657 : : {
1658 : : // Expected output table content. 0 = empty cell
1659 : : const char* aOutputCheck[][5] = {
1660 : : { "Sum - Score", "Group", 0, 0, 0 },
1661 : : { "Name", "A", "B", "C", "Total Result" },
1662 : : { "Andy", "100", 0, 0, "100" },
1663 : : { "Bruce", "200", 0, 0, "200" },
1664 : : { "Charlie", 0, "300", 0, "300" },
1665 : : { "David", 0, "400", 0, "400" },
1666 : : { "Edward", 0, 0, "500", "500" },
1667 : : { "Frank", 0, 0, "600", "600" },
1668 : : { "Total Result", "300", "700", "1100", "2100" }
1669 : 3 : };
1670 : :
1671 [ + - ]: 3 : bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (refreshed)");
1672 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1673 : : }
1674 : :
1675 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache should be here.", pDPs->GetSheetCaches().hasCache(aSrcRange));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1676 : :
1677 : : // Swap the two sheets.
1678 [ + - ]: 3 : m_pDoc->MoveTab(1, 0);
1679 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Swapping the sheets shouldn't remove the cache.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1680 [ + - ]: 3 : pDPs->GetSheetCaches().size() == 1);
1681 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache should have moved.", !pDPs->GetSheetCaches().hasCache(aSrcRange));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1682 : 3 : aSrcRange.aStart.SetTab(1);
1683 : 3 : aSrcRange.aEnd.SetTab(1);
1684 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache should be here.", pDPs->GetSheetCaches().hasCache(aSrcRange));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1685 : :
1686 [ + - ]: 3 : pDPs->FreeTable(pDPObj2);
1687 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1688 [ + - ]: 3 : pDPs->GetCount() == 0);
1689 : :
1690 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("There shouldn't be any more data cache.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1691 [ + - ]: 3 : pDPs->GetSheetCaches().size() == 0);
1692 : :
1693 : : // Insert a brand new pivot table object once again, but this time, don't
1694 : : // create the output to avoid creating a data cache.
1695 [ + - ]: 3 : m_pDoc->DeleteTab(1);
1696 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
1697 : :
1698 : : pDPObj = createDPFromRange(
1699 [ + - ]: 3 : m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
1700 [ + - ]: 3 : bSuccess = pDPs->InsertNewTable(pDPObj);
1701 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1702 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1703 [ + - ]: 3 : pDPs->GetCount() == 1);
1704 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
1705 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Data cache shouldn't exist yet before creating the table output.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1706 [ + - ]: 3 : pDPs->GetSheetCaches().size() == 0);
1707 : :
1708 : : // Now, "refresh" the table. This should still return a reference to self
1709 : : // even with the absence of data cache.
1710 : 3 : aRefs.clear();
1711 [ + - ]: 3 : pDPs->ReloadCache(pDPObj, aRefs);
1712 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("It should return the same object as a reference.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
1713 [ + - ]: 3 : aRefs.size() == 1 && *aRefs.begin() == pDPObj);
1714 : :
1715 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
1716 : :
1717 [ + - ]: 3 : m_pDoc->DeleteTab(1);
1718 [ + - ]: 3 : m_pDoc->DeleteTab(0);
1719 : 3 : }
1720 : :
1721 : 3 : void Test::testPivotTableLabels()
1722 : : {
1723 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
1724 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
1725 : :
1726 : : // Dimension definition
1727 : : DPFieldDef aFields[] = {
1728 : : { "Software", sheet::DataPilotFieldOrientation_ROW, 0 },
1729 : : { "Version", sheet::DataPilotFieldOrientation_COLUMN, 0 },
1730 : : { "1.2.3", sheet::DataPilotFieldOrientation_DATA, 0 }
1731 : 3 : };
1732 : :
1733 : : // Raw data
1734 : : const char* aData[][3] = {
1735 : : { "LibreOffice", "3.3.0", "30" },
1736 : : { "LibreOffice", "3.3.1", "20" },
1737 : : { "LibreOffice", "3.4.0", "45" },
1738 : 3 : };
1739 : :
1740 : 3 : size_t nFieldCount = SAL_N_ELEMENTS(aFields);
1741 : 3 : size_t nDataCount = SAL_N_ELEMENTS(aData);
1742 : :
1743 [ + - ]: 3 : ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
1744 : 3 : SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
1745 : 3 : SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
1746 : :
1747 : : ScDPObject* pDPObj = createDPFromRange(
1748 [ + - ]: 3 : m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
1749 : :
1750 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
1751 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
1752 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1753 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1754 [ + - ]: 3 : pDPs->GetCount() == 1);
1755 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
1756 : :
1757 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
1758 : : {
1759 : : // Expected output table content. 0 = empty cell
1760 : : const char* aOutputCheck[][5] = {
1761 : : { "Sum - 1.2.3", "Version", 0, 0, 0 },
1762 : : { "Software", "3.3.0", "3.3.1", "3.4.0", "Total Result" },
1763 : : { "LibreOffice", "30", "20", "45", "95" },
1764 : : { "Total Result", "30", "20", "45", "95" }
1765 : 3 : };
1766 : :
1767 [ + - ]: 3 : bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
1768 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1769 : : }
1770 : :
1771 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
1772 : :
1773 [ + - ]: 3 : m_pDoc->DeleteTab(1);
1774 [ + - ]: 3 : m_pDoc->DeleteTab(0);
1775 : 3 : }
1776 : :
1777 : 3 : void Test::testPivotTableDateLabels()
1778 : : {
1779 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
1780 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
1781 : :
1782 : : // Dimension definition
1783 : : DPFieldDef aFields[] = {
1784 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
1785 : : { "Date", sheet::DataPilotFieldOrientation_COLUMN, 0 },
1786 : : { "Value", sheet::DataPilotFieldOrientation_DATA, 0 }
1787 : 3 : };
1788 : :
1789 : : // Raw data
1790 : : const char* aData[][3] = {
1791 : : { "Zena", "2011-1-1", "30" },
1792 : : { "Yodel", "2011-1-2", "20" },
1793 : : { "Xavior", "2011-1-3", "45" }
1794 : 3 : };
1795 : :
1796 : 3 : size_t nFieldCount = SAL_N_ELEMENTS(aFields);
1797 : 3 : size_t nDataCount = SAL_N_ELEMENTS(aData);
1798 : :
1799 [ + - ]: 3 : ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
1800 : 3 : SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
1801 : 3 : SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
1802 : :
1803 : : ScDPObject* pDPObj = createDPFromRange(
1804 [ + - ]: 3 : m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
1805 : :
1806 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
1807 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
1808 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1809 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1810 [ + - ]: 3 : pDPs->GetCount() == 1);
1811 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
1812 : :
1813 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
1814 : : {
1815 : : // Expected output table content. 0 = empty cell
1816 : : const char* aOutputCheck[][5] = {
1817 : : { "Sum - Value", "Date", 0, 0, 0 },
1818 : : { "Name", "2011-01-01", "2011-01-02", "2011-01-03", "Total Result" },
1819 : : { "Xavior", 0, 0, "45", "45" },
1820 : : { "Yodel", 0, "20", 0, "20" },
1821 : : { "Zena", "30", 0, 0, "30" },
1822 : : { "Total Result", "30", "20", "45", "95" }
1823 : 3 : };
1824 : :
1825 [ + - ]: 3 : bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
1826 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1827 : : }
1828 : :
1829 : : {
1830 : : const char* aChecks[] = {
1831 : : "2011-01-01", "2011-01-02", "2011-01-03"
1832 : 3 : };
1833 : :
1834 : : // Make sure those cells that contain dates are numeric.
1835 : 3 : SCROW nRow = aOutRange.aStart.Row() + 1;
1836 : 3 : nCol1 = aOutRange.aStart.Col() + 1;
1837 : 3 : nCol2 = nCol1 + 2;
1838 [ + + ]: 12 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1839 : : {
1840 [ + - ]: 9 : OUString aVal = m_pDoc->GetString(nCol, nRow, 1);
1841 [ + - ][ + - ]: 9 : CPPUNIT_ASSERT_MESSAGE("Cell value is not as expected.", aVal.equalsAscii(aChecks[nCol-nCol1]));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1842 [ + - ][ + - ]: 18 : CPPUNIT_ASSERT_MESSAGE("This cell contains a date value and is supposed to be numeric.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1843 [ + - ]: 9 : m_pDoc->HasValueData(nCol, nRow, 1));
1844 : 9 : }
1845 : : }
1846 : :
1847 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
1848 : :
1849 [ + - ]: 3 : m_pDoc->DeleteTab(1);
1850 [ + - ]: 3 : m_pDoc->DeleteTab(0);
1851 : 3 : }
1852 : :
1853 : 3 : void Test::testPivotTableFilters()
1854 : : {
1855 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
1856 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
1857 : :
1858 : : // Dimension definition
1859 : : DPFieldDef aFields[] = {
1860 : : { "Name", sheet::DataPilotFieldOrientation_HIDDEN, 0 },
1861 : : { "Group1", sheet::DataPilotFieldOrientation_HIDDEN, 0 },
1862 : : { "Group2", sheet::DataPilotFieldOrientation_PAGE, 0 },
1863 : : { "Val1", sheet::DataPilotFieldOrientation_DATA, 0 },
1864 : : { "Val2", sheet::DataPilotFieldOrientation_DATA, 0 }
1865 : 3 : };
1866 : :
1867 : : // Raw data
1868 : : const char* aData[][5] = {
1869 : : { "A", "1", "A", "1", "10" },
1870 : : { "B", "1", "A", "1", "10" },
1871 : : { "C", "1", "B", "1", "10" },
1872 : : { "D", "1", "B", "1", "10" },
1873 : : { "E", "2", "A", "1", "10" },
1874 : : { "F", "2", "A", "1", "10" },
1875 : : { "G", "2", "B", "1", "10" },
1876 : : { "H", "2", "B", "1", "10" }
1877 : 3 : };
1878 : :
1879 : 3 : size_t nFieldCount = SAL_N_ELEMENTS(aFields);
1880 : 3 : size_t nDataCount = SAL_N_ELEMENTS(aData);
1881 : :
1882 [ + - ]: 3 : ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
1883 : 3 : SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
1884 : 3 : SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
1885 : :
1886 : : ScDPObject* pDPObj = createDPFromRange(
1887 [ + - ]: 3 : m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, true);
1888 : :
1889 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
1890 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
1891 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1892 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1893 [ + - ]: 3 : pDPs->GetCount() == 1);
1894 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
1895 : :
1896 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
1897 : : {
1898 : : // Expected output table content. 0 = empty cell
1899 : : const char* aOutputCheck[][2] = {
1900 : : { "Filter", 0 },
1901 : : { "Group2", "- all -" },
1902 : : { 0, 0 },
1903 : : { "Data", 0 },
1904 : : { "Sum - Val1", "8" },
1905 : : { "Sum - Val2", "80" }
1906 : 3 : };
1907 : :
1908 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (unfiltered)");
1909 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1910 : : }
1911 : :
1912 [ + - ]: 3 : AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
1913 : :
1914 : 3 : ScAddress aFormulaAddr = aOutRange.aEnd;
1915 [ + - ]: 3 : aFormulaAddr.IncRow(2);
1916 : 6 : m_pDoc->SetString(aFormulaAddr.Col(), aFormulaAddr.Row(), aFormulaAddr.Tab(),
1917 [ + - ]: 9 : rtl::OUString("=B6"));
1918 [ + - ]: 3 : double fTest = m_pDoc->GetValue(aFormulaAddr);
1919 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Incorrect formula value that references a cell in the pivot table output.", fTest == 80.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1920 : :
1921 : : // Set current page of 'Group2' to 'A'.
1922 [ + - ]: 3 : ScDPSaveData aSaveData(*pDPObj->GetSaveData());
1923 : : ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(
1924 [ + - ]: 3 : OUString("Group2"));
1925 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Dimension not found", pDim);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1926 : 3 : OUString aPage("A");
1927 [ + - ]: 3 : pDim->SetCurrentPage(&aPage);
1928 [ + - ]: 3 : pDPObj->SetSaveData(aSaveData);
1929 [ + - ]: 3 : aOutRange = refresh(pDPObj);
1930 : : {
1931 : : // Expected output table content. 0 = empty cell
1932 : : const char* aOutputCheck[][2] = {
1933 : : { "Filter", 0 },
1934 : : { "Group2", "A" },
1935 : : { 0, 0 },
1936 : : { "Data", 0 },
1937 : : { "Sum - Val1", "4" },
1938 : : { "Sum - Val2", "40" }
1939 : 3 : };
1940 : :
1941 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by page)");
1942 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1943 : : }
1944 : :
1945 [ + - ]: 3 : fTest = m_pDoc->GetValue(aFormulaAddr);
1946 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Incorrect formula value that references a cell in the pivot table output.", fTest == 40.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1947 : :
1948 : : // Set query filter.
1949 [ + - ]: 3 : ScSheetSourceDesc aDesc(*pDPObj->GetSheetDesc());
1950 [ + - ][ + - ]: 3 : ScQueryParam aQueryParam(aDesc.GetQueryParam());
1951 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be at least one query entry.", aQueryParam.GetEntryCount() > 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1952 [ + - ]: 3 : ScQueryEntry& rEntry = aQueryParam.GetEntry(0);
1953 : 3 : rEntry.bDoQuery = true;
1954 : 3 : rEntry.nField = 1; // Group1
1955 [ + - ]: 3 : rEntry.GetQueryItem().mfVal = 1;
1956 [ + - ]: 3 : aDesc.SetQueryParam(aQueryParam);
1957 [ + - ]: 3 : pDPObj->SetSheetDesc(aDesc);
1958 [ + - ]: 3 : aOutRange = refresh(pDPObj);
1959 : : {
1960 : : // Expected output table content. 0 = empty cell
1961 : : const char* aOutputCheck[][2] = {
1962 : : { "Filter", 0 },
1963 : : { "Group2", "A" },
1964 : : { 0, 0 },
1965 : : { "Data", 0 },
1966 : : { "Sum - Val1", "2" },
1967 : : { "Sum - Val2", "20" }
1968 : 3 : };
1969 : :
1970 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by query)");
1971 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1972 : : }
1973 : :
1974 [ + - ]: 3 : fTest = m_pDoc->GetValue(aFormulaAddr);
1975 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Incorrect formula value that references a cell in the pivot table output.", fTest == 20.0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1976 : :
1977 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
1978 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1979 [ + - ]: 3 : pDPs->GetCount() == 0);
1980 : :
1981 [ + - ]: 3 : m_pDoc->DeleteTab(1);
1982 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
[ + - ][ + - ]
[ + - ]
1983 : 3 : }
1984 : :
1985 : 3 : void Test::testPivotTableNamedSource()
1986 : : {
1987 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
1988 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
1989 : :
1990 : : // Dimension definition
1991 : : DPFieldDef aFields[] = {
1992 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
1993 : : { "Group", sheet::DataPilotFieldOrientation_COLUMN, 0 },
1994 : : { "Score", sheet::DataPilotFieldOrientation_DATA, 0 }
1995 : 3 : };
1996 : :
1997 : : // Raw data
1998 : : const char* aData[][3] = {
1999 : : { "Andy", "A", "30" },
2000 : : { "Bruce", "A", "20" },
2001 : : { "Charlie", "B", "45" },
2002 : : { "David", "B", "12" },
2003 : : { "Edward", "C", "8" },
2004 : : { "Frank", "C", "15" },
2005 : 3 : };
2006 : :
2007 : 3 : size_t nFieldCount = SAL_N_ELEMENTS(aFields);
2008 : 3 : size_t nDataCount = SAL_N_ELEMENTS(aData);
2009 : :
2010 : : // Insert the raw data.
2011 [ + - ]: 3 : ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
2012 : 3 : rtl::OUString aRangeStr;
2013 [ + - ]: 3 : aSrcRange.Format(aRangeStr, SCR_ABS_3D, m_pDoc);
2014 : :
2015 : : // Name this range.
2016 : 3 : rtl::OUString aRangeName("MyData");
2017 [ + - ]: 3 : ScRangeName* pNames = m_pDoc->GetRangeName();
2018 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to get global range name container.", pNames);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2019 : : ScRangeData* pName = new ScRangeData(
2020 [ + - ][ + - ]: 3 : m_pDoc, aRangeName, aRangeStr);
[ + - ][ + - ]
2021 [ + - ]: 3 : bool bSuccess = pNames->insert(pName);
2022 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2023 : :
2024 [ + - ]: 3 : ScSheetSourceDesc aSheetDesc(m_pDoc);
2025 [ + - ]: 3 : aSheetDesc.SetRangeName(aRangeName);
2026 [ + - ]: 3 : ScDPObject* pDPObj = createDPFromSourceDesc(m_pDoc, aSheetDesc, aFields, nFieldCount, false);
2027 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to create a new pivot table object.", pDPObj);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2028 : :
2029 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2030 [ + - ]: 3 : bSuccess = pDPs->InsertNewTable(pDPObj);
2031 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2032 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2033 [ + - ]: 3 : pDPs->GetCount() == 1);
2034 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2035 : :
2036 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
2037 : : {
2038 : : // Expected output table content. 0 = empty cell
2039 : : const char* aOutputCheck[][5] = {
2040 : : { "Sum - Score", "Group", 0, 0, 0 },
2041 : : { "Name", "A", "B", "C", "Total Result" },
2042 : : { "Andy", "30", 0, 0, "30" },
2043 : : { "Bruce", "20", 0, 0, "20" },
2044 : : { "Charlie", 0, "45", 0, "45" },
2045 : : { "David", 0, "12", 0, "12" },
2046 : : { "Edward", 0, 0, "8", "8" },
2047 : : { "Frank", 0, 0, "15", "15" },
2048 : : { "Total Result", "50", "57", "23", "130" }
2049 : 3 : };
2050 : :
2051 [ + - ]: 3 : bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
2052 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2053 : : }
2054 : :
2055 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("There should be one named range data cache.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
2056 [ + - ]: 3 : pDPs->GetNameCaches().size() == 1 && pDPs->GetSheetCaches().size() == 0);
2057 : :
2058 : : // Move the table with pivot table to the left of the source data sheet.
2059 [ + - ]: 3 : m_pDoc->MoveTab(1, 0);
2060 : 3 : rtl::OUString aTabName;
2061 [ + - ]: 3 : m_pDoc->GetName(0, aTabName);
2062 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong sheet name.", aTabName == "Table" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2063 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Pivot table output is on the wrong sheet!",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2064 [ + - ]: 3 : pDPObj->GetOutRange().aStart.Tab() == 0);
2065 : :
2066 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Moving the pivot table to another sheet shouldn't have changed the cache state.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
2067 [ + - ]: 3 : pDPs->GetNameCaches().size() == 1 && pDPs->GetSheetCaches().size() == 0);
2068 : :
2069 : 3 : const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
2070 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Sheet source description doesn't exist.", pDesc);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2071 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Named source range has been altered unexpectedly!",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2072 [ + - ]: 3 : pDesc->GetRangeName().equals(aRangeName));
2073 : :
2074 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache should exist.", pDPs->GetNameCaches().hasCache(aRangeName));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2075 : :
2076 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2077 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be no more tables.", pDPs->GetCount() == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2078 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2079 [ + - ]: 3 : pDPs->GetNameCaches().size() == 0);
2080 : :
2081 [ + - ]: 3 : pNames->clear();
2082 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2083 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
2084 : 3 : }
2085 : :
2086 : 3 : void Test::testPivotTableCache()
2087 : : {
2088 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2089 : :
2090 : : // Raw data
2091 : : const char* aData[][3] = {
2092 : : { "F1", "F2", "F3" },
2093 : : { "Z", "A", "30" },
2094 : : { "R", "A", "20" },
2095 : : { "A", "B", "45" },
2096 : : { "F", "B", "12" },
2097 : : { "Y", "C", "8" },
2098 : : { "12", "C", "15" },
2099 : 3 : };
2100 : :
2101 : 3 : ScAddress aPos(1,1,0);
2102 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2103 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2104 : :
2105 [ + - ]: 3 : ScDPCache aCache(m_pDoc);
2106 [ + - ]: 3 : aCache.InitFromDoc(m_pDoc, aDataRange);
2107 [ + - ]: 3 : long nDimCount = aCache.GetColumnCount();
2108 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension count.", nDimCount == 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2109 [ + - ]: 3 : rtl::OUString aDimName = aCache.GetDimensionName(0);
2110 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension name", aDimName.equalsAscii("F1"));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2111 [ + - ]: 3 : aDimName = aCache.GetDimensionName(1);
2112 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension name", aDimName.equalsAscii("F2"));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2113 [ + - ]: 3 : aDimName = aCache.GetDimensionName(2);
2114 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension name", aDimName.equalsAscii("F3"));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2115 : :
2116 : : // In each dimension, member ID values also represent their sort order (in
2117 : : // source dimensions only, not in group dimensions). Value items are
2118 : : // sorted before string ones. Also, no duplicate dimension members should
2119 : : // exist.
2120 : :
2121 : : // Dimension 0 - a mix of strings and values.
2122 [ + - ]: 3 : long nMemCount = aCache.GetDimMemberCount(0);
2123 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension member count", nMemCount == 6);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2124 [ + - ]: 3 : const ScDPItemData* pItem = aCache.GetItemDataById(0, 0);
2125 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2126 : : pItem->GetType() == ScDPItemData::Value &&
2127 [ + - ]: 3 : pItem->GetValue() == 12);
2128 [ + - ]: 3 : pItem = aCache.GetItemDataById(0, 1);
2129 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2130 : : pItem->GetType() == ScDPItemData::String &&
2131 [ + - ]: 3 : pItem->GetString().equalsAscii("A"));
2132 [ + - ]: 3 : pItem = aCache.GetItemDataById(0, 2);
2133 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2134 : : pItem->GetType() == ScDPItemData::String &&
2135 [ + - ]: 3 : pItem->GetString().equalsAscii("F"));
2136 [ + - ]: 3 : pItem = aCache.GetItemDataById(0, 3);
2137 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2138 : : pItem->GetType() == ScDPItemData::String &&
2139 [ + - ]: 3 : pItem->GetString().equalsAscii("R"));
2140 [ + - ]: 3 : pItem = aCache.GetItemDataById(0, 4);
2141 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2142 : : pItem->GetType() == ScDPItemData::String &&
2143 [ + - ]: 3 : pItem->GetString().equalsAscii("Y"));
2144 [ + - ]: 3 : pItem = aCache.GetItemDataById(0, 5);
2145 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2146 : : pItem->GetType() == ScDPItemData::String &&
2147 [ + - ]: 3 : pItem->GetString().equalsAscii("Z"));
2148 [ + - ]: 3 : pItem = aCache.GetItemDataById(0, 6);
2149 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong item value", !pItem);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2150 : :
2151 : : // Dimension 1 - duplicate values in source.
2152 [ + - ]: 3 : nMemCount = aCache.GetDimMemberCount(1);
2153 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension member count", nMemCount == 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2154 [ + - ]: 3 : pItem = aCache.GetItemDataById(1, 0);
2155 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2156 : : pItem->GetType() == ScDPItemData::String &&
2157 [ + - ]: 3 : pItem->GetString().equalsAscii("A"));
2158 [ + - ]: 3 : pItem = aCache.GetItemDataById(1, 1);
2159 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2160 : : pItem->GetType() == ScDPItemData::String &&
2161 [ + - ]: 3 : pItem->GetString().equalsAscii("B"));
2162 [ + - ]: 3 : pItem = aCache.GetItemDataById(1, 2);
2163 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
2164 : : pItem->GetType() == ScDPItemData::String &&
2165 [ + - ]: 3 : pItem->GetString().equalsAscii("C"));
2166 [ + - ]: 3 : pItem = aCache.GetItemDataById(1, 3);
2167 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong item value", !pItem);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2168 : :
2169 : : // Dimension 2 - values only.
2170 [ + - ]: 3 : nMemCount = aCache.GetDimMemberCount(2);
2171 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong dimension member count", nMemCount == 6);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2172 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 0);
2173 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2174 : : pItem->GetType() == ScDPItemData::Value &&
2175 [ + - ]: 3 : pItem->GetValue() == 8);
2176 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 1);
2177 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2178 : : pItem->GetType() == ScDPItemData::Value &&
2179 [ + - ]: 3 : pItem->GetValue() == 12);
2180 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 2);
2181 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2182 : : pItem->GetType() == ScDPItemData::Value &&
2183 [ + - ]: 3 : pItem->GetValue() == 15);
2184 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 3);
2185 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2186 : : pItem->GetType() == ScDPItemData::Value &&
2187 [ + - ]: 3 : pItem->GetValue() == 20);
2188 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 4);
2189 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2190 : : pItem->GetType() == ScDPItemData::Value &&
2191 [ + - ]: 3 : pItem->GetValue() == 30);
2192 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 5);
2193 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ]
2194 : : pItem->GetType() == ScDPItemData::Value &&
2195 [ + - ]: 3 : pItem->GetValue() == 45);
2196 [ + - ]: 3 : pItem = aCache.GetItemDataById(2, 6);
2197 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong item value", !pItem);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2198 : :
2199 : : {
2200 : : // Check the integrity of the source data.
2201 [ + - ]: 3 : ScDPItemData aTest;
2202 : : long nDim;
2203 : :
2204 : : {
2205 : : // Dimension 0: Z, R, A, F, Y, 12
2206 : 3 : nDim = 0;
2207 : 3 : const char* aChecks[] = { "Z", "R", "A", "F", "Y" };
2208 [ + + ]: 18 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
2209 : : {
2210 [ + - ][ + - ]: 15 : pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, i, false));
2211 [ + - ]: 15 : aTest.SetString(rtl::OUString::createFromAscii(aChecks[i]));
2212 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
2213 : : }
2214 : :
2215 [ + - ][ + - ]: 3 : pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, 5, false));
2216 [ + - ]: 3 : aTest.SetValue(12);
2217 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
2218 : : }
2219 : :
2220 : : {
2221 : : // Dimension 1: A, A, B, B, C, C
2222 : 3 : nDim = 1;
2223 : 3 : const char* aChecks[] = { "A", "A", "B", "B", "C", "C" };
2224 [ + + ]: 21 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
2225 : : {
2226 [ + - ][ + - ]: 18 : pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, i, false));
2227 [ + - ]: 18 : aTest.SetString(rtl::OUString::createFromAscii(aChecks[i]));
2228 [ + - ][ + - ]: 18 : CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
2229 : : }
2230 : : }
2231 : :
2232 : : {
2233 : : // Dimension 2: 30, 20, 45, 12, 8, 15
2234 : 3 : nDim = 2;
2235 : 3 : double aChecks[] = { 30, 20, 45, 12, 8, 15 };
2236 [ + + ]: 21 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
2237 : : {
2238 [ + - ][ + - ]: 18 : pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, i, false));
2239 [ + - ]: 18 : aTest.SetValue(aChecks[i]);
2240 [ + - ][ + - ]: 18 : CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
2241 : : }
2242 [ + - ]: 3 : }
2243 : : }
2244 : :
2245 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
2246 : 3 : }
2247 : :
2248 : 3 : void Test::testPivotTableDuplicateDataFields()
2249 : : {
2250 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2251 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2252 : :
2253 : : // Raw data
2254 : : const char* aData[][2] = {
2255 : : { "Name", "Value" },
2256 : : { "A", "45" },
2257 : : { "A", "5" },
2258 : : { "A", "41" },
2259 : : { "A", "49" },
2260 : : { "A", "4" },
2261 : : { "B", "33" },
2262 : : { "B", "84" },
2263 : : { "B", "74" },
2264 : : { "B", "8" },
2265 : : { "B", "68" }
2266 : 3 : };
2267 : :
2268 : : // Dimension definition
2269 : : DPFieldDef aFields[] = {
2270 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
2271 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2272 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_COUNT }
2273 : 3 : };
2274 : :
2275 : 3 : ScAddress aPos(2,2,0);
2276 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2277 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2278 : :
2279 : : ScDPObject* pDPObj = createDPFromRange(
2280 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2281 : :
2282 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2283 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2284 : :
2285 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2286 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ]
2287 [ + - ]: 3 : pDPs->GetCount(), static_cast<size_t>(1));
2288 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2289 : :
2290 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
2291 : : {
2292 : : // Expected output table content. 0 = empty cell
2293 : : const char* aOutputCheck[][3] = {
2294 : : { "Name", "Data", 0 },
2295 : : { "A", "Sum - Value", "144" },
2296 : : { 0, "Count - Value", "5" },
2297 : : { "B", "Sum - Value", "267" },
2298 : : { 0, "Count - Value", "5" },
2299 : : { "Total Sum - Value", 0, "411" },
2300 : : { "Total Count - Value", 0, "10" },
2301 : 3 : };
2302 : :
2303 [ + - ]: 3 : bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
2304 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2305 : : }
2306 : :
2307 : : // Move the data layout dimension from row to column.
2308 : 3 : ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2309 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No save data!?", pSaveData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2310 [ + - ]: 3 : ScDPSaveDimension* pDataLayout = pSaveData->GetDataLayoutDimension();
2311 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No data layout dimension.", pDataLayout);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2312 [ + - ]: 3 : pDataLayout->SetOrientation(sheet::DataPilotFieldOrientation_COLUMN);
2313 [ + - ]: 3 : pDPObj->SetSaveData(*pSaveData);
2314 : :
2315 : : // Refresh the table output.
2316 [ + - ]: 3 : aOutRange = refresh(pDPObj);
2317 : : {
2318 : : // Expected output table content. 0 = empty cell
2319 : : const char* aOutputCheck[][3] = {
2320 : : { 0, "Data", 0 },
2321 : : { "Name", "Sum - Value", "Count - Value" },
2322 : : { "A", "144", "5" },
2323 : : { "B", "267", "5" },
2324 : : { "Total Result", "411", "10" }
2325 : 3 : };
2326 : :
2327 [ + - ]: 3 : bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
2328 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2329 : : }
2330 : :
2331 [ + - ]: 3 : ScPivotParam aParam;
2332 [ + - ]: 3 : pDPObj->FillLabelData(aParam);
2333 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be exactly 4 labels (2 original, 1 data layout, and 1 duplicate dimensions).",
[ + - ][ + - ]
2334 [ + - ]: 3 : aParam.maLabelArray.size(), static_cast<size_t>(4));
2335 : :
2336 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2337 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2338 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2339 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2340 : :
2341 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2342 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
2343 : 3 : }
2344 : :
2345 : 3 : void Test::testPivotTableNormalGrouping()
2346 : : {
2347 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2348 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2349 : :
2350 : : // Raw data
2351 : : const char* aData[][2] = {
2352 : : { "Name", "Value" },
2353 : : { "A", "1" },
2354 : : { "B", "2" },
2355 : : { "C", "3" },
2356 : : { "D", "4" },
2357 : : { "E", "5" },
2358 : : { "F", "6" },
2359 : : { "G", "7" }
2360 : 3 : };
2361 : :
2362 : : // Dimension definition
2363 : : DPFieldDef aFields[] = {
2364 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
2365 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2366 : 3 : };
2367 : :
2368 : 3 : ScAddress aPos(1,1,0);
2369 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2370 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2371 : :
2372 : : ScDPObject* pDPObj = createDPFromRange(
2373 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2374 : :
2375 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2376 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2377 : :
2378 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2379 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ]
2380 [ + - ]: 3 : pDPs->GetCount(), static_cast<size_t>(1));
2381 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2382 : :
2383 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
2384 : : {
2385 : : // Expected output table content. 0 = empty cell
2386 : : const char* aOutputCheck[][2] = {
2387 : : { "Name", 0 },
2388 : : { "A", "1" },
2389 : : { "B", "2" },
2390 : : { "C", "3" },
2391 : : { "D", "4" },
2392 : : { "E", "5" },
2393 : : { "F", "6" },
2394 : : { "G", "7" },
2395 : : { "Total Result", "28" }
2396 : 3 : };
2397 : :
2398 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Initial output without grouping");
2399 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2400 : : }
2401 : :
2402 : 3 : ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2403 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No save data !?", pSaveData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2404 [ + - ]: 3 : ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();
2405 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to create dimension data.", pDimData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2406 : :
2407 : 3 : rtl::OUString aGroupPrefix("Group");
2408 : 3 : rtl::OUString aBaseDimName("Name");
2409 : : rtl::OUString aGroupDimName =
2410 [ + - ]: 3 : pDimData->CreateGroupDimName(aBaseDimName, *pDPObj, false, NULL);
2411 : :
2412 : : {
2413 : : // Group A, B and C together.
2414 [ + - ]: 3 : ScDPSaveGroupDimension aGroupDim(aBaseDimName, aGroupDimName);
2415 [ + - ]: 3 : rtl::OUString aGroupName = aGroupDim.CreateGroupName(aGroupPrefix);
2416 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected group name", aGroupName.equalsAscii("Group1"));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2417 : :
2418 [ + - ]: 3 : ScDPSaveGroupItem aGroup(aGroupName);
2419 [ + - ]: 3 : aGroup.AddElement(rtl::OUString("A"));
2420 [ + - ]: 3 : aGroup.AddElement(rtl::OUString("B"));
2421 [ + - ]: 3 : aGroup.AddElement(rtl::OUString("C"));
2422 [ + - ]: 3 : aGroupDim.AddGroupItem(aGroup);
2423 [ + - ]: 3 : pDimData->AddGroupDimension(aGroupDim);
2424 : :
2425 [ + - ]: 3 : ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aGroupDimName);
2426 [ + - ]: 3 : pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
2427 [ + - ][ + - ]: 3 : pSaveData->SetPosition(pDim, 0); // Set it before the base dimension.
[ + - ]
2428 : : }
2429 : :
2430 [ + - ]: 3 : pDPObj->SetSaveData(*pSaveData);
2431 [ + - ]: 3 : aOutRange = refreshGroups(pDPs, pDPObj);
2432 : : {
2433 : : // Expected output table content. 0 = empty cell
2434 : : const char* aOutputCheck[][3] = {
2435 : : { "Name2", "Name", 0 },
2436 : : { "D", "D", "4" },
2437 : : { "E", "E", "5" },
2438 : : { "F", "F", "6" },
2439 : : { "G", "G", "7" },
2440 : : { "Group1", "A", "1" },
2441 : : { 0, "B", "2" },
2442 : : { 0, "C", "3" },
2443 : : { "Total Result", 0, "28" }
2444 : 3 : };
2445 : :
2446 [ + - ]: 3 : bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "A, B, C grouped by Group1.");
2447 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2448 : : }
2449 : :
2450 : 3 : pSaveData = pDPObj->GetSaveData();
2451 [ + - ]: 3 : pDimData = pSaveData->GetDimensionData();
2452 : :
2453 : : {
2454 : : // Group D, E, F together.
2455 [ + - ]: 3 : ScDPSaveGroupDimension* pGroupDim = pDimData->GetGroupDimAccForBase(aBaseDimName);
2456 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be an existing group dimension.", pGroupDim);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2457 [ + - ]: 3 : rtl::OUString aGroupName = pGroupDim->CreateGroupName(aGroupPrefix);
2458 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected group name", aGroupName.equalsAscii("Group2"));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2459 : :
2460 [ + - ]: 3 : ScDPSaveGroupItem aGroup(aGroupName);
2461 [ + - ]: 3 : aGroup.AddElement(rtl::OUString("D"));
2462 [ + - ]: 3 : aGroup.AddElement(rtl::OUString("E"));
2463 [ + - ]: 3 : aGroup.AddElement(rtl::OUString("F"));
2464 [ + - ][ + - ]: 3 : pGroupDim->AddGroupItem(aGroup);
2465 : : }
2466 : :
2467 [ + - ]: 3 : pDPObj->SetSaveData(*pSaveData);
2468 [ + - ]: 3 : aOutRange = refreshGroups(pDPs, pDPObj);
2469 : : {
2470 : : // Expected output table content. 0 = empty cell
2471 : : const char* aOutputCheck[][3] = {
2472 : : { "Name2", "Name", 0 },
2473 : : { "G", "G", "7" },
2474 : : { "Group1", "A", "1" },
2475 : : { 0, "B", "2" },
2476 : : { 0, "C", "3" },
2477 : : { "Group2", "D", "4" },
2478 : : { 0, "E", "5" },
2479 : : { 0, "F", "6" },
2480 : : { "Total Result", 0, "28" }
2481 : 3 : };
2482 : :
2483 [ + - ]: 3 : bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "D, E, F grouped by Group2.");
2484 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2485 : : }
2486 : :
2487 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2488 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2489 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2490 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2491 : :
2492 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2493 [ + - ]: 3 : m_pDoc->DeleteTab(0);
2494 : 3 : }
2495 : :
2496 : 3 : void Test::testPivotTableNumberGrouping()
2497 : : {
2498 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2499 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2500 : :
2501 : : // Raw data
2502 : : const char* aData[][2] = {
2503 : : { "Order", "Score" },
2504 : : { "43", "171" },
2505 : : { "18", "20" },
2506 : : { "69", "159" },
2507 : : { "95", "19" },
2508 : : { "96", "163" },
2509 : : { "46", "70" },
2510 : : { "22", "36" },
2511 : : { "81", "49" },
2512 : : { "54", "61" },
2513 : : { "39", "62" },
2514 : : { "86", "17" },
2515 : : { "34", "0" },
2516 : : { "30", "25" },
2517 : : { "24", "103" },
2518 : : { "16", "59" },
2519 : : { "24", "119" },
2520 : : { "15", "86" },
2521 : : { "69", "170" }
2522 : 3 : };
2523 : :
2524 : : // Dimension definition
2525 : : DPFieldDef aFields[] = {
2526 : : { "Order", sheet::DataPilotFieldOrientation_ROW, 0 },
2527 : : { "Score", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2528 : 3 : };
2529 : :
2530 : 3 : ScAddress aPos(1,1,0);
2531 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2532 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2533 : :
2534 : : ScDPObject* pDPObj = createDPFromRange(
2535 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2536 : :
2537 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2538 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2539 : :
2540 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2541 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ]
2542 [ + - ]: 3 : pDPs->GetCount(), static_cast<size_t>(1));
2543 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2544 : :
2545 : 3 : ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2546 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No save data !?", pSaveData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2547 [ + - ]: 3 : ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();
2548 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No dimension data !?", pDimData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2549 : :
2550 : : {
2551 [ + - ]: 3 : ScDPNumGroupInfo aInfo;
2552 : 3 : aInfo.mbEnable = true;
2553 : 3 : aInfo.mbAutoStart = false;
2554 : 3 : aInfo.mbAutoEnd = false;
2555 : 3 : aInfo.mbDateValues = false;
2556 : 3 : aInfo.mbIntegerOnly = true;
2557 : 3 : aInfo.mfStart = 30;
2558 : 3 : aInfo.mfEnd = 60;
2559 : 3 : aInfo.mfStep = 10;
2560 [ + - ]: 3 : ScDPSaveNumGroupDimension aGroup(rtl::OUString("Order"), aInfo);
2561 [ + - ][ + - ]: 3 : pDimData->AddNumGroupDimension(aGroup);
2562 : : }
2563 : :
2564 [ + - ]: 3 : pDPObj->SetSaveData(*pSaveData);
2565 [ + - ]: 3 : ScRange aOutRange = refreshGroups(pDPs, pDPObj);
2566 : : {
2567 : : // Expected output table content. 0 = empty cell
2568 : : const char* aOutputCheck[][2] = {
2569 : : { "Order", 0 },
2570 : : { "<30", "423" },
2571 : : { "30-39", "87" },
2572 : : { "40-49", "241" },
2573 : : { "50-60", "61" },
2574 : : { ">60", "577" },
2575 : : { "Total Result", "1389" }
2576 : 3 : };
2577 : :
2578 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Order grouped by numbers");
2579 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2580 : : }
2581 : :
2582 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2583 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2584 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2585 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2586 : :
2587 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2588 [ + - ]: 3 : m_pDoc->DeleteTab(0);
2589 : 3 : }
2590 : :
2591 : 3 : void Test::testPivotTableDateGrouping()
2592 : : {
2593 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2594 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2595 : :
2596 : : // Raw data
2597 : : const char* aData[][2] = {
2598 : : { "Date", "Value" },
2599 : : { "2011-01-01", "1" },
2600 : : { "2011-03-02", "2" },
2601 : : { "2012-01-04", "3" },
2602 : : { "2012-02-23", "4" },
2603 : : { "2012-02-24", "5" },
2604 : : { "2012-03-15", "6" },
2605 : : { "2011-09-03", "7" },
2606 : : { "2012-12-25", "8" }
2607 : 3 : };
2608 : :
2609 : : // Dimension definition
2610 : : DPFieldDef aFields[] = {
2611 : : { "Date", sheet::DataPilotFieldOrientation_ROW, 0 },
2612 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2613 : 3 : };
2614 : :
2615 : 3 : ScAddress aPos(1,1,0);
2616 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2617 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2618 : :
2619 : : ScDPObject* pDPObj = createDPFromRange(
2620 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2621 : :
2622 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2623 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2624 : :
2625 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2626 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2627 [ + - ]: 3 : pDPs->GetCount() == 1);
2628 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2629 : :
2630 : 3 : ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2631 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No save data !?", pSaveData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2632 [ + - ]: 3 : ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();
2633 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No dimension data !?", pDimData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2634 : :
2635 : 3 : rtl::OUString aBaseDimName("Date");
2636 : :
2637 [ + - ]: 3 : ScDPNumGroupInfo aInfo;
2638 : 3 : aInfo.mbEnable = true;
2639 : 3 : aInfo.mbAutoStart = true;
2640 : 3 : aInfo.mbAutoEnd = true;
2641 : : {
2642 : : // Turn the Date dimension into months. The first of the date
2643 : : // dimensions is always a number-group dimension which replaces the
2644 : : // original dimension.
2645 [ + - ]: 3 : ScDPSaveNumGroupDimension aGroup(aBaseDimName, aInfo, sheet::DataPilotFieldGroupBy::MONTHS);
2646 [ + - ][ + - ]: 3 : pDimData->AddNumGroupDimension(aGroup);
2647 : : }
2648 : :
2649 : : {
2650 : : // Add quarter dimension. This will be an additional dimension.
2651 : : rtl::OUString aGroupDimName =
2652 : : pDimData->CreateDateGroupDimName(
2653 [ + - ]: 3 : sheet::DataPilotFieldGroupBy::QUARTERS, *pDPObj, true, NULL);
2654 [ + - ]: 3 : ScDPSaveGroupDimension aGroupDim(aBaseDimName, aGroupDimName);
2655 [ + - ]: 3 : aGroupDim.SetDateInfo(aInfo, sheet::DataPilotFieldGroupBy::QUARTERS);
2656 [ + - ]: 3 : pDimData->AddGroupDimension(aGroupDim);
2657 : :
2658 : : // Set orientation.
2659 [ + - ]: 3 : ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aGroupDimName);
2660 [ + - ]: 3 : pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
2661 [ + - ][ + - ]: 3 : pSaveData->SetPosition(pDim, 0); // set it to the left end.
2662 : : }
2663 : :
2664 : : {
2665 : : // Add year dimension. This is a new dimension also.
2666 : : rtl::OUString aGroupDimName =
2667 : : pDimData->CreateDateGroupDimName(
2668 [ + - ]: 3 : sheet::DataPilotFieldGroupBy::YEARS, *pDPObj, true, NULL);
2669 [ + - ]: 3 : ScDPSaveGroupDimension aGroupDim(aBaseDimName, aGroupDimName);
2670 [ + - ]: 3 : aGroupDim.SetDateInfo(aInfo, sheet::DataPilotFieldGroupBy::YEARS);
2671 [ + - ]: 3 : pDimData->AddGroupDimension(aGroupDim);
2672 : :
2673 : : // Set orientation.
2674 [ + - ]: 3 : ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aGroupDimName);
2675 [ + - ]: 3 : pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
2676 [ + - ][ + - ]: 3 : pSaveData->SetPosition(pDim, 0); // set it to the left end.
2677 : : }
2678 : :
2679 [ + - ]: 3 : pDPObj->SetSaveData(*pSaveData);
2680 [ + - ]: 3 : ScRange aOutRange = refreshGroups(pDPs, pDPObj);
2681 : : {
2682 : : // Expected output table content. 0 = empty cell
2683 : : const char* aOutputCheck[][4] = {
2684 : : { "Years", "Quarters", "Date", 0 },
2685 : : { "2011", "Q1", "Jan", "1" },
2686 : : { 0, 0, "Mar", "2" },
2687 : : { 0, "Q3", "Sep", "7" },
2688 : : { "2012", "Q1", "Jan", "3" },
2689 : : { 0, 0, "Feb", "9" },
2690 : : { 0, 0, "Mar", "6" },
2691 : : { 0, "Q4", "Dec", "8" },
2692 : : { "Total Result", 0, 0, "36" },
2693 : 3 : };
2694 : :
2695 [ + - ]: 3 : bSuccess = checkDPTableOutput<4>(m_pDoc, aOutRange, aOutputCheck, "Years, quarters and months date groups.");
2696 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2697 : : }
2698 : :
2699 : : {
2700 : : // Let's hide year 2012.
2701 : 3 : pSaveData = pDPObj->GetSaveData();
2702 [ + - ]: 3 : ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(rtl::OUString("Years"));
2703 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Years dimension should exist.", pDim);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2704 [ + - ]: 3 : ScDPSaveMember* pMem = pDim->GetMemberByName(rtl::OUString("2012"));
2705 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Member should exist.", pMem);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2706 [ + - ]: 3 : pMem->SetIsVisible(false);
2707 : : }
2708 [ + - ]: 3 : pDPObj->SetSaveData(*pSaveData);
2709 [ + - ]: 3 : pDPObj->ReloadGroupTableData();
2710 [ + - ]: 3 : pDPObj->InvalidateData();
2711 : :
2712 [ + - ]: 3 : aOutRange = refresh(pDPObj);
2713 : : {
2714 : : // Expected output table content. 0 = empty cell
2715 : : const char* aOutputCheck[][4] = {
2716 : : { "Years", "Quarters", "Date", 0 },
2717 : : { "2011", "Q1", "Jan", "1" },
2718 : : { 0, 0, "Mar", "2" },
2719 : : { 0, "Q3", "Sep", "7" },
2720 : : { "Total Result", 0, 0, "10" },
2721 : 3 : };
2722 : :
2723 [ + - ]: 3 : bSuccess = checkDPTableOutput<4>(m_pDoc, aOutRange, aOutputCheck, "Year 2012 data now hidden");
2724 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2725 : : }
2726 : :
2727 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2728 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2729 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2730 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2731 : :
2732 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2733 [ + - ]: 3 : m_pDoc->DeleteTab(0);
2734 : 3 : }
2735 : :
2736 : 3 : void Test::testPivotTableEmptyRows()
2737 : : {
2738 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2739 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2740 : :
2741 : : // Raw data
2742 : : const char* aData[][2] = {
2743 : : { "Name", "Value" },
2744 : : { "A", "1" },
2745 : : { "B", "2" },
2746 : : { "C", "3" },
2747 : : { "D", "4" },
2748 : 3 : };
2749 : :
2750 : : // Dimension definition
2751 : : DPFieldDef aFields[] = {
2752 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
2753 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2754 : 3 : };
2755 : :
2756 : 3 : ScAddress aPos(1,1,0);
2757 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2758 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2759 : :
2760 : : // Extend the range downward to include some trailing empty rows.
2761 [ + - ]: 3 : aDataRange.aEnd.IncRow(2);
2762 : :
2763 : : ScDPObject* pDPObj = createDPFromRange(
2764 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2765 : :
2766 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2767 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2768 : :
2769 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2770 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2771 [ + - ]: 3 : pDPs->GetCount() == 1);
2772 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2773 : :
2774 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
2775 : :
2776 : : {
2777 : : // Expected output table content. 0 = empty cell
2778 : : const char* aOutputCheck[][2] = {
2779 : : { "Name", 0 },
2780 : : { "A", "1" },
2781 : : { "B", "2" },
2782 : : { "C", "3" },
2783 : : { "D", "4" },
2784 : : { "(empty)", 0 },
2785 : : { "Total Result", "10" },
2786 : 3 : };
2787 : :
2788 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Include empty rows");
2789 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2790 : : }
2791 : :
2792 : : // This time, ignore empty rows.
2793 : 3 : ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2794 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Save data doesn't exist.", pSaveData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2795 [ + - ]: 3 : pSaveData->SetIgnoreEmptyRows(true);
2796 [ + - ]: 3 : pDPObj->ClearTableData();
2797 [ + - ]: 3 : aOutRange = refresh(pDPObj);
2798 : :
2799 : : {
2800 : : // Expected output table content. 0 = empty cell
2801 : : const char* aOutputCheck[][2] = {
2802 : : { "Name", 0 },
2803 : : { "A", "1" },
2804 : : { "B", "2" },
2805 : : { "C", "3" },
2806 : : { "D", "4" },
2807 : : { "Total Result", "10" },
2808 : 3 : };
2809 : :
2810 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Ignore empty rows");
2811 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2812 : : }
2813 : :
2814 : : // Modify the source to remove member 'A', then refresh the table.
2815 [ + - ]: 3 : m_pDoc->SetString(1, 2, 0, "B");
2816 : :
2817 [ + - ]: 3 : std::set<ScDPObject*> aRefs;
2818 [ + - ]: 3 : sal_uLong nErr = pDPs->ReloadCache(pDPObj, aRefs);
2819 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to reload cache.", !nErr);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2820 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("There should only be one pivot table linked to this cache.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ # # ]
[ + - ]
2821 [ + - ]: 3 : aRefs.size() == 1 && *aRefs.begin() == pDPObj);
2822 : :
2823 [ + - ]: 3 : pDPObj->ClearTableData();
2824 [ + - ]: 3 : aOutRange = refresh(pDPObj);
2825 : :
2826 : : {
2827 : : // Expected output table content. 0 = empty cell
2828 : : const char* aOutputCheck[][2] = {
2829 : : { "Name", 0 },
2830 : : { "B", "3" },
2831 : : { "C", "3" },
2832 : : { "D", "4" },
2833 : : { "Total Result", "10" },
2834 : 3 : };
2835 : :
2836 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Ignore empty rows");
2837 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2838 : : }
2839 : :
2840 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2841 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2842 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2843 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2844 : :
2845 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2846 [ + - ]: 3 : m_pDoc->DeleteTab(0);
2847 : 3 : }
2848 : :
2849 : 3 : void Test::testPivotTableTextNumber()
2850 : : {
2851 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2852 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2853 : :
2854 : : // Raw data
2855 : : const char* aData[][2] = {
2856 : : { "Name", "Value" },
2857 : : { "0001", "1" },
2858 : : { "0002", "2" },
2859 : : { "0003", "3" },
2860 : : { "0004", "4" },
2861 : 3 : };
2862 : :
2863 : : // Dimension definition
2864 : : DPFieldDef aFields[] = {
2865 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
2866 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2867 : 3 : };
2868 : :
2869 : : // Insert raw data such that the first column values are entered as text.
2870 : 3 : size_t nRowCount = SAL_N_ELEMENTS(aData);
2871 [ + + ]: 18 : for (size_t nRow = 0; nRow < nRowCount; ++nRow)
2872 : : {
2873 [ + - ]: 15 : ScSetStringParam aParam;
2874 : 15 : aParam.mbDetectNumberFormat = false;
2875 : 15 : aParam.meSetTextNumFormat = ScSetStringParam::Always;
2876 [ + - ]: 15 : m_pDoc->SetString(0, nRow, 0, OUString::createFromAscii(aData[nRow][0]), &aParam);
2877 : 15 : aParam.meSetTextNumFormat = ScSetStringParam::Never;
2878 [ + - ]: 15 : m_pDoc->SetString(1, nRow, 0, OUString::createFromAscii(aData[nRow][1]), &aParam);
2879 : :
2880 [ + + ]: 15 : if (nRow == 0)
2881 : : // Don't check the header row.
2882 : 3 : continue;
2883 : :
2884 : : // Check the data rows.
2885 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("This cell is supposed to be text.", m_pDoc->HasStringData(0, nRow, 0));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2886 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("This cell is supposed to be numeric.", m_pDoc->HasValueData(1, nRow, 0));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2887 : : }
2888 : :
2889 : 3 : ScRange aDataRange(0, 0, 0, 1, 4, 0);
2890 : :
2891 : : ScDPObject* pDPObj = createDPFromRange(
2892 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2893 : :
2894 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2895 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2896 : :
2897 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2898 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2899 [ + - ]: 3 : pDPs->GetCount() == 1);
2900 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2901 : :
2902 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
2903 : :
2904 : : {
2905 : : // Expected output table content. 0 = empty cell
2906 : : const char* aOutputCheck[][2] = {
2907 : : { "Name", 0 },
2908 : : { "0001", "1" },
2909 : : { "0002", "2" },
2910 : : { "0003", "3" },
2911 : : { "0004", "4" },
2912 : : { "Total Result", "10" },
2913 : 3 : };
2914 : :
2915 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Text number field members");
2916 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2917 : : }
2918 : :
2919 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2920 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2921 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2922 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2923 : :
2924 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2925 [ + - ]: 3 : m_pDoc->DeleteTab(0);
2926 : 3 : }
2927 : :
2928 : 3 : void Test::testPivotTableCaseInsensitiveStrings()
2929 : : {
2930 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
2931 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Table"));
2932 : :
2933 : : // Raw data
2934 : : const char* aData[][2] = {
2935 : : { "Name", "Value" },
2936 : : { "A", "1" },
2937 : : { "a", "2" },
2938 : 3 : };
2939 : :
2940 : : // Dimension definition
2941 : : DPFieldDef aFields[] = {
2942 : : { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
2943 : : { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
2944 : 3 : };
2945 : :
2946 : 3 : ScAddress aPos(1,1,0);
2947 [ + - ]: 3 : ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
2948 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2949 : :
2950 : : ScDPObject* pDPObj = createDPFromRange(
2951 [ + - ]: 3 : m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
2952 : :
2953 [ + - ]: 3 : ScDPCollection* pDPs = m_pDoc->GetDPCollection();
2954 [ + - ]: 3 : bool bSuccess = pDPs->InsertNewTable(pDPObj);
2955 : :
2956 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2957 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2958 [ + - ]: 3 : pDPs->GetCount() == 1);
2959 [ + - ][ + - ]: 3 : pDPObj->SetName(pDPs->CreateNewName());
2960 : :
2961 [ + - ]: 3 : ScRange aOutRange = refresh(pDPObj);
2962 : :
2963 : : {
2964 : : // Expected output table content. 0 = empty cell
2965 : : const char* aOutputCheck[][2] = {
2966 : : { "Name", 0 },
2967 : : { "A", "3" },
2968 : : { "Total Result", "3" },
2969 : 3 : };
2970 : :
2971 [ + - ]: 3 : bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Case insensitive strings");
2972 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2973 : : }
2974 : :
2975 [ + - ]: 3 : pDPs->FreeTable(pDPObj);
2976 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
[ + - ][ + - ]
[ + - ][ + - ]
2977 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
[ + - ][ + - ]
[ + - ][ + - ]
2978 [ + - ]: 3 : pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
2979 : :
2980 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2981 [ + - ]: 3 : m_pDoc->DeleteTab(0);
2982 : 3 : }
2983 : :
2984 : 3 : void Test::testSheetCopy()
2985 : : {
2986 : 3 : OUString aTabName("TestTab");
2987 [ + - ]: 3 : m_pDoc->InsertTab(0, aTabName);
2988 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("document should have one sheet to begin with.", m_pDoc->GetTableCount() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2989 : : SCROW nRow1, nRow2;
2990 [ + - ]: 3 : bool bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
2991 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
2992 : :
2993 : : // Copy and test the result.
2994 [ + - ]: 3 : m_pDoc->CopyTab(0, 1);
2995 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount() == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
2996 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
2997 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("copied sheet should also have all rows visible as the original.", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
2998 [ + - ]: 3 : m_pDoc->DeleteTab(1);
2999 : :
3000 [ + - ]: 3 : m_pDoc->SetRowHidden(5, 10, 0, true);
3001 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
3002 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3003 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(5, 0, &nRow1, &nRow2);
3004 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3005 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(11, 0, &nRow1, &nRow2);
3006 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3007 : :
3008 : : // Copy the sheet once again.
3009 [ + - ]: 3 : m_pDoc->CopyTab(0, 1);
3010 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount() == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3011 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
3012 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3013 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(5, 1, &nRow1, &nRow2);
3014 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3015 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(11, 1, &nRow1, &nRow2);
3016 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3017 [ + - ]: 3 : m_pDoc->DeleteTab(1);
3018 [ + - ]: 3 : m_pDoc->DeleteTab(0);
3019 : 3 : }
3020 : :
3021 : 3 : void Test::testSheetMove()
3022 : : {
3023 : 3 : OUString aTabName("TestTab1");
3024 [ + - ]: 3 : m_pDoc->InsertTab(0, aTabName);
3025 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("document should have one sheet to begin with.", m_pDoc->GetTableCount(), static_cast<SCTAB>(1));
[ + - ][ + - ]
[ + - ][ + - ]
3026 : : SCROW nRow1, nRow2;
3027 [ + - ]: 3 : bool bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
3028 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3029 : :
3030 : : //test if inserting before another sheet works
3031 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("TestTab2"));
3032 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("document should have two sheets", m_pDoc->GetTableCount(), static_cast<SCTAB>(2));
[ + - ][ + - ]
[ + - ][ + - ]
3033 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
3034 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3035 : :
3036 : : // Move and test the result.
3037 [ + - ]: 3 : m_pDoc->MoveTab(0, 1);
3038 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount(), static_cast<SCTAB>(2));
[ + - ][ + - ]
[ + - ][ + - ]
3039 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
3040 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("copied sheet should also have all rows visible as the original.", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3041 : 3 : rtl::OUString aName;
3042 [ + - ]: 3 : m_pDoc->GetName(0, aName);
3043 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "sheets should have changed places", aName == "TestTab1" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3044 : :
3045 [ + - ]: 3 : m_pDoc->SetRowHidden(5, 10, 0, true);
3046 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
3047 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3048 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(5, 0, &nRow1, &nRow2);
3049 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3050 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(11, 0, &nRow1, &nRow2);
3051 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3052 : :
3053 : : // Move the sheet once again.
3054 [ + - ]: 3 : m_pDoc->MoveTab(1, 0);
3055 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount(), static_cast<SCTAB>(2));
[ + - ][ + - ]
[ + - ][ + - ]
3056 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
3057 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3058 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(5, 1, &nRow1, &nRow2);
3059 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3060 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(11, 1, &nRow1, &nRow2);
3061 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3062 [ + - ]: 3 : m_pDoc->GetName(0, aName);
3063 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "sheets should have changed places", aName == "TestTab2" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3064 [ + - ]: 3 : m_pDoc->DeleteTab(1);
3065 [ + - ]: 3 : m_pDoc->DeleteTab(0);
3066 : 3 : }
3067 : :
3068 : 15 : ScDocShell* findLoadedDocShellByName(const OUString& rName)
3069 : : {
3070 [ + - ]: 15 : TypeId aType(TYPE(ScDocShell));
3071 [ + - ]: 15 : ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
3072 [ + + ]: 450 : while (pShell)
3073 : : {
3074 : 444 : SfxMedium* pMedium = pShell->GetMedium();
3075 [ + + ]: 444 : if (pMedium)
3076 : : {
3077 [ + - ]: 12 : OUString aName = pMedium->GetName();
3078 [ + + ]: 12 : if (aName.equals(rName))
3079 [ + + ]: 12 : return pShell;
3080 : : }
3081 [ + - ]: 435 : pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
3082 : : }
3083 : 15 : return NULL;
3084 : : }
3085 : :
3086 : 6 : ScRange getCachedRange(const ScExternalRefCache::TableTypeRef& pCacheTab)
3087 : : {
3088 : 6 : ScRange aRange;
3089 : :
3090 [ + - ]: 6 : vector<SCROW> aRows;
3091 [ + - ]: 6 : pCacheTab->getAllRows(aRows);
3092 [ + - ][ + - ]: 6 : vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
3093 : 6 : bool bFirst = true;
3094 [ + - ][ + - ]: 33 : for (; itrRow != itrRowEnd; ++itrRow)
[ + + ]
3095 : : {
3096 [ + - ]: 27 : SCROW nRow = *itrRow;
3097 [ + - ]: 27 : vector<SCCOL> aCols;
3098 [ + - ]: 27 : pCacheTab->getAllCols(nRow, aCols);
3099 [ + - ][ + - ]: 27 : vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
3100 [ + - ][ + - ]: 81 : for (; itrCol != itrColEnd; ++itrCol)
[ + + ]
3101 : : {
3102 [ + - ]: 54 : SCCOL nCol = *itrCol;
3103 [ + + ]: 54 : if (bFirst)
3104 : : {
3105 : 6 : aRange.aStart = ScAddress(nCol, nRow, 0);
3106 : 6 : aRange.aEnd = aRange.aStart;
3107 : 6 : bFirst = false;
3108 : : }
3109 : : else
3110 : : {
3111 [ - + ]: 48 : if (nCol < aRange.aStart.Col())
3112 : 0 : aRange.aStart.SetCol(nCol);
3113 [ + + ]: 48 : else if (aRange.aEnd.Col() < nCol)
3114 : 6 : aRange.aEnd.SetCol(nCol);
3115 : :
3116 [ - + ]: 48 : if (nRow < aRange.aStart.Row())
3117 : 0 : aRange.aStart.SetRow(nRow);
3118 [ + + ]: 48 : else if (aRange.aEnd.Row() < nRow)
3119 : 21 : aRange.aEnd.SetRow(nRow);
3120 : : }
3121 : : }
3122 : 27 : }
3123 : 6 : return aRange;
3124 : : }
3125 : :
3126 : 3 : void Test::testExternalRef()
3127 : : {
3128 [ + - ][ + - ]: 3 : ScDocShellRef xExtDocSh = new ScDocShell;
3129 : 3 : OUString aExtDocName("file:///extdata.fake");
3130 : 3 : OUString aExtSh1Name("Data1");
3131 : 3 : OUString aExtSh2Name("Data2");
3132 : 3 : OUString aExtSh3Name("Data3");
3133 [ + - ][ + - ]: 3 : SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
[ + - ][ + - ]
3134 [ + - ]: 3 : xExtDocSh->DoInitNew(pMed);
3135 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3136 [ + - ]: 3 : findLoadedDocShellByName(aExtDocName) != NULL);
3137 : :
3138 : : // Populate the external source document.
3139 : 3 : ScDocument* pExtDoc = xExtDocSh->GetDocument();
3140 [ + - ]: 3 : pExtDoc->InsertTab(0, aExtSh1Name);
3141 [ + - ]: 3 : pExtDoc->InsertTab(1, aExtSh2Name);
3142 [ + - ]: 3 : pExtDoc->InsertTab(2, aExtSh3Name);
3143 : :
3144 : 3 : OUString name("Name");
3145 : 3 : OUString value("Value");
3146 : 3 : OUString andy("Andy");
3147 : 3 : OUString bruce("Bruce");
3148 : 3 : OUString charlie("Charlie");
3149 : 3 : OUString david("David");
3150 : 3 : OUString edward("Edward");
3151 : 3 : OUString frank("Frank");
3152 : 3 : OUString george("George");
3153 : 3 : OUString henry("Henry");
3154 : :
3155 : : // Sheet 1
3156 [ + - ]: 3 : pExtDoc->SetString(0, 0, 0, name);
3157 [ + - ]: 3 : pExtDoc->SetString(0, 1, 0, andy);
3158 [ + - ]: 3 : pExtDoc->SetString(0, 2, 0, bruce);
3159 [ + - ]: 3 : pExtDoc->SetString(0, 3, 0, charlie);
3160 [ + - ]: 3 : pExtDoc->SetString(0, 4, 0, david);
3161 [ + - ]: 3 : pExtDoc->SetString(1, 0, 0, value);
3162 : 3 : double val = 10;
3163 [ + - ]: 3 : pExtDoc->SetValue(1, 1, 0, val);
3164 : 3 : val = 11;
3165 [ + - ]: 3 : pExtDoc->SetValue(1, 2, 0, val);
3166 : 3 : val = 12;
3167 [ + - ]: 3 : pExtDoc->SetValue(1, 3, 0, val);
3168 : 3 : val = 13;
3169 [ + - ]: 3 : pExtDoc->SetValue(1, 4, 0, val);
3170 : :
3171 : : // Sheet 2 remains empty.
3172 : :
3173 : : // Sheet 3
3174 [ + - ]: 3 : pExtDoc->SetString(0, 0, 2, name);
3175 [ + - ]: 3 : pExtDoc->SetString(0, 1, 2, edward);
3176 [ + - ]: 3 : pExtDoc->SetString(0, 2, 2, frank);
3177 [ + - ]: 3 : pExtDoc->SetString(0, 3, 2, george);
3178 [ + - ]: 3 : pExtDoc->SetString(0, 4, 2, henry);
3179 [ + - ]: 3 : pExtDoc->SetString(1, 0, 2, value);
3180 : 3 : val = 99;
3181 [ + - ]: 3 : pExtDoc->SetValue(1, 1, 2, val);
3182 : 3 : val = 98;
3183 [ + - ]: 3 : pExtDoc->SetValue(1, 2, 2, val);
3184 : 3 : val = 97;
3185 [ + - ]: 3 : pExtDoc->SetValue(1, 3, 2, val);
3186 : 3 : val = 96;
3187 [ + - ]: 3 : pExtDoc->SetValue(1, 4, 2, val);
3188 : :
3189 : : // Test external refernces on the main document while the external
3190 : : // document is still in memory.
3191 : 3 : OUString test;
3192 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Test Sheet"));
3193 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, OUString("='file:///extdata.fake'#Data1.A1"));
3194 [ + - ]: 3 : m_pDoc->GetString(0, 0, 0, test);
3195 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(name));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3196 : :
3197 : : // After the initial access to the external document, the external ref
3198 : : // manager should create sheet cache entries for *all* sheets from that
3199 : : // document. Note that the doc may have more than 3 sheets but ensure
3200 : : // that the first 3 are what we expect.
3201 [ + - ]: 3 : ScExternalRefManager* pRefMgr = m_pDoc->GetExternalRefManager();
3202 [ + - ]: 3 : sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtDocName);
3203 [ + - ]: 3 : vector<OUString> aTabNames;
3204 [ + - ]: 3 : pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
3205 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be at least 3 sheets.", aTabNames.size() >= 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3206 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[0].equals(aExtSh1Name));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3207 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[1].equals(aExtSh2Name));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3208 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[2].equals(aExtSh3Name));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3209 : :
3210 [ + - ]: 3 : m_pDoc->SetString(1, 0, 0, OUString("='file:///extdata.fake'#Data1.B1"));
3211 [ + - ]: 3 : m_pDoc->GetString(1, 0, 0, test);
3212 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(value));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3213 : :
3214 [ + - ]: 3 : m_pDoc->SetString(0, 1, 0, OUString("='file:///extdata.fake'#Data1.A2"));
3215 [ + - ]: 3 : m_pDoc->SetString(0, 2, 0, OUString("='file:///extdata.fake'#Data1.A3"));
3216 [ + - ]: 3 : m_pDoc->SetString(0, 3, 0, OUString("='file:///extdata.fake'#Data1.A4"));
3217 [ + - ]: 3 : m_pDoc->SetString(0, 4, 0, OUString("='file:///extdata.fake'#Data1.A5"));
3218 [ + - ]: 3 : m_pDoc->SetString(0, 5, 0, OUString("='file:///extdata.fake'#Data1.A6"));
3219 : :
3220 : : {
3221 : : // Referencing an empty cell should display '0'.
3222 : 3 : const char* pChecks[] = { "Andy", "Bruce", "Charlie", "David", "0" };
3223 [ + + ]: 18 : for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
3224 : : {
3225 [ + - ]: 15 : m_pDoc->GetString(0, static_cast<SCROW>(i+1), 0, test);
3226 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", test.equalsAscii(pChecks[i]));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3227 : : }
3228 : : }
3229 [ + - ]: 3 : m_pDoc->SetString(1, 1, 0, OUString("='file:///extdata.fake'#Data1.B2"));
3230 [ + - ]: 3 : m_pDoc->SetString(1, 2, 0, OUString("='file:///extdata.fake'#Data1.B3"));
3231 [ + - ]: 3 : m_pDoc->SetString(1, 3, 0, OUString("='file:///extdata.fake'#Data1.B4"));
3232 [ + - ]: 3 : m_pDoc->SetString(1, 4, 0, OUString("='file:///extdata.fake'#Data1.B5"));
3233 [ + - ]: 3 : m_pDoc->SetString(1, 5, 0, OUString("='file:///extdata.fake'#Data1.B6"));
3234 : : {
3235 : 3 : double pChecks[] = { 10, 11, 12, 13, 0 };
3236 [ + + ]: 18 : for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
3237 : : {
3238 [ + - ]: 15 : m_pDoc->GetValue(1, static_cast<SCROW>(i+1), 0, val);
3239 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", val == pChecks[i]);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3240 : : }
3241 : : }
3242 : :
3243 [ + - ]: 3 : m_pDoc->SetString(2, 0, 0, OUString("='file:///extdata.fake'#Data3.A1"));
3244 [ + - ]: 3 : m_pDoc->SetString(2, 1, 0, OUString("='file:///extdata.fake'#Data3.A2"));
3245 [ + - ]: 3 : m_pDoc->SetString(2, 2, 0, OUString("='file:///extdata.fake'#Data3.A3"));
3246 [ + - ]: 3 : m_pDoc->SetString(2, 3, 0, OUString("='file:///extdata.fake'#Data3.A4"));
3247 : : {
3248 : 3 : const char* pChecks[] = { "Name", "Edward", "Frank", "George" };
3249 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
3250 : : {
3251 [ + - ]: 12 : m_pDoc->GetString(2, static_cast<SCROW>(i), 0, test);
3252 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", test.equalsAscii(pChecks[i]));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3253 : : }
3254 : : }
3255 : :
3256 [ + - ]: 3 : m_pDoc->SetString(3, 0, 0, OUString("='file:///extdata.fake'#Data3.B1"));
3257 [ + - ]: 3 : m_pDoc->SetString(3, 1, 0, OUString("='file:///extdata.fake'#Data3.B2"));
3258 [ + - ]: 3 : m_pDoc->SetString(3, 2, 0, OUString("='file:///extdata.fake'#Data3.B3"));
3259 [ + - ]: 3 : m_pDoc->SetString(3, 3, 0, OUString("='file:///extdata.fake'#Data3.B4"));
3260 : : {
3261 : 3 : const char* pChecks[] = { "Value", "99", "98", "97" };
3262 [ + + ]: 15 : for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
3263 : : {
3264 [ + - ]: 12 : m_pDoc->GetString(3, static_cast<SCROW>(i), 0, test);
3265 [ + - ][ + - ]: 12 : CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", test.equalsAscii(pChecks[i]));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3266 : : }
3267 : : }
3268 : :
3269 : : // At this point, all accessed cell data from the external document should
3270 : : // have been cached.
3271 : : ScExternalRefCache::TableTypeRef pCacheTab = pRefMgr->getCacheTable(
3272 [ + - ]: 3 : nFileId, aExtSh1Name, false);
3273 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 1 should exist.", pCacheTab.get() != NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3274 [ + - ]: 3 : ScRange aCachedRange = getCachedRange(pCacheTab);
3275 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
3276 : : aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
3277 [ + - ]: 3 : aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 4);
3278 : :
3279 : : // Sheet2 is not referenced at all; the cache table shouldn't even exist.
3280 [ + - ][ + - ]: 3 : pCacheTab = pRefMgr->getCacheTable(nFileId, aExtSh2Name, false);
[ + - ]
3281 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 2 should *not* exist.", pCacheTab.get() == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3282 : :
3283 : : // Sheet3's row 5 is not referenced; it should not be cached.
3284 [ + - ][ + - ]: 3 : pCacheTab = pRefMgr->getCacheTable(nFileId, aExtSh3Name, false);
[ + - ]
3285 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 3 should exist.", pCacheTab.get() != NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3286 [ + - ]: 3 : aCachedRange = getCachedRange(pCacheTab);
3287 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3288 : : aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
3289 [ + - ]: 3 : aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 3);
3290 : :
3291 : : // Unload the external document shell.
3292 [ + - ]: 3 : xExtDocSh->DoClose();
3293 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3294 [ + - ]: 3 : findLoadedDocShellByName(aExtDocName) == NULL);
3295 : :
3296 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
[ + - ]
3297 : 3 : }
3298 : :
3299 : 3 : void testExtRefFuncT(ScDocument* pDoc, ScDocument* pExtDoc)
3300 : : {
3301 [ + - ]: 3 : clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
3302 [ + - ]: 3 : clearRange(pExtDoc, ScRange(0, 0, 0, 1, 9, 0));
3303 : :
3304 [ + - ]: 3 : pExtDoc->SetString(0, 0, 0, rtl::OUString("'1.2"));
3305 [ + - ]: 3 : pExtDoc->SetString(0, 1, 0, rtl::OUString("Foo"));
3306 [ + - ]: 3 : pExtDoc->SetValue(0, 2, 0, 12.3);
3307 [ + - ]: 3 : pDoc->SetString(0, 0, 0, rtl::OUString("=T('file:///extdata.fake'#Data.A1)"));
3308 [ + - ]: 3 : pDoc->SetString(0, 1, 0, rtl::OUString("=T('file:///extdata.fake'#Data.A2)"));
3309 [ + - ]: 3 : pDoc->SetString(0, 2, 0, rtl::OUString("=T('file:///extdata.fake'#Data.A3)"));
3310 [ + - ]: 3 : pDoc->CalcAll();
3311 : :
3312 [ + - ]: 3 : rtl::OUString aRes = pDoc->GetString(0, 0, 0);
3313 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "1.2" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3314 [ + - ]: 3 : aRes = pDoc->GetString(0, 1, 0);
3315 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "Foo" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3316 [ + - ]: 3 : aRes = pDoc->GetString(0, 2, 0);
3317 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected result with T.", aRes.isEmpty());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3318 : 3 : }
3319 : :
3320 : 3 : void Test::testExternalRefFunctions()
3321 : : {
3322 [ + - ][ + - ]: 3 : ScDocShellRef xExtDocSh = new ScDocShell;
3323 : 3 : OUString aExtDocName("file:///extdata.fake");
3324 [ + - ][ + - ]: 3 : SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
[ + - ][ + - ]
3325 [ + - ]: 3 : xExtDocSh->DoInitNew(pMed);
3326 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3327 [ + - ]: 3 : findLoadedDocShellByName(aExtDocName) != NULL);
3328 : :
3329 [ + - ]: 3 : ScExternalRefManager* pRefMgr = m_pDoc->GetExternalRefManager();
3330 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("external reference manager doesn't exist.", pRefMgr);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3331 [ + - ]: 3 : sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtDocName);
3332 [ + - ]: 3 : const OUString* pFileName = pRefMgr->getExternalFileName(nFileId);
3333 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("file name registration has somehow failed.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
3334 [ + - ]: 3 : pFileName && pFileName->equals(aExtDocName));
3335 : :
3336 : : // Populate the external source document.
3337 : 3 : ScDocument* pExtDoc = xExtDocSh->GetDocument();
3338 [ + - ]: 3 : pExtDoc->InsertTab(0, rtl::OUString("Data"));
3339 : 3 : double val = 1;
3340 [ + - ]: 3 : pExtDoc->SetValue(0, 0, 0, val);
3341 : : // leave cell B1 empty.
3342 : 3 : val = 2;
3343 [ + - ]: 3 : pExtDoc->SetValue(0, 1, 0, val);
3344 [ + - ]: 3 : pExtDoc->SetValue(1, 1, 0, val);
3345 : 3 : val = 3;
3346 [ + - ]: 3 : pExtDoc->SetValue(0, 2, 0, val);
3347 [ + - ]: 3 : pExtDoc->SetValue(1, 2, 0, val);
3348 : 3 : val = 4;
3349 [ + - ]: 3 : pExtDoc->SetValue(0, 3, 0, val);
3350 [ + - ]: 3 : pExtDoc->SetValue(1, 3, 0, val);
3351 : :
3352 [ + - ]: 3 : m_pDoc->InsertTab(0, rtl::OUString("Test"));
3353 : :
3354 : : struct {
3355 : : const char* pFormula; double fResult;
3356 : : } aChecks[] = {
3357 : : { "=SUM('file:///extdata.fake'#Data.A1:A4)", 10 },
3358 : : { "=SUM('file:///extdata.fake'#Data.B1:B4)", 9 },
3359 : : { "=AVERAGE('file:///extdata.fake'#Data.A1:A4)", 2.5 },
3360 : : { "=AVERAGE('file:///extdata.fake'#Data.B1:B4)", 3 },
3361 : : { "=COUNT('file:///extdata.fake'#Data.A1:A4)", 4 },
3362 : : { "=COUNT('file:///extdata.fake'#Data.B1:B4)", 3 }
3363 : 3 : };
3364 : :
3365 [ + + ]: 21 : for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
3366 : : {
3367 [ + - ]: 18 : m_pDoc->SetString(0, 0, 0, rtl::OUString::createFromAscii(aChecks[i].pFormula));
3368 [ + - ]: 18 : m_pDoc->CalcAll();
3369 [ + - ]: 18 : m_pDoc->GetValue(0, 0, 0, val);
3370 [ + - ][ + - ]: 18 : CPPUNIT_ASSERT_MESSAGE("unexpected result involving external ranges.", val == aChecks[i].fResult);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3371 : : }
3372 : :
3373 [ + - ]: 3 : pRefMgr->clearCache(nFileId);
3374 [ + - ]: 3 : testExtRefFuncT(m_pDoc, pExtDoc);
3375 : :
3376 : : // Unload the external document shell.
3377 [ + - ]: 3 : xExtDocSh->DoClose();
3378 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3379 [ + - ]: 3 : findLoadedDocShellByName(aExtDocName) == NULL);
3380 : :
3381 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
3382 : 3 : }
3383 : :
3384 : 3 : void Test::testDataArea()
3385 : : {
3386 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Data"));
3387 : :
3388 : : // Totally empty sheet should be rightfully considered empty in all accounts.
3389 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Sheet is expected to be empty.", m_pDoc->IsPrintEmpty(0, 0, 0, 100, 100));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3390 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Sheet is expected to be empty.", m_pDoc->IsBlockEmpty(0, 0, 0, 100, 100));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3391 : :
3392 : : // Now, set borders in some cells....
3393 [ + - ]: 3 : ::editeng::SvxBorderLine aLine(NULL, 50, table::BorderLineStyle::SOLID);
3394 [ + - ]: 3 : SvxBoxItem aBorderItem(ATTR_BORDER);
3395 [ + - ]: 3 : aBorderItem.SetLine(&aLine, BOX_LINE_LEFT);
3396 [ + - ]: 3 : aBorderItem.SetLine(&aLine, BOX_LINE_RIGHT);
3397 [ + + ]: 303 : for (SCROW i = 0; i < 100; ++i)
3398 : : // Set borders from row 1 to 100.
3399 [ + - ]: 300 : m_pDoc->ApplyAttr(0, i, 0, aBorderItem);
3400 : :
3401 : : // Now the sheet is considered non-empty for printing purposes, but still
3402 : : // be empty in all the other cases.
3403 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Empty sheet with borders should be printable.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3404 [ + - ]: 3 : !m_pDoc->IsPrintEmpty(0, 0, 0, 100, 100));
3405 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("But it should still be considered empty in all the other cases.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3406 [ + - ]: 3 : m_pDoc->IsBlockEmpty(0, 0, 0, 100, 100));
3407 : :
3408 : : // Adding a real cell content should turn the block non-empty.
3409 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, OUString("Some text"));
3410 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Now the block should not be empty with a real cell content.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3411 [ + - ]: 3 : !m_pDoc->IsBlockEmpty(0, 0, 0, 100, 100));
3412 : :
3413 : : // TODO: Add more tests for normal data area calculation.
3414 : :
3415 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
3416 : 3 : }
3417 : :
3418 : 3 : void Test::testStreamValid()
3419 : : {
3420 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Sheet1"));
3421 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Sheet2"));
3422 [ + - ]: 3 : m_pDoc->InsertTab(2, OUString("Sheet3"));
3423 [ + - ]: 3 : m_pDoc->InsertTab(3, OUString("Sheet4"));
3424 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("We should have 4 sheet instances.", m_pDoc->GetTableCount(), static_cast<SCTAB>(4));
[ + - ][ + - ]
[ + - ][ + - ]
3425 : :
3426 : 3 : OUString a1("A1");
3427 : 3 : OUString a2("A2");
3428 : 3 : OUString test;
3429 : :
3430 : : // Put values into Sheet1.
3431 [ + - ]: 3 : m_pDoc->SetString(0, 0, 0, a1);
3432 [ + - ]: 3 : m_pDoc->SetString(0, 1, 0, a2);
3433 [ + - ]: 3 : m_pDoc->GetString(0, 0, 0, test);
3434 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet1.A1", test.equals(a1));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3435 [ + - ]: 3 : m_pDoc->GetString(0, 1, 0, test);
3436 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet1.A2", test.equals(a2));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3437 : :
3438 : : // Put formulas into Sheet2 to Sheet4 to reference values from Sheet1.
3439 [ + - ]: 3 : m_pDoc->SetString(0, 0, 1, OUString("=Sheet1.A1"));
3440 [ + - ]: 3 : m_pDoc->SetString(0, 1, 1, OUString("=Sheet1.A2"));
3441 [ + - ]: 3 : m_pDoc->SetString(0, 0, 2, OUString("=Sheet1.A1"));
3442 [ + - ]: 3 : m_pDoc->SetString(0, 0, 3, OUString("=Sheet1.A2"));
3443 : :
3444 [ + - ]: 3 : m_pDoc->GetString(0, 0, 1, test);
3445 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet2.A1", test.equals(a1));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3446 [ + - ]: 3 : m_pDoc->GetString(0, 1, 1, test);
3447 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet2.A2", test.equals(a2));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3448 [ + - ]: 3 : m_pDoc->GetString(0, 0, 2, test);
3449 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet3.A1", test.equals(a1));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3450 [ + - ]: 3 : m_pDoc->GetString(0, 0, 3, test);
3451 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet3.A1", test.equals(a2));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3452 : :
3453 : : // Set all sheet streams valid after all the initial cell values are in
3454 : : // place. In reality we need to have real XML streams stored in order to
3455 : : // claim they are valid, but we are just testing the flag values here.
3456 [ + - ]: 3 : m_pDoc->SetStreamValid(0, true);
3457 [ + - ]: 3 : m_pDoc->SetStreamValid(1, true);
3458 [ + - ]: 3 : m_pDoc->SetStreamValid(2, true);
3459 [ + - ]: 3 : m_pDoc->SetStreamValid(3, true);
3460 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(0));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3461 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(1));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3462 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(2));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3463 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(3));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3464 : :
3465 : : // Now, insert a new row at row 2 position on Sheet1. This will move cell
3466 : : // A2 downward but cell A1 remains unmoved.
3467 [ + - ]: 3 : m_pDoc->InsertRow(0, 0, MAXCOL, 0, 1, 2);
3468 [ + - ]: 3 : m_pDoc->GetString(0, 0, 0, test);
3469 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cell A1 should not have moved.", test.equals(a1));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3470 [ + - ]: 3 : m_pDoc->GetString(0, 3, 0, test);
3471 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the old cell A2 should now be at A4.", test.equals(a2));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3472 [ + - ]: 3 : const ScBaseCell* pCell = m_pDoc->GetCell(ScAddress(0, 1, 0));
3473 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cell A2 should be empty.", pCell == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3474 [ + - ]: 3 : pCell = m_pDoc->GetCell(ScAddress(0, 2, 0));
3475 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cell A3 should be empty.", pCell == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3476 : :
3477 : : // After the move, Sheet1, Sheet2, and Sheet4 should have their stream
3478 : : // invalidated, whereas Sheet3's stream should still be valid.
3479 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(0));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3480 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(1));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3481 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(3));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3482 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Stream should still be valid.", m_pDoc->IsStreamValid(2));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3483 : :
3484 [ + - ]: 3 : m_pDoc->DeleteTab(3);
3485 [ + - ]: 3 : m_pDoc->DeleteTab(2);
3486 [ + - ]: 3 : m_pDoc->DeleteTab(1);
3487 [ + - ]: 3 : m_pDoc->DeleteTab(0);
3488 : 3 : }
3489 : :
3490 : 3 : void Test::testFunctionLists()
3491 : : {
3492 : : const char* aDataBase[] = {
3493 : : "DAVERAGE",
3494 : : "DCOUNT",
3495 : : "DCOUNTA",
3496 : : "DGET",
3497 : : "DMAX",
3498 : : "DMIN",
3499 : : "DPRODUCT",
3500 : : "DSTDEV",
3501 : : "DSTDEVP",
3502 : : "DSUM",
3503 : : "DVAR",
3504 : : "DVARP",
3505 : : 0
3506 : 3 : };
3507 : :
3508 : : const char* aDateTime[] = {
3509 : : "DATE",
3510 : : "DATEDIF",
3511 : : "DATEVALUE",
3512 : : "DAY",
3513 : : "DAYS",
3514 : : "DAYS360",
3515 : : "EASTERSUNDAY",
3516 : : "HOUR",
3517 : : "MINUTE",
3518 : : "MONTH",
3519 : : "NOW",
3520 : : "SECOND",
3521 : : "TIME",
3522 : : "TIMEVALUE",
3523 : : "TODAY",
3524 : : "WEEKDAY",
3525 : : "WEEKNUM",
3526 : : "YEAR",
3527 : : 0
3528 : 3 : };
3529 : :
3530 : : const char* aFinancial[] = {
3531 : : "CUMIPMT",
3532 : : "CUMPRINC",
3533 : : "DB",
3534 : : "DDB",
3535 : : "DURATION",
3536 : : "EFFECTIVE",
3537 : : "FV",
3538 : : "IPMT",
3539 : : "IRR",
3540 : : "ISPMT",
3541 : : "MIRR",
3542 : : "NOMINAL",
3543 : : "NPER",
3544 : : "NPV",
3545 : : "PMT",
3546 : : "PPMT",
3547 : : "PV",
3548 : : "RATE",
3549 : : "RRI",
3550 : : "SLN",
3551 : : "SYD",
3552 : : "VDB",
3553 : : 0
3554 : 3 : };
3555 : :
3556 : : const char* aInformation[] = {
3557 : : "CELL",
3558 : : "CURRENT",
3559 : : "FORMULA",
3560 : : "INFO",
3561 : : "ISBLANK",
3562 : : "ISERR",
3563 : : "ISERROR",
3564 : : "ISFORMULA",
3565 : : "ISLOGICAL",
3566 : : "ISNA",
3567 : : "ISNONTEXT",
3568 : : "ISNUMBER",
3569 : : "ISREF",
3570 : : "ISTEXT",
3571 : : "N",
3572 : : "NA",
3573 : : "TYPE",
3574 : : 0
3575 : 3 : };
3576 : :
3577 : : const char* aLogical[] = {
3578 : : "AND",
3579 : : "FALSE",
3580 : : "IF",
3581 : : "NOT",
3582 : : "OR",
3583 : : "TRUE",
3584 : : "XOR",
3585 : : 0
3586 : 3 : };
3587 : :
3588 : : const char* aMathematical[] = {
3589 : : "ABS",
3590 : : "ACOS",
3591 : : "ACOSH",
3592 : : "ACOT",
3593 : : "ACOTH",
3594 : : "ASIN",
3595 : : "ASINH",
3596 : : "ATAN",
3597 : : "ATAN2",
3598 : : "ATANH",
3599 : : "BITAND",
3600 : : "BITLSHIFT",
3601 : : "BITOR",
3602 : : "BITRSHIFT",
3603 : : "BITXOR",
3604 : : "CEILING",
3605 : : "COMBIN",
3606 : : "COMBINA",
3607 : : "CONVERT",
3608 : : "COS",
3609 : : "COSH",
3610 : : "COT",
3611 : : "COTH",
3612 : : "COUNTBLANK",
3613 : : "COUNTIF",
3614 : : "CSC",
3615 : : "CSCH",
3616 : : "DEGREES",
3617 : : "EUROCONVERT",
3618 : : "EVEN",
3619 : : "EXP",
3620 : : "FACT",
3621 : : "FLOOR",
3622 : : "GCD",
3623 : : "INT",
3624 : : "ISEVEN",
3625 : : "ISODD",
3626 : : "LCM",
3627 : : "LN",
3628 : : "LOG",
3629 : : "LOG10",
3630 : : "MOD",
3631 : : "ODD",
3632 : : "PI",
3633 : : "POWER",
3634 : : "PRODUCT",
3635 : : "RADIANS",
3636 : : "RAND",
3637 : : "ROUND",
3638 : : "ROUNDDOWN",
3639 : : "ROUNDUP",
3640 : : "SEC",
3641 : : "SECH",
3642 : : "SIGN",
3643 : : "SIN",
3644 : : "SINH",
3645 : : "SQRT",
3646 : : "SUBTOTAL",
3647 : : "SUM",
3648 : : "SUMIF",
3649 : : "SUMSQ",
3650 : : "TAN",
3651 : : "TANH",
3652 : : "TRUNC",
3653 : : 0
3654 : 3 : };
3655 : :
3656 : : const char* aArray[] = {
3657 : : "FREQUENCY",
3658 : : "GROWTH",
3659 : : "LINEST",
3660 : : "LOGEST",
3661 : : "MDETERM",
3662 : : "MINVERSE",
3663 : : "MMULT",
3664 : : "MUNIT",
3665 : : "SUMPRODUCT",
3666 : : "SUMX2MY2",
3667 : : "SUMX2PY2",
3668 : : "SUMXMY2",
3669 : : "TRANSPOSE",
3670 : : "TREND",
3671 : : 0
3672 : 3 : };
3673 : :
3674 : : const char* aStatistical[] = {
3675 : : "AVEDEV",
3676 : : "AVERAGE",
3677 : : "AVERAGEA",
3678 : : "B",
3679 : : "BETADIST",
3680 : : "BETAINV",
3681 : : "BINOMDIST",
3682 : : "CHIDIST",
3683 : : "CHIINV",
3684 : : "CHISQDIST",
3685 : : "CHISQINV",
3686 : : "CHITEST",
3687 : : "CONFIDENCE",
3688 : : "CORREL",
3689 : : "COUNT",
3690 : : "COUNTA",
3691 : : "COVAR",
3692 : : "CRITBINOM",
3693 : : "DEVSQ",
3694 : : "EXPONDIST",
3695 : : "FDIST",
3696 : : "FINV",
3697 : : "FISHER",
3698 : : "FISHERINV",
3699 : : "FORECAST",
3700 : : "FTEST",
3701 : : "GAMMA",
3702 : : "GAMMADIST",
3703 : : "GAMMAINV",
3704 : : "GAMMALN",
3705 : : "GAUSS",
3706 : : "GEOMEAN",
3707 : : "HARMEAN",
3708 : : "HYPGEOMDIST",
3709 : : "INTERCEPT",
3710 : : "KURT",
3711 : : "LARGE",
3712 : : "LOGINV",
3713 : : "LOGNORMDIST",
3714 : : "MAX",
3715 : : "MAXA",
3716 : : "MEDIAN",
3717 : : "MIN",
3718 : : "MINA",
3719 : : "MODE",
3720 : : "NEGBINOMDIST",
3721 : : "NORMDIST",
3722 : : "NORMINV",
3723 : : "NORMSDIST",
3724 : : "NORMSINV",
3725 : : "PEARSON",
3726 : : "PERCENTILE",
3727 : : "PERCENTRANK",
3728 : : "PERMUT",
3729 : : "PERMUTATIONA",
3730 : : "PHI",
3731 : : "POISSON",
3732 : : "PROB",
3733 : : "QUARTILE",
3734 : : "RANK",
3735 : : "RSQ",
3736 : : "SKEW",
3737 : : "SLOPE",
3738 : : "SMALL",
3739 : : "STANDARDIZE",
3740 : : "STDEV",
3741 : : "STDEVA",
3742 : : "STDEVP",
3743 : : "STDEVPA",
3744 : : "STEYX",
3745 : : "TDIST",
3746 : : "TINV",
3747 : : "TRIMMEAN",
3748 : : "TTEST",
3749 : : "VAR",
3750 : : "VARA",
3751 : : "VARP",
3752 : : "VARPA",
3753 : : "WEIBULL",
3754 : : "ZTEST",
3755 : : 0
3756 : 3 : };
3757 : :
3758 : : const char* aSpreadsheet[] = {
3759 : : "ADDRESS",
3760 : : "AREAS",
3761 : : "CHOOSE",
3762 : : "COLUMN",
3763 : : "COLUMNS",
3764 : : "DDE",
3765 : : "ERRORTYPE",
3766 : : "GETPIVOTDATA",
3767 : : "HLOOKUP",
3768 : : "HYPERLINK",
3769 : : "INDEX",
3770 : : "INDIRECT",
3771 : : "LOOKUP",
3772 : : "MATCH",
3773 : : "OFFSET",
3774 : : "ROW",
3775 : : "ROWS",
3776 : : "SHEET",
3777 : : "SHEETS",
3778 : : "STYLE",
3779 : : "VLOOKUP",
3780 : : 0
3781 : 3 : };
3782 : :
3783 : : const char* aText[] = {
3784 : : "ARABIC",
3785 : : "ASC",
3786 : : "BAHTTEXT",
3787 : : "BASE",
3788 : : "CHAR",
3789 : : "CLEAN",
3790 : : "CODE",
3791 : : "CONCATENATE",
3792 : : "DECIMAL",
3793 : : "DOLLAR",
3794 : : "EXACT",
3795 : : "FIND",
3796 : : "FIXED",
3797 : : "JIS",
3798 : : "LEFT",
3799 : : "LEN",
3800 : : "LOWER",
3801 : : "MID",
3802 : : "PROPER",
3803 : : "REPLACE",
3804 : : "REPT",
3805 : : "RIGHT",
3806 : : "ROMAN",
3807 : : "SEARCH",
3808 : : "SUBSTITUTE",
3809 : : "T",
3810 : : "TEXT",
3811 : : "TRIM",
3812 : : "UNICHAR",
3813 : : "UNICODE",
3814 : : "UPPER",
3815 : : "VALUE",
3816 : : 0
3817 : 3 : };
3818 : :
3819 : : struct {
3820 : : const char* Category; const char** Functions;
3821 : : } aTests[] = {
3822 : : { "Database", aDataBase },
3823 : : { "Date&Time", aDateTime },
3824 : : { "Financial", aFinancial },
3825 : : { "Information", aInformation },
3826 : : { "Logical", aLogical },
3827 : : { "Mathematical", aMathematical },
3828 : : { "Array", aArray },
3829 : : { "Statistical", aStatistical },
3830 : : { "Spreadsheet", aSpreadsheet },
3831 : : { "Text", aText },
3832 : : { "Add-in", 0 },
3833 : : { 0, 0 }
3834 : 3 : };
3835 : :
3836 [ + - ]: 3 : ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
3837 [ + - ]: 3 : sal_uInt32 n = pFuncMgr->getCount();
3838 [ + + ]: 36 : for (sal_uInt32 i = 0; i < n; ++i)
3839 : : {
3840 [ + - ]: 33 : const formula::IFunctionCategory* pCat = pFuncMgr->getCategory(i);
3841 [ + - ][ + - ]: 33 : CPPUNIT_ASSERT_MESSAGE("Unexpected category name", pCat->getName().equalsAscii(aTests[i].Category));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3842 [ + - ]: 33 : sal_uInt32 nFuncCount = pCat->getCount();
3843 [ + + ]: 894 : for (sal_uInt32 j = 0; j < nFuncCount; ++j)
3844 : : {
3845 [ + - ]: 861 : const formula::IFunctionDescription* pFunc = pCat->getFunction(j);
3846 [ + - ][ + - ]: 861 : CPPUNIT_ASSERT_MESSAGE("Unexpected function name", pFunc->getFunctionName().equalsAscii(aTests[i].Functions[j]));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3847 : : }
3848 : : }
3849 : 3 : }
3850 : :
3851 : 3 : void Test::testGraphicsInGroup()
3852 : : {
3853 : 3 : OUString aTabName("TestTab");
3854 [ + - ]: 3 : m_pDoc->InsertTab(0, aTabName);
3855 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("document should have one sheet to begin with.", m_pDoc->GetTableCount() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3856 : : SCROW nRow1, nRow2;
3857 [ + - ]: 3 : bool bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
3858 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3859 : :
3860 [ + - ]: 3 : m_pDoc->InitDrawLayer();
3861 [ + - ]: 3 : ScDrawLayer *pDrawLayer = m_pDoc->GetDrawLayer();
3862 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("must have a draw layer", pDrawLayer != NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3863 [ + - ]: 3 : SdrPage* pPage = pDrawLayer->GetPage(0);
3864 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("must have a draw page", pPage != NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3865 : :
3866 : : {
3867 : : //Add a square
3868 [ + - ]: 3 : Rectangle aOrigRect(2,2,100,100);
3869 [ + - ][ + - ]: 3 : SdrRectObj *pObj = new SdrRectObj(aOrigRect);
3870 [ + - ]: 3 : pPage->InsertObject(pObj);
3871 [ + - ]: 3 : const Rectangle &rNewRect = pObj->GetLogicRect();
3872 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("must have equal position and size", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3873 : :
3874 [ + - ]: 3 : ScDrawLayer::SetPageAnchored(*pObj);
3875 : :
3876 : : //Use a range of rows guaranteed to include all of the square
3877 [ + - ]: 3 : m_pDoc->ShowRows(0, 100, 0, false);
3878 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3879 [ + - ]: 3 : m_pDoc->ShowRows(0, 100, 0, true);
3880 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3881 : :
3882 [ + - ]: 3 : ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
3883 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("That shouldn't change size or positioning", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3884 : :
3885 [ + - ]: 3 : m_pDoc->ShowRows(0, 100, 0, false);
3886 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Left and Right should be unchanged",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
3887 [ + - ]: 3 : aOrigRect.nLeft == rNewRect.nLeft && aOrigRect.nRight == rNewRect.nRight);
3888 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Height should be minimum allowed height",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3889 [ + - ]: 3 : (rNewRect.nBottom - rNewRect.nTop) <= 1);
3890 [ + - ]: 3 : m_pDoc->ShowRows(0, 100, 0, true);
3891 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3892 : : }
3893 : :
3894 : : {
3895 : : // Add a circle.
3896 [ + - ]: 3 : Rectangle aOrigRect = Rectangle(10,10,210,210); // 200 x 200
3897 [ + - ][ + - ]: 3 : SdrCircObj* pObj = new SdrCircObj(OBJ_CIRC, aOrigRect);
3898 [ + - ]: 3 : pPage->InsertObject(pObj);
3899 [ + - ]: 3 : const Rectangle& rNewRect = pObj->GetLogicRect();
3900 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Position and size of the circle shouldn't change when inserted into the page.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3901 [ + - ]: 3 : aOrigRect == rNewRect);
3902 : :
3903 [ + - ]: 3 : ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
3904 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Size changed when cell anchored. Not good.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3905 [ + - ]: 3 : aOrigRect == rNewRect);
3906 : :
3907 : : // Insert 2 rows at the top. This should push the circle object down.
3908 [ + - ]: 3 : m_pDoc->InsertRow(0, 0, MAXCOL, 0, 0, 2);
3909 : :
3910 : : // Make sure the size of the circle is still identical.
3911 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Size of the circle has changed, but shouldn't!",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3912 [ + - ]: 3 : aOrigRect.GetSize() == rNewRect.GetSize());
3913 : :
3914 : : // Delete 2 rows at the top. This should bring the circle object to its original position.
3915 [ + - ]: 3 : m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 0, 2);
3916 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to move back to its original position.", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3917 : : }
3918 : :
3919 : : {
3920 : : // Add a line.
3921 [ + - ]: 3 : basegfx::B2DPolygon aTempPoly;
3922 : 3 : Point aStartPos(10,300), aEndPos(110,200); // bottom-left to top-right.
3923 [ + - ]: 3 : Rectangle aOrigRect(10,200,110,300); // 100 x 100
3924 [ + - ]: 3 : aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y()));
3925 [ + - ]: 3 : aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y()));
3926 [ + - ][ + - ]: 3 : SdrPathObj* pObj = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aTempPoly));
[ + - ][ + - ]
3927 [ + - ]: 3 : pObj->NbcSetLogicRect(aOrigRect);
3928 [ + - ]: 3 : pPage->InsertObject(pObj);
3929 [ + - ]: 3 : const Rectangle& rNewRect = pObj->GetLogicRect();
3930 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Size differ.", aOrigRect == rNewRect);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3931 : :
3932 [ + - ]: 3 : ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
3933 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Size changed when cell-anchored. Not good.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3934 [ + - ]: 3 : aOrigRect == rNewRect);
3935 : :
3936 : : // Insert 2 rows at the top and delete them immediately.
3937 [ + - ]: 3 : m_pDoc->InsertRow(0, 0, MAXCOL, 0, 0, 2);
3938 [ + - ]: 3 : m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 0, 2);
3939 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Size of a line object changed after row insertion and removal.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3940 [ + - ]: 3 : aOrigRect == rNewRect);
3941 : :
3942 [ + - ]: 3 : sal_Int32 n = pObj->GetPointCount();
3943 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be exactly 2 points in a line object.", n == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3944 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Line shape has changed.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ]
[ # # # # ]
[ + - ]
3945 [ + - + - ]: 6 : aStartPos == pObj->GetPoint(0) && aEndPos == pObj->GetPoint(1));
3946 : : }
3947 : :
3948 [ + - ]: 3 : m_pDoc->DeleteTab(0);
3949 : 3 : }
3950 : :
3951 : 3 : void Test::testGraphicsOnSheetMove()
3952 : : {
3953 [ + - ]: 3 : m_pDoc->InsertTab(0, rtl::OUString("Tab1"));
3954 [ + - ]: 3 : m_pDoc->InsertTab(1, rtl::OUString("Tab2"));
3955 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("There should be only 2 sheets to begin with", m_pDoc->GetTableCount() == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3956 : :
3957 [ + - ]: 3 : m_pDoc->InitDrawLayer();
3958 [ + - ]: 3 : ScDrawLayer* pDrawLayer = m_pDoc->GetDrawLayer();
3959 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3960 [ + - ]: 3 : SdrPage* pPage = pDrawLayer->GetPage(0);
3961 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3962 : :
3963 : : // Insert an object.
3964 [ + - ]: 3 : Rectangle aObjRect(2,2,100,100);
3965 [ + - ][ + - ]: 3 : SdrObject* pObj = new SdrRectObj(aObjRect);
3966 [ + - ]: 3 : pPage->InsertObject(pObj);
3967 [ + - ]: 3 : ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
3968 : :
3969 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be one object on the 1st sheet.", pPage->GetObjCount(), static_cast<sal_uIntPtr>(1));
[ + - ][ + - ]
[ + - ][ + - ]
3970 : :
3971 [ + - ]: 3 : const ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
3972 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Object meta-data doesn't exist.", pData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3973 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 0 && pData->maEnd.Tab() == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ]
3974 : :
3975 [ + - ]: 3 : pPage = pDrawLayer->GetPage(1);
3976 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("No page instance for the 2nd sheet.", pPage);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
3977 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("2nd sheet shouldn't have any object.", pPage->GetObjCount(), static_cast<sal_uIntPtr>(0));
[ + - ][ + - ]
[ + - ][ + - ]
3978 : :
3979 : : // Insert a new sheet at left-end, and make sure the object has moved to
3980 : : // the 2nd page.
3981 [ + - ]: 3 : m_pDoc->InsertTab(0, rtl::OUString("NewTab"));
3982 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 3 sheets.", m_pDoc->GetTableCount(), static_cast<SCTAB>(3));
[ + - ][ + - ]
[ + - ][ + - ]
3983 [ + - ]: 3 : pPage = pDrawLayer->GetPage(0);
3984 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("1st sheet should have no object.", pPage && pPage->GetObjCount() == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3985 [ + - ]: 3 : pPage = pDrawLayer->GetPage(1);
3986 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("2nd sheet should have one object.", pPage && pPage->GetObjCount() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3987 [ + - ]: 3 : pPage = pDrawLayer->GetPage(2);
3988 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("3rd sheet should have no object.", pPage && pPage->GetObjCount() == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3989 : :
3990 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 1 && pData->maEnd.Tab() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ]
3991 : :
3992 : : // Now, delete the sheet that just got inserted. The object should be back
3993 : : // on the 1st sheet.
3994 [ + - ]: 3 : m_pDoc->DeleteTab(0);
3995 [ + - ]: 3 : pPage = pDrawLayer->GetPage(0);
3996 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("1st sheet should have one object.", pPage && pPage->GetObjCount() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
3997 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("Size and position of the object shouldn't change.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
3998 [ + - ]: 3 : pObj->GetLogicRect() == aObjRect);
3999 : :
4000 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 0 && pData->maEnd.Tab() == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ]
4001 : :
4002 : : // Move the 1st sheet to the last position.
4003 [ + - ]: 3 : m_pDoc->MoveTab(0, 1);
4004 [ + - ]: 3 : pPage = pDrawLayer->GetPage(0);
4005 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("1st sheet should have no object.", pPage && pPage->GetObjCount() == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4006 [ + - ]: 3 : pPage = pDrawLayer->GetPage(1);
4007 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("2nd sheet should have one object.", pPage && pPage->GetObjCount() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4008 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 1 && pData->maEnd.Tab() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ]
4009 : :
4010 : : // Copy the 2nd sheet, which has one drawing object to the last position.
4011 [ + - ]: 3 : m_pDoc->CopyTab(1, 2);
4012 [ + - ]: 3 : pPage = pDrawLayer->GetPage(2);
4013 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Copied sheet should have one object.", pPage && pPage->GetObjCount() == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4014 [ + - ]: 3 : pObj = pPage->GetObj(0);
4015 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4016 [ + - ]: 3 : pData = ScDrawLayer::GetObjData(pObj);
4017 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object meta-data.", pData);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4018 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 2 && pData->maEnd.Tab() == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ + - ]
4019 : :
4020 [ + - ]: 3 : m_pDoc->DeleteTab(2);
4021 [ + - ]: 3 : m_pDoc->DeleteTab(1);
4022 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4023 : 3 : }
4024 : :
4025 : 3 : void Test::testPostIts()
4026 : : {
4027 : 3 : rtl::OUString aHello("Hello world");
4028 : 3 : rtl::OUString aJimBob("Jim Bob");
4029 : 3 : rtl::OUString aTabName("PostIts");
4030 : 3 : rtl::OUString aTabName2("Table2");
4031 [ + - ]: 3 : m_pDoc->InsertTab(0, aTabName);
4032 : :
4033 : 3 : ScAddress rAddr(2, 2, 0);
4034 [ + - ][ + - ]: 3 : ScPostIt *pNote = m_pDoc->GetNotes(rAddr.Tab())->GetOrCreateNote(rAddr);
4035 [ + - ]: 3 : pNote->SetText(rAddr, aHello);
4036 : 3 : pNote->SetAuthor(aJimBob);
4037 : :
4038 [ + - ][ + - ]: 3 : ScPostIt *pGetNote = m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr);
4039 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note should be itself", pGetNote == pNote );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4040 : :
4041 [ + - ]: 3 : bool bInsertRow = m_pDoc->InsertRow( 0, 0, 100, 0, 1, 1 );
4042 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert row", bInsertRow );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4043 : :
4044 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4045 [ + - ]: 3 : rAddr.IncRow();
4046 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4047 : :
4048 [ + - ]: 3 : bool bInsertCol = m_pDoc->InsertCol( 0, 0, 100, 0, 1, 1 );
4049 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert column", bInsertCol );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4050 : :
4051 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4052 [ + - ]: 3 : rAddr.IncCol();
4053 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4054 : :
4055 [ + - ]: 3 : m_pDoc->InsertTab(0, aTabName2);
4056 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4057 [ + - ]: 3 : rAddr.IncTab();
4058 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4059 : :
4060 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4061 [ + - ]: 3 : rAddr.IncTab(-1);
4062 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4063 : :
4064 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4065 : 3 : }
4066 : :
4067 : 3 : void Test::testToggleRefFlag()
4068 : : {
4069 : : // In this test, there is no need to insert formula string into a cell in
4070 : : // the document, as ScRefFinder does not depend on the content of the
4071 : : // document except for the sheet names.
4072 : :
4073 : 3 : OUString aTabName("Test");
4074 [ + - ]: 3 : m_pDoc->InsertTab(0, aTabName);
4075 : :
4076 : : {
4077 : : // Calc A1: basic 2D reference
4078 : :
4079 : 3 : OUString aFormula("=B100");
4080 : 3 : ScAddress aPos(1, 5, 0);
4081 [ + - ][ + - ]: 3 : ScRefFinder aFinder(aFormula, aPos, m_pDoc, formula::FormulaGrammar::CONV_OOO);
[ + - ]
4082 : :
4083 : : // Original
4084 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula.equals(aFinder.GetText()));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4085 : :
4086 : : // column relative / row relative -> column absolute / row absolute
4087 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4088 [ + - ]: 3 : aFormula = aFinder.GetText();
4089 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=$B$100" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4090 : :
4091 : : // column absolute / row absolute -> column relative / row absolute
4092 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4093 [ + - ]: 3 : aFormula = aFinder.GetText();
4094 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=B$100" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4095 : :
4096 : : // column relative / row absolute -> column absolute / row relative
4097 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4098 [ + - ]: 3 : aFormula = aFinder.GetText();
4099 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=$B100" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4100 : :
4101 : : // column absolute / row relative -> column relative / row relative
4102 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4103 [ + - ]: 3 : aFormula = aFinder.GetText();
4104 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=B100" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4105 : : }
4106 : :
4107 : : {
4108 : : // Excel R1C1: basic 2D reference
4109 : :
4110 : 3 : OUString aFormula("=R2C1");
4111 : 3 : ScAddress aPos(3, 5, 0);
4112 [ + - ][ + - ]: 3 : ScRefFinder aFinder(aFormula, aPos, m_pDoc, formula::FormulaGrammar::CONV_XL_R1C1);
[ + - ]
4113 : :
4114 : : // Original
4115 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula.equals(aFinder.GetText()));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4116 : :
4117 : : // column absolute / row absolute -> column relative / row absolute
4118 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4119 [ + - ]: 3 : aFormula = aFinder.GetText();
4120 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R2C[-3]" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4121 : :
4122 : : // column relative / row absolute - > column absolute / row relative
4123 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4124 [ + - ]: 3 : aFormula = aFinder.GetText();
4125 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R[-4]C1" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4126 : :
4127 : : // column absolute / row relative -> column relative / row relative
4128 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4129 [ + - ]: 3 : aFormula = aFinder.GetText();
4130 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R[-4]C[-3]" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4131 : :
4132 : : // column relative / row relative -> column absolute / row absolute
4133 [ + - ]: 3 : aFinder.ToggleRel(0, aFormula.getLength());
4134 [ + - ]: 3 : aFormula = aFinder.GetText();
4135 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R2C1" );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4136 : : }
4137 : :
4138 : : // TODO: Add more test cases esp. for 3D references, Excel A1 syntax, and
4139 : : // partial selection within formula string.
4140 : :
4141 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4142 : 3 : }
4143 : :
4144 : 3 : void Test::testAutofilter()
4145 : : {
4146 : 3 : OUString aTabName("Test");
4147 : 3 : OUString aDBName("NONAME");
4148 : :
4149 [ + - ]: 3 : m_pDoc->InsertTab( 0, aTabName );
4150 : :
4151 : : // cell contents (0 = empty cell)
4152 : : const char* aData[][3] = {
4153 : : { "C1", "C2", "C3" },
4154 : : { "0", "1", "A" },
4155 : : { "1", "2", 0 },
4156 : : { "1", "2", "B" },
4157 : : { "0", "2", "B" }
4158 : 3 : };
4159 : :
4160 : 3 : SCCOL nCols = SAL_N_ELEMENTS(aData[0]);
4161 : 3 : SCROW nRows = SAL_N_ELEMENTS(aData);
4162 : :
4163 : : // Populate cells.
4164 [ + + ]: 18 : for (SCROW i = 0; i < nRows; ++i)
4165 [ + + ]: 60 : for (SCCOL j = 0; j < nCols; ++j)
4166 [ + + ]: 45 : if (aData[i][j])
4167 [ + - ]: 42 : m_pDoc->SetString(j, i, 0, rtl::OUString::createFromAscii(aData[i][j]));
4168 : :
4169 [ + - ][ + - ]: 3 : ScDBData* pDBData = new ScDBData(aDBName, 0, 0, 0, nCols-1, nRows-1);
4170 [ + - ]: 3 : m_pDoc->SetAnonymousDBData(0,pDBData);
4171 : :
4172 : 3 : pDBData->SetAutoFilter(true);
4173 : 3 : ScRange aRange;
4174 [ + - ]: 3 : pDBData->GetArea(aRange);
4175 : 3 : m_pDoc->ApplyFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
4176 : 3 : aRange.aEnd.Col(), aRange.aStart.Row(),
4177 [ + - ]: 9 : aRange.aStart.Tab(), SC_MF_AUTO);
4178 : :
4179 : : //create the query param
4180 [ + - ]: 3 : ScQueryParam aParam;
4181 [ + - ]: 3 : pDBData->GetQueryParam(aParam);
4182 [ + - ]: 3 : ScQueryEntry& rEntry = aParam.GetEntry(0);
4183 : 3 : rEntry.bDoQuery = true;
4184 : 3 : rEntry.nField = 0;
4185 : 3 : rEntry.eOp = SC_EQUAL;
4186 [ + - ]: 3 : rEntry.GetQueryItem().mfVal = 0;
4187 : : // add queryParam to database range.
4188 [ + - ]: 3 : pDBData->SetQueryParam(aParam);
4189 : :
4190 : : // perform the query.
4191 [ + - ]: 3 : m_pDoc->Query(0, aParam, true);
4192 : :
4193 : : //control output
4194 : : SCROW nRow1, nRow2;
4195 [ + - ]: 3 : bool bHidden = m_pDoc->RowHidden(2, 0, &nRow1, &nRow2);
4196 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 2 & 3 should be hidden", bHidden && nRow1 == 2 && nRow2 == 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4197 : :
4198 : : // Remove filtering.
4199 [ + - ]: 3 : rEntry.Clear();
4200 [ + - ]: 3 : m_pDoc->Query(0, aParam, true);
4201 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
4202 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("All rows should be shown.", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4203 : :
4204 : : // Filter for non-empty cells by column C.
4205 : 3 : rEntry.bDoQuery = true;
4206 : 3 : rEntry.nField = 2;
4207 [ + - ]: 3 : rEntry.SetQueryByNonEmpty();
4208 [ + - ]: 3 : m_pDoc->Query(0, aParam, true);
4209 : :
4210 : : // only row 3 should be hidden. The rest should be visible.
4211 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
4212 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 1 & 2 should be visible.", !bHidden && nRow1 == 0 && nRow2 == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4213 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(2, 0, &nRow1, &nRow2);
4214 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("row 3 should be hidden.", bHidden && nRow1 == 2 && nRow2 == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4215 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(3, 0, &nRow1, &nRow2);
4216 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("row 4 and down should be visible.", !bHidden && nRow1 == 3 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4217 : :
4218 : : // Now, filter for empty cells by column C.
4219 [ + - ]: 3 : rEntry.SetQueryByEmpty();
4220 [ + - ]: 3 : m_pDoc->Query(0, aParam, true);
4221 : :
4222 : : // Now, only row 1 and 3, and 6 and down should be visible.
4223 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
4224 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("row 1 should be visible.", !bHidden && nRow1 == 0 && nRow2 == 0);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4225 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(1, 0, &nRow1, &nRow2);
4226 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("row 2 should be hidden.", bHidden && nRow1 == 1 && nRow2 == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4227 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(2, 0, &nRow1, &nRow2);
4228 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("row 3 should be visible.", !bHidden && nRow1 == 2 && nRow2 == 2);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4229 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(3, 0, &nRow1, &nRow2);
4230 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 4 & 5 should be hidden.", bHidden && nRow1 == 3 && nRow2 == 4);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4231 [ + - ]: 3 : bHidden = m_pDoc->RowHidden(5, 0, &nRow1, &nRow2);
4232 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("rows 6 and down should be all visible.", !bHidden && nRow1 == 5 && nRow2 == MAXROW);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
4233 : :
4234 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
4235 : 3 : }
4236 : :
4237 : 3 : void Test::testCopyPaste()
4238 : : {
4239 [ + - ]: 3 : m_pDoc->InsertTab(0, OUString("Sheet1"));
4240 [ + - ]: 3 : m_pDoc->InsertTab(1, OUString("Sheet2"));
4241 : : //test copy&paste + ScUndoPaste
4242 : : //copy local and global range names in formulas
4243 : : //string cells and value cells
4244 [ + - ]: 3 : m_pDoc->SetValue(0, 0, 0, 1);
4245 [ + - ]: 3 : m_pDoc->SetValue(3, 0, 0, 0);
4246 [ + - ]: 3 : m_pDoc->SetValue(3, 1, 0, 1);
4247 [ + - ]: 3 : m_pDoc->SetValue(3, 2, 0, 2);
4248 [ + - ]: 3 : m_pDoc->SetValue(3, 3, 0, 3);
4249 [ + - ]: 3 : m_pDoc->SetString(2, 0, 0, OUString("test"));
4250 : 3 : ScAddress aAdr (0, 0, 0);
4251 : :
4252 : : //create some range names, local and global
4253 [ + - ][ + - ]: 3 : ScRangeData* pLocal1 = new ScRangeData(m_pDoc, rtl::OUString("local1"), aAdr);
4254 [ + - ][ + - ]: 3 : ScRangeData* pLocal2 = new ScRangeData(m_pDoc, OUString("local2"), aAdr);
4255 [ + - ][ + - ]: 3 : ScRangeData* pGlobal = new ScRangeData(m_pDoc, OUString("global"), aAdr);
4256 [ + - ][ + - ]: 3 : ScRangeName* pGlobalRangeName = new ScRangeName();
4257 [ + - ]: 3 : pGlobalRangeName->insert(pGlobal);
4258 [ + - ][ + - ]: 3 : ScRangeName* pLocalRangeName1 = new ScRangeName();
4259 [ + - ]: 3 : pLocalRangeName1->insert(pLocal1);
4260 [ + - ]: 3 : pLocalRangeName1->insert(pLocal2);
4261 [ + - ]: 3 : m_pDoc->SetRangeName(pGlobalRangeName);
4262 [ + - ]: 3 : m_pDoc->SetRangeName(0, pLocalRangeName1);
4263 : :
4264 : : //add formula
4265 : 3 : rtl::OUString aFormulaString("=local1+global+SUM($C$1:$D$4)");
4266 [ + - ]: 3 : m_pDoc->SetString(1, 0, 0, aFormulaString);
4267 : :
4268 : 3 : double aValue = 0;
4269 [ + - ]: 3 : m_pDoc->GetValue(1, 0, 0, aValue);
4270 [ + - ][ + - ]: 3 : std::cout << "Value: " << aValue << std::endl;
[ + - ]
4271 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 8", aValue, 8, 0.00000001);
[ + - ][ + - ]
[ + - ]
4272 : :
4273 : : //copy Sheet1.A1:C1 to Sheet2.A2:C2
4274 : 3 : ScRange aRange(0,0,0,2,0,0);
4275 [ + - ]: 3 : ScClipParam aClipParam(aRange, false);
4276 [ + - ]: 3 : ScMarkData aMark;
4277 [ + - ]: 3 : aMark.SetMarkArea(aRange);
4278 [ + - ][ + - ]: 3 : ScDocument* pClipDoc = new ScDocument(SCDOCMODE_CLIP);
4279 [ + - ]: 3 : m_pDoc->CopyToClip(aClipParam, pClipDoc, &aMark);
4280 : :
4281 : 3 : sal_uInt16 nFlags = IDF_ALL;
4282 : 3 : aRange = ScRange(0,1,1,2,1,1);//target: Sheet2.A2:C2
4283 [ + - ][ + - ]: 3 : ScDocument* pUndoDoc = new ScDocument(SCDOCMODE_UNDO);
4284 [ + - ]: 3 : pUndoDoc->InitUndo(m_pDoc, 1, 1, true, true);
4285 [ + - ]: 3 : ScMarkData aMarkData2;
4286 [ + - ]: 3 : aMarkData2.SetMarkArea(aRange);
4287 [ + - ][ + - ]: 3 : ScRefUndoData* pRefUndoData= new ScRefUndoData(m_pDoc);
4288 : : SfxUndoAction* pUndo = new ScUndoPaste(
4289 [ + - ][ + - ]: 3 : &m_xDocShRef, ScRange(0, 1, 1, 2, 1, 1), aMarkData2, pUndoDoc, NULL, IDF_ALL, pRefUndoData, false);
[ + - ][ + - ]
4290 [ + - ]: 3 : m_pDoc->CopyFromClip(aRange, aMarkData2, nFlags, NULL, pClipDoc);
4291 : :
4292 : : //check values after copying
4293 : 3 : rtl::OUString aString;
4294 [ + - ]: 3 : m_pDoc->GetValue(1,1,1, aValue);
4295 [ + - ]: 3 : m_pDoc->GetFormula(1,1,1, aString);
4296 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("copied formula should return 2", aValue, 2, 0.00000001);
[ + - ][ + - ]
[ + - ]
4297 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("formula string was not copied correctly", aString == aFormulaString);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4298 [ + - ]: 3 : m_pDoc->GetValue(0,1,1, aValue);
4299 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("copied value should be 1", aValue == 1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4300 : :
4301 : : //chack local range name after copying
4302 [ + - ][ + - ]: 3 : pLocal1 = m_pDoc->GetRangeName(1)->findByUpperName(OUString("LOCAL1"));
4303 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("local range name 1 should be copied", pLocal1);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4304 : 3 : ScRange aRangeLocal1;
4305 [ + - ]: 3 : pLocal1->IsValidReference(aRangeLocal1);
4306 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("local range 1 should still point to Sheet1.A1",aRangeLocal1 == ScRange(0,0,0,0,0,0));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4307 [ + - ][ + - ]: 3 : pLocal2 = m_pDoc->GetRangeName(1)->findByUpperName(OUString("LOCAL2"));
4308 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("local2 should not be copied", pLocal2 == NULL);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4309 : :
4310 : :
4311 : : //check undo and redo
4312 [ + - ]: 3 : pUndo->Undo();
4313 [ + - ]: 3 : m_pDoc->GetValue(1,1,1, aValue);
4314 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after undo formula should return nothing", aValue, 0, 0.00000001);
[ + - ][ + - ]
[ + - ]
4315 [ + - ]: 3 : m_pDoc->GetString(2,1,1, aString);
4316 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("after undo string should be removed", aString.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("")));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4317 : :
4318 [ + - ]: 3 : pUndo->Redo();
4319 [ + - ]: 3 : m_pDoc->GetValue(1,1,1, aValue);
4320 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 2 after redo", aValue, 2, 0.00000001);
[ + - ][ + - ]
[ + - ]
4321 [ + - ]: 3 : m_pDoc->GetString(2,1,1, aString);
4322 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Cell Sheet2.C2 should contain: test", aString.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("test")));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4323 [ + - ]: 3 : m_pDoc->GetFormula(1,1,1, aString);
4324 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("Formula should be correct again", aString == aFormulaString);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4325 : :
4326 : : //clear all variables
4327 [ + - ][ + - ]: 3 : delete pClipDoc;
4328 [ + - ][ + - ]: 3 : delete pUndoDoc;
4329 [ + - ]: 3 : m_pDoc->DeleteTab(1);
4330 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
[ + - ][ + - ]
4331 : 3 : }
4332 : :
4333 : 3 : void Test::testMergedCells()
4334 : : {
4335 : : //test merge and unmerge
4336 : : //TODO: an undo/redo test for this would be a good idea
4337 [ + - ]: 3 : m_pDoc->InsertTab(0, rtl::OUString("Sheet1"));
4338 [ + - ]: 3 : m_pDoc->DoMerge(0, 1, 1, 3, 3, false);
4339 : 3 : SCCOL nEndCol = 1;
4340 : 3 : SCROW nEndRow = 1;
4341 [ + - ]: 3 : m_pDoc->ExtendMerge( 1, 1, nEndCol, nEndRow, 0, false);
4342 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("did not merge cells", nEndCol == 3 && nEndRow == 3);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ]
4343 : 3 : ScRange aRange(0,2,0,MAXCOL,2,0);
4344 [ + - ]: 3 : ScMarkData aMark;
4345 [ + - ]: 3 : aMark.SetMarkArea(aRange);
4346 : 3 : m_pDoc->SetInTest();
4347 [ + - ]: 3 : m_xDocShRef->GetDocFunc().InsertCells(aRange, &aMark, INS_INSROWS, true, true);
4348 [ + - ]: 3 : m_pDoc->ExtendMerge(1, 1, nEndCol, nEndRow, 0, false);
4349 [ + - ][ + - ]: 3 : cout << nEndRow << nEndCol;
4350 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("did not increase merge area", nEndCol == 3 && nEndRow == 4);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ]
4351 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
4352 : 3 : }
4353 : :
4354 : :
4355 : 3 : void Test::testRenameTable()
4356 : : {
4357 : : //test set rename table
4358 : : //TODO: set name1 and name2 and do an undo to check if name 1 is set now
4359 : : //TODO: also check if new name for table is same as another table
4360 : :
4361 [ + - ]: 3 : m_pDoc->InsertTab(0, "Sheet1");
4362 [ + - ]: 3 : m_pDoc->InsertTab(1, "Sheet2");
4363 : :
4364 : : //test case 1 , rename table2 to sheet 1, it should return error
4365 : 3 : rtl::OUString nameToSet = "Sheet1";
4366 : 3 : ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
4367 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("name same as another table is being set", !rDocFunc.RenameTable(1,nameToSet,false,true) );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4368 : :
4369 : : //test case 2 , simple rename to check name
4370 : 3 : nameToSet = "test1";
4371 [ + - ][ + - ]: 3 : m_xDocShRef->GetDocFunc().RenameTable(0,nameToSet,false,true);
[ + - ]
4372 : 3 : rtl::OUString nameJustSet;
4373 [ + - ]: 3 : m_pDoc->GetName(0,nameJustSet);
4374 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("table not renamed", nameToSet != nameJustSet);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4375 : :
4376 : : //test case 3 , rename again
4377 : 3 : rtl::OUString anOldName;
4378 [ + - ]: 3 : m_pDoc->GetName(0,anOldName);
4379 : :
4380 : 3 : nameToSet = "test2";
4381 [ + - ][ + - ]: 3 : rDocFunc.RenameTable(0,nameToSet,false,true);
[ + - ]
4382 [ + - ]: 3 : m_pDoc->GetName(0,nameJustSet);
4383 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("table not renamed", nameToSet != nameJustSet);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4384 : :
4385 : : //test case 4 , check if undo works
4386 [ + - ][ + - ]: 3 : SfxUndoAction* pUndo = new ScUndoRenameTab(m_xDocShRef,0,anOldName,nameToSet);
[ + - ][ + - ]
[ + - ][ + - ]
4387 [ + - ]: 3 : pUndo->Undo();
4388 [ + - ]: 3 : m_pDoc->GetName(0,nameJustSet);
4389 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the correct name is not set after undo", nameJustSet == anOldName);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4390 : :
4391 [ + - ]: 3 : pUndo->Redo();
4392 [ + - ]: 3 : m_pDoc->GetName(0,nameJustSet);
4393 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the correct color is not set after redo", nameJustSet == nameToSet);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4394 : :
4395 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4396 [ + - ]: 3 : m_pDoc->DeleteTab(1);
4397 : 3 : }
4398 : :
4399 : :
4400 : :
4401 : 3 : void Test::testSetBackgroundColor()
4402 : : {
4403 : : //test set background color
4404 : : //TODO: set color1 and set color2 and do an undo to check if color1 is set now.
4405 : :
4406 [ + - ]: 3 : m_pDoc->InsertTab(0, rtl::OUString("Sheet1"));
4407 : 3 : Color aColor;
4408 : :
4409 : : //test yellow
4410 : 3 : aColor=Color(COL_YELLOW);
4411 [ + - ]: 3 : m_xDocShRef->GetDocFunc().SetTabBgColor(0,aColor,false, true);
4412 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the correct color is not set", m_pDoc->GetTabBgColor(0)!= aColor);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4413 : :
4414 : :
4415 [ + - ]: 3 : Color aOldTabBgColor=m_pDoc->GetTabBgColor(0);
4416 : 3 : aColor.SetColor(COL_BLUE);//set BLUE
4417 [ + - ]: 3 : m_xDocShRef->GetDocFunc().SetTabBgColor(0,aColor,false, true);
4418 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the correct color is not set the second time", m_pDoc->GetTabBgColor(0)!= aColor);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4419 : :
4420 : : //now check for undo
4421 [ + - ][ + - ]: 3 : SfxUndoAction* pUndo = new ScUndoTabColor(m_xDocShRef,0, aOldTabBgColor, aColor);
4422 [ + - ]: 3 : pUndo->Undo();
4423 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the correct color is not set after undo", m_pDoc->GetTabBgColor(0)== aOldTabBgColor);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4424 [ + - ]: 3 : pUndo->Redo();
4425 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("the correct color is not set after undo", m_pDoc->GetTabBgColor(0)== aColor);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4426 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4427 : 3 : }
4428 : :
4429 : :
4430 : :
4431 : 3 : void Test::testUpdateReference()
4432 : : {
4433 : : //test that formulas are correctly updated during sheet delete
4434 : : //TODO: add tests for relative references, updating of named ranges, ...
4435 : 3 : rtl::OUString aSheet1("Sheet1");
4436 : 3 : rtl::OUString aSheet2("Sheet2");
4437 : 3 : rtl::OUString aSheet3("Sheet3");
4438 : 3 : rtl::OUString aSheet4("Sheet4");
4439 [ + - ]: 3 : m_pDoc->InsertTab(0, aSheet1);
4440 [ + - ]: 3 : m_pDoc->InsertTab(1, aSheet2);
4441 [ + - ]: 3 : m_pDoc->InsertTab(2, aSheet3);
4442 [ + - ]: 3 : m_pDoc->InsertTab(3, aSheet4);
4443 : :
4444 [ + - ]: 3 : m_pDoc->SetValue(0,0,2, 1);
4445 [ + - ]: 3 : m_pDoc->SetValue(1,0,2, 2);
4446 [ + - ]: 3 : m_pDoc->SetValue(1,1,3, 4);
4447 [ + - ]: 3 : m_pDoc->SetString(2,0,2, rtl::OUString("=A1+B1"));
4448 [ + - ]: 3 : m_pDoc->SetString(2,1,2, rtl::OUString("=Sheet4.B2+A1"));
4449 : :
4450 : : double aValue;
4451 [ + - ]: 3 : m_pDoc->GetValue(2,0,2, aValue);
4452 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4453 [ + - ]: 3 : m_pDoc->GetValue(2,1,2, aValue);
4454 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("formula does not return correct result", aValue == 5);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4455 : :
4456 : : //test deleting both sheets: one is not directly before the sheet, the other one is
4457 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4458 [ + - ]: 3 : m_pDoc->GetValue(2,0,1, aValue);
4459 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4460 [ + - ]: 3 : m_pDoc->GetValue(2,1,1, aValue);
4461 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 5, 0.00000001);
[ + - ][ + - ]
[ + - ]
4462 : :
4463 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4464 [ + - ]: 3 : m_pDoc->GetValue(2,0,0, aValue);
4465 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4466 [ + - ]: 3 : m_pDoc->GetValue(2,1,0, aValue);
4467 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 5, 0.00000001);
[ + - ][ + - ]
[ + - ]
4468 : :
4469 : : //test adding two sheets
4470 [ + - ]: 3 : m_pDoc->InsertTab(0, aSheet2);
4471 [ + - ]: 3 : m_pDoc->GetValue(2,0,1, aValue);
4472 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4473 [ + - ]: 3 : m_pDoc->GetValue(2,1,1, aValue);
4474 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 5, 0.00000001);
[ + - ][ + - ]
[ + - ]
4475 : :
4476 [ + - ]: 3 : m_pDoc->InsertTab(0, aSheet1);
4477 [ + - ]: 3 : m_pDoc->GetValue(2,0,2, aValue);
4478 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4479 [ + - ]: 3 : m_pDoc->GetValue(2,1,2, aValue);
4480 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 5, 0.00000001);
[ + - ][ + - ]
[ + - ]
4481 : :
4482 : : //test new DeleteTabs/InsertTabs methods
4483 [ + - ]: 3 : m_pDoc->DeleteTabs(0, 2);
4484 [ + - ]: 3 : m_pDoc->GetValue(2, 0, 0, aValue);
4485 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4486 [ + - ]: 3 : m_pDoc->GetValue(2, 1, 0, aValue);
4487 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 5, 0.00000001);
[ + - ][ + - ]
[ + - ]
4488 : :
4489 [ + - ]: 3 : std::vector<rtl::OUString> aSheets;
4490 [ + - ]: 3 : aSheets.push_back(aSheet1);
4491 [ + - ]: 3 : aSheets.push_back(aSheet2);
4492 [ + - ]: 3 : m_pDoc->InsertTabs(0, aSheets, false, true);
4493 [ + - ]: 3 : m_pDoc->GetValue(2, 0, 2, aValue);
4494 : 3 : rtl::OUString aFormula;
4495 [ + - ]: 3 : m_pDoc->GetFormula(2,0,2, aFormula);
4496 [ + - ][ + - ]: 3 : std::cout << "formel: " << rtl::OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8).getStr() << std::endl;
[ + - ][ + - ]
4497 [ + - ][ + - ]: 3 : std::cout << std::endl << aValue << std::endl;
[ + - ]
4498 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 3, 0.00000001);
[ + - ][ + - ]
[ + - ]
4499 [ + - ]: 3 : m_pDoc->GetValue(2, 1, 2, aValue);
4500 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 5, 0.00000001);
[ + - ][ + - ]
[ + - ]
4501 : :
4502 [ + - ]: 3 : m_pDoc->DeleteTab(3);
4503 [ + - ]: 3 : m_pDoc->DeleteTab(2);
4504 [ + - ]: 3 : m_pDoc->DeleteTab(1);
4505 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4506 : 3 : }
4507 : :
4508 : : namespace {
4509 : :
4510 : 12 : bool hasRange(const std::vector<ScTokenRef>& rRefTokens, const ScRange& rRange)
4511 : : {
4512 : 12 : std::vector<ScTokenRef>::const_iterator it = rRefTokens.begin(), itEnd = rRefTokens.end();
4513 [ + - ][ + - ]: 15 : for (; it != itEnd; ++it)
4514 : : {
4515 : 15 : const ScTokenRef& p = *it;
4516 [ + - ][ + - ]: 15 : if (!ScRefTokenHelper::isRef(p) || ScRefTokenHelper::isExternalRef(p))
[ - + ][ - + ]
[ + - ]
4517 : 0 : continue;
4518 : :
4519 [ + + - ]: 15 : switch (p->GetType())
4520 : : {
4521 : : case formula::svSingleRef:
4522 : : {
4523 [ + - ]: 6 : ScSingleRefData aData = p->GetSingleRef();
4524 [ + - ]: 6 : if (rRange.aStart != rRange.aEnd)
4525 : : break;
4526 : :
4527 : 6 : ScAddress aThis(aData.nCol, aData.nRow, aData.nTab);
4528 [ + - ]: 6 : if (aThis == rRange.aStart)
4529 : 6 : return true;
4530 : : }
4531 : 0 : break;
4532 : : case formula::svDoubleRef:
4533 : : {
4534 [ + - ]: 9 : ScComplexRefData aData = p->GetDoubleRef();
4535 : 9 : ScRange aThis(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab, aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
4536 [ + + ]: 9 : if (aThis == rRange)
4537 : 6 : return true;
4538 : : }
4539 : 3 : break;
4540 : : default:
4541 : : ;
4542 : : }
4543 : : }
4544 : 12 : return false;
4545 : : }
4546 : :
4547 : : }
4548 : :
4549 : 3 : void Test::testJumpToPrecedentsDependents()
4550 : : {
4551 : : // Precedent is another cell that the cell references, while dependent is
4552 : : // another cell that references it.
4553 [ + - ]: 3 : m_pDoc->InsertTab(0, rtl::OUString("Test"));
4554 : :
4555 [ + - ]: 3 : m_pDoc->SetString(2, 0, 0, rtl::OUString("=A1+A2+B3")); // C1
4556 [ + - ]: 3 : m_pDoc->SetString(2, 1, 0, rtl::OUString("=A1")); // C2
4557 [ + - ]: 3 : m_pDoc->CalcAll();
4558 : :
4559 [ + - ]: 3 : std::vector<ScTokenRef> aRefTokens;
4560 : 3 : ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
4561 : :
4562 : : {
4563 : : // C1's precedent should be A1:A2,B3.
4564 [ + - ]: 3 : ScRangeList aRange(ScRange(2, 0, 0));
4565 [ + - ]: 3 : rDocFunc.DetectiveCollectAllPreds(aRange, aRefTokens);
4566 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("A1:A2 should be a precedent of C1.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4567 [ + - ]: 3 : hasRange(aRefTokens, ScRange(0, 0, 0, 0, 1, 0)));
4568 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("B3 should be a precedent of C1.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4569 [ + - + - ]: 6 : hasRange(aRefTokens, ScRange(1, 2, 0)));
4570 : : }
4571 : :
4572 : : {
4573 : : // C2's precedent should be A1 only.
4574 [ + - ]: 3 : ScRangeList aRange(ScRange(2, 1, 0));
4575 [ + - ]: 3 : rDocFunc.DetectiveCollectAllPreds(aRange, aRefTokens);
4576 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE("there should only be one reference token.",
[ + - ][ + - ]
4577 [ + - ]: 3 : aRefTokens.size(), static_cast<size_t>(1));
4578 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("A1 should be a precedent of C1.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4579 [ + - + - ]: 6 : hasRange(aRefTokens, ScRange(0, 0, 0)));
4580 : : }
4581 : :
4582 : : {
4583 : : // A1's dependent should be C1:C2.
4584 [ + - ]: 3 : ScRangeList aRange(ScRange(0, 0, 0));
4585 [ + - ]: 3 : rDocFunc.DetectiveCollectAllSuccs(aRange, aRefTokens);
4586 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("C1:C2 should be the only dependent of A1.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
[ # # ]
4587 [ + - + - ]: 6 : aRefTokens.size() == 1 && hasRange(aRefTokens, ScRange(2, 0, 0, 2, 1, 0)));
4588 : : }
4589 : :
4590 [ + - ]: 3 : m_pDoc->DeleteTab(0);
4591 : 3 : }
4592 : :
4593 : 3 : void Test::testAutoFill()
4594 : : {
4595 [ + - ]: 3 : m_pDoc->InsertTab(0, "test");
4596 : :
4597 [ + - ]: 3 : m_pDoc->SetValue(0,0,0,1);
4598 : :
4599 [ + - ]: 3 : ScMarkData aMarkData;
4600 [ + - ]: 3 : aMarkData.SelectTable(0, true);
4601 : :
4602 [ + - ]: 3 : m_pDoc->Fill( 0, 0, 0, 0, NULL, aMarkData, 5);
4603 [ + + ]: 21 : for (SCROW i = 0; i< 6; ++i)
4604 [ + - ][ + - ]: 18 : CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1.0), m_pDoc->GetValue(0, i, 0), 0.00000001);
[ + - ][ + - ]
[ + - ][ + - ]
4605 : :
4606 : : // check that hidden rows are not affected by autofill
4607 : : // set values for hidden rows
4608 [ + - ]: 3 : m_pDoc->SetValue(0,1,0,10);
4609 [ + - ]: 3 : m_pDoc->SetValue(0,2,0,10);
4610 : :
4611 [ + - ]: 3 : m_pDoc->SetRowHidden(1, 2, 0, true);
4612 [ + - ]: 3 : m_pDoc->Fill( 0, 0, 0, 0, NULL, aMarkData, 8);
4613 : :
4614 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,1,0), 1e-08);
[ + - ][ + - ]
[ + - ][ + - ]
4615 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,2,0), 1e-08);
[ + - ][ + - ]
[ + - ][ + - ]
4616 [ + + ]: 18 : for (SCROW i = 3; i< 8; ++i)
4617 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i-1.0), m_pDoc->GetValue(0, i, 0), 0.00000001);
[ + - ][ + - ]
[ + - ][ + - ]
4618 : :
4619 [ + - ]: 3 : m_pDoc->Fill( 0, 0, 0, 8, NULL, aMarkData, 5, FILL_TO_RIGHT );
4620 [ + + ]: 18 : for (SCCOL i = 0; i < 5; ++i)
4621 : : {
4622 [ + + ]: 135 : for(SCROW j = 0; j < 8; ++j)
4623 : : {
4624 [ + + ]: 120 : if (j > 2)
4625 : : {
4626 [ + - ][ + - ]: 75 : CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(j-1+i), m_pDoc->GetValue(i, j, 0), 1e-8);
[ + - ][ + - ]
[ + - ][ + - ]
4627 : : }
4628 [ + + ]: 45 : else if (j == 0)
4629 : : {
4630 [ + - ][ + - ]: 15 : CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(i, 0, 0), 1e-8);
[ + - ][ + - ]
[ + - ][ + - ]
4631 : : }
4632 [ + + ][ + - ]: 30 : else if (j == 1 || j== 2)
4633 : : {
4634 [ + + ]: 30 : if(i == 0)
4635 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,j,0), 1e-8);
[ + - ][ + - ]
[ + - ][ + - ]
4636 : : else
4637 [ + - ][ + - ]: 24 : CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, m_pDoc->GetValue(i,j,0), 1e-8);
[ + - ][ + - ]
[ + - ][ + - ]
4638 : : }
4639 : : }
4640 : : }
4641 : :
4642 : : // test auto fill user data lists
4643 [ + - ]: 3 : m_pDoc->SetString( 0, 100, 0, "January" );
4644 [ + - ]: 3 : m_pDoc->Fill( 0, 100, 0, 100, NULL, aMarkData, 2, FILL_TO_BOTTOM, FILL_AUTO );
4645 [ + - ]: 3 : rtl::OUString aTestValue = m_pDoc->GetString( 0, 101, 0 );
4646 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL( aTestValue, rtl::OUString("February") );
[ + - ][ + - ]
[ + - ]
4647 [ + - ]: 3 : aTestValue = m_pDoc->GetString( 0, 102, 0 );
4648 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL( aTestValue, rtl::OUString("March") );
[ + - ][ + - ]
[ + - ]
4649 : :
4650 : : // test that two same user data list entries will not result in incremental fill
4651 [ + - ]: 3 : m_pDoc->SetString( 0, 101, 0, "January" );
4652 [ + - ]: 3 : m_pDoc->Fill( 0, 100, 0, 101, NULL, aMarkData, 2, FILL_TO_BOTTOM, FILL_AUTO );
4653 [ + + ]: 9 : for ( SCROW i = 102; i <= 103; ++i )
4654 : : {
4655 [ + - ]: 6 : aTestValue = m_pDoc->GetString( 0, i, 0 );
4656 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_EQUAL( aTestValue, rtl::OUString("January") );
[ + - ][ + - ]
[ + - ]
4657 : : }
4658 [ + - ][ + - ]: 3 : m_pDoc->DeleteTab(0);
4659 : 3 : }
4660 : :
4661 : 3 : void Test::testCopyPasteFormulas()
4662 : : {
4663 [ + - ]: 3 : m_pDoc->InsertTab(0, "Sheet1");
4664 [ + - ]: 3 : m_pDoc->InsertTab(1, "Sheet2");
4665 : :
4666 [ + - ]: 3 : m_pDoc->SetString(0,0,0, "=COLUMN($A$1)");
4667 [ + - ]: 3 : m_pDoc->SetString(0,1,0, "=$A$1+B2" );
4668 [ + - ]: 3 : m_pDoc->SetString(0,2,0, "=$Sheet2.A1");
4669 [ + - ]: 3 : m_pDoc->SetString(0,3,0, "=$Sheet2.$A$1");
4670 [ + - ]: 3 : m_pDoc->SetString(0,4,0, "=$Sheet2.A$1");
4671 : :
4672 : : // to prevent ScEditableTester in ScDocFunc::MoveBlock
4673 : 3 : m_pDoc->SetInTest();
4674 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,0,0), 1.0, 1e-08);
[ + - ][ + - ]
[ + - ][ + - ]
4675 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,1,0), 1.0, 1e-08);
[ + - ][ + - ]
[ + - ][ + - ]
4676 : 3 : ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
4677 [ + - ]: 3 : bool bMoveDone = rDocFunc.MoveBlock(ScRange(0,0,0,0,4,0), ScAddress( 10, 10, 0), false, false, false, true);
4678 : :
4679 : : // check that moving was succesful, mainly for editable tester
4680 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT(bMoveDone);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4681 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,10,0), 1.0, 1e-8);
[ + - ][ + - ]
[ + - ][ + - ]
4682 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,11,0), 1.0, 1e-8);
[ + - ][ + - ]
[ + - ][ + - ]
4683 : 3 : rtl::OUString aFormula;
4684 [ + - ]: 3 : m_pDoc->GetFormula(10,10,0, aFormula);
4685 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=COLUMN($A$1)"));
[ + - ][ + - ]
[ + - ]
4686 [ + - ]: 3 : m_pDoc->GetFormula(10,11,0, aFormula);
4687 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$A$1+L12"));
[ + - ][ + - ]
[ + - ]
4688 [ + - ]: 3 : m_pDoc->GetFormula(10,12,0, aFormula);
4689 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$Sheet2.K11"));
[ + - ][ + - ]
[ + - ]
4690 [ + - ]: 3 : m_pDoc->GetFormula(10,13,0, aFormula);
4691 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$Sheet2.$A$1"));
[ + - ][ + - ]
[ + - ]
4692 [ + - ]: 3 : m_pDoc->GetFormula(10,14,0, aFormula);
4693 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$Sheet2.K$1"));
[ + - ][ + - ]
[ + - ]
4694 : 3 : }
4695 : :
4696 : 3 : void Test::testCopyPasteFormulasExternalDoc()
4697 : : {
4698 : 3 : rtl::OUString aDocName("file:///source.fake");
4699 [ + - ][ + - ]: 3 : SfxMedium* pMedium = new SfxMedium(aDocName, STREAM_STD_READWRITE);
[ + - ][ + - ]
4700 [ + - ]: 3 : m_xDocShRef->DoInitNew(pMedium);
4701 : 3 : m_pDoc = m_xDocShRef->GetDocument();
4702 : :
4703 [ + - ][ + - ]: 3 : ScDocShellRef xExtDocSh = new ScDocShell;
4704 : 3 : OUString aExtDocName("file:///extdata.fake");
4705 : 3 : OUString aExtSh1Name("ExtSheet1");
4706 : 3 : OUString aExtSh2Name("ExtSheet2");
4707 [ + - ][ + - ]: 3 : SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
[ + - ][ + - ]
4708 [ + - ]: 3 : xExtDocSh->DoInitNew(pMed);
4709 [ + - ][ + - ]: 6 : CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4710 [ + - ]: 3 : findLoadedDocShellByName(aExtDocName) != NULL);
4711 : :
4712 : 3 : ScDocument* pExtDoc = xExtDocSh->GetDocument();
4713 [ + - ]: 3 : pExtDoc->InsertTab(0, aExtSh1Name);
4714 [ + - ]: 3 : pExtDoc->InsertTab(1, aExtSh2Name);
4715 : :
4716 [ + - ]: 3 : m_pDoc->InsertTab(0, "Sheet1");
4717 [ + - ]: 3 : m_pDoc->InsertTab(1, "Sheet2");
4718 : :
4719 [ + - ]: 3 : m_pDoc->SetString(0,0,0, "=COLUMN($A$1)");
4720 [ + - ]: 3 : m_pDoc->SetString(0,1,0, "=$A$1+B2" );
4721 [ + - ]: 3 : m_pDoc->SetString(0,2,0, "=$Sheet2.A1");
4722 [ + - ]: 3 : m_pDoc->SetString(0,3,0, "=$Sheet2.$A$1");
4723 [ + - ]: 3 : m_pDoc->SetString(0,4,0, "=$Sheet2.A$1");
4724 [ + - ]: 3 : m_pDoc->SetString(0,5,0, "=$Sheet1.$A$1");
4725 : :
4726 : 3 : ScRange aRange(0,0,0,0,5,0);
4727 [ + - ]: 3 : ScClipParam aClipParam(aRange, false);
4728 [ + - ]: 3 : ScMarkData aMark;
4729 [ + - ]: 3 : aMark.SetMarkArea(aRange);
4730 [ + - ][ + - ]: 3 : ScDocument* pClipDoc = new ScDocument(SCDOCMODE_CLIP);
4731 [ + - ]: 3 : m_pDoc->CopyToClip(aClipParam, pClipDoc, &aMark);
4732 : :
4733 : 3 : sal_uInt16 nFlags = IDF_ALL;
4734 : 3 : aRange = ScRange(1,1,1,1,6,1);
4735 [ + - ]: 3 : ScMarkData aMarkData2;
4736 [ + - ]: 3 : aMarkData2.SetMarkArea(aRange);
4737 [ + - ]: 3 : pExtDoc->CopyFromClip(aRange, aMarkData2, nFlags, NULL, pClipDoc);
4738 : :
4739 : 3 : rtl::OUString aFormula;
4740 [ + - ]: 3 : pExtDoc->GetFormula(1,1,1, aFormula);
4741 : : //adjust absolute refs pointing to the copy area
4742 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=COLUMN($B$2)"));
[ + - ][ + - ]
[ + - ]
4743 [ + - ]: 3 : pExtDoc->GetFormula(1,2,1, aFormula);
4744 : : //adjust absolute refs and keep relative refs
4745 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$B$2+C3"));
[ + - ][ + - ]
[ + - ]
4746 [ + - ]: 3 : pExtDoc->GetFormula(1,3,1, aFormula);
4747 : : // make absolute sheet refs external refs
4748 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("='file:///source.fake'#$Sheet2.B2"));
[ + - ][ + - ]
[ + - ]
4749 [ + - ]: 3 : pExtDoc->GetFormula(1,4,1, aFormula);
4750 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("='file:///source.fake'#$Sheet2.$A$1"));
[ + - ][ + - ]
[ + - ]
4751 [ + - ]: 3 : pExtDoc->GetFormula(1,5,1, aFormula);
4752 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("='file:///source.fake'#$Sheet2.B$1"));
[ + - ][ + - ]
[ + - ]
4753 [ + - ]: 3 : pExtDoc->GetFormula(1,6,1, aFormula);
4754 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$ExtSheet2.$B$2"));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4755 : 3 : }
4756 : :
4757 : 3 : void Test::testFindAreaPosRowDown()
4758 : : {
4759 : : const char* aData[][2] = {
4760 : : { "", "1" },
4761 : : { "1", "" },
4762 : : { "1", "1" },
4763 : : { "", "1" },
4764 : : { "1", "1" },
4765 : : { "1", "" },
4766 : 3 : { "1", "1" }, };
4767 : :
4768 : 3 : ScDocument* pDoc = m_xDocShRef->GetDocument();
4769 : 3 : rtl::OUString aTabName1("test1");
4770 [ + - ]: 3 : pDoc->InsertTab(0, aTabName1);
4771 [ + - ]: 3 : clearRange( pDoc, ScRange(0, 0, 0, 1, SAL_N_ELEMENTS(aData), 0));
4772 : 3 : ScAddress aPos(0,0,0);
4773 [ + - ]: 3 : ScRange aDataRange = insertRangeData( pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
4774 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4775 : :
4776 [ + - ]: 3 : pDoc->SetRowHidden(4,4,0,true);
4777 [ + - ]: 3 : bool bHidden = pDoc->RowHidden(4,0);
4778 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT(bHidden);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4779 : :
4780 : 3 : SCCOL nCol = 0;
4781 : 3 : SCROW nRow = 0;
4782 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4783 : :
4784 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), nRow);
[ + - ][ + - ]
[ + - ]
4785 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
[ + - ][ + - ]
[ + - ]
4786 : :
4787 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4788 : :
4789 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), nRow);
[ + - ][ + - ]
[ + - ]
4790 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
[ + - ][ + - ]
[ + - ]
4791 : :
4792 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4793 : :
4794 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), nRow);
[ + - ][ + - ]
[ + - ]
4795 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
[ + - ][ + - ]
[ + - ]
4796 : :
4797 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4798 : :
4799 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), nRow);
[ + - ][ + - ]
[ + - ]
4800 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
[ + - ][ + - ]
[ + - ]
4801 : :
4802 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4803 : :
4804 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(MAXROW), nRow);
[ + - ][ + - ]
[ + - ]
4805 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
[ + - ][ + - ]
[ + - ]
4806 : :
4807 : 3 : nCol = 1;
4808 : 3 : nRow = 2;
4809 : :
4810 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4811 : :
4812 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), nRow);
[ + - ][ + - ]
[ + - ]
4813 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCol);
[ + - ][ + - ]
[ + - ]
4814 : :
4815 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
4816 : :
4817 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), nRow);
[ + - ][ + - ]
[ + - ]
4818 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCol);
[ + - ][ + - ]
[ + - ]
4819 : :
4820 [ + - ]: 3 : pDoc->DeleteTab(0);
4821 : 3 : }
4822 : :
4823 : 3 : void Test::testFindAreaPosColRight()
4824 : : {
4825 : : const char* aData[][7] = {
4826 : : { "", "1", "1", "", "1", "1", "1" },
4827 : 3 : { "", "", "1", "1", "1", "", "1" }, };
4828 : :
4829 : 3 : ScDocument* pDoc = m_xDocShRef->GetDocument();
4830 : 3 : rtl::OUString aTabName1("test1");
4831 [ + - ]: 3 : pDoc->InsertTab(0, aTabName1);
4832 [ + - ]: 3 : clearRange( pDoc, ScRange(0, 0, 0, 7, SAL_N_ELEMENTS(aData), 0));
4833 : 3 : ScAddress aPos(0,0,0);
4834 [ + - ]: 3 : ScRange aDataRange = insertRangeData( pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
4835 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
4836 : :
4837 [ + - ]: 3 : pDoc->SetColHidden(4,4,0,true);
4838 [ + - ]: 3 : bool bHidden = pDoc->ColHidden(4,0);
4839 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT(bHidden);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
4840 : :
4841 : 3 : SCCOL nCol = 0;
4842 : 3 : SCROW nRow = 0;
4843 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4844 : :
4845 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
[ + - ][ + - ]
[ + - ]
4846 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCol);
[ + - ][ + - ]
[ + - ]
4847 : :
4848 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4849 : :
4850 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
[ + - ][ + - ]
[ + - ]
4851 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(2), nCol);
[ + - ][ + - ]
[ + - ]
4852 : :
4853 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4854 : :
4855 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
[ + - ][ + - ]
[ + - ]
4856 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(5), nCol);
[ + - ][ + - ]
[ + - ]
4857 : :
4858 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4859 : :
4860 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
[ + - ][ + - ]
[ + - ]
4861 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(6), nCol);
[ + - ][ + - ]
[ + - ]
4862 : :
4863 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4864 : :
4865 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
[ + - ][ + - ]
[ + - ]
4866 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(MAXCOL), nCol);
[ + - ][ + - ]
[ + - ]
4867 : :
4868 : 3 : nCol = 2;
4869 : 3 : nRow = 1;
4870 : :
4871 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4872 : :
4873 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), nRow);
[ + - ][ + - ]
[ + - ]
4874 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(3), nCol);
[ + - ][ + - ]
[ + - ]
4875 : :
4876 [ + - ]: 3 : pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
4877 : :
4878 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), nRow);
[ + - ][ + - ]
[ + - ]
4879 [ + - ][ + - ]: 3 : CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(6), nCol);
[ + - ][ + - ]
[ + - ]
4880 : :
4881 [ + - ]: 3 : pDoc->DeleteTab(0);
4882 : 3 : }
4883 : :
4884 : 3 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
4885 : :
4886 : : }
4887 : :
4888 [ + - ][ + - ]: 12 : CPPUNIT_PLUGIN_IMPLEMENT();
[ + - ][ + - ]
[ + - ][ # # ]
4889 : :
4890 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|