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