1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "dptabsrc.hxx"
25 #include <boost/unordered_set.hpp>
26 #include <boost/unordered_map.hpp>
28 #include <rtl/math.hxx>
29 #include <svl/itemprop.hxx>
30 #include <svl/intitem.hxx>
31 #include <vcl/svapp.hxx>
33 #include "scitems.hxx"
34 #include "document.hxx"
35 #include "docpool.hxx"
36 #include "patattr.hxx"
37 #include "formulacell.hxx"
39 #include "dptabres.hxx"
40 #include "dptabdat.hxx"
42 #include "datauno.hxx"
43 #include "miscuno.hxx"
44 #include "unonames.hxx"
45 #include "dpitemdata.hxx"
47 #include "dpresfilter.hxx"
48 #include "calcmacros.hxx"
50 #include <com/sun/star/beans/PropertyAttribute.hpp>
51 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
52 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
53 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
54 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
55 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
56 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
57 #include <com/sun/star/table/CellAddress.hpp>
59 #include "comphelper/string.hxx"
60 #include <unotools/collatorwrapper.hxx>
61 #include <unotools/calendarwrapper.hxx>
62 #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
64 using namespace com::sun::star
;
67 using ::com::sun::star::uno::Reference
;
68 using ::com::sun::star::uno::Sequence
;
69 using ::com::sun::star::uno::Any
;
70 using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo
;
72 // -----------------------------------------------------------------------
74 #define SC_MINCOUNT_LIMIT 1000000
76 // -----------------------------------------------------------------------
78 SC_SIMPLE_SERVICE_INFO( ScDPSource
, "ScDPSource", "com.sun.star.sheet.DataPilotSource" )
79 SC_SIMPLE_SERVICE_INFO( ScDPDimensions
, "ScDPDimensions", "com.sun.star.sheet.DataPilotSourceDimensions" )
80 SC_SIMPLE_SERVICE_INFO( ScDPDimension
, "ScDPDimension", "com.sun.star.sheet.DataPilotSourceDimension" )
81 SC_SIMPLE_SERVICE_INFO( ScDPHierarchies
, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
82 SC_SIMPLE_SERVICE_INFO( ScDPHierarchy
, "ScDPHierarchy", "com.sun.star.sheet.DataPilotSourceHierarcy" )
83 SC_SIMPLE_SERVICE_INFO( ScDPLevels
, "ScDPLevels", "com.sun.star.sheet.DataPilotSourceLevels" )
84 SC_SIMPLE_SERVICE_INFO( ScDPLevel
, "ScDPLevel", "com.sun.star.sheet.DataPilotSourceLevel" )
85 SC_SIMPLE_SERVICE_INFO( ScDPMembers
, "ScDPMembers", "com.sun.star.sheet.DataPilotSourceMembers" )
86 SC_SIMPLE_SERVICE_INFO( ScDPMember
, "ScDPMember", "com.sun.star.sheet.DataPilotSourceMember" )
88 // -----------------------------------------------------------------------
90 // property maps for PropertySetInfo
91 // DataDescription / NumberFormat are internal
93 // -----------------------------------------------------------------------
96 static sal_Bool
lcl_GetBoolFromAny( const uno::Any
& aAny
)
98 if ( aAny
.getValueTypeClass() == uno::TypeClass_BOOLEAN
)
99 return *(sal_Bool
*)aAny
.getValue();
103 static void lcl_SetBoolInAny( uno::Any
& rAny
, sal_Bool bValue
)
105 rAny
.setValue( &bValue
, getBooleanCppuType() );
108 // -----------------------------------------------------------------------
110 ScDPSource::ScDPSource( ScDPTableData
* pD
) :
113 bColumnGrand( true ), // default is true
115 bIgnoreEmptyRows( false ),
116 bRepeatIfEmpty( false ),
123 bResultOverflow( false ),
124 bPageFiltered( false ),
125 mpGrandTotalName(NULL
)
127 pData
->SetEmptyFlags( bIgnoreEmptyRows
, bRepeatIfEmpty
);
130 ScDPSource::~ScDPSource()
133 pDimensions
->release(); // ref-counted
137 delete[] pColResults
;
138 delete[] pRowResults
;
145 const OUString
* ScDPSource::GetGrandTotalName() const
147 return mpGrandTotalName
.get();
150 sal_uInt16
ScDPSource::GetOrientation(long nColumn
)
152 if (std::find(maColDims
.begin(), maColDims
.end(), nColumn
) != maColDims
.end())
153 return sheet::DataPilotFieldOrientation_COLUMN
;
155 if (std::find(maRowDims
.begin(), maRowDims
.end(), nColumn
) != maRowDims
.end())
156 return sheet::DataPilotFieldOrientation_ROW
;
158 if (std::find(maDataDims
.begin(), maDataDims
.end(), nColumn
) != maDataDims
.end())
159 return sheet::DataPilotFieldOrientation_DATA
;
161 if (std::find(maPageDims
.begin(), maPageDims
.end(), nColumn
) != maPageDims
.end())
162 return sheet::DataPilotFieldOrientation_PAGE
;
164 return sheet::DataPilotFieldOrientation_HIDDEN
;
167 long ScDPSource::GetDataDimensionCount()
169 return maDataDims
.size();
172 ScDPDimension
* ScDPSource::GetDataDimension(long nIndex
)
174 if (nIndex
< 0 || static_cast<size_t>(nIndex
) >= maDataDims
.size())
177 long nDimIndex
= maDataDims
[nIndex
];
178 return GetDimensionsObject()->getByIndex(nDimIndex
);
181 OUString
ScDPSource::GetDataDimName(long nIndex
)
184 ScDPDimension
* pDim
= GetDataDimension(nIndex
);
186 aRet
= pDim
->getName();
190 long ScDPSource::GetPosition(long nColumn
)
192 std::vector
<long>::const_iterator it
, itBeg
= maColDims
.begin(), itEnd
= maColDims
.end();
193 it
= std::find(itBeg
, itEnd
, nColumn
);
195 return std::distance(itBeg
, it
);
197 itBeg
= maRowDims
.begin();
198 itEnd
= maRowDims
.end();
199 it
= std::find(itBeg
, itEnd
, nColumn
);
201 return std::distance(itBeg
, it
);
203 itBeg
= maDataDims
.begin();
204 itEnd
= maDataDims
.end();
205 it
= std::find(itBeg
, itEnd
, nColumn
);
207 return std::distance(itBeg
, it
);
209 itBeg
= maPageDims
.begin();
210 itEnd
= maPageDims
.end();
211 it
= std::find(itBeg
, itEnd
, nColumn
);
213 return std::distance(itBeg
, it
);
220 bool testSubTotal( bool& rAllowed
, long nColumn
, const std::vector
<long>& rDims
, ScDPSource
* pSource
)
223 std::vector
<long>::const_iterator it
= rDims
.begin(), itEnd
= rDims
.end();
224 for (; it
!= itEnd
; ++it
)
229 if ( pSource
->IsDataLayoutDimension(nColumn
) )
231 // no subtotals for data layout dim, no matter where
236 // no subtotals if no other dim but data layout follows
238 if (it
!= itEnd
&& pSource
->IsDataLayoutDimension(*it
))
243 return true; // found
249 void removeDim( long nRemove
, std::vector
<long>& rDims
)
251 std::vector
<long>::iterator it
= std::find(rDims
.begin(), rDims
.end(), nRemove
);
252 if (it
!= rDims
.end())
258 sal_Bool
ScDPSource::SubTotalAllowed(long nColumn
)
260 //! cache this at ScDPResultData
261 bool bAllowed
= true;
262 if ( testSubTotal(bAllowed
, nColumn
, maColDims
, this) )
264 if ( testSubTotal(bAllowed
, nColumn
, maRowDims
, this) )
269 void ScDPSource::SetOrientation(long nColumn
, sal_uInt16 nNew
)
271 //! change to no-op if new orientation is equal to old?
273 // remove from old list
274 removeDim(nColumn
, maColDims
);
275 removeDim(nColumn
, maRowDims
);
276 removeDim(nColumn
, maDataDims
);
277 removeDim(nColumn
, maPageDims
);
282 case sheet::DataPilotFieldOrientation_COLUMN
:
283 maColDims
.push_back(nColumn
);
285 case sheet::DataPilotFieldOrientation_ROW
:
286 maRowDims
.push_back(nColumn
);
288 case sheet::DataPilotFieldOrientation_DATA
:
289 maDataDims
.push_back(nColumn
);
291 case sheet::DataPilotFieldOrientation_PAGE
:
292 maPageDims
.push_back(nColumn
);
294 // DataPilot Migration - Cache&&Performance
295 case sheet::DataPilotFieldOrientation_HIDDEN
:
298 OSL_FAIL( "ScDPSource::SetOrientation: unexpected orientation" );
303 sal_Bool
ScDPSource::IsDataLayoutDimension(long nDim
)
305 return nDim
== pData
->GetColumnCount();
308 sal_uInt16
ScDPSource::GetDataLayoutOrientation()
310 return GetOrientation(pData
->GetColumnCount());
313 sal_Bool
ScDPSource::IsDateDimension(long nDim
)
315 return pData
->IsDateDimension(nDim
);
318 ScDPDimensions
* ScDPSource::GetDimensionsObject()
322 pDimensions
= new ScDPDimensions(this);
323 pDimensions
->acquire(); // ref-counted
328 uno::Reference
<container::XNameAccess
> SAL_CALL
ScDPSource::getDimensions() throw(uno::RuntimeException
)
330 return GetDimensionsObject();
333 void ScDPSource::SetDupCount( long nNew
)
338 ScDPDimension
* ScDPSource::AddDuplicated(long /* nSource */, const OUString
& rNewName
)
340 OSL_ENSURE( pDimensions
, "AddDuplicated without dimensions?" );
344 long nOldDimCount
= pDimensions
->getCount();
345 for (long i
=0; i
<nOldDimCount
; i
++)
347 ScDPDimension
* pDim
= pDimensions
->getByIndex(i
);
348 if (pDim
&& pDim
->getName().equals(rNewName
))
350 //! test if pDim is a duplicate of source
355 SetDupCount( nDupCount
+ 1 );
356 pDimensions
->CountChanged(); // uses nDupCount
358 return pDimensions
->getByIndex( pDimensions
->getCount() - 1 );
361 long ScDPSource::GetSourceDim(long nDim
)
363 // original source dimension or data layout dimension?
364 if ( nDim
<= pData
->GetColumnCount() )
367 if ( nDim
< pDimensions
->getCount() )
369 ScDPDimension
* pDimObj
= pDimensions
->getByIndex( nDim
);
372 long nSource
= pDimObj
->GetSourceDim();
378 OSL_FAIL("GetSourceDim: wrong dim");
382 uno::Sequence
< uno::Sequence
<sheet::DataResult
> > SAL_CALL
ScDPSource::getResults()
383 throw(uno::RuntimeException
)
385 CreateRes_Impl(); // create pColResRoot and pRowResRoot
387 if ( bResultOverflow
) // set in CreateRes_Impl
389 // no results available
390 throw uno::RuntimeException();
393 long nColCount
= pColResRoot
->GetSize(pResData
->GetColStartMeasure());
394 long nRowCount
= pRowResRoot
->GetSize(pResData
->GetRowStartMeasure());
396 // allocate full sequence
397 //! leave out empty rows???
399 uno::Sequence
< uno::Sequence
<sheet::DataResult
> > aSeq( nRowCount
);
400 uno::Sequence
<sheet::DataResult
>* pRowAry
= aSeq
.getArray();
401 for (long nRow
= 0; nRow
< nRowCount
; nRow
++)
403 uno::Sequence
<sheet::DataResult
> aColSeq( nColCount
);
404 // use default values of DataResult
405 pRowAry
[nRow
] = aColSeq
;
408 ScDPResultFilterContext aFilterCxt
;
409 pRowResRoot
->FillDataResults(
410 pColResRoot
, aFilterCxt
, aSeq
, pResData
->GetRowStartMeasure());
412 maResFilterSet
.swap(aFilterCxt
.maFilterSet
); // Keep this data for GETPIVOTDATA.
417 uno::Sequence
<double> ScDPSource::getFilteredResults(
418 const uno::Sequence
<sheet::DataPilotFieldFilter
>& aFilters
)
419 throw (uno::RuntimeException
)
421 if (maResFilterSet
.empty())
422 getResults(); // Build result tree first.
424 // Get result values from the tree.
425 const ScDPResultTree::ValuesType
* pVals
= maResFilterSet
.getResults(aFilters
);
428 size_t n
= pVals
->size();
429 uno::Sequence
<double> aRet(n
);
430 for (size_t i
= 0; i
< n
; ++i
)
431 aRet
[i
] = (*pVals
)[i
];
436 if (aFilters
.getLength() == 1)
438 // Try to get result from the leaf nodes.
439 double fVal
= maResFilterSet
.getLeafResult(aFilters
[0]);
440 if (!rtl::math::isNan(fVal
))
442 uno::Sequence
<double> aRet(1);
448 return uno::Sequence
<double>();
451 void SAL_CALL
ScDPSource::refresh() throw(uno::RuntimeException
)
456 void SAL_CALL
ScDPSource::addRefreshListener( const uno::Reference
<util::XRefreshListener
>& )
457 throw(uno::RuntimeException
)
459 OSL_FAIL("not implemented"); //! exception?
462 void SAL_CALL
ScDPSource::removeRefreshListener( const uno::Reference
<util::XRefreshListener
>& )
463 throw(uno::RuntimeException
)
465 OSL_FAIL("not implemented"); //! exception?
468 Sequence
< Sequence
<Any
> > SAL_CALL
ScDPSource::getDrillDownData(const Sequence
<sheet::DataPilotFieldFilter
>& aFilters
)
469 throw (uno::RuntimeException
)
471 long nColumnCount
= GetData()->GetColumnCount();
473 vector
<ScDPFilteredCache::Criterion
> aFilterCriteria
;
474 sal_Int32 nFilterCount
= aFilters
.getLength();
475 for (sal_Int32 i
= 0; i
< nFilterCount
; ++i
)
477 const sheet::DataPilotFieldFilter
& rFilter
= aFilters
[i
];
478 const OUString
& aFieldName
= rFilter
.FieldName
;
479 for (long nCol
= 0; nCol
< nColumnCount
; ++nCol
)
481 if (aFieldName
.equals(pData
->getDimensionName(nCol
)))
483 ScDPDimension
* pDim
= GetDimensionsObject()->getByIndex( nCol
);
484 ScDPMembers
* pMembers
= pDim
->GetHierarchiesObject()->getByIndex(0)->
485 GetLevelsObject()->getByIndex(0)->GetMembersObject();
486 sal_Int32 nIndex
= pMembers
->GetIndexFromName( rFilter
.MatchValue
);
490 pMembers
->getByIndex(nIndex
)->FillItemData( aItem
);
491 aFilterCriteria
.push_back( ScDPFilteredCache::Criterion() );
492 aFilterCriteria
.back().mnFieldIndex
= nCol
;
493 aFilterCriteria
.back().mpFilter
.reset(
494 new ScDPFilteredCache::SingleFilter(aItem
));
500 // Take into account the visibilities of field members.
501 ScDPResultVisibilityData
aResVisData(this);
502 pRowResRoot
->FillVisibilityData(aResVisData
);
503 pColResRoot
->FillVisibilityData(aResVisData
);
504 aResVisData
.fillFieldFilters(aFilterCriteria
);
506 Sequence
< Sequence
<Any
> > aTabData
;
507 boost::unordered_set
<sal_Int32
> aCatDims
;
508 GetCategoryDimensionIndices(aCatDims
);
509 pData
->GetDrillDownData(aFilterCriteria
, aCatDims
, aTabData
);
513 OUString
ScDPSource::getDataDescription()
515 CreateRes_Impl(); // create pResData
518 if ( pResData
->GetMeasureCount() == 1 )
520 bool bTotalResult
= false;
521 aRet
= pResData
->GetMeasureString(0, true, SUBTOTAL_FUNC_NONE
, bTotalResult
);
524 // empty for more than one measure
529 void ScDPSource::setIgnoreEmptyRows(bool bSet
)
531 bIgnoreEmptyRows
= bSet
;
532 pData
->SetEmptyFlags( bIgnoreEmptyRows
, bRepeatIfEmpty
);
535 void ScDPSource::setRepeatIfEmpty(bool bSet
)
537 bRepeatIfEmpty
= bSet
;
538 pData
->SetEmptyFlags( bIgnoreEmptyRows
, bRepeatIfEmpty
);
541 void ScDPSource::disposeData()
543 maResFilterSet
.clear();
549 DELETEZ(pColResRoot
);
550 DELETEZ(pRowResRoot
);
552 delete[] pColResults
;
553 delete[] pRowResults
;
556 aColLevelList
.clear();
557 aRowLevelList
.clear();
562 pDimensions
->release(); // ref-counted
563 pDimensions
= NULL
; // settings have to be applied (from SaveData) again!
572 pData
->DisposeData(); // cached entries etc.
573 bPageFiltered
= false;
574 bResultOverflow
= false;
577 static long lcl_CountMinMembers(const vector
<ScDPDimension
*>& ppDim
, const vector
<ScDPLevel
*>& ppLevel
, long nLevels
)
579 // Calculate the product of the member count for those consecutive levels that
580 // have the "show all" flag, one following level, and the data layout dimension.
584 sal_Bool bWasShowAll
= sal_True
;
590 if ( nPos
+1 < nLevels
&& ppDim
[nPos
] == ppDim
[nPos
+1] )
592 OSL_FAIL("lcl_CountMinMembers: multiple levels from one dimension not implemented");
596 sal_Bool bDo
= false;
597 if ( ppDim
[nPos
]->getIsDataLayoutDimension() )
599 // data layout dim doesn't interfere with "show all" flags
600 nDataCount
= ppLevel
[nPos
]->GetMembersObject()->getCount();
601 if ( nDataCount
== 0 )
604 else if ( bWasShowAll
) // "show all" set for all following levels?
607 if ( !ppLevel
[nPos
]->getShowEmpty() )
609 // this level is counted, following ones are not
615 long nThisCount
= ppLevel
[nPos
]->GetMembersObject()->getMinMembers();
616 if ( nThisCount
== 0 )
618 nTotal
= 1; // empty level -> start counting from here
619 //! start with visible elements in this level?
623 if ( nTotal
>= LONG_MAX
/ nThisCount
)
624 return LONG_MAX
; // overflow
625 nTotal
*= nThisCount
;
630 // always include data layout dim, even after restarting
631 if ( nTotal
>= LONG_MAX
/ nDataCount
)
632 return LONG_MAX
; // overflow
633 nTotal
*= nDataCount
;
638 static long lcl_GetIndexFromName( const OUString rName
, const uno::Sequence
<OUString
>& rElements
)
640 long nCount
= rElements
.getLength();
641 const OUString
* pArray
= rElements
.getConstArray();
642 for (long nPos
=0; nPos
<nCount
; nPos
++)
643 if (pArray
[nPos
] == rName
)
646 return -1; // not found
649 void ScDPSource::FillCalcInfo(bool bIsRow
, ScDPTableData::CalcInfo
& rInfo
, bool &rHasAutoShow
)
651 const std::vector
<long>& rDims
= bIsRow
? maRowDims
: maColDims
;
652 std::vector
<long>::const_iterator it
= rDims
.begin(), itEnd
= rDims
.end();
653 for (; it
!= itEnd
; ++it
)
655 ScDPDimension
* pDim
= GetDimensionsObject()->getByIndex(*it
);
656 long nHierarchy
= pDim
->getUsedHierarchy();
657 if ( nHierarchy
>= pDim
->GetHierarchiesObject()->getCount() )
659 ScDPLevels
* pLevels
= pDim
->GetHierarchiesObject()->getByIndex(nHierarchy
)->GetLevelsObject();
660 long nCount
= pLevels
->getCount();
663 if (pDim
->getIsDataLayoutDimension() && maDataDims
.size() < 2)
667 for (long j
= 0; j
< nCount
; ++j
)
669 ScDPLevel
* pLevel
= pLevels
->getByIndex(j
);
670 pLevel
->EvaluateSortOrder();
672 // no layout flags for column fields, only for row fields
673 pLevel
->SetEnableLayout( bIsRow
);
675 if ( pLevel
->GetAutoShow().IsEnabled
)
680 rInfo
.aRowLevelDims
.push_back(*it
);
681 rInfo
.aRowDims
.push_back(pDim
);
682 rInfo
.aRowLevels
.push_back(pLevel
);
686 rInfo
.aColLevelDims
.push_back(*it
);
687 rInfo
.aColDims
.push_back(pDim
);
688 rInfo
.aColLevels
.push_back(pLevel
);
691 pLevel
->GetMembersObject(); // initialize for groups
698 class CategoryDimInserter
: std::unary_function
<long, void>
700 ScDPSource
& mrSource
;
701 boost::unordered_set
<sal_Int32
>& mrCatDims
;
703 CategoryDimInserter(ScDPSource
& rSource
, boost::unordered_set
<sal_Int32
>& rCatDims
) :
705 mrCatDims(rCatDims
) {}
707 void operator() (long nDim
)
709 if (!mrSource
.IsDataLayoutDimension(nDim
))
710 mrCatDims
.insert(nDim
);
716 void ScDPSource::GetCategoryDimensionIndices(boost::unordered_set
<sal_Int32
>& rCatDims
)
718 boost::unordered_set
<sal_Int32
> aCatDims
;
720 CategoryDimInserter
aInserter(*this, aCatDims
);
721 std::for_each(maColDims
.begin(), maColDims
.end(), aInserter
);
722 std::for_each(maRowDims
.begin(), maRowDims
.end(), aInserter
);
723 std::for_each(maPageDims
.begin(), maPageDims
.end(), aInserter
);
725 rCatDims
.swap(aCatDims
);
728 void ScDPSource::FilterCacheByPageDimensions()
730 // #i117661# Repeated calls to ScDPFilteredCache::filterByPageDimension
731 // are invalid because rows are only hidden, never shown again. If
732 // FilterCacheByPageDimensions is called again, the cache table must
733 // be re-initialized. Currently, CreateRes_Impl always uses a fresh cache
734 // because ScDBDocFunc::DataPilotUpdate calls InvalidateData.
738 SAL_WARN( "sc.core","tried to apply page field filters several times");
740 pData
->DisposeData();
741 pData
->CreateCacheTable(); // re-initialize the cache table
742 bPageFiltered
= false;
745 // filter table by page dimensions.
746 vector
<ScDPFilteredCache::Criterion
> aCriteria
;
747 vector
<long>::const_iterator it
= maPageDims
.begin(), itEnd
= maPageDims
.end();
748 for (; it
!= itEnd
; ++it
)
750 ScDPDimension
* pDim
= GetDimensionsObject()->getByIndex(*it
);
751 long nField
= pDim
->GetDimension();
753 ScDPMembers
* pMems
= pDim
->GetHierarchiesObject()->getByIndex(0)->
754 GetLevelsObject()->getByIndex(0)->GetMembersObject();
756 long nMemCount
= pMems
->getCount();
757 ScDPFilteredCache::Criterion aFilter
;
758 aFilter
.mnFieldIndex
= static_cast<sal_Int32
>(nField
);
759 aFilter
.mpFilter
.reset(new ScDPFilteredCache::GroupFilter
);
760 ScDPFilteredCache::GroupFilter
* pGrpFilter
=
761 static_cast<ScDPFilteredCache::GroupFilter
*>(aFilter
.mpFilter
.get());
762 for (long j
= 0; j
< nMemCount
; ++j
)
764 ScDPMember
* pMem
= pMems
->getByIndex(j
);
765 if (pMem
->isVisible())
768 pMem
->FillItemData(aData
);
769 pGrpFilter
->addMatchItem(aData
);
772 if (pGrpFilter
->getMatchItemCount() < static_cast<size_t>(nMemCount
))
773 // there is at least one invisible item. Add this filter criterion to the mix.
774 aCriteria
.push_back(aFilter
);
776 if (!pDim
|| !pDim
->HasSelectedPage())
779 const ScDPItemData
& rData
= pDim
->GetSelectedData();
780 aCriteria
.push_back(ScDPFilteredCache::Criterion());
781 ScDPFilteredCache::Criterion
& r
= aCriteria
.back();
782 r
.mnFieldIndex
= static_cast<sal_Int32
>(nField
);
783 r
.mpFilter
.reset(new ScDPFilteredCache::SingleFilter(rData
));
785 if (!aCriteria
.empty())
787 boost::unordered_set
<sal_Int32
> aCatDims
;
788 GetCategoryDimensionIndices(aCatDims
);
789 pData
->FilterCacheTable(aCriteria
, aCatDims
);
790 bPageFiltered
= true;
794 void ScDPSource::CreateRes_Impl()
799 sal_uInt16 nDataOrient
= GetDataLayoutOrientation();
800 if (maDataDims
.size() > 1 && ( nDataOrient
!= sheet::DataPilotFieldOrientation_COLUMN
&&
801 nDataOrient
!= sheet::DataPilotFieldOrientation_ROW
) )
803 // if more than one data dimension, data layout orientation must be set
804 SetOrientation( pData
->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW
);
805 nDataOrient
= sheet::DataPilotFieldOrientation_ROW
;
808 // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and
809 // eDataFunctions into a structure and use vector instead of static
810 // or pointer arrays.
811 vector
<OUString
> aDataNames
;
812 vector
<sheet::DataPilotFieldReference
> aDataRefValues
;
813 vector
<ScSubTotalFunc
> aDataFunctions
;
814 vector
<sal_uInt16
> aDataRefOrient
;
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 vector
<long>::const_iterator it
= maDataDims
.begin(), itEnd
= maDataDims
.end();
827 for (; it
!= itEnd
; ++it
)
829 // Get function for each data field.
830 long nDimIndex
= *it
;
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 aDataFunctions
.push_back(ScDPUtil::toSubTotalFunc(eUser
));
842 // Get reference field/item information.
843 aDataRefValues
.push_back(pDim
->GetReferenceValue());
844 sal_uInt16 nDataRefOrient
= sheet::DataPilotFieldOrientation_HIDDEN
; // default if not used
845 sal_Int32 eRefType
= aDataRefValues
.back().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(
852 aDataRefValues
.back().ReferenceField
, GetDimensionsObject()->getElementNames());
855 nDataRefOrient
= 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.
863 aDataRefOrient
.push_back(nDataRefOrient
);
865 aDataNames
.push_back(pDim
->getName());
867 //! modify user visible strings as in ScDPResultData::GetMeasureString instead!
869 aDataNames
.back() = ScDPUtil::getSourceDimensionName(aDataNames
.back());
871 //! if the name is overridden by user, a flag must be set
872 //! so the user defined name replaces the function string and field name.
874 //! the complete name (function and field) must be stored at the dimension
876 long nSource
= pDim
->GetSourceDim();
878 aInfo
.aDataSrcCols
.push_back(nSource
);
880 aInfo
.aDataSrcCols
.push_back(nDimIndex
);
883 pResData
= new ScDPResultData(*this);
884 pResData
->SetMeasureData(aDataFunctions
, aDataRefValues
, aDataRefOrient
, aDataNames
);
885 pResData
->SetDataLayoutOrientation(nDataOrient
);
886 pResData
->SetLateInit( bLateInit
);
888 bool bHasAutoShow
= false;
890 ScDPInitState aInitState
;
892 // Page field selections restrict the members shown in related fields
893 // (both in column and row fields). aInitState is filled with the page
894 // field selections, they are kept across the data iterator loop.
896 for (it
= maPageDims
.begin(), itEnd
= maPageDims
.end(); it
!= itEnd
; ++it
)
898 ScDPDimension
* pDim
= GetDimensionsObject()->getByIndex(*it
);
899 if ( pDim
->HasSelectedPage() )
900 aInitState
.AddMember(*it
, GetMemberId(*it
, pDim
->GetSelectedData()));
903 // Show grand total columns only when the option is set *and* there is at
904 // least one column field. Same for the grand total rows.
905 sal_uInt16 nDataLayoutOrient
= GetDataLayoutOrientation();
906 long nColDimCount2
= maColDims
.size() - (nDataLayoutOrient
== sheet::DataPilotFieldOrientation_COLUMN
? 1 : 0);
907 long nRowDimCount2
= maRowDims
.size() - (nDataLayoutOrient
== sheet::DataPilotFieldOrientation_ROW
? 1 : 0);
908 bool bShowColGrand
= bColumnGrand
&& nColDimCount2
> 0;
909 bool bShowRowGrand
= bRowGrand
&& nRowDimCount2
> 0;
910 pColResRoot
= new ScDPResultMember(pResData
, bShowColGrand
);
911 pRowResRoot
= new ScDPResultMember(pResData
, bShowRowGrand
);
913 FillCalcInfo(false, aInfo
, bHasAutoShow
);
914 long nColLevelCount
= aInfo
.aColLevels
.size();
916 pColResRoot
->InitFrom( aInfo
.aColDims
, aInfo
.aColLevels
, 0, aInitState
);
917 pColResRoot
->SetHasElements();
919 FillCalcInfo(true, aInfo
, bHasAutoShow
);
920 long nRowLevelCount
= aInfo
.aRowLevels
.size();
922 if ( nRowLevelCount
> 0 )
924 // disable layout flags for the innermost row field (level)
925 aInfo
.aRowLevels
[nRowLevelCount
-1]->SetEnableLayout( false );
928 pRowResRoot
->InitFrom( aInfo
.aRowDims
, aInfo
.aRowLevels
, 0, aInitState
);
929 pRowResRoot
->SetHasElements();
931 // initialize members object also for all page dimensions (needed for numeric groups)
932 for (it
= maPageDims
.begin(), itEnd
= maPageDims
.end(); it
!= itEnd
; ++it
)
934 ScDPDimension
* pDim
= GetDimensionsObject()->getByIndex(*it
);
935 long nHierarchy
= pDim
->getUsedHierarchy();
936 if ( nHierarchy
>= pDim
->GetHierarchiesObject()->getCount() )
939 ScDPLevels
* pLevels
= pDim
->GetHierarchiesObject()->getByIndex(nHierarchy
)->GetLevelsObject();
940 long nCount
= pLevels
->getCount();
941 for (long j
=0; j
<nCount
; j
++)
942 pLevels
->getByIndex(j
)->GetMembersObject(); // initialize for groups
945 // pre-check: calculate minimum number of result columns / rows from
946 // levels that have the "show all" flag set
948 long nMinColMembers
= lcl_CountMinMembers( aInfo
.aColDims
, aInfo
.aColLevels
, nColLevelCount
);
949 long nMinRowMembers
= lcl_CountMinMembers( aInfo
.aRowDims
, aInfo
.aRowLevels
, nRowLevelCount
);
951 if ( nMinColMembers
> MAXCOLCOUNT
/*SC_MINCOUNT_LIMIT*/ || nMinRowMembers
> SC_MINCOUNT_LIMIT
)
953 // resulting table is too big -> abort before calculating
954 // (this relies on late init, so no members are allocated in InitFrom above)
956 bResultOverflow
= true;
960 FilterCacheByPageDimensions();
962 aInfo
.aPageDims
.reserve(maPageDims
.size());
963 for (it
= maPageDims
.begin(), itEnd
= maPageDims
.end(); it
!= itEnd
; ++it
)
964 aInfo
.aPageDims
.push_back(*it
);
966 aInfo
.pInitState
= &aInitState
;
967 aInfo
.pColRoot
= pColResRoot
;
968 aInfo
.pRowRoot
= pRowResRoot
;
969 pData
->CalcResults(aInfo
, false);
971 pColResRoot
->CheckShowEmpty();
972 pRowResRoot
->CheckShowEmpty();
973 // ----------------------------------------------------------------
974 // With all data processed, calculate the final results:
976 // UpdateDataResults calculates all original results from the collected values,
977 // and stores them as reference values if needed.
978 pRowResRoot
->UpdateDataResults( pColResRoot
, pResData
->GetRowStartMeasure() );
980 if ( bHasAutoShow
) // do the double calculation only if AutoShow is used
982 // Find the desired members and set bAutoHidden flag for the others
983 pRowResRoot
->DoAutoShow( pColResRoot
);
985 // Reset all results to empty, so they can be built again with data for the
986 // desired members only.
987 pColResRoot
->ResetResults();
988 pRowResRoot
->ResetResults();
989 pData
->CalcResults(aInfo
, true);
991 // Call UpdateDataResults again, with the new (limited) values.
992 pRowResRoot
->UpdateDataResults( pColResRoot
, pResData
->GetRowStartMeasure() );
995 // SortMembers does the sorting by a result dimension, using the orginal results,
996 // but not running totals etc.
997 pRowResRoot
->SortMembers( pColResRoot
);
999 // UpdateRunningTotals calculates running totals along column/row dimensions,
1000 // differences from other members (named or relative), and column/row percentages
1002 // Running totals and relative differences need to be done using the sorted values.
1003 // Column/row percentages and index values must be done after sorting, because the
1004 // results may no longer be in the right order (row total for percentage of row is
1006 ScDPRunningTotalState
aRunning( pColResRoot
, pRowResRoot
);
1007 ScDPRowTotals aTotals
;
1008 pRowResRoot
->UpdateRunningTotals( pColResRoot
, pResData
->GetRowStartMeasure(), aRunning
, aTotals
);
1012 void ScDPSource::FillLevelList( sal_uInt16 nOrientation
, std::vector
<ScDPLevel
*> &rList
)
1016 std::vector
<long>* pDimIndex
= NULL
;
1017 switch (nOrientation
)
1019 case sheet::DataPilotFieldOrientation_COLUMN
:
1020 pDimIndex
= &maColDims
;
1022 case sheet::DataPilotFieldOrientation_ROW
:
1023 pDimIndex
= &maRowDims
;
1025 case sheet::DataPilotFieldOrientation_DATA
:
1026 pDimIndex
= &maDataDims
;
1028 case sheet::DataPilotFieldOrientation_PAGE
:
1029 pDimIndex
= &maPageDims
;
1032 OSL_FAIL( "ScDPSource::FillLevelList: unexpected orientation" );
1037 OSL_FAIL("invalid orientation");
1041 ScDPDimensions
* pDims
= GetDimensionsObject();
1042 std::vector
<long>::const_iterator it
= pDimIndex
->begin(), itEnd
= pDimIndex
->end();
1043 for (; it
!= itEnd
; ++it
)
1045 ScDPDimension
* pDim
= pDims
->getByIndex(*it
);
1046 OSL_ENSURE( pDim
->getOrientation() == nOrientation
, "orientations are wrong" );
1048 ScDPHierarchies
* pHiers
= pDim
->GetHierarchiesObject();
1049 long nHierarchy
= pDim
->getUsedHierarchy();
1050 if ( nHierarchy
>= pHiers
->getCount() )
1052 ScDPHierarchy
* pHier
= pHiers
->getByIndex(nHierarchy
);
1053 ScDPLevels
* pLevels
= pHier
->GetLevelsObject();
1054 long nLevCount
= pLevels
->getCount();
1055 for (long nLev
=0; nLev
<nLevCount
; nLev
++)
1057 ScDPLevel
* pLevel
= pLevels
->getByIndex(nLev
);
1058 rList
.push_back(pLevel
);
1063 void ScDPSource::FillMemberResults()
1065 if ( !pColResults
&& !pRowResults
)
1069 if ( bResultOverflow
) // set in CreateRes_Impl
1071 // no results available -> abort (leave empty)
1072 // exception is thrown in ScDPSource::getResults
1076 FillLevelList( sheet::DataPilotFieldOrientation_COLUMN
, aColLevelList
);
1077 long nColLevelCount
= aColLevelList
.size();
1080 long nColDimSize
= pColResRoot
->GetSize(pResData
->GetColStartMeasure());
1081 pColResults
= new uno::Sequence
<sheet::MemberResult
>[nColLevelCount
];
1082 for (long i
=0; i
<nColLevelCount
; i
++)
1083 pColResults
[i
].realloc(nColDimSize
);
1086 pColResRoot
->FillMemberResults( pColResults
, nPos
, pResData
->GetColStartMeasure(),
1087 sal_True
, NULL
, NULL
);
1090 FillLevelList( sheet::DataPilotFieldOrientation_ROW
, aRowLevelList
);
1091 long nRowLevelCount
= aRowLevelList
.size();
1094 long nRowDimSize
= pRowResRoot
->GetSize(pResData
->GetRowStartMeasure());
1095 pRowResults
= new uno::Sequence
<sheet::MemberResult
>[nRowLevelCount
];
1096 for (long i
=0; i
<nRowLevelCount
; i
++)
1097 pRowResults
[i
].realloc(nRowDimSize
);
1100 pRowResRoot
->FillMemberResults( pRowResults
, nPos
, pResData
->GetRowStartMeasure(),
1101 sal_True
, NULL
, NULL
);
1106 const uno::Sequence
<sheet::MemberResult
>* ScDPSource::GetMemberResults( ScDPLevel
* pLevel
)
1108 FillMemberResults();
1111 long nColCount
= aColLevelList
.size();
1112 for (i
=0; i
<nColCount
; i
++)
1114 ScDPLevel
* pColLevel
= aColLevelList
[i
];
1115 if ( pColLevel
== pLevel
)
1116 return pColResults
+i
;
1118 long nRowCount
= aRowLevelList
.size();
1119 for (i
=0; i
<nRowCount
; i
++)
1121 ScDPLevel
* pRowLevel
= aRowLevelList
[i
];
1122 if ( pRowLevel
== pLevel
)
1123 return pRowResults
+i
;
1130 uno::Reference
<beans::XPropertySetInfo
> SAL_CALL
ScDPSource::getPropertySetInfo()
1131 throw(uno::RuntimeException
)
1133 SolarMutexGuard aGuard
;
1134 using beans::PropertyAttribute::READONLY
;
1136 static const SfxItemPropertyMapEntry aDPSourceMap_Impl
[] =
1138 {MAP_CHAR_LEN(SC_UNO_DP_COLGRAND
), 0, &getBooleanCppuType(), 0, 0 },
1139 {MAP_CHAR_LEN(SC_UNO_DP_DATADESC
), 0, &getCppuType((OUString
*)0), beans::PropertyAttribute::READONLY
, 0 },
1140 {MAP_CHAR_LEN(SC_UNO_DP_IGNOREEMPTY
), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1141 {MAP_CHAR_LEN(SC_UNO_DP_REPEATEMPTY
), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1142 {MAP_CHAR_LEN(SC_UNO_DP_ROWGRAND
), 0, &getBooleanCppuType(), 0, 0 },
1143 {MAP_CHAR_LEN(SC_UNO_DP_ROWFIELDCOUNT
), 0, &getCppuType(static_cast<sal_Int32
*>(0)), READONLY
, 0 },
1144 {MAP_CHAR_LEN(SC_UNO_DP_COLUMNFIELDCOUNT
), 0, &getCppuType(static_cast<sal_Int32
*>(0)), READONLY
, 0 },
1145 {MAP_CHAR_LEN(SC_UNO_DP_DATAFIELDCOUNT
), 0, &getCppuType(static_cast<sal_Int32
*>(0)), READONLY
, 0 },
1146 {MAP_CHAR_LEN(SC_UNO_DP_GRANDTOTAL_NAME
), 0, &getCppuType(static_cast<OUString
*>(0)), 0, 0 },
1149 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
1150 new SfxItemPropertySetInfo( aDPSourceMap_Impl
);
1154 void SAL_CALL
ScDPSource::setPropertyValue( const OUString
& aPropertyName
, const uno::Any
& aValue
)
1155 throw(beans::UnknownPropertyException
, beans::PropertyVetoException
,
1156 lang::IllegalArgumentException
, lang::WrappedTargetException
,
1157 uno::RuntimeException
)
1159 if (aPropertyName
.equalsAscii(SC_UNO_DP_COLGRAND
))
1160 bColumnGrand
= lcl_GetBoolFromAny(aValue
);
1161 else if (aPropertyName
.equalsAscii(SC_UNO_DP_ROWGRAND
))
1162 bRowGrand
= lcl_GetBoolFromAny(aValue
);
1163 else if (aPropertyName
.equalsAscii(SC_UNO_DP_IGNOREEMPTY
))
1164 setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue
) );
1165 else if (aPropertyName
.equalsAscii(SC_UNO_DP_REPEATEMPTY
))
1166 setRepeatIfEmpty( lcl_GetBoolFromAny( aValue
) );
1167 else if (aPropertyName
.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME
))
1170 if (aValue
>>= aName
)
1171 mpGrandTotalName
.reset(new OUString(aName
));
1175 OSL_FAIL("unknown property");
1176 //! THROW( UnknownPropertyException() );
1180 uno::Any SAL_CALL
ScDPSource::getPropertyValue( const OUString
& aPropertyName
)
1181 throw(beans::UnknownPropertyException
, lang::WrappedTargetException
,
1182 uno::RuntimeException
)
1185 if ( aPropertyName
.equalsAscii( SC_UNO_DP_COLGRAND
) )
1186 lcl_SetBoolInAny(aRet
, bColumnGrand
);
1187 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_ROWGRAND
) )
1188 lcl_SetBoolInAny(aRet
, bRowGrand
);
1189 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_IGNOREEMPTY
) )
1190 lcl_SetBoolInAny(aRet
, bIgnoreEmptyRows
);
1191 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_REPEATEMPTY
) )
1192 lcl_SetBoolInAny(aRet
, bRepeatIfEmpty
);
1193 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_DATADESC
) ) // read-only
1194 aRet
<<= getDataDescription();
1195 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_ROWFIELDCOUNT
) ) // read-only
1196 aRet
<<= static_cast<sal_Int32
>(maRowDims
.size());
1197 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_COLUMNFIELDCOUNT
) ) // read-only
1198 aRet
<<= static_cast<sal_Int32
>(maColDims
.size());
1199 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_DATAFIELDCOUNT
) ) // read-only
1200 aRet
<<= static_cast<sal_Int32
>(maDataDims
.size());
1201 else if (aPropertyName
.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME
))
1203 if (mpGrandTotalName
.get())
1204 aRet
<<= *mpGrandTotalName
;
1208 OSL_FAIL("unknown property");
1209 //! THROW( UnknownPropertyException() );
1214 #if DEBUG_PIVOT_TABLE
1215 void ScDPSource::DumpResults() const
1217 std::cout
<< "+++++ column root" << std::endl
;
1218 pColResRoot
->Dump(1);
1219 std::cout
<< "+++++ row root" << std::endl
;
1220 pRowResRoot
->Dump(1);
1224 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource
)
1226 // -----------------------------------------------------------------------
1228 ScDPDimensions::ScDPDimensions( ScDPSource
* pSrc
) :
1234 // include data layout dimension and duplicated dimensions
1235 nDimCount
= pSource
->GetData()->GetColumnCount() + 1 + pSource
->GetDupCount();
1238 ScDPDimensions::~ScDPDimensions()
1244 for (long i
=0; i
<nDimCount
; i
++)
1246 ppDims
[i
]->release(); // ref-counted
1251 void ScDPDimensions::CountChanged()
1253 // include data layout dimension and duplicated dimensions
1254 long nNewCount
= pSource
->GetData()->GetColumnCount() + 1 + pSource
->GetDupCount();
1258 long nCopy
= std::min( nNewCount
, nDimCount
);
1259 ScDPDimension
** ppNew
= new ScDPDimension
*[nNewCount
];
1261 for (i
=0; i
<nCopy
; i
++) // copy existing dims
1262 ppNew
[i
] = ppDims
[i
];
1263 for (i
=nCopy
; i
<nNewCount
; i
++) // clear additional pointers
1265 for (i
=nCopy
; i
<nDimCount
; i
++) // delete old dims if count is decreased
1267 ppDims
[i
]->release(); // ref-counted
1272 nDimCount
= nNewCount
;
1275 // very simple XNameAccess implementation using getCount/getByIndex
1277 uno::Any SAL_CALL
ScDPDimensions::getByName( const OUString
& aName
)
1278 throw(container::NoSuchElementException
,
1279 lang::WrappedTargetException
, uno::RuntimeException
)
1281 long nCount
= getCount();
1282 for (long i
=0; i
<nCount
; i
++)
1283 if ( getByIndex(i
)->getName() == aName
)
1285 uno::Reference
<container::XNamed
> xNamed
= getByIndex(i
);
1291 throw container::NoSuchElementException();
1292 // return uno::Any();
1295 uno::Sequence
<OUString
> SAL_CALL
ScDPDimensions::getElementNames() throw(uno::RuntimeException
)
1297 long nCount
= getCount();
1298 uno::Sequence
<OUString
> aSeq(nCount
);
1299 OUString
* pArr
= aSeq
.getArray();
1300 for (long i
=0; i
<nCount
; i
++)
1301 pArr
[i
] = getByIndex(i
)->getName();
1305 sal_Bool SAL_CALL
ScDPDimensions::hasByName( const OUString
& aName
) throw(uno::RuntimeException
)
1307 long nCount
= getCount();
1308 for (long i
=0; i
<nCount
; i
++)
1309 if ( getByIndex(i
)->getName() == aName
)
1314 uno::Type SAL_CALL
ScDPDimensions::getElementType() throw(uno::RuntimeException
)
1316 return getCppuType((uno::Reference
<container::XNamed
>*)0);
1319 sal_Bool SAL_CALL
ScDPDimensions::hasElements() throw(uno::RuntimeException
)
1321 return ( getCount() > 0 );
1324 // end of XNameAccess implementation
1326 long ScDPDimensions::getCount() const
1328 // in tabular data, every column of source data is a dimension
1333 ScDPDimension
* ScDPDimensions::getByIndex(long nIndex
) const
1335 if ( nIndex
>= 0 && nIndex
< nDimCount
)
1339 ((ScDPDimensions
*)this)->ppDims
= new ScDPDimension
*[nDimCount
];
1340 for (long i
=0; i
<nDimCount
; i
++)
1343 if ( !ppDims
[nIndex
] )
1345 ppDims
[nIndex
] = new ScDPDimension( pSource
, nIndex
);
1346 ppDims
[nIndex
]->acquire(); // ref-counted
1349 return ppDims
[nIndex
];
1352 return NULL
; //! exception?
1355 // -----------------------------------------------------------------------
1357 ScDPDimension::ScDPDimension( ScDPSource
* pSrc
, long nD
) :
1360 pHierarchies( NULL
),
1362 nFunction( SUBTOTAL_FUNC_SUM
), // sum is default
1364 mpSubtotalName(NULL
),
1366 bHasSelectedPage( false ),
1367 pSelectedData( NULL
),
1368 mbHasHiddenMember(false)
1373 ScDPDimension::~ScDPDimension()
1378 pHierarchies
->release(); // ref-counted
1380 delete pSelectedData
;
1383 ScDPHierarchies
* ScDPDimension::GetHierarchiesObject()
1387 pHierarchies
= new ScDPHierarchies( pSource
, nDim
);
1388 pHierarchies
->acquire(); // ref-counted
1390 return pHierarchies
;
1393 const OUString
* ScDPDimension::GetLayoutName() const
1395 return mpLayoutName
.get();
1398 const OUString
* ScDPDimension::GetSubtotalName() const
1400 return mpSubtotalName
.get();
1403 uno::Reference
<container::XNameAccess
> SAL_CALL
ScDPDimension::getHierarchies()
1404 throw(uno::RuntimeException
)
1406 return GetHierarchiesObject();
1409 OUString SAL_CALL
ScDPDimension::getName() throw(uno::RuntimeException
)
1411 if (!aName
.isEmpty())
1414 return pSource
->GetData()->getDimensionName( nDim
);
1417 void SAL_CALL
ScDPDimension::setName( const OUString
& rNewName
) throw(uno::RuntimeException
)
1419 // used after cloning
1423 sal_uInt16
ScDPDimension::getOrientation() const
1425 return pSource
->GetOrientation( nDim
);
1428 void ScDPDimension::setOrientation(sal_uInt16 nNew
)
1430 pSource
->SetOrientation( nDim
, nNew
);
1433 long ScDPDimension::getPosition() const
1435 return pSource
->GetPosition( nDim
);
1438 bool ScDPDimension::getIsDataLayoutDimension() const
1440 return pSource
->GetData()->getIsDataLayoutDimension( nDim
);
1443 sal_uInt16
ScDPDimension::getFunction() const
1448 void ScDPDimension::setFunction(sal_uInt16 nNew
)
1453 long ScDPDimension::getUsedHierarchy() const
1458 void ScDPDimension::setUsedHierarchy(long /* nNew */)
1460 // #i52547# don't use the incomplete date hierarchy implementation - ignore the call
1463 ScDPDimension
* ScDPDimension::CreateCloneObject()
1465 OSL_ENSURE( nSourceDim
< 0, "recursive duplicate - not implemented" );
1467 //! set new name here, or temporary name ???
1468 OUString aNewName
= aName
;
1470 ScDPDimension
* pNew
= pSource
->AddDuplicated( nDim
, aNewName
);
1472 pNew
->aName
= aNewName
; //! here or in source?
1473 pNew
->nSourceDim
= nDim
; //! recursive?
1478 uno::Reference
<util::XCloneable
> SAL_CALL
ScDPDimension::createClone() throw(uno::RuntimeException
)
1480 return CreateCloneObject();
1483 const sheet::DataPilotFieldReference
& ScDPDimension::GetReferenceValue() const
1485 return aReferenceValue
;
1488 const ScDPItemData
& ScDPDimension::GetSelectedData()
1490 if ( !pSelectedData
)
1492 // find the named member to initialize pSelectedData from it, with name and value
1496 long nHierarchy
= getUsedHierarchy();
1497 if ( nHierarchy
>= GetHierarchiesObject()->getCount() )
1499 ScDPLevels
* pLevels
= GetHierarchiesObject()->getByIndex(nHierarchy
)->GetLevelsObject();
1500 long nLevCount
= pLevels
->getCount();
1501 if ( nLevel
< nLevCount
)
1503 ScDPMembers
* pMembers
= pLevels
->getByIndex(nLevel
)->GetMembersObject();
1505 //! merge with ScDPMembers::getByName
1506 long nCount
= pMembers
->getCount();
1507 for (long i
=0; i
<nCount
&& !pSelectedData
; i
++)
1509 ScDPMember
* pMember
= pMembers
->getByIndex(i
);
1510 if (aSelectedPage
.equals(pMember
->GetNameStr()))
1512 pSelectedData
= new ScDPItemData();
1513 pMember
->FillItemData( *pSelectedData
);
1518 if ( !pSelectedData
)
1519 pSelectedData
= new ScDPItemData(aSelectedPage
); // default - name only
1522 return *pSelectedData
;
1527 uno::Reference
<beans::XPropertySetInfo
> SAL_CALL
ScDPDimension::getPropertySetInfo()
1528 throw(uno::RuntimeException
)
1530 SolarMutexGuard aGuard
;
1532 static const SfxItemPropertyMapEntry aDPDimensionMap_Impl
[] =
1534 {MAP_CHAR_LEN(SC_UNO_DP_FILTER
), 0, &getCppuType((uno::Sequence
<sheet::TableFilterField
>*)0), 0, 0 },
1535 {MAP_CHAR_LEN(SC_UNO_DP_FLAGS
), 0, &getCppuType((sal_Int32
*)0), beans::PropertyAttribute::READONLY
, 0 },
1536 {MAP_CHAR_LEN(SC_UNO_DP_FUNCTION
), 0, &getCppuType((sheet::GeneralFunction
*)0), 0, 0 },
1537 {MAP_CHAR_LEN(SC_UNO_DP_ISDATALAYOUT
), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY
, 0 },
1538 {MAP_CHAR_LEN(SC_UNO_DP_NUMBERFO
), 0, &getCppuType((sal_Int32
*)0), beans::PropertyAttribute::READONLY
, 0 },
1539 {MAP_CHAR_LEN(SC_UNO_DP_ORIENTATION
), 0, &getCppuType((sheet::DataPilotFieldOrientation
*)0), 0, 0 },
1540 {MAP_CHAR_LEN(SC_UNO_DP_ORIGINAL
), 0, &getCppuType((uno::Reference
<container::XNamed
>*)0), beans::PropertyAttribute::READONLY
, 0 },
1541 {MAP_CHAR_LEN(SC_UNO_DP_ORIGINAL_POS
), 0, &getCppuType((sal_Int32
*)0), 0, 0 },
1542 {MAP_CHAR_LEN(SC_UNO_DP_POSITION
), 0, &getCppuType((sal_Int32
*)0), 0, 0 },
1543 {MAP_CHAR_LEN(SC_UNO_DP_REFVALUE
), 0, &getCppuType((sheet::DataPilotFieldReference
*)0), 0, 0 },
1544 {MAP_CHAR_LEN(SC_UNO_DP_USEDHIERARCHY
), 0, &getCppuType((sal_Int32
*)0), 0, 0 },
1545 {MAP_CHAR_LEN(SC_UNO_DP_LAYOUTNAME
), 0, &getCppuType(static_cast<OUString
*>(0)), 0, 0 },
1546 {MAP_CHAR_LEN(SC_UNO_DP_FIELD_SUBTOTALNAME
), 0, &getCppuType(static_cast<OUString
*>(0)), 0, 0 },
1547 {MAP_CHAR_LEN(SC_UNO_DP_HAS_HIDDEN_MEMBER
), 0, &getBooleanCppuType(), 0, 0 },
1550 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
1551 new SfxItemPropertySetInfo( aDPDimensionMap_Impl
);
1555 void SAL_CALL
ScDPDimension::setPropertyValue( const OUString
& aPropertyName
, const uno::Any
& aValue
)
1556 throw(beans::UnknownPropertyException
, beans::PropertyVetoException
,
1557 lang::IllegalArgumentException
, lang::WrappedTargetException
,
1558 uno::RuntimeException
)
1560 if ( aPropertyName
.equalsAscii( SC_UNO_DP_USEDHIERARCHY
) )
1563 if (aValue
>>= nInt
)
1564 setUsedHierarchy( nInt
);
1566 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_ORIENTATION
) )
1568 sheet::DataPilotFieldOrientation eEnum
;
1569 if (aValue
>>= eEnum
)
1570 setOrientation( sal::static_int_cast
<sal_uInt16
>(eEnum
) );
1572 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_FUNCTION
) )
1574 sheet::GeneralFunction eEnum
;
1575 if (aValue
>>= eEnum
)
1576 setFunction( sal::static_int_cast
<sal_uInt16
>(eEnum
) );
1578 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_REFVALUE
) )
1579 aValue
>>= aReferenceValue
;
1580 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_FILTER
) )
1582 sal_Bool bDone
= false;
1583 uno::Sequence
<sheet::TableFilterField
> aSeq
;
1584 if (aValue
>>= aSeq
)
1586 sal_Int32 nLength
= aSeq
.getLength();
1590 bHasSelectedPage
= false;
1593 else if ( nLength
== 1 )
1595 const sheet::TableFilterField
& rField
= aSeq
[0];
1596 if ( rField
.Field
== 0 && rField
.Operator
== sheet::FilterOperator_EQUAL
&& !rField
.IsNumeric
)
1598 aSelectedPage
= rField
.StringValue
;
1599 bHasSelectedPage
= true;
1606 OSL_FAIL("Filter property is not a single string");
1607 throw lang::IllegalArgumentException();
1609 DELETEZ( pSelectedData
); // invalid after changing aSelectedPage
1611 else if (aPropertyName
.equalsAscii(SC_UNO_DP_LAYOUTNAME
))
1614 if (aValue
>>= aTmpName
)
1615 mpLayoutName
.reset(new OUString(aTmpName
));
1617 else if (aPropertyName
.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME
))
1620 if (aValue
>>= aTmpName
)
1621 mpSubtotalName
.reset(new OUString(aTmpName
));
1623 else if (aPropertyName
.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER
))
1627 mbHasHiddenMember
= b
;
1631 OSL_FAIL("unknown property");
1632 //! THROW( UnknownPropertyException() );
1636 uno::Any SAL_CALL
ScDPDimension::getPropertyValue( const OUString
& aPropertyName
)
1637 throw(beans::UnknownPropertyException
, lang::WrappedTargetException
,
1638 uno::RuntimeException
)
1641 if ( aPropertyName
.equalsAscii( SC_UNO_DP_POSITION
) )
1642 aRet
<<= (sal_Int32
) getPosition();
1643 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_USEDHIERARCHY
) )
1644 aRet
<<= (sal_Int32
) getUsedHierarchy();
1645 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_ORIENTATION
) )
1647 sheet::DataPilotFieldOrientation eVal
= (sheet::DataPilotFieldOrientation
)getOrientation();
1650 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_FUNCTION
) )
1652 sheet::GeneralFunction eVal
= (sheet::GeneralFunction
)getFunction();
1655 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_REFVALUE
) )
1656 aRet
<<= aReferenceValue
;
1657 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_ISDATALAYOUT
) ) // read-only properties
1658 lcl_SetBoolInAny( aRet
, getIsDataLayoutDimension() );
1659 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_NUMBERFO
) )
1661 sal_Int32 nFormat
= 0;
1662 sheet::GeneralFunction eFunc
= (sheet::GeneralFunction
)getFunction();
1663 // #i63745# don't use source format for "count"
1664 if ( eFunc
!= sheet::GeneralFunction_COUNT
&& eFunc
!= sheet::GeneralFunction_COUNTNUMS
)
1665 nFormat
= pSource
->GetData()->GetNumberFormat( ( nSourceDim
>= 0 ) ? nSourceDim
: nDim
);
1667 switch ( aReferenceValue
.ReferenceType
)
1669 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE
:
1670 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE
:
1671 case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE
:
1672 case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE
:
1673 case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE
:
1674 nFormat
= pSource
->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset
)NF_PERCENT_DEC2
);
1676 case sheet::DataPilotFieldReferenceType::INDEX
:
1677 nFormat
= pSource
->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset
)NF_NUMBER_SYSTEM
);
1685 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_ORIGINAL
) )
1687 uno::Reference
<container::XNamed
> xOriginal
;
1688 if (nSourceDim
>= 0)
1689 xOriginal
= pSource
->GetDimensionsObject()->getByIndex(nSourceDim
);
1692 else if (aPropertyName
.equalsAscii(SC_UNO_DP_ORIGINAL_POS
))
1694 sal_Int32 nPos
= static_cast<sal_Int32
>(nSourceDim
);
1697 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_FILTER
) )
1699 if ( bHasSelectedPage
)
1701 // single filter field: first field equal to selected string
1702 sheet::TableFilterField
aField( sheet::FilterConnection_AND
, 0,
1703 sheet::FilterOperator_EQUAL
, false, 0.0, aSelectedPage
);
1704 aRet
<<= uno::Sequence
<sheet::TableFilterField
>( &aField
, 1 );
1707 aRet
<<= uno::Sequence
<sheet::TableFilterField
>(0);
1709 else if (aPropertyName
.equalsAscii(SC_UNO_DP_LAYOUTNAME
))
1710 aRet
<<= mpLayoutName
.get() ? *mpLayoutName
: OUString("");
1711 else if (aPropertyName
.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME
))
1712 aRet
<<= mpSubtotalName
.get() ? *mpSubtotalName
: OUString("");
1713 else if (aPropertyName
.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER
))
1714 aRet
<<= static_cast<sal_Bool
>(mbHasHiddenMember
);
1715 else if (aPropertyName
.equalsAscii(SC_UNO_DP_FLAGS
))
1717 sal_Int32 nFlags
= 0; // tabular data: all orientations are possible
1722 OSL_FAIL("unknown property");
1723 //! THROW( UnknownPropertyException() );
1728 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension
)
1730 // -----------------------------------------------------------------------
1732 ScDPHierarchies::ScDPHierarchies( ScDPSource
* pSrc
, long nD
) :
1739 // date columns have 3 hierarchies (flat/quarter/week), other columns only one
1741 // #i52547# don't offer the incomplete date hierarchy implementation
1745 ScDPHierarchies::~ScDPHierarchies()
1751 for (long i
=0; i
<nHierCount
; i
++)
1753 ppHiers
[i
]->release(); // ref-counted
1758 // very simple XNameAccess implementation using getCount/getByIndex
1760 uno::Any SAL_CALL
ScDPHierarchies::getByName( const OUString
& aName
)
1761 throw(container::NoSuchElementException
,
1762 lang::WrappedTargetException
, uno::RuntimeException
)
1764 long nCount
= getCount();
1765 for (long i
=0; i
<nCount
; i
++)
1766 if ( getByIndex(i
)->getName() == aName
)
1768 uno::Reference
<container::XNamed
> xNamed
= getByIndex(i
);
1774 throw container::NoSuchElementException();
1777 uno::Sequence
<OUString
> SAL_CALL
ScDPHierarchies::getElementNames() throw(uno::RuntimeException
)
1779 long nCount
= getCount();
1780 uno::Sequence
<OUString
> aSeq(nCount
);
1781 OUString
* pArr
= aSeq
.getArray();
1782 for (long i
=0; i
<nCount
; i
++)
1783 pArr
[i
] = getByIndex(i
)->getName();
1787 sal_Bool SAL_CALL
ScDPHierarchies::hasByName( const OUString
& aName
) throw(uno::RuntimeException
)
1789 long nCount
= getCount();
1790 for (long i
=0; i
<nCount
; i
++)
1791 if ( getByIndex(i
)->getName() == aName
)
1796 uno::Type SAL_CALL
ScDPHierarchies::getElementType() throw(uno::RuntimeException
)
1798 return getCppuType((uno::Reference
<container::XNamed
>*)0);
1801 sal_Bool SAL_CALL
ScDPHierarchies::hasElements() throw(uno::RuntimeException
)
1803 return ( getCount() > 0 );
1806 // end of XNameAccess implementation
1808 long ScDPHierarchies::getCount() const
1813 ScDPHierarchy
* ScDPHierarchies::getByIndex(long nIndex
) const
1815 // pass hierarchy index to new object in case the implementation
1816 // will be extended to more than one hierarchy
1818 if ( nIndex
>= 0 && nIndex
< nHierCount
)
1822 ((ScDPHierarchies
*)this)->ppHiers
= new ScDPHierarchy
*[nHierCount
];
1823 for (long i
=0; i
<nHierCount
; i
++)
1826 if ( !ppHiers
[nIndex
] )
1828 ppHiers
[nIndex
] = new ScDPHierarchy( pSource
, nDim
, nIndex
);
1829 ppHiers
[nIndex
]->acquire(); // ref-counted
1832 return ppHiers
[nIndex
];
1835 return NULL
; //! exception?
1838 // -----------------------------------------------------------------------
1840 ScDPHierarchy::ScDPHierarchy( ScDPSource
* pSrc
, long nD
, long nH
) :
1849 ScDPHierarchy::~ScDPHierarchy()
1854 pLevels
->release(); // ref-counted
1857 ScDPLevels
* ScDPHierarchy::GetLevelsObject()
1861 pLevels
= new ScDPLevels( pSource
, nDim
, nHier
);
1862 pLevels
->acquire(); // ref-counted
1867 uno::Reference
<container::XNameAccess
> SAL_CALL
ScDPHierarchy::getLevels()
1868 throw(uno::RuntimeException
)
1870 return GetLevelsObject();
1873 OUString SAL_CALL
ScDPHierarchy::getName() throw(uno::RuntimeException
)
1875 OUString aRet
; //! globstr-ID !!!!
1878 case SC_DAPI_HIERARCHY_FLAT
:
1880 break; //! name ???????
1881 case SC_DAPI_HIERARCHY_QUARTER
:
1883 break; //! name ???????
1884 case SC_DAPI_HIERARCHY_WEEK
:
1886 break; //! name ???????
1888 OSL_FAIL( "ScDPHierarchy::getName: unexpected hierarchy" );
1894 void SAL_CALL
ScDPHierarchy::setName( const OUString
& /* rNewName */ ) throw(uno::RuntimeException
)
1896 OSL_FAIL("not implemented"); //! exception?
1899 // -----------------------------------------------------------------------
1901 ScDPLevels::ScDPLevels( ScDPSource
* pSrc
, long nD
, long nH
) :
1909 // text columns have only one level
1911 long nSrcDim
= pSource
->GetSourceDim( nDim
);
1912 if ( pSource
->IsDateDimension( nSrcDim
) )
1916 case SC_DAPI_HIERARCHY_FLAT
: nLevCount
= SC_DAPI_FLAT_LEVELS
; break;
1917 case SC_DAPI_HIERARCHY_QUARTER
: nLevCount
= SC_DAPI_QUARTER_LEVELS
; break;
1918 case SC_DAPI_HIERARCHY_WEEK
: nLevCount
= SC_DAPI_WEEK_LEVELS
; break;
1920 OSL_FAIL("wrong hierarchy");
1928 ScDPLevels::~ScDPLevels()
1934 for (long i
=0; i
<nLevCount
; i
++)
1936 ppLevs
[i
]->release(); // ref-counted
1941 // very simple XNameAccess implementation using getCount/getByIndex
1943 uno::Any SAL_CALL
ScDPLevels::getByName( const OUString
& aName
)
1944 throw(container::NoSuchElementException
,
1945 lang::WrappedTargetException
, uno::RuntimeException
)
1947 long nCount
= getCount();
1948 for (long i
=0; i
<nCount
; i
++)
1949 if ( getByIndex(i
)->getName() == aName
)
1951 uno::Reference
<container::XNamed
> xNamed
= getByIndex(i
);
1957 throw container::NoSuchElementException();
1960 uno::Sequence
<OUString
> SAL_CALL
ScDPLevels::getElementNames() throw(uno::RuntimeException
)
1962 long nCount
= getCount();
1963 uno::Sequence
<OUString
> aSeq(nCount
);
1964 OUString
* pArr
= aSeq
.getArray();
1965 for (long i
=0; i
<nCount
; i
++)
1966 pArr
[i
] = getByIndex(i
)->getName();
1970 sal_Bool SAL_CALL
ScDPLevels::hasByName( const OUString
& aName
) throw(uno::RuntimeException
)
1972 long nCount
= getCount();
1973 for (long i
=0; i
<nCount
; i
++)
1974 if ( getByIndex(i
)->getName() == aName
)
1979 uno::Type SAL_CALL
ScDPLevels::getElementType() throw(uno::RuntimeException
)
1981 return getCppuType((uno::Reference
<container::XNamed
>*)0);
1984 sal_Bool SAL_CALL
ScDPLevels::hasElements() throw(uno::RuntimeException
)
1986 return ( getCount() > 0 );
1989 // end of XNameAccess implementation
1991 long ScDPLevels::getCount() const
1996 ScDPLevel
* ScDPLevels::getByIndex(long nIndex
) const
1998 if ( nIndex
>= 0 && nIndex
< nLevCount
)
2002 ((ScDPLevels
*)this)->ppLevs
= new ScDPLevel
*[nLevCount
];
2003 for (long i
=0; i
<nLevCount
; i
++)
2006 if ( !ppLevs
[nIndex
] )
2008 ppLevs
[nIndex
] = new ScDPLevel( pSource
, nDim
, nHier
, nIndex
);
2009 ppLevs
[nIndex
]->acquire(); // ref-counted
2012 return ppLevs
[nIndex
];
2015 return NULL
; //! exception?
2018 // -----------------------------------------------------------------------
2020 class ScDPGlobalMembersOrder
2023 sal_Bool bAscending
;
2026 ScDPGlobalMembersOrder( ScDPLevel
& rLev
, sal_Bool bAsc
) :
2030 ~ScDPGlobalMembersOrder() {}
2032 sal_Bool
operator()( sal_Int32 nIndex1
, sal_Int32 nIndex2
) const;
2035 sal_Bool
ScDPGlobalMembersOrder::operator()( sal_Int32 nIndex1
, sal_Int32 nIndex2
) const
2037 sal_Int32 nCompare
= 0;
2038 // seems that some ::std::sort() implementations pass the same index twice
2039 if( nIndex1
!= nIndex2
)
2041 ScDPMembers
* pMembers
= rLevel
.GetMembersObject();
2042 ScDPMember
* pMember1
= pMembers
->getByIndex(nIndex1
);
2043 ScDPMember
* pMember2
= pMembers
->getByIndex(nIndex2
);
2044 nCompare
= pMember1
->Compare( *pMember2
);
2046 return bAscending
? (nCompare
< 0) : (nCompare
> 0);
2049 // -----------------------------------------------------------------------
2051 ScDPLevel::ScDPLevel( ScDPSource
* pSrc
, long nD
, long nH
, long nL
) :
2057 aSortInfo( EMPTY_OUSTRING
, sal_True
, sheet::DataPilotFieldSortMode::NAME
), // default: sort by name
2060 bShowEmpty( false ),
2061 bEnableLayout( false )
2064 // aSubTotals is empty
2067 ScDPLevel::~ScDPLevel()
2072 pMembers
->release(); // ref-counted
2075 void ScDPLevel::EvaluateSortOrder()
2077 switch (aSortInfo
.Mode
)
2079 case sheet::DataPilotFieldSortMode::DATA
:
2081 // find index of measure (index among data dimensions)
2083 long nMeasureCount
= pSource
->GetDataDimensionCount();
2084 for (long nMeasure
=0; nMeasure
<nMeasureCount
; nMeasure
++)
2086 if (pSource
->GetDataDimName(nMeasure
).equals(aSortInfo
.Field
))
2088 nSortMeasure
= nMeasure
;
2093 //! error if not found?
2096 case sheet::DataPilotFieldSortMode::MANUAL
:
2097 case sheet::DataPilotFieldSortMode::NAME
:
2099 ScDPMembers
* pLocalMembers
= GetMembersObject();
2100 long nCount
= pLocalMembers
->getCount();
2102 aGlobalOrder
.resize( nCount
);
2103 for (long nPos
=0; nPos
<nCount
; nPos
++)
2104 aGlobalOrder
[nPos
] = nPos
;
2106 // allow manual or name (manual is always ascending)
2107 sal_Bool bAscending
= ( aSortInfo
.Mode
== sheet::DataPilotFieldSortMode::MANUAL
|| aSortInfo
.IsAscending
);
2108 ScDPGlobalMembersOrder
aComp( *this, bAscending
);
2109 ::std::sort( aGlobalOrder
.begin(), aGlobalOrder
.end(), aComp
);
2114 if ( aAutoShowInfo
.IsEnabled
)
2116 // find index of measure (index among data dimensions)
2118 long nMeasureCount
= pSource
->GetDataDimensionCount();
2119 for (long nMeasure
=0; nMeasure
<nMeasureCount
; nMeasure
++)
2121 if (pSource
->GetDataDimName(nMeasure
).equals(aAutoShowInfo
.DataField
))
2123 nAutoMeasure
= nMeasure
;
2128 //! error if not found?
2132 void ScDPLevel::SetEnableLayout(bool bSet
)
2134 bEnableLayout
= bSet
;
2137 ScDPMembers
* ScDPLevel::GetMembersObject()
2141 pMembers
= new ScDPMembers( pSource
, nDim
, nHier
, nLev
);
2142 pMembers
->acquire(); // ref-counted
2147 uno::Reference
<container::XNameAccess
> SAL_CALL
ScDPLevel::getMembers() throw(uno::RuntimeException
)
2149 return GetMembersObject();
2152 uno::Sequence
<sheet::MemberResult
> SAL_CALL
ScDPLevel::getResults() throw(uno::RuntimeException
)
2154 const uno::Sequence
<sheet::MemberResult
>* pRes
= pSource
->GetMemberResults( this );
2158 return uno::Sequence
<sheet::MemberResult
>(0); //! Error?
2161 OUString SAL_CALL
ScDPLevel::getName() throw(uno::RuntimeException
)
2163 long nSrcDim
= pSource
->GetSourceDim( nDim
);
2164 if ( pSource
->IsDateDimension( nSrcDim
) )
2166 OUString aRet
; //! globstr-ID !!!!
2168 if ( nHier
== SC_DAPI_HIERARCHY_QUARTER
)
2172 case SC_DAPI_LEVEL_YEAR
:
2175 case SC_DAPI_LEVEL_QUARTER
:
2178 case SC_DAPI_LEVEL_MONTH
:
2181 case SC_DAPI_LEVEL_DAY
:
2185 OSL_FAIL( "ScDPLevel::getName: unexpected level" );
2189 else if ( nHier
== SC_DAPI_HIERARCHY_WEEK
)
2193 case SC_DAPI_LEVEL_YEAR
:
2196 case SC_DAPI_LEVEL_WEEK
:
2199 case SC_DAPI_LEVEL_WEEKDAY
:
2203 OSL_FAIL( "ScDPLevel::getName: unexpected level" );
2207 if (!aRet
.isEmpty())
2211 ScDPDimension
* pDim
= pSource
->GetDimensionsObject()->getByIndex(nSrcDim
);
2215 return pDim
->getName();
2218 void SAL_CALL
ScDPLevel::setName( const OUString
& /* rNewName */ ) throw(uno::RuntimeException
)
2220 OSL_FAIL("not implemented"); //! exception?
2223 uno::Sequence
<sheet::GeneralFunction
> ScDPLevel::getSubTotals() const
2225 //! separate functions for settings and evaluation?
2227 long nSrcDim
= pSource
->GetSourceDim( nDim
);
2228 if ( !pSource
->SubTotalAllowed( nSrcDim
) )
2229 return uno::Sequence
<sheet::GeneralFunction
>(0);
2234 bool ScDPLevel::getShowEmpty() const
2241 uno::Reference
<beans::XPropertySetInfo
> SAL_CALL
ScDPLevel::getPropertySetInfo()
2242 throw(uno::RuntimeException
)
2244 SolarMutexGuard aGuard
;
2246 static const SfxItemPropertyMapEntry aDPLevelMap_Impl
[] =
2248 //! change type of AutoShow/Layout/Sorting to API struct when available
2249 {MAP_CHAR_LEN(SC_UNO_DP_AUTOSHOW
), 0, &getCppuType((sheet::DataPilotFieldAutoShowInfo
*)0), 0, 0 },
2250 {MAP_CHAR_LEN(SC_UNO_DP_LAYOUT
), 0, &getCppuType((sheet::DataPilotFieldLayoutInfo
*)0), 0, 0 },
2251 {MAP_CHAR_LEN(SC_UNO_DP_SHOWEMPTY
), 0, &getBooleanCppuType(), 0, 0 },
2252 {MAP_CHAR_LEN(SC_UNO_DP_SORTING
), 0, &getCppuType((sheet::DataPilotFieldSortInfo
*)0), 0, 0 },
2253 {MAP_CHAR_LEN(SC_UNO_DP_SUBTOTAL
), 0, &getCppuType((uno::Sequence
<sheet::GeneralFunction
>*)0), 0, 0 },
2256 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
2257 new SfxItemPropertySetInfo( aDPLevelMap_Impl
);
2261 void SAL_CALL
ScDPLevel::setPropertyValue( const OUString
& aPropertyName
, const uno::Any
& aValue
)
2262 throw(beans::UnknownPropertyException
, beans::PropertyVetoException
,
2263 lang::IllegalArgumentException
, lang::WrappedTargetException
,
2264 uno::RuntimeException
)
2266 if ( aPropertyName
.equalsAscii( SC_UNO_DP_SHOWEMPTY
) )
2267 bShowEmpty
= lcl_GetBoolFromAny(aValue
);
2268 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_SUBTOTAL
) )
2269 aValue
>>= aSubTotals
;
2270 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_SORTING
) )
2271 aValue
>>= aSortInfo
;
2272 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_AUTOSHOW
) )
2273 aValue
>>= aAutoShowInfo
;
2274 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_LAYOUT
) )
2275 aValue
>>= aLayoutInfo
;
2278 OSL_FAIL("unknown property");
2282 uno::Any SAL_CALL
ScDPLevel::getPropertyValue( const OUString
& aPropertyName
)
2283 throw(beans::UnknownPropertyException
, lang::WrappedTargetException
,
2284 uno::RuntimeException
)
2287 if ( aPropertyName
.equalsAscii( SC_UNO_DP_SHOWEMPTY
) )
2288 lcl_SetBoolInAny(aRet
, bShowEmpty
);
2289 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_SUBTOTAL
) )
2291 uno::Sequence
<sheet::GeneralFunction
> aSeq
= getSubTotals(); //! avoid extra copy?
2294 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_SORTING
) )
2296 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_AUTOSHOW
) )
2297 aRet
<<= aAutoShowInfo
;
2298 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_LAYOUT
) )
2299 aRet
<<= aLayoutInfo
;
2300 else if (aPropertyName
.equalsAscii(SC_UNO_DP_LAYOUTNAME
))
2302 // read only property
2303 long nSrcDim
= pSource
->GetSourceDim(nDim
);
2304 ScDPDimension
* pDim
= pSource
->GetDimensionsObject()->getByIndex(nSrcDim
);
2308 const OUString
* pLayoutName
= pDim
->GetLayoutName();
2312 aRet
<<= *pLayoutName
;
2316 OSL_FAIL("unknown property");
2321 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel
)
2323 // -----------------------------------------------------------------------
2325 ScDPMembers::ScDPMembers( ScDPSource
* pSrc
, long nD
, long nH
, long nL
) :
2333 long nSrcDim
= pSource
->GetSourceDim( nDim
);
2334 if ( pSource
->IsDataLayoutDimension(nSrcDim
) )
2335 nMbrCount
= pSource
->GetDataDimensionCount();
2336 else if ( nHier
!= SC_DAPI_HIERARCHY_FLAT
&& pSource
->IsDateDimension( nSrcDim
) )
2339 if ( nHier
== SC_DAPI_HIERARCHY_QUARTER
)
2343 case SC_DAPI_LEVEL_YEAR
:
2345 const ScDPItemData
* pLastNumData
= NULL
;
2346 for ( SCROW n
= 0 ;n
<GetSrcItemsCount() ; n
-- )
2348 const ScDPItemData
* pData
= GetSrcItemDataByIndex( n
);
2349 if ( pData
&& pData
->HasStringData() )
2352 pLastNumData
= pData
;
2357 const ScDPItemData
* pFirstData
= GetSrcItemDataByIndex( 0 );
2358 double fFirstVal
= pFirstData
->GetValue();
2359 double fLastVal
= pLastNumData
->GetValue();
2361 long nFirstYear
= pSource
->GetData()->GetDatePart(
2362 (long)::rtl::math::approxFloor( fFirstVal
),
2364 long nLastYear
= pSource
->GetData()->GetDatePart(
2365 (long)::rtl::math::approxFloor( fLastVal
),
2368 nMbrCount
= nLastYear
+ 1 - nFirstYear
;
2371 nMbrCount
= 0; // no values
2374 case SC_DAPI_LEVEL_QUARTER
: nMbrCount
= 4; break;
2375 case SC_DAPI_LEVEL_MONTH
: nMbrCount
= 12; break;
2376 case SC_DAPI_LEVEL_DAY
: nMbrCount
= 31; break;
2378 OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
2382 else if ( nHier
== SC_DAPI_HIERARCHY_WEEK
)
2386 case SC_DAPI_LEVEL_YEAR
: nMbrCount
= 1; break; //! get years from source
2387 case SC_DAPI_LEVEL_WEEK
: nMbrCount
= 53; break;
2388 case SC_DAPI_LEVEL_WEEKDAY
: nMbrCount
= 7; break;
2390 OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
2396 nMbrCount
= pSource
->GetData()->GetMembersCount( nSrcDim
);
2399 ScDPMembers::~ScDPMembers()
2403 // XNameAccess implementation using getCount/getByIndex
2405 sal_Int32
ScDPMembers::GetIndexFromName( const OUString
& rName
) const
2407 if ( aHashMap
.empty() )
2409 // store the index for each name
2411 sal_Int32 nCount
= getCount();
2412 for (sal_Int32 i
=0; i
<nCount
; i
++)
2413 aHashMap
[ getByIndex(i
)->getName() ] = i
;
2416 ScDPMembersHashMap::const_iterator aIter
= aHashMap
.find( rName
);
2417 if ( aIter
!= aHashMap
.end() )
2418 return aIter
->second
; // found index
2420 return -1; // not found
2423 uno::Any SAL_CALL
ScDPMembers::getByName( const OUString
& aName
)
2424 throw(container::NoSuchElementException
,
2425 lang::WrappedTargetException
, uno::RuntimeException
)
2427 sal_Int32 nIndex
= GetIndexFromName( aName
);
2430 uno::Reference
<container::XNamed
> xNamed
= getByIndex(nIndex
);
2436 throw container::NoSuchElementException();
2439 uno::Sequence
<OUString
> SAL_CALL
ScDPMembers::getElementNames() throw(uno::RuntimeException
)
2441 // Return list of names in sorted order,
2442 // so it's displayed in that order in the field options dialog.
2443 // Sorting is done at the level object (parent of this).
2445 ScDPLevel
* pLevel
= pSource
->GetDimensionsObject()->getByIndex(nDim
)->
2446 GetHierarchiesObject()->getByIndex(nHier
)->GetLevelsObject()->getByIndex(nLev
);
2447 pLevel
->EvaluateSortOrder();
2448 const std::vector
<sal_Int32
>& rGlobalOrder
= pLevel
->GetGlobalOrder();
2449 bool bSort
= !rGlobalOrder
.empty();
2451 long nCount
= getCount();
2452 uno::Sequence
<OUString
> aSeq(nCount
);
2453 OUString
* pArr
= aSeq
.getArray();
2454 for (long i
=0; i
<nCount
; i
++)
2455 pArr
[i
] = getByIndex(bSort
? rGlobalOrder
[i
] : i
)->getName();
2459 sal_Bool SAL_CALL
ScDPMembers::hasByName( const OUString
& aName
) throw(uno::RuntimeException
)
2461 return ( GetIndexFromName( aName
) >= 0 );
2464 uno::Type SAL_CALL
ScDPMembers::getElementType() throw(uno::RuntimeException
)
2466 return getCppuType((uno::Reference
<container::XNamed
>*)0);
2469 sal_Bool SAL_CALL
ScDPMembers::hasElements() throw(uno::RuntimeException
)
2471 return ( getCount() > 0 );
2474 // end of XNameAccess implementation
2476 long ScDPMembers::getCount() const
2481 long ScDPMembers::getMinMembers() const
2483 // used in lcl_CountMinMembers
2486 if (!maMembers
.empty())
2488 MembersType::const_iterator it
= maMembers
.begin(), itEnd
= maMembers
.end();
2489 for (; it
!= itEnd
; ++it
)
2491 // count only visible with details (default is true for both)
2492 const rtl::Reference
<ScDPMember
>& pMbr
= *it
;
2493 if (!pMbr
.get() || (pMbr
->isVisible() && pMbr
->getShowDetails()))
2498 nVisCount
= nMbrCount
; // default for all
2503 ScDPMember
* ScDPMembers::getByIndex(long nIndex
) const
2505 // result of GetColumnEntries must not change between ScDPMembers ctor
2506 // and all calls to getByIndex
2508 if ( nIndex
>= 0 && nIndex
< nMbrCount
)
2510 if (maMembers
.empty())
2511 maMembers
.resize(nMbrCount
);
2513 if (!maMembers
[nIndex
].get())
2515 rtl::Reference
<ScDPMember
> pNew
;
2516 long nSrcDim
= pSource
->GetSourceDim( nDim
);
2517 if ( pSource
->IsDataLayoutDimension(nSrcDim
) )
2519 // empty name (never shown, not used for lookup)
2520 pNew
.set(new ScDPMember(pSource
, nDim
, nHier
, nLev
, 0));
2522 else if ( nHier
!= SC_DAPI_HIERARCHY_FLAT
&& pSource
->IsDateDimension( nSrcDim
) )
2524 sal_Int32 nGroupBy
= 0;
2528 if ( nLev
== SC_DAPI_LEVEL_YEAR
) // YEAR is in both hierarchies
2530 //! cache year range here!
2532 double fFirstVal
= pSource
->GetData()->GetMemberByIndex( nSrcDim
, 0 )->GetValue();
2533 long nFirstYear
= pSource
->GetData()->GetDatePart(
2534 (long)::rtl::math::approxFloor( fFirstVal
),
2537 nVal
= nFirstYear
+ nIndex
;
2539 else if ( nHier
== SC_DAPI_HIERARCHY_WEEK
&& nLev
== SC_DAPI_LEVEL_WEEKDAY
)
2541 nVal
= nIndex
; // DayOfWeek is 0-based
2542 aName
= ScGlobal::GetCalendar()->getDisplayName(
2543 ::com::sun::star::i18n::CalendarDisplayIndex::DAY
,
2544 sal::static_int_cast
<sal_Int16
>(nVal
), 0 );
2546 else if ( nHier
== SC_DAPI_HIERARCHY_QUARTER
&& nLev
== SC_DAPI_LEVEL_MONTH
)
2548 nVal
= nIndex
; // Month is 0-based
2549 aName
= ScGlobal::GetCalendar()->getDisplayName(
2550 ::com::sun::star::i18n::CalendarDisplayIndex::MONTH
,
2551 sal::static_int_cast
<sal_Int16
>(nVal
), 0 );
2554 nVal
= nIndex
+ 1; // Quarter, Day, Week are 1-based
2558 case SC_DAPI_LEVEL_YEAR
:
2559 nGroupBy
= sheet::DataPilotFieldGroupBy::YEARS
;
2561 case SC_DAPI_LEVEL_QUARTER
:
2562 case SC_DAPI_LEVEL_WEEK
:
2563 nGroupBy
= sheet::DataPilotFieldGroupBy::QUARTERS
;
2565 case SC_DAPI_LEVEL_MONTH
:
2566 case SC_DAPI_LEVEL_WEEKDAY
:
2567 nGroupBy
= sheet::DataPilotFieldGroupBy::MONTHS
;
2569 case SC_DAPI_LEVEL_DAY
:
2570 nGroupBy
= sheet::DataPilotFieldGroupBy::DAYS
;
2575 if (aName
.isEmpty())
2576 aName
= OUString::number(nVal
);
2578 ScDPItemData
aData(nGroupBy
, nVal
);
2579 SCROW nId
= pSource
->GetCache()->GetIdByItemData(nDim
, aData
);
2580 pNew
.set(new ScDPMember(pSource
, nDim
, nHier
, nLev
, nId
));
2584 const std::vector
<SCROW
>& memberIndexs
= pSource
->GetData()->GetColumnEntries(nSrcDim
);
2585 pNew
.set(new ScDPMember(pSource
, nDim
, nHier
, nLev
, memberIndexs
[nIndex
]));
2587 maMembers
[nIndex
] = pNew
;
2590 return maMembers
[nIndex
].get();
2593 return NULL
; //! exception?
2596 // -----------------------------------------------------------------------
2598 ScDPMember::ScDPMember(
2599 ScDPSource
* pSrc
, long nD
, long nH
, long nL
, SCROW nIndex
) :
2613 ScDPMember::~ScDPMember()
2618 bool ScDPMember::IsNamedItem(SCROW nIndex
) const
2620 long nSrcDim
= pSource
->GetSourceDim( nDim
);
2621 if ( nHier
!= SC_DAPI_HIERARCHY_FLAT
&& pSource
->IsDateDimension( nSrcDim
) )
2623 const ScDPItemData
* pData
= pSource
->GetCache()->GetItemDataById(nDim
, nIndex
);
2624 if (pData
->IsValue())
2626 long nComp
= pSource
->GetData()->GetDatePart(
2627 (long)::rtl::math::approxFloor( pData
->GetValue() ),
2629 // fValue is converted from integer, so simple comparison works
2630 const ScDPItemData
* pData2
= GetItemData();
2631 return pData2
&& nComp
== pData2
->GetValue();
2635 return nIndex
== mnDataId
;
2638 sal_Int32
ScDPMember::Compare( const ScDPMember
& rOther
) const
2640 if ( nPosition
>= 0 )
2642 if ( rOther
.nPosition
>= 0 )
2644 OSL_ENSURE( nPosition
!= rOther
.nPosition
, "same position for two members" );
2645 return ( nPosition
< rOther
.nPosition
) ? -1 : 1;
2649 // only this has a position - members with specified positions come before those without
2653 else if ( rOther
.nPosition
>= 0 )
2655 // only rOther has a position
2659 // no positions set - compare names
2660 return pSource
->GetData()->Compare( pSource
->GetSourceDim(nDim
),mnDataId
,rOther
.GetItemDataId());
2663 void ScDPMember::FillItemData( ScDPItemData
& rData
) const
2665 //! handle date hierarchy...
2667 const ScDPItemData
* pData
= GetItemData();
2668 rData
= (pData
? *pData
: ScDPItemData());
2671 const OUString
* ScDPMember::GetLayoutName() const
2673 return mpLayoutName
.get();
2676 long ScDPMember::GetDim() const
2681 OUString
ScDPMember::GetNameStr() const
2683 const ScDPItemData
* pData
= GetItemData();
2685 return pSource
->GetData()->GetFormattedString(nDim
, *pData
);
2689 OUString SAL_CALL
ScDPMember::getName() throw(uno::RuntimeException
)
2691 return GetNameStr();
2694 void SAL_CALL
ScDPMember::setName( const OUString
& /* rNewName */ ) throw(uno::RuntimeException
)
2696 OSL_FAIL("not implemented"); //! exception?
2699 bool ScDPMember::isVisible() const
2704 bool ScDPMember::getShowDetails() const
2711 uno::Reference
<beans::XPropertySetInfo
> SAL_CALL
ScDPMember::getPropertySetInfo()
2712 throw(uno::RuntimeException
)
2714 SolarMutexGuard aGuard
;
2716 static const SfxItemPropertyMapEntry aDPMemberMap_Impl
[] =
2718 {MAP_CHAR_LEN(SC_UNO_DP_ISVISIBLE
), 0, &getBooleanCppuType(), 0, 0 },
2719 {MAP_CHAR_LEN(SC_UNO_DP_POSITION
), 0, &getCppuType((sal_Int32
*)0), 0, 0 },
2720 {MAP_CHAR_LEN(SC_UNO_DP_SHOWDETAILS
), 0, &getBooleanCppuType(), 0, 0 },
2721 {MAP_CHAR_LEN(SC_UNO_DP_LAYOUTNAME
), 0, &getCppuType(static_cast<OUString
*>(0)), 0, 0 },
2724 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
2725 new SfxItemPropertySetInfo( aDPMemberMap_Impl
);
2729 void SAL_CALL
ScDPMember::setPropertyValue( const OUString
& aPropertyName
, const uno::Any
& aValue
)
2730 throw(beans::UnknownPropertyException
, beans::PropertyVetoException
,
2731 lang::IllegalArgumentException
, lang::WrappedTargetException
,
2732 uno::RuntimeException
)
2734 if ( aPropertyName
.equalsAscii( SC_UNO_DP_ISVISIBLE
) )
2735 bVisible
= lcl_GetBoolFromAny(aValue
);
2736 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_SHOWDETAILS
) )
2737 bShowDet
= lcl_GetBoolFromAny(aValue
);
2738 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_POSITION
) )
2739 aValue
>>= nPosition
;
2740 else if (aPropertyName
.equalsAscii(SC_UNO_DP_LAYOUTNAME
))
2743 if (aValue
>>= aName
)
2744 mpLayoutName
.reset(new OUString(aName
));
2748 OSL_FAIL("unknown property");
2752 uno::Any SAL_CALL
ScDPMember::getPropertyValue( const OUString
& aPropertyName
)
2753 throw(beans::UnknownPropertyException
, lang::WrappedTargetException
,
2754 uno::RuntimeException
)
2757 if ( aPropertyName
.equalsAscii( SC_UNO_DP_ISVISIBLE
) )
2758 lcl_SetBoolInAny(aRet
, bVisible
);
2759 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_SHOWDETAILS
) )
2760 lcl_SetBoolInAny(aRet
, bShowDet
);
2761 else if ( aPropertyName
.equalsAscii( SC_UNO_DP_POSITION
) )
2763 else if (aPropertyName
.equalsAscii(SC_UNO_DP_LAYOUTNAME
))
2764 aRet
<<= mpLayoutName
.get() ? *mpLayoutName
: OUString();
2767 OSL_FAIL("unknown property");
2772 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember
)
2775 const ScDPCache
* ScDPSource::GetCache()
2777 OSL_ENSURE( GetData() , "empty ScDPTableData pointer");
2778 return ( GetData()!=NULL
) ? GetData()->GetCacheTable().getCache() : NULL
;
2781 const ScDPItemData
* ScDPMember::GetItemData() const
2783 const ScDPItemData
* pData
= pSource
->GetItemDataById(nDim
, mnDataId
);
2784 SAL_WARN_IF( !pData
, "sc", "ScDPMember::GetItemData: what data? nDim " << nDim
<< ", mnDataId " << mnDataId
);
2788 const ScDPItemData
* ScDPSource::GetItemDataById(long nDim
, long nId
)
2790 return GetData()->GetMemberById(nDim
, nId
);
2793 SCROW
ScDPSource::GetMemberId(long nDim
, const ScDPItemData
& rData
)
2795 return GetCache()->GetIdByItemData(nDim
, rData
);
2798 const ScDPItemData
* ScDPMembers::GetSrcItemDataByIndex(SCROW nIndex
)
2800 const std::vector
< SCROW
>& memberIds
= pSource
->GetData()->GetColumnEntries( nDim
);
2801 if ( nIndex
>= (long )(memberIds
.size()) || nIndex
< 0 )
2803 SCROW nId
= memberIds
[ nIndex
];
2804 return pSource
->GetItemDataById( nDim
, nId
);
2807 SCROW
ScDPMembers::GetSrcItemsCount()
2809 return pSource
->GetData()->GetColumnEntries(nDim
).size();
2812 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */