1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dpobject.cxx,v $
10 * $Revision: 1.23.30.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "dpobject.hxx"
39 #include "dptabsrc.hxx"
41 #include "dpdimsave.hxx"
42 #include "dpoutput.hxx"
43 #include "dpshttab.hxx"
44 #include "dpsdbtab.hxx"
45 #include "dpgroup.hxx"
46 #include "document.hxx"
47 #include "rechead.hxx"
48 #include "pivot.hxx" // PIVOT_DATA_FIELD
49 #include "dapiuno.hxx" // ScDataPilotConversion
50 #include "miscuno.hxx"
51 #include "scerrors.hxx"
52 #include "refupdat.hxx"
53 #include "scresid.hxx"
56 #include "scitems.hxx"
57 #include "unonames.hxx"
59 #include <com/sun/star/beans/XPropertySet.hpp>
60 #include <com/sun/star/sheet/GeneralFunction.hpp>
61 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
62 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
63 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
64 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
65 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
66 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
67 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
68 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
69 #include <com/sun/star/lang/XInitialization.hpp>
70 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
71 #include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
73 #include <comphelper/processfactory.hxx>
74 #include <tools/debug.hxx>
75 #include <svtools/zforlist.hxx> // IsNumberFormat
79 using namespace com::sun::star
;
81 using ::boost::shared_ptr
;
82 using ::com::sun::star::uno::Sequence
;
83 using ::com::sun::star::uno::Reference
;
84 using ::com::sun::star::uno::UNO_QUERY
;
85 using ::com::sun::star::uno::Any
;
86 using ::com::sun::star::sheet::DataPilotTableHeaderData
;
87 using ::com::sun::star::sheet::DataPilotTablePositionData
;
88 using ::com::sun::star::beans::XPropertySet
;
89 using ::rtl::OUString
;
91 // -----------------------------------------------------------------------
93 #define MAX_LABELS 256 //!!! from fieldwnd.hxx, must be moved to global.hxx
95 // -----------------------------------------------------------------------
97 #define SCDPSOURCE_SERVICE "com.sun.star.sheet.DataPilotSource"
99 // -----------------------------------------------------------------------
101 // incompatible versions of data pilot files
102 #define SC_DP_VERSION_CURRENT 6
104 // type of source data
105 #define SC_DP_SOURCE_SHEET 0
106 #define SC_DP_SOURCE_DATABASE 1
107 #define SC_DP_SOURCE_SERVICE 2
109 // -----------------------------------------------------------------------
111 //! move to a header file
112 #define DP_PROP_COLUMNGRAND "ColumnGrand"
113 #define DP_PROP_FUNCTION "Function"
114 #define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows"
115 #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
116 //#define DP_PROP_ISVISIBLE "IsVisible"
117 #define DP_PROP_ORIENTATION "Orientation"
118 #define DP_PROP_ORIGINAL "Original"
119 #define DP_PROP_POSITION "Position"
120 #define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty"
121 #define DP_PROP_ROWGRAND "RowGrand"
122 #define DP_PROP_SHOWDETAILS "ShowDetails"
123 #define DP_PROP_SHOWEMPTY "ShowEmpty"
124 #define DP_PROP_SUBTOTALS "SubTotals"
125 #define DP_PROP_USEDHIERARCHY "UsedHierarchy"
127 // -----------------------------------------------------------------------
129 USHORT
lcl_GetDataGetOrientation( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
)
131 long nRet
= sheet::DataPilotFieldOrientation_HIDDEN
;
134 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
135 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
136 long nIntCount
= xIntDims
->getCount();
138 for (long nIntDim
=0; nIntDim
<nIntCount
&& !bFound
; nIntDim
++)
140 uno::Reference
<uno::XInterface
> xIntDim
=
141 ScUnoHelpFunctions::AnyToInterface( xIntDims
->getByIndex(nIntDim
) );
142 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
145 bFound
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
146 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
147 //! error checking -- is "IsDataLayoutDimension" property required??
149 nRet
= ScUnoHelpFunctions::GetEnumProperty(
150 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
),
151 sheet::DataPilotFieldOrientation_HIDDEN
);
155 return static_cast< USHORT
>( nRet
);
158 // -----------------------------------------------------------------------
160 ScDPObject::ScDPObject( ScDocument
* pD
) :
166 mpTableData(static_cast<ScDPTableData
*>(NULL
)),
168 bSettingsChanged( FALSE
),
170 nAutoFormatIndex( 65535 ),
173 bHeaderLayout( false )
177 ScDPObject::ScDPObject(const ScDPObject
& r
) :
181 aTableName( r
.aTableName
),
182 aTableTag( r
.aTableTag
),
183 aOutRange( r
.aOutRange
),
187 mpTableData(static_cast<ScDPTableData
*>(NULL
)),
189 bSettingsChanged( FALSE
),
191 nAutoFormatIndex( r
.nAutoFormatIndex
),
193 nHeaderRows( r
.nHeaderRows
),
194 bHeaderLayout( r
.bHeaderLayout
)
197 pSaveData
= new ScDPSaveData(*r
.pSaveData
);
199 pSheetDesc
= new ScSheetSourceDesc(*r
.pSheetDesc
);
201 pImpDesc
= new ScImportSourceDesc(*r
.pImpDesc
);
203 pServDesc
= new ScDPServiceDesc(*r
.pServDesc
);
204 // xSource (and pOutput) is not copied
207 ScDPObject::~ScDPObject()
216 ScDataObject
* ScDPObject::Clone() const
218 return new ScDPObject(*this);
221 void ScDPObject::SetAlive(BOOL bSet
)
226 void ScDPObject::SetAllowMove(BOOL bSet
)
231 void ScDPObject::SetSaveData(const ScDPSaveData
& rData
)
233 if ( pSaveData
!= &rData
) // API implementation modifies the original SaveData object
236 pSaveData
= new ScDPSaveData( rData
);
239 InvalidateData(); // re-init source from SaveData
242 void ScDPObject::SetAutoFormatIndex(const USHORT nIndex
)
244 nAutoFormatIndex
= nIndex
;
247 void ScDPObject::SetHeaderLayout (bool bUseGrid
)
249 bHeaderLayout
= bUseGrid
;
252 void ScDPObject::SetOutRange(const ScRange
& rRange
)
257 pOutput
->SetPosition( rRange
.aStart
);
260 void ScDPObject::SetSheetDesc(const ScSheetSourceDesc
& rDesc
)
262 if ( pSheetDesc
&& rDesc
== *pSheetDesc
)
263 return; // nothing to do
266 DELETEZ( pServDesc
);
269 pSheetDesc
= new ScSheetSourceDesc(rDesc
);
271 // make valid QueryParam
273 pSheetDesc
->aQueryParam
.nCol1
= pSheetDesc
->aSourceRange
.aStart
.Col();
274 pSheetDesc
->aQueryParam
.nRow1
= pSheetDesc
->aSourceRange
.aStart
.Row();
275 pSheetDesc
->aQueryParam
.nCol2
= pSheetDesc
->aSourceRange
.aEnd
.Col();
276 pSheetDesc
->aQueryParam
.nRow2
= pSheetDesc
->aSourceRange
.aEnd
.Row();;
277 pSheetDesc
->aQueryParam
.bHasHeader
= TRUE
;
279 InvalidateSource(); // new source must be created
282 void ScDPObject::SetImportDesc(const ScImportSourceDesc
& rDesc
)
284 if ( pImpDesc
&& rDesc
== *pImpDesc
)
285 return; // nothing to do
287 DELETEZ( pSheetDesc
);
288 DELETEZ( pServDesc
);
291 pImpDesc
= new ScImportSourceDesc(rDesc
);
293 InvalidateSource(); // new source must be created
296 void ScDPObject::SetServiceData(const ScDPServiceDesc
& rDesc
)
298 if ( pServDesc
&& rDesc
== *pServDesc
)
299 return; // nothing to do
301 DELETEZ( pSheetDesc
);
305 pServDesc
= new ScDPServiceDesc(rDesc
);
307 InvalidateSource(); // new source must be created
310 void ScDPObject::WriteSourceDataTo( ScDPObject
& rDest
) const
313 rDest
.SetSheetDesc( *pSheetDesc
);
315 rDest
.SetImportDesc( *pImpDesc
);
316 else if ( pServDesc
)
317 rDest
.SetServiceData( *pServDesc
);
319 // name/tag are not source data, but needed along with source data
321 rDest
.aTableName
= aTableName
;
322 rDest
.aTableTag
= aTableTag
;
325 void ScDPObject::WriteTempDataTo( ScDPObject
& rDest
) const
327 rDest
.nHeaderRows
= nHeaderRows
;
330 BOOL
ScDPObject::IsSheetData() const
332 return ( pSheetDesc
!= NULL
);
335 void ScDPObject::SetName(const String
& rNew
)
340 void ScDPObject::SetTag(const String
& rNew
)
345 bool ScDPObject::IsDataDescriptionCell(const ScAddress
& rPos
)
350 long nDataDimCount
= pSaveData
->GetDataDimensionCount();
351 if (nDataDimCount
!= 1)
352 // There has to be exactly one data dimension for the description to
353 // appear at top-left corner.
357 ScRange aTabRange
= pOutput
->GetOutputRange(sheet::DataPilotOutputRangeType::TABLE
);
358 return (rPos
== aTabRange
.aStart
);
361 uno::Reference
<sheet::XDimensionsSupplier
> ScDPObject::GetSource()
367 void ScDPObject::CreateOutput()
372 BOOL bFilterButton
= IsSheetData() && pSaveData
&& pSaveData
->GetFilterButton();
373 pOutput
= new ScDPOutput( pDoc
, xSource
, aOutRange
.aStart
, bFilterButton
);
374 pOutput
->SetHeaderLayout ( bHeaderLayout
);
376 long nOldRows
= nHeaderRows
;
377 nHeaderRows
= pOutput
->GetHeaderRows();
379 if ( bAllowMove
&& nHeaderRows
!= nOldRows
)
381 long nDiff
= nOldRows
- nHeaderRows
;
384 if ( nHeaderRows
== 0 )
387 long nNewRow
= aOutRange
.aStart
.Row() + nDiff
;
391 ScAddress
aStart( aOutRange
.aStart
);
392 aStart
.SetRow(nNewRow
);
393 pOutput
->SetPosition( aStart
);
395 //! modify aOutRange?
397 bAllowMove
= FALSE
; // use only once
402 ScDPTableData
* ScDPObject::GetTableData()
409 mpTableData
.reset(new ScDatabaseDPData(pDoc
, *pImpDesc
));
416 DBG_ERROR("no source descriptor");
417 pSheetDesc
= new ScSheetSourceDesc
; // dummy defaults
419 mpTableData
.reset(new ScSheetDPData(pDoc
, *pSheetDesc
));
422 // grouping (for cell or database data)
423 if ( pSaveData
&& pSaveData
->GetExistingDimensionData() )
425 shared_ptr
<ScDPGroupTableData
> pGroupData(new ScDPGroupTableData(mpTableData
, pDoc
));
426 pSaveData
->GetExistingDimensionData()->WriteToData(*pGroupData
);
427 mpTableData
= pGroupData
;
431 return mpTableData
.get();
434 void ScDPObject::CreateObjects()
436 // if groups are involved, create a new source with the ScDPGroupTableData
437 if ( bSettingsChanged
&& pSaveData
&& pSaveData
->GetExistingDimensionData() )
442 //! cache DPSource and/or Output?
444 DBG_ASSERT( bAlive
, "CreateObjects on non-inserted DPObject" );
446 DELETEZ( pOutput
); // not valid when xSource is changed
450 xSource
= CreateSource( *pServDesc
);
453 if ( !xSource
.is() ) // database or sheet data, or error in CreateSource
455 DBG_ASSERT( !pServDesc
, "DPSource could not be created" );
456 ScDPTableData
* pData
= GetTableData();
457 ScDPSource
* pSource
= new ScDPSource( pData
);
462 pSaveData
->WriteToSource( xSource
);
464 else if (bSettingsChanged
)
466 DELETEZ( pOutput
); // not valid when xSource is changed
468 uno::Reference
<util::XRefreshable
> xRef( xSource
, uno::UNO_QUERY
);
475 catch(uno::Exception
&)
477 DBG_ERROR("exception in refresh");
482 pSaveData
->WriteToSource( xSource
);
484 bSettingsChanged
= FALSE
;
487 void ScDPObject::InvalidateData()
489 bSettingsChanged
= TRUE
;
492 void ScDPObject::InvalidateSource()
498 ScRange
ScDPObject::GetNewOutputRange( BOOL
& rOverflow
)
500 CreateOutput(); // create xSource and pOutput if not already done
502 rOverflow
= pOutput
->HasError(); // range overflow or exception from source
504 return ScRange( aOutRange
.aStart
);
507 // don't store the result in aOutRange, because nothing has been output yet
508 return pOutput
->GetOutputRange();
512 void ScDPObject::Output( const ScAddress
& rPos
)
514 // clear old output area
515 pDoc
->DeleteAreaTab( aOutRange
.aStart
.Col(), aOutRange
.aStart
.Row(),
516 aOutRange
.aEnd
.Col(), aOutRange
.aEnd
.Row(),
517 aOutRange
.aStart
.Tab(), IDF_ALL
);
518 pDoc
->RemoveFlagsTab( aOutRange
.aStart
.Col(), aOutRange
.aStart
.Row(),
519 aOutRange
.aEnd
.Col(), aOutRange
.aEnd
.Row(),
520 aOutRange
.aStart
.Tab(), SC_MF_AUTO
);
522 CreateOutput(); // create xSource and pOutput if not already done
524 pOutput
->SetPosition( rPos
);
528 // aOutRange is always the range that was last output to the document
529 aOutRange
= pOutput
->GetOutputRange();
532 const ScRange
ScDPObject::GetOutputRangeByType( sal_Int32 nType
)
536 if (pOutput
->HasError())
537 return ScRange(aOutRange
.aStart
);
539 return pOutput
->GetOutputRange(nType
);
542 BOOL
lcl_HasButton( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
544 return ((const ScMergeFlagAttr
*)pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
))->HasButton();
547 void ScDPObject::RefreshAfterLoad()
549 // apply drop-down attribute, initialize nHeaderRows, without accessing the source
550 // (button attribute must be present)
552 // simple test: block of button cells at the top, followed by an empty cell
554 SCCOL nFirstCol
= aOutRange
.aStart
.Col();
555 SCROW nFirstRow
= aOutRange
.aStart
.Row();
556 SCTAB nTab
= aOutRange
.aStart
.Tab();
559 SCROW nOutRows
= aOutRange
.aEnd
.Row() + 1 - aOutRange
.aStart
.Row();
560 while ( nInitial
+ 1 < nOutRows
&& lcl_HasButton( pDoc
, nFirstCol
, nFirstRow
+ nInitial
, nTab
) )
563 if ( nInitial
+ 1 < nOutRows
&&
564 pDoc
->IsBlockEmpty( nTab
, nFirstCol
, nFirstRow
+ nInitial
, nFirstCol
, nFirstRow
+ nInitial
) &&
565 aOutRange
.aEnd
.Col() > nFirstCol
)
567 BOOL bFilterButton
= IsSheetData(); // when available, filter button setting must be checked here
569 SCROW nSkip
= bFilterButton
? 1 : 0;
570 for (SCROW nPos
=nSkip
; nPos
<nInitial
; nPos
++)
571 pDoc
->ApplyAttr( nFirstCol
+ 1, nFirstRow
+ nPos
, nTab
, ScMergeFlagAttr(SC_MF_AUTO
) );
573 nHeaderRows
= nInitial
;
576 nHeaderRows
= 0; // nothing found, no drop-down lists
579 void ScDPObject::BuildAllDimensionMembers()
584 pSaveData
->BuildAllDimensionMembers(GetTableData());
587 void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode
,
588 const ScRange
& rRange
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
592 SCCOL nCol1
= aOutRange
.aStart
.Col();
593 SCROW nRow1
= aOutRange
.aStart
.Row();
594 SCTAB nTab1
= aOutRange
.aStart
.Tab();
595 SCCOL nCol2
= aOutRange
.aEnd
.Col();
596 SCROW nRow2
= aOutRange
.aEnd
.Row();
597 SCTAB nTab2
= aOutRange
.aEnd
.Tab();
599 ScRefUpdateRes eRes
=
600 ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
601 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
602 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(), nDx
, nDy
, nDz
,
603 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
604 if ( eRes
!= UR_NOTHING
)
605 SetOutRange( ScRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
) );
611 nCol1
= pSheetDesc
->aSourceRange
.aStart
.Col();
612 nRow1
= pSheetDesc
->aSourceRange
.aStart
.Row();
613 nTab1
= pSheetDesc
->aSourceRange
.aStart
.Tab();
614 nCol2
= pSheetDesc
->aSourceRange
.aEnd
.Col();
615 nRow2
= pSheetDesc
->aSourceRange
.aEnd
.Row();
616 nTab2
= pSheetDesc
->aSourceRange
.aEnd
.Tab();
618 eRes
= ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
619 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
620 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(), nDx
, nDy
, nDz
,
621 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
622 if ( eRes
!= UR_NOTHING
)
624 ScSheetSourceDesc aNewDesc
;
625 aNewDesc
.aSourceRange
= ScRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
627 SCsCOL nDiffX
= nCol1
- (SCsCOL
) pSheetDesc
->aSourceRange
.aStart
.Col();
628 SCsROW nDiffY
= nRow1
- (SCsROW
) pSheetDesc
->aSourceRange
.aStart
.Row();
630 aNewDesc
.aQueryParam
= pSheetDesc
->aQueryParam
;
631 aNewDesc
.aQueryParam
.nCol1
= sal::static_int_cast
<SCCOL
>( aNewDesc
.aQueryParam
.nCol1
+ nDiffX
);
632 aNewDesc
.aQueryParam
.nCol2
= sal::static_int_cast
<SCCOL
>( aNewDesc
.aQueryParam
.nCol2
+ nDiffX
);
633 aNewDesc
.aQueryParam
.nRow1
+= nDiffY
; //! used?
634 aNewDesc
.aQueryParam
.nRow2
+= nDiffY
; //! used?
635 SCSIZE nEC
= aNewDesc
.aQueryParam
.GetEntryCount();
636 for (SCSIZE i
=0; i
<nEC
; i
++)
637 if (aNewDesc
.aQueryParam
.GetEntry(i
).bDoQuery
)
638 aNewDesc
.aQueryParam
.GetEntry(i
).nField
+= nDiffX
;
640 SetSheetDesc( aNewDesc
); // allocates new pSheetDesc
645 BOOL
ScDPObject::RefsEqual( const ScDPObject
& r
) const
647 if ( aOutRange
!= r
.aOutRange
)
650 if ( pSheetDesc
&& r
.pSheetDesc
)
652 if ( pSheetDesc
->aSourceRange
!= r
.pSheetDesc
->aSourceRange
)
655 else if ( pSheetDesc
|| r
.pSheetDesc
)
657 DBG_ERROR("RefsEqual: SheetDesc set at only one object");
664 void ScDPObject::WriteRefsTo( ScDPObject
& r
) const
666 r
.SetOutRange( aOutRange
);
668 r
.SetSheetDesc( *pSheetDesc
);
671 void ScDPObject::GetPositionData(const ScAddress
& rPos
, DataPilotTablePositionData
& rPosData
)
674 pOutput
->GetPositionData(rPos
, rPosData
);
677 bool ScDPObject::GetDataFieldPositionData(
678 const ScAddress
& rPos
, Sequence
<sheet::DataPilotFieldFilter
>& rFilters
)
682 vector
<sheet::DataPilotFieldFilter
> aFilters
;
683 if (!pOutput
->GetDataResultPositionData(aFilters
, rPos
))
686 sal_Int32 n
= static_cast<sal_Int32
>(aFilters
.size());
688 for (sal_Int32 i
= 0; i
< n
; ++i
)
689 rFilters
[i
] = aFilters
[i
];
694 void ScDPObject::GetDrillDownData(const ScAddress
& rPos
, Sequence
< Sequence
<Any
> >& rTableData
)
698 Reference
<sheet::XDrillDownDataSupplier
> xDrillDownData(xSource
, UNO_QUERY
);
699 if (!xDrillDownData
.is())
702 Sequence
<sheet::DataPilotFieldFilter
> filters
;
703 if (!GetDataFieldPositionData(rPos
, filters
))
706 rTableData
= xDrillDownData
->getDrillDownData(filters
);
709 bool ScDPObject::IsDimNameInUse(const OUString
& rName
) const
714 Reference
<container::XNameAccess
> xDims
= xSource
->getDimensions();
715 Sequence
<OUString
> aDimNames
= xDims
->getElementNames();
716 sal_Int32 n
= aDimNames
.getLength();
717 for (sal_Int32 i
= 0; i
< n
; ++i
)
719 const OUString
& rDimName
= aDimNames
[i
];
720 if (rDimName
.equalsIgnoreAsciiCase(rName
))
723 Reference
<beans::XPropertySet
> xPropSet(xDims
->getByName(rDimName
), UNO_QUERY
);
727 Any any
= xPropSet
->getPropertyValue(OUString::createFromAscii(SC_UNO_LAYOUTNAME
));
728 OUString aLayoutName
;
729 if (any
>>= aLayoutName
)
731 if (aLayoutName
.equalsIgnoreAsciiCase(rName
))
738 String
ScDPObject::GetDimName( long nDim
, BOOL
& rIsDataLayout
)
740 rIsDataLayout
= FALSE
;
745 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
746 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
747 long nDimCount
= xDims
->getCount();
748 if ( nDim
< nDimCount
)
750 uno::Reference
<uno::XInterface
> xIntDim
=
751 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
752 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
753 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
754 if ( xDimName
.is() && xDimProp
.is() )
756 BOOL bData
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
757 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
758 //! error checking -- is "IsDataLayoutDimension" property required??
763 aName
= xDimName
->getName();
765 catch(uno::Exception
&)
769 rIsDataLayout
= TRUE
;
771 aRet
= String( aName
);
779 BOOL
ScDPObject::IsDuplicated( long nDim
)
781 BOOL bDuplicated
= FALSE
;
784 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
785 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
786 long nDimCount
= xDims
->getCount();
787 if ( nDim
< nDimCount
)
789 uno::Reference
<uno::XInterface
> xIntDim
=
790 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
791 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
796 uno::Any aOrigAny
= xDimProp
->getPropertyValue(
797 rtl::OUString::createFromAscii(DP_PROP_ORIGINAL
) );
798 uno::Reference
<uno::XInterface
> xIntOrig
;
799 if ( (aOrigAny
>>= xIntOrig
) && xIntOrig
.is() )
802 catch(uno::Exception
&)
811 long ScDPObject::GetDimCount()
818 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
819 if ( xDimsName
.is() )
820 nRet
= xDimsName
->getElementNames().getLength();
822 catch(uno::Exception
&)
829 void ScDPObject::FillPageList( TypedScStrCollection
& rStrings
, long nField
)
831 //! merge members access with ToggleDetails?
833 //! convert field index to dimension index?
835 DBG_ASSERT( xSource
.is(), "no source" );
836 if ( !xSource
.is() ) return;
838 uno::Reference
<container::XNamed
> xDim
;
839 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
840 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
841 long nIntCount
= xIntDims
->getCount();
842 if ( nField
< nIntCount
)
844 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface(
845 xIntDims
->getByIndex(nField
) );
846 xDim
= uno::Reference
<container::XNamed
>( xIntDim
, uno::UNO_QUERY
);
848 DBG_ASSERT( xDim
.is(), "dimension not found" );
849 if ( !xDim
.is() ) return;
851 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
852 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
853 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
857 uno::Reference
<container::XIndexAccess
> xHiers
;
858 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSupp( xDim
, uno::UNO_QUERY
);
859 if ( xHierSupp
.is() )
861 uno::Reference
<container::XNameAccess
> xHiersName
= xHierSupp
->getHierarchies();
862 xHiers
= new ScNameToIndexAccess( xHiersName
);
863 nHierCount
= xHiers
->getCount();
865 uno::Reference
<uno::XInterface
> xHier
;
866 if ( nHierarchy
< nHierCount
)
867 xHier
= ScUnoHelpFunctions::AnyToInterface( xHiers
->getByIndex(nHierarchy
) );
868 DBG_ASSERT( xHier
.is(), "hierarchy not found" );
869 if ( !xHier
.is() ) return;
872 uno::Reference
<container::XIndexAccess
> xLevels
;
873 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHier
, uno::UNO_QUERY
);
876 uno::Reference
<container::XNameAccess
> xLevsName
= xLevSupp
->getLevels();
877 xLevels
= new ScNameToIndexAccess( xLevsName
);
878 nLevCount
= xLevels
->getCount();
880 uno::Reference
<uno::XInterface
> xLevel
;
881 if ( nLevel
< nLevCount
)
882 xLevel
= ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex(nLevel
) );
883 DBG_ASSERT( xLevel
.is(), "level not found" );
884 if ( !xLevel
.is() ) return;
886 uno::Reference
<container::XNameAccess
> xMembers
;
887 uno::Reference
<sheet::XMembersSupplier
> xMbrSupp( xLevel
, uno::UNO_QUERY
);
889 xMembers
= xMbrSupp
->getMembers();
890 DBG_ASSERT( xMembers
.is(), "members not found" );
891 if ( !xMembers
.is() ) return;
893 uno::Sequence
<rtl::OUString
> aNames
= xMembers
->getElementNames();
894 long nNameCount
= aNames
.getLength();
895 const rtl::OUString
* pNameArr
= aNames
.getConstArray();
896 for (long nPos
= 0; nPos
< nNameCount
; ++nPos
)
898 // Make sure to insert only visible members.
899 Reference
<XPropertySet
> xPropSet(xMembers
->getByName(pNameArr
[nPos
]), UNO_QUERY
);
900 sal_Bool bVisible
= false;
903 Any any
= xPropSet
->getPropertyValue(OUString::createFromAscii(SC_UNO_ISVISIBL
));
909 // use the order from getElementNames
910 TypedStrData
* pData
= new TypedStrData( pNameArr
[nPos
] );
911 if ( !rStrings
.AtInsert( rStrings
.GetCount(), pData
) )
916 // add "-all-" entry to the top (unsorted)
917 TypedStrData
* pAllData
= new TypedStrData( String( ScResId( SCSTR_ALL
) ) ); //! separate string? (also output)
918 if ( !rStrings
.AtInsert( 0, pAllData
) )
922 void ScDPObject::GetHeaderPositionData(const ScAddress
& rPos
, DataPilotTableHeaderData
& rData
)
924 using namespace ::com::sun::star::sheet::DataPilotTablePositionType
;
926 CreateOutput(); // create xSource and pOutput if not already done
928 // Reset member values to invalid state.
929 rData
.Dimension
= rData
.Hierarchy
= rData
.Level
= -1;
932 DataPilotTablePositionData aPosData
;
933 pOutput
->GetPositionData(rPos
, aPosData
);
934 const sal_Int32 nPosType
= aPosData
.PositionType
;
935 if (nPosType
== COLUMN_HEADER
|| nPosType
== ROW_HEADER
)
936 aPosData
.PositionData
>>= rData
;
939 // Returns TRUE on success and stores the result in rTarget
940 BOOL
ScDPObject::GetPivotData( ScDPGetPivotDataField
& rTarget
,
941 const std::vector
< ScDPGetPivotDataField
>& rFilters
)
943 CreateOutput(); // create xSource and pOutput if not already done
945 return pOutput
->GetPivotData( rTarget
, rFilters
);
948 BOOL
ScDPObject::IsFilterButton( const ScAddress
& rPos
)
950 CreateOutput(); // create xSource and pOutput if not already done
952 return pOutput
->IsFilterButton( rPos
);
955 long ScDPObject::GetHeaderDim( const ScAddress
& rPos
, USHORT
& rOrient
)
957 CreateOutput(); // create xSource and pOutput if not already done
959 return pOutput
->GetHeaderDim( rPos
, rOrient
);
962 BOOL
ScDPObject::GetHeaderDrag( const ScAddress
& rPos
, BOOL bMouseLeft
, BOOL bMouseTop
, long nDragDim
,
963 Rectangle
& rPosRect
, USHORT
& rOrient
, long& rDimPos
)
965 CreateOutput(); // create xSource and pOutput if not already done
967 return pOutput
->GetHeaderDrag( rPos
, bMouseLeft
, bMouseTop
, nDragDim
, rPosRect
, rOrient
, rDimPos
);
970 void ScDPObject::GetMemberResultNames( ScStrCollection
& rNames
, long nDimension
)
972 CreateOutput(); // create xSource and pOutput if not already done
974 pOutput
->GetMemberResultNames( rNames
, nDimension
); // used only with table data -> level not needed
977 bool lcl_Dequote( const String
& rSource
, xub_StrLen nStartPos
, xub_StrLen
& rEndPos
, String
& rResult
)
979 // nStartPos has to point to opening quote
982 const sal_Unicode cQuote
= '\'';
984 if ( rSource
.GetChar(nStartPos
) == cQuote
)
986 rtl::OUStringBuffer aBuffer
;
987 xub_StrLen nPos
= nStartPos
+ 1;
988 const xub_StrLen nLen
= rSource
.Len();
990 while ( nPos
< nLen
)
992 const sal_Unicode cNext
= rSource
.GetChar(nPos
);
993 if ( cNext
== cQuote
)
995 if ( nPos
+1 < nLen
&& rSource
.GetChar(nPos
+1) == cQuote
)
997 // double quote is used for an embedded quote
998 aBuffer
.append( cNext
); // append one quote
999 ++nPos
; // skip the next one
1003 // end of quoted string
1004 rResult
= aBuffer
.makeStringAndClear();
1005 rEndPos
= nPos
+ 1; // behind closing quote
1010 aBuffer
.append( cNext
);
1014 // no closing quote before the end of the string -> error (bRet still false)
1020 struct ScGetPivotDataFunctionEntry
1022 const sal_Char
* pName
;
1023 sheet::GeneralFunction eFunc
;
1026 bool lcl_ParseFunction( const String
& rList
, xub_StrLen nStartPos
, xub_StrLen
& rEndPos
, sheet::GeneralFunction
& rFunc
)
1028 static const ScGetPivotDataFunctionEntry aFunctions
[] =
1031 { "Sum", sheet::GeneralFunction_SUM
},
1032 { "Count", sheet::GeneralFunction_COUNT
},
1033 { "Average", sheet::GeneralFunction_AVERAGE
},
1034 { "Max", sheet::GeneralFunction_MAX
},
1035 { "Min", sheet::GeneralFunction_MIN
},
1036 { "Product", sheet::GeneralFunction_PRODUCT
},
1037 { "CountNums", sheet::GeneralFunction_COUNTNUMS
},
1038 { "StDev", sheet::GeneralFunction_STDEV
},
1039 { "StDevp", sheet::GeneralFunction_STDEVP
},
1040 { "Var", sheet::GeneralFunction_VAR
},
1041 { "VarP", sheet::GeneralFunction_VARP
},
1042 // compatibility names
1043 { "Count Nums", sheet::GeneralFunction_COUNTNUMS
},
1044 { "StdDev", sheet::GeneralFunction_STDEV
},
1045 { "StdDevp", sheet::GeneralFunction_STDEVP
}
1048 const xub_StrLen nListLen
= rList
.Len();
1049 while ( nStartPos
< nListLen
&& rList
.GetChar(nStartPos
) == ' ' )
1052 bool bParsed
= false;
1053 bool bFound
= false;
1055 xub_StrLen nFuncEnd
= 0;
1056 if ( nStartPos
< nListLen
&& rList
.GetChar(nStartPos
) == '\'' )
1057 bParsed
= lcl_Dequote( rList
, nStartPos
, nFuncEnd
, aFuncStr
);
1060 nFuncEnd
= rList
.Search( static_cast<sal_Unicode
>(']'), nStartPos
);
1061 if ( nFuncEnd
!= STRING_NOTFOUND
)
1063 aFuncStr
= rList
.Copy( nStartPos
, nFuncEnd
- nStartPos
);
1070 aFuncStr
.EraseLeadingAndTrailingChars( ' ' );
1072 const sal_Int32 nFuncCount
= sizeof(aFunctions
) / sizeof(aFunctions
[0]);
1073 for ( sal_Int32 nFunc
=0; nFunc
<nFuncCount
&& !bFound
; nFunc
++ )
1075 if ( aFuncStr
.EqualsIgnoreCaseAscii( aFunctions
[nFunc
].pName
) )
1077 rFunc
= aFunctions
[nFunc
].eFunc
;
1080 while ( nFuncEnd
< nListLen
&& rList
.GetChar(nFuncEnd
) == ' ' )
1090 bool lcl_IsAtStart( const String
& rList
, const String
& rSearch
, sal_Int32
& rMatched
,
1091 bool bAllowBracket
, sheet::GeneralFunction
* pFunc
)
1093 sal_Int32 nMatchList
= 0;
1094 sal_Int32 nMatchSearch
= 0;
1095 sal_Unicode cFirst
= rList
.GetChar(0);
1096 if ( cFirst
== '\'' || cFirst
== '[' )
1098 // quoted string or string in brackets must match completely
1101 xub_StrLen nQuoteEnd
= 0;
1102 bool bParsed
= false;
1104 if ( cFirst
== '\'' )
1105 bParsed
= lcl_Dequote( rList
, 0, nQuoteEnd
, aDequoted
);
1106 else if ( cFirst
== '[' )
1108 // skip spaces after the opening bracket
1110 xub_StrLen nStartPos
= 1;
1111 const xub_StrLen nListLen
= rList
.Len();
1112 while ( nStartPos
< nListLen
&& rList
.GetChar(nStartPos
) == ' ' )
1115 if ( rList
.GetChar(nStartPos
) == '\'' ) // quoted within the brackets?
1117 if ( lcl_Dequote( rList
, nStartPos
, nQuoteEnd
, aDequoted
) )
1119 // after the quoted string, there must be the closing bracket, optionally preceded by spaces,
1120 // and/or a function name
1121 while ( nQuoteEnd
< nListLen
&& rList
.GetChar(nQuoteEnd
) == ' ' )
1124 // semicolon separates function name
1125 if ( nQuoteEnd
< nListLen
&& rList
.GetChar(nQuoteEnd
) == ';' && pFunc
)
1127 xub_StrLen nFuncEnd
= 0;
1128 if ( lcl_ParseFunction( rList
, nQuoteEnd
+ 1, nFuncEnd
, *pFunc
) )
1129 nQuoteEnd
= nFuncEnd
;
1131 if ( nQuoteEnd
< nListLen
&& rList
.GetChar(nQuoteEnd
) == ']' )
1133 ++nQuoteEnd
; // include the closing bracket for the matched length
1140 // implicit quoting to the closing bracket
1142 xub_StrLen nClosePos
= rList
.Search( static_cast<sal_Unicode
>(']'), nStartPos
);
1143 if ( nClosePos
!= STRING_NOTFOUND
)
1145 xub_StrLen nNameEnd
= nClosePos
;
1146 xub_StrLen nSemiPos
= rList
.Search( static_cast<sal_Unicode
>(';'), nStartPos
);
1147 if ( nSemiPos
!= STRING_NOTFOUND
&& nSemiPos
< nClosePos
&& pFunc
)
1149 xub_StrLen nFuncEnd
= 0;
1150 if ( lcl_ParseFunction( rList
, nSemiPos
+ 1, nFuncEnd
, *pFunc
) )
1151 nNameEnd
= nSemiPos
;
1154 aDequoted
= rList
.Copy( nStartPos
, nNameEnd
- nStartPos
);
1155 aDequoted
.EraseTrailingChars( ' ' ); // spaces before the closing bracket or semicolon
1156 nQuoteEnd
= nClosePos
+ 1;
1162 if ( bParsed
&& ScGlobal::pTransliteration
->isEqual( aDequoted
, rSearch
) )
1164 nMatchList
= nQuoteEnd
; // match count in the list string, including quotes
1165 nMatchSearch
= rSearch
.Len();
1170 // otherwise look for search string at the start of rList
1171 ScGlobal::pTransliteration
->equals( rList
, 0, rList
.Len(), nMatchList
,
1172 rSearch
, 0, rSearch
.Len(), nMatchSearch
);
1175 if ( nMatchSearch
== rSearch
.Len() )
1177 // search string is at start of rList - look for following space or end of string
1179 bool bValid
= false;
1180 if ( sal::static_int_cast
<xub_StrLen
>(nMatchList
) >= rList
.Len() )
1184 sal_Unicode cNext
= rList
.GetChar(sal::static_int_cast
<xub_StrLen
>(nMatchList
));
1185 if ( cNext
== ' ' || ( bAllowBracket
&& cNext
== '[' ) )
1191 rMatched
= nMatchList
;
1199 BOOL
ScDPObject::ParseFilters( ScDPGetPivotDataField
& rTarget
,
1200 std::vector
< ScDPGetPivotDataField
>& rFilters
,
1201 const String
& rFilterList
)
1203 // parse the string rFilterList into parameters for GetPivotData
1205 CreateObjects(); // create xSource if not already done
1207 std::vector
<String
> aDataNames
; // data fields (source name)
1208 std::vector
<String
> aGivenNames
; // data fields (compound name)
1209 std::vector
<String
> aFieldNames
; // column/row/data fields
1210 std::vector
< uno::Sequence
<rtl::OUString
> > aFieldValues
;
1213 // get all the field and item names
1216 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1217 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
1218 sal_Int32 nDimCount
= xIntDims
->getCount();
1219 for ( sal_Int32 nDim
= 0; nDim
<nDimCount
; nDim
++ )
1221 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface( xIntDims
->getByIndex(nDim
) );
1222 uno::Reference
<container::XNamed
> xDim( xIntDim
, uno::UNO_QUERY
);
1223 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
1224 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDim
, uno::UNO_QUERY
);
1225 BOOL bDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1226 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1227 sal_Int32 nOrient
= ScUnoHelpFunctions::GetEnumProperty(
1228 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
),
1229 sheet::DataPilotFieldOrientation_HIDDEN
);
1232 if ( nOrient
== sheet::DataPilotFieldOrientation_DATA
)
1236 ScDPOutput::GetDataDimensionNames( aSourceName
, aGivenName
, xIntDim
);
1237 aDataNames
.push_back( aSourceName
);
1238 aGivenNames
.push_back( aGivenName
);
1240 else if ( nOrient
!= sheet::DataPilotFieldOrientation_HIDDEN
)
1242 // get level names, as in ScDPOutput
1244 uno::Reference
<container::XIndexAccess
> xHiers
= new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
1245 sal_Int32 nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1246 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
1247 if ( nHierarchy
>= xHiers
->getCount() )
1250 uno::Reference
<uno::XInterface
> xHier
= ScUnoHelpFunctions::AnyToInterface(
1251 xHiers
->getByIndex(nHierarchy
) );
1252 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
1253 if ( xHierSupp
.is() )
1255 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess( xHierSupp
->getLevels() );
1256 sal_Int32 nLevCount
= xLevels
->getCount();
1257 for (sal_Int32 nLev
=0; nLev
<nLevCount
; nLev
++)
1259 uno::Reference
<uno::XInterface
> xLevel
= ScUnoHelpFunctions::AnyToInterface(
1260 xLevels
->getByIndex(nLev
) );
1261 uno::Reference
<container::XNamed
> xLevNam( xLevel
, uno::UNO_QUERY
);
1262 uno::Reference
<sheet::XMembersSupplier
> xLevSupp( xLevel
, uno::UNO_QUERY
);
1263 if ( xLevNam
.is() && xLevSupp
.is() )
1265 uno::Reference
<container::XNameAccess
> xMembers
= xLevSupp
->getMembers();
1267 String
aFieldName( xLevNam
->getName() );
1268 uno::Sequence
<rtl::OUString
> aMemberNames( xMembers
->getElementNames() );
1270 aFieldNames
.push_back( aFieldName
);
1271 aFieldValues
.push_back( aMemberNames
);
1280 // compare and build filters
1283 SCSIZE nDataFields
= aDataNames
.size();
1284 SCSIZE nFieldCount
= aFieldNames
.size();
1285 DBG_ASSERT( aGivenNames
.size() == nDataFields
&& aFieldValues
.size() == nFieldCount
, "wrong count" );
1287 bool bError
= false;
1288 bool bHasData
= false;
1289 String
aRemaining( rFilterList
);
1290 aRemaining
.EraseLeadingAndTrailingChars( ' ' );
1291 while ( aRemaining
.Len() && !bError
)
1295 // look for data field name
1297 for ( SCSIZE nDataPos
=0; nDataPos
<nDataFields
&& !bUsed
; nDataPos
++ )
1300 sal_Int32 nMatched
= 0;
1301 if ( lcl_IsAtStart( aRemaining
, aDataNames
[nDataPos
], nMatched
, false, NULL
) )
1302 aFound
= aDataNames
[nDataPos
];
1303 else if ( lcl_IsAtStart( aRemaining
, aGivenNames
[nDataPos
], nMatched
, false, NULL
) )
1304 aFound
= aGivenNames
[nDataPos
];
1308 rTarget
.maFieldName
= aFound
;
1309 aRemaining
.Erase( 0, sal::static_int_cast
<xub_StrLen
>(nMatched
) );
1315 // look for field name
1318 bool bHasFieldName
= false;
1321 sal_Int32 nMatched
= 0;
1322 for ( SCSIZE nField
=0; nField
<nFieldCount
&& !bHasFieldName
; nField
++ )
1324 if ( lcl_IsAtStart( aRemaining
, aFieldNames
[nField
], nMatched
, true, NULL
) )
1326 aSpecField
= aFieldNames
[nField
];
1327 aRemaining
.Erase( 0, sal::static_int_cast
<xub_StrLen
>(nMatched
) );
1328 aRemaining
.EraseLeadingChars( ' ' );
1330 // field name has to be followed by item name in brackets
1331 if ( aRemaining
.GetChar(0) == '[' )
1333 bHasFieldName
= true;
1334 // bUsed remains false - still need the item
1345 // look for field item
1349 bool bItemFound
= false;
1350 sal_Int32 nMatched
= 0;
1353 sheet::GeneralFunction eFunc
= sheet::GeneralFunction_NONE
;
1354 sheet::GeneralFunction eFoundFunc
= sheet::GeneralFunction_NONE
;
1356 for ( SCSIZE nField
=0; nField
<nFieldCount
; nField
++ )
1358 // If a field name is given, look in that field only, otherwise in all fields.
1359 // aSpecField is initialized from aFieldNames array, so exact comparison can be used.
1360 if ( !bHasFieldName
|| aFieldNames
[nField
] == aSpecField
)
1362 const uno::Sequence
<rtl::OUString
>& rItems
= aFieldValues
[nField
];
1363 sal_Int32 nItemCount
= rItems
.getLength();
1364 const rtl::OUString
* pItemArr
= rItems
.getConstArray();
1365 for ( sal_Int32 nItem
=0; nItem
<nItemCount
; nItem
++ )
1367 if ( lcl_IsAtStart( aRemaining
, pItemArr
[nItem
], nMatched
, false, &eFunc
) )
1370 bError
= true; // duplicate (also across fields)
1373 aFoundName
= aFieldNames
[nField
];
1374 aFoundValue
= pItemArr
[nItem
];
1384 if ( bItemFound
&& !bError
)
1386 ScDPGetPivotDataField aField
;
1387 aField
.maFieldName
= aFoundName
;
1388 aField
.meFunction
= eFoundFunc
;
1389 aField
.mbValIsStr
= true;
1390 aField
.maValStr
= aFoundValue
;
1391 aField
.mnValNum
= 0.0;
1392 rFilters
.push_back( aField
);
1394 aRemaining
.Erase( 0, sal::static_int_cast
<xub_StrLen
>(nMatched
) );
1401 aRemaining
.EraseLeadingChars( ' ' ); // remove any number of spaces between entries
1404 if ( !bError
&& !bHasData
&& aDataNames
.size() == 1 )
1406 // if there's only one data field, its name need not be specified
1407 rTarget
.maFieldName
= aDataNames
[0];
1411 return bHasData
&& !bError
;
1414 void ScDPObject::ToggleDetails(const DataPilotTableHeaderData
& rElemDesc
, ScDPObject
* pDestObj
)
1416 CreateObjects(); // create xSource if not already done
1418 // find dimension name
1420 uno::Reference
<container::XNamed
> xDim
;
1421 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1422 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
1423 long nIntCount
= xIntDims
->getCount();
1424 if ( rElemDesc
.Dimension
< nIntCount
)
1426 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface(
1427 xIntDims
->getByIndex(rElemDesc
.Dimension
) );
1428 xDim
= uno::Reference
<container::XNamed
>( xIntDim
, uno::UNO_QUERY
);
1430 DBG_ASSERT( xDim
.is(), "dimension not found" );
1431 if ( !xDim
.is() ) return;
1432 String aDimName
= xDim
->getName();
1434 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
1435 BOOL bDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1436 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1439 // the elements of the data layout dimension can't be found by their names
1440 // -> don't change anything
1446 long nHierCount
= 0;
1447 uno::Reference
<container::XIndexAccess
> xHiers
;
1448 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSupp( xDim
, uno::UNO_QUERY
);
1449 if ( xHierSupp
.is() )
1451 uno::Reference
<container::XNameAccess
> xHiersName
= xHierSupp
->getHierarchies();
1452 xHiers
= new ScNameToIndexAccess( xHiersName
);
1453 nHierCount
= xHiers
->getCount();
1455 uno::Reference
<uno::XInterface
> xHier
;
1456 if ( rElemDesc
.Hierarchy
< nHierCount
)
1457 xHier
= ScUnoHelpFunctions::AnyToInterface( xHiers
->getByIndex(rElemDesc
.Hierarchy
) );
1458 DBG_ASSERT( xHier
.is(), "hierarchy not found" );
1459 if ( !xHier
.is() ) return;
1462 uno::Reference
<container::XIndexAccess
> xLevels
;
1463 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHier
, uno::UNO_QUERY
);
1464 if ( xLevSupp
.is() )
1466 uno::Reference
<container::XNameAccess
> xLevsName
= xLevSupp
->getLevels();
1467 xLevels
= new ScNameToIndexAccess( xLevsName
);
1468 nLevCount
= xLevels
->getCount();
1470 uno::Reference
<uno::XInterface
> xLevel
;
1471 if ( rElemDesc
.Level
< nLevCount
)
1472 xLevel
= ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex(rElemDesc
.Level
) );
1473 DBG_ASSERT( xLevel
.is(), "level not found" );
1474 if ( !xLevel
.is() ) return;
1476 uno::Reference
<container::XNameAccess
> xMembers
;
1477 uno::Reference
<sheet::XMembersSupplier
> xMbrSupp( xLevel
, uno::UNO_QUERY
);
1478 if ( xMbrSupp
.is() )
1479 xMembers
= xMbrSupp
->getMembers();
1481 BOOL bFound
= FALSE
;
1482 BOOL bShowDetails
= TRUE
;
1484 if ( xMembers
.is() )
1486 if ( xMembers
->hasByName(rElemDesc
.MemberName
) )
1488 uno::Reference
<uno::XInterface
> xMemberInt
= ScUnoHelpFunctions::AnyToInterface(
1489 xMembers
->getByName(rElemDesc
.MemberName
) );
1490 uno::Reference
<beans::XPropertySet
> xMbrProp( xMemberInt
, uno::UNO_QUERY
);
1491 if ( xMbrProp
.is() )
1493 bShowDetails
= ScUnoHelpFunctions::GetBoolProperty( xMbrProp
,
1494 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS
) );
1495 //! don't set bFound if property is unknown?
1501 DBG_ASSERT( bFound
, "member not found" );
1503 //! use Hierarchy and Level in SaveData !!!!
1505 // modify pDestObj if set, this object otherwise
1506 ScDPSaveData
* pModifyData
= pDestObj
? ( pDestObj
->pSaveData
) : pSaveData
;
1507 DBG_ASSERT( pModifyData
, "no data?" );
1510 const String aName
= rElemDesc
.MemberName
;
1511 pModifyData
->GetDimensionByName(aDimName
)->
1512 GetMemberByName(aName
)->SetShowDetails( !bShowDetails
); // toggle
1515 pDestObj
->InvalidateData(); // re-init source from SaveData
1517 InvalidateData(); // re-init source from SaveData
1521 long lcl_FindName( const rtl::OUString
& rString
, const uno::Reference
<container::XNameAccess
>& xCollection
)
1523 if ( xCollection
.is() )
1525 uno::Sequence
<rtl::OUString
> aSeq
= xCollection
->getElementNames();
1526 long nCount
= aSeq
.getLength();
1527 const rtl::OUString
* pArr
= aSeq
.getConstArray();
1528 for (long nPos
=0; nPos
<nCount
; nPos
++)
1529 if ( pArr
[nPos
] == rString
)
1532 return -1; // not found
1535 USHORT
lcl_FirstSubTotal( const uno::Reference
<beans::XPropertySet
>& xDimProp
) // PIVOT_FUNC mask
1537 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDimProp
, uno::UNO_QUERY
);
1538 if ( xDimProp
.is() && xDimSupp
.is() )
1540 uno::Reference
<container::XIndexAccess
> xHiers
= new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
1541 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1542 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
1543 if ( nHierarchy
>= xHiers
->getCount() )
1546 uno::Reference
<uno::XInterface
> xHier
= ScUnoHelpFunctions::AnyToInterface(
1547 xHiers
->getByIndex(nHierarchy
) );
1548 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
1549 if ( xHierSupp
.is() )
1551 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess( xHierSupp
->getLevels() );
1552 uno::Reference
<uno::XInterface
> xLevel
=
1553 ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex( 0 ) );
1554 uno::Reference
<beans::XPropertySet
> xLevProp( xLevel
, uno::UNO_QUERY
);
1555 if ( xLevProp
.is() )
1560 aSubAny
= xLevProp
->getPropertyValue(
1561 rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS
) );
1563 catch(uno::Exception
&)
1566 uno::Sequence
<sheet::GeneralFunction
> aSeq
;
1567 if ( aSubAny
>>= aSeq
)
1570 const sheet::GeneralFunction
* pArray
= aSeq
.getConstArray();
1571 long nCount
= aSeq
.getLength();
1572 for (long i
=0; i
<nCount
; i
++)
1573 nMask
|= ScDataPilotConversion::FunctionBit(pArray
[i
]);
1580 DBG_ERROR("FirstSubTotal: NULL");
1584 USHORT
lcl_CountBits( USHORT nBits
)
1586 if (!nBits
) return 0;
1590 for (USHORT i
=0; i
<16; i
++)
1592 if ( nBits
& nMask
)
1599 SCSIZE
lcl_FillOldFields( PivotField
* pFields
,
1600 const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
,
1601 USHORT nOrient
, SCCOL nColAdd
, BOOL bAddData
)
1603 SCSIZE nOutCount
= 0;
1604 BOOL bDataFound
= FALSE
;
1606 SCSIZE nCount
= (nOrient
== sheet::DataPilotFieldOrientation_PAGE
) ? PIVOT_MAXPAGEFIELD
: PIVOT_MAXFIELD
;
1608 //! merge multiple occurences (data field with different functions)
1609 //! force data field in one dimension
1611 std::vector
< long > aPos( nCount
, 0 );
1613 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1614 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
1615 long nDimCount
= xDims
->getCount();
1616 for (long nDim
=0; nDim
< nDimCount
&& nOutCount
< nCount
; nDim
++)
1618 uno::Reference
<uno::XInterface
> xIntDim
=
1619 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
1620 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
1621 long nDimOrient
= ScUnoHelpFunctions::GetEnumProperty(
1622 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
),
1623 sheet::DataPilotFieldOrientation_HIDDEN
);
1624 if ( xDimProp
.is() && nDimOrient
== nOrient
)
1627 if ( nOrient
== sheet::DataPilotFieldOrientation_DATA
)
1629 sheet::GeneralFunction eFunc
= (sheet::GeneralFunction
)ScUnoHelpFunctions::GetEnumProperty(
1630 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_FUNCTION
),
1631 sheet::GeneralFunction_NONE
);
1632 if ( eFunc
== sheet::GeneralFunction_AUTO
)
1634 //! test for numeric data
1635 eFunc
= sheet::GeneralFunction_SUM
;
1637 nMask
= ScDataPilotConversion::FunctionBit(eFunc
);
1640 nMask
= lcl_FirstSubTotal( xDimProp
); // from first hierarchy
1642 BOOL bDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1643 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1647 aOrigAny
= xDimProp
->getPropertyValue(
1648 rtl::OUString::createFromAscii(DP_PROP_ORIGINAL
) );
1650 catch(uno::Exception
&)
1654 long nDupSource
= -1;
1655 uno::Reference
<uno::XInterface
> xIntOrig
= ScUnoHelpFunctions::AnyToInterface( aOrigAny
);
1656 if ( xIntOrig
.is() )
1658 uno::Reference
<container::XNamed
> xNameOrig( xIntOrig
, uno::UNO_QUERY
);
1659 if ( xNameOrig
.is() )
1660 nDupSource
= lcl_FindName( xNameOrig
->getName(), xDimsName
);
1663 BOOL bDupUsed
= FALSE
;
1664 if ( nDupSource
>= 0 )
1666 // add function bit to previous entry
1670 nCompCol
= PIVOT_DATA_FIELD
;
1672 nCompCol
= static_cast<SCsCOL
>(nDupSource
)+nColAdd
; //! seek source column from name
1674 for (SCSIZE nOld
=0; nOld
<nOutCount
&& !bDupUsed
; nOld
++)
1675 if ( pFields
[nOld
].nCol
== nCompCol
)
1677 // add to previous column only if new bits aren't already set there
1678 if ( ( pFields
[nOld
].nFuncMask
& nMask
) == 0 )
1680 pFields
[nOld
].nFuncMask
|= nMask
;
1681 pFields
[nOld
].nFuncCount
= lcl_CountBits( pFields
[nOld
].nFuncMask
);
1687 if ( !bDupUsed
) // also for duplicated dim if original has different orientation
1691 pFields
[nOutCount
].nCol
= PIVOT_DATA_FIELD
;
1694 else if ( nDupSource
>= 0 ) // if source was not found (different orientation)
1695 pFields
[nOutCount
].nCol
= static_cast<SCsCOL
>(nDupSource
)+nColAdd
; //! seek from name
1697 pFields
[nOutCount
].nCol
= static_cast<SCsCOL
>(nDim
)+nColAdd
; //! seek source column from name
1699 pFields
[nOutCount
].nFuncMask
= nMask
;
1700 pFields
[nOutCount
].nFuncCount
= lcl_CountBits( nMask
);
1701 aPos
[nOutCount
] = ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1702 rtl::OUString::createFromAscii(DP_PROP_POSITION
) );
1706 if( nOrient
== sheet::DataPilotFieldOrientation_DATA
)
1707 xDimProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_REFVALUE
) ) )
1708 >>= pFields
[nOutCount
].maFieldRef
;
1710 catch( uno::Exception
& )
1719 // sort by getPosition() value
1721 for (SCSIZE i
=0; i
+1<nOutCount
; i
++)
1723 for (SCSIZE j
=0; j
+i
+1<nOutCount
; j
++)
1724 if ( aPos
[j
+1] < aPos
[j
] )
1726 std::swap( aPos
[j
], aPos
[j
+1] );
1727 std::swap( pFields
[j
], pFields
[j
+1] );
1731 if ( bAddData
&& !bDataFound
)
1733 if ( nOutCount
>= nCount
) // space for data field?
1734 --nOutCount
; //! error?
1735 pFields
[nOutCount
].nCol
= PIVOT_DATA_FIELD
;
1736 pFields
[nOutCount
].nFuncMask
= 0;
1737 pFields
[nOutCount
].nFuncCount
= 0;
1744 BOOL
ScDPObject::FillOldParam(ScPivotParam
& rParam
, BOOL bForFile
) const
1746 ((ScDPObject
*)this)->CreateObjects(); // xSource is needed for field numbers
1748 rParam
.nCol
= aOutRange
.aStart
.Col();
1749 rParam
.nRow
= aOutRange
.aStart
.Row();
1750 rParam
.nTab
= aOutRange
.aStart
.Tab();
1751 // ppLabelArr / nLabels is not changed
1756 // in old file format, columns are within document, not within source range
1758 DBG_ASSERT( pSheetDesc
, "FillOldParam: bForFile, !pSheetDesc" );
1759 nColAdd
= pSheetDesc
->aSourceRange
.aStart
.Col();
1762 BOOL bAddData
= ( lcl_GetDataGetOrientation( xSource
) == sheet::DataPilotFieldOrientation_HIDDEN
);
1763 rParam
.nPageCount
= lcl_FillOldFields( rParam
.aPageArr
,
1764 xSource
, sheet::DataPilotFieldOrientation_PAGE
, nColAdd
, FALSE
);
1765 rParam
.nColCount
= lcl_FillOldFields( rParam
.aColArr
,
1766 xSource
, sheet::DataPilotFieldOrientation_COLUMN
, nColAdd
, bAddData
);
1767 rParam
.nRowCount
= lcl_FillOldFields( rParam
.aRowArr
,
1768 xSource
, sheet::DataPilotFieldOrientation_ROW
, nColAdd
, FALSE
);
1769 rParam
.nDataCount
= lcl_FillOldFields( rParam
.aDataArr
,
1770 xSource
, sheet::DataPilotFieldOrientation_DATA
, nColAdd
, FALSE
);
1772 uno::Reference
<beans::XPropertySet
> xProp( xSource
, uno::UNO_QUERY
);
1777 rParam
.bMakeTotalCol
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1778 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND
), TRUE
);
1779 rParam
.bMakeTotalRow
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1780 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND
), TRUE
);
1782 // following properties may be missing for external sources
1783 rParam
.bIgnoreEmptyRows
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1784 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY
) );
1785 rParam
.bDetectCategories
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1786 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY
) );
1788 catch(uno::Exception
&)
1796 void lcl_FillLabelData( ScDPLabelData
& rData
, const uno::Reference
< beans::XPropertySet
>& xDimProp
)
1798 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDimProp
, uno::UNO_QUERY
);
1799 if ( xDimProp
.is() && xDimSupp
.is() )
1801 uno::Reference
<container::XIndexAccess
> xHiers
= new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
1802 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1803 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
1804 if ( nHierarchy
>= xHiers
->getCount() )
1806 rData
.mnUsedHier
= nHierarchy
;
1808 uno::Reference
<uno::XInterface
> xHier
= ScUnoHelpFunctions::AnyToInterface(
1809 xHiers
->getByIndex(nHierarchy
) );
1811 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
1812 if ( xHierSupp
.is() )
1814 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess( xHierSupp
->getLevels() );
1815 uno::Reference
<uno::XInterface
> xLevel
=
1816 ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex( 0 ) );
1817 uno::Reference
<beans::XPropertySet
> xLevProp( xLevel
, uno::UNO_QUERY
);
1818 if ( xLevProp
.is() )
1820 rData
.mbShowAll
= ScUnoHelpFunctions::GetBoolProperty( xLevProp
,
1821 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY
) );
1825 xLevProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SORTING
) ) )
1826 >>= rData
.maSortInfo
;
1827 xLevProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_LAYOUT
) ) )
1828 >>= rData
.maLayoutInfo
;
1829 xLevProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_AUTOSHOW
) ) )
1830 >>= rData
.maShowInfo
;
1832 catch(uno::Exception
&)
1840 BOOL
ScDPObject::FillLabelData(ScPivotParam
& rParam
)
1842 rParam
.maLabelArray
.clear();
1844 ((ScDPObject
*)this)->CreateObjects();
1846 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1847 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
1848 long nDimCount
= xDims
->getCount();
1849 if ( nDimCount
> MAX_LABELS
)
1850 nDimCount
= MAX_LABELS
;
1854 for (long nDim
=0; nDim
< nDimCount
; nDim
++)
1857 uno::Reference
<uno::XInterface
> xIntDim
=
1858 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
1859 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
1860 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
1862 if ( xDimName
.is() && xDimProp
.is() )
1864 BOOL bDuplicated
= FALSE
;
1865 BOOL bData
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1866 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1867 //! error checking -- is "IsDataLayoutDimension" property required??
1871 aFieldName
= String( xDimName
->getName() );
1873 uno::Any aOrigAny
= xDimProp
->getPropertyValue(
1874 rtl::OUString::createFromAscii(DP_PROP_ORIGINAL
) );
1875 uno::Reference
<uno::XInterface
> xIntOrig
;
1876 if ( (aOrigAny
>>= xIntOrig
) && xIntOrig
.is() )
1879 catch(uno::Exception
&)
1883 if ( aFieldName
.Len() && !bData
&& !bDuplicated
)
1885 SCsCOL nCol
= static_cast< SCsCOL
>( nDim
); //! ???
1886 bool bIsValue
= true; //! check
1888 ScDPLabelDataRef
pNewLabel(new ScDPLabelData(aFieldName
, nCol
, bIsValue
));
1889 GetHierarchies(nDim
, pNewLabel
->maHiers
);
1890 GetMembers(nDim
, pNewLabel
->maMembers
, &pNewLabel
->maVisible
, &pNewLabel
->maShowDet
);
1891 lcl_FillLabelData(*pNewLabel
, xDimProp
);
1892 rParam
.maLabelArray
.push_back(pNewLabel
);
1900 BOOL
ScDPObject::GetHierarchiesNA( sal_Int32 nDim
, uno::Reference
< container::XNameAccess
>& xHiers
)
1903 uno::Reference
<container::XNameAccess
> xDimsName( GetSource()->getDimensions() );
1904 uno::Reference
<container::XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
1907 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSup(xIntDims
->getByIndex( nDim
), uno::UNO_QUERY
);
1910 xHiers
.set( xHierSup
->getHierarchies() );
1917 BOOL
ScDPObject::GetHierarchies( sal_Int32 nDim
, uno::Sequence
< rtl::OUString
>& rHiers
)
1920 uno::Reference
< container::XNameAccess
> xHiersNA
;
1921 if( GetHierarchiesNA( nDim
, xHiersNA
) )
1923 rHiers
= xHiersNA
->getElementNames();
1929 sal_Int32
ScDPObject::GetUsedHierarchy( sal_Int32 nDim
)
1931 sal_Int32 nHier
= 0;
1932 uno::Reference
<container::XNameAccess
> xDimsName( GetSource()->getDimensions() );
1933 uno::Reference
<container::XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
1934 uno::Reference
<beans::XPropertySet
> xDim(xIntDims
->getByIndex( nDim
), uno::UNO_QUERY
);
1936 nHier
= ScUnoHelpFunctions::GetLongProperty( xDim
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_UNO_USEDHIER
) ) );
1940 BOOL
ScDPObject::GetMembersNA( sal_Int32 nDim
, uno::Reference
< container::XNameAccess
>& xMembers
)
1942 return GetMembersNA( nDim
, GetUsedHierarchy( nDim
), xMembers
);
1945 BOOL
ScDPObject::GetMembers( sal_Int32 nDim
,
1946 uno::Sequence
< rtl::OUString
>& rMembers
,
1947 uno::Sequence
< sal_Bool
>* pVisible
,
1948 uno::Sequence
< sal_Bool
>* pShowDet
)
1950 return GetMembers( nDim
, GetUsedHierarchy( nDim
), rMembers
, pVisible
, pShowDet
);
1953 BOOL
ScDPObject::GetMembersNA( sal_Int32 nDim
, sal_Int32 nHier
, uno::Reference
< container::XNameAccess
>& xMembers
)
1956 uno::Reference
<container::XNameAccess
> xDimsName( GetSource()->getDimensions() );
1957 uno::Reference
<container::XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
1958 uno::Reference
<beans::XPropertySet
> xDim(xIntDims
->getByIndex( nDim
), uno::UNO_QUERY
);
1961 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSup(xDim
, uno::UNO_QUERY
);
1964 uno::Reference
<container::XIndexAccess
> xHiers(new ScNameToIndexAccess(xHierSup
->getHierarchies()));
1965 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHiers
->getByIndex(nHier
), uno::UNO_QUERY
);
1966 if ( xLevSupp
.is() )
1968 uno::Reference
<container::XIndexAccess
> xLevels(new ScNameToIndexAccess( xLevSupp
->getLevels()));
1971 sal_Int32 nLevCount
= xLevels
->getCount();
1974 uno::Reference
<sheet::XMembersSupplier
> xMembSupp( xLevels
->getByIndex(0), uno::UNO_QUERY
);
1975 if ( xMembSupp
.is() )
1977 xMembers
.set(xMembSupp
->getMembers());
1988 BOOL
ScDPObject::GetMembers( sal_Int32 nDim
, sal_Int32 nHier
,
1989 uno::Sequence
< rtl::OUString
>& rMembers
,
1990 uno::Sequence
< sal_Bool
>* pVisible
,
1991 uno::Sequence
< sal_Bool
>* pShowDet
)
1994 uno::Reference
< container::XNameAccess
> xMembersNA
;
1995 if( GetMembersNA( nDim
, nHier
, xMembersNA
) )
1997 uno::Reference
< container::XIndexAccess
> xMembersIA( new ScNameToIndexAccess( xMembersNA
) );
1998 sal_Int32 nCount
= xMembersIA
->getCount();
1999 rMembers
.realloc( nCount
);
2001 pVisible
->realloc( nCount
);
2003 pShowDet
->realloc( nCount
);
2005 rtl::OUString
* pAry
= rMembers
.getArray();
2006 for( sal_Int32 nItem
= 0; nItem
< nCount
; ++nItem
)
2008 uno::Reference
< container::XNamed
> xMember( xMembersIA
->getByIndex( nItem
), uno::UNO_QUERY
);
2010 pAry
[ nItem
] = xMember
->getName();
2011 if( pVisible
|| pShowDet
)
2013 uno::Reference
< beans::XPropertySet
> xMemProp( xMember
, uno::UNO_QUERY
);
2016 sal_Bool bVis
= sal_True
;
2018 bVis
= ScUnoHelpFunctions::GetBoolProperty( xMemProp
,
2019 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ISVISIBL
) ) );
2020 (*pVisible
)[ nItem
] = bVis
;
2024 sal_Bool bShow
= sal_True
;
2026 bShow
= ScUnoHelpFunctions::GetBoolProperty( xMemProp
,
2027 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHOWDETA
) ) );
2028 (*pShowDet
)[ nItem
] = bShow
;
2037 //------------------------------------------------------------------------
2038 // convert old pivot tables into new datapilot tables
2040 String
lcl_GetDimName( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
, long nDim
)
2042 rtl::OUString aName
;
2045 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
2046 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
2047 long nDimCount
= xDims
->getCount();
2048 if ( nDim
< nDimCount
)
2050 uno::Reference
<uno::XInterface
> xIntDim
=
2051 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
2052 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
2057 aName
= xDimName
->getName();
2059 catch(uno::Exception
&)
2069 void ScDPObject::ConvertOrientation( ScDPSaveData
& rSaveData
,
2070 PivotField
* pFields
, SCSIZE nCount
, USHORT nOrient
,
2071 ScDocument
* pDoc
, SCROW nRow
, SCTAB nTab
,
2072 const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
,
2074 PivotField
* pRefColFields
, SCSIZE nRefColCount
,
2075 PivotField
* pRefRowFields
, SCSIZE nRefRowCount
,
2076 PivotField
* pRefPageFields
, SCSIZE nRefPageCount
)
2078 // pDoc or xSource must be set
2079 DBG_ASSERT( pDoc
|| xSource
.is(), "missing string source" );
2082 ScDPSaveDimension
* pDim
;
2084 for (SCSIZE i
=0; i
<nCount
; i
++)
2086 SCCOL nCol
= pFields
[i
].nCol
;
2087 USHORT nFuncs
= pFields
[i
].nFuncMask
;
2088 const sheet::DataPilotFieldReference
& rFieldRef
= pFields
[i
].maFieldRef
;
2090 if ( nCol
== PIVOT_DATA_FIELD
)
2091 pDim
= rSaveData
.GetDataLayoutDimension();
2095 pDoc
->GetString( nCol
, nRow
, nTab
, aDocStr
);
2097 aDocStr
= lcl_GetDimName( xSource
, nCol
); // cols must start at 0
2099 if ( aDocStr
.Len() )
2100 pDim
= rSaveData
.GetDimensionByName(aDocStr
);
2107 if ( nOrient
== sheet::DataPilotFieldOrientation_DATA
) // set summary function
2109 // generate an individual entry for each function
2112 // if a dimension is used for column/row/page and data,
2113 // use duplicated dimensions for all data occurrences
2115 for (SCSIZE nRefCol
=0; nRefCol
<nRefColCount
; nRefCol
++)
2116 if (pRefColFields
[nRefCol
].nCol
== nCol
)
2119 for (SCSIZE nRefRow
=0; nRefRow
<nRefRowCount
; nRefRow
++)
2120 if (pRefRowFields
[nRefRow
].nCol
== nCol
)
2123 for (USHORT nRefPage
=0; nRefPage
<nRefPageCount
; ++nRefPage
)
2124 if (pRefPageFields
[nRefPage
].nCol
== nCol
)
2127 // if set via api, a data column may occur several times
2128 // (if the function hasn't been changed yet) -> also look for duplicate data column
2129 for (SCSIZE nPrevData
=0; nPrevData
<i
; nPrevData
++)
2130 if (pFields
[nPrevData
].nCol
== nCol
)
2134 for (USHORT nBit
=0; nBit
<16; nBit
++)
2136 if ( nFuncs
& nMask
)
2138 sheet::GeneralFunction eFunc
= ScDataPilotConversion::FirstFunc( nMask
);
2139 ScDPSaveDimension
* pCurrDim
= bFirst
? pDim
: rSaveData
.DuplicateDimension(pDim
->GetName());
2140 pCurrDim
->SetOrientation( nOrient
);
2141 pCurrDim
->SetFunction( sal::static_int_cast
<USHORT
>(eFunc
) );
2143 if( rFieldRef
.ReferenceType
== sheet::DataPilotFieldReferenceType::NONE
)
2144 pCurrDim
->SetReferenceValue( 0 );
2146 pCurrDim
->SetReferenceValue( &rFieldRef
);
2153 else // set SubTotals
2155 pDim
->SetOrientation( nOrient
);
2157 USHORT nFuncArray
[16];
2158 USHORT nFuncCount
= 0;
2160 for (USHORT nBit
=0; nBit
<16; nBit
++)
2162 if ( nFuncs
& nMask
)
2163 nFuncArray
[nFuncCount
++] = sal::static_int_cast
<USHORT
>(ScDataPilotConversion::FirstFunc( nMask
));
2166 pDim
->SetSubTotals( nFuncCount
, nFuncArray
);
2168 // ShowEmpty was implicit in old tables,
2169 // must be set for data layout dimension (not accessible in dialog)
2170 if ( bOldDefaults
|| nCol
== PIVOT_DATA_FIELD
)
2171 pDim
->SetShowEmpty( TRUE
);
2177 // -----------------------------------------------------------------------
2180 BOOL
ScDPObject::HasRegisteredSources()
2182 BOOL bFound
= FALSE
;
2184 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
2185 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
2188 uno::Reference
<container::XEnumeration
> xEnum
= xEnAc
->createContentEnumeration(
2189 rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE
) );
2190 if ( xEnum
.is() && xEnum
->hasMoreElements() )
2198 uno::Sequence
<rtl::OUString
> ScDPObject::GetRegisteredSources()
2201 uno::Sequence
<rtl::OUString
> aSeq(0);
2203 // use implementation names...
2205 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
2206 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
2209 uno::Reference
<container::XEnumeration
> xEnum
= xEnAc
->createContentEnumeration(
2210 rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE
) );
2213 while ( xEnum
->hasMoreElements() )
2215 uno::Any aAddInAny
= xEnum
->nextElement();
2216 // if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
2218 uno::Reference
<uno::XInterface
> xIntFac
;
2219 aAddInAny
>>= xIntFac
;
2222 uno::Reference
<lang::XServiceInfo
> xInfo( xIntFac
, uno::UNO_QUERY
);
2225 rtl::OUString sName
= xInfo
->getImplementationName();
2227 aSeq
.realloc( nCount
+1 );
2228 aSeq
.getArray()[nCount
] = sName
;
2241 uno::Reference
<sheet::XDimensionsSupplier
> ScDPObject::CreateSource( const ScDPServiceDesc
& rDesc
)
2243 rtl::OUString aImplName
= rDesc
.aServiceName
;
2244 uno::Reference
<sheet::XDimensionsSupplier
> xRet
= NULL
;
2246 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
2247 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
2250 uno::Reference
<container::XEnumeration
> xEnum
= xEnAc
->createContentEnumeration(
2251 rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE
) );
2254 while ( xEnum
->hasMoreElements() && !xRet
.is() )
2256 uno::Any aAddInAny
= xEnum
->nextElement();
2257 // if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
2259 uno::Reference
<uno::XInterface
> xIntFac
;
2260 aAddInAny
>>= xIntFac
;
2263 uno::Reference
<lang::XServiceInfo
> xInfo( xIntFac
, uno::UNO_QUERY
);
2264 uno::Reference
<lang::XSingleServiceFactory
> xFac( xIntFac
, uno::UNO_QUERY
);
2265 if ( xFac
.is() && xInfo
.is() && xInfo
->getImplementationName() == aImplName
)
2269 uno::Reference
<uno::XInterface
> xInterface
= xFac
->createInstance();
2270 uno::Reference
<lang::XInitialization
> xInit( xInterface
, uno::UNO_QUERY
);
2274 uno::Sequence
<uno::Any
> aSeq(4);
2275 uno::Any
* pArray
= aSeq
.getArray();
2276 pArray
[0] <<= rtl::OUString( rDesc
.aParSource
);
2277 pArray
[1] <<= rtl::OUString( rDesc
.aParName
);
2278 pArray
[2] <<= rtl::OUString( rDesc
.aParUser
);
2279 pArray
[3] <<= rtl::OUString( rDesc
.aParPass
);
2280 xInit
->initialize( aSeq
);
2282 xRet
= uno::Reference
<sheet::XDimensionsSupplier
>( xInterface
, uno::UNO_QUERY
);
2284 catch(uno::Exception
&)
2297 // ============================================================================
2299 ScDPCacheCell::ScDPCacheCell() :
2300 mnStrId(ScSimpleSharedString::EMPTY
),
2301 mnType(SC_VALTYPE_EMPTY
),
2307 ScDPCacheCell::ScDPCacheCell(const ScDPCacheCell
& r
) :
2311 mbNumeric(r
.mbNumeric
)
2315 ScDPCacheCell::~ScDPCacheCell()
2319 // ============================================================================
2321 size_t ScDPCollection::CacheCellHash::operator()(const ScDPCacheCell
* pCell
) const
2323 return pCell
->mnStrId
+ static_cast<size_t>(pCell
->mnType
) +
2324 static_cast<size_t>(pCell
->mfValue
) + static_cast<size_t>(pCell
->mbNumeric
);
2327 bool ScDPCollection::CacheCellEqual::operator()(const ScDPCacheCell
* p1
, const ScDPCacheCell
* p2
) const
2332 if ((!p1
&& p2
) || (p1
&& !p2
))
2335 return p1
->mnStrId
== p2
->mnStrId
&& p1
->mfValue
== p2
->mfValue
&&
2336 p1
->mbNumeric
== p2
->mbNumeric
&& p1
->mnType
== p2
->mnType
;
2339 // ----------------------------------------------------------------------------
2341 ScDPCollection::ScDPCollection(ScDocument
* pDocument
) :
2346 ScDPCollection::ScDPCollection(const ScDPCollection
& r
) :
2349 maSharedString(r
.maSharedString
),
2350 maCacheCellPool() // #i101725# don't copy hash_set with pointers from the other collection
2354 ScDPCollection::~ScDPCollection()
2356 clearCacheCellPool();
2359 ScDataObject
* ScDPCollection::Clone() const
2361 return new ScDPCollection(*this);
2364 void ScDPCollection::DeleteOnTab( SCTAB nTab
)
2367 while ( nPos
< nCount
)
2369 // look for output positions on the deleted sheet
2370 if ( static_cast<const ScDPObject
*>(At(nPos
))->GetOutRange().aStart
.Tab() == nTab
)
2377 void ScDPCollection::UpdateReference( UpdateRefMode eUpdateRefMode
,
2378 const ScRange
& r
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
2380 for (USHORT i
=0; i
<nCount
; i
++)
2381 ((ScDPObject
*)At(i
))->UpdateReference( eUpdateRefMode
, r
, nDx
, nDy
, nDz
);
2384 BOOL
ScDPCollection::RefsEqual( const ScDPCollection
& r
) const
2386 if ( nCount
!= r
.nCount
)
2389 for (USHORT i
=0; i
<nCount
; i
++)
2390 if ( ! ((const ScDPObject
*)At(i
))->RefsEqual( *((const ScDPObject
*)r
.At(i
)) ) )
2393 return TRUE
; // all equal
2396 void ScDPCollection::WriteRefsTo( ScDPCollection
& r
) const
2398 if ( nCount
== r
.nCount
)
2400 //! assert equal names?
2401 for (USHORT i
=0; i
<nCount
; i
++)
2402 ((const ScDPObject
*)At(i
))->WriteRefsTo( *((ScDPObject
*)r
.At(i
)) );
2406 // #i8180# If data pilot tables were deleted with their sheet,
2407 // this collection contains extra entries that must be restored.
2408 // Matching objects are found by their names.
2410 DBG_ASSERT( nCount
>= r
.nCount
, "WriteRefsTo: missing entries in document" );
2411 for (USHORT nSourcePos
=0; nSourcePos
<nCount
; nSourcePos
++)
2413 const ScDPObject
* pSourceObj
= static_cast<const ScDPObject
*>(At(nSourcePos
));
2414 String aName
= pSourceObj
->GetName();
2415 bool bFound
= false;
2416 for (USHORT nDestPos
=0; nDestPos
<r
.nCount
&& !bFound
; nDestPos
++)
2418 ScDPObject
* pDestObj
= static_cast<ScDPObject
*>(r
.At(nDestPos
));
2419 if ( pDestObj
->GetName() == aName
)
2421 pSourceObj
->WriteRefsTo( *pDestObj
); // found object, copy refs
2427 // none found, re-insert deleted object (see ScUndoDataPilot::Undo)
2429 ScDPObject
* pDestObj
= new ScDPObject( *pSourceObj
);
2430 pDestObj
->SetAlive(TRUE
);
2431 if ( !r
.Insert(pDestObj
) )
2433 DBG_ERROR("cannot insert DPObject");
2434 DELETEZ( pDestObj
);
2438 DBG_ASSERT( nCount
== r
.nCount
, "WriteRefsTo: couldn't restore all entries" );
2442 String
ScDPCollection::CreateNewName( USHORT nMin
) const
2444 String aBase
= String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("DataPilot"));
2447 for (USHORT nAdd
=0; nAdd
<=nCount
; nAdd
++) // nCount+1 tries
2449 String aNewName
= aBase
;
2450 aNewName
+= String::CreateFromInt32( nMin
+ nAdd
);
2451 BOOL bFound
= FALSE
;
2452 for (USHORT i
=0; i
<nCount
&& !bFound
; i
++)
2453 if (((const ScDPObject
*)pItems
[i
])->GetName() == aNewName
)
2456 return aNewName
; // found unused Name
2458 return String(); // should not happen
2461 ScSimpleSharedString
& ScDPCollection::GetSharedString()
2463 return maSharedString
;
2466 ScDPCacheCell
* ScDPCollection::getCacheCellFromPool(const ScDPCacheCell
& rCell
)
2468 ScDPCacheCell
aCell(rCell
);
2469 CacheCellPoolType::iterator itr
= maCacheCellPool
.find(&aCell
);
2470 if (itr
== maCacheCellPool
.end())
2472 // Insert a new instance.
2473 ScDPCacheCell
* p
= new ScDPCacheCell(rCell
);
2474 ::std::pair
<CacheCellPoolType::iterator
, bool> r
=
2475 maCacheCellPool
.insert(p
);
2479 ScDPCacheCell
* p2
= r
.second
? *r
.first
: NULL
;
2480 DBG_ASSERT(p
== p2
, "ScDPCollection::getCacheCellFromPool: pointer addresses differ");
2488 class DeleteCacheCells
: public ::std::unary_function
<ScDPCacheCell
*, void>
2491 void operator()(ScDPCacheCell
* p
) const
2499 void ScDPCollection::clearCacheCellPool()
2501 // Transferring all stored pointers to a vector first. For some unknown
2502 // reason, deleting cell content instances by directly iterating through
2503 // the hash set causes the iteration to return an identical pointer
2504 // value twice, causing a double-delete. I have no idea why this happens.
2507 using ::std::back_inserter
;
2509 vector
<ScDPCacheCell
*> ps
;
2510 ps
.reserve(maCacheCellPool
.size());
2511 copy(maCacheCellPool
.begin(), maCacheCellPool
.end(), back_inserter(ps
));
2512 maCacheCellPool
.clear();
2513 // for correctness' sake, delete the elements after clearing the hash_set
2514 for_each(ps
.begin(), ps
.end(), DeleteCacheCells());