Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "dptabsrc.hxx"
21 :
22 : #include <algorithm>
23 : #include <set>
24 : #include <unordered_set>
25 : #include <vector>
26 :
27 : #include <rtl/math.hxx>
28 : #include <svl/itemprop.hxx>
29 : #include <svl/intitem.hxx>
30 : #include <vcl/svapp.hxx>
31 :
32 : #include "scitems.hxx"
33 : #include "document.hxx"
34 : #include "docpool.hxx"
35 : #include "patattr.hxx"
36 : #include "formulacell.hxx"
37 :
38 : #include "dptabres.hxx"
39 : #include "dptabdat.hxx"
40 : #include "global.hxx"
41 : #include "datauno.hxx"
42 : #include "miscuno.hxx"
43 : #include "unonames.hxx"
44 : #include "dpitemdata.hxx"
45 : #include "dputil.hxx"
46 : #include "dpresfilter.hxx"
47 : #include "calcmacros.hxx"
48 :
49 : #include <com/sun/star/beans/PropertyAttribute.hpp>
50 : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
51 : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
52 : #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
53 : #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
54 : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
55 : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
56 : #include <com/sun/star/table/CellAddress.hpp>
57 :
58 : #include <comphelper/string.hxx>
59 : #include <unotools/collatorwrapper.hxx>
60 : #include <unotools/calendarwrapper.hxx>
61 : #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
62 :
63 : using namespace com::sun::star;
64 : using ::std::vector;
65 : using ::std::set;
66 : using ::com::sun::star::uno::Reference;
67 : using ::com::sun::star::uno::Sequence;
68 : using ::com::sun::star::uno::Any;
69 : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
70 :
71 : #define SC_MINCOUNT_LIMIT 1000000
72 :
73 0 : SC_SIMPLE_SERVICE_INFO( ScDPSource, "ScDPSource", "com.sun.star.sheet.DataPilotSource" )
74 0 : SC_SIMPLE_SERVICE_INFO( ScDPDimensions, "ScDPDimensions", "com.sun.star.sheet.DataPilotSourceDimensions" )
75 0 : SC_SIMPLE_SERVICE_INFO( ScDPDimension, "ScDPDimension", "com.sun.star.sheet.DataPilotSourceDimension" )
76 0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
77 0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchy, "ScDPHierarchy", "com.sun.star.sheet.DataPilotSourceHierarcy" )
78 0 : SC_SIMPLE_SERVICE_INFO( ScDPLevels, "ScDPLevels", "com.sun.star.sheet.DataPilotSourceLevels" )
79 0 : SC_SIMPLE_SERVICE_INFO( ScDPLevel, "ScDPLevel", "com.sun.star.sheet.DataPilotSourceLevel" )
80 0 : SC_SIMPLE_SERVICE_INFO( ScDPMembers, "ScDPMembers", "com.sun.star.sheet.DataPilotSourceMembers" )
81 0 : SC_SIMPLE_SERVICE_INFO( ScDPMember, "ScDPMember", "com.sun.star.sheet.DataPilotSourceMember" )
82 :
83 : // property maps for PropertySetInfo
84 : // DataDescription / NumberFormat are internal
85 :
86 : //TODO: move to a header?
87 1539 : static bool lcl_GetBoolFromAny( const uno::Any& aAny )
88 : {
89 1539 : if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
90 1539 : return *static_cast<sal_Bool const *>(aAny.getValue());
91 0 : return false;
92 : }
93 :
94 3754 : static void lcl_SetBoolInAny( uno::Any& rAny, bool bValue )
95 : {
96 3754 : rAny.setValue( &bValue, cppu::UnoType<bool>::get() );
97 3754 : }
98 :
99 122 : ScDPSource::ScDPSource( ScDPTableData* pD ) :
100 : pData( pD ),
101 : pDimensions( NULL ),
102 : bColumnGrand( true ), // default is true
103 : bRowGrand( true ),
104 : bIgnoreEmptyRows( false ),
105 : bRepeatIfEmpty( false ),
106 : nDupCount( 0 ),
107 : pResData( NULL ),
108 : pColResRoot( NULL ),
109 : pRowResRoot( NULL ),
110 : pColResults( NULL ),
111 : pRowResults( NULL ),
112 : bResultOverflow( false ),
113 122 : bPageFiltered( false )
114 : {
115 122 : pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
116 122 : }
117 :
118 360 : ScDPSource::~ScDPSource()
119 : {
120 120 : if (pDimensions)
121 120 : pDimensions->release(); // ref-counted
122 :
123 : // free lists
124 :
125 120 : delete[] pColResults;
126 120 : delete[] pRowResults;
127 :
128 120 : delete pColResRoot;
129 120 : delete pRowResRoot;
130 120 : delete pResData;
131 240 : }
132 :
133 109 : const OUString* ScDPSource::GetGrandTotalName() const
134 : {
135 109 : return mpGrandTotalName.get();
136 : }
137 :
138 3294 : sal_uInt16 ScDPSource::GetOrientation(long nColumn)
139 : {
140 3294 : if (std::find(maColDims.begin(), maColDims.end(), nColumn) != maColDims.end())
141 800 : return sheet::DataPilotFieldOrientation_COLUMN;
142 :
143 2494 : if (std::find(maRowDims.begin(), maRowDims.end(), nColumn) != maRowDims.end())
144 1127 : return sheet::DataPilotFieldOrientation_ROW;
145 :
146 1367 : if (std::find(maDataDims.begin(), maDataDims.end(), nColumn) != maDataDims.end())
147 560 : return sheet::DataPilotFieldOrientation_DATA;
148 :
149 807 : if (std::find(maPageDims.begin(), maPageDims.end(), nColumn) != maPageDims.end())
150 64 : return sheet::DataPilotFieldOrientation_PAGE;
151 :
152 743 : return sheet::DataPilotFieldOrientation_HIDDEN;
153 : }
154 :
155 10 : long ScDPSource::GetDataDimensionCount()
156 : {
157 10 : return maDataDims.size();
158 : }
159 :
160 132 : ScDPDimension* ScDPSource::GetDataDimension(long nIndex)
161 : {
162 132 : if (nIndex < 0 || static_cast<size_t>(nIndex) >= maDataDims.size())
163 11 : return NULL;
164 :
165 121 : long nDimIndex = maDataDims[nIndex];
166 121 : return GetDimensionsObject()->getByIndex(nDimIndex);
167 : }
168 :
169 27 : OUString ScDPSource::GetDataDimName(long nIndex)
170 : {
171 27 : OUString aRet;
172 27 : ScDPDimension* pDim = GetDataDimension(nIndex);
173 27 : if (pDim)
174 27 : aRet = pDim->getName();
175 27 : return aRet;
176 : }
177 :
178 452 : long ScDPSource::GetPosition(long nColumn)
179 : {
180 452 : std::vector<long>::const_iterator it, itBeg = maColDims.begin(), itEnd = maColDims.end();
181 452 : it = std::find(itBeg, itEnd, nColumn);
182 452 : if (it != itEnd)
183 49 : return std::distance(itBeg, it);
184 :
185 403 : itBeg = maRowDims.begin();
186 403 : itEnd = maRowDims.end();
187 403 : it = std::find(itBeg, itEnd, nColumn);
188 403 : if (it != itEnd)
189 130 : return std::distance(itBeg, it);
190 :
191 273 : itBeg = maDataDims.begin();
192 273 : itEnd = maDataDims.end();
193 273 : it = std::find(itBeg, itEnd, nColumn);
194 273 : if (it != itEnd)
195 86 : return std::distance(itBeg, it);
196 :
197 187 : itBeg = maPageDims.begin();
198 187 : itEnd = maPageDims.end();
199 187 : it = std::find(itBeg, itEnd, nColumn);
200 187 : if (it != itEnd)
201 27 : return std::distance(itBeg, it);
202 :
203 160 : return 0;
204 : }
205 :
206 : namespace {
207 :
208 10076 : bool testSubTotal( bool& rAllowed, long nColumn, const std::vector<long>& rDims, ScDPSource* pSource )
209 : {
210 10076 : rAllowed = true;
211 10076 : std::vector<long>::const_iterator it = rDims.begin(), itEnd = rDims.end();
212 12778 : for (; it != itEnd; ++it)
213 : {
214 10275 : if (*it != nColumn)
215 2702 : continue;
216 :
217 7573 : if ( pSource->IsDataLayoutDimension(nColumn) )
218 : {
219 : // no subtotals for data layout dim, no matter where
220 290 : rAllowed = false;
221 290 : return true;
222 : }
223 :
224 : // no subtotals if no other dim but data layout follows
225 7283 : ++it;
226 7283 : if (it != itEnd && pSource->IsDataLayoutDimension(*it))
227 1087 : ++it;
228 7283 : if (it == itEnd)
229 5835 : rAllowed = false;
230 :
231 7283 : return true; // found
232 : }
233 :
234 2503 : return false;
235 : }
236 :
237 3740 : void removeDim( long nRemove, std::vector<long>& rDims )
238 : {
239 3740 : std::vector<long>::iterator it = std::find(rDims.begin(), rDims.end(), nRemove);
240 3740 : if (it != rDims.end())
241 0 : rDims.erase(it);
242 3740 : }
243 :
244 : }
245 :
246 7573 : bool ScDPSource::SubTotalAllowed(long nColumn)
247 : {
248 : //TODO: cache this at ScDPResultData
249 7573 : bool bAllowed = true;
250 7573 : if ( testSubTotal(bAllowed, nColumn, maColDims, this) )
251 5070 : return bAllowed;
252 2503 : if ( testSubTotal(bAllowed, nColumn, maRowDims, this) )
253 2503 : return bAllowed;
254 0 : return bAllowed;
255 : }
256 :
257 935 : void ScDPSource::SetOrientation(long nColumn, sal_uInt16 nNew)
258 : {
259 : //TODO: change to no-op if new orientation is equal to old?
260 :
261 : // remove from old list
262 935 : removeDim(nColumn, maColDims);
263 935 : removeDim(nColumn, maRowDims);
264 935 : removeDim(nColumn, maDataDims);
265 935 : removeDim(nColumn, maPageDims);
266 :
267 : // add to new list
268 935 : switch (nNew)
269 : {
270 : case sheet::DataPilotFieldOrientation_COLUMN:
271 51 : maColDims.push_back(nColumn);
272 51 : break;
273 : case sheet::DataPilotFieldOrientation_ROW:
274 139 : maRowDims.push_back(nColumn);
275 139 : break;
276 : case sheet::DataPilotFieldOrientation_DATA:
277 90 : maDataDims.push_back(nColumn);
278 90 : break;
279 : case sheet::DataPilotFieldOrientation_PAGE:
280 28 : maPageDims.push_back(nColumn);
281 28 : break;
282 : // DataPilot Migration - Cache&&Performance
283 : case sheet::DataPilotFieldOrientation_HIDDEN:
284 627 : break;
285 : default:
286 : OSL_FAIL( "ScDPSource::SetOrientation: unexpected orientation" );
287 0 : break;
288 : }
289 935 : }
290 :
291 11736 : bool ScDPSource::IsDataLayoutDimension(long nDim)
292 : {
293 11736 : return nDim == pData->GetColumnCount();
294 : }
295 :
296 182 : sal_uInt16 ScDPSource::GetDataLayoutOrientation()
297 : {
298 182 : return GetOrientation(pData->GetColumnCount());
299 : }
300 :
301 2137 : bool ScDPSource::IsDateDimension(long nDim)
302 : {
303 2137 : return pData->IsDateDimension(nDim);
304 : }
305 :
306 4658 : ScDPDimensions* ScDPSource::GetDimensionsObject()
307 : {
308 4658 : if (!pDimensions)
309 : {
310 131 : pDimensions = new ScDPDimensions(this);
311 131 : pDimensions->acquire(); // ref-counted
312 : }
313 4658 : return pDimensions;
314 : }
315 :
316 1219 : uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException, std::exception)
317 : {
318 1219 : return GetDimensionsObject();
319 : }
320 :
321 14 : void ScDPSource::SetDupCount( long nNew )
322 : {
323 14 : nDupCount = nNew;
324 14 : }
325 :
326 5 : ScDPDimension* ScDPSource::AddDuplicated(long /* nSource */, const OUString& rNewName)
327 : {
328 : OSL_ENSURE( pDimensions, "AddDuplicated without dimensions?" );
329 :
330 : // re-use
331 :
332 5 : long nOldDimCount = pDimensions->getCount();
333 20 : for (long i=0; i<nOldDimCount; i++)
334 : {
335 15 : ScDPDimension* pDim = pDimensions->getByIndex(i);
336 15 : if (pDim && pDim->getName().equals(rNewName))
337 : {
338 : //TODO: test if pDim is a duplicate of source
339 0 : return pDim;
340 : }
341 : }
342 :
343 5 : SetDupCount( nDupCount + 1 );
344 5 : pDimensions->CountChanged(); // uses nDupCount
345 :
346 5 : return pDimensions->getByIndex( pDimensions->getCount() - 1 );
347 : }
348 :
349 16411 : long ScDPSource::GetSourceDim(long nDim)
350 : {
351 : // original source dimension or data layout dimension?
352 16411 : if ( nDim <= pData->GetColumnCount() )
353 16374 : return nDim;
354 :
355 37 : if ( nDim < pDimensions->getCount() )
356 : {
357 37 : ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
358 37 : if ( pDimObj )
359 : {
360 37 : long nSource = pDimObj->GetSourceDim();
361 37 : if ( nSource >= 0 )
362 37 : return nSource;
363 : }
364 : }
365 :
366 : OSL_FAIL("GetSourceDim: wrong dim");
367 0 : return nDim;
368 : }
369 :
370 91 : uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
371 : throw(uno::RuntimeException, std::exception)
372 : {
373 91 : CreateRes_Impl(); // create pColResRoot and pRowResRoot
374 :
375 91 : if ( bResultOverflow ) // set in CreateRes_Impl
376 : {
377 : // no results available
378 0 : throw uno::RuntimeException();
379 : }
380 :
381 91 : long nColCount = pColResRoot->GetSize(pResData->GetColStartMeasure());
382 91 : long nRowCount = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
383 :
384 : // allocate full sequence
385 : //TODO: leave out empty rows???
386 :
387 91 : uno::Sequence< uno::Sequence<sheet::DataResult> > aSeq( nRowCount );
388 91 : uno::Sequence<sheet::DataResult>* pRowAry = aSeq.getArray();
389 520 : for (long nRow = 0; nRow < nRowCount; nRow++)
390 : {
391 429 : uno::Sequence<sheet::DataResult> aColSeq( nColCount );
392 : // use default values of DataResult
393 429 : pRowAry[nRow] = aColSeq;
394 429 : }
395 :
396 182 : ScDPResultFilterContext aFilterCxt;
397 : pRowResRoot->FillDataResults(
398 91 : pColResRoot, aFilterCxt, aSeq, pResData->GetRowStartMeasure());
399 :
400 91 : maResFilterSet.swap(aFilterCxt.maFilterSet); // Keep this data for GETPIVOTDATA.
401 :
402 182 : return aSeq;
403 : }
404 :
405 43 : uno::Sequence<double> ScDPSource::getFilteredResults(
406 : const uno::Sequence<sheet::DataPilotFieldFilter>& aFilters )
407 : throw (uno::RuntimeException, std::exception)
408 : {
409 43 : if (maResFilterSet.empty())
410 3 : getResults(); // Build result tree first.
411 :
412 : // Get result values from the tree.
413 43 : const ScDPResultTree::ValuesType* pVals = maResFilterSet.getResults(aFilters);
414 43 : if (pVals)
415 : {
416 19 : size_t n = pVals->size();
417 19 : uno::Sequence<double> aRet(n);
418 44 : for (size_t i = 0; i < n; ++i)
419 25 : aRet[i] = (*pVals)[i];
420 :
421 19 : return aRet;
422 : }
423 :
424 24 : if (aFilters.getLength() == 1)
425 : {
426 : // Try to get result from the leaf nodes.
427 24 : double fVal = maResFilterSet.getLeafResult(aFilters[0]);
428 24 : if (!rtl::math::isNan(fVal))
429 : {
430 24 : uno::Sequence<double> aRet(1);
431 24 : aRet[0] = fVal;
432 24 : return aRet;
433 : }
434 : }
435 :
436 0 : return uno::Sequence<double>();
437 : }
438 :
439 9 : void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException, std::exception)
440 : {
441 9 : disposeData();
442 9 : }
443 :
444 0 : void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& )
445 : throw(uno::RuntimeException, std::exception)
446 : {
447 : OSL_FAIL("not implemented"); //TODO: exception?
448 0 : }
449 :
450 0 : void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& )
451 : throw(uno::RuntimeException, std::exception)
452 : {
453 : OSL_FAIL("not implemented"); //TODO: exception?
454 0 : }
455 :
456 133 : Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters)
457 : throw (uno::RuntimeException, std::exception)
458 : {
459 133 : long nColumnCount = GetData()->GetColumnCount();
460 :
461 133 : vector<ScDPFilteredCache::Criterion> aFilterCriteria;
462 133 : sal_Int32 nFilterCount = aFilters.getLength();
463 593 : for (sal_Int32 i = 0; i < nFilterCount; ++i)
464 : {
465 460 : const sheet::DataPilotFieldFilter& rFilter = aFilters[i];
466 460 : const OUString& aFieldName = rFilter.FieldName;
467 2760 : for (long nCol = 0; nCol < nColumnCount; ++nCol)
468 : {
469 2300 : if (aFieldName.equals(pData->getDimensionName(nCol)))
470 : {
471 460 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
472 : ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
473 460 : GetLevelsObject()->getByIndex(0)->GetMembersObject();
474 460 : sal_Int32 nIndex = pMembers->GetIndexFromName( rFilter.MatchValue );
475 460 : if ( nIndex >= 0 )
476 : {
477 460 : ScDPItemData aItem;
478 460 : pMembers->getByIndex(nIndex)->FillItemData( aItem );
479 460 : aFilterCriteria.push_back( ScDPFilteredCache::Criterion() );
480 460 : aFilterCriteria.back().mnFieldIndex = nCol;
481 460 : aFilterCriteria.back().mpFilter.reset(
482 920 : new ScDPFilteredCache::SingleFilter(aItem));
483 : }
484 : }
485 : }
486 : }
487 :
488 : // Take into account the visibilities of field members.
489 266 : ScDPResultVisibilityData aResVisData(this);
490 133 : pRowResRoot->FillVisibilityData(aResVisData);
491 133 : pColResRoot->FillVisibilityData(aResVisData);
492 133 : aResVisData.fillFieldFilters(aFilterCriteria);
493 :
494 133 : Sequence< Sequence<Any> > aTabData;
495 266 : std::unordered_set<sal_Int32> aCatDims;
496 133 : GetCategoryDimensionIndices(aCatDims);
497 133 : pData->GetDrillDownData(aFilterCriteria, aCatDims, aTabData);
498 266 : return aTabData;
499 : }
500 :
501 88 : OUString ScDPSource::getDataDescription()
502 : {
503 88 : CreateRes_Impl(); // create pResData
504 :
505 88 : OUString aRet;
506 88 : if ( pResData->GetMeasureCount() == 1 )
507 : {
508 79 : bool bTotalResult = false;
509 79 : aRet = pResData->GetMeasureString(0, true, SUBTOTAL_FUNC_NONE, bTotalResult);
510 : }
511 :
512 : // empty for more than one measure
513 :
514 88 : return aRet;
515 : }
516 :
517 130 : void ScDPSource::setIgnoreEmptyRows(bool bSet)
518 : {
519 130 : bIgnoreEmptyRows = bSet;
520 130 : pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
521 130 : }
522 :
523 130 : void ScDPSource::setRepeatIfEmpty(bool bSet)
524 : {
525 130 : bRepeatIfEmpty = bSet;
526 130 : pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
527 130 : }
528 :
529 9 : void ScDPSource::disposeData()
530 : {
531 9 : maResFilterSet.clear();
532 :
533 9 : if ( pResData )
534 : {
535 : // reset all data...
536 :
537 9 : DELETEZ(pColResRoot);
538 9 : DELETEZ(pRowResRoot);
539 9 : DELETEZ(pResData);
540 9 : delete[] pColResults;
541 9 : delete[] pRowResults;
542 9 : pColResults = NULL;
543 9 : pRowResults = NULL;
544 9 : aColLevelList.clear();
545 9 : aRowLevelList.clear();
546 : }
547 :
548 9 : if ( pDimensions )
549 : {
550 9 : pDimensions->release(); // ref-counted
551 9 : pDimensions = NULL; // settings have to be applied (from SaveData) again!
552 : }
553 9 : SetDupCount( 0 );
554 :
555 9 : maColDims.clear();
556 9 : maRowDims.clear();
557 9 : maDataDims.clear();
558 9 : maPageDims.clear();
559 :
560 9 : pData->DisposeData(); // cached entries etc.
561 9 : bPageFiltered = false;
562 9 : bResultOverflow = false;
563 9 : }
564 :
565 182 : static long lcl_CountMinMembers(const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLevel, long nLevels )
566 : {
567 : // Calculate the product of the member count for those consecutive levels that
568 : // have the "show all" flag, one following level, and the data layout dimension.
569 :
570 182 : long nTotal = 1;
571 182 : long nDataCount = 1;
572 182 : bool bWasShowAll = true;
573 182 : long nPos = nLevels;
574 509 : while ( nPos > 0 )
575 : {
576 145 : --nPos;
577 :
578 145 : if ( nPos+1 < nLevels && ppDim[nPos] == ppDim[nPos+1] )
579 : {
580 : OSL_FAIL("lcl_CountMinMembers: multiple levels from one dimension not implemented");
581 0 : return 0;
582 : }
583 :
584 145 : bool bDo = false;
585 145 : if ( ppDim[nPos]->getIsDataLayoutDimension() )
586 : {
587 : // data layout dim doesn't interfere with "show all" flags
588 9 : nDataCount = ppLevel[nPos]->GetMembersObject()->getCount();
589 9 : if ( nDataCount == 0 )
590 0 : nDataCount = 1;
591 : }
592 136 : else if ( bWasShowAll ) // "show all" set for all following levels?
593 : {
594 115 : bDo = true;
595 115 : if ( !ppLevel[nPos]->getShowEmpty() )
596 : {
597 : // this level is counted, following ones are not
598 115 : bWasShowAll = false;
599 : }
600 : }
601 145 : if ( bDo )
602 : {
603 115 : long nThisCount = ppLevel[nPos]->GetMembersObject()->getMinMembers();
604 115 : if ( nThisCount == 0 )
605 : {
606 0 : nTotal = 1; // empty level -> start counting from here
607 : //TODO: start with visible elements in this level?
608 : }
609 : else
610 : {
611 115 : if ( nTotal >= LONG_MAX / nThisCount )
612 0 : return LONG_MAX; // overflow
613 115 : nTotal *= nThisCount;
614 : }
615 : }
616 : }
617 :
618 : // always include data layout dim, even after restarting
619 182 : if ( nTotal >= LONG_MAX / nDataCount )
620 0 : return LONG_MAX; // overflow
621 182 : nTotal *= nDataCount;
622 :
623 182 : return nTotal;
624 : }
625 :
626 4 : static long lcl_GetIndexFromName( const OUString& rName, const uno::Sequence<OUString>& rElements )
627 : {
628 4 : long nCount = rElements.getLength();
629 4 : const OUString* pArray = rElements.getConstArray();
630 4 : for (long nPos=0; nPos<nCount; nPos++)
631 4 : if (pArray[nPos] == rName)
632 4 : return nPos;
633 :
634 0 : return -1; // not found
635 : }
636 :
637 182 : void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &rHasAutoShow)
638 : {
639 182 : const std::vector<long>& rDims = bIsRow ? maRowDims : maColDims;
640 182 : std::vector<long>::const_iterator it = rDims.begin(), itEnd = rDims.end();
641 369 : for (; it != itEnd; ++it)
642 : {
643 187 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
644 187 : long nHierarchy = pDim->getUsedHierarchy();
645 187 : if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
646 0 : nHierarchy = 0;
647 187 : ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
648 187 : long nCount = pLevels->getCount();
649 :
650 : //TODO: Test
651 187 : if (pDim->getIsDataLayoutDimension() && maDataDims.size() < 2)
652 42 : nCount = 0;
653 : //TODO: Test
654 :
655 332 : for (long j = 0; j < nCount; ++j)
656 : {
657 145 : ScDPLevel* pLevel = pLevels->getByIndex(j);
658 145 : pLevel->EvaluateSortOrder();
659 :
660 : // no layout flags for column fields, only for row fields
661 145 : pLevel->SetEnableLayout( bIsRow );
662 :
663 145 : if ( pLevel->GetAutoShow().IsEnabled )
664 1 : rHasAutoShow = true;
665 :
666 145 : if (bIsRow)
667 : {
668 95 : rInfo.aRowLevelDims.push_back(*it);
669 95 : rInfo.aRowDims.push_back(pDim);
670 95 : rInfo.aRowLevels.push_back(pLevel);
671 : }
672 : else
673 : {
674 50 : rInfo.aColLevelDims.push_back(*it);
675 50 : rInfo.aColDims.push_back(pDim);
676 50 : rInfo.aColLevels.push_back(pLevel);
677 : }
678 :
679 145 : pLevel->GetMembersObject(); // initialize for groups
680 : }
681 : }
682 182 : }
683 :
684 : namespace {
685 :
686 : class CategoryDimInserter : std::unary_function<long, void>
687 : {
688 : ScDPSource& mrSource;
689 : std::unordered_set<sal_Int32>& mrCatDims;
690 : public:
691 137 : CategoryDimInserter(ScDPSource& rSource, std::unordered_set<sal_Int32>& rCatDims) :
692 : mrSource(rSource),
693 137 : mrCatDims(rCatDims) {}
694 :
695 541 : void operator() (long nDim)
696 : {
697 541 : if (!mrSource.IsDataLayoutDimension(nDim))
698 537 : mrCatDims.insert(nDim);
699 541 : }
700 : };
701 :
702 : }
703 :
704 137 : void ScDPSource::GetCategoryDimensionIndices(std::unordered_set<sal_Int32>& rCatDims)
705 : {
706 137 : std::unordered_set<sal_Int32> aCatDims;
707 :
708 137 : CategoryDimInserter aInserter(*this, aCatDims);
709 137 : std::for_each(maColDims.begin(), maColDims.end(), aInserter);
710 137 : std::for_each(maRowDims.begin(), maRowDims.end(), aInserter);
711 137 : std::for_each(maPageDims.begin(), maPageDims.end(), aInserter);
712 :
713 137 : rCatDims.swap(aCatDims);
714 137 : }
715 :
716 91 : void ScDPSource::FilterCacheByPageDimensions()
717 : {
718 : // #i117661# Repeated calls to ScDPFilteredCache::filterByPageDimension
719 : // are invalid because rows are only hidden, never shown again. If
720 : // FilterCacheByPageDimensions is called again, the cache table must
721 : // be re-initialized. Currently, CreateRes_Impl always uses a fresh cache
722 : // because ScDBDocFunc::DataPilotUpdate calls InvalidateData.
723 :
724 91 : if (bPageFiltered)
725 : {
726 : SAL_WARN( "sc.core","tried to apply page field filters several times");
727 :
728 0 : pData->DisposeData();
729 0 : pData->CreateCacheTable(); // re-initialize the cache table
730 0 : bPageFiltered = false;
731 : }
732 :
733 : // filter table by page dimensions.
734 91 : vector<ScDPFilteredCache::Criterion> aCriteria;
735 91 : vector<long>::const_iterator it = maPageDims.begin(), itEnd = maPageDims.end();
736 118 : for (; it != itEnd; ++it)
737 : {
738 27 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
739 27 : long nField = pDim->GetDimension();
740 :
741 : ScDPMembers* pMems = pDim->GetHierarchiesObject()->getByIndex(0)->
742 27 : GetLevelsObject()->getByIndex(0)->GetMembersObject();
743 :
744 27 : long nMemCount = pMems->getCount();
745 27 : ScDPFilteredCache::Criterion aFilter;
746 27 : aFilter.mnFieldIndex = static_cast<sal_Int32>(nField);
747 27 : aFilter.mpFilter.reset(new ScDPFilteredCache::GroupFilter);
748 : ScDPFilteredCache::GroupFilter* pGrpFilter =
749 27 : static_cast<ScDPFilteredCache::GroupFilter*>(aFilter.mpFilter.get());
750 138 : for (long j = 0; j < nMemCount; ++j)
751 : {
752 111 : ScDPMember* pMem = pMems->getByIndex(j);
753 111 : if (pMem->isVisible())
754 : {
755 103 : ScDPItemData aData;
756 103 : pMem->FillItemData(aData);
757 103 : pGrpFilter->addMatchItem(aData);
758 : }
759 : }
760 27 : if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount))
761 : // there is at least one invisible item. Add this filter criterion to the mix.
762 4 : aCriteria.push_back(aFilter);
763 :
764 27 : if (!pDim->HasSelectedPage())
765 27 : continue;
766 :
767 0 : const ScDPItemData& rData = pDim->GetSelectedData();
768 0 : aCriteria.push_back(ScDPFilteredCache::Criterion());
769 0 : ScDPFilteredCache::Criterion& r = aCriteria.back();
770 0 : r.mnFieldIndex = static_cast<sal_Int32>(nField);
771 0 : r.mpFilter.reset(new ScDPFilteredCache::SingleFilter(rData));
772 0 : }
773 91 : if (!aCriteria.empty())
774 : {
775 4 : std::unordered_set<sal_Int32> aCatDims;
776 4 : GetCategoryDimensionIndices(aCatDims);
777 4 : pData->FilterCacheTable(aCriteria, aCatDims);
778 4 : bPageFiltered = true;
779 91 : }
780 91 : }
781 :
782 255 : void ScDPSource::CreateRes_Impl()
783 : {
784 255 : if (pResData)
785 328 : return;
786 :
787 91 : sal_uInt16 nDataOrient = GetDataLayoutOrientation();
788 91 : if (maDataDims.size() > 1 && ( nDataOrient != sheet::DataPilotFieldOrientation_COLUMN &&
789 : nDataOrient != sheet::DataPilotFieldOrientation_ROW ) )
790 : {
791 : // if more than one data dimension, data layout orientation must be set
792 0 : SetOrientation( pData->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW );
793 0 : nDataOrient = sheet::DataPilotFieldOrientation_ROW;
794 : }
795 :
796 : // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and
797 : // eDataFunctions into a structure and use vector instead of static
798 : // or pointer arrays.
799 91 : vector<OUString> aDataNames;
800 182 : vector<sheet::DataPilotFieldReference> aDataRefValues;
801 182 : vector<ScSubTotalFunc> aDataFunctions;
802 182 : vector<sal_uInt16> aDataRefOrient;
803 :
804 182 : ScDPTableData::CalcInfo aInfo;
805 :
806 : // LateInit (initialize only those rows/children that are used) can be used unless
807 : // any data dimension needs reference values from column/row dimensions
808 91 : bool bLateInit = true;
809 :
810 : // Go through all data dimensions (i.e. fields) and build their meta data
811 : // so that they can be passed on to ScDPResultData instance later.
812 : // TODO: aggregate all of data dimension info into a structure.
813 91 : vector<long>::const_iterator it = maDataDims.begin(), itEnd = maDataDims.end();
814 180 : for (; it != itEnd; ++it)
815 : {
816 : // Get function for each data field.
817 89 : long nDimIndex = *it;
818 89 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
819 89 : sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
820 89 : if (eUser == sheet::GeneralFunction_AUTO)
821 : {
822 : //TODO: test for numeric data
823 27 : eUser = sheet::GeneralFunction_SUM;
824 : }
825 :
826 : // Map UNO's enum to internal enum ScSubTotalFunc.
827 89 : aDataFunctions.push_back(ScDPUtil::toSubTotalFunc(eUser));
828 :
829 : // Get reference field/item information.
830 89 : aDataRefValues.push_back(pDim->GetReferenceValue());
831 89 : sal_uInt16 nDataRefOrient = sheet::DataPilotFieldOrientation_HIDDEN; // default if not used
832 89 : sal_Int32 eRefType = aDataRefValues.back().ReferenceType;
833 89 : if ( eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
834 87 : eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
835 86 : eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE ||
836 : eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
837 : {
838 : long nColumn = lcl_GetIndexFromName(
839 4 : aDataRefValues.back().ReferenceField, GetDimensionsObject()->getElementNames());
840 4 : if ( nColumn >= 0 )
841 : {
842 4 : nDataRefOrient = GetOrientation(nColumn);
843 : // need fully initialized results to find reference values
844 : // (both in column or row dimensions), so updated values or
845 : // differences to 0 can be displayed even for empty results.
846 4 : bLateInit = false;
847 : }
848 : }
849 :
850 89 : aDataRefOrient.push_back(nDataRefOrient);
851 :
852 89 : aDataNames.push_back(pDim->getName());
853 :
854 : //TODO: modify user visible strings as in ScDPResultData::GetMeasureString instead!
855 :
856 89 : aDataNames.back() = ScDPUtil::getSourceDimensionName(aDataNames.back());
857 :
858 : //TODO: if the name is overridden by user, a flag must be set
859 : //TODO: so the user defined name replaces the function string and field name.
860 :
861 : //TODO: the complete name (function and field) must be stored at the dimension
862 :
863 89 : long nSource = pDim->GetSourceDim();
864 89 : if (nSource >= 0)
865 5 : aInfo.aDataSrcCols.push_back(nSource);
866 : else
867 84 : aInfo.aDataSrcCols.push_back(nDimIndex);
868 : }
869 :
870 91 : pResData = new ScDPResultData(*this);
871 91 : pResData->SetMeasureData(aDataFunctions, aDataRefValues, aDataRefOrient, aDataNames);
872 91 : pResData->SetDataLayoutOrientation(nDataOrient);
873 91 : pResData->SetLateInit( bLateInit );
874 :
875 91 : bool bHasAutoShow = false;
876 :
877 182 : ScDPInitState aInitState;
878 :
879 : // Page field selections restrict the members shown in related fields
880 : // (both in column and row fields). aInitState is filled with the page
881 : // field selections, they are kept across the data iterator loop.
882 :
883 118 : for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
884 : {
885 27 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
886 27 : if ( pDim->HasSelectedPage() )
887 0 : aInitState.AddMember(*it, GetMemberId(*it, pDim->GetSelectedData()));
888 : }
889 :
890 : // Show grand total columns only when the option is set *and* there is at
891 : // least one column field. Same for the grand total rows.
892 91 : sal_uInt16 nDataLayoutOrient = GetDataLayoutOrientation();
893 91 : long nColDimCount2 = maColDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_COLUMN ? 1 : 0);
894 91 : long nRowDimCount2 = maRowDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_ROW ? 1 : 0);
895 91 : bool bShowColGrand = bColumnGrand && nColDimCount2 > 0;
896 91 : bool bShowRowGrand = bRowGrand && nRowDimCount2 > 0;
897 91 : pColResRoot = new ScDPResultMember(pResData, bShowColGrand);
898 91 : pRowResRoot = new ScDPResultMember(pResData, bShowRowGrand);
899 :
900 91 : FillCalcInfo(false, aInfo, bHasAutoShow);
901 91 : long nColLevelCount = aInfo.aColLevels.size();
902 :
903 91 : pColResRoot->InitFrom( aInfo.aColDims, aInfo.aColLevels, 0, aInitState );
904 91 : pColResRoot->SetHasElements();
905 :
906 91 : FillCalcInfo(true, aInfo, bHasAutoShow);
907 91 : long nRowLevelCount = aInfo.aRowLevels.size();
908 :
909 91 : if ( nRowLevelCount > 0 )
910 : {
911 : // disable layout flags for the innermost row field (level)
912 76 : aInfo.aRowLevels[nRowLevelCount-1]->SetEnableLayout( false );
913 : }
914 :
915 91 : pRowResRoot->InitFrom( aInfo.aRowDims, aInfo.aRowLevels, 0, aInitState );
916 91 : pRowResRoot->SetHasElements();
917 :
918 : // initialize members object also for all page dimensions (needed for numeric groups)
919 118 : for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
920 : {
921 27 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
922 27 : long nHierarchy = pDim->getUsedHierarchy();
923 27 : if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
924 0 : nHierarchy = 0;
925 :
926 27 : ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
927 27 : long nCount = pLevels->getCount();
928 54 : for (long j=0; j<nCount; j++)
929 27 : pLevels->getByIndex(j)->GetMembersObject(); // initialize for groups
930 : }
931 :
932 : // pre-check: calculate minimum number of result columns / rows from
933 : // levels that have the "show all" flag set
934 :
935 91 : long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount );
936 91 : long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount );
937 :
938 91 : if ( nMinColMembers > MAXCOLCOUNT/*SC_MINCOUNT_LIMIT*/ || nMinRowMembers > SC_MINCOUNT_LIMIT )
939 : {
940 : // resulting table is too big -> abort before calculating
941 : // (this relies on late init, so no members are allocated in InitFrom above)
942 :
943 0 : bResultOverflow = true;
944 0 : return;
945 : }
946 :
947 91 : FilterCacheByPageDimensions();
948 :
949 91 : aInfo.aPageDims.reserve(maPageDims.size());
950 118 : for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
951 27 : aInfo.aPageDims.push_back(*it);
952 :
953 91 : aInfo.pInitState = &aInitState;
954 91 : aInfo.pColRoot = pColResRoot;
955 91 : aInfo.pRowRoot = pRowResRoot;
956 91 : pData->CalcResults(aInfo, false);
957 :
958 91 : pColResRoot->CheckShowEmpty();
959 91 : pRowResRoot->CheckShowEmpty();
960 :
961 : // With all data processed, calculate the final results:
962 :
963 : // UpdateDataResults calculates all original results from the collected values,
964 : // and stores them as reference values if needed.
965 91 : pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
966 :
967 91 : if ( bHasAutoShow ) // do the double calculation only if AutoShow is used
968 : {
969 : // Find the desired members and set bAutoHidden flag for the others
970 1 : pRowResRoot->DoAutoShow( pColResRoot );
971 :
972 : // Reset all results to empty, so they can be built again with data for the
973 : // desired members only.
974 1 : pColResRoot->ResetResults();
975 1 : pRowResRoot->ResetResults();
976 1 : pData->CalcResults(aInfo, true);
977 :
978 : // Call UpdateDataResults again, with the new (limited) values.
979 1 : pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
980 : }
981 :
982 : // SortMembers does the sorting by a result dimension, using the original results,
983 : // but not running totals etc.
984 91 : pRowResRoot->SortMembers( pColResRoot );
985 :
986 : // UpdateRunningTotals calculates running totals along column/row dimensions,
987 : // differences from other members (named or relative), and column/row percentages
988 : // or index values.
989 : // Running totals and relative differences need to be done using the sorted values.
990 : // Column/row percentages and index values must be done after sorting, because the
991 : // results may no longer be in the right order (row total for percentage of row is
992 : // always 1).
993 182 : ScDPRunningTotalState aRunning( pColResRoot, pRowResRoot );
994 182 : ScDPRowTotals aTotals;
995 182 : pRowResRoot->UpdateRunningTotals( pColResRoot, pResData->GetRowStartMeasure(), aRunning, aTotals );
996 : }
997 :
998 152 : void ScDPSource::FillLevelList( sal_uInt16 nOrientation, std::vector<ScDPLevel*> &rList )
999 : {
1000 152 : rList.clear();
1001 :
1002 152 : std::vector<long>* pDimIndex = NULL;
1003 152 : switch (nOrientation)
1004 : {
1005 : case sheet::DataPilotFieldOrientation_COLUMN:
1006 76 : pDimIndex = &maColDims;
1007 76 : break;
1008 : case sheet::DataPilotFieldOrientation_ROW:
1009 76 : pDimIndex = &maRowDims;
1010 76 : break;
1011 : case sheet::DataPilotFieldOrientation_DATA:
1012 0 : pDimIndex = &maDataDims;
1013 0 : break;
1014 : case sheet::DataPilotFieldOrientation_PAGE:
1015 0 : pDimIndex = &maPageDims;
1016 0 : break;
1017 : default:
1018 : OSL_FAIL( "ScDPSource::FillLevelList: unexpected orientation" );
1019 0 : break;
1020 : }
1021 152 : if (!pDimIndex)
1022 : {
1023 : OSL_FAIL("invalid orientation");
1024 152 : return;
1025 : }
1026 :
1027 152 : ScDPDimensions* pDims = GetDimensionsObject();
1028 152 : std::vector<long>::const_iterator it = pDimIndex->begin(), itEnd = pDimIndex->end();
1029 331 : for (; it != itEnd; ++it)
1030 : {
1031 179 : ScDPDimension* pDim = pDims->getByIndex(*it);
1032 : OSL_ENSURE( pDim->getOrientation() == nOrientation, "orientations are wrong" );
1033 :
1034 179 : ScDPHierarchies* pHiers = pDim->GetHierarchiesObject();
1035 179 : long nHierarchy = pDim->getUsedHierarchy();
1036 179 : if ( nHierarchy >= pHiers->getCount() )
1037 0 : nHierarchy = 0;
1038 179 : ScDPHierarchy* pHier = pHiers->getByIndex(nHierarchy);
1039 179 : ScDPLevels* pLevels = pHier->GetLevelsObject();
1040 179 : long nLevCount = pLevels->getCount();
1041 358 : for (long nLev=0; nLev<nLevCount; nLev++)
1042 : {
1043 179 : ScDPLevel* pLevel = pLevels->getByIndex(nLev);
1044 179 : rList.push_back(pLevel);
1045 : }
1046 : }
1047 : }
1048 :
1049 228 : void ScDPSource::FillMemberResults()
1050 : {
1051 228 : if ( !pColResults && !pRowResults )
1052 : {
1053 76 : CreateRes_Impl();
1054 :
1055 76 : if ( bResultOverflow ) // set in CreateRes_Impl
1056 : {
1057 : // no results available -> abort (leave empty)
1058 : // exception is thrown in ScDPSource::getResults
1059 228 : return;
1060 : }
1061 :
1062 76 : FillLevelList( sheet::DataPilotFieldOrientation_COLUMN, aColLevelList );
1063 76 : long nColLevelCount = aColLevelList.size();
1064 76 : if (nColLevelCount)
1065 : {
1066 45 : long nColDimSize = pColResRoot->GetSize(pResData->GetColStartMeasure());
1067 45 : pColResults = new uno::Sequence<sheet::MemberResult>[nColLevelCount];
1068 94 : for (long i=0; i<nColLevelCount; i++)
1069 49 : pColResults[i].realloc(nColDimSize);
1070 :
1071 45 : long nPos = 0;
1072 : pColResRoot->FillMemberResults( pColResults, nPos, pResData->GetColStartMeasure(),
1073 45 : true, NULL, NULL );
1074 : }
1075 :
1076 76 : FillLevelList( sheet::DataPilotFieldOrientation_ROW, aRowLevelList );
1077 76 : long nRowLevelCount = aRowLevelList.size();
1078 76 : if (nRowLevelCount)
1079 : {
1080 74 : long nRowDimSize = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
1081 74 : pRowResults = new uno::Sequence<sheet::MemberResult>[nRowLevelCount];
1082 204 : for (long i=0; i<nRowLevelCount; i++)
1083 130 : pRowResults[i].realloc(nRowDimSize);
1084 :
1085 74 : long nPos = 0;
1086 : pRowResRoot->FillMemberResults( pRowResults, nPos, pResData->GetRowStartMeasure(),
1087 74 : true, NULL, NULL );
1088 : }
1089 : }
1090 : }
1091 :
1092 228 : const uno::Sequence<sheet::MemberResult>* ScDPSource::GetMemberResults( ScDPLevel* pLevel )
1093 : {
1094 228 : FillMemberResults();
1095 :
1096 228 : long i = 0;
1097 228 : long nColCount = aColLevelList.size();
1098 320 : for (i=0; i<nColCount; i++)
1099 : {
1100 144 : ScDPLevel* pColLevel = aColLevelList[i];
1101 144 : if ( pColLevel == pLevel )
1102 52 : return pColResults+i;
1103 : }
1104 176 : long nRowCount = aRowLevelList.size();
1105 294 : for (i=0; i<nRowCount; i++)
1106 : {
1107 294 : ScDPLevel* pRowLevel = aRowLevelList[i];
1108 294 : if ( pRowLevel == pLevel )
1109 176 : return pRowResults+i;
1110 : }
1111 0 : return NULL;
1112 : }
1113 :
1114 : // XPropertySet
1115 :
1116 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo()
1117 : throw(uno::RuntimeException, std::exception)
1118 : {
1119 0 : SolarMutexGuard aGuard;
1120 : using beans::PropertyAttribute::READONLY;
1121 :
1122 : static const SfxItemPropertyMapEntry aDPSourceMap_Impl[] =
1123 : {
1124 0 : { OUString(SC_UNO_DP_COLGRAND), 0, cppu::UnoType<bool>::get(), 0, 0 },
1125 0 : { OUString(SC_UNO_DP_DATADESC), 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
1126 0 : { OUString(SC_UNO_DP_IGNOREEMPTY), 0, cppu::UnoType<bool>::get(), 0, 0 }, // for sheet data only
1127 0 : { OUString(SC_UNO_DP_REPEATEMPTY), 0, cppu::UnoType<bool>::get(), 0, 0 }, // for sheet data only
1128 0 : { OUString(SC_UNO_DP_ROWGRAND), 0, cppu::UnoType<bool>::get(), 0, 0 },
1129 0 : { OUString(SC_UNO_DP_ROWFIELDCOUNT), 0, cppu::UnoType<sal_Int32>::get(), READONLY, 0 },
1130 0 : { OUString(SC_UNO_DP_COLUMNFIELDCOUNT), 0, cppu::UnoType<sal_Int32>::get(), READONLY, 0 },
1131 0 : { OUString(SC_UNO_DP_DATAFIELDCOUNT), 0, cppu::UnoType<sal_Int32>::get(), READONLY, 0 },
1132 0 : { OUString(SC_UNO_DP_GRANDTOTAL_NAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
1133 : { OUString(), 0, css::uno::Type(), 0, 0 }
1134 0 : };
1135 : static uno::Reference<beans::XPropertySetInfo> aRef =
1136 0 : new SfxItemPropertySetInfo( aDPSourceMap_Impl );
1137 0 : return aRef;
1138 : }
1139 :
1140 522 : void SAL_CALL ScDPSource::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
1141 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
1142 : lang::IllegalArgumentException, lang::WrappedTargetException,
1143 : uno::RuntimeException, std::exception)
1144 : {
1145 522 : if (aPropertyName == SC_UNO_DP_COLGRAND)
1146 131 : bColumnGrand = lcl_GetBoolFromAny(aValue);
1147 391 : else if (aPropertyName == SC_UNO_DP_ROWGRAND)
1148 131 : bRowGrand = lcl_GetBoolFromAny(aValue);
1149 260 : else if (aPropertyName == SC_UNO_DP_IGNOREEMPTY)
1150 130 : setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
1151 130 : else if (aPropertyName == SC_UNO_DP_REPEATEMPTY)
1152 130 : setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
1153 0 : else if (aPropertyName == SC_UNO_DP_GRANDTOTAL_NAME)
1154 : {
1155 0 : OUString aName;
1156 0 : if (aValue >>= aName)
1157 0 : mpGrandTotalName.reset(new OUString(aName));
1158 : }
1159 : else
1160 : {
1161 : OSL_FAIL("unknown property");
1162 : //TODO: THROW( UnknownPropertyException() );
1163 : }
1164 522 : }
1165 :
1166 1263 : uno::Any SAL_CALL ScDPSource::getPropertyValue( const OUString& aPropertyName )
1167 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
1168 : uno::RuntimeException, std::exception)
1169 : {
1170 1263 : uno::Any aRet;
1171 1263 : if ( aPropertyName == SC_UNO_DP_COLGRAND )
1172 327 : lcl_SetBoolInAny(aRet, bColumnGrand);
1173 936 : else if ( aPropertyName == SC_UNO_DP_ROWGRAND )
1174 327 : lcl_SetBoolInAny(aRet, bRowGrand);
1175 609 : else if ( aPropertyName == SC_UNO_DP_IGNOREEMPTY )
1176 0 : lcl_SetBoolInAny(aRet, bIgnoreEmptyRows);
1177 609 : else if ( aPropertyName == SC_UNO_DP_REPEATEMPTY )
1178 0 : lcl_SetBoolInAny(aRet, bRepeatIfEmpty);
1179 609 : else if ( aPropertyName == SC_UNO_DP_DATADESC ) // read-only
1180 88 : aRet <<= getDataDescription();
1181 521 : else if ( aPropertyName == SC_UNO_DP_ROWFIELDCOUNT ) // read-only
1182 0 : aRet <<= static_cast<sal_Int32>(maRowDims.size());
1183 521 : else if ( aPropertyName == SC_UNO_DP_COLUMNFIELDCOUNT ) // read-only
1184 0 : aRet <<= static_cast<sal_Int32>(maColDims.size());
1185 521 : else if ( aPropertyName == SC_UNO_DP_DATAFIELDCOUNT ) // read-only
1186 521 : aRet <<= static_cast<sal_Int32>(maDataDims.size());
1187 0 : else if (aPropertyName == SC_UNO_DP_GRANDTOTAL_NAME)
1188 : {
1189 0 : if (mpGrandTotalName.get())
1190 0 : aRet <<= *mpGrandTotalName;
1191 : }
1192 : else
1193 : {
1194 : OSL_FAIL("unknown property");
1195 : //TODO: THROW( UnknownPropertyException() );
1196 : }
1197 1263 : return aRet;
1198 : }
1199 :
1200 : #if DEBUG_PIVOT_TABLE
1201 : void ScDPSource::DumpResults() const
1202 : {
1203 : std::cout << "+++++ column root" << std::endl;
1204 : pColResRoot->Dump(1);
1205 : std::cout << "+++++ row root" << std::endl;
1206 : pRowResRoot->Dump(1);
1207 : }
1208 : #endif
1209 :
1210 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )
1211 :
1212 131 : ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
1213 : pSource( pSrc ),
1214 131 : ppDims( NULL )
1215 : {
1216 : //TODO: hold pSource
1217 :
1218 : // include data layout dimension and duplicated dimensions
1219 131 : nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
1220 131 : }
1221 :
1222 387 : ScDPDimensions::~ScDPDimensions()
1223 : {
1224 : //TODO: release pSource
1225 :
1226 129 : if (ppDims)
1227 : {
1228 724 : for (long i=0; i<nDimCount; i++)
1229 595 : if ( ppDims[i] )
1230 595 : ppDims[i]->release(); // ref-counted
1231 129 : delete[] ppDims;
1232 : }
1233 258 : }
1234 :
1235 5 : void ScDPDimensions::CountChanged()
1236 : {
1237 : // include data layout dimension and duplicated dimensions
1238 5 : long nNewCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
1239 5 : if ( ppDims )
1240 : {
1241 : long i;
1242 5 : long nCopy = std::min( nNewCount, nDimCount );
1243 5 : ScDPDimension** ppNew = new ScDPDimension*[nNewCount];
1244 :
1245 20 : for (i=0; i<nCopy; i++) // copy existing dims
1246 15 : ppNew[i] = ppDims[i];
1247 10 : for (i=nCopy; i<nNewCount; i++) // clear additional pointers
1248 5 : ppNew[i] = NULL;
1249 5 : for (i=nCopy; i<nDimCount; i++) // delete old dims if count is decreased
1250 0 : if ( ppDims[i] )
1251 0 : ppDims[i]->release(); // ref-counted
1252 :
1253 5 : delete[] ppDims;
1254 5 : ppDims = ppNew;
1255 : }
1256 5 : nDimCount = nNewCount;
1257 5 : }
1258 :
1259 : // very simple XNameAccess implementation using getCount/getByIndex
1260 :
1261 5746 : uno::Any SAL_CALL ScDPDimensions::getByName( const OUString& aName )
1262 : throw(container::NoSuchElementException,
1263 : lang::WrappedTargetException, uno::RuntimeException, std::exception)
1264 : {
1265 5746 : long nCount = getCount();
1266 17831 : for (long i=0; i<nCount; i++)
1267 17831 : if ( getByIndex(i)->getName() == aName )
1268 : {
1269 5746 : uno::Reference<container::XNamed> xNamed = getByIndex(i);
1270 11492 : uno::Any aRet;
1271 5746 : aRet <<= xNamed;
1272 17238 : return aRet;
1273 : }
1274 :
1275 0 : throw container::NoSuchElementException();
1276 : // return uno::Any();
1277 : }
1278 :
1279 1187 : uno::Sequence<OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException, std::exception)
1280 : {
1281 1187 : long nCount = getCount();
1282 1187 : uno::Sequence<OUString> aSeq(nCount);
1283 1187 : OUString* pArr = aSeq.getArray();
1284 7989 : for (long i=0; i<nCount; i++)
1285 6802 : pArr[i] = getByIndex(i)->getName();
1286 1187 : return aSeq;
1287 : }
1288 :
1289 0 : sal_Bool SAL_CALL ScDPDimensions::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
1290 : {
1291 0 : long nCount = getCount();
1292 0 : for (long i=0; i<nCount; i++)
1293 0 : if ( getByIndex(i)->getName() == aName )
1294 0 : return sal_True;
1295 0 : return false;
1296 : }
1297 :
1298 0 : uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException, std::exception)
1299 : {
1300 0 : return cppu::UnoType<container::XNamed>::get();
1301 : }
1302 :
1303 0 : sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException, std::exception)
1304 : {
1305 0 : return ( getCount() > 0 );
1306 : }
1307 :
1308 : // end of XNameAccess implementation
1309 :
1310 6980 : long ScDPDimensions::getCount() const
1311 : {
1312 : // in tabular data, every column of source data is a dimension
1313 :
1314 6980 : return nDimCount;
1315 : }
1316 :
1317 34297 : ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
1318 : {
1319 34297 : if ( nIndex >= 0 && nIndex < nDimCount )
1320 : {
1321 34297 : if ( !ppDims )
1322 : {
1323 131 : const_cast<ScDPDimensions*>(this)->ppDims = new ScDPDimension*[nDimCount];
1324 729 : for (long i=0; i<nDimCount; i++)
1325 598 : ppDims[i] = NULL;
1326 : }
1327 34297 : if ( !ppDims[nIndex] )
1328 : {
1329 603 : ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
1330 603 : ppDims[nIndex]->acquire(); // ref-counted
1331 : }
1332 :
1333 34297 : return ppDims[nIndex];
1334 : }
1335 :
1336 0 : return NULL; //TODO: exception?
1337 : }
1338 :
1339 603 : ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
1340 : pSource( pSrc ),
1341 : nDim( nD ),
1342 : pHierarchies( NULL ),
1343 : nUsedHier( 0 ),
1344 : nFunction( SUBTOTAL_FUNC_SUM ), // sum is default
1345 : mpLayoutName(NULL),
1346 : mpSubtotalName(NULL),
1347 : nSourceDim( -1 ),
1348 : bHasSelectedPage( false ),
1349 : pSelectedData( NULL ),
1350 603 : mbHasHiddenMember(false)
1351 : {
1352 : //TODO: hold pSource
1353 603 : }
1354 :
1355 1785 : ScDPDimension::~ScDPDimension()
1356 : {
1357 : //TODO: release pSource
1358 :
1359 595 : if ( pHierarchies )
1360 333 : pHierarchies->release(); // ref-counted
1361 :
1362 595 : delete pSelectedData;
1363 1190 : }
1364 :
1365 2486 : ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
1366 : {
1367 2486 : if (!pHierarchies)
1368 : {
1369 341 : pHierarchies = new ScDPHierarchies( pSource, nDim );
1370 341 : pHierarchies->acquire(); // ref-counted
1371 : }
1372 2486 : return pHierarchies;
1373 : }
1374 :
1375 386 : const OUString* ScDPDimension::GetLayoutName() const
1376 : {
1377 386 : return mpLayoutName.get();
1378 : }
1379 :
1380 0 : const OUString* ScDPDimension::GetSubtotalName() const
1381 : {
1382 0 : return mpSubtotalName.get();
1383 : }
1384 :
1385 736 : uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
1386 : throw(uno::RuntimeException, std::exception)
1387 : {
1388 736 : return GetHierarchiesObject();
1389 : }
1390 :
1391 28117 : OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException, std::exception)
1392 : {
1393 28117 : if (!aName.isEmpty())
1394 46 : return aName;
1395 : else
1396 28071 : return pSource->GetData()->getDimensionName( nDim );
1397 : }
1398 :
1399 5 : void SAL_CALL ScDPDimension::setName( const OUString& rNewName ) throw(uno::RuntimeException, std::exception)
1400 : {
1401 : // used after cloning
1402 5 : aName = rNewName;
1403 5 : }
1404 :
1405 3108 : sal_uInt16 ScDPDimension::getOrientation() const
1406 : {
1407 3108 : return pSource->GetOrientation( nDim );
1408 : }
1409 :
1410 935 : void ScDPDimension::setOrientation(sal_uInt16 nNew)
1411 : {
1412 935 : pSource->SetOrientation( nDim, nNew );
1413 935 : }
1414 :
1415 452 : long ScDPDimension::getPosition() const
1416 : {
1417 452 : return pSource->GetPosition( nDim );
1418 : }
1419 :
1420 3450 : bool ScDPDimension::getIsDataLayoutDimension() const
1421 : {
1422 3450 : return pSource->GetData()->getIsDataLayoutDimension( nDim );
1423 : }
1424 :
1425 337 : void ScDPDimension::setFunction(sal_uInt16 nNew)
1426 : {
1427 337 : nFunction = nNew;
1428 337 : }
1429 :
1430 5 : ScDPDimension* ScDPDimension::CreateCloneObject()
1431 : {
1432 : OSL_ENSURE( nSourceDim < 0, "recursive duplicate - not implemented" );
1433 :
1434 : //TODO: set new name here, or temporary name ???
1435 5 : OUString aNewName = aName;
1436 :
1437 5 : ScDPDimension* pNew = pSource->AddDuplicated( nDim, aNewName );
1438 :
1439 5 : pNew->aName = aNewName; //TODO: here or in source?
1440 5 : pNew->nSourceDim = nDim; //TODO: recursive?
1441 :
1442 5 : return pNew;
1443 : }
1444 :
1445 5 : uno::Reference<util::XCloneable> SAL_CALL ScDPDimension::createClone() throw(uno::RuntimeException, std::exception)
1446 : {
1447 5 : return CreateCloneObject();
1448 : }
1449 :
1450 0 : const ScDPItemData& ScDPDimension::GetSelectedData()
1451 : {
1452 0 : if ( !pSelectedData )
1453 : {
1454 : // find the named member to initialize pSelectedData from it, with name and value
1455 :
1456 0 : long nLevel = 0;
1457 :
1458 0 : long nHierarchy = getUsedHierarchy();
1459 0 : if ( nHierarchy >= GetHierarchiesObject()->getCount() )
1460 0 : nHierarchy = 0;
1461 0 : ScDPLevels* pLevels = GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
1462 0 : long nLevCount = pLevels->getCount();
1463 0 : if ( nLevel < nLevCount )
1464 : {
1465 0 : ScDPMembers* pMembers = pLevels->getByIndex(nLevel)->GetMembersObject();
1466 :
1467 : //TODO: merge with ScDPMembers::getByName
1468 0 : long nCount = pMembers->getCount();
1469 0 : for (long i=0; i<nCount && !pSelectedData; i++)
1470 : {
1471 0 : ScDPMember* pMember = pMembers->getByIndex(i);
1472 0 : if (aSelectedPage.equals(pMember->GetNameStr()))
1473 : {
1474 0 : pSelectedData = new ScDPItemData();
1475 0 : pMember->FillItemData( *pSelectedData );
1476 : }
1477 : }
1478 : }
1479 :
1480 0 : if ( !pSelectedData )
1481 0 : pSelectedData = new ScDPItemData(aSelectedPage); // default - name only
1482 : }
1483 :
1484 0 : return *pSelectedData;
1485 : }
1486 :
1487 : // XPropertySet
1488 :
1489 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo()
1490 : throw(uno::RuntimeException, std::exception)
1491 : {
1492 0 : SolarMutexGuard aGuard;
1493 :
1494 : static const SfxItemPropertyMapEntry aDPDimensionMap_Impl[] =
1495 : {
1496 0 : { OUString(SC_UNO_DP_FILTER), 0, cppu::UnoType<uno::Sequence<sheet::TableFilterField>>::get(), 0, 0 },
1497 0 : { OUString(SC_UNO_DP_FLAGS), 0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0 },
1498 0 : { OUString(SC_UNO_DP_FUNCTION), 0, cppu::UnoType<sheet::GeneralFunction>::get(), 0, 0 },
1499 0 : { OUString(SC_UNO_DP_ISDATALAYOUT), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0 },
1500 0 : { OUString(SC_UNO_DP_NUMBERFO), 0, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY, 0 },
1501 0 : { OUString(SC_UNO_DP_ORIENTATION), 0, cppu::UnoType<sheet::DataPilotFieldOrientation>::get(), 0, 0 },
1502 0 : { OUString(SC_UNO_DP_ORIGINAL), 0, cppu::UnoType<container::XNamed>::get(), beans::PropertyAttribute::READONLY, 0 },
1503 0 : { OUString(SC_UNO_DP_ORIGINAL_POS), 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
1504 0 : { OUString(SC_UNO_DP_POSITION), 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
1505 0 : { OUString(SC_UNO_DP_REFVALUE), 0, cppu::UnoType<sheet::DataPilotFieldReference>::get(), 0, 0 },
1506 0 : { OUString(SC_UNO_DP_USEDHIERARCHY), 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
1507 0 : { OUString(SC_UNO_DP_LAYOUTNAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
1508 0 : { OUString(SC_UNO_DP_FIELD_SUBTOTALNAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
1509 0 : { OUString(SC_UNO_DP_HAS_HIDDEN_MEMBER), 0, cppu::UnoType<bool>::get(), 0, 0 },
1510 : { OUString(), 0, css::uno::Type(), 0, 0 }
1511 0 : };
1512 : static uno::Reference<beans::XPropertySetInfo> aRef =
1513 0 : new SfxItemPropertySetInfo( aDPDimensionMap_Impl );
1514 0 : return aRef;
1515 : }
1516 :
1517 1764 : void SAL_CALL ScDPDimension::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
1518 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
1519 : lang::IllegalArgumentException, lang::WrappedTargetException,
1520 : uno::RuntimeException, std::exception)
1521 : {
1522 1764 : if ( aPropertyName == SC_UNO_DP_USEDHIERARCHY )
1523 : {
1524 : // #i52547# don't use the incomplete date hierarchy implementation - ignore the call
1525 : }
1526 1618 : else if ( aPropertyName == SC_UNO_DP_ORIENTATION )
1527 : {
1528 : sheet::DataPilotFieldOrientation eEnum;
1529 935 : if (aValue >>= eEnum)
1530 935 : setOrientation( sal::static_int_cast<sal_uInt16>(eEnum) );
1531 : }
1532 683 : else if ( aPropertyName == SC_UNO_DP_FUNCTION )
1533 : {
1534 : sheet::GeneralFunction eEnum;
1535 337 : if (aValue >>= eEnum)
1536 337 : setFunction( sal::static_int_cast<sal_uInt16>(eEnum) );
1537 : }
1538 346 : else if ( aPropertyName == SC_UNO_DP_REFVALUE )
1539 7 : aValue >>= aReferenceValue;
1540 339 : else if ( aPropertyName == SC_UNO_DP_FILTER )
1541 : {
1542 0 : bool bDone = false;
1543 0 : uno::Sequence<sheet::TableFilterField> aSeq;
1544 0 : if (aValue >>= aSeq)
1545 : {
1546 0 : sal_Int32 nLength = aSeq.getLength();
1547 0 : if ( nLength == 0 )
1548 : {
1549 0 : aSelectedPage.clear();
1550 0 : bHasSelectedPage = false;
1551 0 : bDone = true;
1552 : }
1553 0 : else if ( nLength == 1 )
1554 : {
1555 0 : const sheet::TableFilterField& rField = aSeq[0];
1556 0 : if ( rField.Field == 0 && rField.Operator == sheet::FilterOperator_EQUAL && !rField.IsNumeric )
1557 : {
1558 0 : aSelectedPage = rField.StringValue;
1559 0 : bHasSelectedPage = true;
1560 0 : bDone = true;
1561 : }
1562 : }
1563 : }
1564 0 : if ( !bDone )
1565 : {
1566 : OSL_FAIL("Filter property is not a single string");
1567 0 : throw lang::IllegalArgumentException();
1568 : }
1569 0 : DELETEZ( pSelectedData ); // invalid after changing aSelectedPage
1570 : }
1571 339 : else if (aPropertyName == SC_UNO_DP_LAYOUTNAME)
1572 : {
1573 2 : OUString aTmpName;
1574 2 : if (aValue >>= aTmpName)
1575 2 : mpLayoutName.reset(new OUString(aTmpName));
1576 : }
1577 337 : else if (aPropertyName == SC_UNO_DP_FIELD_SUBTOTALNAME)
1578 : {
1579 0 : OUString aTmpName;
1580 0 : if (aValue >>= aTmpName)
1581 0 : mpSubtotalName.reset(new OUString(aTmpName));
1582 : }
1583 337 : else if (aPropertyName == SC_UNO_DP_HAS_HIDDEN_MEMBER)
1584 : {
1585 337 : bool b = false;
1586 337 : aValue >>= b;
1587 337 : mbHasHiddenMember = b;
1588 : }
1589 : else
1590 : {
1591 : OSL_FAIL("unknown property");
1592 : //TODO: THROW( UnknownPropertyException() );
1593 : }
1594 1764 : }
1595 :
1596 9454 : uno::Any SAL_CALL ScDPDimension::getPropertyValue( const OUString& aPropertyName )
1597 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
1598 : uno::RuntimeException, std::exception)
1599 : {
1600 9454 : uno::Any aRet;
1601 9454 : if ( aPropertyName == SC_UNO_DP_POSITION )
1602 452 : aRet <<= (sal_Int32) getPosition();
1603 9002 : else if ( aPropertyName == SC_UNO_DP_USEDHIERARCHY )
1604 396 : aRet <<= (sal_Int32) getUsedHierarchy();
1605 8606 : else if ( aPropertyName == SC_UNO_DP_ORIENTATION )
1606 : {
1607 3108 : sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
1608 3108 : aRet <<= eVal;
1609 : }
1610 5498 : else if ( aPropertyName == SC_UNO_DP_FUNCTION )
1611 : {
1612 346 : sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
1613 346 : aRet <<= eVal;
1614 : }
1615 5152 : else if ( aPropertyName == SC_UNO_DP_REFVALUE )
1616 0 : aRet <<= aReferenceValue;
1617 5152 : else if ( aPropertyName == SC_UNO_DP_ISDATALAYOUT ) // read-only properties
1618 2917 : lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
1619 2235 : else if ( aPropertyName == SC_UNO_DP_NUMBERFO )
1620 : {
1621 618 : sal_Int32 nFormat = 0;
1622 618 : sheet::GeneralFunction eFunc = (sheet::GeneralFunction)getFunction();
1623 : // #i63745# don't use source format for "count"
1624 618 : if ( eFunc != sheet::GeneralFunction_COUNT && eFunc != sheet::GeneralFunction_COUNTNUMS )
1625 608 : nFormat = pSource->GetData()->GetNumberFormat( ( nSourceDim >= 0 ) ? nSourceDim : nDim );
1626 :
1627 618 : switch ( aReferenceValue.ReferenceType )
1628 : {
1629 : case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
1630 : case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
1631 : case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE:
1632 : case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
1633 : case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
1634 6 : nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_PERCENT_DEC2 );
1635 6 : break;
1636 : case sheet::DataPilotFieldReferenceType::INDEX:
1637 0 : nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_NUMBER_SYSTEM );
1638 0 : break;
1639 : default:
1640 612 : break;
1641 : }
1642 :
1643 618 : aRet <<= nFormat;
1644 : }
1645 1617 : else if ( aPropertyName == SC_UNO_DP_ORIGINAL )
1646 : {
1647 648 : uno::Reference<container::XNamed> xOriginal;
1648 648 : if (nSourceDim >= 0)
1649 0 : xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
1650 648 : aRet <<= xOriginal;
1651 : }
1652 969 : else if (aPropertyName == SC_UNO_DP_ORIGINAL_POS)
1653 : {
1654 4 : sal_Int32 nPos = static_cast<sal_Int32>(nSourceDim);
1655 4 : aRet <<= nPos;
1656 : }
1657 965 : else if ( aPropertyName == SC_UNO_DP_FILTER )
1658 : {
1659 0 : if ( bHasSelectedPage )
1660 : {
1661 : // single filter field: first field equal to selected string
1662 : sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
1663 0 : sheet::FilterOperator_EQUAL, false, 0.0, aSelectedPage );
1664 0 : aRet <<= uno::Sequence<sheet::TableFilterField>( &aField, 1 );
1665 : }
1666 : else
1667 0 : aRet <<= uno::Sequence<sheet::TableFilterField>(0);
1668 : }
1669 965 : else if (aPropertyName == SC_UNO_DP_LAYOUTNAME)
1670 506 : aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString("");
1671 459 : else if (aPropertyName == SC_UNO_DP_FIELD_SUBTOTALNAME)
1672 4 : aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString("");
1673 455 : else if (aPropertyName == SC_UNO_DP_HAS_HIDDEN_MEMBER)
1674 452 : aRet <<= mbHasHiddenMember;
1675 3 : else if (aPropertyName == SC_UNO_DP_FLAGS)
1676 : {
1677 3 : sal_Int32 nFlags = 0; // tabular data: all orientations are possible
1678 3 : aRet <<= nFlags;
1679 : }
1680 : else
1681 : {
1682 : OSL_FAIL("unknown property");
1683 : //TODO: THROW( UnknownPropertyException() );
1684 : }
1685 9454 : return aRet;
1686 : }
1687 :
1688 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )
1689 :
1690 341 : ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
1691 : pSource( pSrc ),
1692 : nDim( nD ),
1693 341 : ppHiers( NULL )
1694 : {
1695 : //TODO: hold pSource
1696 :
1697 : // date columns have 3 hierarchies (flat/quarter/week), other columns only one
1698 :
1699 : // #i52547# don't offer the incomplete date hierarchy implementation
1700 341 : nHierCount = 1;
1701 341 : }
1702 :
1703 999 : ScDPHierarchies::~ScDPHierarchies()
1704 : {
1705 : //TODO: release pSource
1706 :
1707 333 : if (ppHiers)
1708 : {
1709 666 : for (long i=0; i<nHierCount; i++)
1710 333 : if ( ppHiers[i] )
1711 333 : ppHiers[i]->release(); // ref-counted
1712 333 : delete[] ppHiers;
1713 : }
1714 666 : }
1715 :
1716 : // very simple XNameAccess implementation using getCount/getByIndex
1717 :
1718 733 : uno::Any SAL_CALL ScDPHierarchies::getByName( const OUString& aName )
1719 : throw(container::NoSuchElementException,
1720 : lang::WrappedTargetException, uno::RuntimeException, std::exception)
1721 : {
1722 733 : long nCount = getCount();
1723 733 : for (long i=0; i<nCount; i++)
1724 733 : if ( getByIndex(i)->getName() == aName )
1725 : {
1726 733 : uno::Reference<container::XNamed> xNamed = getByIndex(i);
1727 1466 : uno::Any aRet;
1728 733 : aRet <<= xNamed;
1729 2199 : return aRet;
1730 : }
1731 :
1732 0 : throw container::NoSuchElementException();
1733 : }
1734 :
1735 736 : uno::Sequence<OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException, std::exception)
1736 : {
1737 736 : long nCount = getCount();
1738 736 : uno::Sequence<OUString> aSeq(nCount);
1739 736 : OUString* pArr = aSeq.getArray();
1740 1472 : for (long i=0; i<nCount; i++)
1741 736 : pArr[i] = getByIndex(i)->getName();
1742 736 : return aSeq;
1743 : }
1744 :
1745 0 : sal_Bool SAL_CALL ScDPHierarchies::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
1746 : {
1747 0 : long nCount = getCount();
1748 0 : for (long i=0; i<nCount; i++)
1749 0 : if ( getByIndex(i)->getName() == aName )
1750 0 : return sal_True;
1751 0 : return false;
1752 : }
1753 :
1754 0 : uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException, std::exception)
1755 : {
1756 0 : return cppu::UnoType<container::XNamed>::get();
1757 : }
1758 :
1759 0 : sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException, std::exception)
1760 : {
1761 0 : return ( getCount() > 0 );
1762 : }
1763 :
1764 : // end of XNameAccess implementation
1765 :
1766 1862 : long ScDPHierarchies::getCount() const
1767 : {
1768 1862 : return nHierCount;
1769 : }
1770 :
1771 3738 : ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
1772 : {
1773 : // pass hierarchy index to new object in case the implementation
1774 : // will be extended to more than one hierarchy
1775 :
1776 3738 : if ( nIndex >= 0 && nIndex < nHierCount )
1777 : {
1778 3738 : if ( !ppHiers )
1779 : {
1780 341 : const_cast<ScDPHierarchies*>(this)->ppHiers = new ScDPHierarchy*[nHierCount];
1781 682 : for (long i=0; i<nHierCount; i++)
1782 341 : ppHiers[i] = NULL;
1783 : }
1784 3738 : if ( !ppHiers[nIndex] )
1785 : {
1786 341 : ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
1787 341 : ppHiers[nIndex]->acquire(); // ref-counted
1788 : }
1789 :
1790 3738 : return ppHiers[nIndex];
1791 : }
1792 :
1793 0 : return NULL; //TODO: exception?
1794 : }
1795 :
1796 341 : ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
1797 : pSource( pSrc ),
1798 : nDim( nD ),
1799 : nHier( nH ),
1800 341 : pLevels( NULL )
1801 : {
1802 : //TODO: hold pSource
1803 341 : }
1804 :
1805 999 : ScDPHierarchy::~ScDPHierarchy()
1806 : {
1807 : //TODO: release pSource
1808 :
1809 333 : if (pLevels)
1810 333 : pLevels->release(); // ref-counted
1811 666 : }
1812 :
1813 2269 : ScDPLevels* ScDPHierarchy::GetLevelsObject()
1814 : {
1815 2269 : if (!pLevels)
1816 : {
1817 341 : pLevels = new ScDPLevels( pSource, nDim, nHier );
1818 341 : pLevels->acquire(); // ref-counted
1819 : }
1820 2269 : return pLevels;
1821 : }
1822 :
1823 733 : uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
1824 : throw(uno::RuntimeException, std::exception)
1825 : {
1826 733 : return GetLevelsObject();
1827 : }
1828 :
1829 1469 : OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException, std::exception)
1830 : {
1831 1469 : OUString aRet; //TODO: globstr-ID !!!!
1832 1469 : switch (nHier)
1833 : {
1834 : case SC_DAPI_HIERARCHY_FLAT:
1835 1469 : aRet = "flat";
1836 1469 : break; //TODO: name ???????
1837 : case SC_DAPI_HIERARCHY_QUARTER:
1838 0 : aRet = "Quarter";
1839 0 : break; //TODO: name ???????
1840 : case SC_DAPI_HIERARCHY_WEEK:
1841 0 : aRet = "Week";
1842 0 : break; //TODO: name ???????
1843 : default:
1844 : OSL_FAIL( "ScDPHierarchy::getName: unexpected hierarchy" );
1845 0 : break;
1846 : }
1847 1469 : return aRet;
1848 : }
1849 :
1850 0 : void SAL_CALL ScDPHierarchy::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException, std::exception)
1851 : {
1852 : OSL_FAIL("not implemented"); //TODO: exception?
1853 0 : }
1854 :
1855 341 : ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
1856 : pSource( pSrc ),
1857 : nDim( nD ),
1858 : nHier( nH ),
1859 341 : ppLevs( NULL )
1860 : {
1861 : //TODO: hold pSource
1862 :
1863 : // text columns have only one level
1864 :
1865 341 : long nSrcDim = pSource->GetSourceDim( nDim );
1866 341 : if ( pSource->IsDateDimension( nSrcDim ) )
1867 : {
1868 8 : switch ( nHier )
1869 : {
1870 8 : case SC_DAPI_HIERARCHY_FLAT: nLevCount = SC_DAPI_FLAT_LEVELS; break;
1871 0 : case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
1872 0 : case SC_DAPI_HIERARCHY_WEEK: nLevCount = SC_DAPI_WEEK_LEVELS; break;
1873 : default:
1874 : OSL_FAIL("wrong hierarchy");
1875 0 : nLevCount = 0;
1876 : }
1877 : }
1878 : else
1879 333 : nLevCount = 1;
1880 341 : }
1881 :
1882 999 : ScDPLevels::~ScDPLevels()
1883 : {
1884 : //TODO: release pSource
1885 :
1886 333 : if (ppLevs)
1887 : {
1888 666 : for (long i=0; i<nLevCount; i++)
1889 333 : if ( ppLevs[i] )
1890 333 : ppLevs[i]->release(); // ref-counted
1891 333 : delete[] ppLevs;
1892 : }
1893 666 : }
1894 :
1895 : // very simple XNameAccess implementation using getCount/getByIndex
1896 :
1897 733 : uno::Any SAL_CALL ScDPLevels::getByName( const OUString& aName )
1898 : throw(container::NoSuchElementException,
1899 : lang::WrappedTargetException, uno::RuntimeException, std::exception)
1900 : {
1901 733 : long nCount = getCount();
1902 733 : for (long i=0; i<nCount; i++)
1903 733 : if ( getByIndex(i)->getName() == aName )
1904 : {
1905 733 : uno::Reference<container::XNamed> xNamed = getByIndex(i);
1906 1466 : uno::Any aRet;
1907 733 : aRet <<= xNamed;
1908 2199 : return aRet;
1909 : }
1910 :
1911 0 : throw container::NoSuchElementException();
1912 : }
1913 :
1914 733 : uno::Sequence<OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException, std::exception)
1915 : {
1916 733 : long nCount = getCount();
1917 733 : uno::Sequence<OUString> aSeq(nCount);
1918 733 : OUString* pArr = aSeq.getArray();
1919 1466 : for (long i=0; i<nCount; i++)
1920 733 : pArr[i] = getByIndex(i)->getName();
1921 733 : return aSeq;
1922 : }
1923 :
1924 0 : sal_Bool SAL_CALL ScDPLevels::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
1925 : {
1926 0 : long nCount = getCount();
1927 0 : for (long i=0; i<nCount; i++)
1928 0 : if ( getByIndex(i)->getName() == aName )
1929 0 : return sal_True;
1930 0 : return false;
1931 : }
1932 :
1933 0 : uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException, std::exception)
1934 : {
1935 0 : return cppu::UnoType<container::XNamed>::get();
1936 : }
1937 :
1938 0 : sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException, std::exception)
1939 : {
1940 0 : return ( getCount() > 0 );
1941 : }
1942 :
1943 : // end of XNameAccess implementation
1944 :
1945 1859 : long ScDPLevels::getCount() const
1946 : {
1947 1859 : return nLevCount;
1948 : }
1949 :
1950 3693 : ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
1951 : {
1952 3693 : if ( nIndex >= 0 && nIndex < nLevCount )
1953 : {
1954 3693 : if ( !ppLevs )
1955 : {
1956 341 : const_cast<ScDPLevels*>(this)->ppLevs = new ScDPLevel*[nLevCount];
1957 682 : for (long i=0; i<nLevCount; i++)
1958 341 : ppLevs[i] = NULL;
1959 : }
1960 3693 : if ( !ppLevs[nIndex] )
1961 : {
1962 341 : ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
1963 341 : ppLevs[nIndex]->acquire(); // ref-counted
1964 : }
1965 :
1966 3693 : return ppLevs[nIndex];
1967 : }
1968 :
1969 0 : return NULL; //TODO: exception?
1970 : }
1971 :
1972 : class ScDPGlobalMembersOrder
1973 : {
1974 : ScDPLevel& rLevel;
1975 : bool bAscending;
1976 :
1977 : public:
1978 269 : ScDPGlobalMembersOrder( ScDPLevel& rLev, bool bAsc ) :
1979 : rLevel(rLev),
1980 269 : bAscending(bAsc)
1981 269 : {}
1982 2239 : ~ScDPGlobalMembersOrder() {}
1983 :
1984 : bool operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
1985 : };
1986 :
1987 1801 : bool ScDPGlobalMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
1988 : {
1989 1801 : sal_Int32 nCompare = 0;
1990 : // seems that some ::std::sort() implementations pass the same index twice
1991 1801 : if( nIndex1 != nIndex2 )
1992 : {
1993 1801 : ScDPMembers* pMembers = rLevel.GetMembersObject();
1994 1801 : ScDPMember* pMember1 = pMembers->getByIndex(nIndex1);
1995 1801 : ScDPMember* pMember2 = pMembers->getByIndex(nIndex2);
1996 1801 : nCompare = pMember1->Compare( *pMember2 );
1997 : }
1998 1801 : return bAscending ? (nCompare < 0) : (nCompare > 0);
1999 : }
2000 :
2001 341 : ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
2002 : pSource( pSrc ),
2003 : nDim( nD ),
2004 : nHier( nH ),
2005 : nLev( nL ),
2006 : pMembers( NULL ),
2007 341 : aSortInfo( EMPTY_OUSTRING, sal_True, sheet::DataPilotFieldSortMode::NAME ), // default: sort by name
2008 : nSortMeasure( 0 ),
2009 : nAutoMeasure( 0 ),
2010 : bShowEmpty( false ),
2011 : bEnableLayout( false ),
2012 682 : bRepeatItemLabels( false )
2013 : {
2014 : //TODO: hold pSource
2015 : // aSubTotals is empty
2016 341 : }
2017 :
2018 999 : ScDPLevel::~ScDPLevel()
2019 : {
2020 : //TODO: release pSource
2021 :
2022 333 : if ( pMembers )
2023 199 : pMembers->release(); // ref-counted
2024 666 : }
2025 :
2026 269 : void ScDPLevel::EvaluateSortOrder()
2027 : {
2028 269 : switch (aSortInfo.Mode)
2029 : {
2030 : case sheet::DataPilotFieldSortMode::DATA:
2031 : {
2032 : // find index of measure (index among data dimensions)
2033 :
2034 0 : long nMeasureCount = pSource->GetDataDimensionCount();
2035 0 : for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
2036 : {
2037 0 : if (pSource->GetDataDimName(nMeasure).equals(aSortInfo.Field))
2038 : {
2039 0 : nSortMeasure = nMeasure;
2040 0 : break;
2041 : }
2042 : }
2043 :
2044 : //TODO: error if not found?
2045 : }
2046 0 : break;
2047 : case sheet::DataPilotFieldSortMode::MANUAL:
2048 : case sheet::DataPilotFieldSortMode::NAME:
2049 : {
2050 269 : ScDPMembers* pLocalMembers = GetMembersObject();
2051 269 : long nCount = pLocalMembers->getCount();
2052 :
2053 269 : aGlobalOrder.resize( nCount );
2054 1441 : for (long nPos=0; nPos<nCount; nPos++)
2055 1172 : aGlobalOrder[nPos] = nPos;
2056 :
2057 : // allow manual or name (manual is always ascending)
2058 269 : bool bAscending = ( aSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL || aSortInfo.IsAscending );
2059 269 : ScDPGlobalMembersOrder aComp( *this, bAscending );
2060 269 : ::std::sort( aGlobalOrder.begin(), aGlobalOrder.end(), aComp );
2061 : }
2062 269 : break;
2063 : }
2064 :
2065 269 : if ( aAutoShowInfo.IsEnabled )
2066 : {
2067 : // find index of measure (index among data dimensions)
2068 :
2069 1 : long nMeasureCount = pSource->GetDataDimensionCount();
2070 2 : for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
2071 : {
2072 1 : if (pSource->GetDataDimName(nMeasure).equals(aAutoShowInfo.DataField))
2073 : {
2074 0 : nAutoMeasure = nMeasure;
2075 0 : break;
2076 : }
2077 : }
2078 :
2079 : //TODO: error if not found?
2080 : }
2081 269 : }
2082 :
2083 221 : void ScDPLevel::SetEnableLayout(bool bSet)
2084 : {
2085 221 : bEnableLayout = bSet;
2086 221 : }
2087 :
2088 3892 : ScDPMembers* ScDPLevel::GetMembersObject()
2089 : {
2090 3892 : if (!pMembers)
2091 : {
2092 205 : pMembers = new ScDPMembers( pSource, nDim, nHier, nLev );
2093 205 : pMembers->acquire(); // ref-counted
2094 : }
2095 3892 : return pMembers;
2096 : }
2097 :
2098 201 : uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException, std::exception)
2099 : {
2100 201 : return GetMembersObject();
2101 : }
2102 :
2103 228 : uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException, std::exception)
2104 : {
2105 228 : const uno::Sequence<sheet::MemberResult>* pRes = pSource->GetMemberResults( this );
2106 228 : if (pRes)
2107 228 : return *pRes;
2108 :
2109 0 : return uno::Sequence<sheet::MemberResult>(0); //TODO: Error?
2110 : }
2111 :
2112 1796 : OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException, std::exception)
2113 : {
2114 1796 : long nSrcDim = pSource->GetSourceDim( nDim );
2115 1796 : if ( pSource->IsDateDimension( nSrcDim ) )
2116 : {
2117 40 : OUString aRet; //TODO: globstr-ID !!!!
2118 :
2119 40 : if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
2120 : {
2121 0 : switch ( nLev )
2122 : {
2123 : case SC_DAPI_LEVEL_YEAR:
2124 0 : aRet = "Year";
2125 0 : break;
2126 : case SC_DAPI_LEVEL_QUARTER:
2127 0 : aRet = "Quarter";
2128 0 : break;
2129 : case SC_DAPI_LEVEL_MONTH:
2130 0 : aRet = "Month";
2131 0 : break;
2132 : case SC_DAPI_LEVEL_DAY:
2133 0 : aRet = "Day";
2134 0 : break;
2135 : default:
2136 : OSL_FAIL( "ScDPLevel::getName: unexpected level" );
2137 0 : break;
2138 : }
2139 : }
2140 40 : else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
2141 : {
2142 0 : switch ( nLev )
2143 : {
2144 : case SC_DAPI_LEVEL_YEAR:
2145 0 : aRet = "Year";
2146 0 : break;
2147 : case SC_DAPI_LEVEL_WEEK:
2148 0 : aRet = "Week";
2149 0 : break;
2150 : case SC_DAPI_LEVEL_WEEKDAY:
2151 0 : aRet = "Weekday";
2152 0 : break;
2153 : default:
2154 : OSL_FAIL( "ScDPLevel::getName: unexpected level" );
2155 0 : break;
2156 : }
2157 : }
2158 40 : if (!aRet.isEmpty())
2159 0 : return aRet;
2160 : }
2161 :
2162 1796 : ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
2163 1796 : if (!pDim)
2164 0 : return OUString();
2165 :
2166 1796 : return pDim->getName();
2167 : }
2168 :
2169 0 : void SAL_CALL ScDPLevel::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException, std::exception)
2170 : {
2171 : OSL_FAIL("not implemented"); //TODO: exception?
2172 0 : }
2173 :
2174 7573 : uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
2175 : {
2176 : //TODO: separate functions for settings and evaluation?
2177 :
2178 7573 : long nSrcDim = pSource->GetSourceDim( nDim );
2179 7573 : if ( !pSource->SubTotalAllowed( nSrcDim ) )
2180 6125 : return uno::Sequence<sheet::GeneralFunction>(0);
2181 :
2182 1448 : return aSubTotals;
2183 : }
2184 :
2185 : // XPropertySet
2186 :
2187 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
2188 : throw(uno::RuntimeException, std::exception)
2189 : {
2190 0 : SolarMutexGuard aGuard;
2191 :
2192 : static const SfxItemPropertyMapEntry aDPLevelMap_Impl[] =
2193 : {
2194 : //TODO: change type of AutoShow/Layout/Sorting to API struct when available
2195 0 : { OUString(SC_UNO_DP_AUTOSHOW), 0, cppu::UnoType<sheet::DataPilotFieldAutoShowInfo>::get(), 0, 0 },
2196 0 : { OUString(SC_UNO_DP_LAYOUT), 0, cppu::UnoType<sheet::DataPilotFieldLayoutInfo>::get(), 0, 0 },
2197 0 : { OUString(SC_UNO_DP_SHOWEMPTY), 0, cppu::UnoType<bool>::get(), 0, 0 },
2198 0 : { OUString(SC_UNO_DP_REPEATITEMLABELS), 0, cppu::UnoType<bool>::get(), 0, 0 },
2199 0 : { OUString(SC_UNO_DP_SORTING), 0, cppu::UnoType<sheet::DataPilotFieldSortInfo>::get(), 0, 0 },
2200 0 : { OUString(SC_UNO_DP_SUBTOTAL), 0, cppu::UnoType<uno::Sequence<sheet::GeneralFunction>>::get(), 0, 0 },
2201 : { OUString(), 0, css::uno::Type(), 0, 0 }
2202 0 : };
2203 : static uno::Reference<beans::XPropertySetInfo> aRef =
2204 0 : new SfxItemPropertySetInfo( aDPLevelMap_Impl );
2205 0 : return aRef;
2206 : }
2207 :
2208 879 : void SAL_CALL ScDPLevel::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
2209 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
2210 : lang::IllegalArgumentException, lang::WrappedTargetException,
2211 : uno::RuntimeException, std::exception)
2212 : {
2213 879 : if ( aPropertyName == SC_UNO_DP_SHOWEMPTY )
2214 127 : bShowEmpty = lcl_GetBoolFromAny(aValue);
2215 752 : else if ( aPropertyName == SC_UNO_DP_REPEATITEMLABELS )
2216 337 : bRepeatItemLabels = lcl_GetBoolFromAny(aValue);
2217 415 : else if ( aPropertyName == SC_UNO_DP_SUBTOTAL )
2218 69 : aValue >>= aSubTotals;
2219 346 : else if ( aPropertyName == SC_UNO_DP_SORTING )
2220 122 : aValue >>= aSortInfo;
2221 224 : else if ( aPropertyName == SC_UNO_DP_AUTOSHOW )
2222 100 : aValue >>= aAutoShowInfo;
2223 124 : else if ( aPropertyName == SC_UNO_DP_LAYOUT )
2224 124 : aValue >>= aLayoutInfo;
2225 : else
2226 : {
2227 : OSL_FAIL("unknown property");
2228 : }
2229 879 : }
2230 :
2231 307 : uno::Any SAL_CALL ScDPLevel::getPropertyValue( const OUString& aPropertyName )
2232 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
2233 : uno::RuntimeException, std::exception)
2234 : {
2235 307 : uno::Any aRet;
2236 307 : if ( aPropertyName == SC_UNO_DP_SHOWEMPTY )
2237 3 : lcl_SetBoolInAny(aRet, bShowEmpty);
2238 307 : if ( aPropertyName == SC_UNO_DP_REPEATITEMLABELS )
2239 3 : lcl_SetBoolInAny(aRet, bRepeatItemLabels);
2240 304 : else if ( aPropertyName == SC_UNO_DP_SUBTOTAL )
2241 : {
2242 0 : uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals(); //TODO: avoid extra copy?
2243 0 : aRet <<= aSeq;
2244 : }
2245 304 : else if ( aPropertyName == SC_UNO_DP_SORTING )
2246 3 : aRet <<= aSortInfo;
2247 301 : else if ( aPropertyName == SC_UNO_DP_AUTOSHOW )
2248 3 : aRet <<= aAutoShowInfo;
2249 298 : else if ( aPropertyName == SC_UNO_DP_LAYOUT )
2250 3 : aRet <<= aLayoutInfo;
2251 295 : else if (aPropertyName == SC_UNO_DP_LAYOUTNAME)
2252 : {
2253 : // read only property
2254 292 : long nSrcDim = pSource->GetSourceDim(nDim);
2255 292 : ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
2256 292 : if (!pDim)
2257 0 : return aRet;
2258 :
2259 292 : const OUString* pLayoutName = pDim->GetLayoutName();
2260 292 : if (!pLayoutName)
2261 292 : return aRet;
2262 :
2263 0 : aRet <<= *pLayoutName;
2264 : }
2265 : else
2266 : {
2267 : OSL_FAIL("unknown property");
2268 : }
2269 15 : return aRet;
2270 : }
2271 :
2272 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )
2273 :
2274 205 : ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) :
2275 : pSource( pSrc ),
2276 : nDim( nD ),
2277 : nHier( nH ),
2278 205 : nLev( nL )
2279 : {
2280 : //TODO: hold pSource
2281 :
2282 205 : long nSrcDim = pSource->GetSourceDim( nDim );
2283 205 : if ( pSource->IsDataLayoutDimension(nSrcDim) )
2284 9 : nMbrCount = pSource->GetDataDimensionCount();
2285 196 : else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2286 : {
2287 0 : nMbrCount = 0;
2288 0 : if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
2289 : {
2290 0 : switch (nLev)
2291 : {
2292 : case SC_DAPI_LEVEL_YEAR:
2293 : {
2294 0 : const ScDPItemData* pLastNumData = NULL;
2295 0 : for ( SCROW n = 0 ;n <GetSrcItemsCount() ; n-- )
2296 : {
2297 0 : const ScDPItemData* pData = GetSrcItemDataByIndex( n );
2298 0 : if ( pData && pData->HasStringData() )
2299 0 : break;
2300 : else
2301 0 : pLastNumData = pData;
2302 : }
2303 :
2304 0 : if ( pLastNumData )
2305 : {
2306 0 : const ScDPItemData* pFirstData = GetSrcItemDataByIndex( 0 );
2307 0 : double fFirstVal = pFirstData->GetValue();
2308 0 : double fLastVal = pLastNumData->GetValue();
2309 :
2310 : long nFirstYear = pSource->GetData()->GetDatePart(
2311 0 : (long)::rtl::math::approxFloor( fFirstVal ),
2312 0 : nHier, nLev );
2313 : long nLastYear = pSource->GetData()->GetDatePart(
2314 0 : (long)::rtl::math::approxFloor( fLastVal ),
2315 0 : nHier, nLev );
2316 :
2317 0 : nMbrCount = nLastYear + 1 - nFirstYear;
2318 : }
2319 : else
2320 0 : nMbrCount = 0; // no values
2321 : }
2322 0 : break;
2323 0 : case SC_DAPI_LEVEL_QUARTER: nMbrCount = 4; break;
2324 0 : case SC_DAPI_LEVEL_MONTH: nMbrCount = 12; break;
2325 0 : case SC_DAPI_LEVEL_DAY: nMbrCount = 31; break;
2326 : default:
2327 : OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
2328 0 : break;
2329 : }
2330 : }
2331 0 : else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
2332 : {
2333 0 : switch (nLev)
2334 : {
2335 0 : case SC_DAPI_LEVEL_YEAR: nMbrCount = 1; break; //TODO: get years from source
2336 0 : case SC_DAPI_LEVEL_WEEK: nMbrCount = 53; break;
2337 0 : case SC_DAPI_LEVEL_WEEKDAY: nMbrCount = 7; break;
2338 : default:
2339 : OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
2340 0 : break;
2341 : }
2342 : }
2343 : }
2344 : else
2345 196 : nMbrCount = pSource->GetData()->GetMembersCount( nSrcDim );
2346 205 : }
2347 :
2348 398 : ScDPMembers::~ScDPMembers()
2349 : {
2350 398 : }
2351 :
2352 : // XNameAccess implementation using getCount/getByIndex
2353 :
2354 1365 : sal_Int32 ScDPMembers::GetIndexFromName( const OUString& rName ) const
2355 : {
2356 1365 : if ( aHashMap.empty() )
2357 : {
2358 : // store the index for each name
2359 :
2360 99 : sal_Int32 nCount = getCount();
2361 519 : for (sal_Int32 i=0; i<nCount; i++)
2362 420 : aHashMap[ getByIndex(i)->getName() ] = i;
2363 : }
2364 :
2365 1365 : ScDPMembersHashMap::const_iterator aIter = aHashMap.find( rName );
2366 1365 : if ( aIter != aHashMap.end() )
2367 1354 : return aIter->second; // found index
2368 : else
2369 11 : return -1; // not found
2370 : }
2371 :
2372 586 : uno::Any SAL_CALL ScDPMembers::getByName( const OUString& aName )
2373 : throw(container::NoSuchElementException,
2374 : lang::WrappedTargetException, uno::RuntimeException, std::exception)
2375 : {
2376 586 : sal_Int32 nIndex = GetIndexFromName( aName );
2377 586 : if ( nIndex >= 0 )
2378 : {
2379 586 : uno::Reference<container::XNamed> xNamed = getByIndex(nIndex);
2380 1172 : uno::Any aRet;
2381 586 : aRet <<= xNamed;
2382 1758 : return aRet;
2383 : }
2384 :
2385 0 : throw container::NoSuchElementException();
2386 : }
2387 :
2388 124 : uno::Sequence<OUString> SAL_CALL ScDPMembers::getElementNames() throw(uno::RuntimeException, std::exception)
2389 : {
2390 : // Return list of names in sorted order,
2391 : // so it's displayed in that order in the field options dialog.
2392 : // Sorting is done at the level object (parent of this).
2393 :
2394 : ScDPLevel* pLevel = pSource->GetDimensionsObject()->getByIndex(nDim)->
2395 124 : GetHierarchiesObject()->getByIndex(nHier)->GetLevelsObject()->getByIndex(nLev);
2396 124 : pLevel->EvaluateSortOrder();
2397 124 : const std::vector<sal_Int32>& rGlobalOrder = pLevel->GetGlobalOrder();
2398 124 : bool bSort = !rGlobalOrder.empty();
2399 :
2400 124 : long nCount = getCount();
2401 124 : uno::Sequence<OUString> aSeq(nCount);
2402 124 : OUString* pArr = aSeq.getArray();
2403 658 : for (long i=0; i<nCount; i++)
2404 534 : pArr[i] = getByIndex(bSort ? rGlobalOrder[i] : i)->getName();
2405 124 : return aSeq;
2406 : }
2407 :
2408 319 : sal_Bool SAL_CALL ScDPMembers::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
2409 : {
2410 319 : return ( GetIndexFromName( aName ) >= 0 );
2411 : }
2412 :
2413 0 : uno::Type SAL_CALL ScDPMembers::getElementType() throw(uno::RuntimeException, std::exception)
2414 : {
2415 0 : return cppu::UnoType<container::XNamed>::get();
2416 : }
2417 :
2418 0 : sal_Bool SAL_CALL ScDPMembers::hasElements() throw(uno::RuntimeException, std::exception)
2419 : {
2420 0 : return ( getCount() > 0 );
2421 : }
2422 :
2423 : // end of XNameAccess implementation
2424 :
2425 115 : long ScDPMembers::getMinMembers() const
2426 : {
2427 : // used in lcl_CountMinMembers
2428 :
2429 115 : long nVisCount = 0;
2430 115 : if (!maMembers.empty())
2431 : {
2432 113 : MembersType::const_iterator it = maMembers.begin(), itEnd = maMembers.end();
2433 648 : for (; it != itEnd; ++it)
2434 : {
2435 : // count only visible with details (default is true for both)
2436 535 : const rtl::Reference<ScDPMember>& pMbr = *it;
2437 535 : if (!pMbr.get() || (pMbr->isVisible() && pMbr->getShowDetails()))
2438 535 : ++nVisCount;
2439 : }
2440 : }
2441 : else
2442 2 : nVisCount = nMbrCount; // default for all
2443 :
2444 115 : return nVisCount;
2445 : }
2446 :
2447 7042 : ScDPMember* ScDPMembers::getByIndex(long nIndex) const
2448 : {
2449 : // result of GetColumnEntries must not change between ScDPMembers ctor
2450 : // and all calls to getByIndex
2451 :
2452 7042 : if ( nIndex >= 0 && nIndex < nMbrCount )
2453 : {
2454 7042 : if (maMembers.empty())
2455 205 : maMembers.resize(nMbrCount);
2456 :
2457 7042 : if (!maMembers[nIndex].get())
2458 : {
2459 882 : rtl::Reference<ScDPMember> pNew;
2460 882 : long nSrcDim = pSource->GetSourceDim( nDim );
2461 882 : if ( pSource->IsDataLayoutDimension(nSrcDim) )
2462 : {
2463 : // empty name (never shown, not used for lookup)
2464 18 : pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, 0));
2465 : }
2466 864 : else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2467 : {
2468 0 : sal_Int32 nGroupBy = 0;
2469 0 : sal_Int32 nVal = 0;
2470 0 : OUString aName;
2471 :
2472 0 : if ( nLev == SC_DAPI_LEVEL_YEAR ) // YEAR is in both hierarchies
2473 : {
2474 : //TODO: cache year range here!
2475 :
2476 0 : double fFirstVal = pSource->GetData()->GetMemberByIndex( nSrcDim, 0 )->GetValue();
2477 : long nFirstYear = pSource->GetData()->GetDatePart(
2478 0 : (long)::rtl::math::approxFloor( fFirstVal ),
2479 0 : nHier, nLev );
2480 :
2481 0 : nVal = nFirstYear + nIndex;
2482 : }
2483 0 : else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY )
2484 : {
2485 0 : nVal = nIndex; // DayOfWeek is 0-based
2486 0 : aName = ScGlobal::GetCalendar()->getDisplayName(
2487 : ::com::sun::star::i18n::CalendarDisplayIndex::DAY,
2488 0 : sal::static_int_cast<sal_Int16>(nVal), 0 );
2489 : }
2490 0 : else if ( nHier == SC_DAPI_HIERARCHY_QUARTER && nLev == SC_DAPI_LEVEL_MONTH )
2491 : {
2492 0 : nVal = nIndex; // Month is 0-based
2493 0 : aName = ScGlobal::GetCalendar()->getDisplayName(
2494 : ::com::sun::star::i18n::CalendarDisplayIndex::MONTH,
2495 0 : sal::static_int_cast<sal_Int16>(nVal), 0 );
2496 : }
2497 : else
2498 0 : nVal = nIndex + 1; // Quarter, Day, Week are 1-based
2499 :
2500 0 : switch (nLev)
2501 : {
2502 : case SC_DAPI_LEVEL_YEAR:
2503 0 : nGroupBy = sheet::DataPilotFieldGroupBy::YEARS;
2504 0 : break;
2505 : case SC_DAPI_LEVEL_QUARTER:
2506 : case SC_DAPI_LEVEL_WEEK:
2507 0 : nGroupBy = sheet::DataPilotFieldGroupBy::QUARTERS;
2508 0 : break;
2509 : case SC_DAPI_LEVEL_MONTH:
2510 : case SC_DAPI_LEVEL_WEEKDAY:
2511 0 : nGroupBy = sheet::DataPilotFieldGroupBy::MONTHS;
2512 0 : break;
2513 : case SC_DAPI_LEVEL_DAY:
2514 0 : nGroupBy = sheet::DataPilotFieldGroupBy::DAYS;
2515 0 : break;
2516 : default:
2517 : ;
2518 : }
2519 0 : if (aName.isEmpty())
2520 0 : aName = OUString::number(nVal);
2521 :
2522 0 : ScDPItemData aData(nGroupBy, nVal);
2523 0 : SCROW nId = pSource->GetCache()->GetIdByItemData(nDim, aData);
2524 0 : pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, nId));
2525 : }
2526 : else
2527 : {
2528 864 : const std::vector<SCROW>& memberIndexs = pSource->GetData()->GetColumnEntries(nSrcDim);
2529 864 : pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, memberIndexs[nIndex]));
2530 : }
2531 882 : maMembers[nIndex] = pNew;
2532 : }
2533 :
2534 7042 : return maMembers[nIndex].get();
2535 : }
2536 :
2537 0 : return NULL; //TODO: exception?
2538 : }
2539 :
2540 882 : ScDPMember::ScDPMember(
2541 : ScDPSource* pSrc, long nD, long nH, long nL, SCROW nIndex) :
2542 : pSource( pSrc ),
2543 : nDim( nD ),
2544 : nHier( nH ),
2545 : nLev( nL ),
2546 : mnDataId( nIndex ),
2547 : mpLayoutName(NULL),
2548 : nPosition( -1 ),
2549 : bVisible( true ),
2550 882 : bShowDet( true )
2551 : {
2552 : //TODO: hold pSource
2553 882 : }
2554 :
2555 1720 : ScDPMember::~ScDPMember()
2556 : {
2557 : //TODO: release pSource
2558 1720 : }
2559 :
2560 3705 : bool ScDPMember::IsNamedItem(SCROW nIndex) const
2561 : {
2562 3705 : long nSrcDim = pSource->GetSourceDim( nDim );
2563 3705 : if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2564 : {
2565 0 : const ScDPItemData* pData = pSource->GetCache()->GetItemDataById(nDim, nIndex);
2566 0 : if (pData->IsValue())
2567 : {
2568 : long nComp = pSource->GetData()->GetDatePart(
2569 0 : (long)::rtl::math::approxFloor( pData->GetValue() ),
2570 0 : nHier, nLev );
2571 : // fValue is converted from integer, so simple comparison works
2572 0 : const ScDPItemData* pData2 = GetItemData();
2573 0 : return pData2 && nComp == pData2->GetValue();
2574 : }
2575 : }
2576 :
2577 3705 : return nIndex == mnDataId;
2578 : }
2579 :
2580 1801 : sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const
2581 : {
2582 1801 : if ( nPosition >= 0 )
2583 : {
2584 181 : if ( rOther.nPosition >= 0 )
2585 : {
2586 : OSL_ENSURE( nPosition != rOther.nPosition, "same position for two members" );
2587 180 : return ( nPosition < rOther.nPosition ) ? -1 : 1;
2588 : }
2589 : else
2590 : {
2591 : // only this has a position - members with specified positions come before those without
2592 1 : return -1;
2593 : }
2594 : }
2595 1620 : else if ( rOther.nPosition >= 0 )
2596 : {
2597 : // only rOther has a position
2598 3 : return 1;
2599 : }
2600 :
2601 : // no positions set - compare names
2602 1617 : return pSource->GetData()->Compare( pSource->GetSourceDim(nDim),mnDataId,rOther.GetItemDataId());
2603 : }
2604 :
2605 8031 : void ScDPMember::FillItemData( ScDPItemData& rData ) const
2606 : {
2607 : //TODO: handle date hierarchy...
2608 :
2609 8031 : const ScDPItemData* pData = GetItemData();
2610 8031 : rData = (pData ? *pData : ScDPItemData());
2611 8031 : }
2612 :
2613 590 : const OUString* ScDPMember::GetLayoutName() const
2614 : {
2615 590 : return mpLayoutName.get();
2616 : }
2617 :
2618 1033 : OUString ScDPMember::GetNameStr() const
2619 : {
2620 1033 : const ScDPItemData* pData = GetItemData();
2621 1033 : if (pData)
2622 1033 : return pSource->GetData()->GetFormattedString(nDim, *pData);
2623 0 : return OUString();
2624 : }
2625 :
2626 1021 : OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException, std::exception)
2627 : {
2628 1021 : return GetNameStr();
2629 : }
2630 :
2631 0 : void SAL_CALL ScDPMember::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException, std::exception)
2632 : {
2633 : OSL_FAIL("not implemented"); //TODO: exception?
2634 0 : }
2635 :
2636 : // XPropertySet
2637 :
2638 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo()
2639 : throw(uno::RuntimeException, std::exception)
2640 : {
2641 0 : SolarMutexGuard aGuard;
2642 :
2643 : static const SfxItemPropertyMapEntry aDPMemberMap_Impl[] =
2644 : {
2645 0 : { OUString(SC_UNO_DP_ISVISIBLE), 0, cppu::UnoType<bool>::get(), 0, 0 },
2646 0 : { OUString(SC_UNO_DP_POSITION), 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
2647 0 : { OUString(SC_UNO_DP_SHOWDETAILS), 0, cppu::UnoType<bool>::get(), 0, 0 },
2648 0 : { OUString(SC_UNO_DP_LAYOUTNAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
2649 : { OUString(), 0, css::uno::Type(), 0, 0 }
2650 0 : };
2651 : static uno::Reference<beans::XPropertySetInfo> aRef =
2652 0 : new SfxItemPropertySetInfo( aDPMemberMap_Impl );
2653 0 : return aRef;
2654 : }
2655 :
2656 630 : void SAL_CALL ScDPMember::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
2657 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
2658 : lang::IllegalArgumentException, lang::WrappedTargetException,
2659 : uno::RuntimeException, std::exception)
2660 : {
2661 630 : if ( aPropertyName == SC_UNO_DP_ISVISIBLE )
2662 297 : bVisible = lcl_GetBoolFromAny(aValue);
2663 333 : else if ( aPropertyName == SC_UNO_DP_SHOWDETAILS )
2664 256 : bShowDet = lcl_GetBoolFromAny(aValue);
2665 77 : else if ( aPropertyName == SC_UNO_DP_POSITION )
2666 77 : aValue >>= nPosition;
2667 0 : else if (aPropertyName == SC_UNO_DP_LAYOUTNAME)
2668 : {
2669 0 : OUString aName;
2670 0 : if (aValue >>= aName)
2671 0 : mpLayoutName.reset(new OUString(aName));
2672 : }
2673 : else
2674 : {
2675 : OSL_FAIL("unknown property");
2676 : }
2677 630 : }
2678 :
2679 320 : uno::Any SAL_CALL ScDPMember::getPropertyValue( const OUString& aPropertyName )
2680 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
2681 : uno::RuntimeException, std::exception)
2682 : {
2683 320 : uno::Any aRet;
2684 320 : if ( aPropertyName == SC_UNO_DP_ISVISIBLE )
2685 144 : lcl_SetBoolInAny(aRet, bVisible);
2686 176 : else if ( aPropertyName == SC_UNO_DP_SHOWDETAILS )
2687 33 : lcl_SetBoolInAny(aRet, bShowDet);
2688 143 : else if ( aPropertyName == SC_UNO_DP_POSITION )
2689 0 : aRet <<= nPosition;
2690 143 : else if (aPropertyName == SC_UNO_DP_LAYOUTNAME)
2691 143 : aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString();
2692 : else
2693 : {
2694 : OSL_FAIL("unknown property");
2695 : }
2696 320 : return aRet;
2697 : }
2698 :
2699 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember )
2700 :
2701 0 : const ScDPCache* ScDPSource::GetCache()
2702 : {
2703 : OSL_ENSURE( GetData() , "empty ScDPTableData pointer");
2704 0 : return ( GetData()!=NULL ) ? &GetData()->GetCacheTable().getCache() : NULL ;
2705 : }
2706 :
2707 9064 : const ScDPItemData* ScDPMember::GetItemData() const
2708 : {
2709 9064 : const ScDPItemData* pData = pSource->GetItemDataById(nDim, mnDataId);
2710 : SAL_WARN_IF( !pData, "sc", "ScDPMember::GetItemData: what data? nDim " << nDim << ", mnDataId " << mnDataId);
2711 9064 : return pData;
2712 : }
2713 :
2714 9131 : const ScDPItemData* ScDPSource::GetItemDataById(long nDim, long nId)
2715 : {
2716 9131 : return GetData()->GetMemberById(nDim, nId);
2717 : }
2718 :
2719 0 : SCROW ScDPSource::GetMemberId(long nDim, const ScDPItemData& rData)
2720 : {
2721 0 : return GetCache()->GetIdByItemData(nDim, rData);
2722 : }
2723 :
2724 0 : const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex(SCROW nIndex)
2725 : {
2726 0 : const std::vector< SCROW >& memberIds = pSource->GetData()->GetColumnEntries( nDim );
2727 0 : if ( nIndex >= (long )(memberIds.size()) || nIndex < 0 )
2728 0 : return NULL;
2729 0 : SCROW nId = memberIds[ nIndex ];
2730 0 : return pSource->GetItemDataById( nDim, nId );
2731 : }
2732 :
2733 0 : SCROW ScDPMembers::GetSrcItemsCount()
2734 : {
2735 0 : return pSource->GetData()->GetColumnEntries(nDim).size();
2736 156 : }
2737 :
2738 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|