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