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 .
23 #include <o3tl/safeint.hxx>
24 #include <svl/hint.hxx>
26 #include <vcl/svapp.hxx>
27 #include <sal/log.hxx>
29 #include <dapiuno.hxx>
30 #include <datauno.hxx>
31 #include <miscuno.hxx>
32 #include <convuno.hxx>
34 #include <tabvwsh.hxx>
35 #include <rangeutl.hxx>
36 #include <dpobject.hxx>
37 #include <dpshttab.hxx>
38 #include <dpsdbtab.hxx>
40 #include <dbdocfun.hxx>
41 #include <unonames.hxx>
42 #include <dpdimsave.hxx>
45 #include <globstr.hrc>
46 #include <scresid.hxx>
47 #include <generalfunction.hxx>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
51 #include <com/sun/star/lang/IllegalArgumentException.hpp>
52 #include <com/sun/star/lang/NullPointerException.hpp>
53 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
54 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
55 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
56 #include <com/sun/star/sheet/XMembersAccess.hpp>
57 #include <com/sun/star/beans/PropertyAttribute.hpp>
58 #include <com/sun/star/sheet/DataImportMode.hpp>
59 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
60 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
61 #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
62 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
63 #include <com/sun/star/sheet/GeneralFunction2.hpp>
65 #include <comphelper/extract.hxx>
66 #include <comphelper/propertysequence.hxx>
67 #include <cppuhelper/queryinterface.hxx>
68 #include <comphelper/sequence.hxx>
69 #include <cppuhelper/exc_hlp.hxx>
71 using namespace com::sun::star
;
72 using namespace com::sun::star::sheet
;
74 using ::com::sun::star::uno::Any
;
75 using ::com::sun::star::uno::Exception
;
76 using ::com::sun::star::uno::Reference
;
77 using ::com::sun::star::uno::RuntimeException
;
78 using ::com::sun::star::uno::Sequence
;
79 using ::com::sun::star::uno::UNO_QUERY
;
80 using ::com::sun::star::uno::UNO_QUERY_THROW
;
82 using ::com::sun::star::container::ElementExistException
;
83 using ::com::sun::star::container::NoSuchElementException
;
84 using ::com::sun::star::container::XEnumeration
;
85 using ::com::sun::star::container::XIndexAccess
;
86 using ::com::sun::star::container::XNameAccess
;
87 using ::com::sun::star::container::XNamed
;
89 using ::com::sun::star::beans::UnknownPropertyException
;
90 using ::com::sun::star::beans::XPropertyChangeListener
;
91 using ::com::sun::star::beans::XPropertySet
;
92 using ::com::sun::star::beans::XPropertySetInfo
;
93 using ::com::sun::star::beans::XVetoableChangeListener
;
95 using ::com::sun::star::lang::IllegalArgumentException
;
96 using ::com::sun::star::lang::IndexOutOfBoundsException
;
97 using ::com::sun::star::lang::NullPointerException
;
99 using ::com::sun::star::table::CellAddress
;
100 using ::com::sun::star::table::CellRangeAddress
;
104 std::span
<const SfxItemPropertyMapEntry
> lcl_GetDataPilotDescriptorBaseMap()
106 static const SfxItemPropertyMapEntry aDataPilotDescriptorBaseMap_Impl
[] =
108 { SC_UNO_DP_COLGRAND
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
109 { SC_UNO_DP_DRILLDOWN
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
110 { SC_UNO_DP_GRANDTOTAL_NAME
,0,cppu::UnoType
<OUString
>::get(), beans::PropertyAttribute::MAYBEVOID
, 0 },
111 { SC_UNO_DP_IGNORE_EMPTYROWS
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
112 { SC_UNO_DP_IMPORTDESC
, 0, cppu::UnoType
<uno::Sequence
<beans::PropertyValue
>>::get(), 0, 0 },
113 { SC_UNO_DP_REPEATEMPTY
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
114 { SC_UNO_DP_ROWGRAND
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
115 { SC_UNO_DP_SERVICEARG
, 0, cppu::UnoType
<uno::Sequence
<beans::PropertyValue
>>::get(), 0, 0 },
116 { SC_UNO_DP_SHOWFILTER
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
117 { SC_UNO_DP_SOURCESERVICE
, 0, cppu::UnoType
<OUString
>::get(), 0, 0 },
119 return aDataPilotDescriptorBaseMap_Impl
;
122 std::span
<const SfxItemPropertyMapEntry
> lcl_GetDataPilotFieldMap()
124 using namespace ::com::sun::star::beans::PropertyAttribute
;
125 static const SfxItemPropertyMapEntry aDataPilotFieldMap_Impl
[] =
127 { SC_UNONAME_AUTOSHOW
, 0, cppu::UnoType
<DataPilotFieldAutoShowInfo
>::get(), MAYBEVOID
, 0 },
128 { SC_UNONAME_FUNCTION
, 0, cppu::UnoType
<GeneralFunction
>::get(), 0, 0 },
129 { SC_UNONAME_FUNCTION2
, 0, cppu::UnoType
<sal_Int16
>::get(), 0, 0 },
130 { SC_UNONAME_GROUPINFO
, 0, cppu::UnoType
<DataPilotFieldGroupInfo
>::get(), MAYBEVOID
, 0 },
131 { SC_UNONAME_HASAUTOSHOW
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
132 { SC_UNONAME_HASLAYOUTINFO
,0, cppu::UnoType
<bool>::get(), 0, 0 },
133 { SC_UNONAME_HASREFERENCE
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
134 { SC_UNONAME_HASSORTINFO
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
135 { SC_UNONAME_ISGROUP
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
136 { SC_UNONAME_LAYOUTINFO
, 0, cppu::UnoType
<DataPilotFieldLayoutInfo
>::get(), MAYBEVOID
, 0 },
137 { SC_UNONAME_ORIENT
, 0, cppu::UnoType
<DataPilotFieldOrientation
>::get(), MAYBEVOID
, 0 },
138 { SC_UNONAME_REFERENCE
, 0, cppu::UnoType
<DataPilotFieldReference
>::get(), MAYBEVOID
, 0 },
139 { SC_UNONAME_SELPAGE
, 0, cppu::UnoType
<OUString
>::get(), 0, 0 },
140 { SC_UNONAME_SHOWEMPTY
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
141 { SC_UNONAME_REPEATITEMLABELS
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
142 { SC_UNONAME_SORTINFO
, 0, cppu::UnoType
<DataPilotFieldSortInfo
>::get(), MAYBEVOID
, 0 },
143 { SC_UNONAME_SUBTOTALS
, 0, cppu::UnoType
<Sequence
<GeneralFunction
>>::get(), 0, 0 },
144 { SC_UNONAME_SUBTOTALS2
, 0, cppu::UnoType
<Sequence
<sal_Int16
>>::get(), 0, 0 },
145 { SC_UNONAME_USESELPAGE
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
147 return aDataPilotFieldMap_Impl
;
150 std::span
<const SfxItemPropertyMapEntry
> lcl_GetDataPilotItemMap()
152 static const SfxItemPropertyMapEntry aDataPilotItemMap_Impl
[] =
154 { SC_UNONAME_ISHIDDEN
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
155 { SC_UNONAME_POS
, 0, cppu::UnoType
<sal_Int32
>::get(), 0, 0 },
156 { SC_UNONAME_SHOWDETAIL
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
158 return aDataPilotItemMap_Impl
;
161 bool lclCheckValidDouble( double fValue
, bool bAuto
)
163 return bAuto
|| std::isfinite( fValue
);
166 bool lclCheckMinMaxStep( const DataPilotFieldGroupInfo
& rInfo
)
169 lclCheckValidDouble( rInfo
.Start
, rInfo
.HasAutoStart
) &&
170 lclCheckValidDouble( rInfo
.End
, rInfo
.HasAutoEnd
) &&
171 (rInfo
.HasAutoStart
|| rInfo
.HasAutoEnd
|| (rInfo
.Start
<= rInfo
.End
)) &&
172 lclCheckValidDouble( rInfo
.Step
, false ) &&
178 SC_SIMPLE_SERVICE_INFO( ScDataPilotDescriptor
, u
"ScDataPilotDescriptor"_ustr
, u
"stardiv::one::sheet::DataPilotDescriptor"_ustr
)
179 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldObj
, u
"ScDataPilotFieldObj"_ustr
, u
"com.sun.star.sheet.DataPilotField"_ustr
)
180 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldsObj
, u
"ScDataPilotFieldsObj"_ustr
, u
"com.sun.star.sheet.DataPilotFields"_ustr
)
181 SC_SIMPLE_SERVICE_INFO( ScDataPilotTableObj
, u
"ScDataPilotTableObj"_ustr
, u
"com.sun.star.sheet.DataPilotTable"_ustr
)
182 SC_SIMPLE_SERVICE_INFO( ScDataPilotTablesObj
, u
"ScDataPilotTablesObj"_ustr
, u
"com.sun.star.sheet.DataPilotTables"_ustr
)
183 SC_SIMPLE_SERVICE_INFO( ScDataPilotItemsObj
, u
"ScDataPilotItemsObj"_ustr
, u
"com.sun.star.sheet.DataPilotItems"_ustr
)
184 SC_SIMPLE_SERVICE_INFO( ScDataPilotItemObj
, u
"ScDataPilotItemObj"_ustr
, u
"com.sun.star.sheet.DataPilotItem"_ustr
)
186 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupsObj
, u
"ScDataPilotFieldGroupsObj"_ustr
, u
"com.sun.star.sheet.DataPilotFieldGroups"_ustr
)
187 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupObj
, u
"ScDataPilotFieldGroupObj"_ustr
, u
"com.sun.star.sheet.DataPilotFieldGroup"_ustr
)
188 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupItemObj
, u
"ScDataPilotFieldGroupItemObj"_ustr
, u
"com.sun.star.sheet.DataPilotFieldGroupItem"_ustr
)
190 // name that is used in the API for the data layout field
191 constexpr OUString SC_DATALAYOUT_NAME
= u
"Data"_ustr
;
193 ScGeneralFunction
ScDataPilotConversion::FirstFunc( PivotFunc nBits
)
195 if ( nBits
& PivotFunc::Sum
) return ScGeneralFunction::SUM
;
196 if ( nBits
& PivotFunc::Count
) return ScGeneralFunction::COUNT
;
197 if ( nBits
& PivotFunc::Average
) return ScGeneralFunction::AVERAGE
;
198 if ( nBits
& PivotFunc::Median
) return ScGeneralFunction::MEDIAN
;
199 if ( nBits
& PivotFunc::Max
) return ScGeneralFunction::MAX
;
200 if ( nBits
& PivotFunc::Min
) return ScGeneralFunction::MIN
;
201 if ( nBits
& PivotFunc::Product
) return ScGeneralFunction::PRODUCT
;
202 if ( nBits
& PivotFunc::CountNum
) return ScGeneralFunction::COUNTNUMS
;
203 if ( nBits
& PivotFunc::StdDev
) return ScGeneralFunction::STDEV
;
204 if ( nBits
& PivotFunc::StdDevP
) return ScGeneralFunction::STDEVP
;
205 if ( nBits
& PivotFunc::StdVar
) return ScGeneralFunction::VAR
;
206 if ( nBits
& PivotFunc::StdVarP
) return ScGeneralFunction::VARP
;
207 if ( nBits
& PivotFunc::Auto
) return ScGeneralFunction::AUTO
;
208 return ScGeneralFunction::NONE
;
211 PivotFunc
ScDataPilotConversion::FunctionBit( sal_Int16 eFunc
)
213 PivotFunc nRet
= PivotFunc::NONE
; // 0
216 case GeneralFunction2::SUM
: nRet
= PivotFunc::Sum
; break;
217 case GeneralFunction2::COUNT
: nRet
= PivotFunc::Count
; break;
218 case GeneralFunction2::AVERAGE
: nRet
= PivotFunc::Average
; break;
219 case GeneralFunction2::MEDIAN
: nRet
= PivotFunc::Median
; break;
220 case GeneralFunction2::MAX
: nRet
= PivotFunc::Max
; break;
221 case GeneralFunction2::MIN
: nRet
= PivotFunc::Min
; break;
222 case GeneralFunction2::PRODUCT
: nRet
= PivotFunc::Product
; break;
223 case GeneralFunction2::COUNTNUMS
: nRet
= PivotFunc::CountNum
; break;
224 case GeneralFunction2::STDEV
: nRet
= PivotFunc::StdDev
; break;
225 case GeneralFunction2::STDEVP
: nRet
= PivotFunc::StdDevP
; break;
226 case GeneralFunction2::VAR
: nRet
= PivotFunc::StdVar
; break;
227 case GeneralFunction2::VARP
: nRet
= PivotFunc::StdVarP
; break;
228 case GeneralFunction2::AUTO
: nRet
= PivotFunc::Auto
; break;
237 void ScDataPilotConversion::FillGroupInfo( DataPilotFieldGroupInfo
& rInfo
, const ScDPNumGroupInfo
& rGroupInfo
)
239 rInfo
.HasDateValues
= rGroupInfo
.mbDateValues
;
240 rInfo
.HasAutoStart
= rGroupInfo
.mbAutoStart
;
241 rInfo
.Start
= rGroupInfo
.mfStart
;
242 rInfo
.HasAutoEnd
= rGroupInfo
.mbAutoEnd
;
243 rInfo
.End
= rGroupInfo
.mfEnd
;
244 rInfo
.Step
= rGroupInfo
.mfStep
;
247 static ScDPObject
* lcl_GetDPObject( ScDocShell
* pDocShell
, SCTAB nTab
, std::u16string_view rName
)
251 ScDocument
& rDoc
= pDocShell
->GetDocument();
252 ScDPCollection
* pColl
= rDoc
.GetDPCollection();
255 size_t nCount
= pColl
->GetCount();
256 for (size_t i
=0; i
<nCount
; ++i
)
258 ScDPObject
& rDPObj
= (*pColl
)[i
];
259 if ( rDPObj
.GetOutRange().aStart
.Tab() == nTab
&&
260 rDPObj
.GetName() == rName
)
265 return nullptr; // not found
268 static OUString
lcl_CreatePivotName( ScDocShell
* pDocShell
)
272 ScDocument
& rDoc
= pDocShell
->GetDocument();
273 ScDPCollection
* pColl
= rDoc
.GetDPCollection();
275 return pColl
->CreateNewName();
277 return OUString(); // shouldn't happen
280 static sal_Int32
lcl_GetObjectIndex( ScDPObject
* pDPObj
, const ScFieldIdentifier
& rFieldId
)
282 // used for items - nRepeat in identifier can be ignored
285 sal_Int32 nCount
= pDPObj
->GetDimCount();
286 for ( sal_Int32 nDim
= 0; nDim
< nCount
; ++nDim
)
288 bool bIsDataLayout
= false;
289 OUString
aDimName( pDPObj
->GetDimName( nDim
, bIsDataLayout
) );
290 if ( rFieldId
.mbDataLayout
? bIsDataLayout
: (aDimName
== rFieldId
.maFieldName
) )
297 ScDataPilotTablesObj::ScDataPilotTablesObj(ScDocShell
& rDocSh
, SCTAB nT
) :
298 pDocShell( &rDocSh
),
301 pDocShell
->GetDocument().AddUnoObject(*this);
304 ScDataPilotTablesObj::~ScDataPilotTablesObj()
309 pDocShell
->GetDocument().RemoveUnoObject(*this);
312 void ScDataPilotTablesObj::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
314 //! update of references
316 if ( rHint
.GetId() == SfxHintId::Dying
)
318 pDocShell
= nullptr; // became invalid
324 rtl::Reference
<ScDataPilotTableObj
> ScDataPilotTablesObj::GetObjectByIndex_Impl( sal_Int32 nIndex
)
328 ScDocument
& rDoc
= pDocShell
->GetDocument();
329 ScDPCollection
* pColl
= rDoc
.GetDPCollection();
332 // count tables on this sheet
333 sal_Int32 nFound
= 0;
334 size_t nCount
= pColl
->GetCount();
335 for (size_t i
=0; i
<nCount
; ++i
)
337 ScDPObject
& rDPObj
= (*pColl
)[i
];
338 if ( rDPObj
.GetOutRange().aStart
.Tab() == nTab
)
340 if ( nFound
== nIndex
)
342 return new ScDataPilotTableObj(*pDocShell
, nTab
, rDPObj
.GetName());
352 rtl::Reference
<ScDataPilotTableObj
> ScDataPilotTablesObj::GetObjectByName_Impl(const OUString
& rName
)
354 if (hasByName(rName
))
355 return new ScDataPilotTableObj(*pDocShell
, nTab
, rName
);
359 Reference
<XDataPilotDescriptor
> SAL_CALL
ScDataPilotTablesObj::createDataPilotDescriptor()
361 SolarMutexGuard aGuard
;
363 return new ScDataPilotDescriptor(*pDocShell
);
367 static bool lcl_IsDuplicated(const Reference
<XPropertySet
>& rDimProps
)
371 Any aAny
= rDimProps
->getPropertyValue( SC_UNO_DP_ORIGINAL
);
372 Reference
< XNamed
> xOriginal( aAny
, UNO_QUERY
);
373 return xOriginal
.is();
381 static OUString
lcl_GetOriginalName(const Reference
< XNamed
>& rDim
)
383 Reference
< XNamed
> xOriginal
;
385 Reference
< XPropertySet
> xDimProps(rDim
, UNO_QUERY
);
386 if ( xDimProps
.is() )
390 Any aAny
= xDimProps
->getPropertyValue(SC_UNO_DP_ORIGINAL
);
398 if ( !xOriginal
.is() )
401 return xOriginal
->getName();
404 void SAL_CALL
ScDataPilotTablesObj::insertNewByName( const OUString
& aNewName
,
405 const CellAddress
& aOutputAddress
,
406 const Reference
<XDataPilotDescriptor
>& xDescriptor
)
408 SolarMutexGuard aGuard
;
409 if (!xDescriptor
.is()) return;
411 if ( !aNewName
.isEmpty() && hasByName( aNewName
) )
412 throw IllegalArgumentException("Name \"" + aNewName
+ "\" already exists", getXWeak(), 0);
415 throw RuntimeException(u
"DocShell is null"_ustr
, getXWeak());
417 auto pImp
= dynamic_cast<ScDataPilotDescriptorBase
*>( xDescriptor
.get() );
419 throw RuntimeException(u
"Failed to get ScDataPilotDescriptor"_ustr
, getXWeak());
421 ScDPObject
* pNewObj
= pImp
->GetDPObject();
423 throw RuntimeException(u
"Failed to get DPObject"_ustr
, getXWeak());
425 ScRange
aOutputRange(static_cast<SCCOL
>(aOutputAddress
.Column
), static_cast<SCROW
>(aOutputAddress
.Row
), static_cast<SCTAB
>(aOutputAddress
.Sheet
),
426 static_cast<SCCOL
>(aOutputAddress
.Column
), static_cast<SCROW
>(aOutputAddress
.Row
), static_cast<SCTAB
>(aOutputAddress
.Sheet
));
427 pNewObj
->SetOutRange(aOutputRange
);
428 OUString aName
= aNewName
;
430 aName
= lcl_CreatePivotName( pDocShell
);
431 pNewObj
->SetName(aName
);
432 OUString aTag
= xDescriptor
->getTag();
433 pNewObj
->SetTag(aTag
);
435 // todo: handle double fields (for more information see ScDPObject)
437 ScDBDocFunc
aFunc(*pDocShell
);
438 if (!aFunc
.CreatePivotTable(*pNewObj
, true, true))
439 throw RuntimeException(u
"Failed to create pivot table"_ustr
, getXWeak());
442 void SAL_CALL
ScDataPilotTablesObj::removeByName( const OUString
& aName
)
444 SolarMutexGuard aGuard
;
445 ScDPObject
* pDPObj
= lcl_GetDPObject( pDocShell
, nTab
, aName
);
446 if (!pDPObj
|| !pDocShell
)
447 throw RuntimeException(); // no other exceptions specified
449 ScDBDocFunc
aFunc(*pDocShell
);
450 aFunc
.RemovePivotTable(*pDPObj
, true, true); // remove - incl. undo etc.
454 // XEnumerationAccess
456 Reference
< XEnumeration
> SAL_CALL
ScDataPilotTablesObj::createEnumeration()
458 SolarMutexGuard aGuard
;
459 return new ScIndexEnumeration(this, u
"com.sun.star.sheet.DataPilotTablesEnumeration"_ustr
);
464 sal_Int32 SAL_CALL
ScDataPilotTablesObj::getCount()
466 SolarMutexGuard aGuard
;
469 ScDocument
& rDoc
= pDocShell
->GetDocument();
470 ScDPCollection
* pColl
= rDoc
.GetDPCollection();
473 // count tables on this sheet
475 sal_uInt16 nFound
= 0;
476 size_t nCount
= pColl
->GetCount();
477 for (size_t i
=0; i
<nCount
; ++i
)
479 ScDPObject
& rDPObj
= (*pColl
)[i
];
480 if ( rDPObj
.GetOutRange().aStart
.Tab() == nTab
)
490 Any SAL_CALL
ScDataPilotTablesObj::getByIndex( sal_Int32 nIndex
)
492 SolarMutexGuard aGuard
;
493 Reference
<XDataPilotTable2
> xTable(GetObjectByIndex_Impl(nIndex
));
495 throw IndexOutOfBoundsException();
496 return Any( xTable
);
499 uno::Type SAL_CALL
ScDataPilotTablesObj::getElementType()
501 return cppu::UnoType
<XDataPilotTable2
>::get();
504 sal_Bool SAL_CALL
ScDataPilotTablesObj::hasElements()
506 SolarMutexGuard aGuard
;
507 return ( getCount() != 0 );
512 Any SAL_CALL
ScDataPilotTablesObj::getByName( const OUString
& aName
)
514 SolarMutexGuard aGuard
;
515 Reference
<XDataPilotTable2
> xTable(GetObjectByName_Impl(aName
));
517 throw NoSuchElementException();
518 return Any( xTable
);
521 Sequence
<OUString
> SAL_CALL
ScDataPilotTablesObj::getElementNames()
523 SolarMutexGuard aGuard
;
526 ScDocument
& rDoc
= pDocShell
->GetDocument();
527 ScDPCollection
* pColl
= rDoc
.GetDPCollection();
530 // count tables on this sheet
532 sal_uInt16 nFound
= 0;
533 size_t nCount
= pColl
->GetCount();
535 for (i
=0; i
<nCount
; ++i
)
537 ScDPObject
& rDPObj
= (*pColl
)[i
];
538 if ( rDPObj
.GetOutRange().aStart
.Tab() == nTab
)
543 Sequence
<OUString
> aSeq(nFound
);
544 OUString
* pAry
= aSeq
.getArray();
545 for (i
=0; i
<nCount
; ++i
)
547 ScDPObject
& rDPObj
= (*pColl
)[i
];
548 if ( rDPObj
.GetOutRange().aStart
.Tab() == nTab
)
549 pAry
[nPos
++] = rDPObj
.GetName();
558 sal_Bool SAL_CALL
ScDataPilotTablesObj::hasByName( const OUString
& aName
)
560 SolarMutexGuard aGuard
;
563 ScDocument
& rDoc
= pDocShell
->GetDocument();
564 ScDPCollection
* pColl
= rDoc
.GetDPCollection();
567 size_t nCount
= pColl
->GetCount();
568 for (size_t i
=0; i
<nCount
; ++i
)
570 ScDPObject
& rDPObj
= (*pColl
)[i
];
571 if ( rDPObj
.GetOutRange().aStart
.Tab() == nTab
&&
572 rDPObj
.GetName() == aName
)
580 ScDataPilotDescriptorBase::ScDataPilotDescriptorBase(ScDocShell
& rDocSh
) :
581 maPropSet( lcl_GetDataPilotDescriptorBaseMap() ),
584 pDocShell
->GetDocument().AddUnoObject(*this);
587 ScDataPilotDescriptorBase::~ScDataPilotDescriptorBase()
592 pDocShell
->GetDocument().RemoveUnoObject(*this);
595 void ScDataPilotDescriptorBase::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
597 //! update of references ?
599 if ( rHint
.GetId() == SfxHintId::Dying
)
601 pDocShell
= nullptr; // became invalid
605 // XDataPilotDescriptor
607 CellRangeAddress SAL_CALL
ScDataPilotDescriptorBase::getSourceRange()
609 SolarMutexGuard aGuard
;
611 ScDPObject
* pDPObject(GetDPObject());
613 throw RuntimeException(u
"Failed to get DPObject"_ustr
, getXWeak());
615 CellRangeAddress aRet
;
616 if (pDPObject
->IsSheetData())
617 ScUnoConversion::FillApiRange( aRet
, pDPObject
->GetSheetDesc()->GetSourceRange() );
621 void SAL_CALL
ScDataPilotDescriptorBase::setSourceRange( const CellRangeAddress
& aSourceRange
)
623 SolarMutexGuard aGuard
;
625 ScDPObject
* pDPObject
= GetDPObject();
627 throw RuntimeException(u
"Failed to get DPObject"_ustr
, getXWeak());
629 ScSheetSourceDesc
aSheetDesc(&pDocShell
->GetDocument());
630 if (pDPObject
->IsSheetData())
631 aSheetDesc
= *pDPObject
->GetSheetDesc();
634 ScUnoConversion::FillScRange(aRange
, aSourceRange
);
635 aSheetDesc
.SetSourceRange(aRange
);
636 pDPObject
->SetSheetDesc( aSheetDesc
);
637 SetDPObject( pDPObject
);
640 Reference
<XSheetFilterDescriptor
> SAL_CALL
ScDataPilotDescriptorBase::getFilterDescriptor()
642 SolarMutexGuard aGuard
;
643 return new ScDataPilotFilterDescriptor( pDocShell
, this );
646 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotDescriptorBase::getDataPilotFields()
648 SolarMutexGuard aGuard
;
649 return new ScDataPilotFieldsObj( *this );
652 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotDescriptorBase::getColumnFields()
654 SolarMutexGuard aGuard
;
655 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_COLUMN
);
658 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotDescriptorBase::getRowFields()
660 SolarMutexGuard aGuard
;
661 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_ROW
);
664 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotDescriptorBase::getPageFields()
666 SolarMutexGuard aGuard
;
667 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_PAGE
);
670 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotDescriptorBase::getDataFields()
672 SolarMutexGuard aGuard
;
673 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_DATA
);
676 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotDescriptorBase::getHiddenFields()
678 SolarMutexGuard aGuard
;
679 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_HIDDEN
);
683 Reference
< XPropertySetInfo
> SAL_CALL
ScDataPilotDescriptorBase::getPropertySetInfo( )
685 SolarMutexGuard aGuard
;
686 static Reference
<XPropertySetInfo
> aRef
=
687 new SfxItemPropertySetInfo( maPropSet
.getPropertyMap() );
691 void SAL_CALL
ScDataPilotDescriptorBase::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
693 SolarMutexGuard aGuard
;
694 ScDPObject
* pDPObject
= GetDPObject();
698 ScDPSaveData
* pOldData
= pDPObject
->GetSaveData();
699 OSL_ENSURE(pOldData
, "Here should be a SaveData");
702 ScDPSaveData
aNewData( *pOldData
);
704 if ( aPropertyName
== SC_UNO_DP_COLGRAND
)
706 aNewData
.SetColumnGrand(::cppu::any2bool( aValue
));
708 else if ( aPropertyName
== SC_UNO_DP_IGNORE_EMPTYROWS
)
710 aNewData
.SetIgnoreEmptyRows(::cppu::any2bool( aValue
));
712 else if ( aPropertyName
== SC_UNO_DP_REPEATEMPTY
)
714 aNewData
.SetRepeatIfEmpty(::cppu::any2bool( aValue
));
716 else if ( aPropertyName
== SC_UNO_DP_ROWGRAND
)
718 aNewData
.SetRowGrand(::cppu::any2bool( aValue
));
720 else if ( aPropertyName
== SC_UNO_DP_SHOWFILTER
)
722 aNewData
.SetFilterButton(::cppu::any2bool( aValue
));
724 else if ( aPropertyName
== SC_UNO_DP_DRILLDOWN
)
726 aNewData
.SetDrillDown(::cppu::any2bool( aValue
));
728 else if ( aPropertyName
== SC_UNO_DP_GRANDTOTAL_NAME
)
731 if ( aValue
>>= aStrVal
)
732 aNewData
.SetGrandTotalName(aStrVal
);
734 else if ( aPropertyName
== SC_UNO_DP_IMPORTDESC
)
736 uno::Sequence
<beans::PropertyValue
> aArgSeq
;
737 if ( aValue
>>= aArgSeq
)
739 ScImportSourceDesc
aImportDesc(&pDocShell
->GetDocument());
741 const ScImportSourceDesc
* pOldDesc
= pDPObject
->GetImportSourceDesc();
743 aImportDesc
= *pOldDesc
;
745 ScImportParam aParam
;
746 ScImportDescriptor::FillImportParam( aParam
, aArgSeq
);
748 sheet::DataImportMode nNewType
= sheet::DataImportMode_NONE
;
749 if ( aParam
.bImport
)
752 nNewType
= sheet::DataImportMode_SQL
;
753 else if ( aParam
.nType
== ScDbQuery
)
754 nNewType
= sheet::DataImportMode_QUERY
;
756 nNewType
= sheet::DataImportMode_TABLE
;
758 aImportDesc
.nType
= nNewType
;
759 aImportDesc
.aDBName
= aParam
.aDBName
;
760 aImportDesc
.aObject
= aParam
.aStatement
;
761 aImportDesc
.bNative
= aParam
.bNative
;
763 pDPObject
->SetImportDesc( aImportDesc
);
766 else if ( aPropertyName
== SC_UNO_DP_SOURCESERVICE
)
769 if ( aValue
>>= aStrVal
)
771 ScDPServiceDesc
aServiceDesc(u
""_ustr
, u
""_ustr
, u
""_ustr
, u
""_ustr
, u
""_ustr
);
773 const ScDPServiceDesc
* pOldDesc
= pDPObject
->GetDPServiceDesc();
775 aServiceDesc
= *pOldDesc
;
777 aServiceDesc
.aServiceName
= aStrVal
;
779 pDPObject
->SetServiceData( aServiceDesc
);
782 else if ( aPropertyName
== SC_UNO_DP_SERVICEARG
)
784 uno::Sequence
<beans::PropertyValue
> aArgSeq
;
785 if ( aValue
>>= aArgSeq
)
787 ScDPServiceDesc
aServiceDesc(u
""_ustr
, u
""_ustr
, u
""_ustr
, u
""_ustr
, u
""_ustr
);
789 const ScDPServiceDesc
* pOldDesc
= pDPObject
->GetDPServiceDesc();
791 aServiceDesc
= *pOldDesc
;
794 for (const beans::PropertyValue
& rProp
: aArgSeq
)
796 OUString
aPropName(rProp
.Name
);
798 if (aPropName
== SC_UNO_DP_SOURCENAME
)
800 if ( rProp
.Value
>>= aStrVal
)
801 aServiceDesc
.aParSource
= aStrVal
;
803 else if (aPropName
== SC_UNO_DP_OBJECTNAME
)
805 if ( rProp
.Value
>>= aStrVal
)
806 aServiceDesc
.aParName
= aStrVal
;
808 else if (aPropName
== SC_UNO_DP_USERNAME
)
810 if ( rProp
.Value
>>= aStrVal
)
811 aServiceDesc
.aParUser
= aStrVal
;
813 else if (aPropName
== SC_UNO_DP_PASSWORD
)
815 if ( rProp
.Value
>>= aStrVal
)
816 aServiceDesc
.aParPass
= aStrVal
;
820 pDPObject
->SetServiceData( aServiceDesc
);
824 throw UnknownPropertyException(aPropertyName
);
826 pDPObject
->SetSaveData( aNewData
);
829 SetDPObject(pDPObject
);
832 Any SAL_CALL
ScDataPilotDescriptorBase::getPropertyValue( const OUString
& aPropertyName
)
834 SolarMutexGuard aGuard
;
837 ScDPObject
* pDPObject(GetDPObject());
840 ScDPSaveData
* pOldData
= pDPObject
->GetSaveData();
841 OSL_ENSURE(pOldData
, "Here should be a SaveData");
844 ScDPSaveData
aNewData( *pOldData
);
846 if ( aPropertyName
== SC_UNO_DP_COLGRAND
)
848 aRet
<<= aNewData
.GetColumnGrand();
850 else if ( aPropertyName
== SC_UNO_DP_IGNORE_EMPTYROWS
)
852 aRet
<<= aNewData
.GetIgnoreEmptyRows();
854 else if ( aPropertyName
== SC_UNO_DP_REPEATEMPTY
)
856 aRet
<<= aNewData
.GetRepeatIfEmpty();
858 else if ( aPropertyName
== SC_UNO_DP_ROWGRAND
)
860 aRet
<<= aNewData
.GetRowGrand();
862 else if ( aPropertyName
== SC_UNO_DP_SHOWFILTER
)
864 aRet
<<= aNewData
.GetFilterButton();
866 else if ( aPropertyName
== SC_UNO_DP_DRILLDOWN
)
868 aRet
<<= aNewData
.GetDrillDown();
870 else if ( aPropertyName
== SC_UNO_DP_GRANDTOTAL_NAME
)
872 const std::optional
<OUString
> & pGrandTotalName
= aNewData
.GetGrandTotalName();
874 aRet
<<= *pGrandTotalName
; // same behavior as in ScDPSource
876 else if ( aPropertyName
== SC_UNO_DP_IMPORTDESC
)
878 const ScImportSourceDesc
* pImportDesc
= pDPObject
->GetImportSourceDesc();
881 // fill ScImportParam so ScImportDescriptor::FillProperties can be used
882 ScImportParam aParam
;
883 aParam
.bImport
= ( pImportDesc
->nType
!= sheet::DataImportMode_NONE
);
884 aParam
.aDBName
= pImportDesc
->aDBName
;
885 aParam
.aStatement
= pImportDesc
->aObject
;
886 aParam
.bNative
= pImportDesc
->bNative
;
887 aParam
.bSql
= ( pImportDesc
->nType
== sheet::DataImportMode_SQL
);
888 aParam
.nType
= static_cast<sal_uInt8
>(( pImportDesc
->nType
== sheet::DataImportMode_QUERY
) ? ScDbQuery
: ScDbTable
);
890 uno::Sequence
<beans::PropertyValue
> aSeq( ScImportDescriptor::GetPropertyCount() );
891 ScImportDescriptor::FillProperties( aSeq
, aParam
);
897 uno::Sequence
<beans::PropertyValue
> aEmpty(0);
901 else if ( aPropertyName
== SC_UNO_DP_SOURCESERVICE
)
903 OUString aServiceName
;
904 const ScDPServiceDesc
* pServiceDesc
= pDPObject
->GetDPServiceDesc();
906 aServiceName
= pServiceDesc
->aServiceName
;
907 aRet
<<= aServiceName
; // empty string if no ServiceDesc set
909 else if ( aPropertyName
== SC_UNO_DP_SERVICEARG
)
911 const ScDPServiceDesc
* pServiceDesc
= pDPObject
->GetDPServiceDesc();
914 uno::Sequence
<beans::PropertyValue
> aSeq( comphelper::InitPropertySequence({
915 { SC_UNO_DP_SOURCENAME
, Any(pServiceDesc
->aParSource
) },
916 { SC_UNO_DP_OBJECTNAME
, Any(pServiceDesc
->aParName
) },
917 { SC_UNO_DP_USERNAME
, Any(pServiceDesc
->aParUser
) },
918 { SC_UNO_DP_PASSWORD
, Any(pServiceDesc
->aParPass
) }
925 uno::Sequence
<beans::PropertyValue
> aEmpty
;
930 throw UnknownPropertyException(aPropertyName
);
937 void SAL_CALL
ScDataPilotDescriptorBase::addPropertyChangeListener(
938 const OUString
& /* aPropertyName */, const Reference
<XPropertyChangeListener
>& /* xListener */ )
942 void SAL_CALL
ScDataPilotDescriptorBase::removePropertyChangeListener(
943 const OUString
& /* aPropertyName */, const Reference
<XPropertyChangeListener
>& /* aListener */ )
947 void SAL_CALL
ScDataPilotDescriptorBase::addVetoableChangeListener(
948 const OUString
& /* PropertyName */, const Reference
<XVetoableChangeListener
>& /* aListener */ )
952 void SAL_CALL
ScDataPilotDescriptorBase::removeVetoableChangeListener(
953 const OUString
& /* PropertyName */, const Reference
<XVetoableChangeListener
>& /* aListener */ )
957 // XDataPilotDataLayoutFieldSupplier
959 Reference
< XDataPilotField
> SAL_CALL
ScDataPilotDescriptorBase::getDataLayoutField()
961 SolarMutexGuard aGuard
;
962 if( ScDPObject
* pDPObject
= GetDPObject() )
964 if( ScDPSaveData
* pSaveData
= pDPObject
->GetSaveData() )
966 if( pSaveData
->GetDataLayoutDimension() )
968 ScFieldIdentifier
aFieldId( SC_DATALAYOUT_NAME
, true );
969 return new ScDataPilotFieldObj( *this, aFieldId
);
976 ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell
& rDocSh
, SCTAB nT
, OUString aN
) :
977 ScDataPilotDescriptorBase( rDocSh
),
979 aName(std::move( aN
)),
980 aModifyListeners( 0 )
984 ScDataPilotTableObj::~ScDataPilotTableObj()
988 Any SAL_CALL
ScDataPilotTableObj::queryInterface( const uno::Type
& rType
)
990 // since we manually do resolve the query for XDataPilotTable2
991 // we also need to do the same for XDataPilotTable
992 uno::Any aReturn
= ::cppu::queryInterface(rType
,
993 static_cast<XDataPilotTable
*>(this),
994 static_cast<XDataPilotTable2
*>(this),
995 static_cast<XModifyBroadcaster
*>(this));
996 if ( aReturn
.hasValue() )
999 return ScDataPilotDescriptorBase::queryInterface( rType
);
1002 void SAL_CALL
ScDataPilotTableObj::acquire() noexcept
1004 ScDataPilotDescriptorBase::acquire();
1007 void SAL_CALL
ScDataPilotTableObj::release() noexcept
1009 ScDataPilotDescriptorBase::release();
1012 Sequence
< uno::Type
> SAL_CALL
ScDataPilotTableObj::getTypes()
1014 return comphelper::concatSequences(
1015 ScDataPilotDescriptorBase::getTypes(),
1016 Sequence
< uno::Type
>
1018 cppu::UnoType
<XDataPilotTable2
>::get(),
1019 cppu::UnoType
<XModifyBroadcaster
>::get()
1023 Sequence
<sal_Int8
> SAL_CALL
ScDataPilotTableObj::getImplementationId()
1025 return css::uno::Sequence
<sal_Int8
>();
1028 ScDPObject
* ScDataPilotTableObj::GetDPObject() const
1030 return lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1033 void ScDataPilotTableObj::SetDPObject( ScDPObject
* pDPObject
)
1035 ScDocShell
* pDocSh
= GetDocShell();
1036 ScDPObject
* pDPObj
= lcl_GetDPObject(pDocSh
, nTab
, aName
);
1037 if ( pDPObj
&& pDocSh
)
1039 ScDBDocFunc
aFunc(*pDocSh
);
1040 aFunc
.DataPilotUpdate( pDPObj
, pDPObject
, true, true );
1044 // "rest of XDataPilotDescriptor"
1046 OUString SAL_CALL
ScDataPilotTableObj::getName()
1048 SolarMutexGuard aGuard
;
1049 ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1051 return pDPObj
->GetName();
1055 void SAL_CALL
ScDataPilotTableObj::setName( const OUString
& aNewName
)
1057 SolarMutexGuard aGuard
;
1058 ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1061 //! test for existing names !!!
1063 pDPObj
->SetName( aNewName
); //! Undo - DBDocFunc ???
1066 // DataPilotUpdate would do too much (output table is not changed)
1067 GetDocShell()->SetDocumentModified();
1071 OUString SAL_CALL
ScDataPilotTableObj::getTag()
1073 SolarMutexGuard aGuard
;
1074 ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1076 return pDPObj
->GetTag();
1080 void SAL_CALL
ScDataPilotTableObj::setTag( const OUString
& aNewTag
)
1082 SolarMutexGuard aGuard
;
1083 ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1086 pDPObj
->SetTag( aNewTag
); //! Undo - DBDocFunc ???
1088 // DataPilotUpdate would do too much (output table is not changed)
1089 GetDocShell()->SetDocumentModified();
1095 CellRangeAddress SAL_CALL
ScDataPilotTableObj::getOutputRange()
1097 SolarMutexGuard aGuard
;
1098 CellRangeAddress aRet
;
1099 ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1102 ScRange
aRange(pDPObj
->GetOutRange());
1103 aRet
.Sheet
= aRange
.aStart
.Tab();
1104 aRet
.StartColumn
= aRange
.aStart
.Col();
1105 aRet
.StartRow
= aRange
.aStart
.Row();
1106 aRet
.EndColumn
= aRange
.aEnd
.Col();
1107 aRet
.EndRow
= aRange
.aEnd
.Row();
1112 void SAL_CALL
ScDataPilotTableObj::refresh()
1114 SolarMutexGuard aGuard
;
1115 ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
);
1118 ScDBDocFunc
aFunc(*GetDocShell());
1119 aFunc
.RefreshPivotTables(pDPObj
, true);
1123 Sequence
< Sequence
<Any
> > SAL_CALL
ScDataPilotTableObj::getDrillDownData(const CellAddress
& aAddr
)
1125 SolarMutexGuard aGuard
;
1126 Sequence
< Sequence
<Any
> > aTabData
;
1127 ScAddress
aAddr2(static_cast<SCCOL
>(aAddr
.Column
), static_cast<SCROW
>(aAddr
.Row
), aAddr
.Sheet
);
1128 ScDPObject
* pObj
= GetDPObject();
1130 throw RuntimeException(u
"Failed to get DPObject"_ustr
, getXWeak());
1132 pObj
->GetDrillDownData(aAddr2
, aTabData
);
1136 DataPilotTablePositionData SAL_CALL
ScDataPilotTableObj::getPositionData(const CellAddress
& aAddr
)
1138 SolarMutexGuard aGuard
;
1139 DataPilotTablePositionData aPosData
;
1140 ScAddress
aAddr2(static_cast<SCCOL
>(aAddr
.Column
), static_cast<SCROW
>(aAddr
.Row
), aAddr
.Sheet
);
1141 ScDPObject
* pObj
= GetDPObject();
1143 throw RuntimeException(u
"Failed to get DPObject"_ustr
, getXWeak());
1145 pObj
->GetPositionData(aAddr2
, aPosData
);
1149 void SAL_CALL
ScDataPilotTableObj::insertDrillDownSheet(const CellAddress
& aAddr
)
1151 SolarMutexGuard aGuard
;
1152 ScDPObject
* pDPObj
= GetDPObject();
1154 throw RuntimeException(u
"Failed to get DPObject"_ustr
, getXWeak());
1155 ScTabViewShell
* pViewSh
= GetDocShell()->GetBestViewShell();
1157 throw RuntimeException(u
"Failed to get ViewShell"_ustr
, getXWeak());
1159 Sequence
<DataPilotFieldFilter
> aFilters
;
1160 pDPObj
->GetDataFieldPositionData(
1161 ScAddress(static_cast<SCCOL
>(aAddr
.Column
), static_cast<SCROW
>(aAddr
.Row
), aAddr
.Sheet
), aFilters
);
1162 pViewSh
->ShowDataPilotSourceData(*pDPObj
, aFilters
);
1165 CellRangeAddress SAL_CALL
ScDataPilotTableObj::getOutputRangeByType( sal_Int32 nType
)
1167 SolarMutexGuard aGuard
;
1168 if (nType
< 0 || nType
> DataPilotOutputRangeType::RESULT
)
1169 throw IllegalArgumentException("nType must be between 0 and " +
1170 OUString::number(DataPilotOutputRangeType::RESULT
) + ", got " + OUString::number(nType
),
1173 CellRangeAddress aRet
;
1174 if (ScDPObject
* pDPObj
= lcl_GetDPObject(GetDocShell(), nTab
, aName
))
1175 ScUnoConversion::FillApiRange( aRet
, pDPObj
->GetOutputRangeByType( nType
) );
1179 void SAL_CALL
ScDataPilotTableObj::addModifyListener( const uno::Reference
<util::XModifyListener
>& aListener
)
1181 SolarMutexGuard aGuard
;
1183 aModifyListeners
.emplace_back( aListener
);
1185 if ( aModifyListeners
.size() == 1 )
1187 acquire(); // don't lose this object (one ref for all listeners)
1191 void SAL_CALL
ScDataPilotTableObj::removeModifyListener( const uno::Reference
<util::XModifyListener
>& aListener
)
1193 SolarMutexGuard aGuard
;
1195 rtl::Reference
<ScDataPilotTableObj
> xSelfHold(this); // in case the listeners have the last ref
1197 sal_uInt16 nCount
= aModifyListeners
.size();
1198 for ( sal_uInt16 n
=nCount
; n
--; )
1200 uno::Reference
<util::XModifyListener
>& rObj
= aModifyListeners
[n
];
1201 if ( rObj
== aListener
)
1203 aModifyListeners
.erase( aModifyListeners
.begin() + n
);
1205 if ( aModifyListeners
.empty() )
1207 release(); // release the ref for the listeners
1215 void ScDataPilotTableObj::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1217 if ( rHint
.GetId() == SfxHintId::ScDataPilotModified
)
1219 auto pDataPilotHint
= static_cast<const ScDataPilotModifiedHint
*>(&rHint
);
1220 if (pDataPilotHint
->GetName() == aName
)
1223 else if ( rHint
.GetId() == SfxHintId::ScUpdateRef
)
1225 auto pRefHint
= static_cast<const ScUpdateRefHint
*>(&rHint
);
1226 ScRange
aRange( 0, 0, nTab
);
1227 ScRangeList
aRanges( aRange
);
1228 if ( aRanges
.UpdateReference( pRefHint
->GetMode(), &GetDocShell()->GetDocument(), pRefHint
->GetRange(),
1229 pRefHint
->GetDx(), pRefHint
->GetDy(), pRefHint
->GetDz() ) &&
1230 aRanges
.size() == 1 )
1232 nTab
= aRanges
.front().aStart
.Tab();
1236 ScDataPilotDescriptorBase::Notify( rBC
, rHint
);
1239 void ScDataPilotTableObj::Refreshed_Impl()
1241 lang::EventObject aEvent
;
1242 aEvent
.Source
= getXWeak();
1244 // the EventObject holds a Ref to this object until after the listener calls
1246 ScDocument
& rDoc
= GetDocShell()->GetDocument();
1247 for (const uno::Reference
<util::XModifyListener
> & xModifyListener
: aModifyListeners
)
1248 rDoc
.AddUnoListenerCall( xModifyListener
, aEvent
);
1251 ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell
& rDocSh
) :
1252 ScDataPilotDescriptorBase( rDocSh
),
1253 mpDPObject(new ScDPObject(&rDocSh
.GetDocument()))
1255 ScDPSaveData aSaveData
;
1256 // set defaults like in ScPivotParam constructor
1257 aSaveData
.SetColumnGrand( true );
1258 aSaveData
.SetRowGrand( true );
1259 aSaveData
.SetIgnoreEmptyRows( false );
1260 aSaveData
.SetRepeatIfEmpty( false );
1261 mpDPObject
->SetSaveData(aSaveData
);
1262 ScSheetSourceDesc
aSheetDesc(&rDocSh
.GetDocument());
1263 mpDPObject
->SetSheetDesc(aSheetDesc
);
1266 ScDataPilotDescriptor::~ScDataPilotDescriptor()
1270 ScDPObject
* ScDataPilotDescriptor::GetDPObject() const
1272 return mpDPObject
.get();
1275 void ScDataPilotDescriptor::SetDPObject( ScDPObject
* pDPObject
)
1277 if (mpDPObject
.get() != pDPObject
)
1279 mpDPObject
.reset( pDPObject
);
1280 OSL_FAIL("replace DPObject should not happen");
1284 // "rest of XDataPilotDescriptor"
1286 OUString SAL_CALL
ScDataPilotDescriptor::getName()
1288 SolarMutexGuard aGuard
;
1289 return mpDPObject
->GetName();
1292 void SAL_CALL
ScDataPilotDescriptor::setName( const OUString
& aNewName
)
1294 SolarMutexGuard aGuard
;
1295 mpDPObject
->SetName( aNewName
);
1298 OUString SAL_CALL
ScDataPilotDescriptor::getTag()
1300 SolarMutexGuard aGuard
;
1301 return mpDPObject
->GetTag();
1304 void SAL_CALL
ScDataPilotDescriptor::setTag( const OUString
& aNewTag
)
1306 SolarMutexGuard aGuard
;
1307 mpDPObject
->SetTag( aNewTag
);
1310 ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase
& rParent
) :
1311 mxParent( &rParent
)
1315 ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase
& rParent
, ScFieldIdentifier aFieldId
) :
1316 mxParent( &rParent
),
1317 maFieldId(std::move( aFieldId
))
1321 ScDataPilotChildObjBase::~ScDataPilotChildObjBase()
1325 ScDPObject
* ScDataPilotChildObjBase::GetDPObject() const
1327 return mxParent
->GetDPObject();
1330 void ScDataPilotChildObjBase::SetDPObject( ScDPObject
* pDPObject
)
1332 mxParent
->SetDPObject( pDPObject
);
1335 ScDPSaveDimension
* ScDataPilotChildObjBase::GetDPDimension( ScDPObject
** ppDPObject
) const
1337 if( ScDPObject
* pDPObj
= GetDPObject() )
1339 if( ppDPObject
) *ppDPObject
= pDPObj
;
1340 if( ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData() )
1342 if( maFieldId
.mbDataLayout
)
1343 return pSaveData
->GetDataLayoutDimension();
1345 if( maFieldId
.mnFieldIdx
== 0 )
1346 return pSaveData
->GetDimensionByName( maFieldId
.maFieldName
);
1348 // find dimension with specified index (search in duplicated dimensions)
1349 const ScDPSaveData::DimsType
& rDims
= pSaveData
->GetDimensions();
1351 sal_Int32 nFoundIdx
= 0;
1352 for (auto const& it
: rDims
)
1354 if (it
->IsDataLayout())
1357 OUString aSrcName
= ScDPUtil::getSourceDimensionName(it
->GetName());
1358 if (aSrcName
== maFieldId
.maFieldName
)
1360 if( nFoundIdx
== maFieldId
.mnFieldIdx
)
1370 sal_Int32
ScDataPilotChildObjBase::GetMemberCount() const
1373 Reference
<XNameAccess
> xMembersNA
= GetMembers();
1374 if (xMembersNA
.is())
1376 Reference
< XIndexAccess
> xMembersIA( new ScNameToIndexAccess( xMembersNA
) );
1377 nRet
= xMembersIA
->getCount();
1382 Reference
< XMembersAccess
> ScDataPilotChildObjBase::GetMembers() const
1384 Reference
< XMembersAccess
> xMembersNA
;
1385 if( ScDPObject
* pDPObj
= GetDPObject() )
1386 pDPObj
->GetMembersNA( lcl_GetObjectIndex( pDPObj
, maFieldId
), xMembersNA
);
1390 ScDocShell
* ScDataPilotChildObjBase::GetDocShell() const
1392 return mxParent
->GetDocShell();
1395 ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase
& rParent
) :
1396 ScDataPilotChildObjBase( rParent
)
1400 ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase
& rParent
, DataPilotFieldOrientation eOrient
) :
1401 ScDataPilotChildObjBase( rParent
),
1406 ScDataPilotFieldsObj::~ScDataPilotFieldsObj()
1410 static sal_Int32
lcl_GetFieldCount( const Reference
<XDimensionsSupplier
>& rSource
, const Any
& rOrient
)
1413 throw NullPointerException();
1417 Reference
<XNameAccess
> xDimsName(rSource
->getDimensions());
1418 Reference
<XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
1419 sal_Int32 nIntCount
= xIntDims
->getCount();
1420 for (sal_Int32 i
= 0; i
< nIntCount
; ++i
)
1422 Reference
<XPropertySet
> xDim(xIntDims
->getByIndex(i
), UNO_QUERY
);
1423 const bool bMatch
= xDim
1424 && (rOrient
.hasValue()
1425 // all fields of the specified orientation, including duplicated
1426 ? (xDim
->getPropertyValue(SC_UNO_DP_ORIENTATION
) == rOrient
)
1427 // count all non-duplicated fields
1428 : !lcl_IsDuplicated(xDim
));
1436 static bool lcl_GetFieldDataByIndex( const Reference
<XDimensionsSupplier
>& rSource
,
1437 const Any
& rOrient
, SCSIZE nIndex
, ScFieldIdentifier
& rFieldId
)
1440 throw NullPointerException();
1444 sal_Int32 nDimIndex
= 0;
1446 Reference
<XNameAccess
> xDimsName(rSource
->getDimensions());
1447 Reference
<XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
1448 sal_Int32 nIntCount
= xIntDims
->getCount();
1449 Reference
<XPropertySet
> xDim
;
1450 for (sal_Int32 i
= 0; i
< nIntCount
; ++i
)
1452 xDim
.set(xIntDims
->getByIndex(i
), UNO_QUERY
);
1453 const bool bMatch
= xDim
1454 && (rOrient
.hasValue()
1455 ? (xDim
->getPropertyValue(SC_UNO_DP_ORIENTATION
) == rOrient
)
1456 : !lcl_IsDuplicated(xDim
));
1472 xDim
.set( xIntDims
->getByIndex(nDimIndex
), UNO_QUERY
);
1473 Reference
<XNamed
> xDimName( xDim
, UNO_QUERY
);
1474 if ( xDimName
.is() )
1476 OUString
sOriginalName( lcl_GetOriginalName( xDimName
) );
1477 rFieldId
.maFieldName
= sOriginalName
;
1478 rFieldId
.mbDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDim
,
1479 SC_UNO_DP_ISDATALAYOUT
);
1481 sal_Int32 nRepeat
= 0;
1482 if ( rOrient
.hasValue() && lcl_IsDuplicated( xDim
) )
1484 // find the repeat count
1485 // (this relies on the original dimension always being before the duplicates)
1487 Reference
<XNamed
> xPrevName
;
1488 for (sal_Int32 i
= 0; i
< nDimIndex
; ++i
)
1490 xPrevName
.set( xIntDims
->getByIndex(i
), UNO_QUERY
);
1491 if ( xPrevName
.is() && lcl_GetOriginalName( xPrevName
) == sOriginalName
)
1495 rFieldId
.mnFieldIdx
= nRepeat
;
1504 static bool lcl_GetFieldDataByName( ScDPObject
* pDPObj
, const OUString
& rFieldName
, ScFieldIdentifier
& rFieldId
)
1506 // "By name" is always the first match.
1507 // The name "Data" always refers to the data layout field.
1508 rFieldId
.maFieldName
= rFieldName
;
1509 rFieldId
.mnFieldIdx
= 0;
1510 rFieldId
.mbDataLayout
= rFieldName
== SC_DATALAYOUT_NAME
;
1512 pDPObj
->GetSource(); // IsDimNameInUse doesn't update source data
1514 // check if the named field exists (not for data layout)
1515 return rFieldId
.mbDataLayout
|| pDPObj
->IsDimNameInUse( rFieldName
);
1520 rtl::Reference
<ScDataPilotFieldObj
> ScDataPilotFieldsObj::GetObjectByIndex_Impl( sal_Int32 nIndex
) const
1522 if (ScDPObject
* pObj
= GetDPObject())
1524 ScFieldIdentifier aFieldId
;
1525 if (lcl_GetFieldDataByIndex( pObj
->GetSource(), maOrient
, nIndex
, aFieldId
))
1526 return new ScDataPilotFieldObj( *mxParent
, aFieldId
, maOrient
);
1531 rtl::Reference
<ScDataPilotFieldObj
> ScDataPilotFieldsObj::GetObjectByName_Impl(const OUString
& aName
) const
1533 if (ScDPObject
* pDPObj
= GetDPObject())
1535 ScFieldIdentifier aFieldId
;
1536 if (lcl_GetFieldDataByName( pDPObj
, aName
, aFieldId
))
1537 return new ScDataPilotFieldObj( *mxParent
, aFieldId
, maOrient
);
1542 // XEnumerationAccess
1544 Reference
<XEnumeration
> SAL_CALL
ScDataPilotFieldsObj::createEnumeration()
1546 SolarMutexGuard aGuard
;
1547 return new ScIndexEnumeration(this, u
"com.sun.star.sheet.DataPilotFieldsEnumeration"_ustr
);
1552 sal_Int32 SAL_CALL
ScDataPilotFieldsObj::getCount()
1554 SolarMutexGuard aGuard
;
1555 ScDPObject
* pDPObj
= GetDPObject();
1556 return pDPObj
? lcl_GetFieldCount( pDPObj
->GetSource(), maOrient
) : 0;
1559 Any SAL_CALL
ScDataPilotFieldsObj::getByIndex( sal_Int32 nIndex
)
1561 SolarMutexGuard aGuard
;
1562 Reference
< XPropertySet
> xField( GetObjectByIndex_Impl( nIndex
) );
1564 throw IndexOutOfBoundsException();
1565 return Any( xField
);
1570 uno::Type SAL_CALL
ScDataPilotFieldsObj::getElementType()
1572 return cppu::UnoType
<XPropertySet
>::get();
1575 sal_Bool SAL_CALL
ScDataPilotFieldsObj::hasElements()
1577 SolarMutexGuard aGuard
;
1578 return ( getCount() != 0 );
1583 Any SAL_CALL
ScDataPilotFieldsObj::getByName( const OUString
& aName
)
1585 SolarMutexGuard aGuard
;
1586 Reference
<XPropertySet
> xField(GetObjectByName_Impl(aName
));
1588 throw NoSuchElementException();
1589 return Any( xField
);
1592 Sequence
<OUString
> SAL_CALL
ScDataPilotFieldsObj::getElementNames()
1594 SolarMutexGuard aGuard
;
1595 if (ScDPObject
* pDPObj
= GetDPObject())
1597 Sequence
< OUString
> aSeq( lcl_GetFieldCount( pDPObj
->GetSource(), maOrient
) );
1598 OUString
* pAry
= aSeq
.getArray();
1600 const ScDPSaveData::DimsType
& rDimensions
= pDPObj
->GetSaveData()->GetDimensions();
1601 for (auto const& it
: rDimensions
)
1603 if(maOrient
.hasValue() && (it
->GetOrientation() == maOrient
.get
< DataPilotFieldOrientation
>()))
1605 *pAry
= it
->GetName();
1611 return Sequence
<OUString
>();
1614 sal_Bool SAL_CALL
ScDataPilotFieldsObj::hasByName( const OUString
& aName
)
1616 SolarMutexGuard aGuard
;
1618 return GetObjectByName_Impl(aName
) != nullptr;
1621 ScDataPilotFieldObj::ScDataPilotFieldObj(
1622 ScDataPilotDescriptorBase
& rParent
, const ScFieldIdentifier
& rFieldId
) :
1623 ScDataPilotChildObjBase( rParent
, rFieldId
),
1624 maPropSet( lcl_GetDataPilotFieldMap() )
1628 ScDataPilotFieldObj::ScDataPilotFieldObj( ScDataPilotDescriptorBase
& rParent
,
1629 const ScFieldIdentifier
& rFieldId
, Any aOrient
) :
1630 ScDataPilotChildObjBase( rParent
, rFieldId
),
1631 maPropSet( lcl_GetDataPilotFieldMap() ),
1632 maOrient(std::move( aOrient
))
1636 ScDataPilotFieldObj::~ScDataPilotFieldObj()
1642 OUString SAL_CALL
ScDataPilotFieldObj::getName()
1644 SolarMutexGuard aGuard
;
1646 if( ScDPSaveDimension
* pDim
= GetDPDimension() )
1648 if( pDim
->IsDataLayout() )
1649 aName
= SC_DATALAYOUT_NAME
;
1652 const std::optional
<OUString
> & pLayoutName
= pDim
->GetLayoutName();
1654 aName
= *pLayoutName
;
1656 aName
= pDim
->GetName();
1662 void SAL_CALL
ScDataPilotFieldObj::setName(const OUString
& rName
)
1664 SolarMutexGuard aGuard
;
1665 ScDPObject
* pDPObj
= nullptr;
1666 ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
);
1667 if( pDim
&& !pDim
->IsDataLayout() )
1669 pDim
->SetLayoutName(rName
);
1670 SetDPObject( pDPObj
);
1676 Reference
<XPropertySetInfo
> SAL_CALL
ScDataPilotFieldObj::getPropertySetInfo()
1678 SolarMutexGuard aGuard
;
1679 static Reference
<XPropertySetInfo
> aRef(
1680 new SfxItemPropertySetInfo( maPropSet
.getPropertyMap() ));
1684 void SAL_CALL
ScDataPilotFieldObj::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
1686 SolarMutexGuard aGuard
;
1687 if ( aPropertyName
== SC_UNONAME_FUNCTION
)
1689 // #i109350# use GetEnumFromAny because it also allows sal_Int32
1690 ScGeneralFunction eFunction
= static_cast<ScGeneralFunction
>(ScUnoHelpFunctions::GetEnumFromAny( aValue
));
1691 setFunction( eFunction
);
1693 else if ( aPropertyName
== SC_UNONAME_FUNCTION2
)
1695 ScGeneralFunction eFunction
= static_cast<ScGeneralFunction
>(ScUnoHelpFunctions::GetInt16FromAny( aValue
));
1696 setFunction( eFunction
);
1698 else if ( aPropertyName
== SC_UNONAME_SUBTOTALS
)
1700 uno::Sequence
<sheet::GeneralFunction
> aSeq
;
1701 if( aValue
>>= aSeq
)
1703 std::vector
< ScGeneralFunction
> aSubTotals(aSeq
.getLength());
1704 std::transform(std::cbegin(aSeq
), std::cend(aSeq
), aSubTotals
.begin(),
1705 [](const sheet::GeneralFunction
& rValue
) -> ScGeneralFunction
{
1706 const int nValAsInt
= static_cast<int>(rValue
);
1707 return static_cast<ScGeneralFunction
>(nValAsInt
);
1709 setSubtotals( aSubTotals
);
1712 else if ( aPropertyName
== SC_UNONAME_SUBTOTALS2
)
1714 Sequence
< sal_Int16
> aSeq
;
1715 if( aValue
>>= aSeq
)
1717 std::vector
< ScGeneralFunction
> aSubTotals(aSeq
.getLength());
1718 std::transform(std::cbegin(aSeq
), std::cend(aSeq
), aSubTotals
.begin(),
1719 [](sal_Int16 nValue
) -> ScGeneralFunction
{ return static_cast<ScGeneralFunction
>(nValue
); });
1720 setSubtotals( aSubTotals
);
1723 else if ( aPropertyName
== SC_UNONAME_ORIENT
)
1725 //! test for correct enum type?
1726 DataPilotFieldOrientation eOrient
= static_cast<DataPilotFieldOrientation
>(ScUnoHelpFunctions::GetEnumFromAny( aValue
));
1727 setOrientation( eOrient
);
1729 else if ( aPropertyName
== SC_UNONAME_SELPAGE
)
1731 OUString sCurrentPage
;
1732 if (aValue
>>= sCurrentPage
)
1733 setCurrentPage(sCurrentPage
);
1735 else if ( aPropertyName
== SC_UNONAME_USESELPAGE
)
1737 setUseCurrentPage(cppu::any2bool(aValue
));
1739 else if ( aPropertyName
== SC_UNONAME_HASAUTOSHOW
)
1741 if (!cppu::any2bool(aValue
))
1742 setAutoShowInfo(nullptr);
1744 else if ( aPropertyName
== SC_UNONAME_AUTOSHOW
)
1746 DataPilotFieldAutoShowInfo aInfo
;
1747 if (aValue
>>= aInfo
)
1748 setAutoShowInfo(&aInfo
);
1750 else if ( aPropertyName
== SC_UNONAME_HASLAYOUTINFO
)
1752 if (!cppu::any2bool(aValue
))
1753 setLayoutInfo(nullptr);
1755 else if ( aPropertyName
== SC_UNONAME_LAYOUTINFO
)
1757 DataPilotFieldLayoutInfo aInfo
;
1758 if (aValue
>>= aInfo
)
1759 setLayoutInfo(&aInfo
);
1761 else if ( aPropertyName
== SC_UNONAME_HASREFERENCE
)
1763 if (!cppu::any2bool(aValue
))
1764 setReference(nullptr);
1766 else if ( aPropertyName
== SC_UNONAME_REFERENCE
)
1768 DataPilotFieldReference aRef
;
1769 if (aValue
>>= aRef
)
1770 setReference(&aRef
);
1772 else if ( aPropertyName
== SC_UNONAME_HASSORTINFO
)
1774 if (!cppu::any2bool(aValue
))
1775 setSortInfo(nullptr);
1777 else if ( aPropertyName
== SC_UNONAME_SORTINFO
)
1779 DataPilotFieldSortInfo aInfo
;
1780 if (aValue
>>= aInfo
)
1781 setSortInfo(&aInfo
);
1783 else if ( aPropertyName
== SC_UNONAME_ISGROUP
)
1785 if (!cppu::any2bool(aValue
))
1786 setGroupInfo(nullptr);
1788 else if ( aPropertyName
== SC_UNONAME_GROUPINFO
)
1790 DataPilotFieldGroupInfo aInfo
;
1791 if (aValue
>>= aInfo
)
1792 setGroupInfo(&aInfo
);
1794 else if ( aPropertyName
== SC_UNONAME_SHOWEMPTY
)
1796 setShowEmpty(cppu::any2bool(aValue
));
1798 else if ( aPropertyName
== SC_UNONAME_REPEATITEMLABELS
)
1800 setRepeatItemLabels(cppu::any2bool(aValue
));
1802 else if (aPropertyName
== SC_UNONAME_NAME
)
1805 if (aValue
>>= sName
)
1810 Any SAL_CALL
ScDataPilotFieldObj::getPropertyValue( const OUString
& aPropertyName
)
1812 SolarMutexGuard aGuard
;
1815 if ( aPropertyName
== SC_UNONAME_FUNCTION
)
1817 sheet::GeneralFunction eVal
;
1818 sal_Int16 nFunction
= getFunction();
1819 if (nFunction
== sheet::GeneralFunction2::MEDIAN
)
1821 eVal
= sheet::GeneralFunction_NONE
;
1825 eVal
= static_cast<sheet::GeneralFunction
>(nFunction
);
1829 else if ( aPropertyName
== SC_UNONAME_FUNCTION2
)
1830 aRet
<<= getFunction();
1831 else if ( aPropertyName
== SC_UNONAME_SUBTOTALS
)
1833 const uno::Sequence
<sal_Int16
> aSeq
= getSubtotals();
1834 uno::Sequence
<sheet::GeneralFunction
> aNewSeq(aSeq
.getLength());
1835 std::transform(aSeq
.begin(), aSeq
.end(), aNewSeq
.getArray(),
1836 [](sal_Int16 nFunc
) -> sheet::GeneralFunction
{
1837 if (nFunc
== sheet::GeneralFunction2::MEDIAN
)
1838 return sheet::GeneralFunction_NONE
;
1839 return static_cast<sheet::GeneralFunction
>(nFunc
);
1843 else if ( aPropertyName
== SC_UNONAME_SUBTOTALS2
)
1845 aRet
<<= getSubtotals();
1847 else if ( aPropertyName
== SC_UNONAME_ORIENT
)
1848 aRet
<<= getOrientation();
1849 else if ( aPropertyName
== SC_UNONAME_SELPAGE
)
1850 aRet
<<= OUString();
1851 else if ( aPropertyName
== SC_UNONAME_USESELPAGE
)
1853 else if ( aPropertyName
== SC_UNONAME_HASAUTOSHOW
)
1854 aRet
<<= (getAutoShowInfo() != nullptr);
1855 else if ( aPropertyName
== SC_UNONAME_AUTOSHOW
)
1857 const DataPilotFieldAutoShowInfo
* pInfo
= getAutoShowInfo();
1861 else if ( aPropertyName
== SC_UNONAME_HASLAYOUTINFO
)
1862 aRet
<<= (getLayoutInfo() != nullptr);
1863 else if ( aPropertyName
== SC_UNONAME_LAYOUTINFO
)
1865 const DataPilotFieldLayoutInfo
* pInfo
= getLayoutInfo();
1869 else if ( aPropertyName
== SC_UNONAME_HASREFERENCE
)
1870 aRet
<<= (getReference() != nullptr);
1871 else if ( aPropertyName
== SC_UNONAME_REFERENCE
)
1873 const DataPilotFieldReference
* pRef
= getReference();
1877 else if ( aPropertyName
== SC_UNONAME_HASSORTINFO
)
1878 aRet
<<= (getSortInfo() != nullptr);
1879 else if ( aPropertyName
== SC_UNONAME_SORTINFO
)
1881 const DataPilotFieldSortInfo
* pInfo
= getSortInfo();
1885 else if ( aPropertyName
== SC_UNONAME_ISGROUP
)
1886 aRet
<<= hasGroupInfo();
1887 else if ( aPropertyName
== SC_UNONAME_GROUPINFO
)
1889 aRet
<<= getGroupInfo();
1891 else if ( aPropertyName
== SC_UNONAME_SHOWEMPTY
)
1892 aRet
<<= getShowEmpty();
1893 else if ( aPropertyName
== SC_UNONAME_REPEATITEMLABELS
)
1894 aRet
<<= getRepeatItemLabels();
1895 else if (aPropertyName
== SC_UNONAME_NAME
)
1903 Reference
<XIndexAccess
> SAL_CALL
ScDataPilotFieldObj::getItems()
1905 SolarMutexGuard aGuard
;
1907 mxItems
.set( new ScDataPilotItemsObj( *mxParent
, maFieldId
) );
1911 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDataPilotFieldObj
)
1913 DataPilotFieldOrientation
ScDataPilotFieldObj::getOrientation() const
1915 SolarMutexGuard aGuard
;
1916 ScDPSaveDimension
* pDim
= GetDPDimension();
1917 return pDim
? pDim
->GetOrientation() : DataPilotFieldOrientation_HIDDEN
;
1920 void ScDataPilotFieldObj::setOrientation(DataPilotFieldOrientation eNew
)
1922 SolarMutexGuard aGuard
;
1923 if (maOrient
.hasValue() && (eNew
== maOrient
.get
< DataPilotFieldOrientation
>()))
1926 ScDPObject
* pDPObj
= nullptr;
1927 ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
);
1931 ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
1933 /* If the field was taken from getDataPilotFields(), don't reset the
1934 orientation for an existing use, but create a duplicated field
1935 instead (for "Data" orientation only). */
1936 if ( !maOrient
.hasValue() && !maFieldId
.mbDataLayout
&&
1937 (pDim
->GetOrientation() != DataPilotFieldOrientation_HIDDEN
) &&
1938 (eNew
== DataPilotFieldOrientation_DATA
) )
1941 ScDPSaveDimension
* pNewDim
= nullptr;
1943 // look for existing duplicate with orientation "hidden"
1945 sal_Int32 nFound
= 0;
1946 const ScDPSaveData::DimsType
& rDimensions
= pSaveData
->GetDimensions();
1947 for (auto const& it
: rDimensions
)
1949 if ( !it
->IsDataLayout() && (it
->GetName() == maFieldId
.maFieldName
) )
1951 if ( it
->GetOrientation() == DataPilotFieldOrientation_HIDDEN
)
1953 pNewDim
= it
.get(); // use this one
1957 ++nFound
; // count existing non-hidden occurrences
1961 if ( !pNewDim
) // if none found, create a new duplicated dimension
1962 pNewDim
= &pSaveData
->DuplicateDimension( *pDim
);
1964 maFieldId
.mnFieldIdx
= nFound
; // keep accessing the new one
1968 pDim
->SetOrientation(eNew
);
1970 // move changed field behind all other fields (make it the last field in dimension)
1971 pSaveData
->SetPosition( pDim
, pSaveData
->GetDimensions().size() );
1973 SetDPObject( pDPObj
);
1975 maOrient
<<= eNew
; // modifying the same object's orientation again doesn't create another duplicate
1978 sal_Int16
ScDataPilotFieldObj::getFunction() const
1980 SolarMutexGuard aGuard
;
1981 sal_Int16 eRet
= GeneralFunction2::NONE
;
1982 if( ScDPSaveDimension
* pDim
= GetDPDimension() )
1984 if( pDim
->GetOrientation() != DataPilotFieldOrientation_DATA
)
1986 // for non-data fields, property Function is the subtotals
1987 tools::Long nSubCount
= pDim
->GetSubTotalsCount();
1988 if ( nSubCount
> 0 )
1989 eRet
= static_cast<sal_Int16
>(pDim
->GetSubTotalFunc(0)); // always use the first one
1993 eRet
= static_cast<sal_Int16
>(pDim
->GetFunction());
1998 void ScDataPilotFieldObj::setFunction(ScGeneralFunction eNewFunc
)
2000 SolarMutexGuard aGuard
;
2001 ScDPObject
* pDPObj
= nullptr;
2002 ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
);
2006 if( pDim
->GetOrientation() != DataPilotFieldOrientation_DATA
)
2008 // for non-data fields, property Function is the subtotals
2009 std::vector
<ScGeneralFunction
> nSubTotalFuncs
;
2010 if ( eNewFunc
!= ScGeneralFunction::NONE
)
2012 nSubTotalFuncs
.push_back( eNewFunc
);
2014 pDim
->SetSubTotals( std::move(nSubTotalFuncs
) );
2017 pDim
->SetFunction( eNewFunc
);
2018 SetDPObject( pDPObj
);
2021 Sequence
< sal_Int16
> ScDataPilotFieldObj::getSubtotals() const
2023 SolarMutexGuard aGuard
;
2024 Sequence
< sal_Int16
> aRet
;
2025 if( ScDPSaveDimension
* pDim
= GetDPDimension() )
2027 if( pDim
->GetOrientation() != DataPilotFieldOrientation_DATA
)
2029 // for non-data fields, property Functions is the sequence of subtotals
2030 sal_Int32 nCount
= static_cast< sal_Int32
>( pDim
->GetSubTotalsCount() );
2033 aRet
.realloc( nCount
);
2034 auto pRet
= aRet
.getArray();
2035 for( sal_Int32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
2036 pRet
[ nIdx
] = static_cast<sal_Int16
>(pDim
->GetSubTotalFunc( nIdx
));
2043 void ScDataPilotFieldObj::setSubtotals( const std::vector
< ScGeneralFunction
>& rSubtotals
)
2045 SolarMutexGuard aGuard
;
2046 ScDPObject
* pDPObj
= nullptr;
2047 ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
);
2051 if( pDim
->GetOrientation() != DataPilotFieldOrientation_DATA
)
2053 sal_Int32 nCount
= rSubtotals
.size();
2056 // count 1: all values are allowed (including NONE and AUTO)
2057 std::vector
<ScGeneralFunction
> nTmpFuncs
;
2058 if( rSubtotals
[ 0 ] != ScGeneralFunction::NONE
)
2060 nTmpFuncs
.push_back( rSubtotals
[ 0 ] );
2062 pDim
->SetSubTotals( std::move(nTmpFuncs
) );
2064 else if( nCount
> 1 )
2066 // set multiple functions, ignore NONE and AUTO in this case
2067 ::std::vector
< ScGeneralFunction
> aSubt
;
2068 for( sal_Int32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
2070 ScGeneralFunction eFunc
= rSubtotals
[ nIdx
];
2071 if( (eFunc
!= ScGeneralFunction::NONE
) && (eFunc
!= ScGeneralFunction::AUTO
) )
2073 // do not insert functions twice
2074 if( ::std::find( aSubt
.begin(), aSubt
.end(), eFunc
) == aSubt
.end() )
2075 aSubt
.push_back( eFunc
);
2078 // set values from vector to ScDPSaveDimension
2079 pDim
->SetSubTotals( std::move(aSubt
) );
2082 SetDPObject( pDPObj
);
2085 void ScDataPilotFieldObj::setCurrentPage( const OUString
& rPage
)
2087 SolarMutexGuard aGuard
;
2088 ScDPObject
* pDPObj
= nullptr;
2089 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2091 pDim
->SetCurrentPage( &rPage
);
2092 SetDPObject( pDPObj
);
2096 void ScDataPilotFieldObj::setUseCurrentPage( bool bUse
)
2098 SolarMutexGuard aGuard
;
2099 ScDPObject
* pDPObj
= nullptr;
2100 ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
);
2106 /* It is somehow useless to set the property "HasSelectedPage" to
2107 true, because it is still needed to set an explicit page name. */
2108 const OUString aPage
;
2109 pDim
->SetCurrentPage( &aPage
);
2112 pDim
->SetCurrentPage( nullptr );
2113 SetDPObject( pDPObj
);
2116 const DataPilotFieldAutoShowInfo
* ScDataPilotFieldObj::getAutoShowInfo() const
2118 SolarMutexGuard aGuard
;
2119 ScDPSaveDimension
* pDim
= GetDPDimension();
2120 return pDim
? pDim
->GetAutoShowInfo() : nullptr;
2123 void ScDataPilotFieldObj::setAutoShowInfo( const DataPilotFieldAutoShowInfo
* pInfo
)
2125 SolarMutexGuard aGuard
;
2126 ScDPObject
* pDPObj
= nullptr;
2127 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2129 pDim
->SetAutoShowInfo( pInfo
);
2130 SetDPObject( pDPObj
);
2134 const DataPilotFieldLayoutInfo
* ScDataPilotFieldObj::getLayoutInfo() const
2136 SolarMutexGuard aGuard
;
2137 ScDPSaveDimension
* pDim
= GetDPDimension();
2138 return pDim
? pDim
->GetLayoutInfo() : nullptr;
2141 void ScDataPilotFieldObj::setLayoutInfo( const DataPilotFieldLayoutInfo
* pInfo
)
2143 SolarMutexGuard aGuard
;
2144 ScDPObject
* pDPObj
= nullptr;
2145 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2147 pDim
->SetLayoutInfo( pInfo
);
2148 SetDPObject( pDPObj
);
2152 const DataPilotFieldReference
* ScDataPilotFieldObj::getReference() const
2154 SolarMutexGuard aGuard
;
2155 ScDPSaveDimension
* pDim
= GetDPDimension();
2156 return pDim
? pDim
->GetReferenceValue() : nullptr;
2159 void ScDataPilotFieldObj::setReference( const DataPilotFieldReference
* pInfo
)
2161 SolarMutexGuard aGuard
;
2162 ScDPObject
* pDPObj
= nullptr;
2163 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2165 pDim
->SetReferenceValue( pInfo
);
2166 SetDPObject( pDPObj
);
2170 const DataPilotFieldSortInfo
* ScDataPilotFieldObj::getSortInfo() const
2172 SolarMutexGuard aGuard
;
2173 ScDPSaveDimension
* pDim
= GetDPDimension();
2174 return pDim
? pDim
->GetSortInfo() : nullptr;
2177 void ScDataPilotFieldObj::setSortInfo( const DataPilotFieldSortInfo
* pInfo
)
2179 SolarMutexGuard aGuard
;
2180 ScDPObject
* pDPObj
= nullptr;
2181 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2183 pDim
->SetSortInfo( pInfo
);
2184 SetDPObject( pDPObj
);
2188 bool ScDataPilotFieldObj::getShowEmpty() const
2190 SolarMutexGuard aGuard
;
2191 ScDPSaveDimension
* pDim
= GetDPDimension();
2192 return pDim
&& pDim
->GetShowEmpty();
2195 void ScDataPilotFieldObj::setShowEmpty( bool bShow
)
2197 SolarMutexGuard aGuard
;
2198 ScDPObject
* pDPObj
= nullptr;
2199 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2201 pDim
->SetShowEmpty( bShow
);
2202 SetDPObject( pDPObj
);
2206 bool ScDataPilotFieldObj::getRepeatItemLabels() const
2208 SolarMutexGuard aGuard
;
2209 ScDPSaveDimension
* pDim
= GetDPDimension();
2210 return pDim
&& pDim
->GetRepeatItemLabels();
2213 void ScDataPilotFieldObj::setRepeatItemLabels( bool bShow
)
2215 SolarMutexGuard aGuard
;
2216 ScDPObject
* pDPObj
= nullptr;
2217 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2219 pDim
->SetRepeatItemLabels( bShow
);
2220 SetDPObject( pDPObj
);
2224 bool ScDataPilotFieldObj::hasGroupInfo() const
2226 SolarMutexGuard aGuard
;
2227 ScDPObject
* pDPObj
= nullptr;
2228 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2229 if( const ScDPDimensionSaveData
* pDimData
= pDPObj
->GetSaveData()->GetExistingDimensionData() )
2230 return pDimData
->GetNamedGroupDim( pDim
->GetName() ) || pDimData
->GetNumGroupDim( pDim
->GetName() );
2234 DataPilotFieldGroupInfo
ScDataPilotFieldObj::getGroupInfo()
2236 SolarMutexGuard aGuard
;
2237 DataPilotFieldGroupInfo aInfo
;
2238 ScDPObject
* pDPObj
= nullptr;
2239 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2241 if( const ScDPDimensionSaveData
* pDimData
= pDPObj
->GetSaveData()->GetExistingDimensionData() )
2243 if( const ScDPSaveGroupDimension
* pGroupDim
= pDimData
->GetNamedGroupDim( pDim
->GetName() ) )
2246 aInfo
.GroupBy
= pGroupDim
->GetDatePart();
2248 // find source field
2251 Reference
< XNameAccess
> xFields( mxParent
->getDataPilotFields(), UNO_QUERY_THROW
);
2252 aInfo
.SourceField
.set( xFields
->getByName( pGroupDim
->GetSourceDimName() ), UNO_QUERY
);
2258 ScDataPilotConversion::FillGroupInfo( aInfo
, pGroupDim
->GetDateInfo() );
2259 if( pGroupDim
->GetDatePart() == 0 )
2261 // fill vector of group and group member information
2262 ScFieldGroups aGroups
;
2263 for( sal_Int32 nIdx
= 0, nCount
= pGroupDim
->GetGroupCount(); nIdx
< nCount
; ++nIdx
)
2265 const ScDPSaveGroupItem
& rGroup
= pGroupDim
->GetGroupByIndex( nIdx
);
2266 ScFieldGroup aGroup
;
2267 aGroup
.maName
= rGroup
.GetGroupName();
2268 for( sal_Int32 nMemIdx
= 0, nMemCount
= rGroup
.GetElementCount(); nMemIdx
< nMemCount
; ++nMemIdx
)
2269 if (const OUString
* pMem
= rGroup
.GetElementByIndex(nMemIdx
))
2270 aGroup
.maMembers
.push_back( *pMem
);
2271 aGroups
.push_back( aGroup
);
2273 aInfo
.Groups
= new ScDataPilotFieldGroupsObj( std::move(aGroups
) );
2276 else if( const ScDPSaveNumGroupDimension
* pNumGroupDim
= pDimData
->GetNumGroupDim( pDim
->GetName() ) )
2278 if (pNumGroupDim
->GetDatePart())
2280 ScDataPilotConversion::FillGroupInfo( aInfo
, pNumGroupDim
->GetDateInfo() );
2281 aInfo
.GroupBy
= pNumGroupDim
->GetDatePart();
2285 ScDataPilotConversion::FillGroupInfo( aInfo
, pNumGroupDim
->GetInfo() );
2293 void ScDataPilotFieldObj::setGroupInfo( const DataPilotFieldGroupInfo
* pInfo
)
2295 SolarMutexGuard aGuard
;
2296 ScDPObject
* pDPObj
= nullptr;
2297 if( /*ScDPSaveDimension* pDim =*/ !GetDPDimension( &pDPObj
) )
2300 ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
2301 if( pInfo
&& lclCheckMinMaxStep( *pInfo
) )
2303 ScDPNumGroupInfo aInfo
;
2304 aInfo
.mbEnable
= true;
2305 aInfo
.mbDateValues
= pInfo
->HasDateValues
;
2306 aInfo
.mbAutoStart
= pInfo
->HasAutoStart
;
2307 aInfo
.mbAutoEnd
= pInfo
->HasAutoEnd
;
2308 aInfo
.mfStart
= pInfo
->Start
;
2309 aInfo
.mfEnd
= pInfo
->End
;
2310 aInfo
.mfStep
= pInfo
->Step
;
2311 Reference
< XNamed
> xNamed( pInfo
->SourceField
, UNO_QUERY
);
2314 ScDPSaveGroupDimension
aGroupDim( xNamed
->getName(), getName() );
2315 if( pInfo
->GroupBy
)
2316 aGroupDim
.SetDateInfo(aInfo
, pInfo
->GroupBy
);
2319 Reference
<XIndexAccess
> xIndex(pInfo
->Groups
, UNO_QUERY
);
2322 sal_Int32
nCount(xIndex
->getCount());
2323 for(sal_Int32 i
= 0; i
< nCount
; i
++)
2325 Reference
<XNamed
> xGroupNamed(xIndex
->getByIndex(i
), UNO_QUERY
);
2326 if (xGroupNamed
.is())
2328 ScDPSaveGroupItem
aItem(xGroupNamed
->getName());
2329 Reference
<XIndexAccess
> xGroupIndex(xGroupNamed
, UNO_QUERY
);
2330 if (xGroupIndex
.is())
2332 sal_Int32
nItemCount(xGroupIndex
->getCount());
2333 for (sal_Int32 j
= 0; j
< nItemCount
; ++j
)
2335 Reference
<XNamed
> xItemNamed(xGroupIndex
->getByIndex(j
), UNO_QUERY
);
2336 if (xItemNamed
.is())
2337 aItem
.AddElement(xItemNamed
->getName());
2340 aGroupDim
.AddGroupItem(aItem
);
2346 // get dimension savedata or create new if none
2347 ScDPDimensionSaveData
& rDimSaveData
= *pSaveData
->GetDimensionData();
2348 rDimSaveData
.ReplaceGroupDimension( aGroupDim
);
2350 else // no source field in group info -> numeric group
2352 ScDPDimensionSaveData
* pDimData
= pSaveData
->GetDimensionData(); // created if not there
2354 ScDPSaveNumGroupDimension
* pExisting
= pDimData
->GetNumGroupDimAcc( getName() );
2358 pExisting
->SetDateInfo(aInfo
, pInfo
->GroupBy
);
2359 // modify existing group dimension
2360 pExisting
->SetGroupInfo( aInfo
);
2362 else if (pInfo
->GroupBy
)
2364 // create new group dimension
2365 ScDPSaveNumGroupDimension
aNumGroupDim( getName(), aInfo
, pInfo
->GroupBy
);
2366 pDimData
->AddNumGroupDimension( aNumGroupDim
);
2370 // create new group dimension
2371 ScDPSaveNumGroupDimension
aNumGroupDim( getName(), aInfo
);
2372 pDimData
->AddNumGroupDimension( aNumGroupDim
);
2376 else // null passed as argument
2378 pSaveData
->SetDimensionData( nullptr );
2381 pDPObj
->SetSaveData( *pSaveData
);
2382 SetDPObject( pDPObj
);
2385 // XDataPilotFieldGrouping
2386 Reference
< XDataPilotField
> SAL_CALL
ScDataPilotFieldObj::createNameGroup( const Sequence
< OUString
>& rItems
)
2388 SolarMutexGuard aGuard
;
2390 if( !rItems
.hasElements() )
2391 throw IllegalArgumentException(u
"rItems is empty"_ustr
, getXWeak(), 0);
2393 Reference
< XMembersAccess
> xMembers
= GetMembers();
2396 SAL_WARN("sc.ui", "Cannot access members of the field object.");
2397 throw RuntimeException(u
"Cannot access members of the field object"_ustr
, getXWeak());
2400 for (const OUString
& aEntryName
: rItems
)
2402 if (!xMembers
->hasByName(aEntryName
))
2404 SAL_WARN("sc.ui", "There is no member with that name: " + aEntryName
+ ".");
2405 throw IllegalArgumentException("There is no member with name \"" + aEntryName
+ "\"", getXWeak(), 0);
2409 Reference
< XDataPilotField
> xRet
;
2411 ScDPObject
* pDPObj
= nullptr;
2412 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2414 const OUString
& aDimName
= pDim
->GetName();
2416 ScDPSaveData aSaveData
= *pDPObj
->GetSaveData();
2417 ScDPDimensionSaveData
* pDimData
= aSaveData
.GetDimensionData(); // created if not there
2419 // find original base
2420 OUString
aBaseDimName( aDimName
);
2421 const ScDPSaveGroupDimension
* pBaseGroupDim
= pDimData
->GetNamedGroupDim( aDimName
);
2422 if ( pBaseGroupDim
)
2424 // any entry's SourceDimName is the original base
2425 aBaseDimName
= pBaseGroupDim
->GetSourceDimName();
2428 // find existing group dimension
2429 // (using the selected dim, can be intermediate group dim)
2430 ScDPSaveGroupDimension
* pGroupDimension
= pDimData
->GetGroupDimAccForBase( aDimName
);
2432 // remove the selected items from their groups
2433 // (empty groups are removed, too)
2434 if ( pGroupDimension
)
2436 for (const OUString
& aEntryName
: rItems
)
2438 if ( pBaseGroupDim
)
2440 // for each selected (intermediate) group, remove all its items
2441 // (same logic as for adding, below)
2442 const ScDPSaveGroupItem
* pBaseGroup
= pBaseGroupDim
->GetNamedGroup( aEntryName
);
2444 pBaseGroup
->RemoveElementsFromGroups( *pGroupDimension
); // remove all elements
2446 pGroupDimension
->RemoveFromGroups( aEntryName
);
2449 pGroupDimension
->RemoveFromGroups( aEntryName
);
2453 std::unique_ptr
<ScDPSaveGroupDimension
> pNewGroupDim
;
2454 if ( !pGroupDimension
)
2456 // create a new group dimension
2457 sNewDim
= pDimData
->CreateGroupDimName( aBaseDimName
, *pDPObj
, false, nullptr );
2458 pNewGroupDim
.reset(new ScDPSaveGroupDimension( aBaseDimName
, sNewDim
));
2460 pGroupDimension
= pNewGroupDim
.get(); // make changes to the new dim if none existed
2462 if ( pBaseGroupDim
)
2464 // If it's a higher-order group dimension, pre-allocate groups for all
2465 // non-selected original groups, so the individual base members aren't
2466 // used for automatic groups (this would make the original groups hard
2468 //! Also do this when removing groups?
2469 //! Handle this case dynamically with automatic groups?
2471 tools::Long nGroupCount
= pBaseGroupDim
->GetGroupCount();
2472 for ( tools::Long nGroup
= 0; nGroup
< nGroupCount
; nGroup
++ )
2474 const ScDPSaveGroupItem
& rBaseGroup
= pBaseGroupDim
->GetGroupByIndex( nGroup
);
2476 if (comphelper::findValue(rItems
, rBaseGroup
.GetGroupName()) == -1) //! ignore case?
2478 // add an additional group for each item that is not in the selection
2479 ScDPSaveGroupItem
aGroup( rBaseGroup
.GetGroupName() );
2480 aGroup
.AddElementsFromGroup( rBaseGroup
);
2481 pGroupDimension
->AddGroupItem( aGroup
);
2486 OUString aGroupDimName
= pGroupDimension
->GetGroupDimName();
2488 ScDPSaveGroupItem
aGroup(pGroupDimension
->CreateGroupName(ScResId(STR_PIVOT_GROUP
)));
2489 for (const OUString
& aEntryName
: rItems
)
2491 if ( pBaseGroupDim
)
2493 // for each selected (intermediate) group, add all its items
2494 const ScDPSaveGroupItem
* pBaseGroup
= pBaseGroupDim
->GetNamedGroup( aEntryName
);
2496 aGroup
.AddElementsFromGroup( *pBaseGroup
);
2498 aGroup
.AddElement( aEntryName
); // no group found -> automatic group, add the item itself
2501 aGroup
.AddElement( aEntryName
); // no group dimension, add all items directly
2504 pGroupDimension
->AddGroupItem( aGroup
);
2508 pDimData
->AddGroupDimension( *pNewGroupDim
);
2509 pNewGroupDim
.reset(); // AddGroupDimension copies the object
2510 // don't access pGroupDimension after here
2512 pGroupDimension
= nullptr;
2515 ScDPSaveDimension
* pSaveDimension
= aSaveData
.GetDimensionByName( aGroupDimName
);
2516 if ( pSaveDimension
->GetOrientation() == DataPilotFieldOrientation_HIDDEN
)
2518 ScDPSaveDimension
* pOldDimension
= aSaveData
.GetDimensionByName( aDimName
);
2519 pSaveDimension
->SetOrientation( pOldDimension
->GetOrientation() );
2520 aSaveData
.SetPosition( pSaveDimension
, 0 ); //! before (immediate) base
2524 pDPObj
->SetSaveData( aSaveData
);
2525 ScDBDocFunc(*GetDocShell()).RefreshPivotTableGroups(pDPObj
);
2528 // if new grouping field has been created (on first group), return it
2529 if( !sNewDim
.isEmpty() )
2531 Reference
< XNameAccess
> xFields(mxParent
->getDataPilotFields(), UNO_QUERY
);
2536 xRet
.set(xFields
->getByName(sNewDim
), UNO_QUERY
);
2537 SAL_WARN_IF(!xRet
.is(), "sc.ui", "there is a name, so there should be also a field");
2539 catch (const container::NoSuchElementException
&)
2541 css::uno::Any anyEx
= cppu::getCaughtException();
2542 SAL_WARN("sc.ui", "Cannot find field with that name: " + sNewDim
+ ".");
2543 // Avoid throwing exception that's not specified in the method signature.
2544 throw css::lang::WrappedTargetRuntimeException(
2545 "Cannot find field with name \"" + sNewDim
+ "\"",
2546 getXWeak(), anyEx
);
2553 Reference
< XDataPilotField
> SAL_CALL
ScDataPilotFieldObj::createDateGroup( const DataPilotFieldGroupInfo
& rInfo
)
2555 SolarMutexGuard aGuard
;
2556 using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy
;
2558 if( !rInfo
.HasDateValues
)
2559 throw IllegalArgumentException(u
"HasDateValues is not set"_ustr
, getXWeak(), 0);
2560 if( !lclCheckMinMaxStep( rInfo
) )
2561 throw IllegalArgumentException(u
"min/max/step"_ustr
, getXWeak(), 0);
2563 // only a single date flag is allowed
2564 if( (rInfo
.GroupBy
== 0) || (rInfo
.GroupBy
> YEARS
) || ((rInfo
.GroupBy
& (rInfo
.GroupBy
- 1)) != 0) )
2565 throw IllegalArgumentException("Invalid GroupBy value: " + OUString::number(rInfo
.GroupBy
), getXWeak(), 0);
2567 // step must be zero, if something else than DAYS is specified
2568 if( rInfo
.Step
>= ((rInfo
.GroupBy
== DAYS
) ? 32768.0 : 1.0) )
2569 throw IllegalArgumentException("Invalid step value: " + OUString::number(rInfo
.Step
), getXWeak(), 0);
2571 OUString aGroupDimName
;
2572 ScDPObject
* pDPObj
= nullptr;
2573 if( ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
) )
2575 ScDPNumGroupInfo aInfo
;
2576 aInfo
.mbEnable
= true;
2577 aInfo
.mbDateValues
= (rInfo
.GroupBy
== DAYS
) && (rInfo
.Step
>= 1.0);
2578 aInfo
.mbAutoStart
= rInfo
.HasAutoStart
;
2579 aInfo
.mbAutoEnd
= rInfo
.HasAutoEnd
;
2580 aInfo
.mfStart
= rInfo
.Start
;
2581 aInfo
.mfEnd
= rInfo
.End
;
2582 aInfo
.mfStep
= std::trunc( rInfo
.Step
);
2584 // create a local copy of the entire save data (will be written back below)
2585 ScDPSaveData aSaveData
= *pDPObj
->GetSaveData();
2586 // get or create dimension save data
2587 ScDPDimensionSaveData
& rDimData
= *aSaveData
.GetDimensionData();
2589 // find source dimension name
2590 const OUString
& rDimName
= pDim
->GetName();
2591 const ScDPSaveGroupDimension
* pGroupDim
= rDimData
.GetNamedGroupDim( rDimName
);
2592 OUString aSrcDimName
= pGroupDim
? pGroupDim
->GetSourceDimName() : rDimName
;
2594 // find a group dimension for the base field, or get numeric grouping
2595 pGroupDim
= rDimData
.GetFirstNamedGroupDim( aSrcDimName
);
2596 const ScDPSaveNumGroupDimension
* pNumGroupDim
= rDimData
.GetNumGroupDim( aSrcDimName
);
2598 // do not group by dates, if named groups or numeric grouping is present
2599 bool bHasNamedGrouping
= pGroupDim
&& !pGroupDim
->GetDateInfo().mbEnable
;
2600 bool bHasNumGrouping
= pNumGroupDim
&& pNumGroupDim
->GetInfo().mbEnable
&& !pNumGroupDim
->GetInfo().mbDateValues
&& !pNumGroupDim
->GetDateInfo().mbEnable
;
2601 if( bHasNamedGrouping
|| bHasNumGrouping
)
2602 throw IllegalArgumentException();
2604 if( aInfo
.mbDateValues
) // create day ranges grouping
2606 // first remove all named group dimensions
2609 OUString aGroupDimName2
= pGroupDim
->GetGroupDimName();
2610 // find next group dimension before deleting this group
2611 pGroupDim
= rDimData
.GetNextNamedGroupDim( aGroupDimName2
);
2612 // remove from dimension save data
2613 rDimData
.RemoveGroupDimension( aGroupDimName2
);
2614 // also remove save data settings for the dimension that no longer exists
2615 aSaveData
.RemoveDimensionByName( aGroupDimName2
);
2617 // create or replace the number grouping dimension
2618 ScDPSaveNumGroupDimension
aNumGroupDim( aSrcDimName
, aInfo
);
2619 rDimData
.ReplaceNumGroupDimension( aNumGroupDim
);
2621 else // create date grouping
2623 // collect all existing date flags
2624 sal_Int32 nDateParts
= rDimData
.CollectDateParts( aSrcDimName
);
2625 if( nDateParts
== 0 )
2627 // insert numeric group dimension, if no date groups exist yet (or replace day range grouping)
2628 ScDPSaveNumGroupDimension
aNumGroupDim( aSrcDimName
, aInfo
, rInfo
.GroupBy
);
2629 rDimData
.ReplaceNumGroupDimension( aNumGroupDim
);
2631 else if( (nDateParts
& rInfo
.GroupBy
) == 0 ) // do nothing if date field exists already
2633 // create new named group dimension for additional date groups
2634 aGroupDimName
= rDimData
.CreateDateGroupDimName( rInfo
.GroupBy
, *pDPObj
, true, nullptr );
2635 ScDPSaveGroupDimension
aGroupDim( aSrcDimName
, aGroupDimName
, aInfo
, rInfo
.GroupBy
);
2636 rDimData
.AddGroupDimension( aGroupDim
);
2638 // set orientation of new named group dimension
2639 ScDPSaveDimension
& rSaveDim
= *aSaveData
.GetDimensionByName( aGroupDimName
);
2640 if( rSaveDim
.GetOrientation() == DataPilotFieldOrientation_HIDDEN
)
2642 ScDPSaveDimension
& rOldDim
= *aSaveData
.GetDimensionByName( aSrcDimName
);
2643 rSaveDim
.SetOrientation( rOldDim
.GetOrientation() );
2644 aSaveData
.SetPosition( &rSaveDim
, 0 ); //! before (immediate) base
2650 pDPObj
->SetSaveData( aSaveData
);
2651 ScDBDocFunc(*GetDocShell()).RefreshPivotTableGroups(pDPObj
);
2654 // return the UNO object of the new dimension, after writing back saved data
2655 Reference
< XDataPilotField
> xRet
;
2656 if( !aGroupDimName
.isEmpty() )
2659 Reference
< XNameAccess
> xFields( mxParent
->getDataPilotFields(), UNO_QUERY_THROW
);
2660 xRet
.set( xFields
->getByName( aGroupDimName
), UNO_QUERY
);
2670 bool lclExtractGroupMembers( ScFieldGroupMembers
& rMembers
, const Any
& rElement
)
2672 // allow empty value to create a new group
2673 if( !rElement
.hasValue() )
2676 // try to extract a simple sequence of strings
2677 Sequence
< OUString
> aSeq
;
2678 if( rElement
>>= aSeq
)
2680 if( aSeq
.hasElements() )
2681 rMembers
.insert( rMembers
.end(), std::cbegin(aSeq
), std::cend(aSeq
) );
2685 // try to use XIndexAccess providing objects that support XNamed
2686 Reference
< XIndexAccess
> xItemsIA( rElement
, UNO_QUERY
);
2689 for( sal_Int32 nIdx
= 0, nCount
= xItemsIA
->getCount(); nIdx
< nCount
; ++nIdx
)
2691 try // getByIndex() should not throw, but we cannot be sure
2693 Reference
< XNamed
> xItemName( xItemsIA
->getByIndex( nIdx
), UNO_QUERY_THROW
);
2694 rMembers
.push_back( xItemName
->getName() );
2698 // ignore exceptions, go ahead with next element in the array
2704 // nothing valid inside the Any -> return false
2710 ScDataPilotFieldGroupsObj::ScDataPilotFieldGroupsObj( ScFieldGroups
&& rGroups
) :
2711 maGroups( std::move(rGroups
) )
2715 ScDataPilotFieldGroupsObj::~ScDataPilotFieldGroupsObj()
2721 Any SAL_CALL
ScDataPilotFieldGroupsObj::getByName( const OUString
& rName
)
2723 SolarMutexGuard aGuard
;
2724 if( implFindByName( rName
) == maGroups
.end() )
2725 throw NoSuchElementException();
2726 return Any( Reference
< XNameAccess
>( new ScDataPilotFieldGroupObj( *this, rName
) ) );
2729 Sequence
< OUString
> SAL_CALL
ScDataPilotFieldGroupsObj::getElementNames()
2731 SolarMutexGuard aGuard
;
2732 Sequence
< OUString
> aSeq
;
2733 if( !maGroups
.empty() )
2735 aSeq
.realloc( static_cast< sal_Int32
>( maGroups
.size() ) );
2736 OUString
* pName
= aSeq
.getArray();
2737 for( const auto& rGroup
: maGroups
)
2739 *pName
= rGroup
.maName
;
2746 sal_Bool SAL_CALL
ScDataPilotFieldGroupsObj::hasByName( const OUString
& rName
)
2748 SolarMutexGuard aGuard
;
2749 return implFindByName( rName
) != maGroups
.end();
2754 void SAL_CALL
ScDataPilotFieldGroupsObj::replaceByName( const OUString
& rName
, const Any
& rElement
)
2756 SolarMutexGuard aGuard
;
2758 if( rName
.isEmpty() )
2759 throw IllegalArgumentException(u
"Name is empty"_ustr
, getXWeak(), 0);
2761 ScFieldGroups::iterator aIt
= implFindByName( rName
);
2762 if( aIt
== maGroups
.end() )
2763 throw NoSuchElementException("Name \"" + rName
+ "\" not found", getXWeak());
2765 // read all item names provided by the passed object
2766 ScFieldGroupMembers aMembers
;
2767 if( !lclExtractGroupMembers( aMembers
, rElement
) )
2768 throw IllegalArgumentException(u
"Invalid element object"_ustr
, getXWeak(), 0);
2770 // copy and forget, faster than vector assignment
2771 aIt
->maMembers
.swap( aMembers
);
2776 void SAL_CALL
ScDataPilotFieldGroupsObj::insertByName( const OUString
& rName
, const Any
& rElement
)
2778 SolarMutexGuard aGuard
;
2780 if( rName
.isEmpty() )
2781 throw IllegalArgumentException(u
"Name is empty"_ustr
, getXWeak(), 0);
2783 ScFieldGroups::iterator aIt
= implFindByName( rName
);
2784 if( aIt
!= maGroups
.end() )
2785 throw ElementExistException("Name \"" + rName
+ "\" already exists", getXWeak());
2787 // read all item names provided by the passed object
2788 ScFieldGroupMembers aMembers
;
2789 if( !lclExtractGroupMembers( aMembers
, rElement
) )
2790 throw IllegalArgumentException(u
"Invalid element object"_ustr
, getXWeak(), 0);
2792 // create the new entry if no error has been occurred
2793 maGroups
.emplace_back();
2794 ScFieldGroup
& rGroup
= maGroups
.back();
2795 rGroup
.maName
= rName
;
2796 rGroup
.maMembers
.swap( aMembers
);
2799 void SAL_CALL
ScDataPilotFieldGroupsObj::removeByName( const OUString
& rName
)
2801 SolarMutexGuard aGuard
;
2803 if( rName
.isEmpty() )
2804 throw IllegalArgumentException(u
"Name is empty"_ustr
, getXWeak(), 0);
2806 ScFieldGroups::iterator aIt
= implFindByName( rName
);
2807 if( aIt
== maGroups
.end() )
2808 throw NoSuchElementException("Name \"" + rName
+ "\" not found", getXWeak());
2810 maGroups
.erase( aIt
);
2815 sal_Int32 SAL_CALL
ScDataPilotFieldGroupsObj::getCount()
2817 SolarMutexGuard aGuard
;
2818 return static_cast< sal_Int32
>( maGroups
.size() );
2821 Any SAL_CALL
ScDataPilotFieldGroupsObj::getByIndex( sal_Int32 nIndex
)
2823 SolarMutexGuard aGuard
;
2824 if ((nIndex
< 0) || (o3tl::make_unsigned(nIndex
) >= maGroups
.size()))
2825 throw IndexOutOfBoundsException();
2826 return Any( Reference
< XNameAccess
>( new ScDataPilotFieldGroupObj( *this, maGroups
[ nIndex
].maName
) ) );
2829 // XEnumerationAccess
2831 Reference
<XEnumeration
> SAL_CALL
ScDataPilotFieldGroupsObj::createEnumeration()
2833 SolarMutexGuard aGuard
;
2834 return new ScIndexEnumeration( this, u
"com.sun.star.sheet.DataPilotFieldGroupsEnumeration"_ustr
);
2839 uno::Type SAL_CALL
ScDataPilotFieldGroupsObj::getElementType()
2841 return cppu::UnoType
<XNameAccess
>::get();
2844 sal_Bool SAL_CALL
ScDataPilotFieldGroupsObj::hasElements()
2846 SolarMutexGuard aGuard
;
2847 return !maGroups
.empty();
2852 ScFieldGroup
& ScDataPilotFieldGroupsObj::getFieldGroup( const OUString
& rName
)
2854 SolarMutexGuard aGuard
;
2855 ScFieldGroups::iterator aIt
= implFindByName( rName
);
2856 if( aIt
== maGroups
.end() )
2857 throw RuntimeException("Field Group with name \"" + rName
+ "\" not found", getXWeak());
2861 void ScDataPilotFieldGroupsObj::renameFieldGroup( const OUString
& rOldName
, const OUString
& rNewName
)
2863 SolarMutexGuard aGuard
;
2864 ScFieldGroups::iterator aOldIt
= implFindByName( rOldName
);
2865 ScFieldGroups::iterator aNewIt
= implFindByName( rNewName
);
2866 if( aOldIt
== maGroups
.end() )
2867 throw RuntimeException("Field Group with name \"" + rOldName
+ "\" not found", getXWeak());
2868 // new name must not exist yet
2869 if( (aNewIt
!= maGroups
.end()) && (aNewIt
!= aOldIt
) )
2870 throw RuntimeException("Field Group with name \"" + rOldName
+ "\" already exists", getXWeak());
2871 aOldIt
->maName
= rNewName
;
2874 ScFieldGroups::iterator
ScDataPilotFieldGroupsObj::implFindByName( const OUString
& rName
)
2876 return std::find_if(maGroups
.begin(), maGroups
.end(),
2877 [&rName
](const ScFieldGroup
& rGroup
) { return rGroup
.maName
== rName
; });
2882 OUString
lclExtractMember( const Any
& rElement
)
2884 if( rElement
.has
< OUString
>() )
2885 return rElement
.get
< OUString
>();
2887 Reference
< XNamed
> xNamed( rElement
, UNO_QUERY
);
2889 return xNamed
->getName();
2896 ScDataPilotFieldGroupObj::ScDataPilotFieldGroupObj( ScDataPilotFieldGroupsObj
& rParent
, OUString aGroupName
) :
2897 mxParent( &rParent
),
2898 maGroupName(std::move( aGroupName
))
2902 ScDataPilotFieldGroupObj::~ScDataPilotFieldGroupObj()
2908 Any SAL_CALL
ScDataPilotFieldGroupObj::getByName( const OUString
& rName
)
2910 SolarMutexGuard aGuard
;
2911 ScFieldGroupMembers
& rMembers
= mxParent
->getFieldGroup( maGroupName
).maMembers
;
2912 ScFieldGroupMembers::iterator aIt
= ::std::find( rMembers
.begin(), rMembers
.end(), rName
);
2913 if( aIt
== rMembers
.end() )
2914 throw NoSuchElementException("Name \"" + rName
+ "\" not found", getXWeak());
2915 return Any( Reference
< XNamed
>( new ScDataPilotFieldGroupItemObj( *this, *aIt
) ) );
2918 Sequence
< OUString
> SAL_CALL
ScDataPilotFieldGroupObj::getElementNames()
2920 SolarMutexGuard aGuard
;
2921 return ::comphelper::containerToSequence( mxParent
->getFieldGroup( maGroupName
).maMembers
);
2924 sal_Bool SAL_CALL
ScDataPilotFieldGroupObj::hasByName( const OUString
& rName
)
2926 SolarMutexGuard aGuard
;
2927 ScFieldGroupMembers
& rMembers
= mxParent
->getFieldGroup( maGroupName
).maMembers
;
2928 return ::std::find( rMembers
.begin(), rMembers
.end(), rName
) != rMembers
.end();
2933 void SAL_CALL
ScDataPilotFieldGroupObj::replaceByName( const OUString
& rName
, const Any
& rElement
)
2935 SolarMutexGuard aGuard
;
2937 // it should be possible to quickly rename an item -> accept string or XNamed
2938 OUString aNewName
= lclExtractMember( rElement
);
2939 if( rName
.isEmpty() || aNewName
.isEmpty() )
2940 throw IllegalArgumentException(u
"Name is empty"_ustr
, getXWeak(), 0);
2941 if( rName
== aNewName
)
2944 ScFieldGroupMembers
& rMembers
= mxParent
->getFieldGroup( maGroupName
).maMembers
;
2945 ScFieldGroupMembers::iterator aOldIt
= ::std::find( rMembers
.begin(), rMembers
.end(), rName
);
2946 ScFieldGroupMembers::iterator aNewIt
= ::std::find( rMembers
.begin(), rMembers
.end(), aNewName
);
2947 if( aOldIt
== rMembers
.end() )
2948 throw NoSuchElementException("Name \"" + rName
+ "\" not found", getXWeak());
2949 if( aNewIt
!= rMembers
.end() )
2950 throw IllegalArgumentException("Name \"" + rName
+ "\" already exists", getXWeak(), 0);
2956 void SAL_CALL
ScDataPilotFieldGroupObj::insertByName( const OUString
& rName
, const Any
& /*rElement*/ )
2958 SolarMutexGuard aGuard
;
2960 // we will ignore the passed element and just try to insert the name
2961 if( rName
.isEmpty() )
2962 throw IllegalArgumentException(u
"Name is empty"_ustr
, getXWeak(), 0);
2964 ScFieldGroupMembers
& rMembers
= mxParent
->getFieldGroup( maGroupName
).maMembers
;
2965 ScFieldGroupMembers::iterator aIt
= ::std::find( rMembers
.begin(), rMembers
.end(), rName
);
2966 if( aIt
!= rMembers
.end() )
2967 throw IllegalArgumentException("Name \"" + rName
+ "\" already exists", getXWeak(), 0);
2968 rMembers
.push_back( rName
);
2971 void SAL_CALL
ScDataPilotFieldGroupObj::removeByName( const OUString
& rName
)
2973 SolarMutexGuard aGuard
;
2975 if( rName
.isEmpty() )
2976 throw IllegalArgumentException(u
"Name is empty"_ustr
, getXWeak(), 0);
2977 ScFieldGroupMembers
& rMembers
= mxParent
->getFieldGroup( maGroupName
).maMembers
;
2978 ScFieldGroupMembers::iterator aIt
= ::std::find( rMembers
.begin(), rMembers
.end(), rName
);
2979 if( aIt
== rMembers
.end() )
2980 throw NoSuchElementException("Name \"" + rName
+ "\" not found", getXWeak());
2981 rMembers
.erase( aIt
);
2986 sal_Int32 SAL_CALL
ScDataPilotFieldGroupObj::getCount()
2988 SolarMutexGuard aGuard
;
2989 return static_cast< sal_Int32
>( mxParent
->getFieldGroup( maGroupName
).maMembers
.size() );
2992 Any SAL_CALL
ScDataPilotFieldGroupObj::getByIndex( sal_Int32 nIndex
)
2994 SolarMutexGuard aGuard
;
2995 ScFieldGroupMembers
& rMembers
= mxParent
->getFieldGroup( maGroupName
).maMembers
;
2996 if ((nIndex
< 0) || (o3tl::make_unsigned(nIndex
) >= rMembers
.size()))
2997 throw IndexOutOfBoundsException();
2998 return Any( Reference
< XNamed
>( new ScDataPilotFieldGroupItemObj( *this, rMembers
[ nIndex
] ) ) );
3001 // XEnumerationAccess
3003 Reference
< XEnumeration
> SAL_CALL
ScDataPilotFieldGroupObj::createEnumeration()
3005 SolarMutexGuard aGuard
;
3006 return new ScIndexEnumeration( this, u
"com.sun.star.sheet.DataPilotFieldGroupEnumeration"_ustr
);
3011 uno::Type SAL_CALL
ScDataPilotFieldGroupObj::getElementType()
3013 return cppu::UnoType
<XNamed
>::get();
3016 sal_Bool SAL_CALL
ScDataPilotFieldGroupObj::hasElements()
3018 SolarMutexGuard aGuard
;
3019 return !mxParent
->getFieldGroup( maGroupName
).maMembers
.empty();
3024 OUString SAL_CALL
ScDataPilotFieldGroupObj::getName()
3026 SolarMutexGuard aGuard
;
3030 void SAL_CALL
ScDataPilotFieldGroupObj::setName( const OUString
& rName
)
3032 SolarMutexGuard aGuard
;
3033 mxParent
->renameFieldGroup( maGroupName
, rName
);
3034 // if call to renameFieldGroup() did not throw, remember the new name
3035 maGroupName
= rName
;
3038 ScDataPilotFieldGroupItemObj::ScDataPilotFieldGroupItemObj( ScDataPilotFieldGroupObj
& rParent
, OUString aName
) :
3039 mxParent( &rParent
),
3040 maName(std::move( aName
))
3044 ScDataPilotFieldGroupItemObj::~ScDataPilotFieldGroupItemObj()
3050 OUString SAL_CALL
ScDataPilotFieldGroupItemObj::getName()
3052 SolarMutexGuard aGuard
;
3056 void SAL_CALL
ScDataPilotFieldGroupItemObj::setName( const OUString
& rName
)
3058 SolarMutexGuard aGuard
;
3059 mxParent
->replaceByName( maName
, Any( rName
) );
3060 // if call to replaceByName() did not throw, remember the new name
3064 ScDataPilotItemsObj::ScDataPilotItemsObj( ScDataPilotDescriptorBase
& rParent
, const ScFieldIdentifier
& rFieldId
) :
3065 ScDataPilotChildObjBase( rParent
, rFieldId
)
3069 ScDataPilotItemsObj::~ScDataPilotItemsObj()
3075 ScDataPilotItemObj
* ScDataPilotItemsObj::GetObjectByIndex_Impl( sal_Int32 nIndex
) const
3077 return ((0 <= nIndex
) && (nIndex
< GetMemberCount())) ?
3078 new ScDataPilotItemObj( *mxParent
, maFieldId
, nIndex
) : nullptr;
3083 Any SAL_CALL
ScDataPilotItemsObj::getByName( const OUString
& aName
)
3085 SolarMutexGuard aGuard
;
3086 Reference
<XNameAccess
> xMembers
= GetMembers();
3089 Reference
<XIndexAccess
> xMembersIndex(new ScNameToIndexAccess( xMembers
));
3090 sal_Int32 nCount
= xMembersIndex
->getCount();
3091 sal_Int32 nItem
= 0;
3092 while (nItem
< nCount
)
3094 Reference
<XNamed
> xMember(xMembersIndex
->getByIndex(nItem
), UNO_QUERY
);
3095 if (xMember
.is() && (aName
== xMember
->getName()))
3097 return Any( Reference
< XPropertySet
>( GetObjectByIndex_Impl( nItem
) ) );
3101 throw NoSuchElementException("Name \"" + aName
+ "\" not found", getXWeak());
3106 Sequence
<OUString
> SAL_CALL
ScDataPilotItemsObj::getElementNames()
3108 SolarMutexGuard aGuard
;
3109 Sequence
< OUString
> aSeq
;
3110 if( ScDPObject
* pDPObj
= GetDPObject() )
3111 pDPObj
->GetMemberNames( lcl_GetObjectIndex( pDPObj
, maFieldId
), aSeq
);
3115 sal_Bool SAL_CALL
ScDataPilotItemsObj::hasByName( const OUString
& aName
)
3117 SolarMutexGuard aGuard
;
3118 bool bFound
= false;
3119 Reference
<XNameAccess
> xMembers
= GetMembers();
3122 Reference
<XIndexAccess
> xMembersIndex(new ScNameToIndexAccess( xMembers
));
3123 sal_Int32 nCount
= xMembersIndex
->getCount();
3124 sal_Int32 nItem
= 0;
3125 while (nItem
< nCount
&& !bFound
)
3127 Reference
<XNamed
> xMember(xMembersIndex
->getByIndex(nItem
), UNO_QUERY
);
3128 if (xMember
.is() && aName
== xMember
->getName())
3137 // XEnumerationAccess
3139 Reference
<XEnumeration
> SAL_CALL
ScDataPilotItemsObj::createEnumeration()
3141 SolarMutexGuard aGuard
;
3142 return new ScIndexEnumeration(this, u
"com.sun.star.sheet.DataPilotItemsEnumeration"_ustr
);
3147 sal_Int32 SAL_CALL
ScDataPilotItemsObj::getCount()
3149 SolarMutexGuard aGuard
;
3150 return GetMemberCount();
3153 Any SAL_CALL
ScDataPilotItemsObj::getByIndex( sal_Int32 nIndex
)
3155 SolarMutexGuard aGuard
;
3156 Reference
< XPropertySet
> xItem( GetObjectByIndex_Impl( nIndex
) );
3158 throw IndexOutOfBoundsException();
3159 return Any( xItem
);
3162 uno::Type SAL_CALL
ScDataPilotItemsObj::getElementType()
3164 return cppu::UnoType
<XPropertySet
>::get();
3167 sal_Bool SAL_CALL
ScDataPilotItemsObj::hasElements()
3169 SolarMutexGuard aGuard
;
3170 return ( getCount() != 0 );
3173 ScDataPilotItemObj::ScDataPilotItemObj( ScDataPilotDescriptorBase
& rParent
, const ScFieldIdentifier
& rFieldId
, sal_Int32 nIndex
) :
3174 ScDataPilotChildObjBase( rParent
, rFieldId
),
3175 maPropSet( lcl_GetDataPilotItemMap() ),
3180 ScDataPilotItemObj::~ScDataPilotItemObj()
3185 OUString SAL_CALL
ScDataPilotItemObj::getName()
3187 SolarMutexGuard aGuard
;
3189 Reference
<XNameAccess
> xMembers
= GetMembers();
3192 Reference
<XIndexAccess
> xMembersIndex(new ScNameToIndexAccess( xMembers
));
3193 sal_Int32 nCount
= xMembersIndex
->getCount();
3194 if (mnIndex
< nCount
)
3196 Reference
<XNamed
> xMember(xMembersIndex
->getByIndex(mnIndex
), UNO_QUERY
);
3197 sRet
= xMember
->getName();
3203 void SAL_CALL
ScDataPilotItemObj::setName( const OUString
& /* aName */ )
3208 Reference
< XPropertySetInfo
>
3209 SAL_CALL
ScDataPilotItemObj::getPropertySetInfo( )
3211 SolarMutexGuard aGuard
;
3212 static Reference
<XPropertySetInfo
> aRef
=
3213 new SfxItemPropertySetInfo( maPropSet
.getPropertyMap() );
3217 void SAL_CALL
ScDataPilotItemObj::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
3219 SolarMutexGuard aGuard
;
3220 ScDPObject
* pDPObj
= nullptr;
3221 ScDPSaveDimension
* pDim
= GetDPDimension( &pDPObj
);
3225 Reference
<XNameAccess
> xMembers
= GetMembers();
3226 if( !xMembers
.is() )
3229 Reference
<XIndexAccess
> xMembersIndex( new ScNameToIndexAccess( xMembers
) );
3230 sal_Int32 nCount
= xMembersIndex
->getCount();
3231 if( mnIndex
>= nCount
)
3234 Reference
<XNamed
> xMember(xMembersIndex
->getByIndex(mnIndex
), UNO_QUERY
);
3235 OUString
sName(xMember
->getName());
3236 ScDPSaveMember
* pMember
= pDim
->GetMemberByName(sName
);
3240 bool bGetNewIndex
= false;
3241 if ( aPropertyName
== SC_UNONAME_SHOWDETAIL
)
3242 pMember
->SetShowDetails(cppu::any2bool(aValue
));
3243 else if ( aPropertyName
== SC_UNONAME_ISHIDDEN
)
3244 pMember
->SetIsVisible(!cppu::any2bool(aValue
));
3245 else if ( aPropertyName
== SC_UNONAME_POS
)
3247 sal_Int32 nNewPos
= 0;
3248 if ( !( aValue
>>= nNewPos
) || nNewPos
< 0 || nNewPos
>= nCount
)
3249 throw IllegalArgumentException();
3251 pDim
->SetMemberPosition( sName
, nNewPos
);
3252 // get new effective index (depends on sorting mode, which isn't modified)
3253 bGetNewIndex
= true;
3256 SetDPObject( pDPObj
);
3258 if ( bGetNewIndex
) // after SetDPObject, get the new index
3260 Sequence
< OUString
> aItemNames
= xMembers
->getElementNames();
3261 sal_Int32 nItemCount
= aItemNames
.getLength();
3262 for (sal_Int32 nItem
=0; nItem
<nItemCount
; ++nItem
)
3263 if (aItemNames
[nItem
] == sName
)
3268 Any SAL_CALL
ScDataPilotItemObj::getPropertyValue( const OUString
& aPropertyName
)
3270 SolarMutexGuard aGuard
;
3272 if( ScDPSaveDimension
* pDim
= GetDPDimension() )
3274 Reference
< XNameAccess
> xMembers
= GetMembers();
3277 Reference
< XIndexAccess
> xMembersIndex( new ScNameToIndexAccess( xMembers
) );
3278 sal_Int32 nCount
= xMembersIndex
->getCount();
3279 if( mnIndex
< nCount
)
3281 Reference
< XNamed
> xMember( xMembersIndex
->getByIndex( mnIndex
), UNO_QUERY
);
3282 OUString
sName( xMember
->getName() );
3283 ScDPSaveMember
* pMember
= pDim
->GetExistingMemberByName( sName
);
3284 if ( aPropertyName
== SC_UNONAME_SHOWDETAIL
)
3286 if (pMember
&& pMember
->HasShowDetails())
3288 aRet
<<= pMember
->GetShowDetails();
3292 Reference
< XPropertySet
> xMemberProps( xMember
, UNO_QUERY
);
3293 if( xMemberProps
.is() )
3294 aRet
= xMemberProps
->getPropertyValue( SC_UNO_DP_SHOWDETAILS
);
3299 else if ( aPropertyName
== SC_UNONAME_ISHIDDEN
)
3301 if (pMember
&& pMember
->HasIsVisible())
3303 aRet
<<= !pMember
->GetIsVisible();
3307 Reference
< XPropertySet
> xMemberProps( xMember
, UNO_QUERY
);
3308 if( xMemberProps
.is() )
3309 aRet
<<= !cppu::any2bool( xMemberProps
->getPropertyValue( SC_UNO_DP_ISVISIBLE
) );
3314 else if ( aPropertyName
== SC_UNONAME_POS
)
3324 void SAL_CALL
ScDataPilotItemObj::addPropertyChangeListener(
3325 const OUString
& /* aPropertyName */, const Reference
< XPropertyChangeListener
>& /* xListener */ )
3329 void SAL_CALL
ScDataPilotItemObj::removePropertyChangeListener(
3330 const OUString
& /* aPropertyName */, const Reference
< XPropertyChangeListener
>& /* aListener */ )
3334 void SAL_CALL
ScDataPilotItemObj::addVetoableChangeListener(
3335 const OUString
& /* PropertyName */, const Reference
< XVetoableChangeListener
>& /* aListener */ )
3339 void SAL_CALL
ScDataPilotItemObj::removeVetoableChangeListener(
3340 const OUString
& /* PropertyName */, const Reference
< XVetoableChangeListener
>& /* aListener */ )
3344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */