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