update ooo310-m15
[ooovba.git] / sc / source / core / data / dptabsrc.cxx
bloba00c2068c34f491b48e252010ca5143564ce7e59
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dptabsrc.cxx,v $
10 * $Revision: 1.27 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
37 // INCLUDE ---------------------------------------------------------------
39 #include <algorithm>
40 #include <vector>
41 #include <set>
42 #include <hash_map>
43 #include <hash_set>
45 #include <tools/debug.hxx>
46 #include <rtl/math.hxx>
47 #include <svtools/itemprop.hxx>
48 #include <svtools/intitem.hxx>
50 #include "scitems.hxx"
51 #include "document.hxx"
52 #include "docpool.hxx"
53 #include "patattr.hxx"
54 #include "cell.hxx"
56 #include "dptabsrc.hxx"
57 #include "dptabres.hxx"
58 #include "dptabdat.hxx"
59 #include "global.hxx"
60 #include "collect.hxx"
61 #include "datauno.hxx" // ScDataUnoConversion
62 #include "unoguard.hxx"
63 #include "miscuno.hxx"
64 #include "unonames.hxx"
66 #include <com/sun/star/beans/PropertyAttribute.hpp>
67 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
68 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
69 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
70 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
71 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
72 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
73 #include <com/sun/star/table/CellAddress.hpp>
75 #include <unotools/collatorwrapper.hxx>
76 #include <unotools/calendarwrapper.hxx>
77 #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
79 using namespace com::sun::star;
80 using ::std::vector;
81 using ::std::set;
82 using ::std::hash_map;
83 using ::std::hash_set;
84 using ::com::sun::star::uno::Reference;
85 using ::com::sun::star::uno::Sequence;
86 using ::com::sun::star::uno::Any;
87 using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
88 using ::rtl::OUString;
90 // -----------------------------------------------------------------------
92 #define SC_MINCOUNT_LIMIT 1000000
94 // -----------------------------------------------------------------------
96 SC_SIMPLE_SERVICE_INFO( ScDPSource, "ScDPSource", "com.sun.star.sheet.DataPilotSource" )
97 SC_SIMPLE_SERVICE_INFO( ScDPDimensions, "ScDPDimensions", "com.sun.star.sheet.DataPilotSourceDimensions" )
98 SC_SIMPLE_SERVICE_INFO( ScDPDimension, "ScDPDimension", "com.sun.star.sheet.DataPilotSourceDimension" )
99 SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
100 SC_SIMPLE_SERVICE_INFO( ScDPHierarchy, "ScDPHierarchy", "com.sun.star.sheet.DataPilotSourceHierarcy" )
101 SC_SIMPLE_SERVICE_INFO( ScDPLevels, "ScDPLevels", "com.sun.star.sheet.DataPilotSourceLevels" )
102 SC_SIMPLE_SERVICE_INFO( ScDPLevel, "ScDPLevel", "com.sun.star.sheet.DataPilotSourceLevel" )
103 SC_SIMPLE_SERVICE_INFO( ScDPMembers, "ScDPMembers", "com.sun.star.sheet.DataPilotSourceMembers" )
104 SC_SIMPLE_SERVICE_INFO( ScDPMember, "ScDPMember", "com.sun.star.sheet.DataPilotSourceMember" )
106 // -----------------------------------------------------------------------
108 // property maps for PropertySetInfo
109 // DataDescription / NumberFormat are internal
111 // -----------------------------------------------------------------------
113 //! move to a header?
114 BOOL lcl_GetBoolFromAny( const uno::Any& aAny )
116 if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
117 return *(sal_Bool*)aAny.getValue();
118 return FALSE;
121 void lcl_SetBoolInAny( uno::Any& rAny, BOOL bValue )
123 rAny.setValue( &bValue, getBooleanCppuType() );
126 // -----------------------------------------------------------------------
128 ScDPSource::ScDPSource( ScDPTableData* pD ) :
129 pData( pD ),
130 pDimensions( NULL ),
131 nColDimCount( 0 ),
132 nRowDimCount( 0 ),
133 nDataDimCount( 0 ),
134 nPageDimCount( 0 ),
135 bColumnGrand( TRUE ), // default is true
136 bRowGrand( TRUE ),
137 bIgnoreEmptyRows( FALSE ),
138 bRepeatIfEmpty( FALSE ),
139 nDupCount( 0 ),
140 pResData( NULL ),
141 pColResRoot( NULL ),
142 pRowResRoot( NULL ),
143 pColResults( NULL ),
144 pRowResults( NULL ),
145 bResultOverflow( FALSE ),
146 mpGrandTotalName(NULL)
148 pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
151 ScDPSource::~ScDPSource()
153 if (pDimensions)
154 pDimensions->release(); // ref-counted
156 //! free lists
158 delete[] pColResults;
159 delete[] pRowResults;
161 delete pColResRoot;
162 delete pRowResRoot;
163 delete pResData;
166 void ScDPSource::SetGrandTotalName(const ::rtl::OUString& rName)
168 mpGrandTotalName.reset(new ::rtl::OUString(rName));
171 const ::rtl::OUString* ScDPSource::GetGrandTotalName() const
173 return mpGrandTotalName.get();
176 USHORT ScDPSource::GetOrientation(long nColumn)
178 long i;
179 for (i=0; i<nColDimCount; i++)
180 if (nColDims[i] == nColumn)
181 return sheet::DataPilotFieldOrientation_COLUMN;
182 for (i=0; i<nRowDimCount; i++)
183 if (nRowDims[i] == nColumn)
184 return sheet::DataPilotFieldOrientation_ROW;
185 for (i=0; i<nDataDimCount; i++)
186 if (nDataDims[i] == nColumn)
187 return sheet::DataPilotFieldOrientation_DATA;
188 for (i=0; i<nPageDimCount; i++)
189 if (nPageDims[i] == nColumn)
190 return sheet::DataPilotFieldOrientation_PAGE;
191 return sheet::DataPilotFieldOrientation_HIDDEN;
194 long ScDPSource::GetDataDimensionCount()
196 return nDataDimCount;
199 ScDPDimension* ScDPSource::GetDataDimension(long nIndex)
201 if (nIndex < 0 || nIndex >= nDataDimCount)
202 return NULL;
204 long nDimIndex = nDataDims[nIndex];
205 return GetDimensionsObject()->getByIndex(nDimIndex);
208 String ScDPSource::GetDataDimName( long nIndex )
210 String aRet;
211 ScDPDimension* pDim = GetDataDimension(nIndex);
212 if (pDim)
213 aRet = String(pDim->getName());
214 return aRet;
217 long ScDPSource::GetPosition(long nColumn)
219 long i;
220 for (i=0; i<nColDimCount; i++)
221 if (nColDims[i] == nColumn)
222 return i;
223 for (i=0; i<nRowDimCount; i++)
224 if (nRowDims[i] == nColumn)
225 return i;
226 for (i=0; i<nDataDimCount; i++)
227 if (nDataDims[i] == nColumn)
228 return i;
229 for (i=0; i<nPageDimCount; i++)
230 if (nPageDims[i] == nColumn)
231 return i;
232 return 0;
235 BOOL lcl_TestSubTotal( BOOL& rAllowed, long nColumn, long* pArray, long nCount, ScDPSource* pSource )
237 for (long i=0; i<nCount; i++)
238 if (pArray[i] == nColumn)
240 // no subtotals for data layout dim, no matter where
241 if ( pSource->IsDataLayoutDimension(nColumn) )
242 rAllowed = FALSE;
243 else
245 // no subtotals if no other dim but data layout follows
246 long nNextIndex = i+1;
247 if ( nNextIndex < nCount && pSource->IsDataLayoutDimension(pArray[nNextIndex]) )
248 ++nNextIndex;
249 if ( nNextIndex >= nCount )
250 rAllowed = FALSE;
253 return TRUE; // found
255 return FALSE;
258 BOOL ScDPSource::SubTotalAllowed(long nColumn)
260 //! cache this at ScDPResultData
261 BOOL bAllowed = TRUE;
262 if ( lcl_TestSubTotal( bAllowed, nColumn, nColDims, nColDimCount, this ) )
263 return bAllowed;
264 if ( lcl_TestSubTotal( bAllowed, nColumn, nRowDims, nRowDimCount, this ) )
265 return bAllowed;
266 return bAllowed;
269 void lcl_RemoveDim( long nRemove, long* pDims, long& rCount )
271 for (long i=0; i<rCount; i++)
272 if ( pDims[i] == nRemove )
274 for (long j=i; j+1<rCount; j++)
275 pDims[j] = pDims[j+1];
276 --rCount;
277 return;
281 void ScDPSource::SetOrientation(long nColumn, USHORT nNew)
283 //! change to no-op if new orientation is equal to old?
285 // remove from old list
286 lcl_RemoveDim( nColumn, nColDims, nColDimCount );
287 lcl_RemoveDim( nColumn, nRowDims, nRowDimCount );
288 lcl_RemoveDim( nColumn, nDataDims, nDataDimCount );
289 lcl_RemoveDim( nColumn, nPageDims, nPageDimCount );
291 // add to new list
292 switch (nNew)
294 case sheet::DataPilotFieldOrientation_COLUMN:
295 nColDims[nColDimCount++] = nColumn;
296 break;
297 case sheet::DataPilotFieldOrientation_ROW:
298 nRowDims[nRowDimCount++] = nColumn;
299 break;
300 case sheet::DataPilotFieldOrientation_DATA:
301 nDataDims[nDataDimCount++] = nColumn;
302 break;
303 case sheet::DataPilotFieldOrientation_PAGE:
304 nPageDims[nPageDimCount++] = nColumn;
305 break;
306 default:
307 DBG_ERROR( "ScDPSource::SetOrientation: unexpected orientation" );
308 break;
312 BOOL ScDPSource::IsDataLayoutDimension(long nDim)
314 return nDim == pData->GetColumnCount();
317 USHORT ScDPSource::GetDataLayoutOrientation()
319 return GetOrientation(pData->GetColumnCount());
322 BOOL ScDPSource::IsDateDimension(long nDim)
324 return pData->IsDateDimension(nDim);
327 ScDPDimensions* ScDPSource::GetDimensionsObject()
329 if (!pDimensions)
331 pDimensions = new ScDPDimensions(this);
332 pDimensions->acquire(); // ref-counted
334 return pDimensions;
337 uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException)
339 return GetDimensionsObject();
342 void ScDPSource::SetDupCount( long nNew )
344 nDupCount = nNew;
347 ScDPDimension* ScDPSource::AddDuplicated(long /* nSource */, const String& rNewName)
349 DBG_ASSERT( pDimensions, "AddDuplicated without dimensions?" );
351 // re-use
353 long nOldDimCount = pDimensions->getCount();
354 for (long i=0; i<nOldDimCount; i++)
356 ScDPDimension* pDim = pDimensions->getByIndex(i);
357 if (pDim && String(pDim->getName()) == rNewName)
359 //! test if pDim is a duplicate of source
360 return pDim;
364 SetDupCount( nDupCount + 1 );
365 pDimensions->CountChanged(); // uses nDupCount
367 return pDimensions->getByIndex( pDimensions->getCount() - 1 );
370 long ScDPSource::GetSourceDim(long nDim)
372 // original source dimension or data layout dimension?
373 if ( nDim <= pData->GetColumnCount() )
374 return nDim;
376 if ( nDim < pDimensions->getCount() )
378 ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
379 if ( pDimObj )
381 long nSource = pDimObj->GetSourceDim();
382 if ( nSource >= 0 )
383 return nSource;
387 DBG_ERROR("GetSourceDim: wrong dim");
388 return nDim;
391 uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
392 throw(uno::RuntimeException)
394 CreateRes_Impl(); // create pColResRoot and pRowResRoot
396 if ( bResultOverflow ) // set in CreateRes_Impl
398 // no results available
399 throw uno::RuntimeException();
402 long nColCount = pColResRoot->GetSize(pResData->GetColStartMeasure());
403 long nRowCount = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
405 // allocate full sequence
406 //! leave out empty rows???
408 uno::Sequence< uno::Sequence<sheet::DataResult> > aSeq( nRowCount );
409 uno::Sequence<sheet::DataResult>* pRowAry = aSeq.getArray();
410 for (long nRow = 0; nRow < nRowCount; nRow++)
412 uno::Sequence<sheet::DataResult> aColSeq( nColCount );
413 // use default values of DataResult
414 pRowAry[nRow] = aColSeq;
417 long nSeqRow = 0;
418 pRowResRoot->FillDataResults( pColResRoot, aSeq, nSeqRow, pResData->GetRowStartMeasure() );
420 return aSeq;
423 void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException)
425 disposeData();
428 void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& )
429 throw(uno::RuntimeException)
431 DBG_ERROR("not implemented"); //! exception?
434 void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& )
435 throw(uno::RuntimeException)
437 DBG_ERROR("not implemented"); //! exception?
440 Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters)
441 throw (uno::RuntimeException)
443 long nColumnCount = GetData()->GetColumnCount();
444 ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
446 typedef hash_map<String, long, ScStringHashCode> FieldNameMapType;
447 FieldNameMapType aFieldNames;
448 for (long i = 0; i < nColumnCount; ++i)
450 aFieldNames.insert(
451 FieldNameMapType::value_type(GetData()->getDimensionName(i), i));
454 // collect ScDPItemData for each filtered column
455 vector<ScDPCacheTable::Criterion> aFilterCriteria;
456 sal_Int32 nFilterCount = aFilters.getLength();
457 for (sal_Int32 i = 0; i < nFilterCount; ++i)
459 const sheet::DataPilotFieldFilter& rFilter = aFilters[i];
460 String aFieldName( rFilter.FieldName );
461 for (long nCol = 0; nCol < nColumnCount; ++nCol)
463 if ( aFieldName == pData->getDimensionName(nCol) )
465 ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
466 ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
467 GetLevelsObject()->getByIndex(0)->GetMembersObject();
468 sal_Int32 nIndex = pMembers->GetIndexFromName( rFilter.MatchValue );
469 if ( nIndex >= 0 )
471 ScDPItemData aItem;
472 pMembers->getByIndex(nIndex)->FillItemData( aItem );
473 aFilterCriteria.push_back( ScDPCacheTable::Criterion() );
474 sal_Int32 nMatchStrId = rSharedString.getStringId(aItem.aString);
475 aFilterCriteria.back().mnFieldIndex = nCol;
476 aFilterCriteria.back().mpFilter.reset(
477 new ScDPCacheTable::SingleFilter(rSharedString, nMatchStrId, aItem.fValue, aItem.bHasValue) );
483 // Take into account the visibilities of field members.
484 ScDPResultVisibilityData aResVisData(rSharedString, this);
485 pRowResRoot->FillVisibilityData(aResVisData);
486 pColResRoot->FillVisibilityData(aResVisData);
487 aResVisData.fillFieldFilters(aFilterCriteria);
489 Sequence< Sequence<Any> > aTabData;
490 hash_set<sal_Int32> aCatDims;
491 GetCategoryDimensionIndices(aCatDims);
492 pData->GetDrillDownData(aFilterCriteria, aCatDims, aTabData);
493 return aTabData;
496 String ScDPSource::getDataDescription()
498 CreateRes_Impl(); // create pResData
500 String aRet;
501 if ( pResData->GetMeasureCount() == 1 )
503 bool bTotalResult = false;
504 aRet = pResData->GetMeasureString( 0, TRUE, SUBTOTAL_FUNC_NONE, bTotalResult );
507 // empty for more than one measure
509 return aRet;
512 BOOL ScDPSource::getColumnGrand() const
514 return bColumnGrand;
517 void ScDPSource::setColumnGrand(BOOL bSet)
519 bColumnGrand = bSet;
522 BOOL ScDPSource::getRowGrand() const
524 return bRowGrand;
527 void ScDPSource::setRowGrand(BOOL bSet)
529 bRowGrand = bSet;
532 BOOL ScDPSource::getIgnoreEmptyRows() const
534 return bIgnoreEmptyRows;
537 void ScDPSource::setIgnoreEmptyRows(BOOL bSet)
539 bIgnoreEmptyRows = bSet;
540 pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
543 BOOL ScDPSource::getRepeatIfEmpty() const
545 return bRepeatIfEmpty;
548 void ScDPSource::setRepeatIfEmpty(BOOL bSet)
550 bRepeatIfEmpty = bSet;
551 pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
554 void ScDPSource::validate() //! ???
556 CreateRes_Impl();
559 void ScDPSource::disposeData()
561 if ( pResData )
563 // reset all data...
565 DELETEZ(pColResRoot);
566 DELETEZ(pRowResRoot);
567 DELETEZ(pResData);
568 delete[] pColResults;
569 delete[] pRowResults;
570 pColResults = NULL;
571 pRowResults = NULL;
572 aColLevelList.Clear();
573 aRowLevelList.Clear();
576 if ( pDimensions )
578 pDimensions->release(); // ref-counted
579 pDimensions = NULL; // settings have to be applied (from SaveData) again!
581 SetDupCount( 0 );
583 //! Test ????
584 nColDimCount = nRowDimCount = nDataDimCount = nPageDimCount = 0;
586 pData->DisposeData(); // cached entries etc.
587 bResultOverflow = FALSE;
590 long lcl_CountMinMembers(const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLevel, long nLevels )
592 // Calculate the product of the member count for those consecutive levels that
593 // have the "show all" flag, one following level, and the data layout dimension.
595 long nTotal = 1;
596 long nDataCount = 1;
597 BOOL bWasShowAll = TRUE;
598 long nPos = nLevels;
599 while ( nPos > 0 )
601 --nPos;
603 if ( nPos+1 < nLevels && ppDim[nPos] == ppDim[nPos+1] )
605 DBG_ERROR("lcl_CountMinMembers: multiple levels from one dimension not implemented");
606 return 0;
609 BOOL bDo = FALSE;
610 if ( ppDim[nPos]->getIsDataLayoutDimension() )
612 // data layout dim doesn't interfere with "show all" flags
613 nDataCount = ppLevel[nPos]->GetMembersObject()->getCount();
614 if ( nDataCount == 0 )
615 nDataCount = 1;
617 else if ( bWasShowAll ) // "show all" set for all following levels?
619 bDo = TRUE;
620 if ( !ppLevel[nPos]->getShowEmpty() )
622 // this level is counted, following ones are not
623 bWasShowAll = FALSE;
626 if ( bDo )
628 long nThisCount = ppLevel[nPos]->GetMembersObject()->getMinMembers();
629 if ( nThisCount == 0 )
631 nTotal = 1; // empty level -> start counting from here
632 //! start with visible elements in this level?
634 else
636 if ( nTotal >= LONG_MAX / nThisCount )
637 return LONG_MAX; // overflow
638 nTotal *= nThisCount;
643 // always include data layout dim, even after restarting
644 if ( nTotal >= LONG_MAX / nDataCount )
645 return LONG_MAX; // overflow
646 nTotal *= nDataCount;
648 return nTotal;
651 long lcl_GetIndexFromName( const rtl::OUString rName, const uno::Sequence<rtl::OUString>& rElements )
653 long nCount = rElements.getLength();
654 const rtl::OUString* pArray = rElements.getConstArray();
655 for (long nPos=0; nPos<nCount; nPos++)
656 if (pArray[nPos] == rName)
657 return nPos;
659 return -1; // not found
662 void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &rHasAutoShow)
664 long* nDims = bIsRow ? nRowDims : nColDims;
665 long nDimCount = bIsRow ? nRowDimCount : nColDimCount;
667 for (long i = 0; i < nDimCount; ++i)
669 ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nDims[i] );
670 long nHierarchy = pDim->getUsedHierarchy();
671 if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
672 nHierarchy = 0;
673 ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
674 long nCount = pLevels->getCount();
676 //! Test
677 if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
678 nCount = 0;
679 //! Test
681 for (long j = 0; j < nCount; ++j)
683 ScDPLevel* pLevel = pLevels->getByIndex(j);
684 pLevel->EvaluateSortOrder();
686 // no layout flags for column fields, only for row fields
687 pLevel->SetEnableLayout( bIsRow );
689 if ( pLevel->GetAutoShow().IsEnabled )
690 rHasAutoShow = TRUE;
692 if (bIsRow)
694 rInfo.aRowLevelDims.push_back(nDims[i]);
695 rInfo.aRowDims.push_back(pDim);
696 rInfo.aRowLevels.push_back(pLevel);
698 else
700 rInfo.aColLevelDims.push_back(nDims[i]);
701 rInfo.aColDims.push_back(pDim);
702 rInfo.aColLevels.push_back(pLevel);
705 pLevel->GetMembersObject(); // initialize for groups
710 void ScDPSource::GetCategoryDimensionIndices(hash_set<sal_Int32>& rCatDims)
712 hash_set<sal_Int32> aCatDims;
713 for (long i = 0; i < nColDimCount; ++i)
715 sal_Int32 nDim = static_cast<sal_Int32>(nColDims[i]);
716 if (!IsDataLayoutDimension(nDim))
717 aCatDims.insert(nDim);
720 for (long i = 0; i < nRowDimCount; ++i)
722 sal_Int32 nDim = static_cast<sal_Int32>(nRowDims[i]);
723 if (!IsDataLayoutDimension(nDim))
724 aCatDims.insert(nDim);
727 for (long i = 0; i < nPageDimCount; ++i)
729 sal_Int32 nDim = static_cast<sal_Int32>(nPageDims[i]);
730 if (!IsDataLayoutDimension(nDim))
731 aCatDims.insert(nDim);
734 rCatDims.swap(aCatDims);
737 void ScDPSource::FilterCacheTableByPageDimensions()
739 ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
741 // filter table by page dimensions.
742 vector<ScDPCacheTable::Criterion> aCriteria;
743 for (long i = 0; i < nPageDimCount; ++i)
745 ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nPageDims[i]);
746 long nField = pDim->GetDimension();
748 ScDPMembers* pMems = pDim->GetHierarchiesObject()->getByIndex(0)->
749 GetLevelsObject()->getByIndex(0)->GetMembersObject();
751 long nMemCount = pMems->getCount();
752 ScDPCacheTable::Criterion aFilter;
753 aFilter.mnFieldIndex = static_cast<sal_Int32>(nField);
754 aFilter.mpFilter.reset(new ScDPCacheTable::GroupFilter(rSharedString));
755 ScDPCacheTable::GroupFilter* pGrpFilter =
756 static_cast<ScDPCacheTable::GroupFilter*>(aFilter.mpFilter.get());
757 for (long j = 0; j < nMemCount; ++j)
759 ScDPMember* pMem = pMems->getByIndex(j);
760 if (pMem->getIsVisible())
762 ScDPItemData aData;
763 pMem->FillItemData(aData);
764 pGrpFilter->addMatchItem(aData.aString, aData.fValue, aData.bHasValue);
767 if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount))
768 // there is at least one invisible item. Add this filter criterion to the mix.
769 aCriteria.push_back(aFilter);
771 if (!pDim || !pDim->HasSelectedPage())
772 continue;
774 const ScDPItemData& rData = pDim->GetSelectedData();
775 aCriteria.push_back(ScDPCacheTable::Criterion());
776 ScDPCacheTable::Criterion& r = aCriteria.back();
777 r.mnFieldIndex = static_cast<sal_Int32>(nField);
778 sal_Int32 nStrId = rSharedString.getStringId(rData.aString);
779 r.mpFilter.reset(
780 new ScDPCacheTable::SingleFilter(rSharedString, nStrId, rData.fValue, rData.bHasValue));
782 if (!aCriteria.empty())
784 hash_set<sal_Int32> aCatDims;
785 GetCategoryDimensionIndices(aCatDims);
786 pData->FilterCacheTable(aCriteria, aCatDims);
790 void ScDPSource::CreateRes_Impl()
792 if ( !pResData )
794 USHORT nDataOrient = GetDataLayoutOrientation();
795 if ( nDataDimCount > 1 && ( nDataOrient != sheet::DataPilotFieldOrientation_COLUMN &&
796 nDataOrient != sheet::DataPilotFieldOrientation_ROW ) )
798 // if more than one data dimension, data layout orientation must be set
799 SetOrientation( pData->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW );
800 nDataOrient = sheet::DataPilotFieldOrientation_ROW;
803 // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and
804 // eDataFunctions into a structure and use vector instead of static
805 // or pointer arrays.
806 String* pDataNames = NULL;
807 sheet::DataPilotFieldReference* pDataRefValues = NULL;
808 ScSubTotalFunc eDataFunctions[SC_DAPI_MAXFIELDS];
809 USHORT nDataRefOrient[SC_DAPI_MAXFIELDS];
810 if (nDataDimCount)
812 pDataNames = new String[nDataDimCount];
813 pDataRefValues = new sheet::DataPilotFieldReference[nDataDimCount];
816 ScDPTableData::CalcInfo aInfo;
819 // LateInit (initialize only those rows/children that are used) can be used unless
820 // any data dimension needs reference values from column/row dimensions
821 BOOL bLateInit = TRUE;
823 // Go through all data dimensions (i.e. fields) and build their meta data
824 // so that they can be passed on to ScDPResultData instance later.
825 // TODO: aggregate all of data dimension info into a structure.
826 long i;
827 for (i=0; i<nDataDimCount; i++)
829 // Get function for each data field.
830 long nDimIndex = nDataDims[i];
831 ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
832 sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
833 if (eUser == sheet::GeneralFunction_AUTO)
835 //! test for numeric data
836 eUser = sheet::GeneralFunction_SUM;
839 // Map UNO's enum to internal enum ScSubTotalFunc.
840 eDataFunctions[i] = ScDataUnoConversion::GeneralToSubTotal( eUser );
842 // Get reference field/item information.
843 pDataRefValues[i] = pDim->GetReferenceValue();
844 nDataRefOrient[i] = sheet::DataPilotFieldOrientation_HIDDEN; // default if not used
845 sal_Int32 eRefType = pDataRefValues[i].ReferenceType;
846 if ( eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
847 eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
848 eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE ||
849 eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
851 long nColumn = lcl_GetIndexFromName( pDataRefValues[i].ReferenceField,
852 GetDimensionsObject()->getElementNames() );
853 if ( nColumn >= 0 )
855 nDataRefOrient[i] = GetOrientation( nColumn );
856 // need fully initialized results to find reference values
857 // (both in column or row dimensions), so updated values or
858 // differences to 0 can be displayed even for empty results.
859 bLateInit = FALSE;
863 pDataNames[i] = String( pDim->getName() ); //! label?
865 // asterisk is added to duplicated dimension names by ScDPSaveData::WriteToSource
866 //! modify user visible strings as in ScDPResultData::GetMeasureString instead!
868 pDataNames[i].EraseTrailingChars('*');
870 //! if the name is overridden by user, a flag must be set
871 //! so the user defined name replaces the function string and field name.
873 //! the complete name (function and field) must be stored at the dimension
875 long nSource = ((ScDPDimension*)pDim)->GetSourceDim();
876 if (nSource >= 0)
877 aInfo.aDataSrcCols.push_back(nSource);
878 else
879 aInfo.aDataSrcCols.push_back(nDimIndex);
882 pResData = new ScDPResultData( this );
883 pResData->SetMeasureData( nDataDimCount, eDataFunctions, pDataRefValues, nDataRefOrient, pDataNames );
884 pResData->SetDataLayoutOrientation(nDataOrient);
885 pResData->SetLateInit( bLateInit );
887 delete[] pDataNames;
888 delete[] pDataRefValues;
890 bool bHasAutoShow = false;
892 ScDPInitState aInitState;
894 // Page field selections restrict the members shown in related fields
895 // (both in column and row fields). aInitState is filled with the page
896 // field selections, they are kept across the data iterator loop.
898 for (i=0; i<nPageDimCount; i++)
900 ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nPageDims[i] );
901 if ( pDim->HasSelectedPage() )
902 aInitState.AddMember( nPageDims[i], pDim->GetSelectedData() );
905 pColResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bColumnGrand );
906 pRowResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bRowGrand );
908 FillCalcInfo(false, aInfo, bHasAutoShow);
909 long nColLevelCount = aInfo.aColLevels.size();
911 pColResRoot->InitFrom( aInfo.aColDims, aInfo.aColLevels, 0, aInitState );
912 pColResRoot->SetHasElements();
914 FillCalcInfo(true, aInfo, bHasAutoShow);
915 long nRowLevelCount = aInfo.aRowLevels.size();
917 if ( nRowLevelCount > 0 )
919 // disable layout flags for the innermost row field (level)
920 aInfo.aRowLevels[nRowLevelCount-1]->SetEnableLayout( FALSE );
923 pRowResRoot->InitFrom( aInfo.aRowDims, aInfo.aRowLevels, 0, aInitState );
924 pRowResRoot->SetHasElements();
926 // initialize members object also for all page dimensions (needed for numeric groups)
927 for (i=0; i<nPageDimCount; i++)
929 ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nPageDims[i] );
930 long nHierarchy = pDim->getUsedHierarchy();
931 if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
932 nHierarchy = 0;
934 ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
935 long nCount = pLevels->getCount();
936 for (long j=0; j<nCount; j++)
937 pLevels->getByIndex(j)->GetMembersObject(); // initialize for groups
940 // pre-check: calculate minimum number of result columns / rows from
941 // levels that have the "show all" flag set
943 long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount );
944 long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount );
946 if ( nMinColMembers > SC_MINCOUNT_LIMIT || nMinRowMembers > SC_MINCOUNT_LIMIT )
948 // resulting table is too big -> abort before calculating
949 // (this relies on late init, so no members are allocated in InitFrom above)
951 bResultOverflow = TRUE;
953 else
955 FilterCacheTableByPageDimensions();
957 aInfo.aPageDims.reserve(nPageDimCount);
958 for (i = 0; i < nPageDimCount; ++i)
959 aInfo.aPageDims.push_back(nPageDims[i]);
961 aInfo.pInitState = &aInitState;
962 aInfo.pColRoot = pColResRoot;
963 aInfo.pRowRoot = pRowResRoot;
964 pData->CalcResults(aInfo, false);
966 // ----------------------------------------------------------------
967 // With all data processed, calculate the final results:
969 // UpdateDataResults calculates all original results from the collected values,
970 // and stores them as reference values if needed.
971 pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
973 if ( bHasAutoShow ) // do the double calculation only if AutoShow is used
975 // Find the desired members and set bAutoHidden flag for the others
976 pRowResRoot->DoAutoShow( pColResRoot );
978 // Reset all results to empty, so they can be built again with data for the
979 // desired members only.
980 pColResRoot->ResetResults( TRUE );
981 pRowResRoot->ResetResults( TRUE );
982 pData->CalcResults(aInfo, true);
984 // Call UpdateDataResults again, with the new (limited) values.
985 pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
988 // SortMembers does the sorting by a result dimension, using the orginal results,
989 // but not running totals etc.
990 pRowResRoot->SortMembers( pColResRoot );
992 // UpdateRunningTotals calculates running totals along column/row dimensions,
993 // differences from other members (named or relative), and column/row percentages
994 // or index values.
995 // Running totals and relative differences need to be done using the sorted values.
996 // Column/row percentages and index values must be done after sorting, because the
997 // results may no longer be in the right order (row total for percentage of row is
998 // always 1).
999 ScDPRunningTotalState aRunning( pColResRoot, pRowResRoot );
1000 ScDPRowTotals aTotals;
1001 pRowResRoot->UpdateRunningTotals( pColResRoot, pResData->GetRowStartMeasure(), aRunning, aTotals );
1003 // ----------------------------------------------------------------
1008 void ScDPSource::DumpState( ScDocument* pDoc, const ScAddress& rPos )
1010 CreateRes_Impl();
1012 ScAddress aDocPos( rPos );
1014 if (pColResRoot->GetChildDimension())
1015 pColResRoot->GetChildDimension()->DumpState( NULL, pDoc, aDocPos );
1016 pRowResRoot->DumpState( pColResRoot, pDoc, aDocPos );
1019 void ScDPSource::FillLevelList( USHORT nOrientation, List& rList )
1021 rList.Clear();
1023 long nDimCount = 0;
1024 long* pDimIndex = NULL;
1025 switch (nOrientation)
1027 case sheet::DataPilotFieldOrientation_COLUMN:
1028 pDimIndex = nColDims;
1029 nDimCount = nColDimCount;
1030 break;
1031 case sheet::DataPilotFieldOrientation_ROW:
1032 pDimIndex = nRowDims;
1033 nDimCount = nRowDimCount;
1034 break;
1035 case sheet::DataPilotFieldOrientation_DATA:
1036 pDimIndex = nDataDims;
1037 nDimCount = nDataDimCount;
1038 break;
1039 case sheet::DataPilotFieldOrientation_PAGE:
1040 pDimIndex = nPageDims;
1041 nDimCount = nPageDimCount;
1042 break;
1043 default:
1044 DBG_ERROR( "ScDPSource::FillLevelList: unexpected orientation" );
1045 break;
1047 if (!pDimIndex)
1049 DBG_ERROR("invalid orientation");
1050 return;
1053 ScDPDimensions* pDims = GetDimensionsObject();
1054 for (long nDim=0; nDim<nDimCount; nDim++)
1056 ScDPDimension* pDim = pDims->getByIndex(pDimIndex[nDim]);
1057 DBG_ASSERT( pDim->getOrientation() == nOrientation, "orientations are wrong" );
1059 ScDPHierarchies* pHiers = pDim->GetHierarchiesObject();
1060 long nHierarchy = pDim->getUsedHierarchy();
1061 if ( nHierarchy >= pHiers->getCount() )
1062 nHierarchy = 0;
1063 ScDPHierarchy* pHier = pHiers->getByIndex(nHierarchy);
1064 ScDPLevels* pLevels = pHier->GetLevelsObject();
1065 long nLevCount = pLevels->getCount();
1066 for (long nLev=0; nLev<nLevCount; nLev++)
1068 ScDPLevel* pLevel = pLevels->getByIndex(nLev);
1069 rList.Insert( pLevel, LIST_APPEND );
1074 void ScDPSource::FillMemberResults()
1076 if ( !pColResults && !pRowResults )
1078 CreateRes_Impl();
1080 if ( bResultOverflow ) // set in CreateRes_Impl
1082 // no results available -> abort (leave empty)
1083 // exception is thrown in ScDPSource::getResults
1084 return;
1087 FillLevelList( sheet::DataPilotFieldOrientation_COLUMN, aColLevelList );
1088 long nColLevelCount = aColLevelList.Count();
1089 if (nColLevelCount)
1091 long nColDimSize = pColResRoot->GetSize(pResData->GetColStartMeasure());
1092 pColResults = new uno::Sequence<sheet::MemberResult>[nColLevelCount];
1093 for (long i=0; i<nColLevelCount; i++)
1094 pColResults[i].realloc(nColDimSize);
1096 // ScDPResultDimension* pColResDim = pColResRoot->GetChildDimension();
1097 // pColResDim->FillMemberResults( pColResults, 0, pResData->GetColStartMeasure() );
1098 long nPos = 0;
1099 pColResRoot->FillMemberResults( pColResults, nPos, pResData->GetColStartMeasure(),
1100 TRUE, NULL, NULL );
1103 FillLevelList( sheet::DataPilotFieldOrientation_ROW, aRowLevelList );
1104 long nRowLevelCount = aRowLevelList.Count();
1105 if (nRowLevelCount)
1107 long nRowDimSize = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
1108 pRowResults = new uno::Sequence<sheet::MemberResult>[nRowLevelCount];
1109 for (long i=0; i<nRowLevelCount; i++)
1110 pRowResults[i].realloc(nRowDimSize);
1112 // ScDPResultDimension* pRowResDim = pRowResRoot->GetChildDimension();
1113 // pRowResDim->FillMemberResults( pRowResults, 0, pResData->GetRowStartMeasure() );
1114 long nPos = 0;
1115 pRowResRoot->FillMemberResults( pRowResults, nPos, pResData->GetRowStartMeasure(),
1116 TRUE, NULL, NULL );
1121 const uno::Sequence<sheet::MemberResult>* ScDPSource::GetMemberResults( ScDPLevel* pLevel )
1123 FillMemberResults();
1125 long i;
1126 long nColCount = aColLevelList.Count();
1127 for (i=0; i<nColCount; i++)
1129 ScDPLevel* pColLevel = (ScDPLevel*)aColLevelList.GetObject(i);
1130 if ( pColLevel == pLevel )
1131 return pColResults+i;
1133 long nRowCount = aRowLevelList.Count();
1134 for (i=0; i<nRowCount; i++)
1136 ScDPLevel* pRowLevel = (ScDPLevel*)aRowLevelList.GetObject(i);
1137 if ( pRowLevel == pLevel )
1138 return pRowResults+i;
1140 return NULL;
1143 // XPropertySet
1145 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo()
1146 throw(uno::RuntimeException)
1148 ScUnoGuard aGuard;
1149 using beans::PropertyAttribute::READONLY;
1151 static SfxItemPropertyMap aDPSourceMap_Impl[] =
1153 {MAP_CHAR_LEN(SC_UNO_COLGRAND), 0, &getBooleanCppuType(), 0, 0 },
1154 {MAP_CHAR_LEN(SC_UNO_DATADESC), 0, &getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 },
1155 {MAP_CHAR_LEN(SC_UNO_IGNOREEM), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1156 {MAP_CHAR_LEN(SC_UNO_REPEATIF), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1157 {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 },
1158 {MAP_CHAR_LEN(SC_UNO_ROWFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1159 {MAP_CHAR_LEN(SC_UNO_COLUMNFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1160 {MAP_CHAR_LEN(SC_UNO_DATAFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1161 {MAP_CHAR_LEN(SC_UNO_GRANDTOTAL_NAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
1162 {0,0,0,0,0,0}
1164 static uno::Reference<beans::XPropertySetInfo> aRef =
1165 new SfxItemPropertySetInfo( aDPSourceMap_Impl );
1166 return aRef;
1169 void SAL_CALL ScDPSource::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
1170 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
1171 lang::IllegalArgumentException, lang::WrappedTargetException,
1172 uno::RuntimeException)
1174 String aNameStr = aPropertyName;
1175 if ( aNameStr.EqualsAscii( SC_UNO_COLGRAND ) )
1176 setColumnGrand( lcl_GetBoolFromAny( aValue ) );
1177 else if ( aNameStr.EqualsAscii( SC_UNO_ROWGRAND ) )
1178 setRowGrand( lcl_GetBoolFromAny( aValue ) );
1179 else if ( aNameStr.EqualsAscii( SC_UNO_IGNOREEM ) )
1180 setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
1181 else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
1182 setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
1183 else if (aNameStr.EqualsAscii(SC_UNO_GRANDTOTAL_NAME))
1185 OUString aName;
1186 if (aValue >>= aName)
1187 mpGrandTotalName.reset(new OUString(aName));
1189 else
1191 DBG_ERROR("unknown property");
1192 //! THROW( UnknownPropertyException() );
1196 uno::Any SAL_CALL ScDPSource::getPropertyValue( const rtl::OUString& aPropertyName )
1197 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
1198 uno::RuntimeException)
1200 uno::Any aRet;
1201 String aNameStr = aPropertyName;
1202 if ( aNameStr.EqualsAscii( SC_UNO_COLGRAND ) )
1203 lcl_SetBoolInAny( aRet, getColumnGrand() );
1204 else if ( aNameStr.EqualsAscii( SC_UNO_ROWGRAND ) )
1205 lcl_SetBoolInAny( aRet, getRowGrand() );
1206 else if ( aNameStr.EqualsAscii( SC_UNO_IGNOREEM ) )
1207 lcl_SetBoolInAny( aRet, getIgnoreEmptyRows() );
1208 else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
1209 lcl_SetBoolInAny( aRet, getRepeatIfEmpty() );
1210 else if ( aNameStr.EqualsAscii( SC_UNO_DATADESC ) ) // read-only
1211 aRet <<= rtl::OUString( getDataDescription() );
1212 else if ( aNameStr.EqualsAscii( SC_UNO_ROWFIELDCOUNT ) ) // read-only
1213 aRet <<= static_cast<sal_Int32>(nRowDimCount);
1214 else if ( aNameStr.EqualsAscii( SC_UNO_COLUMNFIELDCOUNT ) ) // read-only
1215 aRet <<= static_cast<sal_Int32>(nColDimCount);
1216 else if ( aNameStr.EqualsAscii( SC_UNO_DATAFIELDCOUNT ) ) // read-only
1217 aRet <<= static_cast<sal_Int32>(nDataDimCount);
1218 else if (aNameStr.EqualsAscii(SC_UNO_GRANDTOTAL_NAME))
1220 if (mpGrandTotalName.get())
1221 aRet <<= *mpGrandTotalName;
1223 else
1225 DBG_ERROR("unknown property");
1226 //! THROW( UnknownPropertyException() );
1228 return aRet;
1231 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )
1233 // -----------------------------------------------------------------------
1235 ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
1236 pSource( pSrc ),
1237 ppDims( NULL )
1239 //! hold pSource
1241 // include data layout dimension and duplicated dimensions
1242 nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
1245 ScDPDimensions::~ScDPDimensions()
1247 //! release pSource
1249 if (ppDims)
1251 for (long i=0; i<nDimCount; i++)
1252 if ( ppDims[i] )
1253 ppDims[i]->release(); // ref-counted
1254 delete[] ppDims;
1258 void ScDPDimensions::CountChanged()
1260 // include data layout dimension and duplicated dimensions
1261 long nNewCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
1262 if ( ppDims )
1264 long i;
1265 long nCopy = Min( nNewCount, nDimCount );
1266 ScDPDimension** ppNew = new ScDPDimension*[nNewCount];
1268 for (i=0; i<nCopy; i++) // copy existing dims
1269 ppNew[i] = ppDims[i];
1270 for (i=nCopy; i<nNewCount; i++) // clear additional pointers
1271 ppNew[i] = NULL;
1272 for (i=nCopy; i<nDimCount; i++) // delete old dims if count is decreased
1273 if ( ppDims[i] )
1274 ppDims[i]->release(); // ref-counted
1276 delete[] ppDims;
1277 ppDims = ppNew;
1279 nDimCount = nNewCount;
1282 // very simple XNameAccess implementation using getCount/getByIndex
1284 uno::Any SAL_CALL ScDPDimensions::getByName( const rtl::OUString& aName )
1285 throw(container::NoSuchElementException,
1286 lang::WrappedTargetException, uno::RuntimeException)
1288 long nCount = getCount();
1289 for (long i=0; i<nCount; i++)
1290 if ( getByIndex(i)->getName() == aName )
1292 uno::Reference<container::XNamed> xNamed = getByIndex(i);
1293 uno::Any aRet;
1294 aRet <<= xNamed;
1295 return aRet;
1298 throw container::NoSuchElementException();
1299 // return uno::Any();
1302 uno::Sequence<rtl::OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException)
1304 long nCount = getCount();
1305 uno::Sequence<rtl::OUString> aSeq(nCount);
1306 rtl::OUString* pArr = aSeq.getArray();
1307 for (long i=0; i<nCount; i++)
1308 pArr[i] = getByIndex(i)->getName();
1309 return aSeq;
1312 sal_Bool SAL_CALL ScDPDimensions::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1314 long nCount = getCount();
1315 for (long i=0; i<nCount; i++)
1316 if ( getByIndex(i)->getName() == aName )
1317 return TRUE;
1318 return FALSE;
1321 uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException)
1323 return getCppuType((uno::Reference<container::XNamed>*)0);
1326 sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException)
1328 return ( getCount() > 0 );
1331 // end of XNameAccess implementation
1333 long ScDPDimensions::getCount() const
1335 // in tabular data, every column of source data is a dimension
1337 return nDimCount;
1340 ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
1342 if ( nIndex >= 0 && nIndex < nDimCount )
1344 if ( !ppDims )
1346 ((ScDPDimensions*)this)->ppDims = new ScDPDimension*[nDimCount];
1347 for (long i=0; i<nDimCount; i++)
1348 ppDims[i] = NULL;
1350 if ( !ppDims[nIndex] )
1352 ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
1353 ppDims[nIndex]->acquire(); // ref-counted
1356 return ppDims[nIndex];
1359 return NULL; //! exception?
1362 // -----------------------------------------------------------------------
1364 ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
1365 pSource( pSrc ),
1366 nDim( nD ),
1367 pHierarchies( NULL ),
1368 nUsedHier( 0 ),
1369 nFunction( SUBTOTAL_FUNC_SUM ), // sum is default
1370 mpLayoutName(NULL),
1371 mpSubtotalName(NULL),
1372 nSourceDim( -1 ),
1373 bHasSelectedPage( FALSE ),
1374 pSelectedData( NULL ),
1375 mbHasHiddenMember(false)
1377 //! hold pSource
1380 ScDPDimension::~ScDPDimension()
1382 //! release pSource
1384 if ( pHierarchies )
1385 pHierarchies->release(); // ref-counted
1387 delete pSelectedData;
1390 ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
1392 if (!pHierarchies)
1394 pHierarchies = new ScDPHierarchies( pSource, nDim );
1395 pHierarchies->acquire(); // ref-counted
1397 return pHierarchies;
1400 const rtl::OUString* ScDPDimension::GetLayoutName() const
1402 return mpLayoutName.get();
1405 const rtl::OUString* ScDPDimension::GetSubtotalName() const
1407 return mpSubtotalName.get();
1410 uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
1411 throw(uno::RuntimeException)
1413 return GetHierarchiesObject();
1416 ::rtl::OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException)
1418 if (aName.Len())
1419 return aName;
1420 else
1421 return pSource->GetData()->getDimensionName( nDim );
1424 void SAL_CALL ScDPDimension::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
1426 // used after cloning
1427 aName = String( rNewName );
1430 USHORT ScDPDimension::getOrientation() const
1432 return pSource->GetOrientation( nDim );
1435 void ScDPDimension::setOrientation(USHORT nNew)
1437 pSource->SetOrientation( nDim, nNew );
1440 long ScDPDimension::getPosition() const
1442 return pSource->GetPosition( nDim );
1445 void ScDPDimension::setPosition(long /* nNew */)
1447 //! ...
1450 BOOL ScDPDimension::getIsDataLayoutDimension() const
1452 return pSource->GetData()->getIsDataLayoutDimension( nDim );
1455 USHORT ScDPDimension::getFunction() const
1457 return nFunction;
1460 void ScDPDimension::setFunction(USHORT nNew)
1462 nFunction = nNew;
1465 long ScDPDimension::getUsedHierarchy() const
1467 return nUsedHier;
1470 void ScDPDimension::setUsedHierarchy(long /* nNew */)
1472 // #i52547# don't use the incomplete date hierarchy implementation - ignore the call
1473 // nUsedHier = nNew;
1476 ScDPDimension* ScDPDimension::CreateCloneObject()
1478 DBG_ASSERT( nSourceDim < 0, "recursive duplicate - not implemented" );
1480 //! set new name here, or temporary name ???
1481 String aNewName = aName;
1483 ScDPDimension* pNew = pSource->AddDuplicated( nDim, aNewName );
1485 pNew->aName = aNewName; //! here or in source?
1486 pNew->nSourceDim = nDim; //! recursive?
1488 return pNew;
1491 uno::Reference<util::XCloneable> SAL_CALL ScDPDimension::createClone() throw(uno::RuntimeException)
1493 return CreateCloneObject();
1496 BOOL ScDPDimension::isDuplicated() const
1498 return (nSourceDim >= 0);
1501 const sheet::DataPilotFieldReference& ScDPDimension::GetReferenceValue() const
1503 return aReferenceValue;
1506 const ScDPItemData& ScDPDimension::GetSelectedData()
1508 if ( !pSelectedData )
1510 // find the named member to initialize pSelectedData from it, with name and value
1512 long nLevel = 0; // same as in ScDPObject::FillPageList
1514 long nHierarchy = getUsedHierarchy();
1515 if ( nHierarchy >= GetHierarchiesObject()->getCount() )
1516 nHierarchy = 0;
1517 ScDPLevels* pLevels = GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
1518 long nLevCount = pLevels->getCount();
1519 if ( nLevel < nLevCount )
1521 ScDPMembers* pMembers = pLevels->getByIndex(nLevel)->GetMembersObject();
1523 //! merge with ScDPMembers::getByName
1524 long nCount = pMembers->getCount();
1525 for (long i=0; i<nCount && !pSelectedData; i++)
1527 ScDPMember* pMember = pMembers->getByIndex(i);
1528 if ( pMember->GetNameStr() == aSelectedPage )
1530 pSelectedData = new ScDPItemData();
1531 pMember->FillItemData( *pSelectedData );
1536 if ( !pSelectedData )
1537 pSelectedData = new ScDPItemData( aSelectedPage, 0.0, FALSE ); // default - name only
1540 return *pSelectedData;
1543 BOOL ScDPDimension::IsValidPage( const ScDPItemData& rData )
1545 if ( bHasSelectedPage )
1546 return rData.IsCaseInsEqual( GetSelectedData() );
1548 return TRUE; // no selection -> all data
1551 // XPropertySet
1553 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo()
1554 throw(uno::RuntimeException)
1556 ScUnoGuard aGuard;
1558 static SfxItemPropertyMap aDPDimensionMap_Impl[] =
1560 {MAP_CHAR_LEN(SC_UNO_FILTER), 0, &getCppuType((uno::Sequence<sheet::TableFilterField>*)0), 0, 0 },
1561 {MAP_CHAR_LEN(SC_UNO_FUNCTION), 0, &getCppuType((sheet::GeneralFunction*)0), 0, 0 },
1562 {MAP_CHAR_LEN(SC_UNO_ISDATALA), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0 },
1563 {MAP_CHAR_LEN(SC_UNO_NUMBERFO), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0 },
1564 {MAP_CHAR_LEN(SC_UNO_ORIENTAT), 0, &getCppuType((sheet::DataPilotFieldOrientation*)0), 0, 0 },
1565 {MAP_CHAR_LEN(SC_UNO_ORIGINAL), 0, &getCppuType((uno::Reference<container::XNamed>*)0), beans::PropertyAttribute::READONLY, 0 },
1566 {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1567 {MAP_CHAR_LEN(SC_UNO_REFVALUE), 0, &getCppuType((sheet::DataPilotFieldReference*)0), 0, 0 },
1568 {MAP_CHAR_LEN(SC_UNO_USEDHIER), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1569 {MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1570 {MAP_CHAR_LEN(SC_UNO_FIELD_SUBTOTALNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1571 {MAP_CHAR_LEN(SC_UNO_HAS_HIDDEN_MEMBER), 0, &getBooleanCppuType(), 0, 0 },
1572 {0,0,0,0,0,0}
1574 static uno::Reference<beans::XPropertySetInfo> aRef =
1575 new SfxItemPropertySetInfo( aDPDimensionMap_Impl );
1576 return aRef;
1579 void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
1580 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
1581 lang::IllegalArgumentException, lang::WrappedTargetException,
1582 uno::RuntimeException)
1584 String aNameStr = aPropertyName;
1585 if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
1587 INT32 nInt = 0;
1588 if (aValue >>= nInt)
1589 setPosition( nInt );
1591 else if ( aNameStr.EqualsAscii( SC_UNO_USEDHIER ) )
1593 INT32 nInt = 0;
1594 if (aValue >>= nInt)
1595 setUsedHierarchy( nInt );
1597 else if ( aNameStr.EqualsAscii( SC_UNO_ORIENTAT ) )
1599 sheet::DataPilotFieldOrientation eEnum;
1600 if (aValue >>= eEnum)
1601 setOrientation( sal::static_int_cast<USHORT>(eEnum) );
1603 else if ( aNameStr.EqualsAscii( SC_UNO_FUNCTION ) )
1605 sheet::GeneralFunction eEnum;
1606 if (aValue >>= eEnum)
1607 setFunction( sal::static_int_cast<USHORT>(eEnum) );
1609 else if ( aNameStr.EqualsAscii( SC_UNO_REFVALUE ) )
1610 aValue >>= aReferenceValue;
1611 else if ( aNameStr.EqualsAscii( SC_UNO_FILTER ) )
1613 BOOL bDone = FALSE;
1614 uno::Sequence<sheet::TableFilterField> aSeq;
1615 if (aValue >>= aSeq)
1617 sal_Int32 nLength = aSeq.getLength();
1618 if ( nLength == 0 )
1620 aSelectedPage.Erase();
1621 bHasSelectedPage = FALSE;
1622 bDone = TRUE;
1624 else if ( nLength == 1 )
1626 const sheet::TableFilterField& rField = aSeq[0];
1627 if ( rField.Field == 0 && rField.Operator == sheet::FilterOperator_EQUAL && !rField.IsNumeric )
1629 aSelectedPage = rField.StringValue;
1630 bHasSelectedPage = TRUE;
1631 bDone = TRUE;
1635 if ( !bDone )
1637 DBG_ERROR("Filter property is not a single string");
1638 throw lang::IllegalArgumentException();
1640 DELETEZ( pSelectedData ); // invalid after changing aSelectedPage
1642 else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1644 OUString aTmpName;
1645 if (aValue >>= aTmpName)
1646 mpLayoutName.reset(new OUString(aTmpName));
1648 else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME))
1650 OUString aTmpName;
1651 if (aValue >>= aTmpName)
1652 mpSubtotalName.reset(new OUString(aTmpName));
1654 else if (aNameStr.EqualsAscii(SC_UNO_HAS_HIDDEN_MEMBER))
1655 aValue >>= mbHasHiddenMember;
1656 else
1658 DBG_ERROR("unknown property");
1659 //! THROW( UnknownPropertyException() );
1663 uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropertyName )
1664 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
1665 uno::RuntimeException)
1667 uno::Any aRet;
1668 String aNameStr = aPropertyName;
1669 if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
1670 aRet <<= (sal_Int32) getPosition();
1671 else if ( aNameStr.EqualsAscii( SC_UNO_USEDHIER ) )
1672 aRet <<= (sal_Int32) getUsedHierarchy();
1673 else if ( aNameStr.EqualsAscii( SC_UNO_ORIENTAT ) )
1675 sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
1676 aRet <<= eVal;
1678 else if ( aNameStr.EqualsAscii( SC_UNO_FUNCTION ) )
1680 sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
1681 aRet <<= eVal;
1683 else if ( aNameStr.EqualsAscii( SC_UNO_REFVALUE ) )
1684 aRet <<= aReferenceValue;
1685 else if ( aNameStr.EqualsAscii( SC_UNO_ISDATALA ) ) // read-only properties
1686 lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
1687 else if ( aNameStr.EqualsAscii( SC_UNO_NUMBERFO ) )
1689 sal_Int32 nFormat = 0;
1690 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)getFunction();
1691 // #i63745# don't use source format for "count"
1692 if ( eFunc != sheet::GeneralFunction_COUNT && eFunc != sheet::GeneralFunction_COUNTNUMS )
1693 nFormat = pSource->GetData()->GetNumberFormat( ( nSourceDim >= 0 ) ? nSourceDim : nDim );
1694 aRet <<= nFormat;
1696 else if ( aNameStr.EqualsAscii( SC_UNO_ORIGINAL ) )
1698 uno::Reference<container::XNamed> xOriginal;
1699 if (nSourceDim >= 0)
1700 xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
1701 aRet <<= xOriginal;
1703 else if ( aNameStr.EqualsAscii( SC_UNO_FILTER ) )
1705 if ( bHasSelectedPage )
1707 // single filter field: first field equal to selected string
1708 sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
1709 sheet::FilterOperator_EQUAL, sal_False, 0.0, aSelectedPage );
1710 aRet <<= uno::Sequence<sheet::TableFilterField>( &aField, 1 );
1712 else
1713 aRet <<= uno::Sequence<sheet::TableFilterField>(0);
1715 else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1716 aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString::createFromAscii("");
1717 else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME))
1718 aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString::createFromAscii("");
1719 else if (aNameStr.EqualsAscii(SC_UNO_HAS_HIDDEN_MEMBER))
1720 aRet <<= mbHasHiddenMember;
1721 else
1723 DBG_ERROR("unknown property");
1724 //! THROW( UnknownPropertyException() );
1726 return aRet;
1729 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )
1731 // -----------------------------------------------------------------------
1733 ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
1734 pSource( pSrc ),
1735 nDim( nD ),
1736 ppHiers( NULL )
1738 //! hold pSource
1740 #if 0
1741 // date columns have 3 hierarchies (flat/quarter/week), other columns only one
1742 long nSrcDim = pSource->GetSourceDim( nDim );
1743 if ( pSource->IsDateDimension( nSrcDim ) )
1744 nHierCount = SC_DAPI_DATE_HIERARCHIES;
1745 else
1746 nHierCount = 1;
1747 #endif
1749 // #i52547# don't offer the incomplete date hierarchy implementation
1750 nHierCount = 1;
1753 ScDPHierarchies::~ScDPHierarchies()
1755 //! release pSource
1757 if (ppHiers)
1759 for (long i=0; i<nHierCount; i++)
1760 if ( ppHiers[i] )
1761 ppHiers[i]->release(); // ref-counted
1762 delete[] ppHiers;
1766 // very simple XNameAccess implementation using getCount/getByIndex
1768 uno::Any SAL_CALL ScDPHierarchies::getByName( const rtl::OUString& aName )
1769 throw(container::NoSuchElementException,
1770 lang::WrappedTargetException, uno::RuntimeException)
1772 long nCount = getCount();
1773 for (long i=0; i<nCount; i++)
1774 if ( getByIndex(i)->getName() == aName )
1776 uno::Reference<container::XNamed> xNamed = getByIndex(i);
1777 uno::Any aRet;
1778 aRet <<= xNamed;
1779 return aRet;
1782 throw container::NoSuchElementException();
1783 // return uno::Any();
1786 uno::Sequence<rtl::OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException)
1788 long nCount = getCount();
1789 uno::Sequence<rtl::OUString> aSeq(nCount);
1790 rtl::OUString* pArr = aSeq.getArray();
1791 for (long i=0; i<nCount; i++)
1792 pArr[i] = getByIndex(i)->getName();
1793 return aSeq;
1796 sal_Bool SAL_CALL ScDPHierarchies::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1798 long nCount = getCount();
1799 for (long i=0; i<nCount; i++)
1800 if ( getByIndex(i)->getName() == aName )
1801 return TRUE;
1802 return FALSE;
1805 uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException)
1807 return getCppuType((uno::Reference<container::XNamed>*)0);
1810 sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException)
1812 return ( getCount() > 0 );
1815 // end of XNameAccess implementation
1817 long ScDPHierarchies::getCount() const
1819 return nHierCount;
1822 ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
1824 // pass hierarchy index to new object in case the implementation
1825 // will be extended to more than one hierarchy
1827 if ( nIndex >= 0 && nIndex < nHierCount )
1829 if ( !ppHiers )
1831 ((ScDPHierarchies*)this)->ppHiers = new ScDPHierarchy*[nHierCount];
1832 for (long i=0; i<nHierCount; i++)
1833 ppHiers[i] = NULL;
1835 if ( !ppHiers[nIndex] )
1837 ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
1838 ppHiers[nIndex]->acquire(); // ref-counted
1841 return ppHiers[nIndex];
1844 return NULL; //! exception?
1847 // -----------------------------------------------------------------------
1849 ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
1850 pSource( pSrc ),
1851 nDim( nD ),
1852 nHier( nH ),
1853 pLevels( NULL )
1855 //! hold pSource
1858 ScDPHierarchy::~ScDPHierarchy()
1860 //! release pSource
1862 if (pLevels)
1863 pLevels->release(); // ref-counted
1866 ScDPLevels* ScDPHierarchy::GetLevelsObject()
1868 if (!pLevels)
1870 pLevels = new ScDPLevels( pSource, nDim, nHier );
1871 pLevels->acquire(); // ref-counted
1873 return pLevels;
1876 uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
1877 throw(uno::RuntimeException)
1879 return GetLevelsObject();
1882 ::rtl::OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException)
1884 String aRet; //! globstr-ID !!!!
1885 switch (nHier)
1887 case SC_DAPI_HIERARCHY_FLAT:
1888 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("flat"));
1889 break; //! name ???????
1890 case SC_DAPI_HIERARCHY_QUARTER:
1891 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Quarter"));
1892 break; //! name ???????
1893 case SC_DAPI_HIERARCHY_WEEK:
1894 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Week"));
1895 break; //! name ???????
1896 default:
1897 DBG_ERROR( "ScDPHierarchy::getName: unexpected hierarchy" );
1898 break;
1900 return aRet;
1903 void SAL_CALL ScDPHierarchy::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
1905 DBG_ERROR("not implemented"); //! exception?
1908 // -----------------------------------------------------------------------
1910 ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
1911 pSource( pSrc ),
1912 nDim( nD ),
1913 nHier( nH ),
1914 ppLevs( NULL )
1916 //! hold pSource
1918 // text columns have only one level
1920 long nSrcDim = pSource->GetSourceDim( nDim );
1921 if ( pSource->IsDateDimension( nSrcDim ) )
1923 switch ( nHier )
1925 case SC_DAPI_HIERARCHY_FLAT: nLevCount = SC_DAPI_FLAT_LEVELS; break;
1926 case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
1927 case SC_DAPI_HIERARCHY_WEEK: nLevCount = SC_DAPI_WEEK_LEVELS; break;
1928 default:
1929 DBG_ERROR("wrong hierarchy");
1930 nLevCount = 0;
1933 else
1934 nLevCount = 1;
1937 ScDPLevels::~ScDPLevels()
1939 //! release pSource
1941 if (ppLevs)
1943 for (long i=0; i<nLevCount; i++)
1944 if ( ppLevs[i] )
1945 ppLevs[i]->release(); // ref-counted
1946 delete[] ppLevs;
1950 // very simple XNameAccess implementation using getCount/getByIndex
1952 uno::Any SAL_CALL ScDPLevels::getByName( const rtl::OUString& aName )
1953 throw(container::NoSuchElementException,
1954 lang::WrappedTargetException, uno::RuntimeException)
1956 long nCount = getCount();
1957 for (long i=0; i<nCount; i++)
1958 if ( getByIndex(i)->getName() == aName )
1960 uno::Reference<container::XNamed> xNamed = getByIndex(i);
1961 uno::Any aRet;
1962 aRet <<= xNamed;
1963 return aRet;
1966 throw container::NoSuchElementException();
1967 // return uno::Any();
1970 uno::Sequence<rtl::OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException)
1972 long nCount = getCount();
1973 uno::Sequence<rtl::OUString> aSeq(nCount);
1974 rtl::OUString* pArr = aSeq.getArray();
1975 for (long i=0; i<nCount; i++)
1976 pArr[i] = getByIndex(i)->getName();
1977 return aSeq;
1980 sal_Bool SAL_CALL ScDPLevels::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1982 long nCount = getCount();
1983 for (long i=0; i<nCount; i++)
1984 if ( getByIndex(i)->getName() == aName )
1985 return TRUE;
1986 return FALSE;
1989 uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException)
1991 return getCppuType((uno::Reference<container::XNamed>*)0);
1994 sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException)
1996 return ( getCount() > 0 );
1999 // end of XNameAccess implementation
2001 long ScDPLevels::getCount() const
2003 return nLevCount;
2006 ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
2008 if ( nIndex >= 0 && nIndex < nLevCount )
2010 if ( !ppLevs )
2012 ((ScDPLevels*)this)->ppLevs = new ScDPLevel*[nLevCount];
2013 for (long i=0; i<nLevCount; i++)
2014 ppLevs[i] = NULL;
2016 if ( !ppLevs[nIndex] )
2018 ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
2019 ppLevs[nIndex]->acquire(); // ref-counted
2022 return ppLevs[nIndex];
2025 return NULL; //! exception?
2028 // -----------------------------------------------------------------------
2030 class ScDPGlobalMembersOrder
2032 ScDPLevel& rLevel;
2033 BOOL bAscending;
2035 public:
2036 ScDPGlobalMembersOrder( ScDPLevel& rLev, BOOL bAsc ) :
2037 rLevel(rLev),
2038 bAscending(bAsc)
2040 ~ScDPGlobalMembersOrder() {}
2042 BOOL operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
2045 BOOL ScDPGlobalMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
2047 ScDPMembers* pMembers = rLevel.GetMembersObject();
2048 ScDPMember* pMember1 = pMembers->getByIndex(nIndex1);
2049 ScDPMember* pMember2 = pMembers->getByIndex(nIndex2);
2051 sal_Int32 nCompare = pMember1->Compare( *pMember2 );
2053 return bAscending ? ( nCompare < 0 ) : ( nCompare > 0 );
2056 // -----------------------------------------------------------------------
2058 ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
2059 pSource( pSrc ),
2060 nDim( nD ),
2061 nHier( nH ),
2062 nLev( nL ),
2063 pMembers( NULL ),
2064 bShowEmpty( FALSE ),
2065 aSortInfo( EMPTY_STRING, sal_True, sheet::DataPilotFieldSortMode::NAME ), // default: sort by name
2066 nSortMeasure( 0 ),
2067 nAutoMeasure( 0 ),
2068 bEnableLayout( FALSE )
2070 //! hold pSource
2071 // aSubTotals is empty
2074 ScDPLevel::~ScDPLevel()
2076 //! release pSource
2078 if ( pMembers )
2079 pMembers->release(); // ref-counted
2082 void ScDPLevel::EvaluateSortOrder()
2084 switch (aSortInfo.Mode)
2086 case sheet::DataPilotFieldSortMode::DATA:
2088 // find index of measure (index among data dimensions)
2090 String aDataFieldName = aSortInfo.Field;
2091 long nMeasureCount = pSource->GetDataDimensionCount();
2092 for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
2094 if ( pSource->GetDataDimName(nMeasure) == aDataFieldName )
2096 nSortMeasure = nMeasure;
2097 break;
2101 //! error if not found?
2103 break;
2104 case sheet::DataPilotFieldSortMode::MANUAL:
2105 case sheet::DataPilotFieldSortMode::NAME:
2107 ScDPMembers* pLocalMembers = GetMembersObject();
2108 long nCount = pLocalMembers->getCount();
2110 DBG_ASSERT( aGlobalOrder.empty(), "sort twice?" );
2111 aGlobalOrder.resize( nCount );
2112 for (long nPos=0; nPos<nCount; nPos++)
2113 aGlobalOrder[nPos] = nPos;
2115 // allow manual or name (manual is always ascending)
2116 BOOL bAscending = ( aSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL || aSortInfo.IsAscending );
2117 ScDPGlobalMembersOrder aComp( *this, bAscending );
2118 ::std::sort( aGlobalOrder.begin(), aGlobalOrder.end(), aComp );
2120 break;
2123 if ( aAutoShowInfo.IsEnabled )
2125 // find index of measure (index among data dimensions)
2127 String aDataFieldName = aAutoShowInfo.DataField;
2128 long nMeasureCount = pSource->GetDataDimensionCount();
2129 for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
2131 if ( pSource->GetDataDimName(nMeasure) == aDataFieldName )
2133 nAutoMeasure = nMeasure;
2134 break;
2138 //! error if not found?
2142 void ScDPLevel::SetEnableLayout( BOOL bSet )
2144 bEnableLayout = bSet;
2147 ScDPMembers* ScDPLevel::GetMembersObject()
2149 if (!pMembers)
2151 pMembers = new ScDPMembers( pSource, nDim, nHier, nLev );
2152 pMembers->acquire(); // ref-counted
2154 return pMembers;
2157 uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException)
2159 return GetMembersObject();
2162 uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException)
2164 const uno::Sequence<sheet::MemberResult>* pRes = pSource->GetMemberResults( this );
2165 if (pRes)
2166 return *pRes;
2168 return uno::Sequence<sheet::MemberResult>(0); //! Error?
2171 ::rtl::OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException)
2173 long nSrcDim = pSource->GetSourceDim( nDim );
2174 if ( pSource->IsDateDimension( nSrcDim ) )
2176 String aRet; //! globstr-ID !!!!
2178 if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
2180 switch ( nLev )
2182 case SC_DAPI_LEVEL_YEAR:
2183 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Year"));
2184 break;
2185 case SC_DAPI_LEVEL_QUARTER:
2186 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Quarter"));
2187 break;
2188 case SC_DAPI_LEVEL_MONTH:
2189 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Month"));
2190 break;
2191 case SC_DAPI_LEVEL_DAY:
2192 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Day"));
2193 break;
2194 default:
2195 DBG_ERROR( "ScDPLevel::getName: unexpected level" );
2196 break;
2199 else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
2201 switch ( nLev )
2203 case SC_DAPI_LEVEL_YEAR:
2204 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Year"));
2205 break;
2206 case SC_DAPI_LEVEL_WEEK:
2207 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Week"));
2208 break;
2209 case SC_DAPI_LEVEL_WEEKDAY:
2210 aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Weekday"));
2211 break;
2212 default:
2213 DBG_ERROR( "ScDPLevel::getName: unexpected level" );
2214 break;
2217 if (aRet.Len())
2218 return aRet;
2221 ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
2222 if (!pDim)
2223 return rtl::OUString();
2225 return pDim->getName();
2228 void SAL_CALL ScDPLevel::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
2230 DBG_ERROR("not implemented"); //! exception?
2233 uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
2235 //! separate functions for settings and evaluation?
2237 long nSrcDim = pSource->GetSourceDim( nDim );
2238 if ( !pSource->SubTotalAllowed( nSrcDim ) )
2239 return uno::Sequence<sheet::GeneralFunction>(0);
2241 return aSubTotals;
2244 void ScDPLevel::setSubTotals(const uno::Sequence<sheet::GeneralFunction>& rNew)
2246 aSubTotals = rNew;
2247 //! set "manual change" flag?
2250 BOOL ScDPLevel::getShowEmpty() const
2252 return bShowEmpty;
2255 void ScDPLevel::setShowEmpty(BOOL bSet)
2257 bShowEmpty = bSet;
2260 // XPropertySet
2262 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
2263 throw(uno::RuntimeException)
2265 ScUnoGuard aGuard;
2267 static SfxItemPropertyMap aDPLevelMap_Impl[] =
2269 //! change type of AutoShow/Layout/Sorting to API struct when available
2270 {MAP_CHAR_LEN(SC_UNO_AUTOSHOW), 0, &getCppuType((sheet::DataPilotFieldAutoShowInfo*)0), 0, 0 },
2271 {MAP_CHAR_LEN(SC_UNO_LAYOUT), 0, &getCppuType((sheet::DataPilotFieldLayoutInfo*)0), 0, 0 },
2272 {MAP_CHAR_LEN(SC_UNO_SHOWEMPT), 0, &getBooleanCppuType(), 0, 0 },
2273 {MAP_CHAR_LEN(SC_UNO_SORTING), 0, &getCppuType((sheet::DataPilotFieldSortInfo*)0), 0, 0 },
2274 {MAP_CHAR_LEN(SC_UNO_SUBTOTAL), 0, &getCppuType((uno::Sequence<sheet::GeneralFunction>*)0), 0, 0 },
2275 {0,0,0,0,0,0}
2277 static uno::Reference<beans::XPropertySetInfo> aRef =
2278 new SfxItemPropertySetInfo( aDPLevelMap_Impl );
2279 return aRef;
2282 void SAL_CALL ScDPLevel::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
2283 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
2284 lang::IllegalArgumentException, lang::WrappedTargetException,
2285 uno::RuntimeException)
2287 String aNameStr = aPropertyName;
2288 if ( aNameStr.EqualsAscii( SC_UNO_SHOWEMPT ) )
2289 setShowEmpty( lcl_GetBoolFromAny( aValue ) );
2290 else if ( aNameStr.EqualsAscii( SC_UNO_SUBTOTAL ) )
2292 uno::Sequence<sheet::GeneralFunction> aSeq;
2293 if ( aValue >>= aSeq )
2294 setSubTotals( aSeq );
2296 else if ( aNameStr.EqualsAscii( SC_UNO_SORTING ) )
2297 aValue >>= aSortInfo;
2298 else if ( aNameStr.EqualsAscii( SC_UNO_AUTOSHOW ) )
2299 aValue >>= aAutoShowInfo;
2300 else if ( aNameStr.EqualsAscii( SC_UNO_LAYOUT ) )
2301 aValue >>= aLayoutInfo;
2302 else
2304 DBG_ERROR("unknown property");
2305 //! THROW( UnknownPropertyException() );
2309 uno::Any SAL_CALL ScDPLevel::getPropertyValue( const rtl::OUString& aPropertyName )
2310 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
2311 uno::RuntimeException)
2313 uno::Any aRet;
2314 String aNameStr = aPropertyName;
2315 if ( aNameStr.EqualsAscii( SC_UNO_SHOWEMPT ) )
2316 lcl_SetBoolInAny( aRet, getShowEmpty() );
2317 else if ( aNameStr.EqualsAscii( SC_UNO_SUBTOTAL ) )
2319 uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals(); //! avoid extra copy?
2320 aRet <<= aSeq;
2322 else if ( aNameStr.EqualsAscii( SC_UNO_SORTING ) )
2323 aRet <<= aSortInfo;
2324 else if ( aNameStr.EqualsAscii( SC_UNO_AUTOSHOW ) )
2325 aRet <<= aAutoShowInfo;
2326 else if ( aNameStr.EqualsAscii( SC_UNO_LAYOUT ) )
2327 aRet <<= aLayoutInfo;
2328 else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
2330 // read only property
2331 long nSrcDim = pSource->GetSourceDim(nDim);
2332 ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
2333 if (!pDim)
2334 return aRet;
2336 const OUString* pLayoutName = pDim->GetLayoutName();
2337 if (!pLayoutName)
2338 return aRet;
2340 aRet <<= *pLayoutName;
2342 else
2344 DBG_ERROR("unknown property");
2345 //! THROW( UnknownPropertyException() );
2347 return aRet;
2350 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )
2352 // -----------------------------------------------------------------------
2354 USHORT lcl_GetFirstStringPos( const TypedScStrCollection& rColl )
2356 USHORT nPos = 0;
2357 USHORT nCount = rColl.GetCount();
2358 while ( nPos < nCount && !rColl[nPos]->IsStrData() )
2359 ++nPos;
2360 return nPos;
2363 ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) :
2364 pSource( pSrc ),
2365 nDim( nD ),
2366 nHier( nH ),
2367 nLev( nL ),
2368 ppMbrs( NULL )
2370 //! hold pSource
2372 long nSrcDim = pSource->GetSourceDim( nDim );
2373 if ( pSource->IsDataLayoutDimension(nSrcDim) )
2374 nMbrCount = pSource->GetDataDimensionCount();
2375 else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2377 nMbrCount = 0;
2378 if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
2380 switch (nLev)
2382 case SC_DAPI_LEVEL_YEAR:
2384 const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
2385 USHORT nFirstString = lcl_GetFirstStringPos( rStrings );
2386 if ( nFirstString > 0 )
2388 double fFirstVal = rStrings[0]->GetValue();
2389 double fLastVal = rStrings[nFirstString-1]->GetValue();
2391 long nFirstYear = pSource->GetData()->GetDatePart(
2392 (long)::rtl::math::approxFloor( fFirstVal ),
2393 nHier, nLev );
2394 long nLastYear = pSource->GetData()->GetDatePart(
2395 (long)::rtl::math::approxFloor( fLastVal ),
2396 nHier, nLev );
2398 nMbrCount = nLastYear + 1 - nFirstYear;
2400 else
2401 nMbrCount = 0; // no values
2403 break;
2404 case SC_DAPI_LEVEL_QUARTER: nMbrCount = 4; break;
2405 case SC_DAPI_LEVEL_MONTH: nMbrCount = 12; break;
2406 case SC_DAPI_LEVEL_DAY: nMbrCount = 31; break;
2407 default:
2408 DBG_ERROR( "ScDPMembers::ScDPMembers: unexpected level" );
2409 break;
2412 else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
2414 switch (nLev)
2416 case SC_DAPI_LEVEL_YEAR: nMbrCount = 1; break; //! get years from source
2417 case SC_DAPI_LEVEL_WEEK: nMbrCount = 53; break;
2418 case SC_DAPI_LEVEL_WEEKDAY: nMbrCount = 7; break;
2419 default:
2420 DBG_ERROR( "ScDPMembers::ScDPMembers: unexpected level" );
2421 break;
2425 else
2427 // StringCollection is cached at TableData
2428 const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
2429 nMbrCount = rStrings.GetCount();
2433 ScDPMembers::~ScDPMembers()
2435 //! release pSource
2437 if (ppMbrs)
2439 for (long i=0; i<nMbrCount; i++)
2440 if ( ppMbrs[i] )
2441 ppMbrs[i]->release(); // ref-counted
2442 delete[] ppMbrs;
2446 // XNameAccess implementation using getCount/getByIndex
2448 sal_Int32 ScDPMembers::GetIndexFromName( const ::rtl::OUString& rName ) const
2450 if ( aHashMap.empty() )
2452 // store the index for each name
2454 sal_Int32 nCount = getCount();
2455 for (sal_Int32 i=0; i<nCount; i++)
2456 aHashMap[ getByIndex(i)->getName() ] = i;
2459 ScDPMembersHashMap::const_iterator aIter = aHashMap.find( rName );
2460 if ( aIter != aHashMap.end() )
2461 return aIter->second; // found index
2462 else
2463 return -1; // not found
2466 uno::Any SAL_CALL ScDPMembers::getByName( const rtl::OUString& aName )
2467 throw(container::NoSuchElementException,
2468 lang::WrappedTargetException, uno::RuntimeException)
2470 sal_Int32 nIndex = GetIndexFromName( aName );
2471 if ( nIndex >= 0 )
2473 uno::Reference<container::XNamed> xNamed = getByIndex(nIndex);
2474 uno::Any aRet;
2475 aRet <<= xNamed;
2476 return aRet;
2479 throw container::NoSuchElementException();
2480 // return uno::Any();
2483 uno::Sequence<rtl::OUString> SAL_CALL ScDPMembers::getElementNames() throw(uno::RuntimeException)
2485 // Return list of names in sorted order,
2486 // so it's displayed in that order in the field options dialog.
2487 // Sorting is done at the level object (parent of this).
2489 ScDPLevel* pLevel = pSource->GetDimensionsObject()->getByIndex(nDim)->
2490 GetHierarchiesObject()->getByIndex(nHier)->GetLevelsObject()->getByIndex(nLev);
2491 pLevel->EvaluateSortOrder();
2492 const std::vector<sal_Int32>& rGlobalOrder = pLevel->GetGlobalOrder();
2493 bool bSort = !rGlobalOrder.empty();
2495 long nCount = getCount();
2496 uno::Sequence<rtl::OUString> aSeq(nCount);
2497 rtl::OUString* pArr = aSeq.getArray();
2498 for (long i=0; i<nCount; i++)
2499 pArr[i] = getByIndex(bSort ? rGlobalOrder[i] : i)->getName();
2500 return aSeq;
2503 sal_Bool SAL_CALL ScDPMembers::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
2505 return ( GetIndexFromName( aName ) >= 0 );
2508 uno::Type SAL_CALL ScDPMembers::getElementType() throw(uno::RuntimeException)
2510 return getCppuType((uno::Reference<container::XNamed>*)0);
2513 sal_Bool SAL_CALL ScDPMembers::hasElements() throw(uno::RuntimeException)
2515 return ( getCount() > 0 );
2518 // end of XNameAccess implementation
2520 long ScDPMembers::getCount() const
2522 return nMbrCount;
2525 long ScDPMembers::getMinMembers() const
2527 // used in lcl_CountMinMembers
2529 long nVisCount = 0;
2530 if ( ppMbrs )
2532 for (long i=0; i<nMbrCount; i++)
2534 // count only visible with details (default is true for both)
2535 const ScDPMember* pMbr = ppMbrs[i];
2536 if ( !pMbr || ( pMbr->getIsVisible() && pMbr->getShowDetails() ) )
2537 ++nVisCount;
2540 else
2541 nVisCount = nMbrCount; // default for all
2543 return nVisCount;
2546 ScDPMember* ScDPMembers::getByIndex(long nIndex) const
2548 // result of GetColumnEntries must not change between ScDPMembers ctor
2549 // and all calls to getByIndex
2551 if ( nIndex >= 0 && nIndex < nMbrCount )
2553 if ( !ppMbrs )
2555 ((ScDPMembers*)this)->ppMbrs = new ScDPMember*[nMbrCount];
2556 for (long i=0; i<nMbrCount; i++)
2557 ppMbrs[i] = NULL;
2559 if ( !ppMbrs[nIndex] )
2561 ScDPMember* pNew;
2562 long nSrcDim = pSource->GetSourceDim( nDim );
2563 if ( pSource->IsDataLayoutDimension(nSrcDim) )
2565 // empty name (never shown, not used for lookup)
2566 pNew = new ScDPMember( pSource, nDim, nHier, nLev,
2567 String(), 0.0, FALSE );
2569 else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2571 long nVal = 0;
2572 String aName;
2574 if ( nLev == SC_DAPI_LEVEL_YEAR ) // YEAR is in both hierarchies
2576 //! cache year range here!
2578 const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
2579 double fFirstVal = rStrings[0]->GetValue();
2580 long nFirstYear = pSource->GetData()->GetDatePart(
2581 (long)::rtl::math::approxFloor( fFirstVal ),
2582 nHier, nLev );
2584 nVal = nFirstYear + nIndex;
2586 else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY )
2588 nVal = nIndex; // DayOfWeek is 0-based
2589 aName = ScGlobal::pCalendar->getDisplayName(
2590 ::com::sun::star::i18n::CalendarDisplayIndex::DAY,
2591 sal::static_int_cast<sal_Int16>(nVal), 0 );
2593 else if ( nHier == SC_DAPI_HIERARCHY_QUARTER && nLev == SC_DAPI_LEVEL_MONTH )
2595 nVal = nIndex; // Month is 0-based
2596 aName = ScGlobal::pCalendar->getDisplayName(
2597 ::com::sun::star::i18n::CalendarDisplayIndex::MONTH,
2598 sal::static_int_cast<sal_Int16>(nVal), 0 );
2600 else
2601 nVal = nIndex + 1; // Quarter, Day, Week are 1-based
2603 if ( !aName.Len() )
2604 aName = String::CreateFromInt32(nVal);
2606 pNew = new ScDPMember( pSource, nDim, nHier, nLev, aName, nVal, TRUE );
2608 else
2610 const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
2611 const TypedStrData* pData = rStrings[(USHORT)nIndex];
2612 pNew = new ScDPMember( pSource, nDim, nHier, nLev,
2613 pData->GetString(), pData->GetValue(), !pData->IsStrData() );
2615 pNew->acquire(); // ref-counted
2616 ppMbrs[nIndex] = pNew;
2619 return ppMbrs[nIndex];
2622 return NULL; //! exception?
2625 // -----------------------------------------------------------------------
2627 ScDPMember::ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL,
2628 const String& rN, double fV, BOOL bHV ) :
2629 pSource( pSrc ),
2630 nDim( nD ),
2631 nHier( nH ),
2632 nLev( nL ),
2633 maData( rN, fV, bHV ),
2634 mpLayoutName(NULL),
2635 nPosition( -1 ),
2636 bVisible( TRUE ),
2637 bShowDet( TRUE )
2639 //! hold pSource
2642 ScDPMember::~ScDPMember()
2644 //! release pSource
2647 BOOL ScDPMember::IsNamedItem( const ScDPItemData& r ) const
2649 long nSrcDim = pSource->GetSourceDim( nDim );
2650 if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) && r.bHasValue )
2652 long nComp = pSource->GetData()->GetDatePart(
2653 (long)::rtl::math::approxFloor( r.fValue ),
2654 nHier, nLev );
2656 // fValue is converted from integer, so simple comparison works
2657 return nComp == maData.fValue;
2660 return r.IsCaseInsEqual( maData );
2663 sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const
2665 if ( nPosition >= 0 )
2667 if ( rOther.nPosition >= 0 )
2669 DBG_ASSERT( nPosition != rOther.nPosition, "same position for two members" );
2670 return ( nPosition < rOther.nPosition ) ? -1 : 1;
2672 else
2674 // only this has a position - members with specified positions come before those without
2675 return -1;
2678 else if ( rOther.nPosition >= 0 )
2680 // only rOther has a position
2681 return 1;
2684 // no positions set - compare names
2685 return ScDPItemData::Compare( maData, rOther.maData );
2688 void ScDPMember::FillItemData( ScDPItemData& rData ) const
2690 //! handle date hierarchy...
2692 rData = maData;
2695 const OUString* ScDPMember::GetLayoutName() const
2697 return mpLayoutName.get();
2700 String ScDPMember::GetNameStr() const
2702 return maData.aString;
2705 ::rtl::OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException)
2707 return maData.aString;
2710 void SAL_CALL ScDPMember::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
2712 DBG_ERROR("not implemented"); //! exception?
2715 BOOL ScDPMember::getIsVisible() const
2717 return bVisible;
2720 void ScDPMember::setIsVisible(BOOL bSet)
2722 bVisible = bSet;
2723 //! set "manual change" flag
2726 BOOL ScDPMember::getShowDetails() const
2728 return bShowDet;
2731 void ScDPMember::setShowDetails(BOOL bSet)
2733 bShowDet = bSet;
2734 //! set "manual change" flag
2737 sal_Int32 ScDPMember::getPosition() const
2739 return nPosition;
2742 void ScDPMember::setPosition(sal_Int32 nNew)
2744 nPosition = nNew;
2747 // XPropertySet
2749 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo()
2750 throw(uno::RuntimeException)
2752 ScUnoGuard aGuard;
2754 static SfxItemPropertyMap aDPMemberMap_Impl[] =
2756 {MAP_CHAR_LEN(SC_UNO_ISVISIBL), 0, &getBooleanCppuType(), 0, 0 },
2757 {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
2758 {MAP_CHAR_LEN(SC_UNO_SHOWDETA), 0, &getBooleanCppuType(), 0, 0 },
2759 {MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
2760 {0,0,0,0,0,0}
2762 static uno::Reference<beans::XPropertySetInfo> aRef =
2763 new SfxItemPropertySetInfo( aDPMemberMap_Impl );
2764 return aRef;
2767 void SAL_CALL ScDPMember::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
2768 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
2769 lang::IllegalArgumentException, lang::WrappedTargetException,
2770 uno::RuntimeException)
2772 String aNameStr = aPropertyName;
2773 if ( aNameStr.EqualsAscii( SC_UNO_ISVISIBL ) )
2774 setIsVisible( lcl_GetBoolFromAny( aValue ) );
2775 else if ( aNameStr.EqualsAscii( SC_UNO_SHOWDETA ) )
2776 setShowDetails( lcl_GetBoolFromAny( aValue ) );
2777 else if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
2779 sal_Int32 nInt = 0;
2780 if (aValue >>= nInt)
2781 setPosition( nInt );
2783 else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
2785 rtl::OUString aName;
2786 if (aValue >>= aName)
2787 mpLayoutName.reset(new rtl::OUString(aName));
2789 else
2791 DBG_ERROR("unknown property");
2792 //! THROW( UnknownPropertyException() );
2796 uno::Any SAL_CALL ScDPMember::getPropertyValue( const rtl::OUString& aPropertyName )
2797 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
2798 uno::RuntimeException)
2800 uno::Any aRet;
2801 String aNameStr = aPropertyName;
2802 if ( aNameStr.EqualsAscii( SC_UNO_ISVISIBL ) )
2803 lcl_SetBoolInAny( aRet, getIsVisible() );
2804 else if ( aNameStr.EqualsAscii( SC_UNO_SHOWDETA ) )
2805 lcl_SetBoolInAny( aRet, getShowDetails() );
2806 else if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
2807 aRet <<= (sal_Int32) getPosition();
2808 else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
2809 aRet <<= mpLayoutName.get() ? *mpLayoutName : rtl::OUString();
2810 else
2812 DBG_ERROR("unknown property");
2813 //! THROW( UnknownPropertyException() );
2815 return aRet;
2818 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember )