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