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